Octopus
simplex.F90
Go to the documentation of this file.
1!! Copyright (C) 2025 Octopus Developers
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 simplex_oct_m
22 use, intrinsic :: iso_fortran_env, only: real64
23 use debug_oct_m, only: debug
24#ifndef NDEBUG
26#endif
27 use global_oct_m, only: &
30 use profiling_oct_m, only: &
32 use sort_oct_m, only: sort
33
34 implicit none
35
36 private
37
38 public :: &
39 simplex_t, &
50
51 type simplex_t
52 integer :: rdim
53 integer :: sdim
54 integer :: n_simplices
55 integer :: n_points
56 integer, allocatable :: simplices(:,:)
57 contains
58 final :: simplex_end
59 end type simplex_t
60
61 interface simplex_t
62 module procedure simplex_init
63 end interface simplex_t
64
65contains
66
82 function simplex_init(dim, naxis, nshifts, shift, kpoints, equiv, opt) result(this)
83 integer, intent(in) :: dim
84 integer, intent(in) :: naxis(1:dim)
85 integer, intent(in) :: nshifts
86 real(real64), intent(in) :: shift(:,:)
87 real(real64), intent(in) :: kpoints(:,:)
88 integer, intent(in), optional :: equiv(:)
89 logical, intent(in) :: opt
90 type(simplex_t), pointer :: this
91
92 real(real64) :: kmin(dim)
93 integer :: ik, npoints
94
95 integer :: ix(dim)
96 integer, allocatable :: kl123(:,:,:)
97
98 integer :: rdim, raxis(3)
99
100 push_sub(simplex_init)
101
102 if (nshifts /= 1) then
103 message(1) = "The linear tetrahedron method only works for automatic k-point grids with a single shift"
104 call messages_fatal(1)
105 end if
106
107 safe_allocate(this)
108 safe_allocate_source(kl123(1:naxis(1), 1:naxis(2), 1:naxis(3)), -1)
109
110 npoints = product(naxis)
111 kmin = minval(kpoints, 2)
112
113 do ik = 1, npoints
114 ix(:) = nint((kpoints(:,ik) - kmin) * naxis + 1)
115 assert(kl123(ix(1), ix(2), ix(3)) == -1)
116 if (present(equiv)) then
117 kl123(ix(1), ix(2), ix(3)) = equiv(ik)
118 else
119 kl123(ix(1), ix(2), ix(3)) = ik
120 end if
121 end do
122
123 rdim = sum(merge(1, 0, naxis > 1))
124 raxis(1:rdim) = pack(naxis, naxis > 1)
125
126 if (any(raxis(1:rdim) /= naxis(1:rdim))) then
127 message(1) = "The periodic dimensions must be consecutive"
128 call messages_fatal(1)
129 end if
130
131 select case (rdim)
132 case default
133 assert(.false.)
134 case (1)
135 block
136 integer, parameter :: submesh_segments(1,2) = reshape([ &
137 1, 2 ], shape(submesh_segments), order=[2, 1])
138 ! coordinates of corners and neighbors in barycentric coordinates
139 integer, parameter :: b(4,2) = reshape([ &
140 1 , 0 , & ! k1
141 0 , 1 , & ! k2
142 2 , -1, & ! 2 * k1 - k2
143 -1, 2 & ! 2 * k2 - k1
144 ], shape(b), order=[2, 1])
145
146 integer :: i, ip1, it, n
147 integer :: corners(2,1), v(2,1), c(1)
148 integer :: this_segment(2), this_corner
150 this%n_points = npoints
151 this%n_simplices = npoints
152 this%rdim = rdim
153 this%sdim = merge(4, 2, opt)
154 safe_allocate(this%simplices(this%n_simplices, this%sdim))
155
156 do i = 1, raxis(1)
157 ip1 = modulo(i, raxis(1)) + 1
158 corners(:,:) = reshape([ i , ip1 ], shape(corners), order=[2, 1])
159
160 do it = 1, size(submesh_segments, 1)
161 n = (it - 1) + 1 * (i - 1) + 1
162 this_segment(:) = submesh_segments(it, :)
163 v(1,:) = corners(this_segment(1), :)
164 v(2,:) = corners(this_segment(2), :)
165 do ik = 1, this%sdim
166 c(:) = b(ik,1) * v(1,:) + b(ik,2) * v(2,:)
167 c(:) = modulo(c(:) - 1, raxis(1:rdim)) + 1
168 this_corner = kl123(c(1), 1, 1)
169 this%simplices(n,ik) = this_corner
170 end do
171 end do
172 end do
173 end block
174 case (2)
175 block
176 integer, parameter :: submesh_triangles(2,3) = reshape([ &
177 1, 2, 3, &
178 1, 4, 3], shape(submesh_triangles), order=[2, 1])
179 ! coordinates of corners and neighbors in barycentric coordinates
180 integer, parameter :: b(10,3) = reshape([ &
181 1 , 0 , 0 , & ! k1
182 0 , 1 , 0 , & ! k2
183 0 , 0 , 1 , & ! k3
184 2 , -1, 0 , & ! 2 * k1 - k2
185 0 , 2 , -1, & ! 2 * k2 - k3
186 2 , 0 , -1, & ! 2 * k1 - k3
187 -1, 0 , 2 , & ! 2 * k3 - k1
188 -1, 2 , 0 , & ! 2 * k2 - k1
189 0 , -1, 2 , & ! 2 * k3 - k2
190 1 , -1, 1 & ! k1 - k2 + k3
191 ], shape(b), order=[2, 1])
192
193 integer :: i, j, ip1, jp1, it, n
194 integer :: corners(4,2), v(3,2), c(2)
195 integer :: this_triangle(3), this_corner
196
197 this%n_points = npoints
198 this%n_simplices = 2 * npoints
199 this%rdim = rdim
200 this%sdim = merge(10, 3, opt)
201 safe_allocate(this%simplices(this%n_simplices, this%sdim))
202
203 do i = 1, raxis(1)
204 do j = 1, raxis(2)
205 ip1 = modulo(i, raxis(1)) + 1
206 jp1 = modulo(j, raxis(2)) + 1
207 corners(:,:) = reshape([ &
208 i , j , &
209 ip1 , j , &
210 ip1 , jp1 , &
211 i , jp1 ], shape(corners), order=[2, 1])
212
213 do it = 1, size(submesh_triangles, 1)
214 n = (it - 1) + 2 * ((j - 1) + raxis(2) * (i - 1)) + 1
215 this_triangle(:) = submesh_triangles(it, :)
216 v(1,:) = corners(this_triangle(1), :)
217 v(2,:) = corners(this_triangle(2), :)
218 v(3,:) = corners(this_triangle(3), :)
219 do ik = 1, this%sdim
220 c(:) = b(ik,1) * v(1,:) + b(ik,2) * v(2,:) + b(ik,3) * v(3,:)
221 c(:) = modulo(c(:) - 1, raxis(1:rdim)) + 1
222 this_corner = kl123(c(1), c(2), 1)
223 this%simplices(n,ik) = this_corner
224 end do
225 end do
226 end do
227 end do
228 end block
229 case(3)
230 block
231 integer, parameter :: submesh_tetras(6,4) = reshape([ &
232 1, 2, 3, 6, &
233 1, 3, 5, 6, &
234 3, 5, 6, 7, &
235 3, 6, 7, 8, &
236 3, 4, 6, 8, &
237 2, 3, 4, 6], shape(submesh_tetras), order=[2, 1])
238 ! coordinates of corners and neighbors in barycentric coordinates
239 integer, parameter :: b(20,4) = reshape([ &
240 1 , 0 , 0 , 0 , & ! k1
241 0 , 1 , 0 , 0 , & ! k2
242 0 , 0 , 1 , 0 , & ! k3
243 0 , 0 , 0 , 1 , & ! k4
244 2 , -1, 0 , 0 , & ! 2 * k1 - k2
245 0 , 2 , -1, 0 , & ! 2 * k2 - k3
246 0 , 0 , 2 , -1, & ! 2 * k3 - k4
247 -1, 0 , 0 , 2 , & ! 2 * k4 - k1
248 2 , 0 , -1, 0 , & ! 2 * k1 - k3
249 0 , 2 , 0 , -1, & ! 2 * k2 - k4
250 -1, 0 , 2 , 0 , & ! 2 * k3 - k1
251 0 , -1, 0 , 2 , & ! 2 * k4 - k2
252 2 , 0 , 0 , -1, & ! 2 * k1 - k4
253 -1, 2 , 0 , 0 , & ! 2 * k2 - k1
254 0 , -1, 2 , 0 , & ! 2 * k3 - k2
255 0 , 0 , -1, 2 , & ! 2 * k4 - k3
256 -1, 1 , 0 , 1 , & ! k4 - k1 + k2
257 1 , -1, 1 , 0 , & ! k1 - k2 + k3
258 0 , 1 , -1, 1 , & ! k2 - k3 + k4
259 1 , 0 , 1 , -1 & ! k3 - k4 + k1
260 ], shape(b), order=[2, 1])
261
262 integer :: i, j, k, ip1, jp1, kp1, it, n
263 integer :: corners(8,3), v(4,3), c(3)
264 integer :: this_tetra(4), this_corner
265
266 this%n_points = npoints
267 this%n_simplices = 6 * npoints
268 this%rdim = rdim
269 this%sdim = merge(20, 4, opt)
270 safe_allocate(this%simplices(this%n_simplices, this%sdim))
271
272 do i = 1, raxis(1)
273 do j = 1, raxis(2)
274 do k = 1, raxis(3)
275 ip1 = modulo(i, raxis(1)) + 1
276 jp1 = modulo(j, raxis(2)) + 1
277 kp1 = modulo(k, raxis(3)) + 1
278 corners(:,:) = reshape([ &
279 i , j , k , &
280 ip1 , j , k , &
281 i , jp1 , k , &
282 ip1 , jp1 , k , &
283 i , j , kp1 , &
284 ip1 , j , kp1 , &
285 i , jp1 , kp1 , &
286 ip1 , jp1 , kp1 ], shape(corners), order=[2, 1])
287
288 do it = 1, size(submesh_tetras, 1)
289 n = (it - 1) + 6 * ((k - 1) + raxis(3) * ((j - 1) + raxis(2) * (i - 1))) + 1
290 this_tetra(:) = submesh_tetras(it, :)
291 v(1,:) = corners(this_tetra(1), :)
292 v(2,:) = corners(this_tetra(2), :)
293 v(3,:) = corners(this_tetra(3), :)
294 v(4,:) = corners(this_tetra(4), :)
295 do ik = 1, this%sdim
296 c(:) = b(ik,1) * v(1,:) + b(ik,2) * v(2,:) + b(ik,3) * v(3,:) + b(ik,4) * v(4,:)
297 c(:) = modulo(c(:) - 1, raxis(1:rdim)) + 1
298 this_corner = kl123(c(1), c(2), c(3))
299 this%simplices(n,ik) = this_corner
300 end do
301 end do
302 end do
303 end do
304 end do
305 end block
306 end select
307
308 safe_deallocate_a(kl123)
309
310 pop_sub(simplex_init)
311 end function simplex_init
312
316 subroutine simplex_end(this)
317 type(simplex_t), intent(inout) :: this
318 push_sub(simplex_end)
319 safe_deallocate_a(this%simplices)
320 pop_sub(simplex_end)
321 end subroutine simplex_end
322
330 subroutine simplex_weights(rdim, esimplex, eF, weights, dos)
331 integer, intent(in) :: rdim
332 real(real64), intent(in) :: esimplex(:)
333 real(real64), intent(in) :: ef
334 real(real64), intent(out) :: weights(:)
335 real(real64), intent(out) :: dos(:)
336
337 ! no PUSH_SUB, called too often
338
339 select case (rdim)
340 case (1)
341 call simplex_weights_1d(esimplex, ef, weights, dos)
342 case (2)
343 call simplex_weights_2d(esimplex, ef, weights, dos)
344 case (3)
345 call simplex_weights_3d(esimplex, ef, weights, dos)
346 case default
347 assert(.false.)
348 end select
349 end subroutine simplex_weights
350
357 subroutine simplex_dos(rdim, esimplex, eF, dos)
358 integer, intent(in) :: rdim
359 real(real64), intent(in) :: esimplex(:)
360 real(real64), intent(in) :: ef
361 real(real64), intent(out) :: dos(:)
362
363 ! no PUSH_SUB, called too often
364
365 select case (rdim)
366 case (1)
367 call simplex_dos_1d(esimplex, ef, dos)
368 case (2)
369 call simplex_dos_2d(esimplex, ef, dos)
370 case (3)
371 call simplex_dos_3d(esimplex, ef, dos)
372 case default
373 assert(.false.)
374 end select
375 end subroutine simplex_dos
376
383 subroutine simplex_weights_1d(esegment, eF, weights, dos)
384 real(real64), intent(in) :: esegment(:)
385 real(real64), intent(in) :: ef
386 real(real64), intent(out) :: weights(:)
387 real(real64), intent(out) :: dos(:)
388
389 real(real64) :: e(2), e1, e2
390 real(real64) :: w(2), d(2)
391 integer :: idx(2)
392
393 real(real64), parameter :: vt_vg = 1.0_real64
394 real(real64), parameter :: vt_2vg = vt_vg / 2.0_real64
395
396 real(real64), parameter :: p(2,4) = 1.0_real64 / 60.0_real64 * reshape([ &
397 64 , 1 , -3 , -2 , &
398 1 , 64 , -2 , -3 ], shape(p), order=[2, 1])
399
400 ! no PUSH_SUB, called too often
401
402 select case (size(esegment))
403 case (2)
404 e(:) = esegment(:)
405 case (4)
406 e(:) = m_zero
407 block
408 integer :: i
409 do i = 1, size(esegment)
410 e(:) = e(:) + p(:,i) * esegment(i)
411 end do
412 end block
413 case default
414 assert(.false.)
415 end select
416
417 idx = [1,2]
418 call sort(e, idx)
419 e1 = e(1)
420 e2 = e(2)
421
422 if (ef <= e1) then
423 w(:) = m_zero
424 d(:) = m_zero
425 elseif (e2 < ef) then
426 w(:) = vt_2vg
427 d(:) = m_zero
428 elseif (e1 < ef .and. ef <= e2) then
429 block
430 real(real64) :: e21, c
431 e21 = e2 - e1
432 c = vt_2vg * (ef - e1) / e21
433
434 w(:) = c * [ &
435 2.0_real64 - (ef - e1) / e21, &
436 (ef - e1) / e21]
437
438 d(:) = vt_vg / e21 * [ &
439 m_one - (ef - e1) / e21, &
440 (ef - e1) / e21]
441 end block
442 else
443 assert(.false.)
444 end if
445
446 dos(idx) = d
447 select case (size(esegment))
448 case (2)
449 weights(idx) = w + sum(d) * (sum(e) - 2.0_real64 * e) / 12.0_real64
450 case (4)
451 weights(idx) = w ! no Bloechl correction
452 case default
453 assert(.false.)
454 end select
455 end subroutine simplex_weights_1d
456
462 subroutine simplex_dos_1d(esegment, eF, dos)
463 real(real64), intent(in) :: esegment(:)
464 real(real64), intent(in) :: ef
465 real(real64), intent(out) :: dos(:)
466
467 real(real64) :: e(2), e1, e2
468 real(real64) :: d(2)
469 integer :: idx(2)
470
471 real(real64), parameter :: vt_vg = 1.0_real64
472
473 real(real64), parameter :: p(2,4) = 1.0_real64 / 60.0_real64 * reshape([ &
474 64 , 1 , -3 , -2 , &
475 1 , 64 , -2 , -3 ], shape(p), order=[2, 1])
476
477 ! no PUSH_SUB, called too often
479 select case (size(esegment))
480 case (2)
481 e(:) = esegment(:)
482 case (4)
483 e(:) = m_zero
484 block
485 integer :: i
486 do i = 1, size(esegment)
487 e(:) = e(:) + p(:,i) * esegment(i)
488 end do
489 end block
490 case default
491 assert(.false.)
492 end select
493
494 idx = [1, 2]
495 call sort(e, idx)
496 e1 = e(1)
497 e2 = e(2)
498
499 if (ef <= e1 .or. e2 < ef) then
500 d(:) = m_zero
501 elseif (e1 < ef .and. ef <= e2) then
502 block
503 real(real64) :: e21
504 e21 = e2 - e1
505
506 d(:) = vt_vg / e21 * [ &
507 m_one - (ef - e1) / e21, &
508 (ef - e1) / e21]
509 end block
510 else
511 assert(.false.)
512 end if
513
514 dos(idx) = d
515 end subroutine simplex_dos_1d
516
529 subroutine simplex_weights_2d(etriangle, eF, weights, dos)
530 real(real64), intent(in) :: etriangle(:)
531 real(real64), intent(in) :: ef
532 real(real64), intent(out) :: weights(:)
533 real(real64), intent(out) :: dos(:)
534
535 real(real64) :: e(3), e1, e2, e3
536 real(real64) :: w(3), d(3)
537 integer :: idx(3)
538
539 real(real64), parameter :: vt_vg = 1.0_real64 / 2.0_real64
540 real(real64), parameter :: vt_3vg = vt_vg / 3.0_real64
541
542 real(real64), parameter :: p(3,10) = 1.0_real64 / 360.0_real64 * reshape([ &
543 402 , 0 , 6 , -13 , 5 , -17 , -13 , -11 , 7 , -6 , &
544 6 , 396 , 6 , -9 , -15 , 3 , 3 , -15 , -9 , -6 , &
545 6 , 0 , 402 , 7 , -11 , -13 , -17 , 5 , -13 , -6 &
546 ], shape(p), order=[2, 1])
547
548 ! no PUSH_SUB, called too often
549
550 select case (size(etriangle))
551 case (3)
552 e(:) = etriangle(:)
553 case (10)
554 e(:) = m_zero
555 block
556 integer :: i
557 do i = 1, size(etriangle)
558 e(:) = e(:) + p(:,i) * etriangle(i)
559 end do
560 end block
561 case default
562 assert(.false.)
563 end select
564
565 idx = [1,2,3]
566 call sort(e, idx)
567 e1 = e(1)
568 e2 = e(2)
569 e3 = e(3)
570
571 if (ef <= e1) then
572 w(:) = m_zero
573 d(:) = m_zero
574 elseif (e3 < ef) then
575 w(:) = vt_3vg
576 d(:) = m_zero
577 elseif (e1 < ef .and. ef <= e2) then
578 block
579 real(real64) :: e21, e31, c
580 e21 = e2 - e1
581 e31 = e3 - e1
582 c = vt_3vg * (ef - e1) ** 2 / (e21 * e31)
583
584 w(:) = c * [ &
585 3.0_real64 - (ef - e1) * (m_one / e21 + m_one / e31), &
586 (ef - e1) / e21, &
587 (ef - e1) / e31]
588
589 d(:) = vt_vg * (ef - e1) / (e21 * e31) * [&
590 2.0_real64 - (ef - e1) * (m_one / e31 + m_one / e21), &
591 (ef - e1) / e21, &
592 (ef - e1) / e31]
593 end block
594 elseif (e2 < ef .and. ef <= e3) then
595 block
596 real(real64) :: e23, e31, c1, c2
597 e23 = e2 - e3
598 e31 = e3 - e1
599 c1 = vt_3vg
600 c2 = vt_3vg * (ef - e3) ** 2 / (e23 * e31)
601
602 w(:) = [ &
603 c1 - c2 * (ef - e3) / e31, &
604 c1 + c2 * (ef - e3) / e23, &
605 c1 + c2 * (3.0_real64 - (ef - e3) * (m_one / e23 - m_one / e31))]
606
607 d(:) = vt_vg * (ef - e3) / (e23 * e31) * [ &
608 - (ef - e3) / e31, &
609 (ef - e3) / e23, &
610 2.0_real64 - (ef - e3) * (m_one / e23 - m_one / e31)]
611 end block
612 else
613 assert(.false.)
614 end if
615
616 dos(idx) = d
617 select case (size(etriangle))
618 case (3)
619 weights(idx) = w + sum(d) * (sum(e) - 3.0_real64 * e) / 24.0_real64
620 case (10)
621 weights(idx) = w ! no Bloechl correction
622 case default
623 assert(.false.)
624 end select
625 end subroutine simplex_weights_2d
626
635 subroutine simplex_dos_2d(etriangle, eF, dos)
636 real(real64), intent(in) :: etriangle(:)
637 real(real64), intent(in) :: ef
638 real(real64), intent(out) :: dos(:)
639
640 real(real64) :: e(3), e1, e2, e3
641 real(real64) :: d(3)
642 integer :: idx(3)
643
644 real(real64), parameter :: vt_vg = 1.0_real64 / 2.0_real64
645
646 real(real64), parameter :: p(3,10) = 1.0_real64 / 360.0_real64 * reshape([ &
647 402 , 0 , 6 , -13 , 5 , -17 , -13 , -11 , 7 , -6 , &
648 6 , 396 , 6 , -9 , -15 , 3 , 3 , -15 , -9 , -6 , &
649 6 , 0 , 402 , 7 , -11 , -13 , -17 , 5 , -13 , -6 &
650 ], shape(p), order=[2, 1])
651
652 ! no PUSH_SUB, called too often
653
654 select case (size(etriangle))
655 case (3)
656 e(:) = etriangle(:)
657 case (10)
658 e(:) = m_zero
659 block
660 integer :: i
661 do i = 1, size(etriangle)
662 e(:) = e(:) + p(:,i) * etriangle(i)
663 end do
664 end block
665 case default
666 assert(.false.)
667 end select
668
669 idx = [1, 2, 3]
670 call sort(e, idx)
671 e1 = e(1)
672 e2 = e(2)
673 e3 = e(3)
674
675 if (ef <= e1 .or. e3 < ef) then
676 d(:) = m_zero
677 elseif (e1 < ef .and. ef <= e2) then
678 block
679 real(real64) :: e21, e31
680 e21 = e2 - e1
681 e31 = e3 - e1
682
683 d(:) = vt_vg * (ef - e1) / (e21 * e31) * [&
684 (2.0_real64 - (ef - e1) * (m_one / e31 + m_one / e21)), &
685 (ef - e1) / e21, &
686 (ef - e1) / e31]
687 end block
688 elseif (e2 < ef .and. ef <= e3) then
689 block
690 real(real64) :: e23, e31
691 e23 = e2 - e3
692 e31 = e3 - e1
693
694 d(:) = vt_vg * (ef - e3) / (e23 * e31) * [ &
695 - (ef - e3) / e31, &
696 (ef - e3) / e23, &
697 2.0_real64 - (ef - e3) * (m_one / e23 - m_one / e31)]
698 end block
699 else
700 assert(.false.)
701 end if
702
703 dos(idx) = d
704 end subroutine simplex_dos_2d
705
721 subroutine simplex_weights_3d(etetra, eF, weights, dos)
722 real(real64), intent(in) :: etetra(:)
723 real(real64), intent(in) :: ef
724 real(real64), intent(out) :: weights(:)
725 real(real64), intent(out) :: dos(:)
726
727 real(real64) :: e(4), e1, e2, e3, e4
728 real(real64) :: w(4), d(4)
729 integer :: idx(4)
731 real(real64), parameter :: vt_vg = 1.0_real64 / 6.0_real64
732 real(real64), parameter :: vt_4vg = vt_vg / 4.0_real64
733
734 real(real64), parameter :: p(4,20) = 1.0_real64 / 1260.0_real64 * reshape([ &
735 1440, 0 , 30 , 0 , -38 , 7 , 17 , -28 , -56 , 9 , -46 , 9 , -38 , -28 , 17 , 7 , -18 , -18 , 12 , -18 , &
736 0 , 1440, 0 , 30 , -28 , -38 , 7 , 17 , 9 , -56 , 9 , -46 , 7 , -38 , -28 , 17 , -18 , -18 , -18 , 12 , &
737 30 , 0 , 1440, 0 , 17 , -28 , -38 , 7 , -46 , 9 , -56 , 9 , 17 , 7 , -38 , -28 , 12 , -18 , -18 , -18 , &
738 0 , 30 , 0 , 1440, 7 , 17 , -28 , -38 , 9 , -46 , 9 , -56 , -28 , 17 , 7 , -38 , -18 , 12 , -18 , -18 &
739 ], shape(p), order=[2, 1])
740
741 ! no PUSH_SUB, called too often
742
743 select case (size(etetra))
744 case (4)
745 e(:) = etetra(:)
746 case (20)
747 e(:) = m_zero
748 block
749 integer :: i
750 do i = 1, size(etetra)
751 e(:) = e(:) + p(:,i) * etetra(i)
752 end do
753 end block
754 case default
755 assert(.false.)
756 end select
757
758 idx = [1,2,3,4]
759 call sort(e, idx)
760 e1 = e(1)
761 e2 = e(2)
762 e3 = e(3)
763 e4 = e(4)
764
765 if (e1 >= ef) then
766 w(:) = m_zero
767 d(:) = m_zero
768 elseif (e4 < ef) then
769 w(:) = vt_4vg
770 d(:) = m_zero
771 elseif (e1 < ef .and. ef <= e2) then
772 block
773 real(real64) :: e21, e31, e41, c
774 e21 = e2 - e1
775 e31 = e3 - e1
776 e41 = e4 - e1
777 c = vt_4vg * (ef - e1) ** 3 / (e21 * e31 * e41)
778
779 w(:) = c * [ &
780 4.0_real64 - (ef - e1) * (m_one / e21 + m_one / e31 + m_one / e41), &
781 (ef - e1) / e21, &
782 (ef - e1) / e31, &
783 (ef - e1) / e41]
784 end block
785 block
786 real(real64) :: f12, f13, f14, f21, f31, f41, g
787 f21 = (ef - e1) / (e2 - e1)
788 f31 = (ef - e1) / (e3 - e1)
789 f41 = (ef - e1) / (e4 - e1)
790 f12 = m_one - f21
791 f13 = m_one - f31
792 f14 = m_one - f41
793 g = f31 * f41 / (e2 - e1)
794 d(:) = vt_vg * g * [&
795 f12 + f13 + f14, &
796 f21, &
797 f31, &
798 f41]
799 end block
800 elseif (e2 < ef .and. ef <= e3) then
801 block
802 real(real64) :: e21, e31, e32, e41, e42, c1, c2, c3
803 e21 = e2 - e1
804 e31 = e3 - e1
805 e32 = e3 - e2
806 e41 = e4 - e1
807 e42 = e4 - e2
808 c1 = vt_4vg * (ef - e1) ** 2 / (e41 * e31)
809 c2 = vt_4vg * (ef - e1) * (ef - e2) * (e3 - ef) / (e41 * e32 * e31)
810 c3 = vt_4vg * (ef - e2) ** 2 * (e4 - ef) / (e42 * e32 * e41)
811
812 w(:) = [ &
813 c1 + (c1 + c2) * (e3 - ef) / e31 + (c1 + c2 + c3) * (e4 - ef) / e41, &
814 c1 + c2 + c3 + (c2 + c3) * (e3 - ef) / e32 + c3 * (e4 - ef) / e42, &
815 (c1 + c2) * (ef - e1) / e31 + (c2 + c3) * (ef - e2) / e32, &
816 (c1 + c2 + c3) * (ef - e1) / e41 + c3 * (ef - e2) / e42]
817 end block
818 block
819 real(real64) :: f13, f14, f23, f24, f31, f32, f41, f42, g, delta
820 delta = e4 - e1
821 f31 = (ef - e1) / (e3 - e1)
822 f41 = (ef - e1) / (e4 - e1)
823 f32 = (ef - e2) / (e3 - e2)
824 f42 = (ef - e2) / (e4 - e2)
825 f13 = m_one - f31
826 f14 = m_one - f41
827 f23 = m_one - f32
828 f24 = m_one - f42
829 g = 3.0_real64 / delta * (f23 * f31 + f32 * f24)
830 d(:) = vt_vg * [&
831 g * f14 / 3.0_real64 + f13 * f31 * f23 / delta, &
832 g * f23 / 3.0_real64 + f24 * f24 * f32 / delta, &
833 g * f32 / 3.0_real64 + f31 * f31 * f23 / delta, &
834 g * f41 / 3.0_real64 + f42 * f24 * f32 / delta]
835 end block
836 elseif (e3 < ef .and. ef <= e4) then
837 block
838 real(real64) :: e41, e42, e43, c
839 e41 = e4 - e1
840 e42 = e4 - e2
841 e43 = e4 - e3
842 c = vt_4vg * (e4 - ef) ** 3 / (e41 * e42 * e43)
843
844 w(:) = vt_4vg - c * [ &
845 (e4 - ef) / e41, &
846 (e4 - ef) / e42, &
847 (e4 - ef) / e43, &
848 4.0_real64 - (e4 - ef) * (m_one / e41 + m_one / e42 + m_one / e43)]
849 end block
850 block
851 real(real64) :: f14, f24, f34, f41, f42, f43, g
852 f14 = (ef - e4) / (e1 - e4)
853 f24 = (ef - e4) / (e2 - e4)
854 f34 = (ef - e4) / (e3 - e4)
855 f41 = m_one - f14
856 f42 = m_one - f24
857 f43 = m_one - f34
858 g = f14 * f24 / (e4 - e3)
859 d(:) = vt_vg * g *[ &
860 f14, &
861 f24, &
862 f34, &
863 f41 + f42 + f43]
864 end block
865 else
866 assert(.false.)
867 end if
868
869 dos(idx) = d
870 select case (size(etetra))
871 case (4)
872 weights(idx) = w + sum(d) * (sum(e) - 4.0_real64 * e) / 40.0_real64
873 case (20)
874 weights(idx) = w ! no Bloechl correction
875 case default
876 assert(.false.)
877 end select
878 end subroutine simplex_weights_3d
879
891 subroutine simplex_dos_3d(etetra, eF, dos)
892 real(real64), intent(in) :: etetra(:)
893 real(real64), intent(in) :: ef
894 real(real64), intent(out) :: dos(:)
895
896 real(real64) :: e(4), e1, e2, e3, e4
897 real(real64) :: d(4)
898 integer :: idx(4)
899
900 real(real64), parameter :: vt_vg = 1.0_real64 / 6.0_real64
901
902 real(real64), parameter :: p(4,20) = 1.0_real64 / 1260.0_real64 * reshape([ &
903 1440, 0 , 30 , 0 , -38 , 7 , 17 , -28 , -56 , 9 , -46 , 9 , -38 , -28 , 17 , 7 , -18 , -18 , 12 , -18 , &
904 0 , 1440, 0 , 30 , -28 , -38 , 7 , 17 , 9 , -56 , 9 , -46 , 7 , -38 , -28 , 17 , -18 , -18 , -18 , 12 , &
905 30 , 0 , 1440, 0 , 17 , -28 , -38 , 7 , -46 , 9 , -56 , 9 , 17 , 7 , -38 , -28 , 12 , -18 , -18 , -18 , &
906 0 , 30 , 0 , 1440, 7 , 17 , -28 , -38 , 9 , -46 , 9 , -56 , -28 , 17 , 7 , -38 , -18 , 12 , -18 , -18 &
907 ], shape(p), order=[2, 1])
908
909 ! no PUSH_SUB, called too often
910
911 select case (size(etetra))
912 case (4)
913 e(:) = etetra(:)
914 case (20)
915 e(:) = m_zero
916 block
917 integer :: i
918 do i = 1, size(etetra)
919 e(:) = e(:) + p(:,i) * etetra(i)
920 end do
921 end block
922 case default
923 assert(.false.)
924 end select
925
926 idx = [1, 2, 3, 4]
927 call sort(e, idx)
928 e1 = e(1)
929 e2 = e(2)
930 e3 = e(3)
931 e4 = e(4)
932
933 if (e1 >= ef .or. e4 < ef) then
934 d(:) = m_zero
935 elseif (e1 < ef .and. ef <= e2) then
936 block
937 real(real64) :: f12, f13, f14, f21, f31, f41, g
938 f21 = (ef - e1) / (e2 - e1)
939 f31 = (ef - e1) / (e3 - e1)
940 f41 = (ef - e1) / (e4 - e1)
941 f12 = m_one - f21
942 f13 = m_one - f31
943 f14 = m_one - f41
944 g = f31 * f41 / (e2 - e1)
945 d(:) = vt_vg * g * [&
946 f12 + f13 + f14, &
947 f21, &
948 f31, &
949 f41]
950 end block
951 elseif (e2 < ef .and. ef <= e3) then
952 block
953 real(real64) :: f13, f14, f23, f24, f31, f32, f41, f42, g, delta
954 delta = e4 - e1
955 f31 = (ef - e1) / (e3 - e1)
956 f41 = (ef - e1) / (e4 - e1)
957 f32 = (ef - e2) / (e3 - e2)
958 f42 = (ef - e2) / (e4 - e2)
959 f13 = m_one - f31
960 f14 = m_one - f41
961 f23 = m_one - f32
962 f24 = m_one - f42
963 g = 3.0_real64 / delta * (f23 * f31 + f32 * f24)
964 d(:) = vt_vg * [&
965 g * f14 / 3.0_real64 + f13 * f31 * f23 / delta, &
966 g * f23 / 3.0_real64 + f24 * f24 * f32 / delta, &
967 g * f32 / 3.0_real64 + f31 * f31 * f23 / delta, &
968 g * f41 / 3.0_real64 + f42 * f24 * f32 / delta]
969 end block
970 elseif (e3 < ef .and. ef <= e4) then
971 block
972 real(real64) :: f14, f24, f34, f41, f42, f43, g
973 f14 = (ef - e4) / (e1 - e4)
974 f24 = (ef - e4) / (e2 - e4)
975 f34 = (ef - e4) / (e3 - e4)
976 f41 = m_one - f14
977 f42 = m_one - f24
978 f43 = m_one - f34
979 g = f14 * f24 / (e4 - e3)
980 d(:) = vt_vg * g *[ &
981 f14, &
982 f24, &
983 f34, &
984 f41 + f42 + f43]
985 end block
986 else
987 assert(.false.)
988 end if
989
990 dos(idx) = d
991 end subroutine simplex_dos_3d
992
993end module simplex_oct_m
This is the common interface to a sorting routine. It performs the shell algorithm,...
Definition: sort.F90:156
type(debug_t), save, public debug
Definition: debug.F90:158
subroutine, public debug_pop_sub(sub_name)
Pop a routine from the debug trace.
Definition: debug.F90:514
subroutine, public debug_push_sub(sub_name)
Push a routine to the debug trace.
Definition: debug.F90:441
real(real64), parameter, public m_two
Definition: global.F90:193
real(real64), parameter, public m_zero
Definition: global.F90:191
integer(int64), public global_sizeof
Definition: global.F90:264
logical pure function, public not_in_openmp()
Definition: global.F90:530
character(len=100), public global_alloc_errmsg
Definition: global.F90:265
integer, public global_alloc_err
Definition: global.F90:263
real(real64), parameter, public m_one
Definition: global.F90:192
subroutine, public alloc_error(size, file, line)
Definition: messages.F90:668
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1067
subroutine, public dealloc_error(size, file, line)
Definition: messages.F90:679
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:161
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:409
type(profile_vars_t), target, save, public prof_vars
Definition: profiling.F90:248
integer, parameter, public profiling_memory
Definition: profiling.F90:208
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
subroutine, public profiling_memory_deallocate(var, file, line, size)
Definition: profiling.F90:1404
subroutine, public profiling_memory_allocate(var, file, line, size_)
Definition: profiling.F90:1333
subroutine, public simplex_weights(rdim, esimplex, eF, weights, dos)
Get the weights and DOS contribution of a single simplex.
Definition: simplex.F90:426
subroutine, public simplex_weights_2d(etriangle, eF, weights, dos)
Get the weights and DOS contribution of a single tetrahedron.
Definition: simplex.F90:625
subroutine, public simplex_dos_3d(etetra, eF, dos)
Get only the DOS contribution of a single tetrahedron.
Definition: simplex.F90:987
type(simplex_t) function, pointer, public simplex_init(dim, naxis, nshifts, shift, kpoints, equiv, opt)
Constructor for linear simplex methods.
Definition: simplex.F90:178
subroutine, public simplex_dos_1d(esegment, eF, dos)
Get only the DOS contribution of a single segment.
Definition: simplex.F90:558
subroutine, public simplex_end(this)
Destructor for linear simplex methods.
Definition: simplex.F90:412
subroutine, public simplex_weights_1d(esegment, eF, weights, dos)
Get the weights and DOS contribution of a single segment.
Definition: simplex.F90:479
subroutine, public simplex_dos_2d(etriangle, eF, dos)
Get only the DOS contribution of a single triangle.
Definition: simplex.F90:731
subroutine, public simplex_weights_3d(etetra, eF, weights, dos)
Get the weights and DOS contribution of a single tetrahedron.
Definition: simplex.F90:817
subroutine, public simplex_dos(rdim, esimplex, eF, dos)
Get only the DOS contribution of a single simplex.
Definition: simplex.F90:453
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119