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

Contents of /branches/ksenija2/models/johnpye/nrel/asc_sunpos.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2857 - (show annotations) (download) (as text)
Sat Mar 21 13:13:27 2015 UTC (7 years, 3 months ago) by jpye
File MIME type: text/x-csrc
File size: 8032 byte(s)
rearranging the idaanaylse file top-down, functions in the order called.
minor changes elsehwere to debug output, commenting.

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, see <http://www.gnu.org/licenses/>.
16 *//** @file
17 Wrapper for sunpos_nrel.c to allow access to the calculation from ASCEND.
18 */
19
20 /* include the external function API from libascend... */
21 #include <ascend/compiler/extfunc.h>
22
23 /* include error reporting API as well, so we can send messages to user */
24 #include <ascend/utilities/error.h>
25
26 /* for accessing the DATA instance */
27 #include <ascend/compiler/child.h>
28 #include <ascend/general/list.h>
29 #include <ascend/compiler/module.h>
30 #include <ascend/compiler/childinfo.h>
31 #include <ascend/compiler/parentchild.h>
32 #include <ascend/compiler/slist.h>
33 #include <ascend/compiler/type_desc.h>
34 #include <ascend/compiler/packages.h>
35 #include <ascend/compiler/symtab.h>
36 #include <ascend/compiler/instquery.h>
37 #include <ascend/compiler/instmacro.h>
38 #include <ascend/compiler/instance_types.h>
39
40 /* the code that we're wrapping... */
41 #include "spa.h"
42
43 #ifndef PI
44 # define PI 3.141592653589793238462
45 #endif
46
47 static ExtBBoxInitFunc sunpos_nrel_prepare;
48 static ExtBBoxFunc sunpos_nrel_calc;
49 static ExtBBoxInitFunc julian_day_nrel_prepare;
50 static ExtBBoxFunc julian_day_nrel_calc;
51
52 static const char *sunpos_nrel_help = "\
53 Calculate sun position using NREL SPA code. Inputs are:\n\
54 * time (relative to reference time)\n\
55 * pressure (instantaneous atmospheric pressure)\n\
56 * temperature (instantaneous absolute atmospheric temperature)\n\
57 * reference time (Julian Day value expressed as seconds)\n\
58 The reference time allows this function to use the same time variable as the\
59 rest of your simulation; the reference time is expected to be pre-calculated\
60 from a year-month-day calculation (see 'julian_day_nrel' external relation).";
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.");
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,4,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(4,2);
193
194 double t, p, T, t_offset;
195
196 t = inputs[0]; /* 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 t_offset = inputs[3];
200
201 spa_data S = *sunpos1;
202 S.pressure = p;
203 S.temperature = T;
204 S.jd = (t + t_offset) / 3600 / 24; /* convert to days */
205
206 int res = spa_calculate(&S);
207 //CONSOLE_DEBUG("Sun position: t = %f JD, p %f mbar, T = %f C: res = %d, az = %f, zen = %f",S.jd, p, T, res, S.azimuth, S.zenith);
208
209 /* returned values are in degrees, need to convert back to base SI: radians */
210 outputs[0] = S.zenith * PI/180.;
211 outputs[1] = S.azimuth180 * PI/180.;
212
213 switch(res){
214 case 0: break;
215 case 16: CONSOLE_DEBUG("Calculated julian day (t + offset) = %f is out of permitted range",S.jd); break;
216 default: CONSOLE_DEBUG("Error code %d returned from spa_calculate",res);
217 }
218
219 /* 0 on success, non-zero is error code from spa_calculate (would prob be input parameters out-of-range) */
220 return res;
221 }
222
223 /*---------- SUNPOS_JULIAN_DAY ------------*/
224
225 static int julian_day_nrel_prepare(struct BBoxInterp *bbox,
226 struct Instance *data,
227 struct gl_list_t *arglist
228 ){
229 bbox->user_data = NULL;
230 return 0;
231 }
232
233 static int julian_day_nrel_calc(struct BBoxInterp *bbox,
234 int ninputs, int noutputs,
235 double *inputs, double *outputs,
236 double *jacobian
237 ){
238 CALCPREPARE(7,1);
239 (void)sunpos1;
240
241 int y,mon,d,h,m,s;
242 double tz;
243
244 y = inputs[0]; /* year */
245 mon = inputs[1]; /* month */
246 d = inputs[2]; /* day */
247 h = inputs[3]; /* hour */
248 m = inputs[4]; /* minute */
249 s = inputs[5]; /* second */
250 tz = inputs[6] / 3600.; /* timezone (in seconds, converted here to hours) */
251
252 double t = julian_day(y,mon,d, h,m,s, tz) * 3600 * 24;
253
254 outputs[0] = t;
255 return 0;
256 }
257
258

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