github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/eepathdat.go (about) 1 package eeslism 2 3 import ( 4 "errors" 5 "fmt" 6 "regexp" 7 "strings" 8 ) 9 10 /* システム要素の接続経路の入力 */ 11 12 func Pathdata( 13 f *EeTokens, 14 Simc *SIMCONTL, 15 Wd *WDAT, 16 Compnt []*COMPNT, 17 Schdl *SCHDL, 18 M *[]*MPATH, 19 Plst *[]*PLIST, 20 Plm *[]*PELM, 21 Eqsys *EQSYS, 22 Elout *[]*ELOUT, 23 Elin *[]*ELIN, 24 ) { 25 var C *COMPNT 26 var stank *STANK 27 var Qmeas *QMEAS 28 var s, ss string 29 var elm string 30 var id int 31 32 var i, j, m, ncv, iswc int 33 34 errkey := "Pathdata" 35 if DEBUG { 36 fmt.Printf("\n") 37 for i := range Compnt { 38 39 C = Compnt[i] 40 fmt.Printf("name=%s Nin=%d Nout=%d\n", C.Name, C.Nin, C.Nout) 41 } 42 } 43 44 // 最外ループ: MPATHの読み込み 開始 45 for f.IsEnd() == false { 46 ss = f.GetToken() 47 if ss[0] == '*' { 48 break 49 } 50 if ss[0] == '\n' { 51 continue 52 } 53 54 if DEBUG { 55 fmt.Printf("eepathdat.c ss=%s\n", ss) 56 } 57 58 Mpath := NewMPATH() 59 60 // if *Nplst > 0 { 61 // // 経路系統 -> 末端経路 への参照ポインタの確保 62 // Mpath.Pl = make([]*PLIST, *Nplst) 63 // for i := 0; i < *Nplst; i++ { 64 // Mpath.Pl[i] = nil 65 // } 66 // } 67 68 // if *Nplst > 0 { 69 // // 流量連立方程式を解くときに使用する分岐・合流機器 への参照ポインタの確保 70 // Mpath.Cbcmp = make([]*COMPNT, *Nplst*2) 71 // for i := 0; i < *Nplst*2; i++ { 72 // Mpath.Cbcmp[i] = nil 73 // } 74 // } 75 76 // SYSPTHにおける';'で区切られる経路の基本設定 77 // 入力例: `LDAC -sys A -f A` 78 Mpath.Name = ss // 経路名称 79 Mpath.NGv = 0 // ガス導管数 80 Mpath.NGv2 = 0 // 開口率が2%未満のガス導管数 81 Mpath.Ncv = 0 // 制御弁数 82 Mpath.Plist = make([]*PLIST, 0) // 末端経路 83 //Pelmpre = nil 84 85 // PLIST読み込み用ループ 開始 86 iPlist := 0 //デフォルト名の設定用カウンタ 87 for f.IsEnd() == false { 88 s = f.GetToken() 89 if s[0] == ';' { 90 break 91 } 92 93 if DEBUG { 94 fmt.Printf("eepathdat.c s=%s\n", s) 95 } 96 97 if s[0] == '-' { 98 // 99 // MPATH用の属性を読み込む -sys or -f 100 // 101 ss = f.GetToken() 102 103 if s[1:] == "sys" { 104 // システムの分類(A:空調・暖房システム、D:給湯システム) 105 Mpath.Sys = ss[0] 106 } else if s[1:] == "f" { 107 // 循環、通過流体の種類(水系統、空気系統の別) 108 //(W:水系統、A:空気系統で温・湿度とも計算、a:空気系統で温度のみ計算。 109 Mpath.Fluid = FliudType(ss[0]) 110 } else { 111 Errprint(1, errkey, s) 112 } 113 } else if s == ">" { 114 // 115 // PLIST用の作成 ">"から">"の塊を読みとる 116 // 117 Plist := NewPLIST() 118 Plist.Plistname = fmt.Sprintf("Path%d", iPlist) // 末端経路名 119 Plist.Pelm = make([]*PELM, 0, 10) // 機器のリスト 120 iPlist++ 121 122 // PELM読み込み用ループ 開始 123 for f.IsEnd() == false { 124 s = f.GetToken() 125 126 // ">" が来ると終了 127 if s == ">" { 128 break 129 } 130 131 if DEBUG { 132 fmt.Printf("eepathdat.c s=%s\n", s) 133 } 134 135 if s[0] == '(' { 136 // 137 // 流量の計算に使用される係数を読み取る - `(<flwvol>)` のような文字列で定義される 138 // 139 140 // "(value)" のような文字列から vaue を取り出す正規表現 141 re := regexp.MustCompile(`\((.*?)\)`) 142 matches := re.FindStringSubmatch(s) 143 144 if len(matches) >= 2 { 145 ss := matches[1] 146 147 if Go, err := readFloat(ss); err == nil { 148 Plist.Go = CreateConstantValuePointer(Go) 149 if DEBUG { 150 fmt.Printf("Go=%f\n", *Plist.Go) 151 } 152 } else { 153 if DEBUG { 154 fmt.Printf("s=%s ss=%s\n", s, ss) 155 } 156 157 if j, err = idsch(ss, Schdl.Sch, ""); err == nil { 158 Plist.Go = &Schdl.Val[j] 159 } else { 160 Plist.Go = envptr(ss, Simc, Compnt, Wd, nil) 161 } 162 163 if DEBUG { 164 fmt.Printf("Go=%f\n", *Plist.Go) 165 } 166 } 167 } 168 } else if s[0] == '[' { 169 // 170 // 流量比率を読み取る - `[<flwrate>]` のような文字列で定義される 171 // 172 173 // 流量比率設定フラグのセット 174 Mpath.Rate = true 175 176 var Go float64 177 i, err := fmt.Scanf(s[1:], "%f", &Go) 178 if err != nil { 179 panic(err) 180 } 181 if i == 1 { 182 // 指定されていたのが数値なので、流量比率に入力された固定値を設定する 183 Plist.Rate = CreateConstantValuePointer(Go) 184 if DEBUG { 185 fmt.Printf("rate=%f\n", *Plist.Rate) 186 } 187 } else { 188 // 指定されたいたのは数値ではなかったので、設定値スケジュール名である。 189 // 、) 文字が見つかるまでの全ての文字を読み取ります. 190 _, err := fmt.Sscanf(s[1:], "%[^]]", &ss) 191 if err != nil { 192 panic(err) 193 } 194 195 if DEBUG { 196 fmt.Printf("s=%s ss=%s\n", s, ss) 197 } 198 199 // 設定値スケジュールの検索 200 if j, err := idsch(ss, Schdl.Sch, ""); err == nil { 201 // 設定値スケジュールが見つかったので、スケジュール設定値へのポインタを指定 202 Plist.Rate = &Schdl.Val[j] 203 } else { 204 Plist.Rate = envptr(ss, Simc, Compnt, Wd, nil) 205 } 206 207 if DEBUG { 208 fmt.Printf("rate=%f\n", *Plist.Rate) 209 } 210 } 211 } else if strings.HasPrefix(s, "name=") { 212 // 末端経路名称の指定 213 // デフォルトでは、 "Path<No.>"のような名前で指定されるので、これを上書きする 214 _, err := fmt.Sscanf(s, "%*[^=]=%s", &ss) 215 if err != nil { 216 panic(err) 217 } 218 Plist.Plistname = ss 219 } else { 220 221 // 要素名を読み取る 4パターンある. 読み取った要素名は elm に格納する。 222 // 223 var stv string = "" // stv=蓄熱槽のスケジュール 224 var ci ELIOType = ELIO_SPACE 225 var co ELIOType = ELIO_SPACE 226 227 if idx := strings.IndexRune(s, '/'); idx >= 0 { 228 // ex: `xxx/LD` 229 s = s[idx+1:] // 蓄熱槽の機器名 230 stv = s[:idx] // stv=蓄熱槽のスケジュール 231 } 232 if idx := strings.IndexRune(s, ':'); idx >= 0 { 233 // ex: `LD:xxx` 234 Plist.Name = s 235 s = s[:idx] 236 elm = s 237 } else { 238 if idx := strings.IndexRune(s, '['); idx >= 0 { 239 // ex: `LD[r]` 240 // rは経路識別子 241 // 2流体式熱交換器や蓄熱槽のように構成要素が複数の経路にまたがる場合の書式 242 co, ci = ELIOType(s[idx+1]), ELIOType(s[idx+1]) 243 s = s[:idx] 244 elm = s 245 } else { 246 // ex: `LD` 247 elm = s 248 co = ELIOType(0) 249 ci = ELIOType(0) 250 } 251 } 252 253 // SYSCMPで定義したシステム要素名から elm を探す 254 err := 1 255 _, cmp, er := FindComponent(elm, Compnt) 256 if er != nil { 257 panic(er) 258 } 259 err = 0 260 261 // 機器の種類に応じた処理分け 262 // 263 if cmp.Eqptype == FLIN_TYPE && len(Plist.Pelm) == 0 { 264 // 経路の先頭が流入境界条件である場合、経路の種類は流入境界条件である。 265 Plist.Type = IN_LPTP 266 } else if cmp.Eqptype == VALV_TYPE || cmp.Eqptype == TVALV_TYPE { 267 // バルブが見つかったので、後の処理のために経路と機器に相互参照を付与する 268 Plist.Nvalv++ 269 Plist.Valv = cmp.Eqp.(*VALV) 270 Plist.Valv.Plist = Plist // 逆参照 271 } else if cmp.Eqptype == OMVAV_TYPE { 272 // OMバルブが見つかったので、後の処理のために経路と機器に相互参照を付与する 273 // Satoh OMVAV 2010/12/16 274 Plist.NOMVAV++ 275 Plist.OMvav = cmp.Eqp.(*OMVAV) 276 Plist.OMvav.Plist = Plist // 逆参照 277 } else if cmp.Eqptype == VAV_TYPE || cmp.Eqptype == VWV_TYPE { 278 /*---- Satoh Debug VAV 2000/12/6 ----*/ 279 // VAVユニットが見つかったが、見つかった数だけ記録する。 280 Plist.Nvav++ 281 } else if cmp.Eqptype == QMEAS_TYPE { 282 /*---- Satoh Debug QMEAS 2003/6/2 ----*/ 283 // カロリーメータが見つかったので、後の処理のために経路と機器に相互参照を付与する 284 // ただし、単一のカロリーメータは、3種類の値を同時に参照できるため注意する。 285 Qmeas = cmp.Eqp.(*QMEAS) 286 if co == ELIO_G { 287 Qmeas.G = &Plist.G 288 Qmeas.PlistG = Plist 289 Qmeas.Fluid = Mpath.Fluid 290 } else if co == ELIO_H { 291 Qmeas.PlistTh = Plist 292 Qmeas.Nelmh = id 293 } else if co == ELIO_C { 294 Qmeas.PlistTc = Plist 295 Qmeas.Nelmc = id 296 } else { 297 // NOTE: オリジナルコードではこのelseはない。念のため導入してみた。 298 panic(co) 299 } 300 } else if cmp.Eqptype == STANK_TYPE { 301 // 蓄熱槽が見つかった 302 if stv != "" { 303 Plist.Batch = true 304 stank = cmp.Eqp.(*STANK) 305 for i := 0; i < stank.Nin; i++ { 306 if stank.Pthcon[i] == co { 307 var err error 308 if iswc, err = idscw(stv, Schdl.Scw, ""); err == nil { 309 stank.Batchcon[i] = Schdl.Isw[iswc] 310 } 311 } 312 } 313 } 314 } 315 316 // バルブ、カロリーメータは末端経路ごとに1つまでのようだ 317 // その他の要素は複数存在しても良い。 318 if cmp.Eqptype != VALV_TYPE && cmp.Eqptype != TVALV_TYPE && 319 cmp.Eqptype != QMEAS_TYPE && cmp.Eqptype != OMVAV_TYPE { 320 321 Pelm := NewPELM() 322 Pelm.Out = nil 323 Pelm.Cmp = cmp 324 Pelm.Ci = ci 325 Pelm.Co = co 326 //Pelmpre = Pelm 327 328 Plist.Pelm = append(Plist.Pelm, Pelm) 329 *Plm = append(*Plm, Pelm) 330 } 331 332 if cmp.Eqptype != VALV_TYPE && cmp.Eqptype != TVALV_TYPE && 333 cmp.Eqptype != QMEAS_TYPE && cmp.Eqptype != DIVERG_TYPE && 334 335 cmp.Eqptype != CONVRG_TYPE && cmp.Eqptype != DIVGAIR_TYPE && 336 cmp.Eqptype != CVRGAIR_TYPE && cmp.Eqptype != OMVAV_TYPE { 337 id++ 338 } 339 340 Errprint(err, errkey, elm) 341 342 if DEBUG { 343 fmt.Printf("<<Pathdata>> Mp=%s elm=%s Npelm=%d\n", Mpath.Name, elm, len(*Plm)) 344 } 345 } 346 } 347 // PELM読み込み用ループ 終了 348 349 *Plst = append(*Plst, Plist) 350 Mpath.Plist = append(Mpath.Plist, Plist) 351 352 Plist.Mpath = Mpath // 子→親の逆参照 353 //Pelmpre = nil 354 id = 0 355 } else { 356 Errprint(1, errkey, s) 357 } 358 } 359 // PLIST読み込み用ループ 終了 360 361 if DEBUG { 362 // 読み取ったMPATHの順番と流体種別を表示 363 fmt.Printf("<<Pathdata>> Mpath=%d fliud=%c\n", len(*M), Mpath.Fluid) 364 } 365 366 // 流体種別が空気の場合: 空気系統用の絶対湿度経路へのコピーを行う必要がある 367 if Mpath.Fluid == AIR_FLD { 368 if DEBUG { 369 fmt.Printf("<<Pathdata a>> Mp=%s Npelm=%d\n", Mpath.Name, len(*Plm)) 370 } 371 372 // 空気温度用の経路を追加 373 *M = append(*M, Mpath) 374 375 // if *Nplst > 0 { 376 // Mpath.Pl = make([]*PLIST, *Nplst) 377 // for k := 0; k < *Nplst; k++ { 378 // Mpath.Pl[k] = nil 379 // } 380 // } 381 382 // if *Nplst > 0 { 383 // Mpath.Cbcmp = make([]*COMPNT, *Nplst*2) 384 // for k := 0; k < *Nplst*2; k++ { 385 // Mpath.Cbcmp[k] = nil 386 // } 387 // } 388 389 // 空気系統用の絶対湿度経路へのコピー 390 Mpath_x := plistcpy(Mpath, Plm, Plst, Compnt) 391 *M = append(*M, Mpath_x) 392 } else { 393 *M = append(*M, Mpath) 394 } 395 } 396 // 最外ループ: MPATHの読み込み 完了 397 398 if DEBUG { 399 if len(*M) > 0 { 400 plistprint(*M, *Plm, *Elout, *Elin) 401 } 402 403 fmt.Printf("SYSPTH Data Read end\n") 404 fmt.Printf("Nmpath=%d\n", len(*M)) 405 } 406 407 /* ============================================================================ */ 408 409 // すべてのMPATHについてのループ 410 for i, Mpath := range *M { 411 if DEBUG { 412 fmt.Printf("1----- MAX=%d i=%d\n", len(*M), i) 413 } 414 415 ncv = 0 416 417 // 418 // --- pelmci or pelmco を呼び出す---- 419 // 420 for j, Plist := range Mpath.Plist { 421 422 if DEBUG { 423 fmt.Printf("eepath.c Mpath->Nlpath=%d\n", len(Mpath.Plist)) 424 fmt.Printf("<<Pathdata>> i=%d Mpath=%d j=%d Plist=%d\n", i, i, j, j) 425 } 426 427 for m, Pelm := range Plist.Pelm { 428 429 if DEBUG { 430 fmt.Printf("<<Pathdata>> m=%d pelm=%d %s\n", m, m, Pelm.Cmp.Name) 431 fmt.Printf("MAX=%d m=%d\n", len(Plist.Pelm), m) 432 } 433 434 // 435 // --- システム要素入出力端割当 --- 436 // 437 438 idci := true // システム要素入力端割当を行うか? 439 idco := true // システム要素出力端割当を行うか? 440 etyp := Pelm.Cmp.Eqptype 441 442 if m == 0 && etyp == FLIN_TYPE { 443 // 末端経路の先頭要素が*流入境界条件*である場合 444 idci = false // 流入境界条件 445 } 446 447 if m == 0 && (etyp == CONVRG_TYPE || etyp == DIVERG_TYPE) { 448 // 末端経路の先頭要素が*水*の合流または分岐である場合 449 idci = false 450 } else if m == 0 && (etyp == CVRGAIR_TYPE || etyp == DIVGAIR_TYPE) { 451 // 末端経路の先頭要素が*空気*の合流または分岐である場合 452 idci = false 453 } 454 455 if m == len(Plist.Pelm)-1 && (etyp == CONVRG_TYPE || etyp == DIVERG_TYPE) { 456 // 末端経路の最後尾要素が*水*の合流または分岐である場合 457 idco = false 458 } else if m == len(Plist.Pelm)-1 && (etyp == CVRGAIR_TYPE || etyp == DIVGAIR_TYPE) { 459 // 末端経路の最後尾要素が*空気*の合流または分岐である場合 460 idco = false 461 } 462 463 if idci { 464 // システム要素入力端割当 465 pelmci(Mpath.Fluid, Pelm, errkey) 466 Pelm.In.Lpath = Plist 467 } 468 469 if idco { 470 // システム要素出力端割当 471 pelmco(Mpath.Fluid, Pelm, errkey) 472 473 Pelm.Out.Lpath = Plist 474 Pelm.Out.Fluid = Mpath.Fluid 475 } 476 } 477 } 478 479 if DEBUG { 480 plistprint((*M)[i:i+1], *Plm, *Elout, *Elin) 481 fmt.Printf("i=%d\n", i) 482 } 483 484 // 485 // --- 貫流経路か循環経路かの判定 + 要素間の接続 --- 486 // 487 if len(Mpath.Plist) == 1 { 488 // 489 // 末端経路の数が1の場合 490 // 491 492 Plist := Mpath.Plist[0] 493 494 if DEBUG { 495 fmt.Printf("<<Pathdata>> Plist->type=%c\n", Plist.Type) 496 } 497 498 if Plist.Type == IN_LPTP { 499 Mpath.Type = THR_PTYP 500 501 if DEBUG { 502 fmt.Printf("<<Pathdata>> Mpath->type=%c\n", Mpath.Type) 503 } 504 } else { 505 Mpath.Type = CIR_PTYP 506 Plist.Type = CIR_PTYP 507 Plist.Pelm[0].In.Upo = Plist.Pelm[len(Plist.Pelm)-1].Out 508 } 509 510 if DEBUG { 511 fmt.Printf("<<Pathdata>> test end\n") 512 } 513 514 // 2番目以降の要素について 515 for m = 1; m < len(Plist.Pelm); m++ { 516 Pelm := Plist.Pelm[m] 517 PelmPrev := Plist.Pelm[m-1] 518 519 // 要素間の接続: 1つ前の要素の出力への参照を設定 520 Pelm.In.Upo = PelmPrev.Out 521 } 522 } else { 523 // 524 // 末端経路の数が2以上の場合 525 // 526 527 Mpath.Type = BRC_PTYP 528 529 if DEBUG { 530 fmt.Printf("<<Pathdata>> Mpath i=%d type=%c\n", i, Mpath.Type) 531 } 532 533 for j, Plist := range Mpath.Plist { 534 // 1. 先頭要素による判定 535 // 536 Pelm_0 := Plist.Pelm[0] 537 etyp_0 := Pelm_0.Cmp.Eqptype 538 539 if DEBUG { 540 fmt.Printf("<<Pathdata>> Plist j=%d name=%s eqptype=%s\n", j, Pelm_0.Cmp.Name, etyp_0) 541 } 542 543 if etyp_0 == DIVERG_TYPE || etyp_0 == DIVGAIR_TYPE { 544 // 先頭要素が水または空気の*分岐*である場合 545 Plist.Type = DIVERG_LPTP 546 } 547 548 if etyp_0 == CONVRG_TYPE || etyp_0 == CVRGAIR_TYPE { 549 // 先頭要素が水または空気の*合流*である場合 550 Plist.Type = CONVRG_LPTP 551 ncv++ 552 } 553 554 // 2. 最後尾要素による判定 555 // 556 etyp_fin := Plist.Pelm[len(Plist.Pelm)-1].Cmp.Eqptype 557 if etyp_fin != DIVERG_TYPE && etyp_fin != CONVRG_TYPE && 558 etyp_fin != DIVGAIR_TYPE && etyp_fin != CVRGAIR_TYPE { 559 // 最後尾要素が水または空気の分岐または合流である場合 560 Plist.Type = OUT_LPTP 561 } 562 563 // 2番目以降の要素について 564 for m := 1; m < len(Plist.Pelm); m++ { 565 Pelm := Plist.Pelm[m] 566 PelmPrev := Plist.Pelm[m-1] 567 568 // 要素間の接続: 1つ前の要素の出力への参照を設定 569 Pelm.In.Upo = PelmPrev.Out 570 } 571 572 if DEBUG { 573 fmt.Printf("<<Pathdata>> Plist MAX=%d j=%d type=%c\n", len(Mpath.Plist), j, Plist.Type) 574 } 575 } 576 } 577 Mpath.Ncv = ncv 578 579 if DEBUG { 580 fmt.Printf("2----- MAX=%d i=%d\n", len(*M), i) 581 } 582 } 583 584 if DEBUG { 585 if len(*M) > 0 { 586 mpi := *M 587 plistprint(mpi, *Plm, *Elout, *Elin) 588 } 589 } 590 591 // バルブがモニターするPlistの検索 592 Valvinit(Eqsys.Valv, *M) 593 594 // 未知流量等の構造解析 595 pflowstrct(*M) 596 597 if DEBUG { 598 if len(*M) > 0 { 599 plistprint(*M, *Plm, *Elout, *Elin) 600 } 601 } 602 603 if DEBUG { 604 fmt.Printf("\n") 605 for i = range Compnt { 606 C := Compnt[i] 607 fmt.Printf("name=%s Nin=%d Nout=%d\n", C.Name, C.Nin, C.Nout) 608 } 609 } 610 } 611 612 /***********************************************************************/ 613 614 func Mpathcount(fi *EeTokens, Pl *int) int { 615 var N int 616 var ad int 617 var s string 618 619 ad = fi.GetPos() 620 *Pl = 0 621 622 for fi.IsEnd() == false { 623 s = fi.GetToken() 624 625 if s == "*" { 626 break 627 } 628 629 if s == ";" { 630 N++ 631 } 632 633 if s == ">" { 634 *Pl++ 635 } 636 } 637 638 *Pl /= 2 639 640 fi.RestorePos(ad) 641 642 return N 643 } 644 645 /***********************************************************************/ 646 647 func Plcount(fi *EeTokens, N []int) { 648 i := 0 649 M := 0 650 ad := fi.GetPos() 651 652 for fi.IsEnd() == false { 653 s := fi.GetToken() 654 655 if s == "*" { 656 break 657 } 658 659 if s == ";" { 660 N[M] = i 661 M++ 662 i = 0 663 } 664 665 if s == ">" { 666 i++ 667 fi.GetToken() // skip next token 668 } 669 } 670 671 // Print the contents of the N slice for debugging purposes 672 // for i := 0; i < len(*N); i++ { 673 // fmt.Printf("i=%d pl=%d\n", i, (*N)[i]) 674 // } 675 676 fi.RestorePos(ad) 677 } 678 679 /***********************************************************************/ 680 681 // 末端経路のシステム要素数を数える。 682 // 流体が空気であって温・湿度の両方を計算する場合には、経路を複製して1経路を2経路分としてカウントする 683 func Pelmcount(fi *EeTokens) int { 684 ad := fi.GetPos() 685 i := 1 686 N := 0 687 688 for fi.IsEnd() == false { 689 s := fi.GetToken() 690 i = 1 691 692 if s == "*" { 693 break 694 } 695 696 for fi.IsEnd() == false { 697 s = fi.GetToken() 698 699 if s == ";" { 700 break 701 } 702 703 if s == "-f" { 704 // 循環、通過流体の種類(水系統、空気系統の別) 705 t := fi.GetToken() 706 707 if t == "W" || t == "a" { 708 // W:水系統、a:空気系統で温度のみ計算 709 i = 1 710 } else { 711 // A:空気系統で温・湿度とも計算 712 i = 2 // 温・湿度に分けるので2経路としてカウントする 713 } 714 } 715 716 if s == "-sys" { 717 // `A` or `D`. システムの分類(A:空調・暖房システム、D:給湯システム) 718 fi.GetToken() 719 } 720 721 if s != ">" && s[:1] != "(" && s[:1] != "-" && s[:1] != ";" { 722 N += i 723 } 724 } 725 } 726 727 fi.RestorePos(ad) 728 return N 729 } 730 731 /***********************************************************************/ 732 733 func Elcount(C []*COMPNT) (int, int) { 734 var Nelout, Nelin int = 0, 0 735 736 for i := range C { 737 e := C[i].Eqptype 738 Nelout += C[i].Nout 739 Nelin += C[i].Nin 740 741 if e == HCLOADW_TYPE { 742 Nelin += 8 743 } else if e == THEX_TYPE { 744 Nelout += 4 745 Nelin += 14 746 } 747 } 748 749 Nelout *= 4 750 Nelin *= 4 751 752 return Nelout, Nelin 753 } 754 755 func FindComponent(name string, Compnt []*COMPNT) (int, *COMPNT, error) { 756 for i := range Compnt { 757 cmp := Compnt[i] 758 if cmp.Name == name { 759 return i, cmp, nil 760 } 761 } 762 return -1, nil, errors.New(fmt.Sprintf("Component %s not found", name)) 763 } 764 765 // 定数ポインタの作成する。初期値は constValue とする。 766 func CreateConstantValuePointer(constValue float64) *float64 { 767 val := new(float64) 768 *val = constValue 769 return val 770 }