github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/blinit.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  	"bufio"
    21  	"fmt"
    22  	"strconv"
    23  	"strings"
    24  )
    25  
    26  /*  壁体デ-タの入力  */
    27  
    28  // WALLデータセットの読み取り
    29  func Walldata(section *EeTokens, fbmlist string, Wall *[]*WALL, dfwl *DFWL, pcm []*PCM) {
    30  	var s string
    31  	var i = -1
    32  	var j, jj, jw, Nlyr, k = 0, 0, 0, 0, -1
    33  	var Nbm, ndiv int // ic
    34  	var dt float64
    35  	var W []BMLST
    36  	var Wl *BMLST
    37  
    38  	W = nil
    39  	// E = fmt.Sprintf(ERRFMT, dsn)
    40  
    41  	NwLines := wbmlistcount(fbmlist)
    42  
    43  	s = "Walldata wbmlist.efl--"
    44  
    45  	k = 0
    46  
    47  	for _, line := range NwLines {
    48  		s := strings.Fields(line)
    49  
    50  		Wl = new(BMLST)
    51  		Wl.Mcode = s[0]
    52  
    53  		for j := 0; j < k-1; j++ {
    54  			Wc := &W[j]
    55  			if Wl.Mcode == Wc.Mcode {
    56  				message := fmt.Sprintf("wbmlist.efl duplicate code=<%s>", Wl.Mcode)
    57  				Eprint("<Walldata>", message)
    58  			}
    59  		}
    60  
    61  		// Cond:熱伝導率[W/mK]、Cro:容積比熱[kJ/m3K]
    62  		var err error
    63  		Wl.Cond, err = strconv.ParseFloat(s[1], 64)
    64  		if err != nil {
    65  			Eprint("<Walldata>", "wbmlist.efl Cond error")
    66  		}
    67  
    68  		Wl.Cro, err = strconv.ParseFloat(s[2], 64)
    69  		if err != nil {
    70  			Eprint("<Walldata>", "wbmlist.efl Cro error")
    71  		}
    72  
    73  		W = append(W, *Wl)
    74  
    75  		for j := 0; j < k+1; j++ {
    76  			fmt.Printf("k=%d code=%s\n", k, W[j].Mcode)
    77  		}
    78  
    79  		fmt.Printf("Walldata>> name=%s Con=%f Cro=%f\n", W[k].Mcode, W[k].Cond, W[k].Cro)
    80  		W[k] = *Wl
    81  		k++
    82  	}
    83  
    84  	k++
    85  	Nbm = k
    86  
    87  	//N = Wallcount(fi)
    88  
    89  	s = "Walldata --"
    90  
    91  	i = 0
    92  	for section.IsEnd() == false {
    93  		line := section.GetLogicalLine()
    94  		if line[0] == "*" {
    95  			break
    96  		}
    97  
    98  		Wa := NewWall()
    99  
   100  		s = line[0]
   101  
   102  		// for jj = 0; jj < len(Wa.welm); jj++ {
   103  		// 	w = NewWelm()
   104  		// }
   105  
   106  		// for jj = 0; jj < len(Wa.PCM); jj++ {
   107  		// 	Wa.PCM[jj] = nil
   108  		// 	Wa.PCMrate[jj] = -999.0
   109  		// }
   110  
   111  		// (1) 部位・壁体名の読み取り
   112  		if strings.HasPrefix(s, "-") {
   113  			// For `-E` or `-R:ROOF` or ...
   114  
   115  			// 部位コードの指定
   116  			Wa.ble = BLEType(s[1])
   117  
   118  			if len(s) > 2 && s[2] == ':' {
   119  				// 壁体名の指定(最初の1文字を必ず英字とする)
   120  				Wa.name = s[3:]
   121  			} else {
   122  				// 部位のみ指定(既定値の定義)
   123  				switch s[1] {
   124  				case 'E': // 外壁
   125  					dfwl.E = i
   126  				case 'R': // 屋根
   127  					dfwl.R = i
   128  				case 'F': // 床(外部)
   129  					dfwl.F = i
   130  				case 'i': // 内壁
   131  					dfwl.i = i
   132  				case 'c': // 天井(内部)
   133  					dfwl.c = i
   134  				case 'f': // 床(内部)
   135  					dfwl.f = i
   136  				}
   137  			}
   138  		} else {
   139  			// 部位コードの指定なし
   140  			Wa.name = s
   141  		}
   142  
   143  		j = -1
   144  
   145  		// (2) 部位・壁体のパラメータを読み取り
   146  		// 例) `Eo=0.9 Ei=0.9 as=0.7 type=1 APR-100 APR-100/20 <P:80.3> ;`
   147  		var layer []string
   148  		for _, s = range line[1:] {
   149  			var err error
   150  			st := strings.IndexRune(s, '=')
   151  			if st != -1 {
   152  				dt, err = strconv.ParseFloat(s[st+1:], 64)
   153  				if err != nil {
   154  					panic(err)
   155  				}
   156  
   157  				switch strings.TrimSpace(s[:st]) {
   158  				case "Ei":
   159  					Wa.Ei = dt // 室内表面放射率
   160  				case "Eo":
   161  					Wa.Eo = dt // 外表面放射率
   162  				case "as":
   163  					Wa.as = dt // 外表面日射吸収率
   164  				case "type":
   165  					Wa.ColType = s[st+1:] // 集熱器のタイプ
   166  				case "tra":
   167  					Wa.tra = dt // τα
   168  				case "Ksu":
   169  					Wa.Ksu = dt // 通気層内上側から屋外までの熱貫流率 [W/m2K]
   170  				case "Ksd":
   171  					Wa.Ksd = dt // 通気層内下側から裏面までの熱貫流率 [W/m2K]
   172  				case "Ru":
   173  					Wa.Ru = dt // 通気層から上面までの熱抵抗 [m2K/W]
   174  				case "Rd":
   175  					Wa.Rd = dt // 通気層から裏面までの熱抵抗 [m2K/W]
   176  				case "fcu":
   177  					Wa.fcu = dt // Kcu / Ksu (太陽光発電設置時のアレイ温度計算のみに使用)
   178  				case "fcd":
   179  					Wa.fcd = dt // Kcd / Ksd (太陽光発電設置時のアレイ温度計算のみに使用)
   180  				case "Kc":
   181  					Wa.Kc = dt
   182  				case "Esu":
   183  					Wa.dblEsu = dt // 通気層内上側の放射率
   184  				case "Esd":
   185  					Wa.dblEsd = dt // 通気層内下側の放射率
   186  				case "Eg":
   187  					Wa.Eg = dt // 透過体の中空層側表面の放射率
   188  				case "Eb":
   189  					Wa.Eb = dt // 集熱板の中空層側表面の放射率
   190  				case "ag":
   191  					Wa.ag = dt // 透過体の日射吸収率
   192  				case "ta":
   193  					Wa.ta = dt / 1000.0 // 中空層の厚さ [mm] -> [m]
   194  				case "tnxt":
   195  					Wa.tnxt = dt
   196  				case "t":
   197  					Wa.air_layer_t = dt / 1000.0
   198  				case "KHD":
   199  					Wa.PVwallcat.KHD = dt // 日射量年変動補正係数 (集熱板が太陽電池一体型のとき)
   200  				case "KPD":
   201  					Wa.PVwallcat.KPD = dt // 経時変化補正係数 (集熱板が太陽電池一体型のとき)
   202  				case "KPM":
   203  					Wa.PVwallcat.KPM = dt // アレイ負荷整合補正係数 (集熱板が太陽電池一体型のとき)
   204  				case "KPA":
   205  					Wa.PVwallcat.KPA = dt // アレイ回路補正係数 (集熱板が太陽電池一体型のとき)
   206  				case "EffInv":
   207  					Wa.PVwallcat.EffINO = dt // インバータ効率 (集熱板が太陽電池一体型のとき)
   208  				case "apamax":
   209  					Wa.PVwallcat.Apmax = dt // 最大出力温度係数 (集熱板が太陽電池一体型のとき)
   210  				case "ap":
   211  					Wa.PVwallcat.Ap = dt // 太陽電池裏面の対流熱伝達率
   212  				case "Rcoloff":
   213  					Wa.PVwallcat.Rcoloff = dt // 太陽電池から集熱器裏面までの熱抵抗 (集熱板が太陽電池一体型のとき)
   214  					Wa.PVwallcat.Kcoloff = 1. / Wa.PVwallcat.Rcoloff
   215  				default:
   216  					Eprint("<Walldata>", s)
   217  				}
   218  			} else {
   219  				layer = append(layer, s)
   220  				j++
   221  			}
   222  		}
   223  
   224  		// 層の数
   225  		Nlyr = j + 1
   226  
   227  		Wa.welm = []WELM{
   228  			{
   229  				Code: "ali", //内表面熱伝達率
   230  				L:    -999.0,
   231  				ND:   0,
   232  				Cond: -999.0,
   233  				Cro:  -999.0,
   234  			},
   235  		}
   236  
   237  		// (3) 層の読み取り
   238  		// `APR-100 APR-100/20 <P:80.3>`
   239  		for j = 1; j <= Nlyr; j++ {
   240  			if Wa.ble == BLE_Roof || Wa.ble == BLE_Ceil {
   241  				jj = Nlyr - j
   242  			} else {
   243  				jj = j - 1
   244  			}
   245  
   246  			// `APR-100`, `APR-100/20` or `<P>:80.3` or `<C>`
   247  			var err error
   248  			st := strings.IndexRune(layer[jj], '-')
   249  			if st != -1 {
   250  				// 一般材料のとき または 一般材料で分割層数を指定するとき
   251  				// For `APR-100` or `APR-100/20`
   252  				var code string // 材料コード
   253  				var ND int      // 内部分割数
   254  				var L float64   // 部材厚さ [mm]
   255  
   256  				// 1) 材料コード
   257  				code = layer[jj][:st]
   258  
   259  				// 2) 同一層内の内部分割数と部材の厚さ
   260  				ss := layer[jj][st+1:]
   261  				st = strings.IndexRune(ss, '/')
   262  				if st != -1 {
   263  					// "20.0/2"のように分割数が指定されている場合
   264  					sss := strings.SplitN(ss, "/", 2)
   265  					L, err = strconv.ParseFloat(sss[0], 64)
   266  					if err != nil {
   267  						panic(err)
   268  					}
   269  
   270  					// 分割数
   271  					ndiv, err = strconv.Atoi(sss[1])
   272  					if err != nil {
   273  						panic(err)
   274  					}
   275  					ND = ndiv - 1
   276  				} else {
   277  					// "20.0"のように分割数が指定されていない場合
   278  					L, err = strconv.ParseFloat(ss, 64)
   279  					if err != nil {
   280  						panic(err)
   281  					}
   282  
   283  					if L >= 50. {
   284  						ND = int((L - 50.) / 50.)
   285  					} else {
   286  						// 50mm未満の場合は分割しない
   287  						ND = 0
   288  					}
   289  				}
   290  
   291  				Wa.welm = append(Wa.welm, WELM{
   292  					Code: code,
   293  					ND:   ND,
   294  					L:    L / 1000.0, // [mm] -> [m]
   295  				})
   296  
   297  			} else if strings.HasPrefix(layer[jj], "<P") || layer[jj] == "<C>" {
   298  				// 放射暖冷房パネル発熱面位置の指定の場合 For `<P:80.3>` or `<P>` or `<C>`
   299  				// ※ `<C>`はマニュアルに記述が見当たらないが、`<P>`と同じ扱いにする
   300  				Wa.Ip = len(Wa.welm) - 1
   301  				if layer[jj][2] == ':' {
   302  					// パネル効率が指定されている場合 `<P:80.3>`
   303  					Wa.effpnl, err = strconv.ParseFloat(layer[jj][3:], 64)
   304  					if err != nil {
   305  						panic(err)
   306  					}
   307  				} else {
   308  					// パネル効率が指定されない場合 `<C>`
   309  					Wa.effpnl = 0.7
   310  				}
   311  			} else if layer[jj] != "alo" && layer[jj] != "ali" {
   312  				// 表面熱伝達率、中空層熱コンダクタンスのとき、材料コードのみを指定する
   313  				Wa.welm = append(Wa.welm, WELM{
   314  					Code: layer[jj],
   315  					ND:   0,
   316  					L:    0.0,
   317  				})
   318  			}
   319  		}
   320  		jw = len(Wa.welm) - 1
   321  
   322  		// 建材一体型空気集熱器の総合熱貫流率の計算、データ入力状況のチェック
   323  		if Wa.Ip >= 0 {
   324  			if Wa.tra > 0. {
   325  				// 壁種類 -> 建材一体型空気集熱器
   326  				Wa.WallType = 'C'
   327  
   328  				if (Wa.Ksu > 0. && Wa.Ksd > 0.) || (Wa.Rd > 0. && (Wa.Ru >= 0. || Wa.ta > 0.)) {
   329  
   330  					if strings.HasPrefix(Wa.ColType, "A") {
   331  						// 集熱器のタイプ = A1,A2,A2P or A3
   332  						if Wa.Ksu > 0. {
   333  							// 熱抵抗が入力されていない
   334  							Wa.Kcu = Wa.fcu * Wa.Ksu
   335  							Wa.Kcd = Wa.fcd * Wa.Ksd
   336  							Wa.Kc = Wa.Kcu + Wa.Kcd
   337  							Wa.ku = Wa.Kcu / Wa.Kc
   338  							Wa.kd = Wa.Kcd / Wa.Kc
   339  						} else {
   340  							// 熱抵抗が入力されている
   341  							Wa.chrRinput = true
   342  						}
   343  					} else if strings.HasPrefix(Wa.ColType, "W") {
   344  						// 集熱器のタイプ = W3
   345  						Wa.Ko = Wa.Ksu + Wa.Ksd
   346  						Wa.ku = Wa.Ksu / Wa.Ko
   347  						Wa.kd = Wa.Ksd / Wa.Ko
   348  					}
   349  
   350  					// PVがある場合は事前計算をする
   351  					if Wa.PVwallcat.KHD > 0. {
   352  						PVwallPreCalc(&Wa.PVwallcat)
   353  					}
   354  				} else {
   355  					s = fmt.Sprintf("ble=%c name=%s 建築一体型空気集熱の熱貫流率Ku、Kdが未定義です", Wa.ble, Wa.name)
   356  					Eprint("<Walldata>", s)
   357  				}
   358  
   359  				if Wa.chrRinput == false && (Wa.Kc < 0. || Wa.Ksu < 0. || Wa.Ksd < 0.) {
   360  					s = fmt.Sprintf("ble=%c name=%s 建築一体型空気集熱の熱貫流率Kc、Kdd、Kudが未定義です",
   361  						Wa.ble, Wa.name)
   362  					Eprint("<Walldata>", s)
   363  				}
   364  
   365  				if Wa.Ip == -1 {
   366  					s = fmt.Sprintf("ble=%c name=%s 建築一体型空気集熱の空気流通層<P>が未定義です",
   367  						Wa.ble, Wa.name)
   368  					Eprint("<Walldata>", s)
   369  				}
   370  			} else {
   371  				// 壁種類 -> 床暖房等放射パネル
   372  				Wa.WallType = WallType_P
   373  			}
   374  		}
   375  
   376  		Wa.N = jw + 1
   377  		Walli(Nbm, W, Wa, pcm)
   378  
   379  		*Wall = append(*Wall, Wa)
   380  		i++
   381  	}
   382  }
   383  
   384  /* ------------------------------------------------ */
   385  
   386  /*  窓デ-タの入力     */
   387  
   388  // WINDOWデータセットの読み取り
   389  func Windowdata(section *EeTokens, Window *[]*WINDOW) {
   390  	E := fmt.Sprintf(ERRFMT, "WINDOW")
   391  
   392  	var N int
   393  	for section.IsEnd() == false {
   394  		line := section.GetLogicalLine()
   395  		if line[0] != "*" {
   396  			N++
   397  		}
   398  	}
   399  	section.Reset()
   400  
   401  	if N > 0 {
   402  		*Window = make([]*WINDOW, N)
   403  
   404  		for j := 0; j < N; j++ {
   405  			(*Window)[j] = NewWINDOW()
   406  		}
   407  	}
   408  
   409  	i := 0
   410  	for section.IsEnd() == false {
   411  		line := section.GetLogicalLine()
   412  
   413  		if line[0] == "*" {
   414  			break
   415  		}
   416  
   417  		W := (*Window)[i]
   418  
   419  		// 名称
   420  		W.Name = line[0]
   421  
   422  		// 名前の重複確認
   423  		for k := 0; k < i; k++ {
   424  			Wc := (*Window)[k]
   425  			if W.Name == Wc.Name {
   426  				ss := fmt.Sprintf("<WINDOW>  WindowName Already Defined  (%s)", W.Name)
   427  				Eprint("<Windowdata>", ss)
   428  			}
   429  		}
   430  
   431  		// プロパティの設定
   432  		for _, s := range line[1:] {
   433  			// 室内透過日射が窓室内側への入射日射を屋外に透過する場合'y'
   434  			if s == "-RStrans" {
   435  				W.RStrans = true
   436  			} else {
   437  				//キー・バリューの分離
   438  				st := strings.IndexRune(s, '=')
   439  				if st == -1 {
   440  					panic("Windowdata: invalid format")
   441  				} else {
   442  					st++
   443  				}
   444  				key := s[:st-1]
   445  				value := s[st:]
   446  
   447  				// 小数読み取り
   448  				var realValue float64
   449  				var err error
   450  				switch key {
   451  				case "t", "B", "R", "Ei", "Eo":
   452  					realValue, err = strconv.ParseFloat(value, 64)
   453  					if err != nil {
   454  						panic(err)
   455  					}
   456  				}
   457  
   458  				// 値の設定
   459  				switch key {
   460  				case "t":
   461  					W.tgtn = realValue // 日射透過率
   462  				case "B":
   463  					W.Bn = realValue // 吸収日射取得率
   464  				case "R":
   465  					W.Rwall = realValue // 窓部材熱抵抗 [m2K/W]
   466  				case "Ei":
   467  					W.Ei = realValue // 室内表面放射率(0.9)
   468  				case "Eo":
   469  					W.Eo = realValue // 外表面放射率(0.9)
   470  				case "Cidtype":
   471  					W.Cidtype = strings.Trim(value, "'") // 入射角特性の種類
   472  				default:
   473  					Err := fmt.Sprintf("%s %s\n", E, s)
   474  					Eprint("<Windowdata>", Err)
   475  				}
   476  
   477  				//NOTE: 以下の項目を入力する箇所が不明
   478  				// 窓ガラス面積 Ag, 開口面積 Ao, 幅 W, 高さ H, ??? K
   479  			}
   480  		}
   481  
   482  		i++
   483  	}
   484  }
   485  
   486  /* --------------------------------------------------- */
   487  
   488  func Snbkdata(section *EeTokens, dsn string, Snbk *[]*SNBK) {
   489  	// 入力チェック用パターン文字列
   490  	typstr := []string{
   491  		"HWDTLR.", // 庇
   492  		"HWDTLRB", // 袖壁(その1) (左右)
   493  		"HWDTL.B", // 袖壁(その2) (左のみ)
   494  		"HWDT.RB", // 袖壁(その3) (右のみ)
   495  		"HWDT...", // 長い庇
   496  		"HWD.LR.", // 長い袖壁(その1) (左右)
   497  		"HWD.L..", // 長い袖壁(その2) (左のみ)
   498  		"HWD..R.", // 長い袖壁(その3) (右のみ)
   499  		"HWDTLRB", // ルーバー
   500  	}
   501  
   502  	Er := fmt.Sprintf(ERRFMT, dsn)
   503  	Type := 0
   504  
   505  	*Snbk = make([]*SNBK, 0)
   506  
   507  	for section.IsEnd() == false {
   508  
   509  		fields := section.GetLogicalLine()
   510  		if fields[0] == "*" {
   511  			break
   512  		}
   513  
   514  		S := NewSNBK()
   515  
   516  		// 名前
   517  		S.Name = fields[0]
   518  
   519  		// 入力チェック用
   520  		code := [7]rune{'.', '.', '.', '.', '.', '.', '.'}
   521  
   522  		for _, s := range fields[1:] {
   523  			// キー・バリューの分離
   524  			st := strings.IndexRune(s, '=')
   525  			if st == -1 {
   526  				panic("Snbkdata: invalid format")
   527  			}
   528  			key := s[:st]
   529  			v := s[st+1:]
   530  
   531  			var err error
   532  			switch key {
   533  			case "type":
   534  				var vs string
   535  				if v[0] == '-' {
   536  					S.Ksi = 1
   537  					vs = v[1:]
   538  				} else {
   539  					S.Ksi = 0
   540  					vs = v[0:]
   541  				}
   542  
   543  				if vs == "H" {
   544  					Type = 1 // 一般の庇
   545  				} else if vs == "HL" {
   546  					Type = 5 // 長い庇
   547  				} else if vs == "S" {
   548  					Type = 2 // 袖壁
   549  				} else if vs == "SL" {
   550  					Type = 6 // 長い袖壁
   551  				} else if vs == "K" {
   552  					Type = 9 // 格子ルーバー
   553  				} else {
   554  					E := fmt.Sprintf("`%s` is invalid", vs)
   555  					Eprint("<Snbkdata>", E)
   556  				}
   557  
   558  			case "window":
   559  				// For `window=HhhhxWwww`
   560  				hw := strings.Split(v, "x")
   561  				h, w := hw[0], hw[1]
   562  
   563  				if h[0] != 'H' || w[0] != 'W' {
   564  					panic(fmt.Sprintf("Invaid window format: %s", v))
   565  				}
   566  
   567  				// 開口部の高さ
   568  				S.H, err = strconv.ParseFloat(h[1:], 64)
   569  				if err != nil {
   570  					panic(err)
   571  				}
   572  				code[0] = 'H'
   573  
   574  				// 開口部の幅
   575  				S.W, err = strconv.ParseFloat(w[1:], 64)
   576  				if err != nil {
   577  					panic(err)
   578  				}
   579  				code[1] = 'W'
   580  
   581  			case "D":
   582  				// 庇の付け根から先端までの長さ
   583  				S.D, err = strconv.ParseFloat(v, 64)
   584  				if err != nil {
   585  					panic(err)
   586  				}
   587  				code[2] = 'D'
   588  
   589  			case "T":
   590  				// 開口部の上端から壁の上端までの距離
   591  				S.H1, err = strconv.ParseFloat(v, 64)
   592  				if err != nil {
   593  					panic(err)
   594  				}
   595  				code[3] = 'T'
   596  
   597  			case "L":
   598  				// 開口部の左端から壁の左端までの距離
   599  				S.W1, err = strconv.ParseFloat(v, 64)
   600  				if err != nil {
   601  					panic(err)
   602  				}
   603  				code[4] = 'L'
   604  
   605  			case "R":
   606  				// 開口部の右端から壁の右端までの距離
   607  				S.W2, err = strconv.ParseFloat(v, 64)
   608  				if err != nil {
   609  					panic(err)
   610  				}
   611  				code[5] = 'R'
   612  
   613  			case "B":
   614  				// 地面から開口部の下端までの高さ
   615  				S.H2, err = strconv.ParseFloat(v, 64)
   616  				if err != nil {
   617  					panic(err)
   618  				}
   619  				code[6] = 'B'
   620  
   621  			default:
   622  				panic(fmt.Sprintf("Invaid window format: %s", s))
   623  			}
   624  		}
   625  
   626  		// 日除けの種類
   627  		S.Type = Type
   628  
   629  		// 日除けの種類ごとに入力チェック
   630  		switch Type {
   631  		case 1, 5, 9:
   632  			// 庇 or ルーバー
   633  			if string(code[:]) != typstr[Type-1] {
   634  				E := fmt.Sprintf("%s %s  type=%d %s\n", Er, fields[0], Type, string(code[:]))
   635  				Eprint("<Snbkdata>", E)
   636  			}
   637  		case 2, 6:
   638  			// 袖壁
   639  			if string(code[:]) != typstr[Type-1] {
   640  				for j := 1; j < 3; j++ {
   641  					if string(code[:]) == typstr[Type+j-1] {
   642  						S.Type = Type + j
   643  						break
   644  					}
   645  					if j == 3 {
   646  						E := fmt.Sprintf("%s %s  type=%d %s\n", Er, fields[0], Type, string(code[:]))
   647  						Eprint("<Snbkdata>", E)
   648  					}
   649  				}
   650  			}
   651  		}
   652  
   653  		*Snbk = append(*Snbk, S)
   654  	}
   655  }
   656  
   657  func NewSNBK() *SNBK {
   658  	S := new(SNBK)
   659  	S.Name = ""
   660  	S.W = 0.0
   661  	S.H = 0.0
   662  	S.D = 0.0
   663  	S.W1 = 0.0
   664  	S.W2 = 0.0
   665  	S.H1 = 0.0
   666  	S.H2 = 0.0
   667  	S.Type = 0
   668  	S.Ksi = 0
   669  	return S
   670  }
   671  
   672  /************************************************************/
   673  
   674  func wbmlistcount(fi string) []string {
   675  	N := make([]string, 0)
   676  
   677  	reader := strings.NewReader(fi)
   678  	scanner := bufio.NewScanner(reader)
   679  
   680  	for scanner.Scan() {
   681  		s := scanner.Text()
   682  
   683  		if strings.HasPrefix(s, "*") {
   684  			break
   685  		}
   686  
   687  		//コメントを読み飛ばす
   688  		st := strings.IndexRune(s, '!')
   689  		if st != -1 {
   690  			s = s[:st]
   691  		}
   692  
   693  		//ゴミ除去
   694  		s = strings.TrimSpace(s)
   695  
   696  		if s != "" {
   697  			N = append(N, s)
   698  		}
   699  	}
   700  
   701  	return N
   702  }
   703  
   704  /************************************************************/
   705  
   706  func Wallcount(scanner *bufio.Scanner) []string {
   707  	N := make([]string, 0)
   708  
   709  	for scanner.Scan() {
   710  		s := scanner.Text()
   711  
   712  		if strings.HasPrefix(s, "*") {
   713  			break
   714  		}
   715  
   716  		//コメントを読み飛ばす
   717  		st := strings.IndexRune(s, '!')
   718  		if st != -1 {
   719  			s = s[:st]
   720  		}
   721  
   722  		//ゴミ除去
   723  		s = strings.TrimSpace(s)
   724  
   725  		if s != "" {
   726  			N = append(N, s)
   727  		}
   728  	}
   729  
   730  	return N
   731  }