• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eT-program / eT / 22216

17 Feb 2025 10:32PM UTC coverage: 88.469%. Remained the same
22216

push

gitlab-ci

Merge branch 'fix-tdhf-website-warning' into 'development'

Remove deprecated `tdhf excited states` keyword

See merge request eT-program/eT!1542

53469 of 60438 relevant lines covered (88.47%)

3059362.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.0
/src/io/input/input_tool_class.F90
1

2

3
! eT - a coupled cluster program
4
! Copyright (C) 2016-2024 the authors of eT
5
!
6
! eT is free software: you can redistribute it and/or modify
7
! it under the terms of the GNU General Public License as published by
8
! the Free Software Foundation, either version 3 of the License, or
9
! (at your option) any later version.
10
!
11
! eT is distributed in the hope that it will be useful,
12
! but WITHOUT ANY WARRANTY; without even the implied warranty of
13
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
! GNU General Public License for more details.
15
!
16
! You should have received a copy of the GNU General Public License
17
! along with this program. If not, see <https://www.gnu.org/licenses/>.
18

19

20
module input_tool_class
21

22
   !!
23
   !! Input tool class module
24
   !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
25
   !!
26

27
   use kinds
28
   use section_class, only: section
29
   use global_out,    only: output
30

31
   use string_utilities, only: string_starts_with, first_index_of_substring
32
   use string_utilities, only: is_substring_in_string, is_empty, remove_substring_after_symbol
33

34

35
   type :: input_tool
36

37
      type(section),     allocatable, dimension(:), private :: sections
38

39
      character(len=30), allocatable, dimension(:), private :: rf_wfs
40
      character(len=30), allocatable, dimension(:), private :: cc_wfs
41
      character(len=30), allocatable, dimension(:), private :: ci_wfs
42

43
      integer, private :: n_keyword_lines ! Number of lines excluding the geometry section
44
      integer, private :: n_qm_atom_lines ! Number of QM atoms
45
      integer, private :: n_mm_atom_lines ! Number of MM atoms
46

47
      ! Arrays storing lines in the input
48
      character(len=200), dimension(:), allocatable, private :: keyword_lines
49
      character(len=200), dimension(:), allocatable, private :: qm_geometry
50
      character(len=200), dimension(:), allocatable, private :: mm_geometry
51

52
   contains
53

54
      procedure, public :: read_input
55
      procedure, public :: set_input
56
      procedure, public :: process_input
57

58
      procedure, private :: print_input_except_geometry
59

60
      procedure, public :: get_n_atoms &
61
                        => get_n_atoms_input_tool
62

63
      procedure, public :: get_n_mm_atoms &
64
                        => get_n_mm_atoms_input_tool
65

66
      procedure, public :: get_n_mm_molecules &
67
                        => get_n_mm_molecules_input_tool
68

69
      procedure, public :: get_geometry &
70
                        => get_geometry_input_tool
71

72
      procedure, public :: get_mm_geometry_fq &
73
                        => get_mm_geometry_fq_input_tool
74

75
      procedure, public :: get_mm_geometry_non_polarizable &
76
                        => get_mm_geometry_non_polarizable_input_tool
77

78
      procedure, public :: get_reference_wavefunction
79
      procedure, public :: get_cc_wavefunction
80
      procedure, public :: get_ci_wavefunction
81

82
      procedure, public :: requested_reference_calculation
83
      procedure, public :: requested_cc_calculation
84
      procedure, public :: requested_ci_calculation
85

86
      generic, public :: get_keyword                &
87
                      => get_32bit_integer_keyword, &
88
                         get_64bit_integer_keyword, &
89
                         get_string_keyword,        &
90
                         get_real_dp_keyword
91

92
      generic, public :: get_required_keyword                 &
93
                      => get_required_string_keyword,         &
94
                         get_required_32bit_integer_keyword,  &
95
                         get_required_64bit_integer_keyword,  &
96
                         get_required_real_dp_keyword
97

98
      procedure, public :: get_n_elements_for_keyword
99

100
      generic, public :: get_array_for_keyword          &
101
                      => get_integer_array_for_keyword, &
102
                         get_real_array_for_keyword,    &
103
                         get_string_array_for_keyword
104

105
      procedure, public :: string_in_array_keyword   => string_in_array_keyword
106

107
      procedure, public :: cleanup &
108
                        => cleanup_input_tool
109

110
      procedure, public :: is_section_present &
111
                        => is_section_present_input_tool
112

113
      procedure, public :: is_keyword_present &
114
                        => is_keyword_present_input_tool
115

116
      procedure, public :: is_embedding_on &
117
                        => is_embedding_on_input_tool
118

119
      procedure, public :: place_records_in_memory &
120
                        => place_records_in_memory_input_tool
121

122
      procedure, public :: get_n_state_guesses
123
      procedure, public :: get_state_guesses
124

125
      procedure, private :: process_keyword_lines
126
      procedure, private :: set_section_keywords
127
      procedure, private :: check_for_errors
128

129
      procedure, private :: get_wavefunction
130
      procedure, private :: requested_calculation
131

132
      procedure, private :: get_section_index
133
      procedure, private :: print_sections
134

135
      procedure, private :: get_32bit_integer_keyword
136
      procedure, private :: get_64bit_integer_keyword
137
      procedure, private :: get_string_keyword
138
      procedure, private :: get_real_dp_keyword
139
      procedure, private :: get_required_string_keyword
140
      procedure, private :: get_required_32bit_integer_keyword
141
      procedure, private :: get_required_64bit_integer_keyword
142
      procedure, private :: get_required_real_dp_keyword
143

144
      procedure, private :: get_n_elements_in_set_or_range
145
      procedure, private :: get_integers_from_set_or_range
146

147
      procedure, private :: get_integer_array_for_keyword
148
      procedure, private :: get_real_array_for_keyword
149
      procedure, private :: get_string_array_for_keyword
150

151
      procedure, private, nopass :: expect_range
152
      procedure, private, nopass :: expect_set
153
      procedure, private, nopass :: check_get_array_for_keyword
154

155
      procedure, private :: is_section_recognized
156
      procedure, private :: section_not_recognized
157

158
   end type input_tool
159

160
   interface input_tool
161

162
      procedure :: new_input_tool
163

164
   end interface input_tool
165

166

167
contains
168

169

170
   function new_input_tool() result(this)
3,163✔
171
      !!
172
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, June 2018
173
      !!
174
      implicit none
175

176
      type(input_tool) :: this
177

178
      type(section) :: active_atoms
179
      type(section) :: active_space
180
      type(section) :: boson
181
      type(section) :: calculations
182
      type(section) :: cc_mean_value
183
      type(section) :: cc_response
184
      type(section) :: cc_real_time
185
      type(section) :: ci_mean_value
186
      type(section) :: ci_transition_property
187
      type(section) :: dft_functional
188
      type(section) :: electric_field
189
      type(section) :: grid_info
190
      type(section) :: harmonic_frequencies
191
      type(section) :: hf_mean_value
192
      type(section) :: hf_response
193
      type(section) :: integrals
194
      type(section) :: lanczos
195
      type(section) :: memory
196
      type(section) :: method
197
      type(section) :: mlcc
198
      type(section) :: mlhf
199
      type(section) :: mm
200
      type(section) :: orbital_localization
201
      type(section) :: pcm
202
      type(section) :: print_
203
      type(section) :: solver_cc_es
204
      type(section) :: solver_cc_gs
205
      type(section) :: solver_cc_multipliers
206
      type(section) :: solver_cc_propagation
207
      type(section) :: solver_cc_response
208
      type(section) :: solver_cholesky
209
      type(section) :: solver_ci
210
      type(section) :: solver_cpp
211
      type(section) :: solver_fft_dipole_moment
212
      type(section) :: solver_fft_electric_field
213
      type(section) :: solver_geoopt
214
      type(section) :: solver_scf
215
      type(section) :: solver_hf_es
216
      type(section) :: solver_hf_response
217
      type(section) :: system
218
      type(section) :: visualization
219

220
      allocate(this%rf_wfs, source=[character(len=30) :: &
221
                                       'dft',            &
222
                                       'hf',             &
223
                                       'uhf',            &
224
                                       'mlhf',           &
225
                                       'qed-hf',         &
226
                                       'sc-qed-hf',      &
227
                                       'cuhf',           &
228
                                       'rohf'])
53,771✔
229

230
      allocate(this%cc_wfs, source=[character(len=30) :: &
231
                                       'ccs',            &
232
                                       'mp2',            &
233
                                       'cc2',            &
234
                                       'lowmem-cc2',     &
235
                                       'ccsd',           &
236
                                       'cc3',            &
237
                                       'ccsd(t)',        &
238
                                       'ccsdt',          &
239
                                       'mlcc2',          &
240
                                       'mlccsd',         &
241
                                       'qed-ccsd'])
72,749✔
242

243
      allocate(this%ci_wfs, source=[character(len=30) :: 'casci',     &
244
                                                         'fci',       &
245
                                                         'qed-fci'])
22,141✔
246

247
      method = section(name_            = 'method', &
248
                       required         = .false.,  &
249
                       allowed_keywords = [this%rf_wfs, this%cc_wfs, this%ci_wfs])
142,335✔
250

251
      ! Set other sections in alphabetical order
252

253
      active_atoms = section(name_            = 'active atoms',       &
254
                             required         = .false.,              &
255
                             allowed_keywords = [character(len=30) :: &
256
                                                 'selection type',    &
257
                                                 'central atom',      &
258
                                                 'hf',                &
259
                                                 'ccs',               &
260
                                                 'cc2',               &
261
                                                 'ccsd',              &
262
                                                 'cc3',               &
263
                                                 'ccsd(t)',           &
264
                                                 'inactive basis',    &
265
                                                 'hf basis',          &
266
                                                 'ccs basis',         &
267
                                                 'cc2 basis',         &
268
                                                 'ccsd basis',        &
269
                                                 'cc3 basis',         &
270
                                                 'ccsd(t) basis'])
50,608✔
271

272

273
      active_space = section(name_            = 'active space',         &
274
                             required         = .false.,                &
275
                             allowed_keywords = [character(len=30) ::   &
276
                                                 'canonical',           &
277
                                                 'freeze core',         &
278
                                                 'freeze atom cores',   &
279
                                                 'localized'])
15,815✔
280

281

282
      boson = section(name_            = 'boson',                         &
283
                      required         = .false.,                         &
284
                      allowed_keywords = [character(len=30) ::            &
285
                                         'boson number',                  &
286
                                         'boson states',                  &
287
                                         'cbo',                           &
288
                                         'coherent state',                &
289
                                         'coupling bilinear',             &
290
                                         'coupling self',                 &
291
                                         'coupling',                      &
292
                                         'frequency',                     &
293
                                         'interaction type',              &
294
                                         'modes',                         &
295
                                         'polarization',                  &
296
                                         'print dipole eri construction', &
297
                                         'quadrupole oei',                &
298
                                         'wavevector'])
47,445✔
299

300

301
      calculations = section(name_            = 'do',                      &
302
                             required         = .false.,                   &
303
                             allowed_keywords = [character(len=30) ::      &
304
                                                'cholesky eri',            &
305
                                                'ground state',            &
306
                                                'geometry optimization',   &
307
                                                'harmonic frequencies',    &
308
                                                'excited state',           &
309
                                                'response',                &
310
                                                'mean value',              &
311
                                                'real time',               &
312
                                                'restart'])
31,630✔
313

314

315
      cc_mean_value = section(name_            = 'cc mean value',           &
316
                              required         = .false.,                   &
317
                              allowed_keywords = [character(len=30) ::      &
318
                                                 'dipole',                  &
319
                                                 'quadrupole',              &
320
                                                 'molecular gradient'])
12,652✔
321

322

323
      cc_response = section(name_            = 'cc response',         &
324
                            required         = .false.,               &
325
                            allowed_keywords = [character(len=30) ::  &
326
                                               'asymmetric',          &
327
                                               'damping',             &
328
                                               'dipole length',       &
329
                                               'dipole velocity',     &
330
                                               'dyson orbitals',      &
331
                                               'eom',                 &
332
                                               'frequencies',         &
333
                                               'initial states',      &
334
                                               'lr',                  &
335
                                               'permanent moments',   &
336
                                               'polarizabilities',    &
337
                                               'response components', &
338
                                               'rotatory strength',   &
339
                                               'transition moments',  &
340
                                               'full-space transition moments'])
50,608✔
341

342

343
      cc_real_time = section(name_            = 'cc real time',       &
344
                             required         = .false.,              &
345
                             allowed_keywords = [character(len=30) :: &
346
                                                'propagation',        &
347
                                                'fft dipole moment',  &
348
                                                'fft electric field'])
12,652✔
349

350

351
      ci_mean_value = section(name_            = 'ci mean value',     &
352
                              required         = .false.,             &
353
                              allowed_keywords = [character(len=30) ::&
354
                                                 'dipole',            &
355
                                                 'quadrupole'])
9,489✔
356

357

358
      ci_transition_property = section(name_            = 'ci transition property',  &
359
                                       required         = .false.,                   &
360
                                       allowed_keywords = [character(len=30) ::      &
361
                                                          'dipole',                  &
362
                                                          'quadrupole',              &
363
                                                          'final states',            &
364
                                                          'initial states'])
15,815✔
365

366

367
      dft_functional = section(name_            = 'dft functional',     &
368
                               required         = .false.,              &
369
                               allowed_keywords = [character(len=30) :: &
370
                                                  'correlation',        &
371
                                                  'exchange',           &
372
                                                  'functional',         &
373
                                                  'hf percentage'])
15,815✔
374

375

376
      electric_field = section(name_            = 'electric field',             &
377
                               required         = .false.,                      &
378
                               allowed_keywords = [character(len=30) ::         &
379
                                                  'envelope',                   &
380
                                                  'x polarization',             &
381
                                                  'y polarization',             &
382
                                                  'z polarization',             &
383
                                                  'central time',               &
384
                                                  'width',                      &
385
                                                  'carrier angular frequency',  &
386
                                                  'peak strength',              &
387
                                                  'phase shift',                &
388
                                                  'repetition',                 &
389
                                                  'separation'])
37,956✔
390

391

392
      harmonic_frequencies = section(name_            = 'harmonic frequencies',      &
393
                                     required         = .false.,                     &
394
                                     allowed_keywords = [character(len=30) ::        &
395
                                                        'gradient displacement',     &
396
                                                        'gradient method',           &
397
                                                        'hessian displacement',      &
398
                                                        'run geometry optimization', &
399
                                                        'state',                     &
400
                                                        'wigner samples',            &
401
                                                        'wigner seed'])
25,304✔
402

403

404
      grid_info = section(name_            = 'grid info',             &
405
                          required         = .false.,                 &
406
                          allowed_keywords = [character(len=30) ::    &
407
                                             'cube side',             &
408
                                             'cube offset',           &
409
                                             'minimum angular order', &
410
                                             'maximum angular order', &
411
                                             'partitioning',          &
412
                                             'radial threshold',      &
413
                                             'quadrature'])
25,304✔
414

415

416
      hf_mean_value = section(name_            = 'hf mean value',      &
417
                              required         = .false.,              &
418
                              allowed_keywords = [character(len=30) :: &
419
                                                 'dipole',             &
420
                                                 'molecular gradient', &
421
                                                 'quadrupole'])
12,652✔
422

423
      hf_response = section(name_            = 'hf response',        &
424
                            required         = .false.,              &
425
                            allowed_keywords = [character(len=30) :: &
426
                                              'shielding', &
427
                                              'polarizabilities'])
9,489✔
428

429

430
      integrals = section(name_            = 'integrals',          &
431
                          required         = .false.,              &
432
                          allowed_keywords = [character(len=30) :: &
433
                                             'cholesky storage',   &
434
                                             'eri storage',        &
435
                                             'mo eri in memory',   &
436
                                             'ri',                 &
437
                                             't1 eri in memory'])
18,978✔
438

439

440
      lanczos = section(name_            = 'lanczos',                &
441
                        required         = .false.,                  &
442
                        allowed_keywords = [character(len=30) ::     &
443
                                           'biorthogonalize last',   &
444
                                           'chain length',           &
445
                                           'deflation threshold',    &
446
                                           'lanczos normalization',  &
447
                                           'max energy',             &
448
                                           'min energy',             &
449
                                           'min transition strength',&
450
                                           'operators',              &
451
                                           'overlap threshold',      &
452
                                           'restart states',         &
453
                                           'skip convergence'])
37,956✔
454

455

456
      memory = section(name_            = 'memory',             &
457
                       required         = .false.,              &
458
                       allowed_keywords = [character(len=30) :: &
459
                                          'available',          &
460
                                          'unit'])
9,489✔
461

462

463
      mlcc = section(name_            = 'mlcc',                   &
464
                     required         = .false.,                  &
465
                     allowed_keywords = [character(len=30) ::     &
466
                                        'levels',                 &
467
                                        'cc2 orbitals',           &
468
                                        'ccsd orbitals',          &
469
                                        'cholesky threshold',     &
470
                                        'nto restart',            &
471
                                        'cnto restart',           &
472
                                        'orbital restart',        &
473
                                        'cnto occupied cc2',      &
474
                                        'cnto virtual cc2',       &
475
                                        'cnto occupied ccsd',     &
476
                                        'cnto virtual ccsd',      &
477
                                        'cnto states',            &
478
                                        'nto states',             &
479
                                        'nto occupied cc2',       &
480
                                        'nto occupied ccsd',      &
481
                                        'canonical virtual cc2',  &
482
                                        'canonical virtual ccsd', &
483
                                        'print ccs calculation',  &
484
                                        'print cc2 calculation'])
63,260✔
485

486

487
      mlhf = section(name_            = 'multilevel hf',            &
488
                     required         = .false.,                    &
489
                     allowed_keywords = [character(len=30) ::       &
490
                                        'initial hf optimization',  &
491
                                        'initial hf threshold',     &
492
                                        'print initial hf',         &
493
                                        'cholesky threshold',       &
494
                                        'project on minimal basis', &
495
                                        'cholesky virtuals',        &
496
                                        'no mo screening'])
25,304✔
497

498

499
      mm = section(name_            = 'molecular mechanics', &
500
                   required         = .false.,               &
501
                   allowed_keywords = [character(len=30) ::  &
502
                                      'forcefield',          &
503
                                      'algorithm '])
9,489✔
504

505

506
      orbital_localization = section(name_            = 'orbital localization', &
507
                                     required         = .false.,                &
508
                                     allowed_keywords = [character(len=30) ::   &
509
                                                         'orbitals',            &
510
                                                         'threshold',           &
511
                                                         'type'])
12,652✔
512

513

514
      pcm = section(name_            = 'pcm',                &
515
                    required         = .false.,              &
516
                    allowed_keywords = [character(len=30) :: &
517
                                       'solvent',            &
518
                                       'input',              &
519
                                       'tesserae area',      &
520
                                       'solver type'])
15,815✔
521

522

523
      print_ = section(name_            = 'print',               &
524
                       required         = .false.,               &
525
                       allowed_keywords = [character(len=30) ::  &
526
                                          'output print level ', &
527
                                          'timing print level ', &
528
                                          'full references',     &
529
                                          'z-matrix'])
15,815✔
530

531

532
      solver_cpp = section(name_    = 'solver cpp',                    &
533
                           required = .false.,                         &
534
                           allowed_keywords = [character(len=30) ::    &
535
                                              'max iterations',        &
536
                                              'max reduced dimension', &
537
                                              'residual minimization', &
538
                                              'residual threshold',    &
539
                                              'restart',               &
540
                                              'storage'])
22,141✔
541

542

543
      solver_cc_es = section(name_            = 'solver cc es',          &
544
                             required         = .false.,                 &
545
                             allowed_keywords = [character(len=30) ::    &
546
                                                'algorithm',             &
547
                                                'olsen',                 &
548
                                                'core excitation',       &
549
                                                'electron attachment',   &
550
                                                'ionization',            &
551
                                                'energy threshold ',     &
552
                                                'crop',                  &
553
                                                'residual threshold',    &
554
                                                'max iterations',        &
555
                                                'restart',               &
556
                                                'left eigenvectors',     &
557
                                                'right eigenvectors',    &
558
                                                'storage',               &
559
                                                'singlet states',        &
560
                                                'triplet states',        &
561
                                                'diis dimension',        &
562
                                                'max reduced dimension', &
563
                                                'max micro iterations',  &
564
                                                'rel micro threshold',   &
565
                                                'remove core',           &
566
                                                'state guesses'])
69,586✔
567

568

569
      solver_cc_gs = section(name_            = 'solver cc gs',            &
570
                             required         = .false.,                   &
571
                             allowed_keywords = [character(len=30) ::      &
572
                                                'algorithm',               &
573
                                                'energy threshold',        &
574
                                                'residual threshold',      &
575
                                                'crop',                    &
576
                                                'micro iteration storage', &
577
                                                'max micro iterations',    &
578
                                                'multimodel newton',       &
579
                                                'rel micro threshold',     &
580
                                                'storage',                 &
581
                                                'max iterations',          &
582
                                                'diis dimension',          &
583
                                                'restart' ])
41,119✔
584

585

586
      solver_cc_multipliers = section(name_            = 'solver cc multipliers',   &
587
                                      required         = .false.,                   &
588
                                      allowed_keywords = [character(len=30) ::      &
589
                                                         'algorithm',               &
590
                                                         'threshold',               &
591
                                                         'storage',                 &
592
                                                         'crop',                    &
593
                                                         'micro iteration storage', &
594
                                                         'max micro iterations',    &
595
                                                         'multimodel newton',       &
596
                                                         'rel micro threshold',     &
597
                                                         'diis dimension',          &
598
                                                         'restart',                 &
599
                                                         'max reduced dimension',   &
600
                                                         'max iterations'])
41,119✔
601

602

603
      solver_cc_propagation = section(name_            = 'solver cc propagation',    &
604
                                      required         = .false.,                    &
605
                                      allowed_keywords = [character(len=30) ::       &
606
                                                         'initial time',             &
607
                                                         'final time',               &
608
                                                         'time step',                &
609
                                                         'steps between output',     &
610
                                                         'step reduction factor',    &
611
                                                         'implicit threshold',       &
612
                                                         'max error',                &
613
                                                         'min error',                &
614
                                                         'energy output',            &
615
                                                         'dipole moment output',     &
616
                                                         'electric field output',    &
617
                                                         'parameters output',        &
618
                                                         'mo density matrix output', &
619
                                                         'method',                   &
620
                                                         'integrator'])
50,608✔
621

622

623
      solver_cc_response = section(name_            = 'solver cc response', &
624
                                   required         = .false.,              &
625
                                   allowed_keywords = [character(len=30) :: &
626
                                                      'threshold',          &
627
                                                      'gradient response threshold', &
628
                                                      'storage',            &
629
                                                      'max iterations'])
15,815✔
630

631

632
      solver_cholesky = section(name_            = 'solver cholesky',    &
633
                                required         = .false.,              &
634
                                allowed_keywords = [character(len=30) :: &
635
                                                   'threshold',          &
636
                                                   'span',               &
637
                                                   'batches',            &
638
                                                   'qualified',          &
639
                                                   'one center',         &
640
                                                   'diagonal test',      &
641
                                                   'mo screening'])
25,304✔
642

643

644
      solver_ci = section(name_            = 'solver ci',              &
645
                          required         = .false.,                  &
646
                          allowed_keywords = [character(len=30) ::     &
647
                                              'energy threshold ',     &
648
                                              'max iterations',        &
649
                                              'max reduced dimension', &
650
                                              'residual threshold',    &
651
                                              'restart',               &
652
                                              'start guess',           &
653
                                              'states',                &
654
                                              'storage'])
28,467✔
655

656
      solver_fft_dipole_moment = section(name_            = 'solver fft dipole moment', &
657
                                         required         = .false.,                    &
658
                                         allowed_keywords = [character(len=30) ::       &
659
                                                            'initial time',             &
660
                                                            'final time',               &
661
                                                            'time step',                &
662
                                                            'padding initial time',     &
663
                                                            'hann window',              &
664
                                                            'rectangular window'])
22,141✔
665

666

667
      solver_fft_electric_field = section(name_            = 'solver fft electric field', &
668
                                          required         = .false.,                     &
669
                                          allowed_keywords = [character(len=30) ::        &
670
                                                             'initial time',              &
671
                                                             'final time',                &
672
                                                             'time step',                 &
673
                                                             'padding initial time',      &
674
                                                             'hann window',               &
675
                                                             'rectangular window'])
22,141✔
676

677

678
      solver_geoopt = section(name_            = 'solver geometry optimization',              &
679
                              required         = .false.,                      &
680
                              allowed_keywords = [character(len=30) ::         &
681
                                                 'algorithm',                  &
682
                                                 'energy threshold',           &
683
                                                 'residual threshold',         &
684
                                                 'residual rms threshold',     &
685
                                                 'state',                      &
686
                                                 'max iterations',             &
687
                                                 'max step',                   &
688
                                                 'gradient method',            &
689
                                                 'restart',                    &
690
                                                 'step size',                  &
691
                                                 'displacement threshold',     &
692
                                                 'displacement rms threshold'])
41,119✔
693

694

695
      solver_scf = section(name_            = 'solver scf',                  &
696
                           required         = .false.,                       &
697
                           allowed_keywords = [character(len=30) ::          &
698
                                              'algorithm',                   &
699
                                              'ao density guess',            &
700
                                              'coulomb exchange terms',      &
701
                                              'coulomb threshold',           &
702
                                              'crop',                        &
703
                                              'cumulative fock threshold',   &
704
                                              'diis dimension',              &
705
                                              'diabatize orbitals',          &
706
                                              'energy threshold',            &
707
                                              'exchange threshold',          &
708
                                              'residual threshold',          &
709
                                              'gradient response threshold', &
710
                                              'max iterations',              &
711
                                              'population analysis',         &
712
                                              'write orbitals',              &
713
                                              'restart',                     &
714
                                              'rohf coupling parameters',    &
715
                                              'skip',                        &
716
                                              'storage',                     &
717
                                              'write molden'])
66,423✔
718

719

720
      solver_hf_es = section(name_            = 'solver hf es',         &
721
                               required         = .false.,                  &
722
                               allowed_keywords = [character(len=30) ::     &
723
                                                  'energy threshold',       &
724
                                                  'max iterations',         &
725
                                                  'max reduced dimension',  &
726
                                                  'residual threshold',     &
727
                                                  'restart',                &
728
                                                  'storage',                &
729
                                                  'singlet states',         &
730
                                                  'tamm-dancoff'])
28,467✔
731

732

733
      solver_hf_response = section(name_           = 'solver hf response',       &
734
                                  required         = .false.,                    &
735
                                  allowed_keywords = [character(len=30) ::       &
736
                                                        'frequencies',           &
737
                                                        'max iterations',        &
738
                                                        'max reduced dimension', &
739
                                                        'print iterations',      &
740
                                                        'residual threshold',    &
741
                                                        'restart',               &
742
                                                        'storage'])
25,304✔
743

744

745
      system = section(name_            = 'system',               &
746
                       required         = .false.,                &
747
                       allowed_keywords = [character(len=30) ::   &
748
                                          'cartesian gaussians',  &
749
                                          'write orbitals',       &
750
                                          'pure gaussians',       &
751
                                          'charge',               &
752
                                          'multiplicity'])
18,978✔
753

754

755
      visualization = section(name_            = 'visualization',             &
756
                              required         = .false.,                     &
757
                              allowed_keywords = [character(len=30) ::        &
758
                                                 'file format',               &
759
                                                 'grid spacing',              &
760
                                                 'grid buffer',               &
761
                                                 'grid min',                  &
762
                                                 'grid max',                  &
763
                                                 'plot cc density',           &
764
                                                 'plot cc orbitals',          &
765
                                                 'plot dyson orbitals',       &
766
                                                 'plot es densities',         &
767
                                                 'plot hf orbitals',          &
768
                                                 'plot hf density',           &
769
                                                 'plot hf active density',    &
770
                                                 'plot cntos',                &
771
                                                 'plot ntos',                 &
772
                                                 'nto threshold',             &
773
                                                 'plot transition densities', &
774
                                                 'states to plot'])
56,934✔
775

776
      ! Gather all sections into the file's section array
777

778
      this%sections = [active_atoms,              &
779
                       active_space,              &
780
                       boson,                     &
781
                       calculations,              &
782
                       cc_mean_value,             &
783
                       cc_response,               &
784
                       cc_real_time,              &
785
                       ci_mean_value,             &
786
                       ci_transition_property,    &
787
                       dft_functional,            &
788
                       electric_field,            &
789
                       grid_info,                 &
790
                       harmonic_frequencies,      &
791
                       hf_mean_value,             &
792
                       hf_response,               &
793
                       integrals,                 &
794
                       lanczos,                   &
795
                       memory,                    &
796
                       method,                    &
797
                       mlcc,                      &
798
                       mlhf,                      &
799
                       mm,                        &
800
                       orbital_localization,      &
801
                       pcm,                       &
802
                       print_,                    &
803
                       solver_cc_es,              &
804
                       solver_cc_gs,              &
805
                       solver_cc_multipliers,     &
806
                       solver_cc_propagation,     &
807
                       solver_cc_response,        &
808
                       solver_cholesky,           &
809
                       solver_ci,                 &
810
                       solver_cpp,                &
811
                       solver_fft_dipole_moment,  &
812
                       solver_fft_electric_field, &
813
                       solver_geoopt,             &
814
                       solver_scf,                &
815
                       solver_hf_es,            &
816
                       solver_hf_response,      &
817
                       system,                    &
818
                       visualization]
265,692✔
819

820
   end function new_input_tool
3,163✔
821

822

823
   subroutine read_input(this, file_name)
3,151✔
824
      !!
825
      !! Written by Eirik F. Kjønstad, May 2022
826
      !!
827
      use input_file_parser_class, only: input_file_parser
828

829
      implicit none
830

831
      class(input_tool), intent(inout) :: this
832

833
      character(len=*), intent(in) :: file_name
834

835
      type(input_file_parser), allocatable :: file_parser
836

837
      file_parser = input_file_parser(file_name)
3,151✔
838

839
      call file_parser%read_and_process_input_file()
3,151✔
840
      call file_parser%get_keyword_lines(this%keyword_lines, this%n_keyword_lines)
3,151✔
841
      call file_parser%get_qm_geometry_lines(this%qm_geometry, this%n_qm_atom_lines)
3,151✔
842

843
      if (file_parser%is_mm_geometry_present()) &
3,151✔
844
         call file_parser%get_mm_geometry_lines(this%mm_geometry, this%n_mm_atom_lines)
96✔
845

846
      deallocate(file_parser)
3,151✔
847

848
   end subroutine read_input
3,151✔
849

850

851
   subroutine process_input(this)
3,163✔
852
      !!
853
      !! Written by Eirik F. Kjønstad, Mar 2024
854
      !!
855
      implicit none
856

857
      class(input_tool), intent(inout) :: this
858

859
      call this%process_keyword_lines()
3,163✔
860
      call this%print_input_except_geometry()
3,163✔
861
      call this%check_for_errors()
3,163✔
862

863
   end subroutine process_input
3,163✔
864

865

866
   subroutine print_input_except_geometry(this)
3,163✔
867
      !!
868
      !! Written by Eirik F. Kjønstad, May 2022
869
      !!
870
      implicit none
871

872
      class(input_tool), intent(in) :: this
873

874
      integer :: n
875

876
      call output%printf('m', ':: Input file', fs='(//t3,a)')
3,163✔
877
      call output%print_separator('m', 13, '=', fs='(t3,a/)')
3,163✔
878

879
      call output%printf('m', 'Note: geometry section is excluded from this print.', fs='(t6,a/)')
3,163✔
880

881
      do n = 1, this%n_keyword_lines
105,053✔
882

883
         call output%printf('m', this%keyword_lines(n), fs='(t6,a)', ll=120)
105,053✔
884

885
      enddo
886

887
   end subroutine print_input_except_geometry
3,163✔
888

889

890
   subroutine set_input(this, keywords, geometry, mm_geometry)
12✔
891
      !!
892
      !! Written by Eirik F. Kjønstad, Mar 2024
893
      !!
894
      implicit none
895

896
      class(input_tool) :: this
897

898
      character(len=200), dimension(:), intent(in), optional :: keywords
899
      character(len=200), dimension(:), intent(in), optional :: geometry
900
      character(len=200), dimension(:), intent(in), optional :: mm_geometry
901

902
      if (present(geometry)) then
12✔
903

904
         this%qm_geometry = geometry
30✔
905
         this%n_qm_atom_lines = size(geometry)
6✔
906

907
      else
908

909
         allocate(this%qm_geometry, &
×
910
                  source=[character(len=200) :: '! no geometry'])
18✔
911

912
         this%n_qm_atom_lines = 1
6✔
913

914
      endif
915

916
      if (present(keywords)) then
12✔
917

918
         this%keyword_lines = keywords
24✔
919
         this%n_keyword_lines = size(keywords)
6✔
920

921
      else
922

923
         allocate(this%keyword_lines, &
×
924
                  source=[character(len=200) :: '! no input keywords'])
18✔
925

926
         this%n_keyword_lines = 1
6✔
927

928
      endif
929

930
      if (present(mm_geometry)) then
12✔
931

932
         this%mm_geometry = mm_geometry
×
933
         this%n_mm_atom_lines = size(mm_geometry)
×
934

935
      endif
936

937
   end subroutine set_input
12✔
938

939

940
   subroutine process_keyword_lines(this)
3,163✔
941
      !!
942
      !! Written by Sara Angelico and Alexander C. Paul, 2023
943
      !!
944
      implicit none
945

946
      class(input_tool), intent(inout) :: this
947

948
      integer :: start_, end_, i, j
949

950
      character(len=200) :: section, line, section_line
951

952
      do i = 1, this%n_keyword_lines
105,053✔
953

954
         line = trim(adjustl(this%keyword_lines(i)))
101,890✔
955

956
         if (.not. string_starts_with(line, '-')) cycle
101,890✔
957

958
         start_ = i + 1
25,526✔
959
         section = trim(adjustl(line(2:)))
25,526✔
960

961
         section = remove_substring_after_symbol(section,"!")
25,526✔
962

963
         if (.not. this%is_section_recognized(section)) call this%section_not_recognized(section)
25,526✔
964

965
         end_ = this%n_keyword_lines
25,526✔
966
         do j = start_, this%n_keyword_lines
101,872✔
967

968
            section_line = trim(adjustl(this%keyword_lines(j)))
98,715✔
969

970
            if (.not. string_starts_with(section_line, '-')) cycle
98,715✔
971

972
            end_ = j - 1
22,369✔
973
            exit
101,872✔
974

975
         enddo
976

977
         call this%set_section_keywords(section, this%keyword_lines(start_:end_))
105,053✔
978

979
      enddo
980

981
   end subroutine process_keyword_lines
3,163✔
982

983

984
   subroutine print_sections(this)
×
985
      !!
986
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
987
      !!
988
      implicit none
989

990
      class(input_tool), intent(in) :: this
991

992
      integer :: k
993

994
      call output%printf('m', 'The valid input sections are:', fs='(/t3,a/)')
×
995

996
      do k = 1, size(this%sections)
×
997

998
         call output%printf('m', '(a0)', chars=[trim(this%sections(k)%name_)], fs='(t6,a)')
×
999

1000
      enddo
1001

1002
   end subroutine print_sections
×
1003

1004

1005
   function requested_reference_calculation(this) result(requested)
2,987✔
1006
      !!
1007
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Apr 2019
1008
      !!
1009
      implicit none
1010

1011
      class(input_tool), intent(in) :: this
1012

1013
      logical :: requested
1014

1015
      requested = this%requested_calculation(this%rf_wfs)
2,987✔
1016

1017
   end function requested_reference_calculation
2,987✔
1018

1019

1020
   function requested_calculation(this, wfs) result(requested)
7,256✔
1021
      !!
1022
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Apr 2019
1023
      !!
1024
      !! Looks for wfs(k) in method and returns true if it finds one such wf
1025
      !! in the input file. Gives an error if it finds more than one of wfs(k).
1026
      !!
1027
      implicit none
1028

1029
      class(input_tool), intent(in) :: this
1030

1031
      character(len=30), dimension(:), intent(in) :: wfs
1032

1033
      logical :: requested
1034

1035
      integer :: n_wfs, k, section_index
1036

1037
      n_wfs = 0
1038

1039
      section_index = this%get_section_index('method')
7,256✔
1040

1041
      do k = 1, size(wfs)
70,223✔
1042

1043
         if (this%sections(section_index)%is_keyword_present(wfs(k))) then
70,223✔
1044

1045
            n_wfs = n_wfs + 1
5,402✔
1046

1047
         endif
1048

1049
      enddo
1050

1051
      requested = .false.
1052

1053
      if (n_wfs == 1) then
7,256✔
1054

1055
         requested = .true.
1056

1057
      elseif (n_wfs > 1) then
1,854✔
1058

1059
         call output%error_msg('Requested more than one method &
1060
                               &of a single kind (e.g., two CC methods).')
×
1061

1062
      endif
1063

1064
   end function requested_calculation
7,256✔
1065

1066

1067
   function requested_cc_calculation(this) result(requested)
3,283✔
1068
      !!
1069
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Apr 2019
1070
      !!
1071
      implicit none
1072

1073
      class(input_tool), intent(in) :: this
1074

1075
      logical :: requested
1076

1077
      requested = this%requested_calculation(this%cc_wfs)
3,283✔
1078

1079
   end function requested_cc_calculation
3,283✔
1080

1081

1082
   function requested_ci_calculation(this) result(requested)
986✔
1083
      !!
1084
      !! Written by Enrico Ronca, 2020
1085
      !!
1086
      implicit none
1087

1088
      class(input_tool), intent(in) :: this
1089

1090
      logical :: requested
1091

1092
      requested = this%requested_calculation(this%ci_wfs)
986✔
1093

1094
   end function requested_ci_calculation
986✔
1095

1096

1097
   function get_reference_wavefunction(this) result(ref_wf)
3,145✔
1098
      !!
1099
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Apr 2019
1100
      !!
1101
      implicit none
1102

1103
      class(input_tool), intent(in) :: this
1104

1105
      character(len=30) :: ref_wf
1106

1107
      ref_wf = this%get_wavefunction(this%rf_wfs)
3,145✔
1108

1109
   end function get_reference_wavefunction
3,145✔
1110

1111

1112
   function get_cc_wavefunction(this) result(cc_wf)
2,055✔
1113
      !!
1114
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Apr 2019
1115
      !!
1116
      implicit none
1117

1118
      class(input_tool), intent(in) :: this
1119

1120
      character(len=30) :: cc_wf
1121

1122
      cc_wf = this%get_wavefunction(this%cc_wfs)
2,055✔
1123

1124
   end function get_cc_wavefunction
2,055✔
1125

1126

1127
   function get_ci_wavefunction(this) result(ci_wf)
312✔
1128
      !!
1129
      !! Written by Enrico Ronca, Apr 2020
1130
      !!
1131
      implicit none
1132

1133
      class(input_tool), intent(in) :: this
1134

1135
      character(len=30) :: ci_wf
1136

1137
      ci_wf = this%get_wavefunction(this%ci_wfs)
312✔
1138

1139
   end function get_ci_wavefunction
312✔
1140

1141

1142
   function get_wavefunction(this, wfs) result(wf)
5,512✔
1143
      !!
1144
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Apr 2019
1145
      !!
1146
      !! Looks for wfs(k) in the 'method' section of the input.
1147
      !!
1148
      implicit none
1149

1150
      class(input_tool), intent(in) :: this
1151

1152
      character(len=30), dimension(:), intent(in) :: wfs
1153

1154
      character(len=30) :: wf
1155

1156
      integer :: k, section_index
1157

1158
      section_index = this%get_section_index('method')
5,512✔
1159

1160
      do k = 1, size(wfs)
19,740✔
1161

1162
         if (this%sections(section_index)%is_keyword_present(wfs(k))) then
19,740✔
1163

1164
            wf = wfs(k)
5,512✔
1165
            return
5,512✔
1166

1167
         endif
1168

1169
      enddo
1170

1171
      call output%error_msg('Failed to read wavefunction from input. &
1172
         & Did you forget to specify all wavefunctions for the calculation?')
×
1173

1174
   end function get_wavefunction
1175

1176

1177
   subroutine get_32bit_integer_keyword(this, keyword, section, keyword_value)
27,802✔
1178
      !!
1179
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1180
      !!
1181
      !! If specified, reads keyword as an integer into keyword value.
1182
      !!
1183
      implicit none
1184

1185
      class(input_tool), intent(in) :: this
1186

1187
      character(len=*), intent(in) :: keyword
1188
      character(len=*), intent(in) :: section
1189

1190
      integer(i32), intent(inout) :: keyword_value
1191

1192
      character(len=200) :: keyword_value_string
1193

1194
      keyword_value_string = ""
27,802✔
1195
      call this%get_string_keyword(keyword, section, keyword_value_string)
27,802✔
1196

1197
      if (is_empty(keyword_value_string)) return
27,802✔
1198

1199
      read(keyword_value_string, *) keyword_value
4,155✔
1200

1201
   end subroutine get_32bit_integer_keyword
1202

1203

1204
   subroutine get_64bit_integer_keyword(this, keyword, section, keyword_value)
59,291✔
1205
      !!
1206
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1207
      !!
1208
      !! If specified, reads keyword as an integer into keyword value.
1209
      !!
1210
      implicit none
1211

1212
      class(input_tool), intent(in) :: this
1213

1214
      character(len=*), intent(in) :: keyword
1215
      character(len=*), intent(in) :: section
1216

1217
      integer(i64), intent(inout) :: keyword_value
1218

1219
      character(len=200) :: keyword_value_string
1220

1221
      keyword_value_string = ""
59,291✔
1222
      call this%get_string_keyword(keyword, section, keyword_value_string)
59,291✔
1223

1224
      if (is_empty(keyword_value_string)) return
59,291✔
1225

1226
      read(keyword_value_string, *) keyword_value
11,216✔
1227

1228
   end subroutine get_64bit_integer_keyword
1229

1230

1231
   subroutine get_required_32bit_integer_keyword(this, keyword, section, keyword_value)
412✔
1232
      !!
1233
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1234
      !!
1235
      !! Reads keyword as an integer into keyword value. If the keyword or the
1236
      !! section is not specified, an error occurs because the keyword is "required".
1237
      !!
1238
      implicit none
1239

1240
      class(input_tool), intent(in) :: this
1241

1242
      character(len=*), intent(in) :: keyword
1243
      character(len=*), intent(in) :: section
1244

1245
      integer(i32), intent(inout) :: keyword_value
1246

1247
      character(len=200) :: keyword_value_string
1248

1249
      keyword_value_string = ""
412✔
1250
      call this%get_string_keyword(keyword, section, keyword_value_string)
412✔
1251

1252
      if (is_empty(keyword_value_string)) then
412✔
1253
         call output%error_msg('could not find the required keyword '// trim(keyword) // &
1254
                               ' in section ' // trim(section))
×
1255

1256
      endif
1257

1258
      read(keyword_value_string, *) keyword_value
412✔
1259

1260
   end subroutine get_required_32bit_integer_keyword
412✔
1261

1262

1263
   subroutine get_required_64bit_integer_keyword(this, keyword, section, keyword_value)
876✔
1264
      !!
1265
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1266
      !!
1267
      !! Reads keyword as an integer into keyword value. If the keyword or the
1268
      !! section is not specified, an error occurs because the keyword is "required".
1269
      !!
1270
      implicit none
1271

1272
      class(input_tool), intent(in) :: this
1273

1274
      character(len=*), intent(in) :: keyword
1275
      character(len=*), intent(in) :: section
1276

1277
      integer(i64), intent(out) :: keyword_value
1278

1279
      character(len=200) :: keyword_value_string
1280

1281
      keyword_value_string = ""
876✔
1282
      call this%get_string_keyword(keyword, section, keyword_value_string)
876✔
1283

1284
      if (is_empty(keyword_value_string)) then
876✔
1285
         call output%error_msg('could not find the required keyword '// trim(keyword) // &
1286
                               ' in section ' // trim(section))
×
1287

1288
      endif
1289

1290
      read(keyword_value_string, *) keyword_value
876✔
1291

1292
   end subroutine get_required_64bit_integer_keyword
876✔
1293

1294

1295
   subroutine get_real_dp_keyword(this, keyword, section, keyword_value)
75,058✔
1296
      !!
1297
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1298
      !!
1299
      !! If specified, reads keyword as a real double precision into keyword value.
1300
      !!
1301
      implicit none
1302

1303
      class(input_tool), intent(in) :: this
1304

1305
      character(len=*), intent(in) :: keyword
1306
      character(len=*), intent(in) :: section
1307

1308
      real(dp), intent(inout) :: keyword_value
1309

1310
      character(len=200) :: keyword_value_string
1311

1312
      keyword_value_string = ""
75,058✔
1313
      call this%get_string_keyword(keyword, section, keyword_value_string)
75,058✔
1314

1315
      if (is_empty(keyword_value_string)) return
75,058✔
1316

1317
      read(keyword_value_string, *) keyword_value
61,179✔
1318

1319
   end subroutine get_real_dp_keyword
1320

1321

1322
   subroutine get_required_real_dp_keyword(this, keyword, section, keyword_value)
486✔
1323
      !!
1324
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1325
      !!
1326
      !! Reads keyword as an double precision into keyword value. If the keyword or the
1327
      !! section is not specified, an error occurs because the keyword is "required".
1328
      !!
1329
      implicit none
1330

1331
      class(input_tool), intent(in) :: this
1332

1333
      character(len=*), intent(in) :: keyword
1334
      character(len=*), intent(in) :: section
1335

1336
      real(dp), intent(out) :: keyword_value
1337

1338
      character(len=200) :: keyword_value_string
1339

1340
      keyword_value_string = ""
486✔
1341
      call this%get_string_keyword(keyword, section, keyword_value_string)
486✔
1342

1343
      if (is_empty(keyword_value_string)) then
486✔
1344
         call output%error_msg('could not find the required keyword '// trim(keyword) // &
1345
                               ' in section ' // trim(section))
×
1346

1347
      endif
1348

1349
      read(keyword_value_string, *) keyword_value
486✔
1350

1351
   end subroutine get_required_real_dp_keyword
486✔
1352

1353

1354
   subroutine get_string_keyword(this, keyword, section, keyword_value)
295,170✔
1355
      !!
1356
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1357
      !!
1358
      !! If specified, reads keyword as a string into keyword value.
1359
      !!
1360
      implicit none
1361

1362
      class(input_tool), intent(in) :: this
1363

1364
      character(len=*), intent(in) :: keyword
1365
      character(len=*), intent(in) :: section
1366

1367
      character(len=200), intent(inout) :: keyword_value
1368
      character(len=200) :: keyword_value_string
1369

1370
      integer :: section_index
1371

1372
      section_index = this%get_section_index(section)
295,170✔
1373

1374
      keyword_value_string = this%sections(section_index)%get_string_keyword(keyword)
295,170✔
1375

1376
      ! Make sure not to overwrite defaults set on the outside
1377
      if (is_empty(keyword_value_string)) return
295,170✔
1378

1379
      keyword_value = keyword_value_string
106,745✔
1380

1381
   end subroutine get_string_keyword
1382

1383

1384
   subroutine get_required_string_keyword(this, keyword, section, keyword_value)
756✔
1385
      !!
1386
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1387
      !!
1388
      !! If specified, reads keyword as a string into keyword value.
1389
      !!
1390
      implicit none
1391

1392
      class(input_tool), intent(in) :: this
1393

1394
      character(len=*), intent(in) :: keyword
1395
      character(len=*), intent(in) :: section
1396

1397
      character(len=200) :: keyword_value
1398

1399
      keyword_value = ""
756✔
1400
      call this%get_string_keyword(keyword, section, keyword_value)
756✔
1401

1402
      if (is_empty(keyword_value)) then
756✔
1403
         call output%error_msg('could not find the required keyword '// trim(keyword) // &
1404
                               ' in section ' // trim(section))
×
1405

1406
      endif
1407

1408
   end subroutine get_required_string_keyword
756✔
1409

1410

1411
   function get_section_index(this, section) result(index)
1,017,990✔
1412
      !!
1413
      !! Written by Sara Angelico and Alexander C. Paul, Feb 2023
1414
      !!
1415
      implicit none
1416

1417
      class(input_tool), intent(in) :: this
1418

1419
      character(len=*), intent(in) :: section
1420

1421
      integer :: index, i
1422

1423
      index = 0
1424

1425
      do i = 1, size(this%sections)
28,443,591✔
1426
         if(trim(this%sections(i)%name_) == trim(section)) then
28,443,591✔
1427
            index = i
1428
            return
1,017,990✔
1429
         end if
1430
      enddo
1431

1432
      call this%section_not_recognized(section)
×
1433

1434
   end function get_section_index
×
1435

1436

1437
   function is_keyword_present_input_tool(this, keyword, section) result(is_present)
643,116✔
1438
      !!
1439
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1440
      !!
1441
      !! Returns true if the keyword is in the section.
1442
      !!
1443
      implicit none
1444

1445
      class(input_tool), intent(in) :: this
1446

1447
      character(len=*), intent(in) :: keyword
1448
      character(len=*), intent(in) :: section
1449

1450
      logical :: is_present
1451

1452
      integer :: section_index
1453

1454
      section_index = this%get_section_index(section)
643,116✔
1455

1456
      is_present = this%sections(section_index)%is_keyword_present(keyword)
643,116✔
1457

1458
   end function is_keyword_present_input_tool
643,116✔
1459

1460

1461
   function is_section_present_input_tool(this, section) result(is_present)
41,410✔
1462
      !!
1463
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1464
      !!
1465
      !! Returns true if the section exists, false if it doesn't.
1466
      !!
1467
      implicit none
1468

1469
      class(input_tool), intent(in) :: this
1470

1471
      character(len=*), intent(in) :: section
1472

1473
      logical :: is_present
1474

1475
      integer :: section_index
1476

1477
      section_index = this%get_section_index(section)
41,410✔
1478

1479
      is_present = this%sections(section_index)%is_section_present()
41,410✔
1480

1481
   end function is_section_present_input_tool
41,410✔
1482

1483

1484
   function get_n_elements_for_keyword(this, keyword, section) result(n_elements)
2,736✔
1485
      !!
1486
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1487
      !!
1488
      !! Gets the number of elements specified for a keyword in set/range notation
1489
      !!
1490
      !! Ranges should always be given as [a,b].
1491
      !! Lists should always be given as {a, b, c, d}.
1492
      !!
1493
      !! Function is called in preparation for get_array_for_keyword
1494
      !!
1495
      implicit none
1496

1497
      class(input_tool), intent(in) :: this
1498

1499
      character(len=*), intent(in) :: keyword
1500
      character(len=*), intent(in) :: section
1501

1502
      integer :: n_elements
1503

1504
      character(len=200) :: keyword_value_string
1505

1506
      n_elements = 0
1507

1508
      call this%get_keyword(keyword, section, keyword_value_string)
2,736✔
1509

1510
      n_elements = this%get_n_elements_in_set_or_range(keyword_value_string)
2,736✔
1511

1512
   end function get_n_elements_for_keyword
2,736✔
1513

1514

1515
   subroutine get_integer_array_for_keyword(this, keyword, section, n_elements, array_)
1,664✔
1516
      !!
1517
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1518
      !!
1519
      !! Gets input variable array (array_) for keyword which is specified on input
1520
      !! by either an integer range or list (of length n_elements).
1521
      !!
1522
      !! Ranges should always be given as [a,b].
1523
      !! Lists should always be given as {a, b, c, d}.
1524
      !!
1525
      !! Routine should be called after the get_n_elements_for_keyword is called
1526
      !! in order to determine n_elements so that array_ can be allocated.
1527
      !!
1528
      implicit none
1529

1530
      class(input_tool), intent(in) :: this
1531

1532
      character(len=*), intent(in) :: keyword
1533
      character(len=*), intent(in) :: section
1534

1535
      integer, intent(in) :: n_elements
1536

1537
      integer, dimension(n_elements) :: array_
1538

1539
      character(len=200) :: keyword_value_string
1540

1541
      call check_get_array_for_keyword(keyword, section, n_elements)
1,664✔
1542

1543
      call this%get_keyword(keyword, section, keyword_value_string)
1,664✔
1544

1545
      call this%get_integers_from_set_or_range(keyword_value_string, n_elements, array_)
1,664✔
1546

1547
   end subroutine get_integer_array_for_keyword
1,664✔
1548

1549

1550
   subroutine get_real_array_for_keyword(this, keyword, section, n_elements, array_)
3,572✔
1551
      !!
1552
      !! Written by Sarai D. Folkestad, Eirik F. Kjønstad, Andreas Skeidsvoll and Alexander C. Paul, 2019-2023
1553
      !!
1554
      !! Gets input variable array (array_) for keyword
1555
      !! which is specified on input by a list
1556
      !!
1557
      !! Lists should always be given as {a, b, c, d}
1558
      !!
1559
      !! Routine should be called after the get_n_elements_for_keyword is called
1560
      !! in order to determine n_elements so that array_ can be allocated.
1561
      !!
1562
      use string_utilities, only: read_comma_separated_list
1563

1564
      implicit none
1565

1566
      class(input_tool), intent(in) :: this
1567

1568
      character(len=*), intent(in) :: keyword
1569
      character(len=*), intent(in) :: section
1570
      integer,          intent(in) :: n_elements
1571

1572
      real(dp), dimension(n_elements), intent(inout) :: array_
1573

1574
      character(len=200) :: keyword_value_string
1575
      character(len=:), allocatable :: string
1576

1577
      call check_get_array_for_keyword(keyword, section, n_elements)
3,572✔
1578

1579
      call this%get_keyword(keyword, section, keyword_value_string)
3,572✔
1580

1581
      string = trim(adjustl(keyword_value_string))
3,572✔
1582
      call this%expect_set(string)
3,572✔
1583

1584
      call read_comma_separated_list(string(2:len(string)-1), array_, n_elements)
3,572✔
1585

1586
   end subroutine get_real_array_for_keyword
3,572✔
1587

1588

1589
   subroutine get_string_array_for_keyword(this, keyword, section, n_elements, array_)
126✔
1590
      !!
1591
      !! Written by Anna Kristina Schnack-Petersen and Alexander C. Paul, 2022-2023
1592
      !!
1593
      !! Gets input variable array (array_) for keyword which is specified on input
1594
      !! by a list of strings (of length n_elements).
1595
      !!
1596
      !! Lists should always be given as {a, b, c, d}
1597
      !!
1598
      !! Routine should be called after the get_n_elements_for_keyword is called
1599
      !! in order to determine n_elements so that array_ can be allocated.
1600
      !!
1601
      use string_utilities, only: split_at_delimiter
1602

1603
      implicit none
1604

1605
      class(input_tool), intent(in) :: this
1606

1607
      character(len=*), intent(in) :: keyword
1608
      character(len=*), intent(in) :: section
1609
      integer,          intent(in) :: n_elements
1610

1611
      character(len=200), dimension(n_elements), intent(inout) :: array_
1612

1613
      character(len=200)            :: keyword_value_string
1614
      character(len=:), allocatable :: string
1615

1616
      call check_get_array_for_keyword(keyword, section, n_elements)
126✔
1617

1618
      call this%get_keyword(keyword, section, keyword_value_string)
126✔
1619

1620
      string = trim(adjustl(keyword_value_string))
126✔
1621
      call this%expect_set(string)
126✔
1622

1623
      call split_at_delimiter(string(2:len(string)-1), n_elements-1, array_, ',')
126✔
1624

1625
   end subroutine get_string_array_for_keyword
126✔
1626

1627

1628
   pure function get_n_atoms_input_tool(this) result(n_atoms)
3,163✔
1629
      !!
1630
      !! Get n atoms
1631
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1632
      !!
1633
      !! Reads the geometry section of the input and counts the number of atoms
1634
      !!
1635
      implicit none
1636

1637
      class(input_tool), intent(in) :: this
1638

1639
      integer :: n_atoms
1640

1641
      integer :: record
1642

1643
      n_atoms = 0
1644

1645
      do record = 1, this%n_qm_atom_lines
19,396✔
1646

1647
         if (this%qm_geometry(record)(1:6) .ne. 'basis:' &
1648
            .and. (this%qm_geometry(record)(1:6) .ne. 'units:') &
1649
            .and. (this%qm_geometry(record)(1:5) .ne. 'ghost')) &
16,233✔
1650
            n_atoms = n_atoms + 1
15,977✔
1651

1652
      enddo
1653

1654
   end function get_n_atoms_input_tool
3,163✔
1655

1656

1657
   pure function get_n_mm_atoms_input_tool(this) result(n_atoms)
156✔
1658
      !!
1659
      !! Get n MM atoms
1660
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
1661
      !!
1662
      implicit none
1663

1664
      class(input_tool), intent(in) :: this
1665

1666
      integer :: n_atoms
1667

1668
      n_atoms = this%n_mm_atom_lines
156✔
1669

1670
   end function  get_n_mm_atoms_input_tool
156✔
1671

1672

1673
   function get_n_mm_molecules_input_tool(this) result(n_molecules)
78✔
1674
      !!
1675
      !! Written by Sarai D. Folkestad, Sep 2020
1676
      !!
1677
      !! Reads the MM geometry and counts the number of molecules
1678
      !!
1679
      implicit none
1680

1681
      class(input_tool), intent(in) :: this
1682

1683
      integer :: n_molecules
1684

1685
      integer :: cursor, record, current_molecule, previous_molecule
1686

1687
      character(len=200) :: string, imolecule
1688

1689
      previous_molecule = 1
1690
      n_molecules       = 1
1691

1692
      do record = 1, this%n_mm_atom_lines
312✔
1693

1694
         string = (trim(adjustl(this%mm_geometry(record))))
234✔
1695
         cursor = first_index_of_substring(string,'=')
234✔
1696

1697
         string = string(cursor+1:200)
234✔
1698

1699
         cursor = first_index_of_substring(string,']')
234✔
1700

1701
         imolecule = string(1:cursor-1)
234✔
1702
         read(imolecule,'(i4)') current_molecule
234✔
1703

1704
         if (record == 1 .and. current_molecule .ne. 1) &
234✔
1705
            call output%error_msg('Molecule 1 is missing!')
×
1706

1707
         if (current_molecule .eq. previous_molecule + 1) then
234✔
1708

1709
            n_molecules = n_molecules + 1
×
1710

1711
         elseif (current_molecule .ne. previous_molecule .and. &
234✔
1712
               current_molecule .ne. previous_molecule + 1) then
1713

1714
            call output%error_msg('Molecule (i0) missing even though (i0) &
1715
                                 &should be present in QM/MM calculation.', &
1716
                                 ints=[previous_molecule + 1, n_molecules])
×
1717

1718
         endif
1719

1720
         previous_molecule = current_molecule
78✔
1721

1722
      enddo
1723

1724
   end function get_n_mm_molecules_input_tool
78✔
1725

1726

1727
   subroutine get_geometry_input_tool(this, n_atoms, symbols,  &
3,163✔
1728
                                      positions, basis_sets,   &
1729
                                      charge, units_angstrom,  &
3,163✔
1730
                                      is_ghost)
1731
      !!
1732
      !! Written by Sarai D. Folkestad, Eirik F. Kjønstad
1733
      !! Åsmund H. Tveten and Tor S. Haugland, 2019-2021
1734
      !!
1735
      !! Reads the geometry from the output file and sets it in the list of atoms.
1736
      !!
1737
      !! Note: This routine should be called after a call to the function
1738
      !! get_n_atoms_input_tool which finds the number of atoms in the system
1739
      !!
1740
      use string_utilities, only: convert_character_to_uppercase
1741

1742
      implicit none
1743

1744
      class(input_tool), intent(in) :: this
1745

1746
      integer, intent(in) :: n_atoms
1747

1748
      character(len=2), dimension(n_atoms), intent(out)   :: symbols
1749
      character(len=100), dimension(n_atoms), intent(out) :: basis_sets
1750
      logical, dimension(n_atoms), intent(out) :: is_ghost
1751

1752
      real(dp), dimension(3, n_atoms), intent(out) :: positions ! x, y, z
1753
      integer, dimension(n_atoms), intent(out) :: charge
1754

1755
      logical, intent(out) :: units_angstrom
1756

1757
      integer :: current_atom, i
1758

1759
      integer :: start_
1760

1761
      character(len=200) :: string
1762
      character(len=100) :: current_basis
1763
      logical :: is_ghost_atom = .false.
1764

1765
      integer :: cursor
1766

1767
      start_ = 1 ! Specifies the line of the first and required basis
1768

1769
      ! Are units specified?
1770
      ! Note that units can only be specified as the first line of the geometry
1771

1772
      units_angstrom = .true. ! Default units are Angstrom
3,163✔
1773
      charge = 0 ! Default charge is zero
15,977✔
1774

1775
      if (this%qm_geometry(1)(1:6) == 'units:') then
3,163✔
1776

1777
         string = (trim(adjustl(this%qm_geometry(1)(7:200))))
220✔
1778

1779
         if (string(1:4) == 'bohr') then
220✔
1780

1781
            units_angstrom = .false.
220✔
1782

1783
         elseif (string(1:8) /= 'angstrom') then
×
1784

1785
            call output%error_msg('units of atom coordinates must be either angstrom or bohr')
×
1786

1787
         endif
1788

1789
         start_ = 2
1790

1791
      endif
1792

1793
      ! Error if next line is not a basis set line
1794

1795
      if(this%qm_geometry(start_)(1:6) /= 'basis:') &
3,163✔
1796
            call output%error_msg('did not find basis in geometry section.')
×
1797

1798
      current_atom = 0
1799

1800
      do i = start_, this%n_qm_atom_lines
19,176✔
1801

1802
         string = trim(adjustl(this%qm_geometry(i)))
16,013✔
1803

1804
         if (string(1:6) == 'units:') &
16,013✔
1805
            call output%error_msg('Units must be specified as the first line in the geometry section.')
×
1806

1807
         if(string(1:6) == 'basis:') then
19,176✔
1808

1809
            current_basis = trim(adjustl(string(7:200)))
3,193✔
1810
            current_basis = remove_substring_after_symbol(current_basis,"!")
3,193✔
1811

1812
         elseif (string(1:5) == 'ghost') then
12,820✔
1813

1814
            ! Every atom after 'ghost' keyword are ghosts
1815
            is_ghost_atom = .true.
6✔
1816

1817
         else
1818

1819
            current_atom = current_atom + 1
12,814✔
1820

1821
            basis_sets(current_atom) = current_basis
12,814✔
1822
            symbols(current_atom)    = string(1:2)
12,814✔
1823
            is_ghost(current_atom)   = is_ghost_atom
12,814✔
1824

1825
            string = adjustl(string(3:200))
12,814✔
1826

1827
            if (is_substring_in_string(string, 'q')) then
12,814✔
1828

1829
               cursor = first_index_of_substring(string, 'q')
12✔
1830
               read(string(1 : cursor - 1), *) positions(:, current_atom)
12✔
1831

1832
               string = adjustl(string(cursor+1:200))
12✔
1833

1834
               if (.not. string_starts_with(string, '=')) &
12✔
1835
                     call output%error_msg('in assignment of charge to atom in the geometry')
×
1836

1837
               string = adjustl(string(2:200))
12✔
1838
               read(string, *) charge(current_atom)
12✔
1839
            else
1840

1841
               read(string(1:), *) positions(:, current_atom)
12,802✔
1842

1843
            endif
1844

1845
         endif
1846

1847
      enddo
1848

1849
      ! First character of symbol should be upper case
1850

1851
      do i = 1, n_atoms
15,977✔
1852

1853
         symbols(i)(1:1) = convert_character_to_uppercase(symbols(i)(1:1))
15,977✔
1854

1855
      enddo
1856

1857
   end subroutine get_geometry_input_tool
3,163✔
1858

1859

1860
   subroutine get_mm_geometry_fq_input_tool(this, n_atoms, n_molecules, &
78✔
1861
                                          n_atoms_per_molecule, symbols,   &
78✔
1862
                                          positions, chi, eta)
1863
      !!
1864
      !! Written by Tommaso Giovanini and Sarai D. Folkestad, 2019-2020
1865
      !!
1866
      !! Reads the geometry of the MM portion from the input file in the case
1867
      !! of an fq calculation and sets it in the list of atoms.
1868
      !!
1869
      !! Note: In order to be run, you need to know the number of MM atoms and molecules
1870
      !!       in the system
1871
      !!
1872
      use string_utilities, only: convert_character_to_uppercase
1873
      use string_utilities, only: last_index_of_substring
1874

1875
      implicit none
1876

1877
      class(input_tool),   intent(in) :: this
1878
      integer,             intent(in) :: n_atoms
1879
      integer,             intent(in) :: n_molecules
1880

1881
      character(len=2), dimension(n_atoms),     intent(out) :: symbols
1882
      real(dp),         dimension(3, n_atoms),  intent(out) :: positions
1883
      real(dp),         dimension(n_atoms),     intent(out) :: chi
1884
      real(dp),         dimension(n_atoms),     intent(out) :: eta
1885
      integer,          dimension(n_molecules), intent(out) :: n_atoms_per_molecule
1886

1887
      integer :: record, cursor, current_atom, i, current_molecule
1888

1889
      character(len=200) :: string, coordinate
1890

1891
      current_atom = 0
1892

1893
      current_molecule     = 0
78✔
1894
      n_atoms_per_molecule = 0
156✔
1895
      cursor = 0
1896

1897
      do record = 1, this%n_mm_atom_lines
312✔
1898

1899
         current_atom = current_atom + 1
234✔
1900
         string = trim(adjustl(this%mm_geometry(record)))
234✔
1901

1902
         ! Determine symbol
1903

1904
         symbols(current_atom) = string(1:2)
234✔
1905
         string = adjustl(string(3:200))
234✔
1906

1907
         ! Determine molecule index
1908

1909
         if (is_substring_in_string(string, 'mol')) then
234✔
1910
            cursor = last_index_of_substring(string, 'mol')
234✔
1911
         else
1912
            call output%error_msg('could not find mol in MM geometry')
×
1913
         endif
1914

1915
         string = adjustl(string(cursor+1:200))
234✔
1916

1917
         if (string(1:1) .ne. '=') call output%error_msg('in mol specification in MM geometry')
234✔
1918
         string = adjustl(string(2:200))
234✔
1919

1920
         cursor = first_index_of_substring(string, ']')
234✔
1921

1922
         read(string(1:cursor-1),*) current_molecule
234✔
1923
         string = adjustl(string(cursor+1:200))
234✔
1924

1925
         n_atoms_per_molecule(current_molecule) = n_atoms_per_molecule(current_molecule) + 1
234✔
1926

1927
         cursor = first_index_of_substring(string, '[')
234✔
1928

1929
         coordinate = string(1:cursor-1)
234✔
1930
         read(coordinate, *) positions(:, current_atom)
234✔
1931

1932
         string = adjustl(string(cursor+1:200))
234✔
1933

1934
         ! Determine chi
1935

1936
         if (is_substring_in_string(string, 'chi')) then
234✔
1937
            cursor = last_index_of_substring(string, 'chi')
234✔
1938
         else
1939
            call output%error_msg('could not find chi in MM geometry')
×
1940
         endif
1941

1942
         string = adjustl(string(cursor+1:200))
234✔
1943

1944
         if (string(1:1) .ne. '=') call output%error_msg('in chi specification in MM geometry')
234✔
1945
         string = adjustl(string(2:200))
234✔
1946

1947
         cursor = first_index_of_substring(string,',')
234✔
1948
         read(string(1:cursor-1), * ) chi(current_atom)
234✔
1949
         string = adjustl(string(cursor+1:200))
234✔
1950

1951
         ! Determine eta
1952

1953
         if (is_substring_in_string(string, 'eta')) then
234✔
1954
            cursor = last_index_of_substring(string, 'eta')
234✔
1955
         else
1956
            call output%error_msg('could not find eta in MM geometry')
×
1957
         endif
1958

1959
         string = trim(adjustl(string(cursor+1:200)))
234✔
1960

1961
         if (string(1:1) .ne. '=') call output%error_msg('in chi specification in MM geometry')
234✔
1962
         string = adjustl(string(2:200))
234✔
1963

1964
         cursor = first_index_of_substring(string,']')
234✔
1965
         read(string(1:cursor-1), * ) eta(current_atom)
234✔
1966

1967
         if(abs(eta(current_atom)).lt.1.0d-8) then
312✔
1968

1969
            call output%error_msg('You have put zero chemical hardness on atom: (i0)', &
1970
                                  ints=[current_atom])
×
1971

1972
         endif
1973

1974
      enddo
1975

1976
      ! First character of symbol should be upper case
1977

1978
      do i = 1, n_atoms
312✔
1979

1980
         symbols(i)(1:1) = convert_character_to_uppercase(symbols(i)(1:1))
312✔
1981

1982
      enddo
1983

1984
   end subroutine get_mm_geometry_fq_input_tool
78✔
1985

1986

1987
   subroutine get_mm_geometry_non_polarizable_input_tool(this, n_atoms, symbols,   &
78✔
1988
                                                         positions, charge)
1989
      !!
1990
      !! Written by Tommaso Giovanini and Sarai D. Folkestad, 2019-2020
1991
      !!
1992
      !! Reads the geometry of the MM portion from the input file and
1993
      !! sets it in the list of atoms.
1994
      !!
1995
      !! Note: In order to be run, you need to know the number of MM atoms
1996
      !!       there are in the system
1997
      !!
1998
      use string_utilities, only: convert_character_to_uppercase
1999
      use string_utilities, only: last_index_of_substring
2000

2001
      implicit none
2002

2003
      class(input_tool), intent(in) :: this
2004

2005
      integer, intent(in) :: n_atoms
2006

2007
      character(len=2), dimension(n_atoms),     intent(out) :: symbols
2008
      real(dp),         dimension(3, n_atoms),  intent(out) :: positions
2009
      real(dp),         dimension(n_atoms),     intent(out) :: charge
2010

2011
      integer :: record, cursor, current_atom, i, current_molecule
2012

2013
      character(len=200) :: string, coordinate
2014

2015
      current_atom      = 0
2016
      current_molecule  = 0
78✔
2017
      cursor            = 0
2018

2019
      do record = 1, this%n_mm_atom_lines
312✔
2020

2021
         current_atom = current_atom + 1
234✔
2022
         string = trim(adjustl(this%mm_geometry(record)))
234✔
2023

2024
         ! Determine symbol
2025

2026
         symbols(current_atom) = string(1:2)
234✔
2027
         string = adjustl(string(3:200))
234✔
2028

2029
         ! Determine molecule index
2030

2031
         if (is_substring_in_string(string, 'mol')) then
234✔
2032
            cursor = last_index_of_substring(string, 'mol')
234✔
2033
         else
2034
            call output%error_msg('could not find mol in MM geometry')
×
2035
         endif
2036

2037
         string = adjustl(string(cursor+1:200))
234✔
2038

2039
         if (string(1:1) .ne. '=') call output%error_msg('in mol specification in MM geometry')
234✔
2040
         string = adjustl(string(2:200))
234✔
2041

2042
         cursor = first_index_of_substring(string, ']')
234✔
2043
         read(string(1:cursor-1),*) current_molecule
234✔
2044
         string = adjustl(string(cursor+1:200))
234✔
2045

2046
         ! Determine position
2047

2048
         cursor = first_index_of_substring(string, '[')
234✔
2049

2050
         coordinate = string(1:cursor-1)
234✔
2051
         read(coordinate, *) positions(:, current_atom)
234✔
2052

2053
         string = adjustl(string(cursor+1:200))
234✔
2054

2055
         ! Determine charge
2056

2057
         cursor = first_index_of_substring(string, 'q')
234✔
2058
         string = adjustl(string(cursor+1:200))
234✔
2059

2060
         if (string(1:1) .ne. '=') call output%error_msg('in charge specification in MM geometry')
234✔
2061
         string = adjustl(string(2:200))
234✔
2062

2063
         cursor = first_index_of_substring(string,']')
234✔
2064
         read(string(1:cursor-1), * ) charge(current_atom)
234✔
2065

2066
         if(abs(charge(current_atom)).lt.1.0d-8) then
312✔
2067

2068
            call output%warning_msg('You put zero charge on atom = (i0)', &
2069
                                     ints=[current_atom], fs='(t6,a)')
×
2070

2071
         endif
2072

2073
      enddo
2074

2075
      ! First character of symbol should be upper case
2076

2077
      do i = 1, n_atoms
312✔
2078

2079
         symbols(i)(1:1) = convert_character_to_uppercase(symbols(i)(1:1))
312✔
2080

2081
      enddo
2082

2083
   end subroutine get_mm_geometry_non_polarizable_input_tool
78✔
2084

2085

2086
   function string_in_array_keyword(this, keyword, section, string) result(in_list)
414✔
2087
      !!
2088
      !! Written by Sarai D. Folkestad and Alexander C. Paul, 2019-2023
2089
      !!
2090
      !! Determines if the 'string' is one of the keyword values in the comma separated
2091
      !! list given with 'keyword' in the given 'section' of the input file.
2092
      !!
2093
      !! Examples of such a keyword is 'levels' from the 'mlcc' section:
2094
      !!
2095
      !!    levels: ccs, cc2, ccsd
2096
      !!
2097
      !! This function assumes that the keyword is requested. If it is not, a test should be performed
2098
      !! before the routine is called
2099
      !!
2100
      use string_utilities, only: string_in_comma_separated_list
2101

2102
      implicit none
2103

2104
      class(input_tool), intent(in) :: this
2105

2106
      character(len=*), intent(in) :: section
2107
      character(len=*), intent(in) :: keyword
2108
      character(len=*), intent(in) :: string
2109

2110
      logical :: in_list
2111

2112
      character(len=200) :: keyword_value_string
2113

2114
      call this%get_required_keyword(keyword, section, keyword_value_string)
414✔
2115
      in_list = string_in_comma_separated_list(keyword_value_string, string)
414✔
2116

2117
   end function string_in_array_keyword
414✔
2118

2119

2120
   subroutine cleanup_input_tool(this)
3,133✔
2121
      !!
2122
      !! Written by Eirik F. Kjønstad, May 2022
2123
      !!
2124
      implicit none
2125

2126
      class(input_tool), intent(inout) :: this
2127

2128
      deallocate(this%keyword_lines)
3,133✔
2129
      deallocate(this%qm_geometry)
3,133✔
2130
      if (allocated(this%mm_geometry)) deallocate(this%mm_geometry)
3,133✔
2131

2132
   end subroutine cleanup_input_tool
3,133✔
2133

2134

2135
   function is_embedding_on_input_tool(this) result(embedding)
8,506✔
2136
      !!
2137
      !! Written by Sarai D. Folkestad, Sep 2020
2138
      !!
2139
      !! Returns true if wavefunction is embedded.
2140
      !!
2141
      implicit none
2142

2143
      class(input_tool), intent(in) :: this
2144

2145
      logical :: embedding
2146

2147
      embedding = this%is_section_present('molecular mechanics') .or. &
2148
                  this%is_section_present('pcm') .or. &
2149
                  this%is_keyword_present('cbo', 'boson')
8,506✔
2150

2151
   end function is_embedding_on_input_tool
8,506✔
2152

2153

2154
   subroutine place_records_in_memory_input_tool(this, section, records_in_memory)
14,866✔
2155
      !!
2156
      !! Written by Sarai D. Folkestad, 2021
2157
      !!
2158
      !! Checks if storage for 'section' is in memory or on disk
2159
      !!
2160
      !! records_in_mem is intent(inout) because it should be set
2161
      !! to a default value before a call to this routine
2162
      !!
2163
      implicit none
2164

2165
      class(input_tool), intent(in) :: this
2166
      character(len=*),  intent(in) :: section
2167

2168
      logical, intent(inout) :: records_in_memory
2169

2170
      character(len=200) :: storage
2171

2172
      if (.not. this%is_keyword_present('storage', trim(section))) return
14,866✔
2173

2174
      call this%get_keyword('storage', trim(section), storage)
30✔
2175

2176
      ! Determine whether to store records in memory or on file
2177

2178
      if (trim(storage) == 'memory') then
30✔
2179

2180
         records_in_memory = .true.
30✔
2181

2182
      elseif (trim(storage) == 'disk') then
×
2183

2184
         records_in_memory = .false.
×
2185

2186
      else
2187

2188
         call output%error_msg('Could not recognize keyword storage in solver: ', &
2189
                                 chars=[trim(storage)])
×
2190

2191
      endif
2192

2193
   end subroutine place_records_in_memory_input_tool
2194

2195

2196
   function get_n_sets_and_ranges(string) result(n_elements)
6✔
2197
      !!
2198
      !! Written by Sarai D. Folkstad and Eirik F. Kjønstad, Mar 2019
2199
      !!
2200
      !! Gets the number of sets/ranges in a string,
2201
      !!
2202
      !! Ranges should always be given as [a,b].
2203
      !!
2204
      !! Lists/ranges should always be given as {a, b, c, d},
2205
      !! that is, in set notation.
2206
      !!
2207
      implicit none
2208

2209
      character(len=200), intent(inout) :: string
2210

2211
      integer :: n_elements
2212

2213
      integer :: i
2214
      integer :: n_set_start, n_set_end
2215
      integer :: n_range_start, n_range_end
2216

2217
      n_set_start = 0
2218
      n_set_end   = 0
2219

2220
      n_range_start = 0
2221
      n_range_end   = 0
2222

2223
      string = adjustl(string)
6✔
2224

2225
      do i = 1, len_trim(string)
126✔
2226

2227
         if (string(i:i) == '{') n_set_start = n_set_start + 1
120✔
2228
         if (string(i:i) == '}') n_set_end = n_set_end + 1
120✔
2229

2230
         if (string(i:i) == '[') n_range_start = n_range_start + 1
120✔
2231
         if (string(i:i) == ']') n_range_end = n_range_end + 1
126✔
2232

2233
      enddo
2234

2235
      if (n_set_start /= n_set_end) call output%error_msg('found open set in input file')
6✔
2236
      if (n_range_start /= n_range_end) call output%error_msg('found open range in input file')
6✔
2237

2238
      n_elements = n_set_start + n_range_start
6✔
2239

2240
   end function get_n_sets_and_ranges
6✔
2241

2242

2243
   function get_n_elements_in_set_or_range(this, string) result(n_elements)
2,736✔
2244
      !!
2245
      !! Written by Sarai D. Folkstad and Eirik F. Kjønstad, Mar 2019
2246
      !!
2247
      !! Gets the number of elements in range or list,
2248
      !!
2249
      !! Ranges should always be given as [a,b], where a and b are integers.
2250
      !! Lists/Sets should always be given as {a, b, c, d}.
2251
      !!
2252
      use string_utilities, only: n_instances_of_character
2253

2254
      implicit none
2255

2256
      class(input_tool), intent(in) :: this
2257

2258
      character(len=200), intent(inout) :: string
2259

2260
      integer :: n_elements
2261

2262
      integer :: last, first, n_characters
2263
      integer :: comma_index
2264

2265
      n_elements = 0
2266

2267
      string = adjustl(string)
2,736✔
2268

2269
      n_characters = len_trim(string)
2,736✔
2270

2271
      if (string_starts_with(string, '[')) then ! range
2,736✔
2272

2273
         call expect_range(string)
198✔
2274

2275
         comma_index = index(string, ',')
198✔
2276

2277
         read(string(2 : comma_index-1), *) first
198✔
2278
         read(string(comma_index+1 : n_characters - 1), *) last
198✔
2279

2280
         n_elements = last - first + 1
198✔
2281

2282
      else if (string_starts_with(string, '{')) then ! set
2,538✔
2283

2284
         call this%expect_set(string)
2,424✔
2285

2286
         n_elements = 1 ! Assuming that the set contains at least one element (otherwise why give list?)
2287
         n_elements = n_elements + n_instances_of_character(string(2:), ',')
2,424✔
2288

2289
      else ! Did not find list or range
2290

2291
         n_elements = 0
2292

2293
      endif
2294

2295
   end function get_n_elements_in_set_or_range
2,736✔
2296

2297

2298
   subroutine get_integers_from_set_or_range(this, string, n_elements, elements)
1,664✔
2299
      !!
2300
      !! Written by Sarai D. Folkstad and Eirik F. Kjønstad, Mar 2019
2301
      !!
2302
      !! Ranges should always be given as [a,b].
2303
      !!
2304
      !! Lists should always be given as {a, b, c, d}.
2305
      !!
2306
      use string_utilities, only: read_comma_separated_list
2307

2308
      implicit none
2309

2310
      class(input_tool), intent(in) :: this
2311

2312
      character(len=200), intent(inout) :: string
2313

2314
      integer, intent(in) :: n_elements
2315

2316
      integer, dimension(n_elements), intent(out) :: elements
2317

2318
      integer :: first, last, length, n_characters
2319
      integer :: i, comma_index
2320

2321
      string = adjustl(string)
1,664✔
2322

2323
      n_characters = len_trim(string)
1,664✔
2324

2325
      if (string_starts_with(string, '[')) then ! range
1,664✔
2326

2327
         call expect_range(string)
198✔
2328

2329
         comma_index = index(string, ',')
198✔
2330

2331
         read(string(2 : comma_index-1), *) first
198✔
2332
         read(string(comma_index+1 : n_characters - 1), *) last
198✔
2333
         length = last - first + 1
198✔
2334

2335
         if (n_elements /= length) call output%error_msg('Mismatch in number of elements of range.')
198✔
2336

2337
         elements = [(i, i=first, last)]
1,482✔
2338

2339
      else if (string_starts_with(string, '{')) then ! set
1,466✔
2340

2341
         call this%expect_set(string)
1,466✔
2342
         call read_comma_separated_list(string(2:n_characters-1), elements, n_elements)
1,466✔
2343

2344
      else ! Did not find list or range
2345

2346
         call output%error_msg('neither list nor range was found.')
×
2347

2348
      endif
2349

2350
   end subroutine get_integers_from_set_or_range
1,664✔
2351

2352

2353
   function get_n_state_guesses(this) result(n_guesses)
6✔
2354
      !!
2355
      !! Written by Eirik F. Kjønstad, Dec 2021
2356
      !!
2357
      implicit none
2358

2359
      class(input_tool) :: this
2360

2361
      integer :: n_guesses
2362

2363
      character(len=200) :: state_guesses
2364

2365
      call this%get_keyword('state guesses', 'solver cc es', state_guesses)
6✔
2366

2367
      n_guesses = get_n_sets_and_ranges(state_guesses)
6✔
2368

2369
   end function get_n_state_guesses
6✔
2370

2371

2372
   subroutine get_state_guesses(this, occupied, virtual, n_states)
6✔
2373
      !!
2374
      !! Written by Sarai D. Folkestad, Dec 2021
2375
      !!
2376
      !! state guesses: {i=1, a=2}, {i=2, a=2}, {i=1, a=1}
2377
      !!
2378
      !! Provided as a (comma separated) list of sets.
2379
      !!
2380
      !! A set comprises of two elements which are
2381
      !! the occupied and virtual indices of the start vector
2382
      !!
2383
      !! 'i =' provides occupied index
2384
      !! 'a =' provides virtual index
2385
      !!
2386
      use string_utilities, only: remove_delimiter_from_string, split_at_delimiter
2387
      use string_utilities, only: n_instances_of_character
2388

2389
      implicit none
2390

2391
      class(input_tool) :: this
2392

2393
      integer, intent(in) :: n_states
2394
      integer, dimension(n_states), intent(out) :: virtual, occupied
2395

2396
      character(len=200) :: state_guesses
2397
      character(len=200), dimension(:), allocatable :: split_string
2398

2399
      integer :: n_elements, cursor_a, cursor_i, i, n_occupied, n_virtual
2400

2401
      call this%get_keyword('state guesses', 'solver cc es', state_guesses)
6✔
2402
      state_guesses = adjustl(state_guesses)
6✔
2403

2404
      n_occupied = n_instances_of_character(state_guesses, 'i')
6✔
2405
      n_virtual = n_instances_of_character(state_guesses, 'a')
6✔
2406

2407
      if (n_virtual /= n_occupied) &
6✔
2408
         call output%error_msg('in keyword (state guesses)')
×
2409

2410
      if (n_virtual /= n_states) &
6✔
2411
         call output%error_msg('in keyword (state guesses)')
×
2412

2413
      ! {i=1, a=2}, {i=2, a=2}, {i=1, a=1} -> i=1, a=2} i=2, a=2} i=1, a=1}
2414
      call remove_delimiter_from_string(state_guesses, '{')
6✔
2415

2416
      n_elements = n_instances_of_character(state_guesses, '}')
6✔
2417

2418
      if (n_elements /= n_states) &
6✔
2419
         call output%error_msg('in keyword (state guesses)')
×
2420

2421
      allocate(split_string(n_elements))
10✔
2422

2423
      ! i=1, a=2} i=2, a=2} i=1, a=1} -> string array ("i=1, a=2", "i=2, a=2", "i=1, a=1")
2424
      call split_at_delimiter(state_guesses, n_elements, split_string, '}')
6✔
2425

2426
      do i = 1, n_elements
18✔
2427

2428
         call remove_delimiter_from_string(split_string(i), '=')
12✔
2429
         call remove_delimiter_from_string(split_string(i), ',')
12✔
2430

2431
         cursor_i = first_index_of_substring(split_string(i), 'i')
12✔
2432
         cursor_a = first_index_of_substring(split_string(i), 'a')
12✔
2433

2434
         if (cursor_i < cursor_a) then
18✔
2435

2436
            read(split_string(i)(cursor_i + 1 : cursor_a -1), *) occupied(i)
6✔
2437
            read(split_string(i)(cursor_a + 1:), *) virtual(i)
6✔
2438

2439
         else
2440

2441
            read(split_string(i)(cursor_a + 1 : cursor_i -1), *) virtual(i)
6✔
2442
            read(split_string(i)(cursor_i + 1:), *) occupied(i)
6✔
2443

2444
         endif
2445

2446
      enddo
2447

2448
      deallocate(split_string)
6✔
2449

2450
   end subroutine get_state_guesses
6✔
2451

2452

2453
   subroutine check_for_errors(this)
3,163✔
2454
      !!
2455
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, Mar 2019
2456
      !!
2457
      !! Looks for errors the user may have made when writing the input file.
2458
      !!
2459
      implicit none
2460

2461
      class(input_tool), intent(in) :: this
2462
      integer :: k
2463

2464
      do k = 1, size(this%sections)
132,846✔
2465

2466
         call this%sections(k)%check_section_for_illegal_keywords()
132,846✔
2467

2468
      enddo
2469

2470
   end subroutine check_for_errors
3,163✔
2471

2472

2473
   function is_section_recognized(this, section) result(allowed)
25,526✔
2474
      !!
2475
      !! Written by Sarai D. Folkestad and Eirik F. Kjønstad, 2019-2021
2476
      !!
2477
      implicit none
2478

2479
      class(input_tool), intent(in) :: this
2480

2481
      character(len=*), intent(in) :: section
2482

2483
      logical :: allowed
2484

2485
      integer :: k
2486

2487
      allowed = .false.
2488

2489
      do k = 1, size(this%sections)
600,805✔
2490

2491
         if (this%sections(k)%name_ == trim(section)) then
600,805✔
2492
            allowed = .true.
2493
            return
2494
         end if
2495

2496
      enddo
2497

2498
   end function is_section_recognized
2499

2500

2501
   subroutine section_not_recognized(this, section)
×
2502
      !!
2503
      !! Written by Sara Angelico and Alexander C. Paul, 2023
2504
      !!
2505
      implicit none
2506

2507
      class(input_tool), intent(in) :: this
2508

2509
      character(len=*), intent(in) :: section
2510

2511
      call output%printf('m', 'Could not recognize section named "(a0)".', &
2512
                        chars=[trim(section)], fs='(/t3,a)')
×
2513
      call this%print_sections()
×
2514
      call output%error_msg('Something is wrong in the input file. See above.')
×
2515

2516
   end subroutine section_not_recognized
×
2517

2518

2519
   subroutine expect_set(string)
7,588✔
2520
      !!
2521
      !! Written by Alexander C. Paul, Mar 2023
2522
      !!
2523
      implicit none
2524

2525
      character(len=*), intent(in) :: string
2526
      integer :: opening, closing
2527

2528
      opening = index(string, '{')
7,588✔
2529
      if (opening == 0) call output%error_msg('Expected set, but no "{" found in string.')
7,588✔
2530

2531
      closing = index(string, '}')
7,588✔
2532
      if (closing == 0) call output%error_msg('Expected set, but no "}" found in string.')
7,588✔
2533

2534
      if (closing < opening) call output%error_msg('Expected set, but "}" found before "{".')
7,588✔
2535

2536
   end subroutine expect_set
7,588✔
2537

2538

2539
   subroutine expect_range(string)
396✔
2540
      !!
2541
      !! Written by Alexander C. Paul, Mar 2023
2542
      !!
2543
      implicit none
2544

2545
      character(len=*), intent(in) :: string
2546
      integer :: opening, closing, comma
2547

2548
      opening = index(string, '[')
396✔
2549
      if (opening == 0) call output%error_msg('Expected range, but no "[" found in string.')
396✔
2550

2551
      closing = index(string, ']')
396✔
2552
      if (closing == 0) call output%error_msg('Expected range, but no "]" found in string.')
396✔
2553

2554
      comma = index(string, ',')
396✔
2555
      if (comma == 0) call output%error_msg('Expected range, but no "," found in string.')
396✔
2556

2557
      if (comma < opening) call output%error_msg('Expected range, but "," found before "[".')
396✔
2558
      if (closing < comma) call output%error_msg('Expected range, but "]" found before ",".')
396✔
2559

2560
   end subroutine expect_range
396✔
2561

2562

2563
   subroutine set_section_keywords(this, section, section_lines)
25,526✔
2564
      !!
2565
      !! Written by Sara Angelico and Alexander C. Paul, Apr 2023
2566
      !!
2567
      !! This routine removes empty lines and comment lines and
2568
      !! sets the keywords for the section
2569
      !!
2570
      implicit none
2571

2572
      class(input_tool),                intent(inout) :: this
2573
      character(len=*),                 intent(in)    :: section
2574
      character(len=200), dimension(:), intent(in)    :: section_lines
2575

2576
      character(len=200), dimension(:), allocatable :: keyword_lines
2577
      character(len=200) :: line
2578
      integer :: section_index, n_lines, l
2579

2580
      allocate(keyword_lines, mold=section_lines)
51,052✔
2581

2582
      n_lines = 0
2583
      do l = 1, size(section_lines)
101,872✔
2584

2585
         line = trim(adjustl(section_lines(l)))
76,346✔
2586

2587
         if (string_starts_with(line, "!")) cycle
76,346✔
2588
         if (is_empty(line)) cycle
76,226✔
2589

2590
         line = remove_substring_after_symbol(line,'!')
50,490✔
2591

2592
         n_lines = n_lines + 1
50,490✔
2593
         keyword_lines(n_lines) = adjustl(line)
101,872✔
2594

2595
      end do
2596

2597
      section_index = this%get_section_index(trim(section))
25,526✔
2598

2599
      call this%sections(section_index)%set_keyword_lines(keyword_lines(1:n_lines))
25,526✔
2600

2601
      deallocate(keyword_lines)
25,526✔
2602

2603
   end subroutine set_section_keywords
25,526✔
2604

2605

2606
   subroutine check_get_array_for_keyword(keyword, section, n_elements)
5,362✔
2607
      !!
2608
      !! Written by Alexander C. Paul, May 2023
2609
      !!
2610
      implicit none
2611

2612
      character(len=*), intent(in) :: keyword, section
2613
      integer,          intent(in) :: n_elements
2614

2615
      if (n_elements .le. 0) then
5,362✔
2616
         call output%error_msg("Get array for keyword called with n_elements=(i0). &
2617
                              &Keyword: (a0) Section: " // section, &
2618
                               ints=[n_elements], chars=[keyword])
×
2619
      end if
2620

2621
   end subroutine check_get_array_for_keyword
5,362✔
2622

2623

2624
end module input_tool_class
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc