/[ascend]/trunk/models/johnpye/nrel/asc_sunpos.c
ViewVC logotype

Contents of /trunk/models/johnpye/nrel/asc_sunpos.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2591 - (show annotations) (download) (as text)
Wed Apr 11 21:23:18 2012 UTC (10 years, 4 months ago) by jpye
File MIME type: text/x-csrc
File size: 7811 byte(s)
Add calculation of Julian Day within ASCEND model.
1 /* ASCEND modelling environment
2 Copyright (C) 2008 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//** @file
19 Wrapper for sunpos_nrel.c to allow access to the calculation from ASCEND.
20 */
21
22 /* include the external function API from libascend... */
23 #include <ascend/compiler/extfunc.h>
24
25 /* include error reporting API as well, so we can send messages to user */
26 #include <ascend/utilities/error.h>
27
28 /* for accessing the DATA instance */
29 #include <ascend/compiler/child.h>
30 #include <ascend/general/list.h>
31 #include <ascend/compiler/module.h>
32 #include <ascend/compiler/childinfo.h>
33 #include <ascend/compiler/parentchild.h>
34 #include <ascend/compiler/slist.h>
35 #include <ascend/compiler/type_desc.h>
36 #include <ascend/compiler/packages.h>
37 #include <ascend/compiler/symtab.h>
38 #include <ascend/compiler/instquery.h>
39 #include <ascend/compiler/instmacro.h>
40 #include <ascend/compiler/instance_types.h>
41
42 /* the code that we're wrapping... */
43 #include "spa.h"
44
45 #ifndef PI
46 # define PI 3.14159265358979
47 #endif
48
49 static ExtBBoxInitFunc sunpos_nrel_prepare;
50 static ExtBBoxFunc sunpos_nrel_calc;
51 static ExtBBoxInitFunc julian_day_nrel_prepare;
52 static ExtBBoxFunc julian_day_nrel_calc;
53
54 static const char *sunpos_nrel_help = "Calculate sun position (local zenith, azimuth "
55 "angles) given time, pressure and temperature, using NREL algorithm. DATA "
56 "member for this external relation is required to provide constants for "
57 "latitude and longitude of the selected location.\n\n"
58 "Time is required to be in the form of Julian Date. ASCEND will convert the "
59 "Julian Date into seconds automatically. The JD should be in the range"
60 "-2000 BC to 6000 AD (12:00pm 1 Jan 2000 GMT is 2451545.0 JD)";
61
62 static const char *julian_day_nrel_help = "Calculate the Julian Day from "
63 "year, month, day, hour, minute, second and timezone inputs. "
64 "Intended for once-off use in ASCEND models to calculate the time offset "
65 "eg for the start of a weather file. Acceptable dates are in the range "
66 "of -2000 BC to AD 6000. All of the inputs should be as 'factor' type "
67 "variables (to avoid needless time unit conversions), except for the "
68 "timezone, which should be in time units eg '8{h}'.";
69
70 /*------------------------------------------------------------------------------
71 REGISTRATION FUNCTION
72 */
73
74 /**
75 This is the function called from 'IMPORT "johnpye/nrel/sunpos_nrels";'
76
77 It sets up the functions contained in this external library
78 */
79 extern
80 ASC_EXPORT int sunpos_nrel_register(){
81 int result = 0;
82
83 ERROR_REPORTER_HERE(ASC_USER_WARNING,"SUNPOS_NREL is still EXPERIMENTAL. Use with caution.\n");
84
85 #define CALCFN(NAME,INPUTS,OUTPUTS) \
86 result += CreateUserFunctionBlackBox(#NAME \
87 , NAME##_prepare \
88 , NAME##_calc /* value */ \
89 , (ExtBBoxFunc*)NULL /* derivatives not provided yet*/ \
90 , (ExtBBoxFunc*)NULL /* hessian not provided yet */ \
91 , (ExtBBoxFinalFunc*)NULL /* finalisation not implemented */ \
92 , INPUTS,OUTPUTS /* inputs, outputs */ \
93 , NAME##_help /* help text */ \
94 , 0.0 \
95 ) /* returns 0 on success */
96
97 CALCFN(sunpos_nrel,3,2);
98 CALCFN(julian_day_nrel,7,1);
99
100 #undef CALCFN
101
102 if(result){
103 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"CreateUserFunction result = %d\n",result);
104 }
105 return result;
106 }
107
108 #define GET_CHILD_VAL(NAME) \
109 inst = ChildByChar(data,AddSymbol(#NAME)); \
110 if(!inst){ \
111 ERROR_REPORTER_HERE(ASC_USER_ERROR \
112 ,"Couldn't locate '" #NAME "' in DATA, please check usage of SUNPOS."\
113 );\
114 return 1;\
115 }\
116 if(InstanceKind(inst)!=REAL_CONSTANT_INST){\
117 ERROR_REPORTER_HERE(ASC_USER_ERROR,"DATA member '" #NAME "' must be a real_constant");\
118 return 1;\
119 }\
120 NAME = RC_INST(inst)->value;
121
122 /**
123 This function is called when the black-box relation is being instantiated.
124
125 This just gets the data member and checks that it's valid, and stores
126 it in the blackbox data field.
127 */
128 static int sunpos_nrel_prepare(struct BBoxInterp *bbox,
129 struct Instance *data,
130 struct gl_list_t *arglist
131 ){
132 struct Instance *inst;
133 double latitude, longitude, elevation;
134
135 /* get the latitude */
136 GET_CHILD_VAL(latitude);
137 CONSOLE_DEBUG("Latitude: %0.3f",latitude);
138 if(latitude > PI/2 || latitude < -PI/2){
139 ERROR_REPORTER_HERE(ASC_USER_ERROR,"'latitude' is out of allowable range -PI/2 to PI/2.");
140 return 1;
141 }
142
143 /* get the longitude */
144 GET_CHILD_VAL(longitude);
145 CONSOLE_DEBUG("Longitude: %0.3f",longitude);
146 if(longitude > PI || longitude < -PI){
147 ERROR_REPORTER_HERE(ASC_USER_ERROR,"'latitude' is out of allowable range -PI to PI.");
148 return 1;
149 }
150
151 /* get the elevation */
152 GET_CHILD_VAL(elevation);
153 CONSOLE_DEBUG("Elevation: %0.3f m",elevation);
154 if(elevation < -6500000){
155 ERROR_REPORTER_HERE(ASC_USER_ERROR,"'elevation' is out of allowable range (must be > -6,500 km)");
156 return 1;
157 }
158
159 spa_data *S = ASC_NEW(spa_data);
160 S->latitude = latitude * 180/PI;
161 S->longitude = longitude * 180/PI;
162 S->elevation = elevation;
163 S->function = SPA_ZA_JD;
164
165 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Prepared position for sun position.\n");
166 bbox->user_data = (void *)S;
167 return 0;
168 }
169
170 #define CALCPREPARE(NIN,NOUT) \
171 /* a few checks about the input requirements */ \
172 if(ninputs != NIN)return -1; \
173 if(noutputs != NOUT)return -2; \
174 if(inputs==NULL)return -3; \
175 if(outputs==NULL)return -4; \
176 if(bbox==NULL)return -5; \
177 \
178 /* the 'user_data' in the black box object will contain the */\
179 /* coefficients required for this fluid; cast it to the required form: */\
180 const spa_data *sunpos1 = (const spa_data *)bbox->user_data
181
182
183 /**
184 Evaluation function for 'sunpos'
185 @return 0 on success
186 */
187 static int sunpos_nrel_calc(struct BBoxInterp *bbox,
188 int ninputs, int noutputs,
189 double *inputs, double *outputs,
190 double *jacobian
191 ){
192 CALCPREPARE(3,2);
193
194 double t, p, T;
195
196 t = inputs[0]/ 86400.; /* convert from JD seconds to JD days */
197 p = inputs[1] / 100. /* convert Pa to mbar */;
198 T = inputs[2] - 273.15 /* convert ��C to K */;
199
200 spa_data S = *sunpos1;
201 S.pressure = p;
202 S.temperature = T;
203 S.jd = t;
204
205 int res = spa_calculate(&S);
206 CONSOLE_DEBUG("Sun position: t = %f JD, p %f mbar, T = %f C: res = %d, az = %f, zen = %f",t, p, T, res, S.azimuth, S.zenith);
207
208 /* returned values are in degrees, need to convert back to base SI: radians */
209 outputs[0] = S.zenith * PI/180.;
210 outputs[1] = S.azimuth * PI/180.;
211
212 /* 0 on success, non-zero is error code from spa_calculate (would prob be input parameters out-of-range) */
213 return res;
214 }
215
216 /*---------- SUNPOS_JULIAN_DAY ------------*/
217
218 static int julian_day_nrel_prepare(struct BBoxInterp *bbox,
219 struct Instance *data,
220 struct gl_list_t *arglist
221 ){
222 bbox->user_data = NULL;
223 return 0;
224 }
225
226 static int julian_day_nrel_calc(struct BBoxInterp *bbox,
227 int ninputs, int noutputs,
228 double *inputs, double *outputs,
229 double *jacobian
230 ){
231 CALCPREPARE(7,1);
232 (void)sunpos1;
233
234 int y,mon,d,h,m,s;
235 double tz;
236
237 y = inputs[0]; /* convert from seconds to years */
238 mon = inputs[1]; /* convert from seconds to months */
239 d = inputs[2]; /* convert from seconds to days */
240 h = inputs[3]; /* seconds to hours */
241 m = inputs[4]; /* seconds to minutes */
242 s = inputs[5];
243 tz = inputs[6] / 3600.; /* seconds to hours */
244
245 double t = julian_day(y,mon,d, h,m,s, tz) * 3600 * 24;
246
247 outputs[0] = t;
248 return 0;
249 }
250
251

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22