[825] | 1 | from dynamico.dev.libs import libxios |
---|
| 2 | from dynamico.dev import wrap |
---|
[615] | 3 | import numpy as np |
---|
[663] | 4 | |
---|
[615] | 5 | from ctypes import c_int, c_double, c_bool, c_void_p, c_char_p, byref, POINTER, Structure |
---|
| 6 | c_void_pp=POINTER(c_void_p) # used in prototype |
---|
| 7 | c_void_p_byref=type(byref(c_void_p())) # used in py2c because byref creates an object of this type, not c_void_pp |
---|
| 8 | |
---|
[825] | 9 | from dynamico import getargs |
---|
[802] | 10 | log_master, log_world = getargs.getLogger(__name__) |
---|
| 11 | INFO, DEBUG, ERROR = log_master.info, log_master.debug, log_world.error |
---|
| 12 | INFO_ALL, DEBUG_ALL = log_world.info, log_world.debug |
---|
| 13 | |
---|
[615] | 14 | # ------------- Direct cython interfaces ----------------- # |
---|
| 15 | |
---|
| 16 | cdef extern from "functions.h": |
---|
[630] | 17 | cdef void cxios_context_close_definition() |
---|
| 18 | cdef void cxios_context_finalize() |
---|
| 19 | cdef void cxios_finalize() |
---|
| 20 | cdef void cxios_write_data_k81(char*, int, double*, int) |
---|
| 21 | cdef void cxios_write_data_k82(char*, int, double*, int,int) |
---|
| 22 | cdef void cxios_write_data_k83(char*, int, double*, int,int,int) |
---|
[615] | 23 | |
---|
[630] | 24 | def context_close_definition(): cxios_context_close_definition() |
---|
| 25 | def context_finalize(): cxios_context_finalize() |
---|
| 26 | def finalize(): cxios_finalize() |
---|
| 27 | |
---|
| 28 | cdef send_field1(char* id, int idlen, double[:] data): cxios_write_data_k81(id, idlen, &data[0], data.shape[0]) |
---|
| 29 | cdef send_field2(char* id, int idlen, double[:,:] data): cxios_write_data_k82(id, idlen, &data[0,0], data.shape[0],data.shape[1]) |
---|
| 30 | cdef send_field3(char* id, int idlen, double[:,:,:] data): cxios_write_data_k83(id, idlen, &data[0,0,0], data.shape[0],data.shape[1],data.shape[2]) |
---|
| 31 | |
---|
| 32 | def send_field(bytes id, data): |
---|
| 33 | cdef char* idptr = id |
---|
| 34 | cdef int idlen = len(id) |
---|
[760] | 35 | # print 'cxios.write_data', id, data.shape |
---|
[630] | 36 | ndim=data.ndim |
---|
| 37 | if ndim==1: send_field1(idptr,idlen,data) |
---|
| 38 | if ndim==2: send_field2(idptr,idlen,data) |
---|
| 39 | if ndim==3: send_field3(idptr,idlen,data) |
---|
| 40 | |
---|
[615] | 41 | # -------------------------------------------------------- # |
---|
| 42 | |
---|
| 43 | lib=wrap.Struct() |
---|
[663] | 44 | cxios = wrap.SharedLib(vars(lib), libxios, prefix_so='cxios_') |
---|
[615] | 45 | |
---|
| 46 | class Duration(Structure): |
---|
| 47 | _fields_ = [(name, c_double) for name in ('year', 'month', 'day', 'hour', 'minute', 'second', 'timestep') ] |
---|
| 48 | class Date(Structure): |
---|
| 49 | _fields_ = [(name, c_int) for name in ('year', 'month', 'day', 'hour', 'minute', 'second') ] |
---|
| 50 | |
---|
| 51 | for x in c_void_p_byref, Duration, Date : wrap.py2c[x]=wrap.noop # accept arguments of type (void*)&, Duration, ... |
---|
| 52 | |
---|
| 53 | def SHAPE(data): return np.asarray(list(reversed(data.shape)),c_int) # reverse shape to follow Fortran convention |
---|
| 54 | |
---|
| 55 | class Handle: |
---|
| 56 | def __init__(self, cat, id=None): |
---|
| 57 | self.handle = c_void_p() |
---|
| 58 | if id is None: |
---|
| 59 | id='default' |
---|
| 60 | create_fun = cxios.vardict['get_current_'+cat] |
---|
| 61 | create_fun(byref(self.handle)) |
---|
| 62 | else: |
---|
| 63 | create_fun = cxios.vardict[cat+'_handle_create'] |
---|
| 64 | create_fun(byref(self.handle), id, c_int(len(id))) |
---|
| 65 | self.cat, self.prefix_set, self.id = cat, 'set_'+cat+'_', id |
---|
[760] | 66 | # print 'Handle', cat, self.id, self.handle |
---|
[615] | 67 | def set_attr(self, **kwargs): |
---|
| 68 | prefix, handle = self.prefix_set, self.handle |
---|
| 69 | for key, value in kwargs.iteritems(): |
---|
| 70 | fun = cxios.vardict[prefix+key] |
---|
| 71 | extra=value |
---|
[759] | 72 | if type(value) in (int,c_int,np.int64,np.int32): |
---|
[615] | 73 | fun(handle,c_int(value)) |
---|
| 74 | elif type(value) is np.ndarray: |
---|
| 75 | extra=SHAPE(value) |
---|
| 76 | fun(handle,value,extra) |
---|
| 77 | elif type(value) is str: |
---|
| 78 | fun(handle,value,c_int(len(value))) |
---|
| 79 | elif type(value) in (Duration, Date): |
---|
| 80 | fun(handle,value) |
---|
| 81 | else: |
---|
| 82 | raise(TypeError) |
---|
[802] | 83 | DEBUG('%s.%s %s %s' % (self.id, prefix+key, type(value), extra) ) |
---|
[615] | 84 | def update_timestep(self): |
---|
| 85 | lib.update_calendar_timestep(self.handle) |
---|
| 86 | |
---|
| 87 | def import_set_attr(cats, *args): #attr_int, attr_array, attr_str): |
---|
| 88 | for arg in args: |
---|
| 89 | argtype = arg.pop(0) |
---|
| 90 | if argtype is str: |
---|
| 91 | argtype = [c_void_p, c_char_p, c_int] #char *str, int strlen |
---|
| 92 | elif argtype is np.ndarray: |
---|
| 93 | argtype = [c_void_p, c_void_p, c_void_p] # void *handle, double *data, int* SHAPE(data) |
---|
| 94 | else: |
---|
| 95 | argtype = [c_void_p, argtype] #void *handle, argtype data |
---|
| 96 | for cat in cats: |
---|
| 97 | cxios.import_funs( [arg + argtype], prefix='set_'+cat+'_') |
---|
| 98 | |
---|
| 99 | def import_cxios_functions(): |
---|
| 100 | cats=['axis','domain','domaingroup','field','fieldgroup'] # XIOS categories |
---|
| 101 | cxios.import_funs([ |
---|
| 102 | [cat+'_handle_create' for cat in cats]+[c_void_pp,c_char_p,c_int], |
---|
| 103 | ['get_current_'+'calendar_wrapper',c_void_pp], |
---|
| 104 | ['update_calendar_timestep',c_void_p], |
---|
| 105 | ['update_calendar',c_int] ]) |
---|
| 106 | |
---|
[759] | 107 | import_set_attr(['domain','domaingroup'], [c_int,'ni_glo','nj_glo','ibegin','jbegin','ni','nvertex','data_dim'], [str,'type'], |
---|
| 108 | [np.ndarray, 'i_index','j_index', |
---|
| 109 | 'lonvalue_1d','latvalue_1d','bounds_lat_1d','bounds_lon_1d']) |
---|
[615] | 110 | import_set_attr(['field','fieldgroup'], [Duration,'freq_op','freq_offset']) |
---|
| 111 | import_set_attr(['axis'], [c_int,'n_glo'], [np.ndarray,'value']) |
---|
| 112 | import_set_attr(['calendar_wrapper'], [Duration,'timestep']) |
---|
| 113 | |
---|
| 114 | import_cxios_functions() |
---|