LCOV - code coverage report
Current view: top level - src/motion - helium_io.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:37c9bd6) Lines: 589 808 72.9 %
Date: 2023-03-30 11:55:16 Functions: 13 14 92.9 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2023 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief  I/O subroutines for helium
      10             : !> \author Lukasz Walewski
      11             : !> \date   2009-06-08
      12             : ! **************************************************************************************************
      13             : MODULE helium_io
      14             : 
      15             :    USE cell_types,                      ONLY: get_cell
      16             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      17             :                                               cp_logger_get_default_unit_nr,&
      18             :                                               cp_logger_type
      19             :    USE cp_output_handling,              ONLY: cp_p_file,&
      20             :                                               cp_print_key_finished_output,&
      21             :                                               cp_print_key_should_output,&
      22             :                                               cp_print_key_unit_nr
      23             :    USE cp_parser_methods,               ONLY: parser_get_next_line,&
      24             :                                               parser_get_object
      25             :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      26             :                                               parser_create,&
      27             :                                               parser_release
      28             :    USE cp_units,                        ONLY: cp_unit_from_cp2k,&
      29             :                                               cp_unit_to_cp2k
      30             :    USE helium_common,                   ONLY: helium_cycle_number,&
      31             :                                               helium_cycle_of,&
      32             :                                               helium_is_winding,&
      33             :                                               helium_path_length,&
      34             :                                               helium_pbc
      35             :    USE helium_interactions,             ONLY: helium_total_inter_action,&
      36             :                                               helium_total_link_action,&
      37             :                                               helium_total_pair_action
      38             :    USE helium_types,                    ONLY: &
      39             :         e_id_interact, e_id_kinetic, e_id_potential, e_id_thermo, e_id_total, e_id_virial, &
      40             :         helium_solvent_p_type, helium_solvent_type, rho_num
      41             :    USE input_constants,                 ONLY: &
      42             :         fmt_id_pdb, fmt_id_xyz, helium_cell_shape_cube, helium_cell_shape_octahedron, &
      43             :         helium_sampling_ceperley, helium_sampling_worm, helium_solute_intpot_mwater, &
      44             :         helium_solute_intpot_none, perm_cycle, perm_plain
      45             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      46             :                                               section_vals_type,&
      47             :                                               section_vals_val_get
      48             :    USE kinds,                           ONLY: default_path_length,&
      49             :                                               default_string_length,&
      50             :                                               dp,&
      51             :                                               int_8
      52             :    USE machine,                         ONLY: m_flush
      53             :    USE memory_utilities,                ONLY: reallocate
      54             :    USE message_passing,                 ONLY: mp_para_env_type
      55             :    USE physcon,                         ONLY: angstrom,&
      56             :                                               massunit
      57             :    USE pint_types,                      ONLY: pint_env_type
      58             : #include "../base/base_uses.f90"
      59             : 
      60             :    IMPLICIT NONE
      61             : 
      62             :    PRIVATE
      63             : 
      64             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      65             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'helium_io'
      66             : 
      67             :    CHARACTER(len=*), DIMENSION(6), PARAMETER, PRIVATE :: m_dist_name = (/ &
      68             :                                                          "SINGLEV    ", &
      69             :                                                          "UNIFORM    ", &
      70             :                                                          "LINEAR     ", &
      71             :                                                          "QUADRATIC  ", &
      72             :                                                          "EXPONENTIAL", &
      73             :                                                          "GAUSSIAN   "/)
      74             : 
      75             :    PUBLIC :: helium_read_xyz
      76             :    PUBLIC :: helium_print_rdf
      77             :    PUBLIC :: helium_print_rho
      78             :    PUBLIC :: helium_write_line
      79             :    PUBLIC :: helium_write_setup
      80             :    PUBLIC :: helium_print_energy
      81             :    PUBLIC :: helium_print_vector
      82             :    PUBLIC :: helium_print_plength
      83             :    PUBLIC :: helium_print_coordinates
      84             :    PUBLIC :: helium_print_force
      85             :    PUBLIC :: helium_print_accepts
      86             :    PUBLIC :: helium_print_perm
      87             :    PUBLIC :: helium_print_action
      88             :    PUBLIC :: helium_write_cubefile
      89             : 
      90             : CONTAINS
      91             : 
      92             : ! ***************************************************************************
      93             : !> \brief  Read XYZ coordinates from file
      94             : !> \param coords ...
      95             : !> \param file_name ...
      96             : !> \param para_env ...
      97             : !> \date   2009-06-03
      98             : !> \author Lukasz Walewski
      99             : !> \note   This is a parallel routine, all ranks get coords defined
     100             : ! **************************************************************************************************
     101           0 :    SUBROUTINE helium_read_xyz(coords, file_name, para_env)
     102             : 
     103             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: coords
     104             :       CHARACTER(LEN=default_path_length)                 :: file_name
     105             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     106             : 
     107             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'helium_read_xyz'
     108             : 
     109             :       CHARACTER(LEN=default_string_length)               :: strtmp
     110             :       INTEGER                                            :: frame, handle, istat, j, natom
     111             :       LOGICAL                                            :: found, my_end
     112             :       TYPE(cp_parser_type)                               :: parser
     113             : 
     114           0 :       CALL timeset(routineN, handle)
     115             : 
     116             :       ! check if the file can be accessed
     117           0 :       INQUIRE (FILE=file_name, EXIST=found, IOSTAT=istat)
     118           0 :       IF (istat /= 0) THEN
     119             :          WRITE (UNIT=strtmp, FMT="(A,I0,A)") &
     120             :             "An error occurred inquiring the file <"// &
     121           0 :             TRIM(file_name)//">"
     122           0 :          CPABORT(TRIM(strtmp))
     123             :       END IF
     124           0 :       IF (.NOT. found) THEN
     125           0 :          CPABORT("Coordinate file <"//TRIM(file_name)//"> not found.")
     126             :       END IF
     127             : 
     128             :       CALL parser_create( &
     129             :          parser, &
     130             :          file_name, &
     131             :          para_env=para_env, &
     132           0 :          parse_white_lines=.TRUE.)
     133             : 
     134             :       natom = 0
     135           0 :       frame = 0
     136           0 :       CALL parser_get_next_line(parser, 1)
     137           0 :       Frames: DO
     138             :          ! Atom number
     139           0 :          CALL parser_get_object(parser, natom)
     140           0 :          frame = frame + 1
     141           0 :          IF (frame == 1) THEN
     142           0 :             ALLOCATE (coords(3*natom))
     143             :          ELSE
     144           0 :             strtmp = "Warning: more than one frame on file <"//TRIM(file_name)//">"
     145           0 :             CALL helium_write_line(strtmp)
     146           0 :             strtmp = "Warning: using the first frame only!"
     147           0 :             CALL helium_write_line(strtmp)
     148           0 :             EXIT Frames
     149             :          END IF
     150             :          ! Dummy line
     151           0 :          CALL parser_get_next_line(parser, 2)
     152           0 :          DO j = 1, natom
     153             :             ! Atom coordinates
     154           0 :             READ (parser%input_line, *) strtmp, &
     155           0 :                coords(3*(j - 1) + 1), &
     156           0 :                coords(3*(j - 1) + 2), &
     157           0 :                coords(3*(j - 1) + 3)
     158           0 :             coords(3*(j - 1) + 1) = cp_unit_to_cp2k(coords(3*(j - 1) + 1), "angstrom")
     159           0 :             coords(3*(j - 1) + 2) = cp_unit_to_cp2k(coords(3*(j - 1) + 2), "angstrom")
     160           0 :             coords(3*(j - 1) + 3) = cp_unit_to_cp2k(coords(3*(j - 1) + 3), "angstrom")
     161             :             ! If there's a white line or end of file exit.. otherwise go on
     162           0 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
     163           0 :             my_end = my_end .OR. (LEN_TRIM(parser%input_line) == 0)
     164           0 :             IF (my_end) THEN
     165           0 :                IF (j /= natom) THEN
     166           0 :                   CPABORT("Error in XYZ format.")
     167             :                END IF
     168             :                EXIT Frames
     169             :             END IF
     170             :          END DO
     171             :       END DO Frames
     172           0 :       CALL parser_release(parser)
     173             : 
     174           0 :       CALL timestop(handle)
     175             : 
     176           0 :    END SUBROUTINE helium_read_xyz
     177             : 
     178             : ! ***************************************************************************
     179             : !> \brief  Write helium parameters to the output unit
     180             : !> \param helium ...
     181             : !> \date   2009-06-03
     182             : !> \author Lukasz Walewski
     183             : ! **************************************************************************************************
     184          24 :    SUBROUTINE helium_write_setup(helium)
     185             : 
     186             :       TYPE(helium_solvent_type), POINTER                 :: helium
     187             : 
     188             :       CHARACTER(len=default_string_length)               :: msg_str, my_label, stmp, stmp1, stmp2, &
     189             :                                                             unit_str
     190             :       INTEGER                                            :: i, itmp, unit_nr
     191             :       INTEGER(KIND=int_8)                                :: i8tmp
     192             :       REAL(KIND=dp)                                      :: rtmp, v1, v2, v3
     193             :       REAL(KIND=dp), DIMENSION(3)                        :: my_abc
     194             :       TYPE(cp_logger_type), POINTER                      :: logger
     195             : 
     196          24 :       NULLIFY (logger)
     197          24 :       logger => cp_get_default_logger()
     198          24 :       my_label = "HELIUM| "
     199             : 
     200          24 :       IF (logger%para_env%is_source()) THEN
     201          12 :          unit_nr = cp_logger_get_default_unit_nr(logger)
     202             : 
     203          12 :          WRITE (unit_nr, *)
     204             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     205          12 :             " Number of helium environments:     ", helium%num_env
     206             : 
     207             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     208          12 :             " Number of solvent atoms:           ", helium%atoms
     209             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     210          12 :             " Number of solvent beads:           ", helium%beads
     211             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     212          12 :             " Total number of solvent particles: ", helium%atoms*helium%beads
     213             : 
     214          12 :          unit_str = "angstrom^-3"
     215             :          rtmp = cp_unit_from_cp2k(helium%density, &
     216          12 :                                   unit_str)
     217             :          WRITE (unit_nr, '(T2,A,F12.6)') TRIM(my_label)//" Density   ["// &
     218          12 :             TRIM(unit_str)//"]:", rtmp
     219             : 
     220          12 :          unit_str = "a.m.u."
     221          12 :          rtmp = helium%he_mass_au/massunit
     222             :          WRITE (unit_nr, '(T2,A,F12.6)') TRIM(my_label)//" He Mass   ["// &
     223          12 :             TRIM(unit_str)//"]: ", rtmp
     224             : 
     225          12 :          unit_str = "angstrom"
     226             :          rtmp = cp_unit_from_cp2k(helium%cell_size, &
     227          12 :                                   unit_str)
     228             :          WRITE (unit_nr, '(T2,A,F12.6)') TRIM(my_label)//" Cell size ["// &
     229          12 :             TRIM(unit_str)//"]:   ", rtmp
     230             : 
     231          12 :          IF (helium%periodic) THEN
     232           8 :             SELECT CASE (helium%cell_shape)
     233             :             CASE (helium_cell_shape_cube)
     234           0 :                CALL helium_write_line("PBC cell shape: CUBE.")
     235             :             CASE (helium_cell_shape_octahedron)
     236           8 :                CALL helium_write_line("PBC cell shape: TRUNCATED OCTAHEDRON.")
     237             :             CASE DEFAULT
     238           8 :                CALL helium_write_line("*** Warning: unknown cell shape.")
     239             :             END SELECT
     240             :          ELSE
     241           4 :             CALL helium_write_line("PBC turned off.")
     242             :          END IF
     243             : 
     244          12 :          IF (helium%droplet_radius .LT. HUGE(1.0_dp)) THEN
     245           4 :             WRITE (stmp, *) helium%droplet_radius*angstrom
     246           4 :             CALL helium_write_line("Droplet radius: "//TRIM(ADJUSTL(stmp))//" [angstrom]")
     247             :          END IF
     248             : 
     249             :          ! first step gets incremented during first iteration
     250             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     251          12 :             " First MC step                      :", helium%first_step + 1
     252             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     253          12 :             " Last MC step                       :", helium%last_step
     254             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     255          12 :             " Total number of MC steps           :", helium%num_steps
     256             :          WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     257          12 :             " Number of outer MC trials per step :", helium%iter_rot
     258          12 :          i8tmp = INT(helium%iter_rot, int_8)
     259          12 :          IF (helium%sampling_method == helium_sampling_ceperley) THEN
     260             :             WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     261           8 :                " Number of inner MC trials per step :", helium%iter_norot
     262           8 :             i8tmp = i8tmp*INT(helium%iter_norot, int_8)
     263             :          END IF
     264          12 :          stmp = ""
     265          12 :          WRITE (stmp, *) i8tmp
     266             :          WRITE (unit_nr, '(T2,A)') TRIM(my_label)// &
     267          12 :             " Total number of MC trials per step : "//TRIM(ADJUSTL(stmp))
     268          12 :          i8tmp = INT(helium%num_steps, int_8)
     269          12 :          i8tmp = i8tmp*INT(helium%iter_rot, int_8)
     270          12 :          IF (helium%sampling_method == helium_sampling_ceperley) THEN
     271           8 :             i8tmp = i8tmp*INT(helium%iter_norot, int_8)
     272             :          END IF
     273          12 :          stmp = ""
     274          12 :          WRITE (stmp, *) i8tmp
     275             :          WRITE (unit_nr, '(T2,A)') TRIM(my_label)// &
     276          12 :             " Total number of MC trials          : "//TRIM(ADJUSTL(stmp))
     277             : 
     278          20 :          SELECT CASE (helium%sampling_method)
     279             : 
     280             :          CASE (helium_sampling_ceperley)
     281             : 
     282             :             ! permutation cycle length sampling
     283           8 :             stmp = ""
     284           8 :             CALL helium_write_line(stmp)
     285           8 :             WRITE (stmp, *) helium%maxcycle
     286           8 :             stmp2 = ""
     287             :             WRITE (stmp2, *) "Using maximum permutation cycle length: "// &
     288           8 :                TRIM(ADJUSTL(stmp))
     289           8 :             CALL helium_write_line(stmp2)
     290           8 :             stmp = ""
     291             :             WRITE (stmp, *) "Permutation cycle length distribution: "// &
     292           8 :                TRIM(ADJUSTL(m_dist_name(helium%m_dist_type)))
     293           8 :             CALL helium_write_line(stmp)
     294           8 :             stmp = ""
     295           8 :             stmp1 = ""
     296           8 :             WRITE (stmp1, *) helium%m_ratio
     297           8 :             stmp2 = ""
     298           8 :             WRITE (stmp2, *) helium%m_value
     299             :             WRITE (stmp, *) "Using ratio "//TRIM(ADJUSTL(stmp1))// &
     300           8 :                " for M = "//TRIM(ADJUSTL(stmp2))
     301           8 :             CALL helium_write_line(stmp)
     302           8 :             stmp = ""
     303           8 :             CALL helium_write_line(stmp)
     304             : 
     305             :          CASE (helium_sampling_worm)
     306             : 
     307           4 :             stmp1 = ""
     308           4 :             stmp2 = ""
     309           4 :             CALL helium_write_line(stmp1)
     310           4 :             WRITE (stmp1, *) helium%worm_centroid_drmax
     311             :             WRITE (stmp2, *) "WORM| Centroid move max. displacement: "// &
     312           4 :                TRIM(ADJUSTL(stmp1))
     313           4 :             CALL helium_write_line(stmp2)
     314           4 :             stmp1 = ""
     315           4 :             stmp2 = ""
     316           4 :             WRITE (stmp1, *) helium%worm_staging_l
     317           4 :             WRITE (stmp2, *) "WORM| Maximal staging length: "//TRIM(ADJUSTL(stmp1))
     318           4 :             CALL helium_write_line(stmp2)
     319           4 :             stmp1 = ""
     320           4 :             stmp2 = ""
     321           4 :             WRITE (stmp1, *) helium%worm_open_close_scale
     322           4 :             WRITE (stmp2, *) "WORM| Open/Close scaling: "//TRIM(ADJUSTL(stmp1))
     323           4 :             CALL helium_write_line(stmp2)
     324           4 :             stmp1 = ""
     325           4 :             stmp2 = ""
     326           4 :             WRITE (stmp1, *) helium%worm_allow_open
     327           4 :             WRITE (stmp2, *) "WORM| Open worm sector: "//TRIM(ADJUSTL(stmp1))
     328           4 :             CALL helium_write_line(stmp2)
     329           4 :             stmp1 = ""
     330           4 :             stmp2 = ""
     331           4 :             WRITE (stmp1, *) helium%worm_show_statistics
     332           4 :             WRITE (stmp2, *) "WORM| Print statistics: "//TRIM(ADJUSTL(stmp1))
     333           4 :             CALL helium_write_line(stmp2)
     334           4 :             IF (helium%worm_max_open_cycles > 0 .AND. helium%worm_allow_open) THEN
     335           0 :                stmp1 = ""
     336           0 :                stmp2 = ""
     337           0 :                WRITE (stmp1, *) helium%worm_max_open_cycles
     338           0 :                WRITE (stmp2, *) "WORM| Max. nb of MC cycles in open sector: "//TRIM(ADJUSTL(stmp1))
     339           0 :                CALL helium_write_line(stmp2)
     340             :             END IF
     341           4 :             stmp1 = ""
     342           4 :             CALL helium_write_line(stmp1)
     343             : 
     344             :          CASE DEFAULT
     345           0 :             WRITE (msg_str, *) helium%sampling_method
     346           0 :             msg_str = "Sampling method ("//TRIM(ADJUSTL(msg_str))//") not supported."
     347          12 :             CPABORT(msg_str)
     348             : 
     349             :          END SELECT
     350             : 
     351             :          ! solute related data
     352          12 :          IF (helium%solute_present) THEN
     353             :             WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     354           7 :                " Number of solute atoms:            ", helium%solute_atoms
     355             :             WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     356           7 :                " Number of solute beads:            ", helium%solute_beads
     357             :             WRITE (unit_nr, '(T2,A,1X,I0)') TRIM(my_label)// &
     358           7 :                " Total number of solute particles:  ", helium%solute_atoms* &
     359          14 :                helium%solute_beads
     360             : 
     361           7 :             stmp1 = ""
     362           7 :             SELECT CASE (helium%solute_interaction)
     363             :             CASE (helium_solute_intpot_none)
     364           0 :                WRITE (stmp1, *) "NONE"
     365             :             CASE (helium_solute_intpot_mwater)
     366           7 :                WRITE (stmp1, *) "MWATER"
     367             :             CASE DEFAULT
     368           7 :                WRITE (stmp1, *) "***UNKNOWN***"
     369             :             END SELECT
     370             :             WRITE (unit_nr, '(T2,A,A,A)') &
     371           7 :                TRIM(my_label), &
     372           7 :                " Solute interaction type: ", &
     373          14 :                TRIM(ADJUSTL(stmp1))
     374             : 
     375           7 :             CALL get_cell(helium%solute_cell, abc=my_abc)
     376           7 :             unit_str = "angstrom"
     377           7 :             v1 = cp_unit_from_cp2k(my_abc(1), unit_str)
     378           7 :             v2 = cp_unit_from_cp2k(my_abc(2), unit_str)
     379           7 :             v3 = cp_unit_from_cp2k(my_abc(3), unit_str)
     380             :             WRITE (unit_nr, '(T2,A,F12.6,1X,F12.6,1X,F12.6)') &
     381             :                TRIM(my_label)//" Solute cell size ["// &
     382           7 :                TRIM(unit_str)//"]:   ", v1, v2, v3
     383             :          ELSE
     384           5 :             WRITE (unit_nr, '(T2,A)') TRIM(my_label)//" Solute is NOT present"
     385             :          END IF
     386             :       END IF
     387          24 :       CALL helium_write_line("")
     388             : 
     389             :       ! RDF related settings
     390          24 :       IF (helium%rdf_present) THEN
     391          16 :          WRITE (stmp, '(I6)') helium%rdf_num
     392          16 :          CALL helium_write_line("RDF| number of centers: "//TRIM(stmp))
     393          16 :          rtmp = cp_unit_from_cp2k(helium%rdf_delr, "angstrom")
     394          16 :          WRITE (stmp, '(1X,F12.6)') rtmp
     395          16 :          CALL helium_write_line("RDF| delr [angstrom]  : "//TRIM(stmp))
     396          16 :          rtmp = cp_unit_from_cp2k(helium%rdf_maxr, "angstrom")
     397          16 :          WRITE (stmp, '(1X,F12.6)') rtmp
     398          16 :          CALL helium_write_line("RDF| maxr [angstrom]  : "//TRIM(stmp))
     399          16 :          itmp = helium%rdf_nbin
     400          16 :          WRITE (stmp, '(I6)') itmp
     401          16 :          CALL helium_write_line("RDF| nbin             : "//TRIM(stmp))
     402          16 :          CALL helium_write_line("")
     403             :       ELSE
     404           8 :          CALL helium_write_line("RDF| radial distributions will NOT be calculated.")
     405           8 :          CALL helium_write_line("")
     406             :       END IF
     407             : 
     408             :       ! RHO related settings
     409          24 :       IF (helium%rho_present) THEN
     410          24 :          CALL helium_write_line('RHO| The following densities will be calculated:')
     411         144 :          DO i = 1, rho_num
     412         144 :             IF (helium%rho_property(i)%is_calculated) THEN
     413          24 :                WRITE (stmp, '(A)') 'RHO|    '//TRIM(helium%rho_property(i)%name)
     414          24 :                CALL helium_write_line(TRIM(stmp))
     415             :             END IF
     416             :          END DO
     417          24 :          CALL helium_write_line('RHO|')
     418          24 :          rtmp = cp_unit_from_cp2k(helium%rho_delr, "angstrom")
     419          24 :          WRITE (stmp, '(1X,F12.6)') rtmp
     420          24 :          CALL helium_write_line("RHO| delr [angstrom]  : "//TRIM(stmp))
     421          24 :          rtmp = cp_unit_from_cp2k(helium%rho_maxr, "angstrom")
     422          24 :          WRITE (stmp, '(1X,F12.6)') rtmp
     423          24 :          CALL helium_write_line("RHO| maxr [angstrom]  : "//TRIM(stmp))
     424          24 :          itmp = helium%rho_nbin
     425          24 :          WRITE (stmp, '(I6)') itmp
     426          24 :          CALL helium_write_line("RHO| nbin             : "//TRIM(stmp))
     427          24 :          CALL helium_write_line("")
     428             :       ELSE
     429           0 :          CALL helium_write_line("RHO| Density distributions will NOT be calculated.")
     430           0 :          CALL helium_write_line("")
     431             :       END IF
     432             : 
     433          24 :       RETURN
     434             :    END SUBROUTINE helium_write_setup
     435             : 
     436             : ! ***************************************************************************
     437             : !> \brief  Writes out a line of text to the default output unit
     438             : !> \param line ...
     439             : !> \date   2009-07-10
     440             : !> \author Lukasz Walewski
     441             : ! **************************************************************************************************
     442         956 :    SUBROUTINE helium_write_line(line)
     443             : 
     444             :       CHARACTER(len=*), INTENT(IN)                       :: line
     445             : 
     446             :       CHARACTER(len=default_string_length)               :: my_label
     447             :       INTEGER                                            :: unit_nr
     448             :       TYPE(cp_logger_type), POINTER                      :: logger
     449             : 
     450         956 :       NULLIFY (logger)
     451         956 :       logger => cp_get_default_logger()
     452         956 :       my_label = "HELIUM|"
     453             : 
     454         956 :       IF (logger%para_env%is_source()) THEN
     455         520 :          unit_nr = cp_logger_get_default_unit_nr(logger)
     456         520 :          WRITE (unit_nr, '(T2,A)') TRIM(my_label)//" "//TRIM(line)
     457             :       END IF
     458             : 
     459         956 :       RETURN
     460             :    END SUBROUTINE helium_write_line
     461             : 
     462             : ! ***************************************************************************
     463             : !> \brief  Print energies according to HELIUM%PRINT%ENERGY
     464             : !> \param helium_env ...
     465             : !> \date   2009-06-08
     466             : !> \par    History
     467             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
     468             : !> \author Lukasz Walewski
     469             : ! **************************************************************************************************
     470         100 :    SUBROUTINE helium_print_energy(helium_env)
     471             : 
     472             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
     473             : 
     474             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_energy'
     475             : 
     476             :       INTEGER                                            :: handle, iteration, k, m, unit_nr
     477             :       LOGICAL                                            :: cepsample, file_is_new, should_output
     478             :       REAL(KIND=dp)                                      :: naccptd, ntot
     479         100 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: my_energy
     480             :       TYPE(cp_logger_type), POINTER                      :: logger
     481             :       TYPE(section_vals_type), POINTER                   :: print_key
     482             : 
     483         100 :       CALL timeset(routineN, handle)
     484             : 
     485         100 :       NULLIFY (logger, print_key)
     486         100 :       logger => cp_get_default_logger()
     487             : 
     488         100 :       IF (logger%para_env%is_source()) THEN
     489             :          print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
     490          50 :                                                  "MOTION%PINT%HELIUM%PRINT%ENERGY")
     491             :          should_output = BTEST(cp_print_key_should_output( &
     492             :                                iteration_info=logger%iter_info, &
     493          50 :                                basis_section=print_key), cp_p_file)
     494          50 :          cepsample = helium_env(1)%helium%sampling_method == helium_sampling_ceperley
     495             :       END IF
     496         100 :       CALL helium_env(1)%comm%bcast(should_output, logger%para_env%source)
     497         100 :       CALL helium_env(1)%comm%bcast(cepsample, logger%para_env%source)
     498             : 
     499         100 :       IF (should_output) THEN
     500             : 
     501         100 :          naccptd = 0.0_dp
     502         100 :          IF (cepsample) THEN
     503          80 :             ntot = 0.0_dp
     504         190 :             DO k = 1, SIZE(helium_env)
     505         110 :                ntot = ntot + helium_env(1)%helium%iter_norot*helium_env(1)%helium%iter_rot
     506         480 :                DO m = 1, helium_env(k)%helium%maxcycle
     507         400 :                   naccptd = naccptd + helium_env(k)%helium%num_accepted(helium_env(k)%helium%bisctlog2 + 2, m)
     508             :                END DO
     509             :             END DO
     510             :          ELSE !(wormsample)
     511          20 :             ntot = 0.0_dp
     512          40 :             DO k = 1, SIZE(helium_env)
     513          20 :                naccptd = naccptd + helium_env(k)%helium%num_accepted(1, 1)
     514          40 :                ntot = ntot + helium_env(k)%helium%num_accepted(2, 1)
     515             :             END DO
     516             :          END IF
     517         100 :          CALL helium_env(1)%comm%sum(naccptd)
     518         100 :          CALL helium_env(1)%comm%sum(ntot)
     519             : 
     520         100 :          IF (logger%para_env%is_source()) THEN
     521          50 :             my_energy => helium_env(1)%helium%energy_avrg
     522          50 :             iteration = logger%iter_info%iteration(2)
     523             : 
     524             :             unit_nr = cp_print_key_unit_nr( &
     525             :                       logger, &
     526             :                       print_key, &
     527             :                       middle_name="helium-energy", &
     528             :                       extension=".dat", &
     529          50 :                       is_new_file=file_is_new)
     530             : 
     531          50 :             IF (file_is_new) THEN
     532             :                WRITE (unit_nr, '(A9,7(1X,A20))') &
     533          10 :                   "#    Step", &
     534          10 :                   "            AccRatio", &
     535          10 :                   "               E_pot", &
     536          10 :                   "               E_kin", &
     537          10 :                   "            E_thermo", &
     538          10 :                   "            E_virial", &
     539          10 :                   "             E_inter", &
     540          20 :                   "               E_tot"
     541             :             END IF
     542             : 
     543             :             WRITE (unit_nr, "(I9,7(1X,F20.9))") &
     544          50 :                iteration, &
     545          50 :                naccptd/ntot, &
     546          50 :                my_energy(e_id_potential), &
     547          50 :                my_energy(e_id_kinetic), &
     548          50 :                my_energy(e_id_thermo), &
     549          50 :                my_energy(e_id_virial), &
     550          50 :                my_energy(e_id_interact), &
     551         100 :                my_energy(e_id_total)
     552             : 
     553          50 :             CALL m_flush(unit_nr)
     554          50 :             CALL cp_print_key_finished_output(unit_nr, logger, print_key)
     555             : 
     556             :          END IF
     557             :       END IF
     558             : 
     559         100 :       CALL timestop(handle)
     560             : 
     561         100 :       RETURN
     562         100 :    END SUBROUTINE helium_print_energy
     563             : 
     564             : ! ***************************************************************************
     565             : !> \brief  Print a 3D real vector according to printkey <pkey>
     566             : !> \param helium_env ...
     567             : !> \param pkey ...
     568             : !> \param DATA ...
     569             : !> \param uconv ...
     570             : !> \param col_label ...
     571             : !> \param cmmnt ...
     572             : !> \param fname ...
     573             : !> \param fpos ...
     574             : !> \param avg ...
     575             : !> \date   2014-09-09
     576             : !> \par    History
     577             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
     578             : !> \author Lukasz Walewski
     579             : ! **************************************************************************************************
     580         600 :    SUBROUTINE helium_print_vector(helium_env, pkey, DATA, uconv, col_label, cmmnt, fname, fpos, avg)
     581             : 
     582             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
     583             :       CHARACTER(len=*)                                   :: pkey
     584             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: DATA
     585             :       REAL(KIND=dp)                                      :: uconv
     586             :       CHARACTER(len=*), DIMENSION(3)                     :: col_label
     587             :       CHARACTER(len=*)                                   :: cmmnt, fname
     588             :       CHARACTER(len=*), OPTIONAL                         :: fpos
     589             :       LOGICAL, OPTIONAL                                  :: avg
     590             : 
     591             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_vector'
     592             : 
     593             :       CHARACTER(len=default_string_length)               :: my_fpos
     594             :       INTEGER                                            :: handle, i, irank, msglen, nenv, offset, &
     595             :                                                             unit_nr
     596             :       LOGICAL                                            :: is_new, my_avg, should_output
     597             :       REAL(KIND=dp), DIMENSION(3)                        :: avg_data
     598         600 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: data_p
     599             :       TYPE(cp_logger_type), POINTER                      :: logger
     600             :       TYPE(section_vals_type), POINTER                   :: psection
     601             : 
     602         600 :       CALL timeset(routineN, handle)
     603             : 
     604         600 :       IF (PRESENT(avg)) THEN
     605         300 :          my_avg = avg
     606             :       ELSE
     607             :          my_avg = .FALSE.
     608             :       END IF
     609             : 
     610         600 :       IF (PRESENT(fpos)) THEN
     611         300 :          my_fpos = fpos
     612             :       ELSE
     613         300 :          my_fpos = "APPEND"
     614             :       END IF
     615             : 
     616         600 :       NULLIFY (logger, psection)
     617         600 :       logger => cp_get_default_logger()
     618             : 
     619         600 :       psection => section_vals_get_subs_vals(helium_env(1)%helium%input, pkey)
     620             :       should_output = BTEST(cp_print_key_should_output( &
     621             :                             iteration_info=logger%iter_info, &
     622         600 :                             basis_section=psection), cp_p_file)
     623             : 
     624         600 :       IF (.NOT. should_output) THEN
     625          30 :          CALL timestop(handle)
     626          30 :          RETURN
     627             :       END IF
     628             : 
     629         570 :       IF (my_avg) THEN
     630             :          ! average data over all processors and environments
     631         300 :          avg_data(:) = 0.0_dp
     632         300 :          msglen = SIZE(avg_data)
     633         690 :          DO i = 0, SIZE(helium_env) - 1
     634        1860 :             avg_data(:) = avg_data(:) + DATA(msglen*i + 1:msglen*(i + 1))
     635             :          END DO
     636         300 :          CALL helium_env(1)%comm%sum(avg_data)
     637         300 :          nenv = helium_env(1)%helium%num_env
     638        1200 :          avg_data(:) = avg_data(:)/REAL(nenv, dp)
     639             :       ELSE
     640             :          ! gather data from all processors
     641         270 :          offset = 0
     642         405 :          DO i = 1, logger%para_env%mepos
     643         405 :             offset = offset + helium_env(1)%env_all(i)
     644             :          END DO
     645             : 
     646        2430 :          helium_env(1)%helium%rtmp_3_np_1d = 0.0_dp
     647         270 :          msglen = SIZE(avg_data)
     648         630 :          DO i = 0, SIZE(helium_env) - 1
     649        2790 :             helium_env(1)%helium%rtmp_3_np_1d(msglen*(offset + i) + 1:msglen*(offset + i + 1)) = DATA(msglen*i + 1:msglen*(i + 1))
     650             :          END DO
     651        4590 :          CALL helium_env(1)%comm%sum(helium_env(1)%helium%rtmp_3_np_1d)
     652             :       END IF
     653             : 
     654             :       unit_nr = cp_print_key_unit_nr( &
     655             :                 logger, &
     656             :                 psection, &
     657             :                 middle_name=fname, &
     658             :                 extension=".dat", &
     659             :                 file_position=my_fpos, &
     660         570 :                 is_new_file=is_new)
     661             : 
     662         570 :       IF (logger%para_env%is_source()) THEN
     663             : 
     664         285 :          IF (is_new) THEN
     665             :             ! comment
     666         177 :             IF (cmmnt .NE. "") THEN
     667         177 :                WRITE (unit_nr, '(A)') "# "//cmmnt
     668             :             END IF
     669             :             ! column labels
     670             :             WRITE (unit_nr, '(A2,A18,1X,A20,1X,A20)') &
     671         177 :                "# ", &
     672         177 :                col_label(1), &
     673         177 :                col_label(2), &
     674         354 :                col_label(3)
     675             :          END IF
     676             : 
     677         285 :          IF (my_avg) THEN
     678         600 :             DO i = 1, 3
     679         450 :                WRITE (unit_nr, '(E27.20)', ADVANCE='NO') uconv*avg_data(i)
     680         600 :                IF (i .LT. 3) THEN
     681         300 :                   WRITE (unit_nr, '(1X)', ADVANCE='NO')
     682             :                END IF
     683             :             END DO
     684         150 :             WRITE (unit_nr, '(A)') ""
     685             :          ELSE
     686             :             ! iterate over processors/helium environments
     687         495 :             DO irank = 1, helium_env(1)%helium%num_env
     688             :                ! unpack data (actually point to the right fragment only)
     689         360 :                msglen = SIZE(avg_data)
     690         360 :                offset = (irank - 1)*msglen
     691         360 :                data_p => helium_env(1)%helium%rtmp_3_np_1d(offset + 1:offset + msglen)
     692             :                ! write out the data
     693        1440 :                DO i = 1, 3
     694        1080 :                   WRITE (unit_nr, '(E27.20)', ADVANCE='NO') uconv*data_p(i)
     695        1440 :                   IF (i .LT. 3) THEN
     696         720 :                      WRITE (unit_nr, '(1X)', ADVANCE='NO')
     697             :                   END IF
     698             :                END DO
     699         495 :                WRITE (unit_nr, '(A)') ""
     700             :             END DO
     701             :          END IF
     702             : 
     703         285 :          CALL m_flush(unit_nr)
     704         285 :          CALL cp_print_key_finished_output(unit_nr, logger, psection)
     705             : 
     706             :       END IF
     707             : 
     708         570 :       CALL timestop(handle)
     709             : 
     710         570 :       RETURN
     711         600 :    END SUBROUTINE helium_print_vector
     712             : 
     713             : ! ***************************************************************************
     714             : !> \brief  Print acceptance counts according to HELIUM%PRINT%ACCEPTS
     715             : !> \param helium_env ...
     716             : !> \date   2010-05-27
     717             : !> \par    History
     718             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
     719             : !> \author Lukasz Walewski
     720             : ! **************************************************************************************************
     721         100 :    SUBROUTINE helium_print_accepts(helium_env)
     722             : 
     723             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
     724             : 
     725             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_accepts'
     726             : 
     727             :       INTEGER                                            :: handle, i, j, unit_nr
     728             :       LOGICAL                                            :: file_is_new, should_output
     729             :       TYPE(cp_logger_type), POINTER                      :: logger
     730             :       TYPE(section_vals_type), POINTER                   :: print_key
     731             : 
     732         100 :       CALL timeset(routineN, handle)
     733             : 
     734         100 :       NULLIFY (logger, print_key)
     735         100 :       logger => cp_get_default_logger()
     736             : 
     737         100 :       IF (logger%para_env%is_source()) THEN
     738             :          print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
     739          50 :                                                  "MOTION%PINT%HELIUM%PRINT%ACCEPTS")
     740             :          should_output = BTEST(cp_print_key_should_output( &
     741             :                                iteration_info=logger%iter_info, &
     742          50 :                                basis_section=print_key), cp_p_file)
     743             : 
     744          50 :          IF (should_output) THEN
     745             :             unit_nr = cp_print_key_unit_nr( &
     746             :                       logger, &
     747             :                       print_key, &
     748             :                       middle_name="helium-accepts", &
     749             :                       extension=".dat", &
     750           0 :                       is_new_file=file_is_new)
     751             : 
     752           0 :             IF (file_is_new) THEN
     753             :                WRITE (unit_nr, '(A8,1X,A15,1X,A20)', ADVANCE='NO') &
     754           0 :                   "# Length", &
     755           0 :                   "         Trials", &
     756           0 :                   "            Selected"
     757           0 :                DO j = 1, helium_env(1)%helium%bisctlog2
     758           0 :                   WRITE (unit_nr, '(A17,1X,I3)', ADVANCE='NO') "            Level", j
     759             :                END DO
     760           0 :                WRITE (unit_nr, '(A)') ""
     761             :             END IF
     762             : 
     763           0 :             DO i = 1, helium_env(1)%helium%maxcycle
     764           0 :                WRITE (unit_nr, '(I3)', ADVANCE='NO') i
     765           0 :                DO j = 1, helium_env(1)%helium%bisctlog2 + 2
     766           0 :                   WRITE (unit_nr, '(1X,F20.2)', ADVANCE='NO') helium_env(1)%helium%num_accepted(j, i)
     767             :                END DO
     768           0 :                WRITE (unit_nr, '(A)') ""
     769             :             END DO
     770           0 :             WRITE (unit_nr, '(A)') "&"
     771             : 
     772           0 :             CALL m_flush(unit_nr)
     773           0 :             CALL cp_print_key_finished_output(unit_nr, logger, print_key)
     774             : 
     775             :          END IF
     776             :       END IF
     777             : 
     778         100 :       CALL timestop(handle)
     779         100 :       RETURN
     780             :    END SUBROUTINE helium_print_accepts
     781             : 
     782             : ! ***************************************************************************
     783             : !> \brief  Print permutation state according to HELIUM%PRINT%PERM
     784             : !> \param helium_env ...
     785             : !> \date   2010-06-07
     786             : !> \par    History
     787             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
     788             : !> \author Lukasz Walewski
     789             : ! **************************************************************************************************
     790         100 :    SUBROUTINE helium_print_perm(helium_env)
     791             : 
     792             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
     793             : 
     794             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'helium_print_perm'
     795             : 
     796             :       CHARACTER                                          :: left_delim, right_delim
     797             :       CHARACTER(len=default_string_length)               :: msg_str, my_middle_name, stmp
     798             :       INTEGER                                            :: curat, handle, i, irank, j, lb, msglen, &
     799             :                                                             nused, offset, outformat, ub, unit_nr
     800         100 :       INTEGER, DIMENSION(:), POINTER                     :: my_cycle, my_perm, used_indices
     801             :       LOGICAL                                            :: first, first_cycle, should_output
     802             :       TYPE(cp_logger_type), POINTER                      :: logger
     803             :       TYPE(section_vals_type), POINTER                   :: print_key
     804             : 
     805         100 :       CALL timeset(routineN, handle)
     806             : 
     807         100 :       NULLIFY (logger, print_key)
     808         100 :       NULLIFY (used_indices)
     809         100 :       logger => cp_get_default_logger()
     810             : 
     811             :       ! determine offset for arrays
     812         100 :       offset = 0
     813         150 :       DO i = 1, logger%para_env%mepos
     814         150 :          offset = offset + helium_env(1)%env_all(i)
     815             :       END DO
     816             : 
     817             :       print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
     818         100 :                                               "MOTION%PINT%HELIUM%PRINT%PERM")
     819             :       should_output = BTEST(cp_print_key_should_output( &
     820             :                             iteration_info=logger%iter_info, &
     821         100 :                             basis_section=print_key), cp_p_file)
     822             : 
     823         100 :       IF (.NOT. should_output) THEN
     824         100 :          CALL timestop(handle)
     825         100 :          RETURN
     826             :       END IF
     827             : 
     828             :       ! get the output type
     829           0 :       CALL section_vals_val_get(print_key, "FORMAT", i_val=outformat)
     830           0 :       IF (outformat .EQ. perm_cycle) THEN
     831             :          ! gather positions from all processors
     832           0 :          helium_env(1)%helium%rtmp_3_atoms_beads_np_1d = 0.0_dp
     833           0 :          j = SIZE(helium_env(1)%helium%rtmp_3_atoms_beads_1d)
     834           0 :          DO i = 1, SIZE(helium_env)
     835             :             helium_env(1)%helium%rtmp_3_atoms_beads_np_1d(j*(offset + i - 1) + 1:j*(offset + i)) = &
     836           0 :                PACK(helium_env(i)%helium%pos(:, :, 1:helium_env(1)%helium%beads), .TRUE.)
     837             :          END DO
     838           0 :          CALL helium_env(1)%comm%sum(helium_env(1)%helium%rtmp_3_atoms_beads_np_1d)
     839             :          ! set logical mask for unpacking coordinates gathered from other ranks
     840           0 :          helium_env(1)%helium%ltmp_3_atoms_beads_3d(:, :, :) = .TRUE.
     841             :       END IF
     842             : 
     843             :       ! gather permutation state from all processors to logger%para_env%source
     844           0 :       helium_env(1)%helium%itmp_atoms_np_1d(:) = 0
     845           0 :       msglen = SIZE(helium_env(1)%helium%permutation)
     846           0 :       DO i = 1, SIZE(helium_env)
     847           0 :          helium_env(1)%helium%itmp_atoms_np_1d(msglen*(offset + i - 1) + 1:msglen*(offset + i)) = helium_env(i)%helium%permutation
     848             :       END DO
     849             : 
     850           0 :       CALL helium_env(1)%comm%sum(helium_env(1)%helium%itmp_atoms_np_1d)
     851             : 
     852           0 :       IF (logger%para_env%is_source()) THEN
     853             : 
     854             :          ! iterate over helium environments
     855           0 :          DO irank = 1, helium_env(1)%helium%num_env
     856             : 
     857             :             ! generate one file per environment
     858           0 :             stmp = ""
     859           0 :             WRITE (stmp, *) irank
     860           0 :             my_middle_name = "helium-perm-"//TRIM(ADJUSTL(stmp))
     861             :             unit_nr = cp_print_key_unit_nr( &
     862             :                       logger, &
     863             :                       print_key, &
     864             :                       middle_name=TRIM(my_middle_name), &
     865           0 :                       extension=".dat")
     866             : 
     867             :             ! unpack permutation state (actually point to the right section only)
     868           0 :             lb = (irank - 1)*helium_env(1)%helium%atoms + 1
     869           0 :             ub = irank*helium_env(1)%helium%atoms
     870           0 :             my_perm => helium_env(1)%helium%itmp_atoms_np_1d(lb:ub)
     871             : 
     872           0 :             SELECT CASE (outformat)
     873             : 
     874             :             CASE (perm_cycle)
     875             :                ! write the permutation grouped into cycles
     876             : 
     877             :                ! unpack coordinates (necessary only for winding path delimiters)
     878           0 :                msglen = SIZE(helium_env(1)%helium%rtmp_3_atoms_beads_1d)
     879           0 :                offset = (irank - 1)*msglen
     880             :                helium_env(1)%helium%work(:, :, 1:helium_env(1)%helium%beads) = &
     881             :                   UNPACK(helium_env(1)%helium%rtmp_3_atoms_beads_np_1d(offset + 1:offset + msglen), &
     882           0 :                          MASK=helium_env(1)%helium%ltmp_3_atoms_beads_3d, FIELD=0.0_dp)
     883             : 
     884           0 :                curat = 1
     885           0 :                nused = 0
     886           0 :                first_cycle = .TRUE.
     887           0 :                DO WHILE (curat .LE. helium_env(1)%helium%atoms)
     888             : 
     889             :                   ! get the permutation cycle the current atom belongs to
     890           0 :                   my_cycle => helium_cycle_of(curat, my_perm)
     891             : 
     892             :                   ! include the current cycle in the pool of "used" indices
     893           0 :                   nused = nused + SIZE(my_cycle)
     894           0 :                   CALL reallocate(used_indices, 1, nused)
     895           0 :                   used_indices(nused - SIZE(my_cycle) + 1:nused) = my_cycle(1:SIZE(my_cycle))
     896             : 
     897             :                   ! select delimiters according to the cycle's winding state
     898           0 :                   IF (helium_is_winding(helium_env(1)%helium, curat, helium_env(1)%helium%work, my_perm)) THEN
     899           0 :                      left_delim = "["
     900           0 :                      right_delim = "]"
     901             :                   ELSE
     902           0 :                      left_delim = "("
     903           0 :                      right_delim = ")"
     904             :                   END IF
     905             : 
     906             :                   ! cycle delimiter
     907           0 :                   IF (first_cycle) THEN
     908             :                      first_cycle = .FALSE.
     909             :                   ELSE
     910           0 :                      WRITE (unit_nr, '(1X)', ADVANCE='NO')
     911             :                   END IF
     912             : 
     913             :                   ! write out the current cycle
     914           0 :                   WRITE (unit_nr, '(A1)', ADVANCE='NO') left_delim
     915           0 :                   first = .TRUE.
     916           0 :                   DO i = 1, SIZE(my_cycle)
     917           0 :                      IF (first) THEN
     918             :                         first = .FALSE.
     919             :                      ELSE
     920           0 :                         WRITE (unit_nr, '(1X)', ADVANCE='NO')
     921             :                      END IF
     922           0 :                      WRITE (unit_nr, '(I0)', ADVANCE='NO') my_cycle(i)
     923             :                   END DO
     924           0 :                   WRITE (unit_nr, '(A1)', ADVANCE='NO') right_delim
     925             : 
     926             :                   ! clean up
     927           0 :                   DEALLOCATE (my_cycle)
     928           0 :                   NULLIFY (my_cycle)
     929             : 
     930             :                   ! try to increment the current atom index
     931           0 :                   DO WHILE (ANY(used_indices .EQ. curat))
     932           0 :                      curat = curat + 1
     933             :                   END DO
     934             : 
     935             :                END DO
     936           0 :                WRITE (unit_nr, *)
     937             : 
     938           0 :                DEALLOCATE (used_indices)
     939           0 :                NULLIFY (used_indices)
     940             : 
     941             :             CASE (perm_plain)
     942             :                ! write the plain permutation
     943             : 
     944           0 :                first = .TRUE.
     945           0 :                DO i = 1, helium_env(1)%helium%atoms
     946           0 :                   IF (first) THEN
     947             :                      first = .FALSE.
     948             :                   ELSE
     949           0 :                      WRITE (unit_nr, '(1X)', ADVANCE='NO')
     950             :                   END IF
     951           0 :                   WRITE (unit_nr, '(I0)', ADVANCE='NO') my_perm(i)
     952             :                END DO
     953           0 :                WRITE (unit_nr, '(A)') ""
     954             : 
     955             :             CASE default
     956             : 
     957           0 :                msg_str = "Format for permutation output unknown."
     958           0 :                CPABORT(msg_str)
     959             : 
     960             :             END SELECT
     961             : 
     962           0 :             CALL m_flush(unit_nr)
     963           0 :             CALL cp_print_key_finished_output(unit_nr, logger, print_key)
     964             : 
     965             :          END DO
     966             : 
     967             :       END IF
     968             : 
     969           0 :       CALL timestop(handle)
     970             : 
     971           0 :       RETURN
     972         100 :    END SUBROUTINE helium_print_perm
     973             : 
     974             : ! **************************************************************************************************
     975             : !> \brief Print helium action file to HELIUM%PRINT%ACTION
     976             : !> \param pint_env ...
     977             : !> \param helium_env ...
     978             : !> \date   2016-06-07
     979             : !> \par    History
     980             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
     981             : !> \author Felix Uhl
     982             : ! **************************************************************************************************
     983         100 :    SUBROUTINE helium_print_action(pint_env, helium_env)
     984             : 
     985             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
     986             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
     987             : 
     988             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_action'
     989             : 
     990             :       CHARACTER(len=default_string_length)               :: my_middle_name, stmp
     991             :       INTEGER                                            :: handle, i, irank, iteration, k, offset, &
     992             :                                                             unit_nr
     993             :       LOGICAL                                            :: file_is_new, should_output
     994         100 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: tmp_inter_action, tmp_link_action, &
     995         100 :                                                             tmp_pair_action
     996             :       TYPE(cp_logger_type), POINTER                      :: logger
     997             :       TYPE(section_vals_type), POINTER                   :: print_key
     998             : 
     999         100 :       CALL timeset(routineN, handle)
    1000             : 
    1001         100 :       NULLIFY (logger, print_key)
    1002         100 :       logger => cp_get_default_logger()
    1003             : 
    1004             :       ! determine offset for arrays
    1005         100 :       offset = 0
    1006         150 :       DO i = 1, logger%para_env%mepos
    1007         150 :          offset = offset + helium_env(1)%env_all(i)
    1008             :       END DO
    1009             : 
    1010             :       print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
    1011         100 :                                               "MOTION%PINT%HELIUM%PRINT%ACTION")
    1012             :       should_output = BTEST(cp_print_key_should_output( &
    1013             :                             iteration_info=logger%iter_info, &
    1014         100 :                             basis_section=print_key), cp_p_file)
    1015             : 
    1016         100 :       IF (.NOT. should_output) THEN
    1017          10 :          CALL timestop(handle)
    1018          10 :          RETURN
    1019             :       END IF
    1020             : 
    1021         210 :       DO k = 1, SIZE(helium_env)
    1022         120 :          helium_env(k)%helium%link_action = helium_total_link_action(helium_env(k)%helium)
    1023         120 :          helium_env(k)%helium%pair_action = helium_total_pair_action(helium_env(k)%helium)
    1024         210 :          helium_env(k)%helium%inter_action = helium_total_inter_action(pint_env, helium_env(k)%helium)
    1025             :       END DO
    1026             : 
    1027          90 :       NULLIFY (tmp_link_action)
    1028          90 :       NULLIFY (tmp_pair_action)
    1029          90 :       NULLIFY (tmp_inter_action)
    1030         270 :       ALLOCATE (tmp_link_action(helium_env(1)%helium%num_env))
    1031         270 :       ALLOCATE (tmp_pair_action(helium_env(1)%helium%num_env))
    1032         270 :       ALLOCATE (tmp_inter_action(helium_env(1)%helium%num_env))
    1033         330 :       tmp_link_action(:) = 0.0_dp
    1034         330 :       tmp_pair_action(:) = 0.0_dp
    1035         330 :       tmp_inter_action(:) = 0.0_dp
    1036             :       ! gather Action from all processors to logger%para_env%source
    1037         210 :       DO k = 1, SIZE(helium_env)
    1038         120 :          tmp_link_action(offset + k) = helium_env(k)%helium%link_action
    1039         120 :          tmp_pair_action(offset + k) = helium_env(k)%helium%pair_action
    1040         210 :          tmp_inter_action(offset + k) = helium_env(k)%helium%inter_action
    1041             :       END DO
    1042         570 :       CALL helium_env(1)%comm%sum(tmp_link_action)
    1043         570 :       CALL helium_env(1)%comm%sum(tmp_pair_action)
    1044         570 :       CALL helium_env(1)%comm%sum(tmp_inter_action)
    1045             : 
    1046          90 :       IF (logger%para_env%is_source()) THEN
    1047          45 :          iteration = logger%iter_info%iteration(2)
    1048             :          ! iterate over processors/helium environments
    1049         165 :          DO irank = 1, helium_env(1)%helium%num_env
    1050             : 
    1051             :             ! generate one file per helium_env
    1052         120 :             stmp = ""
    1053         120 :             WRITE (stmp, *) irank
    1054         120 :             my_middle_name = "helium-action-"//TRIM(ADJUSTL(stmp))
    1055             :             unit_nr = cp_print_key_unit_nr( &
    1056             :                       logger, &
    1057             :                       print_key, &
    1058             :                       middle_name=TRIM(my_middle_name), &
    1059             :                       extension=".dat", &
    1060         120 :                       is_new_file=file_is_new)
    1061             : 
    1062         120 :             IF (file_is_new) THEN
    1063             :                WRITE (unit_nr, '(A9,3(1X,A25))') &
    1064          21 :                   "#    Step", &
    1065          21 :                   "     He_Total_Link_Action", &
    1066          21 :                   "     He_Total_Pair_Action", &
    1067          42 :                   "     He_Total_Interaction"
    1068             :             END IF
    1069             : 
    1070             :             WRITE (unit_nr, "(I9,3(1X,F25.14))") &
    1071         120 :                iteration, &
    1072         120 :                tmp_link_action(irank), &
    1073         120 :                tmp_pair_action(irank), &
    1074         240 :                tmp_inter_action(irank)
    1075             : 
    1076         120 :             CALL m_flush(unit_nr)
    1077         165 :             CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1078             : 
    1079             :          END DO
    1080             :       END IF
    1081             : 
    1082          90 :       DEALLOCATE (tmp_link_action)
    1083          90 :       DEALLOCATE (tmp_pair_action)
    1084          90 :       DEALLOCATE (tmp_inter_action)
    1085          90 :       NULLIFY (tmp_link_action)
    1086          90 :       NULLIFY (tmp_pair_action)
    1087          90 :       NULLIFY (tmp_inter_action)
    1088             : 
    1089          90 :       CALL timestop(handle)
    1090             : 
    1091          90 :       RETURN
    1092         100 :    END SUBROUTINE helium_print_action
    1093             : 
    1094             : ! ***************************************************************************
    1095             : !> \brief  Print coordinates according to HELIUM%PRINT%COORDINATES
    1096             : !> \param helium_env ...
    1097             : !> \date   2009-07-16
    1098             : !> \par    History
    1099             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
    1100             : !> \author Lukasz Walewski
    1101             : ! **************************************************************************************************
    1102         100 :    SUBROUTINE helium_print_coordinates(helium_env)
    1103             : 
    1104             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
    1105             : 
    1106             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_coordinates'
    1107             : 
    1108             :       CHARACTER(3)                                       :: resName
    1109             :       CHARACTER(len=default_string_length)               :: fmt_string, my_middle_name, stmp
    1110             :       INTEGER                                            :: handle, i, ia, ib, ib1, ib2, ic, icycle, &
    1111             :                                                             irank, j, k, msglen, offset, &
    1112             :                                                             outformat, tmp1, tmp2, unit_nr
    1113         100 :       INTEGER, DIMENSION(:), POINTER                     :: my_perm
    1114             :       LOGICAL                                            :: are_connected, is_winding, ltmp, &
    1115             :                                                             should_output
    1116             :       REAL(KIND=dp)                                      :: xtmp, ytmp, ztmp
    1117             :       REAL(KIND=dp), DIMENSION(3)                        :: r0, r1, r2
    1118             :       TYPE(cp_logger_type), POINTER                      :: logger
    1119             :       TYPE(section_vals_type), POINTER                   :: print_key
    1120             : 
    1121         100 :       CALL timeset(routineN, handle)
    1122             : 
    1123         100 :       NULLIFY (logger, print_key)
    1124         100 :       logger => cp_get_default_logger()
    1125             : 
    1126             :       ! determine offset for arrays
    1127         100 :       offset = 0
    1128         150 :       DO i = 1, logger%para_env%mepos
    1129         150 :          offset = offset + helium_env(1)%env_all(i)
    1130             :       END DO
    1131             : 
    1132             :       print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
    1133         100 :                                               "MOTION%PINT%HELIUM%PRINT%COORDINATES")
    1134             :       should_output = BTEST(cp_print_key_should_output( &
    1135             :                             iteration_info=logger%iter_info, &
    1136         100 :                             basis_section=print_key), cp_p_file)
    1137             : 
    1138         100 :       IF (.NOT. should_output) THEN
    1139          80 :          CALL timestop(handle)
    1140          80 :          RETURN
    1141             :       END IF
    1142             : 
    1143             :       ! prepare the coordinates for output (use unit cell centered around r0)
    1144          70 :       DO k = 1, SIZE(helium_env)
    1145         200 :          r0(:) = helium_env(k)%helium%center(:)
    1146         320 :          DO ia = 1, helium_env(k)%helium%atoms
    1147        4300 :             DO ib = 1, helium_env(k)%helium%beads
    1148       16000 :                r1(:) = helium_env(k)%helium%pos(:, ia, ib) - r0(:)
    1149       16000 :                r2(:) = helium_env(k)%helium%pos(:, ia, ib) - r0(:)
    1150        4000 :                CALL helium_pbc(helium_env(k)%helium, r2)
    1151        4000 :                ltmp = .FALSE.
    1152       16000 :                DO ic = 1, 3
    1153       16000 :                   IF (ABS(r1(ic) - r2(ic)) .GT. 100.0_dp*EPSILON(0.0_dp)) THEN
    1154           0 :                      ltmp = .TRUE.
    1155           0 :                      CYCLE
    1156             :                   END IF
    1157             :                END DO
    1158        4250 :                IF (ltmp) THEN
    1159           0 :                   helium_env(k)%helium%work(:, ia, ib) = r0(:) + r2(:)
    1160             :                ELSE
    1161       16000 :                   helium_env(k)%helium%work(:, ia, ib) = helium_env(k)%helium%pos(:, ia, ib)
    1162             :                END IF
    1163             :             END DO
    1164             :          END DO
    1165             :       END DO
    1166             : 
    1167             :       ! gather positions from all processors to logger%para_env%source
    1168       24020 :       helium_env(1)%helium%rtmp_3_atoms_beads_np_1d = 0.0_dp
    1169          20 :       j = SIZE(helium_env(1)%helium%rtmp_3_atoms_beads_1d)
    1170          70 :       DO i = 1, SIZE(helium_env)
    1171             :          helium_env(1)%helium%rtmp_3_atoms_beads_np_1d(j*(offset + i - 1) + 1:j*(offset + i)) = &
    1172       12070 :             PACK(helium_env(i)%helium%pos(:, :, 1:helium_env(1)%helium%beads), .TRUE.)
    1173             :       END DO
    1174       48020 :       CALL helium_env(1)%comm%sum(helium_env(1)%helium%rtmp_3_atoms_beads_np_1d)
    1175             : 
    1176             :       ! gather permutation state from all processors to logger%para_env%source
    1177         520 :       helium_env(1)%helium%itmp_atoms_np_1d(:) = 0
    1178          20 :       j = SIZE(helium_env(1)%helium%permutation)
    1179          70 :       DO i = 1, SIZE(helium_env)
    1180         320 :          helium_env(1)%helium%itmp_atoms_np_1d(j*(offset + i - 1) + 1:j*(offset + i)) = helium_env(i)%helium%permutation
    1181             :       END DO
    1182             : 
    1183        1020 :       CALL helium_env(1)%comm%sum(helium_env(1)%helium%itmp_atoms_np_1d)
    1184             : 
    1185             :       ! set logical mask for unpacking coordinates gathered from other ranks
    1186        6740 :       helium_env(1)%helium%ltmp_3_atoms_beads_3d(:, :, :) = .TRUE.
    1187             : 
    1188          20 :       IF (logger%para_env%is_source()) THEN
    1189             : 
    1190          10 :          CALL section_vals_val_get(print_key, "FORMAT", i_val=outformat)
    1191             : 
    1192             :          ! iterate over helium environments
    1193          60 :          DO irank = 1, helium_env(1)%helium%num_env
    1194          60 :             IF (outformat == fmt_id_pdb) THEN
    1195             :                ! generate one file per environment
    1196          50 :                stmp = ""
    1197          50 :                WRITE (stmp, *) irank
    1198          50 :                my_middle_name = "helium-pos-"//TRIM(ADJUSTL(stmp))
    1199             :                unit_nr = cp_print_key_unit_nr( &
    1200             :                          logger, &
    1201             :                          print_key, &
    1202             :                          middle_name=TRIM(my_middle_name), &
    1203          50 :                          extension=".pdb")
    1204             : 
    1205             :                ! write out the unit cell parameters
    1206          50 :                fmt_string = "(A6,3F9.3,3F7.2,1X,A11,1X,I3)"
    1207          50 :                xtmp = helium_env(1)%helium%cell_size
    1208          50 :                xtmp = cp_unit_from_cp2k(xtmp, "angstrom")
    1209         100 :                SELECT CASE (helium_env(1)%helium%cell_shape)
    1210             :                CASE (helium_cell_shape_cube)
    1211          50 :                   stmp = "C          "
    1212             :                CASE (helium_cell_shape_octahedron)
    1213           0 :                   stmp = "O          "
    1214             :                CASE DEFAULT
    1215          50 :                   stmp = "UNKNOWN    "
    1216             :                END SELECT
    1217          50 :                WRITE (unit_nr, fmt_string) "CRYST1", &
    1218          50 :                   xtmp, xtmp, xtmp, &
    1219          50 :                   90.0_dp, 90.0_dp, 90.0_dp, &
    1220         100 :                   stmp, helium_env(1)%helium%beads
    1221             : 
    1222             :                ! unpack coordinates
    1223          50 :                msglen = SIZE(helium_env(1)%helium%rtmp_3_atoms_beads_1d)
    1224          50 :                offset = (irank - 1)*msglen
    1225             :                helium_env(1)%helium%work(:, :, 1:helium_env(1)%helium%beads) = &
    1226             :                   UNPACK(helium_env(1)%helium%rtmp_3_atoms_beads_np_1d(offset + 1:offset + msglen), &
    1227       16850 :                          MASK=helium_env(1)%helium%ltmp_3_atoms_beads_3d, FIELD=0.0_dp)
    1228             : 
    1229             :                ! unpack permutation state (actually point to the right section only)
    1230          50 :                msglen = SIZE(helium_env(1)%helium%permutation)
    1231          50 :                offset = (irank - 1)*msglen
    1232          50 :                my_perm => helium_env(1)%helium%itmp_atoms_np_1d(offset + 1:offset + msglen)
    1233             : 
    1234             :                ! write out coordinates
    1235             :                fmt_string = &
    1236          50 :                   "(A6,I5,1X,A4,A1,A3,1X,A1,I4,A1,3X,3F8.3,2F6.2,10X,A2,A2)"
    1237         300 :                DO ia = 1, helium_env(1)%helium%atoms
    1238         250 :                   icycle = helium_cycle_number(helium_env(1)%helium, ia, my_perm)
    1239         250 :                   is_winding = helium_is_winding(helium_env(1)%helium, ia, helium_env(1)%helium%work, my_perm)
    1240         250 :                   IF (is_winding) THEN
    1241           0 :                      resName = "SPR"
    1242             :                   ELSE
    1243         250 :                      resName = "NRM"
    1244             :                   END IF
    1245        4300 :                   DO ib = 1, helium_env(1)%helium%beads
    1246        4000 :                      xtmp = helium_env(1)%helium%work(1, ia, ib)
    1247        4000 :                      xtmp = cp_unit_from_cp2k(xtmp, "angstrom")
    1248        4000 :                      ytmp = helium_env(1)%helium%work(2, ia, ib)
    1249        4000 :                      ytmp = cp_unit_from_cp2k(ytmp, "angstrom")
    1250        4000 :                      ztmp = helium_env(1)%helium%work(3, ia, ib)
    1251        4000 :                      ztmp = cp_unit_from_cp2k(ztmp, "angstrom")
    1252        4000 :                      WRITE (unit_nr, fmt_string) "ATOM  ", &
    1253        4000 :                         (ia - 1)*helium_env(1)%helium%beads + ib, &
    1254        4000 :                         " He ", " ", resName, "X", &
    1255        4000 :                         icycle, &
    1256        4000 :                         " ", &
    1257        4000 :                         xtmp, ytmp, ztmp, &
    1258        8250 :                         1.0_dp, 0.0_dp, "HE", "  "
    1259             :                   END DO
    1260             :                END DO
    1261             : 
    1262             :                ! write out the bead connectivity information
    1263         300 :                DO ia = 1, helium_env(1)%helium%atoms
    1264             : 
    1265             :                   ! write connectivity records for this atom only if the path
    1266             :                   ! it belongs to is longer than 1.
    1267         250 :                   IF (helium_path_length(helium_env(1)%helium, ia, my_perm) .LE. 1) THEN
    1268             :                      CYCLE
    1269             :                   END IF
    1270             : 
    1271           0 :                   DO ib = 1, helium_env(1)%helium%beads - 1
    1272             :                      ! check whether the consecutive beads belong to the same box
    1273           0 :                      r1(:) = helium_env(1)%helium%work(:, ia, ib) - helium_env(1)%helium%work(:, ia, ib + 1)
    1274           0 :                      r2(:) = r1(:)
    1275           0 :                      CALL helium_pbc(helium_env(1)%helium, r2)
    1276           0 :                      are_connected = .TRUE.
    1277           0 :                      DO ic = 1, 3
    1278           0 :                         IF (ABS(r1(ic) - r2(ic)) .GT. 100.0_dp*EPSILON(0.0_dp)) THEN
    1279             :                            ! if the distance betw ib and ib+1 changes upon applying
    1280             :                            ! PBC do not connect them
    1281           0 :                            are_connected = .FALSE.
    1282           0 :                            CYCLE
    1283             :                         END IF
    1284             :                      END DO
    1285           0 :                      IF (are_connected) THEN
    1286           0 :                         tmp1 = (ia - 1)*helium_env(1)%helium%beads + ib
    1287           0 :                         tmp2 = (ia - 1)*helium_env(1)%helium%beads + ib + 1
    1288             :                         ! smaller value has to go first
    1289             :                         IF (tmp1 .LT. tmp2) THEN
    1290           0 :                            ib1 = tmp1
    1291           0 :                            ib2 = tmp2
    1292             :                         ELSE
    1293             :                            ib1 = tmp2
    1294             :                            ib2 = tmp1
    1295             :                         END IF
    1296           0 :                         WRITE (unit_nr, '(A6,2I5)') "CONECT", ib1, ib2
    1297             :                      END IF
    1298             :                   END DO
    1299             : 
    1300             :                   ! last bead of atom <ia> connects to the first bead
    1301             :                   ! of the next atom in the permutation cycle
    1302           0 :                  r1(:) = helium_env(1)%helium%work(:, ia, helium_env(1)%helium%beads) - helium_env(1)%helium%work(:, my_perm(ia), 1)
    1303           0 :                   r2(:) = r1(:)
    1304           0 :                   CALL helium_pbc(helium_env(1)%helium, r2)
    1305           0 :                   are_connected = .TRUE.
    1306           0 :                   DO ic = 1, 3
    1307           0 :                      IF (ABS(r1(ic) - r2(ic)) .GT. 100.0_dp*EPSILON(0.0_dp)) THEN
    1308             :                         ! if the distance betw ib and ib+1 changes upon applying
    1309             :                         ! PBC do not connect them
    1310           0 :                         are_connected = .FALSE.
    1311           0 :                         CYCLE
    1312             :                      END IF
    1313             :                   END DO
    1314          50 :                   IF (are_connected) THEN
    1315           0 :                      tmp1 = ia*helium_env(1)%helium%beads
    1316           0 :                      tmp2 = (my_perm(ia) - 1)*helium_env(1)%helium%beads + 1
    1317           0 :                      IF (tmp1 .LT. tmp2) THEN
    1318           0 :                         ib1 = tmp1
    1319           0 :                         ib2 = tmp2
    1320             :                      ELSE
    1321           0 :                         ib1 = tmp2
    1322           0 :                         ib2 = tmp1
    1323             :                      END IF
    1324           0 :                      WRITE (unit_nr, '(A6,2I5)') "CONECT", ib1, ib2
    1325             :                   END IF
    1326             :                END DO
    1327          50 :                WRITE (unit_nr, '(A)') "END"
    1328             : 
    1329          50 :                CALL m_flush(unit_nr)
    1330          50 :                CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1331           0 :             ELSE IF (outformat == fmt_id_xyz) THEN
    1332             :                ! generate one file per environment and bead
    1333           0 :                DO ib = 1, helium_env(1)%helium%beads
    1334           0 :                   stmp = ""
    1335           0 :                   WRITE (stmp, *) irank
    1336           0 :                   my_middle_name = "helium-pos-"//TRIM(ADJUSTL(stmp))
    1337           0 :                   WRITE (stmp, *) ib
    1338           0 :                   my_middle_name = TRIM(my_middle_name)//"-"//TRIM(ADJUSTL(stmp))
    1339             :                   unit_nr = cp_print_key_unit_nr( &
    1340             :                             logger, &
    1341             :                             print_key, &
    1342             :                             middle_name=TRIM(my_middle_name), &
    1343           0 :                             extension=".xyz")
    1344             :                   ! write out xyz header
    1345           0 :                   WRITE (unit_nr, *) helium_env(1)%helium%atoms
    1346           0 :                   stmp = ""
    1347           0 :                   WRITE (stmp, *) logger%iter_info%n_rlevel
    1348           0 :                   fmt_string = "(A6,"//TRIM(ADJUSTL(stmp))//"I12)"
    1349           0 :                   WRITE (unit_nr, fmt_string) "iter= ", logger%iter_info%iteration(:)
    1350           0 :                   fmt_string = "(A6,3F9.3,3F7.2,1X,A11,1X,I3)"
    1351             : 
    1352             :                   ! unpack coordinates
    1353           0 :                   msglen = SIZE(helium_env(1)%helium%rtmp_3_atoms_beads_1d)
    1354           0 :                   offset = (irank - 1)*msglen
    1355             :                   helium_env(1)%helium%work(:, :, 1:helium_env(1)%helium%beads) = &
    1356             :                      UNPACK(helium_env(1)%helium%rtmp_3_atoms_beads_np_1d(offset + 1:offset + msglen), &
    1357           0 :                             MASK=helium_env(1)%helium%ltmp_3_atoms_beads_3d, FIELD=0.0_dp)
    1358             : 
    1359             :                   ! unpack permutation state (actually point to the right section only)
    1360           0 :                   msglen = SIZE(helium_env(1)%helium%permutation)
    1361           0 :                   offset = (irank - 1)*msglen
    1362           0 :                   my_perm => helium_env(1)%helium%itmp_atoms_np_1d(offset + 1:offset + msglen)
    1363             : 
    1364             :                   ! write out coordinates
    1365           0 :                   fmt_string = "(A2,3(1X,F20.10))"
    1366           0 :                   DO ia = 1, helium_env(1)%helium%atoms
    1367           0 :                      xtmp = helium_env(1)%helium%work(1, ia, ib)
    1368           0 :                      xtmp = cp_unit_from_cp2k(xtmp, "angstrom")
    1369           0 :                      ytmp = helium_env(1)%helium%work(2, ia, ib)
    1370           0 :                      ytmp = cp_unit_from_cp2k(ytmp, "angstrom")
    1371           0 :                      ztmp = helium_env(1)%helium%work(3, ia, ib)
    1372           0 :                      ztmp = cp_unit_from_cp2k(ztmp, "angstrom")
    1373           0 :                      WRITE (unit_nr, fmt_string) "He", xtmp, ytmp, ztmp
    1374             :                   END DO
    1375           0 :                   CALL m_flush(unit_nr)
    1376           0 :                   CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1377             :                END DO
    1378             :             ELSE
    1379           0 :                CPABORT("")
    1380             :             END IF
    1381             :          END DO
    1382             : 
    1383             :       END IF
    1384             : 
    1385          20 :       CALL timestop(handle)
    1386             : 
    1387          20 :       RETURN
    1388         100 :    END SUBROUTINE helium_print_coordinates
    1389             : 
    1390             : ! ***************************************************************************
    1391             : !> \brief  Print radial distribution functions according to HELIUM%PRINT%RDF
    1392             : !> \param helium_env ...
    1393             : !> \date   2009-07-23
    1394             : !> \par    History
    1395             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
    1396             : !> \author Lukasz Walewski
    1397             : ! **************************************************************************************************
    1398          72 :    SUBROUTINE helium_print_rdf(helium_env)
    1399             : 
    1400             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
    1401             : 
    1402             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'helium_print_rdf'
    1403             : 
    1404             :       CHARACTER(len=default_string_length)               :: stmp
    1405             :       INTEGER                                            :: handle, ia, ic, id, itmp, iweight, k, &
    1406             :                                                             nsteps, unit_nr
    1407             :       LOGICAL                                            :: should_output
    1408             :       REAL(KIND=dp)                                      :: inv_norm, rtmp, rtmp2
    1409          72 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: message
    1410             :       TYPE(cp_logger_type), POINTER                      :: logger
    1411             :       TYPE(section_vals_type), POINTER                   :: print_key
    1412             : 
    1413          72 :       CALL timeset(routineN, handle)
    1414             : 
    1415          72 :       NULLIFY (logger, print_key)
    1416          72 :       logger => cp_get_default_logger()
    1417             : 
    1418          72 :       IF (logger%para_env%is_source()) THEN
    1419             :          print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
    1420          36 :                                                  "MOTION%PINT%HELIUM%PRINT%RDF")
    1421             :          should_output = BTEST(cp_print_key_should_output( &
    1422             :                                iteration_info=logger%iter_info, &
    1423          36 :                                basis_section=print_key), cp_p_file)
    1424             :       END IF
    1425          72 :       CALL helium_env(1)%comm%bcast(should_output, logger%para_env%source)
    1426             : 
    1427          72 :       IF (should_output) THEN
    1428             :          ! work on the temporary array so that accumulated data remains intact
    1429             :          ! save accumulated data of different env on same core in first temp
    1430       67072 :          helium_env(1)%helium%rdf_inst(:, :) = 0.0_dp
    1431         174 :          DO k = 1, SIZE(helium_env)
    1432             :             helium_env(1)%helium%rdf_inst(:, :) = helium_env(1)%helium%rdf_inst(:, :) + &
    1433       97174 :                                                   helium_env(k)%helium%rdf_accu(:, :)
    1434             :          END DO
    1435             : 
    1436             :          ! average over processors
    1437          72 :          NULLIFY (message)
    1438          72 :          message => helium_env(1)%helium%rdf_inst(:, :)
    1439      134072 :          CALL helium_env(1)%comm%sum(message)
    1440          72 :          itmp = helium_env(1)%helium%num_env
    1441          72 :          inv_norm = 1.0_dp/REAL(itmp, dp)
    1442       67072 :          helium_env(1)%helium%rdf_inst(:, :) = helium_env(1)%helium%rdf_inst(:, :)*inv_norm
    1443             : 
    1444             :          ! average over steps performed so far in this run
    1445          72 :          nsteps = helium_env(1)%helium%current_step - helium_env(1)%helium%first_step
    1446          72 :          inv_norm = 1.0_dp/REAL(nsteps, dp)
    1447       67072 :          helium_env(1)%helium%rdf_inst(:, :) = helium_env(1)%helium%rdf_inst(:, :)*inv_norm
    1448             : 
    1449          72 :          iweight = helium_env(1)%helium%rdf_iweight
    1450             :          ! average over the old and the current density (observe the weights!)
    1451             :          helium_env(1)%helium%rdf_inst(:, :) = nsteps*helium_env(1)%helium%rdf_inst(:, :) + &
    1452       67072 :                                                iweight*helium_env(1)%helium%rdf_rstr(:, :)
    1453       67072 :          helium_env(1)%helium%rdf_inst(:, :) = helium_env(1)%helium%rdf_inst(:, :)/REAL(nsteps + iweight, dp)
    1454             : 
    1455          72 :          IF (logger%para_env%is_source()) THEN
    1456             : 
    1457          36 :             ia = 0
    1458          36 :             rtmp = cp_unit_from_cp2k(1.0_dp, "angstrom")
    1459          36 :             rtmp2 = 1.0_dp
    1460          36 :             IF (.NOT. helium_env(1)%helium%periodic) THEN
    1461             :                ! RDF in non-periodic case has unit 1/bohr**3, convert to Angstrom:
    1462          16 :                rtmp2 = rtmp**(-3)
    1463             :             END IF
    1464             : 
    1465          36 :             IF (helium_env(1)%helium%rdf_he_he) THEN
    1466             :                ! overwrite RDF file each time it is written
    1467           5 :                ia = 1
    1468           5 :                stmp = ""
    1469           5 :                WRITE (stmp, *) "He-He"
    1470             :                unit_nr = cp_print_key_unit_nr( &
    1471             :                          logger, &
    1472             :                          print_key, &
    1473             :                          middle_name="helium-rdf-"//TRIM(ADJUSTL(stmp)), &
    1474             :                          extension=".dat", &
    1475             :                          file_position="REWIND", &
    1476           5 :                          do_backup=.FALSE.)
    1477             : 
    1478        1255 :                DO ic = 1, helium_env(1)%helium%rdf_nbin
    1479        1250 :                   WRITE (unit_nr, '(F20.10)', ADVANCE='NO') (REAL(ic, dp) - 0.5_dp)*helium_env(1)%helium%rdf_delr*rtmp
    1480        1250 :                   WRITE (unit_nr, '(F20.10)', ADVANCE='NO') helium_env(1)%helium%rdf_inst(ia, ic)*rtmp2
    1481        1255 :                   WRITE (unit_nr, *)
    1482             :                END DO
    1483             : 
    1484           5 :                CALL m_flush(unit_nr)
    1485           5 :                CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1486             :             END IF
    1487             : 
    1488          36 :             IF (helium_env(1)%helium%rdf_sol_he) THEN
    1489             :                ! overwrite RDF file each time it is written
    1490          31 :                stmp = ""
    1491          31 :                WRITE (stmp, *) "Solute-He"
    1492             :                unit_nr = cp_print_key_unit_nr( &
    1493             :                          logger, &
    1494             :                          print_key, &
    1495             :                          middle_name="helium-rdf-"//TRIM(ADJUSTL(stmp)), &
    1496             :                          extension=".dat", &
    1497             :                          file_position="REWIND", &
    1498          31 :                          do_backup=.FALSE.)
    1499             : 
    1500        7781 :                DO ic = 1, helium_env(1)%helium%rdf_nbin
    1501        7750 :                   WRITE (unit_nr, '(F20.10)', ADVANCE='NO') (REAL(ic, dp) - 0.5_dp)*helium_env(1)%helium%rdf_delr*rtmp
    1502       31000 :                   DO id = 1 + ia, helium_env(1)%helium%rdf_num
    1503       31000 :                      WRITE (unit_nr, '(F20.10)', ADVANCE='NO') helium_env(1)%helium%rdf_inst(id, ic)*rtmp2
    1504             :                   END DO
    1505        7781 :                   WRITE (unit_nr, *)
    1506             :                END DO
    1507             : 
    1508          31 :                CALL m_flush(unit_nr)
    1509          31 :                CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1510             :             END IF
    1511             : 
    1512             :          END IF
    1513             :       END IF
    1514             : 
    1515          72 :       CALL timestop(handle)
    1516             : 
    1517          72 :       RETURN
    1518          72 :    END SUBROUTINE helium_print_rdf
    1519             : 
    1520             : ! ***************************************************************************
    1521             : !> \brief  Print densities according to HELIUM%PRINT%RHO
    1522             : !> \param helium_env ...
    1523             : !> \date   2011-06-21
    1524             : !> \par History
    1525             : !>      08.2015 cleaned code from unneeded arrays
    1526             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
    1527             : !> \author Lukasz Walewski
    1528             : ! **************************************************************************************************
    1529         100 :    SUBROUTINE helium_print_rho(helium_env)
    1530             : 
    1531             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
    1532             : 
    1533             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'helium_print_rho'
    1534             : 
    1535             :       CHARACTER(len=default_string_length)               :: comment, fname
    1536             :       INTEGER                                            :: handle, ic, id, itmp, iweight, k, &
    1537             :                                                             nsteps, unit_nr
    1538             :       LOGICAL                                            :: should_output
    1539             :       REAL(KIND=dp)                                      :: inv_norm, invproc
    1540             :       REAL(KIND=dp), DIMENSION(3)                        :: center
    1541         100 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: cubdata
    1542             :       TYPE(cp_logger_type), POINTER                      :: logger
    1543             :       TYPE(section_vals_type), POINTER                   :: print_key
    1544             : 
    1545         100 :       CALL timeset(routineN, handle)
    1546             : 
    1547         100 :       NULLIFY (logger, print_key)
    1548         100 :       logger => cp_get_default_logger()
    1549             : 
    1550             :       print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
    1551         100 :                                               "MOTION%PINT%HELIUM%PRINT%RHO")
    1552             :       should_output = BTEST(cp_print_key_should_output( &
    1553             :                             iteration_info=logger%iter_info, &
    1554         100 :                             basis_section=print_key), cp_p_file)
    1555             : 
    1556         100 :       IF (.NOT. should_output) THEN
    1557          76 :          CALL timestop(handle)
    1558          76 :          RETURN
    1559             :       END IF
    1560             : 
    1561             :       ! work on temporary array so that the average remains intact
    1562             :       ! save accumulated data of different env on same core in first temp
    1563    44226444 :       helium_env(1)%helium%rho_inst(:, :, :, :) = 0.0_dp
    1564          54 :       DO k = 1, SIZE(helium_env)
    1565             :          helium_env(1)%helium%rho_inst(:, :, :, :) = helium_env(1)%helium%rho_inst(:, :, :, :) + &
    1566    56287074 :                                                      helium_env(k)%helium%rho_accu(:, :, :, :)
    1567             :       END DO
    1568             : 
    1569             :       ! average over processors
    1570    88452864 :       CALL helium_env(1)%comm%sum(helium_env(1)%helium%rho_inst)
    1571          24 :       itmp = helium_env(1)%helium%num_env
    1572          24 :       invproc = 1.0_dp/REAL(itmp, dp)
    1573    44226444 :       helium_env(1)%helium%rho_inst(:, :, :, :) = helium_env(1)%helium%rho_inst(:, :, :, :)*invproc
    1574             : 
    1575             :       ! average over steps performed so far in this run
    1576          24 :       nsteps = helium_env(1)%helium%current_step - helium_env(1)%helium%first_step
    1577          24 :       inv_norm = 1.0_dp/REAL(nsteps, dp)
    1578    44226444 :       helium_env(1)%helium%rho_inst(:, :, :, :) = helium_env(1)%helium%rho_inst(:, :, :, :)*inv_norm
    1579             : 
    1580          24 :       iweight = helium_env(1)%helium%rho_iweight
    1581             :       ! average over the old and the current density (observe the weights!)
    1582             :       helium_env(1)%helium%rho_inst(:, :, :, :) = nsteps*helium_env(1)%helium%rho_inst(:, :, :, :) + &
    1583    44226444 :                                                   iweight*helium_env(1)%helium%rho_rstr(:, :, :, :)
    1584    44226444 :       helium_env(1)%helium%rho_inst(:, :, :, :) = helium_env(1)%helium%rho_inst(:, :, :, :)/REAL(nsteps + iweight, dp)
    1585             : 
    1586             :       ! set center of the cubefile
    1587          24 :       IF (helium_env(1)%helium%solute_present) THEN
    1588             :          ! should be set to solute's COM
    1589          56 :          center(:) = helium_env(1)%helium%center(:)
    1590             :       ELSE
    1591             :          ! regardless of whether we are periodic or not use the origin, since
    1592             :          ! pure cluster's COM might drift, but we want the cube fixed (note that
    1593             :          ! the densities are correctly calculated wrt to COM in such case)
    1594          10 :          center(:) = (/0.0_dp, 0.0_dp, 0.0_dp/)
    1595             :       END IF
    1596             : 
    1597         144 :       DO id = 1, rho_num ! loop over densities ---
    1598             : 
    1599         120 :          IF (.NOT. helium_env(1)%helium%rho_property(id)%is_calculated) THEN
    1600             :             ! skip densities that are not requested by the user
    1601             :             CYCLE
    1602             :          END IF
    1603             : 
    1604          72 :          DO ic = 1, helium_env(1)%helium%rho_property(id)%num_components ! loop over components
    1605             : 
    1606             :             WRITE (fname, '(A)') "helium-rho-"// &
    1607          24 :                TRIM(ADJUSTL(helium_env(1)%helium%rho_property(id)%filename_suffix(ic)))
    1608          24 :             IF (helium_env(1)%helium%rho_property(id)%component_name(ic) .EQ. "") THEN
    1609          24 :                WRITE (comment, '(A)') TRIM(helium_env(1)%helium%rho_property(id)%name)
    1610             :             ELSE
    1611             :                WRITE (comment, '(A)') TRIM(helium_env(1)%helium%rho_property(id)%name)// &
    1612             :                   ", "// &
    1613           0 :                   TRIM(helium_env(1)%helium%rho_property(id)%component_name(ic))
    1614             :             END IF
    1615          24 :             cubdata => helium_env(1)%helium%rho_inst(helium_env(1)%helium%rho_property(id)%component_index(ic), :, :, :)
    1616             : 
    1617             :             unit_nr = cp_print_key_unit_nr( &
    1618             :                       logger, &
    1619             :                       print_key, &
    1620             :                       middle_name=TRIM(ADJUSTL(fname)), &
    1621             :                       extension=".cube", &
    1622             :                       file_position="REWIND", &
    1623          24 :                       do_backup=.FALSE.)
    1624             : 
    1625         144 :             IF (logger%para_env%is_source()) THEN
    1626             :                CALL helium_write_cubefile( &
    1627             :                   unit_nr, &
    1628             :                   comment, &
    1629             :                   center - 0.5_dp*(helium_env(1)%helium%rho_maxr - helium_env(1)%helium%rho_delr), &
    1630             :                   helium_env(1)%helium%rho_delr, &
    1631             :                   helium_env(1)%helium%rho_nbin, &
    1632          48 :                   cubdata)
    1633          12 :                CALL m_flush(unit_nr)
    1634          12 :                CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1635             :             END IF
    1636             : 
    1637             :          END DO ! loop over components
    1638             : 
    1639             :       END DO ! loop over densities ---
    1640             : 
    1641          24 :       CALL timestop(handle)
    1642             : 
    1643         100 :    END SUBROUTINE helium_print_rho
    1644             : 
    1645             : ! ***************************************************************************
    1646             : !> \brief Write volumetric data to an orthorhombic cubefile
    1647             : !> \param   unit   unit number to which output will be sent
    1648             : !> \param   comment   description of the data stored in the cubefile
    1649             : !> \param   origin   position of the cubefile origin
    1650             : !> \param   deltar   voxel side length
    1651             : !> \param   ndim   number of voxels in each dimension
    1652             : !> \param   DATA   array (ndim x ndim x ndim) with the data for output
    1653             : !> \date 2013-11-25
    1654             : !> \author Lukasz Walewski
    1655             : ! **************************************************************************************************
    1656          12 :    SUBROUTINE helium_write_cubefile(unit, comment, origin, deltar, ndim, DATA)
    1657             : 
    1658             :       INTEGER, INTENT(IN)                                :: unit
    1659             :       CHARACTER(len=default_string_length), INTENT(IN)   :: comment
    1660             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: origin
    1661             :       REAL(KIND=dp), INTENT(IN)                          :: deltar
    1662             :       INTEGER, INTENT(IN)                                :: ndim
    1663             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
    1664             :          POINTER                                         :: DATA
    1665             : 
    1666             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_write_cubefile'
    1667             : 
    1668             :       INTEGER                                            :: handle, ix, iy, iz, nw
    1669             :       REAL(KIND=dp)                                      :: delr, inva3
    1670             :       REAL(KIND=dp), DIMENSION(3)                        :: orig
    1671             : 
    1672          12 :       CALL timeset(routineN, handle)
    1673             : 
    1674             :       ! convert cubefile data to the proper units of measure
    1675          12 :       delr = angstrom*deltar
    1676          48 :       orig(:) = angstrom*origin(:)
    1677             : 
    1678             :       ! output cube file header
    1679          12 :       WRITE (unit, '(A)') comment
    1680          12 :       WRITE (unit, '(A)') "Volumetric data in cubefile format generated by CP2K"
    1681          12 :       WRITE (unit, '(I5,3(1X,F12.8))') 0, orig(1), orig(2), orig(3)
    1682          12 :       WRITE (unit, '(I5,3(1X,F12.8))') ndim, delr, 0.0_dp, 0.0_dp
    1683          12 :       WRITE (unit, '(I5,3(1X,F12.8))') ndim, 0.0_dp, delr, 0.0_dp
    1684          12 :       WRITE (unit, '(I5,3(1X,F12.8))') ndim, 0.0_dp, 0.0_dp, delr
    1685             : 
    1686             :       ! output cube file data
    1687          12 :       nw = 0
    1688          12 :       inva3 = 1.0_dp/(angstrom*angstrom*angstrom)
    1689        1122 :       DO ix = 1, ndim
    1690      111222 :          DO iy = 1, ndim
    1691    11112210 :             DO iz = 1, ndim
    1692    11001000 :                WRITE (unit, '(1X,E13.5)', ADVANCE='NO') inva3*DATA(ix, iy, iz)
    1693    11001000 :                nw = nw + 1
    1694    11111100 :                IF (MOD(nw, 6) .EQ. 0) THEN
    1695     1833492 :                   nw = 0
    1696     1833492 :                   WRITE (unit, *)
    1697             :                END IF
    1698             :             END DO
    1699             :          END DO
    1700             :       END DO
    1701             :       ! some compilers write over the first entry on a line losing all previous
    1702             :       ! values written on that line unless line terminator is written at the end
    1703             :       ! so make sure that the last WRITE statement runs without ADVANCE='NO'
    1704             :       ! (observed for ifort 14.0.1 and 14.0.2 but not for gfortran 4.8.2)
    1705          12 :       IF (nw .NE. 0) THEN
    1706          12 :          WRITE (unit, *)
    1707             :       END IF
    1708             : 
    1709          12 :       CALL timestop(handle)
    1710             : 
    1711          12 :    END SUBROUTINE helium_write_cubefile
    1712             : 
    1713             : ! ***************************************************************************
    1714             : !> \brief  Print permutation length according to HELIUM%PRINT%PLENGTH
    1715             : !> \param helium_env ...
    1716             : !> \date   2010-06-07
    1717             : !> \par    History
    1718             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
    1719             : !> \author Lukasz Walewski
    1720             : ! **************************************************************************************************
    1721         100 :    SUBROUTINE helium_print_plength(helium_env)
    1722             : 
    1723             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
    1724             : 
    1725             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_plength'
    1726             : 
    1727             :       INTEGER                                            :: handle, i, unit_nr
    1728             :       LOGICAL                                            :: is_new, should_output
    1729             :       TYPE(cp_logger_type), POINTER                      :: logger
    1730             :       TYPE(section_vals_type), POINTER                   :: print_key
    1731             : 
    1732         100 :       CALL timeset(routineN, handle)
    1733             : 
    1734         100 :       NULLIFY (logger, print_key)
    1735         100 :       logger => cp_get_default_logger()
    1736             : 
    1737         100 :       IF (logger%para_env%is_source()) THEN
    1738             :          print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
    1739          50 :                                                  "MOTION%PINT%HELIUM%PRINT%PLENGTH")
    1740             :          should_output = BTEST(cp_print_key_should_output( &
    1741             :                                iteration_info=logger%iter_info, &
    1742          50 :                                basis_section=print_key), cp_p_file)
    1743             : 
    1744          50 :          IF (should_output) THEN
    1745             : 
    1746             :             unit_nr = cp_print_key_unit_nr( &
    1747             :                       logger, &
    1748             :                       print_key, &
    1749             :                       middle_name="helium-plength", &
    1750             :                       extension=".dat", &
    1751          45 :                       is_new_file=is_new)
    1752             : 
    1753        1215 :             DO i = 1, helium_env(1)%helium%atoms
    1754        1170 :                WRITE (unit_nr, '(F20.10)', ADVANCE='NO') helium_env(1)%helium%plength_avrg(i)
    1755        1215 :                IF (i .LT. helium_env(1)%helium%atoms) THEN
    1756        1125 :                   WRITE (unit_nr, '(1X)', ADVANCE='NO')
    1757             :                END IF
    1758             :             END DO
    1759          45 :             WRITE (unit_nr, '(A)') ""
    1760             : 
    1761          45 :             CALL m_flush(unit_nr)
    1762          45 :             CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1763             : 
    1764             :          END IF
    1765             :       END IF
    1766             : 
    1767         100 :       CALL timestop(handle)
    1768             : 
    1769         100 :       RETURN
    1770             :    END SUBROUTINE helium_print_plength
    1771             : 
    1772             : ! ***************************************************************************
    1773             : !> \brief  Print helium force according to HELIUM%PRINT%FORCE
    1774             : !> \param helium_env ...
    1775             : !> \date   2010-01-27
    1776             : !> \par    History
    1777             : !>         2016-07-14 Modified to work with independent helium_env [cschran]
    1778             : !> \author Lukasz Walewski
    1779             : ! **************************************************************************************************
    1780         100 :    SUBROUTINE helium_print_force(helium_env)
    1781             : 
    1782             :       TYPE(helium_solvent_p_type), DIMENSION(:), POINTER :: helium_env
    1783             : 
    1784             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_force'
    1785             : 
    1786             :       CHARACTER(len=default_string_length)               :: msgstr
    1787             :       INTEGER                                            :: handle, ia, ib, ic, idim, unit_nr
    1788             :       LOGICAL                                            :: should_output
    1789             :       TYPE(cp_logger_type), POINTER                      :: logger
    1790             :       TYPE(section_vals_type), POINTER                   :: print_key
    1791             : 
    1792         100 :       CALL timeset(routineN, handle)
    1793             : 
    1794         100 :       NULLIFY (logger, print_key)
    1795         100 :       logger => cp_get_default_logger()
    1796             : 
    1797             :       print_key => section_vals_get_subs_vals(helium_env(1)%helium%input, &
    1798         100 :                                               "MOTION%PINT%HELIUM%PRINT%FORCES")
    1799             :       should_output = BTEST(cp_print_key_should_output( &
    1800             :                             logger%iter_info, &
    1801         100 :                             basis_section=print_key), cp_p_file)
    1802             : 
    1803         100 :       IF (.NOT. should_output) THEN
    1804         100 :          CALL timestop(handle)
    1805         100 :          RETURN
    1806             :       END IF
    1807             : 
    1808             :       ! check if there is anything to be printed out
    1809           0 :       IF (.NOT. helium_env(1)%helium%solute_present) THEN
    1810           0 :          msgstr = "Warning: force printout requested but there is no solute!"
    1811           0 :          CALL helium_write_line(msgstr)
    1812           0 :          CALL timestop(handle)
    1813           0 :          RETURN
    1814             :       END IF
    1815             : 
    1816           0 :       IF (logger%para_env%is_source()) THEN
    1817             : 
    1818             :          unit_nr = cp_print_key_unit_nr( &
    1819             :                    logger, &
    1820             :                    print_key, &
    1821             :                    middle_name="helium-force", &
    1822           0 :                    extension=".dat")
    1823             : 
    1824             :          ! print all force components in one line
    1825           0 :          DO ib = 1, helium_env(1)%helium%solute_beads
    1826           0 :             idim = 0
    1827           0 :             DO ia = 1, helium_env(1)%helium%solute_atoms
    1828           0 :                DO ic = 1, 3
    1829           0 :                   idim = idim + 1
    1830           0 :                   WRITE (unit_nr, '(F20.10)', ADVANCE='NO') helium_env(1)%helium%force_avrg(ib, idim)
    1831             :                END DO
    1832             :             END DO
    1833             :          END DO
    1834           0 :          WRITE (unit_nr, *)
    1835             : 
    1836           0 :          CALL m_flush(unit_nr)
    1837           0 :          CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1838             : 
    1839             :       END IF
    1840             : 
    1841           0 :       CALL timestop(handle)
    1842             : 
    1843           0 :       RETURN
    1844             :    END SUBROUTINE helium_print_force
    1845             : 
    1846             : #if 0
    1847             : 
    1848             : ! ***************************************************************************
    1849             : !> \brief  Print instantaneous force according to HELIUM%PRINT%FORCES_INST
    1850             : !> \param helium ...
    1851             : !> \date   2010-01-29
    1852             : !> \author Lukasz Walewski
    1853             : !> \note   Collects instantaneous helium forces from all processors on
    1854             : !> logger%para_env%source and writes them to files - one file per processor.
    1855             : !>         !TODO: Generalize for helium_env
    1856             : ! **************************************************************************************************
    1857             :    SUBROUTINE helium_print_force_inst(helium)
    1858             : 
    1859             :       TYPE(helium_solvent_type), POINTER                 :: helium
    1860             : 
    1861             :       CHARACTER(len=*), PARAMETER :: routineN = 'helium_print_force_inst', &
    1862             :          routineP = moduleN//':'//routineN
    1863             : 
    1864             :       CHARACTER(len=default_string_length)               :: my_middle_name, stmp
    1865             :       INTEGER                                            :: handle, ia, ib, ic, idim, irank, offset, &
    1866             :                                                             unit_nr
    1867             :       LOGICAL                                            :: should_output
    1868             :       TYPE(cp_logger_type), POINTER                      :: logger
    1869             :       TYPE(section_vals_type), POINTER                   :: print_key
    1870             : 
    1871             :       CALL timeset(routineN, handle)
    1872             : 
    1873             :       NULLIFY (logger, print_key)
    1874             :       logger => cp_get_default_logger()
    1875             :       print_key => section_vals_get_subs_vals(helium%input, &
    1876             :                                               "MOTION%PINT%HELIUM%PRINT%FORCES_INST")
    1877             :       should_output = BTEST(cp_print_key_should_output( &
    1878             :                             logger%iter_info, &
    1879             :                             basis_section=print_key), cp_p_file)
    1880             : 
    1881             :       IF (should_output) THEN
    1882             : 
    1883             :          ! check if there is anything to be printed out
    1884             :          IF (.NOT. helium%solute_present) THEN
    1885             :             stmp = "Warning: force printout requested but there is no solute!"
    1886             :             CALL helium_write_line(stmp)
    1887             :             CALL timestop(handle)
    1888             :             RETURN
    1889             :          END IF
    1890             : 
    1891             :          ! fill the tmp buffer with instantaneous helium forces at each proc
    1892             :          helium%rtmp_p_ndim_1d(:) = PACK(helium%force_inst, .TRUE.)
    1893             : 
    1894             :          ! pass the message from all processors to logger%para_env%source
    1895             :          helium%rtmp_p_ndim_np_1d(:) = 0.0_dp
    1896             :          CALL logger%para_env%gather(helium%rtmp_p_ndim_1d, helium%rtmp_p_ndim_np_1d)
    1897             : 
    1898             :          IF (logger%para_env%is_source()) THEN
    1899             : 
    1900             :             ! iterate over processors/helium environments
    1901             :             DO irank = 1, helium%num_env
    1902             : 
    1903             :                ! generate one file per processor
    1904             :                stmp = ""
    1905             :                WRITE (stmp, *) irank
    1906             :                my_middle_name = "helium-force-inst-"//TRIM(ADJUSTL(stmp))
    1907             :                unit_nr = cp_print_key_unit_nr( &
    1908             :                          logger, &
    1909             :                          print_key, &
    1910             :                          middle_name=TRIM(my_middle_name), &
    1911             :                          extension=".dat")
    1912             : 
    1913             :                ! unpack and actually print the forces - all components in one line
    1914             :                offset = (irank - 1)*SIZE(helium%rtmp_p_ndim_1d)
    1915             :                idim = 0
    1916             :                DO ib = 1, helium%solute_beads
    1917             :                   DO ia = 1, helium%solute_atoms
    1918             :                      DO ic = 1, 3
    1919             :                         idim = idim + 1
    1920             :                         WRITE (unit_nr, '(F20.10)', ADVANCE='NO') helium%rtmp_p_ndim_np_1d(offset + idim)
    1921             :                      END DO
    1922             :                   END DO
    1923             :                END DO
    1924             :                WRITE (unit_nr, *)
    1925             : 
    1926             :                CALL m_flush(unit_nr)
    1927             :                CALL cp_print_key_finished_output(unit_nr, logger, print_key)
    1928             : 
    1929             :             END DO
    1930             : 
    1931             :          END IF
    1932             :       END IF
    1933             : 
    1934             :       CALL timestop(handle)
    1935             : 
    1936             :    END SUBROUTINE helium_print_force_inst
    1937             : 
    1938             : #endif
    1939             : 
    1940             : END MODULE helium_io

Generated by: LCOV version 1.15