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")
85
86 call calc_mode_par%set_parallelization(p_strategy_states, default = .false.)
88 call sys%init_parallelization(mpi_world)
89 ! make shortcut copies
90 st = sys%st
91
92 ! generate the full hamiltonian following the sequence in td_init
93 call hamiltonian_elec_epot_generate(sys%hm, global_namespace, sys%space, sys%gr, sys%ions, &
94 sys%ext_partners, st, time=m_zero)
95 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, time = m_zero)
96
97 call states_elec_allocate_wfns(st, sys%gr)
98
99 call restart%init(global_namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=sys%gr, exact=.true.)
100 if (ierr == 0) then
101 call states_elec_load(restart, global_namespace, sys%space, st, sys%gr, sys%kpoints, ierr, label = ": gs")
102 end if
103 if (ierr /= 0) then
104 message(1) = 'Unable to read ground-state wavefunctions.'
105 call messages_fatal(1)
106 end if
107
108 call density_calc(st, sys%gr, st%rho)
109 call v_ks_calc(sys%ks, global_namespace, sys%space, sys%hm, st, sys%ions, sys%ext_partners, &
110 calc_eigenval=.true., time = m_zero)
111 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, time = m_zero)
112
113 call floquet_init()
114
117
118 ! wait for all processors to finish
119 call mpi_world%barrier()
120
121 call fft_all_end()
122 safe_deallocate_p(sys)
124 call io_end()
125 call print_date("Calculation ended on ")
126 call messages_end()
127
128 call parser_end()
129 call global_end()
130
131contains
132
133 !------------------------------------------------
134 subroutine floquet_init()
135
136 push_sub(floquet_init)
137
138 !for now no domain distribution allowed
139 assert(sys%gr%np == sys%gr%np_global)
140
141 ! variables documented in td/td_write.F90
142 call parse_variable(global_namespace, 'TDFloquetFrequency', m_zero, omega, units_inp%energy)
143 call messages_print_var_value('Frequency used for Floquet analysis', omega)
144 if (abs(omega) <= m_epsilon) then
145 message(1) = "Please give a non-zero value for TDFloquetFrequency"
146 call messages_fatal(1)
147 end if
148
149 ! get time of one cycle
150 tcycle = m_two * m_pi / omega
151
152 call parse_variable(global_namespace, 'TDFloquetSample',20 ,nt)
153 call messages_print_var_value('Number of Floquet time-sampling points', nt)
154 dt = tcycle/real(nt, real64)
155
156 call parse_variable(global_namespace, 'TDFloquetDimension',-1,forder)
157 if (forder.ge.0) then
158 call messages_print_var_value('Order of multiphoton Floquet-Hamiltonian', forder)
159 !Dimension of multiphoton Floquet-Hamiltonian
160 fdim = 2 * forder + 1
161 else
162 message(1) = 'Floquet-Hamiltonian is downfolded'
163 call messages_info(1)
164 downfolding = .true.
165 forder = 1
166 fdim = 3
167 end if
168
169 dt = tcycle/real(nt, real64)
170
171 pop_sub(floquet_init)
172
173 end subroutine floquet_init
174
175 !---------------------------------------------------
177 type(states_elec_t) :: hm_st
178
180
181 mesh => sys%gr
182 nst = st%nst
183
184 safe_allocate(hmss(1:nst,1:nst))
185 safe_allocate( psi(1:nst,1:st%d%dim,1:mesh%np))
186 safe_allocate(hpsi(1:nst,1:st%d%dim,1:mesh%np))
187 safe_allocate(temp_state1(1:mesh%np,1:st%d%dim))
188
189 ! this is used to initialize the local state object
190 call states_elec_copy(hm_st, st)
191
192 ! we are only interested for k-point with zero weight
193 nik = sys%kpoints%nik_skip
194
195 ! multiphoton Floquet Hamiltonian, layout:
196 ! (H_{-n,-m} ... H_{-n,0} ... H_{-n,m})
197 ! ( . . . . . )
198 ! H = (H_{0,-m} ... H_{0,0} ... H_{0,m} )
199 ! ( . . . . . )
200 ! (H_{n,-m} ... H_{n,0} ... H_{n,m} )
201 safe_allocate(hfloquet(1:nik,1:nst*fdim, 1:nst*fdim))
202 hfloquet(1:nik,1:nst*fdim, 1:nst*fdim) = m_zero
203
204 ! perform time-integral over one cycle
205 do it = 1, nt
206 ! get non-interacting Hamiltonian at time (offset by one cycle to allow for ramp)
207 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, &
208 time=tcycle+it*dt)
209 ! get hpsi
210 call zhamiltonian_elec_apply_all(sys%hm, global_namespace, sys%gr, st, hm_st)
211
212 ! project Hamiltonian into grounstates for zero weight k-points
213 ik_count = 0
214
215 do ik = sys%kpoints%reduced%npoints-nik+1, sys%kpoints%reduced%npoints
216 ik_count = ik_count + 1
217
218 psi(1:nst, 1:st%d%dim, 1:mesh%np)= m_zero
219 hpsi(1:nst, 1:st%d%dim, 1:mesh%np)= m_zero
220
221 do ist = st%st_start, st%st_end
222 if (state_kpt_is_local(st, ist, ik)) then
223 call states_elec_get_state(st, mesh, ist, ik,temp_state1)
224 do idim = 1, st%d%dim
225 psi(ist, idim, 1:mesh%np) = temp_state1(1:mesh%np, idim)
226 end do
227 call states_elec_get_state(hm_st, mesh, ist, ik,temp_state1)
228 do idim = 1, st%d%dim
229 hpsi(ist, idim, 1:mesh%np) = temp_state1(1:mesh%np, idim)
230 end do
231 end if
232 end do
233 call comm_allreduce(mpi_world, psi)
234 call comm_allreduce(mpi_world, hpsi)
235 assert(mesh%np_global*st%d%dim < huge(0_int32))
236 hmss(1:nst, 1:nst) = m_zero
237 call zgemm( 'n', &
238 'c', &
239 nst, &
240 nst, &
241 i8_to_i4(mesh%np_global*st%d%dim), &
242 cmplx(mesh%volume_element, m_zero, real64) , &
243 hpsi(1, 1, 1), &
244 ubound(hpsi, dim = 1), &
245 psi(1, 1, 1), &
246 ubound(psi, dim = 1), &
247 m_z0, &
248 hmss(1, 1), &
249 ubound(hmss, dim = 1))
250
251 hmss(1:nst,1:nst) = conjg(hmss(1:nst,1:nst))
252
253 ! accumulate the Floquet integrals
254 do in = -forder, forder
255 do im = -forder, forder
256 ii = (in + forder) * nst
257 jj = (im + forder) * nst
258 hfloquet(ik_count, ii+1:ii+nst, jj+1:jj+nst) = &
259 hfloquet(ik_count, ii+1:ii+nst, jj+1:jj+nst) &
260 + hmss(1:nst, 1:nst) * exp(-(in - im)* m_zi * omega * it * dt)
261 ! diagonal term
262 if (in == im) then
263 do ist = 1,nst
264 hfloquet(ik_count, ii+ist, ii+ist) = hfloquet(ik_count, ii+ist, ii+ist) + in * omega
265 end do
266 end if
267 end do
268 end do
269 end do !ik
270 end do ! it
272 hfloquet(:,:,:) = m_one / nt * hfloquet(:,:,:)
273
274 ! diagonalize Floquet Hamiltonian
275 if (downfolding) then
276 ! here perform downfolding
277 safe_allocate(hfloq_eff(1:nst,1:nst))
278 safe_allocate(eigenval(1:nst))
279 safe_allocate(bands(1:nik,1:nst))
280
281 hfloq_eff(1:nst,1:nst) = m_zero
282 do ik = 1, nik
283 ! the HFloquet blocks are copied directly out of the super matrix
284 m0 = nst ! the m=0 start position
285 n0 = nst ! the n=0 start postion
286 n1 = 2 * nst ! the n=+1 start postion
287 hfloq_eff(1:nst,1:nst) = hfloquet(ik,n0+1:n0+nst,m0+1:m0+nst) + &
288 m_one/omega*(matmul(hfloquet(ik,1:nst,m0+1:m0+nst), hfloquet(ik,n1+1:n1+nst,m0+1:m0+nst))- &
289 matmul(hfloquet(ik,n1+1:n1+nst,m0+1:m0+nst), hfloquet(ik,1:nst,m0+1:m0+nst)))
290
291 eigenval(1:nst) = m_zero
292 call lalg_eigensolve(nst, hfloq_eff, eigenval)
293 bands(ik,1:nst) = eigenval(1:nst)
294 end do
295 safe_deallocate_a(hfloq_eff)
296 else
297 ! the full Floquet
298 safe_allocate(eigenval(1:nst*fdim))
299 safe_allocate(bands(1:nik,1:nst*fdim))
300 safe_allocate(temp(1:nst*fdim, 1:nst*fdim))
301
302 do ik = 1, nik
303 temp(1:nst*fdim,1:nst*fdim) = hfloquet(ik,1:nst*fdim,1:nst*fdim)
304 call lalg_eigensolve(nst*fdim, temp, eigenval)
305 bands(ik,1:nst*fdim) = eigenval(1:nst*fdim)
306 end do
307 end if
308
309 !write bandstructure to file
310 if (downfolding) then
311 lim_nst = nst
312 filename="downfolded_floquet_bands"
313 else
314 lim_nst = nst*fdim
315 filename="floquet_bands"
316 end if
317 ! write bands (full or downfolded)
318 if (mpi_world%is_root()) then
319 file = 987254
320 file = io_open(filename, sys%namespace, action = 'write')
321 do ik = 1, nik
322 do ist = 1, lim_nst
323 write(file,'(e13.6, 1x)',advance='no') bands(ik,ist)
324 end do
325 write(file,'(1x)')
326 end do
327 call io_close(file)
328 end if
329
330 if (.not. downfolding) then
331 ! for the full Floquet case compute also the trivially shifted
332 ! Floquet bands for reference (i.e. setting H_{nm}=0 for n!=m)
333 bands(1:nik,1:nst*fdim) = m_zero
334 do ik = 1,nik
335 temp(1:nst*fdim, 1:nst*fdim) = m_zero
336 do jj = 0, fdim - 1
337 ii = jj * nst
338 temp(ii+1:ii+nst, ii+1:ii+nst) = hfloquet(ik, ii+1:ii+nst, ii+1:ii+nst)
339 end do
340 call lalg_eigensolve(nst*fdim, temp, eigenval)
341 bands(ik, 1:nst*fdim) = eigenval(1:nst*fdim)
342 end do
343
344 if (mpi_world%is_root()) then
345 filename='trivial_floquet_bands'
346 file = io_open(filename, sys%namespace, action = 'write')
347 do ik = 1, nik
348 do ist = 1, lim_nst
349 write(file,'(e13.6, 1x)',advance='no') bands(ik,ist)
350 end do
351 write(file,'(1x)')
352 end do
353 call io_close(file)
354 end if
355 end if
356
357 ! reset time in Hamiltonian
358 call sys%hm%update(sys%gr, global_namespace, sys%space, sys%ext_partners, time=m_zero)
359
360 safe_deallocate_a(hmss)
361 safe_deallocate_a(psi)
362 safe_deallocate_a(hpsi)
363 safe_deallocate_a(temp_state1)
364 safe_deallocate_a(hfloquet)
365 safe_deallocate_a(eigenval)
366 safe_deallocate_a(bands)
367 safe_deallocate_a(temp)
368
370
371 end subroutine floquet_solve_non_interacting
372
373end program oct_floquet
374
375!! Local Variables:
376!! mode: f90
377!! coding: utf-8
378!! End:
subroutine floquet_init()
Definition: floquet.F90:230
subroutine floquet_solve_non_interacting()
Definition: floquet.F90:272
program oct_floquet
Definition: floquet.F90:116
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:182
double exp(double __x) __attribute__((__nothrow__
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:120
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:122
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
Definition: density.F90:612
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
subroutine, public fft_all_init(namespace)
initialize the table
Definition: fft.F90:280
subroutine, public fft_all_end()
delete all plans
Definition: fft.F90:391
real(real64), parameter, public m_two
Definition: global.F90:192
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
Definition: global.F90:387
real(real64), parameter, public m_zero
Definition: global.F90:190
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:188
complex(real64), parameter, public m_z0
Definition: global.F90:200
complex(real64), parameter, public m_zi
Definition: global.F90:204
real(real64), parameter, public m_epsilon
Definition: global.F90:206
subroutine, public global_init(communicator)
Initialise Octopus.
Definition: global.F90:330
real(real64), parameter, public m_one
Definition: global.F90:191
This module implements the underlying real-space grid.
Definition: grid.F90:119
subroutine, public hamiltonian_elec_epot_generate(this, namespace, space, gr, ions, ext_partners, st, time)
subroutine, public zhamiltonian_elec_apply_all(hm, namespace, gr, st, hst)
Definition: io.F90:116
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:165
subroutine, public io_close(iunit, grp)
Definition: io.F90:466
subroutine, public io_end()
Definition: io.F90:270
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:401
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_end()
Definition: messages.F90:279
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:904
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_init(output_dir)
Definition: messages.F90:226
subroutine, public print_date(str)
Definition: messages.F90:989
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:416
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1069
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:600
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
type(namespace_t), public global_namespace
Definition: namespace.F90:134
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:453
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:484
subroutine, public profiling_end(namespace)
Definition: profiling.F90:415
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:257
integer, parameter, public restart_gs
Definition: restart.F90:156
integer, parameter, public restart_type_load
Definition: restart.F90:183
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:134
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:120
subroutine, public print_header()
This subroutine prints the logo followed by information about the compilation and the system....
Definition: utils.F90:304
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:748
Definition: xc.F90:116
Class describing the electron system.
Definition: electrons.F90:220
The states_elec_t class contains all electronic wave functions.
int true(void)