メインコンテンツに移動

直方格子

ここでは,多数の等分割の直方体の格子から構成されるデータの時間発展を記述する例を示します.詳細はXCodeでVTK楽園を参照

概要

//ヘッダー{{{
#include <boost/filesystem.hpp>  //      フォルダーの操作を行うので, boostを使います.
#include <iostream>                    //     この辺は,おなじみですよね♪
#include <vector>                        //      もちろんSTLを使っても大丈夫です. ただしMicrosoft-CLIを使って良いか?不明です.
#include <cmath>
#include <sstream>
#include <vtkVersion.h>               //     VTKのヘッダーです
#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkImageData.h>         //       等分割直方格子の領域を使います
#include <vtkMultiBlockDataSet.h>          //   1ケースに多数の領域が含まれる場合,これが必要
#include <vtkXMLMultiBlockDataWriter.h>//   多数の領域を一発で保存する
#include <vtkDoubleArray.h>       //      セルや格子点に取り付ける物理量を定義します
#include <vtkPointData.h>          //       格子点のデータ
#include <vtkCellData.h>            //       セルのデータ
#include <vtkCell.h>                   //       セル
//}}}
int main()      //      複雑形状を構成  {{{
{
+---  7 行:時間ステップ----------------------------------------------------------------------------------------------------
+--- 12 行:フォルダーを作成------------------------------------------------------------------------------------------------
        //      時間ステップだけ作業する
        for(unsigned int nt=1;nt<=ntMax;nt++)
        {
       //      この時間のデータを保存するMultiBlockDataSetを定義
                vtkSmartPointer<vtkMultiBlockDataSet> multi=vtkSmartPointer<vtkMultiBlockDataSet>::New();
                //      領域達を定義    {{{
                for(int idom=0;idom<領域総数;idom++)
                {
+---- 22 行:ImageData形状を定義--------------------------------------------------------------------------------------------
+----  3 行:MultiBlockDataSetに追加----------------------------------------------------------------------------------------
+---- 35 行:ImageDataに物理量を定義 ---------------------------------------------------------------------------------------
                        std::cout << "作製:" << idom << std::endl;
                }//}}}
+--- 16 行:ファイルに保存 -------------------------------------------------------------------------------------------------
        }
        return EXIT_SUCCESS;
}//}}}
 

時間ステップの設定およびフォルダー作成

        //      時間ステップ{{{
        unsigned int ntMax=100;
        boost::filesystem::path folderName("myDSMC");
        std::string stemName="time";    //      ファイル名は    folderName/stemName時間ステップ(N桁の数字)extName
        std::string extName=".vtm";       //      複数領域では,拡張子は .vtm です
        int fileN=4;                               //       まあテストなので, 4桁あれば十分
        //}}}
        //      フォルダーを作成(既存のフォルダーは黙って削除){{{
        try
        {
                if (boost::filesystem::exists(folderName)) boost::filesystem::remove_all(folderName);
                boost::filesystem::create_directory(folderName);
        }
        catch (std::exception& e)
        {
                std::cerr << folderName << "フォルダがエラー:" << e.what() << std::endl;
                return 1;
        }//}}}
 

ImageData形状を定義

                        //      ImageData形状を定義{{{
                        typedef vtkSmartPointer<vtkImageData> ImageDataPtr; //行が長くなるのでtypedef
                        ImageDataPtr image=ImageDataPtr::New();                  //上のtypedefを用いてImageDataを作成
                        image->SetSpacing(0.05,0.05,0.05); // もちろんX-Y-Z方向の格子の間隔
                        int imageExtent[6]={0,0,0,0,0,0};      //  あとで各領域の原点や格子点数を設定します
                        double imageOrigin[3]={0.,0.,0.};
                        switch (idom)
                        {
                        case 0: //      領域0のパラメータを設定
                                imageExtent[1]=20;      imageExtent[3]=10;      imageExtent[5]=10;
                                imageOrigin[0]=0;       imageOrigin[1]=0;       imageOrigin[2]=0;
                                break;
                                ;;
                        case 1: //      領域1のパラメータを設定
                                imageExtent[1]=10;      imageExtent[3]=40;      imageExtent[5]=40;
                                imageOrigin[0]=1;       imageOrigin[1]=-0.5;    imageOrigin[2]=-0.5;
                                break;
                                ;;
           //     その他の領域も必要なら書く
                        }
                        image->SetExtent(imageExtent);
                        image->SetOrigin(imageOrigin);
                        //}}}
 

MultiBlockDataSetに追加

                        //      MultiBlockDataSetに追加{{{
                        multi->SetBlock(idom,image);
                        //}}}

ImageDataに物理量を定義

                        //      ImageDataに物理量を定義 {{{ // ここでは,セルに物理量を準備してみましょう.格子点の場合 Cell をPointに書き換えます
                        vtkDoubleArray* pressure = vtkDoubleArray::New();   //  圧力の配列を作成
                        vtkDoubleArray* velocity = vtkDoubleArray::New();     //  流速の配列を作成
                        pressure->SetNumberOfComponents(0);  // 圧力はスケーラなので成分は無いっす
                        velocity->SetNumberOfComponents(3);   //  流速はベクタで3成分すね
                        pressure->SetName("p");                       //  名前を付けておきませう
                        velocity->SetName("v");
                        velocity->SetComponentName(0,"v_1");
                        velocity->SetComponentName(1,"v_2");
                        velocity->SetComponentName(2,"v_3");
                        pressure->SetNumberOfTuples(image->GetNumberOfCells());   // 圧力の要素数は, セルの総数
                        velocity->SetNumberOfTuples(image->GetNumberOfCells());       // 流速の要素数は, セルの総数
                        image->GetCellData()->AddArray(pressure);                               //領域のセルデータに,さっき作った圧力を追加
                        image->GetCellData()->AddArray(velocity);                                 // さっき作った流速を追加
                        //      まあ,テストのために値を定義しておきましょう
                        double* weight = new double [image->GetMaxCellSize()];
                        for(vtkIdType cellId=0; cellId < image->GetNumberOfCells(); cellId++)
                        {       //  セルの中心座標を取得します. 格子点の場合には image->GetPoint(pointId,Xcoord)で取得できますが, セルは面倒
                                vtkCell* cell=image->GetCell(cellId);
                                double Pcoord[3]; // セルは体積要素ですので,内部にいちいち曲線座標が存在します
                                int subId= cell->GetParametricCenter(Pcoord); //曲線座標表示で, セルの中心を求めます.
                                                    // セルは複合セルであったりするので, subIdも取得します(普通はsubId=0)
                                double Xcoord[3];
                                cell->EvaluateLocation(subId,Pcoord,Xcoord,weight); // ようやく, セル中心のXcoordが取得できました♪
                                double T=pow(Xcoord[0],2)+pow(Xcoord[1],2)+pow(Xcoord[2],2); // てきとーです.サンプルですので
                                double p=exp(-0.1*T);
                                pressure->SetValue(cellId,p);              // まあ,要するにこうやって値を設定するわけ
                                double v1=0.1;
                                double v2=p*Xcoord[1];
                                double v3=-0.1;
                                velocity->SetComponent(cellId,0,v1);
                                velocity->SetComponent(cellId,1,v2);
                                velocity->SetComponent(cellId,2,v3);
                        }
                        //}}}
                        std::cout << "作製:" << idom << std::endl;
                }//}}}
 

ファイルに保存

                //      ファイルに保存  {{{
                std::stringstream       sst;
                sst<< stemName <<  std::setfill('0') <<  std::setw(fileN) << nt << extName;
                boost::filesystem::path fileName(sst.str());
                fileName = folderName / fileName;
                //      保存を実行
                vtkSmartPointer<vtkXMLMultiBlockDataWriter> writer = vtkSmartPointer<vtkXMLMultiBlockDataWriter>::New();
                writer->SetFileName(fileName.c_str());    // ここでファイル名を設定
#if VTK_MAJOR_VERSION <= 5  // 2012年現在,たまたま移行期なので・・・今はまだVersion5です
                writer->SetInputConnection(multi->GetProducerPort());
#else
                writer->SetInputData(multi);
#endif
                writer->Write();                                     //  これで大量のファイルが生成されます
                //}}}

コンパイル

上記プログラムは, 次のようにコンパイルできます]

ic++ --boost --vtk myProgram.cxx -o myExecutable