LCOV - code coverage report
Current view: top level - src - mixed_cdft_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 82.0 % 2177 1786
Test Date: 2026-09-24 01:27:39 Functions: 88.9 % 18 16

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Methods for mixed CDFT calculations
      10              : !> \par   History
      11              : !>                 Separated CDFT routines from mixed_environment_utils
      12              : !> \author Nico Holmberg [01.2017]
      13              : ! **************************************************************************************************
      14              : MODULE mixed_cdft_methods
      15              :    USE ao_util,                         ONLY: exp_radius_very_extended
      16              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      17              :                                               get_atomic_kind
      18              :    USE cell_types,                      ONLY: cell_type,&
      19              :                                               pbc
      20              :    USE cp_array_utils,                  ONLY: cp_1d_i_p_type,&
      21              :                                               cp_1d_r_p_type,&
      22              :                                               cp_2d_r_p_type
      23              :    USE cp_control_types,                ONLY: dft_control_type
      24              :    USE cp_dbcsr_api,                    ONLY: &
      25              :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_init_p, dbcsr_p_type, dbcsr_release, &
      26              :         dbcsr_release_p, dbcsr_scale, dbcsr_type
      27              :    USE cp_dbcsr_diag,                   ONLY: cp_dbcsr_syevd
      28              :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply
      29              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      30              :                                               cp_fm_invert,&
      31              :                                               cp_fm_transpose
      32              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      33              :                                               cp_fm_struct_release,&
      34              :                                               cp_fm_struct_type
      35              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      36              :                                               cp_fm_get_info,&
      37              :                                               cp_fm_release,&
      38              :                                               cp_fm_set_all,&
      39              :                                               cp_fm_to_fm,&
      40              :                                               cp_fm_type,&
      41              :                                               cp_fm_write_formatted
      42              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      43              :                                               cp_logger_type,&
      44              :                                               cp_to_string
      45              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      46              :                                               cp_print_key_unit_nr
      47              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      48              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      49              :                                               cp_subsys_type
      50              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      51              :    USE force_env_types,                 ONLY: force_env_get,&
      52              :                                               force_env_type,&
      53              :                                               use_qmmm,&
      54              :                                               use_qmmmx,&
      55              :                                               use_qs_force
      56              :    USE grid_api,                        ONLY: GRID_FUNC_AB,&
      57              :                                               collocate_pgf_product
      58              :    USE hirshfeld_methods,               ONLY: create_shape_function
      59              :    USE hirshfeld_types,                 ONLY: hirshfeld_type
      60              :    USE input_constants,                 ONLY: &
      61              :         becke_cutoff_element, becke_cutoff_global, cdft_alpha_constraint, cdft_beta_constraint, &
      62              :         cdft_charge_constraint, cdft_magnetization_constraint, mix_cdft, mixed_cdft_parallel, &
      63              :         mixed_cdft_parallel_nobuild, mixed_cdft_serial, outer_scf_becke_constraint
      64              :    USE input_section_types,             ONLY: section_get_lval,&
      65              :                                               section_vals_get,&
      66              :                                               section_vals_get_subs_vals,&
      67              :                                               section_vals_type,&
      68              :                                               section_vals_val_get
      69              :    USE kinds,                           ONLY: default_path_length,&
      70              :                                               dp
      71              :    USE machine,                         ONLY: m_walltime
      72              :    USE mathlib,                         ONLY: diamat_all
      73              :    USE memory_utilities,                ONLY: reallocate
      74              :    USE message_passing,                 ONLY: mp_request_type,&
      75              :                                               mp_testall,&
      76              :                                               mp_waitall
      77              :    USE mixed_cdft_types,                ONLY: mixed_cdft_result_type_set,&
      78              :                                               mixed_cdft_settings_type,&
      79              :                                               mixed_cdft_type,&
      80              :                                               mixed_cdft_type_create,&
      81              :                                               mixed_cdft_work_type_release
      82              :    USE mixed_cdft_utils,                ONLY: &
      83              :         hfun_zero, map_permutation_to_states, mixed_cdft_assemble_block_diag, &
      84              :         mixed_cdft_diagonalize_blocks, mixed_cdft_get_blocks, mixed_cdft_init_structures, &
      85              :         mixed_cdft_parse_settings, mixed_cdft_print_couplings, mixed_cdft_read_block_diag, &
      86              :         mixed_cdft_redistribute_arrays, mixed_cdft_release_work, mixed_cdft_transfer_settings
      87              :    USE mixed_environment_types,         ONLY: get_mixed_env,&
      88              :                                               mixed_environment_type,&
      89              :                                               set_mixed_env
      90              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      91              :    USE particle_list_types,             ONLY: particle_list_type
      92              :    USE particle_types,                  ONLY: particle_type
      93              :    USE pw_env_types,                    ONLY: pw_env_get,&
      94              :                                               pw_env_type
      95              :    USE pw_methods,                      ONLY: pw_copy,&
      96              :                                               pw_scale,&
      97              :                                               pw_zero
      98              :    USE pw_pool_types,                   ONLY: pw_pool_type
      99              :    USE qs_cdft_types,                   ONLY: cdft_control_type
     100              :    USE qs_energy_types,                 ONLY: qs_energy_type
     101              :    USE qs_environment_types,            ONLY: get_qs_env,&
     102              :                                               qs_environment_type
     103              :    USE qs_kind_types,                   ONLY: qs_kind_type
     104              :    USE qs_mo_io,                        ONLY: read_mo_set_from_restart,&
     105              :                                               wfn_restart_file_name
     106              :    USE qs_mo_methods,                   ONLY: make_basis_simple,&
     107              :                                               make_basis_sm
     108              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
     109              :                                               deallocate_mo_set,&
     110              :                                               mo_set_type,&
     111              :                                               set_mo_set
     112              :    USE realspace_grid_types,            ONLY: realspace_grid_type,&
     113              :                                               rs_grid_zero,&
     114              :                                               transfer_rs2pw
     115              :    USE util,                            ONLY: sort
     116              : #include "./base/base_uses.f90"
     117              : 
     118              :    IMPLICIT NONE
     119              : 
     120              :    PRIVATE
     121              : 
     122              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mixed_cdft_methods'
     123              :    LOGICAL, PARAMETER, PRIVATE          :: debug_this_module = .FALSE.
     124              : 
     125              :    TYPE buffers_idx_irr
     126              :       INTEGER                                         :: imap(6) = 0
     127              :       INTEGER, DIMENSION(:), &
     128              :          POINTER                                      :: iv => null()
     129              :       REAL(KIND=dp), POINTER, &
     130              :          DIMENSION(:, :, :)                           :: r3 => null()
     131              :       REAL(KIND=dp), POINTER, &
     132              :          DIMENSION(:, :, :, :)                        :: r4 => null()
     133              :    END TYPE buffers_idx_irr
     134              : 
     135              :    TYPE buffers_bi
     136              :       LOGICAL, POINTER, DIMENSION(:)        :: bv => NULL()
     137              :       INTEGER, POINTER, DIMENSION(:)        :: iv => NULL()
     138              :    END TYPE buffers_bi
     139              : 
     140              :    PUBLIC :: mixed_cdft_init, &
     141              :              mixed_cdft_build_weight, &
     142              :              mixed_cdft_calculate_coupling
     143              : 
     144              : CONTAINS
     145              : 
     146              : ! **************************************************************************************************
     147              : !> \brief Initialize a mixed CDFT calculation
     148              : !> \param force_env the force_env that holds the CDFT states
     149              : !> \param calculate_forces determines if forces should be calculated
     150              : !> \par History
     151              : !>       01.2016  created [Nico Holmberg]
     152              : ! **************************************************************************************************
     153          532 :    SUBROUTINE mixed_cdft_init(force_env, calculate_forces)
     154              :       TYPE(force_env_type), POINTER                      :: force_env
     155              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     156              : 
     157              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mixed_cdft_init'
     158              : 
     159              :       INTEGER                                            :: et_freq, handle, iforce_eval, iounit, &
     160              :                                                             mixing_type, nforce_eval
     161              :       LOGICAL                                            :: explicit, is_parallel, is_qmmm
     162              :       TYPE(cp_logger_type), POINTER                      :: logger
     163              :       TYPE(cp_subsys_type), POINTER                      :: subsys_mix
     164              :       TYPE(force_env_type), POINTER                      :: force_env_qs
     165              :       TYPE(mixed_cdft_settings_type)                     :: settings
     166              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
     167              :       TYPE(mixed_environment_type), POINTER              :: mixed_env
     168              :       TYPE(particle_list_type), POINTER                  :: particles_mix
     169              :       TYPE(section_vals_type), POINTER                   :: force_env_section, mapping_section, &
     170              :                                                             md_section, mixed_section, &
     171              :                                                             print_section, root_section
     172              : 
     173          532 :       NULLIFY (subsys_mix, force_env_qs, force_env_section, print_section, &
     174          532 :                root_section, mixed_section, md_section, mixed_env, mixed_cdft, &
     175          532 :                mapping_section)
     176              : 
     177              :       NULLIFY (settings%grid_span, settings%npts, settings%cutoff, settings%rel_cutoff, &
     178              :                settings%spherical, settings%rs_dims, settings%odd, settings%atoms, &
     179              :                settings%coeffs, settings%si, settings%sr, &
     180              :                settings%cutoffs, settings%radii)
     181              : 
     182          532 :       is_qmmm = .FALSE.
     183         1064 :       logger => cp_get_default_logger()
     184          532 :       CPASSERT(ASSOCIATED(force_env))
     185          532 :       nforce_eval = SIZE(force_env%sub_force_env)
     186          532 :       CALL timeset(routineN, handle)
     187          532 :       CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
     188          532 :       mixed_env => force_env%mixed_env
     189          532 :       mixed_section => section_vals_get_subs_vals(force_env_section, "MIXED")
     190          532 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
     191          532 :       iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
     192              :       ! Check if a mixed CDFT calculation is requested
     193          532 :       CALL section_vals_val_get(mixed_section, "MIXING_TYPE", i_val=mixing_type)
     194          532 :       IF (mixing_type == mix_cdft .AND. .NOT. ASSOCIATED(mixed_env%cdft_control)) THEN
     195           80 :          mixed_env%do_mixed_cdft = .TRUE.
     196          160 :          IF (mixed_env%do_mixed_cdft) THEN
     197              :             ! Sanity check
     198           80 :             IF (nforce_eval < 2) THEN
     199              :                CALL cp_abort(__LOCATION__, &
     200            0 :                              "Mixed CDFT calculation requires at least 2 force_evals.")
     201              :             END IF
     202           80 :             mapping_section => section_vals_get_subs_vals(mixed_section, "MAPPING")
     203           80 :             CALL section_vals_get(mapping_section, explicit=explicit)
     204              :             ! The sub_force_envs must share the same geometrical structure
     205           80 :             IF (explicit) THEN
     206            0 :                CPABORT("Please disable section &MAPPING for mixed CDFT calculations")
     207              :             END IF
     208           80 :             CALL section_vals_val_get(mixed_section, "MIXED_CDFT%COUPLING", i_val=et_freq)
     209           80 :             IF (et_freq < 0) THEN
     210            0 :                mixed_env%do_mixed_et = .FALSE.
     211              :             ELSE
     212           80 :                mixed_env%do_mixed_et = .TRUE.
     213           80 :                IF (et_freq == 0) THEN
     214            0 :                   mixed_env%et_freq = 1
     215              :                ELSE
     216           80 :                   mixed_env%et_freq = et_freq
     217              :                END IF
     218              :             END IF
     219              :             ! Start initializing the mixed_cdft type
     220              :             ! First determine if the calculation is pure DFT or QMMM and find the qs force_env
     221          264 :             DO iforce_eval = 1, nforce_eval
     222          184 :                IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
     223          304 :                SELECT CASE (force_env%sub_force_env(iforce_eval)%force_env%in_use)
     224              :                CASE (use_qs_force)
     225          146 :                   force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
     226              :                CASE (use_qmmm)
     227           12 :                   is_qmmm = .TRUE.
     228              :                   ! This is really the container for QMMM
     229           12 :                   force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
     230              :                CASE (use_qmmmx)
     231            0 :                   CPABORT("No force mixing allowed for mixed CDFT QM/MM")
     232              :                CASE DEFAULT
     233              :                   CALL cp_abort(__LOCATION__, &
     234              :                                 "Only use_qs_force and use_qmmm are "// &
     235          158 :                                 "supported for mixed_cdft_init")
     236              :                END SELECT
     237          238 :                CPASSERT(ASSOCIATED(force_env_qs))
     238              :             END DO
     239              :             ! Get infos about the mixed subsys
     240           80 :             IF (.NOT. is_qmmm) THEN
     241              :                CALL force_env_get(force_env=force_env, &
     242           72 :                                   subsys=subsys_mix)
     243              :                CALL cp_subsys_get(subsys=subsys_mix, &
     244           72 :                                   particles=particles_mix)
     245              :             ELSE
     246              :                CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
     247            8 :                                cp_subsys=subsys_mix)
     248              :                CALL cp_subsys_get(subsys=subsys_mix, &
     249            8 :                                   particles=particles_mix)
     250              :             END IF
     251              :             ! Init mixed_cdft_type
     252           80 :             ALLOCATE (mixed_cdft)
     253           80 :             CALL mixed_cdft_type_create(mixed_cdft)
     254           80 :             mixed_cdft%first_iteration = .TRUE.
     255              :             ! Determine what run type to use
     256           80 :             IF (mixed_env%ngroups == 1) THEN
     257              :                ! States treated in serial, possibly copying CDFT weight function and gradients from state to state
     258           54 :                mixed_cdft%run_type = mixed_cdft_serial
     259           26 :             ELSE IF (mixed_env%ngroups == 2) THEN
     260           26 :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%PARALLEL_BUILD", l_val=is_parallel)
     261           26 :                IF (is_parallel) THEN
     262              :                   ! Treat states in parallel, build weight function and gradients in parallel before SCF process
     263           24 :                   mixed_cdft%run_type = mixed_cdft_parallel
     264           24 :                   IF (.NOT. nforce_eval == 2) THEN
     265              :                      CALL cp_abort(__LOCATION__, &
     266            0 :                                    "Parallel mode mixed CDFT calculation supports only 2 force_evals.")
     267              :                   END IF
     268              :                ELSE
     269              :                   ! Treat states in parallel, but each states builds its own weight function and gradients
     270            2 :                   mixed_cdft%run_type = mixed_cdft_parallel_nobuild
     271              :                END IF
     272              :             ELSE
     273            0 :                mixed_cdft%run_type = mixed_cdft_parallel_nobuild
     274              :             END IF
     275              :             ! Store QMMM flag
     276           80 :             mixed_env%do_mixed_qmmm_cdft = is_qmmm
     277              :             ! Setup dynamic load balancing
     278           80 :             CALL section_vals_val_get(mixed_section, "MIXED_CDFT%DLB", l_val=mixed_cdft%dlb)
     279           80 :             mixed_cdft%dlb = mixed_cdft%dlb .AND. calculate_forces ! disable if forces are not needed
     280           80 :             mixed_cdft%dlb = mixed_cdft%dlb .AND. (mixed_cdft%run_type == mixed_cdft_parallel) ! disable if not parallel
     281           80 :             IF (mixed_cdft%dlb) THEN
     282           40 :                ALLOCATE (mixed_cdft%dlb_control)
     283            4 :                NULLIFY (mixed_cdft%dlb_control%weight, mixed_cdft%dlb_control%gradients, &
     284            4 :                         mixed_cdft%dlb_control%cavity, mixed_cdft%dlb_control%target_list, &
     285            4 :                         mixed_cdft%dlb_control%bo, mixed_cdft%dlb_control%expected_work, &
     286            4 :                         mixed_cdft%dlb_control%prediction_error, mixed_cdft%dlb_control%sendbuff, &
     287            4 :                         mixed_cdft%dlb_control%recvbuff, mixed_cdft%dlb_control%recv_work_repl, &
     288            4 :                         mixed_cdft%dlb_control%recv_info)
     289              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%LOAD_SCALE", &
     290            4 :                                          r_val=mixed_cdft%dlb_control%load_scale)
     291              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%VERY_OVERLOADED", &
     292            4 :                                          r_val=mixed_cdft%dlb_control%very_overloaded)
     293              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%MORE_WORK", &
     294            4 :                                          i_val=mixed_cdft%dlb_control%more_work)
     295              :             END IF
     296              :             ! Metric/Wavefunction overlap method/Lowdin orthogonalization/CDFT-CI
     297           80 :             mixed_cdft%calculate_metric = .FALSE.
     298           80 :             mixed_cdft%wfn_overlap_method = .FALSE.
     299           80 :             mixed_cdft%use_lowdin = .FALSE.
     300           80 :             mixed_cdft%do_ci = .FALSE.
     301           80 :             mixed_cdft%nonortho_coupling = .FALSE.
     302           80 :             mixed_cdft%identical_constraints = .TRUE.
     303           80 :             mixed_cdft%block_diagonalize = .FALSE.
     304           80 :             IF (mixed_env%do_mixed_et) THEN
     305              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%METRIC", &
     306           80 :                                          l_val=mixed_cdft%calculate_metric)
     307              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%WFN_OVERLAP", &
     308           80 :                                          l_val=mixed_cdft%wfn_overlap_method)
     309              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%LOWDIN", &
     310           80 :                                          l_val=mixed_cdft%use_lowdin)
     311              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%CI", &
     312           80 :                                          l_val=mixed_cdft%do_ci)
     313              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%NONORTHOGONAL_COUPLING", &
     314           80 :                                          l_val=mixed_cdft%nonortho_coupling)
     315              :                CALL section_vals_val_get(mixed_section, "MIXED_CDFT%BLOCK_DIAGONALIZE", &
     316           80 :                                          l_val=mixed_cdft%block_diagonalize)
     317              :             END IF
     318              :             ! Inversion method
     319           80 :             CALL section_vals_val_get(mixed_section, "MIXED_CDFT%EPS_SVD", r_val=mixed_cdft%eps_svd)
     320           80 :             IF (mixed_cdft%eps_svd < 0.0_dp .OR. mixed_cdft%eps_svd > 1.0_dp) THEN
     321            0 :                CPABORT("Illegal value for EPS_SVD. Value must be between 0.0 and 1.0.")
     322              :             END IF
     323              :             ! MD related settings
     324           80 :             CALL force_env_get(force_env, root_section=root_section)
     325           80 :             md_section => section_vals_get_subs_vals(root_section, "MOTION%MD")
     326           80 :             CALL section_vals_val_get(md_section, "TIMESTEP", r_val=mixed_cdft%sim_dt)
     327           80 :             CALL section_vals_val_get(md_section, "STEP_START_VAL", i_val=mixed_cdft%sim_step)
     328           80 :             mixed_cdft%sim_step = mixed_cdft%sim_step - 1 ! to get the first step correct
     329           80 :             mixed_cdft%sim_dt = cp_unit_from_cp2k(mixed_cdft%sim_dt, "fs")
     330              :             ! Parse constraint settings from the individual force_evals and check consistency
     331              :             CALL mixed_cdft_parse_settings(force_env, mixed_env, mixed_cdft, &
     332           80 :                                            settings, natom=SIZE(particles_mix%els))
     333              :             ! Transfer settings to mixed_cdft
     334           80 :             CALL mixed_cdft_transfer_settings(force_env, mixed_cdft, settings)
     335              :             ! Initilize necessary structures
     336           80 :             CALL mixed_cdft_init_structures(force_env, force_env_qs, mixed_env, mixed_cdft, settings)
     337              :             ! Write information about the mixed CDFT calculation
     338           80 :             IF (iounit > 0) THEN
     339           40 :                WRITE (iounit, *) ""
     340              :                WRITE (iounit, FMT="(T2,A,T71)") &
     341           40 :                   "MIXED_CDFT| Activating mixed CDFT calculation"
     342              :                WRITE (iounit, FMT="(T2,A,T71,I10)") &
     343           40 :                   "MIXED_CDFT| Number of CDFT states:                                  ", nforce_eval
     344           52 :                SELECT CASE (mixed_cdft%run_type)
     345              :                CASE (mixed_cdft_parallel)
     346              :                   WRITE (iounit, FMT="(T2,A,T71)") &
     347           12 :                      "MIXED_CDFT| CDFT states calculation mode: parallel with build"
     348              :                   WRITE (iounit, FMT="(T2,A,T71)") &
     349           12 :                      "MIXED_CDFT| Becke constraint is first built using all available processors"
     350              :                   WRITE (iounit, FMT="(T2,A,T71)") &
     351           12 :                      "            and then copied to both states with their own processor groups"
     352              :                CASE (mixed_cdft_serial)
     353              :                   WRITE (iounit, FMT="(T2,A,T71)") &
     354           27 :                      "MIXED_CDFT| CDFT states calculation mode: serial"
     355           27 :                   IF (mixed_cdft%identical_constraints) THEN
     356              :                      WRITE (iounit, FMT="(T2,A,T71)") &
     357           26 :                         "MIXED_CDFT| The constraints are built before the SCF procedure of the first"
     358              :                      WRITE (iounit, FMT="(T2,A,T71)") &
     359           26 :                         "            CDFT state and subsequently copied to the other states"
     360              :                   ELSE
     361              :                      WRITE (iounit, FMT="(T2,A,T71)") &
     362            1 :                         "MIXED_CDFT| The constraints are separately built for all CDFT states"
     363              :                   END IF
     364              :                CASE (mixed_cdft_parallel_nobuild)
     365              :                   WRITE (iounit, FMT="(T2,A,T71)") &
     366            1 :                      "MIXED_CDFT| CDFT states calculation mode: parallel without build"
     367              :                   WRITE (iounit, FMT="(T2,A,T71)") &
     368            1 :                      "MIXED_CDFT| The constraints are separately built for all CDFT states"
     369              :                CASE DEFAULT
     370           40 :                   CPABORT("Unknown mixed CDFT run type.")
     371              :                END SELECT
     372              :                WRITE (iounit, FMT="(T2,A,T71,L10)") &
     373           40 :                   "MIXED_CDFT| Calculating electronic coupling between states:         ", mixed_env%do_mixed_et
     374              :                WRITE (iounit, FMT="(T2,A,T71,L10)") &
     375           40 :                   "MIXED_CDFT| Calculating electronic coupling reliability metric:     ", mixed_cdft%calculate_metric
     376              :                WRITE (iounit, FMT="(T2,A,T71,L10)") &
     377           40 :                   "MIXED_CDFT| Configuration interaction (CDFT-CI) was requested:      ", mixed_cdft%do_ci
     378              :                WRITE (iounit, FMT="(T2,A,T71,L10)") &
     379           40 :                   "MIXED_CDFT| Block diagonalizing the mixed CDFT Hamiltonian:         ", mixed_cdft%block_diagonalize
     380           40 :                IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
     381              :                   WRITE (iounit, FMT="(T2,A,T71,L10)") &
     382           12 :                      "MIXED_CDFT| Dynamic load balancing enabled:                         ", mixed_cdft%dlb
     383           12 :                   IF (mixed_cdft%dlb) THEN
     384            2 :                      WRITE (iounit, FMT="(T2,A,T71)") "MIXED_CDFT| Dynamic load balancing parameters:"
     385              :                      WRITE (iounit, FMT="(T2,A,T71,F10.2)") &
     386            2 :                         "MIXED_CDFT| load_scale:", mixed_cdft%dlb_control%load_scale
     387              :                      WRITE (iounit, FMT="(T2,A,T71,F10.2)") &
     388            2 :                         "MIXED_CDFT| very_overloaded:", mixed_cdft%dlb_control%very_overloaded
     389              :                      WRITE (iounit, FMT="(T2,A,T71,I10)") &
     390            2 :                         "MIXED_CDFT| more_work:", mixed_cdft%dlb_control%more_work
     391              :                   END IF
     392              :                END IF
     393           40 :                IF (mixed_env%do_mixed_et) THEN
     394           40 :                   IF (mixed_cdft%eps_svd == 0.0_dp) THEN
     395           32 :                      WRITE (iounit, FMT="(T2,A,T71)") "MIXED_CDFT| Matrix inversions calculated with LU decomposition."
     396              :                   ELSE
     397            8 :                      WRITE (iounit, FMT="(T2,A,T71)") "MIXED_CDFT| Matrix inversions calculated with SVD decomposition."
     398            8 :                      WRITE (iounit, FMT="(T2,A,T71,ES10.2)") "MIXED_CDFT| EPS_SVD:", mixed_cdft%eps_svd
     399              :                   END IF
     400              :                END IF
     401              :             END IF
     402           80 :             CALL set_mixed_env(mixed_env, cdft_control=mixed_cdft)
     403              :          END IF
     404              :       END IF
     405              :       CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
     406          532 :                                         "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
     407          532 :       CALL timestop(handle)
     408              : 
     409         5320 :    END SUBROUTINE mixed_cdft_init
     410              : 
     411              : ! **************************************************************************************************
     412              : !> \brief Driver routine to handle the build of CDFT weight/gradient in parallel and serial modes
     413              : !> \param force_env the force_env that holds the CDFT states
     414              : !> \param calculate_forces if forces should be calculated
     415              : !> \param iforce_eval index of the currently active CDFT state (serial mode only)
     416              : !> \par History
     417              : !>       01.2017  created [Nico Holmberg]
     418              : ! **************************************************************************************************
     419          292 :    SUBROUTINE mixed_cdft_build_weight(force_env, calculate_forces, iforce_eval)
     420              :       TYPE(force_env_type), POINTER                      :: force_env
     421              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     422              :       INTEGER, INTENT(IN), OPTIONAL                      :: iforce_eval
     423              : 
     424              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
     425              : 
     426          292 :       NULLIFY (mixed_cdft)
     427          292 :       CPASSERT(ASSOCIATED(force_env))
     428          292 :       CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
     429          292 :       CPASSERT(ASSOCIATED(mixed_cdft))
     430          292 :       IF (.NOT. PRESENT(iforce_eval)) THEN
     431          138 :          SELECT CASE (mixed_cdft%run_type)
     432              :          CASE (mixed_cdft_parallel)
     433           36 :             CALL mixed_cdft_build_weight_parallel(force_env, calculate_forces)
     434              :          CASE (mixed_cdft_parallel_nobuild)
     435          102 :             CALL mixed_cdft_set_flags(force_env)
     436              :          CASE DEFAULT
     437              :             ! Do nothing
     438              :          END SELECT
     439              :       ELSE
     440          342 :          SELECT CASE (mixed_cdft%run_type)
     441              :          CASE (mixed_cdft_serial)
     442          190 :             CALL mixed_cdft_transfer_weight(force_env, calculate_forces, iforce_eval)
     443              :          CASE DEFAULT
     444              :             ! Do nothing
     445              :          END SELECT
     446              :       END IF
     447              : 
     448          292 :    END SUBROUTINE mixed_cdft_build_weight
     449              : 
     450              : ! **************************************************************************************************
     451              : !> \brief Build CDFT weight and gradient on 2N processors and copy it to two N processor subgroups
     452              : !> \param force_env the force_env that holds the CDFT states
     453              : !> \param calculate_forces if forces should be calculted
     454              : !> \par History
     455              : !>       01.2016  created [Nico Holmberg]
     456              : ! **************************************************************************************************
     457           36 :    SUBROUTINE mixed_cdft_build_weight_parallel(force_env, calculate_forces)
     458              :       TYPE(force_env_type), POINTER                      :: force_env
     459              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     460              : 
     461              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_build_weight_parallel'
     462              : 
     463              :       INTEGER :: handle, handle2, i, iforce_eval, ind, INDEX(6), iounit, j, lb_min, &
     464              :          my_special_work, natom, nforce_eval, recv_offset, ub_max
     465              :       INTEGER, DIMENSION(2, 3)                           :: bo
     466           36 :       INTEGER, DIMENSION(:), POINTER                     :: lb, sendbuffer_i, ub
     467              :       REAL(KIND=dp)                                      :: t1, t2
     468           36 :       TYPE(buffers_idx_irr), DIMENSION(:), POINTER       :: recvbuffer
     469              :       TYPE(cdft_control_type), POINTER                   :: cdft_control, cdft_control_target
     470              :       TYPE(cp_logger_type), POINTER                      :: logger
     471              :       TYPE(cp_subsys_type), POINTER                      :: subsys_mix
     472              :       TYPE(dft_control_type), POINTER                    :: dft_control
     473              :       TYPE(force_env_type), POINTER                      :: force_env_qs
     474              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
     475              :       TYPE(mixed_environment_type), POINTER              :: mixed_env
     476           36 :       TYPE(mp_request_type), DIMENSION(:), POINTER       :: req_total
     477              :       TYPE(particle_list_type), POINTER                  :: particles_mix
     478              :       TYPE(pw_env_type), POINTER                         :: pw_env
     479              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool, mixed_auxbas_pw_pool
     480              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     481              :       TYPE(section_vals_type), POINTER                   :: force_env_section, print_section
     482              : 
     483           36 :       NULLIFY (subsys_mix, force_env_qs, particles_mix, force_env_section, print_section, &
     484           36 :                mixed_env, mixed_cdft, pw_env, auxbas_pw_pool, mixed_auxbas_pw_pool, &
     485           36 :                qs_env, dft_control, sendbuffer_i, lb, ub, req_total, recvbuffer, &
     486           36 :                cdft_control, cdft_control_target)
     487              : 
     488           72 :       logger => cp_get_default_logger()
     489           36 :       CPASSERT(ASSOCIATED(force_env))
     490           36 :       nforce_eval = SIZE(force_env%sub_force_env)
     491           36 :       CALL timeset(routineN, handle)
     492           36 :       t1 = m_walltime()
     493              :       ! Get infos about the mixed subsys
     494              :       CALL force_env_get(force_env=force_env, &
     495              :                          subsys=subsys_mix, &
     496           36 :                          force_env_section=force_env_section)
     497              :       CALL cp_subsys_get(subsys=subsys_mix, &
     498           36 :                          particles=particles_mix)
     499          108 :       DO iforce_eval = 1, nforce_eval
     500           72 :          IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
     501           36 :          SELECT CASE (force_env%sub_force_env(iforce_eval)%force_env%in_use)
     502              :          CASE (use_qs_force)
     503              :             force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
     504              :          CASE (use_qmmm)
     505            0 :             force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
     506              :          CASE DEFAULT
     507              :             CALL cp_abort(__LOCATION__, &
     508              :                           "Only use_qs_force and use_qmmm are "// &
     509           72 :                           "supported for mixed_cdft_build_weight_parallel")
     510              :          END SELECT
     511              :       END DO
     512           36 :       IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
     513              :          CALL force_env_get(force_env=force_env_qs, &
     514              :                             qs_env=qs_env, &
     515           28 :                             subsys=subsys_mix)
     516              :          CALL cp_subsys_get(subsys=subsys_mix, &
     517           28 :                             particles=particles_mix)
     518              :       ELSE
     519            8 :          qs_env => force_env_qs%qmmm_env%qs_env
     520            8 :          CALL get_qs_env(qs_env, cp_subsys=subsys_mix)
     521              :          CALL cp_subsys_get(subsys=subsys_mix, &
     522            8 :                             particles=particles_mix)
     523              :       END IF
     524           36 :       mixed_env => force_env%mixed_env
     525           36 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
     526           36 :       iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
     527           36 :       CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
     528           36 :       CPASSERT(ASSOCIATED(mixed_cdft))
     529           36 :       cdft_control => mixed_cdft%cdft_control
     530           36 :       CPASSERT(ASSOCIATED(cdft_control))
     531              :       ! Calculate the Becke weight function and gradient on all np processors
     532           36 :       CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_pw_pool=mixed_auxbas_pw_pool)
     533           36 :       natom = SIZE(particles_mix%els)
     534           36 :       CALL mixed_becke_constraint(force_env, calculate_forces)
     535              :       ! Start replicating the working arrays on both np/2 processor groups
     536           36 :       mixed_cdft%sim_step = mixed_cdft%sim_step + 1
     537           36 :       CALL get_qs_env(qs_env, pw_env=pw_env, dft_control=dft_control)
     538           36 :       cdft_control_target => dft_control%qs_control%cdft_control
     539           36 :       CPASSERT(dft_control%qs_control%cdft)
     540           36 :       CPASSERT(ASSOCIATED(cdft_control_target))
     541           36 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     542          360 :       bo = auxbas_pw_pool%pw_grid%bounds_local
     543              :       ! First determine the size of the arrays along the confinement dir
     544           36 :       IF (mixed_cdft%is_special) THEN
     545              :          my_special_work = 2
     546              :       ELSE
     547           36 :          my_special_work = 1
     548              :       END IF
     549          432 :       ALLOCATE (recvbuffer(SIZE(mixed_cdft%source_list)))
     550          252 :       ALLOCATE (req_total(my_special_work*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)))
     551          144 :       ALLOCATE (lb(SIZE(mixed_cdft%source_list)), ub(SIZE(mixed_cdft%source_list)))
     552           36 :       IF (cdft_control%becke_control%cavity_confine) THEN
     553              :          ! Gaussian confinement => the bounds depend on the processor and need to be communicated
     554           34 :          ALLOCATE (sendbuffer_i(2))
     555          204 :          sendbuffer_i = cdft_control%becke_control%confine_bounds
     556          102 :          DO i = 1, SIZE(mixed_cdft%source_list)
     557           68 :             ALLOCATE (recvbuffer(i)%iv(2))
     558              :             CALL force_env%para_env%irecv(msgout=recvbuffer(i)%iv, source=mixed_cdft%source_list(i), &
     559          102 :                                           request=req_total(i))
     560              :          END DO
     561           68 :          DO i = 1, my_special_work
     562          136 :             DO j = 1, SIZE(mixed_cdft%dest_list)
     563           68 :                ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
     564              :                CALL force_env%para_env%isend(msgin=sendbuffer_i, &
     565              :                                              dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
     566          102 :                                              request=req_total(ind))
     567              :             END DO
     568              :          END DO
     569           34 :          CALL mp_waitall(req_total)
     570              :          ! Find the largest/smallest value of ub/lb
     571           34 :          DEALLOCATE (sendbuffer_i)
     572           34 :          lb_min = HUGE(0)
     573           34 :          ub_max = -HUGE(0)
     574          102 :          DO i = 1, SIZE(mixed_cdft%source_list)
     575           68 :             lb(i) = recvbuffer(i)%iv(1)
     576           68 :             ub(i) = recvbuffer(i)%iv(2)
     577           68 :             IF (lb(i) < lb_min) lb_min = lb(i)
     578           68 :             IF (ub(i) > ub_max) ub_max = ub(i)
     579          102 :             DEALLOCATE (recvbuffer(i)%iv)
     580              :          END DO
     581              :          ! Take into account the grids already communicated during dlb
     582           34 :          IF (mixed_cdft%dlb) THEN
     583           16 :             IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
     584           24 :                DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
     585           24 :                   IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
     586           16 :                      DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
     587           16 :                         IF (LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3) &
     588            0 :                             < lb_min) lb_min = LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3)
     589           16 :                         IF (UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3) &
     590            8 :                             > ub_max) ub_max = UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3)
     591              :                      END DO
     592              :                   END IF
     593              :                END DO
     594              :             END IF
     595              :          END IF
     596              :       ELSE
     597              :          ! No confinement
     598            2 :          ub_max = bo(2, 3)
     599            2 :          lb_min = bo(1, 3)
     600            6 :          lb = lb_min
     601            6 :          ub = ub_max
     602              :       END IF
     603              :       ! Determine the sender specific indices of grid slices that are to be received
     604           36 :       CALL timeset(routineN//"_comm", handle2)
     605          108 :       DO j = 1, SIZE(recvbuffer)
     606           72 :          ind = j + (j/2)
     607          108 :          IF (mixed_cdft%is_special) THEN
     608              :             recvbuffer(j)%imap = [mixed_cdft%source_list_bo(1, j), mixed_cdft%source_list_bo(2, j), &
     609              :                                   mixed_cdft%source_list_bo(3, j), mixed_cdft%source_list_bo(4, j), &
     610            0 :                                   lb(j), ub(j)]
     611           72 :          ELSE IF (mixed_cdft%is_pencil) THEN
     612            0 :             recvbuffer(j)%imap = [bo(1, 1), bo(2, 1), mixed_cdft%recv_bo(ind), mixed_cdft%recv_bo(ind + 1), lb(j), ub(j)]
     613              :          ELSE
     614          504 :             recvbuffer(j)%imap = [mixed_cdft%recv_bo(ind), mixed_cdft%recv_bo(ind + 1), bo(1, 2), bo(2, 2), lb(j), ub(j)]
     615              :          END IF
     616              :       END DO
     617           36 :       IF (mixed_cdft%dlb .AND. .NOT. mixed_cdft%is_special) THEN
     618            8 :          IF (mixed_cdft%dlb_control%recv_work_repl(1) .OR. mixed_cdft%dlb_control%recv_work_repl(2)) THEN
     619           24 :             DO j = 1, 2
     620           16 :                recv_offset = 0
     621           16 :                IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
     622           16 :                   recv_offset = SUM(mixed_cdft%dlb_control%recv_info(j)%target_list(2, :))
     623              :                END IF
     624           24 :                IF (mixed_cdft%is_pencil) THEN
     625            0 :                   recvbuffer(j)%imap(1) = recvbuffer(j)%imap(1) + recv_offset
     626              :                ELSE
     627           16 :                   recvbuffer(j)%imap(3) = recvbuffer(j)%imap(3) + recv_offset
     628              :                END IF
     629              :             END DO
     630              :          END IF
     631              :       END IF
     632              :       ! Transfer the arrays one-by-one and deallocate shared storage
     633              :       ! Start with the weight function
     634          108 :       DO j = 1, SIZE(mixed_cdft%source_list)
     635              :          ALLOCATE (recvbuffer(j)%r3(recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
     636              :                                     recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
     637          360 :                                     recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)))
     638              : 
     639              :          CALL force_env%para_env%irecv(msgout=recvbuffer(j)%r3, source=mixed_cdft%source_list(j), &
     640          108 :                                        request=req_total(j))
     641              :       END DO
     642           72 :       DO i = 1, my_special_work
     643          144 :          DO j = 1, SIZE(mixed_cdft%dest_list)
     644           72 :             ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
     645          108 :             IF (mixed_cdft%is_special) THEN
     646              :                CALL force_env%para_env%isend(msgin=mixed_cdft%sendbuff(j)%weight, &
     647              :                                              dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
     648            0 :                                              request=req_total(ind))
     649              :             ELSE
     650              :                CALL force_env%para_env%isend(msgin=mixed_cdft%weight, dest=mixed_cdft%dest_list(j), &
     651           72 :                                              request=req_total(ind))
     652              :             END IF
     653              :          END DO
     654              :       END DO
     655           36 :       CALL mp_waitall(req_total)
     656           36 :       IF (mixed_cdft%is_special) THEN
     657            0 :          DO j = 1, SIZE(mixed_cdft%dest_list)
     658            0 :             DEALLOCATE (mixed_cdft%sendbuff(j)%weight)
     659              :          END DO
     660              :       ELSE
     661           36 :          DEALLOCATE (mixed_cdft%weight)
     662              :       END IF
     663              :       ! In principle, we could reduce the memory footprint of becke_pot by only transferring the nonzero portion
     664              :       ! of the potential, but this would require a custom integrate_v_rspace
     665           36 :       ALLOCATE (cdft_control_target%group(1)%weight)
     666           36 :       CALL auxbas_pw_pool%create_pw(cdft_control_target%group(1)%weight)
     667           36 :       CALL pw_zero(cdft_control_target%group(1)%weight)
     668              :       ! Assemble the recved slices
     669          108 :       DO j = 1, SIZE(mixed_cdft%source_list)
     670              :          cdft_control_target%group(1)%weight%array(recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
     671              :                                                    recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
     672      7517624 :                                                    recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)) = recvbuffer(j)%r3
     673              :       END DO
     674              :       ! Do the same for slices sent during dlb
     675           36 :       IF (mixed_cdft%dlb) THEN
     676           16 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
     677           24 :             DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
     678           24 :                IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
     679           16 :                   DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
     680              :                      index = [LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 1), &
     681              :                               UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 1), &
     682              :                               LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 2), &
     683              :                               UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 2), &
     684              :                               LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3), &
     685          104 :                               UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3)]
     686              :                      cdft_control_target%group(1)%weight%array(INDEX(1):INDEX(2), &
     687              :                                                                INDEX(3):INDEX(4), &
     688              :                                                                INDEX(5):INDEX(6)) = &
     689        14096 :                         mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight
     690           16 :                      DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight)
     691              :                   END DO
     692              :                END IF
     693              :             END DO
     694              :          END IF
     695              :       END IF
     696              :       ! Gaussian confinement cavity
     697           36 :       IF (cdft_control%becke_control%cavity_confine) THEN
     698          102 :          DO j = 1, SIZE(mixed_cdft%source_list)
     699              :             CALL force_env%para_env%irecv(msgout=recvbuffer(j)%r3, source=mixed_cdft%source_list(j), &
     700          102 :                                           request=req_total(j))
     701              :          END DO
     702           68 :          DO i = 1, my_special_work
     703          136 :             DO j = 1, SIZE(mixed_cdft%dest_list)
     704           68 :                ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
     705          102 :                IF (mixed_cdft%is_special) THEN
     706              :                   CALL force_env%para_env%isend(msgin=mixed_cdft%sendbuff(j)%cavity, &
     707              :                                                 dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
     708            0 :                                                 request=req_total(ind))
     709              :                ELSE
     710              :                   CALL force_env%para_env%isend(msgin=mixed_cdft%cavity, dest=mixed_cdft%dest_list(j), &
     711           68 :                                                 request=req_total(ind))
     712              :                END IF
     713              :             END DO
     714              :          END DO
     715           34 :          CALL mp_waitall(req_total)
     716           34 :          IF (mixed_cdft%is_special) THEN
     717            0 :             DO j = 1, SIZE(mixed_cdft%dest_list)
     718            0 :                DEALLOCATE (mixed_cdft%sendbuff(j)%cavity)
     719              :             END DO
     720              :          ELSE
     721           34 :             DEALLOCATE (mixed_cdft%cavity)
     722              :          END IF
     723              :          ! We only need the nonzero part of the confinement cavity
     724              :          ALLOCATE (cdft_control_target%becke_control%cavity_mat(bo(1, 1):bo(2, 1), &
     725              :                                                                 bo(1, 2):bo(2, 2), &
     726          170 :                                                                 lb_min:ub_max))
     727      3504226 :          cdft_control_target%becke_control%cavity_mat = 0.0_dp
     728              : 
     729          102 :          DO j = 1, SIZE(mixed_cdft%source_list)
     730              :             cdft_control_target%becke_control%cavity_mat(recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
     731              :                                                          recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
     732      7136554 :                                                          recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)) = recvbuffer(j)%r3
     733              :          END DO
     734           34 :          IF (mixed_cdft%dlb) THEN
     735           16 :             IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
     736           24 :                DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
     737           24 :                   IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
     738           16 :                      DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
     739              :                         index = [LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 1), &
     740              :                                  UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 1), &
     741              :                                  LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 2), &
     742              :                                  UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 2), &
     743              :                                  LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 3), &
     744          104 :                                  UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 3)]
     745              :                         cdft_control_target%becke_control%cavity_mat(INDEX(1):INDEX(2), &
     746              :                                                                      INDEX(3):INDEX(4), &
     747              :                                                                      INDEX(5):INDEX(6)) = &
     748        14096 :                            mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity
     749           16 :                         DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity)
     750              :                      END DO
     751              :                   END IF
     752              :                END DO
     753              :             END IF
     754              :          END IF
     755              :       END IF
     756          108 :       DO j = 1, SIZE(mixed_cdft%source_list)
     757          108 :          DEALLOCATE (recvbuffer(j)%r3)
     758              :       END DO
     759           36 :       IF (calculate_forces) THEN
     760              :          ! Gradients of the weight function
     761           72 :          DO j = 1, SIZE(mixed_cdft%source_list)
     762              :             ALLOCATE (recvbuffer(j)%r4(3*natom, recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
     763              :                                        recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
     764          288 :                                        recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)))
     765              :             CALL force_env%para_env%irecv(msgout=recvbuffer(j)%r4, source=mixed_cdft%source_list(j), &
     766           72 :                                           request=req_total(j))
     767              :          END DO
     768           48 :          DO i = 1, my_special_work
     769           96 :             DO j = 1, SIZE(mixed_cdft%dest_list)
     770           48 :                ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
     771           72 :                IF (mixed_cdft%is_special) THEN
     772              :                   CALL force_env%para_env%isend(msgin=mixed_cdft%sendbuff(j)%gradients, &
     773              :                                                 dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
     774            0 :                                                 request=req_total(ind))
     775              :                ELSE
     776              :                   CALL force_env%para_env%isend(msgin=cdft_control%group(1)%gradients, dest=mixed_cdft%dest_list(j), &
     777           48 :                                                 request=req_total(ind))
     778              :                END IF
     779              :             END DO
     780              :          END DO
     781           24 :          CALL mp_waitall(req_total)
     782           24 :          IF (mixed_cdft%is_special) THEN
     783            0 :             DO j = 1, SIZE(mixed_cdft%dest_list)
     784            0 :                DEALLOCATE (mixed_cdft%sendbuff(j)%gradients)
     785              :             END DO
     786            0 :             DEALLOCATE (mixed_cdft%sendbuff)
     787              :          ELSE
     788           24 :             DEALLOCATE (cdft_control%group(1)%gradients)
     789              :          END IF
     790              :          ALLOCATE (cdft_control_target%group(1)%gradients(3*natom, bo(1, 1):bo(2, 1), &
     791          144 :                                                           bo(1, 2):bo(2, 2), lb_min:ub_max))
     792           72 :          DO j = 1, SIZE(mixed_cdft%source_list)
     793              :             cdft_control_target%group(1)%gradients(:, recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
     794              :                                                    recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
     795     39235744 :                                                    recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)) = recvbuffer(j)%r4
     796           72 :             DEALLOCATE (recvbuffer(j)%r4)
     797              :          END DO
     798           24 :          IF (mixed_cdft%dlb) THEN
     799           16 :             IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
     800           24 :                DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
     801           24 :                   IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
     802           16 :                      DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
     803              :                         index = [LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 2), &
     804              :                                  UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 2), &
     805              :                                  LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 3), &
     806              :                                  UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 3), &
     807              :                                  LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 4), &
     808          104 :                                  UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 4)]
     809              :                         cdft_control_target%group(1)%gradients(:, INDEX(1):INDEX(2), &
     810              :                                                                INDEX(3):INDEX(4), &
     811              :                                                                INDEX(5):INDEX(6)) = &
     812        90896 :                            mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients
     813           16 :                         DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients)
     814              :                      END DO
     815              :                   END IF
     816              :                END DO
     817              :             END IF
     818              :          END IF
     819              :       END IF
     820              :       ! Clean up remaining temporaries
     821           36 :       IF (mixed_cdft%dlb) THEN
     822           16 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
     823           24 :             DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
     824           24 :                IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
     825            8 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%recv_info(j)%target_list)) THEN
     826            8 :                      DEALLOCATE (mixed_cdft%dlb_control%recv_info(j)%target_list)
     827              :                   END IF
     828            8 :                   DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs)
     829              :                END IF
     830              :             END DO
     831            8 :             DEALLOCATE (mixed_cdft%dlb_control%recv_info, mixed_cdft%dlb_control%recvbuff)
     832              :          END IF
     833            8 :          IF (ASSOCIATED(mixed_cdft%dlb_control%target_list)) THEN
     834            4 :             DEALLOCATE (mixed_cdft%dlb_control%target_list)
     835              :          END IF
     836            8 :          DEALLOCATE (mixed_cdft%dlb_control%recv_work_repl)
     837              :       END IF
     838           36 :       DEALLOCATE (recvbuffer)
     839           36 :       DEALLOCATE (req_total)
     840           36 :       DEALLOCATE (lb)
     841           36 :       DEALLOCATE (ub)
     842           36 :       CALL timestop(handle2)
     843              :       ! Set some flags so the weight is not rebuilt during SCF
     844           36 :       cdft_control_target%external_control = .TRUE.
     845           36 :       cdft_control_target%need_pot = .FALSE.
     846           36 :       cdft_control_target%transfer_pot = .FALSE.
     847              :       ! Store the bound indices for force calculation
     848           36 :       IF (calculate_forces) THEN
     849           24 :          cdft_control_target%becke_control%confine_bounds(2) = ub_max
     850           24 :          cdft_control_target%becke_control%confine_bounds(1) = lb_min
     851              :       END IF
     852              :       CALL pw_scale(cdft_control_target%group(1)%weight, &
     853           36 :                     cdft_control_target%group(1)%weight%pw_grid%dvol)
     854              :       ! Set flags for ET coupling calculation
     855           36 :       IF (mixed_env%do_mixed_et) THEN
     856           36 :          IF (MODULO(mixed_cdft%sim_step, mixed_env%et_freq) == 0) THEN
     857           36 :             dft_control%qs_control%cdft_control%do_et = .TRUE.
     858           36 :             dft_control%qs_control%cdft_control%calculate_metric = mixed_cdft%calculate_metric
     859              :          ELSE
     860            0 :             dft_control%qs_control%cdft_control%do_et = .FALSE.
     861            0 :             dft_control%qs_control%cdft_control%calculate_metric = .FALSE.
     862              :          END IF
     863              :       END IF
     864           36 :       t2 = m_walltime()
     865           36 :       IF (iounit > 0) THEN
     866           18 :          WRITE (iounit, '(A)') ' '
     867           18 :          WRITE (iounit, '(T2,A,F6.1,A)') 'MIXED_CDFT| Becke constraint built in ', t2 - t1, ' seconds'
     868           18 :          WRITE (iounit, '(A)') ' '
     869              :       END IF
     870              :       CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
     871           36 :                                         "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
     872           36 :       CALL timestop(handle)
     873              : 
     874          108 :    END SUBROUTINE mixed_cdft_build_weight_parallel
     875              : 
     876              : ! **************************************************************************************************
     877              : !> \brief Transfer CDFT weight/gradient between force_evals
     878              : !> \param force_env the force_env that holds the CDFT sub_force_envs
     879              : !> \param calculate_forces if forces should be computed
     880              : !> \param iforce_eval index of the currently active CDFT state
     881              : !> \par History
     882              : !>       01.2017  created [Nico Holmberg]
     883              : ! **************************************************************************************************
     884          304 :    SUBROUTINE mixed_cdft_transfer_weight(force_env, calculate_forces, iforce_eval)
     885              :       TYPE(force_env_type), POINTER                      :: force_env
     886              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     887              :       INTEGER, INTENT(IN)                                :: iforce_eval
     888              : 
     889              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_transfer_weight'
     890              : 
     891              :       INTEGER                                            :: bounds_of(8), handle, iatom, igroup, &
     892              :                                                             jforce_eval, nforce_eval
     893              :       LOGICAL, SAVE                                      :: first_call = .TRUE.
     894              :       TYPE(cdft_control_type), POINTER                   :: cdft_control_source, cdft_control_target
     895              :       TYPE(dft_control_type), POINTER                    :: dft_control_source, dft_control_target
     896              :       TYPE(force_env_type), POINTER                      :: force_env_qs_source, force_env_qs_target
     897              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
     898              :       TYPE(mixed_environment_type), POINTER              :: mixed_env
     899              :       TYPE(pw_env_type), POINTER                         :: pw_env_source, pw_env_target
     900              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool_source, &
     901              :                                                             auxbas_pw_pool_target
     902              :       TYPE(qs_environment_type), POINTER                 :: qs_env_source, qs_env_target
     903              : 
     904          152 :       NULLIFY (mixed_cdft, dft_control_source, dft_control_target, force_env_qs_source, &
     905          152 :                force_env_qs_target, pw_env_source, pw_env_target, auxbas_pw_pool_source, &
     906          152 :                auxbas_pw_pool_target, qs_env_source, qs_env_target, mixed_env, &
     907          152 :                cdft_control_source, cdft_control_target)
     908          152 :       mixed_env => force_env%mixed_env
     909          152 :       CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
     910          152 :       CALL timeset(routineN, handle)
     911          152 :       IF (iforce_eval == 1) THEN
     912              :          jforce_eval = 1
     913              :       ELSE
     914           88 :          jforce_eval = iforce_eval - 1
     915              :       END IF
     916          152 :       nforce_eval = SIZE(force_env%sub_force_env)
     917          304 :       SELECT CASE (force_env%sub_force_env(jforce_eval)%force_env%in_use)
     918              :       CASE (use_qs_force, use_qmmm)
     919          152 :          force_env_qs_source => force_env%sub_force_env(jforce_eval)%force_env
     920          152 :          force_env_qs_target => force_env%sub_force_env(iforce_eval)%force_env
     921              :       CASE DEFAULT
     922              :          CALL cp_abort(__LOCATION__, &
     923              :                        "Only use_qs_force and use_qmmm are "// &
     924          152 :                        "supported for mixed_cdft_transfer_weight")
     925              :       END SELECT
     926          152 :       IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
     927              :          CALL force_env_get(force_env=force_env_qs_source, &
     928          136 :                             qs_env=qs_env_source)
     929              :          CALL force_env_get(force_env=force_env_qs_target, &
     930          136 :                             qs_env=qs_env_target)
     931              :       ELSE
     932           16 :          qs_env_source => force_env_qs_source%qmmm_env%qs_env
     933           16 :          qs_env_target => force_env_qs_target%qmmm_env%qs_env
     934              :       END IF
     935          152 :       IF (iforce_eval == 1) THEN
     936              :          ! The first force_eval builds the weight function and gradients in qs_cdft_methods.F
     937              :          ! Set some flags so the constraint is saved if the constraint definitions are identical in all CDFT states
     938           64 :          CALL get_qs_env(qs_env_source, dft_control=dft_control_source)
     939           64 :          cdft_control_source => dft_control_source%qs_control%cdft_control
     940           64 :          cdft_control_source%external_control = .FALSE.
     941           64 :          cdft_control_source%need_pot = .TRUE.
     942           64 :          IF (mixed_cdft%identical_constraints) THEN
     943           62 :             cdft_control_source%transfer_pot = .TRUE.
     944              :          ELSE
     945            2 :             cdft_control_source%transfer_pot = .FALSE.
     946              :          END IF
     947           64 :          mixed_cdft%sim_step = mixed_cdft%sim_step + 1
     948              :       ELSE
     949              :          ! Transfer the constraint from the ith force_eval to the i+1th
     950              :          CALL get_qs_env(qs_env_source, dft_control=dft_control_source, &
     951           88 :                          pw_env=pw_env_source)
     952           88 :          CALL pw_env_get(pw_env_source, auxbas_pw_pool=auxbas_pw_pool_source)
     953           88 :          cdft_control_source => dft_control_source%qs_control%cdft_control
     954              :          CALL get_qs_env(qs_env_target, dft_control=dft_control_target, &
     955           88 :                          pw_env=pw_env_target)
     956           88 :          CALL pw_env_get(pw_env_target, auxbas_pw_pool=auxbas_pw_pool_target)
     957           88 :          cdft_control_target => dft_control_target%qs_control%cdft_control
     958              :          ! The constraint can be transferred only when the constraint defitions are identical in all CDFT states
     959           88 :          IF (mixed_cdft%identical_constraints) THEN
     960              :             ! Weight function
     961          174 :             DO igroup = 1, SIZE(cdft_control_target%group)
     962           88 :                ALLOCATE (cdft_control_target%group(igroup)%weight)
     963           88 :                CALL auxbas_pw_pool_target%create_pw(cdft_control_target%group(igroup)%weight)
     964              :                ! We have ensured that the grids are consistent => no danger in using explicit copy
     965           88 :                CALL pw_copy(cdft_control_source%group(igroup)%weight, cdft_control_target%group(igroup)%weight)
     966           88 :                CALL auxbas_pw_pool_source%give_back_pw(cdft_control_source%group(igroup)%weight)
     967          174 :                DEALLOCATE (cdft_control_source%group(igroup)%weight)
     968              :             END DO
     969              :             ! Cavity
     970           86 :             IF (cdft_control_source%type == outer_scf_becke_constraint) THEN
     971           80 :                IF (cdft_control_source%becke_control%cavity_confine) THEN
     972           72 :                   CALL auxbas_pw_pool_target%create_pw(cdft_control_target%becke_control%cavity)
     973           72 :                   CALL pw_copy(cdft_control_source%becke_control%cavity, cdft_control_target%becke_control%cavity)
     974           72 :                   CALL auxbas_pw_pool_source%give_back_pw(cdft_control_source%becke_control%cavity)
     975              :                END IF
     976              :             END IF
     977              :             ! Gradients
     978           86 :             IF (calculate_forces) THEN
     979           40 :                DO igroup = 1, SIZE(cdft_control_source%group)
     980              :                   bounds_of = [LBOUND(cdft_control_source%group(igroup)%gradients, 1), &
     981              :                                UBOUND(cdft_control_source%group(igroup)%gradients, 1), &
     982              :                                LBOUND(cdft_control_source%group(igroup)%gradients, 2), &
     983              :                                UBOUND(cdft_control_source%group(igroup)%gradients, 2), &
     984              :                                LBOUND(cdft_control_source%group(igroup)%gradients, 3), &
     985              :                                UBOUND(cdft_control_source%group(igroup)%gradients, 3), &
     986              :                                LBOUND(cdft_control_source%group(igroup)%gradients, 4), &
     987          340 :                                UBOUND(cdft_control_source%group(igroup)%gradients, 4)]
     988              :                   ALLOCATE (cdft_control_target%group(igroup)% &
     989              :                             gradients(bounds_of(1):bounds_of(2), bounds_of(3):bounds_of(4), &
     990          120 :                                       bounds_of(5):bounds_of(6), bounds_of(7):bounds_of(8)))
     991     17857864 :                   cdft_control_target%group(igroup)%gradients = cdft_control_source%group(igroup)%gradients
     992           40 :                   DEALLOCATE (cdft_control_source%group(igroup)%gradients)
     993              :                END DO
     994              :             END IF
     995              :             ! Atomic weight functions needed for CDFT charges
     996           86 :             IF (cdft_control_source%atomic_charges) THEN
     997           18 :                IF (.NOT. ASSOCIATED(cdft_control_target%charge)) THEN
     998           10 :                   ALLOCATE (cdft_control_target%charge(cdft_control_target%natoms))
     999              :                END IF
    1000           54 :                DO iatom = 1, cdft_control_target%natoms
    1001           36 :                   CALL auxbas_pw_pool_target%create_pw(cdft_control_target%charge(iatom))
    1002           36 :                   CALL pw_copy(cdft_control_source%charge(iatom), cdft_control_target%charge(iatom))
    1003           54 :                   CALL auxbas_pw_pool_source%give_back_pw(cdft_control_source%charge(iatom))
    1004              :                END DO
    1005              :             END IF
    1006              :             ! Set some flags so the weight is not rebuilt during SCF
    1007           86 :             cdft_control_target%external_control = .FALSE.
    1008           86 :             cdft_control_target%need_pot = .FALSE.
    1009              :             ! For states i+1 < nforce_eval, prevent deallocation of constraint
    1010           86 :             IF (iforce_eval == nforce_eval) THEN
    1011           62 :                cdft_control_target%transfer_pot = .FALSE.
    1012              :             ELSE
    1013           24 :                cdft_control_target%transfer_pot = .TRUE.
    1014              :             END IF
    1015           86 :             cdft_control_target%first_iteration = .FALSE.
    1016              :          ELSE
    1017              :             ! Force rebuild of constraint and dont save it
    1018            2 :             cdft_control_target%external_control = .FALSE.
    1019            2 :             cdft_control_target%need_pot = .TRUE.
    1020            2 :             cdft_control_target%transfer_pot = .FALSE.
    1021            2 :             IF (first_call) THEN
    1022            2 :                cdft_control_target%first_iteration = .TRUE.
    1023              :             ELSE
    1024            0 :                cdft_control_target%first_iteration = .FALSE.
    1025              :             END IF
    1026              :          END IF
    1027              :       END IF
    1028              :       ! Set flags for ET coupling calculation
    1029          152 :       IF (mixed_env%do_mixed_et) THEN
    1030          152 :          IF (MODULO(mixed_cdft%sim_step, mixed_env%et_freq) == 0) THEN
    1031          152 :             IF (iforce_eval == 1) THEN
    1032           64 :                cdft_control_source%do_et = .TRUE.
    1033           64 :                cdft_control_source%calculate_metric = mixed_cdft%calculate_metric
    1034              :             ELSE
    1035           88 :                cdft_control_target%do_et = .TRUE.
    1036           88 :                cdft_control_target%calculate_metric = mixed_cdft%calculate_metric
    1037              :             END IF
    1038              :          ELSE
    1039            0 :             IF (iforce_eval == 1) THEN
    1040            0 :                cdft_control_source%do_et = .FALSE.
    1041            0 :                cdft_control_source%calculate_metric = .FALSE.
    1042              :             ELSE
    1043            0 :                cdft_control_target%do_et = .FALSE.
    1044            0 :                cdft_control_target%calculate_metric = .FALSE.
    1045              :             END IF
    1046              :          END IF
    1047              :       END IF
    1048          152 :       IF (iforce_eval == nforce_eval .AND. first_call) first_call = .FALSE.
    1049          152 :       CALL timestop(handle)
    1050              : 
    1051          152 :    END SUBROUTINE mixed_cdft_transfer_weight
    1052              : 
    1053              : ! **************************************************************************************************
    1054              : !> \brief In case CDFT states are treated in parallel, sets flags so that each CDFT state
    1055              : !>        builds their own weight functions and gradients
    1056              : !> \param force_env the force_env that holds the CDFT sub_force_envs
    1057              : !> \par History
    1058              : !>       09.2018  created [Nico Holmberg]
    1059              : ! **************************************************************************************************
    1060            4 :    SUBROUTINE mixed_cdft_set_flags(force_env)
    1061              :       TYPE(force_env_type), POINTER                      :: force_env
    1062              : 
    1063              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_set_flags'
    1064              : 
    1065              :       INTEGER                                            :: handle, iforce_eval, nforce_eval
    1066              :       LOGICAL, SAVE                                      :: first_call = .TRUE.
    1067              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
    1068              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1069              :       TYPE(force_env_type), POINTER                      :: force_env_qs
    1070              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    1071              :       TYPE(mixed_environment_type), POINTER              :: mixed_env
    1072              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1073              : 
    1074            2 :       NULLIFY (mixed_cdft, dft_control, force_env_qs, qs_env, mixed_env, cdft_control)
    1075            2 :       mixed_env => force_env%mixed_env
    1076            2 :       CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
    1077            2 :       CALL timeset(routineN, handle)
    1078            2 :       nforce_eval = SIZE(force_env%sub_force_env)
    1079            6 :       DO iforce_eval = 1, nforce_eval
    1080            4 :          IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
    1081            2 :          SELECT CASE (force_env%sub_force_env(iforce_eval)%force_env%in_use)
    1082              :          CASE (use_qs_force, use_qmmm)
    1083            0 :             force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
    1084              :          CASE DEFAULT
    1085              :             CALL cp_abort(__LOCATION__, &
    1086              :                           "Only use_qs_force and use_qmmm are "// &
    1087            2 :                           "supported for mixed_cdft_set_flags")
    1088              :          END SELECT
    1089            2 :          IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
    1090            2 :             CALL force_env_get(force_env=force_env_qs, qs_env=qs_env)
    1091              :          ELSE
    1092            0 :             qs_env => force_env_qs%qmmm_env%qs_env
    1093              :          END IF
    1094              :          ! All force_evals build the weight function and gradients in qs_cdft_methods.F
    1095              :          ! Update flags to match run type
    1096            2 :          CALL get_qs_env(qs_env, dft_control=dft_control)
    1097            2 :          cdft_control => dft_control%qs_control%cdft_control
    1098            2 :          cdft_control%external_control = .FALSE.
    1099            2 :          cdft_control%need_pot = .TRUE.
    1100            2 :          cdft_control%transfer_pot = .FALSE.
    1101            2 :          IF (first_call) THEN
    1102            2 :             cdft_control%first_iteration = .TRUE.
    1103              :          ELSE
    1104            0 :             cdft_control%first_iteration = .FALSE.
    1105              :          END IF
    1106              :          ! Set flags for ET coupling calculation
    1107            4 :          IF (mixed_env%do_mixed_et) THEN
    1108            2 :             IF (MODULO(mixed_cdft%sim_step, mixed_env%et_freq) == 0) THEN
    1109            2 :                cdft_control%do_et = .TRUE.
    1110            2 :                cdft_control%calculate_metric = mixed_cdft%calculate_metric
    1111              :             ELSE
    1112            0 :                cdft_control%do_et = .FALSE.
    1113            0 :                cdft_control%calculate_metric = .FALSE.
    1114              :             END IF
    1115              :          END IF
    1116              :       END DO
    1117            2 :       mixed_cdft%sim_step = mixed_cdft%sim_step + 1
    1118            2 :       IF (first_call) first_call = .FALSE.
    1119            2 :       CALL timestop(handle)
    1120              : 
    1121            2 :    END SUBROUTINE mixed_cdft_set_flags
    1122              : 
    1123              : ! **************************************************************************************************
    1124              : !> \brief Driver routine to calculate the electronic coupling(s) between CDFT states.
    1125              : !> \param force_env the force_env that holds the CDFT states
    1126              : !> \par History
    1127              : !>       02.15  created [Nico Holmberg]
    1128              : ! **************************************************************************************************
    1129          204 :    SUBROUTINE mixed_cdft_calculate_coupling(force_env)
    1130              :       TYPE(force_env_type), POINTER                      :: force_env
    1131              : 
    1132              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_calculate_coupling'
    1133              : 
    1134              :       INTEGER                                            :: handle
    1135              : 
    1136          102 :       CPASSERT(ASSOCIATED(force_env))
    1137          102 :       CALL timeset(routineN, handle)
    1138              :       ! Move needed arrays from individual CDFT states to the mixed CDFT env
    1139          102 :       CALL mixed_cdft_redistribute_arrays(force_env)
    1140              :       ! Calculate the mixed CDFT Hamiltonian and overlap matrices.
    1141              :       ! All work matrices defined in the wavefunction basis get deallocated on exit.
    1142              :       ! Any analyses which depend on these work matrices are performed within.
    1143          102 :       CALL mixed_cdft_interaction_matrices(force_env)
    1144              :       ! Calculate eletronic couplings between states (Lowdin/rotation)
    1145          102 :       CALL mixed_cdft_calculate_coupling_low(force_env)
    1146              :       ! Print out couplings
    1147          102 :       CALL mixed_cdft_print_couplings(force_env)
    1148              :       ! Block diagonalize the mixed CDFT Hamiltonian matrix
    1149          102 :       CALL mixed_cdft_block_diag(force_env)
    1150              :       ! CDFT Configuration Interaction
    1151          102 :       CALL mixed_cdft_configuration_interaction(force_env)
    1152              :       ! Clean up
    1153          102 :       CALL mixed_cdft_release_work(force_env)
    1154          102 :       CALL timestop(handle)
    1155              : 
    1156          102 :    END SUBROUTINE mixed_cdft_calculate_coupling
    1157              : 
    1158              : ! **************************************************************************************************
    1159              : !> \brief Routine to calculate the mixed CDFT Hamiltonian and overlap matrices.
    1160              : !> \param force_env the force_env that holds the CDFT states
    1161              : !> \par History
    1162              : !>       11.17  created [Nico Holmberg]
    1163              : ! **************************************************************************************************
    1164          102 :    SUBROUTINE mixed_cdft_interaction_matrices(force_env)
    1165              :       TYPE(force_env_type), POINTER                      :: force_env
    1166              : 
    1167              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_interaction_matrices'
    1168              : 
    1169              :       INTEGER :: check_ao(2), check_mo(2), handle, iforce_eval, ipermutation, ispin, istate, ivar, &
    1170              :          j, jstate, k, moeigvalunit, mounit, nao, ncol_local, nforce_eval, nmo, npermutations, &
    1171              :          nrow_local, nspins, nvar
    1172              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ncol_mo, nrow_mo
    1173          102 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: homo
    1174              :       LOGICAL                                            :: nelectron_mismatch, print_mo, &
    1175              :                                                             print_mo_eigval, should_scale, &
    1176              :                                                             uniform_occupation
    1177              :       REAL(KIND=dp)                                      :: c(2), eps_occupied, nelectron_tot, &
    1178              :                                                             sum_a(2), sum_b(2)
    1179          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: coupling_nonortho, eigenv, energy, Sda
    1180          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: H_mat, S_det, S_mat, strength, tmp_mat, &
    1181          102 :                                                             W_diagonal, Wad, Wda
    1182          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: a, b
    1183          102 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigval
    1184              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_mo, mo_mo_fmstruct
    1185              :       TYPE(cp_fm_type)                                   :: inverse_mat, Tinverse, tmp2
    1186          102 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_overlap
    1187          102 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: w_matrix_mo
    1188          102 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: mixed_mo_coeff
    1189              :       TYPE(cp_logger_type), POINTER                      :: logger
    1190          102 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: density_matrix, density_matrix_diff, &
    1191          102 :                                                             w_matrix
    1192              :       TYPE(dbcsr_type), POINTER                          :: mixed_matrix_s
    1193              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1194              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    1195              :       TYPE(mixed_environment_type), POINTER              :: mixed_env
    1196              :       TYPE(qs_energy_type), POINTER                      :: energy_qs
    1197              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1198              :       TYPE(section_vals_type), POINTER                   :: force_env_section, mixed_cdft_section, &
    1199              :                                                             print_section
    1200              : 
    1201          102 :       NULLIFY (force_env_section, print_section, mixed_cdft_section, &
    1202          102 :                mixed_env, mixed_cdft, qs_env, dft_control, fm_struct_mo, &
    1203          102 :                density_matrix_diff, mo_mo_fmstruct, &
    1204          102 :                mixed_mo_coeff, mixed_matrix_s, &
    1205          102 :                density_matrix, energy_qs, w_matrix, mo_eigval)
    1206          204 :       logger => cp_get_default_logger()
    1207          102 :       CPASSERT(ASSOCIATED(force_env))
    1208          102 :       CALL timeset(routineN, handle)
    1209              :       CALL force_env_get(force_env=force_env, &
    1210          102 :                          force_env_section=force_env_section)
    1211          102 :       mixed_env => force_env%mixed_env
    1212          102 :       nforce_eval = SIZE(force_env%sub_force_env)
    1213          102 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    1214          102 :       IF (section_get_lval(print_section, "MO_OVERLAP_MATRIX")) THEN
    1215            2 :          print_mo = .TRUE.
    1216            2 :          mounit = cp_print_key_unit_nr(logger, print_section, extension='.moOverlap', on_file=.TRUE.)
    1217              :       ELSE
    1218              :          print_mo = .FALSE.
    1219              :       END IF
    1220          102 :       IF (section_get_lval(print_section, "MO_OVERLAP_EIGENVALUES")) THEN
    1221           14 :          print_mo_eigval = .TRUE.
    1222           14 :          moeigvalunit = cp_print_key_unit_nr(logger, print_section, extension='.moOverlapEigval', on_file=.TRUE.)
    1223              :       ELSE
    1224              :          print_mo_eigval = .FALSE.
    1225              :       END IF
    1226          102 :       CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
    1227              :       ! Get redistributed work matrices
    1228          102 :       CPASSERT(ASSOCIATED(mixed_cdft))
    1229          102 :       CPASSERT(ASSOCIATED(mixed_cdft%matrix%mixed_mo_coeff))
    1230          102 :       CPASSERT(ASSOCIATED(mixed_cdft%matrix%w_matrix))
    1231          102 :       CPASSERT(ASSOCIATED(mixed_cdft%matrix%mixed_matrix_s))
    1232          102 :       mixed_mo_coeff => mixed_cdft%matrix%mixed_mo_coeff
    1233          102 :       w_matrix => mixed_cdft%matrix%w_matrix
    1234          102 :       mixed_matrix_s => mixed_cdft%matrix%mixed_matrix_s
    1235          102 :       IF (mixed_cdft%calculate_metric) THEN
    1236           14 :          CPASSERT(ASSOCIATED(mixed_cdft%matrix%density_matrix))
    1237           14 :          density_matrix => mixed_cdft%matrix%density_matrix
    1238              :       END IF
    1239              :       ! Get number of weight functions per state
    1240          102 :       nvar = SIZE(w_matrix, 2)
    1241          102 :       nspins = SIZE(mixed_mo_coeff, 2)
    1242              :       ! Check that the number of MOs/AOs is equal in every CDFT state
    1243          408 :       ALLOCATE (nrow_mo(nspins), ncol_mo(nspins))
    1244          298 :       DO ispin = 1, nspins
    1245          196 :          CALL cp_fm_get_info(mixed_mo_coeff(1, ispin), ncol_global=check_mo(1), nrow_global=check_ao(1))
    1246          542 :          DO iforce_eval = 2, nforce_eval
    1247          244 :             CALL cp_fm_get_info(mixed_mo_coeff(iforce_eval, ispin), ncol_global=check_mo(2), nrow_global=check_ao(2))
    1248          244 :             IF (check_ao(1) /= check_ao(2)) THEN
    1249              :                CALL cp_abort(__LOCATION__, &
    1250            0 :                              "The number of atomic orbitals must be the same in every CDFT state.")
    1251              :             END IF
    1252          440 :             IF (check_mo(1) /= check_mo(2)) THEN
    1253              :                CALL cp_abort(__LOCATION__, &
    1254            0 :                              "The number of molecular orbitals must be the same in every CDFT state.")
    1255              :             END IF
    1256              :          END DO
    1257              :       END DO
    1258              :       ! Allocate work
    1259          102 :       npermutations = nforce_eval*(nforce_eval - 1)/2 ! Size of upper triangular part
    1260         1450 :       ALLOCATE (w_matrix_mo(nforce_eval, nforce_eval, nvar))
    1261          796 :       ALLOCATE (mo_overlap(npermutations), S_det(npermutations, nspins))
    1262          816 :       ALLOCATE (a(nspins, nvar, npermutations), b(nspins, nvar, npermutations))
    1263          102 :       a = 0.0_dp
    1264          102 :       b = 0.0_dp
    1265          102 :       IF (mixed_cdft%calculate_metric) THEN
    1266          106 :          ALLOCATE (density_matrix_diff(npermutations, nspins))
    1267           42 :          DO ispin = 1, nspins
    1268           78 :             DO ipermutation = 1, npermutations
    1269           36 :                NULLIFY (density_matrix_diff(ipermutation, ispin)%matrix)
    1270           36 :                CALL dbcsr_init_p(density_matrix_diff(ipermutation, ispin)%matrix)
    1271           36 :                CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1272              :                CALL dbcsr_copy(density_matrix_diff(ipermutation, ispin)%matrix, &
    1273           64 :                                density_matrix(istate, ispin)%matrix, name="DENSITY_MATRIX")
    1274              :             END DO
    1275              :          END DO
    1276              :       END IF
    1277              :       ! Check for uniform occupations
    1278          102 :       uniform_occupation = .NOT. ALLOCATED(mixed_cdft%occupations)
    1279          102 :       should_scale = .FALSE.
    1280          102 :       IF (.NOT. uniform_occupation) THEN
    1281           56 :          ALLOCATE (homo(nforce_eval, nspins))
    1282           14 :          mixed_cdft_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT")
    1283           14 :          CALL section_vals_val_get(mixed_cdft_section, "EPS_OCCUPIED", r_val=eps_occupied)
    1284           14 :          IF (eps_occupied > 1.0_dp .OR. eps_occupied < 0.0_dp) THEN
    1285              :             CALL cp_abort(__LOCATION__, &
    1286            0 :                           "Keyword EPS_OCCUPIED only accepts values between 0.0 and 1.0")
    1287              :          END IF
    1288           14 :          IF (mixed_cdft%eps_svd == 0.0_dp) THEN
    1289              :             CALL cp_warn(__LOCATION__, &
    1290              :                          "The usage of SVD based matrix inversions with fractionally occupied "// &
    1291            0 :                          "orbitals is strongly recommended to screen nearly orthogonal states.")
    1292              :          END IF
    1293           28 :          CALL section_vals_val_get(mixed_cdft_section, "SCALE_WITH_OCCUPATION_NUMBERS", l_val=should_scale)
    1294              :       END IF
    1295              :       ! Start the actual calculation
    1296          298 :       DO ispin = 1, nspins
    1297              :          ! Create the MOxMO fm struct (mo_mo_fm_pools%struct)
    1298              :          ! The number of MOs/AOs is equal to the number of columns/rows of mo_coeff(:,:)%matrix
    1299          196 :          NULLIFY (fm_struct_mo, mo_mo_fmstruct)
    1300          196 :          CALL cp_fm_get_info(mixed_mo_coeff(1, ispin), ncol_global=ncol_mo(ispin), nrow_global=nrow_mo(ispin))
    1301          196 :          nao = nrow_mo(ispin)
    1302          196 :          IF (uniform_occupation) THEN
    1303          168 :             nmo = ncol_mo(ispin)
    1304              :          ELSE
    1305           28 :             nmo = ncol_mo(ispin)
    1306              :             ! Find indices of highest (fractionally) occupied molecular orbital
    1307           84 :             homo(:, ispin) = nmo
    1308           84 :             DO istate = 1, nforce_eval
    1309          152 :                DO j = nmo, 1, -1
    1310          124 :                   IF (mixed_cdft%occupations(istate, ispin)%array(j) >= eps_occupied) THEN
    1311           56 :                      homo(istate, ispin) = j
    1312           56 :                      EXIT
    1313              :                   END IF
    1314              :                END DO
    1315              :             END DO
    1316              :             ! Make matrices square by using the largest homo and emit warning if a state has fewer occupied MOs
    1317              :             ! Although it would be possible to handle the nonsquare situation as well,
    1318              :             ! all CDFT states should be in the same spin state for meaningful results
    1319           84 :             nmo = MAXVAL(homo(:, ispin))
    1320              :             ! Also check that the number of electrons is conserved (using a fixed sensible threshold)
    1321           28 :             nelectron_mismatch = .FALSE.
    1322           92 :             nelectron_tot = SUM(mixed_cdft%occupations(1, ispin)%array(1:nmo))
    1323           56 :             DO istate = 2, nforce_eval
    1324          120 :                IF (ABS(SUM(mixed_cdft%occupations(istate, ispin)%array(1:nmo)) - nelectron_tot) > 1.0E-4_dp) THEN
    1325            0 :                   nelectron_mismatch = .TRUE.
    1326              :                END IF
    1327              :             END DO
    1328           84 :             IF (ANY(homo(:, ispin) /= nmo)) THEN
    1329            0 :                IF (ispin == 1) THEN
    1330              :                   CALL cp_warn(__LOCATION__, &
    1331              :                                "The number of occupied alpha MOs is not constant across all CDFT states. "// &
    1332            0 :                                "Calculation proceeds but the results will likely be meaningless.")
    1333              :                ELSE
    1334              :                   CALL cp_warn(__LOCATION__, &
    1335              :                                "The number of occupied beta MOs is not constant across all CDFT states. "// &
    1336            0 :                                "Calculation proceeds but the results will likely be meaningless.")
    1337              :                END IF
    1338           28 :             ELSE IF (nelectron_mismatch) THEN
    1339            0 :                IF (ispin == 1) THEN
    1340              :                   CALL cp_warn(__LOCATION__, &
    1341              :                                "The number of alpha electrons is not constant across all CDFT states. "// &
    1342            0 :                                "Calculation proceeds but the results will likely be meaningless.")
    1343              :                ELSE
    1344              :                   CALL cp_warn(__LOCATION__, &
    1345              :                                "The number of beta electrons is not constant across all CDFT states. "// &
    1346            0 :                                "Calculation proceeds but the results will likely be meaningless.")
    1347              :                END IF
    1348              :             END IF
    1349              :          END IF
    1350              :          CALL cp_fm_struct_create(fm_struct_mo, nrow_global=nao, ncol_global=nmo, &
    1351          196 :                                   context=mixed_cdft%blacs_env, para_env=force_env%para_env)
    1352              :          CALL cp_fm_struct_create(mo_mo_fmstruct, nrow_global=nmo, ncol_global=nmo, &
    1353          196 :                                   context=mixed_cdft%blacs_env, para_env=force_env%para_env)
    1354              :          ! Allocate work
    1355              :          CALL cp_fm_create(matrix=tmp2, matrix_struct=fm_struct_mo, &
    1356          196 :                            name="ET_TMP_"//TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
    1357          196 :          CALL cp_fm_struct_release(fm_struct_mo)
    1358              :          CALL cp_fm_create(matrix=inverse_mat, matrix_struct=mo_mo_fmstruct, &
    1359          196 :                            name="INVERSE_"//TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
    1360              :          CALL cp_fm_create(matrix=Tinverse, matrix_struct=mo_mo_fmstruct, &
    1361          196 :                            name="T_INVERSE_"//TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
    1362          556 :          DO istate = 1, npermutations
    1363              :             CALL cp_fm_create(matrix=mo_overlap(istate), matrix_struct=mo_mo_fmstruct, &
    1364              :                               name="MO_OVERLAP_"//TRIM(ADJUSTL(cp_to_string(istate)))//"_"// &
    1365          556 :                               TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
    1366              :          END DO
    1367          396 :          DO ivar = 1, nvar
    1368          844 :             DO istate = 1, nforce_eval
    1369         1824 :                DO jstate = 1, nforce_eval
    1370         1176 :                   IF (istate == jstate) CYCLE
    1371              :                   CALL cp_fm_create(matrix=w_matrix_mo(istate, jstate, ivar), matrix_struct=mo_mo_fmstruct, &
    1372              :                                     name="W_"//TRIM(ADJUSTL(cp_to_string(istate)))//"_"// &
    1373              :                                     TRIM(ADJUSTL(cp_to_string(jstate)))//"_"// &
    1374         1624 :                                     TRIM(ADJUSTL(cp_to_string(ivar)))//"_MATRIX")
    1375              :                END DO
    1376              :             END DO
    1377              :          END DO
    1378          196 :          CALL cp_fm_struct_release(mo_mo_fmstruct)
    1379              :          ! Remove empty MOs and (possibly) scale rest with occupation numbers
    1380          196 :          IF (.NOT. uniform_occupation) THEN
    1381           84 :             DO iforce_eval = 1, nforce_eval
    1382           56 :                CALL cp_fm_to_fm(mixed_mo_coeff(iforce_eval, ispin), tmp2, nmo, 1, 1)
    1383           56 :                CALL cp_fm_release(mixed_mo_coeff(iforce_eval, ispin))
    1384              :                CALL cp_fm_create(mixed_mo_coeff(iforce_eval, ispin), &
    1385              :                                  matrix_struct=tmp2%matrix_struct, &
    1386              :                                  name="MO_COEFF_"//TRIM(ADJUSTL(cp_to_string(iforce_eval)))//"_" &
    1387           56 :                                  //TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
    1388           56 :                CALL cp_fm_to_fm(tmp2, mixed_mo_coeff(iforce_eval, ispin))
    1389           56 :                IF (should_scale) THEN
    1390              :                   CALL cp_fm_column_scale(mixed_mo_coeff(iforce_eval, ispin), &
    1391           40 :                                           mixed_cdft%occupations(iforce_eval, ispin)%array(1:nmo))
    1392              :                END IF
    1393           84 :                DEALLOCATE (mixed_cdft%occupations(iforce_eval, ispin)%array)
    1394              :             END DO
    1395              :          END IF
    1396              :          ! calculate the MO overlaps (C_j)^T S C_i
    1397          196 :          ipermutation = 0
    1398          636 :          DO istate = 1, nforce_eval
    1399          996 :             DO jstate = istate + 1, nforce_eval
    1400          360 :                ipermutation = ipermutation + 1
    1401              :                CALL cp_dbcsr_sm_fm_multiply(mixed_matrix_s, mixed_mo_coeff(istate, ispin), &
    1402          360 :                                             tmp2, nmo, 1.0_dp, 0.0_dp)
    1403              :                CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
    1404              :                                   mixed_mo_coeff(jstate, ispin), &
    1405          360 :                                   tmp2, 0.0_dp, mo_overlap(ipermutation))
    1406          800 :                IF (print_mo) THEN
    1407              :                   CALL cp_fm_write_formatted(mo_overlap(ipermutation), mounit, &
    1408              :                                              "# MO overlap matrix (step "//TRIM(ADJUSTL(cp_to_string(mixed_cdft%sim_step)))// &
    1409              :                                              "): CDFT states "//TRIM(ADJUSTL(cp_to_string(istate)))//" and "// &
    1410              :                                              TRIM(ADJUSTL(cp_to_string(jstate)))//" (spin "// &
    1411            4 :                                              TRIM(ADJUSTL(cp_to_string(ispin)))//")")
    1412              :                END IF
    1413              :             END DO
    1414              :          END DO
    1415              :          ! calculate the MO-representations of the restraint matrices of all CDFT states
    1416          396 :          DO ivar = 1, nvar
    1417          844 :             DO jstate = 1, nforce_eval
    1418         1824 :                DO istate = 1, nforce_eval
    1419         1176 :                   IF (istate == jstate) CYCLE
    1420              :                   ! State i: (C_j)^T W_i C_i
    1421              :                   CALL cp_dbcsr_sm_fm_multiply(w_matrix(istate, ivar)%matrix, &
    1422              :                                                mixed_mo_coeff(istate, ispin), &
    1423          728 :                                                tmp2, nmo, 1.0_dp, 0.0_dp)
    1424              :                   CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
    1425              :                                      mixed_mo_coeff(jstate, ispin), &
    1426         1624 :                                      tmp2, 0.0_dp, w_matrix_mo(istate, jstate, ivar))
    1427              :                END DO
    1428              :             END DO
    1429              :          END DO
    1430          556 :          DO ipermutation = 1, npermutations
    1431              :             ! Invert and calculate determinant of MO overlaps
    1432          360 :             CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1433          360 :             IF (print_mo_eigval) THEN
    1434           28 :                NULLIFY (mo_eigval)
    1435              :                CALL cp_fm_invert(mo_overlap(ipermutation), inverse_mat, &
    1436              :                                  S_det(ipermutation, ispin), eps_svd=mixed_cdft%eps_svd, &
    1437           28 :                                  eigval=mo_eigval)
    1438           28 :                IF (moeigvalunit > 0) THEN
    1439           14 :                   IF (mixed_cdft%eps_svd == 0.0_dp) THEN
    1440              :                      WRITE (moeigvalunit, '(A,I2,A,I2,A,I1,A)') &
    1441            0 :                         "# MO Overlap matrix eigenvalues for CDFT states ", istate, " and ", jstate, &
    1442            0 :                         " (spin ", ispin, ")"
    1443              :                   ELSE
    1444              :                      WRITE (moeigvalunit, '(A,I2,A,I2,A,I1,A)') &
    1445           14 :                         "# MO Overlap matrix singular values for CDFT states ", istate, " and ", jstate, &
    1446           28 :                         " (spin ", ispin, ")"
    1447              :                   END IF
    1448           14 :                   WRITE (moeigvalunit, '(A1, A9, A12)') "#", "Index", ADJUSTL("Value")
    1449           46 :                   DO j = 1, SIZE(mo_eigval)
    1450           46 :                      WRITE (moeigvalunit, '(I10, F12.8)') j, mo_eigval(j)
    1451              :                   END DO
    1452              :                END IF
    1453           28 :                DEALLOCATE (mo_eigval)
    1454              :             ELSE
    1455              :                CALL cp_fm_invert(mo_overlap(ipermutation), inverse_mat, &
    1456          332 :                                  S_det(ipermutation, ispin), eps_svd=mixed_cdft%eps_svd)
    1457              :             END IF
    1458          360 :             CALL cp_fm_get_info(inverse_mat, nrow_local=nrow_local, ncol_local=ncol_local)
    1459              :             ! Calculate <Psi_i | w_j(r) | Psi_j> for ivar:th constraint
    1460          928 :             DO j = 1, ncol_local
    1461         1442 :                DO k = 1, nrow_local
    1462         1601 :                   DO ivar = 1, nvar
    1463              :                      b(ispin, ivar, ipermutation) = b(ispin, ivar, ipermutation) + &
    1464              :                                                     w_matrix_mo(jstate, istate, ivar)%local_data(k, j)* &
    1465         1033 :                                                     inverse_mat%local_data(k, j)
    1466              :                   END DO
    1467              :                END DO
    1468              :             END DO
    1469              :             ! Calculate <Psi_j | w_i(r) | Psi_i> for ivar:th constraint
    1470          360 :             CALL cp_fm_transpose(inverse_mat, Tinverse)
    1471          928 :             DO j = 1, ncol_local
    1472         1442 :                DO k = 1, nrow_local
    1473         1601 :                   DO ivar = 1, nvar
    1474              :                      a(ispin, ivar, ipermutation) = a(ispin, ivar, ipermutation) + &
    1475              :                                                     w_matrix_mo(istate, jstate, ivar)%local_data(k, j)* &
    1476         1033 :                                                     Tinverse%local_data(k, j)
    1477              :                   END DO
    1478              :                END DO
    1479              :             END DO
    1480              :             ! Handle different constraint types
    1481          724 :             DO ivar = 1, nvar
    1482          364 :                SELECT CASE (mixed_cdft%constraint_type(ivar, istate))
    1483              :                CASE (cdft_charge_constraint)
    1484              :                   ! No action needed
    1485              :                CASE (cdft_magnetization_constraint)
    1486            0 :                   IF (ispin == 2) a(ispin, ivar, ipermutation) = -a(ispin, ivar, ipermutation)
    1487              :                CASE (cdft_alpha_constraint)
    1488              :                   ! Constraint applied to alpha electrons only, set integrals involving beta to zero
    1489            4 :                   IF (ispin == 2) a(ispin, ivar, ipermutation) = 0.0_dp
    1490              :                CASE (cdft_beta_constraint)
    1491              :                   ! Constraint applied to beta electrons only, set integrals involving alpha to zero
    1492            4 :                   IF (ispin == 1) a(ispin, ivar, ipermutation) = 0.0_dp
    1493              :                CASE DEFAULT
    1494          364 :                   CPABORT("Unknown constraint type.")
    1495              :                END SELECT
    1496          360 :                SELECT CASE (mixed_cdft%constraint_type(ivar, jstate))
    1497              :                CASE (cdft_charge_constraint)
    1498              :                   ! No action needed
    1499              :                CASE (cdft_magnetization_constraint)
    1500            0 :                   IF (ispin == 2) b(ispin, ivar, ipermutation) = -b(ispin, ivar, ipermutation)
    1501              :                CASE (cdft_alpha_constraint)
    1502              :                   ! Constraint applied to alpha electrons only, set integrals involving beta to zero
    1503            4 :                   IF (ispin == 2) b(ispin, ivar, ipermutation) = 0.0_dp
    1504              :                CASE (cdft_beta_constraint)
    1505              :                   ! Constraint applied to beta electrons only, set integrals involving alpha to zero
    1506            4 :                   IF (ispin == 1) b(ispin, ivar, ipermutation) = 0.0_dp
    1507              :                CASE DEFAULT
    1508          364 :                   CPABORT("Unknown constraint type.")
    1509              :                END SELECT
    1510              :             END DO
    1511              :             ! Compute density matrix difference P = P_j - P_i
    1512          360 :             IF (mixed_cdft%calculate_metric) THEN
    1513              :                CALL dbcsr_add(density_matrix_diff(ipermutation, ispin)%matrix, &
    1514           36 :                               density_matrix(jstate, ispin)%matrix, -1.0_dp, 1.0_dp)
    1515              :             END IF
    1516              :             !
    1517         1088 :             CALL force_env%para_env%sum(a(ispin, :, ipermutation))
    1518         2004 :             CALL force_env%para_env%sum(b(ispin, :, ipermutation))
    1519              :          END DO
    1520              :          ! Release work
    1521          196 :          CALL cp_fm_release(tmp2)
    1522          396 :          DO ivar = 1, nvar
    1523          844 :             DO jstate = 1, nforce_eval
    1524         1824 :                DO istate = 1, nforce_eval
    1525         1176 :                   IF (istate == jstate) CYCLE
    1526         1624 :                   CALL cp_fm_release(w_matrix_mo(istate, jstate, ivar))
    1527              :                END DO
    1528              :             END DO
    1529              :          END DO
    1530          556 :          DO ipermutation = 1, npermutations
    1531          556 :             CALL cp_fm_release(mo_overlap(ipermutation))
    1532              :          END DO
    1533          196 :          CALL cp_fm_release(Tinverse)
    1534          298 :          CALL cp_fm_release(inverse_mat)
    1535              :       END DO
    1536          102 :       DEALLOCATE (mo_overlap)
    1537          102 :       DEALLOCATE (w_matrix_mo)
    1538          102 :       IF (.NOT. uniform_occupation) THEN
    1539           14 :          DEALLOCATE (homo)
    1540           14 :          DEALLOCATE (mixed_cdft%occupations)
    1541              :       END IF
    1542          102 :       IF (print_mo) THEN
    1543              :          CALL cp_print_key_finished_output(mounit, logger, force_env_section, &
    1544            2 :                                            "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO", on_file=.TRUE.)
    1545              :       END IF
    1546          102 :       IF (print_mo_eigval) THEN
    1547              :          CALL cp_print_key_finished_output(moeigvalunit, logger, force_env_section, &
    1548           14 :                                            "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO", on_file=.TRUE.)
    1549              :       END IF
    1550              :       ! solve eigenstates for the projector matrix
    1551          408 :       ALLOCATE (Wda(nvar, npermutations))
    1552          306 :       ALLOCATE (Sda(npermutations))
    1553          106 :       IF (.NOT. mixed_cdft%identical_constraints) ALLOCATE (Wad(nvar, npermutations))
    1554          286 :       DO ipermutation = 1, npermutations
    1555          184 :          IF (nspins == 2) THEN
    1556          176 :             Sda(ipermutation) = ABS(S_det(ipermutation, 1)*S_det(ipermutation, 2))
    1557              :          ELSE
    1558            8 :             Sda(ipermutation) = S_det(ipermutation, 1)**2
    1559              :          END IF
    1560              :          ! Finalize <Psi_j | w_i(r) | Psi_i> by multiplication with Sda
    1561          472 :          DO ivar = 1, nvar
    1562          370 :             IF (mixed_cdft%identical_constraints) THEN
    1563              :                Wda(ivar, ipermutation) = (SUM(a(:, ivar, ipermutation)) + SUM(b(:, ivar, ipermutation)))* &
    1564          904 :                                          Sda(ipermutation)/2.0_dp
    1565              :             ELSE
    1566            6 :                Wda(ivar, ipermutation) = SUM(a(:, ivar, ipermutation))*Sda(ipermutation)
    1567            6 :                Wad(ivar, ipermutation) = SUM(b(:, ivar, ipermutation))*Sda(ipermutation)
    1568              :             END IF
    1569              :          END DO
    1570              :       END DO
    1571          102 :       DEALLOCATE (a, b, S_det)
    1572              :       ! Transfer info about the constraint calculations
    1573          816 :       ALLOCATE (W_diagonal(nvar, nforce_eval), strength(nvar, nforce_eval), energy(nforce_eval))
    1574          102 :       W_diagonal = 0.0_dp
    1575          330 :       DO iforce_eval = 1, nforce_eval
    1576          562 :          strength(:, iforce_eval) = mixed_env%strength(iforce_eval, :)
    1577              :       END DO
    1578          102 :       energy = 0.0_dp
    1579          330 :       DO iforce_eval = 1, nforce_eval
    1580          228 :          IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
    1581          190 :          IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
    1582           24 :             qs_env => force_env%sub_force_env(iforce_eval)%force_env%qmmm_env%qs_env
    1583              :          ELSE
    1584          166 :             CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, qs_env=qs_env)
    1585              :          END IF
    1586          190 :          CALL get_qs_env(qs_env, energy=energy_qs, dft_control=dft_control)
    1587          292 :          IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
    1588          230 :             W_diagonal(:, iforce_eval) = dft_control%qs_control%cdft_control%value(:)
    1589              :             ! The mixed CDFT Hamiltonian is built from the physical KS energies.
    1590              :             ! Remove the Lagrange term sum_k lambda_k*(C_k - target_k), which
    1591              :             ! need not vanish at finite constraint tolerances.
    1592          152 :             energy(iforce_eval) = energy_qs%total - energy_qs%cdft
    1593              :          END IF
    1594              :       END DO
    1595          102 :       CALL force_env%para_env%sum(W_diagonal)
    1596          102 :       CALL force_env%para_env%sum(energy)
    1597              :       CALL mixed_cdft_result_type_set(mixed_cdft%results, Wda=Wda, W_diagonal=W_diagonal, &
    1598          102 :                                       energy=energy, strength=strength)
    1599          102 :       IF (.NOT. mixed_cdft%identical_constraints) CALL mixed_cdft_result_type_set(mixed_cdft%results, Wad=Wad)
    1600              :       ! Construct S
    1601          408 :       ALLOCATE (S_mat(nforce_eval, nforce_eval))
    1602          330 :       DO istate = 1, nforce_eval
    1603          330 :          S_mat(istate, istate) = 1.0_dp
    1604              :       END DO
    1605          286 :       DO ipermutation = 1, npermutations
    1606          184 :          CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1607          184 :          S_mat(istate, jstate) = Sda(ipermutation)
    1608          286 :          S_mat(jstate, istate) = Sda(ipermutation)
    1609              :       END DO
    1610          102 :       CALL mixed_cdft_result_type_set(mixed_cdft%results, S=S_mat)
    1611              :       ! Invert S via eigendecomposition and compute S^-(1/2)
    1612          408 :       ALLOCATE (eigenv(nforce_eval), tmp_mat(nforce_eval, nforce_eval))
    1613          102 :       CALL diamat_all(S_mat, eigenv, .TRUE.)
    1614          102 :       tmp_mat = 0.0_dp
    1615          330 :       DO istate = 1, nforce_eval
    1616          228 :          IF (eigenv(istate) < 1.0e-14_dp) THEN
    1617              :             ! Safeguard against division with 0 and negative numbers
    1618           10 :             eigenv(istate) = 1.0e-14_dp
    1619              :             CALL cp_warn(__LOCATION__, &
    1620              :                          "The overlap matrix is numerically nearly singular. "// &
    1621           10 :                          "Calculation proceeds but the results might be meaningless.")
    1622              :          END IF
    1623          330 :          tmp_mat(istate, istate) = 1.0_dp/SQRT(eigenv(istate))
    1624              :       END DO
    1625         5998 :       tmp_mat(:, :) = MATMUL(tmp_mat, TRANSPOSE(S_mat))
    1626        10450 :       S_mat(:, :) = MATMUL(S_mat, tmp_mat) ! S^(-1/2)
    1627          102 :       CALL mixed_cdft_result_type_set(mixed_cdft%results, S_minushalf=S_mat)
    1628          102 :       DEALLOCATE (eigenv, tmp_mat, S_mat)
    1629              :       ! Construct nonorthogonal diabatic Hamiltonian matrix H''
    1630          306 :       ALLOCATE (H_mat(nforce_eval, nforce_eval))
    1631          120 :       IF (mixed_cdft%nonortho_coupling) ALLOCATE (coupling_nonortho(npermutations))
    1632          330 :       DO istate = 1, nforce_eval
    1633          330 :          H_mat(istate, istate) = energy(istate)
    1634              :       END DO
    1635          286 :       DO ipermutation = 1, npermutations
    1636          184 :          CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1637          184 :          sum_a = 0.0_dp
    1638          184 :          sum_b = 0.0_dp
    1639          370 :          DO ivar = 1, nvar
    1640              :             ! V_J * <Psi_J | w_J(r) | Psi_J>
    1641          186 :             sum_b(1) = sum_b(1) + strength(ivar, jstate)*W_diagonal(ivar, jstate)
    1642              :             ! V_I * <Psi_I | w_I(r) | Psi_I>
    1643          186 :             sum_a(1) = sum_a(1) + strength(ivar, istate)*W_diagonal(ivar, istate)
    1644          370 :             IF (mixed_cdft%identical_constraints) THEN
    1645              :                ! V_J * W_IJ
    1646          184 :                sum_b(2) = sum_b(2) + strength(ivar, jstate)*Wda(ivar, ipermutation)
    1647              :                ! V_I * W_JI
    1648          184 :                sum_a(2) = sum_a(2) + strength(ivar, istate)*Wda(ivar, ipermutation)
    1649              :             ELSE
    1650              :                ! V_J * W_IJ
    1651            2 :                sum_b(2) = sum_b(2) + strength(ivar, jstate)*Wad(ivar, ipermutation)
    1652              :                ! V_I * W_JI
    1653            2 :                sum_a(2) = sum_a(2) + strength(ivar, istate)*Wda(ivar, ipermutation)
    1654              :             END IF
    1655              :          END DO
    1656              :          ! Denote F_X = <Psi_X | H_X + V_X*w_X(r) | Psi_X> = E_X + V_X*<Psi_X | w_X(r) | Psi_X>
    1657              :          ! H_IJ = F_J*S_IJ - V_J * W_IJ
    1658          184 :          c(1) = (energy(jstate) + sum_b(1))*Sda(ipermutation) - sum_b(2)
    1659              :          ! H_JI = F_I*S_JI - V_I * W_JI
    1660          184 :          c(2) = (energy(istate) + sum_a(1))*Sda(ipermutation) - sum_a(2)
    1661              :          ! H''(I,J) = 0.5*(H_IJ+H_JI) = H''(J,I)
    1662          184 :          H_mat(istate, jstate) = (c(1) + c(2))*0.5_dp
    1663          184 :          H_mat(jstate, istate) = H_mat(istate, jstate)
    1664          470 :          IF (mixed_cdft%nonortho_coupling) coupling_nonortho(ipermutation) = H_mat(istate, jstate)
    1665              :       END DO
    1666          102 :       CALL mixed_cdft_result_type_set(mixed_cdft%results, H=H_mat)
    1667          102 :       DEALLOCATE (H_mat, W_diagonal, Wda, strength, energy, Sda)
    1668          102 :       IF (ALLOCATED(Wad)) DEALLOCATE (Wad)
    1669          102 :       IF (mixed_cdft%nonortho_coupling) THEN
    1670           18 :          CALL mixed_cdft_result_type_set(mixed_cdft%results, nonortho=coupling_nonortho)
    1671           18 :          DEALLOCATE (coupling_nonortho)
    1672              :       END IF
    1673              :       ! Compute metric to assess reliability of coupling
    1674          102 :       IF (mixed_cdft%calculate_metric) CALL mixed_cdft_calculate_metric(force_env, mixed_cdft, density_matrix_diff, ncol_mo)
    1675              :       ! Compute coupling also with the wavefunction overlap method, see Migliore2009
    1676              :       ! Requires the unconstrained KS ground state wavefunction as input
    1677          102 :       IF (mixed_cdft%wfn_overlap_method) THEN
    1678            8 :          IF (.NOT. uniform_occupation) THEN
    1679              :             CALL cp_abort(__LOCATION__, &
    1680            0 :                           "Wavefunction overlap method supports only uniformly occupied MOs.")
    1681              :          END IF
    1682            8 :          CALL mixed_cdft_wfn_overlap_method(force_env, mixed_cdft, ncol_mo, nrow_mo)
    1683              :       END IF
    1684              :       ! Release remaining work
    1685          102 :       DEALLOCATE (nrow_mo, ncol_mo)
    1686          102 :       CALL mixed_cdft_work_type_release(mixed_cdft%matrix)
    1687          102 :       CALL timestop(handle)
    1688              : 
    1689          306 :    END SUBROUTINE mixed_cdft_interaction_matrices
    1690              : 
    1691              : ! **************************************************************************************************
    1692              : !> \brief Routine to calculate the CDFT electronic couplings.
    1693              : !> \param force_env the force_env that holds the CDFT states
    1694              : !> \par History
    1695              : !>       11.17  created [Nico Holmberg]
    1696              : ! **************************************************************************************************
    1697          102 :    SUBROUTINE mixed_cdft_calculate_coupling_low(force_env)
    1698              :       TYPE(force_env_type), POINTER                      :: force_env
    1699              : 
    1700              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_calculate_coupling_low'
    1701              : 
    1702              :       INTEGER                                            :: handle, ipermutation, istate, jstate, &
    1703              :                                                             nforce_eval, npermutations, nvar
    1704              :       LOGICAL                                            :: use_lowdin, use_rotation
    1705          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: coupling_lowdin, coupling_rotation, &
    1706          102 :                                                             eigenv
    1707          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: tmp_mat, W_mat
    1708              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    1709              : 
    1710          102 :       NULLIFY (mixed_cdft)
    1711          102 :       CPASSERT(ASSOCIATED(force_env))
    1712          102 :       CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
    1713          102 :       CALL timeset(routineN, handle)
    1714          102 :       CPASSERT(ASSOCIATED(mixed_cdft))
    1715          102 :       CPASSERT(ALLOCATED(mixed_cdft%results%W_diagonal))
    1716          102 :       CPASSERT(ALLOCATED(mixed_cdft%results%Wda))
    1717          102 :       CPASSERT(ALLOCATED(mixed_cdft%results%S_minushalf))
    1718          102 :       CPASSERT(ALLOCATED(mixed_cdft%results%H))
    1719              :       ! Decide which methods to use for computing the coupling
    1720              :       ! Default behavior is to use rotation when a single constraint is active, otherwise uses Lowdin orthogonalization
    1721              :       ! The latter can also be explicitly requested when a single constraint is active
    1722              :       ! Possibly computes the coupling additionally with the wavefunction overlap method
    1723          102 :       nforce_eval = SIZE(mixed_cdft%results%H, 1)
    1724          102 :       nvar = SIZE(mixed_cdft%results%Wda, 1)
    1725          102 :       npermutations = nforce_eval*(nforce_eval - 1)/2
    1726          408 :       ALLOCATE (tmp_mat(nforce_eval, nforce_eval))
    1727          102 :       IF (nvar == 1 .AND. mixed_cdft%identical_constraints) THEN
    1728           98 :          use_rotation = .TRUE.
    1729           98 :          use_lowdin = mixed_cdft%use_lowdin
    1730              :       ELSE
    1731              :          use_rotation = .FALSE.
    1732              :          use_lowdin = .TRUE.
    1733              :       END IF
    1734              :       ! Calculate coupling by rotating the CDFT states to eigenstates of the weight matrix W (single constraint only)
    1735              :       IF (use_rotation) THEN
    1736              :          ! Construct W
    1737          490 :          ALLOCATE (W_mat(nforce_eval, nforce_eval), coupling_rotation(npermutations))
    1738          294 :          ALLOCATE (eigenv(nforce_eval))
    1739              :          ! W_mat(i, i) = N_i where N_i is the value of the constraint in state i
    1740          318 :          DO istate = 1, nforce_eval
    1741          538 :             W_mat(istate, istate) = SUM(mixed_cdft%results%W_diagonal(:, istate))
    1742              :          END DO
    1743              :          ! W_mat(i, j) = <Psi_i|w(r)|Psi_j>
    1744          278 :          DO ipermutation = 1, npermutations
    1745          180 :             CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1746          360 :             W_mat(istate, jstate) = SUM(mixed_cdft%results%Wda(:, ipermutation))
    1747          458 :             W_mat(jstate, istate) = W_mat(istate, jstate)
    1748              :          END DO
    1749              :          ! Solve generalized eigenvalue equation WV = SVL
    1750              :          ! Convert to standard eigenvalue problem via symmetric orthogonalisation
    1751         5082 :          tmp_mat(:, :) = MATMUL(W_mat, mixed_cdft%results%S_minushalf) ! W * S^(-1/2)
    1752         5082 :          W_mat(:, :) = MATMUL(mixed_cdft%results%S_minushalf, tmp_mat) ! W' = S^(-1/2) * W * S^(-1/2)
    1753           98 :          CALL diamat_all(W_mat, eigenv, .TRUE.) ! Solve W'V' = AV'
    1754         9266 :          tmp_mat(:, :) = MATMUL(mixed_cdft%results%S_minushalf, W_mat) ! Reverse transformation V = S^(-1/2) V'
    1755              :          ! Construct final, orthogonal diabatic Hamiltonian matrix H
    1756         9266 :          W_mat(:, :) = MATMUL(mixed_cdft%results%H, tmp_mat) ! H'' * V
    1757        10262 :          W_mat(:, :) = MATMUL(TRANSPOSE(tmp_mat), W_mat) ! H = V^T * H'' * V
    1758          278 :          DO ipermutation = 1, npermutations
    1759          180 :             CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1760          278 :             coupling_rotation(ipermutation) = W_mat(istate, jstate)
    1761              :          END DO
    1762           98 :          CALL mixed_cdft_result_type_set(mixed_cdft%results, rotation=coupling_rotation)
    1763           98 :          DEALLOCATE (W_mat, coupling_rotation, eigenv)
    1764              :       END IF
    1765              :       ! Calculate coupling by Lowdin orthogonalization
    1766          102 :       IF (use_lowdin) THEN
    1767           60 :          ALLOCATE (coupling_lowdin(npermutations))
    1768          780 :          tmp_mat(:, :) = MATMUL(mixed_cdft%results%H, mixed_cdft%results%S_minushalf) ! H'' * S^(-1/2)
    1769              :          ! Final orthogonal diabatic Hamiltonian matrix H
    1770          580 :          tmp_mat(:, :) = MATMUL(mixed_cdft%results%S_minushalf, tmp_mat) ! H = S^(-1/2) * H'' * S^(-1/2)
    1771           40 :          DO ipermutation = 1, npermutations
    1772           20 :             CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    1773           40 :             coupling_lowdin(ipermutation) = tmp_mat(istate, jstate)
    1774              :          END DO
    1775           20 :          CALL mixed_cdft_result_type_set(mixed_cdft%results, lowdin=coupling_lowdin)
    1776           20 :          DEALLOCATE (coupling_lowdin)
    1777              :       END IF
    1778          102 :       DEALLOCATE (tmp_mat)
    1779          102 :       CALL timestop(handle)
    1780              : 
    1781          204 :    END SUBROUTINE mixed_cdft_calculate_coupling_low
    1782              : 
    1783              : ! **************************************************************************************************
    1784              : !> \brief Performs a configuration interaction calculation in the basis spanned by the CDFT states.
    1785              : !> \param force_env the force_env that holds the CDFT states
    1786              : !> \par History
    1787              : !>       11.17  created [Nico Holmberg]
    1788              : ! **************************************************************************************************
    1789          102 :    SUBROUTINE mixed_cdft_configuration_interaction(force_env)
    1790              :       TYPE(force_env_type), POINTER                      :: force_env
    1791              : 
    1792              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_configuration_interaction'
    1793              : 
    1794              :       INTEGER                                            :: handle, info, iounit, istate, ivar, &
    1795              :                                                             nforce_eval, work_array_size
    1796          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenv, work
    1797          102 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: H_mat, H_mat_copy, S_mat, S_mat_copy
    1798              :       REAL(KIND=dp), EXTERNAL                            :: dnrm2
    1799              :       TYPE(cp_logger_type), POINTER                      :: logger
    1800              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    1801              :       TYPE(section_vals_type), POINTER                   :: force_env_section, print_section
    1802              : 
    1803              :       EXTERNAL                                           :: dsygv
    1804              : 
    1805          102 :       NULLIFY (logger, force_env_section, print_section, mixed_cdft)
    1806              : 
    1807          102 :       CPASSERT(ASSOCIATED(force_env))
    1808          102 :       CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
    1809          102 :       CPASSERT(ASSOCIATED(mixed_cdft))
    1810              : 
    1811          102 :       IF (.NOT. mixed_cdft%do_ci) RETURN
    1812              : 
    1813           22 :       logger => cp_get_default_logger()
    1814           22 :       CALL timeset(routineN, handle)
    1815              :       CALL force_env_get(force_env=force_env, &
    1816           22 :                          force_env_section=force_env_section)
    1817           22 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    1818           22 :       iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
    1819              : 
    1820           22 :       CPASSERT(ALLOCATED(mixed_cdft%results%S))
    1821           22 :       CPASSERT(ALLOCATED(mixed_cdft%results%H))
    1822           22 :       nforce_eval = SIZE(mixed_cdft%results%S, 1)
    1823          132 :       ALLOCATE (S_mat(nforce_eval, nforce_eval), H_mat(nforce_eval, nforce_eval))
    1824           66 :       ALLOCATE (eigenv(nforce_eval))
    1825          182 :       S_mat(:, :) = mixed_cdft%results%S(:, :)
    1826          182 :       H_mat(:, :) = mixed_cdft%results%H(:, :)
    1827              :       ! Workspace query
    1828           22 :       ALLOCATE (work(1))
    1829           22 :       info = 0
    1830          110 :       ALLOCATE (H_mat_copy(nforce_eval, nforce_eval), S_mat_copy(nforce_eval, nforce_eval))
    1831          182 :       H_mat_copy(:, :) = H_mat(:, :) ! Need explicit copies because dsygv destroys original values
    1832          182 :       S_mat_copy(:, :) = S_mat(:, :)
    1833           22 :       CALL dsygv(1, 'V', 'U', nforce_eval, H_mat_copy, nforce_eval, S_mat_copy, nforce_eval, eigenv, work, -1, info)
    1834           22 :       work_array_size = NINT(work(1))
    1835           22 :       DEALLOCATE (H_mat_copy, S_mat_copy)
    1836              :       ! Allocate work array
    1837           22 :       DEALLOCATE (work)
    1838           66 :       ALLOCATE (work(work_array_size))
    1839           22 :       work = 0.0_dp
    1840              :       ! Solve Hc = eSc
    1841           22 :       info = 0
    1842           22 :       CALL dsygv(1, 'V', 'U', nforce_eval, H_mat, nforce_eval, S_mat, nforce_eval, eigenv, work, work_array_size, info)
    1843           22 :       IF (info /= 0) THEN
    1844            0 :          IF (info > nforce_eval) THEN
    1845            0 :             CPABORT("Matrix S is not positive definite")
    1846              :          ELSE
    1847            0 :             CPABORT("Diagonalization of H matrix failed.")
    1848              :          END IF
    1849              :       END IF
    1850              :       ! dsygv returns eigenvectors (stored in columns of H_mat) that are normalized to H^T * S * H = I
    1851              :       ! Renormalize eigenvectors to H^T * H = I
    1852           70 :       DO ivar = 1, nforce_eval
    1853          182 :          H_mat(:, ivar) = H_mat(:, ivar)/dnrm2(nforce_eval, H_mat(:, ivar), 1)
    1854              :       END DO
    1855           22 :       DEALLOCATE (work)
    1856           22 :       IF (iounit > 0) THEN
    1857           11 :          WRITE (iounit, '(/,T3,A)') '------------------ CDFT Configuration Interaction (CDFT-CI) ------------------'
    1858           35 :          DO ivar = 1, nforce_eval
    1859           24 :             IF (ivar == 1) THEN
    1860           11 :                WRITE (iounit, '(T3,A,T58,(3X,F20.14))') 'Ground state energy:', eigenv(ivar)
    1861              :             ELSE
    1862           13 :                WRITE (iounit, '(/,T3,A,I2,A,T58,(3X,F20.14))') 'Excited state (', ivar - 1, ' ) energy:', eigenv(ivar)
    1863              :             END IF
    1864           63 :             DO istate = 1, nforce_eval, 2
    1865           52 :                IF (istate == 1) THEN
    1866              :                   WRITE (iounit, '(T3,A,T54,(3X,2F12.6))') &
    1867           24 :                      'Expansion coefficients:', H_mat(istate, ivar), H_mat(istate + 1, ivar)
    1868            4 :                ELSE IF (istate < nforce_eval) THEN
    1869            4 :                   WRITE (iounit, '(T54,(3X,2F12.6))') H_mat(istate, ivar), H_mat(istate + 1, ivar)
    1870              :                ELSE
    1871            0 :                   WRITE (iounit, '(T54,(3X,F12.6))') H_mat(istate, ivar)
    1872              :                END IF
    1873              :             END DO
    1874              :          END DO
    1875              :          WRITE (iounit, '(T3,A)') &
    1876           11 :             '------------------------------------------------------------------------------'
    1877              :       END IF
    1878           22 :       DEALLOCATE (S_mat, H_mat, eigenv)
    1879              :       CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
    1880           22 :                                         "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    1881           22 :       CALL timestop(handle)
    1882              : 
    1883           22 :    END SUBROUTINE mixed_cdft_configuration_interaction
    1884              : ! **************************************************************************************************
    1885              : !> \brief Block diagonalizes the mixed CDFT Hamiltonian matrix.
    1886              : !> \param force_env the force_env that holds the CDFT states
    1887              : !> \par History
    1888              : !>       11.17  created [Nico Holmberg]
    1889              : !>       01.18  added recursive diagonalization
    1890              : !>              split to subroutines [Nico Holmberg]
    1891              : ! **************************************************************************************************
    1892          102 :    SUBROUTINE mixed_cdft_block_diag(force_env)
    1893              :       TYPE(force_env_type), POINTER                      :: force_env
    1894              : 
    1895              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_block_diag'
    1896              : 
    1897              :       INTEGER                                            :: handle, i, iounit, irecursion, j, n, &
    1898              :                                                             nblk, nforce_eval, nrecursion
    1899              :       LOGICAL                                            :: ignore_excited
    1900          102 :       TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:)    :: blocks
    1901          102 :       TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:)    :: eigenvalues
    1902          102 :       TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:)    :: H_block, S_block
    1903              :       TYPE(cp_logger_type), POINTER                      :: logger
    1904              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    1905              :       TYPE(section_vals_type), POINTER                   :: force_env_section, print_section
    1906              : 
    1907              :       EXTERNAL                                           :: dsygv
    1908              : 
    1909          102 :       NULLIFY (logger, force_env_section, print_section, mixed_cdft)
    1910              : 
    1911          102 :       CPASSERT(ASSOCIATED(force_env))
    1912          102 :       CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
    1913          102 :       CPASSERT(ASSOCIATED(mixed_cdft))
    1914              : 
    1915          102 :       IF (.NOT. mixed_cdft%block_diagonalize) RETURN
    1916              : 
    1917            8 :       logger => cp_get_default_logger()
    1918            8 :       CALL timeset(routineN, handle)
    1919              : 
    1920            8 :       CPASSERT(ALLOCATED(mixed_cdft%results%S))
    1921            8 :       CPASSERT(ALLOCATED(mixed_cdft%results%H))
    1922            8 :       nforce_eval = SIZE(mixed_cdft%results%S, 1)
    1923              : 
    1924              :       CALL force_env_get(force_env=force_env, &
    1925            8 :                          force_env_section=force_env_section)
    1926            8 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    1927            8 :       iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
    1928              :       ! Read block definitions from input
    1929            8 :       CALL mixed_cdft_read_block_diag(force_env, blocks, ignore_excited, nrecursion)
    1930            8 :       nblk = SIZE(blocks)
    1931              :       ! Start block diagonalization
    1932           18 :       DO irecursion = 1, nrecursion
    1933              :          ! Print block definitions
    1934           10 :          IF (iounit > 0 .AND. irecursion == 1) THEN
    1935            4 :             WRITE (iounit, '(/,T3,A)') '-------------------------- CDFT BLOCK DIAGONALIZATION ------------------------'
    1936            4 :             WRITE (iounit, '(T3,A)') 'Block diagonalizing the mixed CDFT Hamiltonian'
    1937            4 :             WRITE (iounit, '(T3,A,I3)') 'Number of blocks:', nblk
    1938            4 :             WRITE (iounit, '(T3,A,L3)') 'Ignoring excited states within blocks:', ignore_excited
    1939            4 :             WRITE (iounit, '(/,T3,A)') 'List of CDFT states for each block'
    1940           14 :             DO i = 1, nblk
    1941           33 :                WRITE (iounit, '(T6,A,I3,A,6I3)') 'Block', i, ':', (blocks(i)%array(j), j=1, SIZE(blocks(i)%array))
    1942              :             END DO
    1943              :          END IF
    1944              :          ! Recursive diagonalization: update counters and references
    1945           10 :          IF (irecursion > 1) THEN
    1946            2 :             nblk = nblk/2
    1947           10 :             ALLOCATE (blocks(nblk))
    1948            2 :             j = 1
    1949            6 :             DO i = 1, nblk
    1950            4 :                NULLIFY (blocks(i)%array)
    1951            4 :                ALLOCATE (blocks(i)%array(2))
    1952           12 :                blocks(i)%array = [j, j + 1]
    1953            6 :                j = j + 2
    1954              :             END DO
    1955              :             ! Print info
    1956            2 :             IF (iounit > 0) THEN
    1957            1 :                WRITE (iounit, '(/, T3,A)') 'Recursive block diagonalization of the mixed CDFT Hamiltonian'
    1958            1 :                WRITE (iounit, '(T6,A)') 'Block diagonalization is continued until only two matrix blocks remain.'
    1959            1 :                WRITE (iounit, '(T6,A)') 'The new blocks are formed by collecting pairs of blocks from the previous'
    1960            1 :                WRITE (iounit, '(T6,A)') 'block diagonalized matrix in ascending order.'
    1961            1 :                WRITE (iounit, '(/,T3,A,I3,A,I3)') 'Recursion step:', irecursion - 1, ' of ', nrecursion - 1
    1962            1 :                WRITE (iounit, '(/,T3,A)') 'List of old block indices for each new block'
    1963            3 :                DO i = 1, nblk
    1964            7 :                   WRITE (iounit, '(T6,A,I3,A,6I3)') 'Block', i, ':', (blocks(i)%array(j), j=1, SIZE(blocks(i)%array))
    1965              :                END DO
    1966              :             END IF
    1967              :          END IF
    1968              :          ! Get the Hamiltonian and overlap matrices of each block
    1969           10 :          CALL mixed_cdft_get_blocks(mixed_cdft, blocks, H_block, S_block)
    1970              :          ! Diagonalize blocks
    1971           10 :          CALL mixed_cdft_diagonalize_blocks(blocks, H_block, S_block, eigenvalues)
    1972              :          ! Assemble the block diagonalized matrices
    1973           10 :          IF (ignore_excited) THEN
    1974            8 :             n = nblk
    1975              :          ELSE
    1976            2 :             n = nforce_eval
    1977              :          END IF
    1978           10 :          CALL mixed_cdft_assemble_block_diag(mixed_cdft, blocks, H_block, eigenvalues, n, iounit)
    1979              :          ! Deallocate work
    1980           34 :          DO i = 1, nblk
    1981           24 :             DEALLOCATE (H_block(i)%array)
    1982           24 :             DEALLOCATE (S_block(i)%array)
    1983           24 :             DEALLOCATE (eigenvalues(i)%array)
    1984           34 :             DEALLOCATE (blocks(i)%array)
    1985              :          END DO
    1986           18 :          DEALLOCATE (H_block, S_block, eigenvalues, blocks)
    1987              :       END DO ! recursion
    1988            8 :       IF (iounit > 0) THEN
    1989              :          WRITE (iounit, '(T3,A)') &
    1990            4 :             '------------------------------------------------------------------------------'
    1991              :       END IF
    1992              :       CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
    1993            8 :                                         "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    1994            8 :       CALL timestop(handle)
    1995              : 
    1996          102 :    END SUBROUTINE mixed_cdft_block_diag
    1997              : ! **************************************************************************************************
    1998              : !> \brief Routine to calculate the CDFT electronic coupling reliability metric
    1999              : !> \param force_env the force_env that holds the CDFT states
    2000              : !> \param mixed_cdft the mixed_cdft env
    2001              : !> \param density_matrix_diff array holding difference density matrices (P_j - P_i) for every CDFT
    2002              : !>                            state permutation
    2003              : !> \param ncol_mo the number of MOs per spin
    2004              : !> \par History
    2005              : !>       11.17  created [Nico Holmberg]
    2006              : ! **************************************************************************************************
    2007           14 :    SUBROUTINE mixed_cdft_calculate_metric(force_env, mixed_cdft, density_matrix_diff, ncol_mo)
    2008              :       TYPE(force_env_type), POINTER                      :: force_env
    2009              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    2010              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: density_matrix_diff
    2011              :       INTEGER, DIMENSION(:)                              :: ncol_mo
    2012              : 
    2013              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_calculate_metric'
    2014              : 
    2015              :       INTEGER                                            :: handle, ipermutation, ispin, j, &
    2016              :                                                             nforce_eval, npermutations, nspins
    2017           14 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: evals
    2018              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: metric
    2019              :       TYPE(dbcsr_type)                                   :: e_vectors
    2020              : 
    2021           14 :       CALL timeset(routineN, handle)
    2022           14 :       nforce_eval = SIZE(mixed_cdft%results%H, 1)
    2023           14 :       npermutations = nforce_eval*(nforce_eval - 1)/2
    2024           14 :       nspins = SIZE(density_matrix_diff, 2)
    2025           56 :       ALLOCATE (metric(npermutations, nspins))
    2026           14 :       metric = 0.0_dp
    2027           14 :       CALL dbcsr_create(e_vectors, template=density_matrix_diff(1, 1)%matrix)
    2028           42 :       DO ispin = 1, nspins
    2029           84 :          ALLOCATE (evals(ncol_mo(ispin)))
    2030           64 :          DO ipermutation = 1, npermutations
    2031              :             ! Take into account doubly occupied orbitals without LSD
    2032           36 :             IF (nspins == 1) THEN
    2033            0 :                CALL dbcsr_scale(density_matrix_diff(ipermutation, 1)%matrix, alpha_scalar=0.5_dp)
    2034              :             END IF
    2035              :             ! Diagonalize difference density matrix
    2036              :             CALL cp_dbcsr_syevd(density_matrix_diff(ipermutation, ispin)%matrix, e_vectors, evals, &
    2037           36 :                                 para_env=force_env%para_env, blacs_env=mixed_cdft%blacs_env)
    2038           36 :             CALL dbcsr_release_p(density_matrix_diff(ipermutation, ispin)%matrix)
    2039          100 :             DO j = 1, ncol_mo(ispin)
    2040           72 :                metric(ipermutation, ispin) = metric(ipermutation, ispin) + (evals(j)**2 - evals(j)**4)
    2041              :             END DO
    2042              :          END DO
    2043           42 :          DEALLOCATE (evals)
    2044              :       END DO
    2045           14 :       CALL dbcsr_release(e_vectors)
    2046           14 :       DEALLOCATE (density_matrix_diff)
    2047           78 :       metric(:, :) = metric(:, :)/4.0_dp
    2048           14 :       CALL mixed_cdft_result_type_set(mixed_cdft%results, metric=metric)
    2049           14 :       DEALLOCATE (metric)
    2050           14 :       CALL timestop(handle)
    2051              : 
    2052           28 :    END SUBROUTINE mixed_cdft_calculate_metric
    2053              : 
    2054              : ! **************************************************************************************************
    2055              : !> \brief Routine to calculate the electronic coupling according to the wavefunction overlap method
    2056              : !> \param force_env the force_env that holds the CDFT states
    2057              : !> \param mixed_cdft the mixed_cdft env
    2058              : !> \param ncol_mo the number of MOs per spin
    2059              : !> \param nrow_mo the number of AOs per spin
    2060              : !> \par History
    2061              : !>       11.17  created [Nico Holmberg]
    2062              : ! **************************************************************************************************
    2063            8 :    SUBROUTINE mixed_cdft_wfn_overlap_method(force_env, mixed_cdft, ncol_mo, nrow_mo)
    2064              :       TYPE(force_env_type), POINTER                      :: force_env
    2065              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    2066              :       INTEGER, DIMENSION(:)                              :: ncol_mo, nrow_mo
    2067              : 
    2068              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_wfn_overlap_method'
    2069              : 
    2070              :       CHARACTER(LEN=default_path_length)                 :: file_name
    2071              :       INTEGER                                            :: handle, ipermutation, ispin, istate, &
    2072              :                                                             jstate, nao, nforce_eval, nmo, &
    2073              :                                                             npermutations, nspins
    2074              :       LOGICAL                                            :: exist, natom_mismatch
    2075              :       REAL(KIND=dp)                                      :: energy_diff, maxocc, Sda
    2076            8 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: coupling_wfn
    2077            8 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: overlaps
    2078            8 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2079              :       TYPE(cp_fm_struct_type), POINTER                   :: mo_mo_fmstruct
    2080              :       TYPE(cp_fm_type)                                   :: inverse_mat, mo_overlap_wfn, mo_tmp
    2081            8 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: mixed_mo_coeff
    2082              :       TYPE(cp_logger_type), POINTER                      :: logger
    2083              :       TYPE(cp_subsys_type), POINTER                      :: subsys_mix
    2084              :       TYPE(dbcsr_type), POINTER                          :: mixed_matrix_s
    2085            8 :       TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:)       :: mo_set
    2086            8 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2087            8 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2088              :       TYPE(section_vals_type), POINTER                   :: force_env_section, mixed_cdft_section
    2089              : 
    2090            8 :       NULLIFY (mixed_cdft_section, subsys_mix, particle_set, qs_kind_set, atomic_kind_set, &
    2091            8 :                mixed_mo_coeff, mixed_matrix_s, force_env_section)
    2092           16 :       logger => cp_get_default_logger()
    2093              : 
    2094            8 :       CALL timeset(routineN, handle)
    2095            8 :       nforce_eval = SIZE(mixed_cdft%results%H, 1)
    2096            8 :       npermutations = nforce_eval*(nforce_eval - 1)/2
    2097            8 :       nspins = SIZE(nrow_mo)
    2098            8 :       mixed_mo_coeff => mixed_cdft%matrix%mixed_mo_coeff
    2099            8 :       mixed_matrix_s => mixed_cdft%matrix%mixed_matrix_s
    2100              :       CALL force_env_get(force_env=force_env, &
    2101            8 :                          force_env_section=force_env_section)
    2102              :       ! Create mo_set for input wfn
    2103           40 :       ALLOCATE (mo_set(nspins))
    2104            8 :       IF (nspins == 2) THEN
    2105            8 :          maxocc = 1.0_dp
    2106              :       ELSE
    2107            0 :          maxocc = 2.0_dp
    2108              :       END IF
    2109           24 :       DO ispin = 1, nspins
    2110           16 :          nao = nrow_mo(ispin)
    2111           16 :          nmo = ncol_mo(ispin)
    2112              :          ! Only OT with fully occupied orbitals is implicitly supported
    2113              :          CALL allocate_mo_set(mo_set(ispin), nao=nao, nmo=nmo, nelectron=INT(maxocc*nmo), &
    2114              :                               n_el_f=REAL(maxocc*nmo, dp), maxocc=maxocc, &
    2115           16 :                               flexible_electron_count=0.0_dp)
    2116           16 :          CALL set_mo_set(mo_set(ispin), uniform_occupation=.TRUE., homo=nmo)
    2117           16 :          ALLOCATE (mo_set(ispin)%mo_coeff)
    2118              :          CALL cp_fm_create(matrix=mo_set(ispin)%mo_coeff, &
    2119              :                            matrix_struct=mixed_mo_coeff(1, ispin)%matrix_struct, &
    2120           16 :                            name="GS_MO_COEFF"//TRIM(ADJUSTL(cp_to_string(ispin)))//"MATRIX")
    2121           48 :          ALLOCATE (mo_set(ispin)%eigenvalues(nmo))
    2122           40 :          ALLOCATE (mo_set(ispin)%occupation_numbers(nmo))
    2123              :       END DO
    2124              :       ! Read wfn file (note we assume that the basis set is the same)
    2125            8 :       IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
    2126              :          ! This really shouldnt be a problem?
    2127              :          CALL cp_abort(__LOCATION__, &
    2128            0 :                        "QMMM + wavefunction overlap method not supported.")
    2129              :       END IF
    2130            8 :       CALL force_env_get(force_env=force_env, subsys=subsys_mix)
    2131            8 :       mixed_cdft_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT")
    2132            8 :       CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set, particle_set=particle_set)
    2133            8 :       CPASSERT(ASSOCIATED(mixed_cdft%qs_kind_set))
    2134            8 :       IF (force_env%para_env%is_source()) THEN
    2135            4 :          CALL wfn_restart_file_name(file_name, exist, mixed_cdft_section, logger)
    2136              :       END IF
    2137            8 :       CALL force_env%para_env%bcast(exist)
    2138            8 :       CALL force_env%para_env%bcast(file_name)
    2139            8 :       IF (.NOT. exist) THEN
    2140              :          CALL cp_abort(__LOCATION__, &
    2141              :                        "User requested to restart the wavefunction from the file named: "// &
    2142              :                        TRIM(file_name)//". This file does not exist. Please check the existence of"// &
    2143              :                        " the file or change properly the value of the keyword WFN_RESTART_FILE_NAME in"// &
    2144            0 :                        " section FORCE_EVAL\MIXED\MIXED_CDFT.")
    2145              :       END IF
    2146              :       CALL read_mo_set_from_restart(mo_array=mo_set, qs_kind_set=mixed_cdft%qs_kind_set, particle_set=particle_set, &
    2147              :                                     para_env=force_env%para_env, id_nr=0, multiplicity=mixed_cdft%multiplicity, &
    2148              :                                     dft_section=mixed_cdft_section, natom_mismatch=natom_mismatch, &
    2149            8 :                                     cdft=.TRUE.)
    2150            8 :       IF (natom_mismatch) THEN
    2151              :          CALL cp_abort(__LOCATION__, &
    2152            0 :                        "Restart wfn file has a wrong number of atoms")
    2153              :       END IF
    2154              :       ! Orthonormalize wfn
    2155           24 :       DO ispin = 1, nspins
    2156           24 :          IF (mixed_cdft%has_unit_metric) THEN
    2157            0 :             CALL make_basis_simple(mo_set(ispin)%mo_coeff, ncol_mo(ispin))
    2158              :          ELSE
    2159           16 :             CALL make_basis_sm(mo_set(ispin)%mo_coeff, ncol_mo(ispin), mixed_matrix_s)
    2160              :          END IF
    2161              :       END DO
    2162              :       ! Calculate MO overlaps between reference state (R) and CDFT state pairs I/J
    2163           24 :       ALLOCATE (coupling_wfn(npermutations))
    2164           32 :       ALLOCATE (overlaps(2, npermutations, nspins))
    2165            8 :       overlaps = 0.0_dp
    2166           24 :       DO ispin = 1, nspins
    2167              :          ! Allocate work
    2168           16 :          nao = nrow_mo(ispin)
    2169           16 :          nmo = ncol_mo(ispin)
    2170              :          CALL cp_fm_struct_create(mo_mo_fmstruct, nrow_global=nmo, ncol_global=nmo, &
    2171           16 :                                   context=mixed_cdft%blacs_env, para_env=force_env%para_env)
    2172              :          CALL cp_fm_create(matrix=mo_overlap_wfn, matrix_struct=mo_mo_fmstruct, &
    2173           16 :                            name="MO_OVERLAP_MATRIX_WFN")
    2174              :          CALL cp_fm_create(matrix=inverse_mat, matrix_struct=mo_mo_fmstruct, &
    2175           16 :                            name="INVERSE_MO_OVERLAP_MATRIX_WFN")
    2176           16 :          CALL cp_fm_struct_release(mo_mo_fmstruct)
    2177              :          CALL cp_fm_create(matrix=mo_tmp, &
    2178              :                            matrix_struct=mixed_mo_coeff(1, ispin)%matrix_struct, &
    2179           16 :                            name="OVERLAP_MO_COEFF_WFN")
    2180           40 :          DO ipermutation = 1, npermutations
    2181           24 :             CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    2182              :             ! S*C_r
    2183              :             CALL cp_dbcsr_sm_fm_multiply(mixed_matrix_s, mo_set(ispin)%mo_coeff, &
    2184           24 :                                          mo_tmp, nmo, 1.0_dp, 0.0_dp)
    2185              :             ! C_i^T * (S*C_r)
    2186           24 :             CALL cp_fm_set_all(mo_overlap_wfn, alpha=0.0_dp)
    2187              :             CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
    2188              :                                mixed_mo_coeff(istate, ispin), &
    2189           24 :                                mo_tmp, 0.0_dp, mo_overlap_wfn)
    2190           24 :             CALL cp_fm_invert(mo_overlap_wfn, inverse_mat, overlaps(1, ipermutation, ispin), eps_svd=mixed_cdft%eps_svd)
    2191              :             ! C_j^T * (S*C_r)
    2192           24 :             CALL cp_fm_set_all(mo_overlap_wfn, alpha=0.0_dp)
    2193              :             CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
    2194              :                                mixed_mo_coeff(jstate, ispin), &
    2195           24 :                                mo_tmp, 0.0_dp, mo_overlap_wfn)
    2196           64 :             CALL cp_fm_invert(mo_overlap_wfn, inverse_mat, overlaps(2, ipermutation, ispin), eps_svd=mixed_cdft%eps_svd)
    2197              :          END DO
    2198           16 :          CALL cp_fm_release(mo_overlap_wfn)
    2199           16 :          CALL cp_fm_release(inverse_mat)
    2200           16 :          CALL cp_fm_release(mo_tmp)
    2201           56 :          CALL deallocate_mo_set(mo_set(ispin))
    2202              :       END DO
    2203            8 :       DEALLOCATE (mo_set)
    2204           20 :       DO ipermutation = 1, npermutations
    2205           12 :          CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
    2206           12 :          IF (nspins == 2) THEN
    2207           12 :             overlaps(1, ipermutation, 1) = ABS(overlaps(1, ipermutation, 1)*overlaps(1, ipermutation, 2)) ! A in eq. 12c
    2208           12 :             overlaps(2, ipermutation, 1) = ABS(overlaps(2, ipermutation, 1)*overlaps(2, ipermutation, 2)) ! B in eq. 12c
    2209              :          ELSE
    2210            0 :             overlaps(1, ipermutation, 1) = overlaps(1, ipermutation, 1)**2
    2211            0 :             overlaps(2, ipermutation, 1) = overlaps(2, ipermutation, 1)**2
    2212              :          END IF
    2213              :          ! Calculate coupling using eq. 12c
    2214              :          ! The coupling is singular if A = B (i.e. states I/J are identical or charge in ground state is fully delocalized)
    2215           32 :          IF (ABS(overlaps(1, ipermutation, 1) - overlaps(2, ipermutation, 1)) <= 1.0e-14_dp) THEN
    2216              :             CALL cp_warn(__LOCATION__, &
    2217              :                          "Coupling between states is singular and set to zero. "// &
    2218              :                          "Potential causes: coupling is computed between identical CDFT states or the spin/charge "// &
    2219            2 :                          "density is fully delocalized in the unconstrained ground state.")
    2220            2 :             coupling_wfn(ipermutation) = 0.0_dp
    2221              :          ELSE
    2222           10 :             energy_diff = mixed_cdft%results%energy(jstate) - mixed_cdft%results%energy(istate)
    2223           10 :             Sda = mixed_cdft%results%S(istate, jstate)
    2224              :             coupling_wfn(ipermutation) = ABS((overlaps(1, ipermutation, 1)*overlaps(2, ipermutation, 1)/ &
    2225              :                                               (overlaps(1, ipermutation, 1)**2 - overlaps(2, ipermutation, 1)**2))* &
    2226              :                                              (energy_diff)/(1.0_dp - Sda**2)* &
    2227              :                                              (1.0_dp - (overlaps(1, ipermutation, 1)**2 + overlaps(2, ipermutation, 1)**2)/ &
    2228              :                                               (2.0_dp*overlaps(1, ipermutation, 1)*overlaps(2, ipermutation, 1))* &
    2229           10 :                                               Sda))
    2230              :          END IF
    2231              :       END DO
    2232            8 :       DEALLOCATE (overlaps)
    2233            8 :       CALL mixed_cdft_result_type_set(mixed_cdft%results, wfn=coupling_wfn)
    2234            8 :       DEALLOCATE (coupling_wfn)
    2235            8 :       CALL timestop(handle)
    2236              : 
    2237           16 :    END SUBROUTINE mixed_cdft_wfn_overlap_method
    2238              : 
    2239              : ! **************************************************************************************************
    2240              : !> \brief Becke constraint adapted to mixed calculations, details in qs_cdft_methods.F
    2241              : !> \param force_env the force_env that holds the CDFT states
    2242              : !> \param calculate_forces determines if forces should be calculted
    2243              : !> \par History
    2244              : !>       02.2016  created [Nico Holmberg]
    2245              : !>       03.2016  added dynamic load balancing (dlb)
    2246              : !>                changed pw_p_type data types to rank-3 reals to accommodate dlb
    2247              : !>                and to reduce overall memory footprint
    2248              : !>                split to subroutines [Nico Holmberg]
    2249              : !>       04.2016  introduced mixed grid mapping [Nico Holmberg]
    2250              : ! **************************************************************************************************
    2251           36 :    SUBROUTINE mixed_becke_constraint(force_env, calculate_forces)
    2252              :       TYPE(force_env_type), POINTER                      :: force_env
    2253              :       LOGICAL, INTENT(IN)                                :: calculate_forces
    2254              : 
    2255              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint'
    2256              : 
    2257              :       INTEGER                                            :: handle
    2258           36 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: catom
    2259              :       LOGICAL                                            :: in_memory, store_vectors
    2260           36 :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: is_constraint
    2261           36 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: coefficients
    2262           36 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: position_vecs, R12
    2263           36 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: pair_dist_vecs
    2264              :       TYPE(cp_logger_type), POINTER                      :: logger
    2265              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    2266              :       TYPE(mixed_environment_type), POINTER              :: mixed_env
    2267              : 
    2268           36 :       NULLIFY (mixed_env, mixed_cdft)
    2269           36 :       store_vectors = .TRUE.
    2270           36 :       logger => cp_get_default_logger()
    2271           36 :       CALL timeset(routineN, handle)
    2272           36 :       mixed_env => force_env%mixed_env
    2273           36 :       CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
    2274              :       CALL mixed_becke_constraint_init(force_env, mixed_cdft, calculate_forces, &
    2275              :                                        is_constraint, in_memory, store_vectors, &
    2276              :                                        R12, position_vecs, pair_dist_vecs, &
    2277           36 :                                        coefficients, catom)
    2278              :       CALL mixed_becke_constraint_low(force_env, mixed_cdft, in_memory, &
    2279              :                                       is_constraint, store_vectors, R12, &
    2280              :                                       position_vecs, pair_dist_vecs, &
    2281           36 :                                       coefficients, catom)
    2282           36 :       CALL timestop(handle)
    2283              : 
    2284           36 :    END SUBROUTINE mixed_becke_constraint
    2285              : ! **************************************************************************************************
    2286              : !> \brief Initialize the mixed Becke constraint calculation
    2287              : !> \param force_env the force_env that holds the CDFT states
    2288              : !> \param mixed_cdft container for structures needed to build the mixed CDFT constraint
    2289              : !> \param calculate_forces determines if forces should be calculted
    2290              : !> \param is_constraint a list used to determine which atoms in the system define the constraint
    2291              : !> \param in_memory decides whether to build the weight function gradients in parallel before solving
    2292              : !>                  the CDFT states or later during the SCF procedure of the individual states
    2293              : !> \param store_vectors should temporary arrays be stored in memory to accelerate the calculation
    2294              : !> \param R12 temporary array holding the pairwise atomic distances
    2295              : !> \param position_vecs temporary array holding the pbc corrected atomic position vectors
    2296              : !> \param pair_dist_vecs temporary array holding the pairwise displament vectors
    2297              : !> \param coefficients array that determines how atoms should be summed to form the constraint
    2298              : !> \param catom temporary array to map the global index of constraint atoms to their position
    2299              : !>              in a list that holds only constraint atoms
    2300              : !> \par History
    2301              : !>       03.2016  created [Nico Holmberg]
    2302              : ! **************************************************************************************************
    2303           36 :    SUBROUTINE mixed_becke_constraint_init(force_env, mixed_cdft, calculate_forces, &
    2304              :                                           is_constraint, in_memory, store_vectors, &
    2305              :                                           R12, position_vecs, pair_dist_vecs, coefficients, &
    2306              :                                           catom)
    2307              :       TYPE(force_env_type), POINTER                      :: force_env
    2308              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    2309              :       LOGICAL, INTENT(IN)                                :: calculate_forces
    2310              :       LOGICAL, ALLOCATABLE, DIMENSION(:), INTENT(OUT)    :: is_constraint
    2311              :       LOGICAL, INTENT(OUT)                               :: in_memory
    2312              :       LOGICAL, INTENT(IN)                                :: store_vectors
    2313              :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
    2314              :          INTENT(out)                                     :: R12, position_vecs
    2315              :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    2316              :          INTENT(out)                                     :: pair_dist_vecs
    2317              :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:), &
    2318              :          INTENT(OUT)                                     :: coefficients
    2319              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(out)    :: catom
    2320              : 
    2321              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint_init'
    2322              : 
    2323              :       CHARACTER(len=2)                                   :: element_symbol
    2324              :       INTEGER :: atom_a, bounds(2), handle, i, iatom, iex, iforce_eval, ikind, iounit, ithread, j, &
    2325              :          jatom, katom, my_work, my_work_size, natom, nforce_eval, nkind, np(3), npme, nthread, &
    2326              :          numexp, offset_dlb, unit_nr
    2327              :       INTEGER, DIMENSION(2, 3)                           :: bo, bo_conf
    2328           36 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list, cores, stride
    2329              :       LOGICAL                                            :: build, mpi_io
    2330              :       REAL(kind=dp)                                      :: alpha, chi, coef, ircov, jrcov, ra(3), &
    2331              :                                                             radius, uij
    2332              :       REAL(kind=dp), DIMENSION(3)                        :: cell_v, dist_vec, dr, r, r1, shift
    2333           36 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: radii_list
    2334           36 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: pab
    2335           36 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2336              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
    2337              :       TYPE(cell_type), POINTER                           :: cell
    2338              :       TYPE(cp_logger_type), POINTER                      :: logger
    2339              :       TYPE(cp_subsys_type), POINTER                      :: subsys_mix
    2340              :       TYPE(force_env_type), POINTER                      :: force_env_qs
    2341              :       TYPE(hirshfeld_type), POINTER                      :: cavity_env
    2342              :       TYPE(particle_list_type), POINTER                  :: particles
    2343           36 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2344              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2345           36 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2346              :       TYPE(realspace_grid_type), POINTER                 :: rs_cavity
    2347              :       TYPE(section_vals_type), POINTER                   :: force_env_section, print_section
    2348              : 
    2349           36 :       NULLIFY (pab, cell, force_env_qs, particle_set, force_env_section, print_section, &
    2350           36 :                qs_kind_set, particles, subsys_mix, rs_cavity, cavity_env, auxbas_pw_pool, &
    2351           36 :                atomic_kind_set, radii_list, cdft_control)
    2352           72 :       logger => cp_get_default_logger()
    2353           36 :       nforce_eval = SIZE(force_env%sub_force_env)
    2354           36 :       CALL timeset(routineN, handle)
    2355           36 :       CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
    2356           36 :       IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
    2357              :          CALL force_env_get(force_env=force_env, &
    2358              :                             subsys=subsys_mix, &
    2359           28 :                             cell=cell)
    2360              :          CALL cp_subsys_get(subsys=subsys_mix, &
    2361              :                             particles=particles, &
    2362           28 :                             particle_set=particle_set)
    2363              :       ELSE
    2364           24 :          DO iforce_eval = 1, nforce_eval
    2365           16 :             IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
    2366           24 :             force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
    2367              :          END DO
    2368              :          CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
    2369              :                          cp_subsys=subsys_mix, &
    2370            8 :                          cell=cell)
    2371              :          CALL cp_subsys_get(subsys=subsys_mix, &
    2372              :                             particles=particles, &
    2373            8 :                             particle_set=particle_set)
    2374              :       END IF
    2375           36 :       natom = SIZE(particles%els)
    2376           36 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    2377           36 :       cdft_control => mixed_cdft%cdft_control
    2378           36 :       CPASSERT(ASSOCIATED(cdft_control))
    2379           36 :       IF (.NOT. ASSOCIATED(cdft_control%becke_control%cutoffs)) THEN
    2380           24 :          CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set)
    2381           72 :          ALLOCATE (cdft_control%becke_control%cutoffs(natom))
    2382           30 :          SELECT CASE (cdft_control%becke_control%cutoff_type)
    2383              :          CASE (becke_cutoff_global)
    2384           18 :             cdft_control%becke_control%cutoffs(:) = cdft_control%becke_control%rglobal
    2385              :          CASE (becke_cutoff_element)
    2386           18 :             IF (.NOT. SIZE(atomic_kind_set) == SIZE(cdft_control%becke_control%cutoffs_tmp)) THEN
    2387              :                CALL cp_abort(__LOCATION__, &
    2388              :                              "Size of keyword BECKE_CONSTRAINT\ELEMENT_CUTOFFS does "// &
    2389            0 :                              "not match number of atomic kinds in the input coordinate file.")
    2390              :             END IF
    2391           54 :             DO ikind = 1, SIZE(atomic_kind_set)
    2392           36 :                CALL get_atomic_kind(atomic_kind_set(ikind), natom=katom, atom_list=atom_list)
    2393           90 :                DO iatom = 1, katom
    2394           36 :                   atom_a = atom_list(iatom)
    2395           72 :                   cdft_control%becke_control%cutoffs(atom_a) = cdft_control%becke_control%cutoffs_tmp(ikind)
    2396              :                END DO
    2397              :             END DO
    2398           42 :             DEALLOCATE (cdft_control%becke_control%cutoffs_tmp)
    2399              :          END SELECT
    2400              :       END IF
    2401           36 :       build = .FALSE.
    2402           36 :       IF (cdft_control%becke_control%adjust .AND. &
    2403              :           .NOT. ASSOCIATED(cdft_control%becke_control%aij)) THEN
    2404           72 :          ALLOCATE (cdft_control%becke_control%aij(natom, natom))
    2405           18 :          build = .TRUE.
    2406              :       END IF
    2407          108 :       ALLOCATE (catom(cdft_control%natoms))
    2408              :       IF (cdft_control%save_pot .OR. &
    2409              :           cdft_control%becke_control%cavity_confine .OR. &
    2410           36 :           cdft_control%becke_control%should_skip .OR. &
    2411              :           mixed_cdft%first_iteration) THEN
    2412          108 :          ALLOCATE (is_constraint(natom))
    2413           36 :          is_constraint = .FALSE.
    2414              :       END IF
    2415           36 :       in_memory = calculate_forces .AND. cdft_control%becke_control%in_memory
    2416           36 :       IF (in_memory .NEQV. calculate_forces) THEN
    2417              :          CALL cp_abort(__LOCATION__, &
    2418              :                        "The flag BECKE_CONSTRAINT\IN_MEMORY must be activated "// &
    2419            0 :                        "for the calculation of mixed CDFT forces")
    2420              :       END IF
    2421          108 :       IF (in_memory .OR. mixed_cdft%first_iteration) ALLOCATE (coefficients(natom))
    2422          108 :       DO i = 1, cdft_control%natoms
    2423           72 :          catom(i) = cdft_control%atoms(i)
    2424              :          IF (cdft_control%save_pot .OR. &
    2425              :              cdft_control%becke_control%cavity_confine .OR. &
    2426           72 :              cdft_control%becke_control%should_skip .OR. &
    2427              :              mixed_cdft%first_iteration) THEN
    2428           72 :             is_constraint(catom(i)) = .TRUE.
    2429              :          END IF
    2430          108 :          IF (in_memory .OR. mixed_cdft%first_iteration) THEN
    2431           72 :             coefficients(catom(i)) = cdft_control%group(1)%coeff(i)
    2432              :          END IF
    2433              :       END DO
    2434           36 :       CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2435          360 :       bo = auxbas_pw_pool%pw_grid%bounds_local
    2436          144 :       np = auxbas_pw_pool%pw_grid%npts
    2437          144 :       dr = auxbas_pw_pool%pw_grid%dr
    2438          144 :       shift = -REAL(MODULO(np, 2), dp)*dr/2.0_dp
    2439           36 :       IF (store_vectors) THEN
    2440          108 :          IF (in_memory) ALLOCATE (pair_dist_vecs(3, natom, natom))
    2441          108 :          ALLOCATE (position_vecs(3, natom))
    2442              :       END IF
    2443          144 :       DO i = 1, 3
    2444          144 :          cell_v(i) = cell%hmat(i, i)
    2445              :       END DO
    2446          144 :       ALLOCATE (R12(natom, natom))
    2447           72 :       DO iatom = 1, natom - 1
    2448          108 :          DO jatom = iatom + 1, natom
    2449          144 :             r = particle_set(iatom)%r
    2450          144 :             r1 = particle_set(jatom)%r
    2451          144 :             DO i = 1, 3
    2452          108 :                r(i) = MODULO(r(i), cell%hmat(i, i)) - cell%hmat(i, i)/2._dp
    2453          144 :                r1(i) = MODULO(r1(i), cell%hmat(i, i)) - cell%hmat(i, i)/2._dp
    2454              :             END DO
    2455          144 :             dist_vec = (r - r1) - ANINT((r - r1)/cell_v)*cell_v
    2456           36 :             IF (store_vectors) THEN
    2457          144 :                position_vecs(:, iatom) = r(:)
    2458          144 :                IF (iatom == 1 .AND. jatom == natom) position_vecs(:, jatom) = r1(:)
    2459           36 :                IF (in_memory) THEN
    2460           96 :                   pair_dist_vecs(:, iatom, jatom) = dist_vec(:)
    2461           96 :                   pair_dist_vecs(:, jatom, iatom) = -dist_vec(:)
    2462              :                END IF
    2463              :             END IF
    2464          144 :             R12(iatom, jatom) = NORM2(dist_vec)
    2465           36 :             R12(jatom, iatom) = R12(iatom, jatom)
    2466           72 :             IF (build) THEN
    2467              :                CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
    2468           18 :                                     kind_number=ikind)
    2469           18 :                ircov = cdft_control%becke_control%radii(ikind)
    2470              :                CALL get_atomic_kind(atomic_kind=particle_set(jatom)%atomic_kind, &
    2471           18 :                                     kind_number=ikind)
    2472           18 :                jrcov = cdft_control%becke_control%radii(ikind)
    2473           18 :                IF (ircov /= jrcov) THEN
    2474           18 :                   chi = ircov/jrcov
    2475           18 :                   uij = (chi - 1.0_dp)/(chi + 1.0_dp)
    2476           18 :                   cdft_control%becke_control%aij(iatom, jatom) = uij/(uij**2 - 1.0_dp)
    2477           18 :                   IF (cdft_control%becke_control%aij(iatom, jatom) &
    2478              :                       > 0.5_dp) THEN
    2479            0 :                      cdft_control%becke_control%aij(iatom, jatom) = 0.5_dp
    2480           18 :                   ELSE IF (cdft_control%becke_control%aij(iatom, jatom) &
    2481              :                            < -0.5_dp) THEN
    2482            0 :                      cdft_control%becke_control%aij(iatom, jatom) = -0.5_dp
    2483              :                   END IF
    2484              :                ELSE
    2485            0 :                   cdft_control%becke_control%aij(iatom, jatom) = 0.0_dp
    2486              :                END IF
    2487              :                cdft_control%becke_control%aij(jatom, iatom) = &
    2488           18 :                   -cdft_control%becke_control%aij(iatom, jatom)
    2489              :             END IF
    2490              :          END DO
    2491              :       END DO
    2492              :       ! Dump some additional information about the calculation
    2493           36 :       IF (mixed_cdft%first_iteration) THEN
    2494           24 :          print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    2495           24 :          iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
    2496           24 :          IF (iounit > 0) THEN
    2497              :             WRITE (iounit, '(/,T3,A,T66)') &
    2498           12 :                '-------------------------- Becke atomic parameters ---------------------------'
    2499           12 :             IF (cdft_control%becke_control%adjust) THEN
    2500              :                WRITE (iounit, '(T3,A,A)') &
    2501            9 :                   'Atom   Element  Coefficient', '     Cutoff (angstrom)       CDFT Radius (angstrom)'
    2502           27 :                DO iatom = 1, natom
    2503              :                   CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
    2504              :                                        element_symbol=element_symbol, &
    2505           18 :                                        kind_number=ikind)
    2506           18 :                   ircov = cp_unit_from_cp2k(cdft_control%becke_control%radii(ikind), "angstrom")
    2507           18 :                   IF (is_constraint(iatom)) THEN
    2508           18 :                      coef = coefficients(iatom)
    2509              :                   ELSE
    2510            0 :                      coef = 0.0_dp
    2511              :                   END IF
    2512              :                   WRITE (iounit, "(i6,T14,A2,T22,F8.3,T44,F8.3,T73,F8.3)") &
    2513           18 :                      iatom, ADJUSTR(element_symbol), coef, &
    2514           18 :                      cp_unit_from_cp2k(cdft_control%becke_control%cutoffs(iatom), "angstrom"), &
    2515           63 :                      ircov
    2516              :                END DO
    2517              :             ELSE
    2518              :                WRITE (iounit, '(T3,A,A)') &
    2519            3 :                   'Atom   Element  Coefficient', '     Cutoff (angstrom)'
    2520            9 :                DO iatom = 1, natom
    2521              :                   CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
    2522            6 :                                        element_symbol=element_symbol)
    2523            6 :                   IF (is_constraint(iatom)) THEN
    2524            6 :                      coef = coefficients(iatom)
    2525              :                   ELSE
    2526            0 :                      coef = 0.0_dp
    2527              :                   END IF
    2528              :                   WRITE (iounit, "(i6,T14,A2,T22,F8.3,T44,F8.3)") &
    2529            6 :                      iatom, ADJUSTR(element_symbol), coef, &
    2530           15 :                      cp_unit_from_cp2k(cdft_control%becke_control%cutoffs(iatom), "angstrom")
    2531              :                END DO
    2532              :             END IF
    2533              :             WRITE (iounit, '(T3,A)') &
    2534           12 :                '------------------------------------------------------------------------------'
    2535              :          END IF
    2536              :          CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
    2537           24 :                                            "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    2538           24 :          mixed_cdft%first_iteration = .FALSE.
    2539              :       END IF
    2540              : 
    2541           36 :       IF (cdft_control%becke_control%cavity_confine) THEN
    2542           34 :          CPASSERT(ASSOCIATED(mixed_cdft%qs_kind_set))
    2543           34 :          cavity_env => cdft_control%becke_control%cavity_env
    2544           34 :          qs_kind_set => mixed_cdft%qs_kind_set
    2545           34 :          CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set)
    2546           34 :          nkind = SIZE(qs_kind_set)
    2547           34 :          IF (.NOT. ASSOCIATED(cavity_env%kind_shape_fn)) THEN
    2548           22 :             IF (ASSOCIATED(cdft_control%becke_control%radii)) THEN
    2549           54 :                ALLOCATE (radii_list(SIZE(cdft_control%becke_control%radii)))
    2550           54 :                DO ikind = 1, SIZE(cdft_control%becke_control%radii)
    2551           54 :                   IF (cavity_env%use_bohr) THEN
    2552            0 :                      radii_list(ikind) = cdft_control%becke_control%radii(ikind)
    2553              :                   ELSE
    2554           36 :                      radii_list(ikind) = cp_unit_from_cp2k(cdft_control%becke_control%radii(ikind), "angstrom")
    2555              :                   END IF
    2556              :                END DO
    2557              :             END IF
    2558              :             CALL create_shape_function(cavity_env, qs_kind_set, atomic_kind_set, &
    2559              :                                        radius=cdft_control%becke_control%rcavity, &
    2560           22 :                                        radii_list=radii_list)
    2561           22 :             IF (ASSOCIATED(radii_list)) THEN
    2562           18 :                DEALLOCATE (radii_list)
    2563              :             END IF
    2564              :          END IF
    2565           34 :          NULLIFY (rs_cavity)
    2566              :          CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_rs_grid=rs_cavity, &
    2567           34 :                          auxbas_pw_pool=auxbas_pw_pool)
    2568              :          ! be careful in parallel nsmax is chosen with multigrid in mind!
    2569           34 :          CALL rs_grid_zero(rs_cavity)
    2570           34 :          ALLOCATE (pab(1, 1))
    2571           34 :          nthread = 1
    2572           34 :          ithread = 0
    2573          102 :          DO ikind = 1, SIZE(atomic_kind_set)
    2574           68 :             numexp = cavity_env%kind_shape_fn(ikind)%numexp
    2575           68 :             IF (numexp <= 0) CYCLE
    2576           68 :             CALL get_atomic_kind(atomic_kind_set(ikind), natom=katom, atom_list=atom_list)
    2577          204 :             ALLOCATE (cores(katom))
    2578          136 :             DO iex = 1, numexp
    2579           68 :                alpha = cavity_env%kind_shape_fn(ikind)%zet(iex)
    2580           68 :                coef = cavity_env%kind_shape_fn(ikind)%coef(iex)
    2581           68 :                npme = 0
    2582          136 :                cores = 0
    2583          136 :                DO iatom = 1, katom
    2584          136 :                   IF (rs_cavity%desc%parallel .AND. .NOT. rs_cavity%desc%distributed) THEN
    2585              :                      ! replicated realspace grid, split the atoms up between procs
    2586           68 :                      IF (MODULO(iatom, rs_cavity%desc%group_size) == rs_cavity%desc%my_pos) THEN
    2587           34 :                         npme = npme + 1
    2588           34 :                         cores(npme) = iatom
    2589              :                      END IF
    2590              :                   ELSE
    2591            0 :                      npme = npme + 1
    2592            0 :                      cores(npme) = iatom
    2593              :                   END IF
    2594              :                END DO
    2595          170 :                DO j = 1, npme
    2596           34 :                   iatom = cores(j)
    2597           34 :                   atom_a = atom_list(iatom)
    2598           34 :                   pab(1, 1) = coef
    2599           34 :                   IF (store_vectors) THEN
    2600          136 :                      ra(:) = position_vecs(:, atom_a) + cell_v(:)/2._dp
    2601              :                   ELSE
    2602            0 :                      ra(:) = pbc(particle_set(atom_a)%r, cell)
    2603              :                   END IF
    2604          102 :                   IF (is_constraint(atom_a)) THEN
    2605              :                      radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
    2606              :                                                        ra=ra, rb=ra, rp=ra, &
    2607              :                                                        zetp=alpha, eps=mixed_cdft%eps_rho_rspace, &
    2608              :                                                        pab=pab, o1=0, o2=0, &  ! without map_consistent
    2609           34 :                                                        prefactor=1.0_dp, cutoff=0.0_dp)
    2610              : 
    2611              :                      CALL collocate_pgf_product(0, alpha, 0, 0, 0.0_dp, 0, ra, &
    2612              :                                                 [0.0_dp, 0.0_dp, 0.0_dp], 1.0_dp, pab, 0, 0, &
    2613              :                                                 rs_cavity, &
    2614              :                                                 radius=radius, ga_gb_function=GRID_FUNC_AB, &
    2615              :                                                 use_subpatch=.TRUE., &
    2616           34 :                                                 subpatch_pattern=0)
    2617              :                   END IF
    2618              :                END DO
    2619              :             END DO
    2620          170 :             DEALLOCATE (cores)
    2621              :          END DO
    2622           34 :          DEALLOCATE (pab)
    2623           34 :          CALL auxbas_pw_pool%create_pw(cdft_control%becke_control%cavity)
    2624           34 :          CALL transfer_rs2pw(rs_cavity, cdft_control%becke_control%cavity)
    2625              :          CALL hfun_zero(cdft_control%becke_control%cavity%array, &
    2626              :                         cdft_control%becke_control%eps_cavity, &
    2627           34 :                         just_zero=.FALSE., bounds=bounds, work=my_work)
    2628           34 :          IF (bounds(2) < bo(2, 3)) THEN
    2629            8 :             bounds(2) = bounds(2) - 1
    2630              :          ELSE
    2631           26 :             bounds(2) = bo(2, 3)
    2632              :          END IF
    2633           34 :          IF (bounds(1) > bo(1, 3)) THEN
    2634              :             ! In the special case bounds(1) == bounds(2) == bo(2, 3), after this check
    2635              :             ! bounds(1) > bounds(2) and the subsequent gradient allocation (:, :, :, bounds(1):bounds(2))
    2636              :             ! will correctly allocate a 0-sized array
    2637            8 :             bounds(1) = bounds(1) + 1
    2638              :          ELSE
    2639           26 :             bounds(1) = bo(1, 3)
    2640              :          END IF
    2641           34 :          IF (bounds(1) > bounds(2)) THEN
    2642            0 :             my_work_size = 0
    2643              :          ELSE
    2644           34 :             my_work_size = (bounds(2) - bounds(1) + 1)
    2645           34 :             IF (mixed_cdft%is_pencil .OR. mixed_cdft%is_special) THEN
    2646            0 :                my_work_size = my_work_size*(bo(2, 2) - bo(1, 2) + 1)
    2647              :             ELSE
    2648           34 :                my_work_size = my_work_size*(bo(2, 1) - bo(1, 1) + 1)
    2649              :             END IF
    2650              :          END IF
    2651          102 :          cdft_control%becke_control%confine_bounds = bounds
    2652           34 :          IF (cdft_control%becke_control%print_cavity) THEN
    2653              :             CALL hfun_zero(cdft_control%becke_control%cavity%array, &
    2654            0 :                            cdft_control%becke_control%eps_cavity, just_zero=.TRUE.)
    2655              :             NULLIFY (stride)
    2656            0 :             ALLOCATE (stride(3))
    2657            0 :             stride = [2, 2, 2]
    2658            0 :             mpi_io = .TRUE.
    2659              :             unit_nr = cp_print_key_unit_nr(logger, print_section, "", &
    2660              :                                            middle_name="BECKE_CAVITY", &
    2661              :                                            extension=".cube", file_position="REWIND", &
    2662            0 :                                            log_filename=.FALSE., mpi_io=mpi_io)
    2663            0 :             IF (force_env%para_env%is_source() .AND. unit_nr < 1) THEN
    2664              :                CALL cp_abort(__LOCATION__, &
    2665            0 :                              "Please turn on PROGRAM_RUN_INFO to print cavity")
    2666              :             END IF
    2667              :             CALL cp_pw_to_cube(cdft_control%becke_control%cavity, &
    2668              :                                unit_nr, "CAVITY", particles=particles, &
    2669            0 :                                stride=stride, mpi_io=mpi_io)
    2670            0 :             CALL cp_print_key_finished_output(unit_nr, logger, print_section, '', mpi_io=mpi_io)
    2671            0 :             DEALLOCATE (stride)
    2672              :          END IF
    2673              :       END IF
    2674           36 :       bo_conf = bo
    2675           36 :       IF (cdft_control%becke_control%cavity_confine) THEN
    2676          102 :          bo_conf(:, 3) = cdft_control%becke_control%confine_bounds
    2677              :       END IF
    2678              :       ! Load balance
    2679           36 :       IF (mixed_cdft%dlb) THEN
    2680              :          CALL mixed_becke_constraint_dlb(force_env, mixed_cdft, my_work, &
    2681            8 :                                          my_work_size, natom, bo, bo_conf)
    2682              :       END IF
    2683              :       ! The bounds have been finalized => time to allocate storage for working matrices
    2684           36 :       offset_dlb = 0
    2685           36 :       IF (mixed_cdft%dlb) THEN
    2686            8 :          IF (mixed_cdft%dlb_control%send_work .AND. .NOT. mixed_cdft%is_special) THEN
    2687            8 :             offset_dlb = SUM(mixed_cdft%dlb_control%target_list(2, :))
    2688              :          END IF
    2689              :       END IF
    2690           36 :       IF (cdft_control%becke_control%cavity_confine) THEN
    2691              :          ! Get rid of the zero part of the confinement cavity (cr3d -> real(:,:,:))
    2692           34 :          IF (mixed_cdft%is_special) THEN
    2693            0 :             ALLOCATE (mixed_cdft%sendbuff(SIZE(mixed_cdft%dest_list)))
    2694            0 :             DO i = 1, SIZE(mixed_cdft%dest_list)
    2695              :                ALLOCATE (mixed_cdft%sendbuff(i)%cavity(mixed_cdft%dest_list_bo(1, i):mixed_cdft%dest_list_bo(2, i), &
    2696            0 :                                                        bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    2697              :                mixed_cdft%sendbuff(i)%cavity = cdft_control%becke_control%cavity%array(mixed_cdft%dest_list_bo(1, i): &
    2698              :                                                                                        mixed_cdft%dest_list_bo(2, i), &
    2699              :                                                                                        bo(1, 2):bo(2, 2), &
    2700            0 :                                                                                        bo_conf(1, 3):bo_conf(2, 3))
    2701              :             END DO
    2702           34 :          ELSE IF (mixed_cdft%is_pencil) THEN
    2703            0 :             ALLOCATE (mixed_cdft%cavity(bo(1, 1) + offset_dlb:bo(2, 1), bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    2704              :             mixed_cdft%cavity = cdft_control%becke_control%cavity%array(bo(1, 1) + offset_dlb:bo(2, 1), &
    2705              :                                                                         bo(1, 2):bo(2, 2), &
    2706            0 :                                                                         bo_conf(1, 3):bo_conf(2, 3))
    2707              :          ELSE
    2708          170 :             ALLOCATE (mixed_cdft%cavity(bo(1, 1):bo(2, 1), bo(1, 2) + offset_dlb:bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    2709              :             mixed_cdft%cavity = cdft_control%becke_control%cavity%array(bo(1, 1):bo(2, 1), &
    2710              :                                                                         bo(1, 2) + offset_dlb:bo(2, 2), &
    2711      3568226 :                                                                         bo_conf(1, 3):bo_conf(2, 3))
    2712              :          END IF
    2713           34 :          CALL auxbas_pw_pool%give_back_pw(cdft_control%becke_control%cavity)
    2714              :       END IF
    2715           36 :       IF (mixed_cdft%is_special) THEN
    2716            0 :          DO i = 1, SIZE(mixed_cdft%dest_list)
    2717              :             ALLOCATE (mixed_cdft%sendbuff(i)%weight(mixed_cdft%dest_list_bo(1, i):mixed_cdft%dest_list_bo(2, i), &
    2718            0 :                                                     bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    2719            0 :             mixed_cdft%sendbuff(i)%weight = 0.0_dp
    2720              :          END DO
    2721           36 :       ELSE IF (mixed_cdft%is_pencil) THEN
    2722            0 :          ALLOCATE (mixed_cdft%weight(bo(1, 1) + offset_dlb:bo(2, 1), bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    2723            0 :          mixed_cdft%weight = 0.0_dp
    2724              :       ELSE
    2725          180 :          ALLOCATE (mixed_cdft%weight(bo(1, 1):bo(2, 1), bo(1, 2) + offset_dlb:bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    2726      1879397 :          mixed_cdft%weight = 0.0_dp
    2727              :       END IF
    2728           36 :       IF (in_memory) THEN
    2729           24 :          IF (mixed_cdft%is_special) THEN
    2730            0 :             DO i = 1, SIZE(mixed_cdft%dest_list)
    2731              :                ALLOCATE (mixed_cdft%sendbuff(i)%gradients(3*natom, mixed_cdft%dest_list_bo(1, i): &
    2732              :                                                           mixed_cdft%dest_list_bo(2, i), &
    2733              :                                                           bo(1, 2):bo(2, 2), &
    2734            0 :                                                           bo_conf(1, 3):bo_conf(2, 3)))
    2735            0 :                mixed_cdft%sendbuff(i)%gradients = 0.0_dp
    2736              :             END DO
    2737           24 :          ELSE IF (mixed_cdft%is_pencil) THEN
    2738              :             ALLOCATE (cdft_control%group(1)%gradients(3*natom, bo(1, 1) + offset_dlb:bo(2, 1), &
    2739              :                                                       bo(1, 2):bo(2, 2), &
    2740            0 :                                                       bo_conf(1, 3):bo_conf(2, 3)))
    2741            0 :             cdft_control%group(1)%gradients = 0.0_dp
    2742              :          ELSE
    2743              :             ALLOCATE (cdft_control%group(1)%gradients(3*natom, bo(1, 1):bo(2, 1), &
    2744              :                                                       bo(1, 2) + offset_dlb:bo(2, 2), &
    2745          144 :                                                       bo_conf(1, 3):bo_conf(2, 3)))
    2746      9808936 :             cdft_control%group(1)%gradients = 0.0_dp
    2747              :          END IF
    2748              :       END IF
    2749              : 
    2750           36 :       CALL timestop(handle)
    2751              : 
    2752           36 :    END SUBROUTINE mixed_becke_constraint_init
    2753              : 
    2754              : ! **************************************************************************************************
    2755              : !> \brief Setup load balancing for mixed Becke calculation
    2756              : !> \param force_env the force_env that holds the CDFT states
    2757              : !> \param mixed_cdft container for structures needed to build the mixed CDFT constraint
    2758              : !> \param my_work an estimate of the work per processor
    2759              : !> \param my_work_size size of the smallest array slice per processor. overloaded processors will
    2760              : !>                     redistribute works as integer multiples of this value.
    2761              : !> \param natom the total number of atoms
    2762              : !> \param bo bounds of the realspace grid that holds the electron density
    2763              : !> \param bo_conf same as bo, but bounds along z-direction have been compacted with confinement
    2764              : !> \par History
    2765              : !>       03.2016  created [Nico Holmberg]
    2766              : ! **************************************************************************************************
    2767            8 :    SUBROUTINE mixed_becke_constraint_dlb(force_env, mixed_cdft, my_work, &
    2768              :                                          my_work_size, natom, bo, bo_conf)
    2769              :       TYPE(force_env_type), POINTER                      :: force_env
    2770              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    2771              :       INTEGER, INTENT(IN)                                :: my_work, my_work_size, natom
    2772              :       INTEGER, DIMENSION(2, 3)                           :: bo, bo_conf
    2773              : 
    2774              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint_dlb'
    2775              :       INTEGER, PARAMETER                                 :: should_deallocate = 7000, &
    2776              :                                                             uninitialized = -7000
    2777              : 
    2778              :       CHARACTER(len=2)                                   :: dummy
    2779              :       INTEGER :: actually_sent, exhausted_work, handle, i, ind, iounit, ispecial, j, max_targets, &
    2780              :          more_work, my_pos, my_special_work, my_target, no_overloaded, no_underloaded, nsend, &
    2781              :          nsend_limit, nsend_max, offset, offset_proc, offset_special, send_total, tags(2)
    2782            8 :       INTEGER, DIMENSION(:), POINTER :: buffsize, cumulative_work, expected_work, load_imbalance, &
    2783           16 :          nrecv, nsend_proc, sendbuffer, should_warn, tmp, work_index, work_size
    2784            8 :       INTEGER, DIMENSION(:, :), POINTER                  :: targets, tmp_bo
    2785              :       LOGICAL                                            :: consistent
    2786           16 :       LOGICAL, DIMENSION(:), POINTER                     :: mask_recv, mask_send, touched
    2787              :       REAL(kind=dp)                                      :: average_work, load_scale, &
    2788              :                                                             very_overloaded, work_factor
    2789            8 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: cavity
    2790           16 :       TYPE(buffers_bi), DIMENSION(:), POINTER            :: recvbuffer, sbuff
    2791              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
    2792              :       TYPE(cp_logger_type), POINTER                      :: logger
    2793           40 :       TYPE(mp_request_type), DIMENSION(4)                :: req
    2794            8 :       TYPE(mp_request_type), DIMENSION(:), POINTER       :: req_recv, req_total
    2795              :       TYPE(section_vals_type), POINTER                   :: force_env_section, print_section
    2796              : 
    2797           16 :       logger => cp_get_default_logger()
    2798            8 :       CALL timeset(routineN, handle)
    2799            8 :       mixed_cdft%dlb_control%recv_work = .FALSE.
    2800            8 :       mixed_cdft%dlb_control%send_work = .FALSE.
    2801            8 :       NULLIFY (expected_work, work_index, load_imbalance, work_size, &
    2802            8 :                cumulative_work, sendbuffer, buffsize, req_recv, req_total, &
    2803            8 :                tmp, nrecv, nsend_proc, targets, tmp_bo, touched, &
    2804            8 :                mask_recv, mask_send, cavity, recvbuffer, sbuff, force_env_section, &
    2805            8 :                print_section, cdft_control)
    2806            8 :       CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
    2807            8 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    2808            8 :       iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
    2809            8 :       cdft_control => mixed_cdft%cdft_control
    2810              :       ! These numerical values control data redistribution and are system sensitive
    2811              :       ! Currently they are not refined during run time which may cause crashes
    2812              :       ! However, using too many processors or a confinement cavity that is too large relative to the
    2813              :       ! total system volume are more likely culprits.
    2814            8 :       load_scale = mixed_cdft%dlb_control%load_scale
    2815            8 :       very_overloaded = mixed_cdft%dlb_control%very_overloaded
    2816            8 :       more_work = mixed_cdft%dlb_control%more_work
    2817            8 :       max_targets = 40
    2818            8 :       work_factor = 0.8_dp
    2819              :       ! Reset targets/sources
    2820            8 :       IF (mixed_cdft%is_special) THEN
    2821            0 :          DEALLOCATE (mixed_cdft%dest_list, mixed_cdft%dest_list_bo, &
    2822            0 :                      mixed_cdft%source_list, mixed_cdft%source_list_bo)
    2823              :          ALLOCATE (mixed_cdft%dest_list(SIZE(mixed_cdft%dest_list_save)), &
    2824              :                    mixed_cdft%dest_list_bo(SIZE(mixed_cdft%dest_bo_save, 1), SIZE(mixed_cdft%dest_bo_save, 2)), &
    2825              :                    mixed_cdft%source_list(SIZE(mixed_cdft%source_list_save)), &
    2826            0 :                    mixed_cdft%source_list_bo(SIZE(mixed_cdft%source_bo_save, 1), SIZE(mixed_cdft%source_bo_save, 2)))
    2827            0 :          mixed_cdft%dest_list = mixed_cdft%dest_list_save
    2828            0 :          mixed_cdft%source_list = mixed_cdft%source_list_save
    2829            0 :          mixed_cdft%dest_list_bo = mixed_cdft%dest_bo_save
    2830            0 :          mixed_cdft%source_list_bo = mixed_cdft%source_bo_save
    2831              :       END IF
    2832              :       ALLOCATE (mixed_cdft%dlb_control%expected_work(force_env%para_env%num_pe), &
    2833              :                 expected_work(force_env%para_env%num_pe), &
    2834           48 :                 work_size(force_env%para_env%num_pe))
    2835              :       IF (debug_this_module) THEN
    2836              :          ALLOCATE (should_warn(force_env%para_env%num_pe))
    2837              :          should_warn = 0
    2838              :       END IF
    2839           24 :       expected_work = 0
    2840            8 :       expected_work(force_env%para_env%mepos + 1) = my_work
    2841           24 :       work_size = 0
    2842            8 :       work_size(force_env%para_env%mepos + 1) = my_work_size
    2843            8 :       IF (ASSOCIATED(mixed_cdft%dlb_control%prediction_error)) THEN
    2844            4 :          IF (mixed_cdft%is_pencil .OR. mixed_cdft%is_special) THEN
    2845              :             work_size(force_env%para_env%mepos + 1) = work_size(force_env%para_env%mepos + 1) - &
    2846              :                                                       NINT(REAL(mixed_cdft%dlb_control% &
    2847              :                                                                 prediction_error(force_env%para_env%mepos + 1), dp)/ &
    2848            0 :                                                            REAL(bo(2, 1) - bo(1, 1) + 1, dp))
    2849              :          ELSE
    2850              :             work_size(force_env%para_env%mepos + 1) = work_size(force_env%para_env%mepos + 1) - &
    2851              :                                                       NINT(REAL(mixed_cdft%dlb_control% &
    2852              :                                                                 prediction_error(force_env%para_env%mepos + 1), dp)/ &
    2853            4 :                                                            REAL(bo(2, 2) - bo(1, 2) + 1, dp))
    2854              :          END IF
    2855              :       END IF
    2856           40 :       CALL force_env%para_env%sum(expected_work)
    2857           40 :       CALL force_env%para_env%sum(work_size)
    2858              :       ! We store the unsorted expected work to refine the estimate on subsequent calls to this routine
    2859           40 :       mixed_cdft%dlb_control%expected_work = expected_work
    2860              :       ! Take into account the prediction error of the last step
    2861            8 :       IF (ASSOCIATED(mixed_cdft%dlb_control%prediction_error)) THEN
    2862           20 :          expected_work = expected_work - mixed_cdft%dlb_control%prediction_error
    2863              :       END IF
    2864              :       !
    2865           24 :       average_work = REAL(SUM(expected_work), dp)/REAL(force_env%para_env%num_pe, dp)
    2866              :       ALLOCATE (work_index(force_env%para_env%num_pe), &
    2867              :                 load_imbalance(force_env%para_env%num_pe), &
    2868           48 :                 targets(2, force_env%para_env%num_pe))
    2869           40 :       load_imbalance = expected_work - NINT(average_work)
    2870            8 :       no_overloaded = 0
    2871            8 :       no_underloaded = 0
    2872           56 :       targets = 0
    2873              :       ! Convert the load imbalance to a multiple of the actual work size
    2874           24 :       DO i = 1, force_env%para_env%num_pe
    2875           24 :          IF (load_imbalance(i) > 0) THEN
    2876            8 :             no_overloaded = no_overloaded + 1
    2877              :             ! Allow heavily overloaded processors to dump more data since most likely they have a lot of 'real' work
    2878            8 :             IF (expected_work(i) > NINT(very_overloaded*average_work)) THEN
    2879            0 :                load_imbalance(i) = (CEILING(REAL(load_imbalance(i), dp)/REAL(work_size(i), dp)) + more_work)*work_size(i)
    2880              :             ELSE
    2881            8 :                load_imbalance(i) = CEILING(REAL(load_imbalance(i), dp)/REAL(work_size(i), dp))*work_size(i)
    2882              :             END IF
    2883              :          ELSE
    2884              :             ! Allow the underloaded processors to take load_scale amount of additional work
    2885              :             ! otherwise we may be unable to exhaust all overloaded processors
    2886            8 :             load_imbalance(i) = NINT(load_imbalance(i)*load_scale)
    2887            8 :             no_underloaded = no_underloaded + 1
    2888              :          END IF
    2889              :       END DO
    2890            8 :       CALL sort(expected_work, force_env%para_env%num_pe, indices=work_index)
    2891              :       ! Redistribute work in order from the most overloaded processors to the most underloaded processors
    2892              :       ! Each underloaded processor is limited to one overloaded processor
    2893            8 :       IF (load_imbalance(force_env%para_env%mepos + 1) > 0) THEN
    2894            4 :          offset = 0
    2895            4 :          mixed_cdft%dlb_control%send_work = .TRUE.
    2896              :          ! Build up the total amount of work that needs redistribution
    2897           12 :          ALLOCATE (cumulative_work(force_env%para_env%num_pe))
    2898           12 :          cumulative_work = 0
    2899            4 :          DO i = force_env%para_env%num_pe, force_env%para_env%num_pe - no_overloaded + 1, -1
    2900            4 :             IF (work_index(i) == force_env%para_env%mepos + 1) THEN
    2901              :                EXIT
    2902              :             ELSE
    2903            0 :                offset = offset + load_imbalance(work_index(i))
    2904            0 :                IF (i == force_env%para_env%num_pe) THEN
    2905            0 :                   cumulative_work(i) = load_imbalance(work_index(i))
    2906              :                ELSE
    2907            0 :                   cumulative_work(i) = cumulative_work(i + 1) + load_imbalance(work_index(i))
    2908              :                END IF
    2909              :             END IF
    2910              :          END DO
    2911            4 :          my_pos = i
    2912            4 :          j = force_env%para_env%num_pe
    2913            4 :          nsend_max = load_imbalance(work_index(j))/work_size(work_index(j))
    2914            4 :          exhausted_work = 0
    2915              :          ! Determine send offset by going through all processors that are more overloaded than my_pos
    2916            4 :          DO i = 1, no_underloaded
    2917            4 :             IF (my_pos == force_env%para_env%num_pe) EXIT
    2918            0 :             nsend = -load_imbalance(work_index(i))/work_size(work_index(j))
    2919            0 :             IF (nsend < 1) nsend = 1
    2920            0 :             nsend_max = nsend_max - nsend
    2921            0 :             IF (nsend_max < 0) nsend = nsend + nsend_max
    2922            0 :             exhausted_work = exhausted_work + nsend*work_size(work_index(j))
    2923            0 :             offset = offset - nsend*work_size(work_index(j))
    2924            0 :             IF (offset < 0) EXIT
    2925            4 :             IF (exhausted_work == cumulative_work(j)) THEN
    2926            0 :                j = j - 1
    2927            0 :                nsend_max = load_imbalance(work_index(j))/work_size(work_index(j))
    2928              :             END IF
    2929              :          END DO
    2930              :          ! Underloaded processors were fully exhausted: rewind index
    2931              :          ! Load balancing will fail if this happens on multiple processors
    2932            4 :          IF (i > no_underloaded) THEN
    2933            0 :             i = no_underloaded
    2934              :          END IF
    2935            4 :          my_target = i
    2936            4 :          DEALLOCATE (cumulative_work)
    2937              :          ! Determine how much and who to send slices of my grid points
    2938            4 :          nsend_max = load_imbalance(force_env%para_env%mepos + 1)/work_size(force_env%para_env%mepos + 1)
    2939              :          ! This the actual number of available array slices
    2940            4 :          IF (mixed_cdft%is_pencil .OR. mixed_cdft%is_special) THEN
    2941            0 :             nsend_limit = bo(2, 1) - bo(1, 1) + 1
    2942              :          ELSE
    2943            4 :             nsend_limit = bo(2, 2) - bo(1, 2) + 1
    2944              :          END IF
    2945            4 :          IF (.NOT. mixed_cdft%is_special) THEN
    2946            4 :             ALLOCATE (mixed_cdft%dlb_control%target_list(3, max_targets))
    2947              :          ELSE
    2948            0 :             ALLOCATE (mixed_cdft%dlb_control%target_list(3 + 2*SIZE(mixed_cdft%dest_list), max_targets))
    2949            0 :             ALLOCATE (touched(SIZE(mixed_cdft%dest_list)))
    2950            0 :             touched = .FALSE.
    2951              :          END IF
    2952          644 :          mixed_cdft%dlb_control%target_list = uninitialized
    2953            4 :          i = 1
    2954            4 :          ispecial = 1
    2955            4 :          offset_special = 0
    2956            4 :          targets(1, my_pos) = my_target
    2957            4 :          send_total = 0
    2958              :          ! Main loop. Note, we actually allow my_pos to offload more slices than nsend_max
    2959              :          DO
    2960            4 :             nsend = -load_imbalance(work_index(my_target))/work_size(force_env%para_env%mepos + 1)
    2961            4 :             IF (nsend < 1) nsend = 1 ! send at least one block
    2962              :             ! Prevent over redistribution: leave at least (1-work_factor)*nsend_limit slices to my_pos
    2963            4 :             IF (nsend > NINT(work_factor*nsend_limit - send_total)) THEN
    2964              :                nsend = NINT(work_factor*nsend_limit - send_total)
    2965              :                IF (debug_this_module) THEN
    2966              :                   should_warn(force_env%para_env%mepos + 1) = 1
    2967              :                END IF
    2968              :             END IF
    2969            4 :             mixed_cdft%dlb_control%target_list(1, i) = work_index(my_target) - 1 ! This is the actual processor rank
    2970            4 :             IF (mixed_cdft%is_special) THEN
    2971            0 :                mixed_cdft%dlb_control%target_list(2, i) = 0
    2972            0 :                actually_sent = nsend
    2973            0 :                DO j = ispecial, SIZE(mixed_cdft%dest_list)
    2974            0 :                   mixed_cdft%dlb_control%target_list(2, i) = mixed_cdft%dlb_control%target_list(2, i) + 1
    2975            0 :                   touched(j) = .TRUE.
    2976            0 :                   IF (nsend < mixed_cdft%dest_list_bo(2, j) - mixed_cdft%dest_list_bo(1, j) + 1) THEN
    2977            0 :                      mixed_cdft%dlb_control%target_list(3 + 2*j - 1, i) = mixed_cdft%dest_list_bo(1, j)
    2978            0 :                      mixed_cdft%dlb_control%target_list(3 + 2*j, i) = mixed_cdft%dest_list_bo(1, j) + nsend - 1
    2979            0 :                      mixed_cdft%dest_list_bo(1, j) = mixed_cdft%dest_list_bo(1, j) + nsend
    2980            0 :                      nsend = 0
    2981            0 :                      EXIT
    2982              :                   ELSE
    2983            0 :                      mixed_cdft%dlb_control%target_list(3 + 2*j - 1, i) = mixed_cdft%dest_list_bo(1, j)
    2984            0 :                      mixed_cdft%dlb_control%target_list(3 + 2*j, i) = mixed_cdft%dest_list_bo(2, j)
    2985            0 :                      nsend = nsend - (mixed_cdft%dest_list_bo(2, j) - mixed_cdft%dest_list_bo(1, j) + 1)
    2986            0 :                      mixed_cdft%dest_list_bo(1:2, j) = should_deallocate
    2987              :                   END IF
    2988            0 :                   IF (nsend <= 0) EXIT
    2989              :                END DO
    2990            0 :                IF (mixed_cdft%dest_list_bo(1, ispecial) == should_deallocate) ispecial = j + 1
    2991            0 :                actually_sent = actually_sent - nsend
    2992            0 :                nsend_max = nsend_max - actually_sent
    2993            0 :                send_total = send_total + actually_sent
    2994              :             ELSE
    2995            4 :                mixed_cdft%dlb_control%target_list(2, i) = nsend
    2996            4 :                nsend_max = nsend_max - nsend
    2997            4 :                send_total = send_total + nsend
    2998              :             END IF
    2999            4 :             IF (nsend_max < 0) nsend_max = 0
    3000            4 :             IF (nsend_max == 0) EXIT
    3001            0 :             IF (my_target /= no_underloaded) THEN
    3002            0 :                my_target = my_target + 1
    3003              :             ELSE
    3004              :                ! If multiple processors execute this block load balancing will fail
    3005            0 :                mixed_cdft%dlb_control%target_list(2, i) = mixed_cdft%dlb_control%target_list(2, i) + nsend_max
    3006            0 :                nsend_max = 0
    3007            0 :                EXIT
    3008              :             END IF
    3009            0 :             i = i + 1
    3010            4 :             IF (i > max_targets) THEN
    3011              :                CALL cp_abort(__LOCATION__, &
    3012            0 :                              "Load balancing error: increase max_targets")
    3013              :             END IF
    3014              :          END DO
    3015            4 :          IF (.NOT. mixed_cdft%is_special) THEN
    3016            4 :             CALL reallocate(mixed_cdft%dlb_control%target_list, 1, 3, 1, i)
    3017              :          ELSE
    3018            0 :             CALL reallocate(mixed_cdft%dlb_control%target_list, 1, 3 + 2*SIZE(mixed_cdft%dest_list), 1, i)
    3019              :          END IF
    3020            4 :          targets(2, my_pos) = my_target
    3021              :          ! Equalize the load on the target processors
    3022            4 :          IF (.NOT. mixed_cdft%is_special) THEN
    3023            4 :             IF (send_total > NINT(work_factor*nsend_limit)) send_total = NINT(work_factor*nsend_limit) - 1
    3024            4 :             nsend = NINT(REAL(send_total, dp)/REAL(SIZE(mixed_cdft%dlb_control%target_list, 2), dp))
    3025            8 :             mixed_cdft%dlb_control%target_list(2, :) = nsend
    3026              :          END IF
    3027              :       ELSE
    3028            4 :          DO i = 1, no_underloaded
    3029            4 :             IF (work_index(i) == force_env%para_env%mepos + 1) EXIT
    3030              :          END DO
    3031              :          my_pos = i
    3032              :       END IF
    3033          104 :       CALL force_env%para_env%sum(targets)
    3034              :       IF (debug_this_module) THEN
    3035              :          CALL force_env%para_env%sum(should_warn)
    3036              :          IF (ANY(should_warn == 1)) THEN
    3037              :             CALL cp_warn(__LOCATION__, &
    3038              :                          "MIXED_CDFT DLB: Attempted to redistribute more array"// &
    3039              :                          " slices than actually available. Leaving a fraction of the total"// &
    3040              :                          " slices on the overloaded processor. Perhaps you have set LOAD_SCALE too high?")
    3041              :          END IF
    3042              :          DEALLOCATE (should_warn)
    3043              :       END IF
    3044              :       ! check that there is one-to-one mapping between over- and underloaded processors
    3045            8 :       IF (force_env%para_env%is_source()) THEN
    3046            4 :          consistent = .TRUE.
    3047            4 :          DO i = force_env%para_env%num_pe - 1, force_env%para_env%num_pe - no_overloaded + 1, -1
    3048            0 :             IF (targets(1, i) > no_underloaded) consistent = .FALSE.
    3049            4 :             IF (targets(1, i) > targets(2, i + 1)) THEN
    3050              :                CYCLE
    3051              :             ELSE
    3052            0 :                consistent = .FALSE.
    3053              :             END IF
    3054              :          END DO
    3055            4 :          IF (.NOT. consistent) THEN
    3056              :             IF (debug_this_module .AND. iounit > 0) THEN
    3057              :                DO i = force_env%para_env%num_pe - 1, force_env%para_env%num_pe - no_overloaded + 1, -1
    3058              :                   WRITE (iounit, '(A,I8,I8,I8,I8,I8)') &
    3059              :                      'load balancing info', load_imbalance(i), work_index(i), &
    3060              :                      work_size(i), targets(1, i), targets(2, i)
    3061              :                END DO
    3062              :             END IF
    3063              :             CALL cp_abort(__LOCATION__, &
    3064              :                           "Load balancing error: too much data to redistribute."// &
    3065              :                           " Increase LOAD_SCALE or change the number of processors."// &
    3066              :                           " If the confinement cavity occupies a large volume relative"// &
    3067            0 :                           " to the total system volume, it might be worth disabling DLB.")
    3068              :          END IF
    3069              :       END IF
    3070              :       ! Tell the target processors which grid points they should compute
    3071            8 :       IF (my_pos <= no_underloaded) THEN
    3072            4 :          DO i = force_env%para_env%num_pe, force_env%para_env%num_pe - no_overloaded + 1, -1
    3073            4 :             IF (targets(1, i) <= my_pos .AND. targets(2, i) >= my_pos) THEN
    3074            4 :                mixed_cdft%dlb_control%recv_work = .TRUE.
    3075            4 :                mixed_cdft%dlb_control%my_source = work_index(i) - 1
    3076            4 :                EXIT
    3077              :             END IF
    3078              :          END DO
    3079            4 :          IF (mixed_cdft%dlb_control%recv_work) THEN
    3080            4 :             IF (.NOT. mixed_cdft%is_special) THEN
    3081            4 :                ALLOCATE (mixed_cdft%dlb_control%bo(12))
    3082              :                CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%bo, source=mixed_cdft%dlb_control%my_source, &
    3083            4 :                                              request=req(1))
    3084            4 :                CALL req(1)%wait()
    3085           12 :                mixed_cdft%dlb_control%my_dest_repl = [mixed_cdft%dlb_control%bo(11), mixed_cdft%dlb_control%bo(12)]
    3086           12 :                mixed_cdft%dlb_control%dest_tags_repl = [mixed_cdft%dlb_control%bo(9), mixed_cdft%dlb_control%bo(10)]
    3087              :                ALLOCATE (mixed_cdft%dlb_control%cavity(mixed_cdft%dlb_control%bo(1):mixed_cdft%dlb_control%bo(2), &
    3088              :                                                        mixed_cdft%dlb_control%bo(3):mixed_cdft%dlb_control%bo(4), &
    3089           20 :                                                        mixed_cdft%dlb_control%bo(7):mixed_cdft%dlb_control%bo(8)))
    3090              :                ALLOCATE (mixed_cdft%dlb_control%weight(mixed_cdft%dlb_control%bo(1):mixed_cdft%dlb_control%bo(2), &
    3091              :                                                        mixed_cdft%dlb_control%bo(3):mixed_cdft%dlb_control%bo(4), &
    3092           20 :                                                        mixed_cdft%dlb_control%bo(7):mixed_cdft%dlb_control%bo(8)))
    3093              :                ALLOCATE (mixed_cdft%dlb_control%gradients(3*natom, &
    3094              :                                                           mixed_cdft%dlb_control%bo(1):mixed_cdft%dlb_control%bo(2), &
    3095              :                                                           mixed_cdft%dlb_control%bo(3):mixed_cdft%dlb_control%bo(4), &
    3096           24 :                                                           mixed_cdft%dlb_control%bo(7):mixed_cdft%dlb_control%bo(8)))
    3097        22724 :                mixed_cdft%dlb_control%gradients = 0.0_dp
    3098         3524 :                mixed_cdft%dlb_control%weight = 0.0_dp
    3099              :                CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%cavity, source=mixed_cdft%dlb_control%my_source, &
    3100            4 :                                              request=req(1))
    3101            4 :                CALL req(1)%wait()
    3102            4 :                DEALLOCATE (mixed_cdft%dlb_control%bo)
    3103              :             ELSE
    3104            0 :                ALLOCATE (buffsize(1))
    3105              :                CALL force_env%para_env%irecv(msgout=buffsize, source=mixed_cdft%dlb_control%my_source, &
    3106            0 :                                              request=req(1))
    3107            0 :                CALL req(1)%wait()
    3108            0 :                ALLOCATE (mixed_cdft%dlb_control%bo(12*buffsize(1)))
    3109              :                CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%bo, source=mixed_cdft%dlb_control%my_source, &
    3110            0 :                                              request=req(1))
    3111            0 :                ALLOCATE (mixed_cdft%dlb_control%sendbuff(buffsize(1)))
    3112            0 :                ALLOCATE (req_recv(buffsize(1)))
    3113            0 :                DEALLOCATE (buffsize)
    3114            0 :                CALL req(1)%wait()
    3115            0 :                DO j = 1, SIZE(mixed_cdft%dlb_control%sendbuff)
    3116              :                   ALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%cavity(mixed_cdft%dlb_control%bo(12*(j - 1) + 1): &
    3117              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 2), &
    3118              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 3): &
    3119              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 4), &
    3120              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 7): &
    3121            0 :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 8)))
    3122              :                   CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%sendbuff(j)%cavity, &
    3123              :                                                 source=mixed_cdft%dlb_control%my_source, &
    3124            0 :                                                 request=req_recv(j))
    3125              :                   ALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%weight(mixed_cdft%dlb_control%bo(12*(j - 1) + 1): &
    3126              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 2), &
    3127              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 3): &
    3128              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 4), &
    3129              :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 7): &
    3130            0 :                                                                       mixed_cdft%dlb_control%bo(12*(j - 1) + 8)))
    3131              :                   ALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%gradients(3*natom, &
    3132              :                                                                          mixed_cdft%dlb_control%bo(12*(j - 1) + 1): &
    3133              :                                                                          mixed_cdft%dlb_control%bo(12*(j - 1) + 2), &
    3134              :                                                                          mixed_cdft%dlb_control%bo(12*(j - 1) + 3): &
    3135              :                                                                          mixed_cdft%dlb_control%bo(12*(j - 1) + 4), &
    3136              :                                                                          mixed_cdft%dlb_control%bo(12*(j - 1) + 7): &
    3137            0 :                                                                          mixed_cdft%dlb_control%bo(12*(j - 1) + 8)))
    3138            0 :                   mixed_cdft%dlb_control%sendbuff(j)%weight = 0.0_dp
    3139            0 :                   mixed_cdft%dlb_control%sendbuff(j)%gradients = 0.0_dp
    3140              :                   mixed_cdft%dlb_control%sendbuff(j)%tag = [mixed_cdft%dlb_control%bo(12*(j - 1) + 9), &
    3141            0 :                                                             mixed_cdft%dlb_control%bo(12*(j - 1) + 10)]
    3142              :                   mixed_cdft%dlb_control%sendbuff(j)%rank = [mixed_cdft%dlb_control%bo(12*(j - 1) + 11), &
    3143            0 :                                                              mixed_cdft%dlb_control%bo(12*(j - 1) + 12)]
    3144              :                END DO
    3145            0 :                CALL mp_waitall(req_recv)
    3146            0 :                DEALLOCATE (req_recv)
    3147              :             END IF
    3148              :          END IF
    3149              :       ELSE
    3150            4 :          IF (.NOT. mixed_cdft%is_special) THEN
    3151            4 :             offset = 0
    3152            4 :             ALLOCATE (sendbuffer(12))
    3153            4 :             send_total = 0
    3154            8 :             DO i = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
    3155              :                tags = [(i - 1)*3 + 1 + force_env%para_env%mepos*6*max_targets, &
    3156           12 :                        (i - 1)*3 + 1 + 3*max_targets + force_env%para_env%mepos*6*max_targets] ! Unique communicator tags
    3157            4 :                mixed_cdft%dlb_control%target_list(3, i) = tags(1)
    3158            4 :                IF (mixed_cdft%is_pencil) THEN
    3159              :                   sendbuffer = [bo_conf(1, 1) + offset, &
    3160              :                                 bo_conf(1, 1) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
    3161              :                                 bo_conf(1, 2), bo_conf(2, 2), bo(1, 3), bo(2, 3), bo_conf(1, 3), bo_conf(2, 3), &
    3162            0 :                                 tags(1), tags(2), mixed_cdft%dest_list(1), mixed_cdft%dest_list(2)]
    3163              :                ELSE
    3164              :                   sendbuffer = [bo_conf(1, 1), bo_conf(2, 1), &
    3165              :                                 bo_conf(1, 2) + offset, &
    3166              :                                 bo_conf(1, 2) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
    3167              :                                 bo(1, 3), bo(2, 3), bo_conf(1, 3), bo_conf(2, 3), tags(1), tags(2), &
    3168           52 :                                 mixed_cdft%dest_list(1), mixed_cdft%dest_list(2)]
    3169              :                END IF
    3170            4 :                send_total = send_total + mixed_cdft%dlb_control%target_list(2, i) - 1
    3171              :                CALL force_env%para_env%isend(msgin=sendbuffer, dest=mixed_cdft%dlb_control%target_list(1, i), &
    3172            4 :                                              request=req(1))
    3173            4 :                CALL req(1)%wait()
    3174            4 :                IF (mixed_cdft%is_pencil) THEN
    3175              :                   ALLOCATE (cavity(bo_conf(1, 1) + offset: &
    3176              :                                    bo_conf(1, 1) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
    3177            0 :                                    bo_conf(1, 2):bo_conf(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    3178              :                   cavity = cdft_control%becke_control%cavity%array(bo_conf(1, 1) + offset: &
    3179              :                                                                    bo_conf(1, 1) + offset + &
    3180              :                                                                    (mixed_cdft%dlb_control%target_list(2, i) - 1), &
    3181              :                                                                    bo_conf(1, 2):bo_conf(2, 2), &
    3182            0 :                                                                    bo_conf(1, 3):bo_conf(2, 3))
    3183              :                ELSE
    3184              :                   ALLOCATE (cavity(bo_conf(1, 1):bo_conf(2, 1), &
    3185              :                                    bo_conf(1, 2) + offset: &
    3186              :                                    bo_conf(1, 2) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
    3187           20 :                                    bo_conf(1, 3):bo_conf(2, 3)))
    3188              :                   cavity = cdft_control%becke_control%cavity%array(bo_conf(1, 1):bo_conf(2, 1), &
    3189              :                                                                    bo_conf(1, 2) + offset: &
    3190              :                                                                    bo_conf(1, 2) + offset + &
    3191              :                                                                    (mixed_cdft%dlb_control%target_list(2, i) - 1), &
    3192         7044 :                                                                    bo_conf(1, 3):bo_conf(2, 3))
    3193              :                END IF
    3194              :                CALL force_env%para_env%isend(msgin=cavity, &
    3195              :                                              dest=mixed_cdft%dlb_control%target_list(1, i), &
    3196            4 :                                              request=req(1))
    3197            4 :                CALL req(1)%wait()
    3198            4 :                offset = offset + mixed_cdft%dlb_control%target_list(2, i)
    3199            8 :                DEALLOCATE (cavity)
    3200              :             END DO
    3201            4 :             IF (mixed_cdft%is_pencil) THEN
    3202            0 :                mixed_cdft%dlb_control%distributed(1) = bo_conf(1, 1)
    3203            0 :                mixed_cdft%dlb_control%distributed(2) = bo_conf(1, 1) + offset - 1
    3204              :             ELSE
    3205            4 :                mixed_cdft%dlb_control%distributed(1) = bo_conf(1, 2)
    3206            4 :                mixed_cdft%dlb_control%distributed(2) = bo_conf(1, 2) + offset - 1
    3207              :             END IF
    3208            4 :             DEALLOCATE (sendbuffer)
    3209              :          ELSE
    3210            0 :             ALLOCATE (buffsize(1))
    3211            0 :             DO i = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
    3212            0 :                buffsize = mixed_cdft%dlb_control%target_list(2, i)
    3213              :                ! Unique communicator tags (dont actually need these, should be removed)
    3214              :                tags = [(i - 1)*3 + 1 + force_env%para_env%mepos*6*max_targets, &
    3215            0 :                        (i - 1)*3 + 1 + 3*max_targets + force_env%para_env%mepos*6*max_targets]
    3216            0 :                DO j = 4, SIZE(mixed_cdft%dlb_control%target_list, 1)
    3217            0 :                   IF (mixed_cdft%dlb_control%target_list(j, i) > uninitialized) EXIT
    3218              :                END DO
    3219            0 :                offset_special = j
    3220            0 :                offset_proc = j - 4 - (j - 4)/2
    3221              :                CALL force_env%para_env%isend(msgin=buffsize, &
    3222              :                                              dest=mixed_cdft%dlb_control%target_list(1, i), &
    3223            0 :                                              request=req(1))
    3224            0 :                CALL req(1)%wait()
    3225            0 :                ALLOCATE (sendbuffer(12*buffsize(1)))
    3226            0 :                DO j = 1, buffsize(1)
    3227              :                   sendbuffer(12*(j - 1) + 1:12*(j - 1) + 12) = [mixed_cdft%dlb_control%target_list(offset_special + 2*(j - 1), i), &
    3228              :                                                                 mixed_cdft%dlb_control%target_list(offset_special + 2*j - 1, i), &
    3229              :                                                                 bo_conf(1, 2), bo_conf(2, 2), bo(1, 3), bo(2, 3), &
    3230              :                                                                 bo_conf(1, 3), bo_conf(2, 3), tags(1), tags(2), &
    3231              :                                                                 mixed_cdft%dest_list(j + offset_proc), &
    3232            0 :                                                                 mixed_cdft%dest_list(j + offset_proc) + force_env%para_env%num_pe/2]
    3233              :                END DO
    3234              :                CALL force_env%para_env%isend(msgin=sendbuffer, &
    3235              :                                              dest=mixed_cdft%dlb_control%target_list(1, i), &
    3236            0 :                                              request=req(1))
    3237            0 :                CALL req(1)%wait()
    3238            0 :                DEALLOCATE (sendbuffer)
    3239            0 :                DO j = 1, buffsize(1)
    3240              :                   ALLOCATE (cavity(mixed_cdft%dlb_control%target_list(offset_special + 2*(j - 1), i): &
    3241              :                                    mixed_cdft%dlb_control%target_list(offset_special + 2*j - 1, i), &
    3242            0 :                                    bo_conf(1, 2):bo_conf(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
    3243              :                   cavity = cdft_control%becke_control%cavity%array(LBOUND(cavity, 1):UBOUND(cavity, 1), &
    3244              :                                                                    bo_conf(1, 2):bo_conf(2, 2), &
    3245            0 :                                                                    bo_conf(1, 3):bo_conf(2, 3))
    3246              :                   CALL force_env%para_env%isend(msgin=cavity, &
    3247              :                                                 dest=mixed_cdft%dlb_control%target_list(1, i), &
    3248            0 :                                                 request=req(1))
    3249            0 :                   CALL req(1)%wait()
    3250            0 :                   DEALLOCATE (cavity)
    3251              :                END DO
    3252              :             END DO
    3253            0 :             DEALLOCATE (buffsize)
    3254              :          END IF
    3255              :       END IF
    3256            8 :       DEALLOCATE (expected_work, work_size, load_imbalance, work_index, targets)
    3257              :       ! Once calculated, data defined on the distributed grid points is sent directly to the processors that own the
    3258              :       ! grid points after the constraint is copied onto the two processor groups, instead of sending the data back to
    3259              :       ! the original owner
    3260            8 :       IF (mixed_cdft%is_special) THEN
    3261            0 :          my_special_work = 2
    3262            0 :          ALLOCATE (mask_send(SIZE(mixed_cdft%dest_list)), mask_recv(SIZE(mixed_cdft%source_list)))
    3263            0 :          ALLOCATE (nsend_proc(SIZE(mixed_cdft%dest_list)), nrecv(SIZE(mixed_cdft%source_list)))
    3264            0 :          nrecv = 0
    3265            0 :          nsend_proc = 0
    3266            0 :          mask_recv = .FALSE.
    3267            0 :          mask_send = .FALSE.
    3268              :       ELSE
    3269              :          my_special_work = 1
    3270              :       END IF
    3271           72 :       ALLOCATE (recvbuffer(SIZE(mixed_cdft%source_list)), sbuff(SIZE(mixed_cdft%dest_list)))
    3272           56 :       ALLOCATE (req_total(my_special_work*SIZE(mixed_cdft%source_list) + (my_special_work**2)*SIZE(mixed_cdft%dest_list)))
    3273           24 :       ALLOCATE (mixed_cdft%dlb_control%recv_work_repl(SIZE(mixed_cdft%source_list)))
    3274           24 :       DO i = 1, SIZE(mixed_cdft%source_list)
    3275           16 :          NULLIFY (recvbuffer(i)%bv, recvbuffer(i)%iv)
    3276           16 :          ALLOCATE (recvbuffer(i)%bv(1), recvbuffer(i)%iv(3))
    3277              :          CALL force_env%para_env%irecv(msgout=recvbuffer(i)%bv, &
    3278              :                                        source=mixed_cdft%source_list(i), &
    3279           16 :                                        request=req_total(i), tag=1)
    3280           24 :          IF (mixed_cdft%is_special) THEN
    3281              :             CALL force_env%para_env%irecv(msgout=recvbuffer(i)%iv, &
    3282              :                                           source=mixed_cdft%source_list(i), &
    3283              :                                           request=req_total(i + SIZE(mixed_cdft%source_list)), &
    3284            0 :                                           tag=2)
    3285              :          END IF
    3286              :       END DO
    3287           16 :       DO i = 1, my_special_work
    3288           32 :          DO j = 1, SIZE(mixed_cdft%dest_list)
    3289           16 :             IF (i == 1) THEN
    3290           16 :                NULLIFY (sbuff(j)%iv, sbuff(j)%bv)
    3291           16 :                ALLOCATE (sbuff(j)%bv(1))
    3292           32 :                sbuff(j)%bv = mixed_cdft%dlb_control%send_work
    3293           16 :                IF (mixed_cdft%is_special) THEN
    3294            0 :                   ALLOCATE (sbuff(j)%iv(3))
    3295            0 :                   sbuff(j)%iv(1:2) = mixed_cdft%dest_list_bo(1:2, j)
    3296            0 :                   sbuff(j)%iv(3) = 0
    3297            0 :                   IF (sbuff(j)%iv(1) == should_deallocate) mask_send(j) = .TRUE.
    3298            0 :                   IF (mixed_cdft%dlb_control%send_work) THEN
    3299            0 :                      sbuff(j)%bv = touched(j)
    3300            0 :                      IF (touched(j)) THEN
    3301            0 :                         nsend = 0
    3302            0 :                         DO ispecial = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
    3303            0 :                            IF (mixed_cdft%dlb_control%target_list(4 + 2*(j - 1), ispecial) /= uninitialized) THEN
    3304            0 :                               nsend = nsend + 1
    3305              :                            END IF
    3306              :                         END DO
    3307            0 :                         sbuff(j)%iv(3) = nsend
    3308            0 :                         nsend_proc(j) = nsend
    3309              :                      END IF
    3310              :                   END IF
    3311              :                END IF
    3312              :             END IF
    3313           16 :             ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + my_special_work*SIZE(mixed_cdft%source_list)
    3314              :             CALL force_env%para_env%isend(msgin=sbuff(j)%bv, &
    3315              :                                           dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
    3316           16 :                                           request=req_total(ind), tag=1)
    3317           24 :             IF (mixed_cdft%is_special) THEN
    3318              :                CALL force_env%para_env%isend(msgin=sbuff(j)%iv, &
    3319              :                                              dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
    3320            0 :                                              request=req_total(ind + 2*SIZE(mixed_cdft%dest_list)), tag=2)
    3321              :             END IF
    3322              :          END DO
    3323              :       END DO
    3324            8 :       CALL mp_waitall(req_total)
    3325            8 :       DEALLOCATE (req_total)
    3326           24 :       DO i = 1, SIZE(mixed_cdft%source_list)
    3327           16 :          mixed_cdft%dlb_control%recv_work_repl(i) = recvbuffer(i)%bv(1)
    3328           16 :          IF (mixed_cdft%is_special .AND. mixed_cdft%dlb_control%recv_work_repl(i)) THEN
    3329            0 :             mixed_cdft%source_list_bo(1:2, i) = recvbuffer(i)%iv(1:2)
    3330            0 :             nrecv(i) = recvbuffer(i)%iv(3)
    3331            0 :             IF (recvbuffer(i)%iv(1) == should_deallocate) mask_recv(i) = .TRUE.
    3332              :          END IF
    3333           16 :          DEALLOCATE (recvbuffer(i)%bv)
    3334           24 :          IF (ASSOCIATED(recvbuffer(i)%iv)) DEALLOCATE (recvbuffer(i)%iv)
    3335              :       END DO
    3336           24 :       DO j = 1, SIZE(mixed_cdft%dest_list)
    3337           16 :          DEALLOCATE (sbuff(j)%bv)
    3338           24 :          IF (ASSOCIATED(sbuff(j)%iv)) DEALLOCATE (sbuff(j)%iv)
    3339              :       END DO
    3340            8 :       DEALLOCATE (recvbuffer)
    3341              :       ! For some reason if debug_this_module is true and is_special is false, the deallocate statement
    3342              :       ! on line 3433 gets executed no matter what (gfortran 5.3.0 bug?). Printing out the variable seems to fix it...
    3343              :       IF (debug_this_module) THEN
    3344              :          WRITE (dummy, *) mixed_cdft%is_special
    3345              :       END IF
    3346              : 
    3347            8 :       IF (.NOT. mixed_cdft%is_special) THEN
    3348            8 :          IF (mixed_cdft%dlb_control%send_work) THEN
    3349           32 :             ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl) + 2))
    3350            4 :             ALLOCATE (sendbuffer(6))
    3351            4 :             IF (mixed_cdft%is_pencil) THEN
    3352              :                sendbuffer = [SIZE(mixed_cdft%dlb_control%target_list, 2), bo_conf(1, 3), bo_conf(2, 3), &
    3353            0 :                              bo_conf(1, 1), bo_conf(1, 2), bo_conf(2, 2)]
    3354              :             ELSE
    3355              :                sendbuffer = [SIZE(mixed_cdft%dlb_control%target_list, 2), bo_conf(1, 3), bo_conf(2, 3), &
    3356           28 :                              bo_conf(1, 2), bo_conf(1, 1), bo_conf(2, 1)]
    3357              :             END IF
    3358            8 :          ELSE IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3359           24 :             ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl)))
    3360              :          END IF
    3361           16 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3362           24 :             ALLOCATE (mixed_cdft%dlb_control%recv_info(2))
    3363            8 :             NULLIFY (mixed_cdft%dlb_control%recv_info(1)%target_list, mixed_cdft%dlb_control%recv_info(2)%target_list)
    3364           24 :             ALLOCATE (mixed_cdft%dlb_control%recvbuff(2))
    3365            8 :             NULLIFY (mixed_cdft%dlb_control%recvbuff(1)%buffs, mixed_cdft%dlb_control%recvbuff(2)%buffs)
    3366              :          END IF
    3367              :          ! First communicate which grid points were distributed
    3368            8 :          IF (mixed_cdft%dlb_control%send_work) THEN
    3369           12 :             ind = COUNT(mixed_cdft%dlb_control%recv_work_repl) + 1
    3370           12 :             DO i = 1, 2
    3371              :                CALL force_env%para_env%isend(msgin=sendbuffer, &
    3372              :                                              dest=mixed_cdft%dest_list(i), &
    3373            8 :                                              request=req_total(ind))
    3374           12 :                ind = ind + 1
    3375              :             END DO
    3376              :          END IF
    3377           16 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3378            8 :             ind = 1
    3379           24 :             DO i = 1, 2
    3380           24 :                IF (mixed_cdft%dlb_control%recv_work_repl(i)) THEN
    3381            8 :                   ALLOCATE (mixed_cdft%dlb_control%recv_info(i)%matrix_info(6))
    3382              :                   CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recv_info(i)%matrix_info, &
    3383              :                                                 source=mixed_cdft%source_list(i), &
    3384            8 :                                                 request=req_total(ind))
    3385            8 :                   ind = ind + 1
    3386              :                END IF
    3387              :             END DO
    3388              :          END IF
    3389            8 :          IF (ASSOCIATED(req_total)) THEN
    3390            8 :             CALL mp_waitall(req_total)
    3391              :          END IF
    3392              :          ! Now communicate which processor handles which grid points
    3393            8 :          IF (mixed_cdft%dlb_control%send_work) THEN
    3394           12 :             ind = COUNT(mixed_cdft%dlb_control%recv_work_repl) + 1
    3395           12 :             DO i = 1, 2
    3396            8 :                IF (i == 2) THEN
    3397            8 :                   mixed_cdft%dlb_control%target_list(3, :) = mixed_cdft%dlb_control%target_list(3, :) + 3*max_targets
    3398              :                END IF
    3399              :                CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%target_list, &
    3400              :                                              dest=mixed_cdft%dest_list(i), &
    3401            8 :                                              request=req_total(ind))
    3402           12 :                ind = ind + 1
    3403              :             END DO
    3404              :          END IF
    3405           16 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3406            8 :             ind = 1
    3407           24 :             DO i = 1, 2
    3408           24 :                IF (mixed_cdft%dlb_control%recv_work_repl(i)) THEN
    3409              :                   ALLOCATE (mixed_cdft%dlb_control%recv_info(i)% &
    3410           24 :                             target_list(3, mixed_cdft%dlb_control%recv_info(i)%matrix_info(1)))
    3411              :                   CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recv_info(i)%target_list, &
    3412              :                                                 source=mixed_cdft%source_list(i), &
    3413            8 :                                                 request=req_total(ind))
    3414            8 :                   ind = ind + 1
    3415              :                END IF
    3416              :             END DO
    3417              :          END IF
    3418            8 :          IF (ASSOCIATED(req_total)) THEN
    3419            8 :             CALL mp_waitall(req_total)
    3420            8 :             DEALLOCATE (req_total)
    3421              :          END IF
    3422            8 :          IF (ASSOCIATED(sendbuffer)) DEALLOCATE (sendbuffer)
    3423              :       ELSE
    3424            0 :          IF (mixed_cdft%dlb_control%send_work) THEN
    3425            0 :             ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl) + 2*COUNT(touched)))
    3426            0 :          ELSE IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3427            0 :             ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl)))
    3428              :          END IF
    3429            0 :          IF (mixed_cdft%dlb_control%send_work) THEN
    3430            0 :             ind = COUNT(mixed_cdft%dlb_control%recv_work_repl)
    3431            0 :             DO j = 1, SIZE(mixed_cdft%dest_list)
    3432            0 :                IF (touched(j)) THEN
    3433            0 :                   ALLOCATE (sbuff(j)%iv(4 + 3*nsend_proc(j)))
    3434            0 :                   sbuff(j)%iv(1:4) = [bo_conf(1, 2), bo_conf(2, 2), bo_conf(1, 3), bo_conf(2, 3)]
    3435            0 :                   offset = 5
    3436            0 :                   DO i = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
    3437            0 :                      IF (mixed_cdft%dlb_control%target_list(4 + 2*(j - 1), i) /= uninitialized) THEN
    3438              :                         sbuff(j)%iv(offset:offset + 2) = [mixed_cdft%dlb_control%target_list(1, i), &
    3439              :                                                           mixed_cdft%dlb_control%target_list(4 + 2*(j - 1), i), &
    3440            0 :                                                           mixed_cdft%dlb_control%target_list(4 + 2*j - 1, i)]
    3441            0 :                         offset = offset + 3
    3442              :                      END IF
    3443              :                   END DO
    3444            0 :                   DO ispecial = 1, my_special_work
    3445              :                      CALL force_env%para_env%isend(msgin=sbuff(j)%iv, &
    3446              :                                                    dest=mixed_cdft%dest_list(j) + (ispecial - 1)*force_env%para_env%num_pe/2, &
    3447            0 :                                                    request=req_total(ind + ispecial))
    3448              :                   END DO
    3449            0 :                   ind = ind + my_special_work
    3450              :                END IF
    3451              :             END DO
    3452              :          END IF
    3453            0 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3454            0 :             ALLOCATE (mixed_cdft%dlb_control%recv_info(SIZE(mixed_cdft%source_list)))
    3455            0 :             ALLOCATE (mixed_cdft%dlb_control%recvbuff(SIZE(mixed_cdft%source_list)))
    3456            0 :             ind = 1
    3457            0 :             DO j = 1, SIZE(mixed_cdft%source_list)
    3458              :                NULLIFY (mixed_cdft%dlb_control%recv_info(j)%target_list, &
    3459            0 :                         mixed_cdft%dlb_control%recvbuff(j)%buffs)
    3460            0 :                IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
    3461            0 :                   ALLOCATE (mixed_cdft%dlb_control%recv_info(j)%matrix_info(4 + 3*nrecv(j)))
    3462              :                   CALL force_env%para_env%irecv(mixed_cdft%dlb_control%recv_info(j)%matrix_info, &
    3463              :                                                 source=mixed_cdft%source_list(j), &
    3464            0 :                                                 request=req_total(ind))
    3465            0 :                   ind = ind + 1
    3466              :                END IF
    3467              :             END DO
    3468              :          END IF
    3469            0 :          IF (ASSOCIATED(req_total)) THEN
    3470            0 :             CALL mp_waitall(req_total)
    3471            0 :             DEALLOCATE (req_total)
    3472              :          END IF
    3473            0 :          IF (ANY(mask_send)) THEN
    3474              :             ALLOCATE (tmp(SIZE(mixed_cdft%dest_list) - COUNT(mask_send)), &
    3475            0 :                       tmp_bo(2, SIZE(mixed_cdft%dest_list) - COUNT(mask_send)))
    3476            0 :             i = 1
    3477            0 :             DO j = 1, SIZE(mixed_cdft%dest_list)
    3478            0 :                IF (.NOT. mask_send(j)) THEN
    3479            0 :                   tmp(i) = mixed_cdft%dest_list(j)
    3480            0 :                   tmp_bo(1:2, i) = mixed_cdft%dest_list_bo(1:2, j)
    3481            0 :                   i = i + 1
    3482              :                END IF
    3483              :             END DO
    3484            0 :             DEALLOCATE (mixed_cdft%dest_list, mixed_cdft%dest_list_bo)
    3485            0 :             ALLOCATE (mixed_cdft%dest_list(SIZE(tmp)), mixed_cdft%dest_list_bo(2, SIZE(tmp)))
    3486            0 :             mixed_cdft%dest_list = tmp
    3487            0 :             mixed_cdft%dest_list_bo = tmp_bo
    3488            0 :             DEALLOCATE (tmp, tmp_bo)
    3489              :          END IF
    3490            0 :          IF (ANY(mask_recv)) THEN
    3491              :             ALLOCATE (tmp(SIZE(mixed_cdft%source_list) - COUNT(mask_recv)), &
    3492            0 :                       tmp_bo(4, SIZE(mixed_cdft%source_list) - COUNT(mask_recv)))
    3493            0 :             i = 1
    3494            0 :             DO j = 1, SIZE(mixed_cdft%source_list)
    3495            0 :                IF (.NOT. mask_recv(j)) THEN
    3496            0 :                   tmp(i) = mixed_cdft%source_list(j)
    3497            0 :                   tmp_bo(1:4, i) = mixed_cdft%source_list_bo(1:4, j)
    3498            0 :                   i = i + 1
    3499              :                END IF
    3500              :             END DO
    3501            0 :             DEALLOCATE (mixed_cdft%source_list, mixed_cdft%source_list_bo)
    3502            0 :             ALLOCATE (mixed_cdft%source_list(SIZE(tmp)), mixed_cdft%source_list_bo(4, SIZE(tmp)))
    3503            0 :             mixed_cdft%source_list = tmp
    3504            0 :             mixed_cdft%source_list_bo = tmp_bo
    3505            0 :             DEALLOCATE (tmp, tmp_bo)
    3506              :          END IF
    3507            0 :          DEALLOCATE (mask_recv, mask_send)
    3508            0 :          DEALLOCATE (nsend_proc, nrecv)
    3509            0 :          IF (mixed_cdft%dlb_control%send_work) THEN
    3510            0 :             DO j = 1, SIZE(mixed_cdft%dest_list)
    3511            0 :                IF (touched(j)) DEALLOCATE (sbuff(j)%iv)
    3512              :             END DO
    3513            0 :             IF (ASSOCIATED(touched)) DEALLOCATE (touched)
    3514              :          END IF
    3515              :       END IF
    3516            8 :       DEALLOCATE (sbuff)
    3517              :       CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
    3518            8 :                                         "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    3519            8 :       CALL timestop(handle)
    3520              : 
    3521           16 :    END SUBROUTINE mixed_becke_constraint_dlb
    3522              : 
    3523              : ! **************************************************************************************************
    3524              : !> \brief Low level routine to build mixed Becke constraint and gradients
    3525              : !> \param force_env the force_env that holds the CDFT states
    3526              : !> \param mixed_cdft container for structures needed to build the mixed CDFT constraint
    3527              : !> \param in_memory decides whether to build the weight function gradients in parallel before solving
    3528              : !>                  the CDFT states or later during the SCF procedure of the individual states
    3529              : !> \param is_constraint a list used to determine which atoms in the system define the constraint
    3530              : !> \param store_vectors should temporary arrays be stored in memory to accelerate the calculation
    3531              : !> \param R12 temporary array holding the pairwise atomic distances
    3532              : !> \param position_vecs temporary array holding the pbc corrected atomic position vectors
    3533              : !> \param pair_dist_vecs temporary array holding the pairwise displament vectors
    3534              : !> \param coefficients array that determines how atoms should be summed to form the constraint
    3535              : !> \param catom temporary array to map the global index of constraint atoms to their position
    3536              : !>              in a list that holds only constraint atoms
    3537              : !> \par History
    3538              : !>       03.2016  created [Nico Holmberg]
    3539              : ! **************************************************************************************************
    3540           36 :    SUBROUTINE mixed_becke_constraint_low(force_env, mixed_cdft, in_memory, &
    3541              :                                          is_constraint, store_vectors, R12, position_vecs, &
    3542              :                                          pair_dist_vecs, coefficients, catom)
    3543              :       TYPE(force_env_type), POINTER                      :: force_env
    3544              :       TYPE(mixed_cdft_type), POINTER                     :: mixed_cdft
    3545              :       LOGICAL, INTENT(IN)                                :: in_memory
    3546              :       LOGICAL, ALLOCATABLE, DIMENSION(:), INTENT(INOUT)  :: is_constraint
    3547              :       LOGICAL, INTENT(IN)                                :: store_vectors
    3548              :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
    3549              :          INTENT(INOUT)                                   :: R12, position_vecs
    3550              :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    3551              :          INTENT(INOUT)                                   :: pair_dist_vecs
    3552              :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:), &
    3553              :          INTENT(INOUT)                                   :: coefficients
    3554              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(INOUT)  :: catom
    3555              : 
    3556              :       CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint_low'
    3557              :       REAL(KIND=dp), PARAMETER :: eps_sum_cell_f_all = 1.0E-06_dp
    3558              : 
    3559              :       INTEGER :: handle, i, iatom, icomm, iforce_eval, index, iounit, ip, ispecial, iwork, j, &
    3560              :          jatom, jcomm, k, my_special_work, my_work, natom, nbuffs, nforce_eval, np(3), &
    3561              :          nsent_total, nskipped, nwork, offset, offset_repl
    3562           36 :       INTEGER, DIMENSION(:), POINTER                     :: work, work_dlb
    3563           36 :       INTEGER, DIMENSION(:, :), POINTER                  :: nsent
    3564              :       LOGICAL                                            :: completed_recv, should_communicate
    3565           36 :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: skip_me
    3566           36 :       LOGICAL, ALLOCATABLE, DIMENSION(:, :)              :: completed
    3567              :       REAL(kind=dp)                                      :: dist1, dist2, dmyexp, my1, my1_homo, &
    3568              :                                                             myexp, sum_cell_f_all, &
    3569              :                                                             sum_cell_f_constr, th, tmp_const
    3570           36 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: cell_functions, distances, ds_dR_i, &
    3571           36 :                                                             ds_dR_j
    3572           36 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: d_sum_const_dR, d_sum_Pm_dR, &
    3573           36 :                                                             distance_vecs, dP_i_dRi
    3574           36 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: dP_i_dRj
    3575              :       REAL(kind=dp), DIMENSION(3)                        :: cell_v, dist_vec, dmy_dR_i, dmy_dR_j, &
    3576              :                                                             dr, dr1_r2, dr_i_dR, dr_ij_dR, &
    3577              :                                                             dr_j_dR, grid_p, r, r1, shift
    3578           36 :       REAL(kind=dp), DIMENSION(:), POINTER               :: cutoffs
    3579           36 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: cavity, weight
    3580           36 :       REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER      :: gradients
    3581              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
    3582              :       TYPE(cell_type), POINTER                           :: cell
    3583              :       TYPE(cp_logger_type), POINTER                      :: logger
    3584              :       TYPE(cp_subsys_type), POINTER                      :: subsys_mix
    3585              :       TYPE(force_env_type), POINTER                      :: force_env_qs
    3586           36 :       TYPE(mp_request_type), DIMENSION(:), POINTER       :: req_recv, req_total
    3587           36 :       TYPE(mp_request_type), DIMENSION(:, :), POINTER    :: req_send
    3588              :       TYPE(particle_list_type), POINTER                  :: particles
    3589           36 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    3590              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3591              :       TYPE(section_vals_type), POINTER                   :: force_env_section, print_section
    3592              : 
    3593           72 :       logger => cp_get_default_logger()
    3594           36 :       NULLIFY (work, req_recv, req_send, work_dlb, nsent, cutoffs, cavity, &
    3595           36 :                weight, gradients, cell, subsys_mix, force_env_qs, &
    3596           36 :                particle_set, particles, auxbas_pw_pool, force_env_section, &
    3597           36 :                print_section, cdft_control)
    3598           36 :       CALL timeset(routineN, handle)
    3599           36 :       nforce_eval = SIZE(force_env%sub_force_env)
    3600           36 :       CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
    3601           36 :       print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    3602           36 :       iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
    3603           36 :       IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
    3604              :          CALL force_env_get(force_env=force_env, &
    3605              :                             subsys=subsys_mix, &
    3606           28 :                             cell=cell)
    3607              :          CALL cp_subsys_get(subsys=subsys_mix, &
    3608              :                             particles=particles, &
    3609           28 :                             particle_set=particle_set)
    3610              :       ELSE
    3611           24 :          DO iforce_eval = 1, nforce_eval
    3612           16 :             IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
    3613           24 :             force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
    3614              :          END DO
    3615              :          CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
    3616              :                          cp_subsys=subsys_mix, &
    3617            8 :                          cell=cell)
    3618              :          CALL cp_subsys_get(subsys=subsys_mix, &
    3619              :                             particles=particles, &
    3620            8 :                             particle_set=particle_set)
    3621              :       END IF
    3622           36 :       natom = SIZE(particles%els)
    3623           36 :       cdft_control => mixed_cdft%cdft_control
    3624           36 :       CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3625          144 :       np = auxbas_pw_pool%pw_grid%npts
    3626          144 :       dr = auxbas_pw_pool%pw_grid%dr
    3627          144 :       shift = -REAL(MODULO(np, 2), dp)*dr/2.0_dp
    3628          180 :       ALLOCATE (cell_functions(natom), skip_me(natom))
    3629           36 :       IF (store_vectors) THEN
    3630           72 :          ALLOCATE (distances(natom))
    3631          108 :          ALLOCATE (distance_vecs(3, natom))
    3632              :       END IF
    3633           36 :       IF (in_memory) THEN
    3634           24 :          ALLOCATE (ds_dR_j(3))
    3635           24 :          ALLOCATE (ds_dR_i(3))
    3636           72 :          ALLOCATE (d_sum_Pm_dR(3, natom))
    3637           48 :          ALLOCATE (d_sum_const_dR(3, natom))
    3638           96 :          ALLOCATE (dP_i_dRj(3, natom, natom))
    3639           48 :          ALLOCATE (dP_i_dRi(3, natom))
    3640           24 :          th = 1.0e-8_dp
    3641              :       END IF
    3642           36 :       IF (mixed_cdft%dlb) THEN
    3643           32 :          ALLOCATE (work(force_env%para_env%num_pe), work_dlb(force_env%para_env%num_pe))
    3644           24 :          work = 0
    3645           24 :          work_dlb = 0
    3646              :       END IF
    3647           36 :       my_work = 1
    3648           36 :       my_special_work = 1
    3649              :       ! Load balancing: allocate storage for receiving buffers and post recv requests
    3650           36 :       IF (mixed_cdft%dlb) THEN
    3651            8 :          IF (mixed_cdft%dlb_control%recv_work) THEN
    3652            4 :             my_work = 2
    3653            4 :             IF (.NOT. mixed_cdft%is_special) THEN
    3654           40 :                ALLOCATE (req_send(2, 3))
    3655              :             ELSE
    3656            0 :                ALLOCATE (req_send(2, 3*SIZE(mixed_cdft%dlb_control%sendbuff)))
    3657              :             END IF
    3658              :          END IF
    3659           16 :          IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    3660            8 :             IF (.NOT. mixed_cdft%is_special) THEN
    3661            8 :                offset_repl = 0
    3662            8 :                IF (mixed_cdft%dlb_control%recv_work_repl(1) .AND. mixed_cdft%dlb_control%recv_work_repl(2)) THEN
    3663              :                   ALLOCATE (req_recv(3*(SIZE(mixed_cdft%dlb_control%recv_info(1)%target_list, 2) + &
    3664            0 :                                         SIZE(mixed_cdft%dlb_control%recv_info(2)%target_list, 2))))
    3665            0 :                   offset_repl = 3*SIZE(mixed_cdft%dlb_control%recv_info(1)%target_list, 2)
    3666            8 :                ELSE IF (mixed_cdft%dlb_control%recv_work_repl(1)) THEN
    3667            0 :                   ALLOCATE (req_recv(3*(SIZE(mixed_cdft%dlb_control%recv_info(1)%target_list, 2))))
    3668              :                ELSE
    3669           48 :                   ALLOCATE (req_recv(3*(SIZE(mixed_cdft%dlb_control%recv_info(2)%target_list, 2))))
    3670              :                END IF
    3671              :             ELSE
    3672            0 :                nbuffs = 0
    3673            0 :                offset_repl = 1
    3674            0 :                DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
    3675            0 :                   IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
    3676            0 :                      nbuffs = nbuffs + (SIZE(mixed_cdft%dlb_control%recv_info(j)%matrix_info) - 4)/3
    3677              :                   END IF
    3678              :                END DO
    3679            0 :                ALLOCATE (req_recv(3*nbuffs))
    3680              :             END IF
    3681           24 :             DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
    3682           24 :                IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
    3683            8 :                   IF (.NOT. mixed_cdft%is_special) THEN
    3684            8 :                      offset = 0
    3685            8 :                      index = j + (j/2)
    3686           64 :                      ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(SIZE(mixed_cdft%dlb_control%recv_info(j)%target_list, 2)))
    3687           16 :                      DO i = 1, SIZE(mixed_cdft%dlb_control%recv_info(j)%target_list, 2)
    3688            8 :                         IF (mixed_cdft%is_pencil) THEN
    3689              :                            ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3690              :                                      weight(mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
    3691              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
    3692              :                                             (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
    3693              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
    3694              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
    3695              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
    3696            0 :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
    3697              :                            ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3698              :                                      cavity(mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
    3699              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
    3700              :                                             (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
    3701              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
    3702              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
    3703              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
    3704            0 :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
    3705              :                            ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3706              :                                      gradients(3*natom, &
    3707              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
    3708              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
    3709              :                                                (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
    3710              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
    3711              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
    3712              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
    3713            0 :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
    3714              :                         ELSE
    3715              :                            ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3716              :                                      weight(mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
    3717              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
    3718              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
    3719              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
    3720              :                                             (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
    3721              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
    3722           40 :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
    3723              :                            ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3724              :                                      cavity(mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
    3725              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
    3726              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
    3727              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
    3728              :                                             (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
    3729              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
    3730           40 :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
    3731              :                            ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3732              :                                      gradients(3*natom, &
    3733              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
    3734              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
    3735              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
    3736              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
    3737              :                                                (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
    3738              :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
    3739           48 :                                                mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
    3740              :                         END IF
    3741              : 
    3742              :                         CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, &
    3743              :                                                       source=mixed_cdft%dlb_control%recv_info(j)%target_list(1, i), &
    3744              :                                                       request=req_recv(3*(i - 1) + (j - 1)*offset_repl + 1), &
    3745            8 :                                                       tag=mixed_cdft%dlb_control%recv_info(j)%target_list(3, i))
    3746              :                         CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, &
    3747              :                                                       source=mixed_cdft%dlb_control%recv_info(j)%target_list(1, i), &
    3748              :                                                       request=req_recv(3*(i - 1) + (j - 1)*offset_repl + 2), &
    3749            8 :                                                       tag=mixed_cdft%dlb_control%recv_info(j)%target_list(3, i) + 1)
    3750              :                         CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, &
    3751              :                                                       source=mixed_cdft%dlb_control%recv_info(j)%target_list(1, i), &
    3752              :                                                       request=req_recv(3*(i - 1) + (j - 1)*offset_repl + 3), &
    3753            8 :                                                       tag=mixed_cdft%dlb_control%recv_info(j)%target_list(3, i) + 2)
    3754           16 :                         offset = offset + mixed_cdft%dlb_control%recv_info(j)%target_list(2, i)
    3755              :                      END DO
    3756            8 :                      DEALLOCATE (mixed_cdft%dlb_control%recv_info(j)%matrix_info)
    3757              :                   ELSE
    3758              :                      ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)% &
    3759            0 :                                buffs((SIZE(mixed_cdft%dlb_control%recv_info(j)%matrix_info) - 4)/3))
    3760            0 :                      index = 6
    3761            0 :                      DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
    3762              :                         ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3763              :                                   weight(mixed_cdft%dlb_control%recv_info(j)%matrix_info(index): &
    3764              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(index + 1), &
    3765              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(1): &
    3766              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(2), &
    3767              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(3): &
    3768            0 :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(4)))
    3769              :                         ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3770              :                                   cavity(mixed_cdft%dlb_control%recv_info(j)%matrix_info(index): &
    3771              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(index + 1), &
    3772              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(1): &
    3773              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(2), &
    3774              :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(3): &
    3775            0 :                                          mixed_cdft%dlb_control%recv_info(j)%matrix_info(4)))
    3776              :                         ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
    3777              :                                   gradients(3*natom, mixed_cdft%dlb_control%recv_info(j)%matrix_info(index): &
    3778              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(index + 1), &
    3779              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(1): &
    3780              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(2), &
    3781              :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(3): &
    3782            0 :                                             mixed_cdft%dlb_control%recv_info(j)%matrix_info(4)))
    3783              :                         CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, &
    3784              :                                                       source=mixed_cdft%dlb_control%recv_info(j)%matrix_info(index - 1), &
    3785            0 :                                                       request=req_recv(offset_repl), tag=1)
    3786              :                         CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, &
    3787              :                                                       source=mixed_cdft%dlb_control%recv_info(j)%matrix_info(index - 1), &
    3788            0 :                                                       request=req_recv(offset_repl + 1), tag=2)
    3789              :                         CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, &
    3790              :                                                       source=mixed_cdft%dlb_control%recv_info(j)%matrix_info(index - 1), &
    3791            0 :                                                       request=req_recv(offset_repl + 2), tag=3)
    3792            0 :                         index = index + 3
    3793            0 :                         offset_repl = offset_repl + 3
    3794              :                      END DO
    3795            0 :                      DEALLOCATE (mixed_cdft%dlb_control%recv_info(j)%matrix_info)
    3796              :                   END IF
    3797              :                END IF
    3798              :             END DO
    3799              :          END IF
    3800              :       END IF
    3801           36 :       cutoffs => cdft_control%becke_control%cutoffs
    3802           36 :       should_communicate = .FALSE.
    3803          144 :       DO i = 1, 3
    3804          144 :          cell_v(i) = cell%hmat(i, i)
    3805              :       END DO
    3806           76 :       DO iwork = my_work, 1, -1
    3807           40 :          IF (iwork == 2) THEN
    3808            4 :             IF (.NOT. mixed_cdft%is_special) THEN
    3809            4 :                cavity => mixed_cdft%dlb_control%cavity
    3810            4 :                weight => mixed_cdft%dlb_control%weight
    3811            4 :                gradients => mixed_cdft%dlb_control%gradients
    3812            4 :                ALLOCATE (completed(2, 3), nsent(2, 3))
    3813              :             ELSE
    3814            0 :                my_special_work = SIZE(mixed_cdft%dlb_control%sendbuff)
    3815            0 :                ALLOCATE (completed(2, 3*my_special_work), nsent(2, 3*my_special_work))
    3816              :             END IF
    3817            4 :             completed = .FALSE.
    3818           40 :             nsent = 0
    3819              :          ELSE
    3820           36 :             IF (.NOT. mixed_cdft%is_special) THEN
    3821           36 :                weight => mixed_cdft%weight
    3822           36 :                cavity => mixed_cdft%cavity
    3823           36 :                gradients => cdft_control%group(1)%gradients
    3824              :             ELSE
    3825            0 :                my_special_work = SIZE(mixed_cdft%dest_list)
    3826              :             END IF
    3827              :          END IF
    3828          116 :          DO ispecial = 1, my_special_work
    3829           40 :             nwork = 0
    3830           40 :             IF (mixed_cdft%is_special) THEN
    3831            0 :                IF (iwork == 1) THEN
    3832            0 :                   weight => mixed_cdft%sendbuff(ispecial)%weight
    3833            0 :                   cavity => mixed_cdft%sendbuff(ispecial)%cavity
    3834            0 :                   gradients => mixed_cdft%sendbuff(ispecial)%gradients
    3835              :                ELSE
    3836            0 :                   weight => mixed_cdft%dlb_control%sendbuff(ispecial)%weight
    3837            0 :                   cavity => mixed_cdft%dlb_control%sendbuff(ispecial)%cavity
    3838            0 :                   gradients => mixed_cdft%dlb_control%sendbuff(ispecial)%gradients
    3839              :                END IF
    3840              :             END IF
    3841         1021 :             DO k = LBOUND(weight, 1), UBOUND(weight, 1)
    3842          901 :                IF (mixed_cdft%dlb .AND. mixed_cdft%is_pencil .AND. .NOT. mixed_cdft%is_special) THEN
    3843            0 :                   IF (mixed_cdft%dlb_control%send_work) THEN
    3844            0 :                      IF (k >= mixed_cdft%dlb_control%distributed(1) .AND. &
    3845              :                          k <= mixed_cdft%dlb_control%distributed(2)) THEN
    3846              :                         CYCLE
    3847              :                      END IF
    3848              :                   END IF
    3849              :                END IF
    3850        41952 :                DO j = LBOUND(weight, 2), UBOUND(weight, 2)
    3851        39209 :                   IF (mixed_cdft%dlb .AND. .NOT. mixed_cdft%is_pencil .AND. .NOT. mixed_cdft%is_special) THEN
    3852         6400 :                      IF (mixed_cdft%dlb_control%send_work) THEN
    3853         3120 :                         IF (j >= mixed_cdft%dlb_control%distributed(1) .AND. &
    3854              :                             j <= mixed_cdft%dlb_control%distributed(2)) THEN
    3855              :                            CYCLE
    3856              :                         END IF
    3857              :                      END IF
    3858              :                   END IF
    3859              :                   ! Check if any of the buffers have become available for deallocation
    3860        39209 :                   IF (should_communicate) THEN
    3861         2048 :                      DO icomm = 1, SIZE(nsent, 2)
    3862         5120 :                         DO jcomm = 1, SIZE(nsent, 1)
    3863         3072 :                            IF (nsent(jcomm, icomm) == 1) CYCLE
    3864          540 :                            completed(jcomm, icomm) = req_send(jcomm, icomm)%test()
    3865          540 :                            IF (completed(jcomm, icomm)) THEN
    3866           24 :                               nsent(jcomm, icomm) = nsent(jcomm, icomm) + 1
    3867           24 :                               nsent_total = nsent_total + 1
    3868           24 :                               IF (nsent_total == SIZE(nsent, 1)*SIZE(nsent, 2)) should_communicate = .FALSE.
    3869              :                            END IF
    3870         2612 :                            IF (ALL(completed(:, icomm))) THEN
    3871           12 :                               IF (MODULO(icomm, 3) == 1) THEN
    3872            4 :                                  IF (.NOT. mixed_cdft%is_special) THEN
    3873            4 :                                     DEALLOCATE (mixed_cdft%dlb_control%cavity)
    3874              :                                  ELSE
    3875            0 :                                     DEALLOCATE (mixed_cdft%dlb_control%sendbuff((icomm - 1)/3 + 1)%cavity)
    3876              :                                  END IF
    3877            8 :                               ELSE IF (MODULO(icomm, 3) == 2) THEN
    3878            4 :                                  IF (.NOT. mixed_cdft%is_special) THEN
    3879            4 :                                     DEALLOCATE (mixed_cdft%dlb_control%weight)
    3880              :                                  ELSE
    3881            0 :                                     DEALLOCATE (mixed_cdft%dlb_control%sendbuff((icomm - 1)/3 + 1)%weight)
    3882              :                                  END IF
    3883              :                               ELSE
    3884            4 :                                  IF (.NOT. mixed_cdft%is_special) THEN
    3885            4 :                                     DEALLOCATE (mixed_cdft%dlb_control%gradients)
    3886              :                                  ELSE
    3887            0 :                                     DEALLOCATE (mixed_cdft%dlb_control%sendbuff((icomm - 1)/3 + 1)%gradients)
    3888              :                                  END IF
    3889              :                               END IF
    3890              :                            END IF
    3891              :                         END DO
    3892              :                      END DO
    3893              :                   END IF
    3894              :                   ! Poll to prevent starvation
    3895        39209 :                   IF (ASSOCIATED(req_recv)) THEN
    3896         6400 :                      completed_recv = mp_testall(req_recv)
    3897              :                   END IF
    3898              :                   !
    3899      1926389 :                   DO i = LBOUND(weight, 3), UBOUND(weight, 3)
    3900      1807861 :                      IF (cdft_control%becke_control%cavity_confine) THEN
    3901      1716736 :                         IF (cavity(k, j, i) < cdft_control%becke_control%eps_cavity) CYCLE
    3902              :                      END IF
    3903       988401 :                      grid_p(1) = k*dr(1) + shift(1)
    3904       988401 :                      grid_p(2) = j*dr(2) + shift(2)
    3905       988401 :                      grid_p(3) = i*dr(3) + shift(3)
    3906       988401 :                      nskipped = 0
    3907      2965203 :                      cell_functions = 1.0_dp
    3908       988401 :                      skip_me = .FALSE.
    3909       988401 :                      IF (store_vectors) distances = 0.0_dp
    3910       988401 :                      IF (in_memory) THEN
    3911       675116 :                         d_sum_Pm_dR = 0.0_dp
    3912       675116 :                         d_sum_const_dR = 0.0_dp
    3913       675116 :                         dP_i_dRi = 0.0_dp
    3914              :                      END IF
    3915      2554568 :                      DO iatom = 1, natom
    3916      1976802 :                         IF (skip_me(iatom)) THEN
    3917        65541 :                            cell_functions(iatom) = 0.0_dp
    3918        65541 :                            IF (cdft_control%becke_control%should_skip) THEN
    3919        37642 :                               IF (is_constraint(iatom)) nskipped = nskipped + 1
    3920        37642 :                               IF (nskipped == cdft_control%natoms) THEN
    3921            0 :                                  IF (in_memory) THEN
    3922            0 :                                     IF (cdft_control%becke_control%cavity_confine) THEN
    3923            0 :                                        cavity(k, j, i) = 0.0_dp
    3924              :                                     END IF
    3925              :                                  END IF
    3926              :                                  EXIT
    3927              :                               END IF
    3928              :                            END IF
    3929              :                            CYCLE
    3930              :                         END IF
    3931      1911261 :                         IF (store_vectors) THEN
    3932      1911261 :                            IF (distances(iatom) == 0.0_dp) THEN
    3933      6889176 :                               r = position_vecs(:, iatom)
    3934      6889176 :                               dist_vec = (r - grid_p) - ANINT((r - grid_p)/cell_v)*cell_v
    3935      6889176 :                               dist1 = NORM2(dist_vec)
    3936      6889176 :                               distance_vecs(:, iatom) = dist_vec
    3937      1722294 :                               distances(iatom) = dist1
    3938              :                            ELSE
    3939       755868 :                               dist_vec = distance_vecs(:, iatom)
    3940              :                               dist1 = distances(iatom)
    3941              :                            END IF
    3942              :                         ELSE
    3943            0 :                            r = particle_set(iatom)%r
    3944            0 :                            DO ip = 1, 3
    3945            0 :                               r(ip) = MODULO(r(ip), cell%hmat(ip, ip)) - cell%hmat(ip, ip)/2._dp
    3946              :                            END DO
    3947            0 :                            dist_vec = (r - grid_p) - ANINT((r - grid_p)/cell_v)*cell_v
    3948            0 :                            dist1 = NORM2(dist_vec)
    3949              :                         END IF
    3950      2489027 :                         IF (dist1 <= cutoffs(iatom)) THEN
    3951       509029 :                            IF (in_memory) THEN
    3952              :                               IF (dist1 <= th) dist1 = th
    3953      1184700 :                               dr_i_dR(:) = dist_vec(:)/dist1
    3954              :                            END IF
    3955      1527087 :                            DO jatom = 1, natom
    3956      1527087 :                               IF (jatom /= iatom) THEN
    3957       509029 :                                  IF (jatom < iatom) THEN
    3958       254521 :                                     IF (.NOT. skip_me(jatom)) CYCLE
    3959              :                                  END IF
    3960       320062 :                                  IF (store_vectors) THEN
    3961       320062 :                                     IF (distances(jatom) == 0.0_dp) THEN
    3962      1018032 :                                        r1 = position_vecs(:, jatom)
    3963      1018032 :                                        dist_vec = (r1 - grid_p) - ANINT((r1 - grid_p)/cell_v)*cell_v
    3964      1018032 :                                        dist2 = NORM2(dist_vec)
    3965      1018032 :                                        distance_vecs(:, jatom) = dist_vec
    3966       254508 :                                        distances(jatom) = dist2
    3967              :                                     ELSE
    3968       262216 :                                        dist_vec = distance_vecs(:, jatom)
    3969              :                                        dist2 = distances(jatom)
    3970              :                                     END IF
    3971              :                                  ELSE
    3972            0 :                                     r1 = particle_set(jatom)%r
    3973            0 :                                     DO ip = 1, 3
    3974            0 :                                        r1(ip) = MODULO(r1(ip), cell%hmat(ip, ip)) - cell%hmat(ip, ip)/2._dp
    3975              :                                     END DO
    3976            0 :                                     dist_vec = (r1 - grid_p) - ANINT((r1 - grid_p)/cell_v)*cell_v
    3977            0 :                                     dist2 = NORM2(dist_vec)
    3978              :                                  END IF
    3979       320062 :                                  IF (in_memory) THEN
    3980       191129 :                                     IF (store_vectors) THEN
    3981       764516 :                                        dr1_r2 = pair_dist_vecs(:, iatom, jatom)
    3982              :                                     ELSE
    3983            0 :                                        dr1_r2 = (r - r1) - ANINT((r - r1)/cell_v)*cell_v
    3984              :                                     END IF
    3985              :                                     IF (dist2 <= th) dist2 = th
    3986       191129 :                                     tmp_const = (R12(iatom, jatom)**3)
    3987       764516 :                                     dr_ij_dR(:) = dr1_r2(:)/tmp_const
    3988              :                                     !derivativ w.r.t. Rj
    3989       764516 :                                     dr_j_dR = dist_vec(:)/dist2
    3990       764516 :                                     dmy_dR_j(:) = -(dr_j_dR(:)/R12(iatom, jatom) - (dist1 - dist2)*dr_ij_dR(:))
    3991              :                                     !derivativ w.r.t. Ri
    3992       764516 :                                     dmy_dR_i(:) = dr_i_dR(:)/R12(iatom, jatom) - (dist1 - dist2)*dr_ij_dR(:)
    3993              :                                  END IF
    3994       320062 :                                  my1 = (dist1 - dist2)/R12(iatom, jatom)
    3995       320062 :                                  IF (cdft_control%becke_control%adjust) THEN
    3996       166839 :                                     my1_homo = my1
    3997              :                                     my1 = my1 + &
    3998       166839 :                                           cdft_control%becke_control%aij(iatom, jatom)*(1.0_dp - my1**2)
    3999              :                                  END IF
    4000       320062 :                                  myexp = 1.5_dp*my1 - 0.5_dp*my1**3
    4001       320062 :                                  IF (in_memory) THEN
    4002       191129 :                                     dmyexp = 1.5_dp - 1.5_dp*my1**2
    4003              :                                     tmp_const = (1.5_dp**2)*dmyexp*(1 - myexp**2)* &
    4004       191129 :                                                 (1.0_dp - ((1.5_dp*myexp - 0.5_dp*(myexp**3))**2))
    4005              : 
    4006       764516 :                                     ds_dR_i(:) = -0.5_dp*tmp_const*dmy_dR_i(:)
    4007       764516 :                                     ds_dR_j(:) = -0.5_dp*tmp_const*dmy_dR_j(:)
    4008       191129 :                                     IF (cdft_control%becke_control%adjust) THEN
    4009       102514 :                                        tmp_const = 1.0_dp - 2.0_dp*my1_homo*cdft_control%becke_control%aij(iatom, jatom)
    4010       410056 :                                        ds_dR_i(:) = ds_dR_i(:)*tmp_const
    4011       410056 :                                        ds_dR_j(:) = ds_dR_j(:)*tmp_const
    4012              :                                     END IF
    4013              :                                  END IF
    4014       320062 :                                  myexp = 1.5_dp*myexp - 0.5_dp*myexp**3
    4015       320062 :                                  myexp = 1.5_dp*myexp - 0.5_dp*myexp**3
    4016       320062 :                                  tmp_const = 0.5_dp*(1.0_dp - myexp)
    4017       320062 :                                  cell_functions(iatom) = cell_functions(iatom)*tmp_const
    4018       320062 :                                  IF (in_memory) THEN
    4019       191129 :                                     IF (ABS(tmp_const) <= th) tmp_const = tmp_const + th
    4020       764516 :                                     dP_i_dRi(:, iatom) = dP_i_dRi(:, iatom) + ds_dR_i(:)/tmp_const
    4021       764516 :                                     dP_i_dRj(:, iatom, jatom) = ds_dR_j(:)/tmp_const
    4022              :                                  END IF
    4023              : 
    4024       320062 :                                  IF (dist2 <= cutoffs(jatom)) THEN
    4025       188967 :                                     tmp_const = 0.5_dp*(1.0_dp + myexp)
    4026       188967 :                                     cell_functions(jatom) = cell_functions(jatom)*tmp_const
    4027       188967 :                                     IF (in_memory) THEN
    4028       105046 :                                        IF (ABS(tmp_const) <= th) tmp_const = tmp_const + th
    4029       420184 :                                        dP_i_dRj(:, jatom, iatom) = -ds_dR_i(:)/tmp_const
    4030       420184 :                                        dP_i_dRi(:, jatom) = dP_i_dRi(:, jatom) - ds_dR_j(:)/tmp_const
    4031              :                                     END IF
    4032              :                                  ELSE
    4033       131095 :                                     skip_me(jatom) = .TRUE.
    4034              :                                  END IF
    4035              :                               END IF
    4036              :                            END DO
    4037       509029 :                            IF (in_memory) THEN
    4038      1184700 :                               dP_i_dRi(:, iatom) = cell_functions(iatom)*dP_i_dRi(:, iatom)
    4039      1184700 :                               d_sum_Pm_dR(:, iatom) = d_sum_Pm_dR(:, iatom) + dP_i_dRi(:, iatom)
    4040       296175 :                               IF (is_constraint(iatom)) THEN
    4041              :                                  d_sum_const_dR(:, iatom) = d_sum_const_dR(:, iatom) + dP_i_dRi(:, iatom)* &
    4042      1184700 :                                                             coefficients(iatom)
    4043              :                               END IF
    4044       888525 :                               DO jatom = 1, natom
    4045       888525 :                                  IF (jatom /= iatom) THEN
    4046       296175 :                                     IF (jatom < iatom) THEN
    4047       148094 :                                        IF (.NOT. skip_me(jatom)) THEN
    4048       420184 :                                           dP_i_dRj(:, iatom, jatom) = cell_functions(iatom)*dP_i_dRj(:, iatom, jatom)
    4049       420184 :                                           d_sum_Pm_dR(:, jatom) = d_sum_Pm_dR(:, jatom) + dP_i_dRj(:, iatom, jatom)
    4050       105046 :                                           IF (is_constraint(iatom)) THEN
    4051              :                                              d_sum_const_dR(:, jatom) = d_sum_const_dR(:, jatom) + &
    4052              :                                                                         dP_i_dRj(:, iatom, jatom)* &
    4053       420184 :                                                                         coefficients(iatom)
    4054              :                                           END IF
    4055              :                                           CYCLE
    4056              :                                        END IF
    4057              :                                     END IF
    4058       764516 :                                     dP_i_dRj(:, iatom, jatom) = cell_functions(iatom)*dP_i_dRj(:, iatom, jatom)
    4059       764516 :                                     d_sum_Pm_dR(:, jatom) = d_sum_Pm_dR(:, jatom) + dP_i_dRj(:, iatom, jatom)
    4060       191129 :                                     IF (is_constraint(iatom)) THEN
    4061              :                                        d_sum_const_dR(:, jatom) = d_sum_const_dR(:, jatom) + dP_i_dRj(:, iatom, jatom)* &
    4062       764516 :                                                                   coefficients(iatom)
    4063              :                                     END IF
    4064              :                                  END IF
    4065              :                               END DO
    4066              :                            END IF
    4067              :                         ELSE
    4068      1402232 :                            cell_functions(iatom) = 0.0_dp
    4069      1402232 :                            skip_me(iatom) = .TRUE.
    4070      1402232 :                            IF (cdft_control%becke_control%should_skip) THEN
    4071       858928 :                               IF (is_constraint(iatom)) nskipped = nskipped + 1
    4072       858928 :                               IF (nskipped == cdft_control%natoms) THEN
    4073       410635 :                                  IF (in_memory) THEN
    4074       252800 :                                     IF (cdft_control%becke_control%cavity_confine) THEN
    4075       252800 :                                        cavity(k, j, i) = 0.0_dp
    4076              :                                     END IF
    4077              :                                  END IF
    4078              :                                  EXIT
    4079              :                               END IF
    4080              :                            END IF
    4081              :                         END IF
    4082              :                      END DO
    4083       988401 :                      IF (nskipped == cdft_control%natoms) CYCLE
    4084              :                      sum_cell_f_constr = 0.0_dp
    4085      1733298 :                      DO ip = 1, cdft_control%natoms
    4086              :                         sum_cell_f_constr = sum_cell_f_constr + cell_functions(catom(ip))* &
    4087      1733298 :                                             cdft_control%group(1)%coeff(ip)
    4088              :                      END DO
    4089       577766 :                      sum_cell_f_all = 0.0_dp
    4090       577766 :                      nwork = nwork + 1
    4091      1733298 :                      DO ip = 1, natom
    4092      1733298 :                         sum_cell_f_all = sum_cell_f_all + cell_functions(ip)
    4093              :                      END DO
    4094       577766 :                      IF (in_memory) THEN
    4095      1266948 :                         DO iatom = 1, natom
    4096      1266948 :                            IF (ABS(sum_cell_f_all) > 0.0_dp) THEN
    4097              :                               gradients(3*(iatom - 1) + 1:3*(iatom - 1) + 3, k, j, i) = &
    4098              :                                  d_sum_const_dR(:, iatom)/sum_cell_f_all - sum_cell_f_constr* &
    4099      1529032 :                                  d_sum_Pm_dR(:, iatom)/(sum_cell_f_all**2)
    4100              :                            END IF
    4101              :                         END DO
    4102              :                      END IF
    4103       616975 :                      IF (ABS(sum_cell_f_all) > eps_sum_cell_f_all) THEN
    4104       320062 :                         weight(k, j, i) = sum_cell_f_constr/sum_cell_f_all
    4105              :                      END IF
    4106              :                   END DO ! i
    4107              :                END DO ! j
    4108              :             END DO ! k
    4109              :             ! Load balancing: post send requests
    4110           80 :             IF (iwork == 2) THEN
    4111            4 :                IF (.NOT. mixed_cdft%is_special) THEN
    4112           12 :                   DO i = 1, SIZE(req_send, 1)
    4113              :                      CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%cavity, &
    4114              :                                                    dest=mixed_cdft%dlb_control%my_dest_repl(i), &
    4115              :                                                    request=req_send(i, 1), &
    4116            8 :                                                    tag=mixed_cdft%dlb_control%dest_tags_repl(i))
    4117              :                      CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%weight, &
    4118              :                                                    dest=mixed_cdft%dlb_control%my_dest_repl(i), &
    4119              :                                                    request=req_send(i, 2), &
    4120            8 :                                                    tag=mixed_cdft%dlb_control%dest_tags_repl(i) + 1)
    4121              :                      CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%gradients, &
    4122              :                                                    dest=mixed_cdft%dlb_control%my_dest_repl(i), &
    4123              :                                                    request=req_send(i, 3), &
    4124           12 :                                                    tag=mixed_cdft%dlb_control%dest_tags_repl(i) + 2)
    4125              :                   END DO
    4126              :                   should_communicate = .TRUE.
    4127              :                   nsent_total = 0
    4128              :                ELSE
    4129            0 :                   DO i = 1, SIZE(req_send, 1)
    4130              :                      CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%sendbuff(ispecial)%cavity, &
    4131              :                                                    dest=mixed_cdft%dlb_control%sendbuff(ispecial)%rank(i), &
    4132            0 :                                                    request=req_send(i, 3*(ispecial - 1) + 1), tag=1)
    4133              :                      CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%sendbuff(ispecial)%weight, &
    4134              :                                                    dest=mixed_cdft%dlb_control%sendbuff(ispecial)%rank(i), &
    4135            0 :                                                    request=req_send(i, 3*(ispecial - 1) + 2), tag=2)
    4136              :                      CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%sendbuff(ispecial)%gradients, &
    4137              :                                                    dest=mixed_cdft%dlb_control%sendbuff(ispecial)%rank(i), &
    4138            0 :                                                    request=req_send(i, 3*(ispecial - 1) + 3), tag=3)
    4139              :                   END DO
    4140            0 :                   IF (ispecial == my_special_work) THEN
    4141            0 :                      should_communicate = .TRUE.
    4142            0 :                      nsent_total = 0
    4143              :                   END IF
    4144              :                END IF
    4145            4 :                work(mixed_cdft%dlb_control%my_source + 1) = work(mixed_cdft%dlb_control%my_source + 1) + nwork
    4146            4 :                work_dlb(force_env%para_env%mepos + 1) = work_dlb(force_env%para_env%mepos + 1) + nwork
    4147              :             ELSE
    4148           36 :                IF (mixed_cdft%dlb) work(force_env%para_env%mepos + 1) = work(force_env%para_env%mepos + 1) + nwork
    4149           36 :                IF (mixed_cdft%dlb) work_dlb(force_env%para_env%mepos + 1) = work_dlb(force_env%para_env%mepos + 1) + nwork
    4150              :             END IF
    4151              :          END DO ! ispecial
    4152              :       END DO ! iwork
    4153              :       ! Load balancing: wait for communication and deallocate sending buffers
    4154           36 :       IF (mixed_cdft%dlb) THEN
    4155           16 :          IF (mixed_cdft%dlb_control%recv_work .AND. &
    4156              :              ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    4157           48 :             ALLOCATE (req_total(SIZE(req_recv) + SIZE(req_send, 1)*SIZE(req_send, 2)))
    4158            4 :             index = SIZE(req_recv)
    4159           28 :             req_total(1:index) = req_recv
    4160           16 :             DO i = 1, SIZE(req_send, 2)
    4161           40 :                DO j = 1, SIZE(req_send, 1)
    4162           24 :                   index = index + 1
    4163           36 :                   req_total(index) = req_send(j, i)
    4164              :                END DO
    4165              :             END DO
    4166            4 :             CALL mp_waitall(req_total)
    4167            4 :             DEALLOCATE (req_total)
    4168            4 :             IF (ASSOCIATED(mixed_cdft%dlb_control%cavity)) THEN
    4169            0 :                DEALLOCATE (mixed_cdft%dlb_control%cavity)
    4170              :             END IF
    4171            4 :             IF (ASSOCIATED(mixed_cdft%dlb_control%weight)) THEN
    4172            0 :                DEALLOCATE (mixed_cdft%dlb_control%weight)
    4173              :             END IF
    4174            4 :             IF (ASSOCIATED(mixed_cdft%dlb_control%gradients)) THEN
    4175            0 :                DEALLOCATE (mixed_cdft%dlb_control%gradients)
    4176              :             END IF
    4177            4 :             IF (mixed_cdft%is_special) THEN
    4178            0 :                DO j = 1, SIZE(mixed_cdft%dlb_control%sendbuff)
    4179            0 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%cavity)) THEN
    4180            0 :                      DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%cavity)
    4181              :                   END IF
    4182            0 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%weight)) THEN
    4183            0 :                      DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%weight)
    4184              :                   END IF
    4185            0 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%gradients)) THEN
    4186            0 :                      DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%gradients)
    4187              :                   END IF
    4188              :                END DO
    4189            0 :                DEALLOCATE (mixed_cdft%dlb_control%sendbuff)
    4190              :             END IF
    4191            4 :             DEALLOCATE (req_send, req_recv)
    4192            4 :          ELSE IF (mixed_cdft%dlb_control%recv_work) THEN
    4193            0 :             IF (should_communicate) THEN
    4194            0 :                CALL mp_waitall(req_send)
    4195              :             END IF
    4196            0 :             IF (ASSOCIATED(mixed_cdft%dlb_control%cavity)) THEN
    4197            0 :                DEALLOCATE (mixed_cdft%dlb_control%cavity)
    4198              :             END IF
    4199            0 :             IF (ASSOCIATED(mixed_cdft%dlb_control%weight)) THEN
    4200            0 :                DEALLOCATE (mixed_cdft%dlb_control%weight)
    4201              :             END IF
    4202            0 :             IF (ASSOCIATED(mixed_cdft%dlb_control%gradients)) THEN
    4203            0 :                DEALLOCATE (mixed_cdft%dlb_control%gradients)
    4204              :             END IF
    4205            0 :             IF (mixed_cdft%is_special) THEN
    4206            0 :                DO j = 1, SIZE(mixed_cdft%dlb_control%sendbuff)
    4207            0 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%cavity)) THEN
    4208            0 :                      DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%cavity)
    4209              :                   END IF
    4210            0 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%weight)) THEN
    4211            0 :                      DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%weight)
    4212              :                   END IF
    4213            0 :                   IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%gradients)) THEN
    4214            0 :                      DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%gradients)
    4215              :                   END IF
    4216              :                END DO
    4217            0 :                DEALLOCATE (mixed_cdft%dlb_control%sendbuff)
    4218              :             END IF
    4219            0 :             DEALLOCATE (req_send)
    4220            8 :          ELSE IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
    4221            4 :             CALL mp_waitall(req_recv)
    4222            4 :             DEALLOCATE (req_recv)
    4223              :          END IF
    4224              :       END IF
    4225           36 :       IF (mixed_cdft%dlb) THEN
    4226           40 :          CALL force_env%para_env%sum(work)
    4227           40 :          CALL force_env%para_env%sum(work_dlb)
    4228            8 :          IF (.NOT. ASSOCIATED(mixed_cdft%dlb_control%prediction_error)) THEN
    4229           12 :             ALLOCATE (mixed_cdft%dlb_control%prediction_error(force_env%para_env%num_pe))
    4230              :          END IF
    4231           40 :          mixed_cdft%dlb_control%prediction_error = mixed_cdft%dlb_control%expected_work - work
    4232              :          IF (debug_this_module .AND. iounit > 0) THEN
    4233              :             DO i = 1, SIZE(work, 1)
    4234              :                WRITE (iounit, '(A,I10,I10,I10)') &
    4235              :                   'Work', work(i), work_dlb(i), mixed_cdft%dlb_control%expected_work(i)
    4236              :             END DO
    4237              :          END IF
    4238            8 :          DEALLOCATE (work, work_dlb, mixed_cdft%dlb_control%expected_work)
    4239              :       END IF
    4240           36 :       NULLIFY (gradients, weight, cavity)
    4241           36 :       IF (ALLOCATED(coefficients)) THEN
    4242           36 :          DEALLOCATE (coefficients)
    4243              :       END IF
    4244           36 :       IF (in_memory) THEN
    4245           24 :          DEALLOCATE (ds_dR_j)
    4246           24 :          DEALLOCATE (ds_dR_i)
    4247           24 :          DEALLOCATE (d_sum_Pm_dR)
    4248           24 :          DEALLOCATE (d_sum_const_dR)
    4249           24 :          DEALLOCATE (dP_i_dRj)
    4250           24 :          DEALLOCATE (dP_i_dRi)
    4251           24 :          NULLIFY (gradients)
    4252           24 :          IF (store_vectors) THEN
    4253           24 :             DEALLOCATE (pair_dist_vecs)
    4254              :          END IF
    4255              :       END IF
    4256           36 :       NULLIFY (cutoffs)
    4257           36 :       IF (ALLOCATED(is_constraint)) THEN
    4258           36 :          DEALLOCATE (is_constraint)
    4259              :       END IF
    4260           36 :       DEALLOCATE (catom)
    4261           36 :       DEALLOCATE (R12)
    4262           36 :       DEALLOCATE (cell_functions)
    4263           36 :       DEALLOCATE (skip_me)
    4264           36 :       IF (ALLOCATED(completed)) THEN
    4265            4 :          DEALLOCATE (completed)
    4266              :       END IF
    4267           36 :       IF (ASSOCIATED(nsent)) THEN
    4268            4 :          DEALLOCATE (nsent)
    4269              :       END IF
    4270           36 :       IF (store_vectors) THEN
    4271           36 :          DEALLOCATE (distances)
    4272           36 :          DEALLOCATE (distance_vecs)
    4273           36 :          DEALLOCATE (position_vecs)
    4274              :       END IF
    4275           36 :       IF (ASSOCIATED(req_send)) THEN
    4276            0 :          DEALLOCATE (req_send)
    4277              :       END IF
    4278           36 :       IF (ASSOCIATED(req_recv)) THEN
    4279            0 :          DEALLOCATE (req_recv)
    4280              :       END IF
    4281              :       CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
    4282           36 :                                         "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
    4283           36 :       CALL timestop(handle)
    4284              : 
    4285           72 :    END SUBROUTINE mixed_becke_constraint_low
    4286              : 
    4287            0 : END MODULE mixed_cdft_methods
        

Generated by: LCOV version 2.0-1