github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/blroom.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 /* room.c */ 17 package eeslism 18 19 import "fmt" 20 21 /* ----------------------------------------------------------- */ 22 23 /* 室内サブシステムに関する計算 */ 24 25 func RMcf(Room *ROOM) { 26 N := Room.N 27 for n := 0; n < N; n++ { 28 Sdn := Room.rsrf[n] 29 30 if Sdn.mrk == '*' || Sdn.PCMflg { 31 32 // 壁体(窓以外の場合) 33 if Sdn.typ == RMSRFType_H || Sdn.typ == RMSRFType_E || Sdn.typ == RMSRFType_e { 34 Mw := Sdn.mw 35 M := Mw.M 36 mp := Mw.mp 37 38 if Sdn.mwside == RMSRFMwSideType_i { 39 Sdn.FI = Mw.uo * Mw.UX[0] 40 41 if Sdn.mw.wall.WallType != WallType_C { 42 Sdn.FO = Mw.um * Mw.UX[M-1] 43 } else { 44 Sdn.FO = Sdn.ColCoeff * Mw.UX[M-1] 45 } 46 47 if Sdn.rpnl != nil { 48 Sdn.FP = Mw.Pc * Mw.UX[mp] * Sdn.rpnl.Wp 49 } else { 50 Sdn.FP = 0.0 51 } 52 } else { 53 MM := (M - 1) * M 54 55 if Sdn.mw.wall.WallType != WallType_C { 56 Sdn.FI = Mw.um * Mw.UX[MM+M-1] 57 } else { 58 Sdn.FI = Sdn.ColCoeff * Mw.UX[MM+M-1] 59 } 60 61 Sdn.FO = Mw.uo * Mw.UX[MM] 62 if Sdn.rpnl != nil { 63 Sdn.FP = Mw.Pc * Mw.UX[MM+mp] * Sdn.rpnl.Wp 64 } else { 65 Sdn.FP = 0.0 66 } 67 } 68 } else { 69 // 窓の場合 70 /*** K = Sdn.K = 1.0/(Sdn.Rwall + rai + rao); ***/ 71 K := Sdn.K 72 ali := Sdn.ali 73 Sdn.FI = 1.0 - K/ali 74 Sdn.FO = K / ali 75 Sdn.FP = 0.0 76 } 77 } 78 } 79 80 alr := Room.alr 81 XA := Room.XA 82 for n := 0; n < N; n++ { 83 Sdn := Room.rsrf[n] 84 85 for j := 0; j < N; j++ { 86 XA[n*N+j] = -Sdn.FI * alr[n*N+j] / Sdn.ali 87 } 88 89 XA[n*N+n] = 1.0 90 } 91 92 E := fmt.Sprintf("<RMcf> name=%s", Room.Name) 93 Matinv(XA, N, N, E) 94 95 for n := 0; n < N; n++ { 96 Sdn := Room.rsrf[n] 97 98 Sdn.WSR = 0.0 99 100 for j := 0; j < N; j++ { 101 sdj := Room.rsrf[j] 102 kc := sdj.alic / sdj.ali 103 Sdn.WSR += XA[n*N+j] * sdj.FI * kc 104 } 105 106 for j := 0; j < Room.Ntr; j++ { 107 wrn := &Sdn.WSRN[j] 108 trn := Room.trnx[j] 109 sdk := trn.sd 110 111 // Find the index of sdk in Room.rsrf 112 var kk int 113 for kk = 0; kk < Room.N; kk++ { 114 if sdk == Room.rsrf[kk] { 115 break 116 } 117 } 118 *wrn = XA[n*N+kk] * sdk.FO * sdk.nxsd.alic / sdk.nxsd.ali 119 } 120 121 for j := 0; j < Room.Nrp; j++ { 122 sdk := Room.rmpnl[j].sd 123 124 // Find the index of sdk in Room.rsrf 125 var kk int 126 for kk = 0; kk < Room.N; kk++ { 127 if sdk == Room.rsrf[kk] { 128 break 129 } 130 } 131 132 // XA:室内表面温度計算のためのマトリックス 133 // FP:パネルの係数 134 Sdn.WSPL[j] = XA[n*N+kk] * sdk.FP 135 } 136 } 137 138 Room.AR = 0.0 139 for n := 0; n < N; n++ { 140 Sdn := Room.rsrf[n] 141 Room.AR += Sdn.A * Sdn.alic * (1.0 - Sdn.WSR) 142 } 143 144 // 室内空気の総合熱収支式の係数 145 for j := 0; j < Room.Ntr; j++ { 146 arn := 0.0 147 for n := 0; n < N; n++ { 148 sdk := Room.rsrf[n] 149 arn += sdk.A * sdk.alic * sdk.WSRN[j] 150 } 151 Room.ARN[j] = arn 152 } 153 154 for j := 0; j < Room.Nrp; j++ { // 室のパネル総数 155 rpnl := 0.0 156 for n := 0; n < N; n++ { 157 sdk := Room.rsrf[n] 158 rpnl += sdk.A * sdk.alic * sdk.WSPL[j] // WSPL:パネルに関する係数 159 } 160 Room.RMP[j] = rpnl 161 } 162 163 // 室温の係数 164 // 家具の熱容量の計算 165 FunCoeff(Room) 166 } 167 168 // 家具内蔵PCMの係数計算 169 func FunCoeff(Room *ROOM) { 170 // 室温の係数 171 // 家具の熱容量の計算 172 Room.FunHcap = 0.0 173 if Room.CM != nil && *Room.CM > 0.0 { 174 if Room.MCAP != nil && *Room.MCAP > 0.0 { 175 Room.FunHcap += *Room.MCAP 176 } 177 if Room.PCM != nil { 178 if Room.PCM.Spctype == 'm' { 179 Room.PCMQl = FNPCMStatefun(Room.PCM.Ctype, Room.PCM.Cros, Room.PCM.Crol, Room.PCM.Ql, 180 Room.PCM.Ts, Room.PCM.Tl, Room.PCM.Tp, Room.oldTM, Room.TM, Room.PCM.DivTemp, &Room.PCM.PCMp) 181 } else { 182 Room.PCMQl = FNPCMstate_table(&Room.PCM.Chartable[0], Room.oldTM, Room.TM, Room.PCM.DivTemp) 183 } 184 Room.FunHcap += Room.mPCM * Room.PCMQl 185 } 186 } 187 if Room.FunHcap > 0.0 { 188 Room.FMT = 1.0 / (Room.FunHcap/DTM/(*Room.CM) + 1.0) 189 } else { 190 Room.FMT = 1.0 191 } 192 193 Room.RMt = Room.MRM/DTM + Room.AR 194 195 if Room.FunHcap > 0.0 { 196 Room.RMt -= *Room.CM * (Room.FMT - 1.0) 197 } 198 } 199 200 func RMrc(Room *ROOM) { 201 N := Room.N 202 XA := Room.XA 203 CRX := make([]float64, N) 204 205 for n := 0; n < N; n++ { // N:表面総数 206 Sdn := Room.rsrf[n] 207 Sdn.CF = 0.0 208 if Sdn.typ == RMSRFType_H || Sdn.typ == RMSRFType_E || Sdn.typ == RMSRFType_e { // 壁の場合 209 Mw := Sdn.mw 210 M := Mw.M 211 if Sdn.mwside != RMSRFMwSideType_M { // 室内側 212 for j := 0; j < M; j++ { 213 Sdn.CF += Mw.UX[j] * Mw.Told[j] 214 } 215 } else { 216 MM := M * (M - 1) 217 UX := Mw.UX[MM:] 218 for j := 0; j < M; j++ { 219 Sdn.CF += UX[j] * Mw.Told[j] 220 } 221 } 222 } 223 } 224 225 Room.HGc = Room.Hc + Room.Lc + Room.Ac + Room.Qeqp*Room.eqcv 226 227 // 表面熱収支に関係する係数の計算 228 for n := 0; n < N; n++ { 229 Sdn := Room.rsrf[n] 230 CRX[n] = Sdn.CF + Sdn.FO*Sdn.Te + Sdn.FI*Sdn.RS/Sdn.ali 231 } 232 233 // 相互放射の計算 234 for n := 0; n < N; n++ { 235 Sdn := Room.rsrf[n] 236 Sdn.WSC = 0.0 237 for j := 0; j < N; j++ { 238 Sdn.WSC += XA[n*N+j] * CRX[j] 239 } 240 } 241 242 Room.CA = 0.0 243 for n := 0; n < N; n++ { 244 Sdn := Room.rsrf[n] 245 Room.CA += Sdn.A * Sdn.alic * Sdn.WSC 246 } 247 248 // 室空気の熱収支の係数計算 249 // 家具の影響項の追加 250 if Room.FunHcap > 0.0 { 251 dblTemp := DTM / Room.FunHcap 252 Room.FMC = 1.0 / (dblTemp**Room.CM + 1.0) * (Room.oldTM + dblTemp*Room.Qsolm) 253 } else { 254 Room.FMC = 0.0 255 } 256 257 Room.RMC = Room.MRM/DTM*Room.Trold + Room.HGc + Room.CA 258 if Room.FunHcap > 0.0 { 259 Room.RMC += *Room.CM * Room.FMC 260 } 261 262 } 263 264 /* ----------------------------------------------------- */ 265 // 室Roomの壁体の表面温度の計算 -- RooM's SuRface Temperature 266 func RMsrt(Room *ROOM) { 267 N := Room.N 268 269 for n := 0; n < N; n++ { 270 Sdn := Room.rsrf[n] 271 272 Sdn.Ts = Sdn.WSR*Room.Tr + Sdn.WSC 273 274 for j := 0; j < Room.Ntr; j++ { 275 trn := Room.trnx[j] 276 Sdn.Ts += Sdn.WSRN[j] * trn.nextroom.Tr 277 } 278 279 for j := 0; j < Room.Nrp; j++ { 280 rmpnl := Room.rmpnl[j] 281 Sdn.Ts += Sdn.WSPL[j] * rmpnl.pnl.Tpi 282 } 283 } 284 285 alr := Room.alr 286 for n := 0; n < N; n++ { 287 Sdn := Room.rsrf[n] 288 Sdn.Tmrt = 0.0 289 290 for j := 0; j < N; j++ { 291 Sd := Room.rsrf[j] 292 if j != n { 293 Sdn.Tmrt += Sd.Ts * alr[n*N+j] 294 } 295 } 296 Sdn.Tmrt /= alr[n*N+n] 297 } 298 299 for n := 0; n < N; n++ { 300 Sd := Room.rsrf[n] 301 Sd.Qc = Sd.alic * Sd.A * (Sd.Ts - Room.Tr) 302 Sd.Qr = Sd.alir * Sd.A * (Sd.Ts - Sd.Tmrt) 303 Sd.Qi = Sd.Qc + Sd.Qr - Sd.RS*Sd.A 304 } 305 } 306 307 /* ----------------------------------------------------- */ 308 309 // 重量壁(後退差分)の係数行列の作成 310 func RMwlc(Mw []*MWALL, Exsfs *EXSFS, Wd *WDAT) { 311 for i := range Mw { 312 var Mw *MWALL = Mw[i] 313 var Wall *WALL = Mw.wall 314 315 var Sd *RMSRF = Mw.sd 316 rai := 1.0 / Sd.ali // 室内側表面熱抵抗 317 rao := 1.0 / Sd.alo // 室外側表面熱抵抗 318 319 Mw.res[0] = rai 320 if Sd.typ == 'H' { 321 Mw.res[Mw.M] = rao 322 } 323 324 // 壁体にパネルがある場合 325 var Wp float64 326 if Sd.rpnl != nil { 327 Wp = Sd.rpnl.Wp 328 } else { 329 Wp = 0.0 330 } 331 332 // 行列作成 333 Wallfdc(Mw.M, Mw.mp, Mw.res, Mw.cap, Wp, Mw.UX, 334 &Mw.uo, &Mw.um, &Mw.Pc, Wall.WallType, Sd, Wd, Exsfs, Wall, 335 Mw.Told, Mw.Toldd, Mw.sd.pcmstate) 336 } 337 } 338 339 /* ----------------------------------------------------- */ 340 341 // 壁体内部温度の計算 342 func RMwlt(Mw []*MWALL) { 343 for i := range Mw { 344 Mw := Mw[i] 345 Sd := Mw.sd 346 347 // 壁体の反対側の表面温度 ? 348 var Tee float64 349 if Sd.mwtype == RMSRFMwType_C { 350 // 共用壁の場合 351 nxsd := Sd.nxsd 352 Tee = (nxsd.alic*nxsd.room.Tr + nxsd.alir*nxsd.Tmrt + nxsd.RS) / nxsd.ali 353 } else if Sd.mwtype == RMSRFMwType_I { 354 // 専用壁の場合 => 外表面の相当外気温度 355 Tee = Sd.Te 356 } else { 357 panic(Sd.mwtype) 358 } 359 360 Room := Sd.room 361 Tie := (Sd.alic*Room.Tr + Sd.alir*Sd.Tmrt + Sd.RS) / Sd.ali 362 363 if DEBUG { 364 fmt.Printf("----- RMwlt i=%d room=%s ble=%c %s Tie=%f Tee=%f\n", i, Sd.room.Name, Sd.ble, get_string_or_null(Sd.Name), Tie, Tee) 365 } 366 367 var WTp float64 368 if Sd.rpnl != nil { 369 WTp = Sd.rpnl.Wp * Sd.rpnl.Tpi 370 } else { 371 WTp = 0.0 372 } 373 374 // 壁体表面、壁体内部温度の計算 375 Twall(Mw.M, Mw.mp, Mw.UX, Mw.uo, Mw.um, Mw.Pc, Tie, Tee, WTp, Mw.Told, Mw.Tw, Sd, Mw.wall.PCMLyr) 376 377 // 壁体表面温度、壁体内部温度の更新 378 for m := 0; m < Mw.M; m++ { 379 // 前時刻の壁体内部温度を更新 380 Mw.Told[m] = Mw.Tw[m] 381 // 収束過程初期値の壁体内部温度を更新 382 Mw.Twd[m] = Mw.Tw[m] 383 Mw.Told[m] = Mw.Tw[m] 384 } 385 } 386 } 387 388 // 壁体内部温度の仮計算 389 func RMwltd(Mw []*MWALL) { 390 for i := range Mw { 391 var Mw *MWALL = Mw[i] 392 var Sd *RMSRF = Mw.sd 393 var nxsd *RMSRF = Sd.nxsd 394 var Room *ROOM = Sd.room 395 396 if Sd.PCMflg { 397 // Tee 398 var Tee float64 399 if Sd.mwtype == RMSRFMwType_C { 400 Tee = (nxsd.alic*nxsd.room.Tr + nxsd.alir*nxsd.Tmrt + nxsd.RS) / nxsd.ali 401 } else if Sd.mwtype == RMSRFMwType_I { 402 Tee = Sd.Te 403 } else { 404 panic(Sd.mwtype) 405 } 406 407 // Tie 408 Tie := (Sd.alic*Room.Tr + Sd.alir*Sd.Tmrt + Sd.RS) / Sd.ali 409 410 if DEBUG { 411 fmt.Printf("----- RMwlt i=%d room=%s ble=%c %s Tie=%f Tee=%f\n", 412 i, Sd.room.Name, Sd.ble, get_string_or_null(Sd.Name), Tie, Tee) 413 } 414 415 // WTp 416 var WTp float64 417 if Sd.rpnl != nil { 418 WTp = Sd.rpnl.Wp * Sd.rpnl.Tpi 419 } else { 420 WTp = 0.0 421 } 422 423 // 壁体内部温度の仮計算 424 Twalld(Mw.M, Mw.mp, Mw.UX, Mw.uo, Mw.um, Mw.Pc, 425 Tie, Tee, WTp, Mw.Told, Mw.Twd, Sd) 426 } 427 } 428 } 429 430 /* ------------------------------------------------------ */ 431 432 // 室内表面 Sd における平均表面温度の計算 (Room's Temperature of Surface - AVerage) 433 func RTsav(N int, Sd []*RMSRF) float64 { 434 var Tav, Aroom float64 435 for n := 0; n < N; n++ { 436 Tav += Sd[n].Ts * Sd[n].A 437 Aroom += Sd[n].A 438 } 439 return Tav / Aroom 440 }