1 | # pyOASIS - A Python wrapper for OASIS |
---|
2 | # Authors: Philippe Gambron, Rupert Ford |
---|
3 | # Copyright (C) 2019 UKRI - STFC |
---|
4 | |
---|
5 | # This program is free software: you can redistribute it and/or modify |
---|
6 | # it under the terms of the GNU Lesser General Public License as |
---|
7 | # published by the Free Software Foundation, either version 3 of the |
---|
8 | # License, or any later version. |
---|
9 | |
---|
10 | # This program is distributed in the hope that it will be useful, |
---|
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | # GNU Lesser General Public License for more details. |
---|
14 | |
---|
15 | # A copy of the GNU Lesser General Public License, version 3, is supplied |
---|
16 | # with this program, in the file lgpl-3.0.txt. It is also available at |
---|
17 | # <https://www.gnu.org/licenses/lgpl-3.0.html>. |
---|
18 | |
---|
19 | |
---|
20 | """Auxiliary OASIS user interfaces""" |
---|
21 | |
---|
22 | import ctypes |
---|
23 | from ctypes import cdll, CDLL, c_int |
---|
24 | import numpy |
---|
25 | import pyoasis.parameters |
---|
26 | |
---|
27 | cdll.LoadLibrary("liboasis.cbind.so") |
---|
28 | LIB = CDLL("liboasis.cbind.so") |
---|
29 | |
---|
30 | LIB.oasis_c_get_localcomm_iso2c.argtypes = [ctypes.POINTER(ctypes.c_int)] |
---|
31 | LIB.oasis_c_get_localcomm_iso2c.restype = ctypes.c_int |
---|
32 | |
---|
33 | |
---|
34 | def get_localcomm(): |
---|
35 | """OASIS user query for the local MPI communicator""" |
---|
36 | localcomm = c_int(0) |
---|
37 | kinfo = c_int(0) |
---|
38 | kinfo = LIB.oasis_c_get_localcomm_iso2c(localcomm) |
---|
39 | return localcomm.value, kinfo |
---|
40 | |
---|
41 | |
---|
42 | LIB.oasis_c_create_couplcomm_iso2c.argtypes = [ctypes.c_int, ctypes.c_int, |
---|
43 | ctypes.POINTER(ctypes.c_int)] |
---|
44 | LIB.oasis_c_create_couplcomm_iso2c.restype = ctypes.c_int |
---|
45 | |
---|
46 | |
---|
47 | def create_couplcomm(icpl, allcomm): |
---|
48 | """OASIS user call to create a new communicator""" |
---|
49 | cplcomm = c_int(0) |
---|
50 | kinfo = c_int(0) |
---|
51 | kinfo = LIB.oasis_c_create_couplcomm_iso2c(icpl, allcomm, cplcomm) |
---|
52 | return cplcomm.value, kinfo |
---|
53 | |
---|
54 | |
---|
55 | LIB.oasis_c_set_couplcomm_iso2c.argtypes = [ctypes.c_int] |
---|
56 | LIB.oasis_c_set_couplcomm_iso2c.restype = ctypes.c_int |
---|
57 | |
---|
58 | |
---|
59 | def set_couplcomm(couplcomm): |
---|
60 | """OASIS user call to specify a local communicator""" |
---|
61 | kinfo = c_int(0) |
---|
62 | kinfo = LIB.oasis_c_set_couplcomm_iso2c(couplcomm.py2f()) |
---|
63 | return kinfo |
---|
64 | |
---|
65 | |
---|
66 | LIB.oasis_c_get_intercomm_iso2c.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_char_p] |
---|
67 | LIB.oasis_c_get_intercomm_iso2c.restype = ctypes.c_int |
---|
68 | |
---|
69 | |
---|
70 | def get_intercomm(cdnam): |
---|
71 | """OASIS user interface to establish an intercomm communicator between the root of two models""" |
---|
72 | new_comm = c_int(0) |
---|
73 | kinfo = c_int(0) |
---|
74 | kinfo = LIB.oasis_c_get_intercomm_iso2c(new_comm, cdnam.encode()) |
---|
75 | return new_comm.value, kinfo |
---|
76 | |
---|
77 | |
---|
78 | LIB.oasis_c_get_intracomm_iso2c.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_char_p] |
---|
79 | LIB.oasis_c_get_intracomm_iso2c.restype = ctypes.c_int |
---|
80 | |
---|
81 | |
---|
82 | def get_intracomm(cdnam): |
---|
83 | """OASIS user interface to establish an intracomm communicator between the root of two models""" |
---|
84 | new_comm = c_int(0) |
---|
85 | kinfo = c_int(0) |
---|
86 | kinfo = LIB.oasis_c_get_intracomm_iso2c(new_comm, cdnam.encode()) |
---|
87 | return new_comm.value, kinfo |
---|
88 | |
---|
89 | |
---|
90 | LIB.oasis_c_get_multi_intracomm_iso2c.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.POINTER(ctypes.c_char_p), ctypes.c_void_p] |
---|
91 | LIB.oasis_c_get_multi_intracomm_iso2c.restype = ctypes.c_int |
---|
92 | |
---|
93 | |
---|
94 | def get_multi_intracomm(cdnam): |
---|
95 | """OASIS user interface to establish an intracomm communicator between the root of more than two models""" |
---|
96 | if isinstance(cdnam, list): |
---|
97 | ncomp = len(cdnam) |
---|
98 | else: |
---|
99 | ncomp = 1 |
---|
100 | cdnam = [cdnam] |
---|
101 | new_comm = c_int(0) |
---|
102 | root_ranks_p = numpy.zeros(ncomp, dtype=numpy.int32) |
---|
103 | cdnam_p = (ctypes.c_char_p * ncomp)() |
---|
104 | for i, comp in enumerate(cdnam): |
---|
105 | cdnam_p[i] = comp.encode() |
---|
106 | kinfo = c_int(0) |
---|
107 | kinfo = LIB.oasis_c_get_multi_intracomm_iso2c(new_comm, c_int(ncomp), cdnam_p, root_ranks_p.ctypes.data) |
---|
108 | root_ranks_l = root_ranks_p.tolist() |
---|
109 | root_ranks = {} |
---|
110 | for key, value in zip(cdnam, root_ranks_l): |
---|
111 | root_ranks[key] = value |
---|
112 | return new_comm.value, root_ranks, kinfo |
---|
113 | |
---|
114 | |
---|
115 | LIB.oasis_c_set_debug.argtypes = [ctypes.c_int] |
---|
116 | LIB.oasis_c_set_debug.restype = ctypes.c_int |
---|
117 | |
---|
118 | |
---|
119 | def set_debug(debug): |
---|
120 | """Set debug level""" |
---|
121 | kinfo = c_int(0) |
---|
122 | kinfo = LIB.oasis_c_set_debug(debug) |
---|
123 | return kinfo |
---|
124 | |
---|
125 | |
---|
126 | LIB.oasis_c_get_debug.argtypes = [ctypes.POINTER(ctypes.c_int)] |
---|
127 | LIB.oasis_c_get_debug.restype = ctypes.c_int |
---|
128 | |
---|
129 | |
---|
130 | def get_debug(): |
---|
131 | """Get debug level""" |
---|
132 | debug = c_int(0) |
---|
133 | kinfo = c_int(0) |
---|
134 | kinfo = LIB.oasis_c_get_debug(debug) |
---|
135 | return debug.value, kinfo |
---|
136 | |
---|
137 | |
---|
138 | LIB.oasis_c_put_inquire.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int)] |
---|
139 | LIB.oasis_c_put_inquire.restype = ctypes.c_int |
---|
140 | |
---|
141 | |
---|
142 | def put_inquire(varid, msec): |
---|
143 | """Gives put return code expected at a specified time |
---|
144 | for a given variable""" |
---|
145 | kinfo = c_int(0) |
---|
146 | ierr = c_int(0) |
---|
147 | ierr = LIB.oasis_c_put_inquire(varid, msec, kinfo) |
---|
148 | return kinfo.value, ierr |
---|
149 | |
---|
150 | |
---|
151 | LIB.oasis_c_get_ncpl.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)] |
---|
152 | LIB.oasis_c_get_ncpl.restype = ctypes.c_int |
---|
153 | |
---|
154 | |
---|
155 | def get_ncpl(varid): |
---|
156 | """Returns the number of unique couplings associated with |
---|
157 | a variable.""" |
---|
158 | ncpl = c_int(0) |
---|
159 | kinfo = c_int(0) |
---|
160 | kinfo = LIB.oasis_c_get_ncpl(varid, ncpl) |
---|
161 | return ncpl.value, kinfo |
---|
162 | |
---|
163 | |
---|
164 | LIB.oasis_c_get_freqs.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, |
---|
165 | ctypes.c_void_p] |
---|
166 | LIB.oasis_c_get_freqs.restype = ctypes.c_int |
---|
167 | |
---|
168 | |
---|
169 | def get_freqs(varid, mop, ncpl): |
---|
170 | """Returns the coupling periods for a given variable.""" |
---|
171 | cpl_freqs_p = numpy.zeros(ncpl, dtype=numpy.int32) |
---|
172 | kinfo = c_int(0) |
---|
173 | kinfo = LIB.oasis_c_get_freqs(varid, c_int(mop), c_int(ncpl), cpl_freqs_p.ctypes.data) |
---|
174 | cpl_freqs = cpl_freqs_p.tolist() |
---|
175 | return cpl_freqs, kinfo |
---|
176 | |
---|
177 | |
---|
178 | def get_freqs_array(varid, mop): |
---|
179 | """Returns the coupling periods for a given variable.""" |
---|
180 | ncpl, kinfo = get_ncpl(varid) |
---|
181 | return get_freqs(varid, mop, ncpl) |
---|