github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/mcvav.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 /* mcvav.c */ 17 18 /* VAVコントローラ */ 19 20 package eeslism 21 22 import ( 23 "errors" 24 "fmt" 25 "io" 26 "math" 27 "strconv" 28 "strings" 29 ) 30 31 /* ------------------------------------------ */ 32 33 /* 機器仕様入力 */ 34 35 /*---- Satoh Debug VAV 2000/10/30 ----*/ 36 37 func VAVdata(cattype EqpType, s string, vavca *VAVCA) int { 38 var st string 39 var dt float64 40 var id int 41 42 if cattype == VAV_TYPE { 43 vavca.Type = VAV_PDT 44 } else if cattype == VWV_TYPE { 45 vavca.Type = VWV_PDT 46 } 47 48 if st = strings.Split(s, "=")[1]; st == "" { 49 vavca.Name = s 50 vavca.Gmax = -999.0 51 vavca.Gmin = -999.0 52 vavca.dTset = -999.0 53 } else { 54 dt, _ = strconv.ParseFloat(st, 64) 55 56 switch s { 57 case "Gmax": 58 vavca.Gmax = dt 59 case "Gmin": 60 vavca.Gmin = dt 61 case "dTset": 62 vavca.dTset = dt 63 default: 64 id = 1 65 } 66 } 67 68 return id 69 } 70 71 func VWVint(VAVs []*VAV, Compn []*COMPNT) { 72 for _, vav := range VAVs { 73 vav.Hcc = nil 74 vav.Hcld = nil 75 vav.Mon = '-' 76 77 if vav.Cat.Type == VWV_PDT { 78 if vav.Cmp.Hccname != "" { 79 vav.Hcc = hccptr('c', vav.Cmp.Hccname, Compn, &vav.Mon).(*HCC) 80 } else if vav.Cmp.Rdpnlname != "" { 81 vav.Rdpnl = rdpnlptr(vav.Cmp.Rdpnlname, Compn) 82 if vav.Rdpnl != nil { 83 vav.Mon = 'f' 84 } 85 } 86 87 if vav.Mon == '-' { 88 vav.Hcld = hccptr('h', vav.Cmp.Hccname, Compn, &vav.Mon).(*HCLOAD) 89 } 90 91 if vav.Mon == '-' { 92 s := fmt.Sprintf("VWV(%s)=%s", vav.Name, vav.Cmp.Hccname) 93 fmt.Printf("xxxxxxxxx %s xxxxxxxxxxx\n", s) 94 } 95 } 96 } 97 } 98 99 /* 特性式の係数 */ 100 /*---- Satoh Debug VAV 2000/11/8 ----*/ 101 /*********************/ 102 103 // 104 // +-----+ ---> [OUT 1] 空気 or 温水温度 105 /// | VAV | 106 // +-----+ ---> [OUT 2] 湿度 (VAV_PDTのみ) 107 // 108 func VAVcfv(vav []*VAV) { 109 for _, v := range vav { 110 Eo1 := v.Cmp.Elouts[0] 111 112 if v.Cmp.Control != OFF_SW && Eo1.Control != OFF_SW { 113 if v.Cat.Gmax < 0.0 { 114 Err := fmt.Sprintf("Name=%s Gmax=%.5g", v.Name, v.Cat.Gmax) 115 Eprint("VAVcfv", Err) 116 } 117 if v.Cat.Gmin < 0.0 { 118 Err := fmt.Sprintf("Name=%s Gmin=%.5g", v.Name, v.Cat.Gmin) 119 Eprint("VAVcfv", Err) 120 } 121 122 if v.Count == 0 { 123 v.G = Eo1.G 124 v.CG = Spcheat(Eo1.Fluid) * v.G 125 126 Eo1.Coeffo = v.CG 127 Eo1.Co = 0.0 128 Eo1.Coeffin[0] = -v.CG 129 } else { 130 Eo1.Coeffo = 1.0 131 Eo1.Co = 0.0 132 Eo1.Coeffin[0] = -1.0 133 } 134 135 if v.Cat.Type == VAV_PDT { 136 Eo2 := v.Cmp.Elouts[1] 137 Eo2.Coeffo = 1.0 138 Eo2.Co = 0.0 139 Eo2.Coeffin[0] = -1.0 140 } 141 } 142 } 143 } 144 145 /************************:/ 146 /* ------------------------------------------ */ 147 148 /* VAVコントローラ再熱部分の計算 */ 149 /*---- Satoh Debug VAV 2000/11/27 ----*/ 150 /*******************/ 151 func VAVene(vav []*VAV, VAVrest *int) { 152 var rest int 153 var elo *ELOUT 154 var Tr, Go, dTset float64 155 156 for _, v := range vav { 157 rest = 0 158 159 elo = v.Cmp.Elouts[0] 160 v.Tin = elo.Elins[0].Sysvin 161 162 if v.Cmp.Control != OFF_SW && elo.Control != OFF_SW { 163 Go = v.G 164 v.Tout = elo.Sysv 165 166 if v.Cat.Type == VAV_PDT { 167 Tr = v.Cmp.Elouts[0].Emonitr.Sysv 168 169 v.Q = Spcheat(elo.Fluid) * Go * (v.Tout - Tr) 170 171 if math.Abs(v.Tin-Tr) > 1.0e-3 { 172 v.G = (v.Tout - Tr) / (v.Tin - Tr) * Go 173 } else { 174 v.G = v.Cat.Gmin 175 } 176 } else { 177 if v.Mon == 'c' && v.Count < VAVCountMAX-1 { 178 v.Qrld = -v.Hcc.Qt 179 } else if v.Mon == 'f' && v.Count < VAVCountMAX-1 { 180 v.Qrld = -v.Rdpnl.Q 181 } else if v.Mon == 'h' { 182 v.Qrld = v.Hcld.Qt 183 } 184 185 v.Q = v.Qrld 186 187 dTset = v.Cat.dTset 188 189 if v.Mon == 'h' && dTset <= 0.0 { 190 fmt.Printf("<VAVene> VWV SetDifferencialTemp=%.1f\n", v.Cat.dTset) 191 } 192 193 if v.Chmode == COOLING_SW { 194 dTset = -dTset 195 } 196 197 if v.Mon == 'h' || v.Mon == 'f' { 198 v.G = v.Q / (Spcheat(elo.Fluid) * dTset) 199 } else if v.Mon == 'c' { 200 v.G = FNVWVG(v) 201 } 202 } 203 204 elo.Control = ON_SW 205 elo.Sysld = 'n' 206 207 if v.Mon != 'h' { 208 elo.Emonitr.Control = ON_SW 209 } 210 211 rest = chvavswreset(v.Q, v.Chmode, v) 212 213 if rest == 1 || math.Abs(v.G-Go) > 1.0e-5 { 214 (*VAVrest)++ 215 } 216 } else { 217 v.Q = 0.0 218 v.G = v.Cat.Gmin 219 220 if v.Count == 0 { 221 (*VAVrest)++ 222 } 223 } 224 } 225 } 226 227 func (eqsys *EQSYS) VAVcountreset() { 228 for _, v := range eqsys.Vav { 229 v.Count = 0 230 } 231 } 232 233 func (eqsys *EQSYS) VAVcountinc() { 234 for _, v := range eqsys.Vav { 235 v.Count++ 236 } 237 } 238 239 // VAVスイッチのポインターを作成します 240 func vavswptr(key []string, VAV *VAV) (VPTR, error) { 241 if key[1] == "chmode" { 242 return VPTR{ 243 Ptr: &VAV.Chmode, 244 Type: SW_CTYPE, 245 }, nil 246 } else if key[1] == "control" { 247 return VPTR{ 248 Ptr: &VAV.Cmp.Elouts[0].Control, 249 Type: SW_CTYPE, 250 }, nil 251 252 } 253 return VPTR{}, errors.New("vavswptr error") 254 } 255 256 func chvavswreset(Qload float64, chmode ControlSWType, vav *VAV) int { 257 if (chmode == HEATING_SW && Qload < 0.0) || 258 (chmode == COOLING_SW && Qload > 0.0) { 259 vav.G = vav.Cat.Gmin 260 return 1 261 } else { 262 if vav.G < vav.Cat.Gmin { 263 vav.G = vav.Cat.Gmin 264 return 1 265 } else if vav.G > vav.Cat.Gmax { 266 vav.G = vav.Cat.Gmax 267 return 1 268 } else { 269 return 0 270 } 271 } 272 } 273 274 func vavprint(fo io.Writer, id int, VAVs []*VAV) { 275 switch id { 276 case 0: 277 if len(VAVs) > 0 { 278 fmt.Fprintf(fo, "%s %d\n", VAV_TYPE, len(VAVs)) 279 } 280 for _, vav := range VAVs { 281 fmt.Fprintf(fo, " %s 1 2\n", vav.Name) 282 } 283 case 1: 284 for _, vav := range VAVs { 285 fmt.Fprintf(fo, "%s_c c c %s_G m f\n", vav.Name, vav.Name) 286 } 287 default: 288 for _, vav := range VAVs { 289 fmt.Fprintf(fo, "%c %6.4g\n", vav.Cmp.Elouts[0].Control, vav.Cmp.Elouts[0].G) 290 } 291 } 292 } 293 294 /* VWVシステムの流量計算 */ 295 func FNVWVG(VWV *VAV) float64 { 296 var Wa, Wwd, Tain, Twin, Q, KA, et, F, emax, emin, Gwd float64 297 var A, B float64 298 var h *HCC 299 var i int 300 301 h = VWV.Hcc 302 Wa = h.cGa 303 Q = VWV.Q 304 KA = h.Cat.KA 305 Tain = h.Tain 306 Twin = VWV.Tin 307 A = VWV.Cat.Gmin 308 B = VWV.Cat.Gmax 309 Gwd = (A + B) / 2.0 310 Wwd = Gwd * Cw 311 312 et = -Q / (Wa * (Tain - Twin)) 313 emin = FNhccet(Wa, Cw*A, KA) 314 emax = FNhccet(Wa, Cw*B, KA) 315 316 if et > emax { 317 return VWV.Cat.Gmax 318 } else if et < emin { 319 return VWV.Cat.Gmin 320 } 321 322 for i = 0; i < 30; i++ { 323 Wwd = Gwd * Cw 324 F = FNhccet(Wa, Wwd, KA) - et 325 if math.Abs(F) < 1.0e-5 { 326 return Gwd 327 } else if F > 0.0 { 328 B = Gwd 329 } else if F < 0.0 { 330 A = Gwd 331 } 332 333 Gwd = (A + B) / 2.0 334 } 335 336 fmt.Println("xxxxxx FNVWVG 収束せず") 337 fmt.Println(Gwd) 338 339 return Gwd 340 } 341 342 func FNFd(Wa, Ww, KA float64) float64 { 343 B := (1.0 - Wa/Ww) * KA / Wa 344 exB := math.Exp(-B) 345 ex2B := math.Exp(-2.0 * B) 346 Ww2 := math.Pow(Ww, 2.0) 347 348 d := Ww * math.Pow(Ww-Wa*exB, 2.0) 349 n := (Ww2+Ww+KA)*ex2B - (Ww*(Ww2+Wa)-Wa*KA)*exB 350 351 return n / d 352 }