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  }