1 | from dynamico.dev.libs import libxios |
---|
2 | from dynamico.dev import wrap |
---|
3 | import numpy as np |
---|
4 | |
---|
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 | |
---|
9 | from dynamico import getargs |
---|
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 | |
---|
14 | # ------------- Direct cython interfaces ----------------- # |
---|
15 | |
---|
16 | cdef extern from "functions.h": |
---|
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) |
---|
23 | |
---|
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) |
---|
35 | # print 'cxios.write_data', id, data.shape |
---|
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 | |
---|
41 | # -------------------------------------------------------- # |
---|
42 | |
---|
43 | lib=wrap.Struct() |
---|
44 | cxios = wrap.SharedLib(vars(lib), libxios, prefix_so='cxios_') |
---|
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 |
---|
66 | # print 'Handle', cat, self.id, self.handle |
---|
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 |
---|
72 | if type(value) in (int,c_int,np.int64,np.int32): |
---|
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) |
---|
83 | DEBUG('%s.%s %s %s' % (self.id, prefix+key, type(value), extra) ) |
---|
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 | |
---|
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']) |
---|
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() |
---|