github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/blsolarwall.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  // 空気集熱建材のシミュレーション
    17  
    18  package eeslism
    19  
    20  import (
    21  	"fmt"
    22  	"math"
    23  )
    24  
    25  // 集熱器の放射取得熱量
    26  func FNScol(ta, I, EffPV, Ku, ao, Eo, Fs, RN float64) float64 {
    27  	return (ta-EffPV)*I - Ku/ao*Eo*Fs*RN
    28  }
    29  
    30  // 建材一体型空気集熱器の相当外気温度を計算する
    31  func CalcSolarWallTe(Rmvls *RMVLS, Wd *WDAT, Exsfs *EXSFS) {
    32  	for i := range Rmvls.Rdpnl {
    33  		rdpnl := Rmvls.Rdpnl[i]
    34  		Sd := rdpnl.sd[0]
    35  		if Sd.mw != nil && Sd.mw.wall.WallType == WallType_C {
    36  			Sd.Tcole = FNTcoleContrl(Sd, Wd, Exsfs)
    37  		}
    38  	}
    39  }
    40  
    41  // 集熱器相当外気温度の計算(制御用)
    42  // 集熱器裏面温度は前時刻の値を使用する
    43  func FNTcoleContrl(Sd *RMSRF, Wd *WDAT, Exsfs *EXSFS) float64 {
    44  	var Cidf float64
    45  	var Wall *WALL
    46  	var Exs *EXSF
    47  	var Glsc float64
    48  	var Ksu, alo, ku, kd float64
    49  
    50  	if Sd.mw.wall.ColType != "" {
    51  		Wall = Sd.mw.wall
    52  		Exs = Exsfs.Exs[Sd.exs]
    53  		Glsc = 1.0
    54  		Cidf = 1.0
    55  		if Sd.mw.wall.ColType != "" &&
    56  			Sd.mw.wall.ColType[:2] != "A2" &&
    57  			Sd.mw.wall.ColType[:2] != "W2" {
    58  			Glsc = Glscid(Exs.Cinc)
    59  			Cidf = 0.91
    60  		}
    61  
    62  		//熱貫流率等の計算
    63  		if Wall.chrRinput {
    64  			FNKc(Wd, Exsfs, Sd)
    65  			Ksu = Sd.dblKsu
    66  			alo = Sd.dblao
    67  			ku = Sd.ku
    68  			kd = Sd.kd
    69  		} else {
    70  			//熱貫流率が入力値の場合
    71  			Ksu = Wall.Ksu
    72  			alo = *Exs.Alo
    73  			ku = Wall.ku
    74  			kd = Wall.kd
    75  		}
    76  
    77  		//Sd.Scol = FNScol(Wall.tra, Glsc*Exs.Idre+Cidf*Exs.Idf, Sd.PVwall.Eff, Ksu, alo, Wall.Eo, Exs.Fs, Wd.RN)
    78  		//fmt.Printf("Ko=%g Scol=%g Ku=%g Ta=%g Kd=%g Tx=%g\n", Wall.Ko, Sd.Scol, Wall.Ku, Wd.T, Wall.Kd, Sd.oldTx)
    79  
    80  		// Satoh DEBUG 2018/2/26  壁体一体型空気集熱器への影の影響を考慮するように修正
    81  		Sd.Tcoled = Sd.oldTx
    82  		Idre := Exs.Idre
    83  		Idf := Exs.Idf
    84  		RN := Exs.Rn
    85  
    86  		Sd.dblSG = (Wall.tra - Sd.PVwall.Eff) * (Glsc*Idre + Cidf*Idf)
    87  		if Sd.mw.wall.ColType[:2] == "A3" {
    88  			Sd.Tcoled += Sd.dblSG / Sd.dblKsd
    89  		}
    90  
    91  		Sd.Tcoleu = Sd.dblSG/Ksu - Wall.Eo*RN/alo + Wd.T
    92  
    93  		//return Wall.ku*(Sd.Scol/Wall.Ksu+Wd.T) + Wall.kd*Sd.oldTx
    94  
    95  		//fmt.Printf("name=%s ku=%.2f kd=%.2f Tcoleu=%.2f Tcoled=%.2f\n", Sd.name, ku, kd, Sd.Tcoleu, Sd.Tcoled)
    96  		return ku*Sd.Tcoleu + kd*Sd.Tcoled
    97  	} else {
    98  		return 0
    99  	}
   100  }
   101  
   102  // 建材一体型空気集熱パネルの境界条件計算
   103  func FNBoundarySolarWall(Sd *RMSRF, ECG, ECt, CFc *float64) {
   104  	Wall := Sd.mw.wall
   105  	Pnl := Sd.rpnl
   106  
   107  	// 戻り値の初期化
   108  	*ECG = 0.0
   109  
   110  	// 各種熱貫流率の設定
   111  	var Kc, Kcd, ku, kd float64
   112  	if Wall.chrRinput {
   113  		Kc = Sd.dblKc
   114  		//Kcu = Sd.dblKcu
   115  		Kcd = Sd.dblKcd
   116  		ku = Sd.ku
   117  		kd = Sd.kd
   118  	} else {
   119  		Kc = Wall.Kc
   120  		//Kcu = Wall.Kcu
   121  		Kcd = Wall.Kcd
   122  		ku = Wall.ku
   123  		kd = Wall.kd
   124  	}
   125  
   126  	// パネル動作時
   127  	if Pnl.cG > 0.0 {
   128  		*ECG = Pnl.cG * Pnl.Ec / (Kc * Sd.A)
   129  	}
   130  
   131  	*ECt = Kcd * ((1.0-*ECG)*ku - 1.0)
   132  	*CFc = Kcd * (1.0 - *ECG) * kd
   133  }
   134  
   135  // 熱媒平均温度の計算
   136  func FNTf(Tcin, Tcole, ECG float64) float64 {
   137  	return (1.0-ECG)*Tcole + ECG*Tcin
   138  }
   139  
   140  // 外表面の総合熱伝達率の計算
   141  func FNSolarWallao(Wd *WDAT, Sd *RMSRF, Exsfs *EXSFS) float64 {
   142  	var dblac, dblar, dblao float64
   143  	var Exs *EXSF
   144  	var dblWdre float64
   145  	var dblWa float64
   146  	var dblu float64
   147  
   148  	// 放射熱伝達率
   149  	// 屋根の表面温度は外気温度で代用
   150  	dblar = Sd.Eo * 4.0 * Sgm * math.Pow((Wd.T+Sd.Tg)/2.0+273.15, 3.0)
   151  
   152  	// 対流熱伝達率
   153  	Exs = Exsfs.Exs[Sd.exs]
   154  
   155  	// 外部風向の計算(南面0゜に換算)
   156  	dblWdre = Wd.Wdre*22.5 - 180.0
   157  	// 外表面と風向のなす角
   158  	dblWa = float64(Exs.Wa) - dblWdre
   159  
   160  	// 風上の場合
   161  	if math.Cos(dblWa*math.Pi/180.0) > 0.0 {
   162  		if Wd.Wv <= 2.0 {
   163  			dblu = 2.0
   164  		} else {
   165  			dblu = 0.25 * Wd.Wv
   166  		}
   167  	} else {
   168  		dblu = 0.3 + 0.05*Wd.Wv
   169  	}
   170  
   171  	// 対流熱伝達率
   172  	dblac = 3.5 + 5.6*dblu
   173  
   174  	// 総合熱伝達率
   175  	dblao = dblar + dblac
   176  
   177  	return dblao
   178  }
   179  
   180  // 通気層の放射熱伝達率の計算
   181  func VentAirLayerar(dblEsu, dblEsd, dblTsu, dblTsd float64) float64 {
   182  	var dblEs float64
   183  
   184  	// 放射率の計算
   185  	dblEs = 1.0 / (1.0/dblEsu + 1.0/dblEsd - 1.0)
   186  
   187  	return 4.0 * dblEs * Sgm * math.Pow((dblTsu+dblTsd)/2.0+273.15, 3.0)
   188  }
   189  
   190  // 通気層の強制対流熱伝達率(ユルゲスの式)
   191  func FNJurgesac(Sd *RMSRF, dblV, a, b float64) float64 {
   192  	var Dh, Nu, Re, lam float64
   193  
   194  	//if(fabs(dblV) <= 1.0e-3)
   195  	//	dblTemp = 3.0 ;
   196  	//else if(dblV <= 5.0)
   197  	//	dblTemp = 7.1 * pow(dblV, 0.78) ;
   198  	//else
   199  	//	dblTemp = 5.8 + 3.9 * dblV ;
   200  
   201  	// 長方形断面の相当直径の計算
   202  	Dh = 1.232 * (a * b) / (a + b)
   203  	// レイノルズ数の計算
   204  	Re = dblV * Dh / FNanew(Sd.dblTf)
   205  	// 空気の熱伝導率
   206  	lam = FNalam(Sd.dblTf)
   207  	// ヌセルト数の計算
   208  	Nu = 0.0158 * math.Pow(Re, 0.8)
   209  	return Nu / Dh * lam
   210  }
   211  
   212  // 屋根一体型空気集熱器の熱伝達率、熱貫流率の計算
   213  func FNKc(Wd *WDAT, Exsfs *EXSFS, Sd *RMSRF) {
   214  	var dblDet, dblWsuWsd, Ru, Cr, Cc float64
   215  	//g := 9.81 // Assuming the value of gravity
   216  	M_rad := math.Pi / 180.0
   217  
   218  	Wall := Sd.mw.wall
   219  	Exs := Exsfs.Exs[Sd.exs]
   220  	rad := M_rad
   221  
   222  	// 外表面の総合熱伝達率の計算
   223  	Sd.dblao = FNSolarWallao(Wd, Sd, Exsfs)
   224  
   225  	// 通気層の対流熱伝達率の計算
   226  	if Wall.air_layer_t < 0.0 {
   227  		fmt.Printf("%s  Ventilation layer thickness is undefined\n", Sd.Name)
   228  	}
   229  	if Sd.rpnl.cmp.Elouts[0].G > 0.0 {
   230  		Sd.dblacc = FNJurgesac(Sd, Sd.rpnl.cmp.Elouts[0].G/Roa/((Sd.dblWsd+Sd.dblWsu)/2.0*Wall.air_layer_t),
   231  			(Sd.dblWsd+Sd.dblWsu)/2.0, Wall.air_layer_t)
   232  	} else {
   233  		Sd.dblacc = FNVentAirLayerac(Sd.dblTsu, Sd.dblTsd, Wall.air_layer_t, Exs.Wb*rad)
   234  	}
   235  
   236  	if math.Abs(Sd.dblacc) > 100.0 || Sd.dblacc < 0.0 {
   237  		fmt.Printf("xxxxxx <FNKc> name=%s acc=%f\n", Sd.Name, Sd.dblacc)
   238  	}
   239  
   240  	// 通気層の放射熱伝達率の計算
   241  	Sd.dblacr = VentAirLayerar(Wall.dblEsu, Wall.dblEsd, Sd.dblTsu, Sd.dblTsd)
   242  
   243  	if math.Abs(Sd.dblacr) > 100.0 || Sd.dblacr < 0.0 {
   244  		fmt.Printf("xxxxxx <FNKc> name=%s acr=%f\n", Sd.Name, Sd.dblacr)
   245  	}
   246  
   247  	// 通気層上面、下面から境界までの熱貫流率の計算
   248  	if Wall.Ru >= 0.0 {
   249  		Ru = Wall.Ru
   250  	} else {
   251  		// 空気層のコンダクタンスの計算
   252  		// 放射成分
   253  		Cr = VentAirLayerar(Wall.Eg, Wall.Eb, Sd.Tg, Sd.dblTsu)
   254  		// 対流成分 component
   255  		Cc = FNVentAirLayerac(Sd.Tg, Sd.dblTsu, Wall.ta, Exs.Wb*rad)
   256  		Ru = 1.0 / (Cc + Cr)
   257  		Sd.ras = Ru
   258  	}
   259  
   260  	Sd.dblKsu = 1.0 / (Ru + 1.0/Sd.dblao)
   261  	Sd.dblKsd = 1.0 / Wall.Rd
   262  
   263  	dblWsuWsd = Sd.dblWsu / Sd.dblWsd
   264  
   265  	dblDet = (Sd.dblacr*dblWsuWsd+Sd.dblacc+Sd.dblKsd)*(Sd.dblacr+Sd.dblacc+Sd.dblKsu) - Sd.dblacr*Sd.dblacr*dblWsuWsd
   266  	Sd.dblb11 = (Sd.dblacr + Sd.dblacc + Sd.dblKsu) / dblDet
   267  	Sd.dblb12 = Sd.dblacr / dblDet
   268  	Sd.dblb21 = Sd.dblacr * dblWsuWsd / dblDet
   269  	Sd.dblb22 = (Sd.dblacr*dblWsuWsd + Sd.dblacc + Sd.dblKsd) / dblDet
   270  
   271  	Sd.dblfcu = Sd.dblacc/dblWsuWsd*Sd.dblb12 + Sd.dblacc*dblWsuWsd*Sd.dblb22
   272  	Sd.dblfcd = Sd.dblacc/dblWsuWsd*Sd.dblb11 + Sd.dblacc*dblWsuWsd*Sd.dblb21
   273  
   274  	Sd.dblKcu = Sd.dblKsu * Sd.dblfcu
   275  	Sd.dblKcd = Sd.dblKsd * Sd.dblfcd
   276  
   277  	// 集熱器の総合熱貫流率の計算
   278  	Sd.dblKc = Sd.dblKcu + Sd.dblKcd
   279  
   280  	Sd.ku = Sd.dblKcu / Sd.dblKc
   281  	Sd.kd = Sd.dblKcd / Sd.dblKc
   282  }
   283  
   284  // 空気集熱器の通気層上面、下面表面温度の計算
   285  func FNTsuTsd(Sd *RMSRF, Wd *WDAT, Exsfs *EXSFS) {
   286  	//var dblTf float64 // 集熱空気の平均温度
   287  	Rdpnl := Sd.rpnl
   288  	Wall := Sd.mw.wall
   289  	Exs := Exsfs.Exs[Sd.exs]
   290  	cG := Sd.rpnl.cG
   291  
   292  	if Wall.chrRinput {
   293  		Kc := Sd.dblKc
   294  		Ksu := Sd.dblKsu
   295  		Ksd := Sd.dblKsd
   296  		ECG := cG * Rdpnl.Ec / (Kc * Sd.A)
   297  		Sd.dblTf = (1.0-ECG)*Sd.Tcole + ECG*Rdpnl.Tpi
   298  		Sd.dblTsd = Sd.dblb11*Ksd*(Sd.Tcoled-Sd.dblTf) + Sd.dblb12*Ksu*(Sd.Tcoleu-Sd.dblTf) + Sd.dblTf
   299  		Sd.dblTsu = Sd.dblb21*Ksd*(Sd.Tcoled-Sd.dblTf) + Sd.dblb22*Ksu*(Sd.Tcoleu-Sd.dblTf) + Sd.dblTf
   300  
   301  		if Sd.dblTsd < -100 {
   302  			fmt.Println("Error")
   303  		}
   304  
   305  		// 空気層の熱抵抗が未定義の場合はガラスの温度を計算する
   306  		if Wall.Ru < 0.0 {
   307  			Sd.Tg = (Sd.dblao*Wd.T + 1.0/Sd.ras*Sd.dblTsu + Wall.ag*Exs.Iw - Wall.Eo*Exs.Fs*Wd.RN) / (Sd.dblao + 1.0/Sd.ras)
   308  		}
   309  	}
   310  }
   311  
   312  // 通気層の集熱停止時の熱コンダクタンス[W/m2K]
   313  func FNVentAirLayerac(Tsu, Tsd, air_layer_t, Wb float64) float64 {
   314  	var Tas, Ra, anew, a, RacosWb, lama float64
   315  	g := 9.81 // Assuming the value of gravity
   316  
   317  	var Tsud float64
   318  	if math.Abs(Tsu-Tsd) < 1.0e-4 {
   319  		Tsud = Tsu + 0.1
   320  	} else {
   321  		Tsud = Tsu
   322  	}
   323  
   324  	// 通気層の温度
   325  	Tas = (Tsud + Tsd) / 2.0
   326  	// 空気の動粘性係数
   327  	anew = FNanew(Tas)
   328  	// 空気の熱拡散率
   329  	a = FNaa(Tas)
   330  	// 空気の熱伝導率
   331  	lama = FNalam(Tas)
   332  	// レーリー数
   333  	Ra = g * (1.0 / Tas) * math.Abs(Tsud-Tsd) * math.Pow(air_layer_t, 3.0) / (anew * a)
   334  
   335  	RacosWb = Ra * math.Cos(Wb)
   336  
   337  	dblTemp := (1.0 + 1.44*math.Max(0.0, 1.0-1708.0/RacosWb)*(1.0-math.Pow(math.Sin(1.8*Wb), 1.6)*1708.0/RacosWb) + math.Max(math.Pow(RacosWb/5830.0, 1.0/3.0)-1.0, 0.0)) * air_layer_t / lama
   338  
   339  	return dblTemp
   340  }