Original WRF subgrid support version from John Michalakes without fire
[wrffire.git] / wrfv2_fire / external / RSL / RSL / message_def.c
blob279605281c6092281995327e0e72a52a97f710c8
1 /***********************************************************************
3 COPYRIGHT
5 The following is a notice of limited availability of the code and
6 Government license and disclaimer which must be included in the
7 prologue of the code and in all source listings of the code.
9 Copyright notice
10 (c) 1977 University of Chicago
12 Permission is hereby granted to use, reproduce, prepare
13 derivative works, and to redistribute to others at no charge. If
14 you distribute a copy or copies of the Software, or you modify a
15 copy or copies of the Software or any portion of it, thus forming
16 a work based on the Software and make and/or distribute copies of
17 such work, you must meet the following conditions:
19 a) If you make a copy of the Software (modified or verbatim)
20 it must include the copyright notice and Government
21 license and disclaimer.
23 b) You must cause the modified Software to carry prominent
24 notices stating that you changed specified portions of
25 the Software.
27 This software was authored by:
29 Argonne National Laboratory
30 J. Michalakes: (630) 252-6646; email: michalak@mcs.anl.gov
31 Mathematics and Computer Science Division
32 Argonne National Laboratory, Argonne, IL 60439
34 ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES
35 OF ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT,
36 AND OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A
37 CONTRACT WITH THE DEPARTMENT OF ENERGY.
39 GOVERNMENT LICENSE AND DISCLAIMER
41 This computer code material was prepared, in part, as an account
42 of work sponsored by an agency of the United States Government.
43 The Government is granted for itself and others acting on its
44 behalf a paid-up, nonexclusive, irrevocable worldwide license in
45 this data to reproduce, prepare derivative works, distribute
46 copies to the public, perform publicly and display publicly, and
47 to permit others to do so. NEITHER THE UNITED STATES GOVERNMENT
48 NOR ANY AGENCY THEREOF, NOR THE UNIVERSITY OF CHICAGO, NOR ANY OF
49 THEIR EMPLOYEES, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
50 ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY,
51 COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS,
52 PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD
53 NOT INFRINGE PRIVATELY OWNED RIGHTS.
55 ***************************************************************************/
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include "rsl.h"
61 /*@
62 RSL_CREATE_MESSAGE - create a descriptor for an RSL message.
64 Synopsis:
65 RSL_CREATE_MESSAGE ( m )
66 integer m
68 Input parameter:
69 . m - message descriptor
71 Notes:
72 Create a descriptor for an RSL message. On return, the
73 integer Arg1 will contain a handle to a new RSL message.
74 Messages exist only temporarily by themselves -- once a message
75 has been asssociated with a stencil or a state vector, the handle
76 becomes invalid.
78 See also:
79 RSL_BUILD_MESSAGE, RSL_DESCRIBE_STENCIL, RSL_DESCRIBE_STATE
81 @*/
84 RSL_CREATE_MESSAGE ( mh_p )
85 int_p mh_p ;
88 int i ;
89 message_desc_t *msg ;
91 /* NOTE: never return the 0th message descriptor */
92 for ( i = 1 ; i < RSL_MAXDESCRIPTORS ; i++ )
93 if ( mh_descriptors[i] == NULL ) break ; /* got one */
95 RSL_TEST_ERR( i == RSL_MAXDESCRIPTORS,
96 "rsl_create_message: out of descriptors.\nAre you creating messages and then not associating them with\na stencil, bcast/merge, or state vector?" ) ;
98 *mh_p = i ;
99 msg = RSL_MALLOC(message_desc_t,1) ;
100 msg->tag = MESSAGE_DESC ;
101 msg->mh = *mh_p ;
102 mh_descriptors[*mh_p] = msg ;
105 /* Only ever called internally to RSL. This routine is for use
106 by routines that associate messages with other RSL constructs. Once
107 the association is made, those constructs point to the messages. We
108 do *not* free the message description structures here, only free up
109 the descriptors so they can be used again. */
111 release_mh_descriptor (mh_p)
112 int_p mh_p ;
114 int mh ;
116 mh = *mh_p ;
118 if ( mh == RSL_INVALID ) return ;
120 RSL_TEST_ERR( mh <= 0 || mh >= RSL_MAXDESCRIPTORS,
121 "internal error. Invalid message descriptor.") ;
122 if ( mh_descriptors[mh] != NULL )
124 mh_descriptors[mh] = NULL ;
126 /* it can happen that this will be called for a descriptor that
127 has already been nulled out. Let it happen. */
132 RSL_BLANK_MESSAGE - (obsolete) describe a message for broadcast/merges.
134 Synopsis:
135 RSL_BLANK_MESSAGE ( m, len )
136 integer m
137 integer len
139 Input parameter:
140 . m - message descriptor
141 . len - length, in bytes, of message
143 Notes:
144 Messages to be used in a broadcast or a merge operation
145 for inter-domain communication do not have fields associated
146 with them ahead of time, unlike messages that are used
147 in stencil exchanges (see RSL_BUILD_MESSAGE). Rather, the
148 packing and unpacking routines are provided by the user,
149 and the message is simply a stream of bytes. RSL_BLANK_MESSAGE
150 designates a message as a blank message and associates with
151 the message its length in bytes.
153 See also:
154 RSL_BUILD_MESSAGE, RSL_COMP_BCAST, RSL_COMP_MERGE
158 RSL_BLANK_MESSAGE ( mh_p, len_p )
159 int_p mh_p ; /* message handle */
160 int_p len_p ; /* length in bytes */
162 int mh, len ;
163 message_desc_t *msg ;
165 mh = *mh_p ; len = *len_p ;
167 RSL_TEST_ERR((mh <= 0)|| (mh >= RSL_MAXDESCRIPTORS),
168 "rsl_blank_message: bad message handle" ) ;
169 RSL_TEST_ERR((msg = (message_desc_t *)mh_descriptors[mh])==NULL,
170 "descriptor for null message");
171 RSL_TEST_ERR( msg->tag != MESSAGE_DESC,
172 "rsl_blank_message: handle given is not for an rsl message def" ) ;
174 msg->tag = BLANK_MESSAGE_DESC ; /* change tag */
175 msg->nbytes = len ;
176 return ;
180 RSL_BUILD_MESSAGE - Add a 2- or 3-dimensional field to a message.
182 Notes:
183 An RSL message is a set of fields that are to be communicated
184 for a point in the model grid. Describing messages in this way
185 allows RSL to assume control of packing and unpacking of model data
186 from and to local processor memory for efficient and transparent
187 communication of stencil exchanges and state remappings.
189 A field (Arg3), a multi-dimensional
190 array of a given type (Arg2),
192 added
193 to a message (Arg1) by repeated calls to RSL_BUILD_MESSAGE.
194 Once constructed, messages may then be combined into stencils
195 (RSL_DESCRIBE_STENCIL) for stencil exchanges (RSL_EXCH_STENCIL).
196 A message may also be used to describe a state-vector (RSL_DESCRIBE_STATE)
197 used in remapping for load balancing.
199 The Arg4 argument gives the number of dimensions in the field
200 being added to the message. It is permissable to mix 2 and 3
201 dimensional fields. Regardless, however, 2 and only dimensions
202 of the field
203 must be decomposed.
204 The three arguments Arg4, Arg5, and Arg6, are integer arrays
205 of size Arg4. The indicies of these arrays correspond to the
206 dimensions of the field being added; index 1 is the most minor,
207 and index ndim is the most major dimension.
209 The values stored in the Arg4 array may be
211 Verbatim:
212 $ RSL_NORTHSOUTH -- decomposed over M
213 $ RSL_EASTWEST -- decomposed over N
214 $ RSL_NOTDECOMPOSED. -- not decomposed.
215 BREAKTHEEXAMPLECODE
217 This tells RSL whether the
218 dimension in question is decomposed over a north/south column of
219 processors in the mesh, an east-west row in the mesh, or -- as is the
220 case with the vertical dimension in 3-d arrays -- not decomposed at
221 all. RSL_NORTHSOUTH, RSL_EASTWEST, and RSL_NOTDECOMPOSED are
222 defined in the RSL include file "rsl.inc".
224 The values stored in the Arg5 array are the global, or
225 undecomposed, sizes of each dimension of the field. The values
226 stored in the Arg6 array are the local, or actual,
227 sizes of the dimensions of the field as it exists in the processor's
228 memory. If the field is statically declared (say, in common) the
229 sizes would be the sizes that were used to declare the array itself.
230 If the array is dynamically allocated using a Fortran90
231 ALLOCATE() statement, the values of llen would be sizes that
232 were specified to the ALLOCATE() statement. In the latter case,
233 if these sizes ever change during the course of a run, it would
234 be necessary to destroy this message and reconstruct a new one
235 for RSL, since it must always be able to determine the true size
236 in memory of the data structures involved in messaging operations.
238 Example:
239 $ integer m ! message descriptor
240 $ integer decomp(3), llen(3), glen(3) ! dimension descriptions
241 $ real ua(ix,jx,kx), va(ix,jx,kx) ! locally dimensioned 3-d arrays
242 $ real psa(ix,jx,kx) ! locally dimensioned 2-d array
244 $ decomp(1) = RSL_NORTHSOUTH ! how most minor dim decomposed
245 $ decomp(2) = RSL_EASTWEST ! how next dim decomposed
246 $ decomp(3) = RSL_NOTDECOMPOSED ! major dim (vertical) not decomposed
248 $ glen(1) = g_ix ! global size in n/s
249 $ glen(2) = g_jx ! global size in e/w
250 $ glen(3) = kx ! size in vertical
251 $ llen(1) = ix ! local size in n/s
252 $ llen(2) = jx ! local size in e/w
253 $ llen(3) = kx ! local size of vertical (same as global)
255 $ call rsl_create_message( m )
256 $ call rsl_build_message( m, RSL_REAL, ua, 3, decomp, glen, llen )
257 $ call rsl_build_message( m, RSL_REAL, va, 3, decomp, glen, llen )
258 $ call rsl_build_message( m, RSL_REAL, psa, 2, decomp, glen, llen )
261 BREAKTHEEXAMPLECODE
263 In the above example, a message is created and then built by
264 adding two three-dimensional fields and one two-dimensional field.
265 The order of the construction is not important. Subsequent
266 to these statements, the completed message could be used to define
267 one or more points of a stencil exchange to communicate ua,
268 psa, and va between processors.
271 See also:
272 RSL_CREATE_MESSAGE, RSL_BLANK_MESSAGE, RSL_DESCRIBE_STENCIL,
273 RSL_DESCRIBE_STATE
277 static struct f90_base_table_entry {
278 char * base, * virt_base ;
279 int size_in_bytes ;
280 } f90_base_table[ MAX_BASE_TABLE_ENTRIES ] ;
281 static int base_table_cursor = 1;
282 static int base_table_size = 1;
284 RSL_BUILD_MESSAGE ( mh_p, t_p, base, ndim_p, decomp, glen, llen )
285 int_p
286 mh_p /* (I) Message handle created by RSL_CREATE_MESSAGE. */
287 ,t_p /* (I) RSL type description. */
288 ,ndim_p ; /* (I) Number of dimensions of field being added to message.*/
289 void *
290 base ; /* (I) Base address field in local memory. */
291 int
292 decomp[] ; /* (I) How decomposed. */
293 int
294 glen[] ; /* (I) Global (undecomposed) dimensions of field. */
295 int
296 llen[] ; /* (I) Local (decomposed) dimensions of field. */
298 int mh, t, ndim, i ;
299 message_desc_t *msg ;
300 rsl_fldspec_t *fld ;
301 int dim ;
302 int f90_table_index ;
303 char errmess[256] ;
305 mh = *mh_p ; t = *t_p ; ndim = *ndim_p ;
307 RSL_TEST_ERR( ndim < 0, "rsl_build_message: bad ndim argument" ) ;
308 RSL_TEST_ERR( ndim > RSL_MAXDIM,
309 "rsl_build_message: ndim too large. Change RSL_MAXDIM; recompile librsl.a." ) ;
310 RSL_TEST_ERR((mh <= 0)||(mh >= RSL_MAXDESCRIPTORS),
311 "rsl_build_message: bad message handle" ) ;
312 if ( (msg = (message_desc_t *)mh_descriptors[mh])==NULL )
314 RSL_TEST_ERR(1, "descriptor for null message");
316 RSL_TEST_ERR( msg->tag != MESSAGE_DESC,
317 "rsl_build_message: handle given is not for an rsl message def" ) ;
319 fld = RSL_MALLOC( rsl_fldspec_t, 1 ) ;
321 fld->type = t ;
322 fld->elemsz = elemsize( t ) ;
323 for ( fld->memsize = fld->elemsz, i = 0 ; i < ndim ; i++ )
325 fld->memsize = fld->memsize * llen[i] ;
328 if ( t >= 100 )
330 if ( ! (fld->f90_table_index = get_index_for_base( base )) )
331 { RSL_TEST_ERR(1,"Use of unregistered f90 typed variable") ; }
332 #if 0
333 fld->base = (void *)((fld->f90_table_index-1) * F90_MAX_FLD_SIZE_IN_BYTES + 1) ; /* don't allow base of 0 */
334 #else
335 fld->base = f90_base_table[ fld->f90_table_index ].virt_base ;
336 #endif
338 else
340 fld->base = base ;
342 fld->ndim = ndim ;
343 for ( dim = 0 ; dim < ndim ; dim++ )
345 fld->decomp[dim] = decomp[dim] ;
346 fld->gdex[dim] = RSL_INVALID ; /* this gets filled in dynamically */
347 if ( decomp[dim] == RSL_NOTDECOMPOSED && glen[dim] != llen[dim] )
349 sprintf(errmess,
350 "rsl_build_message: mesg %d: dim %d is RSL_NOTDECOMPOSED so glen(%d)=%d must eq llen(%d)=%d",
351 mh, dim+1, dim+1, glen[dim], dim+1, llen[dim] ) ;
352 RSL_TEST_WRN( 1, errmess ) ;
354 fld->glen[dim] = glen[dim] ;
355 fld->llen[dim] = llen[dim] ;
356 if ( decomp[dim] > 10 )
357 fld->stag[dim] = 1 ;
358 else
359 fld->stag[dim] = 0 ;
362 /* work out pack/unpack strategy for this field */
363 switch ( ndim )
365 case 2 :
366 if ( decomp[0]%10 == RSL_M &&
367 decomp[1]%10 == RSL_N )
368 fld->strategy = MINNS_MAJEW_2D ;
369 else if ( decomp[1]%10 == RSL_M &&
370 decomp[0]%10 == RSL_N )
371 fld->strategy = MINEW_MAJNS_2D ;
372 else
373 RSL_TEST_ERR(1,"rsl_build_message: unsupported decomposition strategy for 2d message") ;
374 break ;
375 case 3 :
376 if ( decomp[0]%10 == RSL_M &&
377 decomp[1]%10 == RSL_N &&
378 decomp[2]%10 == RSL_NOTDECOMPOSED)
379 fld->strategy = MINNS_MAJEW_K_3D ;
380 else if ( decomp[0]%10 == RSL_N &&
381 decomp[1]%10 == RSL_M &&
382 decomp[2]%10 == RSL_NOTDECOMPOSED)
383 fld->strategy = MINEW_MAJNS_K_3D ;
384 else if ( decomp[0]%10 == RSL_NOTDECOMPOSED &&
385 decomp[1]%10 == RSL_M &&
386 decomp[2]%10 == RSL_N )
387 fld->strategy = K_MIDNS_MAJEW_3D ;
388 else if ( decomp[0]%10 == RSL_M &&
389 decomp[1]%10 == RSL_NOTDECOMPOSED &&
390 decomp[2]%10 == RSL_N )
391 fld->strategy = MINNS_K_MAJEW_3D ;
392 else
393 RSL_TEST_ERR(1,"rsl_build_message: unsupported decomposition strategy for 3d message") ;
394 break ;
395 default :
396 sprintf(mess,"rsl_build_message: %d dimension flds not supported yet\n",
397 ndim ) ;
398 RSL_TEST_ERR(1,mess) ;
399 break ;
402 /* insert fldspec at beginning of list (note: we're not concerning
403 ourselves with order of the fields -- this will reverse them from
404 the order they were specified in.) */
406 fld->next = msg->fldspecs ;
407 msg->fldspecs = fld ;
408 msg->nflds++ ;
412 RSL_REGISTER_F90 ( base )
413 char * base ;
415 if ( base_table_cursor < MAX_BASE_TABLE_ENTRIES )
417 f90_base_table[ base_table_cursor ].base = base ;
418 base_table_cursor++ ;
420 else
422 RSL_TEST_ERR(1,"Exceeded MAX_BASE_TABLE_ENTRIES number of f90 fields") ;
426 #define BASE_TABLE_PADDING sizeof(double) ;
427 RSL_REGISTER_F90_BASE_AND_SIZE ( base , size )
428 char * base ;
429 int * size ;
431 if ( base_table_cursor < MAX_BASE_TABLE_ENTRIES )
433 f90_base_table[ base_table_cursor ].base = base ;
434 f90_base_table[ base_table_cursor ].size_in_bytes = * size ;
435 f90_base_table[ base_table_cursor ].virt_base =
436 f90_base_table[ base_table_cursor-1 ].virt_base +
437 f90_base_table[ base_table_cursor-1 ].size_in_bytes + BASE_TABLE_PADDING ;
438 base_table_cursor++ ;
440 else
442 RSL_TEST_ERR(1,"Exceeded MAX_BASE_TABLE_ENTRIES number of f90 fields") ;
446 RSL_END_REGISTER_F90 ()
448 base_table_size = base_table_cursor ;
451 RSL_START_REGISTER_F90 ()
453 base_table_cursor = 1 ;
454 f90_base_table[ 0 ].virt_base = (char *) BASE_TABLE_PADDING ;
455 f90_base_table[ 0 ].size_in_bytes = 0 ;
458 void *
459 get_base_for_index ( dex )
460 int dex ;
462 if ( dex < 1 || dex >= base_table_size )
464 sprintf(mess, "bad index %d into f90_base_table. base_table_size %d\n", dex, base_table_size ) ;
465 RSL_TEST_ERR( 1, mess ) ;
467 return( (void *) f90_base_table[dex].base ) ;
470 get_index_for_base ( base )
471 char * base ;
473 int i ;
474 for ( i = 1 ; i < base_table_size ; i++ )
476 if ( base == f90_base_table[ i ].base )
478 return( i ) ;
481 return(0) ;
484 /* return the number of bytes this message will require
485 (only the data requirements -- descriptors not figured here */
487 message_size( msg )
488 message_desc_t *msg ;
490 int dim, dimlen ;
491 int accum ;
492 rsl_fldspec_t * fld ;
494 if ( msg == NULL ) return(0) ;
495 if ( msg->tag != MESSAGE_DESC ) return(-1) ;
496 accum = 0 ;
497 for ( fld = msg->fldspecs ; fld != NULL ; fld = fld->next )
499 accum += fldsize( fld ) ;
501 return(accum) ;
505 fldsize( fld )
506 rsl_fldspec_t * fld ;
508 int dim, dimlen ;
509 int accum, fldaccum ;
510 fldaccum = 1 ;
511 for ( dim = 0 ; dim < fld->ndim ; dim++ )
513 fldaccum *= (fld->decomp[dim] == RSL_NOTDECOMPOSED)?fld->llen[dim]:1;
515 return (fldaccum * fld->elemsz) ;
518 /* only used internally within the RSL package... called by routines
519 that destroy larger RSL constructs such as stencils, bcast/merges,
520 state vectors (note: this routine was written using emacs, so
521 be careful) */
522 destroy_message( msg )
523 message_desc_t * msg ;
525 rsl_fldspec_t *fld, *doomed ;
526 if ( msg == NULL ) return ;
527 RSL_TEST_ERR( msg->tag != MESSAGE_DESC, "destroy_message: arg not a msg.") ;
529 for ( fld = msg->fldspecs ; fld != NULL ; )
531 doomed = fld ;
532 fld = fld->next ;
533 RSL_FREE( doomed ) ;
535 RSL_FREE( msg ) ;
536 msg = NULL ;
540 elemsize( t )
541 int t ;
543 if ( t >= 100 ) t = t % 100 ; /* remove extra info */
544 switch ( t )
546 #ifdef T3D
547 case RSL_REAL : return(sizeof(double)) ;
548 #else
549 case RSL_REAL : return(sizeof(float)) ;
550 #endif
551 case RSL_DOUBLE : return(sizeof(double)) ;
552 #ifdef T3D
553 case RSL_COMPLEX : return(2*sizeof(double)) ;
554 #else
555 case RSL_COMPLEX : return(2*sizeof(float)) ;
556 #endif
557 case RSL_INTEGER : return(sizeof(int)) ;
558 case RSL_CHARACTER : return(sizeof(char)) ;
560 return(-1) ;