github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/mcboiler.go (about) 1 //This file is part of EESLISM. 2 // 3 //Foobar is free software : you can redistribute itand /or modify 4 //it under the terms of the GNU General Public License as published by 5 //the Free Software Foundation, either version 3 of the License, or 6 //(at your option) any later version. 7 // 8 //Foobar is distributed in the hope that it will be useful, 9 //but WITHOUT ANY WARRANTY; without even the implied warranty of 10 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 11 //GNU General Public License for more details. 12 // 13 //You should have received a copy of the GNU General Public License 14 //along with Foobar.If not, see < https://www.gnu.org/licenses/>. 15 16 /* boiler.c */ 17 18 /* ボイラ- */ 19 20 package eeslism 21 22 /* 機器仕様入力 */ 23 24 import ( 25 "errors" 26 "fmt" 27 "io" 28 "math" 29 "strconv" 30 "strings" 31 ) 32 33 func Boidata(s string, boica *BOICA) int { 34 var id int 35 36 st := strings.IndexRune(s, '=') 37 if st == -1 && s[0] != '-' { 38 boica.name = s 39 boica.unlimcap = 'n' 40 boica.ene = ' ' 41 boica.plf = ' ' 42 boica.Qo = nil 43 boica.eff = 1.0 44 boica.Ph = -999.0 45 boica.Qmin = -999.0 46 //boica.mode = 'n' 47 boica.Qostr = "" 48 } else if s == "-U" { 49 boica.unlimcap = 'y' 50 } else { 51 if st >= 0 { 52 s1, s2 := s[:st], s[st+1:] 53 switch s1 { 54 case "p": 55 boica.plf = rune(s2[0]) 56 case "en": 57 boica.ene = rune(s2[0]) 58 case "blwQmin": 59 60 if s2 == "ON" { 61 // 負荷が最小出力以下のときに最小出力でONとする 62 boica.belowmin = ON_SW 63 } else if s2 == "OFF" { 64 // 負荷が最小出力以下のときにOFFとする 65 boica.belowmin = OFF_SW 66 } else { 67 id = 1 68 } 69 case "Qo": 70 boica.Qostr = s2 71 case "Qmin", "eff", "Ph": 72 dt, err := strconv.ParseFloat(s2, 64) 73 if err != nil { 74 id = 1 75 } else { 76 switch s1 { 77 case "Qmin": 78 boica.Qmin = dt 79 case "eff": 80 boica.eff = dt 81 case "Ph": 82 boica.Ph = dt 83 } 84 } 85 default: 86 id = 1 87 } 88 } 89 } 90 return id 91 } 92 93 func (eqcat *EQCAT) Boicaint(Simc *SIMCONTL, Compnt []*COMPNT, Wd *WDAT, Exsf *EXSFS, Schdl *SCHDL) { 94 for _, Boica := range eqcat.Boica { 95 if idx, err := idsch(Boica.Qostr, Schdl.Sch, ""); err == nil { 96 Boica.Qo = &Schdl.Val[idx] 97 } else { 98 Boica.Qo = envptr(Boica.Qostr, Simc, nil, nil, nil) 99 } 100 } 101 } 102 103 /* --------------------------- */ 104 105 /* 特性式の係数 */ 106 107 // 108 // +-----+ 109 // [IN 1] ---> | BOI | ---> [OUT 1] 出口温度?? 110 // +-----+ 111 // 112 func Boicfv(Boi []*BOI) { 113 var cG, Qocat, Temp float64 114 115 if len(Boi) != len(Boi) { 116 panic("len(Boi) != len(Boi)") 117 } 118 119 for _, boi := range Boi { 120 121 Eo1 := boi.Cmp.Elouts[0] 122 123 if boi.Cmp.Control != OFF_SW { 124 Temp = math.Abs(*boi.Cat.Qo - (-999.9)) 125 if math.Abs(Temp) < 1e-3 { 126 Qocat = 0.0 127 } else { 128 Qocat = *boi.Cat.Qo 129 } 130 131 if Qocat > 0.0 { 132 boi.HCmode = HEATING_LOAD 133 } else { 134 boi.HCmode = COOLING_LOAD 135 } 136 137 boi.Do = Qocat 138 139 if (boi.Do < 0.0 && boi.HCmode == HEATING_LOAD) || (boi.Do > 0.0 && boi.HCmode == COOLING_LOAD) || boi.HCmode == 'n' { 140 fmt.Printf("<BOI> name=%s Qo=%.4g\n", boi.Cmp.Name, boi.Do) 141 } 142 143 boi.D1 = 0.0 144 145 cG = Spcheat(Eo1.Fluid) * Eo1.G 146 boi.cG = cG 147 Eo1.Coeffo = cG 148 149 if Eo1.Control != OFF_SW { 150 if Eo1.Sysld == 'y' { 151 // 出口を設定温度に制御 152 Eo1.Co = 0.0 153 Eo1.Coeffin[0] = -cG 154 } else { 155 if boi.Mode == 'M' { 156 // 最大能力 157 Eo1.Co = boi.Do 158 } else { 159 // 最小能力 160 Eo1.Co = boi.Cat.Qmin 161 } 162 Eo1.Coeffin[0] = boi.D1 - cG 163 } 164 } 165 } else { 166 // 機器が停止 167 Eo1.Co = 0.0 168 Eo1.Coeffo = 1.0 169 Eo1.Coeffin[0] = -1.0 170 } 171 } 172 } 173 174 /* --------------------------- */ 175 176 // 供給熱量、エネルギーの計算 177 func Boiene(Boi []*BOI, BOIreset *int) { 178 for i, boi := range Boi { 179 boi.Tin = boi.Cmp.Elins[0].Sysvin 180 Qmin := boi.Cat.Qmin 181 if math.Abs(Qmin-(-999.0)) < 1.0e-5 { 182 Qmin = 0.0 183 } 184 185 Eo := boi.Cmp.Elouts[0] 186 reset := 0 187 188 if Eo.Control != OFF_SW { 189 boi.Q = boi.cG * (Eo.Sysv - boi.Tin) 190 191 // 次回ループの機器制御判定用の熱量 192 Qcheck := boi.Q 193 194 // 加熱設定での冷却、冷却設定での加熱時はボイラを止める 195 if (Qcheck < 0.0 && boi.HCmode == 'H') || (Qcheck > 0.0 && boi.HCmode == 'C') { 196 boi.Cmp.Control = OFF_SW 197 Eo.Control = ON_SW 198 Eo.Emonitr.Control = ON_SW 199 Eo.Sysld = 'n' 200 201 reset = 1 202 } else if Qmin > 0.0 && Qcheck < Qmin { 203 // 最小出力以下はOFFにする場合 204 if boi.Cat.belowmin == OFF_SW { 205 boi.Cmp.Elouts[0].Control = OFF_SW 206 boi.Cmp.Control = OFF_SW 207 Eo.Control = ON_SW 208 Eo.Emonitr.Control = ON_SW 209 Eo.Sysld = 'n' 210 } else { 211 Eo.Control = ON_SW 212 Eo.Emonitr.Control = ON_SW 213 Eo.Sysld = 'n' 214 boi.Mode = 'm' 215 } 216 217 reset = 1 218 } else if boi.Cat.unlimcap == 'n' { 219 // 過負荷状態のチェック 220 Qocat := 0.0 221 if math.Abs(*boi.Cat.Qo-(-999.9)) < 1.0e-3 { 222 Qocat = 0.0 223 } else { 224 Qocat = *boi.Cat.Qo 225 } 226 227 reset0 := maxcapreset(Qcheck, Qocat, boi.HCmode, Eo) 228 229 if reset == 0 { 230 reset = reset0 231 } 232 } 233 234 if reset == 1 { 235 Boicfv(Boi[i : i+1]) 236 (*BOIreset)++ 237 } 238 239 boi.E = boi.Q / boi.Cat.eff 240 boi.Ph = boi.Cat.Ph 241 } else { 242 boi.Q = 0.0 243 boi.E = 0.0 244 boi.Ph = 0.0 245 } 246 } 247 } 248 249 /* --------------------------- */ 250 251 /* 負荷計算指定時の設定値のポインター */ 252 253 func boildptr(load *ControlSWType, key []string, Boi *BOI) (VPTR, error) { 254 var err error 255 var vptr VPTR 256 257 if strings.Compare(key[1], "Tout") == 0 { 258 vptr.Ptr = &Boi.Toset 259 vptr.Type = VAL_CTYPE 260 Boi.Load = load 261 } else { 262 err = errors.New("Tout expected") 263 } 264 return vptr, err 265 } 266 267 /* --------------------------- */ 268 269 /* 負荷計算指定時のスケジュール設定 */ 270 271 func boildschd(Boi *BOI) { 272 Eo := Boi.Cmp.Elouts[0] 273 274 if Boi.Load != nil { 275 if Eo.Control != OFF_SW { 276 if Boi.Toset > TEMPLIMIT { 277 Eo.Control = LOAD_SW 278 Eo.Sysv = Boi.Toset 279 } else { 280 Eo.Control = OFF_SW 281 } 282 } 283 } 284 } 285 286 /* --------------------------- */ 287 288 func boiprint(fo io.Writer, id int, Boi []*BOI) { 289 for _, boi := range Boi { 290 switch id { 291 case 0: 292 if len(Boi) > 0 { 293 fmt.Fprintf(fo, "%s %d\n", BOILER_TYPE, len(Boi)) 294 } 295 fmt.Fprintf(fo, " %s 1 7\n", boi.Name) 296 case 1: 297 fmt.Fprintf(fo, "%s_c c c %s_G m f %s_Ti t f %s_To t f ", boi.Name, boi.Name, boi.Name, boi.Name) 298 fmt.Fprintf(fo, "%s_Q q f %s_E e f %s_P e f\n", boi.Name, boi.Name, boi.Name) 299 default: 300 fmt.Fprintf(fo, "%c %.4g %4.2f %4.2f %4.0f %4.0f %2.0f\n", 301 boi.Cmp.Elouts[0].Control, boi.Cmp.Elouts[0].G, 302 boi.Tin, boi.Cmp.Elouts[0].Sysv, boi.Q, boi.E, boi.Ph) 303 } 304 } 305 } 306 307 /* --------------------------- */ 308 309 /* 日積算値に関する処理 */ 310 311 func boidyint(Boi []*BOI) { 312 for _, boi := range Boi { 313 // 日集計のリセット 314 svdyint(&boi.Tidy) 315 qdyint(&boi.Qdy) 316 edyint(&boi.Edy) 317 edyint(&boi.Phdy) 318 } 319 } 320 321 /* --------------------------- */ 322 323 /* 月積算値に関する処理 */ 324 325 func boimonint(Boi []*BOI) { 326 for _, boi := range Boi { 327 // 日集計のリセット 328 svdyint(&boi.mTidy) 329 qdyint(&boi.mQdy) 330 edyint(&boi.mEdy) 331 edyint(&boi.mPhdy) 332 } 333 } 334 335 func boiday(Mon, Day, ttmm int, Boi []*BOI, Nday, SimDayend int) { 336 var Mo, tt int 337 338 Mo = Mon - 1 339 tt = ConvertHour(ttmm) 340 for _, boi := range Boi { 341 // 日集計 342 svdaysum(int64(ttmm), boi.Cmp.Control, boi.Tin, &boi.Tidy) 343 qdaysum(int64(ttmm), boi.Cmp.Control, boi.Q, &boi.Qdy) 344 edaysum(ttmm, boi.Cmp.Control, boi.E, &boi.Edy) 345 edaysum(ttmm, boi.Cmp.Control, boi.Ph, &boi.Phdy) 346 347 // 月集計 348 svmonsum(Mon, Day, ttmm, boi.Cmp.Control, boi.Tin, &boi.mTidy, Nday, SimDayend) 349 qmonsum(Mon, Day, ttmm, boi.Cmp.Control, boi.Q, &boi.mQdy, Nday, SimDayend) 350 emonsum(Mon, Day, ttmm, boi.Cmp.Control, boi.E, &boi.mEdy, Nday, SimDayend) 351 emonsum(Mon, Day, ttmm, boi.Cmp.Control, boi.Ph, &boi.mPhdy, Nday, SimDayend) 352 353 // 月・時刻のクロス集計 354 emtsum(Mon, Day, ttmm, boi.Cmp.Control, boi.E, &boi.MtEdy[Mo][tt]) 355 emtsum(Mon, Day, ttmm, boi.Cmp.Control, boi.E, &boi.MtPhdy[Mo][tt]) 356 } 357 } 358 359 func boidyprt(fo io.Writer, id int, Boi []*BOI) { 360 switch id { 361 case 0: 362 if len(Boi) > 0 { 363 fmt.Fprintf(fo, "%s %d\n", BOILER_TYPE, len(Boi)) 364 } 365 for _, boi := range Boi { 366 fmt.Fprintf(fo, " %s 1 22\n", boi.Name) 367 } 368 case 1: 369 for _, boi := range Boi { 370 fmt.Fprintf(fo, "%s_Ht H d %s_T T f ", boi.Name, boi.Name) 371 fmt.Fprintf(fo, "%s_ttn h d %s_Tn t f %s_ttm h d %s_Tm t f\n", 372 boi.Name, boi.Name, boi.Name, boi.Name) 373 fmt.Fprintf(fo, "%s_Hh H d %s_Qh Q f %s_Hc H d %s_Qc Q f\n", 374 boi.Name, boi.Name, boi.Name, boi.Name) 375 fmt.Fprintf(fo, "%s_th h d %s_qh q f %s_tc h d %s_qc q f\n", 376 boi.Name, boi.Name, boi.Name, boi.Name) 377 fmt.Fprintf(fo, "%s_He H d %s_E E f %s_te h d %s_Em e f\n", 378 boi.Name, boi.Name, boi.Name, boi.Name) 379 fmt.Fprintf(fo, "%s_Hp H d %s_P E f %s_tp h d %s_Pm e f\n\n", 380 boi.Name, boi.Name, boi.Name, boi.Name) 381 } 382 default: 383 for _, boi := range Boi { 384 fmt.Fprintf(fo, "%1d %3.1f %1d %3.1f %1d %3.1f ", 385 boi.Tidy.Hrs, boi.Tidy.M, 386 boi.Tidy.Mntime, boi.Tidy.Mn, 387 boi.Tidy.Mxtime, boi.Tidy.Mx) 388 389 fmt.Fprintf(fo, "%1d %3.1f ", boi.Qdy.Hhr, boi.Qdy.H) 390 fmt.Fprintf(fo, "%1d %3.1f ", boi.Qdy.Chr, boi.Qdy.C) 391 fmt.Fprintf(fo, "%1d %2.0f ", boi.Qdy.Hmxtime, boi.Qdy.Hmx) 392 fmt.Fprintf(fo, "%1d %2.0f ", boi.Qdy.Cmxtime, boi.Qdy.Cmx) 393 394 fmt.Fprintf(fo, "%1d %3.1f ", boi.Edy.Hrs, boi.Edy.D) 395 fmt.Fprintf(fo, "%1d %2.0f ", boi.Edy.Mxtime, boi.Edy.Mx) 396 397 fmt.Fprintf(fo, "%1d %3.1f ", boi.Phdy.Hrs, boi.Phdy.D) 398 fmt.Fprintf(fo, "%1d %2.0f\n", boi.Phdy.Mxtime, boi.Phdy.Mx) 399 } 400 } 401 } 402 403 func boimonprt(fo io.Writer, id int, Boi []*BOI) { 404 switch id { 405 case 0: 406 if len(Boi) > 0 { 407 fmt.Fprintf(fo, "%s %d\n", BOILER_TYPE, len(Boi)) 408 } 409 for _, boi := range Boi { 410 fmt.Fprintf(fo, " %s 1 22\n", boi.Name) 411 } 412 case 1: 413 for _, boi := range Boi { 414 fmt.Fprintf(fo, "%s_Ht H d %s_T T f ", boi.Name, boi.Name) 415 fmt.Fprintf(fo, "%s_ttn h d %s_Tn t f %s_ttm h d %s_Tm t f\n", 416 boi.Name, boi.Name, boi.Name, boi.Name) 417 fmt.Fprintf(fo, "%s_Hh H d %s_Qh Q f %s_Hc H d %s_Qc Q f\n", 418 boi.Name, boi.Name, boi.Name, boi.Name) 419 fmt.Fprintf(fo, "%s_th h d %s_qh q f %s_tc h d %s_qc q f\n", 420 boi.Name, boi.Name, boi.Name, boi.Name) 421 fmt.Fprintf(fo, "%s_He H d %s_E E f %s_te h d %s_Em e f\n", 422 boi.Name, boi.Name, boi.Name, boi.Name) 423 fmt.Fprintf(fo, "%s_Hp H d %s_P E f %s_tp h d %s_Pm e f\n\n", 424 boi.Name, boi.Name, boi.Name, boi.Name) 425 } 426 default: 427 for _, boi := range Boi { 428 fmt.Fprintf(fo, "%1d %3.1f %1d %3.1f %1d %3.1f ", 429 boi.mTidy.Hrs, boi.mTidy.M, 430 boi.mTidy.Mntime, boi.mTidy.Mn, 431 boi.mTidy.Mxtime, boi.mTidy.Mx) 432 433 fmt.Fprintf(fo, "%1d %3.1f ", boi.mQdy.Hhr, boi.mQdy.H) 434 fmt.Fprintf(fo, "%1d %3.1f ", boi.mQdy.Chr, boi.mQdy.C) 435 fmt.Fprintf(fo, "%1d %2.0f ", boi.mQdy.Hmxtime, boi.mQdy.Hmx) 436 fmt.Fprintf(fo, "%1d %2.0f ", boi.mQdy.Cmxtime, boi.mQdy.Cmx) 437 438 fmt.Fprintf(fo, "%1d %3.1f ", boi.mEdy.Hrs, boi.mEdy.D) 439 fmt.Fprintf(fo, "%1d %2.0f ", boi.mEdy.Mxtime, boi.mEdy.Mx) 440 441 fmt.Fprintf(fo, "%1d %3.1f ", boi.mPhdy.Hrs, boi.mPhdy.D) 442 fmt.Fprintf(fo, "%1d %2.0f\n", boi.mPhdy.Mxtime, boi.mPhdy.Mx) 443 } 444 } 445 } 446 447 func boimtprt(fo io.Writer, id int, Boi []*BOI, Mo int, tt int) { 448 switch id { 449 case 0: 450 if len(Boi) > 0 { 451 fmt.Fprintf(fo, "%s %d\n", BOILER_TYPE, len(Boi)) 452 } 453 for _, boi := range Boi { 454 fmt.Fprintf(fo, " %s 1 2\n", boi.Name) 455 } 456 case 1: 457 for _, boi := range Boi { 458 fmt.Fprintf(fo, "%s_E E f %s_Ph E f \n", boi.Name, boi.Name) 459 } 460 default: 461 for _, boi := range Boi { 462 fmt.Fprintf(fo, " %.2f %.2f\n", 463 boi.MtEdy[Mo-1][tt-1].D*Cff_kWh, boi.MtPhdy[Mo-1][tt-1].D*Cff_kWh) 464 } 465 } 466 }