Octopus
utils.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2021 S. Ohlmann
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
24
25module utils_oct_m
26 use debug_oct_m
27 use global_oct_m
28 use io_oct_m
29 use iso_c_binding
30 use loct_oct_m
32 use mpi_oct_m
36 use unit_oct_m
38 use string_oct_m
39
40 implicit none
41
42 private
43 public :: &
45 index2axis, &
51 lead_dim, &
55
57 module procedure dleading_dimension_is_known, &
69 end interface leading_dimension_is_known
70
71 interface lead_dim
72 module procedure dlead_dim, zlead_dim
73 module procedure dlead_dim2, zlead_dim2
74 module procedure slead_dim, clead_dim
75 module procedure slead_dim2, clead_dim2
76 end interface lead_dim
77
78contains
79
80 ! ---------------------------------------------------------
81 subroutine get_divisors(nn, n_divisors, divisors)
82 integer, intent(in) :: nn
83 integer, intent(inout) :: n_divisors
84 integer, intent(out) :: divisors(:)
85
86 integer :: ii, max_d
87
88 push_sub(get_divisors)
89
90 assert(n_divisors > 1)
91 max_d = n_divisors
92
93 n_divisors = 1
94 divisors(n_divisors) = 1
95 do ii = 2, nn / 2
96 if (mod(nn, ii) == 0) then
97 n_divisors = n_divisors + 1
98
99 if (n_divisors > max_d - 1) then
100 message(1) = "Internal error in get_divisors. Please increase n_divisors"
101 call messages_fatal(1)
102 end if
103
104 divisors(n_divisors) = ii
105 end if
106 end do
107 n_divisors = n_divisors + 1
108 divisors(n_divisors) = nn
109
110 pop_sub(get_divisors)
111 end subroutine get_divisors
112
113
114 ! ---------------------------------------------------------
115 character pure function index2axis(idir) result(ch)
116 integer, intent(in) :: idir
117
118 select case (idir)
119 case (1)
120 ch = 'x'
121 case (2)
122 ch = 'y'
123 case (3)
124 ch = 'z'
125 case (4)
126 ch = 'w'
127 case default
128 write(ch,'(i1)') idir
129 end select
130
131 end function index2axis
132
133 ! ---------------------------------------------------------
134 pure function index2axisbz(idir) result(ch)
135 integer, intent(in) :: idir
136 character(len=2) :: ch
137
138 select case (idir)
139 case (1)
140 ch = "kx"
141 case (2)
142 ch = "ky"
143 case (3)
144 ch = "kz"
145 case (4)
146 ch = "kw"
147 case default
148 write(ch,'(i2)') idir
149 end select
150
151 end function index2axisbz
152
153
154 ! ---------------------------------------------------------
155 subroutine output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
156 real(real64), intent(in) :: tensor(:,:)
157 integer, intent(in) :: ndim
158 type(unit_t), intent(in) :: unit
159 logical, optional, intent(in) :: write_average
160 integer, optional, intent(in) :: iunit
161 type(namespace_t), optional, intent(in) :: namespace
162
163 real(real64) :: trace
164 integer :: jj, kk
165 logical :: write_average_
167 push_sub(output_tensor)
168
169 write_average_ = optional_default(write_average, .true.)
170
171 trace = m_zero
172 message(1) = ""
173 do jj = 1, ndim
174 do kk = 1, ndim
175 write(message(1), '(a,f20.6)') trim(message(1)), units_from_atomic(unit, tensor(jj, kk))
176 end do
177 trace = trace + tensor(jj, jj)
178 call messages_info(1, iunit=iunit, namespace=namespace)
179 end do
180
181 if (write_average_) then
182 write(message(1), '(a, f20.6)') 'Isotropic average', units_from_atomic(unit, trace/real(ndim, real64) )
183 call messages_info(1, iunit=iunit, namespace=namespace)
184 end if
185
186 pop_sub(output_tensor)
187 end subroutine output_tensor
188
189
190 ! ---------------------------------------------------------
191 subroutine output_dipole(dipole, ndim, iunit, namespace)
192 real(real64), intent(in) :: dipole(:)
193 integer, intent(in) :: ndim
194 integer, optional, intent(in) :: iunit
195 type(namespace_t), optional, intent(in) :: namespace
196
197 integer :: idir
198
199 push_sub(output_dipole)
200
201 write(message(1), '(a,a20,a17)') 'Dipole:', '[' // trim(units_abbrev(units_out%length)) // ']', &
202 '[' // trim(units_abbrev(unit_debye)) // ']'
203 do idir = 1, ndim
204 write(message(1+idir), '(6x,3a,es14.5,3x,2es14.5)') '<', index2axis(idir), '> = ', &
205 units_from_atomic(units_out%length, dipole(idir)), units_from_atomic(unit_debye, dipole(idir))
206 end do
207 call messages_info(1+ndim, iunit=iunit, namespace=namespace)
208
209 pop_sub(output_dipole)
210 end subroutine output_dipole
211
214 subroutine print_header()
215 use iso_fortran_env
216
217 character(len=256) :: sys_name
218
219 ! Let us print our logo
220 call io_dump_file(stdout, trim(trim(conf%share) // '/logo'))
221
222 ! Let us print the version
223 message(1) = ""
224 message(2) = str_center("Running octopus", 70)
225 message(3) = ""
226 call messages_info(3)
227
228 message(1) = &
229 "Version : " // trim(conf%version)
230 message(2) = &
231 "Commit : "// trim(conf%git_commit)
232 message(3) = &
233 "Configuration time : "// trim(conf%config_time)
234 call messages_info(3)
235
236 message(1) = 'Configuration options : ' // trim(get_config_opts())
237 message(2) = 'Optional libraries :' // trim(get_optional_libraries())
238
239 message(3) = 'Architecture : ' + tostring(oct_arch)
240 call messages_info(3)
241
243
244 message(1) = &
245 "C compiler : "//trim(conf%cc)
246 message(2) = &
247 "C compiler flags : "//trim(conf%cflags)
248 message(3) = &
249 "C++ compiler : "//trim(conf%cxx)
250 message(4) = &
251 "C++ compiler flags : "//trim(conf%cxxflags)
252#ifdef HAVE_FC_COMPILER_VERSION
253 message(5) = "Fortran compiler : "//trim(conf%fc) //" ("//compiler_version()//")"
254#else
255 message(5) = "Fortran compiler : "//trim(conf%fc)
256#endif
257 message(6) = &
258 "Fortran compiler flags : "//trim(conf%fcflags)
259 call messages_info(6)
260
261 message(1) = ""
262 call messages_info(1)
263
264 ! Let us print where we are running
265 call loct_sysname(sys_name)
266 write(message(1), '(a)') "The octopus is swimming in " // trim(sys_name)
267 message(2) = ""
268 call messages_info(2)
269
270 call mpi_world%barrier()
271
272 call print_date("Calculation started on ")
273 end subroutine print_header
274
275
279 character(len=256) function get_config_opts()
280
281 get_config_opts = ''
282#ifdef HAVE_OPENMP
283 get_config_opts = trim(get_config_opts)//' openmp'
284#endif
285#ifdef HAVE_MPI
287#endif
288#ifdef HAVE_CUDA
289 get_config_opts = trim(get_config_opts)//' cuda'
290#endif
291#ifdef HAVE_CUDA_MPI
292 get_config_opts = trim(get_config_opts)//' cuda-mpi'
293#endif
294#ifdef HAVE_LIBXC_FXC
295 get_config_opts = trim(get_config_opts)//' libxc_fxc'
296#endif
297#ifdef HAVE_LIBXC_KXC
298 get_config_opts = trim(get_config_opts)//' libxc_kxc'
299#endif
300#ifdef HAVE_LIBXC_FUNCS
301 get_config_opts = trim(get_config_opts)//' libxc_funcs'
302#endif
303#ifdef HAVE_LIBXC_DEVICE
304 get_config_opts = trim(get_config_opts)//' libxc_device'
305#endif
306#ifdef HAVE_HIP
307 get_config_opts = trim(get_config_opts)//' hip'
308#endif
309#ifdef HAVE_FFTW3_THREADS
310 get_config_opts = trim(get_config_opts)//' fftw3_threads'
311#endif
312#ifdef HAVE_CUBIN
313 get_config_opts = trim(get_config_opts)//' cubin'
314#endif
315#ifdef HAVE_NVTX
316 get_config_opts = trim(get_config_opts)//' nvtx'
317#endif
318
319 end function get_config_opts
320
324 character(len=256) function get_optional_libraries()
325
326 ! keep in alphabetical order, for ease in seeing if something is listed
328#ifdef HAVE_ADIOS2
330#endif
331#ifdef HAVE_BERKELEYGW
333#endif
334#ifdef HAVE_CGAL
336#endif
337#ifdef HAVE_DFTBPLUS
339#endif
340#ifdef HAVE_ELPA
342#endif
343#ifdef HAVE_LIKWID
345#endif
346#ifdef HAVE_LIBVDWXC
348#endif
349#ifdef HAVE_LIBVDWXC_MPI
350 get_optional_libraries = trim(get_optional_libraries)//' libvdwxc_mpi'
351#endif
352#ifdef HAVE_MATTERSIM
354#endif
355#ifdef HAVE_METIS
357#endif
358#ifdef HAVE_NETCDF
360#endif
361#ifdef HAVE_NFFT
363#endif
364#ifdef HAVE_PARMETIS
366#endif
367#ifdef HAVE_PFFT
369#endif
370#ifdef HAVE_PNFFT
372#endif
373#ifdef HAVE_PSOLVER
375#endif
376#ifdef HAVE_PSPIO
378#endif
379#ifdef HAVE_SCALAPACK
381#endif
382#ifdef HAVE_SPARSKIT
384#endif
385#ifdef HAVE_NLOPT
387#endif
388#ifdef HAVE_VERROU
390#endif
391#ifdef HAVE_WANNIER90
393#endif
394
395 end function get_optional_libraries
396
397 ! ---------------------------------------------------------
398
399 logical function dleading_dimension_is_known(array) result(known)
400 real(real64), target, intent(in) :: array(:, :)
401
402 integer(c_intptr_t) :: addr1, addr2
403
404 known = .true.
405
406 if (ubound(array, dim = 2) > 1) then
407 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
408 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
409 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
410 end if
411
412 end function dleading_dimension_is_known
413
414
415 ! ---------------------------------------------------------
416
417 logical function zleading_dimension_is_known(array) result(known)
418 complex(real64), target, intent(in) :: array(:, :)
419
420 integer(c_intptr_t) :: addr1, addr2
421
422 known = .true.
423
424 if (ubound(array, dim = 2) > 1) then
425 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
426 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
427 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
428 end if
429
430 end function zleading_dimension_is_known
431
432 ! ---------------------------------------------------------
433
434 logical function ileading_dimension_is_known(array) result(known)
435 integer, target, intent(in) :: array(:, :)
436
437 integer(c_intptr_t) :: addr1, addr2
438
439 known = .true.
440
441 if (ubound(array, dim = 2) > 1) then
442 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
443 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
445 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
446 end if
447
448 end function ileading_dimension_is_known
449
450
451 logical function lleading_dimension_is_known(array) result(known)
452 integer(int64), target, intent(in) :: array(:, :)
453
454 integer(c_intptr_t) :: addr1, addr2
455
456 known = .true.
457
458 if (ubound(array, dim = 2) > 1) then
459 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
460 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
461
462 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
463 end if
464
465 end function lleading_dimension_is_known
466
467
468 ! ---------------------------------------------------------
469
470 logical function sleading_dimension_is_known(array) result(known)
471 real(real32), target, intent(in) :: array(:, :)
472
473 integer(c_intptr_t) :: addr1, addr2
474
475 known = .true.
476
477 if (ubound(array, dim = 2) > 1) then
478 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
479 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
480 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
481 end if
482
483 end function sleading_dimension_is_known
484
485
486 ! ---------------------------------------------------------
487
488 logical function cleading_dimension_is_known(array) result(known)
489 complex(real32), target, intent(in) :: array(:, :)
490
491 integer(c_intptr_t) :: addr1, addr2
492
493 known = .true.
494
495 if (ubound(array, dim = 2) > 1) then
496 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
497 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
498 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
499 end if
500
501 end function cleading_dimension_is_known
502
503
504 ! ---------------------------------------------------------
505
506 logical function dleading_dimension_is_known2(array) result(known)
507 real(real64), target, intent(in) :: array(:, :, :)
508
509 integer(c_intptr_t) :: addr1, addr2
510
511 known = .true.
512
513 if (ubound(array, dim = 2) > 1) then
514 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
515 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
516 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
517 end if
518
520
521
522 ! ---------------------------------------------------------
523
524 logical function zleading_dimension_is_known2(array) result(known)
525 complex(real64), target, intent(in) :: array(:, :, :)
526
527 integer(c_intptr_t) :: addr1, addr2
528
529 known = .true.
530
531 if (ubound(array, dim = 2) > 1) then
532 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
533 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
534 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
535 end if
536
538
539 ! ---------------------------------------------------------
540
541 logical function ileading_dimension_is_known2(array) result(known)
542 integer, target, intent(in) :: array(:, :, :)
543
544 integer(c_intptr_t) :: addr1, addr2
545
546 known = .true.
547
548 if (ubound(array, dim = 2) > 1) then
549 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
550 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
551 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
552 end if
553
555
556
557 logical function lleading_dimension_is_known2(array) result(known)
558 integer(int64), target, intent(in) :: array(:, :, :)
559
560 integer(c_intptr_t) :: addr1, addr2
561
562 known = .true.
563
564 if (ubound(array, dim = 2) > 1) then
565 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
566 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
567 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
568 end if
569
571
572 ! ---------------------------------------------------------
573
574 logical function sleading_dimension_is_known2(array) result(known)
575 real(real32), target, intent(in) :: array(:, :, :)
576
577 integer(c_intptr_t) :: addr1, addr2
578
579 known = .true.
580
581 if (ubound(array, dim = 2) > 1) then
582 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
583 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
584 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
585 end if
586
588
589 ! ---------------------------------------------------------
590
591 logical function cleading_dimension_is_known2(array) result(known)
592 complex(real32), target, intent(in) :: array(:, :, :)
593
594 integer(c_intptr_t) :: addr1, addr2
595
596 known = .true.
597
598 if (ubound(array, dim = 2) > 1) then
599 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
600 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
601 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
602 end if
603
605
606 ! ---------------------------------------------------------
607
608 integer function dlead_dim(array) result(lead_dim)
609 real(real64), intent(in) :: array(:, :)
610
612
613 lead_dim = ubound(array, dim = 1)
614 end function dlead_dim
615
616 ! ---------------------------------------------------------
617
618 integer function zlead_dim(array) result(lead_dim)
619 complex(real64), intent(in) :: array(:, :)
620
622
623 lead_dim = ubound(array, dim = 1)
624 end function zlead_dim
625
626 ! ---------------------------------------------------------
627
628 integer function dlead_dim2(array) result(lead_dim)
629 real(real64), intent(in) :: array(:, :, :)
630
632
633 lead_dim = ubound(array, dim = 1) * ubound(array, dim = 2)
634 end function dlead_dim2
635
636 ! ---------------------------------------------------------
637
638 integer function zlead_dim2(array) result(lead_dim)
639 complex(real64), intent(in) :: array(:, :, :)
640
642
643 lead_dim = ubound(array, dim = 1) * ubound(array, dim = 2)
644 end function zlead_dim2
645
646 ! ---------------------------------------------------------
647
648 integer function slead_dim(array) result(lead_dim)
649 real(real32), intent(in) :: array(:, :)
650
652
653 lead_dim = ubound(array, dim = 1)
654 end function slead_dim
655
656 ! ---------------------------------------------------------
657
658 integer function clead_dim(array) result(lead_dim)
659 complex(real32), intent(in) :: array(:, :)
660
662
663 lead_dim = ubound(array, dim = 1)
664 end function clead_dim
665
666 ! ---------------------------------------------------------
667
668 integer function slead_dim2(array) result(lead_dim)
669 real(real32), intent(in) :: array(:, :, :)
670
672
673 lead_dim = ubound(array, dim = 1) * ubound(array, dim = 2)
674 end function slead_dim2
675
676 ! ---------------------------------------------------------
677
678 integer function clead_dim2(array) result(lead_dim)
679 complex(real32), intent(in) :: array(:, :, :)
680
681 assert(leading_dimension_is_known(array))
682
683 lead_dim = ubound(array, dim = 1) * ubound(array, dim = 2)
684 end function clead_dim2
685
686 subroutine make_array_larger(array, new_size)
687 integer(int64), allocatable, intent(inout) :: array(:)
688 integer, intent(in) :: new_size
689
690 integer(int64), allocatable :: tmp(:)
691 integer :: copy_size
692
693 push_sub(make_array_larger)
694
695 ! Use allocate here as move_alloc deallocate internally the from array
696 allocate(tmp(1:new_size))
697 copy_size = min(new_size, size(array))
698 tmp(1:copy_size) = array(1:copy_size)
699 safe_deallocate_a(array)
700 call move_alloc(tmp, array)
701
702 pop_sub(make_array_larger)
703 end subroutine make_array_larger
704
706 subroutine write_vectorization_level()
707 character(len=32) :: vec
708 character(kind=c_char) :: c_str(33)
709
710 c_str = c_null_char
711 call get_vectorization_level(c_str)
712 call string_c_to_f(c_str, vec)
713 message(1) = 'Vectorization level : ' // trim(vec)
714 call messages_info(1)
715
716 end subroutine write_vectorization_level
717
718end module utils_oct_m
719
720!! Local Variables:
721!! mode: f90
722!! coding: utf-8
723!! End:
Definition: io.F90:116
System information (time, memory, sysname)
Definition: loct.F90:117
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
This module contains interfaces for routines in operate.c.
Definition: operate_f.F90:119
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
subroutine, public output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
Definition: utils.F90:251
character(len=256) function, public get_config_opts()
Character string containing compile-time options.
Definition: utils.F90:375
logical function cleading_dimension_is_known(array)
Definition: utils.F90:482
integer function zlead_dim2(array)
Definition: utils.F90:632
subroutine write_vectorization_level()
Prints the level of vectorization used for the vectorized finite differences.
Definition: utils.F90:700
subroutine, public output_dipole(dipole, ndim, iunit, namespace)
Definition: utils.F90:287
logical function zleading_dimension_is_known2(array)
Definition: utils.F90:518
logical function lleading_dimension_is_known(array)
Definition: utils.F90:445
logical function zleading_dimension_is_known(array)
Definition: utils.F90:411
subroutine, public get_divisors(nn, n_divisors, divisors)
Definition: utils.F90:177
integer function dlead_dim(array)
Definition: utils.F90:602
subroutine, public make_array_larger(array, new_size)
Definition: utils.F90:680
integer function clead_dim(array)
Definition: utils.F90:652
logical function dleading_dimension_is_known2(array)
Definition: utils.F90:500
character(len=256) function, public get_optional_libraries()
Character string containing optional external libraries.
Definition: utils.F90:384
logical function ileading_dimension_is_known(array)
Definition: utils.F90:428
integer function dlead_dim2(array)
Definition: utils.F90:622
integer function slead_dim2(array)
Definition: utils.F90:662
logical function cleading_dimension_is_known2(array)
Definition: utils.F90:585
character pure function, public index2axis(idir)
Definition: utils.F90:211
integer function clead_dim2(array)
Definition: utils.F90:672
logical function lleading_dimension_is_known2(array)
Definition: utils.F90:551
integer function slead_dim(array)
Definition: utils.F90:642
logical function ileading_dimension_is_known2(array)
Definition: utils.F90:535
logical function sleading_dimension_is_known(array)
Definition: utils.F90:464
pure character(len=2) function, public index2axisbz(idir)
Definition: utils.F90:230
subroutine, public print_header()
This subroutine prints the logo followed by information about the compilation and the system....
Definition: utils.F90:310
logical function sleading_dimension_is_known2(array)
Definition: utils.F90:568
integer function zlead_dim(array)
Definition: utils.F90:612
logical function dleading_dimension_is_known(array)
Definition: utils.F90:393
void get_vectorization_level(char *level)
Definition: operate.c:1492
int true(void)