LCOV - code coverage report
Current view: top level - src - optimize_basis_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 81.5 % 536 437
Test Date: 2026-09-03 07:32:15 Functions: 95.5 % 22 21

            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              : MODULE optimize_basis_utils
       8              :    USE cp_files,                        ONLY: close_file,&
       9              :                                               open_file
      10              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      11              :                                               cp_logger_get_default_unit_nr,&
      12              :                                               cp_logger_type,&
      13              :                                               cp_to_string
      14              :    USE cp_parser_methods,               ONLY: parser_get_object,&
      15              :                                               parser_search_string
      16              :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      17              :                                               parser_create,&
      18              :                                               parser_release
      19              :    USE input_constants,                 ONLY: do_opt_all,&
      20              :                                               do_opt_coeff,&
      21              :                                               do_opt_exps,&
      22              :                                               do_opt_none
      23              :    USE input_section_types,             ONLY: section_vals_get,&
      24              :                                               section_vals_get_subs_vals,&
      25              :                                               section_vals_type,&
      26              :                                               section_vals_val_get
      27              :    USE kinds,                           ONLY: default_path_length,&
      28              :                                               default_string_length,&
      29              :                                               dp
      30              :    USE machine,                         ONLY: default_output_unit,&
      31              :                                               m_getcwd
      32              :    USE message_passing,                 ONLY: mp_para_env_type
      33              :    USE optimize_basis_types,            ONLY: basis_optimization_type,&
      34              :                                               derived_basis_info,&
      35              :                                               flex_basis_type,&
      36              :                                               method_mo_fit_occ,&
      37              :                                               method_mo_fit_occ_virtual,&
      38              :                                               subset_type
      39              :    USE powell,                          ONLY: opt_state_type
      40              :    USE string_utilities,                ONLY: uppercase
      41              : #include "./base/base_uses.f90"
      42              : 
      43              :    IMPLICIT NONE
      44              :    PRIVATE
      45              : 
      46              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'optimize_basis_utils'
      47              : 
      48              :    PUBLIC :: optimize_basis_init_read_input, get_set_and_basis_id, &
      49              :              update_derived_basis_sets, write_basis
      50              : 
      51              : CONTAINS
      52              : 
      53              : ! **************************************************************************************************
      54              : !> \brief initialize all parts of the optimization type and read input settings
      55              : !> \param opt_bas ...
      56              : !> \param root_section ...
      57              : !> \param para_env ...
      58              : !> \param quiet_output ...
      59              : !> \param embedded_training ...
      60              : !> \author Florian Schiffmann
      61              : ! **************************************************************************************************
      62              : 
      63            8 :    SUBROUTINE optimize_basis_init_read_input(opt_bas, root_section, para_env, quiet_output, embedded_training)
      64              :       TYPE(basis_optimization_type)                      :: opt_bas
      65              :       TYPE(section_vals_type), POINTER                   :: root_section
      66              :       TYPE(mp_para_env_type), POINTER                    :: para_env
      67              :       LOGICAL, INTENT(IN), OPTIONAL                      :: quiet_output, embedded_training
      68              : 
      69              :       CHARACTER(LEN=default_path_length)                 :: main_dir
      70              :       INTEGER                                            :: ikind, iset, iweight, nrep
      71              :       LOGICAL                                            :: frontier_orbitals_explicit, &
      72              :                                                             use_embedded_training
      73              :       TYPE(section_vals_type), POINTER                   :: frontier_orbitals_section, kind_section, &
      74              :                                                             optbas_section, powell_section, &
      75              :                                                             train_section
      76              : 
      77            8 :       optbas_section => section_vals_get_subs_vals(root_section, "OPTIMIZE_BASIS")
      78            8 :       powell_section => section_vals_get_subs_vals(optbas_section, "OPTIMIZATION")
      79            8 :       train_section => section_vals_get_subs_vals(optbas_section, "TRAINING_FILES")
      80            8 :       kind_section => section_vals_get_subs_vals(optbas_section, "FIT_KIND")
      81            8 :       frontier_orbitals_section => section_vals_get_subs_vals(optbas_section, "FRONTIER_ORBITALS")
      82              : 
      83            8 :       IF (PRESENT(quiet_output)) opt_bas%quiet_output = quiet_output
      84            8 :       use_embedded_training = .FALSE.
      85            8 :       IF (PRESENT(embedded_training)) use_embedded_training = embedded_training
      86              : 
      87            8 :       CALL section_vals_val_get(optbas_section, "BASIS_TEMPLATE_FILE", c_val=opt_bas%template_basis_file)
      88            8 :       CALL section_vals_val_get(optbas_section, "BASIS_OUTPUT_FILE", c_val=opt_bas%output_basis_file)
      89            8 :       CALL m_getcwd(main_dir)
      90              : 
      91            8 :       CALL section_vals_val_get(optbas_section, "WRITE_FREQUENCY", i_val=opt_bas%write_frequency)
      92            8 :       CALL section_vals_val_get(optbas_section, "USE_CONDITION_NUMBER", l_val=opt_bas%use_condition_number)
      93              : 
      94            8 :       CALL generate_initial_basis(kind_section, opt_bas, para_env)
      95              : 
      96            8 :       CALL section_vals_get(frontier_orbitals_section, explicit=frontier_orbitals_explicit)
      97            8 :       IF (use_embedded_training) THEN
      98            2 :          opt_bas%method = method_mo_fit_occ_virtual
      99            6 :       ELSE IF (frontier_orbitals_explicit) THEN
     100            2 :          opt_bas%method = method_mo_fit_occ_virtual
     101              :          CALL section_vals_val_get(frontier_orbitals_section, "OCCUPIED_WEIGHT", &
     102            2 :                                    r_val=opt_bas%occupied_weight)
     103              :          CALL section_vals_val_get(frontier_orbitals_section, "VIRTUAL_WEIGHT", &
     104            2 :                                    r_val=opt_bas%virtual_weight)
     105              :          CALL section_vals_val_get(frontier_orbitals_section, "EMPTY_OVERLAP_WEIGHT", &
     106            2 :                                    r_val=opt_bas%empty_overlap_weight)
     107              :          CALL section_vals_val_get(frontier_orbitals_section, "GAP_WEIGHT", &
     108            2 :                                    r_val=opt_bas%gap_weight)
     109              :          CALL section_vals_val_get(frontier_orbitals_section, "COEFFICIENT_WEIGHT", &
     110            2 :                                    r_val=opt_bas%coefficient_weight)
     111              :          CALL section_vals_val_get(frontier_orbitals_section, "GAP_ENERGY_SCALE", &
     112            2 :                                    r_val=opt_bas%gap_energy_scale)
     113              :          CALL section_vals_val_get(frontier_orbitals_section, "VIRTUAL_ENERGY_CUTOFF", &
     114            2 :                                    r_val=opt_bas%virtual_energy_cutoff)
     115              :          CALL section_vals_val_get(frontier_orbitals_section, "VIRTUAL_ENERGY_SMOOTHING", &
     116            2 :                                    r_val=opt_bas%virtual_energy_smoothing)
     117              :       END IF
     118            8 :       IF (opt_bas%method == method_mo_fit_occ) THEN
     119            4 :          CALL section_vals_val_get(optbas_section, "BASIS_WORK_FILE", c_val=opt_bas%work_basis_file)
     120            4 :          opt_bas%work_basis_file = TRIM(ADJUSTL(main_dir))//"/"//TRIM(ADJUSTL(opt_bas%work_basis_file))
     121              :       END IF
     122            8 :       IF (frontier_orbitals_explicit) THEN
     123            2 :          IF (opt_bas%gap_energy_scale <= 0.0_dp) CPABORT("GAP_ENERGY_SCALE must be positive")
     124            2 :          IF (opt_bas%virtual_energy_smoothing <= 0.0_dp) THEN
     125            0 :             CPABORT("VIRTUAL_ENERGY_SMOOTHING must be positive")
     126              :          END IF
     127            2 :          IF (MIN(opt_bas%occupied_weight, opt_bas%virtual_weight, &
     128              :                  opt_bas%empty_overlap_weight, opt_bas%gap_weight, &
     129              :                  opt_bas%coefficient_weight) < 0.0_dp) THEN
     130            0 :             CPABORT("FRONTIER_ORBITALS weights must be non-negative")
     131              :          END IF
     132              :       END IF
     133            8 :       IF (opt_bas%method == method_mo_fit_occ_virtual) THEN
     134           12 :          DO ikind = 1, opt_bas%nkind
     135           20 :             DO iset = 1, opt_bas%kind_basis(ikind)%flex_basis(0)%nsets
     136           68 :                IF (ANY(opt_bas%kind_basis(ikind)%flex_basis(0)%subset(iset)%opt_exps)) THEN
     137            0 :                   CPABORT("FRONTIER_ORBITALS requires fixed Gaussian exponents")
     138              :                END IF
     139              :             END DO
     140              :          END DO
     141              :       END IF
     142              : 
     143            8 :       CALL section_vals_get(train_section, n_repetition=opt_bas%ntraining_sets)
     144            8 :       IF (use_embedded_training) THEN
     145            2 :          IF (opt_bas%ntraining_sets /= 0) THEN
     146              :             CALL cp_abort(__LOCATION__, &
     147              :                           "TRAINING_FILES is not allowed together with FRONTIER_ORBITAL_SCREENING "// &
     148            0 :                           "because it is overwritten automatically")
     149              :          END IF
     150            2 :          opt_bas%ntraining_sets = 1
     151            6 :       ELSE IF (opt_bas%ntraining_sets == 0) THEN
     152            0 :          CPABORT("No training set was specified in the Input")
     153              :       END IF
     154              : 
     155           24 :       ALLOCATE (opt_bas%training_input(opt_bas%ntraining_sets))
     156           16 :       ALLOCATE (opt_bas%training_dir(opt_bas%ntraining_sets))
     157            8 :       IF (use_embedded_training) THEN
     158            2 :          opt_bas%training_input(1) = ""
     159            2 :          opt_bas%training_dir(1) = "."
     160              :       ELSE
     161           14 :          DO iset = 1, opt_bas%ntraining_sets
     162              :             CALL section_vals_val_get(train_section, "DIRECTORY", c_val=opt_bas%training_dir(iset), &
     163            8 :                                       i_rep_section=iset)
     164              :             CALL section_vals_val_get(train_section, "INPUT_FILE_NAME", c_val=opt_bas%training_input(iset), &
     165           14 :                                       i_rep_section=iset)
     166              :          END DO
     167              :       END IF
     168              : 
     169            8 :       CALL init_powell_var(opt_bas%powell_param, powell_section)
     170            8 :       opt_bas%powell_param%nvar = SIZE(opt_bas%x_opt)
     171              : 
     172              :       CALL generate_derived_basis_sets( &
     173            8 :          opt_bas, para_env, write_work_file=opt_bas%method == method_mo_fit_occ)
     174              : 
     175            8 :       CALL generate_basis_combinations(opt_bas, optbas_section)
     176              : 
     177            8 :       CALL section_vals_val_get(optbas_section, "RESIDUUM_WEIGHT", n_rep_val=nrep)
     178           24 :       ALLOCATE (opt_bas%fval_weight(0:opt_bas%ncombinations))
     179           32 :       opt_bas%fval_weight = 1.0_dp
     180           24 :       DO iweight = 1, nrep
     181              :          CALL section_vals_val_get(optbas_section, "RESIDUUM_WEIGHT", r_val=opt_bas%fval_weight(iweight - 1), &
     182           24 :                                    i_rep_val=iweight)
     183              :       END DO
     184              : 
     185            8 :       CALL section_vals_val_get(optbas_section, "CONDITION_WEIGHT", n_rep_val=nrep)
     186           24 :       ALLOCATE (opt_bas%condition_weight(0:opt_bas%ncombinations))
     187           32 :       opt_bas%condition_weight = 1.0_dp
     188           24 :       DO iweight = 1, nrep
     189              :          CALL section_vals_val_get(optbas_section, "CONDITION_WEIGHT", r_val=opt_bas%condition_weight(iweight - 1), &
     190           24 :                                    i_rep_val=iweight)
     191              :       END DO
     192              : 
     193            8 :       CALL generate_computation_groups(opt_bas, optbas_section, para_env)
     194              : 
     195            8 :       IF (.NOT. opt_bas%quiet_output) CALL print_opt_info(opt_bas)
     196              : 
     197           24 :    END SUBROUTINE optimize_basis_init_read_input
     198              : 
     199              : ! **************************************************************************************************
     200              : !> \brief ...
     201              : !> \param opt_bas ...
     202              : ! **************************************************************************************************
     203            6 :    SUBROUTINE print_opt_info(opt_bas)
     204              :       TYPE(basis_optimization_type)                      :: opt_bas
     205              : 
     206              :       INTEGER                                            :: icomb, ikind, unit_nr
     207              :       TYPE(cp_logger_type), POINTER                      :: logger
     208              : 
     209            6 :       logger => cp_get_default_logger()
     210            6 :       unit_nr = -1
     211            6 :       IF (logger%para_env%is_source()) THEN
     212            3 :          unit_nr = cp_logger_get_default_unit_nr(logger)
     213              :       END IF
     214              : 
     215            3 :       IF (unit_nr > 0) THEN
     216            3 :          WRITE (unit_nr, '(1X,A,A)') "BASOPT| Total number of calculations ", &
     217            6 :             TRIM(cp_to_string(opt_bas%ncombinations*opt_bas%ntraining_sets))
     218            3 :          WRITE (unit_nr, '(A)') ""
     219           10 :          DO icomb = 1, opt_bas%ncombinations
     220            7 :             WRITE (unit_nr, '(1X,A,A)') "BASOPT| Content of basis combination ", TRIM(cp_to_string(icomb))
     221           21 :             DO ikind = 1, opt_bas%nkind
     222           14 :                WRITE (unit_nr, '(1X,A,A4,4X,A,3X,A)') "BASOPT|     Element: ", TRIM(opt_bas%kind_basis(ikind)%element), &
     223           35 :                   "Basis set: ", TRIM(opt_bas%kind_basis(ikind)%flex_basis(opt_bas%combination(icomb, ikind))%basis_name)
     224              :             END DO
     225           10 :             WRITE (unit_nr, '(A)') ""
     226              :          END DO
     227              :       END IF
     228            6 :    END SUBROUTINE print_opt_info
     229              : 
     230              : ! **************************************************************************************************
     231              : !> \brief Generation of the requested basis set combinations if multiple kinds
     232              : !>        are fitted at the same time (if not specified create all possible)
     233              : !> \param opt_bas ...
     234              : !> \param optbas_section ...
     235              : !> \author Florian Schiffmann
     236              : ! **************************************************************************************************
     237            8 :    SUBROUTINE generate_basis_combinations(opt_bas, optbas_section)
     238              :       TYPE(basis_optimization_type)                      :: opt_bas
     239              :       TYPE(section_vals_type), POINTER                   :: optbas_section
     240              : 
     241              :       INTEGER                                            :: i, ikind, j, n_rep
     242            8 :       INTEGER, DIMENSION(:), POINTER                     :: i_vals, tmp_i, tmp_i2
     243              :       LOGICAL                                            :: explicit, raise
     244              : 
     245              : !setup the basis combinations to optimize
     246              : 
     247            8 :       CALL section_vals_val_get(optbas_section, "BASIS_COMBINATIONS", explicit=explicit, n_rep_val=n_rep)
     248            8 :       IF (.NOT. explicit) THEN
     249            4 :          opt_bas%ncombinations = 1
     250           12 :          ALLOCATE (tmp_i(opt_bas%nkind))
     251            8 :          ALLOCATE (tmp_i2(opt_bas%nkind))
     252           12 :          DO ikind = 1, opt_bas%nkind
     253            8 :             opt_bas%ncombinations = opt_bas%ncombinations*SIZE(opt_bas%kind_basis(ikind)%flex_basis)
     254           12 :             tmp_i(ikind) = opt_bas%kind_basis(ikind)%nbasis_deriv
     255              :          END DO
     256           16 :          ALLOCATE (opt_bas%combination(opt_bas%ncombinations, opt_bas%nkind))
     257           12 :          tmp_i2 = 0
     258            8 :          DO i = 1, opt_bas%ncombinations
     259           12 :             DO j = 1, opt_bas%nkind
     260           12 :                opt_bas%combination(i, j) = tmp_i2(j)
     261              :             END DO
     262            4 :             tmp_i2(opt_bas%nkind) = tmp_i2(opt_bas%nkind) + 1
     263            4 :             raise = .FALSE.
     264           16 :             DO j = opt_bas%nkind, 1, -1
     265            8 :                IF (raise) tmp_i2(j) = tmp_i2(j) + 1
     266           12 :                IF (tmp_i2(j) > tmp_i(j)) THEN
     267            8 :                   tmp_i2(j) = 0
     268            8 :                   raise = .TRUE.
     269              :                END IF
     270              :             END DO
     271              :          END DO
     272            4 :          DEALLOCATE (tmp_i)
     273            4 :          DEALLOCATE (tmp_i2)
     274              :       ELSE
     275            4 :          opt_bas%ncombinations = n_rep
     276           16 :          ALLOCATE (opt_bas%combination(opt_bas%ncombinations, opt_bas%nkind))
     277           16 :          DO i = 1, n_rep
     278           12 :             CALL section_vals_val_get(optbas_section, "BASIS_COMBINATIONS", i_vals=i_vals, i_rep_val=i)
     279           40 :             opt_bas%combination(i, :) = i_vals(:)
     280              :          END DO
     281              :       END IF
     282              : 
     283            8 :    END SUBROUTINE generate_basis_combinations
     284              : 
     285              : ! **************************************************************************************************
     286              : !> \brief returns a mapping from the calculation id to the trainings set id and
     287              : !>        basis combination id
     288              : !> \param calc_id ...
     289              : !> \param opt_bas ...
     290              : !> \param set_id ...
     291              : !> \param bas_id ...
     292              : !> \author Florian Schiffmann
     293              : ! **************************************************************************************************
     294              : 
     295          656 :    SUBROUTINE get_set_and_basis_id(calc_id, opt_bas, set_id, bas_id)
     296              : 
     297              :       INTEGER                                            :: calc_id
     298              :       TYPE(basis_optimization_type)                      :: opt_bas
     299              :       INTEGER                                            :: set_id, bas_id
     300              : 
     301              :       INTEGER                                            :: ncom, nset
     302              : 
     303          656 :       ncom = opt_bas%ncombinations
     304          656 :       nset = opt_bas%ntraining_sets
     305              : 
     306          656 :       set_id = (calc_id)/ncom + 1
     307          656 :       bas_id = MOD(calc_id, ncom) + 1
     308              : 
     309          656 :    END SUBROUTINE get_set_and_basis_id
     310              : 
     311              : ! **************************************************************************************************
     312              : !> \brief Pack calculations in groups. If less MPI tasks than systems are used
     313              : !>        multiple systems will be assigned to a single MPI task
     314              : !> \param opt_bas ...
     315              : !> \param optbas_section ...
     316              : !> \param para_env ...
     317              : !> \author Florian Schiffmann
     318              : ! **************************************************************************************************
     319              : 
     320            8 :    SUBROUTINE generate_computation_groups(opt_bas, optbas_section, para_env)
     321              :       TYPE(basis_optimization_type)                      :: opt_bas
     322              :       TYPE(section_vals_type), POINTER                   :: optbas_section
     323              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     324              : 
     325              :       INTEGER                                            :: iadd1, iadd2, icount, igroup, isize, j, &
     326              :                                                             ncalc, nproc, nptot
     327            8 :       INTEGER, DIMENSION(:), POINTER                     :: i_vals
     328              :       LOGICAL                                            :: explicit
     329              : 
     330            8 :       nproc = para_env%num_pe
     331            8 :       ncalc = opt_bas%ncombinations*opt_bas%ntraining_sets
     332            8 :       CALL section_vals_val_get(optbas_section, "GROUP_PARTITION", explicit=explicit)
     333              : 
     334              :       ! No input information available, try to equally distribute
     335            8 :       IF (.NOT. explicit) THEN
     336            8 :          IF (nproc >= ncalc) THEN
     337            4 :             iadd1 = nproc/ncalc
     338            4 :             iadd2 = MOD(nproc, ncalc)
     339           16 :             ALLOCATE (opt_bas%comp_group(ncalc))
     340           12 :             ALLOCATE (opt_bas%group_partition(0:ncalc - 1))
     341            8 :             DO igroup = 0, ncalc - 1
     342            4 :                ALLOCATE (opt_bas%comp_group(igroup + 1)%member_list(1))
     343            4 :                opt_bas%comp_group(igroup + 1)%member_list(1) = igroup
     344            4 :                opt_bas%group_partition(igroup) = iadd1
     345            8 :                IF (igroup < iadd2) opt_bas%group_partition(igroup) = opt_bas%group_partition(igroup) + 1
     346              :             END DO
     347              :          ELSE
     348            4 :             iadd1 = ncalc/nproc
     349            4 :             iadd2 = MOD(ncalc, nproc)
     350           20 :             ALLOCATE (opt_bas%comp_group(nproc))
     351           12 :             ALLOCATE (opt_bas%group_partition(0:nproc - 1))
     352            4 :             icount = 0
     353           12 :             DO igroup = 0, nproc - 1
     354            8 :                opt_bas%group_partition(igroup) = 1
     355            8 :                isize = iadd1
     356            8 :                IF (igroup < iadd2) isize = isize + 1
     357           24 :                ALLOCATE (opt_bas%comp_group(igroup + 1)%member_list(isize))
     358           30 :                DO j = 1, isize
     359           18 :                   opt_bas%comp_group(igroup + 1)%member_list(j) = icount
     360           26 :                   icount = icount + 1
     361              :                END DO
     362              :             END DO
     363              :          END IF
     364              :       ELSE
     365              : 
     366              :          ! Group partition from input. see if all systems can be assigned. If not add to existing group
     367            0 :          CALL section_vals_val_get(optbas_section, "GROUP_PARTITION", i_vals=i_vals)
     368            0 :          isize = SIZE(i_vals)
     369            0 :          nptot = SUM(i_vals)
     370            0 :          IF (nptot /= nproc) THEN
     371              :             CALL cp_abort(__LOCATION__, &
     372              :                           "Number of processors in group distribution does not match number of MPI tasks."// &
     373            0 :                           " Please change input.")
     374              :          END IF
     375            0 :          IF (.NOT. isize <= ncalc) THEN
     376              :             CALL cp_abort(__LOCATION__, &
     377              :                           "Number of Groups larger than number of calculations"// &
     378            0 :                           " Please change input.")
     379              :          END IF
     380            0 :          CPASSERT(nptot == nproc)
     381            0 :          ALLOCATE (opt_bas%comp_group(isize))
     382            0 :          ALLOCATE (opt_bas%group_partition(0:isize - 1))
     383            0 :          IF (isize < ncalc) THEN
     384            0 :             iadd1 = ncalc/isize
     385            0 :             iadd2 = MOD(ncalc, isize)
     386            0 :             icount = 0
     387            0 :             DO igroup = 0, isize - 1
     388            0 :                opt_bas%group_partition(igroup) = i_vals(igroup + 1)
     389            0 :                isize = iadd1
     390            0 :                IF (igroup < iadd2) isize = isize + 1
     391            0 :                ALLOCATE (opt_bas%comp_group(igroup + 1)%member_list(isize))
     392            0 :                DO j = 1, isize
     393            0 :                   opt_bas%comp_group(igroup + 1)%member_list(j) = icount
     394            0 :                   icount = icount + 1
     395              :                END DO
     396              :             END DO
     397              :          ELSE
     398            0 :             DO igroup = 0, isize - 1
     399            0 :                opt_bas%group_partition(igroup) = i_vals(igroup + 1)
     400            0 :                ALLOCATE (opt_bas%comp_group(igroup + 1)%member_list(1))
     401            0 :                opt_bas%comp_group(igroup + 1)%member_list(1) = igroup
     402              :             END DO
     403              :          END IF
     404              :       END IF
     405              : 
     406            8 :    END SUBROUTINE generate_computation_groups
     407              : 
     408              : ! **************************************************************************************************
     409              : !> \brief Regenerate the basis sets from reference 0 after an update from the
     410              : !>        optimizer to reference was performed, and print basis file if required
     411              : !> \param opt_bas ...
     412              : !> \param write_it ...
     413              : !> \param output_file ...
     414              : !> \param para_env ...
     415              : !> \author Florian Schiffmann
     416              : ! **************************************************************************************************
     417          526 :    SUBROUTINE update_derived_basis_sets(opt_bas, write_it, output_file, para_env)
     418              :       TYPE(basis_optimization_type)                      :: opt_bas
     419              :       LOGICAL                                            :: write_it
     420              :       CHARACTER(LEN=default_path_length)                 :: output_file
     421              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     422              : 
     423              :       INTEGER                                            :: ibasis, ikind, unit_nr
     424              : 
     425         1578 :       DO ikind = 1, opt_bas%nkind
     426         2050 :          DO ibasis = 1, opt_bas%kind_basis(ikind)%nbasis_deriv
     427              :             CALL update_used_parts(opt_bas%kind_basis(ikind)%deriv_info(ibasis), &
     428              :                                    opt_bas%kind_basis(ikind)%flex_basis(0), &
     429         1524 :                                    opt_bas%kind_basis(ikind)%flex_basis(ibasis))
     430              :          END DO
     431              :       END DO
     432              : 
     433          526 :       IF (write_it) THEN
     434           14 :          IF (para_env%is_source()) THEN
     435              :             CALL open_file(file_name=output_file, file_status="UNKNOWN", &
     436            7 :                            file_action="WRITE", unit_number=unit_nr)
     437              :          ELSE
     438            7 :             unit_nr = -999
     439              :          END IF
     440           42 :          DO ikind = 1, opt_bas%nkind
     441          118 :             DO ibasis = 0, opt_bas%kind_basis(ikind)%nbasis_deriv
     442              :                CALL write_basis(opt_bas%kind_basis(ikind)%flex_basis(ibasis), opt_bas%kind_basis(ikind)%element, &
     443          104 :                                 unit_nr)
     444              :             END DO
     445              :          END DO
     446           14 :          IF (para_env%is_source()) CALL close_file(unit_number=unit_nr)
     447              :       END IF
     448              : 
     449          526 :    END SUBROUTINE update_derived_basis_sets
     450              : 
     451              : ! **************************************************************************************************
     452              : !> \brief Update the the information in a given basis set
     453              : !> \param info_new ...
     454              : !> \param basis ...
     455              : !> \param basis_new ...
     456              : !> \author Florian Schiffmann
     457              : ! **************************************************************************************************
     458              : 
     459          472 :    SUBROUTINE update_used_parts(info_new, basis, basis_new)
     460              :       TYPE(derived_basis_info)                           :: info_new
     461              :       TYPE(flex_basis_type)                              :: basis, basis_new
     462              : 
     463              :       INTEGER                                            :: icont, iset, jcont, jset
     464              : 
     465          472 :       jset = 0
     466          944 :       DO iset = 1, basis%nsets
     467          944 :          IF (info_new%in_use_set(iset)) THEN
     468          472 :             jset = jset + 1
     469         3776 :             basis_new%subset(jset)%exps(:) = basis%subset(iset)%exps
     470          472 :             jcont = 0
     471         3068 :             DO icont = 1, basis%subset(iset)%ncon_tot
     472         3068 :                IF (info_new%use_contr(iset)%in_use(icont)) THEN
     473         1298 :                   jcont = jcont + 1
     474        10384 :                   basis_new%subset(jset)%coeff(:, jcont) = basis%subset(iset)%coeff(:, icont)
     475              :                END IF
     476              :             END DO
     477              :          END IF
     478              :       END DO
     479              : 
     480          472 :    END SUBROUTINE update_used_parts
     481              : 
     482              : ! **************************************************************************************************
     483              : !> \brief Initial generation of the basis set from the file and DERIVED_SET
     484              : !> \param opt_bas ...
     485              : !> \param para_env ...
     486              : !> \param write_work_file ...
     487              : !> \author Florian Schiffmann
     488              : ! **************************************************************************************************
     489              : 
     490            8 :    SUBROUTINE generate_derived_basis_sets(opt_bas, para_env, write_work_file)
     491              :       TYPE(basis_optimization_type)                      :: opt_bas
     492              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     493              :       LOGICAL, INTENT(IN)                                :: write_work_file
     494              : 
     495              :       INTEGER                                            :: ibasis, ikind, iref, jbasis, unit_nr
     496              : 
     497           24 :       DO ikind = 1, opt_bas%nkind
     498           16 :          CALL init_deriv_info_ref(opt_bas%kind_basis(ikind)%deriv_info(0), opt_bas%kind_basis(ikind)%flex_basis(0))
     499           16 :          opt_bas%kind_basis(ikind)%deriv_info(0)%basis_name = TRIM(ADJUSTL(opt_bas%kind_basis(ikind)%basis_name))
     500              :          ! initialize the reference set used as template for the rest
     501           40 :          DO ibasis = 1, opt_bas%kind_basis(ikind)%nbasis_deriv
     502           16 :             iref = opt_bas%kind_basis(ikind)%deriv_info(ibasis)%reference_set
     503           80 :             DO jbasis = 0, opt_bas%kind_basis(ikind)%nbasis_deriv
     504           48 :                IF (iref == jbasis) CALL setup_used_parts_init_basis(opt_bas%kind_basis(ikind)%deriv_info(ibasis), &
     505              :                                                                     opt_bas%kind_basis(ikind)%deriv_info(iref), &
     506              :                                                                     opt_bas%kind_basis(ikind)%flex_basis(0), &
     507           32 :                                                                     opt_bas%kind_basis(ikind)%flex_basis(ibasis))
     508              :             END DO
     509              :          END DO
     510              :       END DO
     511              : 
     512            8 :       IF (write_work_file .AND. para_env%is_source()) THEN
     513              :          CALL open_file(file_name=opt_bas%work_basis_file, file_status="UNKNOWN", &
     514            2 :                         file_action="WRITE", unit_number=unit_nr)
     515              :       ELSE
     516            6 :          unit_nr = -999
     517              :       END IF
     518           24 :       DO ikind = 1, opt_bas%nkind
     519           56 :          DO ibasis = 0, opt_bas%kind_basis(ikind)%nbasis_deriv
     520           32 :             IF (LEN_TRIM(opt_bas%kind_basis(ikind)%deriv_info(ibasis)%basis_name) > 0) THEN
     521              :                opt_bas%kind_basis(ikind)%flex_basis(ibasis)%basis_name = &
     522           24 :                   TRIM(ADJUSTL(opt_bas%kind_basis(ikind)%deriv_info(ibasis)%basis_name))
     523              :             ELSE
     524              :                opt_bas%kind_basis(ikind)%flex_basis(ibasis)%basis_name = &
     525            8 :                   TRIM(ADJUSTL(opt_bas%kind_basis(ikind)%basis_name))//"-DERIVED_SET-"//ADJUSTL(cp_to_string(ibasis))
     526              :             END IF
     527           48 :             IF (write_work_file) THEN
     528              :                CALL write_basis(opt_bas%kind_basis(ikind)%flex_basis(ibasis), &
     529           24 :                                 opt_bas%kind_basis(ikind)%element, unit_nr)
     530              :             END IF
     531              :          END DO
     532              :       END DO
     533            8 :       IF (write_work_file .AND. para_env%is_source()) CALL close_file(unit_number=unit_nr)
     534              : 
     535            8 :    END SUBROUTINE generate_derived_basis_sets
     536              : 
     537              : ! **************************************************************************************************
     538              : !> \brief Write a basis set file which can be used from CP2K
     539              : !> \param basis ...
     540              : !> \param element ...
     541              : !> \param unit_nr ...
     542              : !> \author Florian Schiffmann
     543              : ! **************************************************************************************************
     544              : 
     545          104 :    SUBROUTINE write_basis(basis, element, unit_nr)
     546              :       TYPE(flex_basis_type)                              :: basis
     547              :       CHARACTER(LEN=default_string_length)               :: element
     548              :       INTEGER                                            :: unit_nr
     549              : 
     550              :       INTEGER                                            :: iexp, iset
     551              : 
     552          104 :       IF (unit_nr > 0) THEN
     553           52 :          WRITE (UNIT=unit_nr, FMT="(A)") TRIM(ADJUSTL(element))//" "//TRIM(ADJUSTL(basis%basis_name))
     554           52 :          WRITE (UNIT=unit_nr, FMT="(1X,I0)") basis%nsets
     555          104 :          DO iset = 1, basis%nsets
     556           52 :             WRITE (UNIT=unit_nr, FMT="(30(1X,I0))") basis%subset(iset)%n, basis%subset(iset)%lmin, basis%subset(iset)%lmax, &
     557          218 :                basis%subset(iset)%nexp, basis%subset(iset)%l
     558          466 :             DO iexp = 1, basis%subset(iset)%nexp
     559              :                WRITE (UNIT=unit_nr, FMT="(T2,F24.14,30(1X,ES24.14))") &
     560         1762 :                   basis%subset(iset)%exps(iexp), basis%subset(iset)%coeff(iexp, :)
     561              :             END DO
     562              :          END DO
     563              :       END IF
     564              : 
     565          104 :    END SUBROUTINE write_basis
     566              : 
     567              : ! **************************************************************************************************
     568              : !> \brief Initialize the derived basis sets and the vectors containing their
     569              : !>        assembly information ehich is used for regeneration of the sets.
     570              : !> \param info_new ...
     571              : !> \param info_ref ...
     572              : !> \param basis ...
     573              : !> \param basis_new ...
     574              : !> \author Florian Schiffmann
     575              : ! **************************************************************************************************
     576              : 
     577           16 :    SUBROUTINE setup_used_parts_init_basis(info_new, info_ref, basis, basis_new)
     578              :       TYPE(derived_basis_info)                           :: info_new, info_ref
     579              :       TYPE(flex_basis_type)                              :: basis, basis_new
     580              : 
     581              :       INTEGER                                            :: i, jset, lind, nsets
     582              : 
     583              : ! copy the reference information on the new set
     584              : 
     585           48 :       ALLOCATE (info_new%in_use_set(SIZE(info_ref%in_use_set)))
     586           32 :       info_new%in_use_set(:) = info_ref%in_use_set
     587           64 :       ALLOCATE (info_new%use_contr(SIZE(info_ref%in_use_set)))
     588           32 :       DO i = 1, SIZE(info_ref%in_use_set)
     589           48 :          ALLOCATE (info_new%use_contr(i)%in_use(SIZE(info_ref%use_contr(i)%in_use)))
     590          120 :          info_new%use_contr(i)%in_use(:) = info_ref%use_contr(i)%in_use
     591              :       END DO
     592           16 :       DO i = 1, info_new%nsets
     593           16 :          info_new%in_use_set(info_new%remove_set(i)) = .FALSE.
     594              :       END DO
     595           48 :       DO i = 1, info_new%ncontr
     596              :          lind = convert_l_contr_to_entry(basis%subset(info_new%remove_contr(i, 1))%lmin, &
     597              :                                          basis%subset(info_new%remove_contr(i, 1))%l, &
     598           32 :                                          info_new%remove_contr(i, 3), info_new%remove_contr(i, 2))
     599              : 
     600           48 :          info_new%use_contr(info_new%remove_contr(i, 1))%in_use(lind) = .FALSE.
     601              :       END DO
     602              : 
     603           16 :       nsets = 0
     604           32 :       DO i = 1, basis%nsets
     605           32 :          IF (info_new%in_use_set(i)) nsets = nsets + 1
     606              :       END DO
     607           16 :       basis_new%nsets = nsets
     608           64 :       ALLOCATE (basis_new%subset(nsets))
     609           16 :       jset = 0
     610           32 :       DO i = 1, basis%nsets
     611           32 :          IF (info_new%in_use_set(i)) THEN
     612           16 :             jset = jset + 1
     613           16 :             CALL create_new_subset(basis%subset(i), basis_new%subset(jset), info_new%use_contr(jset)%in_use)
     614              :          END IF
     615              :       END DO
     616              : 
     617           16 :    END SUBROUTINE setup_used_parts_init_basis
     618              : 
     619              : ! **************************************************************************************************
     620              : !> \brief Fill the low level information of the derived basis set.
     621              : !> \param subset ...
     622              : !> \param subset_new ...
     623              : !> \param in_use ...
     624              : !> \author Florian Schiffmann
     625              : ! **************************************************************************************************
     626              : 
     627           16 :    SUBROUTINE create_new_subset(subset, subset_new, in_use)
     628              :       TYPE(subset_type)                                  :: subset, subset_new
     629              :       LOGICAL, DIMENSION(:)                              :: in_use
     630              : 
     631              :       INTEGER                                            :: icon, iind, il
     632           16 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: tmp_l
     633              : 
     634           48 :       ALLOCATE (tmp_l(SIZE(subset%l)))
     635           56 :       tmp_l(:) = subset%l
     636           16 :       subset_new%lmin = subset%lmin
     637           16 :       subset_new%lmax = subset%lmin - 1
     638           16 :       subset_new%nexp = subset%nexp
     639           16 :       subset_new%n = subset%n
     640           56 :       DO il = 1, SIZE(subset%l)
     641          128 :          DO icon = 1, subset%l(il)
     642           88 :             iind = convert_l_contr_to_entry(subset%lmin, subset%l, icon, subset%lmin + il - 1)
     643          128 :             IF (.NOT. in_use(iind)) tmp_l(il) = tmp_l(il) - 1
     644              :          END DO
     645           56 :          IF (tmp_l(il) > 0) subset_new%lmax = subset_new%lmax + 1
     646              :       END DO
     647           16 :       subset_new%nl = subset_new%lmax - subset_new%lmin + 1
     648           56 :       subset_new%ncon_tot = SUM(tmp_l)
     649           48 :       ALLOCATE (subset_new%l(subset_new%nl))
     650           64 :       ALLOCATE (subset_new%coeff(subset_new%nexp, subset_new%ncon_tot))
     651           48 :       ALLOCATE (subset_new%exps(subset_new%nexp))
     652          128 :       subset_new%exps(:) = subset%exps
     653           48 :       DO il = 1, SIZE(subset%l)
     654           40 :          IF (tmp_l(il) == 0) EXIT
     655           48 :          subset_new%l(il) = tmp_l(il)
     656              :       END DO
     657           16 :       DEALLOCATE (tmp_l)
     658           16 :       iind = 0
     659          104 :       DO icon = 1, subset%ncon_tot
     660          104 :          IF (in_use(icon)) THEN
     661           44 :             iind = iind + 1
     662          352 :             subset_new%coeff(:, iind) = subset%coeff(:, icon)
     663              :          END IF
     664              :       END DO
     665              : 
     666           16 :    END SUBROUTINE create_new_subset
     667              : 
     668              : ! **************************************************************************************************
     669              : !> \brief for completeness generate the derived info for set 0(reference from file)
     670              : !> \param info ...
     671              : !> \param basis ...
     672              : !> \author Florian Schiffmann
     673              : ! **************************************************************************************************
     674              : 
     675           16 :    SUBROUTINE init_deriv_info_ref(info, basis)
     676              :       TYPE(derived_basis_info)                           :: info
     677              :       TYPE(flex_basis_type)                              :: basis
     678              : 
     679              :       INTEGER                                            :: i
     680              : 
     681           48 :       ALLOCATE (info%in_use_set(basis%nsets))
     682           32 :       info%in_use_set = .TRUE.
     683           64 :       ALLOCATE (info%use_contr(basis%nsets))
     684           32 :       DO i = 1, basis%nsets
     685           48 :          ALLOCATE (info%use_contr(i)%in_use(basis%subset(i)%ncon_tot))
     686          112 :          info%use_contr(i)%in_use = .TRUE.
     687              :       END DO
     688              : 
     689           16 :    END SUBROUTINE init_deriv_info_ref
     690              : 
     691              : ! **************************************************************************************************
     692              : !> \brief get the general information for the basis sets. E.g. what to optimize,
     693              : !>        Basis set name, constraints upon optimization and read the reference basis
     694              : !> \param kind_section ...
     695              : !> \param opt_bas ...
     696              : !> \param para_env ...
     697              : !> \author Florian Schiffmann
     698              : ! **************************************************************************************************
     699              : 
     700            8 :    SUBROUTINE generate_initial_basis(kind_section, opt_bas, para_env)
     701              :       TYPE(section_vals_type), POINTER                   :: kind_section
     702              :       TYPE(basis_optimization_type)                      :: opt_bas
     703              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     704              : 
     705              :       INTEGER                                            :: ikind, variable_counter
     706              :       LOGICAL                                            :: explicit
     707              :       TYPE(section_vals_type), POINTER                   :: set_section
     708              : 
     709            8 :       CALL section_vals_get(kind_section, n_repetition=opt_bas%nkind)
     710           40 :       ALLOCATE (opt_bas%kind_basis(opt_bas%nkind))
     711              : 
     712              :       ! counter to get the number of free variables in optimization
     713            8 :       variable_counter = 0
     714           24 :       DO ikind = 1, opt_bas%nkind
     715              :          CALL section_vals_val_get(kind_section, "_SECTION_PARAMETERS_", c_val=opt_bas%kind_basis(ikind)%element, &
     716           16 :                                    i_rep_section=ikind)
     717              :          CALL section_vals_val_get(kind_section, "BASIS_SET", c_val=opt_bas%kind_basis(ikind)%basis_name, &
     718           16 :                                    i_rep_section=ikind)
     719              :          set_section => section_vals_get_subs_vals(kind_section, "DERIVED_BASIS_SETS", &
     720           16 :                                                    i_rep_section=ikind)
     721           16 :          CALL section_vals_get(set_section, n_repetition=opt_bas%kind_basis(ikind)%nbasis_deriv, explicit=explicit)
     722           16 :          IF (.NOT. explicit) opt_bas%kind_basis(ikind)%nbasis_deriv = 0
     723           80 :          ALLOCATE (opt_bas%kind_basis(ikind)%flex_basis(0:opt_bas%kind_basis(ikind)%nbasis_deriv))
     724           80 :          ALLOCATE (opt_bas%kind_basis(ikind)%deriv_info(0:opt_bas%kind_basis(ikind)%nbasis_deriv))
     725              : 
     726              :          CALL fill_basis_template(kind_section, opt_bas%kind_basis(ikind)%flex_basis(0), opt_bas%template_basis_file, &
     727           16 :                                   opt_bas%kind_basis(ikind)%element, opt_bas%kind_basis(ikind)%basis_name, para_env, ikind)
     728              : 
     729           16 :          CALL setup_exp_constraints(kind_section, opt_bas%kind_basis(ikind)%flex_basis(0))
     730              : 
     731           16 :          CALL parse_derived_basis(kind_section, opt_bas%kind_basis(ikind)%deriv_info, ikind)
     732              : 
     733           40 :          variable_counter = variable_counter + opt_bas%kind_basis(ikind)%flex_basis(0)%nopt
     734              :       END DO
     735              : 
     736           24 :       ALLOCATE (opt_bas%x_opt(variable_counter))
     737              : 
     738            8 :       variable_counter = 0
     739           24 :       DO ikind = 1, opt_bas%nkind
     740           24 :          CALL assign_x_to_basis(opt_bas%x_opt, opt_bas%kind_basis(ikind)%flex_basis(0), variable_counter)
     741              :       END DO
     742              : 
     743            8 :       CPASSERT(variable_counter == SIZE(opt_bas%x_opt))
     744              : 
     745            8 :    END SUBROUTINE generate_initial_basis
     746              : 
     747              : ! **************************************************************************************************
     748              : !> \brief get low level information about how to construc new basis sets from reference
     749              : !> \param kind_section ...
     750              : !> \param deriv_info ...
     751              : !> \param ikind ...
     752              : !> \author Florian Schiffmann
     753              : ! **************************************************************************************************
     754              : 
     755           16 :    SUBROUTINE parse_derived_basis(kind_section, deriv_info, ikind)
     756              :       TYPE(section_vals_type), POINTER                   :: kind_section
     757              :       TYPE(derived_basis_info), DIMENSION(:)             :: deriv_info
     758              :       INTEGER                                            :: ikind
     759              : 
     760              :       INTEGER                                            :: i_rep, iset, jset, n_rep, nsets
     761           16 :       INTEGER, DIMENSION(:), POINTER                     :: i_vals
     762              :       LOGICAL                                            :: explicit
     763              :       TYPE(section_vals_type), POINTER                   :: set1_section
     764              : 
     765           16 :       nsets = SIZE(deriv_info) - 1
     766              :       set1_section => section_vals_get_subs_vals(kind_section, "DERIVED_BASIS_SETS", &
     767           32 :                                                  i_rep_section=ikind)
     768           32 :       DO jset = 1, nsets
     769              :          ! stracnge but as derive info is allcated from 0 to n the count over here has to be shifted
     770           16 :          iset = jset + 1
     771              :          CALL section_vals_val_get(set1_section, "BASIS_SET_NAME", c_val=deriv_info(iset)%basis_name, &
     772           16 :                                    i_rep_section=jset)
     773           16 :          CALL section_vals_val_get(set1_section, "REFERENCE_SET", i_vals=i_vals, i_rep_section=jset)
     774           16 :          deriv_info(iset)%reference_set = i_vals(1)
     775              :          CALL section_vals_val_get(set1_section, "REMOVE_CONTRACTION", explicit=explicit, n_rep_val=n_rep, &
     776           16 :                                    i_rep_section=jset)
     777           16 :          deriv_info(iset)%ncontr = n_rep
     778           16 :          IF (explicit) THEN
     779           48 :             ALLOCATE (deriv_info(iset)%remove_contr(n_rep, 3))
     780           48 :             DO i_rep = 1, n_rep
     781              :                CALL section_vals_val_get(set1_section, "REMOVE_CONTRACTION", i_rep_val=i_rep, i_vals=i_vals, &
     782           32 :                                          i_rep_section=jset)
     783          144 :                deriv_info(iset)%remove_contr(i_rep, :) = i_vals(:)
     784              :             END DO
     785              :          END IF
     786              :          CALL section_vals_val_get(set1_section, "REMOVE_SET", explicit=explicit, n_rep_val=n_rep, &
     787           16 :                                    i_rep_section=jset)
     788           16 :          deriv_info(iset)%nsets = n_rep
     789           48 :          IF (explicit) THEN
     790            0 :             ALLOCATE (deriv_info(iset)%remove_set(n_rep))
     791            0 :             DO i_rep = 1, n_rep
     792              :                CALL section_vals_val_get(set1_section, "REMOVE_SET", i_rep_val=i_rep, i_vals=i_vals, &
     793            0 :                                          i_rep_section=jset)
     794            0 :                deriv_info(iset)%remove_set(i_rep) = i_vals(1)
     795              :             END DO
     796              :          END IF
     797              :       END DO
     798              : 
     799           16 :    END SUBROUTINE parse_derived_basis
     800              : 
     801              : ! **************************************************************************************************
     802              : !> \brief get low level information about constraint on exponents
     803              : !> \param kind1_section ...
     804              : !> \param flex_basis ...
     805              : !> \author Florian Schiffmann
     806              : ! **************************************************************************************************
     807              : 
     808           32 :    SUBROUTINE setup_exp_constraints(kind1_section, flex_basis)
     809              :       TYPE(section_vals_type), POINTER                   :: kind1_section
     810              :       TYPE(flex_basis_type)                              :: flex_basis
     811              : 
     812              :       INTEGER                                            :: ipgf, irep, iset, nrep
     813           16 :       INTEGER, DIMENSION(:), POINTER                     :: def_exp
     814              :       LOGICAL                                            :: is_bound, is_varlim
     815              :       TYPE(section_vals_type), POINTER                   :: const_section
     816              : 
     817           32 :       const_section => section_vals_get_subs_vals(kind1_section, "CONSTRAIN_EXPONENTS")
     818           16 :       CALL section_vals_get(const_section, n_repetition=nrep)
     819           16 :       DO irep = 1, nrep
     820            0 :          CALL section_vals_val_get(const_section, "USE_EXP", i_vals=def_exp, i_rep_section=irep)
     821            0 :          CALL section_vals_val_get(const_section, "BOUNDARIES", explicit=is_bound, i_rep_section=irep)
     822            0 :          CALL section_vals_val_get(const_section, "MAX_VAR_FRACTION", explicit=is_varlim, i_rep_section=irep)
     823            0 :          IF (is_bound .AND. is_varlim) THEN
     824              :             CALL cp_abort(__LOCATION__, "Exponent has two constraints. "// &
     825            0 :                           "This is not possible at the moment. Please change input.")
     826              :          END IF
     827            0 :          IF (.NOT. is_bound .AND. .NOT. is_varlim) THEN
     828              :             CALL cp_abort(__LOCATION__, "Exponent is declared to be constraint but none is given"// &
     829            0 :                           " Please change input.")
     830              :          END IF
     831           16 :          IF (def_exp(1) == -1) THEN
     832            0 :             DO iset = 1, flex_basis%nsets
     833            0 :                IF (def_exp(2) == -1) THEN
     834            0 :                   DO ipgf = 1, flex_basis%subset(iset)%nexp
     835            0 :                      CALL set_constraint(flex_basis, iset, ipgf, const_section, is_bound, is_varlim, irep)
     836              :                   END DO
     837              :                ELSE
     838            0 :                   IF (def_exp(2) <= flex_basis%subset(iset)%nexp) THEN
     839              :                      CALL cp_abort(__LOCATION__, &
     840              :                                    "Exponent declared in constraint is larger than number of exponents in the set"// &
     841            0 :                                    " Please change input.")
     842              :                   END IF
     843            0 :                   CALL set_constraint(flex_basis, iset, def_exp(2), const_section, is_bound, is_varlim, irep)
     844              :                END IF
     845              :             END DO
     846              :          ELSE
     847            0 :             IF (.NOT. def_exp(1) <= flex_basis%nsets) THEN
     848              :                CALL cp_abort(__LOCATION__, &
     849              :                              "Set number of constraint is larger than number of sets in the template basis set."// &
     850            0 :                              " Please change input.")
     851              :             END IF
     852            0 :             IF (def_exp(2) == -1) THEN
     853            0 :                DO ipgf = 1, flex_basis%subset(iset)%nexp
     854            0 :                   CALL set_constraint(flex_basis, def_exp(1), ipgf, const_section, is_bound, is_varlim, irep)
     855              :                END DO
     856              :             ELSE
     857            0 :                IF (.NOT. def_exp(2) <= flex_basis%subset(def_exp(1))%nexp) THEN
     858              :                   CALL cp_abort(__LOCATION__, &
     859              :                                 "Exponent declared in constraint is larger than number of exponents in the set"// &
     860            0 :                                 " Please change input.")
     861              :                END IF
     862            0 :                CALL set_constraint(flex_basis, def_exp(1), def_exp(2), const_section, is_bound, is_varlim, irep)
     863              :             END IF
     864              :          END IF
     865              :       END DO
     866              : 
     867           16 :    END SUBROUTINE setup_exp_constraints
     868              : 
     869              : ! **************************************************************************************************
     870              : !> \brief put the constraint information in type and process if requires
     871              : !>        BOUNDARIES constraint gets transformed into MAX_VAR_FRACTION constraint.
     872              : !> \param flex_basis ...
     873              : !> \param iset ...
     874              : !> \param ipgf ...
     875              : !> \param const_section ...
     876              : !> \param is_bound ...
     877              : !> \param is_varlim ...
     878              : !> \param irep ...
     879              : !> \author Florian Schiffmann
     880              : ! **************************************************************************************************
     881              : 
     882            0 :    SUBROUTINE set_constraint(flex_basis, iset, ipgf, const_section, is_bound, is_varlim, irep)
     883              :       TYPE(flex_basis_type)                              :: flex_basis
     884              :       INTEGER                                            :: iset, ipgf
     885              :       TYPE(section_vals_type), POINTER                   :: const_section
     886              :       LOGICAL                                            :: is_bound, is_varlim
     887              :       INTEGER                                            :: irep
     888              : 
     889              :       REAL(KIND=dp)                                      :: r_val
     890            0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: r_vals
     891              : 
     892            0 :       IF (flex_basis%subset(iset)%exp_has_const(ipgf)) THEN
     893              :          CALL cp_abort(__LOCATION__, &
     894              :                        "Multiple constraints due to collision in CONSTRAIN_EXPONENTS."// &
     895            0 :                        " Please change input.")
     896              :       END IF
     897            0 :       flex_basis%subset(iset)%exp_has_const(ipgf) = .TRUE.
     898            0 :       IF (is_bound) THEN
     899            0 :          flex_basis%subset(iset)%exp_const(ipgf)%const_type = 0
     900            0 :          CALL section_vals_val_get(const_section, "BOUNDARIES", r_vals=r_vals, i_rep_section=irep)
     901            0 :          flex_basis%subset(iset)%exp_const(ipgf)%llim = MINVAL(r_vals)
     902            0 :          flex_basis%subset(iset)%exp_const(ipgf)%ulim = MAXVAL(r_vals)
     903            0 :          r_val = flex_basis%subset(iset)%exps(ipgf)
     904            0 :          IF (flex_basis%subset(iset)%exps(ipgf) > MAXVAL(r_vals) .OR. flex_basis%subset(iset)%exps(ipgf) < MINVAL(r_vals)) THEN
     905              :             CALL cp_abort(__LOCATION__, &
     906              :                           "Exponent "//cp_to_string(r_val)// &
     907              :                           " declared in constraint is out of bounds of constraint"//cp_to_string(MINVAL(r_vals))// &
     908              :                           " to"//cp_to_string(MAXVAL(r_vals))// &
     909            0 :                           " Please change input.")
     910              :          END IF
     911            0 :          flex_basis%subset(iset)%exp_const(ipgf)%init = SUM(r_vals)/2.0_dp
     912            0 :          flex_basis%subset(iset)%exp_const(ipgf)%var_fac = MAXVAL(r_vals)/flex_basis%subset(iset)%exp_const(ipgf)%init - 1.0_dp
     913              :       END IF
     914            0 :       IF (is_varlim) THEN
     915            0 :          flex_basis%subset(iset)%exp_const(ipgf)%const_type = 1
     916            0 :          CALL section_vals_val_get(const_section, "MAX_VAR_FRACTION", r_vals=r_vals, i_rep_section=irep)
     917            0 :          flex_basis%subset(iset)%exp_const(ipgf)%var_fac = r_vals(1)
     918            0 :          flex_basis%subset(iset)%exp_const(ipgf)%init = flex_basis%subset(iset)%exps(ipgf)
     919              :       END IF
     920              : 
     921            0 :    END SUBROUTINE set_constraint
     922              : 
     923              : ! **************************************************************************************************
     924              : !> \brief Initialize the optimization vector with the values from the refernece sets
     925              : !> \param x ...
     926              : !> \param basis ...
     927              : !> \param x_ind ...
     928              : !> \author Florian Schiffmann
     929              : ! **************************************************************************************************
     930              : 
     931           16 :    SUBROUTINE assign_x_to_basis(x, basis, x_ind)
     932              :       REAL(KIND=dp), DIMENSION(:)                        :: x
     933              :       TYPE(flex_basis_type)                              :: basis
     934              :       INTEGER                                            :: x_ind
     935              : 
     936              :       INTEGER                                            :: icont, ipgf, iset
     937              : 
     938           32 :       DO iset = 1, basis%nsets
     939          140 :          DO ipgf = 1, basis%subset(iset)%nexp
     940          108 :             IF (basis%subset(iset)%opt_exps(ipgf)) THEN
     941            0 :                x_ind = x_ind + 1
     942            0 :                basis%subset(iset)%exp_x_ind(ipgf) = x_ind
     943            0 :                x(x_ind) = basis%subset(iset)%exps(ipgf)
     944              :             END IF
     945          664 :             DO icont = 1, basis%subset(iset)%ncon_tot
     946          648 :                IF (basis%subset(iset)%opt_coeff(ipgf, icont)) THEN
     947          380 :                   x_ind = x_ind + 1
     948          380 :                   basis%subset(iset)%coeff_x_ind(ipgf, icont) = x_ind
     949          380 :                   x(x_ind) = basis%subset(iset)%coeff(ipgf, icont)
     950              :                END IF
     951              :             END DO
     952              :          END DO
     953              :       END DO
     954              : 
     955           16 :    END SUBROUTINE assign_x_to_basis
     956              : 
     957              : ! **************************************************************************************************
     958              : !> \brief Fill the reference set and get the free varialbles from input
     959              : !> \param kind1_section ...
     960              : !> \param flex_basis ...
     961              : !> \param template_basis_file ...
     962              : !> \param element ...
     963              : !> \param basis_name ...
     964              : !> \param para_env ...
     965              : !> \param ikind ...
     966              : !> \author Florian Schiffmann
     967              : ! **************************************************************************************************
     968              : 
     969           96 :    SUBROUTINE fill_basis_template(kind1_section, flex_basis, template_basis_file, element, basis_name, para_env, ikind)
     970              :       TYPE(section_vals_type), POINTER                   :: kind1_section
     971              :       TYPE(flex_basis_type)                              :: flex_basis
     972              :       CHARACTER(LEN=default_path_length)                 :: template_basis_file
     973              :       CHARACTER(LEN=default_string_length)               :: element, basis_name
     974              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     975              :       INTEGER                                            :: ikind
     976              : 
     977              :       INTEGER                                            :: icont, idof, ipgf, irep, iset, nrep
     978           16 :       INTEGER, DIMENSION(:), POINTER                     :: switch
     979              : 
     980           16 :       CALL parse_basis(flex_basis, template_basis_file, element, basis_name, para_env)
     981              : 
     982              :       ! get the optimizable parameters. Many way to modify them but in the end only logical matrix
     983              :       ! is either set or values get flipped according to the input
     984              :       CALL section_vals_val_get(kind1_section, "INITIAL_DEGREES_OF_FREEDOM", i_val=idof, &
     985           16 :                                 i_rep_section=ikind)
     986           32 :       DO iset = 1, flex_basis%nsets
     987           16 :          SELECT CASE (idof)
     988              :          CASE (do_opt_none)
     989              :             ! initialization in parse subset did the job
     990              :          CASE (do_opt_all)
     991            0 :             flex_basis%subset(iset)%opt_coeff = .TRUE.
     992            0 :             flex_basis%subset(iset)%opt_exps = .TRUE.
     993              :          CASE (do_opt_coeff)
     994          360 :             flex_basis%subset(iset)%opt_coeff = .TRUE.
     995              :          CASE (do_opt_exps)
     996            0 :             flex_basis%subset(iset)%opt_exps = .TRUE.
     997              :          CASE DEFAULT
     998           16 :             CPABORT("No initialization available?????")
     999              :          END SELECT
    1000              :       END DO
    1001              : 
    1002           16 :       CALL section_vals_val_get(kind1_section, "SWITCH_CONTRACTION_STATE", n_rep_val=nrep, i_rep_section=ikind)
    1003           28 :       DO irep = 1, nrep
    1004              :          CALL section_vals_val_get(kind1_section, "SWITCH_CONTRACTION_STATE", i_rep_val=irep, &
    1005           12 :                                    i_rep_section=ikind, i_vals=switch)
    1006           12 :          icont = convert_l_contr_to_entry(flex_basis%subset(switch(1))%lmin, flex_basis%subset(switch(1))%l, switch(3), switch(2))
    1007          100 :          DO ipgf = 1, flex_basis%subset(switch(1))%nexp
    1008           84 :             flex_basis%subset(switch(1))%opt_coeff(ipgf, icont) = .NOT. flex_basis%subset(switch(1))%opt_coeff(ipgf, icont)
    1009              :          END DO
    1010              :       END DO
    1011              : 
    1012           16 :       CALL section_vals_val_get(kind1_section, "SWITCH_COEFF_STATE", n_rep_val=nrep, i_rep_section=ikind)
    1013           16 :       DO irep = 1, nrep
    1014              :          CALL section_vals_val_get(kind1_section, "SWITCH_COEFF_STATE", i_rep_val=irep, &
    1015            0 :                                    i_rep_section=ikind, i_vals=switch)
    1016            0 :          icont = convert_l_contr_to_entry(flex_basis%subset(switch(1))%lmin, flex_basis%subset(switch(1))%l, switch(3), switch(2))
    1017              :          flex_basis%subset(switch(1))%opt_coeff(switch(4), icont) = &
    1018           16 :             .NOT. flex_basis%subset(switch(1))%opt_coeff(switch(4), icont)
    1019              :       END DO
    1020              : 
    1021           16 :       CALL section_vals_val_get(kind1_section, "SWITCH_EXP_STATE", n_rep_val=nrep, i_rep_section=ikind)
    1022           16 :       DO irep = 1, nrep
    1023              :          CALL section_vals_val_get(kind1_section, "SWITCH_EXP_STATE", i_rep_val=irep, &
    1024            0 :                                    i_rep_section=ikind, i_vals=switch)
    1025           16 :          flex_basis%subset(switch(1))%opt_exps(switch(2)) = .NOT. flex_basis%subset(switch(1))%opt_exps(switch(2))
    1026              :       END DO
    1027              : 
    1028           16 :       CALL section_vals_val_get(kind1_section, "SWITCH_SET_STATE", n_rep_val=nrep, i_rep_section=ikind)
    1029           16 :       DO irep = 1, nrep
    1030              :          CALL section_vals_val_get(kind1_section, "SWITCH_SET_STATE", i_rep_val=irep, &
    1031            0 :                                    i_rep_section=ikind, i_vals=switch)
    1032           16 :          DO ipgf = 1, flex_basis%subset(switch(2))%nexp
    1033            0 :             SELECT CASE (switch(1))
    1034              :             CASE (0) ! switch all states in the set
    1035            0 :                DO icont = 1, flex_basis%subset(switch(2))%ncon_tot
    1036              :                   flex_basis%subset(switch(2))%opt_coeff(ipgf, icont) = &
    1037            0 :                      .NOT. flex_basis%subset(switch(2))%opt_coeff(ipgf, icont)
    1038              :                END DO
    1039            0 :                flex_basis%subset(switch(2))%opt_exps(ipgf) = .NOT. flex_basis%subset(switch(2))%opt_exps(ipgf)
    1040              :             CASE (1) ! switch only exp
    1041            0 :                flex_basis%subset(switch(2))%opt_exps(ipgf) = .NOT. flex_basis%subset(switch(2))%opt_exps(ipgf)
    1042              :             CASE (2) ! switch only coeff
    1043            0 :                DO icont = 1, flex_basis%subset(switch(2))%ncon_tot
    1044              :                   flex_basis%subset(switch(2))%opt_coeff(ipgf, icont) = &
    1045            0 :                      .NOT. flex_basis%subset(switch(2))%opt_coeff(ipgf, icont)
    1046              :                END DO
    1047              :             CASE DEFAULT
    1048            0 :                CPABORT("Invalid option in SWITCH_SET_STATE, 1st value has to be 0, 1 or 2")
    1049              :             END SELECT
    1050              :          END DO
    1051              :       END DO
    1052              : 
    1053              :       ! perform a final modification. If basis set is uncontracted coefficient will never have to be optimized
    1054           32 :       DO irep = 1, flex_basis%nsets
    1055           32 :          IF (flex_basis%subset(irep)%nexp == 1) THEN
    1056            0 :             DO ipgf = 1, flex_basis%subset(irep)%nexp
    1057            0 :                flex_basis%subset(irep)%opt_coeff(ipgf, 1) = .FALSE.
    1058              :             END DO
    1059              :          END IF
    1060              :       END DO
    1061              : 
    1062              :       ! finally count the total number of free parameters
    1063           16 :       flex_basis%nopt = 0
    1064           32 :       DO irep = 1, flex_basis%nsets
    1065          140 :          DO ipgf = 1, flex_basis%subset(irep)%nexp
    1066          648 :             DO icont = 1, flex_basis%subset(irep)%ncon_tot
    1067          648 :                IF (flex_basis%subset(irep)%opt_coeff(ipgf, icont)) flex_basis%nopt = flex_basis%nopt + 1
    1068              :             END DO
    1069          124 :             IF (flex_basis%subset(irep)%opt_exps(ipgf)) flex_basis%nopt = flex_basis%nopt + 1
    1070              :          END DO
    1071              :       END DO
    1072              : 
    1073           16 :    END SUBROUTINE fill_basis_template
    1074              : 
    1075              : ! **************************************************************************************************
    1076              : !> \brief Helper function to parse input. Converts l and index position of
    1077              : !>        a contraction to index in the contraction array of the set using lmin and nl
    1078              : !> \param lmin ...
    1079              : !> \param nl ...
    1080              : !> \param icontr ...
    1081              : !> \param l ...
    1082              : !> \return ...
    1083              : !> \author Florian Schiffmann
    1084              : ! **************************************************************************************************
    1085              : 
    1086          132 :    FUNCTION convert_l_contr_to_entry(lmin, nl, icontr, l) RESULT(ientry)
    1087              :       INTEGER                                            :: lmin
    1088              :       INTEGER, DIMENSION(:)                              :: nl
    1089              :       INTEGER                                            :: icontr, l, ientry
    1090              : 
    1091              :       INTEGER                                            :: i, icon2l, iwork
    1092              : 
    1093          132 :       iwork = l - lmin
    1094          132 :       icon2l = 0
    1095          212 :       DO i = 1, iwork
    1096          212 :          icon2l = icon2l + nl(i)
    1097              :       END DO
    1098          132 :       ientry = icon2l + icontr
    1099              : 
    1100          132 :    END FUNCTION convert_l_contr_to_entry
    1101              : 
    1102              : ! **************************************************************************************************
    1103              : !> \brief Read the reference basis sets from the template basis file
    1104              : !> \param flex_basis ...
    1105              : !> \param template_basis_file ...
    1106              : !> \param element ...
    1107              : !> \param basis_name ...
    1108              : !> \param para_env ...
    1109              : !> \author Florian Schiffmann
    1110              : ! **************************************************************************************************
    1111              : 
    1112           32 :    SUBROUTINE parse_basis(flex_basis, template_basis_file, element, basis_name, para_env)
    1113              :       TYPE(flex_basis_type)                              :: flex_basis
    1114              :       CHARACTER(LEN=default_path_length)                 :: template_basis_file
    1115              :       CHARACTER(LEN=default_string_length)               :: element, basis_name
    1116              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1117              : 
    1118              :       CHARACTER(LEN=240)                                 :: line
    1119              :       CHARACTER(LEN=242)                                 :: line2
    1120              :       CHARACTER(LEN=LEN(basis_name)+2)                   :: basis_name2
    1121              :       CHARACTER(LEN=LEN(element)+2)                      :: element2
    1122              :       INTEGER                                            :: iset, strlen1, strlen2
    1123              :       LOGICAL                                            :: basis_found, found, match
    1124              :       TYPE(cp_parser_type)                               :: parser
    1125              : 
    1126           16 :       basis_found = .FALSE.
    1127           16 :       CALL uppercase(element)
    1128           16 :       CALL uppercase(basis_name)
    1129           16 :       CALL parser_create(parser, template_basis_file, para_env=para_env)
    1130              : 
    1131              :       search_loop: DO
    1132           32 :          CALL parser_search_string(parser, TRIM(basis_name), .TRUE., found, line)
    1133           32 :          IF (found) THEN
    1134           32 :             match = .FALSE.
    1135           32 :             CALL uppercase(line)
    1136              :             ! Check both the element symbol and the basis set name
    1137           32 :             line2 = " "//line//" "
    1138           32 :             element2 = " "//TRIM(element)//" "
    1139           32 :             basis_name2 = " "//TRIM(basis_name)//" "
    1140           32 :             strlen1 = LEN_TRIM(element2) + 1
    1141           32 :             strlen2 = LEN_TRIM(basis_name2) + 1
    1142           32 :             IF ((INDEX(line2, element2(:strlen1)) > 0) .AND. &
    1143           16 :                 (INDEX(line2, basis_name2(:strlen2)) > 0)) match = .TRUE.
    1144           32 :             IF (match) THEN
    1145           16 :                CALL parser_get_object(parser, flex_basis%nsets, newline=.TRUE.)
    1146           64 :                ALLOCATE (flex_basis%subset(flex_basis%nsets))
    1147           32 :                DO iset = 1, flex_basis%nsets
    1148           32 :                   CALL parse_subset(parser, flex_basis%subset(iset))
    1149              :                END DO
    1150              :                basis_found = .TRUE.
    1151              :                EXIT search_loop
    1152              :             END IF
    1153              :          ELSE
    1154              :             EXIT search_loop
    1155              :          END IF
    1156              :       END DO search_loop
    1157           16 :       CALL parser_release(parser)
    1158              : 
    1159           16 :       IF (.NOT. basis_found) CALL cp_abort(__LOCATION__, &
    1160              :                                            "The requested basis set <"//TRIM(basis_name)// &
    1161              :                                            "> for element <"//TRIM(element)//"> was not "// &
    1162            0 :                                            "found in the template basis set file ")
    1163              : 
    1164           48 :    END SUBROUTINE parse_basis
    1165              : 
    1166              : ! **************************************************************************************************
    1167              : !> \brief Read the subset information from the template basis file
    1168              : !> \param parser ...
    1169              : !> \param subset ...
    1170              : !> \author Florian Schiffmann
    1171              : ! **************************************************************************************************
    1172           16 :    SUBROUTINE parse_subset(parser, subset)
    1173              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1174              :       TYPE(subset_type)                                  :: subset
    1175              : 
    1176              :       CHARACTER(len=20*default_string_length)            :: line_att
    1177              :       INTEGER                                            :: icon1, icon2, il, ipgf, ishell, istart
    1178              :       REAL(KIND=dp)                                      :: gs_scale
    1179              :       REAL(KIND=dp), POINTER                             :: r_val
    1180              : 
    1181              :       line_att = ""
    1182           16 :       CALL parser_get_object(parser, subset%n, newline=.TRUE.)
    1183           16 :       CALL parser_get_object(parser, subset%lmin)
    1184           16 :       CALL parser_get_object(parser, subset%lmax)
    1185           16 :       CALL parser_get_object(parser, subset%nexp)
    1186           16 :       subset%nl = subset%lmax - subset%lmin + 1
    1187           16 :       ALLOCATE (r_val)
    1188           48 :       ALLOCATE (subset%l(subset%nl))
    1189           48 :       ALLOCATE (subset%exps(subset%nexp))
    1190           48 :       ALLOCATE (subset%exp_has_const(subset%nexp))
    1191          124 :       subset%exp_has_const = .FALSE.
    1192           32 :       ALLOCATE (subset%opt_exps(subset%nexp))
    1193          124 :       subset%opt_exps = .FALSE.
    1194          156 :       ALLOCATE (subset%exp_const(subset%nexp))
    1195           32 :       ALLOCATE (subset%exp_x_ind(subset%nexp))
    1196           56 :       DO ishell = 1, subset%nl
    1197           56 :          CALL parser_get_object(parser, subset%l(ishell))
    1198              :       END DO
    1199           56 :       subset%ncon_tot = SUM(subset%l)
    1200           64 :       ALLOCATE (subset%coeff(subset%nexp, subset%ncon_tot))
    1201           64 :       ALLOCATE (subset%opt_coeff(subset%nexp, subset%ncon_tot))
    1202          636 :       subset%opt_coeff = .FALSE.
    1203           48 :       ALLOCATE (subset%coeff_x_ind(subset%nexp, subset%ncon_tot))
    1204          124 :       DO ipgf = 1, subset%nexp
    1205          108 :          CALL parser_get_object(parser, r_val, newline=.TRUE.)
    1206          108 :          subset%exps(ipgf) = r_val
    1207          664 :          DO ishell = 1, subset%ncon_tot
    1208          540 :             CALL parser_get_object(parser, r_val)
    1209          648 :             subset%coeff(ipgf, ishell) = r_val
    1210              :          END DO
    1211              :       END DO
    1212              : 
    1213              :       ! orthonormalize contraction coefficients using gram schmidt
    1214           16 :       istart = 1
    1215           56 :       DO il = 1, subset%nl
    1216           80 :          DO icon1 = istart, istart + subset%l(il) - 2
    1217          136 :             DO icon2 = icon1 + 1, istart + subset%l(il) - 1
    1218              :                gs_scale = DOT_PRODUCT(subset%coeff(:, icon2), subset%coeff(:, icon1))/ &
    1219          824 :                           DOT_PRODUCT(subset%coeff(:, icon1), subset%coeff(:, icon1))
    1220          480 :                subset%coeff(:, icon2) = subset%coeff(:, icon2) - gs_scale*subset%coeff(:, icon1)
    1221              :             END DO
    1222              :          END DO
    1223           56 :          istart = istart + subset%l(il)
    1224              :       END DO
    1225              : 
    1226              :       ! just to get an understandable basis normalize coefficients
    1227           96 :       DO icon1 = 1, subset%ncon_tot
    1228         1176 :          subset%coeff(:, icon1) = subset%coeff(:, icon1)/NORM2(subset%coeff(:, icon1))
    1229              :       END DO
    1230           16 :       DEALLOCATE (r_val)
    1231              : 
    1232           16 :    END SUBROUTINE parse_subset
    1233              : 
    1234              : ! **************************************************************************************************
    1235              : !> \brief Initialize the variables for the powell optimizer
    1236              : !> \param p_param ...
    1237              : !> \param powell_section ...
    1238              : !> \author Florian Schiffmann
    1239              : ! **************************************************************************************************
    1240              : 
    1241            8 :    SUBROUTINE init_powell_var(p_param, powell_section)
    1242              :       TYPE(opt_state_type), INTENT(INOUT)                :: p_param
    1243              :       TYPE(section_vals_type), POINTER                   :: powell_section
    1244              : 
    1245            8 :       p_param%state = 0
    1246            8 :       p_param%nvar = 0
    1247            8 :       p_param%iprint = 0
    1248            8 :       p_param%unit = default_output_unit
    1249            8 :       CALL section_vals_val_get(powell_section, "ACCURACY", r_val=p_param%rhoend)
    1250            8 :       CALL section_vals_val_get(powell_section, "STEP_SIZE", r_val=p_param%rhobeg)
    1251            8 :       CALL section_vals_val_get(powell_section, "MAX_FUN", i_val=p_param%maxfun)
    1252              : 
    1253            8 :    END SUBROUTINE init_powell_var
    1254              : 
    1255              : END MODULE optimize_basis_utils
        

Generated by: LCOV version 2.0-1