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  }