@@ -32,6 +32,8 @@ def __init__(self, **kwargs):
32
32
self ._kind = None
33
33
self ._intent = None
34
34
self ._active = None
35
+ self ._optional = None
36
+ self ._pointer = False
35
37
self ._target = None
36
38
self ._actions = { 'in' : None , 'out' : None }
37
39
for key , value in kwargs .items ():
@@ -134,6 +136,30 @@ def active(self, value):
134
136
raise ValueError ('Invalid value {0} for variable property active, must be a string' .format (value ))
135
137
self ._active = value
136
138
139
+ @property
140
+ def optional (self ):
141
+ '''Get the optional attribute of the variable.'''
142
+ return self ._optional
143
+
144
+ @optional .setter
145
+ def optional (self , value ):
146
+ if not isinstance (value , str ):
147
+ raise ValueError ('Invalid value {0} for variable property optional, must be a string' .format (value ))
148
+ self ._optional = value
149
+
150
+ # Pointer is not set by parsing metadata attributes, but by mkstatic.
151
+ # This is a quick and dirty solution!
152
+ @property
153
+ def pointer (self ):
154
+ '''Get the pointer attribute of the variable.'''
155
+ return self ._pointer
156
+
157
+ @pointer .setter
158
+ def pointer (self , value ):
159
+ if not isinstance (value , bool ):
160
+ raise ValueError ('Invalid value {0} for variable property pointer, must be a logical' .format (value ))
161
+ self ._pointer = value
162
+
137
163
@property
138
164
def target (self ):
139
165
'''Get the target of the variable.'''
@@ -270,62 +296,128 @@ def print_def_intent(self, metadata):
270
296
dictionary to resolve lower bounds for array dimensions.'''
271
297
# Resolve dimensisons to local names using undefined upper bounds (assumed shape)
272
298
dimstring = self .dimstring_local_names (metadata , assume_shape = True )
299
+ # It is an error for host model variables to have the optional attribute in the metadata
300
+ if self .optional == 'T' :
301
+ error_message = "This routine should only be called for host model variables" + \
302
+ " that cannot be optional, but got self.optional=T"
303
+ raise Exception (error_message )
304
+ # If the host variable is potentially unallocated, add optional and target to variable declaration
305
+ elif not self .active == 'T' :
306
+ optional = ', optional, target'
307
+ else :
308
+ optional = ''
273
309
#
274
310
if self .type in STANDARD_VARIABLE_TYPES :
275
311
if self .kind :
276
- str = "{s.type}({s._kind}), intent({s.intent}) :: {s.local_name}{dimstring}"
312
+ str = "{s.type}({s._kind}), intent({s.intent}){optional} :: {s.local_name}{dimstring}"
277
313
else :
278
- str = "{s.type}, intent({s.intent}) :: {s.local_name}{dimstring}"
314
+ str = "{s.type}, intent({s.intent}){optional} :: {s.local_name}{dimstring}"
279
315
else :
280
316
if self .kind :
281
317
error_message = "Generating variable definition statements for derived types with" + \
282
318
" kind attributes not implemented; variable: {0}" .format (self .standard_name )
283
319
raise Exception (error_message )
284
320
else :
285
- str = "type({s.type}), intent({s.intent}) :: {s.local_name}{dimstring}"
286
- return str .format (s = self , dimstring = dimstring )
321
+ str = "type({s.type}), intent({s.intent}){optional} :: {s.local_name}{dimstring}"
322
+ return str .format (s = self , optional = optional , dimstring = dimstring )
287
323
288
324
def print_def_local (self , metadata ):
289
325
'''Print the definition line for the variable, assuming it is a local variable.'''
290
- if self .type in STANDARD_VARIABLE_TYPES :
291
- if self .kind :
292
- if self .rank :
293
- str = "{s.type}({s._kind}), dimension{s.rank}, allocatable :: {s.local_name}"
326
+ # It is an error for local variables to have the active attribute
327
+ if not self .active == 'T' :
328
+ error_message = "This routine should only be called for local variables" + \
329
+ " that cannot have an active attribute other than the" + \
330
+ " default T, but got self.active=T"
331
+ raise Exception (error_message )
332
+
333
+ # If it is a pointer, everything is different!
334
+ if self .pointer :
335
+ if self .type in STANDARD_VARIABLE_TYPES :
336
+ if self .kind :
337
+ if self .rank :
338
+ str = "{s.type}({s._kind}), dimension{s.rank}, pointer :: p => null()"
339
+ else :
340
+ str = "{s.type}({s._kind}), pointer :: p => null()"
294
341
else :
295
- str = "{s.type}({s._kind}) :: {s.local_name}"
342
+ if self .rank :
343
+ str = "{s.type}, dimension{s.rank}, pointer :: p => null()"
344
+ else :
345
+ str = "{s.type}, pointer :: p => null()"
296
346
else :
297
- if self .rank :
298
- str = "{s.type}, dimension{s.rank}, allocatable :: {s.local_name}"
347
+ if self .kind :
348
+ error_message = "Generating variable definition statements for derived types with" + \
349
+ " kind attributes not implemented; variable: {0}" .format (self .standard_name )
350
+ raise Exception (error_message )
299
351
else :
300
- str = "{s.type} :: {s.local_name}"
352
+ if self .rank :
353
+ str = "type({s.type}), dimension{s.rank}, pointer :: p => null()"
354
+ else :
355
+ str = "type({s.type}), pointer :: p => null()"
356
+ return str .format (s = self )
301
357
else :
302
- if self . kind :
303
- error_message = "Generating variable definition statements for derived types with" + \
304
- " kind attributes not implemented; variable: {0}" . format ( self . standard_name )
305
- raise Exception ( error_message )
358
+ # If the host variable is potentially unallocated, the active attribute is
359
+ # also set accordingly for the local variable; add target to variable declaration
360
+ if self . optional == 'T' :
361
+ target = ', target'
306
362
else :
307
- if self .rank :
308
- str = "type({s.type}), dimension{s.rank}, allocatable :: {s.local_name}"
363
+ target = ''
364
+ if self .type in STANDARD_VARIABLE_TYPES :
365
+ if self .kind :
366
+ if self .rank :
367
+ str = "{s.type}({s._kind}), dimension{s.rank}, allocatable{target} :: {s.local_name}"
368
+ else :
369
+ str = "{s.type}({s._kind}){target} :: {s.local_name}"
309
370
else :
310
- str = "type({s.type}) :: {s.local_name}"
311
- return str .format (s = self )
371
+ if self .rank :
372
+ str = "{s.type}, dimension{s.rank}, allocatable{target} :: {s.local_name}"
373
+ else :
374
+ str = "{s.type}{target} :: {s.local_name}"
375
+ else :
376
+ if self .kind :
377
+ error_message = "Generating variable definition statements for derived types with" + \
378
+ " kind attributes not implemented; variable: {0}" .format (self .standard_name )
379
+ raise Exception (error_message )
380
+ else :
381
+ if self .rank :
382
+ str = "type({s.type}), dimension{s.rank}, allocatable{target} :: {s.local_name}"
383
+ else :
384
+ str = "type({s.type}){target} :: {s.local_name}"
385
+ return str .format (s = self , target = target )
312
386
313
387
def print_debug (self ):
314
388
'''Print the data retrieval line for the variable.'''
315
- str = '''Contents of {s} (* = mandatory for compatibility):
316
- standard_name = {s.standard_name} *
317
- long_name = {s.long_name}
318
- units = {s.units} *
319
- local_name = {s.local_name}
320
- type = {s.type} *
321
- dimensions = {s.dimensions}
322
- rank = {s.rank} *
323
- kind = {s.kind} *
324
- intent = {s.intent}
325
- active = {s.active}
326
- target = {s.target}
327
- container = {s.container}
328
- actions = {s.actions}'''
389
+ # Scheme variables don't have the active attribute
390
+ if 'SCHEME' in self .container :
391
+ str = '''Contents of {s} (* = mandatory for compatibility):
392
+ standard_name = {s.standard_name} *
393
+ long_name = {s.long_name}
394
+ units = {s.units} *
395
+ local_name = {s.local_name}
396
+ type = {s.type} *
397
+ dimensions = {s.dimensions}
398
+ rank = {s.rank} *
399
+ kind = {s.kind} *
400
+ intent = {s.intent}
401
+ optional = {s.optional}
402
+ target = {s.target}
403
+ container = {s.container}
404
+ actions = {s.actions}'''
405
+ # Host model variables don't have the optional attribute
406
+ else :
407
+ str = '''Contents of {s} (* = mandatory for compatibility):
408
+ standard_name = {s.standard_name} *
409
+ long_name = {s.long_name}
410
+ units = {s.units} *
411
+ local_name = {s.local_name}
412
+ type = {s.type} *
413
+ dimensions = {s.dimensions}
414
+ rank = {s.rank} *
415
+ kind = {s.kind} *
416
+ intent = {s.intent}
417
+ active = {s.active}
418
+ target = {s.target}
419
+ container = {s.container}
420
+ actions = {s.actions}'''
329
421
return str .format (s = self )
330
422
331
423
class CapsMakefile (object ):
0 commit comments