23 module drifters_core_mod
29 public :: drifters_core_type, drifters_core_new, drifters_core_del, drifters_core_set_ids
30 public :: drifters_core_remove_and_add, drifters_core_set_positions,
assignment(=)
31 public :: drifters_core_print, drifters_core_resize
34 integer,
parameter,
private :: MAX_STR_LEN = 128
36 #include<file_version.h>
42 type drifters_core_type
43 integer(kind=i8_kind) :: it
47 integer,
allocatable :: ids(:)
48 real ,
allocatable :: positions(:,:)
49 end type drifters_core_type
53 interface assignment(=)
54 module procedure drifters_core_copy_new
63 subroutine drifters_core_new(self, nd, npdim, ermesg)
64 type(drifters_core_type) :: self
65 integer,
intent(in) :: nd
66 integer,
intent(in) :: npdim
67 character(*),
intent(out) :: ermesg
72 call drifters_core_del(self, ermesg)
74 allocate(self%positions(nd, npdim), stat=iflag)
75 if(iflag/=0) ier = ier + 1
78 allocate(self%ids(npdim), stat=iflag)
79 if(iflag/=0) ier = ier + 1
80 self%ids = (/(i, i=1,npdim)/)
85 if(ier/=0) ermesg =
'drifters::ERROR in drifters_core_new'
86 end subroutine drifters_core_new
90 subroutine drifters_core_del(self, ermesg)
91 type(drifters_core_type) :: self
92 character(*),
intent(out) :: ermesg
100 if(
allocated(self%positions))
deallocate(self%positions, stat=iflag)
101 if(iflag/=0) ier = ier + 1
102 if(
allocated(self%ids))
deallocate(self%ids, stat=iflag)
103 if(iflag/=0) ier = ier + 1
105 if(ier/=0) ermesg =
'drifters::ERROR in drifters_core_del'
106 end subroutine drifters_core_del
109 subroutine drifters_core_copy_new(new_instance, old_instance)
111 type(drifters_core_type),
intent(inout) :: new_instance
112 type(drifters_core_type),
intent(in) :: old_instance
114 character(len=MAX_STR_LEN) :: ermesg
117 call drifters_core_del(new_instance, ermesg)
118 if(ermesg/=
'')
return
120 new_instance%it = old_instance%it
121 new_instance%nd = old_instance%nd
122 new_instance%np = old_instance%np
123 new_instance%npdim = old_instance%npdim
124 allocate(new_instance%ids(
size(old_instance%ids) ))
125 new_instance%ids = old_instance%ids
126 allocate(new_instance%positions(
size(old_instance%positions,1), &
127 &
size(old_instance%positions,2) ))
128 new_instance%positions = old_instance%positions
130 end subroutine drifters_core_copy_new
132 subroutine drifters_core_resize(self, npdim, ermesg)
133 type(drifters_core_type) :: self
134 integer,
intent(in) :: npdim
135 character(*),
intent(out) :: ermesg
136 integer ier, iflag, i
138 real ,
allocatable :: positions(:,:)
139 integer,
allocatable :: ids(:)
143 if(npdim <= self%npdim)
return
146 allocate(positions(self%nd, self%np), stat=iflag)
147 allocate( ids(self%np), stat=iflag)
149 positions = self%positions(:, 1:self%np)
150 ids = self%ids(1:self%np)
152 deallocate(self%positions, stat=iflag)
153 deallocate(self%ids , stat=iflag)
155 allocate(self%positions(self%nd, npdim), stat=iflag)
156 allocate(self%ids(npdim), stat=iflag)
159 self%ids = (/ (i, i=1,npdim) /)
160 self%positions(:, 1:self%np) = positions
163 if(ier/=0) ermesg =
'drifters::ERROR in drifters_core_resize'
164 end subroutine drifters_core_resize
167 subroutine drifters_core_set_positions(self, positions, ermesg)
168 type(drifters_core_type) :: self
169 real,
intent(in) :: positions(:,:)
170 character(*),
intent(out) :: ermesg
174 self%np = min(self%npdim,
size(positions, 2))
175 self%positions(:,1:self%np) = positions(:,1:self%np)
176 self%it = self%it + 1
177 if(ier/=0) ermesg =
'drifters::ERROR in drifters_core_set_positions'
178 end subroutine drifters_core_set_positions
181 subroutine drifters_core_set_ids(self1, ids1, ermesg1)
182 type(drifters_core_type) :: self1
183 integer,
intent(in) :: ids1(:)
184 character(*),
intent(out) :: ermesg1
188 np = min(self1%npdim,
size(ids1))
189 self1%ids(1:np) = ids1(1:np)
190 if(ier/=0) ermesg1 =
'drifters::ERROR in drifters_core_set_ids'
191 end subroutine drifters_core_set_ids
194 subroutine drifters_core_remove_and_add(self, indices_to_remove_in, &
195 & ids_to_add, positions_to_add, &
197 type(drifters_core_type) :: self
198 integer,
intent(in ) :: indices_to_remove_in(:)
199 integer,
intent(in ) :: ids_to_add(:)
200 real ,
intent(in ) :: positions_to_add(:,:)
201 character(*),
intent(out) :: ermesg
202 integer ier, np_add, np_remove, i, j, n_diff
203 integer indices_to_remove(size(indices_to_remove_in))
204 external qksrt_quicksort
209 indices_to_remove = indices_to_remove_in
210 np_remove =
size(indices_to_remove)
211 np_add =
size(ids_to_add, 1)
212 n_diff = np_add - np_remove
215 if(self%np + n_diff < 0)
then
216 ermesg =
'drifters::ERROR attempting to remove more elements than there are elements in '// &
217 &
'drifters_core_remove_and_add'
222 if(self%np + n_diff > self%npdim) &
223 &
call drifters_core_resize(self, int(1.2*(self%np + n_diff))+1, ermesg)
225 do i = 1, min(np_add, np_remove)
226 j = indices_to_remove(i)
227 self%ids(j) = ids_to_add(i)
228 self%positions(:,j) = positions_to_add(:,i)
234 self%ids( self%np+1:self%np+n_diff) = ids_to_add( np_remove+1:np_add)
235 self%positions(:, self%np+1:self%np+n_diff) = positions_to_add(:,np_remove+1:np_add)
237 self%np = self%np + n_diff
239 else if(n_diff < 0)
then
245 call qksrt_quicksort(
size(indices_to_remove), indices_to_remove, np_add+1, np_remove)
247 do i = np_remove, np_add+1, -1
248 if(self%np <= 0)
exit
249 j = indices_to_remove(i)
250 self%ids ( j) = self%ids ( self%np)
251 self%positions(:,j) = self%positions(:,self%np)
252 self%np = self%np - 1
256 if(ier/=0) ermesg =
'drifters::ERROR in drifters_core_remove_and_add'
257 end subroutine drifters_core_remove_and_add
260 subroutine drifters_core_print(self1, ermesg1)
261 type(drifters_core_type) :: self1
262 character(*),
intent(out) :: ermesg1
266 print
'(a,i10,a,i6,a,i6,a,i4,a,i4,a,i4)',
'it=',self1%it, &
267 &
' np=', self1%np,
' npdim=', self1%npdim
269 print *,
'ids and positions:'
271 print *,self1%ids(j), self1%positions(:,j)
274 end subroutine drifters_core_print
277 end module drifters_core_mod