/[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 2592 - (show annotations) (download) (as text)
Wed Apr 11 22:15:24 2012 UTC (10 years, 3 months ago) by jpye
File MIME type: text/x-csrc
File size: 7930 byte(s)
Julian Day test model, sunpos_nrel updated to make use of the Julian Day offset calculation.
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 = "\
55 Calculate sun position using NREL SPA code. Inputs are:\n\
56 * time (relative to reference time)\n\
57 * pressure (instantaneous atmospheric pressure)\n\
58 * temperature (instantaneous absolute atmospheric temperature)\n\
59 * reference time (Julian Day value expressed as seconds)\n\
60 The reference time allows this function to use the same time variable as the\
61 rest of your simulation; the reference time is expected to be pre-calculated\
62 from a year-month-day calculation (see 'julian_day_nrel' external relation).";
63
64 static const char *julian_day_nrel_help = "Calculate the Julian Day from "
65 "year, month, day, hour, minute, second and timezone inputs. "
66 "Intended for once-off use in ASCEND models to calculate the time offset "
67 "eg for the start of a weather file. Acceptable dates are in the range "
68 "of -2000 BC to AD 6000. All of the inputs should be as 'factor' type "
69 "variables (to avoid needless time unit conversions), except for the "
70 "timezone, which should be in time units eg '8{h}'.";
71
72 /*------------------------------------------------------------------------------
73 REGISTRATION FUNCTION
74 */
75
76 /**
77 This is the function called from 'IMPORT "johnpye/nrel/sunpos_nrels";'
78
79 It sets up the functions contained in this external library
80 */
81 extern
82 ASC_EXPORT int sunpos_nrel_register(){
83 int result = 0;
84
85 ERROR_REPORTER_HERE(ASC_USER_WARNING,"SUNPOS_NREL is still EXPERIMENTAL. Use with caution.\n");
86
87 #define CALCFN(NAME,INPUTS,OUTPUTS) \
88 result += CreateUserFunctionBlackBox(#NAME \
89 , NAME##_prepare \
90 , NAME##_calc /* value */ \
91 , (ExtBBoxFunc*)NULL /* derivatives not provided yet*/ \
92 , (ExtBBoxFunc*)NULL /* hessian not provided yet */ \
93 , (ExtBBoxFinalFunc*)NULL /* finalisation not implemented */ \
94 , INPUTS,OUTPUTS /* inputs, outputs */ \
95 , NAME##_help /* help text */ \
96 , 0.0 \
97 ) /* returns 0 on success */
98
99 CALCFN(sunpos_nrel,4,2);
100 CALCFN(julian_day_nrel,7,1);
101
102 #undef CALCFN
103
104 if(result){
105 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"CreateUserFunction result = %d\n",result);
106 }
107 return result;
108 }
109
110 #define GET_CHILD_VAL(NAME) \
111 inst = ChildByChar(data,AddSymbol(#NAME)); \
112 if(!inst){ \
113 ERROR_REPORTER_HERE(ASC_USER_ERROR \
114 ,"Couldn't locate '" #NAME "' in DATA, please check usage of SUNPOS."\
115 );\
116 return 1;\
117 }\
118 if(InstanceKind(inst)!=REAL_CONSTANT_INST){\
119 ERROR_REPORTER_HERE(ASC_USER_ERROR,"DATA member '" #NAME "' must be a real_constant");\
120 return 1;\
121 }\
122 NAME = RC_INST(inst)->value;
123
124 /**
125 This function is called when the black-box relation is being instantiated.
126
127 This just gets the data member and checks that it's valid, and stores
128 it in the blackbox data field.
129 */
130 static int sunpos_nrel_prepare(struct BBoxInterp *bbox,
131 struct Instance *data,
132 struct gl_list_t *arglist
133 ){
134 struct Instance *inst;
135 double latitude, longitude, elevation;
136
137 /* get the latitude */
138 GET_CHILD_VAL(latitude);
139 CONSOLE_DEBUG("Latitude: %0.3f",latitude);
140 if(latitude > PI/2 || latitude < -PI/2){
141 ERROR_REPORTER_HERE(ASC_USER_ERROR,"'latitude' is out of allowable range -PI/2 to PI/2.");
142 return 1;
143 }
144
145 /* get the longitude */
146 GET_CHILD_VAL(longitude);
147 CONSOLE_DEBUG("Longitude: %0.3f",longitude);
148 if(longitude > PI || longitude < -PI){
149 ERROR_REPORTER_HERE(ASC_USER_ERROR,"'latitude' is out of allowable range -PI to PI.");
150 return 1;
151 }
152
153 /* get the elevation */
154 GET_CHILD_VAL(elevation);
155 CONSOLE_DEBUG("Elevation: %0.3f m",elevation);
156 if(elevation < -6500000){
157 ERROR_REPORTER_HERE(ASC_USER_ERROR,"'elevation' is out of allowable range (must be > -6,500 km)");
158 return 1;
159 }
160
161 spa_data *S = ASC_NEW(spa_data);
162 S->latitude = latitude * 180/PI;
163 S->longitude = longitude * 180/PI;
164 S->elevation = elevation;
165 S->function = SPA_ZA_JD;
166
167 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Prepared position for sun position.\n");
168 bbox->user_data = (void *)S;
169 return 0;
170 }
171
172 #define CALCPREPARE(NIN,NOUT) \
173 /* a few checks about the input requirements */ \
174 if(ninputs != NIN)return -1; \
175 if(noutputs != NOUT)return -2; \
176 if(inputs==NULL)return -3; \
177 if(outputs==NULL)return -4; \
178 if(bbox==NULL)return -5; \
179 \
180 /* the 'user_data' in the black box object will contain the */\
181 /* coefficients required for this fluid; cast it to the required form: */\
182 const spa_data *sunpos1 = (const spa_data *)bbox->user_data
183
184
185 /**
186 Evaluation function for 'sunpos'
187 @return 0 on success
188 */
189 static int sunpos_nrel_calc(struct BBoxInterp *bbox,
190 int ninputs, int noutputs,
191 double *inputs, double *outputs,
192 double *jacobian
193 ){
194 CALCPREPARE(4,2);
195
196 double t, p, T, t_offset;
197
198 t = inputs[0]; /* convert from JD seconds to JD days */
199 p = inputs[1] / 100. /* convert Pa to mbar */;
200 T = inputs[2] - 273.15 /* convert ��C to K */;
201 t_offset = inputs[3];
202
203 spa_data S = *sunpos1;
204 S.pressure = p;
205 S.temperature = T;
206 S.jd = (t + t_offset) / 3600 / 24; /* convert to days */
207
208 int res = spa_calculate(&S);
209 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);
210
211 /* returned values are in degrees, need to convert back to base SI: radians */
212 outputs[0] = S.zenith * PI/180.;
213 outputs[1] = S.azimuth * PI/180.;
214
215 /* 0 on success, non-zero is error code from spa_calculate (would prob be input parameters out-of-range) */
216 return res;
217 }
218
219 /*---------- SUNPOS_JULIAN_DAY ------------*/
220
221 static int julian_day_nrel_prepare(struct BBoxInterp *bbox,
222 struct Instance *data,
223 struct gl_list_t *arglist
224 ){
225 bbox->user_data = NULL;
226 return 0;
227 }
228
229 static int julian_day_nrel_calc(struct BBoxInterp *bbox,
230 int ninputs, int noutputs,
231 double *inputs, double *outputs,
232 double *jacobian
233 ){
234 CALCPREPARE(7,1);
235 (void)sunpos1;
236
237 int y,mon,d,h,m,s;
238 double tz;
239
240 y = inputs[0]; /* convert from seconds to years */
241 mon = inputs[1]; /* convert from seconds to months */
242 d = inputs[2]; /* convert from seconds to days */
243 h = inputs[3]; /* seconds to hours */
244 m = inputs[4]; /* seconds to minutes */
245 s = inputs[5];
246 tz = inputs[6] / 3600.; /* seconds to hours */
247
248 double t = julian_day(y,mon,d, h,m,s, tz) * 3600 * 24;
249
250 outputs[0] = t;
251 return 0;
252 }
253
254

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