Bic SIMに変えた

iPhoneのSIMカード変更

2015年にフランスに長期滞在するということでSIMロックフリーのiPhoneを買っていたので,日本に帰ってきてから格安SIMに変更しました。

いろいろ調べましたが,インターネットも新しく契約する必要があったのでビックSIMにしました。フレッツ光の回線をつかうBic光との組み合わせで割引がつくという今時なサービスです。

携帯電話はiPhoneしかないので,音声通話付きで月のデータ容量3GB,1600円のにしました。
ビックSIM

使い勝手

2015年の10月頃に変えて,2ヶ月ちょい使ってみました。

仕事がら2,3ヶ月に一回くらい3日くらいの出張に行く感じで,他は普通に町中で使うくらいですが,月3GBで十分でした。出張にいっても全然だいじょうぶ。毎日に通信料をチェックするためのアプリもあります。毎日動画を長時間みるようだと足りないかもしれませんが,自宅で見ましょう。

Wi2 300が使える

ビックSIMの特典として,公衆無線LANのWi2 300のベーシックエリアが使えます。
Wi2 300

これでUQ Wi-fiとかに繋がるんですが,この前東海道新幹線にのったときにはまりました。新幹線内はUQ Wi-fiエリアですが,オプションになっていて別途料金を払う必要があります。ちなみに常磐線の特急のUQ Wi-fiは無料で使えます。ややこしい。

気になること

年に1回くらい海外出張しますが,ビックSIMだと国際ローミングで通話は可能ですが,データ通信ができないとかいてあります。基本的にデータ通信使いませんが,全く使えないのも困りもんです。

今度出張するなら現地SIMを買うのかなー。

2015年末にGPUを買ってみた

目的

GPU使った流体計算に興味があって,今までGPUを全く買ったことがなかったので買ってみました。

Geforce GTX960を買ってみた

全く知らないのでとりあえずCUDAが使えればいいや+予算3万までとおもって,NVIDIAのGTX960を買いました。

GPU計算について

順番がおかしいですが,買ってから性能とか調べてみました。
Wikipediaが一番詳しかったです。
https://en.wikipedia.org/wiki/GeForce_900_series

衝撃的事実。最近のGPUは倍精度計算の性能がほとんどない。
GTX960は 単精度2.3TFLOPSに対して,倍精度は1/32の72GFLOPSしかない。

数値計算する上では倍精度の速度がほしいのに。

なにを買えばよかったか?

GPU計算するならGPGPUとして出てるTeslaを素直に買うのが一番だというのが結論だと思います。それは知ってましたが,個人で買うようなものでもないので,様子見がしたかった。

個人が手が出せるとしたらTitanが限界かと。これも落とし穴があって,今でてるTitan Xだと倍精度計算の性能は全然だめです。Titan Zを買いましょう。Titan Zなら倍精度計算性能が2.7TFLOPSもあります。

まとめ

買ってしまった以上GTX960でなんかできることを考えてやってみようと思います。とりあえず倍精度はやめて単精度でベンチマークとってみるとか。OpenFOAMのCUDA版RapidCFDをとりあえずやってみようと思います。

pisoFOAMのpEqn.flux()について調べてみる

はじめに

縁あって流体解析なんぞやっていて,オープンソースのOpenFOAMをよく使うので,それについてメモ書き。ややこしいコードなので間違ってるかもしれませんが,そのときはご指摘ください。

ブログの本筋からは大分外れててすいません。

概要

OpenFOAM2.3.xのpisoFOAM中にある非直交補正のループ内に

pisoFoam.C

 120                     if (nonOrth == nNonOrthCorr)
 121                     {
 122                         phi = phiHbyA - pEqn.flux();
 123                     }

pEqn.flux()関数の呼び出しがあります。(行頭は行番号です)flux()関数がどうなっているかをGDBによるデバッグとGNU Globalによるソースコードの読解で調べてみました。

GDBとGlobal

GDB

GDBはGCCのデバッガです。OpenFOAMでGDBを使えるようにするには,コンパイルオプションWM_COMPILE_OPTIONをDebugにしてAllwmakeします。詳細は下記なんかがわかりやすいです。

http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2008/debugging.pdf

Global

GNU Globalはソースコードにタグをつけてくれるソフトです。関数のソースがどこにあるかなどの情報が見やすくなります。EclipseのF3を押しても同様のことができますが,候補が一覧で表示されるので,個人的にはEclipseよりも使いやすいです。

参考

http://www.machu.jp/diary/20090307.html#p01
http://uguisu.skr.jp/Windows/gtags.html

Globalはソースコードにタグ付けを行うので,OpenFOAMで使う場合にはtutorials, etc, bin, docを除外します。除外の仕方は以下を参考にしました。
http://d.hatena.ne.jp/ohtorii/20110219/1298092604

pisoFOAMのソースコードを見る

はじめにGlobalでflux()関数を見る

GlobalでpisoFoam.Cを見ると,flux()へのリンクができています。リンクをたどると以下のような候補が表示されます。

flux               58 src/OpenFOAM/primitives/Vector/vector/vector.H class flux
flux               65 src/OpenFOAM/primitives/Vector/vector/vector.H class flux<scalar>
flux               57 src/finiteVolume/finiteVolume/convectionSchemes/boundedConvectionScheme/boundedConvectionScheme.C boundedConvectionScheme<Type>::flux
flux               64 src/finiteVolume/finiteVolume/convectionSchemes/gaussConvectionScheme/gaussConvectionScheme.C gaussConvectionScheme<Type>::flux
flux               61 src/finiteVolume/finiteVolume/convectionSchemes/multivariateGaussConvectionScheme/multivariateGaussConvectionScheme.C multivariateGaussConvectionScheme<Type>::flux
flux               44 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux               62 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux               80 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux               98 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux              117 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux              132 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux              149 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux              166 src/finiteVolume/finiteVolume/fvc/fvcFlux.C flux
flux              883 src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.C flux() const
flux              213 src/finiteVolume/interpolation/surfaceInterpolation/limitedSchemes/limitedSurfaceInterpolationScheme/limitedSurfaceInterpolationScheme.C limitedSurfaceInterpolationScheme<Type>::flux

ごちゃごちゃしてますが,pEqnがfvMatrixのオブジェクトなので,fvMatrix.Cのflux()を見てみます。

fvMatrix.C

 880 template<class Type>
 881 Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> >
 882 Foam::fvMatrix<Type>::
 883 flux() const
 884 {
 885     if (!psi_.mesh().fluxRequired(psi_.name()))
 886     {
 887         FatalErrorIn("fvMatrix<Type>::flux()")
 888             << "flux requested but " << psi_.name()
 889             << " not specified in the fluxRequired sub-dictionary"
 890                " of fvSchemes."
 891             << abort(FatalError);
 892     }
 893 
 894     // construct GeometricField<Type, fvsPatchField, surfaceMesh>
 895     tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > tfieldFlux
 896     (
 897         new GeometricField<Type, fvsPatchField, surfaceMesh>
 898         (
 899             IOobject
 900             (
 901                 "flux("+psi_.name()+')',
 902                 psi_.instance(),
 903                 psi_.mesh(),
 904                 IOobject::NO_READ,
 905                 IOobject::NO_WRITE
 906             ),
 907             psi_.mesh(),
 908             dimensions()
 909         )
 910     );
 911     GeometricField<Type, fvsPatchField, surfaceMesh>& fieldFlux = tfieldFlux();
 912 
 913     for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
 914     {
 915         fieldFlux.internalField().replace
 916         (
 917             cmpt,
 918             lduMatrix::faceH(psi_.internalField().component(cmpt))
 919         );
 920     }
 921 
 922     FieldField<Field, Type> InternalContrib = internalCoeffs_;
 923 
 924     forAll(InternalContrib, patchI)
 925     {
 926         InternalContrib[patchI] =
 927             cmptMultiply
 928             (
 929                 InternalContrib[patchI],
 930                 psi_.boundaryField()[patchI].patchInternalField()
 931             );
 932     }
 933 
 934     FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
 935 
 936     forAll(NeighbourContrib, patchI)
 937     {
 938         if (psi_.boundaryField()[patchI].coupled())
 939         {
 940             NeighbourContrib[patchI] =
 941                 cmptMultiply
 942                 (
 943                     NeighbourContrib[patchI],
 944                     psi_.boundaryField()[patchI].patchNeighbourField()
 945                 );
 946         }
 947     }
 948 
 949     forAll(fieldFlux.boundaryField(), patchI)
 950     {
 951         fieldFlux.boundaryField()[patchI] =
 952             InternalContrib[patchI] - NeighbourContrib[patchI];
 953     }
 954 
 955     if (faceFluxCorrectionPtr_)
 956     {
 957         fieldFlux += *faceFluxCorrectionPtr_;
 958     }
 959 
 960     return tfieldFlux;
 961 }

途中boundaryFieldの量を各パッチで計算したりしています。これは

の資料にあるように,flux()は圧力勾配から来る流束の修正を行っているように見えます。
(上のNozakiさんの資料は大変参考になります)

気になるのが955行目からの以下の部分

 955     if (faceFluxCorrectionPtr_)
 956     {
 957         fieldFlux += *faceFluxCorrectionPtr_;
 958     }

faceFluxCorrectionPtr_の示す値が追加されています。これが何をやっているかを調べてみます。

faceFluxCorrectionPtr_について

faceFluxCorrecitonPtr_のゲッターとしてfaceFluxCorrectionPtr()関数があります。fvMatrix.Hより

fvMatrix.H

 321             //- Return pointer to face-flux non-orthogonal correction field
 322             surfaceTypeFieldPtr& faceFluxCorrectionPtr()
 323             {
 324                 return faceFluxCorrectionPtr_;
 325             }

pisoFoamのfaceFluxCorrectionPtr()関数の詳細について次で調べてみます。

GDBでデバッグしてみる

ここからGDBによるデバッグでfaceFluxCorrectionPtr()関数について調べてみます。

デバッグのためのセットアップ

GDBの結果を見るのにはEmacsが便利だと思います。以下の設定を.emacs.d/init.elや.emacsにします。Emacs+GDBは以下参照。 http://d.hatena.ne.jp/higepon/20090505/p1

(setq gdb-many-windows t) 

EmacsをGUIで起動して,M-x gdbでGDBを起動します。起動時にはpisoFOAMが立ち上がるようにします。OpenFOAMのコードを走らせるときにはLocal bufferを閉じておきます。こうしないとデバッグが途中で停止します。

cavity flowのチュートリアルをもとにしてデバッグします。fvSchemesはそのままです。非直交補正のについて調べるので,laplacianスキーム,snGradスキームがcorrectedになっているか確認して下さい。

fvSchemes

/*--------------------------------*- C++ -*----------------------------------*
| =========                 |                                                 |
|       /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|      /   O peration     | Version:  2.3.0                                 |
|     /    A nd           | Web:      www.OpenFOAM.org                      |
|    /     M anipulation  |                                                 |
*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    location    "system";
    object      fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

ddtSchemes
{
    default         Euler;
}

gradSchemes
{
    default         Gauss linear;
}

divSchemes
{
    default         none;
    div(phi,U)      Gauss limitedLinearV 1;
    div(phi,k)      Gauss limitedLinear 1;
    div(phi,epsilon) Gauss limitedLinear 1;
    div(phi,R)      Gauss limitedLinear 1;
    div(R)          Gauss linear;
    div(phi,nuTilda) Gauss limitedLinear 1;
    div((nuEff*dev(T(grad(U))))) Gauss linear;
}

laplacianSchemes
{
    default         Gauss linear corrected;
}

interpolationSchemes
{
    default         linear;
}

snGradSchemes
{
    default         corrected;
}

fluxRequired
{
    default         no;
    p               ;
}

// ************************************************************************* //

fvSolutionは以下のようにしました。

fvSolution

/*--------------------------------*- C++ -*----------------------------------*
| =========                 |                                                 |
|       /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|      /   O peration     | Version:  2.3.0                                 |
|     /    A nd           | Web:      www.OpenFOAM.org                      |
|    /     M anipulation  |                                                 |
*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    location    "system";
    object      fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

solvers
{
    p
    {
        solver          PCG;
        preconditioner  DIC;
        tolerance       1e-06;
        relTol          0;
    }

    pFinal
    {
        solver          PCG;
        preconditioner  DIC;
        tolerance       1e-06;
        relTol          0;
    }

    U
    {
        solver          smoothSolver;
        smoother        GaussSeidel;
        tolerance       1e-05;
        relTol          0;
    }
}

PISO
{
    nCorrectors     2;
    nNonOrthogonalCorrectors 1;
    pRefCell        0;
    pRefValue       0;
}

メッシュ数が多いとデバッグで見ていくときに何かと大変なので,セル数5個のメッシュを作成しました。以下がそのメッシュを生成するためのblockMeshdictです。blockMeshでメッシュを生成します。初期条件,境界条件は適当に設定します。

blockMeshDict

/*--------------------------------*- C++ -*----------------------------------*
| =========                 |                                                 |
|       /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|      /   O peration     | Version:  2.3.0                                 |
|     /    A nd           | Web:      www.OpenFOAM.org                      |
|    /     M anipulation  |                                                 |
*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

convertToMeters 1;

vertices
(
    (0 0 0)
    (1 0 0)
    (5 5 0)
    (1 5 0)

    (0 0 0.1)
    (1 0 0.1)
    (5 5 0.1)
    (1 5 0.1)
);

blocks
(
    hex (0 1 2 3 4 5 6 7) (1 5 1) simpleGrading (1 1 1)
);

edges
(
);

boundary
(
    wall
    {
        type wall;
        faces
        (
            (1 2 6 5)
        (0 3 7 4)
        );
    }
    inlet
    {
        type patch;
        faces
        (
            (0 1 5 4)
        );
    }
    outlet
    {
        type patch;
        faces
        (
            (2 3 7 6)
        );
    }

    frontAndBack
    {
        type empty;
        faces
        (
            (0 1 2 3)
            (4 5 6 7)
        );
    }
);

mergePatchPairs
(
);

// ************************************************************************* //

GDBでブレークポイントを設定する

実際にブレイクポイントを設定して,pisoFoamのfaceFluxCorrectionPtr()関数の挙動を見てみます。

fvMatrix.Hはsrc/finiteVolume/fvMatrices/fvMatrix/fvMatrix.Hにありますが,計算時に参照されるのはsrc/finiteVolume/lnInclude/fvMatrix.Hです。ここにブレイクポイントを置きます。

runで計算を走らせます。コールスタックを抜き出したのが以下。

#0  Foam::fvMatrix<double>::faceFluxCorrectionPtr (this=0x828fe0) at lnInclude/fvMatrix.H:324
#1  0x00007ffff66f5404 in Foam::fv::gaussLaplacianScheme<double, double>::fvmLaplacian (this=0x827ba0, gamma=..., vf=...) at finiteVolume/laplacianSchemes/gaussLaplacianScheme/gaussLaplacianSchemes.C:117
#2  0x00007ffff6713278 in Foam::fv::laplacianScheme<double, double>::fvmLaplacian (this=0x827ba0, gamma=..., vf=...) at lnInclude/laplacianScheme.C:107
#3  0x000000000045d2c1 in Foam::fvm::laplacian<double, double> (gamma=..., vf=..., name=...) at /home/ishigaki/OpenFOAM/Debug/OpenFOAM-2.3.xdbg/src/finiteVolume/lnInclude/fvmLaplacian.C:219
#4  0x0000000000451497 in Foam::fvm::laplacian<double, double> (gamma=..., vf=...) at /home/ishigaki/OpenFOAM/Debug/OpenFOAM-2.3.xdbg/src/finiteVolume/lnInclude/fvmLaplacian.C:251
#5  0x0000000000448efc in main (argc=1, argv=0x7fffffffbfd8) at pisoFoam.C:102

#1をクリックするとその呼出が表示されます。gaussLapalacianSchemes.Cの該当箇所を見ると,

gaussLapacianSchemes.C

declareFvmLaplacianScalarGamma(scalar);

となっています。これはマクロでその定義はすぐ上にあります。

gaussLapacianSchemes.C

  39 #define declareFvmLaplacianScalarGamma(Type)                                 \
  40                                                                              \
  41 template<>                                                                   \
  42 Foam::tmp<Foam::fvMatrix<Foam::Type> >                                       \
  43 Foam::fv::gaussLaplacianScheme<Foam::Type, Foam::scalar>::fvmLaplacian       \
  44 (                                                                            \
  45     const GeometricField<scalar, fvsPatchField, surfaceMesh>& gamma,         \
  46     const GeometricField<Type, fvPatchField, volMesh>& vf                    \
  47 )                                                                            \
  48 {                                                                            \
  49     const fvMesh& mesh = this->mesh();                                       \
  50                                                                              \
  51     GeometricField<scalar, fvsPatchField, surfaceMesh> gammaMagSf            \
  52     (                                                                        \
  53         gamma*mesh.magSf()                                                   \
  54     );                                                                       \
  55                                                                              \
  56     tmp<fvMatrix<Type> > tfvm = fvmLaplacianUncorrected                      \
  57     (                                                                        \
  58         gammaMagSf,                                                          \
  59         this->tsnGradScheme_().deltaCoeffs(vf),                              \
  60         vf                                                                   \
  61     );                                                                       \
  62     fvMatrix<Type>& fvm = tfvm();                                            \
  63                                                                              \
  64     if (this->tsnGradScheme_().corrected())                                  \
  65     {                                                                        \
  66         if (mesh.fluxRequired(vf.name()))                                    \
  67         {                                                                    \
  68             fvm.faceFluxCorrectionPtr() = new                                \
  69             GeometricField<Type, fvsPatchField, surfaceMesh>                 \
  70             (                                                                \
  71                 gammaMagSf*this->tsnGradScheme_().correction(vf)             \
  72             );                                                               \
  73                                                                              \
  74             fvm.source() -=                                                  \
  75                 mesh.V()*                                                    \
  76                 fvc::div                                                     \
  77                 (                                                            \
  78                     *fvm.faceFluxCorrectionPtr()                             \
  79                 )().internalField();                                         \
  80         }                                                                    \
  81         else                                                                 \
  82         {                                                                    \
  83             fvm.source() -=                                                  \
  84                 mesh.V()*                                                    \
  85                 fvc::div                                                     \
  86                 (                                                            \
  87                     gammaMagSf*this->tsnGradScheme_().correction(vf)         \
  88                 )().internalField();                                         \
  89         }                                                                    \
  90     }                                                                        \
  91                                                                              \
  92     return tfvm;                                                             \
  93 }                                                                            \
  94                                                                              \
  95                                                                              \
  96 template<>                                                                   \
  97 Foam::tmp<Foam::GeometricField<Foam::Type, Foam::fvPatchField, Foam::volMesh> >\
  98 Foam::fv::gaussLaplacianScheme<Foam::Type, Foam::scalar>::fvcLaplacian       \
  99 (                                                                            \
 100     const GeometricField<scalar, fvsPatchField, surfaceMesh>& gamma,         \
 101     const GeometricField<Type, fvPatchField, volMesh>& vf                    \
 102 )                                                                            \
 103 {                                                                            \
 104     const fvMesh& mesh = this->mesh();                                       \
 105                                                                              \
 106     tmp<GeometricField<Type, fvPatchField, volMesh> > tLaplacian             \
 107     (                                                                        \
 108         fvc::div(gamma*this->tsnGradScheme_().snGrad(vf)*mesh.magSf())       \
 109     );                                                                       \
 110                                                                              \
 111     tLaplacian().rename("laplacian(" + gamma.name() + ',' + vf.name() + ')');\
 112                                                                              \
 113     return tLaplacian;                                                       \
 114 }

64行目以降が非直交補正に関係有るところです。fvSchemesでfluxRequiredを指定してあるので,68行目でfaceFluxCorrectionPtr()関数に対して,snGradの非直交補正による補正量が代入されています。74行目でsource項に非直交補正による補正を代入しています。

このようにGDBを使うことで,OpenFOAMの深い関数呼び出しの関係を調べられます。途中マクロ展開で関数呼び出しを実装することがOpenFOAMの場合には多くあります。このため,関数にあたりをつけて,適切にブレイクポイントを設定する必要があります。

次に71行目のcorrection()関数についてGlobalで見てみます。

 71                 gammaMagSf*this->tsnGradScheme_().correction(vf)  

GlobalでtsnGradScheme_().correction()を調べる

correction()関数の候補はたくさん表示されます。ここではcorrectedSnGradを使っているので,correctedSnGrad.Cのcorrection()を見てみます。

実装が以下で,correction()関数の計算には102行目にあるfullGradCorrection()関数が関わっています。

correctedSnGrad.C

  68 template<class Type>
  69 Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> >
  70 Foam::fv::correctedSnGrad<Type>::correction
  71 (
  72     const GeometricField<Type, fvPatchField, volMesh>& vf
  73 ) const
  74 {
  75     const fvMesh& mesh = this->mesh();
  76 
  77     // construct GeometricField<Type, fvsPatchField, surfaceMesh>
  78     tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > tssf
  79     (
  80         new GeometricField<Type, fvsPatchField, surfaceMesh>
  81         (
  82             IOobject
  83             (
  84                 "snGradCorr("+vf.name()+')',
  85                 vf.instance(),
  86                 mesh,
  87                 IOobject::NO_READ,
  88                 IOobject::NO_WRITE
  89             ),
  90             mesh,
  91             vf.dimensions()*mesh.nonOrthDeltaCoeffs().dimensions()
  92         )
  93     );
  94     GeometricField<Type, fvsPatchField, surfaceMesh>& ssf = tssf();
  95 
  96     for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
  97     {
  98         ssf.replace
  99         (
 100             cmpt,
 101             correctedSnGrad<typename pTraits<Type>::cmptType>(mesh)
 102            .fullGradCorrection(vf.component(cmpt))
 103         );
 104     }
 105 
 106     return tssf;
 107 }

fullGradCorrection()はその上に定義されています。

correctedSnGrad.C

  42 template<class Type>
  43 Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> >
  44 Foam::fv::correctedSnGrad<Type>::fullGradCorrection
  45 (
  46     const GeometricField<Type, fvPatchField, volMesh>& vf
  47 ) const
  48 {
  49     const fvMesh& mesh = this->mesh();
  50 
  51     // construct GeometricField<Type, fvsPatchField, surfaceMesh>
  52     tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > tssf =
  53         mesh.nonOrthCorrectionVectors()
  54       & linear<typename outerProduct<vector, Type>::type>(mesh).interpolate
  55         (
  56             gradScheme<Type>::New
  57             (
  58                 mesh,
  59                 mesh.gradScheme("grad(" + vf.name() + ')')
  60             )().grad(vf, "grad(" + vf.name() + ')')
  61         );
  62     tssf().rename("snGradCorr(" + vf.name() + ')');
  63 
  64     return tssf;
  65 }

mesh.nonOrthCorrectionVectors()とlinearで補間されたgradの値の内積を計算しています。これはJasakさんのD論 ( http://powerlab.fsb.hr/ped/kturbo/OpenFOAM/docs/HrvojeJasakPhD.pdf )にある,非直交補正の式と対応します。

以上の内容はNozakiさんの資料にも説明がありますので,そちらを参考にするとわかりやすいです。

まとめ

flux()関数を使った流束の補正とfaceFluxCorrectionPtr()関数から始まる非直交補正の詳細について調べてみました。GDBとGlobalでいろいろたどれるので,使ってみてください。

SphinxでTeXのコマンドを直接使う

ドキュメント作成ツールSphinxで,TeXのコマンドを直接使う方法について。

Sphinx上でLaTeXをつかって,PDF作るのに,sectionごとに改ページしたいとかで,TeXのコマンドを直接使うには

.. raw:: latex

   \newpage

のようにrawディレクティブを使います。\newpageはTeXで改ページするためのコマンド。

普通はhtmlのタグをそのまま使うときなどに使うようですが,TeXにも使えます。

SphinxのLaTeXのフォーマットをいじる

ドキュメント作成システムSphinxが便利という話を書きました。PDFを出力する方法は2つあって,rst2pdfという拡張を使う方法とLaTeXのファイルをつくってPDFに変換する方法です。ここでは自動で生成されるTeXのフォーマットを変更する方法について述べます。Sphinxは1.2.2を使ってます。

LaTeXでPDFを作るにはまずTeXを一式インストールしておく必要があります。これはユーザー会のサイトに詳しい説明があります。

SphinxとLaTeXの設定が終わったとして,いざ日本語のドキュメントを作ってみると,ドキュメントクラスにjsarticleを使っていてもかなり個性的なフォーマットになっています。気に入らないので,SphinxのTeXソース自動生成の設定を変更します。(ただし,まだ試行錯誤中なので,完全に自分の好みにするには至ってません)

まずSphinxのPythonのソースコードを見ます。MacPortsでMacにインストールした場合は/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sphinx/にSphinxのソースコードがあります。他の方法でインストールした場合は適宜探して下さい。

このディレクトリには多くのファイルがあります。 lsで見てみると,

__init__.py config.pyc locale/ setup_command.pyc __init__.pyc directives/ make_mode.py texinputs/ addnodes.py domains/ make_mode.pyc themes/ addnodes.pyc environment.py pycode/ theming.py apidoc.py environment.pyc pygments_styles.py theming.pyc apidoc.pyc errors.py pygments_styles.pyc transforms.py application.py errors.pyc quickstart.py transforms.pyc application.pyc ext/ quickstart.pyc util/ builders/ highlighting.py roles.py versioning.py cmdline.py highlighting.pyc roles.pyc versioning.pyc cmdline.pyc jinja2glue.py search/ websupport/ config.py jinja2glue.pyc setup_command.py writers/

がでます。今回変更するのはconfig.py, quickstart.py, writerのlatex.py, texinputsのsphinx.sty, sphinxhowto.cls, sphinxmanual.clsです。

まず,config.pyです。Sphinxではデフォルトの用紙サイズがletterpaperになっているので,a4paperに変更します。これはconfig.pyの中のlatex関係の設定のところにあります。

– latex_paper_size = (‘letter’, None),

+ latex_paper_size = (‘a4’, None),

latex_paper_sizeの設定を変更します。git diffの様子(-が修正前,+が修正後です。以下同様)
sphinxにはsphinx-quickstartという必要なファイルを一気に作ってくれるコマンドがあります。便利なのですが,LaTeXのreportクラスを使う”manual”がデフォルトになっています。LaTeXのarticle (jsarticle)クラスを使う”howto”をデフォルトにします。これはquickstart.pyにあります。quickstart.py内に自動生成するconf.pyの内容がそのまま書いてあるので,そこのLaTeX関連のところを変更します。

– u’%(author_texescaped_str)s’, ‘manual’),

+ u’%(author_texescaped_str)s’, ‘howto’),

上のように自動生成するタイプを変更します。
次にwriterディレクトリのlatex.pyを変更します。このファイルで,元のreSTファイルからTeXのソースファイルを生成するための設定を行っていると思われます。デフォルトの行間が広すぎ気がするので,行間を狭くするように設定しました。全体の行間指定をどこで行っているのかよくわからないので,とりあえず\baselinestretchのコマンドを挿入するようにしました。\baselinestrechを1以下にすると全体の行間が狭くなります。TeXソースの最初のほうに設定が入るように,BEGIN_DOCを以下のように設定しました。

BEGIN_DOC = r”’

\begin{document}

%(shorthandoff)s

\renewcommand{\baselinestretch}{0.8}

”’

途中にdefault_elementsという設定があるので,とりあえず余計な設定は消しました。ここでもpapersizeとpointsizeがありますが,ここだけ変更しても反映されません。config.pyの修正が必要になります。

default_elements = {

‘papersize’: ‘a4paper’,

‘pointsize’: ’10pt’,

‘classoptions’: ”,

‘extraclassoptions’: ”,

‘inputenc’: ‘\\usepackage[utf8]{inputenc}’,

‘utf8extra’: ‘\\DeclareUnicodeCharacter{00A0}{\\nobreakspace}’,

‘cmappkg’: ‘\\usepackage{cmap}’,

‘fontenc’: ‘\\usepackage[T1]{fontenc}’,

‘babel’: ‘\\usepackage{babel}’,

‘fontpkg’: ”,

‘fncychap’: ”,

‘longtable’: ‘\\usepackage{longtable}’,

‘preamble’: ”,

‘title’: ”,

‘date’: ”,

‘release’: ”,

‘author’: ”,

‘logo’: ”,

‘releasename’: ‘Release’,

‘makeindex’: ‘\\makeindex’,

‘shorthandoff’: ”,

‘maketitle’: ‘\\maketitle’,

‘tableofcontents’: ‘\\tableofcontents’,

‘footer’: ”,

‘printindex’: ‘\\printindex’,

‘transition’: ‘\n\n\\bigskip\\hrule{}\\bigskip\n\n’,

}

TeXのドキュメントクラスにjsarticle, jsbookを使いたいので,以下のようにしました。

if document.settings.docclass == ‘howto’:

docclass = builder.config.latex_docclass.get(‘howto’, ‘jsarticle’)

else:

docclass = builder.config.latex_docclass.get(‘manual’, ‘jsbook’)

Sphinxで自動生成されたLaTeXのソースファイルが参照している,sphinx.sty, sphinxhowto.cls, sphinxmanual.clsを変更します。ドキュメントをhowtoにすると,sphinxhowto.cls,manualにするとsphinxmanual.clsが使われます。とりあえずここではsphinxhowto.clsを使うとします。manualの場合は適宜読み替えて下さい。
ページ番号が表示されるようにpagestyleをplainにします。sphinx.styにあります。

\pagestyle{plain}

最初のページのページスタイルはsphinxhowto.clsで指定していますので,それを修正します。ページスタイルが全体で統一されるように81行目あたりの\thispagestyleをコメントアウト。

%\thispagestyle{empty}

デフォルトだと,howtoでsection, subsection, manualでchapter, sectionにしか番号がふられないので,番号がふられる階層を深くします。sphinxhowto.clsのsecnumdepthを変えます。

% Set some sane defaults for section numbering depth and TOC depth. You can

% reset these counters in your preamble.

%

-\setcounter{secnumdepth}{2}

+\setcounter{secnumdepth}{3}

タイトルと目次を変更します。sphinxhowto.clsを修正します。デフォルトの設定だとタイトル部分が広すぎるので,狭くなるように文字サイズを縮小して,リリース番号を消去しました。仕切りの横罫線も消すようにしました。

% Change the title page to look a bit better, and fit in with the fncychap

% “Bjarne” style a bit better.

%

\renewcommand{\maketitle}{

% \rule{\textwidth}{1pt}

\ifsphinxpdfoutput

\begingroup

% These \defs are required to deal with multi-line authors; it

% changes \\ to ‘, ‘ (comma-space), making it pass muster for

% generating document info in the PDF file.

\def\\{, }

\def\and{and }

\pdfinfo{

/Author (\@author)

/Title (\@title)

}

\endgroup

\fi

\begin{center}

\sphinxlogo%

{\Large \@title} \par

% {\em\large\py@HeaderFamily \py@release\releaseinfo} \par

% \vspace{20pt}

\end{center}

\begin{flushright}

\@date \hspace{3zw} \@author \par

% {\large

% \begin{tabular}[t]{c}

% \@author

% \end{tabular}} \par

%% \vspace{2pt}

\py@authoraddress \par

\end{flushright}

目次の横罫線を消去。

\let\py@OldTableofcontents=\tableofcontents

\renewcommand{\tableofcontents}{

\begingroup

\parskip = 0mm

\py@OldTableofcontents

\endgroup

% \rule{\textwidth}{1pt}

\vspace{12pt}

}

結局のところ,Sphinxが生成するLaTeXのフォーマットの変更はwriterのlatex.py, texinputsのsphinx.sty, sphinxhowto.cls, sphinxmanual.clsの修正で行えます。これらの修正はTeXの知識が必要になってきます。今回書いたことがSphinxユーザーの役に立てば幸いです。

疑問なこともまだあります。情報あれば教えて下さい。

  • languageをjaにすると日本語設定になる。”release”が「リリース」になったり,日付が「年月日」になったりする。この変更をはどこでしているのか?
  • 行間の設定はどこでしているのか?