github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/eeinput_s.go (about) 1 package eeslism 2 3 import ( 4 "bufio" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "strings" 10 ) 11 12 type EeTokens struct { 13 tokens []string 14 pos int 15 } 16 17 // Get length 18 func (t *EeTokens) Len() int { 19 return len(t.tokens) 20 } 21 22 // Get position 23 func (t *EeTokens) GetPos() int { 24 return t.pos 25 } 26 27 // Restore position 28 func (t *EeTokens) RestorePos(pos int) { 29 t.pos = pos 30 } 31 32 // Reset position 33 func (t *EeTokens) Reset() { 34 t.pos = 0 35 } 36 37 // Create EeTokes from string 38 func NewEeTokens(s string) *EeTokens { 39 reader := strings.NewReader(s) 40 scanner := bufio.NewScanner(reader) 41 tokens := make([]string, 0) 42 for scanner.Scan() { 43 //行単位の処理 44 line := scanner.Text() 45 46 // コメントの除去 47 if st := strings.IndexRune(line, '!'); st != -1 { 48 line = line[:st] 49 } 50 51 // 空文字の除去 52 line = strings.TrimSpace(line) 53 54 for _, s := range strings.Fields(line) { 55 if strings.HasSuffix(s, ";") { 56 s = s[:len(s)-1] 57 if s != "" { 58 tokens = append(tokens, s) 59 } 60 tokens = append(tokens, ";") 61 } else if strings.ContainsRune(s, ';') { 62 panic("Invalid position of `;`") 63 } else { 64 tokens = append(tokens, s) 65 } 66 } 67 68 //改行 69 tokens = append(tokens, "\n") 70 } 71 return &EeTokens{tokens: tokens, pos: 0} 72 } 73 74 // Return tokens from current position to `\n` 75 func (t *EeTokens) GetLine() []string { 76 var line []string 77 78 // find `\n` 79 var found bool = false 80 for i := t.pos; i < len(t.tokens); i++ { 81 if t.tokens[i] == "\n" { 82 line = t.tokens[t.pos:i] 83 t.pos = i + 1 84 found = true 85 break 86 } 87 } 88 // not found 89 if found == false { 90 t.pos = len(t.tokens) 91 line = t.tokens[t.pos:] 92 } 93 94 return line 95 } 96 97 // Return tokens from current position to `;` 98 func (t *EeTokens) GetLogicalLine() []string { 99 var logiline []string 100 var filtered []string 101 102 // find `;` 103 var found bool = false 104 for i := t.pos; i < len(t.tokens); i++ { 105 if t.tokens[i] == ";" { 106 logiline = t.tokens[t.pos:i] // `;` is not included 107 t.pos = i + 1 108 found = true 109 break 110 } 111 } 112 // not found 113 if found == false { 114 logiline = t.tokens[t.pos:] 115 t.pos = len(t.tokens) 116 } 117 118 // filter `\n` token and return it 119 for _, s := range logiline { 120 if s != "\n" { 121 filtered = append(filtered, s) 122 } 123 } 124 return filtered 125 } 126 127 // Skip `;` or `\n` 128 func (t *EeTokens) SkipToEndOfLine() { 129 for t.pos < len(t.tokens) && (t.tokens[t.pos] == "\n" || t.tokens[t.pos] == ";") { 130 t.pos++ 131 } 132 } 133 134 // Return tokens from current position to `*` 135 func (t *EeTokens) GetSection() *EeTokens { 136 t.SkipToEndOfLine() 137 138 // find `*` at start of some line 139 for i := t.pos; i < len(t.tokens); i++ { 140 if i > 0 && t.tokens[i-1] == "\n" && t.tokens[i] == "*" { 141 section := &EeTokens{tokens: t.tokens[t.pos : i+1], pos: 0} 142 t.pos = i + 1 143 return section 144 } 145 } 146 // not found 147 section := &EeTokens{tokens: t.tokens[t.pos:], pos: 0} 148 t.pos = len(t.tokens) 149 return section 150 } 151 152 // Check if pos is at the end of tokens 153 func (t *EeTokens) IsEnd() bool { 154 return t.pos >= len(t.tokens) 155 } 156 157 // Peek next token 158 func (t *EeTokens) PeekToken() string { 159 if t.pos < len(t.tokens) { 160 return t.tokens[t.pos] 161 } 162 return "" 163 } 164 165 // Get next token 166 func (t *EeTokens) GetToken() string { 167 if t.pos < len(t.tokens) { 168 t.pos++ 169 return t.tokens[t.pos-1] 170 } 171 return "" 172 } 173 174 // Get next token as float64 value 175 func (t *EeTokens) GetFloat() float64 { 176 var f float64 177 fmt.Sscanf(t.GetToken(), "%f", &f) 178 return f 179 } 180 181 // Get next token as int value 182 func (t *EeTokens) GetInt() int { 183 var i int 184 fmt.Sscanf(t.GetToken(), "%d", &i) 185 return i 186 } 187 188 // 建築・設備システムデータ入力 189 func Eeinput(Ipath string, efl_path string, bdata, week, schtba, schnma string, Simc *SIMCONTL, 190 Exsf *EXSFS, Rmvls *RMVLS, Eqcat *EQCAT, Eqsys *EQSYS, 191 Compnt *[]*COMPNT, 192 Elout *[]*ELOUT, 193 Elin *[]*ELIN, 194 Mpath *[]*MPATH, 195 Plist *[]*PLIST, 196 Pelm *[]*PELM, 197 Contl *[]*CONTL, 198 Ctlif *[]*CTLIF, 199 Ctlst *[]*CTLST, 200 Wd *WDAT, Daytm *DAYTM, key int, 201 bdpn *int, obsn *int, treen *int, shadn *int, polyn *int, 202 bp *[]BBDP, obs *[]OBS, tree *[]TREE, shadtb *[]SHADTB, poly *[]POLYGN, monten *int, gpn *int, DE *float64, Noplpmp *NOPLPMP) (*SCHDL, []*FLOUT) { 203 204 var Twallinit float64 205 var j int 206 dtm := 3600 207 var nday int 208 var Nday int 209 daystartx := 0 210 daystart := 0 211 dayend := 0 212 var Err, File string 213 214 // 出力フラグ (GDAT.PRINT) 215 // 中) 熱負荷要素の出力指定だけ変則的なことに注意 216 wdpri := 0 // 気象データの出力指定 217 revpri := 0 // 室内熱環境データの出力指定 218 pmvpri := 0 // 室内のPMVの出力指定 219 220 Nrmspri := 0 // 表面温度出力指定(室の数) 221 Nqrmpri := 0 // 日射、室内発熱取得出力指定(室の数) 222 Nwalpri := 0 // 壁体内部温度出力指定(壁体の数) 223 Npcmpri := 0 // PCMの状態値出力フラグ(壁体の数) 224 Nshdpri := 0 // 日よけの影面積出力 (壁体の数) 225 226 var dfwl DFWL 227 228 /*-------higuchi 070918---------start*/ 229 //RRMP *rp; 230 //MADO *wp; 231 //sunblk *sb; 232 var smonth, sday, emonth, eday int 233 234 //sb = bp.SBLK; 235 //rp = bp.RMP; 236 //wp = rp.WD; 237 /*-------higuchi------------end*/ 238 239 Err = fmt.Sprintf(ERRFMT, "(Eeinput)") 240 241 var err error 242 243 // ------------------------------------------------------- 244 // 曜日設定ファイルの読み取り 245 // ------------------------------------------------------- 246 var fi_dayweek []byte 247 if fi_dayweek, err = ioutil.ReadFile(filepath.Join(efl_path, "dayweek.efl")); err != nil { 248 Eprint("<Eeinput>", "dayweek.efl") 249 os.Exit(EXIT_DAYWEK) 250 } 251 Dayweek(string(fi_dayweek), week, Simc.Daywk, key) 252 253 if DEBUG { 254 dprdayweek(Simc.Daywk) 255 } 256 257 // ------------------------------------------------------- 258 // スケジュ-ル表の読み取り 259 // ------------------------------------------------------- 260 var Schdl *SCHDL = new(SCHDL) 261 Schtable(schtba, Schdl) 262 Schname(Schdl) 263 264 // ------------------------------------------------------- 265 // 季節、曜日によるスケジュ-ル表の組み合わせの読み取り 266 // ------------------------------------------------------- 267 Schdata(schnma, "schnm", Simc.Daywk, Schdl) 268 269 // 入力を正規化することで後処理を簡単にする 270 tokens := NewEeTokens(bdata) 271 272 for !tokens.IsEnd() { 273 s := tokens.GetToken() 274 if s == "\n" || s == ";" || s == "*" { 275 continue 276 } 277 fmt.Printf("=== %s\n", s) 278 279 switch s { 280 case "TITLE": 281 line := tokens.GetLogicalLine() 282 Simc.Title = strings.Join(line, " ") 283 fmt.Printf("%s\n", Simc.Title) 284 case "GDAT": 285 section := tokens.GetSection() 286 Wd.RNtype = 'C' 287 Wd.Intgtsupw = 'N' 288 Simc.Perio = 'n' // 周期定常計算フラグを'n'に初期化 289 Gdata(section, Simc.File, &Simc.Wfname, &Simc.Ofname, &dtm, &Simc.Sttmm, 290 &daystartx, &daystart, &dayend, &Twallinit, Simc.Dayprn, 291 &wdpri, &revpri, &pmvpri, &Simc.Helmkey, &Simc.MaxIterate, Daytm, Wd, &Simc.Perio) 292 293 // 気象データファイル名からファイル種別を判定 294 if Simc.Wfname == "" { 295 Simc.Wdtype = 'E' 296 } else { 297 Simc.Wdtype = 'H' 298 } 299 300 // 初期温度 (15[deg]) 301 Rmvls.Twallinit = Twallinit 302 303 // 計算時間間隔 [s] 304 Simc.DTm = dtm 305 306 Simc.Unit = "t_C x_kg/kg r_% q_W e_W" 307 Simc.Unitdy = "Q_kWh E_kWh" 308 309 fmt.Printf("== File Output=%s\n", Simc.Ofname) 310 // case "SCHTB": 311 // // SCHDBデータセットの読み取り 312 // //Schtable(schtba, Schdl) 313 // Schname(Schdl) 314 // case "SCHNM": 315 // // SCHNMデータセットの読み取り 316 // Schdata(schnma, s, Simc.Daywk, Schdl) 317 case "EXSRF": 318 // EXSRFデータセットの読み取り 319 section := tokens.GetSection() 320 Exsfdata(section, s, Exsf, Schdl, Simc) 321 322 case "SUNBRK": 323 // 日よけの読み込み 324 section := tokens.GetSection() 325 Snbkdata(section, s, &Rmvls.Snbk) 326 327 case "PCM": 328 section := tokens.GetSection() 329 PCMdata(section, s, &Rmvls.PCM, &Rmvls.Pcmiterate) 330 331 case "WALL": 332 if Fbmlist == "" { 333 File = "wbmlist.efl" 334 } else { 335 File = Fbmlist 336 } 337 338 var fullpath string 339 if filepath.IsAbs(File) { 340 fullpath = File 341 } else { 342 fullpath = filepath.Join(efl_path, File) 343 } 344 345 var fbmContent []byte 346 if fbmContent, err = ioutil.ReadFile(fullpath); err != nil { 347 Eprint("<Eeinput>", "wbmlist.efl") 348 os.Exit(EXIT_WBMLST) 349 } 350 /*******************/ 351 352 section := tokens.GetSection() 353 Walldata(section, string(fbmContent), &Rmvls.Wall, &dfwl, Rmvls.PCM) 354 355 case "WINDOW": 356 section := tokens.GetSection() 357 Windowdata(section, &Rmvls.Window) 358 359 case "ROOM": 360 Roomdata(tokens, Exsf.Exs, &dfwl, Rmvls, Schdl, Simc) 361 Balloc(Rmvls.Sd, Rmvls.Wall, &Rmvls.Mw) 362 363 case "RAICH", "VENT": 364 section := tokens.GetSection() 365 Ventdata(section, Schdl, Rmvls.Room, Simc) 366 367 case "RESI": 368 section := tokens.GetSection() 369 Residata(section, Schdl, Rmvls.Room, &pmvpri, Simc) 370 371 case "APPL": 372 section := tokens.GetSection() 373 Appldata(section, Schdl, Rmvls.Room, Simc) 374 375 case "VCFILE": 376 section := tokens.GetSection() 377 Vcfdata(section, Simc) 378 379 case "EQPCAT": 380 section := tokens.GetSection() 381 Eqcadata(section, Eqcat) 382 383 case "SYSCMP": // 接続用のノードを設定している 384 /*****Flwindata(Flwin, Nflwin, Wd);********/ 385 section := tokens.GetSection() 386 Compodata(section, Rmvls, Eqcat, Compnt, Eqsys) 387 Elmalloc(*Compnt, Eqcat, Eqsys, Elout, Elin) 388 389 case "SYSPTH": // 接続パスの設定をしている 390 section := tokens.GetSection() 391 Pathdata(section, Simc, Wd, *Compnt, Schdl, Mpath, Plist, Pelm, Eqsys, Elout, Elin) 392 Roomelm(Rmvls.Room, Rmvls.Rdpnl) 393 394 // 変数の割り当て 395 Hclelm(Eqsys.Hcload) 396 Thexelm(Eqsys.Thex) 397 Desielm(Eqsys.Desi) 398 Evacelm(Eqsys.Evac) 399 400 Qmeaselm(Eqsys.Qmeas) 401 402 case "CONTL": 403 section := tokens.GetSection() 404 Contrldata(section, Contl, Ctlif, Ctlst, Simc, *Compnt, *Mpath, Wd, Exsf, Schdl) 405 406 /*--------------higuchi add-------------------start*/ 407 408 // 20170503 higuchi add 409 case "DIVID": 410 section := tokens.GetSection() 411 dividdata(section, monten, DE) 412 413 /*--対象建物データ読み込み--*/ 414 case "COORDNT": 415 section := tokens.GetSection() 416 bdpdata(section, bdpn, bp, Exsf) 417 418 /*--障害物データ読み込み--*/ 419 case "OBS": 420 section := tokens.GetSection() 421 obsdata(section, obsn, obs) 422 423 /*--樹木データ読み込み--*/ 424 case "TREE": 425 section := tokens.GetSection() 426 treedata(section, treen, tree) 427 428 /*--多角形障害物直接入力分の読み込み--*/ 429 case "POLYGON": 430 section := tokens.GetSection() 431 polydata(section, polyn, poly) 432 433 /*--落葉スケジュール読み込み--*/ 434 case "SHDSCHTB": 435 *shadn = 0 436 var Nshadn int 437 //var shdp *SHADTB 438 // 落葉スケジュールの数を数える 439 section := tokens.GetSection() 440 Nshadn = InputCount(section, ";") 441 section.Reset() 442 443 if Nshadn > 0 { 444 *shadtb = make([]SHADTB, Nshadn) 445 } 446 447 i := 0 448 for section.IsEnd() == false { 449 s = section.GetToken() 450 if s[0] == '*' { 451 break 452 } 453 shdp := (*shadtb)[i] 454 shdp.lpname = s 455 (*shadn)++ 456 shdp.indatn = 0 457 458 for section.IsEnd() == false { 459 s = section.GetToken() 460 if s[0] == '*' { 461 break 462 } 463 _, err = fmt.Sscanf(s, "%d/%d-%f-%d/%d", &smonth, &sday, &shdp.shad[shdp.indatn], &emonth, &eday) 464 if err != nil { 465 panic(err) 466 } 467 shdp.ndays[shdp.indatn] = nennkann(smonth, sday) 468 shdp.ndaye[shdp.indatn] = nennkann(emonth, eday) 469 shdp.indatn = shdp.indatn + 1 470 } 471 i++ 472 } 473 474 /*----------higuchi add-----------------end-*/ 475 476 default: 477 Err = Err + " " + s 478 Eprint("<Eeinput>", Err) 479 } 480 } 481 482 /*--------------higuchi 070918-------------------start-*/ 483 if *bdpn != 0 { 484 fmt.Printf("deviding of wall mm: %f\n", *DE) 485 fmt.Printf("number of point in montekalro: %d\n", *monten) 486 } 487 /*----------------higuchi 7.11,061123------------------end*/ 488 489 // 外部障害物の数を数える 490 Noplpmp.Nop = OPcount(*bdpn, *bp, *polyn, *poly) 491 Noplpmp.Nlp = LPcount(*bdpn, *bp, *obsn, *obs, *treen, *polyn, *poly) 492 Noplpmp.Nmp = Noplpmp.Nop + Noplpmp.Nlp 493 494 ////////////////////////////////////// 495 496 //---------------------------------------------------- 497 // シミュレーション設定 498 //---------------------------------------------------- 499 500 if daystart > dayend { 501 dayend = dayend + 365 502 } 503 Nday = dayend - daystart + 1 504 505 if daystartx > daystart { 506 daystart = daystart + 365 507 } 508 509 Nday += daystart - daystartx 510 Simc.Dayend = daystartx + Nday - 1 511 Simc.Daystartx = daystartx 512 Simc.Daystart = daystart 513 514 Simc.Timeid = []rune{'M', 'D', 'T'} 515 516 Simc.Ntimedyprt = Simc.Dayend - Simc.Daystart + 1 517 Simc.Dayntime = 24 * 3600 / dtm 518 Simc.Ntimehrprt = 0 519 520 for nday = Simc.Daystart; nday <= Simc.Dayend; nday++ { 521 // NOTE: オリジナルコードはバッファーオーバーランしているので、`%366`を追加 522 if Simc.Dayprn[nday%366] != 0 { 523 Simc.Ntimehrprt += Simc.Dayntime 524 } 525 } 526 527 //---------------------------------------------------- 528 // 出力ファイルの追加 529 //---------------------------------------------------- 530 531 for i := range Rmvls.Room { 532 Rm := Rmvls.Room[i] 533 if Rm.sfpri { 534 Nrmspri++ 535 } 536 if Rm.eqpri { 537 Nqrmpri++ 538 } 539 } 540 541 for _, Sd := range Rmvls.Sd { 542 if Sd.wlpri { 543 Nwalpri++ 544 } 545 546 if Sd.pcmpri { 547 Npcmpri++ 548 } 549 550 // 日よけの影面積出力 551 if Sd.shdpri { 552 Nshdpri++ 553 } 554 } 555 556 // 出力ファイルの追加手続き 557 var Flout []*FLOUT = make([]*FLOUT, 0, 30) // ファイル出力設定 558 addFlout := func(idn PrintType) { 559 Flout = append(Flout, &FLOUT{Idn: idn}) 560 } 561 562 // 必須出力ファイル 563 addFlout(PRTPATH) // 時間別計算値(システム経路の温湿度出力) 564 addFlout(PRTCOMP) // 時間別計算値(機器の出力) 565 addFlout(PRTDYCOMP) // 日別計算値(システム要素機器の日集計結果出力) 566 addFlout(PRTMNCOMP) // 月別計算値(システム要素機器の月集計結果出力) 567 addFlout(PRTMTCOMP) // 月-時刻計算値(部屋ごとの熱集計結果出力) 568 addFlout(PRTHRSTANK) // 時間別計算値(蓄熱槽内温度分布の出力) 569 addFlout(PRTWK) // 計算年月日出力 570 addFlout(PRTREV) // 時間別計算値(毎時室温、MRTの出力) 571 addFlout(PRTHROOM) // 時間別計算値(放射パネルの出力) 572 addFlout(PRTDYRM) // 日別計算値(部屋ごとの熱集計結果出力) 573 addFlout(PRTMNRM) // 月別計算値(部屋ごとの熱集計結果出力) 574 575 // 要素別熱損失・熱取得(記憶域確保) 576 Helminit("Helminit", Simc.Helmkey, Rmvls.Room, &Rmvls.Qetotal) 577 578 if Simc.Helmkey == 'y' { 579 addFlout(PRTHELM) // 時間別計算値(要素別熱損失・熱取得) 580 addFlout(PRTDYHELM) // 日別計算値(要素別熱損失・熱取得) 581 582 Simc.Nhelmsfpri = 0 583 for i := range Rmvls.Room { 584 Rm := Rmvls.Room[i] 585 for j = 0; j < Rm.N; j++ { 586 Sdd := Rm.rsrf[j] 587 if Sdd.sfepri { 588 Simc.Nhelmsfpri++ 589 } 590 } 591 } 592 if Simc.Nhelmsfpri > 0 { 593 addFlout(PRTHELMSF) // 時間別計算値(要素別熱損失・熱取得) 表面? 594 } 595 } 596 597 if pmvpri > 0 { 598 addFlout(PRTPMV) // 時間別計算値(PMV計算) 599 } 600 601 if Nqrmpri > 0 { 602 addFlout(PRTQRM) // 時間別計算値(日射、室内熱取得の出力) 603 addFlout(PRTDQR) // 日別計算値(日射、室内熱取得の出力) 604 } 605 606 if Nrmspri > 0 { 607 addFlout(PRTRSF) // 時間別計算値(室内表面温度の出力) 608 addFlout(PRTSFQ) // 時間別計算値(室内表面熱流の出力) 609 addFlout(PRTSFA) // 時間別計算値(室内表面熱伝達率の出力) 610 addFlout(PRTDYSF) // 日別計算値(日積算壁体貫流熱取得の出力) 611 } 612 613 if Nwalpri > 0 { 614 addFlout(PRTWAL) // // 時間別計算値(壁体内部温度の出力) 615 } 616 617 // 日よけの影面積出力 618 if Nshdpri > 0 { 619 addFlout(PRTSHD) // 時間別計算値(日よけの影面積の出力) 620 } 621 622 // 潜熱蓄熱材がある場合 623 if Npcmpri > 0 { 624 addFlout(PRTPCM) // 時間別計算値(潜熱蓄熱材の状態値の出力) 625 } 626 627 // 気象データの出力を追加 628 if wdpri > 0 { 629 addFlout(PRTHWD) // 時間別計算値(気象データ出力) 630 addFlout(PRTDWD) // 日別計算値(気象データ日集計値出力) 631 addFlout(PRTMWD) // 月別計算値(気象データ月集計値出力) 632 } 633 634 return Schdl, Flout 635 }