SABER
tools_qsort.F90
Go to the documentation of this file.
1 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
2 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../generics.fypp" 1
3 !----------------------------------------------------------------------
4 ! Header: generics
5 !> Generic ranks, dimensions and types
6 ! Author: Benjamin Menetrier
7 ! Licensing: this code is distributed under the CeCILL-C license
8 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
9 !----------------------------------------------------------------------
10 
11 # 57 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../generics.fypp"
12 # 2 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp" 2
13 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../instrumentation.fypp" 1
14 # 1 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../subr_list.fypp" 1
15 !----------------------------------------------------------------------
16 ! Header: subr_list
17 !> Subroutines/functions list
18 ! Author: Benjamin Menetrier
19 ! Licensing: this code is distributed under the CeCILL-C license
20 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
21 !----------------------------------------------------------------------
22 
23 # 926 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../subr_list.fypp"
24 # 2 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../instrumentation.fypp" 2
25 !----------------------------------------------------------------------
26 ! Header: instrumentation
27 !> Instrumentation functions
28 ! Author: Benjamin Menetrier
29 ! Licensing: this code is distributed under the CeCILL-C license
30 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
31 !----------------------------------------------------------------------
32 
33 # 112 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/../instrumentation.fypp"
34 # 3 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp" 2
35 !----------------------------------------------------------------------
36 ! Module: tools_qsort
37 !> Qsort routines
38 ! Source: http://jblevins.org/mirror/amiller/qsort.f90
39 ! Author: Brainerd, W.S., Goldberg, C.H. & Adams, J.C. (1990) "Programmer's Guide to Fortran 90", McGraw-Hill ISBN 0-07-000248-7, pages 149-150.
40 ! Original licensing: none
41 ! Modified by Alan Miller
42 ! Modified by Benjamin Menetrier for BUMP
43 ! Licensing: this code is distributed under the CeCILL-C license
44 ! Copyright 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
45 !----------------------------------------------------------------------
47 
49 use tools_repro, only: eq,inf
50 
51 
52 implicit none
53 
54 interface qsort
55 # 24 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
56  module procedure qsort_qsort_int
57  module procedure qsort_qsort_pair_int
58 # 24 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
59  module procedure qsort_qsort_real
60  module procedure qsort_qsort_pair_real
61 # 27 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
62 end interface
63 interface quick_sort
64 # 30 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
65  module procedure qsort_quick_sort_int
66 # 30 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
67  module procedure qsort_quick_sort_real
68 # 32 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
69 end interface
71 # 35 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
72  module procedure qsort_interchange_sort_int
73 # 35 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
74  module procedure qsort_interchange_sort_real
75 # 37 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
76 end interface
77 interface reorder_eq
78  module procedure qsort_reorder_eq
79 end interface
80 
81 private
82 public :: qsort
83 
84 contains
85 
86 # 48 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
87 !----------------------------------------------------------------------
88 ! Subroutine: qsort_qsort_int
89 !> Sort a vector
90 !----------------------------------------------------------------------
91 recursive subroutine qsort_qsort_int(n,list,order,order_list)
92 
93 implicit none
94 
95 ! Passed variables
96 integer, intent(in) :: n !< Input vector size
97 integer(kind_int),intent(inout) :: list(n) !< Vector to sort
98 integer,intent(out) :: order(n) !< Positions of the elements in the original order
99 logical,intent(in),optional :: order_list !< Flag to reorder the list (default: .true.)
100 
101 ! Local variables
102 integer :: i
103 integer(kind_int),allocatable :: list_tmp(:)
104 logical :: lorder_list
105 
106 ! Local flag
107 lorder_list = .true.
108 if (present(order_list)) lorder_list = order_list
109 
110 ! Initialize order
111 do i=1,n
112  order(i) = i
113 end do
114 
115 if (lorder_list) then
116  ! Sort
117  call quick_sort(n,1,n,list,order)
118 
119  ! Reorder equal values
120 
121 else
122  ! Allocation
123  allocate(list_tmp(n))
124 
125  ! Copy list
126  list = list_tmp
127 
128  ! Sort
129  call quick_sort(n,1,n,list_tmp,order)
130 
131  ! Reorder equal values
132 
133 
134  ! Release memory
135  deallocate(list_tmp)
136 end if
137 
138 end subroutine qsort_qsort_int
139 # 48 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
140 !----------------------------------------------------------------------
141 ! Subroutine: qsort_qsort_real
142 !> Sort a vector
143 !----------------------------------------------------------------------
144 recursive subroutine qsort_qsort_real(n,list,order,order_list)
145 
146 implicit none
147 
148 ! Passed variables
149 integer, intent(in) :: n !< Input vector size
150 real(kind_real),intent(inout) :: list(n) !< Vector to sort
151 integer,intent(out) :: order(n) !< Positions of the elements in the original order
152 logical,intent(in),optional :: order_list !< Flag to reorder the list (default: .true.)
153 
154 ! Local variables
155 integer :: i
156 real(kind_real),allocatable :: list_tmp(:)
157 logical :: lorder_list
158 
159 ! Local flag
160 lorder_list = .true.
161 if (present(order_list)) lorder_list = order_list
162 
163 ! Initialize order
164 do i=1,n
165  order(i) = i
166 end do
167 
168 if (lorder_list) then
169  ! Sort
170  call quick_sort(n,1,n,list,order)
171 
172  ! Reorder equal values
173  call reorder_eq(n,list,order)
174 else
175  ! Allocation
176  allocate(list_tmp(n))
177 
178  ! Copy list
179  list = list_tmp
180 
181  ! Sort
182  call quick_sort(n,1,n,list_tmp,order)
183 
184  ! Reorder equal values
185  call reorder_eq(n,list_tmp,order)
186 
187  ! Release memory
188  deallocate(list_tmp)
189 end if
190 
191 end subroutine qsort_qsort_real
192 # 101 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
193 
194 # 103 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
195 !----------------------------------------------------------------------
196 ! Subroutine: qsort_qsort_pair_int
197 !> Sort two joint vectors
198 !----------------------------------------------------------------------
199 recursive subroutine qsort_qsort_pair_int(n,list1,list2,order,order_list)
200 
201 implicit none
202 
203 ! Passed variables
204 integer, intent(in) :: n !< Input vector size
205 integer(kind_int),intent(inout) :: list1(n) !< First vector to sort
206 integer(kind_int),intent(inout) :: list2(n) !< Second vector to sort
207 integer,intent(out) :: order(n) !< Positions of the elements in the original order
208 logical,intent(in),optional :: order_list !< Flag to reorder the list (default: .true.)
209 
210 ! Local variables
211 integer :: i_s,i_e,ntmp,i
212 integer,allocatable :: order_tmp(:)
213 integer(kind_int) :: list1_tmp(n),list2_tmp(n)
214 logical :: lorder_list,chain,diff
215 
216 ! Local flag
217 lorder_list = .true.
218 if (present(order_list)) lorder_list = order_list
219 
220 ! Initialize order
221 do i=1,n
222  order(i) = i
223 end do
224 
225 ! Copy first vector
226 list1_tmp = list1
227 
228 ! Sort first vector
229 call quick_sort(n,1,n,list1_tmp,order)
230 
231 ! Reorder equal values
232 
233 
234 ! Order second vector
235 list2_tmp = list2(order)
236 
237 ! Initialization
238 i_s = 1
239 chain = .false.
240 do i_e=2,n+1
241  if (i_e==n+1) then
242  diff = .true.
243  else
244  diff = inf(list1_tmp(i_s),list1_tmp(i_e))
245  end if
246  if (diff) then
247  ! Different value
248  if (chain) then
249  ! Allocation
250  ntmp = i_e-i_s
251  allocate(order_tmp(ntmp))
252 
253  ! Initialize order
254  do i=1,ntmp
255  order_tmp(i) = i
256  end do
257 
258  ! Sort second vector
259  call quick_sort(ntmp,1,ntmp,list2_tmp(i_s:i_e-1),order_tmp)
260 
261  ! Reorder equal values
262 
263 
264  ! Offset temporary order
265  order_tmp = order_tmp+i_s-1
266 
267  ! Sorder order
268  order(i_s:i_e-1) = order(order_tmp)
269 
270  ! Chain done
271  chain = .false.
272 
273  ! Release memory
274  deallocate(order_tmp)
275  end if
276 
277  ! Update
278  i_s = i_e
279  else
280  ! Same value, this is a chain
281  chain = .true.
282  endif
283 end do
284 
285 if (lorder_list) then
286  ! Reorder vectors
287  list1 = list1(order)
288  list2 = list2(order)
289 end if
290 
291 end subroutine qsort_qsort_pair_int
292 # 103 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
293 !----------------------------------------------------------------------
294 ! Subroutine: qsort_qsort_pair_real
295 !> Sort two joint vectors
296 !----------------------------------------------------------------------
297 recursive subroutine qsort_qsort_pair_real(n,list1,list2,order,order_list)
298 
299 implicit none
300 
301 ! Passed variables
302 integer, intent(in) :: n !< Input vector size
303 real(kind_real),intent(inout) :: list1(n) !< First vector to sort
304 real(kind_real),intent(inout) :: list2(n) !< Second vector to sort
305 integer,intent(out) :: order(n) !< Positions of the elements in the original order
306 logical,intent(in),optional :: order_list !< Flag to reorder the list (default: .true.)
307 
308 ! Local variables
309 integer :: i_s,i_e,ntmp,i
310 integer,allocatable :: order_tmp(:)
311 real(kind_real) :: list1_tmp(n),list2_tmp(n)
312 logical :: lorder_list,chain,diff
313 
314 ! Local flag
315 lorder_list = .true.
316 if (present(order_list)) lorder_list = order_list
317 
318 ! Initialize order
319 do i=1,n
320  order(i) = i
321 end do
322 
323 ! Copy first vector
324 list1_tmp = list1
325 
326 ! Sort first vector
327 call quick_sort(n,1,n,list1_tmp,order)
328 
329 ! Reorder equal values
330  call reorder_eq(n,list1_tmp,order)
331 
332 ! Order second vector
333 list2_tmp = list2(order)
334 
335 ! Initialization
336 i_s = 1
337 chain = .false.
338 do i_e=2,n+1
339  if (i_e==n+1) then
340  diff = .true.
341  else
342  diff = inf(list1_tmp(i_s),list1_tmp(i_e))
343  end if
344  if (diff) then
345  ! Different value
346  if (chain) then
347  ! Allocation
348  ntmp = i_e-i_s
349  allocate(order_tmp(ntmp))
350 
351  ! Initialize order
352  do i=1,ntmp
353  order_tmp(i) = i
354  end do
355 
356  ! Sort second vector
357  call quick_sort(ntmp,1,ntmp,list2_tmp(i_s:i_e-1),order_tmp)
358 
359  ! Reorder equal values
360  call reorder_eq(ntmp,list2_tmp(i_s:i_e-1),order_tmp)
361 
362  ! Offset temporary order
363  order_tmp = order_tmp+i_s-1
364 
365  ! Sorder order
366  order(i_s:i_e-1) = order(order_tmp)
367 
368  ! Chain done
369  chain = .false.
370 
371  ! Release memory
372  deallocate(order_tmp)
373  end if
374 
375  ! Update
376  i_s = i_e
377  else
378  ! Same value, this is a chain
379  chain = .true.
380  endif
381 end do
382 
383 if (lorder_list) then
384  ! Reorder vectors
385  list1 = list1(order)
386  list2 = list2(order)
387 end if
388 
389 end subroutine qsort_qsort_pair_real
390 # 201 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
391 
392 # 203 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
393 !----------------------------------------------------------------------
394 ! Subroutine: qsort_quick_sort_int
395 !> Sort an integer subvector
396 !----------------------------------------------------------------------
397 recursive subroutine qsort_quick_sort_int(n,left_end,right_end,list,order)
398 
399 implicit none
400 
401 ! Passed variables
402 integer,intent(in) :: n !< Input vector size
403 integer,intent(in) :: left_end !< Left end of the vector
404 integer,intent(in) :: right_end !< Right end of the vector
405 integer(kind_int),intent(inout) :: list(n) !< Vector to sort
406 integer,intent(inout) :: order(n) !< Positions of the elements in the original order
407 
408 ! Local variables
409 integer,parameter :: max_simple_sort_size = 6
410 integer :: i,j,itemp
411 integer(kind_int) :: reference,temp
412 
413 if (right_end<left_end+max_simple_sort_size) then
414  ! Use interchange sort for small lists
415  call interchange_sort(n,left_end,right_end,list,order)
416 else
417  ! Use partition ("quick") sort
418  reference = list((left_end+right_end)/2)
419  i = left_end-1
420  j = right_end+1
421  do
422  ! Scan list from left end until element >= reference is found
423  do
424  i = i+1
425  if (.not.(list(i)<reference)) exit
426  end do
427  ! Scan list from right end until element <= reference is found
428  do
429  j = j-1
430  if (.not.(list(j)>reference)) exit
431  end do
432 
433  if (i<j) then
434  ! Swap two out-of-order elements
435  temp = list(i)
436  list(i) = list(j)
437  list(j) = temp
438  itemp = order(i)
439  order(i) = order(j)
440  order(j) = itemp
441  elseif (i==j) then
442  i = i+1
443  exit
444  else
445  exit
446  end if
447  end do
448 
449  if (left_end<j) call quick_sort(n,left_end,j,list,order)
450  if (i<right_end) call quick_sort(n,i,right_end,list,order)
451 end if
452 
453 end subroutine qsort_quick_sort_int
454 # 203 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
455 !----------------------------------------------------------------------
456 ! Subroutine: qsort_quick_sort_real
457 !> Sort an integer subvector
458 !----------------------------------------------------------------------
459 recursive subroutine qsort_quick_sort_real(n,left_end,right_end,list,order)
460 
461 implicit none
462 
463 ! Passed variables
464 integer,intent(in) :: n !< Input vector size
465 integer,intent(in) :: left_end !< Left end of the vector
466 integer,intent(in) :: right_end !< Right end of the vector
467 real(kind_real),intent(inout) :: list(n) !< Vector to sort
468 integer,intent(inout) :: order(n) !< Positions of the elements in the original order
469 
470 ! Local variables
471 integer,parameter :: max_simple_sort_size = 6
472 integer :: i,j,itemp
473 real(kind_real) :: reference,temp
474 
475 if (right_end<left_end+max_simple_sort_size) then
476  ! Use interchange sort for small lists
477  call interchange_sort(n,left_end,right_end,list,order)
478 else
479  ! Use partition ("quick") sort
480  reference = list((left_end+right_end)/2)
481  i = left_end-1
482  j = right_end+1
483  do
484  ! Scan list from left end until element >= reference is found
485  do
486  i = i+1
487  if (.not.(list(i)<reference)) exit
488  end do
489  ! Scan list from right end until element <= reference is found
490  do
491  j = j-1
492  if (.not.(list(j)>reference)) exit
493  end do
494 
495  if (i<j) then
496  ! Swap two out-of-order elements
497  temp = list(i)
498  list(i) = list(j)
499  list(j) = temp
500  itemp = order(i)
501  order(i) = order(j)
502  order(j) = itemp
503  elseif (i==j) then
504  i = i+1
505  exit
506  else
507  exit
508  end if
509  end do
510 
511  if (left_end<j) call quick_sort(n,left_end,j,list,order)
512  if (i<right_end) call quick_sort(n,i,right_end,list,order)
513 end if
514 
515 end subroutine qsort_quick_sort_real
516 # 265 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
517 
518 # 267 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
519 !----------------------------------------------------------------------
520 ! Subroutine: qsort_interchange_sort_int
521 !> Interchange integers
522 !----------------------------------------------------------------------
523 subroutine qsort_interchange_sort_int(n,left_end,right_end,list,order)
524 
525 implicit none
526 
527 ! Passed variables
528 integer,intent(in) :: n !< Input vector size
529 integer,intent(in) :: left_end !< Left end of the vector
530 integer,intent(in) :: right_end !< Right end of the vector
531 integer(kind_int),intent(inout) :: list(n) !< Vector to sort
532 integer,intent(inout) :: order(n) !< Positions of the elements in the original order
533 
534 ! Local variables
535 integer :: i,j,itemp
536 integer(kind_int) :: temp
537 
538 ! Set name
539 
540 
541 ! Probe in
542 
543 
544 do i=left_end,right_end-1
545  do j=i+1,right_end
546  if (list(i)>list(j)) then
547  temp = list(i)
548  list(i) = list(j)
549  list(j) = temp
550  itemp = order(i)
551  order(i) = order(j)
552  order(j) = itemp
553  end if
554  end do
555 end do
556 
557 ! Probe out
558 
559 
560 end subroutine qsort_interchange_sort_int
561 # 267 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
562 !----------------------------------------------------------------------
563 ! Subroutine: qsort_interchange_sort_real
564 !> Interchange integers
565 !----------------------------------------------------------------------
566 subroutine qsort_interchange_sort_real(n,left_end,right_end,list,order)
567 
568 implicit none
569 
570 ! Passed variables
571 integer,intent(in) :: n !< Input vector size
572 integer,intent(in) :: left_end !< Left end of the vector
573 integer,intent(in) :: right_end !< Right end of the vector
574 real(kind_real),intent(inout) :: list(n) !< Vector to sort
575 integer,intent(inout) :: order(n) !< Positions of the elements in the original order
576 
577 ! Local variables
578 integer :: i,j,itemp
579 real(kind_real) :: temp
580 
581 ! Set name
582 
583 
584 ! Probe in
585 
586 
587 do i=left_end,right_end-1
588  do j=i+1,right_end
589  if (list(i)>list(j)) then
590  temp = list(i)
591  list(i) = list(j)
592  list(j) = temp
593  itemp = order(i)
594  order(i) = order(j)
595  order(j) = itemp
596  end if
597  end do
598 end do
599 
600 ! Probe out
601 
602 
603 end subroutine qsort_interchange_sort_real
604 # 310 "/Users/miesch/JEDI/code/working_copy/internal/mpas-bundle/saber/src/saber/external/tools_qsort.fypp"
605 
606 !----------------------------------------------------------------------
607 ! Subroutine: qsort_reorder_eq
608 !> Reorder equal values
609 !----------------------------------------------------------------------
610 recursive subroutine qsort_reorder_eq(n,list,order)
611 
612 implicit none
613 
614 ! Passed variables
615 integer, intent(in) :: n !< Input vector size
616 real(kind_real),intent(inout) :: list(n) !< Vector to sort
617 integer,intent(out) :: order(n) !< Positions of the elements in the original order
618 
619 ! Local variables
620 integer :: i_s,i_e,ntmp,i
621 integer,allocatable :: order_tmp(:)
622 logical :: chain,diff
623 
624 ! Initialization
625 i_s = 1
626 chain = .false.
627 do i_e=2,n+1
628  if (i_e==n+1) then
629  diff = .true.
630  else
631  diff = .not.eq(list(i_s),list(i_e))
632  end if
633  if (diff) then
634  ! Different value
635  if (chain) then
636  ! Allocation
637  ntmp = i_e-i_s
638  allocate(order_tmp(ntmp))
639 
640  ! Initialize order
641  do i=1,ntmp
642  order_tmp(i) = i
643  end do
644 
645  ! Sort second vector
646  call quick_sort(ntmp,1,ntmp,order(i_s:i_e-1),order_tmp)
647  order_tmp = order_tmp+i_s-1
648  list(i_s:i_e-1) = list(order_tmp)
649 
650  ! Chain done
651  chain = .false.
652 
653  ! Release memory
654  deallocate(order_tmp)
655  end if
656 
657  ! Update
658  i_s = i_e
659  else
660  ! Same value, this is a chain
661  chain = .true.
662  endif
663 end do
664 
665 end subroutine qsort_reorder_eq
666 
667 end module tools_qsort
Kinds definition.
Definition: tools_kinds.F90:9
integer, parameter, public kind_int
Integer kind.
Definition: tools_kinds.F90:17
integer, parameter, public kind_real
Real kind alias for the whole code.
Definition: tools_kinds.F90:31
Generic ranks, dimensions and types.
Definition: tools_qsort.F90:46
recursive subroutine qsort_quick_sort_real(n, left_end, right_end, list, order)
Sort an integer subvector.
recursive subroutine qsort_qsort_pair_real(n, list1, list2, order, order_list)
Sort two joint vectors.
recursive subroutine qsort_reorder_eq(n, list, order)
Reorder equal values.
recursive subroutine qsort_quick_sort_int(n, left_end, right_end, list, order)
Sort an integer subvector.
subroutine qsort_interchange_sort_int(n, left_end, right_end, list, order)
Interchange integers.
subroutine qsort_interchange_sort_real(n, left_end, right_end, list, order)
Interchange integers.
recursive subroutine qsort_qsort_int(n, list, order, order_list)
Sort a vector.
Definition: tools_qsort.F90:92
recursive subroutine qsort_qsort_real(n, list, order, order_list)
Sort a vector.
recursive subroutine qsort_qsort_pair_int(n, list1, list2, order, order_list)
Sort two joint vectors.
Generic ranks, dimensions and types.
Definition: tools_repro.F90:42