ITM Grid Service Library: Fortran 90
|
00001 module itm_grid_object 00002 00003 use itm_types 00004 use itm_assert 00005 use euitm_schemas ! IGNORE 00006 00007 use itm_grid_common 00008 use itm_grid_access 00009 00010 implicit none 00011 00012 ! TODO: rename GridObject -> GridObject 00013 type GridObject 00014 ! cls: class of object. Gives Dimension of subobjects / elemental objects in the individual spaces 00015 ! ind: indices of subobjects in the individual spaces 00016 ! Wanted to call the components class and index, but both are Fortran keywords/intrinsics. 00017 ! Therefore the short names. Also shorter to type. 00018 integer, dimension(:), allocatable :: cls, ind 00019 end type GridObject 00020 00021 INTERFACE OPERATOR (.eq.) 00022 module procedure objectsEqual 00023 END INTERFACE 00024 00025 interface assignment (=) 00026 module procedure objectAssign 00027 end interface 00028 00029 contains 00030 00031 !> Get class descriptor for the highest-dimensional objects defined in this grid. 00032 !> (Depending on how the grid is defined, this is not necessarily the grid dimension.) 00033 function gridGetMaxDimClass(grid) result (cls) 00034 type(type_complexgrid), intent(in) :: grid 00035 integer, dimension( gridNSpace( grid ) ) :: cls 00036 00037 ! internal 00038 integer :: iSp 00039 00040 do iSp = 1, gridNSpace(grid) 00041 cls(iSp) = gridSpaceMaxObjDim(grid%spaces(iSp)) 00042 end do 00043 end function gridGetMaxDimClass 00044 00045 !> Return the dimension of the objects of class cls 00046 integer function classDim(cls) result(dim) 00047 integer, dimension(:), intent(in) :: cls 00048 00049 dim = sum(cls) 00050 end function classDim 00051 00052 !> Return GridObject for given class and index tuple 00053 function getObject( cls, ind ) result( object ) 00054 type(GridObject) :: object 00055 integer, dimension(:), intent(in) :: cls, ind 00056 00057 call assert( size( cls ) == size( ind ), & 00058 & "getObject: size of cls does not match size of ind" ) 00059 00060 allocate( object % cls( size( cls ) ) ) 00061 allocate( object % ind( size( ind ) ) ) 00062 00063 object % cls = cls 00064 object % ind = ind 00065 end function getObject 00066 00067 00068 !> Test whether the given object is a grid node (i.e. a zero-dimensional object) 00069 !> @return True if this is the case, false if not. 00070 logical function objectIsNode( obj ) 00071 type(GridObject), intent(in) :: obj 00072 00073 objectIsNode = ( sum( abs( obj % cls ) ) == 0 ) 00074 end function objectIsNode 00075 00076 !> Test whether two GridObject strucutres are equal, 00077 !> i.e. they describe the same grid object 00078 logical function objectsEqual( objA, objB ) 00079 type(GridObject), intent(in) :: objA, objB 00080 00081 objectsEqual = all(objA%cls == objB%cls) & 00082 & .and. all(objA%ind == objB%ind) 00083 end function objectsEqual 00084 00085 !> Assign one object variable to another object variable. 00086 !> Used to extend the assignment operator (=). 00087 !> 00088 !> Note: one should not have to define this explicitly, 00089 !> as this should be the default behaviour of the compiler for 00090 !> allocatable components. However, the PGI compiler (v10) fails at this. 00091 subroutine objectAssign(out, in) 00092 type(GridObject), intent(out) :: out 00093 type(GridObject), intent(in) :: in 00094 00095 if (allocated(in%cls)) then 00096 allocate(out%cls(size(in%cls))) 00097 allocate(out%ind(size(in%ind))) 00098 out%cls = in%cls 00099 out%ind = in%ind 00100 end if 00101 end subroutine objectAssign 00102 00103 !> Return the dimension of an object. 00104 integer function objectDim( obj ) 00105 type(GridObject), intent(in) :: obj 00106 00107 objectDim = sum(obj%cls) 00108 end function objectDim 00109 00110 00111 !> Get the total number of objects of the given cls in the grid 00112 integer function gridNObject( grid, cls ) result( objcount ) 00113 type(type_complexgrid), intent(in) :: grid 00114 integer, dimension( gridNSpace( grid ) ), intent(in) :: cls 00115 00116 ! internal 00117 integer :: is 00118 00119 objcount = 1 00120 00121 do is = 1, gridNSpace( grid ) 00122 objcount = objcount * gridSpaceNObject( grid % spaces( is ), cls( is ) ) 00123 end do 00124 00125 end function gridNObject 00126 00127 00128 !> Return the global index of an object 00129 integer function objectGlobalIndex( grid, object ) result( ind ) 00130 type(type_complexgrid), intent(in) :: grid 00131 type(GridObject), intent(in) :: object 00132 00133 ! internal 00134 integer :: is, s 00135 00136 ind = object % ind( 1 ) 00137 s = gridSpaceNObject( grid % spaces( 1 ), object % cls( 1 ) ) 00138 00139 do is = 2, gridNSpace( grid ) 00140 ind = ind + s * ( object % ind( is ) - 1 ) 00141 s = s * gridSpaceNObject( grid % spaces( is ), object % cls( is ) ) 00142 end do 00143 00144 end function objectGlobalIndex 00145 00146 00147 !> TODO: rename to gridGetObjectByGlobalIndex 00148 00149 type(GridObject) function getObjectByGlobalIndex( grid, cls, ind ) result( object ) 00150 type(type_complexgrid), intent(in) :: grid 00151 integer, dimension(gridNSpace( grid )), intent(in) :: cls 00152 integer, intent(in) :: ind 00153 00154 ! internal 00155 integer :: is, s, tind, irem, oc( gridNSpace( grid ) ) 00156 00157 call assert( size( cls ) == gridNSpace( grid ), & 00158 & "getObjectByGlobalIndex: size of cls does not match grid description" ) 00159 00160 allocate( object % cls( gridNSpace( grid ) ) ) 00161 allocate( object % ind( gridNSpace( grid ) ) ) 00162 00163 object % cls = cls 00164 00165 do is = 1, gridNSpace( grid ) 00166 oc( is ) = gridSpaceNObject( grid % spaces( is ), cls( is ) ) 00167 end do 00168 00169 irem = ind 00170 do is = gridNSpace( grid ), 2, -1 00171 s = product( oc( 1 : is - 1 ) ) 00172 tind = ( ( irem - 1 ) / s ) 00173 irem = irem - tind * s 00174 object % ind( is ) = tind + 1 00175 end do 00176 object % ind( 1 ) = irem 00177 00178 end function getObjectByGlobalIndex 00179 00180 00181 !> For a given object desriptor, retrieves a list that holds the object descriptors 00182 !> describing the lower-dimensional objects composing the given object 00183 subroutine getComposingObjects( grid, object, objlist ) 00184 type(type_complexgrid), intent(in) :: grid 00185 type(GridObject), intent(in) :: object 00186 type(GridObject), dimension(:), allocatable, intent(out) :: objlist 00187 00188 integer :: is, cobj, iobj, nobjs, nbounds( size( grid % spaces ) ) 00189 00190 ! Corner case: the composing object of a node (0d object) is the node itself 00191 if ( objectIsNode( object ) ) then 00192 allocate( objlist(1) ) 00193 objlist(1) = object 00194 return 00195 end if 00196 00197 ! General case: figure out how many objects are returned 00198 nobjs = 0 00199 00200 do is = 1, size( grid % spaces ) 00201 ! every space contributes objects according to the boundaries of the subobject in the spaces 00202 00203 ! if subobject in the space is a node, skip 00204 if ( object % cls( is ) == 0 ) cycle 00205 00206 ! get number of boundaries of subobject 00207 do iobj = 1, gridSpaceMaxNBoundaries( grid % spaces( is ), object % cls( is ) ) 00208 if ( grid % spaces( is ) % objects( object % cls( is ) + 1 ) % & 00209 & boundary( object % ind( is ), iobj ) == GRID_UNDEFINED ) then 00210 exit 00211 end if 00212 nbounds( is ) = iobj 00213 end do 00214 00215 nobjs = nobjs + nbounds( is ) 00216 end do 00217 00218 allocate( objlist( nobjs ) ) 00219 00220 ! For every space: get composing objects (boundaries) of the subobject in this space 00221 ! and transform them into the requested composing objects. 00222 ! If the subobject in the space is a node, skip the space 00223 00224 cobj = 0 00225 00226 do is = 1, size( grid % spaces ) 00227 00228 ! if subobject in this space is a node, cycle 00229 if ( object % cls( is ) == 0 ) cycle 00230 00231 ! for all boundary subobjects... 00232 do iobj = 1, nbounds( is ) 00233 00234 cobj = cobj + 1 00235 ! assert: cobj < size( objlist ) 00236 00237 ! copy current object (automatic allocation)... 00238 objlist( cobj ) = object 00239 ! ...reduce dimension... 00240 objlist( cobj ) % cls( is ) = objlist( cobj ) % cls( is ) - 1 00241 ! ...and set index 00242 objlist( cobj ) % ind( is ) = grid % spaces( is ) % & 00243 & objects( object % cls( is ) + 1 ) % boundary( object % ind( is ), iobj ) 00244 00245 end do 00246 00247 end do 00248 00249 call assert( cobj == nobjs, 'getComposingObjects: found less objects than anticipated' ) 00250 00251 end subroutine getComposingObjects 00252 00253 00254 ! Output routines 00255 00256 !> Write a list of object descriptors to stdout. 00257 subroutine writeObjectList( objs ) 00258 type(GridObject), dimension(:), intent(in) :: objs 00259 00260 ! internal 00261 integer :: i 00262 00263 do i = 1, size( objs ) 00264 call gridWriteGridObject( objs(i) ) 00265 end do 00266 00267 end subroutine writeObjectList 00268 00269 !> Write an object descriptor to stdout. 00270 subroutine gridWriteGridObject( obj ) 00271 type(GridObject), intent(in) :: obj 00272 00273 write (*,*) '( (', obj % cls, ') (', obj % ind, ') )' 00274 00275 end subroutine gridWriteGridObject 00276 00277 00278 end module itm_grid_object