github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/blpcm.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  /*   binit.c   */
    17  package eeslism
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"os"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  /*  壁体デ-タの入力  */
    28  
    29  func PCMdata(fi *EeTokens, dsn string, pcm *[]*PCM, pcmiterate *rune) {
    30  	N := PCMcount(fi)
    31  
    32  	s := "PCMdata --"
    33  
    34  	if N > 0 {
    35  		*pcm = make([]*PCM, N)
    36  
    37  		for j := 0; j < N; j++ {
    38  			var PCMa = new(PCM)
    39  
    40  			PCMa.Name = ""
    41  			PCMa.Condl = -999.0
    42  			PCMa.Conds = -999.0
    43  			PCMa.Crol = -999.0
    44  			PCMa.Cros = -999.0
    45  			PCMa.Ql = -999.0
    46  			PCMa.Tl = -999.0
    47  			PCMa.Ts = -999.0
    48  			PCMa.Tp = -999.0
    49  
    50  			PCMa.Iterate = false // 収束なしがデフォルト
    51  			//PCMa.iterateTemp = false	// デフォルトは見かけの比熱だけで収束
    52  			PCMa.IterateTemp = true
    53  			PCMa.NWeight = 0.5 // 収束計算時の現在ステップ温度の重み係数
    54  			PCMa.AveTemp = 'y'
    55  			PCMa.DivTemp = 1
    56  			PCMa.Ctype = 2 // 二等辺三角形がデフォルト
    57  			// パラメータの初期化
    58  			PCMa.PCMp.a = -999.0
    59  			PCMa.PCMp.B = -999.0
    60  			PCMa.PCMp.b = -999.0
    61  			PCMa.PCMp.bl = -999.0
    62  			PCMa.PCMp.bs = -999.0
    63  			PCMa.PCMp.c = -999.0
    64  			PCMa.PCMp.d = -999.0
    65  			PCMa.PCMp.e = -999.0
    66  			PCMa.PCMp.f = -999.0
    67  			PCMa.PCMp.omega = -999.0
    68  			PCMa.PCMp.skew = -999.0
    69  			PCMa.PCMp.T = -999.0
    70  			PCMa.IterateJudge = 0.05 //	収束判定条件は前ステップ見かけの比熱の5%
    71  			PCMa.Spctype = 'm'       // モデル形式をデフォルトとする
    72  			PCMa.Condtype = 'm'
    73  
    74  			ct := &PCMa.Chartable
    75  			ct[0].PCMchar = 'E' // 引数0はエンタルピー
    76  			ct[1].PCMchar = 'C' // 引数1は熱伝導率
    77  			for i := 0; i < 2; i++ {
    78  				ct[i].itablerow = 0
    79  				ct[i].T = nil
    80  				ct[i].Chara = nil
    81  				ct[i].filename = ""
    82  				ct[i].tabletype = 'e'
    83  				ct[i].fp = nil
    84  				ct[i].lowA = 0.0
    85  				ct[i].lowB = 0.0
    86  				ct[i].upA = 0.0
    87  				ct[i].upB = 0.0
    88  				ct[i].minTempChng = 0.5 // 最低温度変動幅
    89  			}
    90  
    91  			(*pcm)[j] = PCMa
    92  		}
    93  	}
    94  
    95  	for i := 0; i < N; i++ {
    96  
    97  		PCMa := (*pcm)[i]
    98  
    99  		s = fi.GetToken()
   100  
   101  		if s[0] == '*' {
   102  			break
   103  		}
   104  
   105  		PCMa.Name = s // PCM名称
   106  
   107  		for {
   108  			s = fi.GetToken()
   109  
   110  			ce := strings.IndexByte(s, ';')
   111  			if ce >= 0 {
   112  				s = s[:ce]
   113  			}
   114  			if st := strings.IndexByte(s, '='); st >= 0 {
   115  				dt, _ := strconv.ParseFloat(s[st+1:], 64)
   116  				if strings.HasPrefix(s, "Ql") { // 潜熱量[J/m3]
   117  					PCMa.Ql = dt
   118  				} else if strings.HasPrefix(s, "spcheattable") {
   119  					PCMa.Chartable[0].filename = s[st+1:]
   120  					PCMa.Spctype = 't'
   121  				} else if strings.HasPrefix(s, "table") {
   122  					if s[st+1] == 'e' {
   123  						PCMa.Chartable[0].tabletype = 'e'
   124  					} else if s[st+1] == 'h' {
   125  						PCMa.Chartable[0].tabletype = 'h'
   126  					}
   127  				} else if strings.HasPrefix(s, "conducttable") {
   128  					PCMa.Chartable[1].filename = s[st+1:]
   129  					PCMa.Condtype = 't'
   130  				} else if strings.HasPrefix(s, "minTempChange") {
   131  					PCMa.Chartable[0].minTempChng = dt
   132  					PCMa.Chartable[1].minTemp = dt
   133  				} else if strings.HasPrefix(s, "Condl") { // 液相熱伝導率[W/mK]
   134  					PCMa.Condl = dt
   135  				} else if strings.HasPrefix(s, "Conds") { // 固相熱伝導率[W/mK]
   136  					PCMa.Conds = dt
   137  				} else if strings.HasPrefix(s, "Crol") { // 液相容積比熱[J/m3K]
   138  					PCMa.Crol = dt
   139  				} else if strings.HasPrefix(s, "Cros") { // 固相容積比熱[J/m3K]
   140  					PCMa.Cros = dt
   141  				} else if strings.HasPrefix(s, "Tl") { // 液体から凝固が始まる温度[℃]
   142  					PCMa.Tl = dt
   143  				} else if strings.HasPrefix(s, "Ts") { // 固体から融解が始まる温度[℃]
   144  					PCMa.Ts = dt
   145  				} else if strings.HasPrefix(s, "Tp") { // 見かけの比熱のピーク温度[℃]
   146  					PCMa.Tp = dt
   147  				} else if strings.HasPrefix(s, "DivTemp") { // 比熱数値積分時の温度分割数
   148  					PCMa.DivTemp = int(dt)
   149  				} else if strings.HasPrefix(s, "Ctype") { // 見かけの比熱の特性曲線番号
   150  					PCMa.Ctype = int(dt)
   151  				} else if strings.HasPrefix(s, "a") { // これ以降は見かけの比熱計算のためのパラメータ
   152  					PCMa.PCMp.a = dt
   153  				} else if strings.HasPrefix(s, "b=") {
   154  					PCMa.PCMp.b = dt
   155  				} else if strings.HasPrefix(s, "c") {
   156  					PCMa.PCMp.c = dt
   157  				} else if strings.HasPrefix(s, "d") {
   158  					PCMa.PCMp.d = dt
   159  				} else if strings.HasPrefix(s, "e") {
   160  					PCMa.PCMp.e = dt
   161  				} else if strings.HasPrefix(s, "f") {
   162  					PCMa.PCMp.f = dt
   163  				} else if strings.HasPrefix(s, "B") {
   164  					PCMa.PCMp.B = dt
   165  				} else if strings.HasPrefix(s, "T") {
   166  					PCMa.PCMp.T = dt
   167  				} else if strings.HasPrefix(s, "bs") {
   168  					PCMa.PCMp.bs = dt
   169  				} else if strings.HasPrefix(s, "bl") {
   170  					PCMa.PCMp.bl = dt
   171  				} else if strings.HasPrefix(s, "skew") {
   172  					PCMa.PCMp.skew = dt
   173  				} else if strings.HasPrefix(s, "omega") {
   174  					PCMa.PCMp.omega = dt
   175  				} else if strings.HasPrefix(s, "nWieght") {
   176  					PCMa.NWeight = dt
   177  				} else if strings.HasPrefix(s, "IterateJudge") {
   178  					PCMa.IterateJudge = dt
   179  				} else {
   180  					Eprint("<PCMdata>", s)
   181  				}
   182  			} else {
   183  				if s == "-iterate" {
   184  					PCMa.Iterate = true
   185  					*pcmiterate = 'y'
   186  				} else if s == "-pcmnode" {
   187  					PCMa.AveTemp = 'n'
   188  				} else {
   189  					Eprint("<PCMdata>", s)
   190  				}
   191  			}
   192  
   193  			if ce != -1 {
   194  				break
   195  			}
   196  		}
   197  
   198  		// テーブルの読み込み(見かけの比熱)
   199  		if PCMa.Spctype == 't' {
   200  			TableRead(&PCMa.Chartable[0])
   201  		}
   202  
   203  		// テーブルの読み込み(熱伝導率)
   204  		if PCMa.Condtype == 't' {
   205  			TableRead(&PCMa.Chartable[1])
   206  		}
   207  
   208  		// 入力情報のチェック
   209  		if PCMa.Spctype == 'm' {
   210  			var Tin, Bin, bsin, blin, skewin, omegain, ain, bin, cin, din, ein, fin int
   211  			var Qlin, Condlin, Condsin, Crolin, Crosin, Tlin, Tsin, Tpin int
   212  
   213  			Tin = dparaminit(PCMa.PCMp.T)
   214  			Bin = dparaminit(PCMa.PCMp.B)
   215  			bsin = dparaminit(PCMa.PCMp.bs)
   216  			blin = dparaminit(PCMa.PCMp.bl)
   217  			skewin = dparaminit(PCMa.PCMp.skew)
   218  			omegain = dparaminit(PCMa.PCMp.omega)
   219  			ain = dparaminit(PCMa.PCMp.a)
   220  			bin = dparaminit(PCMa.PCMp.b)
   221  			cin = dparaminit(PCMa.PCMp.c)
   222  			din = dparaminit(PCMa.PCMp.d)
   223  			ein = dparaminit(PCMa.PCMp.e)
   224  			fin = dparaminit(PCMa.PCMp.f)
   225  			Qlin = dparaminit(PCMa.Ql)
   226  			Condlin = dparaminit(PCMa.Condl)
   227  			Condsin = dparaminit(PCMa.Conds)
   228  			Crolin = dparaminit(PCMa.Crol)
   229  			Crosin = dparaminit(PCMa.Cros)
   230  			Tlin = dparaminit(PCMa.Tl)
   231  			Tsin = dparaminit(PCMa.Ts)
   232  			Tpin = dparaminit(PCMa.Tp)
   233  
   234  			// 必須入力項目のチェック
   235  			if Condlin+Condsin+Crolin+Crosin+Tlin+Tsin != 0 {
   236  				fmt.Printf("<PCMdata> name=%s Condl=%f Conds=%f Crol=%f Cros=%f Tl=%f Ts=%f\n",
   237  					PCMa.Name, PCMa.Condl, PCMa.Conds, PCMa.Crol, PCMa.Cros, PCMa.Tl, PCMa.Ts)
   238  			}
   239  
   240  			// モデルごとに入力値をチェックする
   241  			if PCMa.Ctype == 1 || PCMa.Ctype == 2 {
   242  				if Qlin+Tsin+Tlin != 0 {
   243  					fmt.Printf("<PCMdata> name=%s Ql=%f Ts=%f Tl=%f\n",
   244  						PCMa.Name, PCMa.Ql, PCMa.Ts, PCMa.Tl)
   245  				}
   246  			} else if PCMa.Ctype == 3 {
   247  				if Qlin+Tpin+Tin+Bin != 0 {
   248  					fmt.Printf("<PCMdata> name=%s Ql=%f Tp=%f T=%f B=%f\n",
   249  						PCMa.Name, PCMa.Ql, PCMa.Tp, PCMa.PCMp.T, PCMa.PCMp.B)
   250  				}
   251  			} else if PCMa.Ctype == 4 {
   252  				if Tpin+ain+bin != 0 {
   253  					fmt.Printf("<PCMdata> name=%s Tp=%f a=%f b=%f\n",
   254  						PCMa.Name, PCMa.Tp, PCMa.PCMp.a, PCMa.PCMp.b)
   255  				}
   256  			} else if PCMa.Ctype == 5 {
   257  				if Tpin+bsin+blin+ain != 0 {
   258  					fmt.Printf("<PCMdata> name=%s Tp=%f bs=%f bl=%f a=%f\n",
   259  						PCMa.Name, PCMa.Tp, PCMa.PCMp.bs, PCMa.PCMp.bl, PCMa.PCMp.a)
   260  				}
   261  			} else if PCMa.Ctype == 6 {
   262  				if Qlin+Tpin+skewin+omegain != 0 {
   263  					fmt.Printf("<PCMdata> name=%s Ql=%f Tp=%f skew=%f omega=%f\n",
   264  						PCMa.Name, PCMa.Ql, PCMa.Tp, PCMa.PCMp.skew, PCMa.PCMp.omega)
   265  				}
   266  			} else if PCMa.Ctype == 7 {
   267  				if ain+bin+cin+din+ein+fin != 0 {
   268  					fmt.Printf("<PCMdata> name=%s a=%f b=%f c=%f d=%f e=%f f=%f\n",
   269  						PCMa.Name, PCMa.PCMp.a, PCMa.PCMp.b, PCMa.PCMp.c, PCMa.PCMp.d, PCMa.PCMp.e, PCMa.PCMp.f)
   270  				}
   271  			}
   272  		}
   273  	}
   274  }
   275  
   276  // PCMの物性値テーブルの読み込み
   277  func TableRead(ct *CHARTABLE) {
   278  	if ct.filename == "" {
   279  		return
   280  	}
   281  
   282  	fp, err := os.Open(ct.filename)
   283  	if err != nil {
   284  		fmt.Printf("<PCMdata> xxxx file not found %s xxxx\n", ct.filename)
   285  		return
   286  	}
   287  	ct.fp = fp
   288  
   289  	// 設定されている行数を数える
   290  	var c byte
   291  	var row int
   292  	row = 0
   293  
   294  	// Count the number of rows
   295  	for {
   296  		_, err := fmt.Fscanf(ct.fp, "%c", &c)
   297  		if err != nil {
   298  			break
   299  		}
   300  		if c == '\n' {
   301  			row++
   302  		}
   303  	}
   304  
   305  	// Close the file temporarily
   306  	err = ct.fp.Close()
   307  	if err != nil {
   308  		fmt.Println("<PCMdata> ファイルのクローズに失敗")
   309  		return
   310  	}
   311  
   312  	// Allocate memory
   313  	ct.T = make([]float64, row)
   314  	ct.Chara = make([]float64, row)
   315  	if ct.T == nil || ct.Chara == nil {
   316  		fmt.Println("<PCMdata> メモリの確保に失敗")
   317  	}
   318  
   319  	// Reopen the file
   320  	fp, err = os.Open(ct.filename)
   321  	if err != nil {
   322  		fmt.Println("<PCMdata> ファイルのオープンに失敗")
   323  		return
   324  	}
   325  	ct.fp = fp
   326  
   327  	var st, tt int
   328  	var spheat, prevheat, prevTemp float64
   329  	prevheat = 0.0
   330  	prevTemp = -999.0
   331  	spheat = 0.0
   332  
   333  	for i := 0; i < row; i++ {
   334  		T := &ct.T[i]
   335  		Char := &ct.Chara[i]
   336  
   337  		// 温度の読み込み
   338  		_, err := fmt.Fscanf(ct.fp, " %f ", T)
   339  		if err != nil {
   340  			fmt.Println("<PCMdata> 温度の読み込みに失敗")
   341  			break
   342  		}
   343  		// テーブルの下限温度
   344  		if st == 0 {
   345  			ct.minTemp = *T
   346  			prevTemp = *T
   347  			st = 1
   348  		}
   349  		// 昇順に並んでいないときのエラー表示
   350  		if *T <= prevTemp && tt == 1 {
   351  			fmt.Printf("i=%d 温度データが昇順に並んでいません T=%f preT=%f\n", i, *T, prevTemp)
   352  		}
   353  		var dblTemp float64
   354  		// 特性値の読み込み
   355  		_, err = fmt.Fscanf(ct.fp, " %f ", &dblTemp)
   356  		if err != nil {
   357  			fmt.Println("<PCMdata> 特性値の読み込みに失敗")
   358  			break
   359  		}
   360  		*Char = dblTemp
   361  		// 見かけの比熱の場合
   362  		if ct.tabletype == 'h' {
   363  			*Char = prevheat + spheat*(*T-prevTemp)
   364  		}
   365  		prevheat = *Char
   366  		prevTemp = *T
   367  		spheat = dblTemp
   368  		// テーブルの上限温度
   369  		ct.maxTemp = *T
   370  		ct.itablerow++
   371  		tt = 1
   372  	}
   373  
   374  	// Close the file
   375  	err = ct.fp.Close()
   376  	if err != nil {
   377  		fmt.Println("<PCMdata> ファイルのクローズに失敗")
   378  	}
   379  
   380  	// 上下限温度範囲以外の線形回帰式を作成
   381  	// 下限以下
   382  	ct.lowA = (ct.Chara[0] - ct.Chara[1]) / (ct.T[0] - ct.T[1])
   383  	ct.lowB = ct.Chara[0] - ct.lowA*ct.T[0]
   384  	// 上限以上
   385  	ct.upA = (ct.Chara[ct.itablerow-1] - ct.Chara[ct.itablerow-2]) / (ct.T[ct.itablerow-1] - ct.T[ct.itablerow-2])
   386  	ct.upB = ct.Chara[ct.itablerow-1] - ct.upA*ct.T[ct.itablerow-1]
   387  }
   388  
   389  // 初期化されているかをチェックする
   390  func dparaminit(A float64) int {
   391  	if math.Abs(A-(-999.0)) < 1e-5 {
   392  		return 1
   393  	} else {
   394  		return 0
   395  	}
   396  }
   397  
   398  func PCMcount(fi *EeTokens) int {
   399  	N := 0
   400  	add := fi.GetPos()
   401  
   402  	for fi.IsEnd() == false {
   403  		s := fi.GetToken()
   404  		if strings.HasPrefix(s, "*") {
   405  			break
   406  		}
   407  		if strings.HasPrefix(s, ";") {
   408  			N++
   409  		}
   410  	}
   411  
   412  	fi.RestorePos(add)
   413  	return N
   414  }
   415  
   416  // 固相、液相物性値と潜熱量からPCM温度の物性値を計算する(比熱、熱伝導率共通)
   417  // 熱伝導率の計算時はQl=0とする
   418  func FNPCMState(Ctype int, Ss, Sl, Ql, Ts, Tl, Tp, T float64, PCMp *PCMPARAM) float64 {
   419  	var Qse, Qla, Tls float64
   420  
   421  	Tls = Tl - Ts
   422  	// 顕熱分の補間
   423  	if T > Ts && T < Tl {
   424  		Qse = Ss + (Sl-Ss)/Tls*(T-Ts)
   425  	} else if T <= Ts {
   426  		Qse = Ss
   427  	} else {
   428  		Qse = Sl
   429  	}
   430  
   431  	// 潜熱分の補間
   432  	Qla = 0.0
   433  
   434  	Ql = 0.0
   435  
   436  	// 熱伝導率計算の場合は潜熱ゼロ
   437  	if Ctype == 0 {
   438  		Qla = 0.0
   439  	} else if Ctype == 1 { // 潜熱変化域潜熱比熱一定
   440  		if T > Ts && T < Tl {
   441  			Qla = Ql / (Tl - Ts)
   442  		}
   443  	} else if Ctype == 2 { // 二等辺三角形
   444  		if T > Ts && T < Tl {
   445  			if T < (Tl+Ts)/2.0 {
   446  				Qla = 4.0 * Ql / (Tls * Tls) * (T - Ts)
   447  			} else {
   448  				Qla = 4.0 * Ql / (Tls * Tls) * (Tl - T)
   449  			}
   450  		}
   451  	} else if Ctype == 3 { // 双曲線関数
   452  		Temp := math.Cosh((2.0 * PCMp.B / PCMp.T) * (T - Tp))
   453  		Qla = 0.5 * Ql * (2.0 * PCMp.B / PCMp.T) / (Temp * Temp)
   454  	} else if Ctype == 4 { // ガウス関数(対象)
   455  		Temp := (T - Tp) / PCMp.B
   456  		Qla = PCMp.a * math.Exp(-0.5*Temp*Temp)
   457  	} else if Ctype == 5 { // ガウス関数(非対称)
   458  		Temp := (T - Tp) / PCMp.B
   459  		if T <= Tp {
   460  			Temp = PCMp.bs
   461  		} else {
   462  			Temp = PCMp.bl
   463  		}
   464  		Qla = PCMp.a * math.Exp(-((T-Tp)/Temp)*((T-Tp)/Temp))
   465  	} else if Ctype == 6 { // 誤差関数歪度
   466  		//Temp := math.Exp(-(T - Tp) * (T - Tp) / ((2.0 * PCMp.omega) * PCMp.omega))
   467  		Qla = Ql / math.Sqrt(2.0*math.Pi) * math.Exp(-(T-Tp)*(T-Tp)/((2.0*PCMp.omega)*PCMp.omega)) * (1.0 + math.Erf(PCMp.skew*(T-Tp)/(math.Sqrt(2.0)*PCMp.omega)))
   468  	} else if Ctype == 7 { // 有理関数
   469  		if T < 0 {
   470  			Qla = 0.0
   471  		} else {
   472  			Qla = math.Pow(T, PCMp.f) * (PCMp.a*T*T + PCMp.B*T + PCMp.c) / (PCMp.d*T*T + PCMp.e*T + 1.0)
   473  		}
   474  	}
   475  
   476  	return (Qse + Qla)
   477  }
   478  
   479  /* ------------------------------------------------------ */
   480  
   481  // PCMの状態値計算(家具用)
   482  
   483  func FNPCMStatefun(Ctype int, Ss, Sl, Ql, Ts, Tl, Tp, oldT, T float64, DivTemp int, PCMp *PCMPARAM) float64 {
   484  	var dblTemp, dTemp, TPCM, Qld, Qllst float64
   485  	dTemp = (T - oldT) / float64(DivTemp)
   486  
   487  	Qllst = 0.0
   488  	// 前時刻からの温度変化が小さい場合は時間積分はしない
   489  	if math.Abs(T-oldT) < 1e-4 {
   490  		Qllst = FNPCMState(Ctype, Ss, Sl, Ql, Ts, Tl, Tp, (T+oldT)*0.5, PCMp)
   491  	} else {
   492  		// 見かけの比熱の時間積分
   493  		for i := 0; i < DivTemp+1; i++ {
   494  			TPCM = oldT + dTemp*float64(i)
   495  			Qld = FNPCMState(Ctype, Ss, Sl, Ql, Ts, Tl, Tp, TPCM, PCMp)
   496  			dblTemp += Qld
   497  		}
   498  
   499  		Qllst = dblTemp / float64(DivTemp+1)
   500  	}
   501  
   502  	return Qllst
   503  }
   504  
   505  // PCMの温度から見かけの比熱を求める(テーブル形式)
   506  // Told:前時刻のPCM温度、T:暫定現在時刻PCM温度
   507  func FNPCMstate_table(ct *CHARTABLE, Told, T float64, Ndiv int) float64 {
   508  	var oldEn, En, Chara float64
   509  
   510  	// 前時刻と暫定現在時刻のPCM温度が同温の場合
   511  	if math.Abs(T-Told) < ct.minTempChng {
   512  		Tave := 0.5 * (T + Told)
   513  		// 見かけの比熱の計算
   514  		if ct.PCMchar == 'E' {
   515  			oldEn = FNPCMenthalpy_table_lib(ct, Tave-0.5*ct.minTempChng)
   516  			En = FNPCMenthalpy_table_lib(ct, Tave+0.5*ct.minTempChng)
   517  			// 見かけの比熱の計算
   518  			Chara = (En - oldEn) / ct.minTempChng
   519  		} else {
   520  			// 熱伝導率の計算
   521  			Chara = FNPCMenthalpy_table_lib(ct, Tave)
   522  		}
   523  	} else {
   524  		if ct.PCMchar == 'E' {
   525  			oldEn = FNPCMenthalpy_table_lib(ct, Told)
   526  			En = FNPCMenthalpy_table_lib(ct, T)
   527  			// 見かけの比熱の計算
   528  			Chara = (En - oldEn) / (T - Told)
   529  		} else {
   530  			// 熱伝導率の計算
   531  			var dblTemp, Tpcm, dTemp float64
   532  			dblTemp = 0.0
   533  			dTemp = (T - Told) / float64(Ndiv)
   534  			// ToldからTまでを積分する
   535  			for i := 0; i < Ndiv; i++ {
   536  				Tpcm = Told + dTemp*float64(i)
   537  				dblTemp += FNPCMenthalpy_table_lib(ct, Tpcm)
   538  			}
   539  			Chara = dblTemp / float64(Ndiv+1)
   540  		}
   541  	}
   542  
   543  	return Chara
   544  }
   545  
   546  func FNPCMenthalpy_table_lib(ct *CHARTABLE, T float64) float64 {
   547  	var prevTpcm, Tpcm, enthalpy, preventhalpy *float64
   548  	var retVal float64
   549  
   550  	if T < ct.minTemp {
   551  		// テーブルの最低温度よりPCM温度が低い場合は端部の特性値を線形で外挿
   552  		retVal = ct.lowA*T + ct.lowB
   553  	} else if T > ct.maxTemp {
   554  		//テーブルの最高温度よりPCM温度が高い場合は端部の特性値を線形で外挿
   555  		retVal = ct.upA*T + ct.upB
   556  	} else {
   557  		for i := 0; i < ct.itablerow; i++ {
   558  
   559  			Tpcm := &ct.T[i]
   560  			enthalpy := &ct.Chara[i]
   561  
   562  			if *Tpcm > T {
   563  				break
   564  			}
   565  			prevTpcm = Tpcm
   566  			preventhalpy = enthalpy
   567  		}
   568  		// 線形補間
   569  		retVal = *preventhalpy + (*enthalpy-*preventhalpy)*(T-*prevTpcm)/(*Tpcm-*prevTpcm)
   570  	}
   571  
   572  	return retVal
   573  }