|
| 1 | +module sharp |
| 2 | + use iso_c_binding |
| 3 | + implicit none |
| 4 | + ! alm_info flags |
| 5 | + integer, parameter :: SHARP_PACKED = 1 |
| 6 | + |
| 7 | + ! sharp job types |
| 8 | + enum, bind(c) |
| 9 | + enumerator :: SHARP_YtW = 0 |
| 10 | + enumerator :: SHARP_Y = 1 |
| 11 | + enumerator :: SHARP_Yt = 2 |
| 12 | + enumerator :: SHARP_WY = 3 |
| 13 | + enumerator :: SHARP_ALM2MAP_DERIV1 = 4 |
| 14 | + end enum |
| 15 | + |
| 16 | + ! sharp job flags |
| 17 | + integer, parameter :: SHARP_DP = ISHFT(1, 4) |
| 18 | + integer, parameter :: SHARP_ADD = ISHFT(1, 5) |
| 19 | + integer, parameter :: SHARP_REAL_HARMONICS = ISHFT(1, 6) |
| 20 | + integer, parameter :: SHARP_NO_FFT = ISHFT(1, 7) |
| 21 | + |
| 22 | + type sharp_geom_info |
| 23 | + type(c_ptr) :: handle |
| 24 | + integer(c_ptrdiff_t) :: n_local |
| 25 | + end type sharp_geom_info |
| 26 | + |
| 27 | + type sharp_alm_info |
| 28 | + type(c_ptr) :: handle |
| 29 | + integer(c_ptrdiff_t) :: n_local |
| 30 | + end type sharp_alm_info |
| 31 | + |
| 32 | + interface |
| 33 | + |
| 34 | + ! alm_info |
| 35 | + subroutine sharp_make_general_alm_info( & |
| 36 | + lmax, nm, stride, mval, mvstart, flags, alm_info) bind(c) |
| 37 | + use iso_c_binding |
| 38 | + integer(c_int), value, intent(in) :: lmax, nm, stride, flags |
| 39 | + integer(c_int), intent(in) :: mval(nm) |
| 40 | + integer(c_ptrdiff_t), intent(in) :: mvstart(nm) |
| 41 | + type(c_ptr), intent(out) :: alm_info |
| 42 | + end subroutine sharp_make_general_alm_info |
| 43 | + |
| 44 | + subroutine c_sharp_make_mmajor_real_packed_alm_info( & |
| 45 | + lmax, stride, nm, ms, alm_info) bind(c, name='sharp_make_mmajor_real_packed_alm_info') |
| 46 | + use iso_c_binding |
| 47 | + integer(c_int), value, intent(in) :: lmax, nm, stride |
| 48 | + integer(c_int), intent(in), optional :: ms(nm) |
| 49 | + type(c_ptr), intent(out) :: alm_info |
| 50 | + end subroutine c_sharp_make_mmajor_real_packed_alm_info |
| 51 | + |
| 52 | + function c_sharp_alm_count(alm_info) bind(c, name='sharp_alm_count') |
| 53 | + use iso_c_binding |
| 54 | + integer(c_ptrdiff_t) :: c_sharp_alm_count |
| 55 | + type(c_ptr), value, intent(in) :: alm_info |
| 56 | + end function c_sharp_alm_count |
| 57 | + |
| 58 | + subroutine c_sharp_destroy_alm_info(alm_info) bind(c, name='sharp_destroy_alm_info') |
| 59 | + use iso_c_binding |
| 60 | + type(c_ptr), value :: alm_info |
| 61 | + end subroutine c_sharp_destroy_alm_info |
| 62 | + |
| 63 | + ! geom_info |
| 64 | + subroutine sharp_make_subset_healpix_geom_info ( & |
| 65 | + nside, stride, nrings, rings, weight, geom_info) bind(c) |
| 66 | + use iso_c_binding |
| 67 | + integer(c_int), value, intent(in) :: nside, stride, nrings |
| 68 | + integer(c_int), intent(in), optional :: rings(nrings) |
| 69 | + real(c_double), intent(in), optional :: weight(2 * nside) |
| 70 | + type(c_ptr), intent(out) :: geom_info |
| 71 | + end subroutine sharp_make_subset_healpix_geom_info |
| 72 | + |
| 73 | + subroutine c_sharp_destroy_geom_info(geom_info) bind(c, name='sharp_destroy_geom_info') |
| 74 | + use iso_c_binding |
| 75 | + type(c_ptr), value :: geom_info |
| 76 | + end subroutine c_sharp_destroy_geom_info |
| 77 | + |
| 78 | + function c_sharp_map_size(info) bind(c, name='sharp_map_size') |
| 79 | + use iso_c_binding |
| 80 | + integer(c_ptrdiff_t) :: c_sharp_map_size |
| 81 | + type(c_ptr), value :: info |
| 82 | + end function c_sharp_map_size |
| 83 | + |
| 84 | + |
| 85 | + ! execute |
| 86 | + subroutine c_sharp_execute(type, spin, alm, map, geom_info, alm_info, ntrans, & |
| 87 | + flags, time, opcnt) bind(c, name='sharp_execute') |
| 88 | + use iso_c_binding |
| 89 | + integer(c_int), value :: type, spin, ntrans, flags |
| 90 | + type(c_ptr), value :: alm_info, geom_info |
| 91 | + real(c_double), intent(out), optional :: time |
| 92 | + integer(c_long_long), intent(out), optional :: opcnt |
| 93 | + type(c_ptr), intent(in) :: alm(*), map(*) |
| 94 | + end subroutine c_sharp_execute |
| 95 | + |
| 96 | + subroutine c_sharp_execute_mpi(comm, type, spin, alm, map, geom_info, alm_info, ntrans, & |
| 97 | + flags, time, opcnt) bind(c, name='sharp_execute_mpi_fortran') |
| 98 | + use iso_c_binding |
| 99 | + integer(c_int), value :: comm, type, spin, ntrans, flags |
| 100 | + type(c_ptr), value :: alm_info, geom_info |
| 101 | + real(c_double), intent(out), optional :: time |
| 102 | + integer(c_long_long), intent(out), optional :: opcnt |
| 103 | + type(c_ptr), intent(in) :: alm(*), map(*) |
| 104 | + end subroutine c_sharp_execute_mpi |
| 105 | + |
| 106 | + end interface |
| 107 | + |
| 108 | + interface sharp_execute |
| 109 | + module procedure sharp_execute_d |
| 110 | + end interface |
| 111 | + |
| 112 | +contains |
| 113 | + ! alm info |
| 114 | + |
| 115 | + ! if ms is not passed, we default to using m=0..lmax. |
| 116 | + subroutine sharp_make_mmajor_real_packed_alm_info(lmax, ms, alm_info) |
| 117 | + use iso_c_binding |
| 118 | + integer(c_int), value, intent(in) :: lmax |
| 119 | + integer(c_int), intent(in), optional :: ms(:) |
| 120 | + type(sharp_alm_info), intent(out) :: alm_info |
| 121 | + !-- |
| 122 | + integer(c_int), allocatable :: ms_copy(:) |
| 123 | + integer(c_int) :: nm |
| 124 | + |
| 125 | + if (present(ms)) then |
| 126 | + nm = size(ms) |
| 127 | + allocate(ms_copy(nm)) |
| 128 | + ms_copy = ms |
| 129 | + call c_sharp_make_mmajor_real_packed_alm_info(lmax, 1, nm, ms_copy, alm_info=alm_info%handle) |
| 130 | + deallocate(ms_copy) |
| 131 | + else |
| 132 | + call c_sharp_make_mmajor_real_packed_alm_info(lmax, 1, lmax + 1, alm_info=alm_info%handle) |
| 133 | + end if |
| 134 | + alm_info%n_local = c_sharp_alm_count(alm_info%handle) |
| 135 | + end subroutine sharp_make_mmajor_real_packed_alm_info |
| 136 | + |
| 137 | + subroutine sharp_destroy_alm_info(alm_info) |
| 138 | + use iso_c_binding |
| 139 | + type(sharp_alm_info), intent(inout) :: alm_info |
| 140 | + call c_sharp_destroy_alm_info(alm_info%handle) |
| 141 | + alm_info%handle = c_null_ptr |
| 142 | + end subroutine sharp_destroy_alm_info |
| 143 | + |
| 144 | + |
| 145 | + ! geom info |
| 146 | + subroutine sharp_make_healpix_geom_info(nside, rings, weight, geom_info) |
| 147 | + integer(c_int), value :: nside |
| 148 | + integer(c_int), optional :: rings(:) |
| 149 | + real(c_double), intent(in), optional :: weight(2 * nside) |
| 150 | + type(sharp_geom_info), intent(out) :: geom_info |
| 151 | + !-- |
| 152 | + integer(c_int) :: nrings |
| 153 | + integer(c_int), allocatable :: rings_copy(:) |
| 154 | + |
| 155 | + if (present(rings)) then |
| 156 | + nrings = size(rings) |
| 157 | + allocate(rings_copy(nrings)) |
| 158 | + rings_copy = rings |
| 159 | + call sharp_make_subset_healpix_geom_info(nside, 1, nrings, rings_copy, & |
| 160 | + weight, geom_info%handle) |
| 161 | + deallocate(rings_copy) |
| 162 | + else |
| 163 | + call sharp_make_subset_healpix_geom_info(nside, 1, nrings=4 * nside - 1, & |
| 164 | + weight=weight, geom_info=geom_info%handle) |
| 165 | + end if |
| 166 | + geom_info%n_local = c_sharp_map_size(geom_info%handle) |
| 167 | + end subroutine sharp_make_healpix_geom_info |
| 168 | + |
| 169 | + subroutine sharp_destroy_geom_info(geom_info) |
| 170 | + use iso_c_binding |
| 171 | + type(sharp_geom_info), intent(inout) :: geom_info |
| 172 | + call c_sharp_destroy_geom_info(geom_info%handle) |
| 173 | + geom_info%handle = c_null_ptr |
| 174 | + end subroutine sharp_destroy_geom_info |
| 175 | + |
| 176 | + |
| 177 | + ! Currently the only mode supported is stacked (not interleaved) maps. |
| 178 | + ! |
| 179 | + ! Note that passing the exact dimension of alm/map is necesarry, it |
| 180 | + ! prevents the caller from doing too crazy slicing prior to pass array |
| 181 | + ! in... |
| 182 | + ! |
| 183 | + ! Usage: |
| 184 | + ! |
| 185 | + ! The alm array must have shape exactly alm(alm_info%n_local, nmaps) |
| 186 | + ! The maps array must have shape exactly map(map_info%n_local, nmaps). |
| 187 | + subroutine sharp_execute_d(type, spin, nmaps, alm, alm_info, map, geom_info, & |
| 188 | + add, time, opcnt, comm) |
| 189 | + use iso_c_binding |
| 190 | + use mpi |
| 191 | + implicit none |
| 192 | + integer(c_int), value :: type, spin, nmaps |
| 193 | + integer(c_int), optional :: comm |
| 194 | + logical, value, optional :: add ! should add instead of replace out |
| 195 | + |
| 196 | + type(sharp_alm_info) :: alm_info |
| 197 | + type(sharp_geom_info) :: geom_info |
| 198 | + real(c_double), intent(out), optional :: time |
| 199 | + integer(c_long_long), intent(out), optional :: opcnt |
| 200 | + real(c_double), target, intent(inout) :: alm(0:alm_info%n_local - 1, 1:nmaps) |
| 201 | + real(c_double), target, intent(inout) :: map(0:geom_info%n_local - 1, 1:nmaps) |
| 202 | + !-- |
| 203 | + integer(c_int) :: mod_flags, ntrans, k |
| 204 | + type(c_ptr), target :: alm_ptr(nmaps) |
| 205 | + type(c_ptr), target :: map_ptr(nmaps) |
| 206 | + |
| 207 | + mod_flags = SHARP_DP |
| 208 | + if (present(add) .and. add) then |
| 209 | + mod_flags = or(mod_flags, SHARP_ADD) |
| 210 | + end if |
| 211 | + |
| 212 | + if (spin == 0) then |
| 213 | + ntrans = nmaps |
| 214 | + else |
| 215 | + ntrans = nmaps / 2 |
| 216 | + end if |
| 217 | + |
| 218 | + ! Set up pointer table to access maps |
| 219 | + do k = 1, nmaps |
| 220 | + alm_ptr(k) = c_loc(alm(0, k)) |
| 221 | + map_ptr(k) = c_loc(map(0, k)) |
| 222 | + end do |
| 223 | + |
| 224 | + if (present(comm)) then |
| 225 | + call c_sharp_execute_mpi(comm, type, spin, alm_ptr, map_ptr, & |
| 226 | + geom_info=geom_info%handle, & |
| 227 | + alm_info=alm_info%handle, & |
| 228 | + ntrans=ntrans, & |
| 229 | + flags=mod_flags, & |
| 230 | + time=time, & |
| 231 | + opcnt=opcnt) |
| 232 | + else |
| 233 | + call c_sharp_execute(type, spin, alm_ptr, map_ptr, & |
| 234 | + geom_info=geom_info%handle, & |
| 235 | + alm_info=alm_info%handle, & |
| 236 | + ntrans=ntrans, & |
| 237 | + flags=mod_flags, & |
| 238 | + time=time, & |
| 239 | + opcnt=opcnt) |
| 240 | + end if |
| 241 | + end subroutine sharp_execute_d |
| 242 | + |
| 243 | + |
| 244 | + |
| 245 | +end module |
0 commit comments