github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/eebslib.go (about)

     1  package eeslism
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"os"
     7  	"strings"
     8  )
     9  
    10  // 外表面方位デ-タの入力
    11  func Exsfdata(section *EeTokens, dsn string, Exsf *EXSFS, Schdl *SCHDL, Simc *SIMCONTL) {
    12  	var ename string
    13  	//var st *string
    14  	var dt, wa, wb, swa, cwa, swb, cwb float64
    15  	var k int
    16  	var err error
    17  
    18  	// 外表面総合伝達率のデフォルト値
    19  	Exsf.Alosch = envptr(fmt.Sprintf("%f", ALO), Simc, nil, nil, nil)
    20  	Exsf.Alotype = Alotype_Fix // 固定値
    21  	Exsf.Exs = make([]*EXSF, 0)
    22  
    23  	var dfrg float64 // 全面地物の日射反射率(デフォルト値)
    24  
    25  	// 最初の行: 全体に対する設定
    26  	line := section.GetLogicalLine()
    27  	for _, s := range line {
    28  		if strings.HasPrefix(s, "alo=") {
    29  			// 外表面総合伝達率[W/m2K]
    30  			//
    31  			value := s[4:]
    32  			if value == "Calc" {
    33  				// 風速から計算する
    34  				Exsf.Alotype = Alotype_V
    35  			} else if k, err = idsch(value, Schdl.Sch, ""); err == nil {
    36  				// スケジュールに基づいて値を変化させる
    37  				Exsf.Alosch = &Schdl.Val[k]
    38  				Exsf.Alotype = Alotype_Schedule
    39  			} else {
    40  				// 数値 or 内部変数名
    41  				Exsf.Alosch = envptr(value, Simc, nil, nil, nil)
    42  				if Exsf.Alosch != nil {
    43  					Exsf.Alotype = Alotype_Schedule
    44  				}
    45  			}
    46  		} else if strings.HasPrefix(s, "r=") {
    47  			// 全面地物の日射反射率[-]
    48  			//
    49  			value := s[2:]
    50  			dfrg, err = readFloat(value)
    51  			if err != nil || dfrg < 0.0 || dfrg > 1.0 {
    52  				fmt.Fprintf(os.Stderr, "%s の設置値が不適切です", s)
    53  				os.Exit(1)
    54  			}
    55  		}
    56  	}
    57  
    58  	for section.IsEnd() == false {
    59  		// 論理行を取得
    60  		line = section.GetLogicalLine()
    61  
    62  		// "*"が出てきたら終了
    63  		if line[0] == "*" {
    64  			break
    65  		}
    66  
    67  		// 外表面データの初期化
    68  		ex := new(EXSF)
    69  		Exsfinit(ex)
    70  		ex.Name = line[0]         // 外表面名
    71  		ex.Alotype = Exsf.Alotype // 外表面総合伝達率の設定方法=デフォルト値
    72  		ex.Alo = Exsf.Alosch      // 外表面総合伝達率=デフォルト値
    73  
    74  		// 特殊名 Hor, EarchSf への対応
    75  		if line[0] == "Hor" {
    76  			// 水平面なので、傾斜角は0
    77  			ex.Wb = 0.0
    78  		} else if line[0] == "EarthSf" {
    79  			// 地表面境界を含むことをフラグに書き込む
    80  			Exsf.EarthSrfFlg = true
    81  
    82  			// 種別: 地表面
    83  			ex.Typ = EXSFType_e
    84  		} else {
    85  			// 通常の表面の定義
    86  			ex.Wb = 90.0 // 傾斜角=90°
    87  			ex.Rg = dfrg // 日射反射率=デフォルト値
    88  		}
    89  
    90  		for _, s := range line[1:] {
    91  			st := strings.IndexRune(s, '=')
    92  
    93  			key := s[:st]
    94  			value := s[st+1:]
    95  
    96  			if key == "a" {
    97  				// *** 方位角 a***
    98  				//
    99  				var err error
   100  				if dt, err = readFloat(value); err == nil {
   101  					// 数値指定
   102  					ex.Wa = dt
   103  				} else {
   104  					var dir rune = ' '
   105  					if strings.Contains(s, "+") {
   106  						st := strings.IndexRune(s, '+')
   107  						dir = '+'
   108  						ename = s[2:st]
   109  						offvalue := s[st+1:]
   110  						dt, err = readFloat(offvalue)
   111  						if err != nil {
   112  							panic(err)
   113  						}
   114  					} else if strings.Contains(s, "-") {
   115  						st := strings.IndexRune(s, '-')
   116  						dir = '-'
   117  						ename = s[2:st]
   118  						offvalue := s[st+1:]
   119  						dt, err = readFloat(offvalue)
   120  						if err != nil {
   121  							panic(err)
   122  						}
   123  					} else {
   124  						ename = s[2:]
   125  					}
   126  
   127  					var found_flag = false
   128  					for _, exj := range Exsf.Exs {
   129  						if exj.Name == ename {
   130  							if dir == '+' {
   131  								ex.Wa = exj.Wa + dt
   132  							} else if dir == '-' {
   133  								ex.Wa = exj.Wa - dt
   134  							} else {
   135  								ex.Wa = exj.Wa
   136  							}
   137  							found_flag = true
   138  							break
   139  						}
   140  					}
   141  					if !found_flag {
   142  						Eprint("<Exsfdata>", s)
   143  					}
   144  				}
   145  			} else if key == "alo" {
   146  				// *** 外表面熱伝達率 alo ***
   147  				//
   148  				if value == "Calc" {
   149  					// 風速から計算
   150  					ex.Alotype = Alotype_V
   151  				} else {
   152  					// スケジュール
   153  					ex.Alotype = Alotype_Schedule
   154  					if k, err = idsch(value, Schdl.Sch, ""); err == nil {
   155  						ex.Alo = &Schdl.Val[k]
   156  					} else {
   157  						ex.Alo = envptr(value, Simc, nil, nil, nil)
   158  					}
   159  				}
   160  			} else {
   161  				// *** 傾斜角 t,日射反射率 r,地中深さ Z,土の熱拡散率 d ***
   162  				//
   163  				dt, err = readFloat(value)
   164  				if err != nil {
   165  					panic(s)
   166  				}
   167  				switch key {
   168  				case "t":
   169  					// 傾斜角[°]
   170  					ex.Wb = dt
   171  				case "r":
   172  					// 全面地物の日射反射率[-]
   173  					ex.Rg = dt
   174  				case "Z":
   175  					// 地中深さ [m]
   176  					ex.Z = dt
   177  					ex.Typ = EXSFType_E // 地下扱いにする
   178  				case "d":
   179  					// 土の熱拡散率 [m2/s]
   180  					ex.Erdff = dt
   181  				default:
   182  					Eprint("<Exsfdata>", s)
   183  				}
   184  			}
   185  		}
   186  
   187  		Exsf.Exs = append(Exsf.Exs, ex)
   188  	}
   189  
   190  	// 外表面熱伝達率の設定
   191  	// if len(Exsf.Exs) > 0 {
   192  	// 	s = strconv.FormatFloat(ALO, 'f', -1, 64)
   193  	// 	Exsf.Alosch = envptr(s, Simc, nil, nil, nil)
   194  	// 	Exsf.Alotype = Alotype_Fix // 固定値
   195  	// 	Exsf.Exs = exs
   196  	// }
   197  
   198  	for _, ex := range Exsf.Exs {
   199  
   200  		// 一般外表面 の場合は、日射に関するパラメータを計算する
   201  		if ex.Typ == EXSFType_S {
   202  			const rad = PI / 180.
   203  			wa = ex.Wa * rad          // 方位角	[rad]
   204  			wb = ex.Wb * rad          // 傾斜角	[rad]
   205  			cwa = math.Cos(wa)        // 方位角の余弦
   206  			swa = math.Sin(wa)        // 方位角の正弦
   207  			cwb = math.Cos(wb)        // 傾斜角の余弦
   208  			swb = math.Sin(wb)        // 傾斜角の正弦
   209  			ex.Cwa = cwa              // = 方位角の余弦
   210  			ex.Swa = swa              // = 方位角の正弦
   211  			ex.Swb = swb              // = 傾斜角の正弦
   212  			ex.Wz = cwb               // = 傾斜角の余弦
   213  			ex.Ww = swb * swa         // = 傾斜角の正弦 ×  方位角の正弦
   214  			ex.Ws = swb * cwa         // = 傾斜角の正弦 ×  方位角の余弦
   215  			ex.CbSa = cwb * swa       // = 傾斜角の余弦 ×  方位角の正弦
   216  			ex.CbCa = cwb * cwa       // = 傾斜角の余弦 ×  方位角の正弦
   217  			ex.Fs = 0.5 * (1.0 + cwb) // 天空を見る形態係数
   218  		}
   219  	}
   220  }
   221  
   222  /*  外表面入射日射量の計算    */
   223  func (exsf *EXSFS) Exsfsol(Wd *WDAT) {
   224  	for _, ex := range exsf.Exs {
   225  
   226  		if ex.Typ == EXSFType_S {
   227  			// 入射角のcos
   228  			cinc := Wd.Sh*ex.Wz + Wd.Sw*ex.Ww + Wd.Ss*ex.Ws
   229  
   230  			if cinc > 0.0 {
   231  				// 太陽が出ている場合
   232  
   233  				// プロファイル角の計算
   234  				ex.Tprof = (Wd.Sh*ex.Swb - Wd.Sw*ex.CbSa - Wd.Ss*ex.CbCa) / cinc
   235  				ex.Prof = math.Atan(ex.Tprof)
   236  
   237  				// 見かけの方位角の計算
   238  				ex.Tazm = (Wd.Sw*ex.Cwa - Wd.Ss*ex.Swa) / cinc
   239  				ex.Gamma = math.Atan(ex.Tazm)
   240  				ex.Cinc = cinc
   241  			} else {
   242  				// 太陽が出ていない場合
   243  				ex.Prof = 0.0
   244  				ex.Gamma = 0.0
   245  				ex.Cinc = 0.0
   246  			}
   247  
   248  			// 日射量の計算
   249  			ex.Idre = Wd.Idn * ex.Cinc                         // 直逹日射  [W/m2]
   250  			ex.Idf = Wd.Isky*ex.Fs + ex.Rg*Wd.Ihor*(1.0-ex.Fs) // 拡散日射  [W/m2]
   251  			ex.Iw = ex.Idre + ex.Idf                           // 全日射    [W/m2]
   252  			ex.Rn = Wd.RN * ex.Fs                              // 夜間輻射  [W/m2]
   253  		}
   254  	}
   255  }
   256  
   257  // ガラス日射熱取得の計算
   258  // 入力:
   259  //   面積 Ag [m2]
   260  //   日射総合取得率 tgtn [-]
   261  //   吸収日射取得率 Bn [-]
   262  //   入射角のcos cinc [-]
   263  //   ********** Fsdw
   264  //   直逹日射 Idr [W/m2]
   265  //   拡散日射 Idf [W/m2]
   266  // 出力:
   267  //   透過日射熱取得 Qgt [W]
   268  //   吸収日射熱取得 Qga [W]
   269  func Glasstga(Ag, tgtn, Bn, cinc, Fsdw, Idr, Idf float64, Cidtype string, Profile, Gamma float64) (Qgt, Qga float64) {
   270  	var Cid, Cidf, Bid, Bidf float64
   271  
   272  	Cid = 0.0
   273  	Bid = 0.0
   274  	Cidf = 0.01
   275  	Bidf = 0.0
   276  
   277  	// 標準
   278  	if Cidtype == "N" {
   279  		Cid = Glscid(cinc)
   280  		Cidf = 0.91
   281  
   282  		Bid = Cid
   283  		Bidf = Cidf
   284  	} else {
   285  		fmt.Printf("xxxxx <eebslib.c  CidType=%s\n", Cidtype)
   286  	}
   287  
   288  	// 透過日射量の計算
   289  	Qt := Ag * (Cid*Idr*(1.0-Fsdw) + Cidf*Idf)
   290  
   291  	// 吸収日射量の計算
   292  	Qb := Ag * (Bid*Idr*(1.0-Fsdw) + Bidf*Idf)
   293  
   294  	Qgt = Qt * tgtn
   295  	Qga = Qb * Bn
   296  
   297  	return Qgt, Qga
   298  }
   299  
   300  // ガラスの直達日射透過率標準特性
   301  // 入力:
   302  //   入射角のcos cinc [-]
   303  // 出力:
   304  //   ガラスの直達日射透過率標準特性 Cid [-]
   305  func Glscid(cinc float64) float64 {
   306  	return math.Max(0, cinc*(3.4167+cinc*(-4.389+cinc*(2.4948-0.5224*cinc))))
   307  }
   308  
   309  // ガラスの直達日射透過率標準特性(普通複層ガラス用)
   310  // 入力:
   311  //   入射角のcos cinc [-]
   312  // 出力:
   313  //   ガラスの直達日射透過率標準特性 Cid [-]
   314  func GlscidDG(cinc float64) float64 {
   315  	return math.Max(0, cinc*(0.341819+cinc*(6.070709+cinc*(-9.899236+4.495774*cinc))))
   316  }
   317  
   318  func ExsfCount(section *EeTokens) int {
   319  	var N int
   320  	for section.IsEnd() == false {
   321  		if section.GetToken() == ";" {
   322  			N++
   323  			break
   324  		}
   325  	}
   326  	section.Reset()
   327  	return N
   328  }