Octopus
hypercube.F90
Go to the documentation of this file.
1!! Copyright (C) 2009 N. Helbig, X. Andrade
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module hypercube_oct_m
22 use debug_oct_m
23 use global_oct_m
26
27 implicit none
28
29 private
30
31 public :: &
39
40 type hypercube_t
41 private
42 integer, allocatable :: boxdim(:)
43 end type hypercube_t
44
45contains
46
47 subroutine hypercube_init(this, ndim, nr, enlarge)
48 type(hypercube_t), intent(out) :: this
49 integer, intent(in) :: ndim
50 integer, intent(in) :: nr(:, :)
51 integer, intent(in) :: enlarge
52
53 integer, allocatable :: npoints(:)
54 integer :: ii, jj
55
56 push_sub(hypercube_init)
57
58 safe_allocate(this%boxdim(1:ndim + 1))
59 safe_allocate(npoints(1:ndim))
60
61 do ii = 1, ndim
62 npoints(ii) = nr(2,ii) - nr(1,ii) + 1
63 end do
64
65 !number of points in each box
66 this%boxdim = 1
67
68 !first box is inner points
69 do jj = 1, ndim
70 this%boxdim(1) = this%boxdim(1)*(npoints(jj)-2*enlarge)
71 end do
72
73 !all other boxes are boundary points
74
75 do ii=2, ndim+1
76 do jj=1, ii-2
77 this%boxdim(ii)=this%boxdim(ii)*(npoints(jj)-2*enlarge)
78 end do
79 this%boxdim(ii)=this%boxdim(ii)*2*enlarge
80 do jj=ii, ndim
81 this%boxdim(ii)=this%boxdim(ii)*npoints(jj)
82 end do
83 end do
84
85 safe_deallocate_a(npoints)
86
87 pop_sub(hypercube_init)
88 end subroutine hypercube_init
89
90
91 ! ---------------------------------------------------------
92 subroutine hypercube_end(this)
93 type(hypercube_t), intent(inout) :: this
94
95 push_sub(hypercube_end)
96
97 safe_deallocate_a(this%boxdim)
98
99 pop_sub(hypercube_end)
100 end subroutine hypercube_end
101
102
103 ! ---------------------------------------------------------
104 subroutine hypercube_x_to_i(this, ndim, nr, enlarge, coord, icoord)
105 type(hypercube_t), intent(in) :: this
106 integer, intent(in) :: ndim
107 integer, intent(in) :: nr(:,:)
108 integer, intent(in) :: enlarge
109 integer, intent(in) :: coord(:)
110 integer, intent(out) :: icoord
111
112 integer :: boxnumb
113 integer :: border(1:ndim), npoints(1:ndim), lowerb(1:ndim), tempcoord(1:ndim)
114 integer :: ii, jj
115
116 ! no push sub, called too frequently
117
118 do ii = 1, ndim
119 npoints(ii) = nr(2, ii) - nr(1, ii) + 1
120 border(ii) = nr(1, ii) + 2*enlarge
121 lowerb(ii) = nr(1, ii)
122 end do
123
124 !move coordinates such that inner box is in the upper right corner
125 do ii = 1, ndim
126 tempcoord(ii) = coord(ii)
127 tempcoord(ii) = tempcoord(ii) + enlarge - nr(1,ii)
128 tempcoord(ii) = mod(tempcoord(ii), npoints(ii))
129 tempcoord(ii) = tempcoord(ii) + nr(1,ii)
130 end do
131
132 !determine which box we are in
133 boxnumb = 1
134 do ii = 1, ndim
135 if (tempcoord(ii) < border(ii)) then
136 boxnumb = ii + 1
137 exit
138 end if
139 end do
141 !transform coordinates
142 icoord = 0
143
144 if (boxnumb == 1) then
145 npoints = npoints - 2*enlarge
146 do ii = ndim, 1, -1
147 icoord = icoord*npoints(ii)
148 icoord = icoord + tempcoord(ii) - border(ii)
149 end do
150 icoord = icoord+1
151 if (icoord > this%boxdim(1) .or. icoord < 1) then
152 message(1) = "hypercube box point outside box"
153 call messages_fatal(1)
154 end if
155 else
156 do jj = 1, boxnumb - 2
157 npoints(jj) = npoints(jj) - 2*enlarge
158 lowerb(jj) = nr(1, jj) + 2*enlarge
159 end do
160 npoints(boxnumb-1) = 2*enlarge
161 do jj=ndim, 1, -1
162 icoord = icoord*npoints(jj)
163 icoord = icoord + (tempcoord(jj) - lowerb(jj))
164 end do
165 icoord = icoord + 1
166 if (icoord > this%boxdim(boxnumb) .or. icoord < 1) then
167 message(1) = "hypercube box point outside box"
168 call messages_fatal(1)
169 else
170 do jj = 1, boxnumb - 1
171 icoord = icoord + this%boxdim(jj)
172 end do
173 end if
174 end if
175
176 end subroutine hypercube_x_to_i
177
178
179 ! ---------------------------------------------------------
180 pure subroutine hypercube_i_to_x(this, ndim, nr, enlarge, icoord, coord)
181 type(hypercube_t), intent(in) :: this
182 integer, intent(in) :: ndim
183 integer, intent(in) :: nr(:,:)
184 integer, intent(in) :: enlarge
185 integer, intent(in) :: icoord
186 integer, intent(out) :: coord(:)
187
188 integer :: boxnumb, tempcoord
189 integer :: border(ndim), npoints(ndim), lowerb(ndim)
190 integer :: ii, jj
191
192 boxnumb = 1
193
194 jj = 0
195
196 do ii = 1, ndim
197 jj = jj + this%boxdim(ii)
198 if (icoord > jj) then
199 boxnumb = ii + 1
200 end if
201 end do
202
203 do ii = 1, ndim
204 npoints(ii) = nr(2, ii) - nr(1, ii)+1
205 border(ii) = nr(1, ii) + 2*enlarge
206 lowerb(ii) = nr(1, ii)
207 end do
208
209 tempcoord=icoord
210
211 if (boxnumb == 1) then
212 npoints = npoints - 2*enlarge
213 tempcoord = tempcoord - 1
214 do ii = 1, ndim
215 coord(ii) = mod(tempcoord, npoints(ii))
216 tempcoord = tempcoord - coord(ii)
217 tempcoord = tempcoord/npoints(ii)
218 coord(ii) = coord(ii) + border(ii)
219 end do
220 else
221 do ii = 1, boxnumb - 2
222 npoints(ii) = npoints(ii) - 2*enlarge
223 lowerb(ii) = nr(1,ii) + 2*enlarge
224 tempcoord = tempcoord - this%boxdim(ii)
225 end do
226 npoints(boxnumb - 1) = 2*enlarge
227 tempcoord = tempcoord - this%boxdim(boxnumb-1)
228 tempcoord = tempcoord - 1
229 do ii = 1, ndim
230 coord(ii) = mod(tempcoord, npoints(ii))
231 tempcoord = tempcoord - coord(ii)
232 tempcoord = tempcoord/npoints(ii)
233 coord(ii) = coord(ii) + lowerb(ii)
234 end do
235 end if
236
237 do ii = 1, ndim
238 npoints(ii) = nr(2,ii) - nr(1,ii) + 1
239 end do
240
241 !move inner box back to the middle
242
243 do ii = 1, ndim
244 coord(ii) = coord(ii) - nr(1,ii) - enlarge
245 if (coord(ii) < 0) then
246 coord(ii) = coord(ii) + npoints(ii)
247 end if
248 coord(ii) = coord(ii) + nr(1,ii)
249 end do
250
251 end subroutine hypercube_i_to_x
252
253
254 ! ---------------------------------------------------------
255 pure integer function hypercube_number_inner_points(this) result(number)
256 type(hypercube_t), intent(in) :: this
257
258 number = this%boxdim(1)
260
261
262 ! ---------------------------------------------------------
263 pure integer function hypercube_number_total_points(this) result(number)
264 type(hypercube_t), intent(in) :: this
265
266 number = sum(this%boxdim)
268
269end module hypercube_oct_m
270
271!! Local Variables:
272!! mode: f90
273!! coding: utf-8
274!! End:
subroutine, public hypercube_x_to_i(this, ndim, nr, enlarge, coord, icoord)
Definition: hypercube.F90:198
subroutine, public hypercube_init(this, ndim, nr, enlarge)
Definition: hypercube.F90:141
pure integer function, public hypercube_number_total_points(this)
Definition: hypercube.F90:357
pure integer function, public hypercube_number_inner_points(this)
Definition: hypercube.F90:349
pure subroutine, public hypercube_i_to_x(this, ndim, nr, enlarge, icoord, coord)
Definition: hypercube.F90:274
subroutine, public hypercube_end(this)
Definition: hypercube.F90:186
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420