main.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106
  1. /*******************************************************************************
  2. r.sun: This program was writen by Jaro Hofierka in Summer 1993 and re-engineered
  3. in 1996-1999. In cooperation with Marcel Suri and Thomas Huld from JRC in Ispra
  4. a new version of r.sun was prepared using ESRA solar radiation formulas.
  5. See manual pages for details.
  6. (C) 2002 Copyright Jaro Hofierka, Gresaka 22, 085 01 Bardejov, Slovakia,
  7. and GeoModel, s.r.o., Bratislava, Slovakia
  8. email: hofierka@geomodel.sk,marcel.suri@jrc.it,suri@geomodel.sk Thomas.Huld@jrc.it
  9. (c) 2003-2013 by The GRASS Development Team
  10. *******************************************************************************/
  11. /*
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * as published by the Free Software Foundation; either version 2
  15. * of the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the
  24. * Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /*v. 2.0 July 2002, NULL data handling, JH */
  28. /*v. 2.1 January 2003, code optimization by Thomas Huld, JH */
  29. /*v. 3.0 February 2006, several changes (shadowing algorithm, earth's curvature JH */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <math.h>
  33. #ifdef USE_OPENCL
  34. #ifdef __APPLE__
  35. #include <OpenCL/opencl.h>
  36. #else
  37. #include <CL/cl.h>
  38. #endif
  39. #endif
  40. #include <grass/gis.h>
  41. #include <grass/raster.h>
  42. #include <grass/gprojects.h>
  43. #include <grass/glocale.h>
  44. #include "sunradstruct.h"
  45. #include "local_proto.h"
  46. #include "rsunglobals.h"
  47. /* default values */
  48. #define NUM_PARTITIONS "1"
  49. #define SKIP "1"
  50. #define BIG 1.e20
  51. #define LINKE "3.0"
  52. #define SLOPE "0.0"
  53. #define ASPECT "270"
  54. #define ALB "0.2"
  55. #define STEP "0.5"
  56. #define BSKY 1.0
  57. #define DSKY 1.0
  58. #define DIST "1.0"
  59. #define SCALING_FACTOR 150.
  60. const double invScale = 1. / SCALING_FACTOR;
  61. #define AMAX1(arg1, arg2) ((arg1) >= (arg2) ? (arg1) : (arg2))
  62. #define AMIN1(arg1, arg2) ((arg1) <= (arg2) ? (arg1) : (arg2))
  63. #define DISTANCE1(x1, x2, y1, y2) (sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)))
  64. #define DISTANCE2(x00, y00) ((xx0 - x00)*(xx0 - x00) + (yy0 - y00)*(yy0 - y00))
  65. const double pihalf = M_PI * 0.5;
  66. const double pi2 = M_PI * 2.;
  67. const double deg2rad = M_PI / 180.;
  68. const double rad2deg = 180. / M_PI;
  69. FILE *felevin, *faspin, *fslopein, *flinkein, *falbedo, *flatin;
  70. FILE *fincidout, *fbeam_rad, *finsol_time, *fdiff_rad, *frefl_rad;
  71. const char *elevin;
  72. const char *aspin;
  73. const char *slopein;
  74. const char *civiltime = NULL;
  75. const char *linkein = NULL;
  76. const char *albedo = NULL;
  77. const char *latin = NULL;
  78. const char *coefbh = NULL;
  79. const char *coefdh = NULL;
  80. const char *incidout = NULL;
  81. const char *longin = NULL;
  82. const char *horizon = NULL;
  83. const char *beam_rad = NULL;
  84. const char *insol_time = NULL;
  85. const char *diff_rad = NULL;
  86. const char *refl_rad = NULL;
  87. const char *glob_rad = NULL;
  88. const char *mapset = NULL;
  89. const char *per;
  90. size_t decimals;
  91. char *str_step;
  92. struct Cell_head cellhd;
  93. struct pj_info iproj;
  94. struct pj_info oproj;
  95. struct History hist;
  96. int INPUT_part(int offset, double *zmax);
  97. int OUTGR(void);
  98. int min(int, int);
  99. int max(int, int);
  100. void cube(int, int);
  101. void (*func) (int, int);
  102. void joules2(struct SunGeometryConstDay *sunGeom,
  103. struct SunGeometryVarDay *sunVarGeom,
  104. struct SunGeometryVarSlope *sunSlopeGeom,
  105. struct SolarRadVar *sunRadVar,
  106. struct GridGeometry *gridGeom,
  107. unsigned char *horizonpointer, double latitude,
  108. double longitude);
  109. void calculate(double singleSlope, double singleAspect,
  110. double singleAlbedo, double singleLinke,
  111. struct GridGeometry gridGeom);
  112. double com_declin(int);
  113. int n, m, ip, jp;
  114. int d, day;
  115. int saveMemory, numPartitions = 1;
  116. long int shadowoffset = 0;
  117. int varCount_global = 0;
  118. int bitCount_global = 0;
  119. int arrayNumInt = 1;
  120. float **z = NULL, **o = NULL, **s = NULL, **li = NULL, **a = NULL,
  121. **latitudeArray = NULL, **longitudeArray, **cbhr = NULL, **cdhr = NULL;
  122. double op, dp;
  123. double invstepx, invstepy;
  124. double sunrise_min = 24., sunrise_max = 0., sunset_min = 24., sunset_max = 0.;
  125. float **lumcl, **beam, **insol, **diff, **refl, **globrad;
  126. unsigned char *horizonarray = NULL;
  127. double civilTime;
  128. /*
  129. * double startTime, endTime;
  130. */
  131. double xmin, xmax, ymin, ymax;
  132. double declin, step, dist;
  133. double linke_max = 0., linke_min = 100., albedo_max = 0., albedo_min = 1.0,
  134. lat_max = -90., lat_min = 90.;
  135. double offsetx = 0.5, offsety = 0.5;
  136. char *ttime;
  137. /*
  138. * double slope;
  139. */
  140. double o_orig, z1;
  141. /*
  142. * double lum_C11, lum_C13, lum_C22, lum_C31, lum_C33;
  143. * double sinSolarAltitude; */
  144. /* Sine of the solar altitude (angle above horizon)
  145. */
  146. /*
  147. * double sunrise_time, sunset_time;
  148. * double solarAltitude;
  149. * double tanSolarAlt, solarAzimuth;
  150. * double stepsinangle, stepcosangle;
  151. * double angle;
  152. */
  153. double horizonStep;
  154. double ltime, tim, timo;
  155. double declination; /* Contains the negative of the declination at the chosen day */
  156. /*
  157. * double lum_C31_l, lum_C33_l;
  158. */
  159. double beam_e, diff_e, refl_e, rr, insol_t;
  160. double cbh, cdh;
  161. double TOLER;
  162. /* 1852m/nm * 60nm/degree = 111120 m/deg */
  163. #define DEGREEINMETERS 111120.
  164. int ll_correction = FALSE;
  165. double coslatsq;
  166. /* why not use G_distance() here which switches to geodesic/great
  167. circle distace as needed? */
  168. double distance(double x1, double x2, double y1, double y2)
  169. {
  170. if (ll_correction) {
  171. return DEGREEINMETERS * sqrt(coslatsq * (x1 - x2) * (x1 - x2)
  172. + (y1 - y2) * (y1 - y2));
  173. }
  174. else {
  175. return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  176. }
  177. }
  178. int main(int argc, char *argv[])
  179. {
  180. double singleSlope;
  181. double singleAspect;
  182. double singleAlbedo;
  183. double singleLinke;
  184. struct GModule *module;
  185. struct
  186. {
  187. struct Option *elevin, *aspin, *aspect, *slopein, *slope, *linkein,
  188. *lin, *albedo, *longin, *alb, *latin, *coefbh, *coefdh,
  189. *incidout, *beam_rad, *insol_time, *diff_rad, *refl_rad,
  190. *glob_rad, *day, *step, *declin, *ltime, *dist, *horizon,
  191. *horizonstep, *numPartitions, *civilTime;
  192. }
  193. parm;
  194. struct
  195. {
  196. struct Flag *noshade, *saveMemory;
  197. }
  198. flag;
  199. struct GridGeometry gridGeom;
  200. G_gisinit(argv[0]);
  201. module = G_define_module();
  202. G_add_keyword(_("raster"));
  203. G_add_keyword(_("solar"));
  204. G_add_keyword(_("sun energy"));
  205. G_add_keyword(_("shadow"));
  206. module->label = _("Solar irradiance and irradiation model.");
  207. module->description =
  208. _("Computes direct (beam), diffuse and reflected solar irradiation raster "
  209. "maps for given day, latitude, surface and atmospheric conditions. Solar "
  210. "parameters (e.g. sunrise, sunset times, declination, extraterrestrial "
  211. "irradiance, daylight length) are saved in the map history file. "
  212. "Alternatively, a local time can be specified to compute solar "
  213. "incidence angle and/or irradiance raster maps. The shadowing effect of "
  214. "the topography is optionally incorporated.");
  215. parm.elevin = G_define_option();
  216. parm.elevin->key = "elevation";
  217. parm.elevin->type = TYPE_STRING;
  218. parm.elevin->required = YES;
  219. parm.elevin->gisprompt = "old,cell,raster";
  220. parm.elevin->description =
  221. _("Name of the input elevation raster map [meters]");
  222. parm.elevin->guisection = _("Input");
  223. parm.aspin = G_define_option();
  224. parm.aspin->key = "aspect";
  225. parm.aspin->type = TYPE_STRING;
  226. parm.aspin->required = NO;
  227. parm.aspin->gisprompt = "old,cell,raster";
  228. parm.aspin->description =
  229. _("Name of the input aspect map (terrain aspect or azimuth of the solar panel) [decimal degrees]");
  230. parm.aspin->guisection = _("Input");
  231. parm.aspect = G_define_option();
  232. parm.aspect->key = "aspect_value";
  233. parm.aspect->type = TYPE_DOUBLE;
  234. parm.aspect->answer = ASPECT;
  235. parm.aspect->required = NO;
  236. parm.aspect->description =
  237. _("A single value of the orientation (aspect), 270 is south");
  238. parm.aspect->guisection = _("Input");
  239. parm.slopein = G_define_option();
  240. parm.slopein->key = "slope";
  241. parm.slopein->type = TYPE_STRING;
  242. parm.slopein->required = NO;
  243. parm.slopein->gisprompt = "old,cell,raster";
  244. parm.slopein->description =
  245. _("Name of the input slope raster map (terrain slope or solar panel inclination) [decimal degrees]");
  246. parm.slopein->guisection = _("Input");
  247. parm.slope = G_define_option();
  248. parm.slope->key = "slope_value";
  249. parm.slope->type = TYPE_DOUBLE;
  250. parm.slope->answer = SLOPE;
  251. parm.slope->required = NO;
  252. parm.slope->description = _("A single value of inclination (slope)");
  253. parm.slope->guisection = _("Input");
  254. parm.linkein = G_define_option();
  255. parm.linkein->key = "linke";
  256. parm.linkein->type = TYPE_STRING;
  257. parm.linkein->required = NO;
  258. parm.linkein->gisprompt = "old,cell,raster";
  259. parm.linkein->description =
  260. _("Name of the Linke atmospheric turbidity coefficient input raster map [-]");
  261. parm.linkein->guisection = _("Input");
  262. parm.lin = G_define_option();
  263. parm.lin->key = "linke_value";
  264. parm.lin->type = TYPE_DOUBLE;
  265. parm.lin->answer = LINKE;
  266. parm.lin->required = NO;
  267. parm.lin->description =
  268. _("A single value of the Linke atmospheric turbidity coefficient [-]");
  269. parm.lin->guisection = _("Input");
  270. parm.albedo = G_define_option();
  271. parm.albedo->key = "albedo";
  272. parm.albedo->type = TYPE_STRING;
  273. parm.albedo->required = NO;
  274. parm.albedo->gisprompt = "old,cell,raster";
  275. parm.albedo->description =
  276. _("Name of the ground albedo coefficient input raster map [-]");
  277. parm.albedo->guisection = _("Input");
  278. parm.alb = G_define_option();
  279. parm.alb->key = "albedo_value";
  280. parm.alb->type = TYPE_DOUBLE;
  281. parm.alb->answer = ALB;
  282. parm.alb->required = NO;
  283. parm.alb->description =
  284. _("A single value of the ground albedo coefficient [-]");
  285. parm.alb->guisection = _("Input");
  286. parm.latin = G_define_option();
  287. parm.latin->key = "lat";
  288. parm.latin->type = TYPE_STRING;
  289. parm.latin->required = NO;
  290. parm.latin->gisprompt = "old,cell,raster";
  291. parm.latin->description =
  292. _("Name of input raster map containing latitudes [decimal degrees]");
  293. parm.latin->guisection = _("Input");
  294. parm.longin = G_define_option();
  295. parm.longin->key = "long";
  296. parm.longin->type = TYPE_STRING;
  297. parm.longin->required = NO;
  298. parm.longin->gisprompt = "old,cell,raster";
  299. parm.longin->description =
  300. _("Name of input raster map containing longitudes [decimal degrees]");
  301. parm.longin->guisection = _("Input");
  302. parm.coefbh = G_define_option();
  303. parm.coefbh->key = "coeff_bh";
  304. parm.coefbh->type = TYPE_STRING;
  305. parm.coefbh->required = NO;
  306. parm.coefbh->gisprompt = "old,cell,raster";
  307. parm.coefbh->description =
  308. _("Name of real-sky beam radiation coefficient (thick cloud) input raster map [0-1]");
  309. parm.coefbh->guisection = _("Input");
  310. parm.coefdh = G_define_option();
  311. parm.coefdh->key = "coeff_dh";
  312. parm.coefdh->type = TYPE_STRING;
  313. parm.coefdh->required = NO;
  314. parm.coefdh->gisprompt = "old,cell,raster";
  315. parm.coefdh->description =
  316. _("Name of real-sky diffuse radiation coefficient (haze) input raster map [0-1]");
  317. parm.coefdh->guisection = _("Input");
  318. parm.horizon = G_define_standard_option(G_OPT_R_BASENAME_INPUT);
  319. parm.horizon->key = "horizon_basename";
  320. parm.horizon->required = NO;
  321. parm.horizon->gisprompt = "old,cell,raster";
  322. parm.horizon->description = _("The horizon information input map basename");
  323. parm.horizon->guisection = _("Input");
  324. parm.horizonstep = G_define_option();
  325. parm.horizonstep->key = "horizon_step";
  326. parm.horizonstep->type = TYPE_DOUBLE;
  327. parm.horizonstep->required = NO;
  328. parm.horizonstep->description =
  329. _("Angle step size for multidirectional horizon [degrees]");
  330. parm.horizonstep->guisection = _("Input");
  331. parm.incidout = G_define_option();
  332. parm.incidout->key = "incidout";
  333. parm.incidout->type = TYPE_STRING;
  334. parm.incidout->required = NO;
  335. parm.incidout->gisprompt = "new,cell,raster";
  336. parm.incidout->description =
  337. _("Output incidence angle raster map (mode 1 only)");
  338. parm.incidout->guisection = _("Output");
  339. parm.beam_rad = G_define_option();
  340. parm.beam_rad->key = "beam_rad";
  341. parm.beam_rad->type = TYPE_STRING;
  342. parm.beam_rad->required = NO;
  343. parm.beam_rad->gisprompt = "new,cell,raster";
  344. parm.beam_rad->description =
  345. _("Output beam irradiance [W.m-2] (mode 1) or irradiation raster map [Wh.m-2.day-1] (mode 2)");
  346. parm.beam_rad->guisection = _("Output");
  347. parm.diff_rad = G_define_option();
  348. parm.diff_rad->key = "diff_rad";
  349. parm.diff_rad->type = TYPE_STRING;
  350. parm.diff_rad->required = NO;
  351. parm.diff_rad->gisprompt = "new,cell,raster";
  352. parm.diff_rad->description =
  353. _("Output diffuse irradiance [W.m-2] (mode 1) or irradiation raster map [Wh.m-2.day-1] (mode 2)");
  354. parm.diff_rad->guisection = _("Output");
  355. parm.refl_rad = G_define_option();
  356. parm.refl_rad->key = "refl_rad";
  357. parm.refl_rad->type = TYPE_STRING;
  358. parm.refl_rad->required = NO;
  359. parm.refl_rad->gisprompt = "new,cell,raster";
  360. parm.refl_rad->description =
  361. _("Output ground reflected irradiance [W.m-2] (mode 1) or irradiation raster map [Wh.m-2.day-1] (mode 2)");
  362. parm.refl_rad->guisection = _("Output");
  363. parm.glob_rad = G_define_option();
  364. parm.glob_rad->key = "glob_rad";
  365. parm.glob_rad->type = TYPE_STRING;
  366. parm.glob_rad->required = NO;
  367. parm.glob_rad->gisprompt = "new,cell,raster";
  368. parm.glob_rad->description =
  369. _("Output global (total) irradiance/irradiation [W.m-2] (mode 1) or irradiance/irradiation raster map [Wh.m-2.day-1] (mode 2)");
  370. parm.glob_rad->guisection = _("Output");
  371. parm.insol_time = G_define_option();
  372. parm.insol_time->key = "insol_time";
  373. parm.insol_time->type = TYPE_STRING;
  374. parm.insol_time->required = NO;
  375. parm.insol_time->gisprompt = "new,cell,raster";
  376. parm.insol_time->description =
  377. _("Output insolation time raster map [h] (mode 2 only)");
  378. parm.insol_time->guisection = _("Output");
  379. parm.day = G_define_option();
  380. parm.day->key = "day";
  381. parm.day->type = TYPE_INTEGER;
  382. parm.day->required = YES;
  383. parm.day->description = _("No. of day of the year (1-365)");
  384. parm.day->options = "1-365";
  385. parm.day->guisection = _("Time");
  386. parm.step = G_define_option();
  387. parm.step->key = "step";
  388. parm.step->type = TYPE_DOUBLE;
  389. parm.step->answer = STEP;
  390. parm.step->required = NO;
  391. parm.step->description =
  392. _("Time step when computing all-day radiation sums [decimal hours]");
  393. parm.step->guisection = _("Time");
  394. parm.declin = G_define_option();
  395. parm.declin->key = "declination";
  396. parm.declin->type = TYPE_DOUBLE;
  397. parm.declin->required = NO;
  398. parm.declin->description =
  399. _("Declination value (overriding the internally computed value) [radians]");
  400. parm.ltime = G_define_option();
  401. parm.ltime->key = "time";
  402. parm.ltime->type = TYPE_DOUBLE;
  403. /* parm.ltime->answer = TIME; */
  404. parm.ltime->required = NO;
  405. parm.ltime->description =
  406. _("Local (solar) time (to be set for mode 1 only) [decimal hours]");
  407. parm.ltime->options = "0-24";
  408. parm.ltime->guisection = _("Time");
  409. /*
  410. * parm.startTime = G_define_option();
  411. * parm.startTime->key = "start_time";
  412. * parm.startTime->type = TYPE_DOUBLE;
  413. * parm.startTime->required = NO;
  414. * parm.startTime->description = _("Starting time for calculating results for several different times.");
  415. *
  416. * parm.endTime = G_define_option();
  417. * parm.endTime->key = "end_time";
  418. * parm.endTime->type = TYPE_DOUBLE;
  419. * parm.endTime->required = NO;
  420. * parm.endTime->description = _("End time for calculating results for several different times.)";
  421. */
  422. parm.dist = G_define_option();
  423. parm.dist->key = "distance_step";
  424. parm.dist->type = TYPE_DOUBLE;
  425. parm.dist->answer = DIST;
  426. parm.dist->required = NO;
  427. parm.dist->description =
  428. _("Sampling distance step coefficient (0.5-1.5)");
  429. parm.numPartitions = G_define_option();
  430. parm.numPartitions->key = "npartitions";
  431. parm.numPartitions->type = TYPE_INTEGER;
  432. parm.numPartitions->answer = NUM_PARTITIONS;
  433. parm.numPartitions->required = NO;
  434. parm.numPartitions->description =
  435. _("Read the input files in this number of chunks");
  436. parm.civilTime = G_define_option();
  437. parm.civilTime->key = "civil_time";
  438. parm.civilTime->type = TYPE_DOUBLE;
  439. parm.civilTime->required = NO;
  440. parm.civilTime->description =
  441. _("Civil time zone value, if none, the time will be local solar time");
  442. parm.civilTime->guisection = _("Time");
  443. flag.noshade = G_define_flag();
  444. flag.noshade->key = 'p';
  445. flag.noshade->description =
  446. _("Do not incorporate the shadowing effect of terrain");
  447. flag.saveMemory = G_define_flag();
  448. flag.saveMemory->key = 'm';
  449. flag.saveMemory->description =
  450. _("Use the low-memory version of the program");
  451. if (G_parser(argc, argv))
  452. exit(EXIT_FAILURE);
  453. G_get_set_window(&cellhd);
  454. gridGeom.stepx = cellhd.ew_res;
  455. gridGeom.stepy = cellhd.ns_res;
  456. invstepx = 1. / gridGeom.stepx;
  457. invstepy = 1. / gridGeom.stepy;
  458. n /*n_cols */ = cellhd.cols;
  459. m /*n_rows */ = cellhd.rows;
  460. xmin = cellhd.west;
  461. ymin = cellhd.south;
  462. xmax = cellhd.east;
  463. ymax = cellhd.north;
  464. gridGeom.deltx = fabs(cellhd.east - cellhd.west);
  465. gridGeom.delty = fabs(cellhd.north - cellhd.south);
  466. setUseShadow(!flag.noshade->answer);
  467. saveMemory = flag.saveMemory->answer;
  468. elevin = parm.elevin->answer;
  469. aspin = parm.aspin->answer;
  470. slopein = parm.slopein->answer;
  471. linkein = parm.linkein->answer;
  472. albedo = parm.albedo->answer;
  473. latin = parm.latin->answer;
  474. longin = parm.longin->answer;
  475. civiltime = parm.civilTime->answer;
  476. if (civiltime != NULL) {
  477. setUseCivilTime(TRUE);
  478. if (longin == NULL)
  479. G_fatal_error(
  480. _("You must give the longitude raster if you use civil time"));
  481. if (sscanf(parm.civilTime->answer, "%lf", &civilTime) != 1)
  482. G_fatal_error(_("Error reading civil time zone value"));
  483. if (civilTime < -24. || civilTime > 24.)
  484. G_fatal_error(_("Invalid civil time zone value"));
  485. /* Normalize if somebody should be weird enough to give more than +- 12
  486. * hours offset. */
  487. if (civilTime < -12.)
  488. civilTime += 24.;
  489. else if (civilTime > 12.)
  490. civilTime -= 24;
  491. }
  492. else {
  493. setUseCivilTime(FALSE);
  494. }
  495. coefbh = parm.coefbh->answer;
  496. coefdh = parm.coefdh->answer;
  497. incidout = parm.incidout->answer;
  498. horizon = parm.horizon->answer;
  499. setUseHorizonData(horizon != NULL);
  500. beam_rad = parm.beam_rad->answer;
  501. insol_time = parm.insol_time->answer;
  502. diff_rad = parm.diff_rad->answer;
  503. refl_rad = parm.refl_rad->answer;
  504. glob_rad = parm.glob_rad->answer;
  505. if ((insol_time != NULL) && (incidout != NULL))
  506. G_fatal_error(_("insol_time and incidout are incompatible options"));
  507. sscanf(parm.day->answer, "%d", &day);
  508. if (sscanf(parm.step->answer, "%lf", &step) != 1)
  509. G_fatal_error(_("Error reading time step size"));
  510. if (step <= 0.0 || step > 24.0)
  511. G_fatal_error(_("Invalid time step size"));
  512. if (parm.horizonstep->answer != NULL) {
  513. if (sscanf(parm.horizonstep->answer, "%lf", &horizonStep) != 1)
  514. G_fatal_error(_("Error reading horizon step size"));
  515. str_step = parm.horizonstep->answer;
  516. if (horizonStep > 0.)
  517. setHorizonInterval(deg2rad * horizonStep);
  518. else
  519. G_fatal_error(_("The horizon step size must be greater than 0."));
  520. }
  521. else if (useHorizonData()) {
  522. G_fatal_error(_("If you use the horizon option you must also set the 'horizonstep' parameter."));
  523. }
  524. ttime = parm.ltime->answer;
  525. if (parm.ltime->answer != NULL) {
  526. if (insol_time != NULL)
  527. G_fatal_error(_("Time and insol_time are incompatible options"));
  528. G_message(_("Mode 1: instantaneous solar incidence angle & irradiance using a set local time"));
  529. sscanf(parm.ltime->answer, "%lf", &timo);
  530. }
  531. else {
  532. if (incidout != NULL)
  533. G_fatal_error(_("incidout requires time parameter to be set"));
  534. G_message(_("Mode 2: integrated daily irradiation for a given day of the year"));
  535. }
  536. /*
  537. * if (parm.startTime->answer != NULL) sscanf(parm.startTime->answer, "%lf", &startTime);
  538. * if (parm.endTime->answer != NULL) sscanf(parm.endTime->answer, "%lf", &endTime);
  539. *
  540. * if((parm.startTime->answer != NULL) ||(parm.endTime->answer != NULL))
  541. * {
  542. */
  543. /* The start and end times should only be defined if the single
  544. * time is not defined, and if the step size *is* defined. */
  545. /*
  546. * if(parm.step->answer==NULL)
  547. * G_fatal_error("If you want to use a time interval you must also define a step size.");
  548. * if(parm.ltime->answer!=NULL)
  549. * G_fatal_error("If you want to use a time interval you can't define a single time value.\n");
  550. * if((parm.startTime->answer==NULL)||(parm.endTime->answer==NULL))
  551. * G_fatal_error("If you want to use a time interval both the start and end times must be defined.\n");
  552. * }
  553. */
  554. if (parm.linkein->answer == NULL){
  555. sscanf(parm.lin->answer, "%lf", &singleLinke);
  556. G_message(_("Using Linke constant: %lf"), singleLinke);
  557. } else {
  558. G_message(_("Using Linke map <%s>"), parm.linkein->answer);
  559. }
  560. if (parm.albedo->answer == NULL){
  561. sscanf(parm.alb->answer, "%lf", &singleAlbedo);
  562. G_message(_("Using albedo constant: %lf"), singleAlbedo);
  563. } else {
  564. G_message(_("Using albedo map <%s>"), parm.albedo->answer);
  565. }
  566. if (parm.slopein->answer == NULL){
  567. sscanf(parm.slope->answer, "%lf", &singleSlope);
  568. G_message(_("Using slope constant: %lf"), singleSlope);
  569. singleSlope *= deg2rad;
  570. } else {
  571. G_message(_("Using slope map <%s>"), parm.slopein->answer);
  572. }
  573. if (parm.aspin->answer == NULL){
  574. sscanf(parm.aspect->answer, "%lf", &singleAspect);
  575. G_message(_("Using aspect constant: %lf"), singleAspect);
  576. singleAspect *= deg2rad;
  577. } else {
  578. G_message(_("Using aspect map <%s>"), parm.aspin->answer);
  579. }
  580. if (parm.coefbh->answer == NULL)
  581. cbh = BSKY;
  582. if (parm.coefdh->answer == NULL)
  583. cdh = DSKY;
  584. sscanf(parm.dist->answer, "%lf", &dist);
  585. if (parm.numPartitions->answer != NULL) {
  586. sscanf(parm.numPartitions->answer, "%d", &numPartitions);
  587. if (useShadow() && (!useHorizonData()) && (numPartitions != 1)) {
  588. /* If you calculate shadows on the fly, the number of partitions
  589. * must be one.
  590. */
  591. G_fatal_error(_("If you use -s and no horizon rasters, numpartitions must be =1"));
  592. }
  593. }
  594. gridGeom.stepxy = dist * 0.5 * (gridGeom.stepx + gridGeom.stepy);
  595. TOLER = gridGeom.stepxy * EPS;
  596. /* The save memory scheme will not work if you want to calculate shadows
  597. * on the fly. If you calculate without shadow effects or if you have the
  598. * shadows pre-calculated, there is no problem. */
  599. if (saveMemory && useShadow() && (!useHorizonData()))
  600. G_fatal_error(
  601. _("If you want to save memory and to use shadows, "
  602. "you must use pre-calculated horizons."));
  603. if (parm.declin->answer == NULL)
  604. declination = com_declin(day);
  605. else {
  606. sscanf(parm.declin->answer, "%lf", &declin);
  607. declination = -declin;
  608. }
  609. if (ttime != 0) {
  610. /* Shadow for just one time during the day */
  611. if (horizon == NULL) {
  612. arrayNumInt = 1;
  613. }
  614. else if (useHorizonData()) {
  615. arrayNumInt = (int)(360. / horizonStep);
  616. }
  617. }
  618. else {
  619. if (useHorizonData()) {
  620. /* Number of bytes holding the horizon information */
  621. arrayNumInt = (int)(360. / horizonStep);
  622. }
  623. }
  624. if (ttime != NULL) {
  625. tim = (timo - 12) * 15;
  626. /* converting to degrees */
  627. /* Jenco (12-timeAngle) * 15 */
  628. if (tim < 0)
  629. tim += 360;
  630. tim = M_PI * tim / 180;
  631. /* conv. to radians */
  632. }
  633. /* Set up parameters for projection to lat/long if necessary */
  634. /* we need to do this even if latin= and longin= were given because
  635. rsunlib's com_par() needs iproj and oproj */
  636. if ((G_projection() != PROJECTION_LL)) {
  637. struct Key_Value *in_proj_info, *in_unit_info;
  638. if ((in_proj_info = G_get_projinfo()) == NULL)
  639. G_fatal_error(
  640. _("Can't get projection info of current location"));
  641. if ((in_unit_info = G_get_projunits()) == NULL)
  642. G_fatal_error(
  643. _("Can't get projection units of current location"));
  644. if (pj_get_kv(&iproj, in_proj_info, in_unit_info) < 0)
  645. G_fatal_error(
  646. _("Can't get projection key values of current location"));
  647. G_free_key_value(in_proj_info);
  648. G_free_key_value(in_unit_info);
  649. /* Set output projection to latlong w/ same ellipsoid */
  650. oproj.zone = 0;
  651. oproj.meters = 1.;
  652. sprintf(oproj.proj, "ll");
  653. if ((oproj.pj = pj_latlong_from_proj(iproj.pj)) == NULL)
  654. G_fatal_error(_("Unable to set up lat/long projection parameters"));
  655. }
  656. if ((latin != NULL || longin != NULL) && (G_projection() == PROJECTION_LL))
  657. G_warning(_("latin and longin raster maps have no effect when in a Lat/Lon location"));
  658. /* true about longin= when civiltime is used? */
  659. /* civiltime needs longin= but not latin= for non-LL projections -
  660. better would be it just use pj_proj() if it needs those?? */
  661. if (latin != NULL && longin == NULL)
  662. G_fatal_error(_("Both latin and longin raster maps must be given, or neither"));
  663. /**********end of parser - ******************************/
  664. if ((G_projection() == PROJECTION_LL))
  665. ll_correction = TRUE;
  666. G_debug(3, "calculate() starts...");
  667. calculate(singleSlope, singleAspect, singleAlbedo, singleLinke, gridGeom);
  668. G_debug(3, "OUTGR() starts...");
  669. OUTGR();
  670. exit(EXIT_SUCCESS);
  671. }
  672. int INPUT_part(int offset, double *zmax)
  673. {
  674. int finalRow, rowrevoffset;
  675. int numRows;
  676. int numDigits;
  677. FCELL *cell1 = NULL, *cell2 = NULL;
  678. FCELL *cell3 = NULL, *cell4 = NULL, *cell5 = NULL, *cell6 = NULL, *cell7 =
  679. NULL;
  680. FCELL *rast1 = NULL, *rast2 = NULL;
  681. static FCELL **horizonbuf;
  682. unsigned char *horizonpointer;
  683. int fd1 = -1, fd2 = -1, fd3 = -1, fd4 = -1, fd5 = -1, fd6 = -1,
  684. fd7 = -1, row, row_rev;
  685. static int *fd_shad;
  686. int fr1 = -1, fr2 = -1;
  687. int l, i, j;
  688. char *shad_filename;
  689. char formatString[10];
  690. double angle_deg = 0.;
  691. finalRow = m - offset - m / numPartitions;
  692. if (finalRow < 0) {
  693. finalRow = 0;
  694. }
  695. numRows = m / numPartitions;
  696. cell1 = Rast_allocate_f_buf();
  697. if (z == NULL) {
  698. z = (float **)G_malloc(sizeof(float *) * (numRows));
  699. for (l = 0; l < numRows; l++) {
  700. z[l] = (float *)G_malloc(sizeof(float) * (n));
  701. }
  702. }
  703. fd1 = Rast_open_old(elevin, "");
  704. if (slopein != NULL) {
  705. cell3 = Rast_allocate_f_buf();
  706. if (s == NULL) {
  707. s = (float **)G_malloc(sizeof(float *) * (numRows));
  708. for (l = 0; l < numRows; l++) {
  709. s[l] = (float *)G_malloc(sizeof(float) * (n));
  710. }
  711. }
  712. fd3 = Rast_open_old(slopein, "");
  713. }
  714. if (aspin != NULL) {
  715. cell2 = Rast_allocate_f_buf();
  716. if (o == NULL) {
  717. o = (float **)G_malloc(sizeof(float *) * (numRows));
  718. for (l = 0; l < numRows; l++) {
  719. o[l] = (float *)G_malloc(sizeof(float) * (n));
  720. }
  721. }
  722. fd2 = Rast_open_old(aspin, "");
  723. }
  724. if (linkein != NULL) {
  725. cell4 = Rast_allocate_f_buf();
  726. if (li == NULL) {
  727. li = (float **)G_malloc(sizeof(float *) * (numRows));
  728. for (l = 0; l < numRows; l++)
  729. li[l] = (float *)G_malloc(sizeof(float) * (n));
  730. }
  731. fd4 = Rast_open_old(linkein, "");
  732. }
  733. if (albedo != NULL) {
  734. cell5 = Rast_allocate_f_buf();
  735. if (a == NULL) {
  736. a = (float **)G_malloc(sizeof(float *) * (numRows));
  737. for (l = 0; l < numRows; l++)
  738. a[l] = (float *)G_malloc(sizeof(float) * (n));
  739. }
  740. fd5 = Rast_open_old(albedo, "");
  741. }
  742. if (latin != NULL) {
  743. cell6 = Rast_allocate_f_buf();
  744. if (latitudeArray == NULL) {
  745. latitudeArray = (float **)G_malloc(sizeof(float *) * (numRows));
  746. for (l = 0; l < numRows; l++)
  747. latitudeArray[l] = (float *)G_malloc(sizeof(float) * (n));
  748. }
  749. fd6 = Rast_open_old(latin, "");
  750. }
  751. if (longin != NULL) {
  752. cell7 = Rast_allocate_f_buf();
  753. longitudeArray = (float **)G_malloc(sizeof(float *) * (numRows));
  754. for (l = 0; l < numRows; l++)
  755. longitudeArray[l] = (float *)G_malloc(sizeof(float) * (n));
  756. fd7 = Rast_open_old(longin, "");
  757. }
  758. if (coefbh != NULL) {
  759. rast1 = Rast_allocate_f_buf();
  760. if (cbhr == NULL) {
  761. cbhr = (float **)G_malloc(sizeof(float *) * (numRows));
  762. for (l = 0; l < numRows; l++)
  763. cbhr[l] = (float *)G_malloc(sizeof(float) * (n));
  764. }
  765. fr1 = Rast_open_old(coefbh, "");
  766. }
  767. if (coefdh != NULL) {
  768. rast2 = Rast_allocate_f_buf();
  769. if (cdhr == NULL) {
  770. cdhr = (float **)G_malloc(sizeof(float *) * (numRows));
  771. for (l = 0; l < numRows; l++)
  772. cdhr[l] = (float *)G_malloc(sizeof(float) * (n));
  773. }
  774. fr2 = Rast_open_old(coefdh, "");
  775. }
  776. if (useHorizonData()) {
  777. if (horizonarray == NULL) {
  778. horizonarray =
  779. (unsigned char *)G_malloc(sizeof(char) * arrayNumInt *
  780. numRows * n);
  781. horizonbuf = (FCELL **) G_malloc(sizeof(FCELL *) * arrayNumInt);
  782. fd_shad = (int *)G_malloc(sizeof(int) * arrayNumInt);
  783. }
  784. /*
  785. * if(ttime != NULL)
  786. * {
  787. *
  788. * horizonbuf[0]=Rast_allocate_f_buf();
  789. * sprintf(shad_filename, "%s_%02d", horizon, arrayNumInt);
  790. * if((mapset=G_find_raster2(shad_filename,""))==NULL)
  791. * G_message("Horizon file no. %d not found\n", arrayNumInt);
  792. *
  793. * fd_shad[0] = Rast_open_old(shad_filename,mapset);
  794. * }
  795. * else
  796. * {
  797. */
  798. decimals = G_get_num_decimals(str_step);
  799. angle_deg = 0;
  800. for (i = 0; i < arrayNumInt; i++) {
  801. horizonbuf[i] = Rast_allocate_f_buf();
  802. shad_filename = G_generate_basename(horizon, angle_deg,
  803. 3, decimals);
  804. fd_shad[i] = Rast_open_old(shad_filename, "");
  805. angle_deg += horizonStep;
  806. G_free(shad_filename);
  807. }
  808. /*
  809. numDigits = (int)(log10(1. * arrayNumInt)) + 1;
  810. sprintf(formatString, "%%s_%%0%dd", numDigits);
  811. for (i = 0; i < arrayNumInt; i++) {
  812. horizonbuf[i] = Rast_allocate_f_buf();
  813. sprintf(shad_filename, formatString, horizon, i);
  814. fd_shad[i] = Rast_open_old(shad_filename, "");
  815. } */
  816. }
  817. /*
  818. * }
  819. */
  820. if (useHorizonData()) {
  821. for (i = 0; i < arrayNumInt; i++) {
  822. for (row = m - offset - 1; row >= finalRow; row--) {
  823. row_rev = m - row - 1;
  824. rowrevoffset = row_rev - offset;
  825. Rast_get_f_row(fd_shad[i], horizonbuf[i], row);
  826. horizonpointer =
  827. horizonarray + (ssize_t) arrayNumInt *n * rowrevoffset;
  828. for (j = 0; j < n; j++) {
  829. horizonpointer[i] = (char)(rint(SCALING_FACTOR *
  830. AMIN1(horizonbuf[i][j],
  831. 256 * invScale)));
  832. horizonpointer += arrayNumInt;
  833. }
  834. }
  835. }
  836. }
  837. for (row = m - offset - 1; row >= finalRow; row--) {
  838. Rast_get_f_row(fd1, cell1, row);
  839. if (aspin != NULL)
  840. Rast_get_f_row(fd2, cell2, row);
  841. if (slopein != NULL)
  842. Rast_get_f_row(fd3, cell3, row);
  843. if (linkein != NULL)
  844. Rast_get_f_row(fd4, cell4, row);
  845. if (albedo != NULL)
  846. Rast_get_f_row(fd5, cell5, row);
  847. if (latin != NULL)
  848. Rast_get_f_row(fd6, cell6, row);
  849. if (longin != NULL)
  850. Rast_get_f_row(fd7, cell7, row);
  851. if (coefbh != NULL)
  852. Rast_get_f_row(fr1, rast1, row);
  853. if (coefdh != NULL)
  854. Rast_get_f_row(fr2, rast2, row);
  855. row_rev = m - row - 1;
  856. rowrevoffset = row_rev - offset;
  857. for (j = 0; j < n; j++) {
  858. if (!Rast_is_f_null_value(cell1 + j))
  859. z[rowrevoffset][j] = (float)cell1[j];
  860. else
  861. z[rowrevoffset][j] = UNDEFZ;
  862. if (aspin != NULL) {
  863. if (!Rast_is_f_null_value(cell2 + j))
  864. o[rowrevoffset][j] = (float)cell2[j];
  865. else
  866. o[rowrevoffset][j] = UNDEFZ;
  867. }
  868. if (slopein != NULL) {
  869. if (!Rast_is_f_null_value(cell3 + j))
  870. s[rowrevoffset][j] = (float)cell3[j];
  871. else
  872. s[rowrevoffset][j] = UNDEFZ;
  873. }
  874. if (linkein != NULL) {
  875. if (!Rast_is_f_null_value(cell4 + j))
  876. li[rowrevoffset][j] = (float)cell4[j];
  877. else
  878. li[rowrevoffset][j] = UNDEFZ;
  879. }
  880. if (albedo != NULL) {
  881. if (!Rast_is_f_null_value(cell5 + j))
  882. a[rowrevoffset][j] = (float)cell5[j];
  883. else
  884. a[rowrevoffset][j] = UNDEFZ;
  885. }
  886. if (latin != NULL) {
  887. if (!Rast_is_f_null_value(cell6 + j))
  888. latitudeArray[rowrevoffset][j] = (float)cell6[j];
  889. else
  890. latitudeArray[rowrevoffset][j] = UNDEFZ;
  891. }
  892. if (longin != NULL) {
  893. if (!Rast_is_f_null_value(cell7 + j))
  894. longitudeArray[rowrevoffset][j] = (float)cell7[j];
  895. else
  896. longitudeArray[rowrevoffset][j] = UNDEFZ;
  897. }
  898. if (coefbh != NULL) {
  899. if (!Rast_is_f_null_value(rast1 + j))
  900. cbhr[rowrevoffset][j] = (float)rast1[j];
  901. else
  902. cbhr[rowrevoffset][j] = UNDEFZ;
  903. }
  904. if (coefdh != NULL) {
  905. if (!Rast_is_f_null_value(rast2 + j))
  906. cdhr[rowrevoffset][j] = (float)rast2[j];
  907. else
  908. cdhr[rowrevoffset][j] = UNDEFZ;
  909. }
  910. }
  911. }
  912. Rast_close(fd1);
  913. G_free(cell1);
  914. if (aspin != NULL) {
  915. G_free(cell2);
  916. Rast_close(fd2);
  917. }
  918. if (slopein != NULL) {
  919. G_free(cell3);
  920. Rast_close(fd3);
  921. }
  922. if (linkein != NULL) {
  923. G_free(cell4);
  924. Rast_close(fd4);
  925. }
  926. if (albedo != NULL) {
  927. G_free(cell5);
  928. Rast_close(fd5);
  929. }
  930. if (latin != NULL) {
  931. G_free(cell6);
  932. Rast_close(fd6);
  933. }
  934. if (longin != NULL) {
  935. G_free(cell7);
  936. Rast_close(fd7);
  937. }
  938. if (coefbh != NULL) {
  939. G_free(rast1);
  940. Rast_close(fr1);
  941. }
  942. if (coefdh != NULL) {
  943. G_free(rast2);
  944. Rast_close(fr2);
  945. }
  946. if (useHorizonData()) {
  947. for (i = 0; i < arrayNumInt; i++) {
  948. Rast_close(fd_shad[i]);
  949. G_free(horizonbuf[i]);
  950. }
  951. }
  952. /*******transformation of angles from 0 to east counterclock
  953. to 0 to north clocwise, for ori=0 upslope flowlines
  954. turn the orientation 2*M_PI ************/
  955. /* needs to be eliminated */
  956. /*for (i = 0; i < m; ++i) */
  957. for (i = 0; i < numRows; i++) {
  958. for (j = 0; j < n; j++) {
  959. *zmax = AMAX1(*zmax, z[i][j]);
  960. if (aspin != NULL) {
  961. if (o[i][j] != 0.) {
  962. if (o[i][j] < 90.)
  963. o[i][j] = 90. - o[i][j];
  964. else
  965. o[i][j] = 450. - o[i][j];
  966. }
  967. /* G_debug(3,"o,z = %d %d i,j, %d %d \n", o[i][j],z[i][j],i,j); */
  968. if ((aspin != NULL) && o[i][j] == UNDEFZ)
  969. z[i][j] = UNDEFZ;
  970. if ((slopein != NULL) && s[i][j] == UNDEFZ)
  971. z[i][j] = UNDEFZ;
  972. if (linkein != NULL && li[i][j] == UNDEFZ)
  973. z[i][j] = UNDEFZ;
  974. if (albedo != NULL && a[i][j] == UNDEFZ)
  975. z[i][j] = UNDEFZ;
  976. if (latin != NULL && latitudeArray[i][j] == UNDEFZ)
  977. z[i][j] = UNDEFZ;
  978. if (coefbh != NULL && cbhr[i][j] == UNDEFZ)
  979. z[i][j] = UNDEFZ;
  980. if (coefdh != NULL && cdhr[i][j] == UNDEFZ)
  981. z[i][j] = UNDEFZ;
  982. }
  983. }
  984. }
  985. return 1;
  986. }
  987. int OUTGR(void)
  988. {
  989. FCELL *cell7 = NULL, *cell8 = NULL, *cell9 = NULL, *cell10 =
  990. NULL, *cell11 = NULL, *cell12 = NULL;
  991. int fd7 = -1, fd8 = -1, fd9 = -1, fd10 = -1, fd11 = -1, fd12 = -1;
  992. int i, iarc, j;
  993. if (incidout != NULL) {
  994. cell7 = Rast_allocate_f_buf();
  995. fd7 = Rast_open_fp_new(incidout);
  996. }
  997. if (beam_rad != NULL) {
  998. cell8 = Rast_allocate_f_buf();
  999. fd8 = Rast_open_fp_new(beam_rad);
  1000. }
  1001. if (insol_time != NULL) {
  1002. cell11 = Rast_allocate_f_buf();
  1003. fd11 = Rast_open_fp_new(insol_time);
  1004. }
  1005. if (diff_rad != NULL) {
  1006. cell9 = Rast_allocate_f_buf();
  1007. fd9 = Rast_open_fp_new(diff_rad);
  1008. }
  1009. if (refl_rad != NULL) {
  1010. cell10 = Rast_allocate_f_buf();
  1011. fd10 = Rast_open_fp_new(refl_rad);
  1012. }
  1013. if (glob_rad != NULL) {
  1014. cell12 = Rast_allocate_f_buf();
  1015. fd12 = Rast_open_fp_new(glob_rad);
  1016. }
  1017. if (m != Rast_window_rows())
  1018. G_fatal_error("OOPS: rows changed from %d to %d", m, Rast_window_rows());
  1019. if (n != Rast_window_cols())
  1020. G_fatal_error("OOPS: cols changed from %d to %d", n, Rast_window_cols());
  1021. for (iarc = 0; iarc < m; iarc++) {
  1022. i = m - iarc - 1;
  1023. if (incidout != NULL) {
  1024. for (j = 0; j < n; j++) {
  1025. if (lumcl[i][j] == UNDEFZ)
  1026. Rast_set_f_null_value(cell7 + j, 1);
  1027. else
  1028. cell7[j] = (FCELL) lumcl[i][j];
  1029. }
  1030. Rast_put_f_row(fd7, cell7);
  1031. }
  1032. if (beam_rad != NULL) {
  1033. for (j = 0; j < n; j++) {
  1034. if (beam[i][j] == UNDEFZ)
  1035. Rast_set_f_null_value(cell8 + j, 1);
  1036. else
  1037. cell8[j] = (FCELL) beam[i][j];
  1038. }
  1039. Rast_put_f_row(fd8, cell8);
  1040. }
  1041. if (glob_rad != NULL) {
  1042. for (j = 0; j < n; j++) {
  1043. if (globrad[i][j] == UNDEFZ)
  1044. Rast_set_f_null_value(cell12 + j, 1);
  1045. else
  1046. cell12[j] = (FCELL) globrad[i][j];
  1047. }
  1048. Rast_put_f_row(fd12, cell12);
  1049. }
  1050. if (insol_time != NULL) {
  1051. for (j = 0; j < n; j++) {
  1052. if (insol[i][j] == UNDEFZ)
  1053. Rast_set_f_null_value(cell11 + j, 1);
  1054. else
  1055. cell11[j] = (FCELL) insol[i][j];
  1056. }
  1057. Rast_put_f_row(fd11, cell11);
  1058. }
  1059. if (diff_rad != NULL) {
  1060. for (j = 0; j < n; j++) {
  1061. if (diff[i][j] == UNDEFZ)
  1062. Rast_set_f_null_value(cell9 + j, 1);
  1063. else
  1064. cell9[j] = (FCELL) diff[i][j];
  1065. }
  1066. Rast_put_f_row(fd9, cell9);
  1067. }
  1068. if (refl_rad != NULL) {
  1069. for (j = 0; j < n; j++) {
  1070. if (refl[i][j] == UNDEFZ)
  1071. Rast_set_f_null_value(cell10 + j, 1);
  1072. else
  1073. cell10[j] = (FCELL) refl[i][j];
  1074. }
  1075. Rast_put_f_row(fd10, cell10);
  1076. }
  1077. }
  1078. if (incidout != NULL) {
  1079. Rast_close(fd7);
  1080. Rast_write_history(incidout, &hist);
  1081. }
  1082. if (beam_rad != NULL) {
  1083. Rast_close(fd8);
  1084. Rast_write_history(beam_rad, &hist);
  1085. }
  1086. if (diff_rad != NULL) {
  1087. Rast_close(fd9);
  1088. Rast_write_history(diff_rad, &hist);
  1089. }
  1090. if (refl_rad != NULL) {
  1091. Rast_close(fd10);
  1092. Rast_write_history(refl_rad, &hist);
  1093. }
  1094. if (insol_time != NULL) {
  1095. Rast_close(fd11);
  1096. Rast_write_history(insol_time, &hist);
  1097. }
  1098. if (glob_rad != NULL) {
  1099. Rast_close(fd12);
  1100. Rast_write_history(glob_rad, &hist);
  1101. }
  1102. return 1;
  1103. }
  1104. /**********************************************************/
  1105. void joules2(struct SunGeometryConstDay *sunGeom,
  1106. struct SunGeometryVarDay *sunVarGeom,
  1107. struct SunGeometryVarSlope *sunSlopeGeom,
  1108. struct SolarRadVar *sunRadVar,
  1109. struct GridGeometry *gridGeom, unsigned char *horizonpointer,
  1110. double latitude, double longitude)
  1111. {
  1112. double s0, dfr, dfr_rad;
  1113. double ra, dra;
  1114. int ss = 1;
  1115. double firstTime;
  1116. double firstAngle, lastAngle;
  1117. int srStepNo;
  1118. double bh;
  1119. double rr;
  1120. beam_e = 0.;
  1121. diff_e = 0.;
  1122. refl_e = 0.;
  1123. insol_t = 0.;
  1124. com_par(sunGeom, sunVarGeom, gridGeom, latitude, longitude);
  1125. if (ttime != NULL) { /*irradiance */
  1126. s0 = lumcline2(sunGeom, sunVarGeom, sunSlopeGeom, gridGeom,
  1127. horizonpointer);
  1128. if (sunVarGeom->solarAltitude > 0.) {
  1129. if ((!sunVarGeom->isShadow) && (s0 > 0.)) {
  1130. ra = brad(s0, &bh, sunVarGeom, sunSlopeGeom, sunRadVar); /* beam radiation */
  1131. beam_e += ra;
  1132. }
  1133. else {
  1134. beam_e = 0.;
  1135. bh = 0.;
  1136. }
  1137. if ((diff_rad != NULL) || (glob_rad != NULL)) {
  1138. dra = drad(s0, bh, &rr, sunVarGeom, sunSlopeGeom, sunRadVar); /* diffuse rad. */
  1139. diff_e += dra;
  1140. }
  1141. if ((refl_rad != NULL) || (glob_rad != NULL)) {
  1142. if ((diff_rad == NULL) && (glob_rad == NULL))
  1143. drad(s0, bh, &rr, sunVarGeom, sunSlopeGeom, sunRadVar);
  1144. refl_e += rr; /* reflected rad. */
  1145. }
  1146. } /* solarAltitude */
  1147. }
  1148. else {
  1149. /* all-day radiation */
  1150. srStepNo = (int)(sunGeom->sunrise_time / step);
  1151. if ((sunGeom->sunrise_time - srStepNo * step) > 0.5 * step) {
  1152. firstTime = (srStepNo + 1.5) * step;
  1153. }
  1154. else {
  1155. firstTime = (srStepNo + 0.5) * step;
  1156. }
  1157. firstAngle = (firstTime - 12) * HOURANGLE;
  1158. lastAngle = (sunGeom->sunset_time - 12) * HOURANGLE;
  1159. dfr_rad = step * HOURANGLE;
  1160. sunGeom->timeAngle = firstAngle;
  1161. varCount_global = 0;
  1162. dfr = step;
  1163. while (ss == 1) {
  1164. com_par(sunGeom, sunVarGeom, gridGeom, latitude, longitude);
  1165. s0 = lumcline2(sunGeom, sunVarGeom, sunSlopeGeom, gridGeom,
  1166. horizonpointer);
  1167. if (sunVarGeom->solarAltitude > 0.) {
  1168. if ((!sunVarGeom->isShadow) && (s0 > 0.)) {
  1169. insol_t += dfr;
  1170. ra = brad(s0, &bh, sunVarGeom, sunSlopeGeom, sunRadVar);
  1171. beam_e += dfr * ra;
  1172. ra = 0.;
  1173. }
  1174. else {
  1175. bh = 0.;
  1176. }
  1177. if ((diff_rad != NULL) || (glob_rad != NULL)) {
  1178. dra =
  1179. drad(s0, bh, &rr, sunVarGeom, sunSlopeGeom,
  1180. sunRadVar);
  1181. diff_e += dfr * dra;
  1182. dra = 0.;
  1183. }
  1184. if ((refl_rad != NULL) || (glob_rad != NULL)) {
  1185. if ((diff_rad == NULL) && (glob_rad == NULL)) {
  1186. drad(s0, bh, &rr, sunVarGeom, sunSlopeGeom,
  1187. sunRadVar);
  1188. }
  1189. refl_e += dfr * rr;
  1190. rr = 0.;
  1191. }
  1192. } /* illuminated */
  1193. sunGeom->timeAngle = sunGeom->timeAngle + dfr_rad;
  1194. if (sunGeom->timeAngle > lastAngle) {
  1195. ss = 0; /* we've got the sunset */
  1196. }
  1197. } /* end of while */
  1198. } /* all-day radiation */
  1199. }
  1200. /*////////////////////////////////////////////////////////////////////// */
  1201. /*
  1202. * void where_is_point(void)
  1203. * {
  1204. * double sx, sy;
  1205. * double dx, dy;
  1206. * double adx, ady;
  1207. * int i, j;
  1208. *
  1209. * sx = xx0 * invstepx + TOLER;
  1210. * sy = yy0 * invstepy + TOLER;
  1211. *
  1212. * i = (int)sx;
  1213. * j = (int)sy;
  1214. * if (i < n - 1 && j < m - 1) {
  1215. *
  1216. * dx = xx0 - (double)i *stepx;
  1217. * dy = yy0 - (double)j *stepy;
  1218. *
  1219. * adx = fabs(dx);
  1220. * ady = fabs(dy);
  1221. *
  1222. * if ((adx > TOLER) && (ady > TOLER)) {
  1223. * cube(j, i);
  1224. * return;
  1225. * }
  1226. * else if ((adx > TOLER) && (ady < TOLER)) {
  1227. * line_x(j, i);
  1228. * return;
  1229. * }
  1230. * else if ((adx < TOLER) && (ady > TOLER)) {
  1231. * line_y(j, i);
  1232. * return;
  1233. * }
  1234. * else if ((adx < TOLER) && (ady < TOLER)) {
  1235. * vertex(j, i);
  1236. * return;
  1237. * }
  1238. *
  1239. *
  1240. * }
  1241. * else {
  1242. * func = NULL;
  1243. * }
  1244. * }
  1245. *
  1246. */
  1247. void where_is_point(double *length, struct SunGeometryVarDay *sunVarGeom,
  1248. struct GridGeometry *gridGeom)
  1249. {
  1250. double sx, sy;
  1251. double dx, dy;
  1252. /* double adx, ady; */
  1253. int i, j;
  1254. sx = gridGeom->xx0 * invstepx + offsetx; /* offset 0.5 cell size to get the right cell i, j */
  1255. sy = gridGeom->yy0 * invstepy + offsety;
  1256. i = (int)sx;
  1257. j = (int)sy;
  1258. /* if (i < n-1 && j < m-1) { to include last row/col */
  1259. if (i <= n - 1 && j <= m - 1) {
  1260. dx = (double)i *gridGeom->stepx;
  1261. dy = (double)j *gridGeom->stepy;
  1262. *length = distance(gridGeom->xg0, dx, gridGeom->yg0, dy); /* dist from orig. grid point to the current grid point */
  1263. sunVarGeom->zp = z[j][i];
  1264. /*
  1265. * cube(j, i);
  1266. */
  1267. }
  1268. }
  1269. /*
  1270. * void vertex(jmin, imin)
  1271. * int jmin, imin;
  1272. * {
  1273. * zp = z[jmin][imin];
  1274. * if ((zp == UNDEFZ))
  1275. * func = NULL;
  1276. * }
  1277. * void line_x(jmin, imin)
  1278. * int jmin, imin;
  1279. * {
  1280. * double c1, c2;
  1281. * double d1, d2, e1, e2;
  1282. * e1 = (double)imin *stepx;
  1283. * e2 = (double)(imin + 1) * stepx;
  1284. *
  1285. * c1 = z[jmin][imin];
  1286. * c2 = z[jmin][imin + 1];
  1287. * if (!((c1 == UNDEFZ) || (c2 == UNDEFZ))) {
  1288. *
  1289. * if (dist <= 1.0) {
  1290. * d1 = (xx0 - e1) / (e2 - e1);
  1291. * d2 = 1 - d1;
  1292. * if (d1 < d2)
  1293. * zp = c1;
  1294. * else
  1295. * zp = c2;
  1296. * }
  1297. *
  1298. * if (dist > 1.0)
  1299. * zp = AMAX1(c1, c2);
  1300. * }
  1301. * else
  1302. * func = NULL;
  1303. * }
  1304. *
  1305. *
  1306. * void line_y(jmin, imin)
  1307. * int jmin, imin;
  1308. * {
  1309. * double c1, c2;
  1310. * double d1, d2, e1, e2;
  1311. * e1 = (double)jmin *stepy;
  1312. * e2 = (double)(jmin + 1) * stepy;
  1313. *
  1314. * c1 = z[jmin][imin];
  1315. * c2 = z[jmin + 1][imin];
  1316. * if (!((c1 == UNDEFZ) || (c2 == UNDEFZ))) {
  1317. *
  1318. * if (dist <= 1.0) {
  1319. * d1 = (yy0 - e1) / (e2 - e1);
  1320. * d2 = 1 - d1;
  1321. * if (d1 < d2)
  1322. * zp = c1;
  1323. * else
  1324. * zp = c2;
  1325. * }
  1326. *
  1327. * if (dist > 1.0)
  1328. * zp = AMAX1(c1, c2);
  1329. *
  1330. * }
  1331. * else
  1332. * func = NULL;
  1333. *
  1334. * }
  1335. *
  1336. * void cube(jmin, imin)
  1337. * int jmin, imin;
  1338. * {
  1339. * int i, ig = 0;
  1340. * double x1, x2, y1, y2;
  1341. * double v[4], vmin = BIG;
  1342. * double c[4], cmax = -BIG;
  1343. *
  1344. * x1 = (double)imin *stepx;
  1345. * x2 = x1 + stepx;
  1346. *
  1347. * y1 = (double)jmin *stepy;
  1348. * y2 = y1 + stepy;
  1349. *
  1350. * v[0] = DISTANCE2(x1, y1);
  1351. *
  1352. * if (v[0] < vmin) {
  1353. * ig = 0;
  1354. * vmin = v[0];
  1355. * }
  1356. * v[1] = DISTANCE2(x2, y1);
  1357. *
  1358. * if (v[1] < vmin) {
  1359. * ig = 1;
  1360. * vmin = v[1];
  1361. * }
  1362. *
  1363. * v[2] = DISTANCE2(x2, y2);
  1364. * if (v[2] < vmin) {
  1365. * ig = 2;
  1366. * vmin = v[2];
  1367. * }
  1368. *
  1369. * v[3] = DISTANCE2(x1, y2);
  1370. * if (v[3] < vmin) {
  1371. * ig = 3;
  1372. * vmin = v[3];
  1373. * }
  1374. *
  1375. * c[0] = z[jmin][imin];
  1376. * c[1] = z[jmin][imin + 1];
  1377. * c[2] = z[jmin + 1][imin + 1];
  1378. * c[3] = z[jmin + 1][imin];
  1379. *
  1380. *
  1381. * if (dist <= 1.0) {
  1382. *
  1383. * if (c[ig] != UNDEFZ)
  1384. * zp = c[ig];
  1385. * else
  1386. * func = NULL;
  1387. * return;
  1388. * }
  1389. *
  1390. * if (dist > 1.0) {
  1391. * for (i = 0; i < 4; i++) {
  1392. * if (c[i] != UNDEFZ) {
  1393. * cmax = AMAX1(cmax, c[i]);
  1394. * zp = cmax;
  1395. * }
  1396. * else
  1397. * func = NULL;
  1398. * }
  1399. * }
  1400. * }
  1401. */
  1402. /*
  1403. * void cube(jmin, imin)
  1404. * int jmin, imin;
  1405. * {
  1406. * zp = z[jmin][imin];
  1407. *
  1408. * }
  1409. */
  1410. void cube(jmin, imin)
  1411. {
  1412. }
  1413. /*////////////////////////////////////////////////////////////////////// */
  1414. void calculate(double singleSlope, double singleAspect, double singleAlbedo,
  1415. double singleLinke, struct GridGeometry gridGeom)
  1416. {
  1417. int i, j, l;
  1418. /* double energy; */
  1419. int someRadiation;
  1420. int numRows;
  1421. int arrayOffset;
  1422. double lum, q1;
  1423. double dayRad;
  1424. double latid_l, cos_u, cos_v, sin_u, sin_v;
  1425. double sin_phi_l, tan_lam_l;
  1426. double zmax;
  1427. double longitTime = 0.;
  1428. double locTimeOffset;
  1429. double latitude, longitude;
  1430. double coslat;
  1431. struct SunGeometryConstDay sunGeom;
  1432. struct SunGeometryVarDay sunVarGeom;
  1433. struct SunGeometryVarSlope sunSlopeGeom;
  1434. struct SolarRadVar sunRadVar;
  1435. sunSlopeGeom.slope = singleSlope;
  1436. sunSlopeGeom.aspect = singleAspect;
  1437. sunRadVar.alb = singleAlbedo;
  1438. sunRadVar.linke = singleLinke;
  1439. sunRadVar.cbh = 1.0;
  1440. sunRadVar.cdh = 1.0;
  1441. sunGeom.sindecl = sin(declination);
  1442. sunGeom.cosdecl = cos(declination);
  1443. someRadiation = (beam_rad != NULL) || (insol_time != NULL) ||
  1444. (diff_rad != NULL) || (refl_rad != NULL) || (glob_rad != NULL);
  1445. if (incidout != NULL) {
  1446. lumcl = (float **)G_malloc(sizeof(float *) * (m));
  1447. for (l = 0; l < m; l++) {
  1448. lumcl[l] = (float *)G_malloc(sizeof(float) * (n));
  1449. }
  1450. for (j = 0; j < m; j++) {
  1451. for (i = 0; i < n; i++)
  1452. lumcl[j][i] = UNDEFZ;
  1453. }
  1454. }
  1455. if (beam_rad != NULL) {
  1456. beam = (float **)G_malloc(sizeof(float *) * (m));
  1457. for (l = 0; l < m; l++) {
  1458. beam[l] = (float *)G_malloc(sizeof(float) * (n));
  1459. }
  1460. for (j = 0; j < m; j++) {
  1461. for (i = 0; i < n; i++)
  1462. beam[j][i] = UNDEFZ;
  1463. }
  1464. }
  1465. if (insol_time != NULL) {
  1466. insol = (float **)G_malloc(sizeof(float *) * (m));
  1467. for (l = 0; l < m; l++) {
  1468. insol[l] = (float *)G_malloc(sizeof(float) * (n));
  1469. }
  1470. for (j = 0; j < m; j++) {
  1471. for (i = 0; i < n; i++)
  1472. insol[j][i] = UNDEFZ;
  1473. }
  1474. }
  1475. if (diff_rad != NULL) {
  1476. diff = (float **)G_malloc(sizeof(float *) * (m));
  1477. for (l = 0; l < m; l++) {
  1478. diff[l] = (float *)G_malloc(sizeof(float) * (n));
  1479. }
  1480. for (j = 0; j < m; j++) {
  1481. for (i = 0; i < n; i++)
  1482. diff[j][i] = UNDEFZ;
  1483. }
  1484. }
  1485. if (refl_rad != NULL) {
  1486. refl = (float **)G_malloc(sizeof(float *) * (m));
  1487. for (l = 0; l < m; l++) {
  1488. refl[l] = (float *)G_malloc(sizeof(float) * (n));
  1489. }
  1490. for (j = 0; j < m; j++) {
  1491. for (i = 0; i < n; i++)
  1492. refl[j][i] = UNDEFZ;
  1493. }
  1494. }
  1495. if (glob_rad != NULL) {
  1496. globrad = (float **)G_malloc(sizeof(float *) * (m));
  1497. for (l = 0; l < m; l++) {
  1498. globrad[l] = (float *)G_malloc(sizeof(float) * (n));
  1499. }
  1500. for (j = 0; j < m; j++) {
  1501. for (i = 0; i < n; i++)
  1502. globrad[j][i] = UNDEFZ;
  1503. }
  1504. }
  1505. sunRadVar.G_norm_extra = com_sol_const(day);
  1506. numRows = m / numPartitions;
  1507. if (useCivilTime()) {
  1508. /* We need to calculate the deviation of the local solar time from the
  1509. * "local clock time". */
  1510. dayRad = 2. * M_PI * day / 365.25;
  1511. locTimeOffset =
  1512. +0.128 * sin(dayRad - 0.04887) + 0.165 * sin(2 * dayRad +
  1513. 0.34383);
  1514. /* Time offset due to timezone as input by user */
  1515. locTimeOffset += civilTime;
  1516. setTimeOffset(locTimeOffset);
  1517. }
  1518. else {
  1519. setTimeOffset(0.);
  1520. }
  1521. for (j = 0; j < m; j++) {
  1522. G_percent(j, m - 1, 2);
  1523. if (j % (numRows) == 0) {
  1524. INPUT_part(j, &zmax);
  1525. arrayOffset = 0;
  1526. shadowoffset = 0;
  1527. }
  1528. sunVarGeom.zmax = zmax;
  1529. for (i = 0; i < n; i++) {
  1530. if (useCivilTime()) {
  1531. /* sun travels 15deg per hour, so 1 TZ every 15 deg and 15 TZs * 24hrs = 360deg */
  1532. longitTime = -longitudeArray[arrayOffset][i] / 15.;
  1533. }
  1534. gridGeom.xg0 = gridGeom.xx0 = (double)i *gridGeom.stepx;
  1535. gridGeom.yg0 = gridGeom.yy0 = (double)j *gridGeom.stepy;
  1536. gridGeom.xp = xmin + gridGeom.xx0;
  1537. gridGeom.yp = ymin + gridGeom.yy0;
  1538. if (ll_correction) {
  1539. coslat = cos(deg2rad * gridGeom.yp);
  1540. coslatsq = coslat * coslat;
  1541. }
  1542. func = NULL;
  1543. sunVarGeom.z_orig = z1 = sunVarGeom.zp = z[arrayOffset][i];
  1544. if (sunVarGeom.z_orig != UNDEFZ) {
  1545. if (aspin != NULL) {
  1546. o_orig = o[arrayOffset][i];
  1547. if (o[arrayOffset][i] != 0.)
  1548. sunSlopeGeom.aspect = o[arrayOffset][i] * deg2rad;
  1549. else
  1550. sunSlopeGeom.aspect = UNDEF;
  1551. }
  1552. if (slopein != NULL) {
  1553. sunSlopeGeom.slope = s[arrayOffset][i] * deg2rad;
  1554. }
  1555. if (linkein != NULL) {
  1556. sunRadVar.linke = li[arrayOffset][i];
  1557. linke_max = AMAX1(linke_max, sunRadVar.linke);
  1558. linke_min = AMIN1(linke_min, sunRadVar.linke);
  1559. }
  1560. if (albedo != NULL) {
  1561. sunRadVar.alb = a[arrayOffset][i];
  1562. albedo_max = AMAX1(albedo_max, sunRadVar.alb);
  1563. albedo_min = AMIN1(albedo_min, sunRadVar.alb);
  1564. }
  1565. if (latin != NULL) {
  1566. latitude = latitudeArray[arrayOffset][i];
  1567. lat_max = AMAX1(lat_max, latitude);
  1568. lat_min = AMIN1(lat_min, latitude);
  1569. latitude *= deg2rad;
  1570. }
  1571. if (longin != NULL) {
  1572. longitude = longitudeArray[arrayOffset][i];
  1573. /* lon_max = AMAX1(lon_max, longitude); */
  1574. /* lon_min = AMIN1(lon_min, longitude); */
  1575. longitude *= deg2rad;
  1576. }
  1577. if ((G_projection() != PROJECTION_LL)) {
  1578. if (latin == NULL || longin == NULL) {
  1579. /* if either is missing we have to calc both from current projection */
  1580. longitude = gridGeom.xp;
  1581. latitude = gridGeom.yp;
  1582. if (pj_do_proj(&longitude, &latitude, &iproj, &oproj) < 0) {
  1583. G_fatal_error("Error in pj_do_proj");
  1584. }
  1585. lat_max = AMAX1(lat_max, latitude);
  1586. lat_min = AMIN1(lat_min, latitude);
  1587. latitude *= deg2rad;
  1588. longitude *= deg2rad;
  1589. }
  1590. }
  1591. else { /* ll projection */
  1592. latitude = gridGeom.yp;
  1593. longitude = gridGeom.xp;
  1594. lat_max = AMAX1(lat_max, latitude);
  1595. lat_min = AMIN1(lat_min, latitude);
  1596. latitude *= deg2rad;
  1597. longitude *= deg2rad;
  1598. }
  1599. if (coefbh != NULL) {
  1600. sunRadVar.cbh = cbhr[arrayOffset][i];
  1601. }
  1602. if (coefdh != NULL) {
  1603. sunRadVar.cdh = cdhr[arrayOffset][i];
  1604. }
  1605. cos_u = cos(M_PI / 2 - sunSlopeGeom.slope); /* = sin(slope) */
  1606. sin_u = sin(M_PI / 2 - sunSlopeGeom.slope); /* = cos(slope) */
  1607. cos_v = cos(M_PI / 2 + sunSlopeGeom.aspect);
  1608. sin_v = sin(M_PI / 2 + sunSlopeGeom.aspect);
  1609. if (ttime != NULL)
  1610. sunGeom.timeAngle = tim;
  1611. gridGeom.sinlat = sin(-latitude);
  1612. gridGeom.coslat = cos(-latitude);
  1613. sin_phi_l =
  1614. -gridGeom.coslat * cos_u * sin_v +
  1615. gridGeom.sinlat * sin_u;
  1616. latid_l = asin(sin_phi_l);
  1617. q1 = gridGeom.sinlat * cos_u * sin_v +
  1618. gridGeom.coslat * sin_u;
  1619. tan_lam_l = -cos_u * cos_v / q1;
  1620. sunSlopeGeom.longit_l = atan(tan_lam_l);
  1621. sunSlopeGeom.lum_C31_l = cos(latid_l) * sunGeom.cosdecl;
  1622. sunSlopeGeom.lum_C33_l = sin_phi_l * sunGeom.sindecl;
  1623. if ((incidout != NULL) || someRadiation) {
  1624. com_par_const(longitTime, &sunGeom, &gridGeom);
  1625. sunrise_min = AMIN1(sunrise_min, sunGeom.sunrise_time);
  1626. sunrise_max = AMAX1(sunrise_max, sunGeom.sunrise_time);
  1627. sunset_min = AMIN1(sunset_min, sunGeom.sunset_time);
  1628. sunset_max = AMAX1(sunset_max, sunGeom.sunset_time);
  1629. }
  1630. if (incidout != NULL) {
  1631. com_par(&sunGeom, &sunVarGeom, &gridGeom, latitude,
  1632. longitude);
  1633. lum =
  1634. lumcline2(&sunGeom, &sunVarGeom, &sunSlopeGeom,
  1635. &gridGeom, horizonarray + shadowoffset);
  1636. if (lum > 0.) {
  1637. lum = rad2deg * asin(lum);
  1638. lumcl[j][i] = (float)lum;
  1639. }
  1640. else lumcl[j][i] = UNDEFZ;
  1641. }
  1642. if (someRadiation) {
  1643. joules2(&sunGeom, &sunVarGeom, &sunSlopeGeom, &sunRadVar,
  1644. &gridGeom, horizonarray + shadowoffset, latitude,
  1645. longitude);
  1646. if (beam_rad != NULL)
  1647. beam[j][i] = (float)beam_e;
  1648. if (insol_time != NULL)
  1649. insol[j][i] = (float)insol_t;
  1650. /* G_debug(3,"\n %f",insol[j][i]); */
  1651. if (diff_rad != NULL)
  1652. diff[j][i] = (float)diff_e;
  1653. if (refl_rad != NULL)
  1654. refl[j][i] = (float)refl_e;
  1655. if (glob_rad != NULL)
  1656. globrad[j][i] = (float)(beam_e + diff_e + refl_e);
  1657. }
  1658. } /* undefs */
  1659. shadowoffset += arrayNumInt;
  1660. }
  1661. arrayOffset++;
  1662. }
  1663. /* re-use &hist, but try all to initiate it for any case */
  1664. /* note this will result in incorrect map titles */
  1665. if (incidout != NULL) {
  1666. Rast_short_history(incidout, "raster", &hist);
  1667. }
  1668. else if (beam_rad != NULL) {
  1669. Rast_short_history(beam_rad, "raster", &hist);
  1670. }
  1671. else if (diff_rad != NULL) {
  1672. Rast_short_history(diff_rad, "raster", &hist);
  1673. }
  1674. else if (refl_rad != NULL) {
  1675. Rast_short_history(refl_rad, "raster", &hist);
  1676. }
  1677. else if (insol_time != NULL) {
  1678. Rast_short_history(insol_time, "raster", &hist);
  1679. }
  1680. else if (glob_rad != NULL) {
  1681. Rast_short_history(glob_rad, "raster", &hist);
  1682. }
  1683. else
  1684. G_fatal_error
  1685. ("Failed to init map history: no output maps requested!");
  1686. Rast_append_format_history(
  1687. &hist,
  1688. " ----------------------------------------------------------------");
  1689. Rast_append_format_history(
  1690. &hist,
  1691. " Day [1-365]: %d",
  1692. day);
  1693. if (ttime != NULL)
  1694. Rast_append_format_history(
  1695. &hist,
  1696. " Local (solar) time (decimal hr.): %.4f", timo);
  1697. Rast_append_format_history(
  1698. &hist,
  1699. " Solar constant (W/m^2): 1367");
  1700. Rast_append_format_history(
  1701. &hist,
  1702. " Extraterrestrial irradiance (W/m^2): %f",
  1703. sunRadVar.G_norm_extra);
  1704. Rast_append_format_history(
  1705. &hist,
  1706. " Declination (rad): %f", -declination);
  1707. Rast_append_format_history(
  1708. &hist,
  1709. " Latitude min-max(deg): %.4f - %.4f",
  1710. lat_min, lat_max);
  1711. if (ttime != NULL) {
  1712. Rast_append_format_history(
  1713. &hist,
  1714. " Sunrise time (hr.): %.2f",
  1715. sunGeom.sunrise_time);
  1716. Rast_append_format_history(
  1717. &hist,
  1718. " Sunset time (hr.): %.2f",
  1719. sunGeom.sunset_time);
  1720. Rast_append_format_history(
  1721. &hist,
  1722. " Daylight time (hr.): %.2f",
  1723. sunGeom.sunset_time - sunGeom.sunrise_time);
  1724. }
  1725. else {
  1726. Rast_append_format_history(
  1727. &hist,
  1728. " Sunrise time min-max (hr.): %.2f - %.2f",
  1729. sunrise_min, sunrise_max);
  1730. Rast_append_format_history(
  1731. &hist,
  1732. " Sunset time min-max (hr.): %.2f - %.2f",
  1733. sunset_min, sunset_max);
  1734. Rast_append_format_history(
  1735. &hist,
  1736. " Time step (hr.): %.4f", step);
  1737. }
  1738. if (incidout != NULL || ttime != NULL) {
  1739. Rast_append_format_history(
  1740. &hist,
  1741. " Solar altitude (deg): %.4f",
  1742. sunVarGeom.solarAltitude * rad2deg);
  1743. Rast_append_format_history(
  1744. &hist,
  1745. " Solar azimuth (deg): %.4f",
  1746. sunVarGeom.solarAzimuth * rad2deg);
  1747. }
  1748. if (linkein == NULL)
  1749. Rast_append_format_history(
  1750. &hist,
  1751. " Linke turbidity factor: %.1f",
  1752. sunRadVar.linke);
  1753. else
  1754. Rast_append_format_history(
  1755. &hist,
  1756. " Linke turbidity factor min-max: %.1f-%.1f",
  1757. linke_min, linke_max);
  1758. if (albedo == NULL)
  1759. Rast_append_format_history(
  1760. &hist,
  1761. " Ground albedo: %.3f",
  1762. sunRadVar.alb);
  1763. else
  1764. Rast_append_format_history(
  1765. &hist,
  1766. " Ground albedo min-max: %.3f-%.3f",
  1767. albedo_min, albedo_max);
  1768. Rast_append_format_history(
  1769. &hist,
  1770. " -----------------------------------------------------------------");
  1771. Rast_command_history(&hist);
  1772. /* don't call Rast_write_history() until after Rast_close() or it just gets overwritten */
  1773. } /* End of ) function */
  1774. double com_declin(int no_of_day)
  1775. {
  1776. double d1, decl;
  1777. /* stretch day number in the following calculation for siderial effect? */
  1778. /* ? double siderial_day = no_of_day + ((no_of_day * 0.25) / 365.) ? */
  1779. /* or just change d1 to : d1 = pi2 * no_of_day / 365.0; ? */
  1780. d1 = pi2 * no_of_day / 365.25;
  1781. decl = asin(0.3978 * sin(d1 - 1.4 + 0.0355 * sin(d1 - 0.0489)));
  1782. decl = -decl;
  1783. /* G_debug(3," declination : %lf\n", decl); */
  1784. return (decl);
  1785. }
  1786. int test(void)
  1787. {
  1788. /* not finshed yet */
  1789. int dej;
  1790. G_message("\n ddd: %f", declin);
  1791. dej = asin(-declin / 0.4093) * 365. / pi2 + 81;
  1792. /* dej = asin(-declin/23.35 * deg2rad) / 0.9856 - 284; */
  1793. /* dej = dej - 365; */
  1794. G_message("\n d: %d ", dej);
  1795. if (dej < day - 5 || dej > day + 5)
  1796. return 0;
  1797. else
  1798. return 1;
  1799. }