傾斜したソーラーパネルに入射する全球放射を計算するために必要な式を実装しようとしています。
私が使用する数式は、次の研究論文に記載されています。
--> ipac.kacst.edu.sa/eDoc/2010/191048_1.pdf
コメント付きの JavaScript コードは次のとおりです。
var config = require('./configuration.json'),
pi = Math.PI;
function solar_efficiency(angle, day) {
var R_mD, // average sun-earth distance (m)
a, // semi-major axis (km)
e, // oval orbit eccentricity (km)
theta, // angle with the perihelion
n, // current nth day of the year (int)
R_D, // actual sun-earth distance (m)
I_o; // extraterrestrial radiation (indice)
R_mD = config.avg_sun_earth_dist;
a = config.semi_major_axis;
e = config.eccentricity;
n = day;
theta = n * 365.25 / 360;
R_D = a * (1 - e * e) / (1 + e * Math.cos(theta));
I_o = 1367 * Math.pow(R_mD / R_D, 2);
var axis, // angle of the earth's axis
D; // sun declination (radian)
axis = config.earth_axis;
D = ((axis * pi) / 180) * Math.sin(((2 * pi) * (284 + n)) / 365);
var Eq_t; // solar time correction (float)
if((1 <= n) && (n <= 106)) {
Eq_t = -14.2 * Math.sin((pi * (n + 7)) / 111);
}
else if((107 <= n) && (n <= 166)) {
Eq_t = 4.0 * Math.sin((pi * (n - 106)) / 59);
}
else if((167 <= n) && (n <= 246)) {
Eq_t = -6.5 * Math.sin((pi * (n - 166)) / 80);
}
else if((247 <= n) && (n <= 365)) {
Eq_t = 16.4 * Math.sin((pi * (n - 247)) / 113);
}
var Long_sm, // longitude of the standard meridian (longitude)
Long_local, // longitude of the panels (longitude)
T_local, // local time (h)
T_solar; // solar time (h)
Long_sm = config.std_meridian_long;
Long_local = config.current_longitutde;
T_local = config.local_time;
T_solar = T_local + (Eq_t / 60) + ((Long_sm - Long_local) / 15);
var W; // hour angle (radian)
W = pi * ((12 - T_solar) / 12);
var Lat_local, // latitude of the panels (latitude)
W_sr, // sunrise hour angle (°)
W_ss; // sunset hour angle (°)
Lat_local = config.current_latitude;
W_sr = W_ss = Math.acos(-1 * Math.tan(Lat_local) * Math.tan(D));
var alpha, // angle between solar panel and horizontal (°) -FIND!!!
R_b; // ratio of avg. beam radiation on horiz. / inclined surface
alpha = angle; // /!\ TESTING ONLY /!\
var num_1 = Math.cos(Lat_local - alpha) * Math.cos(D) * Math.sin(W_ss);
var num_2 = W_ss * Math.sin(Lat_local - alpha) * Math.sin(D);
var det_1 = Math.cos(Lat_local) * Math.cos(D) * Math.sin(W_ss);
var det_2 = W_ss * Math.sin(Lat_local) * Math.sin(D);
R_b = (num_1 + num_2) / (det_1 + det_2); // in the northern hemisphere
var H_g, // global radiation on horizontal surface (W h/m^2/day) ---DB!!!
H_d, // diffuse radiation on horizontal surface (W h/m^2/day) ---DB!!!
H_B; // beam radiation on inclined surface (W h/m^2/day)
H_g = 700;
H_d = 500;
H_B = (H_g - H_d) / R_b;
var R_d; // ratio of avg. daily diffuse radiation tilted / horiz. surface
R_d = (3 + Math.cos(2 * alpha)) / 2; // isotropic Badesco model
var H_D; // sky-diffuse radiation on inclined surface (W h/m^2/day)
H_D = R_d * H_d;
var p, // albedo std. = 0.2 (soil = 0.17, grass = 0.25, concrete = 0.55)
H_R; // ground reflected radiation on inclined surface (W h/m^2/day)
p = config.ground_albedo;
H_R = H_g * p * ((1 - Math.cos(alpha)) / 2);
var H_T; // daily global radiation on a tilted surface (W h/m^2/day)
H_T = H_B + H_D + H_R;
return H_T;
}
var results = {}, current_day;
for(var i = 0; i < 365; i++) {
current_day = [];
for(var k = 0; k <= 90; k++) {
current_day.push([k, solar_efficiency(k, i)]);
}
current_day.sort(function(a, b) { return b[1] - a[1]; });
current_day.length = 1;
results[i] = current_day[0];
}
console.log(results);
緯度や経度などの構成は、JSON ファイルにあります。プログラムをテストしている値は次のとおりです。
{
"avg_sun_earth_dist" : 149597870.7,
"earth_axis" : 23.45,
"eccentricity" : 0.0167,
"semi_major_axis" : 149598261,
"local_time" : 12,
"std_meridian_long" : 0,
"current_longitude" : 2.294351,
"current_latitude" : 48.858844,
"ground_albedo" : 0.2
}
緯度を少し変更すると、NaN が得られるか、値が安定しますが、突然「i」の特定の値が急上昇することがわかります。
問題は次の行のようです:
W_sr = W_ss = Math.acos(-1 * Math.tan(Lat_local) * Math.tan(D));
入力データが間違っているためにプログラムがクラッシュするのか、それとも数式を間違って実装しただけなのかはわかりません。