github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/blrmaceqcf.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  package eeslism
    17  
    18  import "fmt"
    19  
    20  /* -------------------------------------- */
    21  
    22  var __Rmhtrcf_count int
    23  
    24  func Rmhtrcf(exs *EXSFS, emrk []rune, rooms []*ROOM, sds []*RMSRF, wd *WDAT) {
    25  	if rooms != nil {
    26  		for i := range rooms {
    27  			room := rooms[i]
    28  			n := room.N
    29  			brs := room.Brs
    30  			sds := sds[brs : brs+n]
    31  
    32  			if DEBUG {
    33  				fmt.Printf("Room Name=%s\n", room.Name)
    34  			}
    35  
    36  			// 放射熱交換係数の計算
    37  			if __Rmhtrcf_count == 0 || emrk[0] == '*' {
    38  				radex(n, sds, room.F, room.Wradx)
    39  			}
    40  			if DEBUG {
    41  				fmt.Printf("radex end\n")
    42  			}
    43  
    44  			// 放射熱伝達率の入れ替え
    45  			Radcf0(room.Tsav, &room.alrbold, n, sds, room.Wradx, room.alr)
    46  			if DEBUG {
    47  				fmt.Printf("Radcf0 end\n")
    48  			}
    49  
    50  			Htrcf(room.alc, exs.Alosch, exs.Alotype, exs.Exs, room.Tr, n, room.alr, sds, &room.mrk, wd)
    51  			if DEBUG {
    52  				fmt.Printf("Htrcf end\n")
    53  			}
    54  		}
    55  
    56  		__Rmhtrcf_count++
    57  	}
    58  
    59  	if sds != nil {
    60  		for _, sd := range sds {
    61  			if sd.mwtype == RMSRFMwType_C && sd.mwside == RMSRFMwSideType_i {
    62  				// 内壁の場合は裏面室の熱伝達率を入れ替える
    63  				nxsd := sd.nxsd
    64  				sd.alo = nxsd.ali
    65  				nxsd.alo = sd.ali
    66  			}
    67  		}
    68  	}
    69  }
    70  
    71  /* ----------------------------------------------------------------- */
    72  
    73  func Rmrdshfc(_Room []*ROOM, Sd []*RMSRF) {
    74  	if len(_Room) == 0 {
    75  		return
    76  	}
    77  
    78  	for i := range _Room {
    79  		Room := _Room[i]
    80  		brs := Room.Brs
    81  		sd := Sd[brs:]
    82  
    83  		Radshfc(Room.N, Room.FArea, Room.Area, sd, Room.tfsol, Room.eqcv, Room.Name, Room.fsolm)
    84  	}
    85  }
    86  
    87  /* ----------------------------------------------------------------- */
    88  func Rmhtrsmcf(_Sd []*RMSRF) {
    89  	for n := range _Sd {
    90  		Sd := _Sd[n]
    91  		Sd.K = 1.0 / (Sd.Rwall + 1.0/Sd.ali + 1.0/Sd.alo)
    92  	}
    93  }
    94  
    95  /* ----------------------------------------------------------------- */
    96  // 透過日射、相当外気温度の計算
    97  func Rmexct(Room []*ROOM, Sd []*RMSRF, Wd *WDAT, Exs []*EXSF, Snbk []*SNBK, Qrm []*QRM, nday, mt int) {
    98  	if len(Room) == 0 {
    99  		return
   100  	}
   101  
   102  	// 部位ごとの日射吸収比率のスケジュール対応(比率入力部位の日射入射比率初期化)
   103  	for _, rm := range Room {
   104  
   105  		// 室内部位の日射吸収比率の計算
   106  		// 2017/12/25毎時計算へ変更
   107  		// 家具の日射吸収割合
   108  		if rm.fsolm != nil {
   109  			rm.tfsol = *(rm.fsolm)
   110  		} else {
   111  			rm.tfsol = 0.0
   112  		}
   113  
   114  		for _, rsd := range rm.rsrf[:rm.N] {
   115  			// 床の場合
   116  			if rsd.ble == BLE_Floor || rsd.ble == BLE_InnerFloor {
   117  				// どの部位も日射吸収比率が定義されていない場合
   118  				if rm.Nfsolfix == 0 {
   119  					// 床の日射吸収比率は固定
   120  					rsd.ffix_flg = '*'
   121  					rsd.fsol = CreateConstantValuePointer(*rm.flrsr * rsd.A / rm.FArea)
   122  				}
   123  			}
   124  
   125  			// fsolが規定されている部位についてfsolを合計する
   126  			if rsd.ffix_flg == '*' {
   127  				rm.tfsol += *rsd.fsol // fsolの合計値計算
   128  			}
   129  		}
   130  	}
   131  
   132  	// 室内部位の日射吸収比率の計算(毎計算ステップへ変更)2017/12/25
   133  	Rmrdshfc(Room, Sd)
   134  	for i, rm := range Room {
   135  		Q := Qrm[i]
   136  
   137  		rm.Qgt = 0.0
   138  		rm.Qsolm = 0.0
   139  		rm.Qsab = 0.0
   140  		rm.Qrnab = 0.0
   141  		Q.Solo = 0.0
   142  		Q.Solw = 0.0
   143  		Q.Asl = 0.0
   144  
   145  		RmSd := Sd[rm.Brs : rm.Brs+rm.N]
   146  
   147  		for n, Sdn := range RmSd {
   148  
   149  			if Sdn.ble == BLE_InnerWall || Sdn.ble == BLE_InnerFloor || Sdn.ble == BLE_Ceil {
   150  				continue
   151  			}
   152  
   153  			e := Exs[Sdn.exs]
   154  
   155  			Sdn.RSsol = 0.0
   156  			Sdn.RSsold = 0.
   157  			Fsdw := 0.0
   158  			Qgtn := 0.0
   159  			Qga := 0.0
   160  
   161  			var Idre float64     // 直逹日射  [W/m2]
   162  			var Idf float64      // 拡散日射  [W/m2]
   163  			var RN float64       //  夜間輻射  [W/m2]
   164  			if Sdn.Sname == "" { /*---higuchi 070918---start-*/
   165  				Sdn.Fsdworg = 0.0
   166  
   167  				sb := Sdn.sb
   168  				if sb >= 0 && e.Cinc > 0.0 {
   169  					S := Snbk[sb]
   170  
   171  					// 日よけの影面積率 [-]
   172  					Fsdw = FNFsdw(S.Type, S.Ksi, e.Tazm, e.Tprof, S.D, S.W, S.H, S.W1, S.H1, S.W2, S.H2)
   173  					Sdn.Fsdworg = Fsdw
   174  
   175  					if DEBUG {
   176  						fmt.Printf(" xxx Rmexct xxx i=%d n=%d  sb=%d  type=%d  tazm=%f  tprof=%f Fsdw=%f\n",
   177  							i, n, sb, S.Type, e.Tazm, e.Tprof, Fsdw)
   178  					}
   179  				} else {
   180  					Fsdw = 0.0
   181  				}
   182  
   183  				Idre = e.Idre
   184  				Idf = e.Idf
   185  				RN = e.Rn
   186  
   187  				if DEBUG {
   188  					fmt.Printf("1:Fsdw=%f,Idre=%f,Idf=%f,rn=%f Sb=%d Cinc=%f\n", Fsdw, Idre, Idf, RN, sb, e.Cinc)
   189  				}
   190  
   191  			} else { /*---higuchi 070918 end--*/ /*--higuchi 070918 start--*/
   192  				Fsdw = Sdn.Fsdw
   193  				//                  Idre = Sdn.Idre ;  090131 higuchi Sdn.Idre が影をすでに考慮していたため、下に変更
   194  				Idre = e.Idre /*--090131 higuchi  --*/
   195  				Idf = Sdn.Idf
   196  				RN = Sdn.rn
   197  			} /*---higuchi 070918 end --*/
   198  
   199  			switch Sdn.ble {
   200  			case BLE_Window:
   201  				// 通常窓の場合
   202  				/*--higuchi add--*/
   203  				Qgtn, Qga = Glasstga(Sdn.A, Sdn.tgtn, Sdn.Bn,
   204  					e.Cinc, Fsdw, Idre, Idf, Sdn.window.Cidtype, e.Prof, e.Gamma)
   205  				Rab := Sdn.Eo * RN / Sdn.alo // 夜間放射熱取得 [W]
   206  
   207  				Sab := Qga / Sdn.A // [W/m2]
   208  				Sdn.TeEsol = Sab
   209  				Sdn.TeErn = -Rab
   210  				Sdn.TeEsol = Sab / Sdn.K
   211  				Sdn.Te = Sab/Sdn.K - Rab + Wd.T // 外表面の相当外気温
   212  				Sdn.Qgt = Qgtn                  // 開口部の透過日射熱取得 [W]
   213  				Sdn.Qga = Qga                   // 開口部の吸収日射熱取得 [W]
   214  				Sdn.Qrn = -Rab                  // 開口部の夜間放射熱取得 [W/m2]
   215  
   216  				// 部屋rm の日射
   217  				rm.Qgt += Qgtn                  // 部屋rmの透過日射熱取得 [W]
   218  				rm.Qsab += Sab * Sdn.A          // 部屋rmの吸収日射熱取得 [W]
   219  				rm.Qrnab += Rab * Sdn.A * Sdn.K // 部屋rmの夜間放射による熱損失 [W]
   220  
   221  				Q.Solw += Sdn.A * (Idre + Idf) /*--higuchi add  --*/
   222  				break
   223  
   224  			case BLE_ExternalWall, BLE_Floor, BLE_Roof: // このあたりを参考に修正(相当外気温度の計算)
   225  				if Sdn.typ != RMSRFType_E && Sdn.typ != RMSRFType_e {
   226  					/*---higuchi add---*/
   227  					Sab := Sdn.as * (Idre*(1.0-Fsdw) + Idf) / Sdn.alo
   228  					Rab := Sdn.Eo * RN / Sdn.alo // 長波長
   229  					/*------------------*/
   230  
   231  					Sdn.TeEsol = Sab
   232  					Sdn.TeErn = -Rab
   233  
   234  					// 建材一体型空気集熱器のための相当外気温度修正
   235  					if Sdn.rpnl != nil && Sdn.rpnl.Type == 'C' {
   236  						//wall := Sdn.mw.wall
   237  						Sdn.Te = Sdn.Tcole
   238  						Sdn.Iwall = Idre*(1.0-Fsdw) + Idf
   239  					} else {
   240  						Sdn.Te = Sab - Rab + Wd.T
   241  					}
   242  
   243  					rm.Qsab += Sab * Sdn.A * Sdn.K
   244  					Sdn.Qga = Sab * Sdn.A * Sdn.K
   245  					rm.Qrnab += Rab * Sdn.A * Sdn.K
   246  					Q.Solo += Sdn.A * (Idre + Idf)
   247  					Q.Asl += Sdn.as * Sdn.A * (Idre + Idf)
   248  				} else {
   249  					Sdn.Te = e.Tearth
   250  					Sdn.TeEsol = 0.0
   251  					Sdn.TeErn = 0.0
   252  				}
   253  				break
   254  
   255  			case BLE_InnerWall, BLE_InnerFloor, BLE_Ceil, BLE_d:
   256  				if Sdn.nxrm < 0 {
   257  					// 隣室が無い場合
   258  					Tr := Sdn.room.Trold
   259  					Eo := Sdn.room.cmp.Elouts[0]
   260  					if Eo.Control == LOAD_SW {
   261  						Tr = Sdn.room.rmld.Tset
   262  					}
   263  
   264  					// 相当外気温を設定
   265  					Sdn.Te = Sdn.c*Tr + (1.0-Sdn.c)*Wd.T
   266  				} else {
   267  					// 隣室がある場合
   268  					Tr := Sdn.nextroom.Trold
   269  					Eo := Sdn.nextroom.cmp.Elouts[0]
   270  					if Eo.Control == LOAD_SW {
   271  						Tr = Sdn.nextroom.rmld.Tset
   272  					}
   273  
   274  					// 相当外気温を設定
   275  					Sdn.Te = Sdn.c*Tr + (1.0-Sdn.c)*Wd.T
   276  				}
   277  				Sdn.TeEsol = 0.0
   278  				Sdn.TeErn = 0.0
   279  				break
   280  			}
   281  		} // 表面ループ
   282  
   283  		// 室内部位への入射日射の計算(吸収日射ではない)
   284  		for _, Sdn := range RmSd {
   285  			// 室内部位への入射日射量の計算
   286  			Sdn.RSsold = rm.Qgt * Sdn.srg
   287  		}
   288  	} // 室ループ終了
   289  
   290  	// 透過日射の室内部位の最終計算(隣接室への日射分配、透過日射のうちガラスから屋外に放熱される分も考慮)
   291  	for _, rm := range Room {
   292  		// 透過間仕切りなど、隣接空間への透過日射分配の計算
   293  		for _, Sdn := range Sd[rm.Brs : rm.Brs+rm.N] {
   294  
   295  			// 隣室への日射の分配率が指定されており、分配する入射がある
   296  			if Sdn.tnxt > 0. && Sdn.RSsold > 0. {
   297  				// 分配する入射量 RSsol
   298  				Rmnxt := Room[Sdn.nxrm]
   299  				RSsol := Sdn.RSsold * Sdn.tnxt
   300  
   301  				// 入射日射×透過率が当該室の透過日射熱取得より減ずる
   302  				rm.Qgt -= RSsol
   303  				if Sdn.nextroom != nil {
   304  					// 外皮でない場合は隣室の透過日射熱取得に透過分を加算
   305  					Rmnxt.Qgt += RSsol
   306  				}
   307  			}
   308  
   309  			// 透過日射が入射したときに屋外に放熱されるときには、表面吸収日射はゼロとする
   310  			if Sdn.RStrans {
   311  				rm.Qgt -= Sdn.RSsold
   312  				Sdn.RSsol = 0.0
   313  			}
   314  		}
   315  	}
   316  
   317  	for i, rm := range Room {
   318  		Q := Qrm[i]
   319  		RmSd := Sd[rm.Brs : rm.Brs+rm.N]
   320  
   321  		// 室内部位の短波長吸収量の計算
   322  		for n, Sdn := range RmSd {
   323  			Sdn.RSsol = rm.Qgt * Sdn.srg2 / Sdn.A
   324  
   325  			Sdn.RS = (Sdn.RSsol*Sdn.A + rm.Hr*Sdn.srh + rm.Lr*Sdn.srl + rm.Ar*Sdn.sra + rm.Qeqp*Sdn.eqrd) / Sdn.A
   326  			Sdn.RSin = (rm.Hr*Sdn.srh + rm.Lr*Sdn.srl + rm.Ar*Sdn.sra + rm.Qeqp*Sdn.eqrd) / Sdn.A
   327  			Sdn.RSli = rm.Lr * Sdn.srl / Sdn.A
   328  
   329  			if DEBUG {
   330  				fmt.Printf("----- Rmexct  i=%d n=%d rm.Qgt=%f Fsdw=%f Fsdworg=%f Qgt=%f Qga=%f srg2=%f RSsol=%f RS=%f RSin=%f RSli=%f\n",
   331  					i, n, rm.Qgt, Sdn.Fsdw, Sdn.Fsdworg, Sdn.Qgt, Sdn.Qga, Sdn.srg2, Sdn.RSsol, Sdn.RS, Sdn.RSin, Sdn.RSli)
   332  			}
   333  		}
   334  
   335  		// 室の透過日射熱取得を再度積算(透明間仕切りによる隣接空間からの透過日射を考慮するため)
   336  		if rm.rsrnx {
   337  			for _, Sdn := range RmSd {
   338  				if Sdn.ble == BLE_Ceil || Sdn.ble == BLE_InnerFloor {
   339  					if Sdn.nxn >= 0 {
   340  						Sdn.Te += Sd[Sdn.nxn].RS / Sdn.alo
   341  					}
   342  				}
   343  			}
   344  		}
   345  
   346  		Q.Tsol = rm.Qgt
   347  		Q.Asol = rm.Qsab
   348  		Q.Arn = rm.Qrnab
   349  
   350  		// 家具の日射吸収量の計算
   351  		rm.Qsolm = 0.
   352  		if rm.fsolm != nil {
   353  			rm.Qsolm = rm.Qgt * rm.Srgm2
   354  		}
   355  
   356  	} // 室ループ
   357  
   358  	for n, Sdn := range Sd {
   359  		// 共用壁の場合の外表面の相当外気温 Te [C] の計算
   360  		if Sdn.mwtype == RMSRFMwType_C {
   361  			Sdnx := Sdn.nxsd
   362  			Sdn.Te = (Sdnx.alir*Sdnx.Tmrt + Sdnx.RS) / Sdnx.ali
   363  
   364  			if DEBUG {
   365  				fmt.Printf("----- Rmexct  n=%d Te=%f nxalir=%f nxTmrt=%f nxSdnx->RS=%f nxali=%f\n",
   366  					n, Sdn.Te, Sdnx.alir, Sdnx.Tmrt, Sdnx.RS, Sdnx.ali)
   367  			}
   368  		}
   369  	}
   370  }
   371  
   372  /* ----------------------------------------------------------------- */
   373  
   374  // 室の係数、定数項の計算
   375  func Roomcf(mw []*MWALL, rooms []*ROOM, rdpnl []*RDPNL, wd *WDAT, exsf *EXSFS) {
   376  	for _, rdpnl := range rdpnl {
   377  		panelwp(rdpnl)
   378  	}
   379  
   380  	// 壁体係数行列の作成(壁体数RMSRF分だけループ)
   381  	RMwlc(mw, exsf, wd)
   382  
   383  	for i := range rooms {
   384  		room := rooms[i]
   385  
   386  		RMcf(room)
   387  		RMrc(room) // 室の定数項の計算
   388  
   389  		room.RMx = room.GRM / DTM
   390  		room.RMXC = room.RMx*room.xrold + (room.HL+room.AL)/Ro
   391  
   392  		room.RMt += Ca * room.Gvent
   393  		room.RMC += Ca * room.Gvent * wd.T
   394  		room.RMx += room.Gvent
   395  		room.RMXC += room.Gvent * wd.X
   396  	}
   397  
   398  	for _, rdpnl := range rdpnl {
   399  		Panelcf(rdpnl)
   400  		rdpnl.EPC = Panelce(rdpnl)
   401  	}
   402  }
   403  
   404  /* ----------------------------------------------------------------- */
   405  // 前時刻の室温の入れ替え、OT、MRTの計算
   406  func Rmsurft(rooms []*ROOM, sd []*RMSRF) {
   407  	if rooms == nil {
   408  		return
   409  	}
   410  
   411  	// 重み係数が未定義もしくは不適切な数値の場合の対処
   412  	r := 0.5
   413  	if rooms[0].OTsetCwgt != nil && *(rooms[0].OTsetCwgt) >= 0.0 && *(rooms[0].OTsetCwgt) <= 1.0 {
   414  		r = *(rooms[0].OTsetCwgt)
   415  	}
   416  
   417  	if DEBUG {
   418  		fmt.Printf("<Rmsurft> Start\n")
   419  	}
   420  
   421  	for i := range rooms {
   422  		room := rooms[i]
   423  		n := room.N
   424  		brs := room.Brs
   425  		sdr := sd[brs:]
   426  
   427  		if DEBUG {
   428  			fmt.Printf("Room[%d]=%s\tN=%d\tbrs=%d\n", i, room.Name, room.N, room.Brs)
   429  		}
   430  
   431  		// 前時刻の温度の入れ替え
   432  		room.mrk = 'C'
   433  		room.Trold = room.Tr
   434  		room.xrold = room.xr
   435  
   436  		if room.FunHcap > 0 {
   437  			// 家具の温度の計算
   438  			room.TM = room.FMT*room.Tr + room.FMC
   439  			// 家具の吸放熱量の計算
   440  			if room.CM != nil {
   441  				room.QM = *room.CM * (room.TM - room.Tr)
   442  			}
   443  
   444  			room.oldTM = room.TM
   445  		}
   446  
   447  		if DEBUG {
   448  			fmt.Printf("<Rmsurft>  RMsrt start\n")
   449  		}
   450  
   451  		// 室内表面温度の計算
   452  		RMsrt(room)
   453  
   454  		if DEBUG {
   455  			fmt.Printf("<Rmsurft>  RMsrt end\n")
   456  		}
   457  
   458  		room.Tsav = RTsav(n, sdr)                // 平均表面温度 Ts,av
   459  		room.Tot = r*room.Tr + (1.0-r)*room.Tsav // 作用温度 Tot
   460  	}
   461  }
   462  
   463  /* ----------------------------------------------------------------- */
   464  // PCM収束計算過程における部位表面温度の計算
   465  func Rmsurftd(_Room []*ROOM, Sd []*RMSRF) {
   466  	var r float64
   467  
   468  	if _Room == nil {
   469  		return
   470  	}
   471  
   472  	Room := _Room[0]
   473  
   474  	if Room.OTsetCwgt == nil || *(Room.OTsetCwgt) < 0.0 || *(Room.OTsetCwgt) > 1.0 {
   475  		r = 0.5
   476  	} else {
   477  		r = *(Room.OTsetCwgt)
   478  	}
   479  
   480  	if DEBUG {
   481  		fmt.Printf("<Rmsurft> Start\n")
   482  	}
   483  
   484  	for i := range _Room {
   485  		Room := _Room[i]
   486  
   487  		if DEBUG {
   488  			fmt.Printf("Room[%d]=%s\tN=%d\tbrs=%d\n", i, Room.Name, Room.N, Room.Brs)
   489  		}
   490  
   491  		N := Room.N
   492  		brs := Room.Brs
   493  		sd := Sd[brs:]
   494  
   495  		if DEBUG {
   496  			fmt.Printf("<Rmsurft>  RMsrt start\n")
   497  		}
   498  
   499  		// 室内表面温度の計算
   500  		RMsrt(Room)
   501  
   502  		if DEBUG {
   503  			fmt.Printf("<Rmsurft>  RMsrt end\n")
   504  		}
   505  
   506  		Room.Tsav = RTsav(N, sd)
   507  		Room.Tot = r*Room.Tr + (1.0-r)*Room.Tsav
   508  	}
   509  }
   510  
   511  /*--------------------------------------------------------------------------------------------*/
   512  
   513  // 室の熱取得要素の計算
   514  func Qrmsim(Room []*ROOM, Wd *WDAT, Qrm []*QRM) {
   515  	for i := range Room {
   516  		Q := Qrm[i]
   517  		rm := Room[i]
   518  
   519  		// 人体・照明・機器の顕熱 [W]
   520  		Q.Hums = rm.Hc + rm.Hr
   521  		Q.Light = rm.Lc + rm.Lr
   522  		Q.Apls = rm.Ac + rm.Ar
   523  		Q.Hgins = Q.Hums + Q.Light + Q.Apls
   524  
   525  		// 人体・機器の潜熱 [W]
   526  		Q.Huml = rm.HL
   527  		Q.Apll = rm.AL
   528  
   529  		// 熱負荷 [W]
   530  		Q.Qinfs = Ca * rm.Gvent * (Wd.T - rm.Tr)
   531  		Q.Qinfl = Ro * rm.Gvent * (Wd.X - rm.xr)
   532  		Q.Qeqp = rm.Qeqp
   533  		Q.Qsto = rm.MRM * (rm.Trold - rm.Tr) / DTM
   534  		Q.Qstol = rm.GRM * Ro * (rm.xrold - rm.xr) / DTM
   535  
   536  		// 電力の消費量 [W]
   537  		if rm.AEsch != nil {
   538  			Q.AE = rm.AE * *rm.AEsch
   539  		} else {
   540  			Q.AE = 0.0
   541  		}
   542  
   543  		// ガスの消費量 [W]
   544  		if rm.AGsch != nil {
   545  			Q.AG = rm.AG * *rm.AGsch
   546  		} else {
   547  			Q.AG = 0.0
   548  		}
   549  	}
   550  }