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, &
65 end interface leading_dimension_is_known
66
67 interface lead_dim
68 module procedure dlead_dim, zlead_dim
69 module procedure dlead_dim2, zlead_dim2
70 end interface lead_dim
71
72contains
73
74 ! ---------------------------------------------------------
75 subroutine get_divisors(nn, n_divisors, divisors)
76 integer, intent(in) :: nn
77 integer, intent(inout) :: n_divisors
78 integer, intent(out) :: divisors(:)
79
80 integer :: ii, max_d
81
82 push_sub(get_divisors)
83
84 assert(n_divisors > 1)
85 max_d = n_divisors
86
87 n_divisors = 1
88 divisors(n_divisors) = 1
89 do ii = 2, nn / 2
90 if (mod(nn, ii) == 0) then
91 n_divisors = n_divisors + 1
92
93 if (n_divisors > max_d - 1) then
94 message(1) = "Internal error in get_divisors. Please increase n_divisors"
95 call messages_fatal(1)
96 end if
97
98 divisors(n_divisors) = ii
99 end if
100 end do
101 n_divisors = n_divisors + 1
102 divisors(n_divisors) = nn
103
104 pop_sub(get_divisors)
105 end subroutine get_divisors
106
107
108 ! ---------------------------------------------------------
109 character pure function index2axis(idir) result(ch)
110 integer, intent(in) :: idir
111
112 select case (idir)
113 case (1)
114 ch = 'x'
115 case (2)
116 ch = 'y'
117 case (3)
118 ch = 'z'
119 case (4)
120 ch = 'w'
121 case default
122 write(ch,'(i1)') idir
123 end select
124
125 end function index2axis
126
127 ! ---------------------------------------------------------
128 pure function index2axisbz(idir) result(ch)
129 integer, intent(in) :: idir
130 character(len=2) :: ch
131
132 select case (idir)
133 case (1)
134 ch = "kx"
135 case (2)
136 ch = "ky"
137 case (3)
138 ch = "kz"
139 case (4)
140 ch = "kw"
141 case default
142 write(ch,'(i2)') idir
143 end select
144
145 end function index2axisbz
146
147
148 ! ---------------------------------------------------------
149 subroutine output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
150 real(real64), intent(in) :: tensor(:,:)
151 integer, intent(in) :: ndim
152 type(unit_t), intent(in) :: unit
153 logical, optional, intent(in) :: write_average
154 integer, optional, intent(in) :: iunit
155 type(namespace_t), optional, intent(in) :: namespace
156
157 real(real64) :: trace
158 integer :: jj, kk
159 logical :: write_average_
160
161 push_sub(output_tensor)
163 write_average_ = optional_default(write_average, .true.)
164
165 trace = m_zero
166 message(1) = ""
167 do jj = 1, ndim
168 do kk = 1, ndim
169 write(message(1), '(a,f20.6)') trim(message(1)), units_from_atomic(unit, tensor(jj, kk))
170 end do
171 trace = trace + tensor(jj, jj)
172 call messages_info(1, iunit=iunit, namespace=namespace)
173 end do
174
175 if (write_average_) then
176 write(message(1), '(a, f20.6)') 'Isotropic average', units_from_atomic(unit, trace/real(ndim, real64) )
177 call messages_info(1, iunit=iunit, namespace=namespace)
178 end if
179
180 pop_sub(output_tensor)
181 end subroutine output_tensor
182
183
184 ! ---------------------------------------------------------
185 subroutine output_dipole(dipole, ndim, iunit, namespace)
186 real(real64), intent(in) :: dipole(:)
187 integer, intent(in) :: ndim
188 integer, optional, intent(in) :: iunit
189 type(namespace_t), optional, intent(in) :: namespace
190
191 integer :: idir
192
193 push_sub(output_dipole)
194
195 write(message(1), '(a,a20,a17)') 'Dipole:', '[' // trim(units_abbrev(units_out%length)) // ']', &
196 '[' // trim(units_abbrev(unit_debye)) // ']'
197 do idir = 1, ndim
198 write(message(1+idir), '(6x,3a,es14.5,3x,2es14.5)') '<', index2axis(idir), '> = ', &
199 units_from_atomic(units_out%length, dipole(idir)), units_from_atomic(unit_debye, dipole(idir))
200 end do
201 call messages_info(1+ndim, iunit=iunit, namespace=namespace)
202
203 pop_sub(output_dipole)
204 end subroutine output_dipole
205
208 subroutine print_header()
209 use iso_fortran_env
210
211 character(len=256) :: sys_name
212
213 ! Let us print our logo
214 call io_dump_file(stdout, trim(trim(conf%share) // '/logo'))
215
216 ! Let us print the version
217 message(1) = ""
218 message(2) = str_center("Running octopus", 70)
219 message(3) = ""
220 call messages_info(3)
221
222 message(1) = &
223 "Version : " // trim(conf%version)
224 message(2) = &
225 "Commit : "// trim(conf%git_commit)
226 message(3) = &
227 "Configuration time : "// trim(conf%config_time)
228 call messages_info(3)
229
230 message(1) = 'Configuration options : ' // trim(get_config_opts())
231 message(2) = 'Optional libraries :' // trim(get_optional_libraries())
232
233 message(3) = 'Architecture : ' + tostring(oct_arch)
234 call messages_info(3)
235
237
238 message(1) = &
239 "C compiler : "//trim(conf%cc)
240 message(2) = &
241 "C compiler flags : "//trim(conf%cflags)
242 message(3) = &
243 "C++ compiler : "//trim(conf%cxx)
244 message(4) = &
245 "C++ compiler flags : "//trim(conf%cxxflags)
246#ifdef HAVE_FC_COMPILER_VERSION
247 message(5) = "Fortran compiler : "//trim(conf%fc) //" ("//compiler_version()//")"
248#else
249 message(5) = "Fortran compiler : "//trim(conf%fc)
250#endif
251 message(6) = &
252 "Fortran compiler flags : "//trim(conf%fcflags)
253 call messages_info(6)
254
255 message(1) = ""
256 call messages_info(1)
257
258 ! Let us print where we are running
259 call loct_sysname(sys_name)
260 write(message(1), '(a)') "The octopus is swimming in " // trim(sys_name)
261 message(2) = ""
262 call messages_info(2)
263
264 call mpi_world%barrier()
265
266 call print_date("Calculation started on ")
267 end subroutine print_header
268
269
273 character(len=256) function get_config_opts()
274
275 get_config_opts = ''
276#ifdef HAVE_OPENMP
277 get_config_opts = trim(get_config_opts)//' openmp'
278#endif
279#ifdef HAVE_MPI
281#endif
282#ifdef HAVE_CUDA
283 get_config_opts = trim(get_config_opts)//' cuda'
284#endif
285#ifdef HAVE_CUDA_MPI
286 get_config_opts = trim(get_config_opts)//' cuda-mpi'
287#endif
288#ifdef HAVE_LIBXC_FXC
289 get_config_opts = trim(get_config_opts)//' libxc_fxc'
290#endif
291#ifdef HAVE_LIBXC_KXC
292 get_config_opts = trim(get_config_opts)//' libxc_kxc'
293#endif
294#ifdef HAVE_LIBXC_FUNCS
295 get_config_opts = trim(get_config_opts)//' libxc_funcs'
296#endif
297#ifdef HAVE_LIBXC_DEVICE
298 get_config_opts = trim(get_config_opts)//' libxc_device'
299#endif
300#ifdef HAVE_HIP
301 get_config_opts = trim(get_config_opts)//' hip'
302#endif
303#ifdef HAVE_FFTW3_THREADS
304 get_config_opts = trim(get_config_opts)//' fftw3_threads'
305#endif
306#ifdef HAVE_CUBIN
307 get_config_opts = trim(get_config_opts)//' cubin'
308#endif
309#ifdef HAVE_NVTX
310 get_config_opts = trim(get_config_opts)//' nvtx'
311#endif
312
313 end function get_config_opts
314
318 character(len=256) function get_optional_libraries()
319
320 ! keep in alphabetical order, for ease in seeing if something is listed
322#ifdef HAVE_ADIOS2
324#endif
325#ifdef HAVE_BERKELEYGW
327#endif
328#ifdef HAVE_CGAL
330#endif
331#ifdef HAVE_DFTBPLUS
333#endif
334#ifdef HAVE_ELPA
336#endif
337#ifdef HAVE_LIKWID
339#endif
340#ifdef HAVE_LIBVDWXC
342#endif
343#ifdef HAVE_LIBVDWXC_MPI
344 get_optional_libraries = trim(get_optional_libraries)//' libvdwxc_mpi'
345#endif
346#ifdef HAVE_METIS
348#endif
349#ifdef HAVE_NETCDF
351#endif
352#ifdef HAVE_NFFT
354#endif
355#ifdef HAVE_NFFT_3_3
357#endif
358#ifdef HAVE_PARMETIS
360#endif
361#ifdef HAVE_PFFT
363#endif
364#ifdef HAVE_PNFFT
366#endif
367#ifdef HAVE_PSOLVER
369#endif
370#ifdef HAVE_PSPIO
372#endif
373#ifdef HAVE_SCALAPACK
375#endif
376#ifdef HAVE_SPARSKIT
378#endif
379#ifdef HAVE_NLOPT
381#endif
382#ifdef HAVE_VERROU
384#endif
385#ifdef HAVE_WANNIER90
387#endif
388
389 end function get_optional_libraries
390
391 ! ---------------------------------------------------------
392
393 logical function dleading_dimension_is_known(array) result(known)
394 real(real64), target, intent(in) :: array(:, :)
395
396 integer(c_intptr_t) :: addr1, addr2
397
398 known = .true.
399
400 if (ubound(array, dim = 2) > 1) then
401 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
402 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
403 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
404 end if
405
406 end function dleading_dimension_is_known
407
408
409 ! ---------------------------------------------------------
410
411 logical function zleading_dimension_is_known(array) result(known)
412 complex(real64), target, intent(in) :: array(:, :)
413
414 integer(c_intptr_t) :: addr1, addr2
415
416 known = .true.
417
418 if (ubound(array, dim = 2) > 1) then
419 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
420 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
421 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
422 end if
423
424 end function zleading_dimension_is_known
425
426 ! ---------------------------------------------------------
427
428 logical function ileading_dimension_is_known(array) result(known)
429 integer, target, intent(in) :: array(:, :)
430
431 integer(c_intptr_t) :: addr1, addr2
432
433 known = .true.
434
435 if (ubound(array, dim = 2) > 1) then
436 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
437 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
439 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
440 end if
441
442 end function ileading_dimension_is_known
443
444
445 logical function lleading_dimension_is_known(array) result(known)
446 integer(int64), target, intent(in) :: array(:, :)
447
448 integer(c_intptr_t) :: addr1, addr2
449
450 known = .true.
451
452 if (ubound(array, dim = 2) > 1) then
453 addr1 = transfer(c_loc(array(1,1)), 0_c_intptr_t)
454 addr2 = transfer(c_loc(array(1,2)), 0_c_intptr_t)
455
456 known = ubound(array, dim = 1) == (addr2-addr1)/c_sizeof(array(1, 1))
457 end if
458
459 end function lleading_dimension_is_known
460
461
462 ! ---------------------------------------------------------
463
464 logical function dleading_dimension_is_known2(array) result(known)
465 real(real64), target, intent(in) :: array(:, :, :)
466
467 integer(c_intptr_t) :: addr1, addr2
468
469 known = .true.
470
471 if (ubound(array, dim = 2) > 1) then
472 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
473 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
474 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
475 end if
476
478
479
480 ! ---------------------------------------------------------
481
482 logical function zleading_dimension_is_known2(array) result(known)
483 complex(real64), target, intent(in) :: array(:, :, :)
484
485 integer(c_intptr_t) :: addr1, addr2
486
487 known = .true.
488
489 if (ubound(array, dim = 2) > 1) then
490 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
491 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
492 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
493 end if
494
496
497 ! ---------------------------------------------------------
498
499 logical function ileading_dimension_is_known2(array) result(known)
500 integer, target, intent(in) :: array(:, :, :)
501
502 integer(c_intptr_t) :: addr1, addr2
503
504 known = .true.
505
506 if (ubound(array, dim = 2) > 1) then
507 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
508 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
509 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
510 end if
511
513
514
515 logical function lleading_dimension_is_known2(array) result(known)
516 integer(int64), target, intent(in) :: array(:, :, :)
517
518 integer(c_intptr_t) :: addr1, addr2
519
520 known = .true.
521
522 if (ubound(array, dim = 2) > 1) then
523 addr1 = transfer(c_loc(array(1,1,1)), 0_c_intptr_t)
524 addr2 = transfer(c_loc(array(1,2,1)), 0_c_intptr_t)
525 known = ubound(array, dim = 1) == (addr2 - addr1)/c_sizeof(array(1, 1, 1))
526 end if
527
529
530 ! ---------------------------------------------------------
531
532 integer function dlead_dim(array) result(lead_dim)
533 real(real64), intent(in) :: array(:, :)
534
536
537 lead_dim = ubound(array, dim = 1)
538 end function dlead_dim
539
540 ! ---------------------------------------------------------
541
542 integer function zlead_dim(array) result(lead_dim)
543 complex(real64), intent(in) :: array(:, :)
544
546
547 lead_dim = ubound(array, dim = 1)
548 end function zlead_dim
549
550 ! ---------------------------------------------------------
551
552 integer function dlead_dim2(array) result(lead_dim)
553 real(real64), intent(in) :: array(:, :, :)
554
556
557 lead_dim = ubound(array, dim = 1) * ubound(array, dim = 2)
558 end function dlead_dim2
559
560 ! ---------------------------------------------------------
561
562 integer function zlead_dim2(array) result(lead_dim)
563 complex(real64), intent(in) :: array(:, :, :)
564
565 assert(leading_dimension_is_known(array))
566
567 lead_dim = ubound(array, dim = 1) * ubound(array, dim = 2)
568 end function zlead_dim2
569
570 subroutine make_array_larger(array, new_size)
571 integer(int64), allocatable, intent(inout) :: array(:)
572 integer, intent(in) :: new_size
573
574 integer(int64), allocatable :: tmp(:)
575 integer :: copy_size
576
577 push_sub(make_array_larger)
578
579 ! Use allocate here as move_alloc deallocate internally the from array
580 allocate(tmp(1:new_size))
581 copy_size = min(new_size, size(array))
582 tmp(1:copy_size) = array(1:copy_size)
583 safe_deallocate_a(array)
584 call move_alloc(tmp, array)
585
586 pop_sub(make_array_larger)
587 end subroutine make_array_larger
588
590 subroutine write_vectorization_level()
591 character(len=32) :: vec
592 character(kind=c_char) :: c_str(33)
593
594 c_str = c_null_char
595 call get_vectorization_level(c_str)
596 call string_c_to_f(c_str, vec)
597 message(1) = 'Vectorization level : ' // trim(vec)
598 call messages_info(1)
599
600 end subroutine write_vectorization_level
601
602end module utils_oct_m
603
604!! Local Variables:
605!! mode: f90
606!! coding: utf-8
607!! 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:245
character(len=256) function, public get_config_opts()
Character string containing compile-time options.
Definition: utils.F90:369
integer function zlead_dim2(array)
Definition: utils.F90:556
subroutine write_vectorization_level()
Prints the level of vectorization used for the vectorized finite differences.
Definition: utils.F90:584
subroutine, public output_dipole(dipole, ndim, iunit, namespace)
Definition: utils.F90:281
logical function zleading_dimension_is_known2(array)
Definition: utils.F90:476
logical function lleading_dimension_is_known(array)
Definition: utils.F90:439
logical function zleading_dimension_is_known(array)
Definition: utils.F90:405
subroutine, public get_divisors(nn, n_divisors, divisors)
Definition: utils.F90:171
integer function dlead_dim(array)
Definition: utils.F90:526
subroutine, public make_array_larger(array, new_size)
Definition: utils.F90:564
logical function dleading_dimension_is_known2(array)
Definition: utils.F90:458
character(len=256) function, public get_optional_libraries()
Character string containing optional external libraries.
Definition: utils.F90:378
logical function ileading_dimension_is_known(array)
Definition: utils.F90:422
integer function dlead_dim2(array)
Definition: utils.F90:546
character pure function, public index2axis(idir)
Definition: utils.F90:205
logical function lleading_dimension_is_known2(array)
Definition: utils.F90:509
logical function ileading_dimension_is_known2(array)
Definition: utils.F90:493
pure character(len=2) function, public index2axisbz(idir)
Definition: utils.F90:224
subroutine, public print_header()
This subroutine prints the logo followed by information about the compilation and the system....
Definition: utils.F90:304
integer function zlead_dim(array)
Definition: utils.F90:536
logical function dleading_dimension_is_known(array)
Definition: utils.F90:387
void get_vectorization_level(char *level)
Definition: operate.c:1492
int true(void)