00001 function MPP_GLOBAL_REDUCE_2D_( domain, field, locus ) 00002 MPP_TYPE_ :: MPP_GLOBAL_REDUCE_2D_ 00003 type(domain2D), intent(in) :: domain 00004 MPP_TYPE_, intent(in) :: field(:,:) 00005 integer, intent(out), optional :: locus(2) 00006 MPP_TYPE_ :: field3D(size(field,1),size(field,2),1) 00007 integer :: locus3D(3) 00008 #ifdef use_CRI_pointers 00009 pointer( ptr, field3D ) 00010 ptr = LOC(field) 00011 if( PRESENT(locus) )then 00012 MPP_GLOBAL_REDUCE_2D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D, locus3D ) 00013 locus = locus3D(1:2) 00014 else 00015 MPP_GLOBAL_REDUCE_2D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D ) 00016 end if 00017 #else 00018 field3D = RESHAPE( field, SHAPE(field3D) ) 00019 if( PRESENT(locus) )then 00020 MPP_GLOBAL_REDUCE_2D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D, locus3D ) 00021 locus = locus3D(1:2) 00022 else 00023 MPP_GLOBAL_REDUCE_2D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D ) 00024 end if 00025 #endif 00026 return 00027 end function MPP_GLOBAL_REDUCE_2D_ 00028 00029 function MPP_GLOBAL_REDUCE_3D_( domain, field, locus ) 00030 MPP_TYPE_ :: MPP_GLOBAL_REDUCE_3D_ 00031 type(domain2D), intent(in) :: domain 00032 MPP_TYPE_, intent(in) :: field(0:,0:,:) 00033 integer, intent(out), optional :: locus(3) 00034 MPP_TYPE_ :: local 00035 integer :: here, ioff, joff 00036 00037 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GLOBAL_REDUCE: You must first call mpp_domains_init.' ) 00038 if( size(field,1).EQ.domain%x%compute%size .AND. size(field,2).EQ.domain%y%compute%size )then 00039 !field is on compute domain 00040 ioff = domain%x%compute%begin 00041 joff = domain%y%compute%begin 00042 else if( size(field,1).EQ.domain%x%data%size .AND. size(field,2).EQ.domain%y%data%size )then 00043 !field is on data domain 00044 ioff = domain%x%data%begin 00045 joff = domain%y%data%begin 00046 else 00047 call mpp_error( FATAL, 'MPP_GLOBAL_REDUCE_: incoming field array must match either compute domain or data domain.' ) 00048 end if 00049 00050 !get your local max/min 00051 local = REDUCE_VAL_(field) 00052 !find the global 00053 MPP_GLOBAL_REDUCE_3D_ = local 00054 call MPP_REDUCE_( MPP_GLOBAL_REDUCE_3D_, domain%list(:)%pe ) 00055 !find locus of the global max/min 00056 if( PRESENT(locus) )then 00057 !which PE is it on? min of all the PEs that have it 00058 here = mpp_npes()+1 00059 if( MPP_GLOBAL_REDUCE_3D_.EQ.local )here = pe 00060 call mpp_min( here, domain%list(:)%pe ) 00061 !find the locus here 00062 if( pe.EQ.here )locus = REDUCE_LOC_(field) 00063 locus(1) = locus(1) + ioff 00064 locus(2) = locus(2) + joff 00065 call mpp_broadcast( locus, 3, here, domain%list(:)%pe ) 00066 end if 00067 return 00068 end function MPP_GLOBAL_REDUCE_3D_ 00069 00070 function MPP_GLOBAL_REDUCE_4D_( domain, field, locus ) 00071 MPP_TYPE_ :: MPP_GLOBAL_REDUCE_4D_ 00072 type(domain2D), intent(in) :: domain 00073 MPP_TYPE_, intent(in) :: field(:,:,:,:) 00074 integer, intent(out), optional :: locus(4) 00075 MPP_TYPE_ :: field3D(size(field,1),size(field,2),size(field,3)*size(field,4)) 00076 integer :: locus3D(3) 00077 #ifdef use_CRI_pointers 00078 pointer( ptr, field3D ) 00079 ptr = LOC(field) 00080 if( PRESENT(locus) )then 00081 MPP_GLOBAL_REDUCE_4D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D, locus3D ) 00082 locus(1:2) = locus3D(1:2) 00083 locus(3) = modulo(locus3D(3),size(field,3)) 00084 locus(4) = (locus3D(3)-locus(3))/size(field,3) + 1 00085 if( locus(3).EQ.0 )then 00086 locus(3) = size(field,3) 00087 locus(4) = locus(4) - 1 00088 end if 00089 else 00090 MPP_GLOBAL_REDUCE_4D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D ) 00091 end if 00092 #else 00093 field3D = RESHAPE( field, SHAPE(field3D) ) 00094 if( PRESENT(locus) )then 00095 MPP_GLOBAL_REDUCE_4D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D, locus3D ) 00096 locus(1:2) = locus3D(1:2) 00097 locus(3) = modulo(locus3D(3),size(field,3)) 00098 locus(4) = (locus3D(3)-locus(3))/size(field,3) + 1 00099 if( locus(3).EQ.0 )then 00100 locus(3) = size(field,3) 00101 locus(4) = locus(4) - 1 00102 end if 00103 else 00104 MPP_GLOBAL_REDUCE_4D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D ) 00105 end if 00106 #endif 00107 return 00108 end function MPP_GLOBAL_REDUCE_4D_ 00109 00110 function MPP_GLOBAL_REDUCE_5D_( domain, field, locus ) 00111 MPP_TYPE_ :: MPP_GLOBAL_REDUCE_5D_ 00112 type(domain2D), intent(in) :: domain 00113 MPP_TYPE_, intent(in) :: field(:,:,:,:,:) 00114 integer, intent(out), optional :: locus(5) 00115 MPP_TYPE_ :: field3D(size(field,1),size(field,2),size(field,3)*size(field,4)*size(field,5)) 00116 integer :: locus3D(3) 00117 #ifdef use_CRI_pointers 00118 pointer( ptr, field3D ) 00119 ptr = LOC(field) 00120 if( PRESENT(locus) )then 00121 MPP_GLOBAL_REDUCE_5D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D, locus3D ) 00122 locus(1:2) = locus3D(1:2) 00123 locus(3) = modulo(locus3D(3),size(field,3)) 00124 locus(4) = modulo(locus3D(3),size(field,3)*size(field,4)) 00125 locus(5) = (locus3D(3)-locus(4))/size(field,3)/size(field,4) + 1 00126 if( locus(3).EQ.0 )then 00127 locus(3) = size(field,3) 00128 locus(4) = locus(4) - 1 00129 end if 00130 else 00131 MPP_GLOBAL_REDUCE_5D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D ) 00132 end if 00133 #else 00134 field3D = RESHAPE( field, SHAPE(field3D) ) 00135 if( PRESENT(locus) )then 00136 MPP_GLOBAL_REDUCE_5D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D, locus3D ) 00137 locus(1:2) = locus3D(1:2) 00138 locus(3) = modulo(locus3D(3),size(field,3)) 00139 locus(4) = modulo(locus3D(3),size(field,3)*size(field,4)) 00140 locus(5) = (locus3D(3)-locus(4))/size(field,3)/size(field,4) + 1 00141 if( locus(3).EQ.0 )then 00142 locus(3) = size(field,3) 00143 locus(4) = locus(4) - 1 00144 end if 00145 else 00146 MPP_GLOBAL_REDUCE_5D_ = MPP_GLOBAL_REDUCE_3D_( domain, field3D ) 00147 end if 00148 #endif 00149 return 00150 end function MPP_GLOBAL_REDUCE_5D_