1 | |
---|
2 | !> OASIS map (interpolation) data and methods |
---|
3 | |
---|
4 | |
---|
5 | MODULE mod_oasis_map |
---|
6 | |
---|
7 | USE mod_oasis_kinds |
---|
8 | USE mod_oasis_data |
---|
9 | USE mod_oasis_parameters |
---|
10 | USE mod_oasis_namcouple |
---|
11 | USE mod_oasis_sys |
---|
12 | USE mod_oasis_part |
---|
13 | USE mod_oasis_var |
---|
14 | USE mod_oasis_mpi |
---|
15 | USE mod_oasis_string |
---|
16 | USE mod_oasis_io |
---|
17 | USE mod_oasis_timer |
---|
18 | USE mct_mod |
---|
19 | USE grids ! scrip |
---|
20 | USE netcdf |
---|
21 | |
---|
22 | IMPLICIT NONE |
---|
23 | |
---|
24 | private |
---|
25 | |
---|
26 | public oasis_map_genmap |
---|
27 | public oasis_map_sMatReaddnc_orig |
---|
28 | public oasis_map_sMatReaddnc_ceg |
---|
29 | |
---|
30 | !--- Type of data |
---|
31 | |
---|
32 | public prism_mapper_type |
---|
33 | |
---|
34 | !> Mapper data for interpolating data between grids |
---|
35 | type prism_mapper_type |
---|
36 | !--- fixed at initialization --- |
---|
37 | type(mct_sMatP),pointer :: sMatP(:) !< stores mapping data such as weights |
---|
38 | integer(kind=ip_i4_p) :: nwgts !< number of weights in weights file |
---|
39 | character(len=ic_long):: file !< file to read/write |
---|
40 | character(len=ic_long):: file2 !< alternate file to read/write |
---|
41 | character(len=ic_med) :: loc !< location setting, src or dst model |
---|
42 | character(len=ic_med) :: opt !< optimization setting, bfb, sum, or opt |
---|
43 | character(len=ic_med) :: optval !< mct map setting, src or dst, derived from opt |
---|
44 | logical :: init !< flag indicating initialization complete |
---|
45 | integer(kind=ip_i4_p) :: spart !< src partition |
---|
46 | integer(kind=ip_i4_p) :: dpart !< dst partition |
---|
47 | character(len=ic_med) :: srcgrid !< source grid name |
---|
48 | character(len=ic_med) :: dstgrid !< target grid name |
---|
49 | end type prism_mapper_type |
---|
50 | |
---|
51 | integer(kind=ip_i4_p) ,public :: prism_mmapper !< max mappers |
---|
52 | integer(kind=ip_i4_p) ,public :: prism_nmapper = 0 !< mapper counter |
---|
53 | type(prism_mapper_type) ,public, pointer :: prism_mapper(:) !< list of defined mappers |
---|
54 | |
---|
55 | !--- local kinds --- |
---|
56 | |
---|
57 | integer,private,parameter :: R8 = ip_double_p |
---|
58 | integer,private,parameter :: IN = ip_i4_p |
---|
59 | |
---|
60 | !--- variable assocaited with local data buffers and reallocation |
---|
61 | |
---|
62 | real(R8),private,allocatable :: Snew(:,:),Sold(:,:) ! reals |
---|
63 | integer,private,allocatable :: Rnew(:),Rold(:) ! ints |
---|
64 | integer,private,allocatable :: Cnew(:),Cold(:) ! ints |
---|
65 | |
---|
66 | logical, parameter :: local_timers_on = .false. |
---|
67 | |
---|
68 | !------------------------------------------------------------ |
---|
69 | CONTAINS |
---|
70 | !------------------------------------------------------------ |
---|
71 | |
---|
72 | !------------------------------------------------------------ |
---|
73 | |
---|
74 | !> Routine to generate mapping weights data via a direct SCRIP call |
---|
75 | |
---|
76 | !> This routine reads in grid data from files and passes that data |
---|
77 | !> to SCRIP. Mapping weights are generated and written to a file. |
---|
78 | !> This entire operation is done on a single task. |
---|
79 | |
---|
80 | SUBROUTINE oasis_map_genmap(mapid,namid) |
---|
81 | |
---|
82 | IMPLICIT NONE |
---|
83 | |
---|
84 | integer(ip_i4_p), intent(in) :: mapid !< map id |
---|
85 | integer(ip_i4_p), intent(in) :: namid !< namcouple id |
---|
86 | !---------------------------------------------------------- |
---|
87 | |
---|
88 | integer(ip_i4_p) :: src_size,src_rank, ncrn_src |
---|
89 | integer(ip_i4_p) ,allocatable :: src_dims(:),src_mask(:) |
---|
90 | real(ip_double_p),allocatable :: src_lon(:),src_lat(:) |
---|
91 | real(ip_double_p),allocatable :: src_area(:) |
---|
92 | real(ip_double_p),allocatable :: src_corner_lon(:,:),src_corner_lat(:,:) |
---|
93 | integer(ip_i4_p) :: dst_size,dst_rank, ncrn_dst |
---|
94 | integer(ip_i4_p) ,allocatable :: dst_dims(:),dst_mask(:) |
---|
95 | real(ip_double_p),allocatable :: dst_lon(:),dst_lat(:) |
---|
96 | real(ip_double_p),allocatable :: dst_area(:) |
---|
97 | real(ip_double_p),allocatable :: dst_corner_lon(:,:),dst_corner_lat(:,:) |
---|
98 | integer(ip_i4_p) ,allocatable :: ifld2(:,:) |
---|
99 | real(ip_double_p),allocatable :: fld2(:,:),fld3(:,:,:) |
---|
100 | integer(ip_i4_p) :: i,j,k,icnt,nx,ny,nc |
---|
101 | logical :: lextrapdone |
---|
102 | logical :: do_corners |
---|
103 | logical :: ll_src_area_in |
---|
104 | logical :: ll_dst_area_in |
---|
105 | character(len=ic_med) :: filename |
---|
106 | character(len=ic_med) :: fldname |
---|
107 | character(len=*),parameter :: subname = '(oasis_map_genmap)' |
---|
108 | |
---|
109 | call oasis_debug_enter(subname) |
---|
110 | |
---|
111 | lextrapdone = .false. |
---|
112 | nx = -1 ! must be read |
---|
113 | ny = -1 ! must be read |
---|
114 | nc = 1 ! might not be read, set to something reasonable |
---|
115 | |
---|
116 | !--- checks first --- |
---|
117 | |
---|
118 | if (trim(namscrtyp(namID)) /= 'SCALAR') then |
---|
119 | write(nulprt,*) subname,estr,'only scrip type SCALAR mapping supported' |
---|
120 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
121 | endif |
---|
122 | |
---|
123 | do_corners = .false. |
---|
124 | if (trim(namscrmet(namID)) == 'CONSERV') then |
---|
125 | do_corners = .true. |
---|
126 | endif |
---|
127 | |
---|
128 | !--- src data --- |
---|
129 | |
---|
130 | filename = 'grids.nc' |
---|
131 | if (do_corners) then |
---|
132 | fldname = trim(namsrcgrd(namID))//'.clo' |
---|
133 | call oasis_io_read_field_fromroot(filename,fldname,nx=nx,ny=ny,nz=nc) |
---|
134 | else |
---|
135 | fldname = trim(namsrcgrd(namID))//'.lon' |
---|
136 | call oasis_io_read_field_fromroot(filename,fldname,nx=nx,ny=ny) |
---|
137 | endif |
---|
138 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',& |
---|
139 | trim(fldname),nx,ny,nc,do_corners |
---|
140 | src_rank = 2 |
---|
141 | src_size = nx*ny |
---|
142 | allocate(src_dims(src_rank)) |
---|
143 | src_dims(1) = nx |
---|
144 | src_dims(2) = ny |
---|
145 | ncrn_src = nc |
---|
146 | allocate(src_mask(src_size)) |
---|
147 | allocate(src_lon (src_size)) |
---|
148 | allocate(src_lat (src_size)) |
---|
149 | allocate(src_area (src_size)) |
---|
150 | allocate(src_corner_lon(ncrn_src,src_size)) |
---|
151 | allocate(src_corner_lat(ncrn_src,src_size)) |
---|
152 | |
---|
153 | filename = 'masks.nc' |
---|
154 | fldname = trim(namsrcgrd(namID))//'.msk' |
---|
155 | allocate(ifld2(nx,ny)) |
---|
156 | call oasis_io_read_field_fromroot(filename,fldname,ifld2=ifld2) |
---|
157 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
158 | src_mask(icnt) = ifld2(i,j) |
---|
159 | enddo; enddo |
---|
160 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
161 | minval(src_mask),maxval(src_mask) |
---|
162 | deallocate(ifld2) |
---|
163 | |
---|
164 | allocate(fld2(nx,ny)) |
---|
165 | |
---|
166 | filename = 'areas.nc' |
---|
167 | fldname = trim(namsrcgrd(namID))//'.srf' |
---|
168 | if (oasis_io_varexists(filename,fldname)) then |
---|
169 | ll_src_area_in = .true. |
---|
170 | call oasis_io_read_field_fromroot(filename,fldname,fld2=fld2) |
---|
171 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
172 | src_area(icnt) = fld2(i,j) |
---|
173 | enddo; enddo |
---|
174 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
175 | minval(src_area),maxval(src_area) |
---|
176 | else |
---|
177 | ll_src_area_in = .false. |
---|
178 | src_area = -9999. |
---|
179 | endif |
---|
180 | |
---|
181 | filename = 'grids.nc' |
---|
182 | fldname = trim(namsrcgrd(namID))//'.lon' |
---|
183 | call oasis_io_read_field_fromroot(filename,fldname,fld2=fld2) |
---|
184 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
185 | src_lon(icnt) = fld2(i,j) |
---|
186 | enddo; enddo |
---|
187 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
188 | minval(src_lon),maxval(src_lon) |
---|
189 | |
---|
190 | fldname = trim(namsrcgrd(namID))//'.lat' |
---|
191 | call oasis_io_read_field_fromroot(filename,fldname,fld2=fld2) |
---|
192 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
193 | src_lat(icnt) = fld2(i,j) |
---|
194 | enddo; enddo |
---|
195 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
196 | minval(src_lat),maxval(src_lat) |
---|
197 | |
---|
198 | deallocate(fld2) |
---|
199 | |
---|
200 | if (do_corners) then |
---|
201 | allocate(fld3(nx,ny,nc)) |
---|
202 | filename = 'grids.nc' |
---|
203 | fldname = trim(namsrcgrd(namID))//'.clo' |
---|
204 | call oasis_io_read_field_fromroot(filename,fldname,fld3=fld3) |
---|
205 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
206 | do k = 1,nc |
---|
207 | src_corner_lon(k,icnt) = fld3(i,j,k) |
---|
208 | enddo |
---|
209 | enddo; enddo |
---|
210 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
211 | minval(src_corner_lon),maxval(src_corner_lon) |
---|
212 | fldname = trim(namsrcgrd(namID))//'.cla' |
---|
213 | call oasis_io_read_field_fromroot(filename,fldname,fld3=fld3) |
---|
214 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
215 | do k = 1,nc |
---|
216 | src_corner_lat(k,icnt) = fld3(i,j,k) |
---|
217 | enddo |
---|
218 | enddo; enddo |
---|
219 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
220 | minval(src_corner_lat),maxval(src_corner_lat) |
---|
221 | deallocate(fld3) |
---|
222 | else |
---|
223 | src_corner_lon = -9999. |
---|
224 | src_corner_lat = -9999. |
---|
225 | endif |
---|
226 | |
---|
227 | !--- dst data --- |
---|
228 | |
---|
229 | filename = 'grids.nc' |
---|
230 | if (do_corners) then |
---|
231 | fldname = trim(namdstgrd(namID))//'.clo' |
---|
232 | call oasis_io_read_field_fromroot(filename,fldname,nx=nx,ny=ny,nz=nc) |
---|
233 | else |
---|
234 | fldname = trim(namdstgrd(namID))//'.lon' |
---|
235 | call oasis_io_read_field_fromroot(filename,fldname,nx=nx,ny=ny) |
---|
236 | endif |
---|
237 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname),nx,ny,nc |
---|
238 | dst_rank = 2 |
---|
239 | dst_size = nx*ny |
---|
240 | allocate(dst_dims(dst_rank)) |
---|
241 | dst_dims(1) = nx |
---|
242 | dst_dims(2) = ny |
---|
243 | ncrn_dst = nc |
---|
244 | allocate(dst_mask(dst_size)) |
---|
245 | allocate(dst_lon (dst_size)) |
---|
246 | allocate(dst_lat (dst_size)) |
---|
247 | allocate(dst_area (dst_size)) |
---|
248 | allocate(dst_corner_lon(ncrn_dst,dst_size)) |
---|
249 | allocate(dst_corner_lat(ncrn_dst,dst_size)) |
---|
250 | |
---|
251 | filename = 'masks.nc' |
---|
252 | fldname = trim(namdstgrd(namID))//'.msk' |
---|
253 | allocate(ifld2(nx,ny)) |
---|
254 | call oasis_io_read_field_fromroot(filename,fldname,ifld2=ifld2) |
---|
255 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
256 | dst_mask(icnt) = ifld2(i,j) |
---|
257 | enddo; enddo |
---|
258 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
259 | minval(dst_mask),maxval(dst_mask) |
---|
260 | deallocate(ifld2) |
---|
261 | |
---|
262 | allocate(fld2(nx,ny)) |
---|
263 | |
---|
264 | filename = 'areas.nc' |
---|
265 | fldname = trim(namdstgrd(namID))//'.srf' |
---|
266 | if (oasis_io_varexists(filename,fldname)) then |
---|
267 | ll_dst_area_in = .true. |
---|
268 | call oasis_io_read_field_fromroot(filename,fldname,fld2=fld2) |
---|
269 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
270 | dst_area(icnt) = fld2(i,j) |
---|
271 | enddo; enddo |
---|
272 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
273 | minval(dst_area),maxval(dst_area) |
---|
274 | else |
---|
275 | ll_dst_area_in = .false. |
---|
276 | dst_area = -9999. |
---|
277 | endif |
---|
278 | |
---|
279 | filename = 'grids.nc' |
---|
280 | fldname = trim(namdstgrd(namID))//'.lon' |
---|
281 | call oasis_io_read_field_fromroot(filename,fldname,fld2=fld2) |
---|
282 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
283 | dst_lon(icnt) = fld2(i,j) |
---|
284 | enddo; enddo |
---|
285 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
286 | minval(dst_lon),maxval(dst_lon) |
---|
287 | |
---|
288 | fldname = trim(namdstgrd(namID))//'.lat' |
---|
289 | call oasis_io_read_field_fromroot(filename,fldname,fld2=fld2) |
---|
290 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
291 | dst_lat(icnt) = fld2(i,j) |
---|
292 | enddo; enddo |
---|
293 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
294 | minval(dst_lat),maxval(dst_lat) |
---|
295 | |
---|
296 | deallocate(fld2) |
---|
297 | |
---|
298 | if (do_corners) then |
---|
299 | allocate(fld3(nx,ny,nc)) |
---|
300 | filename = 'grids.nc' |
---|
301 | fldname = trim(namdstgrd(namID))//'.clo' |
---|
302 | call oasis_io_read_field_fromroot(filename,fldname,fld3=fld3) |
---|
303 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
304 | do k = 1,nc |
---|
305 | dst_corner_lon(k,icnt) = fld3(i,j,k) |
---|
306 | enddo |
---|
307 | enddo; enddo |
---|
308 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
309 | minval(dst_corner_lon),maxval(dst_corner_lon) |
---|
310 | fldname = trim(namdstgrd(namID))//'.cla' |
---|
311 | call oasis_io_read_field_fromroot(filename,fldname,fld3=fld3) |
---|
312 | icnt = 0; do j = 1,ny; do i = 1,nx; icnt = icnt + 1 |
---|
313 | do k = 1,nc |
---|
314 | dst_corner_lat(k,icnt) = fld3(i,j,k) |
---|
315 | enddo |
---|
316 | enddo; enddo |
---|
317 | if (OASIS_debug >= 15) write(nulprt,*) subname,' read ',trim(filename),' ',trim(fldname), & |
---|
318 | minval(dst_corner_lat),maxval(dst_corner_lat) |
---|
319 | deallocate(fld3) |
---|
320 | else |
---|
321 | dst_corner_lon = -9999. |
---|
322 | dst_corner_lat = -9999. |
---|
323 | endif |
---|
324 | |
---|
325 | if (OASIS_debug >= 15) THEN |
---|
326 | write(nulprt,*) subname,' call grid_init ' |
---|
327 | call oasis_flush(nulprt) |
---|
328 | endif |
---|
329 | |
---|
330 | !--- 0/1 mask convention opposite in scrip vs oasis |
---|
331 | src_mask = 1 - src_mask |
---|
332 | dst_mask = 1 - dst_mask |
---|
333 | call grid_init(namscrmet(namID),namscrres(namID),namscrbin(namID), & |
---|
334 | src_size, dst_size, src_dims, dst_dims, & |
---|
335 | src_rank, dst_rank, ncrn_src, ncrn_dst, & |
---|
336 | src_mask, dst_mask, namsrcgrd(namID), namdstgrd(namID), & |
---|
337 | src_lat, src_lon, dst_lat, dst_lon, & |
---|
338 | src_corner_lat, src_corner_lon, & |
---|
339 | dst_corner_lat, dst_corner_lon, & |
---|
340 | ll_src_area_in, src_area, & |
---|
341 | ll_dst_area_in, dst_area, & |
---|
342 | ilogunit=nulprt,ilogprt=OASIS_debug) |
---|
343 | if (OASIS_debug >= 15) then |
---|
344 | write(nulprt,*) subname,' done grid_init ' |
---|
345 | call oasis_flush(nulprt) |
---|
346 | endif |
---|
347 | |
---|
348 | if (OASIS_debug >= 15) THEN |
---|
349 | write(nulprt,*) subname,' call scrip ' |
---|
350 | call oasis_flush(nulprt) |
---|
351 | endif |
---|
352 | if (local_timers_on) call oasis_timer_start('cpl_genmap_scrip') |
---|
353 | call scrip(prism_mapper(mapid)%file,prism_mapper(mapid)%file,namscrmet(namID), & |
---|
354 | namscrnor(namID),lextrapdone,namscrvam(namID),namscrnbr(namID),namscrord(namID), & |
---|
355 | namscrnth(namID),namscrsth(namID), & |
---|
356 | mpi_comm_map, mpi_size_map, mpi_rank_map, mpi_root_map, namcdftyp) |
---|
357 | if (local_timers_on) call oasis_timer_stop('cpl_genmap_scrip') |
---|
358 | if (OASIS_debug >= 15) THEN |
---|
359 | write(nulprt,*) subname,' done scrip ' |
---|
360 | call oasis_flush(nulprt) |
---|
361 | endif |
---|
362 | |
---|
363 | deallocate(src_dims, dst_dims) |
---|
364 | deallocate(src_mask) |
---|
365 | deallocate(src_lon) |
---|
366 | deallocate(src_lat) |
---|
367 | deallocate(src_area) |
---|
368 | deallocate(src_corner_lon) |
---|
369 | deallocate(src_corner_lat) |
---|
370 | deallocate(dst_mask) |
---|
371 | deallocate(dst_lon) |
---|
372 | deallocate(dst_lat) |
---|
373 | deallocate(dst_area) |
---|
374 | deallocate(dst_corner_lon) |
---|
375 | deallocate(dst_corner_lat) |
---|
376 | |
---|
377 | |
---|
378 | call oasis_debug_exit(subname) |
---|
379 | |
---|
380 | END SUBROUTINE oasis_map_genmap |
---|
381 | |
---|
382 | !------------------------------------------------------------ |
---|
383 | !BOP =========================================================================== |
---|
384 | !> Read in mapping matrix data from a SCRIP netCDF weights file |
---|
385 | ! |
---|
386 | ! !IROUTINE: oasis_map_sMatReaddnc_orig - Do a distributed read of a NetCDF SCRIP file and |
---|
387 | ! return weights in a distributed SparseMatrix |
---|
388 | ! |
---|
389 | ! !DESCRIPTION: |
---|
390 | !> Read in mapping matrix data from a SCRIP netCDF data file using |
---|
391 | !> a low memory method and then scatter to all pes. Based on |
---|
392 | !> the sMatReaddnc method from CESM1.0.3. |
---|
393 | !> |
---|
394 | ! !REMARKS: |
---|
395 | !> This routine leverages gsmaps to determine scatter pattern. |
---|
396 | !> |
---|
397 | !> The scatter is implemented as a broadcast of all weights then a local |
---|
398 | !> computation on each pe to determine with weights to keep based |
---|
399 | !> on gsmap information. |
---|
400 | !> |
---|
401 | !> The algorithm to determine whether a weight belongs on a pe involves |
---|
402 | !> creating a couple local arrays (lsstart and lscount) which are |
---|
403 | !> the local values of start and length from the gsmap. These are |
---|
404 | !> sorted via a bubble sort and then searched via a binary search |
---|
405 | !> to check whether a global index is on the local pe. |
---|
406 | !> |
---|
407 | !> The local buffer sizes are estimated up front based on ngridcell/npes |
---|
408 | !> plus 20% (search for 1.2 below). If the local buffer size fills up, then |
---|
409 | !> the buffer is reallocated 50% larger (search for 1.5 below) and the fill |
---|
410 | !> continues. The idea is to trade off memory reallocation and copy |
---|
411 | !> with memory usage. 1.2 and 1.5 are arbitary, other values may |
---|
412 | !> result in better performance. |
---|
413 | !> |
---|
414 | !> Once all the matrix weights have been read, the sMat is initialized, |
---|
415 | !> the values from the buffers are copied in, and everything is deallocated. |
---|
416 | ! |
---|
417 | ! !INTERFACE: ----------------------------------------------------------------- |
---|
418 | |
---|
419 | subroutine oasis_map_sMatReaddnc_orig(sMat,SgsMap,DgsMap,newdom, & |
---|
420 | fileName,mytask,mpicom,nwgts, & |
---|
421 | areasrc,areadst,ni_i,nj_i,ni_o,nj_o ) |
---|
422 | |
---|
423 | ! !USES: |
---|
424 | |
---|
425 | !--- local kinds --- |
---|
426 | integer,parameter :: R8 = ip_double_p |
---|
427 | integer,parameter :: IN = ip_i4_p |
---|
428 | |
---|
429 | ! !INPUT/OUTPUT PARAMETERS: |
---|
430 | |
---|
431 | type(mct_sMat) ,intent(out),pointer :: sMat(:) !< mapping data |
---|
432 | type(mct_gsMap) ,intent(in) ,target :: SgsMap !< src gsmap |
---|
433 | type(mct_gSMap) ,intent(in) ,target :: DgsMap !< dst gsmap |
---|
434 | character(*) ,intent(in) :: newdom !< type of sMat (src or dst) |
---|
435 | !< src = rearrange and map (bfb), dst = map and rearrange (partial sums) |
---|
436 | character(*) ,intent(in) :: filename!< netCDF file to read |
---|
437 | integer(IN) ,intent(in) :: mytask !< processor id |
---|
438 | integer(IN) ,intent(in) :: mpicom !< mpi communicator |
---|
439 | integer(IN) ,intent(out) :: nwgts !< number of weights |
---|
440 | type(mct_Avect) ,intent(out), optional :: areasrc !< area of src grid from mapping file |
---|
441 | type(mct_Avect) ,intent(out), optional :: areadst !< area of dst grid from mapping file |
---|
442 | integer(IN) ,intent(out), optional :: ni_i !< number of lons on input grid |
---|
443 | integer(IN) ,intent(out), optional :: nj_i !< number of lats on input grid |
---|
444 | integer(IN) ,intent(out), optional :: ni_o !< number of lons on output grid |
---|
445 | integer(IN) ,intent(out), optional :: nj_o !< number of lats on output grid |
---|
446 | |
---|
447 | ! !EOP |
---|
448 | |
---|
449 | !--- local --- |
---|
450 | integer :: n,m ! generic loop indicies |
---|
451 | integer :: na ! size of source domain |
---|
452 | integer :: nb ! size of destination domain |
---|
453 | integer :: ns ! number of non-zero elements in matrix |
---|
454 | integer :: ni,nj ! number of row and col in the matrix |
---|
455 | integer :: igrow ! aVect index for matrix row |
---|
456 | integer :: igcol ! aVect index for matrix column |
---|
457 | integer :: iwgt ! aVect index for matrix element |
---|
458 | integer :: iarea ! aVect index for area |
---|
459 | integer :: rsize ! size of read buffer |
---|
460 | integer :: cnt ! local num of wgts |
---|
461 | integer :: cntold ! local num of wgts, previous read |
---|
462 | integer :: start(1)! netcdf read |
---|
463 | integer :: count(1)! netcdf read |
---|
464 | integer :: start2(2)! netcdf read |
---|
465 | integer :: count2(2)! netcdf read |
---|
466 | integer :: bsize ! buffer size |
---|
467 | integer :: nread ! number of reads |
---|
468 | logical :: mywt ! does this weight belong on my pe |
---|
469 | integer :: dims(2) |
---|
470 | logical :: abort_weight ! flag if bad weight found |
---|
471 | |
---|
472 | !--- buffers for i/o --- |
---|
473 | real(R8) ,allocatable :: rtemp(:) ! real temporary |
---|
474 | real(R8) ,allocatable :: Sbuf(:,:) ! real weights |
---|
475 | real(R8) ,allocatable :: remaps(:,:) ! real weights with num_wgts dim |
---|
476 | integer,allocatable :: Rbuf(:) ! ints rows |
---|
477 | integer,allocatable :: Cbuf(:) ! ints cols |
---|
478 | |
---|
479 | !--- variables associated with local computation of global indices |
---|
480 | integer :: lsize ! size of local seg map |
---|
481 | integer :: commsize ! size of local communicator |
---|
482 | integer,allocatable :: lsstart(:) ! local seg map info |
---|
483 | integer,allocatable :: lscount(:) ! local seg map info |
---|
484 | type(mct_gsMap),pointer :: mygsmap ! pointer to one of the gsmaps |
---|
485 | integer :: l1,l2 ! generice indices for sort |
---|
486 | logical :: found ! for sort |
---|
487 | |
---|
488 | !--- variable assocaited with local data buffers and reallocation |
---|
489 | real(R8) ,allocatable :: Snew(:,:),Sold(:,:) ! reals |
---|
490 | integer,allocatable :: Rnew(:),Rold(:) ! ints |
---|
491 | integer,allocatable :: Cnew(:),Cold(:) ! ints |
---|
492 | |
---|
493 | character,allocatable :: str(:) ! variable length char string |
---|
494 | character(len=ic_long):: attstr ! netCDF attribute name string |
---|
495 | integer :: status ! netCDF routine return code |
---|
496 | integer :: fid ! netCDF file ID |
---|
497 | integer :: vid ! netCDF variable ID |
---|
498 | integer :: did ! netCDF dimension ID |
---|
499 | !--- arbitrary size of read buffer, this is the chunk size weights reading |
---|
500 | integer,parameter :: rbuf_size = 100000 |
---|
501 | |
---|
502 | !--- global source and destination areas --- |
---|
503 | type(mct_Avect) :: areasrc0 ! area of src grid from mapping file |
---|
504 | type(mct_Avect) :: areadst0 ! area of src grid from mapping file |
---|
505 | |
---|
506 | character(*),parameter :: areaAV_field = 'aream' |
---|
507 | |
---|
508 | !--- formats --- |
---|
509 | character(*),parameter :: subName = '(oasis_map_sMatReaddnc_orig)' |
---|
510 | |
---|
511 | !------------------------------------------------------------------------------- |
---|
512 | ! |
---|
513 | !------------------------------------------------------------------------------- |
---|
514 | |
---|
515 | call oasis_debug_enter(subname) |
---|
516 | call oasis_mpi_commsize(mpicom,commsize) |
---|
517 | nwgts = -1 |
---|
518 | if (local_timers_on) call oasis_timer_start('map_read_orig_read') |
---|
519 | |
---|
520 | if (mytask == 0) then |
---|
521 | if (OASIS_debug >= 2) write(nulprt,*) subname," reading mapping matrix data decomposed..." |
---|
522 | |
---|
523 | !---------------------------------------------------------------------------- |
---|
524 | !> * Open and read the file SCRIP weights size on the root task |
---|
525 | !---------------------------------------------------------------------------- |
---|
526 | |
---|
527 | if (OASIS_debug >=2 ) write(nulprt,*) subname," * file name : ",trim(fileName) |
---|
528 | status = nf90_open(trim(filename),NF90_NOWRITE,fid) |
---|
529 | if (status /= NF90_NOERR) then |
---|
530 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
531 | write(nulprt,*) subname,estr,'mapping file not found = ',trim(filename) |
---|
532 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
533 | endif |
---|
534 | |
---|
535 | !--- get matrix dimensions ---------- |
---|
536 | ! status = nf90_inq_dimid (fid, 'n_s', did) ! size of sparse matrix |
---|
537 | status = nf90_inq_dimid (fid, 'num_links', did) ! size of sparse matrix |
---|
538 | if (status /= NF90_NOERR) then |
---|
539 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
540 | write(nulprt,*) subname,estr,'mapping file not found = ',trim(filename) |
---|
541 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
542 | endif |
---|
543 | status = nf90_inquire_dimension(fid, did , len = ns) |
---|
544 | if (status /= NF90_NOERR) then |
---|
545 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
546 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
547 | endif |
---|
548 | ! status = nf90_inq_dimid (fid, 'n_a', did) ! size of input vector |
---|
549 | status = nf90_inq_dimid (fid, 'src_grid_size', did) ! size of input vector |
---|
550 | if (status /= NF90_NOERR) then |
---|
551 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
552 | write(nulprt,*) subname,estr,'dim not found = ','src_grid_size' |
---|
553 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
554 | endif |
---|
555 | status = nf90_inquire_dimension(fid, did , len = na) |
---|
556 | if (status /= NF90_NOERR) then |
---|
557 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
558 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
559 | endif |
---|
560 | ! status = nf90_inq_dimid (fid, 'n_b', did) ! size of output vector |
---|
561 | status = nf90_inq_dimid (fid, 'dst_grid_size', did) ! size of output vector |
---|
562 | if (status /= NF90_NOERR) then |
---|
563 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
564 | write(nulprt,*) subname,estr,'dim not found = ','dst_grid_size' |
---|
565 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
566 | endif |
---|
567 | status = nf90_inquire_dimension(fid, did , len = nb) |
---|
568 | if (status /= NF90_NOERR) then |
---|
569 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
570 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
571 | endif |
---|
572 | status = nf90_inq_dimid (fid, 'num_wgts', did) ! size of output vector |
---|
573 | if (status /= NF90_NOERR) then |
---|
574 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
575 | write(nulprt,*) subname,estr,'dim not found = ','num_wgts' |
---|
576 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
577 | endif |
---|
578 | status = nf90_inquire_dimension(fid, did , len = nwgts) |
---|
579 | if (status /= NF90_NOERR) then |
---|
580 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
581 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
582 | endif |
---|
583 | |
---|
584 | if (present(ni_i) .and. present(nj_i) .and. present(ni_o) .and. present(nj_o)) then |
---|
585 | ! status = nf90_inq_dimid (fid, 'ni_a', did) ! number of lons in input grid |
---|
586 | ! status = nf90_inquire_dimension(fid, did , len = ni_i) |
---|
587 | ! status = nf90_inq_dimid (fid, 'nj_a', did) ! number of lats in input grid |
---|
588 | ! status = nf90_inquire_dimension(fid, did , len = nj_i) |
---|
589 | ! status = nf90_inq_dimid (fid, 'ni_b', did) ! number of lons in output grid |
---|
590 | ! status = nf90_inquire_dimension(fid, did , len = ni_o) |
---|
591 | ! status = nf90_inq_dimid (fid, 'nj_b', did) ! number of lats in output grid |
---|
592 | ! status = nf90_inquire_dimension(fid, did , len = nj_o) |
---|
593 | status = nf90_inq_varid(fid, 'src_grid_dims', vid) |
---|
594 | if (status /= NF90_NOERR) then |
---|
595 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
596 | write(nulprt,*) subname,estr,'var not found = ','src_grid_dims' |
---|
597 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
598 | endif |
---|
599 | status = nf90_get_var(fid, vid, dims) |
---|
600 | if (status /= NF90_NOERR) then |
---|
601 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
602 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
603 | endif |
---|
604 | ni_i = dims(1) |
---|
605 | nj_i = dims(2) |
---|
606 | status = nf90_inq_varid(fid, 'dst_grid_dims', vid) |
---|
607 | if (status /= NF90_NOERR) then |
---|
608 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
609 | write(nulprt,*) subname,estr,'var not found = ','dst_grid_dims' |
---|
610 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
611 | endif |
---|
612 | status = nf90_get_var(fid, vid, dims) |
---|
613 | if (status /= NF90_NOERR) then |
---|
614 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
615 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
616 | endif |
---|
617 | ni_o = dims(1) |
---|
618 | nj_o = dims(2) |
---|
619 | end if |
---|
620 | |
---|
621 | if (OASIS_debug >= 2) write(nulprt,*) subname," * matrix dims src x dst : ",na,' x',nb |
---|
622 | if (OASIS_debug >= 2) write(nulprt,*) subname," * number of non-zero elements: ",ns |
---|
623 | |
---|
624 | endif |
---|
625 | |
---|
626 | !---------------------------------------------------------------------------- |
---|
627 | !> * Read and load area_a on root task |
---|
628 | !---------------------------------------------------------------------------- |
---|
629 | |
---|
630 | if (present(areasrc)) then |
---|
631 | if (mytask == 0) then |
---|
632 | call mct_aVect_init(areasrc0,' ',areaAV_field,na) |
---|
633 | ! status = nf90_inq_varid (fid,'area_a',vid) |
---|
634 | status = nf90_inq_varid (fid,'src_grid_area',vid) |
---|
635 | if (status /= NF90_NOERR) THEN |
---|
636 | write(nulprt,*) subname,' nf90_strerrr = ',TRIM(nf90_strerror(status)) |
---|
637 | write(nulprt,*) subname,estr,'var not found = ','src_grid_area' |
---|
638 | call oasis_flush(nulprt) |
---|
639 | endif |
---|
640 | status = nf90_get_var(fid, vid, areasrc0%rAttr) |
---|
641 | if (status /= NF90_NOERR) THEN |
---|
642 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
643 | call oasis_flush(nulprt) |
---|
644 | endif |
---|
645 | endif |
---|
646 | call mct_aVect_scatter(areasrc0, areasrc, SgsMap, 0, mpicom, status) |
---|
647 | if (status /= 0) call mct_die(subname,"Error on scatter of areasrc0") |
---|
648 | if (mytask == 0) then |
---|
649 | ! if (present(dbug)) then |
---|
650 | ! if (dbug > 2) then |
---|
651 | ! write(nulprt,*) subName,'Size of src ',mct_aVect_lSize(areasrc0) |
---|
652 | ! write(nulprt,*) subName,'min/max src ',minval(areasrc0%rAttr(1,:)),maxval(areasrc0%rAttr(1,:)) |
---|
653 | ! endif |
---|
654 | ! end if |
---|
655 | call mct_aVect_clean(areasrc0) |
---|
656 | end if |
---|
657 | end if |
---|
658 | |
---|
659 | !---------------------------------------------------------------------------- |
---|
660 | !> * Read and load area_b on root task |
---|
661 | !---------------------------------------------------------------------------- |
---|
662 | |
---|
663 | if (present(areadst)) then |
---|
664 | if (mytask == 0) then |
---|
665 | call mct_aVect_init(areadst0,' ',areaAV_field,nb) |
---|
666 | ! status = nf90_inq_varid (fid,'area_b',vid) |
---|
667 | status = nf90_inq_varid (fid,'dst_grid_area',vid) |
---|
668 | if (status /= NF90_NOERR) THEN |
---|
669 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
670 | write(nulprt,*) subname,estr,'var not found = ','dst_grid_area' |
---|
671 | call oasis_flush(nulprt) |
---|
672 | endif |
---|
673 | status = nf90_get_var(fid, vid, areadst0%rAttr) |
---|
674 | if (status /= NF90_NOERR) THEN |
---|
675 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
676 | call oasis_flush(nulprt) |
---|
677 | endif |
---|
678 | endif |
---|
679 | call mct_aVect_scatter(areadst0, areadst, DgsMap, 0, mpicom, status) |
---|
680 | if (status /= 0) call mct_die(subname,"Error on scatter of areadst0") |
---|
681 | if (mytask == 0) then |
---|
682 | ! if (present(dbug)) then |
---|
683 | ! if (dbug > 2) then |
---|
684 | ! write(nulprt,*) subName,'Size of dst ',mct_aVect_lSize(areadst0) |
---|
685 | ! write(nulprt,*) subName,'min/max dst ',minval(areadst0%rAttr(1,:)),maxval(areadst0%rAttr(1,:)) |
---|
686 | ! endif |
---|
687 | ! end if |
---|
688 | call mct_aVect_clean(areadst0) |
---|
689 | endif |
---|
690 | endif |
---|
691 | |
---|
692 | !---------------------------------------------------------------------------- |
---|
693 | !> * Broadcast ni and nj if requested |
---|
694 | !---------------------------------------------------------------------------- |
---|
695 | |
---|
696 | if (present(ni_i) .and. present(nj_i) .and. present(ni_o) .and. present(nj_o)) then |
---|
697 | call oasis_mpi_bcast(ni_i,mpicom,subName//" MPI in ni_i bcast") |
---|
698 | call oasis_mpi_bcast(nj_i,mpicom,subName//" MPI in nj_i bcast") |
---|
699 | call oasis_mpi_bcast(ni_o,mpicom,subName//" MPI in ni_o bcast") |
---|
700 | call oasis_mpi_bcast(nj_o,mpicom,subName//" MPI in nj_o bcast") |
---|
701 | end if |
---|
702 | |
---|
703 | !---------------------------------------------------------------------------- |
---|
704 | !> * Broadcast array sizes and allocate arrays for local storage |
---|
705 | !---------------------------------------------------------------------------- |
---|
706 | |
---|
707 | call oasis_mpi_bcast(ns,mpicom,subName//" MPI in ns bcast") |
---|
708 | call oasis_mpi_bcast(na,mpicom,subName//" MPI in na bcast") |
---|
709 | call oasis_mpi_bcast(nb,mpicom,subName//" MPI in nb bcast") |
---|
710 | call oasis_mpi_bcast(nwgts,mpicom,subName//" MPI in nwgts bcast") |
---|
711 | if (local_timers_on) call oasis_timer_stop('map_read_orig_read') |
---|
712 | |
---|
713 | if (local_timers_on) call oasis_timer_start('map_read_orig_sort') |
---|
714 | !--- setup local seg map, sorted |
---|
715 | if (newdom == 'src') then |
---|
716 | mygsmap => DgsMap |
---|
717 | elseif (newdom == 'dst') then |
---|
718 | mygsmap => SgsMap |
---|
719 | else |
---|
720 | write(nulprt,*) subname,estr,'invalid newdom value, expect src or dst = ',newdom |
---|
721 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
722 | endif |
---|
723 | lsize = 0 |
---|
724 | do n = 1,size(mygsmap%start) |
---|
725 | if (mygsmap%pe_loc(n) == mytask) then |
---|
726 | lsize=lsize+1 |
---|
727 | endif |
---|
728 | enddo |
---|
729 | allocate(lsstart(lsize),lscount(lsize),stat=status) |
---|
730 | if (status /= 0) call mct_perr_die(subName,':: allocate Lsstart',status) |
---|
731 | |
---|
732 | !---------------------------------------------------------------------------- |
---|
733 | !> * Initialize lsstart and lscount, the sorted list of local indices |
---|
734 | !---------------------------------------------------------------------------- |
---|
735 | |
---|
736 | lsize = 0 |
---|
737 | do n = 1,size(mygsmap%start) |
---|
738 | if (mygsmap%pe_loc(n) == mytask) then ! on my pe |
---|
739 | lsize=lsize+1 |
---|
740 | found = .false. |
---|
741 | l1 = 1 |
---|
742 | do while (.not.found .and. l1 < lsize) ! bubble sort copy |
---|
743 | if (mygsmap%start(n) < lsstart(l1)) then |
---|
744 | do l2 = lsize, l1+1, -1 |
---|
745 | lsstart(l2) = lsstart(l2-1) |
---|
746 | lscount(l2) = lscount(l2-1) |
---|
747 | enddo |
---|
748 | found = .true. |
---|
749 | else |
---|
750 | l1 = l1 + 1 |
---|
751 | endif |
---|
752 | enddo |
---|
753 | lsstart(l1) = mygsmap%start(n) |
---|
754 | lscount(l1) = mygsmap%length(n) |
---|
755 | endif |
---|
756 | enddo |
---|
757 | do n = 1,lsize-1 |
---|
758 | if (lsstart(n) > lsstart(n+1)) then |
---|
759 | write(nulprt,*) subname,estr,'lsstart not properly sorted' |
---|
760 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
761 | endif |
---|
762 | enddo |
---|
763 | if (local_timers_on) call oasis_timer_stop('map_read_orig_sort') |
---|
764 | |
---|
765 | !---------------------------------------------------------------------------- |
---|
766 | !> * Compute the number of chunks to read, read size is rbuf_size |
---|
767 | !---------------------------------------------------------------------------- |
---|
768 | |
---|
769 | if (local_timers_on) call oasis_timer_start('map_read_orig_dist') |
---|
770 | rsize = min(rbuf_size,ns) ! size of i/o chunks |
---|
771 | bsize = ((ns/commsize) + 1 ) * 1.2 ! local temporary buffer size |
---|
772 | if (ns == 0) then |
---|
773 | nread = 0 |
---|
774 | else |
---|
775 | nread = (ns-1)/rsize + 1 ! num of reads to do |
---|
776 | endif |
---|
777 | |
---|
778 | !---------------------------------------------------------------------------- |
---|
779 | !> * Allocate arrays for local weights plus row and column indices |
---|
780 | !---------------------------------------------------------------------------- |
---|
781 | |
---|
782 | if (mytask == 0) then |
---|
783 | allocate(remaps(nwgts,rsize),stat=status) |
---|
784 | if (status /= 0) call mct_perr_die(subName,':: allocate remaps',status) |
---|
785 | endif |
---|
786 | allocate(Smat(nwgts),stat=status) |
---|
787 | if (status /= 0) call mct_perr_die(subName,':: allocate Smat',status) |
---|
788 | allocate(Sbuf(nwgts,rsize),Rbuf(rsize),Cbuf(rsize),stat=status) |
---|
789 | if (status /= 0) call mct_perr_die(subName,':: allocate Sbuf',status) |
---|
790 | allocate(Snew(nwgts,bsize),Cnew(bsize),Rnew(bsize),stat=status) |
---|
791 | if (status /= 0) call mct_perr_die(subName,':: allocate Snew1',status) |
---|
792 | |
---|
793 | !---------------------------------------------------------------------------- |
---|
794 | !> * Loop over the chunks of weights data |
---|
795 | !---------------------------------------------------------------------------- |
---|
796 | |
---|
797 | cnt = 0 |
---|
798 | do n = 1,nread |
---|
799 | start(1) = (n-1)*rsize + 1 |
---|
800 | count(1) = min(rsize,ns-start(1)+1) |
---|
801 | start2(1) = 1 |
---|
802 | count2(1) = nwgts |
---|
803 | start2(2) = start(1) |
---|
804 | count2(2) = count(1) |
---|
805 | |
---|
806 | !---------------------------------------------------------------------------- |
---|
807 | !> * Read chunk of data on root pe |
---|
808 | !---------------------------------------------------------------------------- |
---|
809 | |
---|
810 | if (mytask== 0) then |
---|
811 | ! status = nf90_inq_varid (fid,'S' ,vid) |
---|
812 | status = nf90_inq_varid (fid,'remap_matrix' ,vid) |
---|
813 | if (status /= NF90_NOERR) then |
---|
814 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
815 | write(nulprt,*) subname,estr,'var not found = ','remap_matrix' |
---|
816 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
817 | endif |
---|
818 | ! status = nf90_get_var(fid,vid,start,count,Sbuf) |
---|
819 | status = nf90_get_var(fid,vid,remaps,start2,count2) |
---|
820 | if (status /= NF90_NOERR) THEN |
---|
821 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
822 | call oasis_flush(nulprt) |
---|
823 | endif |
---|
824 | Sbuf(:,:) = remaps(:,:) |
---|
825 | |
---|
826 | ! status = nf90_inq_varid (fid,'row',vid) |
---|
827 | status = nf90_inq_varid (fid,'dst_address',vid) |
---|
828 | if (status /= NF90_NOERR) then |
---|
829 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
830 | write(nulprt,*) subname,estr,'var not found = ','dst_address' |
---|
831 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
832 | endif |
---|
833 | status = nf90_get_var (fid,vid,Rbuf,start,count) |
---|
834 | if (status /= NF90_NOERR) THEN |
---|
835 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
836 | call oasis_flush(nulprt) |
---|
837 | endif |
---|
838 | |
---|
839 | ! status = nf90_inq_varid (fid,'col',vid) |
---|
840 | status = nf90_inq_varid (fid,'src_address',vid) |
---|
841 | if (status /= NF90_NOERR) then |
---|
842 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
843 | write(nulprt,*) subname,estr,'var not found = ','src_address' |
---|
844 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
845 | endif |
---|
846 | status = nf90_get_var (fid,vid,Cbuf,start,count) |
---|
847 | if (status /= NF90_NOERR) THEN |
---|
848 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
849 | call oasis_flush(nulprt) |
---|
850 | endif |
---|
851 | endif |
---|
852 | |
---|
853 | !---------------------------------------------------------------------------- |
---|
854 | !> * Broadcast S, row, col to all tasks |
---|
855 | !---------------------------------------------------------------------------- |
---|
856 | |
---|
857 | call oasis_mpi_bcast(Sbuf,mpicom,subName//" MPI in Sbuf bcast") |
---|
858 | call oasis_mpi_bcast(Rbuf,mpicom,subName//" MPI in Rbuf bcast") |
---|
859 | call oasis_mpi_bcast(Cbuf,mpicom,subName//" MPI in Cbuf bcast") |
---|
860 | |
---|
861 | !---------------------------------------------------------------------------- |
---|
862 | !> * Each task keeps only the data required |
---|
863 | !---------------------------------------------------------------------------- |
---|
864 | |
---|
865 | if (namwgtopt == "abort_on_bad_index") then |
---|
866 | abort_weight = .false. |
---|
867 | do m = 1,count(1) |
---|
868 | !--- check for bad weights |
---|
869 | if ((Rbuf(m) <= 0 .or. Rbuf(m) > nb .or. & |
---|
870 | Cbuf(m) <= 0 .or. Cbuf(m) > na) & |
---|
871 | ! tcx weight = 0 |
---|
872 | .and. (minval(Sbuf(:,m)) /= 0._R8 .or. maxval(Sbuf(:,m)) /= 0._R8) & |
---|
873 | ) then |
---|
874 | abort_weight = .true. |
---|
875 | write(nulprt,'(3A,I12,A,I12,A,I12,A,G14.7,A,G14.7,A)') & |
---|
876 | subname,wstr,'BAD weight found in '//trim(filename), & |
---|
877 | m,'=id',Cbuf(m),'=src',Rbuf(m),'=dst',minval(Sbuf(:,m)),'=minS',maxval(Sbuf(:,m)),'=maxS' |
---|
878 | endif |
---|
879 | enddo |
---|
880 | if (abort_weight) then |
---|
881 | write(nulprt,*) subname,wstr,'BAD weight found, aborting' |
---|
882 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
883 | endif |
---|
884 | endif |
---|
885 | |
---|
886 | do m = 1,count(1) |
---|
887 | !--- check for bad weights |
---|
888 | if ((namwgtopt(1:16) == "ignore_bad_index") .and. & |
---|
889 | (Rbuf(m) <= 0 .or. Rbuf(m) > nb .or. & |
---|
890 | Cbuf(m) <= 0 .or. Cbuf(m) > na)) then |
---|
891 | mywt = .false. |
---|
892 | ! tcx weight = 0 |
---|
893 | if (minval(Sbuf(:,m)) /= 0._R8 .or. maxval(Sbuf(:,m)) /= 0._R8) then |
---|
894 | if (OASIS_debug >= 2 .and. namwgtopt /= "ignore_bad_index_silently") then |
---|
895 | write(nulprt,'(3A,I12,A,I12,A,I12,A,G14.7,A,G14.7,A)') & |
---|
896 | subname,wstr,'BAD weight found in '//trim(filename), & |
---|
897 | m,'=id',Cbuf(m),'=src',Rbuf(m),'=dst',minval(Sbuf(:,m)),'=minS',maxval(Sbuf(:,m)),'=maxS' |
---|
898 | endif |
---|
899 | endif |
---|
900 | elseif (newdom == 'src') then |
---|
901 | mywt = check_myindex(Rbuf(m),lsstart,lscount) |
---|
902 | elseif (newdom == 'dst') then |
---|
903 | mywt = check_myindex(Cbuf(m),lsstart,lscount) |
---|
904 | endif |
---|
905 | |
---|
906 | if (mywt) then |
---|
907 | cntold = cnt |
---|
908 | cnt = cnt + 1 |
---|
909 | |
---|
910 | !---------------------------------------------------------------------------- |
---|
911 | !> * Reallocate local weights arrays if they need to be bigger |
---|
912 | !---------------------------------------------------------------------------- |
---|
913 | if (cnt > bsize) then |
---|
914 | !--- allocate old arrays and copy new into old |
---|
915 | allocate(Sold(1:nwgts,cntold),Rold(cntold),Cold(cntold),stat=status) |
---|
916 | if (status /= 0) call mct_perr_die(subName,':: allocate old',status) |
---|
917 | Sold(1:nwgts,1:cntold) = Snew(1:nwgts,1:cntold) |
---|
918 | Rold(1:cntold) = Rnew(1:cntold) |
---|
919 | Cold(1:cntold) = Cnew(1:cntold) |
---|
920 | |
---|
921 | !--- reallocate new to bigger size, increase buffer by 50% (arbitrary) |
---|
922 | deallocate(Snew,Rnew,Cnew,stat=status) |
---|
923 | if (status /= 0) call mct_perr_die(subName,':: allocate new',status) |
---|
924 | bsize = 1.5 * bsize |
---|
925 | if (OASIS_debug > 15) write(nulprt,*) subname,' reallocate bsize to ',bsize |
---|
926 | allocate(Snew(nwgts,bsize),Rnew(bsize),Cnew(bsize),stat=status) |
---|
927 | if (status /= 0) call mct_perr_die(subName,':: allocate old',status) |
---|
928 | |
---|
929 | !--- copy data back into new |
---|
930 | Snew(1:nwgts,1:cntold) = Sold(1:nwgts,1:cntold) |
---|
931 | Rnew(1:cntold) = Rold(1:cntold) |
---|
932 | Cnew(1:cntold) = Cold(1:cntold) |
---|
933 | deallocate(Sold,Rold,Cold,stat=status) |
---|
934 | if (status /= 0) call mct_perr_die(subName,':: deallocate old',status) |
---|
935 | endif |
---|
936 | |
---|
937 | Snew(1:nwgts,cnt) = Sbuf(1:nwgts,m) |
---|
938 | Rnew(cnt) = Rbuf(m) |
---|
939 | Cnew(cnt) = Cbuf(m) |
---|
940 | endif |
---|
941 | enddo ! count |
---|
942 | enddo ! nread |
---|
943 | |
---|
944 | !---------------------------------------------------------------------------- |
---|
945 | !> * Clean up arrays |
---|
946 | !---------------------------------------------------------------------------- |
---|
947 | |
---|
948 | if (mytask == 0) then |
---|
949 | deallocate(remaps, stat=status) |
---|
950 | if (status /= 0) call mct_perr_die(subName,':: deallocate remaps',status) |
---|
951 | endif |
---|
952 | deallocate(Sbuf,Rbuf,Cbuf, stat=status) |
---|
953 | if (status /= 0) call mct_perr_die(subName,':: deallocate Sbuf',status) |
---|
954 | if (local_timers_on) call oasis_timer_stop('map_read_orig_dist') |
---|
955 | |
---|
956 | !---------------------------------------------------------------------------- |
---|
957 | !> * Initialize the mct sMat data type |
---|
958 | !---------------------------------------------------------------------------- |
---|
959 | |
---|
960 | if (local_timers_on) call oasis_timer_start('map_read_orig_smati') |
---|
961 | ! mct_sMat_init must be given the number of rows and columns that |
---|
962 | ! would be in the full matrix. Nrows= size of output vector=nb. |
---|
963 | ! Ncols = size of input vector = na. |
---|
964 | do n = 1,nwgts |
---|
965 | call mct_sMat_init(sMat(n), nb, na, cnt) |
---|
966 | enddo |
---|
967 | |
---|
968 | igrow = mct_sMat_indexIA(sMat(1),'grow') |
---|
969 | igcol = mct_sMat_indexIA(sMat(1),'gcol') |
---|
970 | iwgt = mct_sMat_indexRA(sMat(1),'weight') |
---|
971 | |
---|
972 | if (cnt /= 0) then |
---|
973 | do n = 1,nwgts |
---|
974 | sMat(n)%data%rAttr(iwgt ,1:cnt) = Snew(n,1:cnt) |
---|
975 | sMat(n)%data%iAttr(igrow,1:cnt) = Rnew(1:cnt) |
---|
976 | sMat(n)%data%iAttr(igcol,1:cnt) = Cnew(1:cnt) |
---|
977 | enddo |
---|
978 | endif |
---|
979 | if (local_timers_on) call oasis_timer_stop('map_read_orig_smati') |
---|
980 | |
---|
981 | !---------------------------------------------------------------------------- |
---|
982 | !> * More clean up |
---|
983 | !---------------------------------------------------------------------------- |
---|
984 | |
---|
985 | if (local_timers_on) call oasis_timer_start('map_read_orig_clean') |
---|
986 | deallocate(Snew,Rnew,Cnew, stat=status) |
---|
987 | deallocate(lsstart,lscount,stat=status) |
---|
988 | if (status /= 0) call mct_perr_die(subName,':: deallocate new',status) |
---|
989 | |
---|
990 | if (mytask == 0) then |
---|
991 | status = nf90_close(fid) |
---|
992 | if (status /= NF90_NOERR) then |
---|
993 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
994 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
995 | endif |
---|
996 | if (OASIS_debug >= 2) THEN |
---|
997 | write(nulprt,*) subname," ... done reading file" |
---|
998 | call oasis_flush(nulprt) |
---|
999 | endif |
---|
1000 | endif |
---|
1001 | if (local_timers_on) call oasis_timer_stop('map_read_orig_clean') |
---|
1002 | |
---|
1003 | call oasis_debug_exit(subname) |
---|
1004 | |
---|
1005 | end subroutine oasis_map_sMatReaddnc_orig |
---|
1006 | |
---|
1007 | !=============================================================================== |
---|
1008 | !BOP =========================================================================== |
---|
1009 | !> Read in mapping matrix data from a SCRIP netCDF file using smart scatter (ceg) |
---|
1010 | ! |
---|
1011 | ! !IROUTINE: oasis_map_sMatReaddnc_ceg - Do a distributed read of a NetCDF SCRIP file and |
---|
1012 | ! return weights in a distributed SparseMatrix |
---|
1013 | ! |
---|
1014 | ! !DESCRIPTION: |
---|
1015 | !> Read in mapping matrix data from a SCRIP netCDF data file using |
---|
1016 | !> a low memory method and then scatter to all pes using a smart method |
---|
1017 | !> where only select data is sent to tasks. Based on the sMatReaddnc method |
---|
1018 | !> from CESM1.0.3 |
---|
1019 | ! !REMARKS: |
---|
1020 | !> This routine leverages gsmaps to determine scatter pattern |
---|
1021 | !> |
---|
1022 | !> The scatter is implemented via the root task reading the data and |
---|
1023 | !> then determining which task gets which weights from the gsmap. |
---|
1024 | !> The root the sends specific data to each task. |
---|
1025 | !> |
---|
1026 | !> The algorithm to determine which task a weigth belongs to involves |
---|
1027 | !> checking the task ownership for a given global index. |
---|
1028 | !> |
---|
1029 | !> The local buffer sizes are estimated up front based on ngridcell/npes |
---|
1030 | !> plus 20% (see 1.2 below). If the local buffer size fills up, then |
---|
1031 | !> the buffer is reallocated 50% larger (see 1.5 below) and the fill |
---|
1032 | !> continues. The idea is to trade off memory reallocation and copy |
---|
1033 | !> with memory usage. 1.2 and 1.5 are arbitary, other values may |
---|
1034 | !> result in better performance. |
---|
1035 | !> |
---|
1036 | !> Once all the matrix weights have been read, the sMat is initialized, |
---|
1037 | !> the values from the buffers are copied in, and everything is deallocated. |
---|
1038 | ! |
---|
1039 | ! !INTERFACE: ----------------------------------------------------------------- |
---|
1040 | |
---|
1041 | subroutine oasis_map_sMatReaddnc_ceg(sMat,SgsMap,DgsMap,newdom, & |
---|
1042 | fileName,mytask,mpicom,nwgts, & |
---|
1043 | areasrc,areadst,ni_i,nj_i,ni_o,nj_o ) |
---|
1044 | |
---|
1045 | ! !USES: |
---|
1046 | |
---|
1047 | ! !INPUT/OUTPUT PARAMETERS: |
---|
1048 | |
---|
1049 | type(mct_sMat) ,intent(out),pointer :: sMat(:) !< mapping data |
---|
1050 | type(mct_gsMap) ,intent(in) ,target :: SgsMap !< src gsmap |
---|
1051 | type(mct_gSMap) ,intent(in) ,target :: DgsMap !< dst gsmap |
---|
1052 | character(*) ,intent(in) :: newdom !< type of sMat (src or dst) |
---|
1053 | !< src = rearrange and map (bfb), dst = map and rearrange (partial sums) |
---|
1054 | character(*) ,intent(in) :: filename!< netCDF file to read |
---|
1055 | integer(IN) ,intent(in) :: mytask !< processor id |
---|
1056 | integer(IN) ,intent(in) :: mpicom !< mpi communicator |
---|
1057 | integer(IN) ,intent(out) :: nwgts !< number of weights |
---|
1058 | type(mct_Avect) ,intent(out), optional :: areasrc !< area of src grid from mapping file |
---|
1059 | type(mct_Avect) ,intent(out), optional :: areadst !< area of dst grid from mapping file |
---|
1060 | integer(IN) ,intent(out), optional :: ni_i !< number of lons on input grid |
---|
1061 | integer(IN) ,intent(out), optional :: nj_i !< number of lats on input grid |
---|
1062 | integer(IN) ,intent(out), optional :: ni_o !< number of lons on output grid |
---|
1063 | integer(IN) ,intent(out), optional :: nj_o !< number of lats on output grid |
---|
1064 | |
---|
1065 | ! !EOP |
---|
1066 | |
---|
1067 | !--- local --- |
---|
1068 | integer :: n,m ! generic loop indicies |
---|
1069 | integer :: na ! size of source domain |
---|
1070 | integer :: nb ! size of destination domain |
---|
1071 | integer :: ns ! number of non-zero elements in matrix |
---|
1072 | integer :: ni,nj ! number of row and col in the matrix |
---|
1073 | integer :: igrow ! aVect index for matrix row |
---|
1074 | integer :: igcol ! aVect index for matrix column |
---|
1075 | integer :: iwgt ! aVect index for matrix element |
---|
1076 | integer :: iarea ! aVect index for area |
---|
1077 | integer :: rsize ! size of read buffer |
---|
1078 | integer :: cnt ! local num of wgts |
---|
1079 | integer :: start(1)! netcdf read |
---|
1080 | integer :: count(1)! netcdf read |
---|
1081 | integer :: start2(2)! netcdf read |
---|
1082 | integer :: count2(2)! netcdf read |
---|
1083 | integer :: bsize ! buffer size |
---|
1084 | integer :: nread ! number of reads |
---|
1085 | logical :: mywt ! does this weight belong on my pe |
---|
1086 | integer :: dims(2) |
---|
1087 | logical :: abort_weight ! flag if bad weight found |
---|
1088 | |
---|
1089 | !--- buffers for i/o --- |
---|
1090 | real(R8) ,allocatable :: rtemp(:) ! real temporary |
---|
1091 | real(R8) ,allocatable :: Sbuf(:,:) ! real weights |
---|
1092 | real(R8) ,allocatable :: remaps(:,:) ! real weights with num_wgts dim |
---|
1093 | integer,allocatable :: Rbuf(:) ! ints rows |
---|
1094 | integer,allocatable :: Cbuf(:) ! ints cols |
---|
1095 | real(R8),allocatable :: SReadData(:,:) ! |
---|
1096 | integer,allocatable :: RReadData(:) ! |
---|
1097 | integer,allocatable :: CReadData(:) ! |
---|
1098 | integer,allocatable :: pesave(:) ! |
---|
1099 | real(R8),allocatable :: SDistData(:,:) ! |
---|
1100 | integer,allocatable :: RDistData(:) ! |
---|
1101 | integer,allocatable :: CDistData(:) ! |
---|
1102 | |
---|
1103 | !--- variables associated with local computation of global indices |
---|
1104 | integer :: commsize ! size of local communicator |
---|
1105 | type(mct_gsMap),pointer :: mygsmap ! pointer to one of the gsmaps |
---|
1106 | integer :: l1,l2,lsize ! generice indices for sort |
---|
1107 | integer,allocatable :: lsstart(:) ! local seg map info |
---|
1108 | integer,allocatable :: lscount(:) ! local seg map info |
---|
1109 | integer,allocatable :: lspeloc(:) ! local seg map info |
---|
1110 | integer,allocatable :: sortkey(:) ! local sort key info |
---|
1111 | logical :: found ! for sort |
---|
1112 | integer :: pe ! Process ID of owning process |
---|
1113 | integer :: reclen ! Length of Rbuf/Cbuf to be received |
---|
1114 | integer :: ierr ! MPI error check |
---|
1115 | integer,allocatable :: cntrs(:) ! Counters of number of elements stored for each processor |
---|
1116 | integer :: mpistatus(MPI_STATUS_SIZE) ! MPI_Status object |
---|
1117 | |
---|
1118 | character,allocatable :: str(:) ! variable length char string |
---|
1119 | character(len=ic_long):: attstr ! netCDF attribute name string |
---|
1120 | integer :: status ! netCDF routine return code |
---|
1121 | integer :: fid ! netCDF file ID |
---|
1122 | integer :: vid ! netCDF variable ID |
---|
1123 | integer :: did ! netCDF dimension ID |
---|
1124 | !--- arbitrary size of read buffer, this is the chunk size weights reading |
---|
1125 | integer,parameter :: rbuf_size = 100000 |
---|
1126 | integer :: dimbuffer(8) |
---|
1127 | |
---|
1128 | !--- global source and destination areas --- |
---|
1129 | type(mct_Avect) :: areasrc0 ! area of src grid from mapping file |
---|
1130 | type(mct_Avect) :: areadst0 ! area of src grid from mapping file |
---|
1131 | |
---|
1132 | character(*),parameter :: areaAV_field = 'aream' |
---|
1133 | |
---|
1134 | !--- formats --- |
---|
1135 | character(*),parameter :: subName = '(oasis_map_sMatReaddnc_ceg)' |
---|
1136 | character*80 :: fname |
---|
1137 | |
---|
1138 | !------------------------------------------------------------------------------- |
---|
1139 | ! |
---|
1140 | !------------------------------------------------------------------------------- |
---|
1141 | |
---|
1142 | call oasis_debug_enter(subname) |
---|
1143 | call oasis_mpi_commsize(mpicom,commsize) |
---|
1144 | nwgts = -1 |
---|
1145 | if (local_timers_on) call oasis_timer_start('map_read_ceg_read') |
---|
1146 | |
---|
1147 | if (mytask == 0) then |
---|
1148 | if (OASIS_debug >= 2) write(nulprt,*) subname," reading mapping matrix data decomposed..." |
---|
1149 | |
---|
1150 | !---------------------------------------------------------------------------- |
---|
1151 | !> * Open and read the file SCRIP weights size on the root task |
---|
1152 | !---------------------------------------------------------------------------- |
---|
1153 | |
---|
1154 | if (OASIS_debug >=2 ) write(nulprt,*) subname," * file name : ",trim(fileName) |
---|
1155 | status = nf90_open(trim(filename),NF90_NOWRITE,fid) |
---|
1156 | if (status /= NF90_NOERR) then |
---|
1157 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1158 | write(nulprt,*) subname,estr,'mapping file not found = ',trim(filename) |
---|
1159 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1160 | endif |
---|
1161 | |
---|
1162 | !--- get matrix dimensions ---------- |
---|
1163 | ! status = nf90_inq_dimid (fid, 'n_s', did) ! size of sparse matrix |
---|
1164 | status = nf90_inq_dimid (fid, 'num_links', did) ! size of sparse matrix |
---|
1165 | if (status /= NF90_NOERR) then |
---|
1166 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1167 | write(nulprt,*) subname,estr,'dim not found = ','num_links' |
---|
1168 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1169 | endif |
---|
1170 | status = nf90_inquire_dimension(fid, did , len = ns) |
---|
1171 | if (status /= NF90_NOERR) then |
---|
1172 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1173 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1174 | endif |
---|
1175 | ! status = nf90_inq_dimid (fid, 'n_a', did) ! size of input vector |
---|
1176 | status = nf90_inq_dimid (fid, 'src_grid_size', did) ! size of input vector |
---|
1177 | if (status /= NF90_NOERR) then |
---|
1178 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1179 | write(nulprt,*) subname,estr,'dim not found = ','src_grid_size' |
---|
1180 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1181 | endif |
---|
1182 | status = nf90_inquire_dimension(fid, did , len = na) |
---|
1183 | if (status /= NF90_NOERR) then |
---|
1184 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1185 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1186 | endif |
---|
1187 | ! status = nf90_inq_dimid (fid, 'n_b', did) ! size of output vector |
---|
1188 | status = nf90_inq_dimid (fid, 'dst_grid_size', did) ! size of output vector |
---|
1189 | if (status /= NF90_NOERR) then |
---|
1190 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1191 | write(nulprt,*) subname,estr,'dim not found = ','dst_grid_size' |
---|
1192 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1193 | endif |
---|
1194 | status = nf90_inquire_dimension(fid, did , len = nb) |
---|
1195 | if (status /= NF90_NOERR) then |
---|
1196 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1197 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1198 | endif |
---|
1199 | status = nf90_inq_dimid (fid, 'num_wgts', did) ! size of output vector |
---|
1200 | if (status /= NF90_NOERR) then |
---|
1201 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1202 | write(nulprt,*) subname,estr,'dim not found = ','num_wgts' |
---|
1203 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1204 | endif |
---|
1205 | status = nf90_inquire_dimension(fid, did , len = nwgts) |
---|
1206 | if (status /= NF90_NOERR) then |
---|
1207 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1208 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1209 | endif |
---|
1210 | |
---|
1211 | if (present(ni_i) .and. present(nj_i) .and. present(ni_o) .and. present(nj_o)) then |
---|
1212 | ! status = nf90_inq_dimid (fid, 'ni_a', did) ! number of lons in input grid |
---|
1213 | ! status = nf90_inquire_dimension(fid, did , len = ni_i) |
---|
1214 | ! status = nf90_inq_dimid (fid, 'nj_a', did) ! number of lats in input grid |
---|
1215 | ! status = nf90_inquire_dimension(fid, did , len = nj_i) |
---|
1216 | ! status = nf90_inq_dimid (fid, 'ni_b', did) ! number of lons in output grid |
---|
1217 | ! status = nf90_inquire_dimension(fid, did , len = ni_o) |
---|
1218 | ! status = nf90_inq_dimid (fid, 'nj_b', did) ! number of lats in output grid |
---|
1219 | ! status = nf90_inquire_dimension(fid, did , len = nj_o) |
---|
1220 | status = nf90_inq_varid(fid, 'src_grid_dims', vid) |
---|
1221 | if (status /= NF90_NOERR) then |
---|
1222 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1223 | write(nulprt,*) subname,estr,'var not found = ','src_grid_dims' |
---|
1224 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1225 | endif |
---|
1226 | status = nf90_get_var(fid, vid, dims) |
---|
1227 | if (status /= NF90_NOERR) then |
---|
1228 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1229 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1230 | endif |
---|
1231 | ni_i = dims(1) |
---|
1232 | nj_i = dims(2) |
---|
1233 | status = nf90_inq_varid(fid, 'dst_grid_dims', vid) |
---|
1234 | if (status /= NF90_NOERR) then |
---|
1235 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1236 | write(nulprt,*) subname,estr,'var not found = ','dst_grid_dims' |
---|
1237 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1238 | endif |
---|
1239 | status = nf90_get_var(fid, vid, dims) |
---|
1240 | if (status /= NF90_NOERR) then |
---|
1241 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1242 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1243 | endif |
---|
1244 | ni_o = dims(1) |
---|
1245 | nj_o = dims(2) |
---|
1246 | end if |
---|
1247 | |
---|
1248 | if (OASIS_debug >= 2) write(nulprt,*) subname," * matrix dims src x dst : ",na,' x',nb |
---|
1249 | if (OASIS_debug >= 2) write(nulprt,*) subname," * number of non-zero elements: ",ns |
---|
1250 | |
---|
1251 | endif |
---|
1252 | |
---|
1253 | !---------------------------------------------------------------------------- |
---|
1254 | !> * Read and load area_a on root task |
---|
1255 | !---------------------------------------------------------------------------- |
---|
1256 | |
---|
1257 | if (present(areasrc)) then |
---|
1258 | if (mytask == 0) then |
---|
1259 | call mct_aVect_init(areasrc0,' ',areaAV_field,na) |
---|
1260 | ! status = nf90_inq_varid (fid,'area_a',vid) |
---|
1261 | status = nf90_inq_varid (fid,'src_grid_area',vid) |
---|
1262 | if (status /= NF90_NOERR) THEN |
---|
1263 | write(nulprt,*) subname,' nf90_strerrr = ',TRIM(nf90_strerror(status)) |
---|
1264 | write(nulprt,*) subname,estr,'var not found = ','src_grid_area' |
---|
1265 | call oasis_flush(nulprt) |
---|
1266 | endif |
---|
1267 | status = nf90_get_var(fid, vid, areasrc0%rAttr) |
---|
1268 | if (status /= NF90_NOERR) THEN |
---|
1269 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
1270 | call oasis_flush(nulprt) |
---|
1271 | endif |
---|
1272 | endif |
---|
1273 | call mct_aVect_scatter(areasrc0, areasrc, SgsMap, 0, mpicom, status) |
---|
1274 | if (status /= 0) call mct_die(subname,"Error on scatter of areasrc0") |
---|
1275 | if (mytask == 0) then |
---|
1276 | ! if (present(dbug)) then |
---|
1277 | ! if (dbug > 2) then |
---|
1278 | ! write(nulprt,*) subName,'min/max src ',minval(areasrc0%rAttr(1,:)),maxval(areasrc0%rAttr(1,:)) |
---|
1279 | ! endif |
---|
1280 | ! end if |
---|
1281 | call mct_aVect_clean(areasrc0) |
---|
1282 | end if |
---|
1283 | end if |
---|
1284 | |
---|
1285 | !---------------------------------------------------------------------------- |
---|
1286 | !> * Read and load area_b on root task |
---|
1287 | !---------------------------------------------------------------------------- |
---|
1288 | |
---|
1289 | if (present(areadst)) then |
---|
1290 | if (mytask == 0) then |
---|
1291 | call mct_aVect_init(areadst0,' ',areaAV_field,nb) |
---|
1292 | ! status = nf90_inq_varid (fid,'area_b',vid) |
---|
1293 | status = nf90_inq_varid (fid,'dst_grid_area',vid) |
---|
1294 | if (status /= NF90_NOERR) THEN |
---|
1295 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
1296 | write(nulprt,*) subname,estr,'var not found = ','dst_grid_area' |
---|
1297 | call oasis_flush(nulprt) |
---|
1298 | endif |
---|
1299 | status = nf90_get_var(fid, vid, areadst0%rAttr) |
---|
1300 | if (status /= NF90_NOERR) THEN |
---|
1301 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
1302 | call oasis_flush(nulprt) |
---|
1303 | endif |
---|
1304 | endif |
---|
1305 | call mct_aVect_scatter(areadst0, areadst, DgsMap, 0, mpicom, status) |
---|
1306 | if (status /= 0) call mct_die(subname,"Error on scatter of areadst0") |
---|
1307 | if (mytask == 0) then |
---|
1308 | ! if (present(dbug)) then |
---|
1309 | ! if (dbug > 2) then |
---|
1310 | ! write(nulprt,*) subName,'min/max dst ',minval(areadst0%rAttr(1,:)),maxval(areadst0%rAttr(1,:)) |
---|
1311 | ! endif |
---|
1312 | ! end if |
---|
1313 | call mct_aVect_clean(areadst0) |
---|
1314 | endif |
---|
1315 | endif |
---|
1316 | |
---|
1317 | !---------------------------------------------------------------------------- |
---|
1318 | !> * Broadcast ni and nj if requested |
---|
1319 | !> * Broadcast array sizes and allocate arrays for local storage |
---|
1320 | ! Replace 8 MPI_Bcasts with just one |
---|
1321 | !---------------------------------------------------------------------------- |
---|
1322 | |
---|
1323 | if (mpi_rank_local.eq.0) then |
---|
1324 | dimbuffer(1) = ns |
---|
1325 | dimbuffer(2) = na |
---|
1326 | dimbuffer(3) = nb |
---|
1327 | dimbuffer(4) = nwgts |
---|
1328 | if (present(ni_i) .and. present(nj_i) .and. present(ni_o) .and. present(nj_o)) then |
---|
1329 | dimbuffer(5) = ni_i |
---|
1330 | dimbuffer(6) = nj_i |
---|
1331 | dimbuffer(7) = ni_o |
---|
1332 | dimbuffer(8) = nj_o |
---|
1333 | end if |
---|
1334 | endif |
---|
1335 | call oasis_mpi_bcast(dimbuffer,mpicom,subName//" MPI of dimbuffer") |
---|
1336 | if (mpi_rank_local.ne.0) then |
---|
1337 | ns = dimbuffer(1) |
---|
1338 | na = dimbuffer(2) |
---|
1339 | nb = dimbuffer(3) |
---|
1340 | nwgts = dimbuffer(4) |
---|
1341 | if (present(ni_i) .and. present(nj_i) .and. present(ni_o) .and. present(nj_o)) then |
---|
1342 | ni_i = dimbuffer(5) |
---|
1343 | nj_i = dimbuffer(6) |
---|
1344 | ni_o = dimbuffer(7) |
---|
1345 | nj_o = dimbuffer(8) |
---|
1346 | end if |
---|
1347 | endif |
---|
1348 | |
---|
1349 | ! call oasis_mpi_bcast(ni_i,mpicom,subName//" MPI in ni_i bcast") |
---|
1350 | ! call oasis_mpi_bcast(nj_i,mpicom,subName//" MPI in nj_i bcast") |
---|
1351 | ! call oasis_mpi_bcast(ni_o,mpicom,subName//" MPI in ni_o bcast") |
---|
1352 | ! call oasis_mpi_bcast(nj_o,mpicom,subName//" MPI in nj_o bcast") |
---|
1353 | |
---|
1354 | !--- setup local seg map, sorted |
---|
1355 | if (newdom == 'src') then |
---|
1356 | mygsmap => DgsMap |
---|
1357 | elseif (newdom == 'dst') then |
---|
1358 | mygsmap => SgsMap |
---|
1359 | else |
---|
1360 | write(nulprt,*) subname,estr,'invalid newdom value, expect src or dst = ',newdom |
---|
1361 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1362 | endif |
---|
1363 | |
---|
1364 | !---------------------------------------------------------------------------- |
---|
1365 | !> * Compute the number of chunks to read, read size is rbuf_size |
---|
1366 | !---------------------------------------------------------------------------- |
---|
1367 | |
---|
1368 | rsize = min(rbuf_size,ns) ! size of i/o chunks |
---|
1369 | bsize = ((ns/commsize) + 1 ) * 1.2 ! local temporary buffer size |
---|
1370 | if (ns == 0) then |
---|
1371 | nread = 0 |
---|
1372 | else |
---|
1373 | nread = (ns-1)/rsize + 1 ! num of reads to do |
---|
1374 | endif |
---|
1375 | |
---|
1376 | !---------------------------------------------------------------------------- |
---|
1377 | !> * Allocate arrays for local weights plus row and column indices |
---|
1378 | !---------------------------------------------------------------------------- |
---|
1379 | |
---|
1380 | allocate(Smat(nwgts),stat=status) |
---|
1381 | if (status /= 0) call mct_perr_die(subName,':: allocate Smat',status) |
---|
1382 | allocate(Sbuf(nwgts,rsize),Rbuf(rsize),Cbuf(rsize),stat=status) |
---|
1383 | if (status /= 0) call mct_perr_die(subName,':: allocate Sbuf',status) |
---|
1384 | allocate(Snew(nwgts,bsize),Cnew(bsize),Rnew(bsize),stat=status) |
---|
1385 | if (status /= 0) call mct_perr_die(subName,':: allocate Snew1',status) |
---|
1386 | ! write(nulprt,*) subname,mpi_rank_local,rsize,rsize*nwgts |
---|
1387 | |
---|
1388 | cnt = 1 |
---|
1389 | if (local_timers_on) call oasis_timer_stop('map_read_ceg_read') |
---|
1390 | |
---|
1391 | !---------------------------------------------------------------------------- |
---|
1392 | !> * On the root task |
---|
1393 | !---------------------------------------------------------------------------- |
---|
1394 | |
---|
1395 | if (mytask == 0) then |
---|
1396 | |
---|
1397 | !---------------------------------------------------------------------------- |
---|
1398 | !> * Initialize lsstart, lscount, and lspeloc, the sorted list of local indices |
---|
1399 | !> * Sort via bubble sort or merge sort depending on size of array |
---|
1400 | !---------------------------------------------------------------------------- |
---|
1401 | |
---|
1402 | if (local_timers_on) call oasis_timer_start('map_read_ceg_sort') |
---|
1403 | lsize = size(mygsmap%start) |
---|
1404 | allocate(lsstart(lsize),lscount(lsize),lspeloc(lsize),stat=status) |
---|
1405 | if (status /= 0) call mct_perr_die(subName,':: allocate Lsstart',status) |
---|
1406 | |
---|
1407 | if (lsize > 10) then |
---|
1408 | ! merge sort |
---|
1409 | allocate(sortkey(lsize),stat=status) |
---|
1410 | if (status /= 0) call mct_perr_die(subName,':: allocate sortkey',status) |
---|
1411 | do n = 1,lsize |
---|
1412 | lsstart(n) = mygsmap%start(n) |
---|
1413 | lscount(n) = mygsmap%length(n) |
---|
1414 | lspeloc(n) = mygsmap%pe_loc(n) |
---|
1415 | sortkey(n) = n |
---|
1416 | enddo |
---|
1417 | call oasis_sys_sortI(lsize,lsstart,sortkey) |
---|
1418 | call oasis_sys_sortIkey(lsize,lscount,sortkey) |
---|
1419 | call oasis_sys_sortIkey(lsize,lspeloc,sortkey) |
---|
1420 | deallocate(sortkey) |
---|
1421 | else |
---|
1422 | ! bubble sort |
---|
1423 | do n = 1,lsize |
---|
1424 | found = .false. |
---|
1425 | l1 = 1 |
---|
1426 | do while (.not.found .and. l1 < n) |
---|
1427 | if (mygsmap%start(n) < lsstart(l1)) then |
---|
1428 | do l2 = n, l1+1, -1 |
---|
1429 | lsstart(l2) = lsstart(l2-1) |
---|
1430 | lscount(l2) = lscount(l2-1) |
---|
1431 | lspeloc(l2) = lspeloc(l2-1) |
---|
1432 | enddo |
---|
1433 | found = .true. |
---|
1434 | else |
---|
1435 | l1 = l1 + 1 |
---|
1436 | endif |
---|
1437 | enddo |
---|
1438 | lsstart(l1) = mygsmap%start(n) |
---|
1439 | lscount(l1) = mygsmap%length(n) |
---|
1440 | lspeloc(l1) = mygsmap%pe_loc(n) |
---|
1441 | enddo |
---|
1442 | endif |
---|
1443 | |
---|
1444 | do n = 1,size(mygsmap%start)-1 |
---|
1445 | if (lsstart(n) > lsstart(n+1)) then |
---|
1446 | write(nulprt,*) subname,estr,'lsstart not properly sorted' |
---|
1447 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1448 | endif |
---|
1449 | enddo |
---|
1450 | if (local_timers_on) call oasis_timer_stop('map_read_ceg_sort') |
---|
1451 | if (local_timers_on) call oasis_timer_start('map_read_ceg_dist') |
---|
1452 | |
---|
1453 | !---------------------------------------------------------------------------- |
---|
1454 | !> * Allocate arrays for reading data on the root |
---|
1455 | !---------------------------------------------------------------------------- |
---|
1456 | |
---|
1457 | allocate(remaps(nwgts,rsize),stat=status) |
---|
1458 | if (status /= 0) call mct_perr_die(subName,':: allocate remaps',status) |
---|
1459 | allocate(SReadData(nwgts,rsize),RReadData(rsize),CReadData(rsize),stat=status) |
---|
1460 | if (status /= 0) call mct_perr_die(subName,':: allocate SReadData',status) |
---|
1461 | allocate(pesave(rsize),stat=status) |
---|
1462 | if (status /= 0) call mct_perr_die(subName,':: allocate pesave',status) |
---|
1463 | allocate(SDistData(nwgts,rsize),RDistData(rsize),CDistData(rsize), stat=status) |
---|
1464 | if (status /= 0) call mct_perr_die(subName,':: allocate SDistData',status) |
---|
1465 | allocate(cntrs(0:mpi_size_local), stat=status) ! Purposefully allocating one extra |
---|
1466 | if (status /= 0) call mct_perr_die(subName,':: allocate cntrs',status) |
---|
1467 | |
---|
1468 | !---------------------------------------------------------------------------- |
---|
1469 | !> * Loop over the chunks of weights data |
---|
1470 | !---------------------------------------------------------------------------- |
---|
1471 | |
---|
1472 | do n = 1,nread |
---|
1473 | start(1) = (n-1)*rsize + 1 |
---|
1474 | count(1) = min(rsize,ns-start(1)+1) |
---|
1475 | start2(1) = 1 |
---|
1476 | count2(1) = nwgts |
---|
1477 | start2(2) = start(1) |
---|
1478 | count2(2) = count(1) |
---|
1479 | |
---|
1480 | !---------------------------------------------------------------------------- |
---|
1481 | !> * Read chunk of data |
---|
1482 | !---------------------------------------------------------------------------- |
---|
1483 | |
---|
1484 | ! status = nf90_inq_varid (fid,'S' ,vid) |
---|
1485 | status = nf90_inq_varid (fid,'remap_matrix' ,vid) |
---|
1486 | if (status /= NF90_NOERR) then |
---|
1487 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1488 | write(nulprt,*) subname,estr,'var not found = ','remap_matrix' |
---|
1489 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1490 | endif |
---|
1491 | ! status = nf90_get_var(fid,vid,start,count,Sbuf) |
---|
1492 | status = nf90_get_var(fid,vid,remaps,start2,count2) |
---|
1493 | if (status /= NF90_NOERR) THEN |
---|
1494 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
1495 | call oasis_flush(nulprt) |
---|
1496 | endif |
---|
1497 | SReadData(:,:) = remaps(:,:) |
---|
1498 | ! status = nf90_inq_varid (fid,'row',vid) |
---|
1499 | status = nf90_inq_varid (fid,'dst_address',vid) |
---|
1500 | if (status /= NF90_NOERR) then |
---|
1501 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1502 | write(nulprt,*) subname,estr,'var not found = ','dst_address' |
---|
1503 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1504 | endif |
---|
1505 | status = nf90_get_var (fid,vid,RReadData,start,count) |
---|
1506 | if (status /= NF90_NOERR) THEN |
---|
1507 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
1508 | call oasis_flush(nulprt) |
---|
1509 | endif |
---|
1510 | |
---|
1511 | ! status = nf90_inq_varid (fid,'col',vid) |
---|
1512 | status = nf90_inq_varid (fid,'src_address',vid) |
---|
1513 | if (status /= NF90_NOERR) then |
---|
1514 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1515 | write(nulprt,*) subname,estr,'var not found = ','src_address' |
---|
1516 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1517 | endif |
---|
1518 | status = nf90_get_var (fid,vid,CReadData,start,count) |
---|
1519 | if (status /= NF90_NOERR) THEN |
---|
1520 | write(nulprt,*) subname,' nf90_strerror = ',TRIM(nf90_strerror(status)) |
---|
1521 | call oasis_flush(nulprt) |
---|
1522 | endif |
---|
1523 | |
---|
1524 | ! Two stage process |
---|
1525 | ! 1. Count how many to send to each process |
---|
1526 | ! 2. Build the sending array up in process receiving order |
---|
1527 | |
---|
1528 | ! Initialize cntrs array for number of accumulations per process |
---|
1529 | cntrs =0 |
---|
1530 | pesave = -99 |
---|
1531 | |
---|
1532 | !---------------------------------------------------------------------------- |
---|
1533 | !> * Determine which process owns each weight and count them |
---|
1534 | !> * Determine offsets in the array |
---|
1535 | !---------------------------------------------------------------------------- |
---|
1536 | |
---|
1537 | if (namwgtopt == "abort_on_bad_index") then |
---|
1538 | abort_weight = .false. |
---|
1539 | do m = 1,count(1) |
---|
1540 | !--- check for bad weights |
---|
1541 | if ((RReadData(m) <= 0 .or. RReadData(m) > nb .or. & |
---|
1542 | CReadData(m) <= 0 .or. CReadData(m) > na) & |
---|
1543 | ! tcx weight = 0 |
---|
1544 | .and. (minval(SReadData(:,m)) /= 0._R8 .or. maxval(SReadData(:,m)) /= 0._R8) & |
---|
1545 | ) then |
---|
1546 | abort_weight = .true. |
---|
1547 | write(nulprt,'(3A,I12,A,I12,A,I12,A,G14.7,A,G14.7,A)') & |
---|
1548 | subname,wstr,'BAD weight found in '//trim(filename), & |
---|
1549 | m,'=id',CReadData(m),'=src',RReadData(m),'=dst',minval(SReadData(:,m)),'=minS',maxval(SReadData(:,m)),'=maxS' |
---|
1550 | endif |
---|
1551 | enddo |
---|
1552 | if (abort_weight) then |
---|
1553 | write(nulprt,*) subname,wstr,'BAD weight found, aborting' |
---|
1554 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1555 | endif |
---|
1556 | endif |
---|
1557 | |
---|
1558 | do m = 1,count(1) |
---|
1559 | !--- check for bad weights |
---|
1560 | if ((namwgtopt(1:16) == "ignore_bad_index") .and. & |
---|
1561 | (RReadData(m) <= 0 .or. RReadData(m) > nb .or. & |
---|
1562 | CReadData(m) <= 0 .or. CReadData(m) > na)) then |
---|
1563 | pe = -11 |
---|
1564 | ! tcx weight = 0 |
---|
1565 | if (minval(SReadData(:,m)) /= 0._R8 .or. maxval(SReadData(:,m)) /= 0._R8) then |
---|
1566 | if (OASIS_debug >= 2 .and. namwgtopt /= "ignore_bad_index_silently") then |
---|
1567 | write(nulprt,'(3A,I12,A,I12,A,I12,A,G14.7,A,G14.7,A)') & |
---|
1568 | subname,wstr,'BAD weight found in '//trim(filename), & |
---|
1569 | m,'=id',CReadData(m),'=src',RReadData(m),'=dst',minval(SReadData(:,m)),'=minS',maxval(SReadData(:,m)),'=maxS' |
---|
1570 | endif |
---|
1571 | endif |
---|
1572 | else if (newdom == 'src') then |
---|
1573 | pe = get_cegindex(RReadData(m),lsstart,lscount,lspeloc) |
---|
1574 | else if (newdom == 'dst') then |
---|
1575 | pe = get_cegindex(CReadData(m),lsstart,lscount,lspeloc) |
---|
1576 | endif |
---|
1577 | pesave(m) = pe |
---|
1578 | |
---|
1579 | ! Copy data, incrementing index array, pe = 1 to mpi_size_local |
---|
1580 | if (pe == -11) then |
---|
1581 | ! skip it, understood, get_cegindex will error with -99 |
---|
1582 | elseif (pe+1 < 1 .or. pe+1 > mpi_size_local) then |
---|
1583 | ! skip this case too |
---|
1584 | ! write(nulprt,*) subname,wstr,'get_cegindex search error', m,count(1),CReadData(m),RReadData(m),SReadData(:,m) |
---|
1585 | else |
---|
1586 | cntrs(pe+1) = cntrs(pe+1) + 1 ! Note incrementing 1->noprocs rather than 0->noprocs-1 |
---|
1587 | endif |
---|
1588 | |
---|
1589 | end do |
---|
1590 | |
---|
1591 | cntrs(0) = 1 |
---|
1592 | do pe = 1, mpi_size_local |
---|
1593 | cntrs(pe) = cntrs(pe-1) + cntrs(pe) |
---|
1594 | end do |
---|
1595 | |
---|
1596 | !---------------------------------------------------------------------------- |
---|
1597 | !> * Determine which process owns each weight and fill arrays |
---|
1598 | !---------------------------------------------------------------------------- |
---|
1599 | |
---|
1600 | do m = 1,count(1) |
---|
1601 | |
---|
1602 | pe = pesave(m) |
---|
1603 | |
---|
1604 | ! Copy data, incrementing index array, pe = 1 to mpi_size_local |
---|
1605 | if (pe+1 < 1 .or. pe+1 > mpi_size_local) then |
---|
1606 | ! skip it |
---|
1607 | ! write(nulprt,*) subname,'get_cegindex search error2', m,count(1),CReadData(m),RReadData(m),SReadData(:,m) |
---|
1608 | else |
---|
1609 | ! Copy data, incrementing index array |
---|
1610 | SDistData(:,cntrs(pe)) = SReadData(:,m) |
---|
1611 | RDistData(cntrs(pe)) = RReadData(m) |
---|
1612 | CDistData(cntrs(pe)) = CReadData(m) |
---|
1613 | |
---|
1614 | cntrs(pe) = cntrs(pe) + 1 |
---|
1615 | endif |
---|
1616 | |
---|
1617 | enddo ! count |
---|
1618 | |
---|
1619 | !---------------------------------------------------------------------------- |
---|
1620 | !> * Send select data from root to other processes |
---|
1621 | ! Copy root process data into local array |
---|
1622 | ! Send data from root to other processes |
---|
1623 | !---------------------------------------------------------------------------- |
---|
1624 | |
---|
1625 | if (cntrs(0).gt.1) then ! Need to do it differently if it is for me! |
---|
1626 | reclen = cntrs(0)-1 |
---|
1627 | ! Reallocate local weights arrays if they need to be bigger |
---|
1628 | call augment_arrays(cnt, reclen, bsize, nwgts) |
---|
1629 | |
---|
1630 | !--- now p0 copies straight into the ?new arrays |
---|
1631 | Snew(1:nwgts,cnt:cnt+reclen-1) = SDistData(1:nwgts,1:reclen) |
---|
1632 | Rnew(cnt:cnt+reclen-1) = RDistData(1:reclen) |
---|
1633 | Cnew(cnt:cnt+reclen-1) = CDistData(1:reclen) |
---|
1634 | cnt = cnt + reclen |
---|
1635 | |
---|
1636 | endif |
---|
1637 | |
---|
1638 | do pe = 1, mpi_size_local |
---|
1639 | if (cntrs(pe).gt.cntrs(pe-1)) then |
---|
1640 | ! Send data out |
---|
1641 | m = cntrs(pe)-cntrs(pe-1) |
---|
1642 | ! write(nulprt,*) subname, 'Sending [to, datalen] ', pe, m, cntrs(pe-1), cntrs(pe) |
---|
1643 | call MPI_Send(m, 1, MPI_INTEGER, pe, 4000, mpicom, ierr) |
---|
1644 | call MPI_Send(SDistData(1,cntrs(pe-1)), nwgts*m, MPI_REAL8, pe, 1000, mpicom, ierr) |
---|
1645 | call MPI_Send(RDistData(cntrs(pe-1)), m, MPI_INTEGER, pe, 2000, mpicom, ierr) |
---|
1646 | call MPI_Send(CDistData(cntrs(pe-1)), m, MPI_INTEGER, pe, 3000, mpicom, ierr) |
---|
1647 | endif |
---|
1648 | enddo |
---|
1649 | |
---|
1650 | enddo ! nread |
---|
1651 | |
---|
1652 | !---------------------------------------------------------------------------- |
---|
1653 | !> * Deallocate memory on root process |
---|
1654 | !---------------------------------------------------------------------------- |
---|
1655 | |
---|
1656 | m = -1 |
---|
1657 | do pe = 1, mpi_size_local-1 |
---|
1658 | !write(nulprt,*) subname, 'Final sending [to, datalen] ', m, cntrs(m) |
---|
1659 | call MPI_Send(m, 1, MPI_INTEGER, pe, 4000, mpicom, ierr) |
---|
1660 | end do |
---|
1661 | |
---|
1662 | ! Free memory used during the distribution |
---|
1663 | deallocate(lsstart,lscount,lspeloc, stat=status) |
---|
1664 | if (status /= 0) call mct_perr_die(subName,':: deallocate lsstart',status) |
---|
1665 | deallocate(pesave, stat=status) |
---|
1666 | if (status /= 0) call mct_perr_die(subName,':: deallocate pesave',status) |
---|
1667 | deallocate(SReadData,RReadData,CReadData, stat=status) |
---|
1668 | if (status /= 0) call mct_perr_die(subName,':: deallocate SReadData',status) |
---|
1669 | deallocate(SDistData,RDistData,CDistData, stat=status) |
---|
1670 | if (status /= 0) call mct_perr_die(subName,':: deallocate SDistData',status) |
---|
1671 | deallocate(cntrs, stat=status) |
---|
1672 | if (status /= 0) call mct_perr_die(subName,':: deallocate cntrs',status) |
---|
1673 | deallocate(remaps, stat=status) |
---|
1674 | if (status /= 0) call mct_perr_die(subName,':: deallocate remaps',status) |
---|
1675 | |
---|
1676 | if (local_timers_on) call oasis_timer_stop('map_read_ceg_dist') |
---|
1677 | |
---|
1678 | !---------------------------------------------------------------------------- |
---|
1679 | !> * On non-root processes |
---|
1680 | !---------------------------------------------------------------------------- |
---|
1681 | |
---|
1682 | else ! mytask == 0 |
---|
1683 | |
---|
1684 | if (local_timers_on) call oasis_timer_start('map_read_ceg_dist') |
---|
1685 | !---------------------------------------------------------------------------- |
---|
1686 | !> * Receive data from root |
---|
1687 | !---------------------------------------------------------------------------- |
---|
1688 | |
---|
1689 | call oasis_mpi_recv(reclen, 0, 4000, mpicom, subName//" MPI in reclen recv") |
---|
1690 | ! Check we haven't now had the last data |
---|
1691 | do while (reclen.ne.-1) |
---|
1692 | |
---|
1693 | !--- recv S, row, col on all other pes |
---|
1694 | !write(nulprt,*) subname, 'Receiving [global-id, datalen] ', mpi_rank_global, reclen |
---|
1695 | call MPI_Recv(Sbuf, reclen*nwgts, MPI_REAL8, 0, 1000, mpicom, MPI_STATUS_IGNORE, ierr) |
---|
1696 | call MPI_Recv(Rbuf, reclen, MPI_INTEGER, 0, 2000, mpicom, MPI_STATUS_IGNORE, ierr) |
---|
1697 | call MPI_Recv(Cbuf, reclen, MPI_INTEGER, 0, MPI_ANY_TAG, mpicom, mpistatus, ierr) |
---|
1698 | |
---|
1699 | !---------------------------------------------------------------------------- |
---|
1700 | !> * Reallocate local weights arrays if they need to be bigger |
---|
1701 | !---------------------------------------------------------------------------- |
---|
1702 | |
---|
1703 | call augment_arrays(cnt, reclen, bsize, nwgts) |
---|
1704 | |
---|
1705 | !--- now each pe keeps what it has been sent |
---|
1706 | Snew(1:nwgts,cnt:cnt+reclen-1) = Sbuf(1:nwgts,1:reclen) |
---|
1707 | Rnew(cnt:cnt+reclen-1) = Rbuf(1:reclen) |
---|
1708 | Cnew(cnt:cnt+reclen-1) = Cbuf(1:reclen) |
---|
1709 | cnt = cnt + reclen |
---|
1710 | |
---|
1711 | call oasis_mpi_recv(reclen, 0, 4000, mpicom, subName//" MPI in reclen recv") |
---|
1712 | end do |
---|
1713 | if (local_timers_on) call oasis_timer_stop('map_read_ceg_dist') |
---|
1714 | |
---|
1715 | endif ! mytask == 0 |
---|
1716 | |
---|
1717 | if (local_timers_on) call oasis_timer_start('map_read_ceg_smati') |
---|
1718 | ! Fix cnt to be the length of the array |
---|
1719 | cnt = cnt-1 |
---|
1720 | |
---|
1721 | !---------------------------------------------------------------------------- |
---|
1722 | !> * Clean up arrays |
---|
1723 | !---------------------------------------------------------------------------- |
---|
1724 | |
---|
1725 | deallocate(Sbuf,Rbuf,Cbuf, stat=status) |
---|
1726 | if (status /= 0) call mct_perr_die(subName,':: deallocate Sbuf',status) |
---|
1727 | |
---|
1728 | !---------------------------------------------------------------------------- |
---|
1729 | !> * Initialize the mct sMat data type |
---|
1730 | !---------------------------------------------------------------------------- |
---|
1731 | |
---|
1732 | ! mct_sMat_init must be given the number of rows and columns that |
---|
1733 | ! would be in the full matrix. Nrows= size of output vector=nb. |
---|
1734 | ! Ncols = size of input vector = na. |
---|
1735 | do n = 1,nwgts |
---|
1736 | call mct_sMat_init(sMat(n), nb, na, cnt) |
---|
1737 | enddo |
---|
1738 | |
---|
1739 | igrow = mct_sMat_indexIA(sMat(1),'grow') |
---|
1740 | igcol = mct_sMat_indexIA(sMat(1),'gcol') |
---|
1741 | iwgt = mct_sMat_indexRA(sMat(1),'weight') |
---|
1742 | |
---|
1743 | if (cnt /= 0) then |
---|
1744 | do n = 1,nwgts |
---|
1745 | sMat(n)%data%rAttr(iwgt ,1:cnt) = Snew(n,1:cnt) |
---|
1746 | sMat(n)%data%iAttr(igrow,1:cnt) = Rnew(1:cnt) |
---|
1747 | sMat(n)%data%iAttr(igcol,1:cnt) = Cnew(1:cnt) |
---|
1748 | enddo |
---|
1749 | endif |
---|
1750 | if (local_timers_on) call oasis_timer_stop('map_read_ceg_smati') |
---|
1751 | |
---|
1752 | !---------------------------------------------------------------------------- |
---|
1753 | !> * More clean up |
---|
1754 | !---------------------------------------------------------------------------- |
---|
1755 | |
---|
1756 | if (local_timers_on) call oasis_timer_start('map_read_ceg_clean') |
---|
1757 | deallocate(Snew,Rnew,Cnew, stat=status) |
---|
1758 | if (status /= 0) call mct_perr_die(subName,':: deallocate new',status) |
---|
1759 | |
---|
1760 | if (mytask == 0) then |
---|
1761 | status = nf90_close(fid) |
---|
1762 | if (status /= NF90_NOERR) then |
---|
1763 | write(nulprt,*) subname,' nf90_strerror = ',trim(nf90_strerror(status)) |
---|
1764 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
1765 | endif |
---|
1766 | if (OASIS_debug >= 2) THEN |
---|
1767 | write(nulprt,*) subname," ... done reading file" |
---|
1768 | call oasis_flush(nulprt) |
---|
1769 | endif |
---|
1770 | endif |
---|
1771 | |
---|
1772 | if (local_timers_on) call oasis_timer_stop('map_read_ceg_clean') |
---|
1773 | call oasis_debug_exit(subname) |
---|
1774 | |
---|
1775 | end subroutine oasis_map_sMatReaddnc_ceg |
---|
1776 | |
---|
1777 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
1778 | !!!!!!!!!!!!!!!!!!!!!!!!! Extend array and store data !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
1779 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
1780 | |
---|
1781 | !> Function that increases temporary work array size of Snew, Rnew, Cnew |
---|
1782 | |
---|
1783 | subroutine augment_arrays(cnt, reclen, bsize, nwgts) |
---|
1784 | |
---|
1785 | ! !USES: |
---|
1786 | |
---|
1787 | integer, intent(inout) :: cnt !< elements in current array |
---|
1788 | integer, intent(in) :: reclen !< elements of new data |
---|
1789 | integer, intent(inout) :: bsize !< max size of current array |
---|
1790 | integer, intent(in) :: nwgts !< number of weights in S |
---|
1791 | |
---|
1792 | integer :: status ! netCDF routine return code |
---|
1793 | !--- formats --- |
---|
1794 | character(*),parameter :: subName = '(ceg_coupler_augment_arrays)' |
---|
1795 | |
---|
1796 | |
---|
1797 | !--- ?new arrays need to be bigger? |
---|
1798 | if (cnt+reclen > bsize) then |
---|
1799 | |
---|
1800 | ! write(nulprt,*) subname,mpi_rank_global, 'EXTEND' |
---|
1801 | |
---|
1802 | !--- allocate old arrays and copy new into old |
---|
1803 | allocate(Sold(1:nwgts,cnt),Rold(cnt),Cold(cnt),stat=status) |
---|
1804 | if (status /= 0) call mct_perr_die(subName,':: allocate old',status) |
---|
1805 | Sold(1:nwgts,1:cnt-1) = Snew(1:nwgts,1:cnt-1) |
---|
1806 | Rold(1:cnt-1) = Rnew(1:cnt-1) |
---|
1807 | Cold(1:cnt-1) = Cnew(1:cnt-1) |
---|
1808 | |
---|
1809 | !--- reallocate new to bigger size, increase buffer by 50% (arbitrary) |
---|
1810 | deallocate(Snew,Rnew,Cnew,stat=status) |
---|
1811 | if (status /= 0) call mct_perr_die(subName,':: allocate new',status) |
---|
1812 | bsize = 1.5 * (cnt+reclen) |
---|
1813 | if (OASIS_debug > 15) write(nulprt,*) subname,' reallocate bsize to ',bsize |
---|
1814 | allocate(Snew(nwgts,bsize),Rnew(bsize),Cnew(bsize),stat=status) |
---|
1815 | if (status /= 0) call mct_perr_die(subName,':: allocate old',status) |
---|
1816 | |
---|
1817 | !--- copy data back into new |
---|
1818 | Snew(1:nwgts,1:cnt-1) = Sold(1:nwgts,1:cnt-1) |
---|
1819 | Rnew(1:cnt-1) = Rold(1:cnt-1) |
---|
1820 | Cnew(1:cnt-1) = Cold(1:cnt-1) |
---|
1821 | deallocate(Sold,Rold,Cold,stat=status) |
---|
1822 | if (status /= 0) call mct_perr_die(subName,':: deallocate old',status) |
---|
1823 | endif |
---|
1824 | |
---|
1825 | end subroutine augment_arrays |
---|
1826 | |
---|
1827 | !------------------------------------------------------------ |
---|
1828 | ! !BOP =========================================================================== |
---|
1829 | ! |
---|
1830 | !> Function that checks whether an index is part of a start and count list |
---|
1831 | ! |
---|
1832 | !> Does a binary search on a sorted start and count list to determine |
---|
1833 | !> whether index is a value in the list. The list values consist of |
---|
1834 | !> the values start(i):start(i)+count(i)-1 for all i. |
---|
1835 | ! |
---|
1836 | ! !DESCRIPTION: |
---|
1837 | ! Do a binary search to see if a value is contained in a list of |
---|
1838 | ! values. return true or false. starti must be monotonically |
---|
1839 | ! increasing, function does NOT check this. |
---|
1840 | ! |
---|
1841 | ! !INTERFACE: ----------------------------------------------------------------- |
---|
1842 | |
---|
1843 | logical function check_myindex(index,starti,counti) |
---|
1844 | |
---|
1845 | ! !USES: |
---|
1846 | |
---|
1847 | !--- local kinds --- |
---|
1848 | integer,parameter :: R8 = ip_double_p |
---|
1849 | integer,parameter :: IN = ip_i4_p |
---|
1850 | |
---|
1851 | ! !INPUT/OUTPUT PARAMETERS: |
---|
1852 | |
---|
1853 | integer(IN) :: index !< index to search |
---|
1854 | integer(IN) :: starti(:) !< start list |
---|
1855 | integer(IN) :: counti(:) !< count list |
---|
1856 | |
---|
1857 | ! !EOP |
---|
1858 | |
---|
1859 | !--- local --- |
---|
1860 | integer(IN) :: nl,nc,nr,ncprev |
---|
1861 | integer(IN) :: lsize |
---|
1862 | logical :: stopnow |
---|
1863 | |
---|
1864 | !--- formats --- |
---|
1865 | character(*),parameter :: subName = '(check_myindex) ' |
---|
1866 | |
---|
1867 | !------------------------------------------------------------------------------- |
---|
1868 | ! |
---|
1869 | !------------------------------------------------------------------------------- |
---|
1870 | |
---|
1871 | ! call oasis_debug_enter(subname) |
---|
1872 | check_myindex = .false. |
---|
1873 | |
---|
1874 | lsize = size(starti) |
---|
1875 | if (lsize < 1) then |
---|
1876 | ! call oasis_debug_exit(subname) |
---|
1877 | return |
---|
1878 | endif |
---|
1879 | |
---|
1880 | nl = 0 |
---|
1881 | nr = lsize + 1 |
---|
1882 | nc = (nl+nr)/2 |
---|
1883 | stopnow = .false. |
---|
1884 | do while (.not.stopnow) |
---|
1885 | if (index < starti(nc)) then |
---|
1886 | nr = nc |
---|
1887 | elseif (index > (starti(nc) + counti(nc) - 1)) then |
---|
1888 | nl = nc |
---|
1889 | else |
---|
1890 | check_myindex = .true. |
---|
1891 | ! call oasis_debug_exit(subname) |
---|
1892 | return |
---|
1893 | endif |
---|
1894 | ncprev = nc |
---|
1895 | nc = (nl + nr)/2 |
---|
1896 | if (nc == ncprev .or. nc < 1 .or. nc > lsize) stopnow = .true. |
---|
1897 | enddo |
---|
1898 | |
---|
1899 | check_myindex = .false. |
---|
1900 | |
---|
1901 | ! call oasis_debug_exit(subname) |
---|
1902 | |
---|
1903 | end function check_myindex |
---|
1904 | |
---|
1905 | !------------------------------------------------------------ |
---|
1906 | ! !BOP =========================================================================== |
---|
1907 | ! |
---|
1908 | !> Function that carrys out a binary search for index in list |
---|
1909 | ! |
---|
1910 | ! !DESCRIPTION: |
---|
1911 | ! Do a binary search to see if a value is contained in a list of |
---|
1912 | ! values. return value of processor that owns it |
---|
1913 | ! starti must be monotonically |
---|
1914 | ! increasing, function does NOT check this. |
---|
1915 | ! |
---|
1916 | ! !INTERFACE: ----------------------------------------------------------------- |
---|
1917 | |
---|
1918 | integer function get_cegindex(index,starti,counti,peloci) |
---|
1919 | |
---|
1920 | ! !USES: |
---|
1921 | |
---|
1922 | |
---|
1923 | !--- local kinds --- |
---|
1924 | integer,parameter :: R8 = ip_double_p |
---|
1925 | integer,parameter :: IN = ip_i4_p |
---|
1926 | |
---|
1927 | ! !INPUT/OUTPUT PARAMETERS: |
---|
1928 | |
---|
1929 | integer(IN) :: index !< index to search |
---|
1930 | integer(IN) :: starti(:) !< start list |
---|
1931 | integer(IN) :: counti(:) !< count list |
---|
1932 | integer(IN) :: peloci(:) !< pe list |
---|
1933 | |
---|
1934 | ! !EOP |
---|
1935 | |
---|
1936 | |
---|
1937 | !--- local --- |
---|
1938 | integer(IN) :: nl,nc,nr,ncprev |
---|
1939 | integer(IN) :: lsize |
---|
1940 | logical :: stopnow |
---|
1941 | |
---|
1942 | !--- formats --- |
---|
1943 | character(*),parameter :: subName = '(get_cegindex) ' |
---|
1944 | |
---|
1945 | !------------------------------------------------------------------------------- |
---|
1946 | ! |
---|
1947 | !------------------------------------------------------------------------------- |
---|
1948 | ! call oasis_debug_enter(subname) |
---|
1949 | |
---|
1950 | get_cegindex = -99 |
---|
1951 | lsize = size(starti) |
---|
1952 | if (lsize < 1) then |
---|
1953 | ! call oasis_debug_exit(subname) |
---|
1954 | return |
---|
1955 | endif |
---|
1956 | |
---|
1957 | nl = 0 |
---|
1958 | nr = lsize + 1 |
---|
1959 | nc = (nl+nr)/2 |
---|
1960 | stopnow = .false. |
---|
1961 | do while (.not.stopnow) |
---|
1962 | if (index < starti(nc)) then |
---|
1963 | nr = nc |
---|
1964 | elseif (index > (starti(nc) + counti(nc) - 1)) then |
---|
1965 | nl = nc |
---|
1966 | else |
---|
1967 | get_cegindex = peloci(nc) |
---|
1968 | ! call oasis_debug_exit(subname) |
---|
1969 | return |
---|
1970 | endif |
---|
1971 | ncprev = nc |
---|
1972 | nc = (nl + nr)/2 |
---|
1973 | if (nc == ncprev .or. nc < 1 .or. nc > lsize) stopnow = .true. |
---|
1974 | enddo |
---|
1975 | |
---|
1976 | |
---|
1977 | ! call oasis_debug_exit(subname) |
---|
1978 | |
---|
1979 | |
---|
1980 | end function get_cegindex |
---|
1981 | |
---|
1982 | !=============================================================================== |
---|
1983 | END MODULE mod_oasis_map |
---|
1984 | |
---|
1985 | |
---|