github.com/archlabjp/eeslism-go@v0.0.0-20231109122333-4bb7bfcdf292/eeslism/mcpv.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  /*  solrcol.c  */
    17  
    18  package eeslism
    19  
    20  /* 太陽光発電システム
    21  
    22  機器仕様入力    */
    23  
    24  import (
    25  	"fmt"
    26  	"io"
    27  	"math"
    28  	"strconv"
    29  	"strings"
    30  )
    31  
    32  func PVcadata(s string, PVca *PVCA) int {
    33  	dt := 0.0
    34  	id := 0
    35  
    36  	var st int
    37  	if st = strings.IndexRune(s, '='); st == -1 {
    38  		PVca.Name = s
    39  		PVca.PVcap = -999.0
    40  		PVca.Area = -999.0
    41  		PVca.KHD = 1.0
    42  		PVca.KPD = 0.95
    43  		PVca.KPM = 0.94
    44  		PVca.KPA = 0.97
    45  		PVca.effINO = 0.9
    46  		PVca.A = -999.0
    47  		PVca.B = -999.0
    48  		PVca.apmax = -0.41
    49  	} else {
    50  		s1 := s[:st]
    51  		s2 := s[st+1:]
    52  
    53  		var err error
    54  		dt, err = strconv.ParseFloat(s2, 64)
    55  		if err != nil {
    56  			panic(err)
    57  		}
    58  
    59  		switch {
    60  		case strings.HasPrefix(s1, "KHD"):
    61  			// 日射量年変動補正係数
    62  			PVca.KHD = dt
    63  		case strings.HasPrefix(s1, "KPD"):
    64  			// 経時変化補正係数
    65  			PVca.KPD = dt
    66  		case strings.HasPrefix(s1, "KPM"):
    67  			// アレイ負荷整合補正係数
    68  			PVca.KPM = dt
    69  		case strings.HasPrefix(s1, "KPA"):
    70  			// アレイ回路補正係数
    71  			PVca.KPA = dt
    72  		case strings.HasPrefix(s1, "EffInv"):
    73  			// インバータ実行効率
    74  			PVca.effINO = dt
    75  		case strings.HasPrefix(s1, "apmax"):
    76  			// 最大出力温度係数
    77  			PVca.apmax = dt
    78  		case s1 == "InstallType":
    79  			PVca.InstallType = rune(s2[0])
    80  			switch PVca.InstallType {
    81  			case 'A':
    82  				PVca.A = 46.0
    83  				PVca.B = 0.41
    84  			case 'B':
    85  				PVca.A = 50.0
    86  				PVca.B = 0.38
    87  			case 'C':
    88  				PVca.A = 57.0
    89  				PVca.B = 0.33
    90  			}
    91  		case strings.HasPrefix(s1, "PVcap"):
    92  			// 太陽電池容量
    93  			PVca.PVcap = dt
    94  		case strings.HasPrefix(s1, "Area"):
    95  			// 太陽電池容量
    96  			PVca.Area = dt
    97  		default:
    98  			id = 1
    99  		}
   100  	}
   101  	return id
   102  }
   103  
   104  /* ------------------------------------- */
   105  
   106  /*  初期設定 */
   107  
   108  func PVint(PV []*PV, Exs []*EXSF, Wd *WDAT) {
   109  	Err := ""
   110  
   111  	for i := range PV {
   112  		PV[i].Ta = &Wd.T
   113  		PV[i].V = &Wd.Wv
   114  
   115  		for _, exs := range Exs {
   116  			if PV[i].Cmp.Exsname == exs.Name {
   117  				PV[i].Sol = exs
   118  				PV[i].I = &PV[i].Sol.Iw
   119  				break
   120  			}
   121  		}
   122  
   123  		if PV[i].Sol == nil {
   124  			Eprint("PVint", PV[i].Cmp.Exsname)
   125  		}
   126  
   127  		if PV[i].Cat.KHD < 0.0 {
   128  			Err = fmt.Sprintf("Name=%s KHD=%.4g", PV[i].Cmp.Name, PV[i].Cat.KHD)
   129  			Eprint("PVint", Err)
   130  		}
   131  
   132  		if PV[i].Cat.KPD < 0.0 {
   133  			Err = fmt.Sprintf("Name=%s KHD=%.4g", PV[i].Cmp.Name, PV[i].Cat.KPD)
   134  			Eprint("PVint", Err)
   135  		}
   136  
   137  		if PV[i].Cat.KPM < 0.0 {
   138  			Err = fmt.Sprintf("Name=%s KPM=%.4g", PV[i].Cmp.Name, PV[i].Cat.KPM)
   139  			Eprint("PVint", Err)
   140  		}
   141  
   142  		if PV[i].Cat.KPA < 0.0 {
   143  			Err = fmt.Sprintf("Name=%s KPA=%.4g", PV[i].Cmp.Name, PV[i].Cat.KPA)
   144  			Eprint("PVint", Err)
   145  		}
   146  
   147  		if PV[i].Cat.effINO < 0.0 {
   148  			Err = fmt.Sprintf("Name=%s EffInv=%.4g", PV[i].Cmp.Name, PV[i].Cat.effINO)
   149  			Eprint("PVint", Err)
   150  		}
   151  
   152  		if PV[i].Cat.apmax > 0.0 {
   153  			Err = fmt.Sprintf("Name=%s apmax=%.4g", PV[i].Cmp.Name, PV[i].Cat.apmax)
   154  			Eprint("PVint", Err)
   155  		}
   156  
   157  		if PV[i].PVcap < 0.0 {
   158  			Err = fmt.Sprintf("Name=%s PVcap=%.4g", PV[i].Cmp.Name, PV[i].PVcap)
   159  			Eprint("PVint", Err)
   160  		}
   161  
   162  		if PV[i].Area < 0.0 {
   163  			Err = fmt.Sprintf("Name=%s Area=%.4g", PV[i].Cmp.Name, PV[i].Area)
   164  			Eprint("PVint", Err)
   165  		}
   166  
   167  		// 計算途中で変化しない各種補正係数の積
   168  		PV[i].KConst = PV[i].Cat.KHD * PV[i].Cat.KPD * PV[i].Cat.KPM * PV[i].Cat.KPA * PV[i].Cat.effINO
   169  	}
   170  }
   171  
   172  // 太陽光発電の発電量計算
   173  /* ------------------------------------- */
   174  
   175  /*  集熱量の計算 */
   176  
   177  func PVene(PV []*PV) {
   178  	for i := range PV {
   179  		// 太陽電池アレイの計算(JIS C 8907:2005 P21による)
   180  		PV[i].TPV = *PV[i].Ta + (PV[i].Cat.A/(PV[i].Cat.B*math.Pow(*PV[i].V, 0.8)+1.0)+2.0)**PV[i].I/1000.0 - 2.0
   181  		PV[i].KPT = FNKPT(PV[i].TPV, PV[i].Cat.apmax)
   182  		PV[i].KTotal = PV[i].KConst * PV[i].KPT
   183  
   184  		// 太陽電池入社日射量の計算
   185  		PV[i].Iarea = *PV[i].I * PV[i].Area
   186  
   187  		// 発電量の計算
   188  		PV[i].Power = PV[i].KTotal * *PV[i].I / 1000.0 * PV[i].PVcap
   189  
   190  		// 発電効率の計算
   191  		PV[i].Eff = 0.0
   192  		if PV[i].Iarea > 0.0 {
   193  			PV[i].Eff = PV[i].Power / PV[i].Iarea
   194  		}
   195  	}
   196  }
   197  
   198  /* ------------------------------------------------------------- */
   199  
   200  func PVprint(fo io.Writer, id int, PV []*PV) {
   201  	switch id {
   202  	case 0:
   203  		if len(PV) > 0 {
   204  			fmt.Fprintf(fo, "%s %d\n", PV_TYPE, len(PV))
   205  		}
   206  		for i := range PV {
   207  			fmt.Fprintf(fo, " %s 1 4\n", PV[i].Name)
   208  		}
   209  		break
   210  
   211  	case 1:
   212  		for i := range PV {
   213  			fmt.Fprintf(fo, " %s_TPV t f %s_I e f %s_P e f %s_Eff r f \n",
   214  				PV[i].Name, PV[i].Name, PV[i].Name, PV[i].Name)
   215  		}
   216  		break
   217  
   218  	default:
   219  		for i := range PV {
   220  			fmt.Fprintf(fo, " %4.1f %4.0f %3.0f %.3f\n",
   221  				PV[i].TPV, PV[i].Iarea, PV[i].Power, PV[i].Eff)
   222  		}
   223  		break
   224  	}
   225  }
   226  
   227  /* --------------------------- */
   228  
   229  /* 日積算値に関する処理 */
   230  
   231  func PVdyint(PV []*PV) {
   232  	for i := range PV {
   233  		qdyint(&PV[i].Edy)
   234  		edyint(&PV[i].Soldy)
   235  	}
   236  }
   237  
   238  func PVmonint(PV []*PV) {
   239  	for i := range PV {
   240  		qdyint(&PV[i].mEdy)
   241  		edyint(&PV[i].mSoldy)
   242  	}
   243  }
   244  
   245  func PVday(Mon int, Day int, ttmm int, PV []*PV, Nday int, SimDayend int) {
   246  	Mo := Mon - 1
   247  	tt := ConvertHour(ttmm)
   248  
   249  	for i := range PV {
   250  		var sw ControlSWType
   251  		if PV[i].Power > 0.0 {
   252  			sw = ON_SW
   253  		} else {
   254  			sw = OFF_SW
   255  		}
   256  
   257  		// 日間集計
   258  		qdaysum(int64(ttmm), sw, PV[i].Power, &PV[i].Edy)
   259  
   260  		if *PV[i].I > 0.0 {
   261  			sw = ON_SW
   262  		} else {
   263  			sw = OFF_SW
   264  		}
   265  		// 時間集計
   266  		edaysum(ttmm, sw, *PV[i].I, &PV[i].Soldy)
   267  
   268  		// 月間集計
   269  		sw = OFF_SW
   270  		if PV[i].Power > 0.0 {
   271  			sw = ON_SW
   272  		}
   273  		qmonsum(Mon, Day, ttmm, sw, PV[i].Power, &PV[i].mEdy, Nday, SimDayend)
   274  
   275  		if *PV[i].I > 0.0 {
   276  			sw = ON_SW
   277  		} else {
   278  			sw = OFF_SW
   279  		}
   280  		// 時間集計
   281  		emonsum(Mon, Day, ttmm, sw, *PV[i].I, &PV[i].mSoldy, Nday, SimDayend)
   282  
   283  		// 月・時刻のクロス集計
   284  		emtsum(Mon, Day, ttmm, sw, PV[i].Power, &PV[i].mtEdy[Mo][tt])
   285  	}
   286  }
   287  
   288  func PVdyprt(fo io.Writer, id int, PV []*PV) {
   289  	switch id {
   290  	case 0:
   291  		if len(PV) > 0 {
   292  			fmt.Fprintf(fo, "%s %d\n", PV_TYPE, len(PV))
   293  		}
   294  		for i := range PV {
   295  			fmt.Fprintf(fo, " %s 1 8\n", PV[i].Name)
   296  		}
   297  	case 1:
   298  		for i := range PV {
   299  			fmt.Fprintf(fo, "%s_Hh H d %s_E E f\n", PV[i].Name, PV[i].Name)
   300  			fmt.Fprintf(fo, "%s_th h d %s_Em e f\n", PV[i].Name, PV[i].Name)
   301  			fmt.Fprintf(fo, "%s_He H d %s_S E f %s_te h d %s_Sm e f\n\n", PV[i].Name, PV[i].Name, PV[i].Name, PV[i].Name)
   302  		}
   303  	default:
   304  		for i := range PV {
   305  			fmt.Fprintf(fo, "%1d %3.1f ", PV[i].Edy.Hhr, PV[i].Edy.H)
   306  			fmt.Fprintf(fo, "%1d %2.0f\n", PV[i].Edy.Hmxtime, PV[i].Edy.Hmx)
   307  
   308  			fmt.Fprintf(fo, "%1d %3.1f ", PV[i].Soldy.Hrs, PV[i].Soldy.D)
   309  			fmt.Fprintf(fo, "%1d %2.0f\n", PV[i].Soldy.Mxtime, PV[i].Soldy.Mx)
   310  		}
   311  	}
   312  }
   313  
   314  func PVmonprt(fo io.Writer, id int, PV []*PV) {
   315  	switch id {
   316  	case 0:
   317  		if len(PV) > 0 {
   318  			fmt.Fprintf(fo, "%s %d\n", PV_TYPE, len(PV))
   319  		}
   320  		for i := range PV {
   321  			fmt.Fprintf(fo, " %s 1 8\n", PV[i].Name)
   322  		}
   323  	case 1:
   324  		for i := range PV {
   325  			fmt.Fprintf(fo, "%s_Hh H d %s_E E f\n", PV[i].Name, PV[i].Name)
   326  			fmt.Fprintf(fo, "%s_th h d %s_Em e f\n", PV[i].Name, PV[i].Name)
   327  			fmt.Fprintf(fo, "%s_He H d %s_S E f %s_te h d %s_Sm e f\n\n", PV[i].Name, PV[i].Name, PV[i].Name, PV[i].Name)
   328  		}
   329  	default:
   330  		for i := range PV {
   331  			fmt.Fprintf(fo, "%1d %3.1f ", PV[i].mEdy.Hhr, PV[i].mEdy.H)
   332  			fmt.Fprintf(fo, "%1d %2.0f\n", PV[i].mEdy.Hmxtime, PV[i].mEdy.Hmx)
   333  
   334  			fmt.Fprintf(fo, "%1d %3.1f ", PV[i].mSoldy.Hrs, PV[i].mSoldy.D)
   335  			fmt.Fprintf(fo, "%1d %2.0f\n", PV[i].mSoldy.Mxtime, PV[i].mSoldy.Mx)
   336  		}
   337  	}
   338  }
   339  
   340  func PVmtprt(fo io.Writer, id int, PV []*PV, Mo int, tt int) {
   341  	switch id {
   342  	case 0:
   343  		if len(PV) > 0 {
   344  			fmt.Fprintf(fo, "%s %d\n", PV_TYPE, len(PV))
   345  		}
   346  		for i := range PV {
   347  			fmt.Fprintf(fo, " %s 1 1\n", PV[i].Name)
   348  		}
   349  	case 1:
   350  		for i := range PV {
   351  			fmt.Fprintf(fo, "%s_E E f\n", PV[i].Name)
   352  		}
   353  	default:
   354  		for i := range PV {
   355  			fmt.Fprintf(fo, " %.2f\n", PV[i].mtEdy[Mo-1][tt-1].D*Cff_kWh)
   356  		}
   357  	}
   358  }