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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2594 - (hide annotations) (download) (as text)
Fri Apr 13 20:20:33 2012 UTC (10 years, 4 months ago) by jpye
File MIME type: text/x-csrc
File size: 7933 byte(s)
Renaming sunpos.a4c to sunpos_db.a4c. 
Changing angle convention for NREL SPA to accord with DB & Grena.
Adding model to compare the three sunpos models.
Updating files depending on sunpos_db.a4c.
1 jpye 2584 /* 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 jpye 2591 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 jpye 2584
54 jpye 2592 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 jpye 2584
64 jpye 2591 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 jpye 2584 /*------------------------------------------------------------------------------
73     REGISTRATION FUNCTION
74     */
75    
76     /**
77 jpye 2591 This is the function called from 'IMPORT "johnpye/nrel/sunpos_nrels";'
78 jpye 2584
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 jpye 2591 ERROR_REPORTER_HERE(ASC_USER_WARNING,"SUNPOS_NREL is still EXPERIMENTAL. Use with caution.\n");
86 jpye 2584
87     #define CALCFN(NAME,INPUTS,OUTPUTS) \
88     result += CreateUserFunctionBlackBox(#NAME \
89 jpye 2591 , NAME##_prepare \
90 jpye 2584 , 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 jpye 2592 CALCFN(sunpos_nrel,4,2);
100 jpye 2591 CALCFN(julian_day_nrel,7,1);
101 jpye 2584
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 jpye 2591 /**
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 jpye 2584 /* 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 jpye 2591 static int sunpos_nrel_calc(struct BBoxInterp *bbox,
190 jpye 2584 int ninputs, int noutputs,
191     double *inputs, double *outputs,
192     double *jacobian
193     ){
194 jpye 2592 CALCPREPARE(4,2);
195 jpye 2584
196 jpye 2592 double t, p, T, t_offset;
197 jpye 2584
198 jpye 2592 t = inputs[0]; /* convert from JD seconds to JD days */
199 jpye 2584 p = inputs[1] / 100. /* convert Pa to mbar */;
200     T = inputs[2] - 273.15 /* convert ��C to K */;
201 jpye 2592 t_offset = inputs[3];
202 jpye 2584
203     spa_data S = *sunpos1;
204     S.pressure = p;
205     S.temperature = T;
206 jpye 2592 S.jd = (t + t_offset) / 3600 / 24; /* convert to days */
207 jpye 2584
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 jpye 2594 outputs[1] = S.azimuth180 * PI/180.;
214 jpye 2584
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 jpye 2591 /*---------- SUNPOS_JULIAN_DAY ------------*/
220 jpye 2584
221 jpye 2591 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 jpye 2584
229 jpye 2591 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