next up previous
: 2.4 Ltank の実装 ltank.cc : 2. 要素モデルの作成例 : 2.2 要素モデルの仕様

2.3 ヘッダファイル ltank.h


#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", &current_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



Michiharu SHIIBA
平成12年10月13日