Octopus
floquet.F90
Go to the documentation of this file.
1!! Copyright (C) 2016 H. Huebener
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
21program oct_floquet
22 use blas_oct_m
24 use comm_oct_m
25 use debug_oct_m
27 use fft_oct_m
29 use global_oct_m
30 use grid_oct_m
32 use io_oct_m
34 use mesh_oct_m
36 use mpi_oct_m
39 use parser_oct_m
42 use space_oct_m
46 use unit_oct_m
48 use utils_oct_m
49 use v_ks_oct_m
50 use xc_oct_m
51
52 implicit none
53
54 integer :: ierr
55
56 type(electrons_t), pointer :: sys
57 type(states_elec_t) :: st
58 complex(real64), allocatable :: hmss(:,:), psi(:,:,:), hpsi(:,:,:), temp_state1(:,:)
59 complex(real64), allocatable :: HFloquet(:,:,:), HFloq_eff(:,:), temp(:,:)
60 real(real64), allocatable :: eigenval(:), bands(:,:)
61 character(len=80) :: filename
62 integer :: it, nT, ik, ist, in, im, file, idim, nik, ik_count
63 integer :: Forder, Fdim, m0, n0, n1, nst, ii, jj, lim_nst
64 real(real64) :: dt, Tcycle,omega
65 logical :: downfolding = .false.
66 class(mesh_t), pointer :: mesh
67 type(restart_t) :: restart
68
69 call global_init()
70
71 call parser_init()
72
73 call messages_init()
74
75 call io_init()
77
78 call print_header()
79 call messages_print_with_emphasis(msg="Non-interacting Floquet", namespace=global_namespace)
81
82 call messages_experimental("oct-floquet utility")
86
87 call calc_mode_par%set_parallelization(p_strategy_states, default = .false.)
89 call sys%init_parallelization(mpi_world)
90 ! make shortcut copies
91 st = sys%st
92
93 ! generate the full hamiltonian following the sequence in td_init
94 call hamiltonian_elec_epot_generate(sys%hm, global_namespace, sys%space, sys%gr, sys%ions, &
95 sys%ext_partners, st, time=m_zero)
96 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, time = m_zero)
97
98 call states_elec_allocate_wfns(st, sys%gr)
99
100 call restart_init(restart, global_namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=sys%gr, exact=.true.)
101 if (ierr == 0) then
102 call states_elec_load(restart, global_namespace, sys%space, st, sys%gr, sys%kpoints, ierr, label = ": gs")
103 end if
104 if (ierr /= 0) then
105 message(1) = 'Unable to read ground-state wavefunctions.'
106 call messages_fatal(1)
107 end if
108
109 call density_calc(st, sys%gr, st%rho)
110 call v_ks_calc(sys%ks, global_namespace, sys%space, sys%hm, st, sys%ions, sys%ext_partners, &
111 calc_eigenval=.true., time = m_zero)
112 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, time = m_zero)
113
115
117
118
119 ! wait for all processors to finish
120 call mpi_world%barrier()
121
122 call fft_all_end()
123 safe_deallocate_p(sys)
125 call io_end()
126 call print_date("Calculation ended on ")
127 call messages_end()
128
129 call parser_end()
130 call global_end()
131
132contains
133
134 !------------------------------------------------
135 subroutine floquet_init()
136
137 push_sub(floquet_init)
138
139 !for now no domain distribution allowed
140 assert(sys%gr%np == sys%gr%np_global)
141
142 ! variables documented in td/td_write.F90
143 call parse_variable(global_namespace, 'TDFloquetFrequency', m_zero, omega, units_inp%energy)
144 call messages_print_var_value('Frequency used for Floquet analysis', omega)
145 if (abs(omega) <= m_epsilon) then
146 message(1) = "Please give a non-zero value for TDFloquetFrequency"
147 call messages_fatal(1)
148 end if
149
150 ! get time of one cycle
151 tcycle = m_two * m_pi / omega
152
153 call parse_variable(global_namespace, 'TDFloquetSample',20 ,nt)
154 call messages_print_var_value('Number of Floquet time-sampling points', nt)
155 dt = tcycle/real(nt, real64)
156
157 call parse_variable(global_namespace, 'TDFloquetDimension',-1,forder)
158 if (forder.ge.0) then
159 call messages_print_var_value('Order of multiphoton Floquet-Hamiltonian', forder)
160 !Dimension of multiphoton Floquet-Hamiltonian
161 fdim = 2 * forder + 1
162 else
163 message(1) = 'Floquet-Hamiltonian is downfolded'
164 call messages_info(1)
165 downfolding = .true.
166 forder = 1
167 fdim = 3
168 end if
169
170 dt = tcycle/real(nt, real64)
171
172 pop_sub(floquet_init)
173
174 end subroutine floquet_init
175
176 !---------------------------------------------------
178 type(states_elec_t) :: hm_st
179
181
182 mesh => sys%gr
183 nst = st%nst
184
185 safe_allocate(hmss(1:nst,1:nst))
186 safe_allocate( psi(1:nst,1:st%d%dim,1:mesh%np))
187 safe_allocate(hpsi(1:nst,1:st%d%dim,1:mesh%np))
188 safe_allocate(temp_state1(1:mesh%np,1:st%d%dim))
189
190 ! this is used to initialize the local state object
191 call states_elec_copy(hm_st, st)
192
193 ! we are only interested for k-point with zero weight
194 nik = sys%kpoints%nik_skip
195
196 ! multiphoton Floquet Hamiltonian, layout:
197 ! (H_{-n,-m} ... H_{-n,0} ... H_{-n,m})
198 ! ( . . . . . )
199 ! H = (H_{0,-m} ... H_{0,0} ... H_{0,m} )
200 ! ( . . . . . )
201 ! (H_{n,-m} ... H_{n,0} ... H_{n,m} )
202 safe_allocate(hfloquet(1:nik,1:nst*fdim, 1:nst*fdim))
203 hfloquet(1:nik,1:nst*fdim, 1:nst*fdim) = m_zero
204
205 ! perform time-integral over one cycle
206 do it = 1, nt
207 ! get non-interacting Hamiltonian at time (offset by one cycle to allow for ramp)
208 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, &
209 time=tcycle+it*dt)
210 ! get hpsi
211 call zhamiltonian_elec_apply_all(sys%hm, global_namespace, sys%gr, st, hm_st)
212
213 ! project Hamiltonian into grounstates for zero weight k-points
214 ik_count = 0
215
216 do ik = sys%kpoints%reduced%npoints-nik+1, sys%kpoints%reduced%npoints
217 ik_count = ik_count + 1
218
219 psi(1:nst, 1:st%d%dim, 1:mesh%np)= m_zero
220 hpsi(1:nst, 1:st%d%dim, 1:mesh%np)= m_zero
221
222 do ist = st%st_start, st%st_end
223 if (state_kpt_is_local(st, ist, ik)) then
224 call states_elec_get_state(st, mesh, ist, ik,temp_state1)
225 do idim = 1, st%d%dim
226 psi(ist, idim, 1:mesh%np) = temp_state1(1:mesh%np, idim)
227 end do
228 call states_elec_get_state(hm_st, mesh, ist, ik,temp_state1)
229 do idim = 1, st%d%dim
230 hpsi(ist, idim, 1:mesh%np) = temp_state1(1:mesh%np, idim)
231 end do
232 end if
233 end do
234 call comm_allreduce(mpi_world, psi)
235 call comm_allreduce(mpi_world, hpsi)
236 assert(mesh%np_global*st%d%dim < huge(0_int32))
237 hmss(1:nst, 1:nst) = m_zero
238 call zgemm( 'n', &
239 'c', &
240 nst, &
241 nst, &
242 i8_to_i4(mesh%np_global*st%d%dim), &
243 cmplx(mesh%volume_element, m_zero, real64) , &
244 hpsi(1, 1, 1), &
245 ubound(hpsi, dim = 1), &
246 psi(1, 1, 1), &
247 ubound(psi, dim = 1), &
248 m_z0, &
249 hmss(1, 1), &
250 ubound(hmss, dim = 1))
251
252 hmss(1:nst,1:nst) = conjg(hmss(1:nst,1:nst))
253
254 ! accumulate the Floquet integrals
255 do in = -forder, forder
256 do im = -forder, forder
257 ii = (in + forder) * nst
258 jj = (im + forder) * nst
259 hfloquet(ik_count, ii+1:ii+nst, jj+1:jj+nst) = &
260 hfloquet(ik_count, ii+1:ii+nst, jj+1:jj+nst) &
261 + hmss(1:nst, 1:nst) * exp(-(in - im)* m_zi * omega * it * dt)
262 ! diagonal term
263 if (in == im) then
264 do ist = 1,nst
265 hfloquet(ik_count, ii+ist, ii+ist) = hfloquet(ik_count, ii+ist, ii+ist) + in * omega
266 end do
267 end if
268 end do
269 end do
270 end do !ik
271 end do ! it
272
273 hfloquet(:,:,:) = m_one / nt * hfloquet(:,:,:)
274
275 ! diagonalize Floquet Hamiltonian
276 if (downfolding) then
277 ! here perform downfolding
278 safe_allocate(hfloq_eff(1:nst,1:nst))
279 safe_allocate(eigenval(1:nst))
280 safe_allocate(bands(1:nik,1:nst))
281
282 hfloq_eff(1:nst,1:nst) = m_zero
283 do ik = 1, nik
284 ! the HFloquet blocks are copied directly out of the super matrix
285 m0 = nst ! the m=0 start position
286 n0 = nst ! the n=0 start postion
287 n1 = 2 * nst ! the n=+1 start postion
288 hfloq_eff(1:nst,1:nst) = hfloquet(ik,n0+1:n0+nst,m0+1:m0+nst) + &
289 m_one/omega*(matmul(hfloquet(ik,1:nst,m0+1:m0+nst), hfloquet(ik,n1+1:n1+nst,m0+1:m0+nst))- &
290 matmul(hfloquet(ik,n1+1:n1+nst,m0+1:m0+nst), hfloquet(ik,1:nst,m0+1:m0+nst)))
291
292 eigenval(1:nst) = m_zero
293 call lalg_eigensolve(nst, hfloq_eff, eigenval)
294 bands(ik,1:nst) = eigenval(1:nst)
295 end do
296 safe_deallocate_a(hfloq_eff)
297 else
298 ! the full Floquet
299 safe_allocate(eigenval(1:nst*fdim))
300 safe_allocate(bands(1:nik,1:nst*fdim))
301 safe_allocate(temp(1:nst*fdim, 1:nst*fdim))
302
303 do ik = 1, nik
304 temp(1:nst*fdim,1:nst*fdim) = hfloquet(ik,1:nst*fdim,1:nst*fdim)
305 call lalg_eigensolve(nst*fdim, temp, eigenval)
306 bands(ik,1:nst*fdim) = eigenval(1:nst*fdim)
307 end do
308 end if
309
310 !write bandstructure to file
311 if (downfolding) then
312 lim_nst = nst
313 filename="downfolded_floquet_bands"
314 else
315 lim_nst = nst*fdim
316 filename="floquet_bands"
317 end if
318 ! write bands (full or downfolded)
319 if (mpi_world%rank == 0) then
320 file = 987254
321 file = io_open(filename, sys%namespace, action = 'write')
322 do ik = 1, nik
323 do ist = 1, lim_nst
324 write(file,'(e13.6, 1x)',advance='no') bands(ik,ist)
325 end do
326 write(file,'(1x)')
327 end do
328 call io_close(file)
329 end if
330
331 if (.not. downfolding) then
332 ! for the full Floquet case compute also the trivially shifted
333 ! Floquet bands for reference (i.e. setting H_{nm}=0 for n!=m)
334 bands(1:nik,1:nst*fdim) = m_zero
335 do ik = 1,nik
336 temp(1:nst*fdim, 1:nst*fdim) = m_zero
337 do jj = 0, fdim - 1
338 ii = jj * nst
339 temp(ii+1:ii+nst, ii+1:ii+nst) = hfloquet(ik, ii+1:ii+nst, ii+1:ii+nst)
340 end do
341 call lalg_eigensolve(nst*fdim, temp, eigenval)
342 bands(ik, 1:nst*fdim) = eigenval(1:nst*fdim)
343 end do
344
345 if (mpi_world%rank == 0) then
346 filename='trivial_floquet_bands'
347 file = io_open(filename, sys%namespace, action = 'write')
348 do ik = 1, nik
349 do ist = 1, lim_nst
350 write(file,'(e13.6, 1x)',advance='no') bands(ik,ist)
351 end do
352 write(file,'(1x)')
353 end do
354 call io_close(file)
355 end if
356 end if
357
358 ! reset time in Hamiltonian
359 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, time=m_zero)
360
361 safe_deallocate_a(hmss)
362 safe_deallocate_a(psi)
363 safe_deallocate_a(hpsi)
364 safe_deallocate_a(temp_state1)
365 safe_deallocate_a(hfloquet)
366 safe_deallocate_a(eigenval)
367 safe_deallocate_a(bands)
368 safe_deallocate_a(temp)
369
371
372 end subroutine floquet_solve_non_interacting
373
374end program oct_floquet
375
376!! Local Variables:
377!! mode: f90
378!! coding: utf-8
379!! End:
subroutine floquet_init()
Definition: floquet.F90:229
subroutine floquet_solve_non_interacting()
Definition: floquet.F90:271
program oct_floquet
Definition: floquet.F90:114
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:180
double exp(double __x) __attribute__((__nothrow__
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:118
This module handles the calculation mode.
type(calc_mode_par_t), public calc_mode_par
Singleton instance of parallel calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
Definition: density.F90:608
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:118
subroutine, public fft_all_init(namespace)
initialize the table
Definition: fft.F90:277
subroutine, public fft_all_end()
delete all plans
Definition: fft.F90:390
real(real64), parameter, public m_two
Definition: global.F90:189
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
Definition: global.F90:381
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
complex(real64), parameter, public m_z0
Definition: global.F90:197
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_epsilon
Definition: global.F90:203
subroutine, public global_init(communicator)
Initialise Octopus.
Definition: global.F90:324
real(real64), parameter, public m_one
Definition: global.F90:188
This module implements the underlying real-space grid.
Definition: grid.F90:117
subroutine, public hamiltonian_elec_epot_generate(this, namespace, space, gr, ions, ext_partners, st, time)
subroutine, public zhamiltonian_elec_apply_all(hm, namespace, mesh, st, hst)
Definition: io.F90:114
subroutine, public io_init(defaults)
If the argument defaults is present and set to true, then the routine will not try to read anything f...
Definition: io.F90:166
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
subroutine, public io_end()
Definition: io.F90:265
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_end()
Definition: messages.F90:277
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:930
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_init(output_dir)
Definition: messages.F90:224
subroutine, public print_date(str)
Definition: messages.F90:1017
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1097
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
type(namespace_t), public global_namespace
Definition: namespace.F90:132
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:450
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:481
subroutine, public profiling_end(namespace)
Definition: profiling.F90:413
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:255
subroutine, public restart_module_init(namespace)
Definition: restart.F90:306
integer, parameter, public restart_gs
Definition: restart.F90:229
subroutine, public restart_init(restart, namespace, data_type, type, mc, ierr, mesh, dir, exact)
Initializes a restart object.
Definition: restart.F90:514
integer, parameter, public restart_type_load
Definition: restart.F90:225
logical function, public state_kpt_is_local(st, ist, ik)
check whether a given state (ist, ik) is on the local node
subroutine, public states_elec_allocate_wfns(st, mesh, wfs_type, skip, packed)
Allocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_copy(stout, stin, exclude_wfns, exclude_eigenval, special)
make a (selective) copy of a states_elec_t object
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, ierr, iter, lr, lowest_missing, label, verbose, skip)
returns in ierr: <0 => Fatal error, or nothing read =0 => read all wavefunctions >0 => could only rea...
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
subroutine, public unit_system_init(namespace)
type(unit_system_t), public units_inp
the units systems for reading and writing
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:118
subroutine, public print_header()
This subroutine prints the logo followed by information about the compilation and the system....
Definition: utils.F90:301
subroutine, public v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval, time, calc_energy, calc_current, force_semilocal)
Definition: v_ks.F90:732
Definition: xc.F90:114
Class describing the electron system.
Definition: electrons.F90:214
The states_elec_t class contains all electronic wave functions.
int true(void)