Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief subroutines for defining and creating Dirichlet type subdomains
10 : !> \par History
11 : !> 08.2014 created [Hossein Bani-Hashemian]
12 : !> 10.2015 completely revised [Hossein Bani-Hashemian]
13 : !> \author Mohammad Hossein Bani-Hashemian
14 : ! **************************************************************************************************
15 : MODULE dirichlet_bc_methods
16 :
17 : USE cp_log_handling, ONLY: cp_get_default_logger,&
18 : cp_logger_get_default_unit_nr,&
19 : cp_logger_type
20 : USE dirichlet_bc_types, ONLY: &
21 : AA_CUBOIDAL, AA_PLANAR, CIRCUMSCRIBED, CYLINDRICAL, INSCRIBED, PLANAR, &
22 : dbc_parameters_dealloc, dirichlet_bc_p_type, dirichlet_bc_type, tile_p_type, x_axis, &
23 : xy_plane, xz_plane, y_axis, yz_plane, z_axis
24 : USE kinds, ONLY: dp
25 : USE mathconstants, ONLY: pi,&
26 : twopi
27 : USE mathlib, ONLY: inv_3x3,&
28 : vector_product
29 : USE physcon, ONLY: angstrom
30 : USE ps_implicit_types, ONLY: MIXED_BC,&
31 : MIXED_PERIODIC_BC,&
32 : NEUMANN_BC,&
33 : PERIODIC_BC
34 : USE pw_grid_types, ONLY: pw_grid_type
35 : USE pw_methods, ONLY: pw_axpy,&
36 : pw_zero
37 : USE pw_poisson_types, ONLY: pw_poisson_parameter_type
38 : USE pw_pool_types, ONLY: pw_pool_type
39 : USE pw_types, ONLY: pw_r3d_rs_type
40 : USE rs_methods, ONLY: setup_grid_axes
41 : #include "../base/base_uses.f90"
42 :
43 : IMPLICIT NONE
44 : PRIVATE
45 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dirichlet_bc_methods'
46 :
47 : PUBLIC dirichlet_boundary_region_setup
48 :
49 : REAL(dp), PARAMETER, PRIVATE :: small_value = 1.0E-8_dp
50 : INTEGER, PARAMETER, PRIVATE :: FWROT = 1, &
51 : BWROT = -1
52 :
53 : CONTAINS
54 :
55 : ! **************************************************************************************************
56 : !> \brief Sets up the Dirichlet boundary condition
57 : !> \param pw_pool pool of plane wave grid
58 : !> \param poisson_params poisson_env parameters
59 : !> \param dbcs the DBC region to be created
60 : !> \par History
61 : !> 10.2014 created [Hossein Bani-Hashemian]
62 : !> \author Mohammad Hossein Bani-Hashemian
63 : ! **************************************************************************************************
64 54 : SUBROUTINE dirichlet_boundary_region_setup(pw_pool, poisson_params, dbcs)
65 :
66 : TYPE(pw_pool_type), INTENT(IN), POINTER :: pw_pool
67 : TYPE(pw_poisson_parameter_type), INTENT(INOUT) :: poisson_params
68 : TYPE(dirichlet_bc_p_type), ALLOCATABLE, &
69 : DIMENSION(:), INTENT(INOUT) :: dbcs
70 :
71 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dirichlet_boundary_region_setup'
72 :
73 : INTEGER :: apx_type, dbc_id, handle, ind_end, ind_start, j, l, n_aa_cuboidal, &
74 : n_aa_cylindrical, n_aa_planar, n_dbcs, n_planar, parallel_axis, parallel_plane, unit_nr
75 : INTEGER, DIMENSION(3) :: n_prtn, npts
76 54 : INTEGER, DIMENSION(:), POINTER :: aa_cylindrical_nsides
77 : LOGICAL :: is_periodic, verbose
78 : REAL(dp) :: base_radius, delta_alpha, frequency, &
79 : oscillating_fraction, phase, sigma, &
80 : thickness, v_D
81 54 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: x_glbl, x_locl, y_glbl, y_locl, z_glbl, &
82 54 : z_locl
83 : REAL(dp), DIMENSION(2) :: base_center
84 : REAL(dp), DIMENSION(2, 3) :: cell_xtnts
85 : REAL(dp), DIMENSION(3) :: dr
86 : TYPE(cp_logger_type), POINTER :: logger
87 : TYPE(pw_grid_type), POINTER :: pw_grid
88 :
89 54 : CALL timeset(routineN, handle)
90 :
91 54 : logger => cp_get_default_logger()
92 54 : IF (logger%para_env%is_source()) THEN
93 27 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
94 : ELSE
95 : unit_nr = -1
96 : END IF
97 :
98 216 : dr = pw_pool%pw_grid%dr
99 216 : npts = pw_pool%pw_grid%npts
100 54 : cell_xtnts = 0.0_dp
101 54 : cell_xtnts(2, 1) = npts(1)*dr(1)
102 54 : cell_xtnts(2, 2) = npts(2)*dr(2)
103 54 : cell_xtnts(2, 3) = npts(3)*dr(3)
104 :
105 54 : verbose = poisson_params%dbc_params%verbose_output
106 :
107 54 : n_aa_planar = poisson_params%dbc_params%n_aa_planar
108 54 : n_aa_cuboidal = poisson_params%dbc_params%n_aa_cuboidal
109 54 : n_planar = poisson_params%dbc_params%n_planar
110 54 : n_aa_cylindrical = poisson_params%dbc_params%n_aa_cylindrical
111 54 : aa_cylindrical_nsides => poisson_params%dbc_params%aa_cylindrical_nsides
112 54 : pw_grid => pw_pool%pw_grid
113 : CALL setup_grid_axes(pw_grid, x_glbl, y_glbl, z_glbl, x_locl, y_locl, z_locl)
114 66 : n_dbcs = n_aa_planar + n_aa_cuboidal + n_planar + SUM(aa_cylindrical_nsides)
115 :
116 92 : SELECT CASE (poisson_params%ps_implicit_params%boundary_condition)
117 : CASE (MIXED_BC, MIXED_PERIODIC_BC)
118 38 : IF (n_dbcs .EQ. 0) THEN
119 0 : CPABORT("No Dirichlet region is defined.")
120 : END IF
121 :
122 242 : ALLOCATE (dbcs(n_dbcs))
123 38 : IF (unit_nr .GT. 0) THEN
124 19 : WRITE (unit_nr, '(/,T3,A,A,/,T3,A)') "POISSON| IMPLICIT (GENERALIZED) SOLVER ", REPEAT('-', 39), &
125 38 : "POISSON| Preparing Dirichlet regions ..."
126 : END IF
127 :
128 62 : DO j = 1, n_aa_planar
129 792 : ALLOCATE (dbcs(j)%dirichlet_bc)
130 96 : n_prtn = poisson_params%dbc_params%aa_planar_nprtn(:, j)
131 24 : dbc_id = AA_PLANAR + j
132 24 : v_D = poisson_params%dbc_params%aa_planar_vD(j)
133 24 : frequency = poisson_params%dbc_params%aa_planar_frequency(j)
134 24 : oscillating_fraction = poisson_params%dbc_params%aa_planar_osc_frac(j)
135 24 : phase = poisson_params%dbc_params%aa_planar_phase(j)
136 24 : sigma = poisson_params%dbc_params%aa_planar_sigma(j)
137 24 : thickness = poisson_params%dbc_params%aa_planar_thickness(j)
138 24 : parallel_plane = poisson_params%dbc_params%aa_planar_pplane(j)
139 24 : is_periodic = poisson_params%dbc_params%aa_planar_is_periodic(j)
140 :
141 24 : IF (unit_nr .GT. 0) THEN
142 12 : WRITE (unit_nr, '(T3,A,I5)') "POISSON| Dirichlet region", j
143 12 : WRITE (unit_nr, '(T3,A)') "POISSON| type : axis-aligned planar"
144 12 : WRITE (unit_nr, '(T3,A,E13.4,2X,A)') "POISSON| applied potential :", v_D, "[Eh/e]"
145 : END IF
146 : CALL aa_planar_dbc_setup(cell_xtnts, parallel_plane, &
147 : poisson_params%dbc_params%aa_planar_xxtnt(:, j), &
148 : poisson_params%dbc_params%aa_planar_yxtnt(:, j), &
149 : poisson_params%dbc_params%aa_planar_zxtnt(:, j), &
150 : thickness, sigma, v_D, oscillating_fraction, frequency, &
151 24 : phase, dbc_id, verbose, dbcs(j)%dirichlet_bc)
152 :
153 : CALL dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
154 62 : x_locl, y_locl, z_locl, is_periodic, verbose, dbcs(j)%dirichlet_bc)
155 : END DO
156 :
157 38 : l = n_aa_planar
158 44 : DO j = l + 1, l + n_aa_cuboidal
159 198 : ALLOCATE (dbcs(j)%dirichlet_bc)
160 24 : n_prtn = poisson_params%dbc_params%aa_cuboidal_nprtn(:, j - l)
161 6 : dbc_id = AA_CUBOIDAL + j - l
162 6 : v_D = poisson_params%dbc_params%aa_cuboidal_vD(j - l)
163 6 : frequency = poisson_params%dbc_params%aa_cuboidal_frequency(j - l)
164 6 : oscillating_fraction = poisson_params%dbc_params%aa_cuboidal_osc_frac(j - l)
165 6 : phase = poisson_params%dbc_params%aa_cuboidal_phase(j - l)
166 6 : sigma = poisson_params%dbc_params%aa_cuboidal_sigma(j - l)
167 6 : is_periodic = poisson_params%dbc_params%aa_cuboidal_is_periodic(j - l)
168 :
169 6 : IF (unit_nr .GT. 0) THEN
170 3 : WRITE (unit_nr, '(T3,A,I5)') "POISSON| Dirichlet region", j
171 3 : WRITE (unit_nr, '(T3,A)') "POISSON| type : axis-aligned cuboidal"
172 3 : WRITE (unit_nr, '(T3,A,E13.4,2X,A)') "POISSON| applied potential :", v_D, "[Eh/e]"
173 : END IF
174 : CALL aa_cuboidal_dbc_setup(cell_xtnts, &
175 : poisson_params%dbc_params%aa_cuboidal_xxtnt(:, j - l), &
176 : poisson_params%dbc_params%aa_cuboidal_yxtnt(:, j - l), &
177 : poisson_params%dbc_params%aa_cuboidal_zxtnt(:, j - l), &
178 : sigma, v_D, oscillating_fraction, frequency, &
179 6 : phase, dbc_id, verbose, dbcs(j)%dirichlet_bc)
180 :
181 : CALL dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
182 44 : x_locl, y_locl, z_locl, is_periodic, verbose, dbcs(j)%dirichlet_bc)
183 : END DO
184 :
185 38 : l = n_aa_planar + n_aa_cuboidal
186 44 : DO j = l + 1, l + n_planar
187 198 : ALLOCATE (dbcs(j)%dirichlet_bc)
188 24 : n_prtn = 1
189 18 : n_prtn(1:2) = poisson_params%dbc_params%planar_nprtn(:, j - l)
190 6 : dbc_id = PLANAR + j - l
191 6 : v_D = poisson_params%dbc_params%planar_vD(j - l)
192 6 : frequency = poisson_params%dbc_params%planar_frequency(j - l)
193 6 : oscillating_fraction = poisson_params%dbc_params%planar_osc_frac(j - l)
194 6 : phase = poisson_params%dbc_params%planar_phase(j - l)
195 6 : sigma = poisson_params%dbc_params%planar_sigma(j - l)
196 6 : thickness = poisson_params%dbc_params%planar_thickness(j - l)
197 6 : is_periodic = poisson_params%dbc_params%planar_is_periodic(j - l)
198 :
199 6 : IF (unit_nr .GT. 0) THEN
200 3 : WRITE (unit_nr, '(T3,A,I5)') "POISSON| Dirichlet region", j
201 3 : WRITE (unit_nr, '(T3,A)') "POISSON| type : planar"
202 3 : WRITE (unit_nr, '(T3,A,E13.4,2X,A)') "POISSON| applied potential :", v_D, "[Eh/e]"
203 : END IF
204 : CALL arbitrary_planar_dbc_setup(cell_xtnts, &
205 : poisson_params%dbc_params%planar_Avtx(:, j - l), &
206 : poisson_params%dbc_params%planar_Bvtx(:, j - l), &
207 : poisson_params%dbc_params%planar_Cvtx(:, j - l), &
208 : thickness, sigma, v_D, oscillating_fraction, frequency, &
209 6 : phase, dbc_id, verbose, dbcs(j)%dirichlet_bc)
210 :
211 : CALL dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
212 44 : x_locl, y_locl, z_locl, is_periodic, verbose, dbcs(j)%dirichlet_bc)
213 : END DO
214 :
215 38 : l = n_aa_planar + n_aa_cuboidal + n_planar
216 104 : DO j = 1, n_aa_cylindrical
217 12 : ind_start = l + 1
218 12 : ind_end = l + aa_cylindrical_nsides(j)
219 :
220 48 : n_prtn = 1
221 36 : n_prtn(1:2) = poisson_params%dbc_params%aa_cylindrical_nprtn(:, j)
222 12 : parallel_axis = poisson_params%dbc_params%aa_cylindrical_paxis(j)
223 12 : apx_type = poisson_params%dbc_params%aa_cylindrical_apxtyp(j)
224 36 : base_center = poisson_params%dbc_params%aa_cylindrical_bctr(:, j)
225 12 : base_radius = poisson_params%dbc_params%aa_cylindrical_brad(j)
226 12 : thickness = poisson_params%dbc_params%aa_cylindrical_thickness(j)
227 12 : delta_alpha = poisson_params%dbc_params%aa_cylindrical_sgap(j)
228 12 : sigma = poisson_params%dbc_params%aa_cylindrical_sigma(j)
229 12 : v_D = poisson_params%dbc_params%aa_cylindrical_vD(j)
230 12 : frequency = poisson_params%dbc_params%aa_cylindrical_frequency(j)
231 12 : oscillating_fraction = poisson_params%dbc_params%aa_cylindrical_osc_frac(j)
232 12 : phase = poisson_params%dbc_params%aa_cylindrical_phase(j)
233 12 : is_periodic = poisson_params%dbc_params%aa_cylindrical_is_periodic(j)
234 :
235 12 : IF (unit_nr .GT. 0) THEN
236 6 : WRITE (unit_nr, '(T3,A,I5)') "POISSON| Dirichlet region", l + j
237 6 : WRITE (unit_nr, '(T3,A)') "POISSON| type : axis-aligned cylindrical"
238 6 : WRITE (unit_nr, '(T3,A,E13.4,2X,A)') "POISSON| applied potential :", v_D, "[Eh/e]"
239 : END IF
240 : CALL aa_cylindrical_dbc_setup(pw_pool, cell_xtnts, x_locl, y_locl, z_locl, apx_type, parallel_axis, &
241 : poisson_params%dbc_params%aa_cylindrical_xtnt(:, j), &
242 : base_center, base_radius, thickness, delta_alpha, sigma, v_D, &
243 : oscillating_fraction, frequency, phase, &
244 12 : n_prtn, is_periodic, verbose, dbcs(ind_start:ind_end))
245 :
246 50 : l = l + aa_cylindrical_nsides(j)
247 : END DO
248 :
249 : CASE (PERIODIC_BC, NEUMANN_BC)
250 : ! do nothing
251 : END SELECT
252 :
253 : ! we won't need parameters anymore so deallocate them
254 54 : CALL dbc_parameters_dealloc(poisson_params%dbc_params)
255 :
256 54 : CALL timestop(handle)
257 :
258 108 : END SUBROUTINE dirichlet_boundary_region_setup
259 :
260 : ! **************************************************************************************************
261 : !> \brief Partitions a dirichlet_bc_type into tiles
262 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
263 : !> \param n_prtn vector of size 3 specifying the number of times that the x, y and
264 : !> z interval (defining the region) should be partitioned into
265 : !> \param pw_pool pool of plane-wave grid
266 : !> \param cell_xtnts extents of the simulation cell
267 : !> \param x_locl x grid vector of the simulation box local to this process
268 : !> \param y_locl y grid vector of the simulation box local to this process
269 : !> \param z_locl z grid vector of the simulation box local to this process
270 : !> \param is_periodic whether or not the tile is periodic with a periodicity of one unit cell
271 : !> \param verbose whether or not to print out the coordinates of the vertices
272 : !> \param dirichlet_bc the dirichlet_bc object to be partitioned
273 : !> \par History
274 : !> 10.2014 created [Hossein Bani-Hashemian]
275 : !> \author Mohammad Hossein Bani-Hashemian
276 : ! **************************************************************************************************
277 128 : SUBROUTINE dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
278 : x_locl, y_locl, z_locl, is_periodic, verbose, dirichlet_bc)
279 :
280 : REAL(dp), INTENT(IN) :: sigma
281 : INTEGER, DIMENSION(3), INTENT(IN) :: n_prtn
282 : TYPE(pw_pool_type), INTENT(IN), POINTER :: pw_pool
283 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
284 : REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(IN) :: x_locl, y_locl, z_locl
285 : LOGICAL, INTENT(IN) :: is_periodic, verbose
286 : TYPE(dirichlet_bc_type), INTENT(INOUT), POINTER :: dirichlet_bc
287 :
288 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dirichlet_bc_partition'
289 :
290 : INTEGER :: handle, i, k, n_tiles, unit_nr
291 : REAL(dp) :: cyl_maxval, tile_volume
292 128 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: tile_maxvals
293 : TYPE(cp_logger_type), POINTER :: logger
294 : TYPE(pw_r3d_rs_type), POINTER :: cylinder_pw
295 128 : TYPE(tile_p_type), DIMENSION(:), POINTER :: tiles
296 :
297 128 : CALL timeset(routineN, handle)
298 :
299 128 : logger => cp_get_default_logger()
300 128 : IF (logger%para_env%is_source()) THEN
301 64 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
302 : ELSE
303 : unit_nr = -1
304 : END IF
305 :
306 134 : SELECT CASE (dirichlet_bc%dbc_geom)
307 : CASE (PLANAR)
308 :
309 6 : CALL arbitrary_dbc_partition(dirichlet_bc%vertices, n_prtn(1:2), tiles)
310 6 : n_tiles = SIZE(tiles)
311 6 : dirichlet_bc%n_tiles = n_tiles
312 36 : ALLOCATE (dirichlet_bc%tiles(n_tiles))
313 42 : dirichlet_bc%tiles = tiles
314 6 : IF ((unit_nr .GT. 0) .AND. verbose) WRITE (unit_nr, '(T7,A,I5)') "number of partitions : ", n_tiles
315 :
316 12 : ALLOCATE (tile_maxvals(n_tiles))
317 24 : tile_maxvals = 0.0_dp
318 24 : DO k = 1, n_tiles
319 18 : ALLOCATE (dirichlet_bc%tiles(k)%tile%tile_pw)
320 18 : CALL pw_pool%create_pw(dirichlet_bc%tiles(k)%tile%tile_pw)
321 18 : CALL pw_zero(dirichlet_bc%tiles(k)%tile%tile_pw)
322 :
323 18 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
324 0 : WRITE (unit_nr, '(T7,A,I5)') "tile", k
325 0 : DO i = 1, 8
326 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') &
327 0 : " vertex ", i, angstrom*dirichlet_bc%tiles(k)%tile%vertices(:, i)
328 : END DO
329 : END IF
330 :
331 : CALL arbitrary_tile_pw_compute(cell_xtnts, x_locl, y_locl, z_locl, dirichlet_bc%tiles(k)%tile%vertices, &
332 18 : sigma, dirichlet_bc%tiles(k)%tile%tile_pw)
333 2270862 : tile_volume = SUM(dirichlet_bc%tiles(k)%tile%tile_pw%array)
334 18 : CALL pw_pool%pw_grid%para%group%sum(tile_volume)
335 24 : dirichlet_bc%tiles(k)%tile%volume = tile_volume
336 : END DO
337 :
338 6 : IF ((unit_nr .GT. 0) .AND. verbose) WRITE (unit_nr, '(T3,A)') REPEAT('=', 78)
339 :
340 6 : DEALLOCATE (tiles)
341 :
342 : CASE (CYLINDRICAL)
343 :
344 92 : CALL arbitrary_dbc_partition(dirichlet_bc%vertices, n_prtn(1:2), tiles)
345 92 : n_tiles = SIZE(tiles)
346 92 : dirichlet_bc%n_tiles = n_tiles
347 418 : ALLOCATE (dirichlet_bc%tiles(n_tiles))
348 376 : dirichlet_bc%tiles = tiles
349 92 : IF ((unit_nr .GT. 0) .AND. verbose) WRITE (unit_nr, '(T7,A,I5)') "number of partitions : ", n_tiles
350 :
351 92 : NULLIFY (cylinder_pw)
352 92 : ALLOCATE (cylinder_pw)
353 92 : CALL pw_pool%create_pw(cylinder_pw)
354 92 : CALL pw_zero(cylinder_pw)
355 :
356 234 : DO k = 1, n_tiles
357 142 : ALLOCATE (dirichlet_bc%tiles(k)%tile%tile_pw)
358 142 : CALL pw_pool%create_pw(dirichlet_bc%tiles(k)%tile%tile_pw)
359 142 : CALL pw_zero(dirichlet_bc%tiles(k)%tile%tile_pw)
360 :
361 142 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
362 0 : WRITE (unit_nr, '(T7,A,I5)') "tile", k
363 0 : DO i = 1, 8
364 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') &
365 0 : " vertex ", i, angstrom*dirichlet_bc%tiles(k)%tile%vertices(:, i)
366 : END DO
367 : END IF
368 :
369 : CALL arbitrary_tile_pw_compute(cell_xtnts, x_locl, y_locl, z_locl, dirichlet_bc%tiles(k)%tile%vertices, &
370 142 : sigma, dirichlet_bc%tiles(k)%tile%tile_pw)
371 142 : CALL pw_axpy(dirichlet_bc%tiles(k)%tile%tile_pw, cylinder_pw)
372 13544386 : tile_volume = SUM(dirichlet_bc%tiles(k)%tile%tile_pw%array)
373 142 : CALL pw_pool%pw_grid%para%group%sum(tile_volume)
374 234 : dirichlet_bc%tiles(k)%tile%volume = tile_volume
375 : END DO
376 :
377 7255676 : cyl_maxval = MAXVAL(cylinder_pw%array)
378 92 : CALL pw_pool%pw_grid%para%group%max(cyl_maxval)
379 92 : IF (cyl_maxval .GT. 1.01_dp) THEN
380 : CALL cp_abort(__LOCATION__, &
381 : "Inaccurate approximation of unit step function at cylindrical Dirichlet region. "// &
382 : "Increase the number of sides (N_SIDES) and/or the base radius. Alternatively, "// &
383 0 : "one can increase DELTA_ALPHA (see the reference manual).")
384 : END IF
385 :
386 92 : CALL pw_pool%give_back_pw(cylinder_pw)
387 92 : DEALLOCATE (cylinder_pw)
388 :
389 92 : IF ((unit_nr .GT. 0) .AND. verbose) WRITE (unit_nr, '(T3,A)') REPEAT('=', 78)
390 :
391 92 : DEALLOCATE (tiles)
392 :
393 : CASE (AA_PLANAR, AA_CUBOIDAL)
394 :
395 30 : CALL aa_dbc_partition(dirichlet_bc%vertices, n_prtn, tiles)
396 30 : n_tiles = SIZE(tiles)
397 30 : dirichlet_bc%n_tiles = n_tiles
398 154 : ALLOCATE (dirichlet_bc%tiles(n_tiles))
399 158 : dirichlet_bc%tiles = tiles
400 30 : IF ((unit_nr .GT. 0) .AND. verbose) WRITE (unit_nr, '(T7,A,I5)') "number of partitions : ", n_tiles
401 :
402 94 : DO k = 1, n_tiles
403 64 : ALLOCATE (dirichlet_bc%tiles(k)%tile%tile_pw)
404 64 : CALL pw_pool%create_pw(dirichlet_bc%tiles(k)%tile%tile_pw)
405 64 : CALL pw_zero(dirichlet_bc%tiles(k)%tile%tile_pw)
406 :
407 64 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
408 0 : WRITE (unit_nr, '(T7,A,I5)') "tile", k
409 0 : DO i = 1, 8
410 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') &
411 0 : " vertex ", i, angstrom*dirichlet_bc%tiles(k)%tile%vertices(:, i)
412 : END DO
413 : END IF
414 :
415 : CALL aa_tile_pw_compute(cell_xtnts, x_locl, y_locl, z_locl, dirichlet_bc%tiles(k)%tile%vertices, &
416 64 : sigma, is_periodic, dirichlet_bc%tiles(k)%tile%tile_pw)
417 8269897 : tile_volume = SUM(dirichlet_bc%tiles(k)%tile%tile_pw%array)
418 64 : CALL pw_pool%pw_grid%para%group%sum(tile_volume)
419 94 : dirichlet_bc%tiles(k)%tile%volume = tile_volume
420 : END DO
421 :
422 30 : IF ((unit_nr .GT. 0) .AND. verbose) WRITE (unit_nr, '(T3,A)') REPEAT('=', 78)
423 :
424 158 : DEALLOCATE (tiles)
425 :
426 : END SELECT
427 :
428 128 : CALL timestop(handle)
429 :
430 256 : END SUBROUTINE dirichlet_bc_partition
431 :
432 : ! **************************************************************************************************
433 : !> \brief Creates an axis-aligned planar Dirichlet region.
434 : !> \param cell_xtnts extents of the simulation cell
435 : !> \param parallel_plane the coordinate plane that the region is parallel to
436 : !> \param x_xtnt the x extent of the planar region
437 : !> \param y_xtnt the y extent of the planar region
438 : !> \param z_xtnt the z extent of the planar region
439 : !> \param thickness the thickness of the region
440 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
441 : !> \param v_D potential imposed at the Dirichlet part of the boundary (gate voltage)
442 : !> \param osc_frac ...
443 : !> \param frequency ...
444 : !> \param phase ...
445 : !> \param dbc_id unique ID for the Dirichlet region
446 : !> \param verbose whether or not to print out the coordinates of the vertices
447 : !> \param dirichlet_bc the dirichlet_bc object to be created
448 : !> \par History
449 : !> 08.2014 created [Hossein Bani-Hashemian]
450 : !> \author Mohammad Hossein Bani-Hashemian
451 : ! **************************************************************************************************
452 24 : SUBROUTINE aa_planar_dbc_setup(cell_xtnts, parallel_plane, x_xtnt, y_xtnt, z_xtnt, &
453 : thickness, sigma, v_D, osc_frac, frequency, phase, dbc_id, verbose, dirichlet_bc)
454 :
455 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
456 : INTEGER, INTENT(IN) :: parallel_plane
457 : REAL(dp), DIMENSION(2), INTENT(IN) :: x_xtnt, y_xtnt, z_xtnt
458 : REAL(dp), INTENT(IN) :: thickness, sigma, v_D, osc_frac, &
459 : frequency, phase
460 : INTEGER, INTENT(IN) :: dbc_id
461 : LOGICAL, INTENT(IN) :: verbose
462 : TYPE(dirichlet_bc_type), INTENT(INOUT), POINTER :: dirichlet_bc
463 :
464 : CHARACTER(LEN=*), PARAMETER :: routineN = 'aa_planar_dbc_setup'
465 : LOGICAL, DIMENSION(6), PARAMETER :: test_forb_xtnts = .TRUE.
466 :
467 : INTEGER :: handle, i, n_forb_xtnts, unit_nr
468 : LOGICAL :: forb_xtnt1, forb_xtnt2, forb_xtnt3, &
469 : forb_xtnt4, forb_xtnt5, forb_xtnt6
470 : REAL(dp) :: xlb, xub, ylb, yub, zlb, zub
471 : TYPE(cp_logger_type), POINTER :: logger
472 :
473 24 : CALL timeset(routineN, handle)
474 :
475 24 : logger => cp_get_default_logger()
476 24 : IF (logger%para_env%is_source()) THEN
477 12 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
478 : ELSE
479 : unit_nr = -1
480 : END IF
481 :
482 24 : xlb = x_xtnt(1); xub = x_xtnt(2)
483 24 : ylb = y_xtnt(1); yub = y_xtnt(2)
484 24 : zlb = z_xtnt(1); zub = z_xtnt(2)
485 :
486 26 : SELECT CASE (parallel_plane)
487 : CASE (xy_plane)
488 2 : zlb = zlb - thickness*0.5_dp
489 2 : zub = zub + thickness*0.5_dp
490 : CASE (xz_plane)
491 2 : ylb = ylb - thickness*0.5_dp
492 2 : yub = yub + thickness*0.5_dp
493 : CASE (yz_plane)
494 20 : xlb = xlb - thickness*0.5_dp
495 24 : xub = xub + thickness*0.5_dp
496 : END SELECT
497 :
498 24 : forb_xtnt1 = xlb .LT. cell_xtnts(1, 1)
499 24 : forb_xtnt2 = xub .GT. cell_xtnts(2, 1)
500 24 : forb_xtnt3 = ylb .LT. cell_xtnts(1, 2)
501 24 : forb_xtnt4 = yub .GT. cell_xtnts(2, 2)
502 24 : forb_xtnt5 = zlb .LT. cell_xtnts(1, 3)
503 24 : forb_xtnt6 = zub .GT. cell_xtnts(2, 3)
504 : n_forb_xtnts = COUNT((/forb_xtnt1, forb_xtnt2, forb_xtnt3, &
505 168 : forb_xtnt4, forb_xtnt5, forb_xtnt6/) .EQV. test_forb_xtnts)
506 24 : IF (n_forb_xtnts .GT. 0) THEN
507 : CALL cp_abort(__LOCATION__, &
508 : "The given extents for the Dirichlet region are outside the range of "// &
509 0 : "the simulation cell.")
510 : END IF
511 :
512 24 : dirichlet_bc%v_D = v_D
513 24 : dirichlet_bc%osc_frac = osc_frac
514 24 : dirichlet_bc%frequency = frequency
515 24 : dirichlet_bc%phase = phase
516 24 : dirichlet_bc%dbc_id = dbc_id
517 24 : dirichlet_bc%dbc_geom = AA_PLANAR
518 24 : dirichlet_bc%smoothing_width = sigma
519 24 : dirichlet_bc%n_tiles = 1
520 :
521 96 : dirichlet_bc%vertices(1:3, 1) = (/xlb, ylb, zlb/)
522 96 : dirichlet_bc%vertices(1:3, 2) = (/xub, ylb, zlb/)
523 96 : dirichlet_bc%vertices(1:3, 3) = (/xub, yub, zlb/)
524 96 : dirichlet_bc%vertices(1:3, 4) = (/xlb, yub, zlb/)
525 96 : dirichlet_bc%vertices(1:3, 5) = (/xlb, yub, zub/)
526 96 : dirichlet_bc%vertices(1:3, 6) = (/xlb, ylb, zub/)
527 96 : dirichlet_bc%vertices(1:3, 7) = (/xub, ylb, zub/)
528 96 : dirichlet_bc%vertices(1:3, 8) = (/xub, yub, zub/)
529 :
530 24 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
531 0 : WRITE (unit_nr, '(T3,A,A)') "======== verbose ", REPEAT('=', 61)
532 0 : DO i = 1, 8
533 0 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') " vertex ", i, angstrom*dirichlet_bc%vertices(:, i)
534 : END DO
535 : END IF
536 :
537 24 : CALL timestop(handle)
538 :
539 24 : END SUBROUTINE aa_planar_dbc_setup
540 :
541 : ! **************************************************************************************************
542 : !> \brief Creates an axis-aligned cuboidal Dirichlet region.
543 : !> \param cell_xtnts extents of the simulation cell
544 : !> \param x_xtnt the x extent of the cuboidal region
545 : !> \param y_xtnt the y extent of the cuboidal region
546 : !> \param z_xtnt the z extent of the cuboidal region
547 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
548 : !> \param v_D potential imposed at the Dirichlet part of the boundary (gate voltage)
549 : !> \param osc_frac ...
550 : !> \param frequency ...
551 : !> \param phase ...
552 : !> \param dbc_id unique ID for the Dirichlet region
553 : !> \param verbose whether or not to print out the coordinates of the vertices
554 : !> \param dirichlet_bc the dirichlet_bc object to be created
555 : !> \par History
556 : !> 12.2014 created [Hossein Bani-Hashemian]
557 : !> \author Mohammad Hossein Bani-Hashemian
558 : ! **************************************************************************************************
559 6 : SUBROUTINE aa_cuboidal_dbc_setup(cell_xtnts, x_xtnt, y_xtnt, z_xtnt, &
560 : sigma, v_D, osc_frac, frequency, phase, dbc_id, verbose, dirichlet_bc)
561 :
562 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
563 : REAL(dp), DIMENSION(2), INTENT(IN) :: x_xtnt, y_xtnt, z_xtnt
564 : REAL(dp), INTENT(IN) :: sigma, v_D, osc_frac, frequency, phase
565 : INTEGER, INTENT(IN) :: dbc_id
566 : LOGICAL, INTENT(IN) :: verbose
567 : TYPE(dirichlet_bc_type), INTENT(INOUT), POINTER :: dirichlet_bc
568 :
569 : CHARACTER(LEN=*), PARAMETER :: routineN = 'aa_cuboidal_dbc_setup'
570 : LOGICAL, DIMENSION(6), PARAMETER :: test_forb_xtnts = .TRUE.
571 :
572 : INTEGER :: handle, i, n_forb_xtnts, unit_nr
573 : LOGICAL :: forb_xtnt1, forb_xtnt2, forb_xtnt3, &
574 : forb_xtnt4, forb_xtnt5, forb_xtnt6
575 : TYPE(cp_logger_type), POINTER :: logger
576 :
577 6 : CALL timeset(routineN, handle)
578 :
579 6 : logger => cp_get_default_logger()
580 6 : IF (logger%para_env%is_source()) THEN
581 3 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
582 : ELSE
583 : unit_nr = -1
584 : END IF
585 :
586 6 : forb_xtnt1 = x_xtnt(1) .LT. cell_xtnts(1, 1)
587 6 : forb_xtnt2 = x_xtnt(2) .GT. cell_xtnts(2, 1)
588 6 : forb_xtnt3 = y_xtnt(1) .LT. cell_xtnts(1, 2)
589 6 : forb_xtnt4 = y_xtnt(2) .GT. cell_xtnts(2, 2)
590 6 : forb_xtnt5 = z_xtnt(1) .LT. cell_xtnts(1, 3)
591 6 : forb_xtnt6 = z_xtnt(2) .GT. cell_xtnts(2, 3)
592 : n_forb_xtnts = COUNT((/forb_xtnt1, forb_xtnt2, forb_xtnt3, &
593 42 : forb_xtnt4, forb_xtnt5, forb_xtnt6/) .EQV. test_forb_xtnts)
594 6 : IF (n_forb_xtnts .GT. 0) THEN
595 : CALL cp_abort(__LOCATION__, &
596 : "The given extents for the Dirichlet region are outside the range of "// &
597 0 : "the simulation cell.")
598 : END IF
599 :
600 6 : dirichlet_bc%v_D = v_D
601 6 : dirichlet_bc%osc_frac = osc_frac
602 6 : dirichlet_bc%frequency = frequency
603 6 : dirichlet_bc%phase = phase
604 6 : dirichlet_bc%dbc_id = dbc_id
605 6 : dirichlet_bc%dbc_geom = AA_CUBOIDAL
606 6 : dirichlet_bc%smoothing_width = sigma
607 6 : dirichlet_bc%n_tiles = 1
608 :
609 24 : dirichlet_bc%vertices(1:3, 1) = (/x_xtnt(1), y_xtnt(1), z_xtnt(1)/)
610 24 : dirichlet_bc%vertices(1:3, 2) = (/x_xtnt(2), y_xtnt(1), z_xtnt(1)/)
611 24 : dirichlet_bc%vertices(1:3, 3) = (/x_xtnt(2), y_xtnt(2), z_xtnt(1)/)
612 24 : dirichlet_bc%vertices(1:3, 4) = (/x_xtnt(1), y_xtnt(2), z_xtnt(1)/)
613 24 : dirichlet_bc%vertices(1:3, 5) = (/x_xtnt(1), y_xtnt(2), z_xtnt(2)/)
614 24 : dirichlet_bc%vertices(1:3, 6) = (/x_xtnt(1), y_xtnt(1), z_xtnt(2)/)
615 24 : dirichlet_bc%vertices(1:3, 7) = (/x_xtnt(2), y_xtnt(1), z_xtnt(2)/)
616 24 : dirichlet_bc%vertices(1:3, 8) = (/x_xtnt(2), y_xtnt(2), z_xtnt(2)/)
617 :
618 6 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
619 0 : WRITE (unit_nr, '(T3,A,A)') "======== verbose ", REPEAT('=', 61)
620 0 : DO i = 1, 8
621 0 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') " vertex ", i, angstrom*dirichlet_bc%vertices(:, i)
622 : END DO
623 : END IF
624 :
625 6 : CALL timestop(handle)
626 :
627 6 : END SUBROUTINE aa_cuboidal_dbc_setup
628 :
629 : ! **************************************************************************************************
630 : !> \brief Creates an arbitrary (rectangular-shaped) planar Dirichlet region given
631 : !> the coordinates of its vertices.
632 : !> \param cell_xtnts extents of the simulation cell
633 : !> \param A coordinates of the vertex A
634 : !> \param B coordinates of the vertex B
635 : !> \param C coordinates of the vertex C
636 : !> \param thickness the thickness of the region
637 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
638 : !> \param v_D potential imposed at the Dirichlet part of the boundary (gate voltage)
639 : !> \param osc_frac ...
640 : !> \param frequency ...
641 : !> \param phase ...
642 : !> \param dbc_id unique ID for the Dirichlet region
643 : !> \param verbose whether or not to print out the coordinates of the vertices
644 : !> \param dirichlet_bc the dirichlet_bc object to be created
645 : !> \par History
646 : !> 08.2014 created [Hossein Bani-Hashemian]
647 : !> \author Mohammad Hossein Bani-Hashemian
648 : ! **************************************************************************************************
649 6 : SUBROUTINE arbitrary_planar_dbc_setup(cell_xtnts, A, B, C, thickness, &
650 : sigma, v_D, osc_frac, frequency, phase, dbc_id, verbose, dirichlet_bc)
651 :
652 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
653 : REAL(dp), DIMENSION(3), INTENT(IN) :: A, B, C
654 : REAL(dp), INTENT(IN) :: thickness, sigma, v_D, osc_frac, &
655 : frequency, phase
656 : INTEGER, INTENT(IN) :: dbc_id
657 : LOGICAL, INTENT(IN) :: verbose
658 : TYPE(dirichlet_bc_type), INTENT(INOUT), POINTER :: dirichlet_bc
659 :
660 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arbitrary_planar_dbc_setup'
661 :
662 : INTEGER :: handle, i, unit_nr
663 : LOGICAL :: A_is_inside, are_coplanar, &
664 : are_orthogonal, B_is_inside, &
665 : C_is_inside, D_is_inside, is_rectangle
666 : REAL(dp) :: dist1, dist2, dist3, dist4
667 : REAL(dp), DIMENSION(3) :: AB, AC, AD, BC, cm, D, normal_vector, &
668 : unit_normal
669 : TYPE(cp_logger_type), POINTER :: logger
670 :
671 6 : CALL timeset(routineN, handle)
672 :
673 6 : logger => cp_get_default_logger()
674 6 : IF (logger%para_env%is_source()) THEN
675 3 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
676 : ELSE
677 : unit_nr = -1
678 : END IF
679 :
680 24 : D = A + (C - B)
681 78 : AB = B - A; AC = C - A; AD = D - A; BC = C - B
682 60 : are_orthogonal = ABS(DOT_PRODUCT(AB, BC)/(SQRT(SUM(AB**2))*SQRT(SUM(BC**2)))) .LE. small_value
683 6 : IF (.NOT. are_orthogonal) THEN
684 : CALL cp_abort(__LOCATION__, "The given vertices for defining a "// &
685 0 : "planar Dirichlet region do not form orthogonal edges.")
686 : END IF
687 :
688 6 : normal_vector = vector_product(AB, AC)
689 42 : unit_normal = normal_vector/SQRT(SUM(normal_vector**2))
690 :
691 : A_is_inside = (A(1) .GT. cell_xtnts(1, 1) .AND. A(1) .LT. cell_xtnts(2, 1)) .AND. &
692 : (A(2) .GT. cell_xtnts(1, 2) .AND. A(2) .LT. cell_xtnts(2, 2)) .AND. &
693 6 : (A(3) .GT. cell_xtnts(1, 3) .AND. A(3) .LT. cell_xtnts(2, 3))
694 : B_is_inside = (B(1) .GT. cell_xtnts(1, 1) .AND. B(1) .LT. cell_xtnts(2, 1)) .AND. &
695 : (B(2) .GT. cell_xtnts(1, 2) .AND. B(2) .LT. cell_xtnts(2, 2)) .AND. &
696 6 : (B(3) .GT. cell_xtnts(1, 3) .AND. B(3) .LT. cell_xtnts(2, 3))
697 : C_is_inside = (C(1) .GT. cell_xtnts(1, 1) .AND. C(1) .LT. cell_xtnts(2, 1)) .AND. &
698 : (C(2) .GT. cell_xtnts(1, 2) .AND. C(2) .LT. cell_xtnts(2, 2)) .AND. &
699 6 : (C(3) .GT. cell_xtnts(1, 3) .AND. C(3) .LT. cell_xtnts(2, 3))
700 : D_is_inside = (D(1) .GT. cell_xtnts(1, 1) .AND. D(1) .LT. cell_xtnts(2, 1)) .AND. &
701 : (D(2) .GT. cell_xtnts(1, 2) .AND. D(2) .LT. cell_xtnts(2, 2)) .AND. &
702 6 : (D(3) .GT. cell_xtnts(1, 3) .AND. D(3) .LT. cell_xtnts(2, 3))
703 6 : IF (.NOT. (A_is_inside .AND. B_is_inside .AND. C_is_inside .AND. D_is_inside)) THEN
704 : CALL cp_abort(__LOCATION__, &
705 : "At least one of the given vertices for defining a planar Dirichlet "// &
706 0 : "region is outside the simulation box.")
707 : END IF
708 :
709 24 : are_coplanar = ABS(DOT_PRODUCT(vector_product(AB, AC), AD)) .LE. small_value
710 6 : IF (.NOT. are_coplanar) THEN
711 0 : CPABORT("The given vertices for defining a planar Dirichlet region are not coplanar.")
712 : END IF
713 :
714 24 : cm = (A + B + C + D)/4.0_dp
715 24 : dist1 = SUM((A - cm)**2)
716 24 : dist2 = SUM((B - cm)**2)
717 24 : dist3 = SUM((C - cm)**2)
718 24 : dist4 = SUM((D - cm)**2)
719 : is_rectangle = (ABS(dist1 - dist2) .LE. small_value) .AND. &
720 : (ABS(dist1 - dist3) .LE. small_value) .AND. &
721 6 : (ABS(dist1 - dist4) .LE. small_value)
722 : IF (.NOT. is_rectangle) THEN
723 : CALL cp_abort(__LOCATION__, "The given vertices for defining "// &
724 0 : "a planar Dirichlet region do not form a rectangle.")
725 : END IF
726 :
727 6 : dirichlet_bc%v_D = v_D
728 6 : dirichlet_bc%osc_frac = osc_frac
729 6 : dirichlet_bc%frequency = frequency
730 6 : dirichlet_bc%phase = phase
731 6 : dirichlet_bc%dbc_id = dbc_id
732 6 : dirichlet_bc%dbc_geom = PLANAR
733 6 : dirichlet_bc%smoothing_width = sigma
734 6 : dirichlet_bc%n_tiles = 1
735 :
736 24 : dirichlet_bc%vertices(1:3, 1) = A - 0.5_dp*thickness*unit_normal
737 24 : dirichlet_bc%vertices(1:3, 2) = B - 0.5_dp*thickness*unit_normal
738 24 : dirichlet_bc%vertices(1:3, 3) = C - 0.5_dp*thickness*unit_normal
739 24 : dirichlet_bc%vertices(1:3, 4) = D - 0.5_dp*thickness*unit_normal
740 24 : dirichlet_bc%vertices(1:3, 5) = D + 0.5_dp*thickness*unit_normal
741 24 : dirichlet_bc%vertices(1:3, 6) = A + 0.5_dp*thickness*unit_normal
742 24 : dirichlet_bc%vertices(1:3, 7) = B + 0.5_dp*thickness*unit_normal
743 24 : dirichlet_bc%vertices(1:3, 8) = C + 0.5_dp*thickness*unit_normal
744 :
745 6 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
746 0 : WRITE (unit_nr, '(T3,A,A)') "======== verbose ", REPEAT('=', 61)
747 0 : DO i = 1, 8
748 0 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') " vertex ", i, angstrom*dirichlet_bc%vertices(:, i)
749 : END DO
750 : END IF
751 :
752 6 : CALL timestop(handle)
753 :
754 6 : END SUBROUTINE arbitrary_planar_dbc_setup
755 :
756 : ! **************************************************************************************************
757 : !> \brief Creates an x-axis-aligned cylindrical Dirichlet region. The cylindrical
758 : !> shape is approximated by an n-gonal (circumscribed or inscribed) uniform prism-
759 : !> like object. The circular base is approximated by a polygon. A second polygon is
760 : !> then created by rotating the first one by delta_alpha radians. Let's name the
761 : !> vertices of the first and the second polygon as v1, v2, v3, ... vn-1, vn and
762 : !> w1, w2, w3, ... wn-1, wn, respectively. Then w1v2, w2v3, ... wn-1vn, wnv1 form
763 : !> the edges of the cross-section of the approximating object. This way the dbcs
764 : !> do not share any edge.
765 : !> \param pw_pool pool of plane wave grid
766 : !> \param cell_xtnts extents of the simulation cell
767 : !> \param x_locl x grid vector of the simulation box local to this process
768 : !> \param y_locl y grid vector of the simulation box local to this process
769 : !> \param z_locl z grid vector of the simulation box local to this process
770 : !> \param apx_type the type of the n-gonal prism approximating the cylinder
771 : !> \param parallel_axis the coordinate axis that the cylindrical region extends along
772 : !> \param xtnt the x extent of the cylindrical region along its central axis
773 : !> \param base_center the y and z coordinates of the cylinder's base
774 : !> \param base_radius the radius of the cylinder's base
775 : !> \param thickness the thickness of the region
776 : !> \param delta_alpha ...
777 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
778 : !> \param v_D potential imposed at the Dirichlet part of the boundary (gate voltage)
779 : !> \param osc_frac ...
780 : !> \param frequency ...
781 : !> \param phase ...
782 : !> \param n_prtn number of partitions along the edges of the faces of the prism
783 : !> \param is_periodic whether or not the tile is periodic with a periodicity of one unit cell
784 : !> \param verbose whether or not to print out the coordinates of the vertices
785 : !> \param dbcs the x-axis-aligned cylindrical gate region to be created
786 : !> \par History
787 : !> 08.2014 created [Hossein Bani-Hashemian]
788 : !> \author Mohammad Hossein Bani-Hashemian
789 : ! **************************************************************************************************
790 12 : SUBROUTINE aa_cylindrical_dbc_setup(pw_pool, cell_xtnts, x_locl, y_locl, z_locl, apx_type, parallel_axis, &
791 : xtnt, base_center, base_radius, thickness, delta_alpha, &
792 12 : sigma, v_D, osc_frac, frequency, phase, n_prtn, is_periodic, verbose, dbcs)
793 :
794 : TYPE(pw_pool_type), POINTER :: pw_pool
795 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
796 : REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(IN) :: x_locl, y_locl, z_locl
797 : INTEGER, INTENT(IN), OPTIONAL :: apx_type
798 : INTEGER, INTENT(IN) :: parallel_axis
799 : REAL(dp), DIMENSION(2), INTENT(IN) :: xtnt, base_center
800 : REAL(dp), INTENT(IN) :: base_radius, thickness, delta_alpha, &
801 : sigma, v_D, osc_frac, frequency, phase
802 : INTEGER, DIMENSION(3), INTENT(IN) :: n_prtn
803 : LOGICAL, INTENT(IN) :: is_periodic, verbose
804 : TYPE(dirichlet_bc_p_type), DIMENSION(:), &
805 : INTENT(INOUT) :: dbcs
806 :
807 : CHARACTER(LEN=*), PARAMETER :: routineN = 'aa_cylindrical_dbc_setup'
808 :
809 : INTEGER :: handle, i, intern_apx_type, j, n_dbcs, &
810 : unit_nr
811 : LOGICAL :: forb_xtnt1, forb_xtnt2, forb_xtnt3, &
812 : forb_xtnt4
813 : REAL(dp) :: cntrlaxis_lb, cntrlaxis_ub, h, Lx, Ly, &
814 : Lz, theta
815 : REAL(dp), DIMENSION(3) :: A, B, C, D, normal_vec, unit_normal
816 : TYPE(cp_logger_type), POINTER :: logger
817 24 : REAL(dp), DIMENSION(SIZE(dbcs)+1) :: alpha, alpha_rotd, xlb, xub, ylb, yub, &
818 24 : zlb, zub
819 :
820 12 : CALL timeset(routineN, handle)
821 :
822 12 : logger => cp_get_default_logger()
823 12 : IF (logger%para_env%is_source()) THEN
824 6 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
825 : ELSE
826 : unit_nr = -1
827 : END IF
828 :
829 12 : Lx = cell_xtnts(2, 1) - cell_xtnts(1, 1)
830 12 : Ly = cell_xtnts(2, 2) - cell_xtnts(1, 2)
831 12 : Lz = cell_xtnts(2, 3) - cell_xtnts(1, 3)
832 :
833 20 : SELECT CASE (parallel_axis)
834 : CASE (x_axis)
835 8 : IF (xtnt(1) .LT. cell_xtnts(1, 1) .OR. xtnt(2) .GT. cell_xtnts(2, 1)) THEN
836 : CALL cp_abort(__LOCATION__, &
837 : "The length of the cylindrical Dirichlet region is larger than the "// &
838 0 : "x range of the simulation cell.")
839 : END IF
840 8 : forb_xtnt1 = base_center(1) - base_radius .LT. cell_xtnts(1, 2)
841 8 : forb_xtnt2 = base_center(1) + base_radius .GT. cell_xtnts(2, 2)
842 8 : forb_xtnt3 = base_center(2) - base_radius .LT. cell_xtnts(1, 3)
843 8 : forb_xtnt4 = base_center(2) + base_radius .GT. cell_xtnts(2, 3)
844 8 : IF (forb_xtnt1 .OR. forb_xtnt2 .OR. forb_xtnt3 .OR. forb_xtnt4) THEN
845 0 : CPABORT("The cylinder does not fit entirely inside the simulation cell.")
846 : END IF
847 : CASE (y_axis)
848 2 : IF (xtnt(1) .LT. cell_xtnts(1, 2) .OR. xtnt(2) .GT. cell_xtnts(2, 2)) THEN
849 : CALL cp_abort(__LOCATION__, &
850 : "The length of the cylindrical Dirichlet region is larger than the "// &
851 0 : "y range of the simulation cell.")
852 : END IF
853 2 : forb_xtnt1 = base_center(1) - base_radius .LT. cell_xtnts(1, 1)
854 2 : forb_xtnt2 = base_center(1) + base_radius .GT. cell_xtnts(2, 1)
855 2 : forb_xtnt3 = base_center(2) - base_radius .LT. cell_xtnts(1, 3)
856 2 : forb_xtnt4 = base_center(2) + base_radius .GT. cell_xtnts(2, 3)
857 2 : IF (forb_xtnt1 .OR. forb_xtnt2 .OR. forb_xtnt3 .OR. forb_xtnt4) THEN
858 0 : CPABORT("The cylinder does not fit entirely inside the simulation cell.")
859 : END IF
860 : CASE (z_axis)
861 2 : IF (xtnt(1) .LT. cell_xtnts(1, 3) .OR. xtnt(2) .GT. cell_xtnts(2, 3)) THEN
862 : CALL cp_abort(__LOCATION__, &
863 : "The length of the cylindrical Dirichlet region is larger than the "// &
864 0 : "z range of the simulation cell.")
865 : END IF
866 2 : forb_xtnt1 = base_center(1) - base_radius .LT. cell_xtnts(1, 1)
867 2 : forb_xtnt2 = base_center(1) + base_radius .GT. cell_xtnts(2, 1)
868 2 : forb_xtnt3 = base_center(2) - base_radius .LT. cell_xtnts(1, 2)
869 2 : forb_xtnt4 = base_center(2) + base_radius .GT. cell_xtnts(2, 2)
870 14 : IF (forb_xtnt1 .OR. forb_xtnt2 .OR. forb_xtnt3 .OR. forb_xtnt4) THEN
871 0 : CPABORT("The cylinder does not fit entirely inside the simulation cell.")
872 : END IF
873 : END SELECT
874 :
875 12 : intern_apx_type = CIRCUMSCRIBED
876 12 : IF (PRESENT(apx_type)) intern_apx_type = apx_type
877 :
878 12 : n_dbcs = SIZE(dbcs)
879 :
880 12 : cntrlaxis_lb = xtnt(1)
881 12 : cntrlaxis_ub = xtnt(2)
882 :
883 12 : theta = twopi/n_dbcs
884 :
885 12 : IF (intern_apx_type .EQ. INSCRIBED) THEN
886 6 : h = base_radius ! inscribed uniform prism
887 6 : ELSE IF (intern_apx_type .EQ. CIRCUMSCRIBED) THEN
888 6 : h = base_radius/COS(0.5*theta) ! circumscribed uniform prism
889 : ELSE
890 0 : CPABORT("Unknown approximation type for cylinder.")
891 : END IF
892 8 : SELECT CASE (parallel_axis)
893 : CASE (x_axis)
894 32 : IF (h .GT. MINVAL((/Ly, Lz/))) THEN
895 0 : CPABORT("Reduce the base radius!")
896 : END IF
897 : CASE (y_axis)
898 8 : IF (h .GT. MINVAL((/Lx, Lz/))) THEN
899 0 : CPABORT("Reduce the base radius!")
900 : END IF
901 : CASE (z_axis)
902 18 : IF (h .GT. MINVAL((/Lx, Ly/))) THEN
903 0 : CPABORT("Reduce the base radius!")
904 : END IF
905 : END SELECT
906 :
907 12 : alpha = linspace(0.0_dp, 2*pi, n_dbcs + 1)
908 116 : alpha_rotd = alpha + delta_alpha;
909 8 : SELECT CASE (parallel_axis)
910 : CASE (x_axis)
911 72 : DO j = 1, n_dbcs
912 64 : ylb(j) = base_center(1) + h*SIN(alpha(j))
913 64 : zlb(j) = base_center(2) + h*COS(alpha(j))
914 64 : yub(j) = base_center(1) + h*SIN(alpha_rotd(j))
915 72 : zub(j) = base_center(2) + h*COS(alpha_rotd(j))
916 : END DO
917 8 : ylb(n_dbcs + 1) = ylb(1)
918 8 : yub(n_dbcs + 1) = yub(1)
919 8 : zlb(n_dbcs + 1) = zlb(1)
920 8 : zub(n_dbcs + 1) = zub(1)
921 72 : DO j = 1, n_dbcs
922 2112 : ALLOCATE (dbcs(j)%dirichlet_bc)
923 64 : dbcs(j)%dirichlet_bc%dbc_geom = CYLINDRICAL
924 64 : dbcs(j)%dirichlet_bc%v_D = v_D
925 64 : dbcs(j)%dirichlet_bc%osc_frac = osc_frac
926 64 : dbcs(j)%dirichlet_bc%frequency = frequency
927 64 : dbcs(j)%dirichlet_bc%phase = phase
928 64 : dbcs(j)%dirichlet_bc%dbc_id = CYLINDRICAL + j
929 64 : dbcs(j)%dirichlet_bc%smoothing_width = sigma
930 :
931 256 : A = (/cntrlaxis_lb, yub(j), zub(j)/)
932 256 : B = (/cntrlaxis_lb, ylb(j + 1), zlb(j + 1)/)
933 256 : C = (/cntrlaxis_ub, ylb(j + 1), zlb(j + 1)/)
934 256 : D = (/cntrlaxis_ub, yub(j), zub(j)/)
935 448 : normal_vec = vector_product((A - C), (D - B))
936 448 : unit_normal = normal_vec/SQRT(SUM(normal_vec**2))
937 :
938 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 1) = A
939 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 2) = B
940 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 3) = C
941 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 4) = D
942 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 5) = D + thickness*unit_normal
943 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 6) = A + thickness*unit_normal
944 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 7) = B + thickness*unit_normal
945 256 : dbcs(j)%dirichlet_bc%vertices(1:3, 8) = C + thickness*unit_normal
946 :
947 64 : dbcs(j)%dirichlet_bc%n_tiles = 1
948 :
949 64 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
950 0 : WRITE (unit_nr, '(T3,A,A)') "======== verbose ", REPEAT('=', 61)
951 0 : WRITE (unit_nr, '(T7,A,I5,T20,A,I5,A)') "edge", j, "of the", n_dbcs, &
952 0 : "-gonal prism approximating the cylinder"
953 0 : DO i = 1, 8
954 0 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') " vertex ", i, &
955 0 : angstrom*dbcs(j)%dirichlet_bc%vertices(:, i)
956 : END DO
957 : END IF
958 :
959 : CALL dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
960 72 : x_locl, y_locl, z_locl, is_periodic, verbose, dbcs(j)%dirichlet_bc)
961 : END DO
962 : CASE (y_axis)
963 16 : DO j = 1, n_dbcs
964 14 : xlb(j) = base_center(1) + h*SIN(alpha(j))
965 14 : zlb(j) = base_center(2) + h*COS(alpha(j))
966 14 : xub(j) = base_center(1) + h*SIN(alpha_rotd(j))
967 16 : zub(j) = base_center(2) + h*COS(alpha_rotd(j))
968 : END DO
969 2 : xlb(n_dbcs + 1) = xlb(1)
970 2 : xub(n_dbcs + 1) = xub(1)
971 2 : zlb(n_dbcs + 1) = zlb(1)
972 2 : zub(n_dbcs + 1) = zub(1)
973 16 : DO j = 1, n_dbcs
974 462 : ALLOCATE (dbcs(j)%dirichlet_bc)
975 14 : dbcs(j)%dirichlet_bc%dbc_geom = CYLINDRICAL
976 14 : dbcs(j)%dirichlet_bc%v_D = v_D
977 14 : dbcs(j)%dirichlet_bc%osc_frac = osc_frac
978 14 : dbcs(j)%dirichlet_bc%frequency = frequency
979 14 : dbcs(j)%dirichlet_bc%phase = phase
980 14 : dbcs(j)%dirichlet_bc%dbc_id = CYLINDRICAL + j
981 14 : dbcs(j)%dirichlet_bc%smoothing_width = sigma
982 :
983 56 : A = (/xub(j), cntrlaxis_lb, zub(j)/)
984 56 : B = (/xlb(j + 1), cntrlaxis_lb, zlb(j + 1)/)
985 56 : C = (/xlb(j + 1), cntrlaxis_ub, zlb(j + 1)/)
986 56 : D = (/xub(j), cntrlaxis_ub, zub(j)/)
987 98 : normal_vec = vector_product((A - C), (D - B))
988 98 : unit_normal = normal_vec/SQRT(SUM(normal_vec**2))
989 :
990 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 1) = A
991 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 2) = B
992 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 3) = C
993 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 4) = D
994 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 5) = D + thickness*unit_normal
995 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 6) = A + thickness*unit_normal
996 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 7) = B + thickness*unit_normal
997 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 8) = C + thickness*unit_normal
998 :
999 14 : dbcs(j)%dirichlet_bc%n_tiles = 1
1000 :
1001 14 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
1002 0 : WRITE (unit_nr, '(T3,A,A)') "======== verbose ", REPEAT('=', 61)
1003 0 : WRITE (unit_nr, '(T7,A,I5,T20,A,I5,A)') "edge", j, "of the", n_dbcs, &
1004 0 : "-gonal prism approximating the cylinder"
1005 0 : DO i = 1, 8
1006 0 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') " vertex ", i, &
1007 0 : angstrom*dbcs(j)%dirichlet_bc%vertices(:, i)
1008 : END DO
1009 : END IF
1010 :
1011 : CALL dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
1012 16 : x_locl, y_locl, z_locl, is_periodic, verbose, dbcs(j)%dirichlet_bc)
1013 : END DO
1014 : CASE (z_axis)
1015 16 : DO j = 1, n_dbcs
1016 14 : xlb(j) = base_center(1) + h*SIN(alpha(j))
1017 14 : ylb(j) = base_center(2) + h*COS(alpha(j))
1018 14 : xub(j) = base_center(1) + h*SIN(alpha_rotd(j))
1019 16 : yub(j) = base_center(2) + h*COS(alpha_rotd(j))
1020 : END DO
1021 2 : xlb(n_dbcs + 1) = xlb(1)
1022 2 : xub(n_dbcs + 1) = xub(1)
1023 2 : ylb(n_dbcs + 1) = ylb(1)
1024 2 : yub(n_dbcs + 1) = yub(1)
1025 28 : DO j = 1, n_dbcs
1026 462 : ALLOCATE (dbcs(j)%dirichlet_bc)
1027 14 : dbcs(j)%dirichlet_bc%dbc_geom = CYLINDRICAL
1028 14 : dbcs(j)%dirichlet_bc%v_D = v_D
1029 14 : dbcs(j)%dirichlet_bc%osc_frac = osc_frac
1030 14 : dbcs(j)%dirichlet_bc%frequency = frequency
1031 14 : dbcs(j)%dirichlet_bc%phase = phase
1032 14 : dbcs(j)%dirichlet_bc%dbc_id = CYLINDRICAL + j
1033 14 : dbcs(j)%dirichlet_bc%smoothing_width = sigma
1034 :
1035 56 : A = (/xub(j), yub(j), cntrlaxis_lb/)
1036 56 : B = (/xlb(j + 1), ylb(j + 1), cntrlaxis_lb/)
1037 56 : C = (/xlb(j + 1), ylb(j + 1), cntrlaxis_ub/)
1038 56 : D = (/xub(j), yub(j), cntrlaxis_ub/)
1039 98 : normal_vec = vector_product((A - C), (D - B))
1040 98 : unit_normal = normal_vec/SQRT(SUM(normal_vec**2))
1041 :
1042 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 1) = A
1043 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 2) = B
1044 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 3) = C
1045 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 4) = D
1046 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 5) = D + thickness*unit_normal
1047 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 6) = A + thickness*unit_normal
1048 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 7) = B + thickness*unit_normal
1049 56 : dbcs(j)%dirichlet_bc%vertices(1:3, 8) = C + thickness*unit_normal
1050 :
1051 14 : dbcs(j)%dirichlet_bc%n_tiles = 1
1052 :
1053 14 : IF ((unit_nr .GT. 0) .AND. verbose) THEN
1054 0 : WRITE (unit_nr, '(T3,A,A)') "======== verbose ", REPEAT('=', 61)
1055 0 : WRITE (unit_nr, '(T7,A,I5,T20,A,I5,A)') "edge", j, "of the", n_dbcs, &
1056 0 : "-gonal prism approximating the cylinder"
1057 0 : DO i = 1, 8
1058 0 : WRITE (unit_nr, '(T10,A,I1,3F10.3)') " vertex ", i, &
1059 0 : angstrom*dbcs(j)%dirichlet_bc%vertices(:, i)
1060 : END DO
1061 : END IF
1062 :
1063 : CALL dirichlet_bc_partition(sigma, n_prtn, pw_pool, cell_xtnts, &
1064 16 : x_locl, y_locl, z_locl, is_periodic, verbose, dbcs(j)%dirichlet_bc)
1065 : END DO
1066 : END SELECT
1067 :
1068 12 : CALL timestop(handle)
1069 :
1070 12 : END SUBROUTINE aa_cylindrical_dbc_setup
1071 :
1072 : ! **************************************************************************************************
1073 : !> \brief Creteas an evenly-spaced 1D array between two values
1074 : !> \param a starting value
1075 : !> \param b end value
1076 : !> \param N number of evenly-spaced points between a and b
1077 : !> \return array containg N evenly-spaced points between a and b
1078 : !> \par History
1079 : !> 07.2014 created [Hossein Bani-Hashemian]
1080 : !> \author Mohammad Hossein Bani-Hashemian
1081 : ! **************************************************************************************************
1082 12 : FUNCTION linspace(a, b, N) RESULT(arr)
1083 :
1084 : REAL(dp), INTENT(IN) :: a, b
1085 : INTEGER, INTENT(IN) :: N
1086 : REAL(dp), DIMENSION(N) :: arr
1087 :
1088 : INTEGER :: i
1089 : REAL(dp) :: dx
1090 :
1091 12 : dx = (b - a)/(N - 1)
1092 232 : arr = (/(a + (i - 1)*dx, i=1, N)/)
1093 :
1094 12 : END FUNCTION linspace
1095 :
1096 : ! **************************************************************************************************
1097 : !> \brief rotates and translates a cuboid
1098 : !> \param cuboid_vtx vertices of the cuboid
1099 : !> \param Rmat rotation matrix
1100 : !> \param Tpnt translation vector (translates the origin to the center of the cuboid)
1101 : !> \param cuboid_transfd_vtx vertices of the transformed cuboid
1102 : !> \par History
1103 : !> 11.2015 created [Hossein Bani-Hashemian]
1104 : !> \author Mohammad Hossein Bani-Hashemian
1105 : ! **************************************************************************************************
1106 160 : SUBROUTINE rotate_translate_cuboid(cuboid_vtx, Rmat, Tpnt, cuboid_transfd_vtx)
1107 :
1108 : REAL(dp), DIMENSION(3, 8), INTENT(IN) :: cuboid_vtx
1109 : REAL(dp), DIMENSION(3, 3), INTENT(OUT) :: Rmat
1110 : REAL(dp), DIMENSION(3), INTENT(OUT) :: Tpnt
1111 : REAL(dp), DIMENSION(3, 8), INTENT(OUT) :: cuboid_transfd_vtx
1112 :
1113 : CHARACTER(LEN=*), PARAMETER :: routineN = 'rotate_translate_cuboid'
1114 :
1115 : INTEGER :: handle
1116 : REAL(dp), DIMENSION(3) :: A, A2, AA2, AB, AD, B, B2, C, C2, D, D2, &
1117 : e1_locl, e2_locl, e3_locl
1118 :
1119 160 : CALL timeset(routineN, handle)
1120 :
1121 160 : Rmat = 0.0_dp
1122 :
1123 1120 : A = cuboid_vtx(1:3, 1); A2 = cuboid_vtx(1:3, 6)
1124 1120 : B = cuboid_vtx(1:3, 2); B2 = cuboid_vtx(1:3, 7)
1125 1120 : C = cuboid_vtx(1:3, 3); C2 = cuboid_vtx(1:3, 8)
1126 1120 : D = cuboid_vtx(1:3, 4); D2 = cuboid_vtx(1:3, 5)
1127 :
1128 640 : Tpnt = (A + C2)/2.0_dp
1129 :
1130 640 : AB = B - A
1131 640 : AD = D - A
1132 640 : AA2 = A2 - A
1133 :
1134 : ! unit vectors generating the local coordinate system
1135 1120 : e1_locl = AB/SQRT(SUM(AB**2))
1136 1120 : e2_locl = AD/SQRT(SUM(AD**2))
1137 1120 : e3_locl = AA2/SQRT(SUM(AA2**2))
1138 : ! rotation matrix
1139 640 : Rmat(1:3, 1) = e1_locl
1140 640 : Rmat(1:3, 2) = e2_locl
1141 640 : Rmat(1:3, 3) = e3_locl
1142 :
1143 160 : cuboid_transfd_vtx(1:3, 1) = rotate_translate_vector(Rmat, Tpnt, BWROT, A)
1144 160 : cuboid_transfd_vtx(1:3, 2) = rotate_translate_vector(Rmat, Tpnt, BWROT, B)
1145 160 : cuboid_transfd_vtx(1:3, 3) = rotate_translate_vector(Rmat, Tpnt, BWROT, C)
1146 160 : cuboid_transfd_vtx(1:3, 4) = rotate_translate_vector(Rmat, Tpnt, BWROT, D)
1147 160 : cuboid_transfd_vtx(1:3, 5) = rotate_translate_vector(Rmat, Tpnt, BWROT, D2)
1148 160 : cuboid_transfd_vtx(1:3, 6) = rotate_translate_vector(Rmat, Tpnt, BWROT, A2)
1149 160 : cuboid_transfd_vtx(1:3, 7) = rotate_translate_vector(Rmat, Tpnt, BWROT, B2)
1150 160 : cuboid_transfd_vtx(1:3, 8) = rotate_translate_vector(Rmat, Tpnt, BWROT, C2)
1151 :
1152 160 : CALL timestop(handle)
1153 :
1154 160 : END SUBROUTINE rotate_translate_cuboid
1155 :
1156 : ! **************************************************************************************************
1157 : !> \brief transforms a position vector according to a given rotation matrix and a
1158 : !> translation vector
1159 : !> \param Rmat rotation matrix
1160 : !> \param Tp image of the origin under the translation
1161 : !> \param direction forward or backward transformation
1162 : !> \param vec input vector
1163 : !> \return transformed vector
1164 : !> \par History
1165 : !> 11.2015 created [Hossein Bani-Hashemian]
1166 : !> \author Mohammad Hossein Bani-Hashemian
1167 : ! **************************************************************************************************
1168 15291164 : FUNCTION rotate_translate_vector(Rmat, Tp, direction, vec) RESULT(vec_transfd)
1169 : REAL(dp), DIMENSION(3, 3), INTENT(IN) :: Rmat
1170 : REAL(dp), DIMENSION(3), INTENT(IN) :: Tp
1171 : INTEGER, INTENT(IN) :: direction
1172 : REAL(dp), DIMENSION(3), INTENT(IN) :: vec
1173 : REAL(dp), DIMENSION(3) :: vec_transfd
1174 :
1175 : REAL(dp), DIMENSION(3) :: Tpoint, vec_tmp
1176 : REAL(dp), DIMENSION(3, 3) :: Rmat_inv
1177 :
1178 15291164 : Tpoint = 0.0_dp
1179 :
1180 15291164 : IF (direction .EQ. FWROT) THEN
1181 0 : vec_tmp = MATMUL(Rmat, vec)
1182 0 : vec_transfd = vec_tmp + Tp
1183 15291164 : ELSEIF (direction .EQ. BWROT) THEN
1184 15291164 : Rmat_inv = inv_3x3(Rmat)
1185 15291164 : Tpoint(1) = Rmat_inv(1, 1)*Tp(1) + Rmat_inv(1, 2)*Tp(2) + Rmat_inv(1, 3)*Tp(3)
1186 15291164 : Tpoint(2) = Rmat_inv(2, 1)*Tp(1) + Rmat_inv(2, 2)*Tp(2) + Rmat_inv(2, 3)*Tp(3)
1187 15291164 : Tpoint(3) = Rmat_inv(3, 1)*Tp(1) + Rmat_inv(3, 2)*Tp(2) + Rmat_inv(3, 3)*Tp(3)
1188 198785132 : vec_tmp = MATMUL(Rmat_inv, vec)
1189 61164656 : vec_transfd = vec_tmp - Tpoint
1190 : END IF
1191 :
1192 15291164 : END FUNCTION rotate_translate_vector
1193 :
1194 : ! **************************************************************************************************
1195 : !> \brief Partitions an axis-aligned cuboid into tiles.
1196 : !> \param dbc_vertices vertices of the axis-aligned Dirichlet region to be partitioned
1197 : !> \param n_prtn vector of size 3 specifying the number of times that the x, y and
1198 : !> z interval (defining the region) should be partitioned into
1199 : !> \param tiles the obtained tiles
1200 : !> \par History
1201 : !> 10.2015 created [Hossein Bani-Hashemian]
1202 : !> \author Mohammad Hossein Bani-Hashemian
1203 : ! **************************************************************************************************
1204 30 : SUBROUTINE aa_dbc_partition(dbc_vertices, n_prtn, tiles)
1205 :
1206 : REAL(dp), DIMENSION(3, 8), INTENT(IN) :: dbc_vertices
1207 : INTEGER, DIMENSION(3), INTENT(IN) :: n_prtn
1208 : TYPE(tile_p_type), DIMENSION(:), INTENT(OUT), &
1209 : POINTER :: tiles
1210 :
1211 : CHARACTER(LEN=*), PARAMETER :: routineN = 'aa_dbc_partition'
1212 :
1213 : INTEGER :: handle, i, ii, jj, k, kk
1214 : REAL(dp) :: step
1215 30 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: xprtn_lb, xprtn_ub, yprtn_lb, yprtn_ub, &
1216 30 : zprtn_lb, zprtn_ub
1217 : REAL(dp), DIMENSION(2) :: x_xtnt, y_xtnt, z_xtnt
1218 :
1219 30 : CALL timeset(routineN, handle)
1220 :
1221 : ! vertices are labeled as:
1222 : ! 6-------5 A2------D2
1223 : ! /| /| /| /|
1224 : ! 7-|-----8 | B2-|----C2 |
1225 : ! | 1-----|-4 or | A-----|-D
1226 : ! |/ |/ |/ |/
1227 : ! 2-------3 B-------C
1228 :
1229 120 : ALLOCATE (xprtn_lb(n_prtn(1)), xprtn_ub(n_prtn(1)))
1230 120 : ALLOCATE (yprtn_lb(n_prtn(2)), yprtn_ub(n_prtn(2)))
1231 120 : ALLOCATE (zprtn_lb(n_prtn(3)), zprtn_ub(n_prtn(3)))
1232 :
1233 : ! find the extents of the cuboid in all three directions
1234 600 : x_xtnt(1) = MINVAL(dbc_vertices(1, :)); x_xtnt(2) = MAXVAL(dbc_vertices(1, :))
1235 600 : y_xtnt(1) = MINVAL(dbc_vertices(2, :)); y_xtnt(2) = MAXVAL(dbc_vertices(2, :))
1236 600 : z_xtnt(1) = MINVAL(dbc_vertices(3, :)); z_xtnt(2) = MAXVAL(dbc_vertices(3, :))
1237 :
1238 : ! divide the x, y and z extents into n_prtn partitions
1239 30 : step = (x_xtnt(2) - x_xtnt(1))/REAL(n_prtn(1), kind=dp)
1240 140 : xprtn_lb(:) = x_xtnt(1) + (/(i, i=0, n_prtn(1) - 1)/)*step ! lower bounds
1241 140 : xprtn_ub(:) = x_xtnt(1) + (/(i, i=1, n_prtn(1))/)*step ! upper bounds
1242 :
1243 30 : step = (y_xtnt(2) - y_xtnt(1))/REAL(n_prtn(2), kind=dp)
1244 136 : yprtn_lb(:) = y_xtnt(1) + (/(i, i=0, n_prtn(2) - 1)/)*step
1245 136 : yprtn_ub(:) = y_xtnt(1) + (/(i, i=1, n_prtn(2))/)*step
1246 :
1247 30 : step = (z_xtnt(2) - z_xtnt(1))/REAL(n_prtn(3), kind=dp)
1248 140 : zprtn_lb(:) = z_xtnt(1) + (/(i, i=0, n_prtn(3) - 1)/)*step
1249 140 : zprtn_ub(:) = z_xtnt(1) + (/(i, i=1, n_prtn(3))/)*step
1250 :
1251 154 : ALLOCATE (tiles(n_prtn(1)*n_prtn(2)*n_prtn(3)))
1252 : k = 1
1253 70 : DO kk = 1, n_prtn(3)
1254 118 : DO jj = 1, n_prtn(2)
1255 152 : DO ii = 1, n_prtn(1)
1256 2176 : ALLOCATE (tiles(k)%tile)
1257 64 : tiles(k)%tile%tile_id = k
1258 :
1259 256 : tiles(k)%tile%vertices(1:3, 1) = (/xprtn_lb(ii), yprtn_lb(jj), zprtn_lb(kk)/)
1260 256 : tiles(k)%tile%vertices(1:3, 2) = (/xprtn_ub(ii), yprtn_lb(jj), zprtn_lb(kk)/)
1261 256 : tiles(k)%tile%vertices(1:3, 3) = (/xprtn_ub(ii), yprtn_ub(jj), zprtn_lb(kk)/)
1262 256 : tiles(k)%tile%vertices(1:3, 4) = (/xprtn_lb(ii), yprtn_ub(jj), zprtn_lb(kk)/)
1263 256 : tiles(k)%tile%vertices(1:3, 5) = (/xprtn_lb(ii), yprtn_ub(jj), zprtn_ub(kk)/)
1264 256 : tiles(k)%tile%vertices(1:3, 6) = (/xprtn_lb(ii), yprtn_lb(jj), zprtn_ub(kk)/)
1265 256 : tiles(k)%tile%vertices(1:3, 7) = (/xprtn_ub(ii), yprtn_lb(jj), zprtn_ub(kk)/)
1266 256 : tiles(k)%tile%vertices(1:3, 8) = (/xprtn_ub(ii), yprtn_ub(jj), zprtn_ub(kk)/)
1267 :
1268 64 : tiles(k)%tile%volume = 0.0_dp
1269 112 : k = k + 1
1270 : END DO
1271 : END DO
1272 : END DO
1273 :
1274 30 : CALL timestop(handle)
1275 :
1276 60 : END SUBROUTINE aa_dbc_partition
1277 :
1278 : ! **************************************************************************************************
1279 : !> \brief Partitions an arbitrary cuboid into tiles.
1280 : !> \param dbc_vertices vertices of the axis-aligned Dirichlet region to be partitioned
1281 : !> \param n_prtn number of partitions along the edges
1282 : !> \param tiles the obtained tiles
1283 : !> \par History
1284 : !> 10.2015 created [Hossein Bani-Hashemian]
1285 : !> \author Mohammad Hossein Bani-Hashemian
1286 : ! **************************************************************************************************
1287 98 : SUBROUTINE arbitrary_dbc_partition(dbc_vertices, n_prtn, tiles)
1288 :
1289 : REAL(dp), DIMENSION(3, 8), INTENT(IN) :: dbc_vertices
1290 : INTEGER, DIMENSION(2), INTENT(IN) :: n_prtn
1291 : TYPE(tile_p_type), DIMENSION(:), INTENT(OUT), &
1292 : POINTER :: tiles
1293 :
1294 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arbitrary_dbc_partition'
1295 :
1296 : INTEGER :: handle, i, k, l, np1, np2
1297 : REAL(dp) :: ABlength, ADlength, step, thickness
1298 98 : REAL(dp), ALLOCATABLE, DIMENSION(:, :, :) :: end_points, X
1299 : REAL(dp), DIMENSION(3) :: A, AB, AC, AD, B, C, D, D2, &
1300 : normal_vector, point1, point2, &
1301 : unit_normal
1302 :
1303 98 : CALL timeset(routineN, handle)
1304 :
1305 392 : A = dbc_vertices(:, 1)
1306 392 : B = dbc_vertices(:, 2)
1307 392 : C = dbc_vertices(:, 3)
1308 392 : D = dbc_vertices(:, 4)
1309 392 : D2 = dbc_vertices(:, 5)
1310 :
1311 392 : AB = B - A
1312 392 : AC = C - A
1313 392 : AD = D - A
1314 98 : normal_vector = vector_product(AB, AC)
1315 686 : unit_normal = normal_vector/SQRT(SUM(normal_vector**2))
1316 392 : thickness = SQRT(SUM((D - D2)**2))
1317 :
1318 : ! the larger n_prtn is assigned to the longer edge
1319 392 : ABlength = SQRT(SUM(AB**2))
1320 392 : ADlength = SQRT(SUM(AD**2))
1321 98 : IF (ADlength .GE. ABlength) THEN
1322 92 : np1 = MAX(n_prtn(1) + 1, n_prtn(2) + 1)
1323 92 : np2 = MIN(n_prtn(1) + 1, n_prtn(2) + 1)
1324 : ELSE
1325 6 : np1 = MIN(n_prtn(1) + 1, n_prtn(2) + 1)
1326 6 : np2 = MAX(n_prtn(1) + 1, n_prtn(2) + 1)
1327 : END IF
1328 :
1329 490 : ALLOCATE (X(np1, np2, 3))
1330 392 : ALLOCATE (end_points(2, np1, 3))
1331 :
1332 : ! partition AD and BC
1333 346 : DO l = 1, np1
1334 248 : step = REAL((l - 1), kind=dp)/REAL((np1 - 1), kind=dp)
1335 992 : end_points(1, l, :) = A*(1.0_dp - step) + D*step
1336 1090 : end_points(2, l, :) = B*(1.0_dp - step) + C*step
1337 : END DO
1338 :
1339 : ! partition in the second direction along the line segments with endpoints from
1340 : ! the previous partitioning step
1341 346 : DO l = 1, np1
1342 992 : point1(:) = end_points(1, l, :)
1343 992 : point2(:) = end_points(2, l, :)
1344 858 : DO i = 1, np2
1345 512 : step = REAL((i - 1), kind=dp)/REAL((np2 - 1), kind=dp)
1346 2296 : X(l, i, :) = point1*(1.0_dp - step) + point2*step
1347 : END DO
1348 : END DO
1349 :
1350 454 : ALLOCATE (tiles((np1 - 1)*(np2 - 1)))
1351 : k = 1
1352 248 : DO l = 1, np1 - 1
1353 408 : DO i = 1, np2 - 1
1354 5280 : ALLOCATE (tiles(k)%tile)
1355 160 : tiles(k)%tile%tile_id = k
1356 :
1357 640 : tiles(k)%tile%vertices(1:3, 1) = X(l, i, :)
1358 640 : tiles(k)%tile%vertices(1:3, 2) = X(l, i + 1, :)
1359 640 : tiles(k)%tile%vertices(1:3, 3) = X(l + 1, i + 1, :)
1360 640 : tiles(k)%tile%vertices(1:3, 4) = X(l + 1, i, :)
1361 640 : tiles(k)%tile%vertices(1:3, 5) = X(l + 1, i, :) + thickness*unit_normal
1362 640 : tiles(k)%tile%vertices(1:3, 6) = X(l, i, :) + thickness*unit_normal
1363 640 : tiles(k)%tile%vertices(1:3, 7) = X(l, i + 1, :) + thickness*unit_normal
1364 640 : tiles(k)%tile%vertices(1:3, 8) = X(l + 1, i + 1, :) + thickness*unit_normal
1365 :
1366 160 : tiles(k)%tile%volume = 0.0_dp
1367 310 : k = k + 1
1368 : END DO
1369 : END DO
1370 :
1371 98 : CALL timestop(handle)
1372 :
1373 196 : END SUBROUTINE arbitrary_dbc_partition
1374 :
1375 : ! **************************************************************************************************
1376 : !> \brief computes the pw data corresponding to an axis-aligned tile
1377 : !> \param cell_xtnts extents of the simulation cell
1378 : !> \param x_locl x grid vector of the simulation box local to this process
1379 : !> \param y_locl y grid vector of the simulation box local to this process
1380 : !> \param z_locl z grid vector of the simulation box local to this process
1381 : !> \param tile_vertices coordinates of the vertices of the input tile
1382 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
1383 : !> \param is_periodic whether or not the tile is periodic with a periodicity of one unit cell
1384 : !> \param tile_pw the output pw data
1385 : !> \par History
1386 : !> 10.2015 created [Hossein Bani-Hashemian]
1387 : !> \author Mohammad Hossein Bani-Hashemian
1388 : ! **************************************************************************************************
1389 64 : SUBROUTINE aa_tile_pw_compute(cell_xtnts, x_locl, y_locl, z_locl, tile_vertices, &
1390 : sigma, is_periodic, tile_pw)
1391 :
1392 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
1393 : REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(IN) :: x_locl, y_locl, z_locl
1394 : REAL(dp), DIMENSION(3, 8), INTENT(IN) :: tile_vertices
1395 : REAL(dp), INTENT(IN) :: sigma
1396 : LOGICAL, INTENT(IN) :: is_periodic
1397 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: tile_pw
1398 :
1399 : CHARACTER(LEN=*), PARAMETER :: routineN = 'aa_tile_pw_compute'
1400 :
1401 : INTEGER :: handle, i, j, k, lb1, lb2, lb3, ub1, &
1402 : ub2, ub3
1403 : INTEGER, DIMENSION(2, 3) :: bounds_local
1404 : REAL(dp) :: fx, fy, fz, gx, gy, gz, hx, hy, hz, xi0, &
1405 : xil, xir, yj0, yjl, yjr, zk0, zkl, zkr
1406 64 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: xlocll, xloclr, ylocll, yloclr, zlocll, &
1407 64 : zloclr
1408 : REAL(dp), DIMENSION(2) :: x_xtnt, y_xtnt, z_xtnt
1409 : REAL(dp), DIMENSION(3) :: per
1410 : REAL(dp), DIMENSION(3, 3) :: prefactor
1411 :
1412 64 : CALL timeset(routineN, handle)
1413 :
1414 640 : bounds_local = tile_pw%pw_grid%bounds_local
1415 64 : lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
1416 64 : lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
1417 64 : lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
1418 :
1419 448 : ALLOCATE (xlocll(lb1:ub1), ylocll(lb2:ub2), zlocll(lb3:ub3))
1420 256 : ALLOCATE (xloclr(lb1:ub1), yloclr(lb2:ub2), zloclr(lb3:ub3))
1421 :
1422 : ! periodicities
1423 256 : per = cell_xtnts(2, :) - cell_xtnts(1, :)
1424 :
1425 1216 : x_xtnt(1) = MINVAL(tile_vertices(1, :)); x_xtnt(2) = MAXVAL(tile_vertices(1, :))
1426 1216 : y_xtnt(1) = MINVAL(tile_vertices(2, :)); y_xtnt(2) = MAXVAL(tile_vertices(2, :))
1427 1216 : z_xtnt(1) = MINVAL(tile_vertices(3, :)); z_xtnt(2) = MAXVAL(tile_vertices(3, :))
1428 :
1429 : ! prefactor: columns: left, original, right - rows: x , y, z directions
1430 832 : prefactor = 0.5_dp
1431 :
1432 64 : IF (is_periodic) THEN
1433 0 : DO k = lb3, ub3
1434 0 : DO j = lb2, ub2
1435 0 : DO i = lb1, ub1
1436 0 : xi0 = x_locl(i); yj0 = y_locl(j); zk0 = z_locl(k)
1437 0 : xil = x_locl(i) - per(1); yjl = y_locl(j) - per(2); zkl = z_locl(k) - per(3)
1438 0 : xir = x_locl(i) + per(1); yjr = y_locl(j) + per(2); zkr = z_locl(k) + per(3)
1439 :
1440 : ! points from the original cell local to the current processor
1441 0 : fx = prefactor(1, 2)*(erf((xi0 - x_xtnt(1))/sigma) - erf((xi0 - x_xtnt(2))/sigma))
1442 0 : fy = prefactor(2, 2)*(erf((yj0 - y_xtnt(1))/sigma) - erf((yj0 - y_xtnt(2))/sigma))
1443 0 : fz = prefactor(3, 2)*(erf((zk0 - z_xtnt(1))/sigma) - erf((zk0 - z_xtnt(2))/sigma))
1444 :
1445 : ! periodically replicated cell on the left, points local to the current processor
1446 0 : gx = prefactor(1, 1)*(erf((xil - x_xtnt(1))/sigma) - erf((xil - x_xtnt(2))/sigma))
1447 0 : gy = prefactor(2, 1)*(erf((yjl - y_xtnt(1))/sigma) - erf((yjl - y_xtnt(2))/sigma))
1448 0 : gz = prefactor(3, 1)*(erf((zkl - z_xtnt(1))/sigma) - erf((zkl - z_xtnt(2))/sigma))
1449 :
1450 : ! periodically replicated cell on the right, points local to the current processor
1451 0 : hx = prefactor(1, 3)*(erf((xir - x_xtnt(1))/sigma) - erf((xir - x_xtnt(2))/sigma))
1452 0 : hy = prefactor(2, 3)*(erf((yjr - y_xtnt(1))/sigma) - erf((yjr - y_xtnt(2))/sigma))
1453 0 : hz = prefactor(3, 3)*(erf((zkr - z_xtnt(1))/sigma) - erf((zkr - z_xtnt(2))/sigma))
1454 :
1455 0 : tile_pw%array(i, j, k) = (fx + gx + hx)*(fy + gy + hy)*(fz + gz + hz)
1456 : END DO
1457 : END DO
1458 : END DO
1459 : ELSE
1460 3926 : DO k = lb3, ub3
1461 249952 : DO j = lb2, ub2
1462 8269833 : DO i = lb1, ub1
1463 8019945 : xi0 = x_locl(i); yj0 = y_locl(j); zk0 = z_locl(k)
1464 :
1465 8019945 : fx = 0.5_dp*(erf((xi0 - x_xtnt(1))/sigma) - erf((xi0 - x_xtnt(2))/sigma))
1466 8019945 : fy = 0.5_dp*(erf((yj0 - y_xtnt(1))/sigma) - erf((yj0 - y_xtnt(2))/sigma))
1467 8019945 : fz = 0.5_dp*(erf((zk0 - z_xtnt(1))/sigma) - erf((zk0 - z_xtnt(2))/sigma))
1468 :
1469 8265971 : tile_pw%array(i, j, k) = fx*fy*fz
1470 : END DO
1471 : END DO
1472 : END DO
1473 : END IF
1474 :
1475 64 : CALL timestop(handle)
1476 :
1477 128 : END SUBROUTINE aa_tile_pw_compute
1478 :
1479 : ! **************************************************************************************************
1480 : !> \brief computes the pw data corresponding to an arbitrary (rectangular-shaped) tile
1481 : !> \param cell_xtnts extents of the simulation cell
1482 : !> \param x_locl x grid vector of the simulation box local to this process
1483 : !> \param y_locl y grid vector of the simulation box local to this process
1484 : !> \param z_locl z grid vector of the simulation box local to this process
1485 : !> \param tile_vertices coordinates of the vertices of the input tile
1486 : !> \param sigma the width of the transition region between 0 and 1 at the edges of the tile
1487 : !> \param tile_pw the output pw data
1488 : !> \par History
1489 : !> 11.2015 created [Hossein Bani-Hashemian]
1490 : !> \author Mohammad Hossein Bani-Hashemian
1491 : ! **************************************************************************************************
1492 160 : SUBROUTINE arbitrary_tile_pw_compute(cell_xtnts, x_locl, y_locl, z_locl, tile_vertices, &
1493 : sigma, tile_pw)
1494 :
1495 : REAL(dp), DIMENSION(2, 3), INTENT(IN) :: cell_xtnts
1496 : REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(IN) :: x_locl, y_locl, z_locl
1497 : REAL(dp), DIMENSION(3, 8), INTENT(IN) :: tile_vertices
1498 : REAL(dp), INTENT(IN) :: sigma
1499 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: tile_pw
1500 :
1501 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arbitrary_tile_pw_compute'
1502 :
1503 : INTEGER :: handle, i, j, k, lb1, lb2, lb3, ub1, &
1504 : ub2, ub3
1505 : INTEGER, DIMENSION(2, 3) :: bounds_local
1506 : REAL(dp) :: cm_x, cm_y, cm_z, fx, fy, fz, xi0, yj0, &
1507 : zk0
1508 160 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: xlocll, xloclr, ylocll, yloclr, zlocll, &
1509 160 : zloclr
1510 : REAL(dp), DIMENSION(2) :: transfdx_xtnt, transfdy_xtnt, &
1511 : transfdz_xtnt, x_xtnt, y_xtnt, z_xtnt
1512 : REAL(dp), DIMENSION(3) :: per, pnt0, Tpnt
1513 : REAL(dp), DIMENSION(3, 3) :: prefactor, Rmat
1514 : REAL(dp), DIMENSION(3, 8) :: tile_transfd_vertices
1515 :
1516 160 : CALL timeset(routineN, handle)
1517 :
1518 1600 : bounds_local = tile_pw%pw_grid%bounds_local
1519 160 : lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
1520 160 : lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
1521 160 : lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
1522 :
1523 1120 : ALLOCATE (xlocll(lb1:ub1), ylocll(lb2:ub2), zlocll(lb3:ub3))
1524 640 : ALLOCATE (xloclr(lb1:ub1), yloclr(lb2:ub2), zloclr(lb3:ub3))
1525 :
1526 640 : per = cell_xtnts(2, :) - cell_xtnts(1, :)
1527 :
1528 160 : CALL rotate_translate_cuboid(tile_vertices, Rmat, Tpnt, tile_transfd_vertices)
1529 :
1530 1600 : transfdx_xtnt(1) = MINVAL(tile_transfd_vertices(1, :))
1531 1600 : transfdx_xtnt(2) = MAXVAL(tile_transfd_vertices(1, :))
1532 1600 : transfdy_xtnt(1) = MINVAL(tile_transfd_vertices(2, :))
1533 1600 : transfdy_xtnt(2) = MAXVAL(tile_transfd_vertices(2, :))
1534 1600 : transfdz_xtnt(1) = MINVAL(tile_transfd_vertices(3, :))
1535 1600 : transfdz_xtnt(2) = MAXVAL(tile_transfd_vertices(3, :))
1536 :
1537 160 : cm_x = 0.5_dp*(transfdx_xtnt(2) + transfdx_xtnt(1))
1538 160 : cm_y = 0.5_dp*(transfdy_xtnt(2) + transfdy_xtnt(1))
1539 160 : cm_z = 0.5_dp*(transfdz_xtnt(2) + transfdz_xtnt(1))
1540 :
1541 480 : x_xtnt = transfdx_xtnt - cm_x
1542 480 : y_xtnt = transfdy_xtnt - cm_y
1543 480 : z_xtnt = transfdz_xtnt - cm_z
1544 :
1545 2080 : prefactor = 0.5_dp
1546 :
1547 9124 : DO k = lb3, ub3
1548 525364 : DO j = lb2, ub2
1549 15815088 : DO i = lb1, ub1
1550 61159536 : pnt0 = rotate_translate_vector(Rmat, Tpnt, BWROT, (/x_locl(i), y_locl(j), z_locl(k)/))
1551 :
1552 15289884 : xi0 = pnt0(1); yj0 = pnt0(2); zk0 = pnt0(3)
1553 :
1554 15289884 : fx = 0.5_dp*(erf((xi0 - x_xtnt(1))/sigma) - erf((xi0 - x_xtnt(2))/sigma))
1555 15289884 : fy = 0.5_dp*(erf((yj0 - y_xtnt(1))/sigma) - erf((yj0 - y_xtnt(2))/sigma))
1556 15289884 : fz = 0.5_dp*(erf((zk0 - z_xtnt(1))/sigma) - erf((zk0 - z_xtnt(2))/sigma))
1557 :
1558 15806124 : tile_pw%array(i, j, k) = fx*fy*fz
1559 : END DO
1560 : END DO
1561 : END DO
1562 :
1563 160 : CALL timestop(handle)
1564 :
1565 320 : END SUBROUTINE arbitrary_tile_pw_compute
1566 :
1567 : END MODULE dirichlet_bc_methods
|