#if !defined(_ltank_h) #define _ltank_h #include <stdio.h> #include <time.h> #include "element.h" // クラス Element の定義. #include "p_tmp.h" // テンプレートクラス Receive, Send の定義. extern "C"{ #include <math.h> // exp を使う } // クラス Ltank の定義 class Ltank : public Element { // (0) クラス Element を継承します。 // 1. 送信端子, 受信端子の作成. // 受信端子. protected: // (1) 受信端子をデータメンバとして宣言します。 Receive<double> rp; // 入力 I(t) を受けとる端子 // (2) 受信端子を登録する関数 void Register_receive_ports(void) を定 // 義します。 void Register_receive_ports(void) { Register((void*) &rp); } // 送信端子. protected: // (3) 送信端子をデータメンバとして宣言します。 Send<double> sp0, sp1; // sp0: 側方流出孔からの流出強度を出力する端子 // sp1: タンク底からの流出強度を出力する端子 // (4) 送信端子を登録する関数 void Register_send_ports(void) を定義 // します。 void Register_send_ports(void) { Register((void*) &sp0); Register((void*) &sp1); } // 2. パラメータ, 状態量. // パラメータ. // (5) パラメタをデータメンバとして宣言します。 protected: double alpha; // パラメタ $\alpha$ double beta; // パラメタ $\beta$ double lambda; // パラメタ $\lambda$ // 状態量. // (6) 状態量をデータメンバとして宣言します。 protected: double s; // 貯水量 $s(t)$ // 作業用変数 // (7) 必要なら作業用に変数を宣言します。 protected: double c1, c2; // パラメタ $c_1$, $c_2$ time_t dt; // 時間間隔 $\Delta t$ double y; // 時刻 t の流入強度 I(t) // パラメータの設定, 状態量の初期化. public: // (8) パラメタをファイルから読み込む関数 void Set_parameter(FILE* // fp) を定義します。 void Set_parameter(FILE* fp) { const int BUFFLEN = 256; char bf[BUFFLEN]; Get_line(fp, bf, BUFFLEN, __FILE__, __LINE__); // # で始まる行,空白行は読み飛ばします。 sscanf(bf, "%lf %lf %lf", &alpha, &beta, &lambda); dt = (time_t)(lambda/(alpha + beta)); lambda = dt * (alpha + beta); // $\lambda = \Delta t /(\alpha + \beta)$ c1 = exp(-lambda); // $c_1 = \exp\{-\lambda\}$ c2 = (1.0 - c1)/(alpha + beta); // $c_2 = (1 - c_1) / (\alpha +\beta)$ } // (9) パラメタを引数で与える関数を定義します。 void Set_parameter(double alphaX, double betaX, double lambdaX) { alpha = alphaX; beta = betaX; lambda = lambdaX; dt = (time_t)(lambda/(alpha + beta)); lambda = dt * (alpha + beta); // $\lambda = \Delta t /(\alpha + \beta)$ c1 = exp(-lambda); // $c_1 = \exp\{-\lambda\}$ c2 = (1.0 - c1)/(alpha + beta); // $c_2 = (1 - c_1) / (\alpha +\beta)$ } //; 状態量の初期化. public: //; (10) 初期値をファイルから読み込む関数 void // Set_initial_state(FILE* fp) を定義します。(必須) void Set_initial_state(FILE* fp) { const int BUFFLEN = 256; char bf[BUFFLEN]; Get_line(fp, pb, BUFFLEN, __FILE__, __LINE__); // # で始まる行,空白行は読み飛ばします。 sscanf(bf, "%ld %lf", ¤t_time, &s); } // (11) 初期値を引数で与える関数を定義します。(必須ではありませんが, // 定義するのが望ましい。部分系モデルを作成するときに役立ちます。) void Set_initial_state(time_t ct, double st) { if (ct > 0) current_time = ct; s = st; } // 状態量の保存 public: // (12) 最終状態をファイルに書く関数 Save_terminal_state(FILE* fp) // を定義します。(必須) void Save_terminal_state(FILE* fp); // (13) 最終状態を引数で指定する変数にコピーして戻る関数を定義します。 // (必須ではありませんが,定義するのが望ましい。部分系モデルを作成す // るときに役立ちます。) void Save_terminal_state(time_t& ct, double& st) { ct = current_time; st = s; } // 3. 初期化関数, コンストラクタ, デストラクタ. private: //; (14) 安全のため,要素の代入を禁止するために,代入演算子を宣言だけ //; して,実装しません。 Ltank& operator=(const Ltank& rhs); public: //; (15) コンストラクタを定義します。 Boolean Init(char* o_name, int o_num, char* p_str = NULL) { return Element::Init(o_name, o_num, 0, p_str); } Ltank(char* o_name, int o_num, char* p_str = NULL) : Element(), rp("rp", 0), sp0("sp", 0), sp1("sp", 1) { class_name = "Ltank"; Init(o_name, o_num, p_str); } Ltank(void) : Element(), rp("rp", 0), //; 受信端子 rp, 0 sp0("sp", 0), //; 送信端子 sp, 0 sp1("sp", 1) //; 送信端子 sp, 1 { class_name = "Ltank"; } ~Ltank(void) {} // 4. 演算機能. //; (16) 初期出力関数 Boolean Initial_output(void) を定義します。 //; データの単位を Set_comment_string で記入しておきます。 Boolean Initial_output(void) { if (rp.Can_you_get_data(current_tim) == NO) return NO; y = rp.Get_data(current_time); double data = alpha * s; sp0.Set_comment_string("time(sec) discharge height(m/sec)"); sp0.Send_data(current_time, data); data = beta * s; sp1.Set_comment_string("time(sec) storage depth(m)"); sp1.Send_data(current_time, data); // printf("Ltank::Initial_output done\n"); return YES; } // (17) 計算時間間隔を計算する関数 time_t Calculate_time_step(void) // を定義します。 time_t Calculate_time_step(void) { return dt; } // (18) 計算をすることができるかを判断する関数 // Boolean Can_you_calculate(void) を定義します。 Boolean Can_you_calculate(void) { return Can_you_calculate0(); } // (19) 一ステップの計算をする関数 Boolean Calculate(void) を定義し // ます。 Boolean Calculate(void); // (20) 初期化後の一連の計算・出力作業をする関数 Boolean Work(void) // を定義します。 Boolean Work(void) { return Work0(); } double Get_mean_data(void); // 入力の平均値を計算 }; #endif // ! _ltank_h