LCOV - code coverage report
Current view: top level - src/motion/mc - mc_misc.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:262480d) Lines: 215 231 93.1 %
Date: 2024-11-22 07:00:40 Functions: 5 5 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief contains miscellaneous subroutines used in the Monte Carlo runs,
      10             : !>      mostly I/O stuff
      11             : !> \author MJM
      12             : ! **************************************************************************************************
      13             : MODULE mc_misc
      14             :    USE cp_files,                        ONLY: close_file,&
      15             :                                               open_file
      16             :    USE force_env_types,                 ONLY: use_fist_force,&
      17             :                                               use_qs_force
      18             :    USE kinds,                           ONLY: default_string_length,&
      19             :                                               dp
      20             :    USE mathconstants,                   ONLY: pi
      21             :    USE mc_types,                        ONLY: &
      22             :         accattempt, get_mc_input_file, get_mc_molecule_info, get_mc_par, mc_averages_type, &
      23             :         mc_input_file_type, mc_molecule_info_type, mc_moves_p_type, mc_moves_type, mc_simpar_type
      24             :    USE physcon,                         ONLY: angstrom
      25             : #include "../../base/base_uses.f90"
      26             : 
      27             :    IMPLICIT NONE
      28             : 
      29             :    PRIVATE
      30             : 
      31             :    PUBLIC :: final_mc_write, mc_averages_create, mc_averages_release, &
      32             :              mc_make_dat_file_new
      33             : 
      34             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mc_misc'
      35             : 
      36             : CONTAINS
      37             : 
      38             : ! **************************************************************************************************
      39             : !> \brief initializes the structure that holds running averages of MC variables
      40             : !> \param averages the mc_averages strucutre you want to initialize
      41             : !>
      42             : !>    Suitable for parallel.
      43             : !> \author MJM
      44             : ! **************************************************************************************************
      45          26 :    SUBROUTINE mc_averages_create(averages)
      46             : 
      47             :       TYPE(mc_averages_type), POINTER                    :: averages
      48             : 
      49             :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_averages_create'
      50             : 
      51             :       INTEGER                                            :: handle
      52             : 
      53             : ! begin the timing of the subroutine
      54             : 
      55          26 :       CALL timeset(routineN, handle)
      56             : 
      57             : ! allocate all the structures...not sure why, but it won't work otherwise
      58          26 :       ALLOCATE (averages)
      59             :       averages%ave_energy = 0.0E0_dp
      60             :       averages%ave_energy_squared = 0.0E0_dp
      61             :       averages%ave_volume = 0.0E0_dp
      62             :       averages%molecules = 0.0E0_dp
      63             : 
      64             : ! end the timing
      65          26 :       CALL timestop(handle)
      66             : 
      67          26 :    END SUBROUTINE mc_averages_create
      68             : 
      69             : ! **************************************************************************************************
      70             : !> \brief deallocates the structure that holds running averages of MC variables
      71             : !> \param averages the mc_averages strucutre you want to release
      72             : !>
      73             : !>    Suitable for parallel.
      74             : !> \author MJM
      75             : ! **************************************************************************************************
      76          26 :    SUBROUTINE mc_averages_release(averages)
      77             : 
      78             :       TYPE(mc_averages_type), POINTER                    :: averages
      79             : 
      80             :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_averages_release'
      81             : 
      82             :       INTEGER                                            :: handle
      83             : 
      84             : ! begin the timing of the subroutine
      85             : 
      86          26 :       CALL timeset(routineN, handle)
      87             : 
      88             : ! deallocate
      89          26 :       DEALLOCATE (averages)
      90             : 
      91             :       NULLIFY (averages)
      92             : 
      93             : ! end the timing
      94          26 :       CALL timestop(handle)
      95             : 
      96          26 :    END SUBROUTINE mc_averages_release
      97             : 
      98             : ! **************************************************************************************************
      99             : !> \brief writes a bunch of simulation data to the specified unit
     100             : !> \param mc_par the mc parameters for the simulation
     101             : !> \param all_moves the structure that holds data on how many moves are
     102             : !>               accepted/rejected
     103             : !> \param iw the unit to write to
     104             : !> \param energy_check the sum of the energy changes of each move
     105             : !> \param initial_energy the initial unbiased energy of the system
     106             : !> \param final_energy the final unbiased energy of the system
     107             : !> \param averages the structure that holds computed average properties for
     108             : !>               the simulation
     109             : !>
     110             : !>    Only use in serial.
     111             : !> \author MJM
     112             : ! **************************************************************************************************
     113          36 :    SUBROUTINE final_mc_write(mc_par, all_moves, iw, energy_check, initial_energy, &
     114             :                              final_energy, averages)
     115             : 
     116             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
     117             :       TYPE(mc_moves_p_type), DIMENSION(:), POINTER       :: all_moves
     118             :       INTEGER, INTENT(IN)                                :: iw
     119             :       REAL(KIND=dp), INTENT(IN)                          :: energy_check, initial_energy, &
     120             :                                                             final_energy
     121             :       TYPE(mc_averages_type), POINTER                    :: averages
     122             : 
     123             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'final_mc_write'
     124             : 
     125             :       CHARACTER(LEN=5)                                   :: molecule_string, tab_string
     126             :       CHARACTER(LEN=default_string_length)               :: format_string, string1, string2, string3
     127             :       INTEGER                                            :: handle, itype, nmol_types
     128             :       LOGICAL                                            :: lbias
     129          12 :       REAL(dp), DIMENSION(:), POINTER                    :: rmangle, rmbond, rmdihedral, rmrot, &
     130          12 :                                                             rmtrans
     131             :       REAL(KIND=dp)                                      :: pmcltrans, pmswap, rmcltrans, rmvolume
     132             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     133             :       TYPE(mc_moves_type), POINTER                       :: moves
     134             : 
     135             : ! begin the timing of the subroutine
     136             : 
     137          12 :       CALL timeset(routineN, handle)
     138             : 
     139          12 :       NULLIFY (mc_molecule_info, rmbond, rmangle, rmdihedral, rmrot, rmtrans)
     140             : 
     141             :       CALL get_mc_par(mc_par, pmswap=pmswap, rmvolume=rmvolume, &
     142             :                       lbias=lbias, rmbond=rmbond, rmangle=rmangle, rmdihedral=rmdihedral, &
     143             :                       rmtrans=rmtrans, rmcltrans=rmcltrans, pmcltrans=pmcltrans, rmrot=rmrot, &
     144          12 :                       mc_molecule_info=mc_molecule_info)
     145          12 :       CALL get_mc_molecule_info(mc_molecule_info, nmol_types=nmol_types)
     146          12 :       WRITE (molecule_string, '(I2)') nmol_types
     147          12 :       WRITE (tab_string, '(I4)') 81 - 11*nmol_types
     148          12 :       format_string = "(A,T"//TRIM(ADJUSTL(tab_string))//","//TRIM(ADJUSTL(molecule_string))//"(2X,F9.6))"
     149             : 
     150             : ! write out some data averaged over the whole simulation
     151          12 :       WRITE (iw, *)
     152          12 :       WRITE (iw, '(A,A)') '*****************************************************', &
     153          24 :          '***************************'
     154          12 :       WRITE (iw, '(A,T66,F15.8)') "Average Energy [Hartrees]:", &
     155          24 :          averages%ave_energy
     156          12 :       IF (pmswap .GT. 0.0E0_dp) THEN
     157           2 :          WRITE (iw, '(A,T66,F15.8)') "Average number of molecules:", &
     158           4 :             averages%molecules
     159             :       END IF
     160          12 :       WRITE (iw, '(A,A,T65,F16.6)') "Average Volume ", &
     161          24 :          "[angstroms**3]:", averages%ave_volume*angstrom**3
     162             : 
     163          12 :       WRITE (iw, *)
     164             : 
     165             : ! write out acceptance rates for the moves
     166             : 
     167             : ! volume moves
     168          12 :       WRITE (iw, '(A,A)') '-----------------------------------------------------', &
     169          24 :          '---------------------------'
     170          12 :       string2 = "Attempted       Accepted       Percent"
     171          12 :       string1 = "Volume Moves"
     172          12 :       string3 = "Maximum volume displacement [angstroms**3]= "
     173          12 :       rmvolume = rmvolume*angstrom**3
     174             :       CALL final_move_write(all_moves(1)%moves%volume, string1, string2, iw, &
     175             :                             displacement=rmvolume, lbias=.FALSE., format_string=format_string, &
     176          12 :                             string3=string3)
     177             : 
     178          12 :       IF (pmcltrans .GT. 0.0E0_dp) THEN
     179             : 
     180             : ! Cluster translation moves
     181           1 :          WRITE (iw, '(A,A)') '-----------------------------------------------------', &
     182           2 :             '---------------------------'
     183           1 :          string2 = "Attempted       Accepted       Percent"
     184           1 :          string1 = "Cluster Translation Moves"
     185           1 :          string3 = "Maximum cluster translational displacement [angstroms]= "
     186           1 :          rmcltrans = rmcltrans*angstrom
     187             :          CALL final_move_write(all_moves(1)%moves%cltrans, string1, string2, iw, &
     188             :                                displacement=rmcltrans, lbias=lbias, format_string=format_string, &
     189           1 :                                string3=string3)
     190             : 
     191           1 :          IF (lbias) THEN
     192           0 :             WRITE (iw, '(A)') "Biased Move Data for cluster translation"
     193           0 :             WRITE (iw, '(A,A)') '-------------------------------------------------', &
     194           0 :                '-------------------------------'
     195             : ! Cluster bias translation moves
     196           0 :             string2 = "Attempted       Accepted       Percent"
     197           0 :             string1 = "Cluster Translation Moves"
     198           0 :             string3 = "Maximum cluster translational displacement [angstroms]="
     199             :             CALL final_move_write(all_moves(1)%moves%bias_cltrans, string1, string2, iw, &
     200             :                                   displacement=rmcltrans, lbias=lbias, format_string=format_string, &
     201           0 :                                   string3=string3)
     202             :          END IF
     203             : 
     204             :       END IF
     205             : 
     206             : ! Hybrid MC moves (basically short MD runs)
     207          12 :       string2 = "Attempted       Accepted       Percent"
     208          12 :       string1 = "HMC Moves"
     209          12 :       CALL final_move_write(all_moves(1)%moves%hmc, string1, string2, iw)
     210             : 
     211             : ! Quickstep moves (a series of moves with one potential, and then corrected for
     212             : ! by another potential
     213          12 :       string2 = "Attempted       Accepted       Percent"
     214          12 :       string1 = "Quickstep Moves"
     215          12 :       CALL final_move_write(all_moves(1)%moves%Quickstep, string1, string2, iw)
     216             : 
     217          32 :       DO itype = 1, nmol_types
     218          20 :          WRITE (iw, '(A,A)') '-----------------------------------------------------', &
     219          40 :             '---------------------------'
     220          20 :          WRITE (iw, '(A,I5)') 'Move Data for Molecule Type ', itype
     221          20 :          WRITE (iw, '(A,A)') '-----------------------------------------------------', &
     222          40 :             '---------------------------'
     223             : 
     224          20 :          moves => all_moves(itype)%moves
     225             : 
     226             : ! AVBMC moves
     227          20 :          string2 = "Attempted       Accepted       Percent"
     228          20 :          string1 = "AVBMC moves from in to in"
     229          20 :          CALL final_move_write(moves%avbmc_inin, string1, string2, iw)
     230          20 :          string1 = "AVBMC moves from in to out"
     231          20 :          CALL final_move_write(moves%avbmc_inout, string1, string2, iw)
     232          20 :          string1 = "AVBMC moves from out to in"
     233          20 :          CALL final_move_write(moves%avbmc_outin, string1, string2, iw)
     234          20 :          string1 = "AVBMC moves from out to out"
     235          20 :          CALL final_move_write(moves%avbmc_outout, string1, string2, iw)
     236             : 
     237             : ! conformation changes
     238             :          IF (moves%angle%attempts .GT. 0 .OR. &
     239          20 :              moves%bond%attempts .GT. 0 .OR. &
     240             :              moves%dihedral%attempts .GT. 0) THEN
     241           2 :             WRITE (iw, '(A,T43,A)') "Conformational Moves", &
     242           4 :                "Attempted       Accepted       Percent"
     243             :             WRITE (iw, '(T46,I6,9X,I6,7X,F7.3)') &
     244             :                moves%bond%attempts + moves%angle%attempts + &
     245           2 :                moves%dihedral%attempts, &
     246             :                moves%bond%successes + moves%angle%successes + &
     247           2 :                moves%dihedral%successes, &
     248             :                REAL(moves%bond%successes + moves%angle%successes + &
     249             :                     moves%dihedral%successes, dp)/ &
     250             :                REAL(moves%bond%attempts + moves%angle%attempts + &
     251           4 :                     moves%dihedral%attempts, dp)*100.0E0_dp
     252           2 :             string2 = "Attempted       Accepted       Percent"
     253           2 :             string1 = "Bond Changes"
     254           2 :             string3 = "Maximum bond displacement [angstroms]= "
     255           2 :             rmbond(itype) = rmbond(itype)*angstrom
     256             :             CALL final_move_write(moves%bond, string1, string2, iw, &
     257             :                                   displacement=rmbond(itype), lbias=lbias, format_string=format_string, &
     258           2 :                                   string3=string3)
     259             : 
     260           2 :             string1 = "Angle Changes"
     261           2 :             string3 = "Maximum angle displacement [degrees]= "
     262           2 :             rmangle(itype) = rmangle(itype)/pi*180.0E0_dp
     263             :             CALL final_move_write(moves%angle, string1, string2, iw, &
     264             :                                   displacement=rmangle(itype), lbias=lbias, format_string=format_string, &
     265           2 :                                   string3=string3)
     266             : 
     267           2 :             string1 = "Dihedral Changes"
     268           2 :             string3 = "Maximum dihedral displacement [degrees]= "
     269           2 :             rmdihedral(itype) = rmdihedral(itype)/pi*180.0E0_dp
     270             :             CALL final_move_write(moves%dihedral, string1, string2, iw, &
     271             :                                   displacement=rmdihedral(itype), lbias=lbias, format_string=format_string, &
     272           2 :                                   string3=string3)
     273             : 
     274           2 :             WRITE (iw, '(A,A,I5)') "Conformational Moves Rejected Because", &
     275           4 :                "Box Was Empty: ", moves%empty_conf
     276           2 :             WRITE (iw, '(A,A)') '-----------------------------------------------', &
     277           4 :                '--------------------------------'
     278             :          END IF
     279             : 
     280             : ! translation moves
     281          20 :          string1 = "Translation Moves"
     282          20 :          string3 = "Maximum molecular translational displacement [angstroms]= "
     283          20 :          rmtrans(itype) = rmtrans(itype)*angstrom
     284             :          CALL final_move_write(moves%trans, string1, string2, iw, &
     285             :                                displacement=rmtrans(itype), lbias=lbias, format_string=format_string, &
     286          20 :                                string3=string3)
     287             : 
     288             : ! rotation moves
     289          20 :          string1 = "Rotation Moves"
     290          20 :          string3 = "Maximum molecular rotational displacement [degrees]= "
     291          20 :          rmrot(itype) = rmrot(itype)/pi*180.0E0_dp
     292             :          CALL final_move_write(moves%rot, string1, string2, iw, &
     293             :                                displacement=rmrot(itype), lbias=lbias, format_string=format_string, &
     294          20 :                                string3=string3)
     295             : 
     296             : ! swap moves
     297          20 :          IF (moves%swap%attempts .GT. 0) THEN
     298           4 :             WRITE (iw, '(A,T43,A)') "Swap Moves into this box", &
     299           8 :                "Attempted       Empty          Percent"
     300             :             WRITE (iw, '(T46,I6,9X,I6,7X,F7.3)') &
     301           4 :                moves%swap%attempts, &
     302           4 :                moves%empty, &
     303             :                REAL(moves%empty, dp)/ &
     304           8 :                REAL(moves%swap%attempts, dp)*100.0E0_dp
     305           4 :             WRITE (iw, '(A,T43,A)') "                  Growths", &
     306           8 :                "Attempted       Successful     Percent"
     307             :             WRITE (iw, '(T46,I6,9X,I6,7X,F7.3)') &
     308           4 :                moves%swap%attempts, &
     309           4 :                moves%grown, &
     310             :                REAL(moves%grown, dp)/ &
     311           8 :                REAL(moves%swap%attempts, dp)*100.0E0_dp
     312           4 :             WRITE (iw, '(A,T43,A)') "                    Total", &
     313           8 :                "Attempted       Accepted       Percent"
     314             :             WRITE (iw, '(T46,I6,9X,I6,7X,F7.3)') &
     315           4 :                moves%swap%attempts, &
     316           4 :                moves%swap%successes, &
     317             :                REAL(moves%swap%successes, dp)/ &
     318           8 :                REAL(moves%swap%attempts, dp)*100.0E0_dp
     319           4 :             WRITE (iw, '(A,A)') '-----------------------------------------------', &
     320           8 :                '--------------------------------'
     321             :          END IF
     322             : 
     323             : ! now we write out information on the classical moves, if it's
     324             : ! a classical simulations
     325          32 :          IF (lbias) THEN
     326          14 :             WRITE (iw, '(A)') "Biased Move Data"
     327          14 :             WRITE (iw, '(A,A)') '-------------------------------------------------', &
     328          28 :                '-------------------------------'
     329          14 :             string2 = "Attempted       Accepted       Percent"
     330          14 :             string1 = "Bond Changes"
     331          14 :             string3 = "Maximum bond displacement [angstroms]= "
     332             :             CALL final_move_write(moves%bias_bond, string1, string2, iw, &
     333             :                                   displacement=rmbond(itype), lbias=lbias, format_string=format_string, &
     334          14 :                                   string3=string3)
     335             : 
     336          14 :             string1 = "Angle Changes"
     337          14 :             string3 = "Maximum angle displacement [degrees]= "
     338             :             CALL final_move_write(moves%bias_angle, string1, string2, iw, &
     339             :                                   displacement=rmangle(itype), lbias=lbias, format_string=format_string, &
     340          14 :                                   string3=string3)
     341             : 
     342          14 :             string1 = "Dihedral Changes"
     343          14 :             string3 = "Maximum dihedral displacement [degrees]= "
     344             :             CALL final_move_write(moves%bias_dihedral, string1, string2, iw, &
     345             :                                   displacement=rmdihedral(itype), lbias=lbias, format_string=format_string, &
     346          14 :                                   string3=string3)
     347             : 
     348             :             ! translation moves
     349          14 :             string1 = "Translation Moves"
     350          14 :             string3 = "Maximum molecular translational displacement [angstroms]= "
     351             :             CALL final_move_write(moves%bias_trans, string1, string2, iw, &
     352             :                                   displacement=rmtrans(itype), lbias=lbias, format_string=format_string, &
     353          14 :                                   string3=string3)
     354             : 
     355             : ! rotation moves
     356          14 :             string1 = "Rotation Moves"
     357          14 :             string3 = "Maximum molecular rotational displacement [degrees]= "
     358             :             CALL final_move_write(moves%bias_rot, string1, string2, iw, &
     359             :                                   displacement=rmrot(itype), lbias=lbias, format_string=format_string, &
     360          14 :                                   string3=string3)
     361             : 
     362             :          END IF
     363             : 
     364             :       END DO
     365             : 
     366             : ! see if the energies add up properly
     367          12 :       IF (ABS(initial_energy + energy_check - final_energy) .GT. 0.0000001E0_dp) &
     368             :          THEN
     369           0 :          WRITE (iw, *) '!!!!!!! We have an energy problem. !!!!!!!!'
     370           0 :          WRITE (iw, '(A,T64,F16.10)') 'Final Energy = ', final_energy
     371           0 :          WRITE (iw, '(A,T64,F16.10)') 'Initial Energy + energy_check =', &
     372           0 :             initial_energy + energy_check
     373             :       END IF
     374          12 :       WRITE (iw, '(A,A)') '****************************************************', &
     375          24 :          '****************************'
     376          12 :       WRITE (iw, *)
     377             : 
     378             : ! end the timing
     379          12 :       CALL timestop(handle)
     380             : 
     381          12 :    END SUBROUTINE final_mc_write
     382             : 
     383             : ! **************************************************************************************************
     384             : !> \brief ...
     385             : !> \param move_data ...
     386             : !> \param string1 ...
     387             : !> \param string2 ...
     388             : !> \param iw ...
     389             : !> \param string3 ...
     390             : !> \param format_string ...
     391             : !> \param lbias ...
     392             : !> \param displacement ...
     393             : ! **************************************************************************************************
     394         233 :    SUBROUTINE final_move_write(move_data, string1, string2, iw, string3, &
     395             :                                format_string, lbias, displacement)
     396             : 
     397             :       TYPE(accattempt), POINTER                          :: move_data
     398             :       CHARACTER(default_string_length), INTENT(IN)       :: string1, string2
     399             :       INTEGER, INTENT(IN)                                :: iw
     400             :       CHARACTER(default_string_length), INTENT(IN), &
     401             :          OPTIONAL                                        :: string3, format_string
     402             :       LOGICAL, INTENT(IN), OPTIONAL                      :: lbias
     403             :       REAL(dp), OPTIONAL                                 :: displacement
     404             : 
     405         233 :       IF (.NOT. PRESENT(format_string)) THEN
     406         104 :          IF (move_data%attempts .GT. 0) THEN
     407           7 :             WRITE (iw, '(A,T43,A)') TRIM(ADJUSTL(string1)), &
     408          14 :                TRIM(ADJUSTL(string2))
     409             :             WRITE (iw, '(T46,I6,9X,I6,7X,F7.3)') &
     410           7 :                move_data%attempts, &
     411           7 :                move_data%successes, &
     412             :                REAL(move_data%successes, dp)/ &
     413          14 :                REAL(move_data%attempts, dp)*100.0E0_dp
     414           7 :             WRITE (iw, '(A,A)') '-----------------------------------------------', &
     415          14 :                '---------------------------------'
     416             :          END IF
     417             :       ELSE
     418         129 :          IF (.NOT. PRESENT(string3) .OR. .NOT. PRESENT(lbias) .OR. &
     419             :              .NOT. PRESENT(displacement)) THEN
     420           0 :             WRITE (iw, *) 'MISSING FLAGS IN FINAL_MOVE_WRITE'
     421             :          END IF
     422         129 :          IF (move_data%attempts .GT. 0) THEN
     423          54 :             WRITE (iw, '(A,T43,A)') TRIM(ADJUSTL(string1)), &
     424         108 :                TRIM(ADJUSTL(string2))
     425             :             WRITE (iw, '(T46,I6,9X,I6,7X,F7.3)') &
     426          54 :                move_data%attempts, &
     427          54 :                move_data%successes, &
     428             :                REAL(move_data%successes, dp)/ &
     429         108 :                REAL(move_data%attempts, dp)*100.0E0_dp
     430          54 :             IF (.NOT. lbias) WRITE (iw, '(A,T71,F10.5)') &
     431          12 :                string3, displacement
     432          54 :             WRITE (iw, '(A,A)') '-----------------------------------------------', &
     433         108 :                '---------------------------------'
     434             :          END IF
     435             :       END IF
     436             : 
     437         233 :    END SUBROUTINE final_move_write
     438             : 
     439             : ! **************************************************************************************************
     440             : !> \brief writes a new input file that CP2K can read in for when we want
     441             : !>      to change a force env (change molecule number)...this is much simpler
     442             : !>      than the version I had used to have, and also more flexible (in a way).
     443             : !>      It assumes that &CELL comes before &COORDS, and &COORDS comes before
     444             : !>      &TOPOLOGY, and &TOPOLOGY comes before &GLOBAL (which comes before MC).
     445             : !>      It also assumes that you use &MOL_SET in &TOPOLOGY.  Still, many fewer
     446             : !>      assumptions than before.
     447             : !>
     448             : !>      box_length and coordinates should be passed in a.u.
     449             : !> \param coordinates the coordinates of the atoms in the force_env (a.u.)
     450             : !> \param atom_names ...
     451             : !> \param nunits_tot the total number of atoms
     452             : !> \param box_length the length of all sides of the simulation box (angstrom)
     453             : !> \param filename the name of the file to write to
     454             : !> \param nchains ...
     455             : !> \param mc_input_file ...
     456             : !> \author MJM
     457             : !> \note   Only use in serial.
     458             : ! **************************************************************************************************
     459         102 :    SUBROUTINE mc_make_dat_file_new(coordinates, atom_names, nunits_tot, &
     460         102 :                                    box_length, filename, nchains, mc_input_file)
     461             : 
     462             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: coordinates
     463             :       CHARACTER(LEN=*), DIMENSION(:), INTENT(IN)         :: atom_names
     464             :       INTEGER, INTENT(IN)                                :: nunits_tot
     465             :       REAL(KIND=dp), DIMENSION(1:3), INTENT(IN)          :: box_length
     466             :       CHARACTER(LEN=*), INTENT(IN)                       :: filename
     467             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: nchains
     468             :       TYPE(mc_input_file_type), POINTER                  :: mc_input_file
     469             : 
     470             :       CHARACTER(60)                                      :: cell_string, mol_string
     471             :       CHARACTER(default_string_length)                   :: line_text
     472             :       CHARACTER(default_string_length), DIMENSION(:), &
     473         102 :          POINTER                                         :: atom_names_empty, text
     474             :       INTEGER :: cell_column, cell_row, coord_row_end, coord_row_start, force_eval_row_end, &
     475             :          force_eval_row_start, global_row_end, global_row_start, iline, in_use, itype, iunit, &
     476             :          motion_row_end, motion_row_start, nmol_types, nunits_empty, run_type_row, start_line, unit
     477         102 :       INTEGER, DIMENSION(:), POINTER                     :: mol_set_nmol_column, mol_set_nmol_row
     478         102 :       REAL(dp), DIMENSION(:, :), POINTER                 :: coordinates_empty
     479             : 
     480             : ! open the file
     481             : 
     482             :       CALL open_file(file_name=filename, unit_number=unit, &
     483         102 :                      file_action='WRITE', file_status='REPLACE')
     484             : 
     485             : ! get all the information from the input_file_type
     486             :       CALL get_mc_input_file(mc_input_file, text=text, cell_row=cell_row, &
     487             :                              cell_column=cell_column, coord_row_start=coord_row_start, &
     488             :                              coord_row_end=coord_row_end, mol_set_nmol_row=mol_set_nmol_row, &
     489             :                              mol_set_nmol_column=mol_set_nmol_column, &
     490             :                              force_eval_row_start=force_eval_row_start, force_eval_row_end=force_eval_row_end, &
     491             :                              global_row_start=global_row_start, global_row_end=global_row_end, &
     492             :                              run_type_row=run_type_row, in_use=in_use, atom_names_empty=atom_names_empty, &
     493             :                              nunits_empty=nunits_empty, coordinates_empty=coordinates_empty, &
     494         102 :                              motion_row_start=motion_row_start, motion_row_end=motion_row_end)
     495             : 
     496             : ! how many molecule types?
     497         102 :       nmol_types = SIZE(nchains)
     498             : 
     499             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     500             : !!!                                                                                              !!!
     501             : !!!   WARNING: This code assumes that some sections of the input file are in a certain order.    !!!
     502             : !!!                                                                                              !!!
     503             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     504             : 
     505         102 :       CPASSERT(force_eval_row_start < cell_row)
     506         102 :       CPASSERT(cell_row < coord_row_start)
     507         102 :       CPASSERT(coord_row_start < coord_row_end)
     508         102 :       CPASSERT(coord_row_end < mol_set_nmol_row(1))
     509         203 :       DO itype = 1, nmol_types - 1
     510         203 :          CPASSERT(mol_set_nmol_row(itype) < mol_set_nmol_row(itype + 1))
     511             :       END DO
     512         102 :       CPASSERT(mol_set_nmol_row(nmol_types) < force_eval_row_end)
     513             : 
     514             : ! write the global section, but replace the RUN_TYPE
     515         408 :       DO iline = global_row_start, run_type_row - 1
     516         408 :          WRITE (unit, '(A)') TRIM(text(iline))
     517             :       END DO
     518         101 :       SELECT CASE (in_use)
     519             :       CASE (use_fist_force)
     520         101 :          WRITE (unit, '(A)') '  RUN_TYPE     ENERGY_FORCE'
     521             :       CASE (use_qs_force)
     522         102 :          WRITE (unit, '(A)') '  RUN_TYPE     ENERGY_FORCE'
     523             :       END SELECT
     524         204 :       DO iline = run_type_row + 1, global_row_end
     525         204 :          WRITE (unit, '(A)') TRIM(text(iline))
     526             :       END DO
     527             : 
     528             : ! write the motion section without modifications
     529        6028 :       DO iline = motion_row_start, motion_row_end
     530        6028 :          WRITE (unit, '(A)') TRIM(text(iline))
     531             :       END DO
     532             : 
     533             : ! write force_eval section up to the cell lengths
     534        8106 :       DO iline = force_eval_row_start, cell_row - 1
     535        8106 :          WRITE (unit, '(A)') TRIM(text(iline))
     536             :       END DO
     537             : 
     538             : ! substitute in the current cell lengths
     539         408 :       WRITE (cell_string, '(3(F13.8,2X))') box_length(1:3)*angstrom
     540         102 :       line_text = text(cell_row)
     541         102 :       line_text(cell_column:cell_column + 50) = cell_string(1:51)
     542         102 :       WRITE (unit, '(A)') TRIM(line_text)
     543             : 
     544             : ! now write everything until the coordinates
     545         309 :       DO iline = cell_row + 1, coord_row_start
     546         309 :          WRITE (unit, '(A)') TRIM(text(iline))
     547             :       END DO
     548             : 
     549             : ! we may pass nunits_tot=0, but we should still have coordinates
     550         102 :       IF (nunits_tot == 0) THEN
     551           0 :          DO iunit = 1, nunits_empty
     552             :             WRITE (unit, '(5X,A,2X,3(F15.10))') &
     553           0 :                TRIM(ADJUSTL(atom_names_empty(iunit))), &
     554           0 :                coordinates_empty(1:3, iunit)*angstrom
     555             :          END DO
     556             :       ELSE
     557        2638 :          DO iunit = 1, nunits_tot
     558             :             WRITE (unit, '(5X,A,2X,3(F15.10))') &
     559        2536 :                TRIM(ADJUSTL(atom_names(iunit))), &
     560       12782 :                coordinates(1:3, iunit)*angstrom
     561             :          END DO
     562             :       END IF
     563             : 
     564             : ! now we need to write the MOL_SET section
     565             :       start_line = coord_row_end
     566         305 :       DO itype = 1, nmol_types
     567        1126 :          DO iline = start_line, mol_set_nmol_row(itype) - 1
     568        1126 :             WRITE (unit, '(A)') TRIM(text(iline))
     569             :          END DO
     570             : 
     571             : ! have to print out one molecule, even if it's empty
     572         203 :          IF (nunits_tot == 0 .AND. itype == 1) THEN
     573           0 :             WRITE (mol_string, '(I8)') 1
     574             :          ELSE
     575         203 :             WRITE (mol_string, '(I8)') nchains(itype)
     576             :          END IF
     577             : 
     578         203 :          line_text = text(mol_set_nmol_row(itype))
     579             :          line_text(mol_set_nmol_column(itype):mol_set_nmol_column(itype) + 9) = &
     580         203 :             mol_string(1:10)
     581         203 :          WRITE (unit, '(A)') TRIM(line_text)
     582         305 :          start_line = mol_set_nmol_row(itype) + 1
     583             :       END DO
     584             : 
     585             : ! write remainder of force_eval section
     586         612 :       DO iline = start_line, force_eval_row_end
     587         612 :          WRITE (unit, '(A)') TRIM(text(iline))
     588             :       END DO
     589             : 
     590             : ! close the file
     591         102 :       CALL close_file(unit_number=unit)
     592             : 
     593         102 :    END SUBROUTINE MC_MAKE_DAT_FILE_NEW
     594             : END MODULE mc_misc
     595             : 

Generated by: LCOV version 1.15