オブジェクト指向型プログラミング
では、ここからオブジェクト指向でコードを修正していきます。
段階を踏んでコードを書いていくことにします。
Step1:x方向とy方向の離散化
$x$方向と$y$方向の空間離散化を行います。
- Mesh.h:変数の定義
- Mesh.cpp:関数処理の定義
Mesh.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #ifndef MESH_H #define MESH_H #include "Mesh.h" #include <vector> using std::vector; class Mesh { public: Mesh(); //constructor Mesh(int&, double&); Mesh(int&, int&, double&, double&); virtual ~Mesh(); //deconstructor int nrows, ncols; //分割数 double lengthx, lengthy; //x方向長さ double dx, dy; //分割幅 vector<double> xpts; //x座標 vector<double> ypts; //y座標 //add void discritized1dgrid(vector<double>&, double&); //x[i], y[i]の作成 //add end }; #endif //MESH_H |
Mesh.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include "Mesh.h" #include <iostream> Mesh::Mesh() { } Mesh::Mesh(int& n, double& txlengthx) : nrows(n),//x分割数 lengthx(txlengthx),//x方向長さ xpts(nrows, 0.0)//vector(要素数, 値) { dx = lengthx / (nrows - 1); discritized1dgrid(xpts, dx); //add } Mesh::Mesh(int& nrows_, int& ncols_, double& lengthx_, double& lengthy_) : nrows(nrows_),//x分割数 ncols(ncols_),//y分割数 lengthx(lengthx_),//x方向長さ lengthy(lengthy_),//y方向長さ xpts(nrows, 0.0),//vector(要素数, 値) ypts(nrows, 0.0) //vector(要素数, 値) { dx = lengthx / (nrows - 1); dy = lengthx / (nrows - 1); discritized1dgrid(xpts, dx); discritized1dgrid(ypts, dy); } void Mesh::discritized1dgrid(vector<double>& vec, double& dx_) { for (int i = 1; i < vec.size(); i++) //vec[0]=0なのでi=1からループする { vec[i] = vec[i - 1] + dx_; } } Mesh::~Mesh() { } |
これで空間の離散化の定義ができたのでmain.cppでMeshクラスをインスタンス化して出力してみましょう。
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <iostream> #include <vector> #include "Mesh.h" //メッシュ設定 /* * #include "Fields.h" //場の定義 #include "Diff1d.h" //空間微分 #include "Solution1D.h" //時間ループ #include "FileWriter.h" //ファイル出力 #include "PrintVector.h" //場のprint文 */ using namespace std; using std::vector; int main() { int nx = 20, ny = 20; double lengthx = 2.0, lengthy = 2.0; Mesh mesh2d_(nx, ny, lengthx, lengthy);//Meshクラスのインスタンス化 cout << "dx = " << mesh2d_.dx << endl; for (int i = 0; i < mesh2d_.xpts.size(); i++) { cout << "mesh2d_.xpts[" << i << "] = " << mesh2d_.xpts[i] << endl; } return 0; } |
今回は「#include “Mesh.h” //メッシュ設定 」しかインクルードとして必要ないので、その他のヘッダーファイルはコメントアウトしています。
【結果】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | dx = 0.105263 mesh2d_.xpts[0] = 0 mesh2d_.xpts[1] = 0.105263 mesh2d_.xpts[2] = 0.210526 mesh2d_.xpts[3] = 0.315789 mesh2d_.xpts[4] = 0.421053 mesh2d_.xpts[5] = 0.526316 mesh2d_.xpts[6] = 0.631579 mesh2d_.xpts[7] = 0.736842 mesh2d_.xpts[8] = 0.842105 mesh2d_.xpts[9] = 0.947368 mesh2d_.xpts[10] = 1.05263 mesh2d_.xpts[11] = 1.15789 mesh2d_.xpts[12] = 1.26316 mesh2d_.xpts[13] = 1.36842 mesh2d_.xpts[14] = 1.47368 mesh2d_.xpts[15] = 1.57895 mesh2d_.xpts[16] = 1.68421 mesh2d_.xpts[17] = 1.78947 mesh2d_.xpts[18] = 1.89474 mesh2d_.xpts[19] = 2 |
エラーがエラーがなければx方向の離散化の結果が出力されます。
Step2:速度ベクトルU,Vの値の設定
Fields.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #ifndef FIELDS_H #define FIELDS_H #include "Mesh.h" #include <vector> using std::vector; class Fields { public: Fields();//constructor virtual ~Fields(); //deconstructor typedef vector<Fields> vectorField1d; typedef vector<vector<Fields> > vectorField2d; double x,y; //座標 double value; //流速の値 Fields::vectorField1d pass1DGridinfomation(Fields::vectorField1d&, vector<double>&); Fields::vectorField2d pass2DGridinfomation(Fields::vectorField2d&, vector<double>&, vector<double>&); //演算子のオーバーロード(1d) friend Fields::vectorField1d operator+(const Fields::vectorField1d&, const Fields::vectorField1d&); friend Fields::vectorField1d operator-(const Fields::vectorField1d&, const Fields::vectorField1d&); friend Fields::vectorField1d operator&&(const Fields::vectorField1d&, const Fields::vectorField1d&); friend Fields::vectorField1d operator*(const double&, const Fields::vectorField1d&); friend Fields::vectorField1d operator*(const Fields::vectorField1d&, const double&); //演算子のオーバーロード(2d) friend Fields::vectorField2d operator+(const Fields::vectorField2d&, const Fields::vectorField2d&); friend Fields::vectorField2d operator-(const Fields::vectorField2d&, const Fields::vectorField2d&); friend Fields::vectorField2d operator&&(const Fields::vectorField2d&, const Fields::vectorField2d&); friend Fields::vectorField2d operator*(const double&, const Fields::vectorField2d&); friend Fields::vectorField2d operator*(const Fields::vectorField2d&, const double&); }; #endif //FIELDS_H |
2次元ベクトルを定義するvectorコンテナvectorField2dの定義と演算子のオーバーロードの定義を追加しました。
Fields.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include "Fields.h" #include <iostream> Fields::Fields() : x(0.0), y(0.0), value(2.0) { } Fields::vectorField1d Fields::pass1DGridinfomation(Fields::vectorField1d& vec, vector<double>& xpts_) { /* typedef vector<Fields> vectorField1d; double value; double x1d; */ for (int i = 0; i < vec.size(); i++) { vec[i].x = xpts_[i]; } return vec; } Fields::vectorField2d Fields::pass2DGridinfomation(Fields::vectorField2d& vec, vector<double>& xpts_, vector<double>& ypts_) { for (int i = 0; i < vec.size(); i++) { double xpos = xpts_[i]; for (int j = 0; j < vec[i].size(); j++) { double ypos = ypts_[j]; vec[i][j].x = xpos; vec[i][j].y = ypos; } } return vec; } Fields::vectorField1d operator+(const Fields::vectorField1d& vecA, const Fields::vectorField1d& vecB) { Fields::vectorField1d temp = vecA; for (int i = 0; i < vecA.size(); i++) { temp[i].value += vecB[i].value; } return temp; } Fields::vectorField1d operator-(const Fields::vectorField1d& vecA, const Fields::vectorField1d& vecB) { Fields::vectorField1d temp = vecA; for (int i = 0; i < vecA.size(); i++) { temp[i].value -= vecB[i].value; } return temp; } Fields::vectorField1d operator&&(const Fields::vectorField1d& vecA, const Fields::vectorField1d& vecB) { Fields::vectorField1d temp = vecA; for (int i = 0; i < vecA.size(); i++) { temp[i].value *= vecB[i].value; } return temp; } Fields::vectorField1d operator*(const double& dbvalue, const Fields::vectorField1d& vecB) { Fields::vectorField1d temp = vecB; for (int i = 0; i < vecB.size(); i++) { temp[i].value = dbvalue * vecB[i].value; } return temp; } Fields::vectorField1d operator*(const Fields::vectorField1d& vecB, const double& dbvalue) { Fields::vectorField1d temp = vecB; for (int i = 0; i < vecB.size(); i++) { temp[i].value = dbvalue * vecB[i].value; } return temp; } Fields::~Fields() { } |
ベクトル場を出力するためにPrintVector.hを作成し、以下としました。
PrintVector.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #include <iostream> #include <string> #include "Fields.h" void print1dvec(vector<double>& vec, std::string name) { std::cout << "======= print1dvec ======" << std::endl; for (int i = 0; i < vec.size(); i++) { std::cout << name << "[" << i << "] = " << vec[i] << std::endl; } std::cout << "======= end print1dvec ======" << std::endl; } void print1dfield(Fields::vectorField1d& field, std::string name) { std::cout << "======= print1dfield ======" << std::endl; for (int i = 0; i < field.size(); i++) { std::cout << name << "[" << i << "] = " << field[i].value << std::endl;; } std::cout << "======= end print1dfield ======" << std::endl; } void print2dfield(Fields::vectorField2d& field, std::string name) { std::cout << "======= print2dfield =" << name << "=====" << std::endl; /* for (int i = 0; i < field.size(); i++) { for (int j = 0; j < field[i].size(); j++) { std::cout << name << "[" << i << "][" << j << "].x = " << field[i][j].x << std::endl; } } */ for (int i = 0; i < field.size(); i++) { for (int j = 0; j < field[i].size(); j++) { std::cout << field[i][j].value << " "; } std::cout << std::endl; } std::cout << "======= end print2dfield ======" << std::endl; } |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include <iostream> #include <vector> #include "Mesh.h" //メッシュ設定 #include "Fields.h" //場の定義 #include "PrintVector.h" //場のprint文 /* #include "Diff1d.h" //空間微分 #include "Solution1D.h" //時間ループ #include "FileWriter.h" //ファイル出力 */ using namespace std; using std::vector; int main() { int nx = 20, ny = 20; double lengthx = 2.0, lengthy = 2.0; Mesh mesh2d_(nx, ny, lengthx, lengthy);//Meshクラスのインスタンス化 Fields FieldsOperations; Fields::vectorField2d U(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d Unew(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d V(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d Vnew(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d P(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d Pnew(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d b(mesh2d_.nrows, vector<Fields>(ny)); U = FieldsOperations.pass2DGridinfomation(U, mesh2d_.xpts, mesh2d_.ypts); Unew = FieldsOperations.pass2DGridinfomation(Unew, mesh2d_.xpts, mesh2d_.ypts); V = FieldsOperations.pass2DGridinfomation(V, mesh2d_.xpts, mesh2d_.ypts); Vnew = FieldsOperations.pass2DGridinfomation(Vnew, mesh2d_.xpts, mesh2d_.ypts); P = FieldsOperations.pass2DGridinfomation(U, mesh2d_.xpts, mesh2d_.ypts); Pnew = FieldsOperations.pass2DGridinfomation(Pnew, mesh2d_.xpts, mesh2d_.ypts); b = FieldsOperations.pass2DGridinfomation(b, mesh2d_.xpts, mesh2d_.ypts); print2dfield(U, "U"); return 0; } |
【結果】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ======= print2dfield =U===== 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ======= end print2dfield ====== |
しかし、「Fields FieldsOperations;」でインスタンス化を行って以降の記述が冗長なので「createFields.h」に書き込んでmain.cppで読み込むようにします。
createFields.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Fields FieldsOperations; Fields::vectorField2d U(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d Unew(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d V(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d Vnew(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d P(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d Pnew(mesh2d_.nrows, vector<Fields>(ny)); Fields::vectorField2d b(mesh2d_.nrows, vector<Fields>(ny)); U = FieldsOperations.pass2DGridinfomation(U, mesh2d_.xpts, mesh2d_.ypts); Unew = FieldsOperations.pass2DGridinfomation(Unew, mesh2d_.xpts, mesh2d_.ypts); V = FieldsOperations.pass2DGridinfomation(V, mesh2d_.xpts, mesh2d_.ypts); Vnew = FieldsOperations.pass2DGridinfomation(Vnew, mesh2d_.xpts, mesh2d_.ypts); P = FieldsOperations.pass2DGridinfomation(U, mesh2d_.xpts, mesh2d_.ypts); Pnew = FieldsOperations.pass2DGridinfomation(Pnew, mesh2d_.xpts, mesh2d_.ypts); b = FieldsOperations.pass2DGridinfomation(b, mesh2d_.xpts, mesh2d_.ypts); |
main.cpp(修正)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include <iostream> #include <vector> #include "Mesh.h" //メッシュ設定 #include "Fields.h" //場の定義 #include "PrintVector.h" //場のprint文 /* #include "Diff1d.h" //空間微分 #include "Solution1D.h" //時間ループ #include "FileWriter.h" //ファイル出力 */ using namespace std; using std::vector; int main() { int nx = 20, ny = 20; double lengthx = 2.0, lengthy = 2.0; Mesh mesh2d_(nx, ny, lengthx, lengthy);//Meshクラスのインスタンス化 /* U,V,P,bの定義 */ #include "creatFields.h" print2dfield(U, "U"); return 0; } |
こちらの方がmainファイルがすっきりしますね。