1!! Copyright (C)  2019 N. Tancogne-Dejean
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module propagator_abst_oct_m
22  use clock_oct_m
23  use global_oct_m
24  use linked_list_oct_m
25  use messages_oct_m
26  use namespace_oct_m
27  use parser_oct_m
28  use profiling_oct_m
29
30  implicit none
31
32  private
33  public ::                            &
34    propagator_abst_t,                 &
35    propagator_step_debug_message
36
37  type, extends(linked_list_t) :: propagator_abst_t
38    private
39
40    type(list_iterator_t) :: iter
41    type(list_iterator_t) :: scf_start
42    integer               :: current_ops
43
44    integer, public       :: start_step
45    integer, public       :: final_step
46
47    integer, public :: algo_steps
48    FLOAT, public   :: dt
49    integer, public :: max_td_steps
50
51    !< Options related to predictor-corrector propagators
52    logical, public :: predictor_corrector = .false.
53    integer, public :: scf_count
54    integer, public :: max_scf_count
55    FLOAT, public   :: scf_tol
56
57    logical :: step_done
58    logical, public :: inside_scf = .false.
59
60    type(clock_t), public :: clock
61
62  contains
63    ! Below are the list of operations that needs to be implemented
64    procedure :: get_td_operation => propagator_get_tdop
65    procedure :: step_is_done => propagator_step_is_done
66    procedure :: next => propagator_next
67    procedure :: rewind => propagator_rewind
68    procedure :: finished => propagator_finished
69    procedure :: save_scf_start => propagator_save_scf_start
70    procedure :: rewind_scf_loop => propagator_rewind_scf_loop
71    procedure :: parse_td_variables => propagator_parse_td_variables
72  end type propagator_abst_t
73
74  ! Known propagation operations
75  integer, public, parameter ::        &
76    FINISHED                     =  0,  &
77    VERLET_START                 =  1,  &
78    VERLET_FINISH                =  2,  &
79    VERLET_UPDATE_POS            =  3,  &
80    VERLET_COMPUTE_ACC           =  4,  &
81    VERLET_COMPUTE_VEL           =  5,  &
82    SYNC                         =  6,  &
83    UPDATE_INTERACTIONS          =  7,  &
84    START_SCF_LOOP               =  8,  &
85    END_SCF_LOOP                 =  9,  &
86    STORE_CURRENT_STATUS         = 10,  &
87    BEEMAN_START                 = 11,  &
88    BEEMAN_FINISH                = 12,  &
89    BEEMAN_PREDICT_POS           = 13,  &
90    BEEMAN_PREDICT_VEL           = 14,  &
91    BEEMAN_CORRECT_POS           = 15,  &
92    BEEMAN_CORRECT_VEL           = 16,  &
93    EXPMID_START                 = 17,  &
94    EXPMID_FINISH                = 18,  &
95    EXPMID_PREDICT_DT_2          = 19,  &
96    EXPMID_PREDICT_DT            = 20,  &
97    EXPMID_CORRECT_DT_2          = 21,  &
98    UPDATE_HAMILTONIAN           = 22
99
100  ! Known multisystem propagators
101  integer, public, parameter ::        &
102    PROP_VERLET                  = 1,  &
103    PROP_BEEMAN                  = 2,  &
104    PROP_BEEMAN_SCF              = 3,  &
105    PROP_EXPMID                  = 4,  &
106    PROP_EXPMID_SCF              = 5
107
108
109contains
110
111  subroutine propagator_rewind(this)
112    class(propagator_abst_t), intent(inout) :: this
113
114    PUSH_SUB(propagator_rewind)
115
116    call this%iter%start(this)
117    call this%next()
118    this%step_done = .false.
119
120    POP_SUB(propagator_rewind)
121  end subroutine propagator_rewind
122
123  subroutine propagator_finished(this)
124    class(propagator_abst_t), intent(inout) :: this
125
126    PUSH_SUB(propagator_finished)
127
128    this%step_done = .true.
129
130    POP_SUB(propagator_finished)
131  end subroutine propagator_finished
132
133  subroutine propagator_next(this)
134    class(propagator_abst_t), intent(inout) :: this
135
136    PUSH_SUB(propagator_next)
137
138    select type(next_ops => this%iter%get_next())
139    type is (integer)
140      this%current_ops = next_ops
141    class default
142      message(1) = "Corrupted list."
143      call messages_fatal(1)
144    end select
145
146    POP_SUB(propagator_next)
147  end subroutine propagator_next
148
149  integer function propagator_get_tdop(this) result(tdop)
150    class(propagator_abst_t), intent(in) :: this
151
152    PUSH_SUB(propagator_get_tdop)
153
154    tdop = this%current_ops
155
156    POP_SUB(propagator_get_tdop)
157  end function propagator_get_tdop
158
159  logical pure function propagator_step_is_done(this) result(step_is_done)
160    class(propagator_abst_t), intent(in) :: this
161
162    step_is_done = this%step_done
163
164  end function propagator_step_is_done
165
166  subroutine propagator_save_scf_start(this)
167    class(propagator_abst_t), intent(inout) :: this
168
169    PUSH_SUB(propagator_save_scf_start)
170
171    ! Save the current iteration state (START_SCF_LOOP) and move to next step
172    this%scf_start = this%iter
173    call this%next()
174    this%scf_count = 0
175
176    POP_SUB(propagator_save_scf_start)
177
178  end subroutine propagator_save_scf_start
179
180  subroutine propagator_rewind_scf_loop(this)
181    class(propagator_abst_t), intent(inout) :: this
182
183    PUSH_SUB(propagator_rewind_scf_loop)
184
185    ! Reset the iteration state to the beginning of the loop (START_SCF_LOOP) and move to next step
186    this%iter = this%scf_start
187    call this%next()
188    this%scf_count = this%scf_count + 1
189
190    POP_SUB(propagator_rewind_scf_loop)
191
192  end subroutine propagator_rewind_scf_loop
193
194  function propagator_step_debug_message(tdop) result(description)
195    integer, intent(in) :: tdop
196    character(len=100) :: description
197
198    PUSH_SUB(propagator_step_debug_message)
199
200    select case (tdop)
201    case (FINISHED)
202      description = "Propagation step finished for"
203    case (UPDATE_INTERACTIONS)
204      description = "Updating interactions for"
205    case (START_SCF_LOOP)
206      description = "Starting SCF loop for"
207    case (END_SCF_LOOP)
208      description = "End of SCF iteration for"
209    case (STORE_CURRENT_STATUS)
210      description = "Storing the current status for"
211    case (VERLET_UPDATE_POS)
212      description = "Propagation step - Updating positions for"
213    case (VERLET_COMPUTE_ACC)
214      description = "Propagation step - Computing acceleration for"
215    case (VERLET_COMPUTE_VEL)
216      description = "Propagation step - Computing velocity for"
217    case (BEEMAN_PREDICT_POS)
218      description = "Prediction step  - Computing position for"
219    case (BEEMAN_PREDICT_VEL)
220      description = "Prediction step  - Computing velocity for"
221    case (BEEMAN_CORRECT_POS)
222      description = "Correction step  - Computing position for"
223    case (BEEMAN_CORRECT_VEL)
224      description = "Correction step  - Computing velocity for"
225    case default
226      description = "Unknown step for "
227    end select
228
229    POP_SUB(propagator_step_debug_message)
230  end function propagator_step_debug_message
231
232  !--------------------------------------------------------
233  subroutine propagator_parse_td_variables(this, namespace)
234    class(propagator_abst_t), intent(inout) :: this
235    type(namespace_t),        intent(in)    :: namespace
236
237    PUSH_SUB(propagator_parse_td_variables)
238
239    ! This variable is also defined (and properly documented) in td/td.F90.
240    ! This is temporary, until all the propagators are moved to the new framework.
241    call parse_variable(namespace, 'TDTimeStep', CNST(10.0), this%dt)
242
243    ! This variable is also defined (and properly documented) in td/td.F90.
244    ! This is temporary, until all the propagators are moved to the new framework.
245    call parse_variable(namespace, 'TDMaxSteps', 1000, this%max_td_steps)
246
247    POP_SUB(propagator_parse_td_variables)
248  end subroutine propagator_parse_td_variables
249
250end module propagator_abst_oct_m
251
252
253!!o, Local Variables:
254!! mode: f90
255!! coding: utf-8
256!! End:
257