Line data Source code
1 :
2 : #if defined HAVE_CONFIG_H
3 : #include "config.h"
4 : #endif
5 :
6 : !!****m* ABINIT/m_BathOperatoroffdiag
7 : !! NAME
8 : !! m_BathOperatoroffdiag
9 : !!
10 : !! FUNCTION
11 : !! Manage all stuff related to the bath for the
12 : !! simgle Anderson Impurity Model
13 : !!
14 : !! COPYRIGHT
15 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder, J. Denier, B. Amadon)
16 : !! This file is distributed under the terms of the
17 : !! GNU General Public License, see ~abinit/COPYING
18 : !! or http://www.gnu.org/copyleft/gpl.txt .
19 : !!
20 : !! NOTES
21 : !!
22 : !! SOURCE
23 :
24 : #include "defs.h"
25 : MODULE m_BathOperatoroffdiag
26 : USE m_MatrixHyb
27 : USE m_Vector
28 : USE m_VectorInt
29 : USE m_Global
30 : USE m_ListCdagC
31 : IMPLICIT NONE
32 :
33 : ! subroutines
34 : public :: BathOperatoroffdiag_init
35 : public :: BathOperatoroffdiag_reset
36 : public :: BathOperatoroffdiag_activateParticle
37 : public :: BathOperatoroffdiag_setMAdd
38 : public :: BathOperatoroffdiag_setMRemove
39 : public :: BathOperatoroffdiag_swap
40 : public :: BathOperatoroffdiag_initF
41 : public :: BathOperatoroffdiag_setF
42 : public :: BathOperatoroffdiag_printF
43 : public :: BathOperatoroffdiag_printM
44 : public :: BathOperatoroffdiag_destroy
45 : public :: BathOperatoroffdiag_doCheck
46 : public :: BathOperatoroffdiag_checkM
47 :
48 : ! functions
49 : ! public :: BathOperatoroffdiag_hybrid
50 : public :: BathOperatoroffdiag_getDetAdd
51 : public :: BathOperatoroffdiag_getDetRemove
52 : public :: BathOperatoroffdiag_getDetF
53 : public :: BathOperatoroffdiag_getError
54 : !!***
55 :
56 : !!****t* m_BathOperatoroffdiag/BathOperatoroffdiag
57 : !! NAME
58 : !! BathOperatoroffdiag
59 : !!
60 : !! FUNCTION
61 : !! This structured datatype contains the necessary data
62 : !!
63 : !! COPYRIGHT
64 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
65 : !! This file is distributed under the terms of the
66 : !! GNU General Public License, see ~abinit/COPYING
67 : !! or http://www.gnu.org/copyleft/gpl.txt .
68 : !!
69 : !! SOURCE
70 :
71 : TYPE BathOperatoroffdiag
72 : LOGICAL :: set = .FALSE.
73 : ! True if the BathOperatoroffdiag is initialized in BathOperatoroffdiag_init
74 :
75 : LOGICAL :: MAddFlag = .FALSE.
76 : ! Set to true if we can compute a new M (see updateDetXX) (ie in
77 : ! BathOperatoroffdiag_getDetAdd)
78 :
79 : LOGICAL :: MRemoveFlag = .FALSE.
80 : ! Set to true if we can compute a new M (see updateDetXX) (ie in
81 : ! BathOperatoroffdiag_getDetRemove)
82 :
83 : LOGICAL :: antiShift = .FALSE.
84 : ! shift when M is updated with antiseg
85 :
86 : LOGICAL :: doCheck = .FALSE.
87 : ! TRUE is checks are activated
88 :
89 : INTEGER :: opt_nondiag = 0
90 : ! if opt_nondiag = 1 F is non diagonal.
91 :
92 : INTEGER :: flavors
93 : ! number of flavors
94 : ! if opt_nondiag = 0 , flavors= number of flavor
95 : ! if opt_nondiag = 1 , flavors= 1
96 :
97 : INTEGER :: activeFlavor
98 : ! Active flavor on which a segment is added/suppressed...
99 :
100 : INTEGER :: samples
101 : ! Number of time slices (given in the input file)
102 :
103 : INTEGER :: sizeHybrid
104 : ! Number of time slices (given in the input file) + 1 (=qmc_l+1)
105 :
106 : INTEGER :: updatePosRow
107 : ! Gives the position of new Row to add
108 : ! Modified in BathOperatoroffdiag_getDetAdd and BathOperatoroffdiag_getDetRemove
109 : ! could be the Row in the Full matrix for the non diag implementation
110 :
111 : INTEGER :: updatePosCol
112 : ! Gives the position of new Col to add
113 : ! Modified in BathOperatoroffdiag_getDetAdd and BathOperatoroffdiag_getDetRemove
114 :
115 : INTEGER :: iTech
116 : ! iTech is an integer which precise the technics used to compute the
117 : ! Green's function (in time or frequency)
118 :
119 : INTEGER :: sumtails
120 : ! size of the full F matrix (sums of tails(iflavor) over iflavor)
121 :
122 : INTEGER, ALLOCATABLE, DIMENSION(:) :: tails
123 : ! tails(iflavor) is the current number of segments for the flavor iflavor
124 :
125 : INTEGER, ALLOCATABLE, DIMENSION(:) :: Fshift
126 : ! Fshift(iflavor) is the sum of number of segments for all flavors iflavor2
127 : ! such that iflavor< iflavor
128 : ! It is thus the shift in the F matrix to have the first segment of the flavor
129 : ! iflavor
130 : ! Fshift(nflavor+1) is the total nb of tails (=sumtails)
131 :
132 : DOUBLE PRECISION :: beta
133 : ! Inverse of Temperature
134 : !
135 :
136 : DOUBLE PRECISION :: dt
137 : ! dt=beta/samples
138 :
139 : DOUBLE PRECISION :: inv_dt
140 : ! inv_dt=1/dt
141 :
142 : DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:,:,:) :: F ! qmc_l+2,Flavors
143 : ! Hybridization function F(1:op%sizeHybrid+1,1:flavors,1:flavors)
144 :
145 : DOUBLE PRECISION :: S
146 : ! Sherman Morrison notations
147 :
148 : DOUBLE PRECISION :: Stau
149 : ! Sherman Morrison notations
150 :
151 : DOUBLE PRECISION :: Stilde
152 : ! Sherman Morrison notations
153 :
154 : TYPE(Vector) :: R
155 : ! Sherman Morrison notations R%vec(size).
156 : ! computed for each flavor (As matrices are made of Blocks for each
157 : ! flavor because the code is restricted to diagonal F matrices)
158 :
159 : TYPE(Vector) :: Q
160 : ! Sherman Morrison notations
161 : ! computed for each flavor (As matrices are made of Blocks for each
162 : ! flavor because the code is restricted to diagonal F matrices)
163 :
164 : TYPE(Vector) :: Rtau
165 : ! Sherman Morrison notations
166 : ! Rtau gives the time length for each elements of R
167 : ! computed for each flavor (As matrices are made of Blocks for each
168 : ! flavor because the code is restricted to diagonal F matrices)
169 :
170 : TYPE(Vector) :: Qtau
171 : ! Sherman Morrison notations
172 : ! Qtau gives the time length for each elements of Q
173 : ! computed for each flavor (As matrices are made of Blocks for each
174 : ! flavor because the code is restricted to diagonal F matrices)
175 :
176 : TYPE(MatrixHyb) :: M ! Flavors
177 : ! inverse of Hybridization matrix M%mat(global_size,global_size)
178 : ! contains the value of the hybridization for all flavor and segments times,
179 : ! the times (mat_tau), and possibly the
180 : ! frequency
181 :
182 : TYPE(MatrixHyb) :: M_update ! Flavors
183 : ! used in BathOperatoroffdiag_getdetF and in BathOperatoroffdiag_checkM
184 : ! for checks
185 :
186 : !#ifdef CTQMC_CHECK
187 : INTEGER :: checkNumber
188 : DOUBLE PRECISION :: meanError
189 : ! TYPE(ListCdagC) :: ListCdagC
190 : !#endif
191 : END TYPE BathOperatoroffdiag
192 : !!***
193 :
194 : CONTAINS
195 : !!***
196 :
197 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_init
198 : !! NAME
199 : !! BathOperatoroffdiag_init
200 : !!
201 : !! FUNCTION
202 : !! Initialize and allocate data
203 : !!
204 : !! COPYRIGHT
205 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
206 : !! This file is distributed under the terms of the
207 : !! GNU General Public License, see ~abinit/COPYING
208 : !! or http://www.gnu.org/copyleft/gpl.txt .
209 : !!
210 : !! INPUTS
211 : !! op=bath object
212 : !! flavors=numbers of flavors we have (including spin)
213 : !! samples=Time slices in the input file
214 : !! beta=inverse temperature
215 : !! iTech=imaginary time or frequencies
216 : !! It is imposes to imaginary time
217 : !!
218 : !! OUTPUT
219 : !!
220 : !! SIDE EFFECTS
221 : !!
222 : !! NOTES
223 : !!
224 : !! SOURCE
225 :
226 0 : SUBROUTINE BathOperatoroffdiag_init(op, flavors, samples, beta, iTech,opt_nondiag)
227 :
228 : !Arguments ------------------------------------
229 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
230 : INTEGER , INTENT(IN ) :: flavors
231 : INTEGER , INTENT(IN ) :: samples
232 : INTEGER , INTENT(IN ) :: opt_nondiag
233 : DOUBLE PRECISION , INTENT(IN ) :: beta
234 : !Local variables ------------------------------
235 : INTEGER , INTENT(IN ) :: iTech
236 : !INTEGER :: it
237 :
238 0 : op%MAddFlag = .FALSE.
239 0 : op%MRemoveFlag = .FALSE.
240 0 : op%flavors = flavors
241 0 : op%opt_nondiag = opt_nondiag
242 0 : op%beta = beta
243 0 : op%samples = samples
244 0 : op%sizeHybrid = samples + 1
245 0 : op%dt = beta / DBLE(samples)
246 0 : op%inv_dt = DBLE(samples) / beta
247 0 : op%activeFlavor= 0
248 0 : op%updatePosRow = 0
249 0 : op%updatePosCol = 0
250 0 : op%iTech = iTech
251 : !#ifdef CTQMC_CHECK
252 0 : op%checkNumber = 0
253 0 : op%meanError = 0.d0
254 0 : op%doCheck = .FALSE.
255 : !#endif
256 :
257 0 : FREEIF(op%F)
258 0 : MALLOC(op%F,(1:op%sizeHybrid+1,1:flavors,1:flavors))
259 0 : DT_FREEIF(op%tails)
260 : #ifdef FC_LLVM
261 : ! LLVM 16 doesn't recognize this macro here
262 : DT_MALLOC(op%tails, (1:op%flavors))
263 : #else
264 0 : DT_MALLOC(op%tails,(1:op%flavors))
265 : #endif
266 0 : op%tails=0
267 0 : DT_FREEIF(op%Fshift)
268 : #ifdef FC_LLVM
269 : ! LLVM 16 doesn't recognize this macro here
270 : DT_MALLOC(op%Fshift, (1:op%flavors+1))
271 : #else
272 0 : DT_MALLOC(op%Fshift,(1:op%flavors+1))
273 : #endif
274 0 : op%Fshift=0
275 :
276 0 : CALL Vector_init(op%R,100*op%flavors)
277 0 : CALL Vector_init(op%Q,100*op%flavors)
278 0 : CALL Vector_init(op%Rtau,100*op%flavors)
279 0 : CALL Vector_init(op%Qtau,100*op%flavors)
280 :
281 0 : CALL MatrixHyb_init(op%M,op%iTech,size=Global_SIZE*op%flavors,Wmax=samples) !FIXME Should be consistent with ListCagC
282 0 : CALL MatrixHyb_init(op%M_update,op%iTech,size=Global_SIZE*op%flavors,Wmax=samples) !FIXME Should be consistent with ListCagC
283 0 : op%F = 0.d0
284 0 : op%set = .TRUE.
285 :
286 0 : END SUBROUTINE BathOperatoroffdiag_init
287 : !!***
288 :
289 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_reset
290 : !! NAME
291 : !! BathOperatoroffdiag_reset
292 : !!
293 : !! FUNCTION
294 : !! Reset all internal variables
295 : !!
296 : !! COPYRIGHT
297 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
298 : !! This file is distributed under the terms of the
299 : !! GNU General Public License, see ~abinit/COPYING
300 : !! or http://www.gnu.org/copyleft/gpl.txt .
301 : !!
302 : !! INPUTS
303 : !! op=bath operator to reset
304 : !!
305 : !! OUTPUT
306 : !!
307 : !! SIDE EFFECTS
308 : !!
309 : !! NOTES
310 : !!
311 : !! SOURCE
312 :
313 0 : SUBROUTINE BathOperatoroffdiag_reset(op)
314 :
315 : !Arguments ------------------------------------
316 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
317 : !Local variables ------------------------------
318 : INTEGER :: iflavor
319 0 : op%MAddFlag = .FALSE.
320 0 : op%MRemoveFlag = .FALSE.
321 0 : op%activeFlavor = 0
322 0 : op%updatePosRow = 0
323 0 : op%updatePosCol = 0
324 : !#ifdef CTQMC_CHECK
325 0 : op%checkNumber = 0
326 0 : op%meanError = 0.d0
327 0 : op%sumtails = 0
328 : !#endif
329 0 : op%doCheck = .FALSE.
330 0 : CALL Vector_clear(op%R)
331 0 : CALL Vector_clear(op%Q)
332 0 : CALL Vector_clear(op%Rtau)
333 0 : CALL Vector_clear(op%Qtau)
334 :
335 0 : CALL MatrixHyb_clear(op%M) !FIXME Should be consistent with ListCagC
336 0 : op%F = 0.d0
337 0 : do iflavor=1,op%flavors
338 0 : op%tails(iflavor)=0
339 0 : op%Fshift(iflavor)=0
340 : enddo
341 :
342 0 : END SUBROUTINE BathOperatoroffdiag_reset
343 : !!***
344 :
345 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_activateParticle
346 : !! NAME
347 : !! BathOperatoroffdiag_activateParticle
348 : !!
349 : !! FUNCTION
350 : !! Just save on wicht flavor we are working
351 : !! It is better to use the macro defined in defs.h
352 : !!
353 : !! COPYRIGHT
354 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
355 : !! This file is distributed under the terms of the
356 : !! GNU General Public License, see ~abinit/COPYING
357 : !! or http://www.gnu.org/copyleft/gpl.txt .
358 : !!
359 : !! INPUTS
360 : !! op=bath operator
361 : !! flavor=the flavor to activate
362 : !!
363 : !! OUTPUT
364 : !!
365 : !! SIDE EFFECTS
366 : !!
367 : !! NOTES
368 : !!
369 : !! SOURCE
370 :
371 0 : SUBROUTINE BathOperatoroffdiag_activateParticle(op,flavor)
372 :
373 : !Arguments ------------------------------------
374 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
375 : !Local variables ------------------------------
376 : INTEGER , INTENT(IN ) :: flavor
377 :
378 0 : IF ( flavor .GT. op%flavors ) &
379 0 : CALL ERROR("BathOperatoroffdiag_activateParticle : out of range ")
380 0 : IF ( op%set .EQV. .TRUE. ) THEN
381 0 : op%activeFlavor = flavor
382 0 : op%MAddFlag = .FALSE.
383 0 : op%MRemoveFlag = .FALSE.
384 : ELSE
385 0 : CALL ERROR("BathOperatoroffdiag_activateParticle : not allocated ")
386 : END IF
387 0 : END SUBROUTINE BathOperatoroffdiag_activateParticle
388 : !!***
389 :
390 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_getDetAdd
391 : !! NAME
392 : !! BathOperatoroffdiag_getDetAdd
393 : !!
394 : !! FUNCTION
395 : !! Compute the determinant ratio when a (anti)segment
396 : !! is trying to be added and store some array for setMAdd
397 : !!
398 : !! COPYRIGHT
399 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
400 : !! This file is distributed under the terms of the
401 : !! GNU General Public License, see ~abinit/COPYING
402 : !! or http://www.gnu.org/copyleft/gpl.txt .
403 : !!
404 : !! INPUTS
405 : !! op=bath operator
406 : !! CdagC_1=segment to be added
407 : !! position=ordered position of the Cdag time
408 : !! particle=full list of CdagC for activeFlavor
409 : !!
410 : !! OUTPUT
411 : !! BathOperatoroffdiag_getDetAdd=the det
412 : !!
413 : !! SIDE EFFECTS
414 : !!
415 : !! NOTES
416 : !!
417 : !! SOURCE
418 0 : DOUBLE PRECISION FUNCTION BathOperatoroffdiag_getDetAdd(op,CdagC_1, position, particle)
419 :
420 : !Arguments ------------------------------------
421 : TYPE(BathOperatoroffdiag) , INTENT(INOUT) :: op
422 : DOUBLE PRECISION, DIMENSION(1:2), INTENT(IN ) :: CdagC_1
423 : INTEGER , INTENT(IN ) :: position
424 : TYPE(ListCdagC), INTENT(IN ) :: particle(:)
425 : !Local variables-------------------------------
426 : INTEGER :: it1
427 : INTEGER :: it2
428 : INTEGER :: it3,iflavor,iflavora,iflavorb
429 : INTEGER :: iflavorbegin,iflavorend
430 : INTEGER :: tail,tailbegin,tailend
431 : INTEGER :: tcheck
432 : INTEGER :: new_tail
433 : DOUBLE PRECISION :: C
434 : DOUBLE PRECISION :: Cbeta
435 : DOUBLE PRECISION :: Cibeta
436 : DOUBLE PRECISION :: Cdag
437 : DOUBLE PRECISION :: Cdagbeta
438 : DOUBLE PRECISION :: beta
439 : DOUBLE PRECISION :: ratio
440 : DOUBLE PRECISION :: time
441 : ! TYPE(CdagC) , POINTER, DIMENSION(:) :: list => NULL()
442 : #include "BathOperatoroffdiag_hybrid.h"
443 :
444 0 : op%antiShift = .FALSE.
445 0 : beta = op%beta
446 0 : C = CdagC_1(C_)
447 : ! Cbeta = C.MOD.beta
448 0 : MODCYCLE(C,beta,Cbeta)
449 0 : Cdag = CdagC_1(Cdag_)
450 : ! cdagbeta = Cdag.MOD.beta
451 0 : MODCYCLE(Cdag,beta,Cdagbeta)
452 : ! IF ( Cdag .GE. beta ) &
453 : ! CALL ERROR("BathOperatoroffdiag_getDetAdd : bad case ... ")
454 0 : IF ( op%activeFlavor .LE. 0 ) &
455 0 : CALL ERROR("BathOperatoroffdiag_getDetAdd : no active hybrid function ")
456 :
457 0 : IF ( size(particle)/=op%flavors ) &
458 0 : CALL ERROR("BathOperatoroffdiag_getDetAdd : size of particle is erroneous ")
459 :
460 : ! tail is now the complete size of the F matrix Fshift(nflavors+1)
461 0 : tail = op%sumtails
462 0 : new_tail = tail+1
463 : ! list => particle%list
464 :
465 0 : if(op%opt_nondiag==1) then
466 0 : iflavorbegin = 1
467 0 : iflavorend = op%flavors
468 0 : tailbegin = 1
469 0 : tailend = tail
470 : else
471 : !sui!write(6,*) "Bathoperator opt_nondiag=0"
472 0 : iflavorbegin = op%activeflavor
473 0 : iflavorend = op%activeflavor
474 0 : tailbegin = op%Fshift(op%activeflavor)+1
475 0 : tailend = op%Fshift(op%activeflavor)+op%tails(op%activeflavor)
476 : endif
477 :
478 : IF ( ((C .GT. Cdag) .AND. (position .EQ. -1)) & ! Segment added at the end of the segment
479 0 : .OR. ((C .LT. Cdag) .AND. (tail .EQ. 0))) THEN ! empty orbital case: only adding a segment is possible
480 : ! If ones add a segment to an empty orbital or a segment at the end
481 : ! of a segment, then:
482 0 : op%updatePosRow = op%tails(op%activeFlavor) + 1
483 0 : op%updatePosCol = op%tails(op%activeFlavor) + 1
484 : ELSE
485 : ! For all the other cases, ABS(position) is the true position.
486 0 : op%updatePosRow = ABS(position)
487 0 : op%updatePosCol = ABS(position)
488 : END IF
489 : !write(6,*) " BathOperatoroffdiag_getDetAdd : op%updatePosRow",op%updatePosRow
490 : !write(6,*) " BathOperatoroffdiag_getDetAdd : op%updatePosCol",op%updatePosCol
491 : !write(6,*) " BathOperatoroffdiag_getDetAdd : C,Cdag",C,Cdag
492 :
493 0 : IF ( C .LT. Cdag .AND. op%tails(op%activeFlavor) .GT. 0) THEN ! only if an antisegment is added
494 : ! ratio = -ratio
495 0 : op%updatePosRow = (op%updatePosRow + 1) !position in [1;tail]
496 : ! If the antisegment created is such that a segment with tcdagger> tc
497 : ! is suppressed
498 : !write(6,*) " BathOperatoroffdiag_getDetAdd : op%updatePosRow",op%updatePosRow
499 : !write(6,*) " BathOperatoroffdiag_getDetAdd : op%updatePosCol",op%updatePosCol
500 0 : IF ( Cdagbeta .LT. particle(op%activeFlavor)%list(op%updatePosCol,Cdag_) ) op%antiShift = .TRUE.
501 : END IF
502 :
503 : ! CALL Vector_setSize(op%R,tail)
504 : ! CALL Vector_setSize(op%Q,tail)
505 0 : Vector_QuickResize(op%R,new_tail)
506 0 : Vector_QuickResize(op%Q,new_tail)
507 0 : Vector_QuickResize(op%Rtau,new_tail)
508 0 : Vector_QuickResize(op%Qtau,new_tail)
509 :
510 : ! This loop compute all Row and Col except op%updatePosRow
511 0 : tcheck=0
512 0 : DO iflavor = iflavorbegin,iflavorend
513 : !write(6,*) " BathOperatoroffdiag_getDetAdd : tails(iflavor)",iflavor,op%tails(iflavor)
514 0 : DO it1 = 1, op%tails(iflavor)
515 0 : tcheck=tcheck+1
516 0 : it2 = it1
517 0 : it3 = it1
518 0 : IF ( iflavor .GE. op%activeFlavor ) THEN
519 0 : it2 = it1 + 1
520 0 : it3 = it1 + 1
521 0 : IF ( iflavor .EQ. op%activeFlavor .AND. it1 .LT. op%updatePosRow ) it2 = it1
522 0 : IF ( iflavor .EQ. op%activeFlavor .AND. it1 .LT. op%updatePosCol ) it3 = it1
523 : !it2 = it1 + ( 1+SIGN(1,it1-op%updatePosRow) )/2
524 : !it3 = it1 + ( 1+SIGN(1,it1-op%updatePoscol) )/2
525 : ! if it1>=op%updatePosRow and iflavor> activeflavor, then it2=it1+1
526 : ! if it1< op%updatePosRow and iflavor> activeflavor, then it2=it1
527 : END IF
528 :
529 : !!write(6,*) size(op%Rtau%vec)
530 : !!write(6,*) size(particle(iflavor)%list,1)
531 : !!write(6,*) size(particle(iflavor)%list,2)
532 : !!write(6,*) size(op%Fshift)
533 : !!write(6,*) it1,Cdag_,op%Fshift(iflavor)+it2
534 0 : op%Rtau%vec(op%Fshift(iflavor)+it2)= C - particle(iflavor)%list(it1,Cdag_)
535 : ! the following line happend only for nondiag case
536 0 : IF(op%Rtau%vec(op%Fshift(iflavor)+it2) .GT. beta) op%Rtau%vec(op%Fshift(iflavor)+it2)=op%Rtau%vec(op%Fshift(iflavor)+it2)-beta
537 : !op%Rtau%vec(it1)= C - particle%list(it1,Cdag_)
538 0 : time = Cbeta - particle(iflavor)%list(it1,Cdag_)
539 0 : if(op%Rtau%vec(op%Fshift(iflavor)+it2)>beta) then
540 : !write(6,*) "Rtau sup beta",op%Rtau%vec(op%Fshift(iflavor)+it2),C,particle(iflavor)%list(it1,Cdag_)
541 : !write(6,*) time
542 0 : stop
543 : endif
544 :
545 : ! "BathOperatoroffdiag_hybrid" interpolates between known values of F for the
546 : ! selected time.
547 0 : iflavora=iflavor
548 0 : iflavorb=op%activeFlavor
549 : #include "BathOperatoroffdiag_hybrid"
550 :
551 0 : op%R%vec(op%Fshift(iflavor)+it1) = hybrid
552 : ! op%R%vec(it) = BathOperatoroffdiag_hybrid(op, Cbeta - list(it)%Cdag)
553 : ! Cibeta = list(it)%C.MOD.beta
554 0 : MODCYCLE(particle(iflavor)%list(it1,C_),beta,Cibeta)
555 0 : time = Cibeta - Cdagbeta
556 0 : op%Qtau%vec(op%Fshift(iflavor)+it3)= time
557 : !op%Qtau%vec(it1)= time
558 :
559 0 : iflavora=op%activeFlavor
560 0 : iflavorb=iflavor
561 : #include "BathOperatoroffdiag_hybrid"
562 0 : op%Q%vec(op%Fshift(iflavor)+it1) = hybrid
563 :
564 : !op%Q%vec(it3) = hybrid
565 : ! Q(it) = BathOperatoroffdiag_hybrid(op, Cibeta - Cdagbeta)
566 : END DO
567 : END DO
568 0 : if(tcheck.ne.tail) then
569 : !write(6,*) " PRB in the loop tail tcheck",tail,tcheck
570 0 : stop
571 : endif
572 :
573 : ! Compute S
574 0 : op%Stau = C - Cdagbeta
575 0 : op%Rtau%vec(op%Fshift(op%activeFlavor)+op%updatePosRow) = op%Stau
576 0 : if(op%Rtau%vec(op%Fshift(op%activeFlavor)+op%updatePosRow)>beta) then
577 : !write(6,*) "Rtau sup beta", op%Stau,C,Cdagbeta
578 0 : stop
579 : endif
580 0 : op%Qtau%vec(op%Fshift(op%activeFlavor)+op%updatePosCol) = op%Rtau%vec(op%Fshift(op%activeFlavor)+op%updatePosRow)
581 : !write(6,*) " getdetAdd op%Stau",op%Stau
582 :
583 0 : time = Cbeta-Cdagbeta
584 : !write(6,*) " getdetAdd time",time
585 0 : iflavora=op%activeFlavor
586 0 : iflavorb=op%activeFlavor
587 : !write(6,*) "time",time
588 : #include "BathOperatoroffdiag_hybrid"
589 : !write(6,*) "hybrid",hybrid
590 0 : op%S = hybrid
591 : !write(6,*) " getdetAdd hybrid=op%S",hybrid
592 :
593 : !ratio = op%S - DOT_PRODUCT(MATMUL(op%R%vec(1:tail),op%M(op%activeFlavor)%mat(1:tail,1:tail)),op%Q%vec(1:tail))
594 :
595 : ! product of matrix R and M(k) is computed now:
596 0 : ratio = 0.d0
597 0 : DO it1 = tailbegin, tailend
598 : time = 0.d0
599 0 : DO it2 = tailbegin, tailend
600 0 : time = time + op%R%vec(it2) * op%M%mat(it2,it1)
601 : END DO
602 0 : ratio = ratio + op%Q%vec(it1) * time
603 : END DO
604 : !sui!write(6,*) " = R Matrix",tail
605 : !sui!write(6,*) " R ",(op%R%vec(it1),it1=1,tail)
606 : !sui!write(6,*) " = Q Matrix",tail
607 : !sui!do it1=1,tail
608 : !sui!write(6,*) " Q ",op%Q%vec(it1)
609 : !sui!enddo
610 : !sui!write(6,*) " = M Matrix",tail
611 : !sui!do it2=1,tail
612 : !sui!write(6,*) " M ",(op%M%mat(it2,it1),it1=1,tail)
613 : !sui!enddo
614 : !sui!write(6,*) " RMQ =", ratio
615 : !sui!write(6,*) " S =", op%S
616 0 : ratio = op%S - ratio
617 : !sui!write(6,*) " S-RMQ =", ratio
618 : !sui!write(6,*) " getdetAdd ratio",ratio
619 :
620 0 : op%Stilde = 1.d0 / ratio
621 : ! If antisegment, the det ratio has to be multiplied by -1 ( sign of the signature of one
622 : ! permutation line in the matrix)
623 0 : IF ( C .LT. Cdag .AND. op%tails(op%activeFlavor) .GT. 0) THEN ! only if an antisegment is added
624 0 : ratio=-ratio
625 : ENDIF
626 :
627 : ! This IF is the LAST "NON CORRECTION" in my opinion this should not appears.
628 : ! IF ( MAX(C,Cdag) .GT. op%beta ) THEN
629 : ! WRITE(*,*) op%Stilde
630 : ! op%Stilde = - ABS(op%Stilde)
631 : ! END IF
632 0 : BathOperatoroffdiag_getDetAdd = ratio
633 : !write(6,*) " getdetAdd",ratio,BathOperatoroffdiag_getDetAdd
634 0 : op%MAddFlag = .TRUE.
635 : !#ifdef CTQMC_CHECK
636 : ! op%ListCdagC = particle
637 : !!write(*,*) op%Stilde
638 : !!write(*,*) op%antishift
639 : !!write(*,*) op%updatePosRow
640 : !!write(*,*) op%updatePosCol
641 : !#endif
642 :
643 0 : END FUNCTION BathOperatoroffdiag_getDetAdd
644 : !!***
645 :
646 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_getDetRemove
647 : !! NAME
648 : !! BathOperatoroffdiag_getDetRemove
649 : !!
650 : !! FUNCTION
651 : !! Compute the determinant ratio when a (anti)segment
652 : !! is trying to be removed
653 : !!
654 : !! COPYRIGHT
655 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
656 : !! This file is distributed under the terms of the
657 : !! GNU General Public License, see ~abinit/COPYING
658 : !! or http://www.gnu.org/copyleft/gpl.txt .
659 : !!
660 : !! INPUTS
661 : !! op=bath operator
662 : !! position=position of segment to be removed
663 : !!
664 : !! OUTPUT
665 : !! BathOperatoroffdiag_getDetRemove=the det
666 : !!
667 : !! SIDE EFFECTS
668 : !!
669 : !! NOTES
670 : !!
671 : !! SOURCE
672 :
673 0 : DOUBLE PRECISION FUNCTION BathOperatoroffdiag_getDetRemove(op,position)
674 :
675 : !Arguments ------------------------------------
676 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
677 : !Local arguments-------------------------------
678 : INTEGER , INTENT(IN ) :: position
679 : INTEGER :: ABSposition
680 : INTEGER :: tail !,it,it1
681 :
682 0 : IF ( op%activeFlavor .LE. 0 ) &
683 0 : CALL ERROR("BathOperatoroffdiag_getDetRemove : no active hybrid fun ")
684 :
685 0 : op%antiShift = .FALSE.
686 0 : tail = op%sumtails
687 0 : ABSposition = ABS(position)
688 0 : IF ( ABSposition .GT. op%tails(op%activeFlavor) ) &
689 0 : CALL ERROR("BathOperatoroffdiag_getDetRemove : position > M size ")
690 0 : op%updatePosCol = ABSposition
691 0 : op%antiShift = .FALSE.
692 0 : IF ( position .GT. 0 ) THEN
693 0 : op%updatePosRow = ABSposition
694 : ELSE
695 0 : op%updatePosRow = ABSposition+1
696 0 : IF ( ABSposition .EQ. op%tails(op%activeFlavor) ) THEN
697 0 : op%antiShift = .TRUE.
698 0 : op%updatePosRow = 1 !ABSposition - 1
699 : ! op%updatePosRow = ABSposition
700 : ! IF ( op%updatePosCol .EQ. 0) op%updatePosCol = tail
701 : END IF
702 : ENDIF
703 : op%Stilde = op%M%mat(op%Fshift(op%activeFlavor)+&
704 0 : & op%updatePosRow,op%Fshift(op%activeFlavor)+op%updatePosCol)
705 : !sui!write(6,*) "Fshift",op%Fshift(op%activeFlavor)
706 : !sui!write(6,*) "updatepos",op%updatePosRow,op%updatePosCol
707 :
708 :
709 0 : op%MRemoveFlag = .TRUE.
710 : !write(6,*) " getdetRemove",op%Stilde
711 0 : BathOperatoroffdiag_getDetRemove = op%Stilde
712 0 : if(position<0.and.op%tails(op%activeFlavor)>1) then
713 0 : BathOperatoroffdiag_getDetRemove = -op%Stilde
714 : endif
715 : !do it=1,op%sumtails
716 : !!sui!write(6,*) " getdetRemove M",(op%M%mat(it,it1),it1=1,op%sumtails)
717 : !enddo
718 : !#ifdef CTQMC_CHECK
719 : ! op%ListCdagC = particle
720 : !!write(*,*) op%updatePosRow, op%updatePosCol, position
721 : !!CALL ListCdagC_print(particle)
722 : !#endif
723 :
724 0 : END FUNCTION BathOperatoroffdiag_getDetRemove
725 : !!***
726 :
727 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_getDetF
728 : !! NAME
729 : !! BathOperatoroffdiag_getDetF
730 : !!
731 : !! FUNCTION
732 : !! Compute the determinant of the F matrix
733 : !! using the hybridization of flavor and the
734 : !! segments of particle
735 : !! used for Gloval moves only
736 : !!
737 : !! COPYRIGHT
738 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
739 : !! This file is distributed under the terms of the
740 : !! GNU General Public License, see ~abinit/COPYING
741 : !! or http://www.gnu.org/copyleft/gpl.txt .
742 : !!
743 : !! INPUTS
744 : !! op=bath operator
745 : !! flavor=hybridization function to take
746 : !! particles=segments to use
747 : !!
748 : !! OUTPUT
749 : !! BathOperatoroffdiag_getDetF=the det
750 : !!
751 : !! SIDE EFFECTS
752 : !!
753 : !! NOTES
754 : !!
755 : !! SOURCE
756 :
757 0 : DOUBLE PRECISION FUNCTION BathOperatoroffdiag_getDetF(op,particle,option)
758 :
759 : !Arguments ------------------------------------
760 : TYPE(BathOperatoroffdiag) , INTENT(INOUT) :: op
761 : TYPE(ListCdagC), OPTIONAL, INTENT(IN ) :: particle(:)
762 : INTEGER , optional :: option
763 : !Local arguments-------------------------------
764 : INTEGER :: iCdag
765 : INTEGER :: iC
766 : INTEGER :: tail
767 : DOUBLE PRECISION :: time
768 : DOUBLE PRECISION :: tC
769 : DOUBLE PRECISION :: tCdag
770 : DOUBLE PRECISION :: beta
771 : DOUBLE PRECISION :: mbeta_two
772 : DOUBLE PRECISION :: signe
773 : DOUBLE PRECISION :: inv_dt
774 : INTEGER :: iflavor,iflavora
775 : INTEGER :: iflavordag,iflavorb
776 : #include "BathOperatoroffdiag_hybrid.h"
777 :
778 0 : BathOperatoroffdiag_getDetF = 1.d0 ! pour eviter des divisions par 0
779 0 : IF ( PRESENT( particle ) ) THEN
780 0 : tail = op%sumtails
781 0 : beta = op%beta
782 0 : mbeta_two = -beta*0.5d0
783 0 : inv_dt = op%inv_dt
784 0 : CALL MatrixHyb_setSize(op%M_update,tail)
785 0 : DO iflavordag=1,op%flavors
786 0 : DO iCdag = 1, op%tails(iflavordag)
787 0 : tCdag = particle(iflavordag)%list(iCdag,Cdag_)
788 0 : DO iflavor=1,op%flavors
789 0 : DO iC = 1, op%tails(iflavor)
790 : !tC = particle%list(C_,iC).MOD.beta
791 0 : MODCYCLE(particle(iflavor)%list(iC,C_),beta,tC)
792 0 : time = tC - tCdag
793 0 : iflavora=iflavordag
794 0 : iflavorb=iflavor
795 : #include "BathOperatoroffdiag_hybrid"
796 0 : op%M_update%mat(op%Fshift(iflavor)+iC,op%Fshift(iflavordag)+iCdag) = hybrid
797 : END DO
798 : END DO
799 : END DO
800 : END DO
801 : ! mat_tau needs to be transpose of ordered time mat (way of measuring
802 : ! G(tau))
803 0 : DO iflavor=1,op%flavors
804 0 : DO iC = 1, tail
805 0 : tC = particle(iflavor)%list(iC,C_)
806 0 : DO iflavordag=1,op%flavors
807 0 : DO iCdag = 1, tail
808 : !sui!write(6,*) iCdag,Cdag_,size(particle(iflavordag)%list,1)
809 : !stop
810 0 : tCdag = particle(iflavordag)%list(iCdag,Cdag_)
811 0 : time = tC - tCdag
812 0 : signe = SIGN(1.d0,time)
813 0 : time = time + (signe-1.d0)*mbeta_two
814 0 : op%M_update%mat_tau(op%Fshift(iflavordag)+iCdag,op%Fshift(iflavor)+iC) = INT( ( time * inv_dt ) + 1.5d0 )
815 : END DO
816 : END DO
817 : END DO
818 : END DO
819 0 : CALL MatrixHyb_inverse(op%M_update,BathOperatoroffdiag_getDetF) ! calcul le det de la matrice et l'inverse
820 : ELSE
821 0 : if(present(option)) then
822 0 : CALL MatrixHyb_getDet(op%M_update,BathOperatoroffdiag_getDetF) ! det M = 1/detF !
823 : else
824 0 : CALL MatrixHyb_getDet(op%M,BathOperatoroffdiag_getDetF) ! det M = 1/detF !
825 : endif
826 0 : BathOperatoroffdiag_getDetF = 1.d0 / BathOperatoroffdiag_getDetF
827 : ENDIF
828 0 : END FUNCTION BathOperatoroffdiag_getDetF
829 : !!***
830 :
831 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_setMAdd
832 : !! NAME
833 : !! BathOperatoroffdiag_setMAdd
834 : !!
835 : !! FUNCTION
836 : !! Update de M matrix inserting a row and a column
837 : !!
838 : !! COPYRIGHT
839 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
840 : !! This file is distributed under the terms of the
841 : !! GNU General Public License, see ~abinit/COPYING
842 : !! or http://www.gnu.org/copyleft/gpl.txt .
843 : !!
844 : !! INPUTS
845 : !! op=bath operator
846 : !! particle=segments of active flavor
847 : !!
848 : !! OUTPUT
849 : !!
850 : !! SIDE EFFECTS
851 : !!
852 : !! NOTES
853 : !!
854 : !! SOURCE
855 :
856 0 : SUBROUTINE BathOperatoroffdiag_setMAdd(op,particle)
857 :
858 : !Arguments ------------------------------------
859 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
860 : TYPE(ListCdagC) , INTENT(IN ) :: particle(:)
861 : !Local variables ------------------------------
862 : INTEGER :: tail
863 : INTEGER :: new_tail
864 : INTEGER :: col
865 : INTEGER :: col_move
866 : INTEGER :: row_move
867 : INTEGER :: row
868 : INTEGER :: positionRow
869 : INTEGER :: positionCol
870 : INTEGER :: aF,indice
871 : INTEGER :: tailb,taile
872 : DOUBLE PRECISION :: Stilde
873 : DOUBLE PRECISION :: time
874 : DOUBLE PRECISION :: mbeta_two
875 : DOUBLE PRECISION :: inv_dt
876 0 : TYPE(Vector) :: vec_tmp
877 0 : TYPE(VectorInt) :: vecI_tmp
878 : INTEGER :: m
879 : INTEGER :: count
880 : INTEGER :: i
881 : INTEGER :: j
882 : INTEGER :: p,it !,it1
883 :
884 :
885 :
886 : ! --- op%MAddFlag is put to .TRUE. in BathOperatoroffdiag_getDetAdd.
887 0 : IF ( op%MAddFlag .EQV. .FALSE. ) &
888 0 : CALL ERROR("BathOperatoroffdiag_setMAdd : MAddFlag turn off ")
889 :
890 : ! --- op%activeFlavor is put in ctqmc_loop
891 0 : aF = op%activeFlavor
892 0 : IF ( aF .LE. 0 ) &
893 0 : CALL ERROR("BathOperatoroffdiag_setMAdd : no active hybrid function ")
894 :
895 : !! do it=1,op%sumtails
896 : !write(6,*) " setMAdd begin M",(op%M%mat(it,it1),it1=1,op%sumtails)
897 : !! enddo
898 : !! do it=1,op%sumtails
899 : !write(6,*) " setMAdd begin M%mat_tau",(op%M%mat_tau(it,it1),it1=1,op%sumtails)
900 : !! enddo
901 : ! old tail
902 : !write(6,*) " BathOperatoroffdiag_setMAdd op%sumtails",op%sumtails
903 0 : tail = op%sumtails
904 0 : new_tail = tail + 1
905 0 : op%tails(aF)= op%tails(aF) + 1
906 0 : DO indice = aF +1, op%flavors+1
907 0 : op%Fshift(indice) = op%Fshift(indice) + 1
908 : END DO
909 0 : op%sumtails = op%Fshift(op%flavors) + op%tails(op%flavors) !last slot of Fshift is the tail of full matrix
910 : !write(6,*) " BathOperatoroffdiag_setMAdd op%sumtails",op%sumtails
911 : !write(6,*) " setMAdd actualized Fshift",(op%Fshift(it),it=1,op%flavors+1)
912 : !write(6,*) " setMAdd actualized tails",(op%tails(it),it=1,op%flavors)
913 : !CALL matrix_print(M)
914 :
915 0 : if(op%opt_nondiag==1) then
916 : tailb = 1
917 : taile = tail
918 : else
919 : !sui!write(6,*) "Bathoperator a opt_nondiag=0"
920 0 : tailb = op%Fshift(aF)+1
921 0 : taile = op%Fshift(aF)+op%tails(aF)
922 : endif
923 :
924 : ! --- data obtained from BathOperatoroffdiag_getDetAdd
925 0 : PositionRow = op%updatePosRow + op%Fshift(aF) ! position in the full matrix
926 0 : PositionCol = op%updatePosCol + op%Fshift(aF) ! position in the full matrix
927 0 : Stilde = op%Stilde
928 :
929 : ! !write(6,*) "before", positionRow, positionCol
930 : !CALL MatrixHyb_print(op%M(aF),opt_print=1)
931 : ! --- MatrixHyb_setSize
932 : !write(6,*) " BathOperatoroffdiag_setMAdd before setsize",size(op%M%mat,1)
933 0 : CALL MatrixHyb_setSize(op%M,new_tail)
934 : !write(6,*) " BathOperatoroffdiag_setMAdd after setsize",size(op%M%mat,1)
935 :
936 : ! Compute Qtilde with Q
937 : !op%Q%vec(1:tail) = (-1.d0) * MATMUL(op%M(aF)%mat(1:tail,1:tail),op%Q%vec(1:tail)) * Stilde
938 :
939 : ! --- M*Q => Q
940 0 : op%Q%vec(tailb:taile) = MATMUL(op%M%mat(tailb:taile,tailb:taile),op%Q%vec(tailb:taile))
941 :
942 : !op%Q%vec(PositionRow:new_tail) = EOSHIFT(op%Q%vec(PositionRow:new_tail), SHIFT=-1, BOUNDARY=-1.d0, DIM=1)
943 : ! op%Qtau%vec(PositionCol:new_tail) = EOSHIFT(op%Qtau%vec(PositionCol:new_tail), SHIFT=-1, BOUNDARY=1.d0, DIM=1)
944 : ! op%Qtau%vec(PositionCol) = op%Stau
945 :
946 : !Compute Rtilde with R and without multiplying by Stilde
947 : !op%R%vec(1:tail) = (-1.d0) * MATMUL(op%R%vec(1:tail),op%M(aF)%mat(1:tail,1:tail))
948 :
949 : ! --- R*M => R
950 0 : op%R%vec(tailb:taile) = MATMUL(op%R%vec(tailb:taile),op%M%mat(tailb:taile,tailb:taile))
951 :
952 : !op%R%vec(PositionCol:new_tail) = EOSHIFT(op%R%vec(PositionCol:new_tail), SHIFT=-1, BOUNDARY=-1.d0, DIM=1)
953 : ! op%Rtau%vec(PositionRow:new_tail) = EOSHIFT(op%Rtau%vec(PositionRow:new_tail), SHIFT=-1, BOUNDARY=1.d0, DIM=1)
954 : ! op%Rtau%vec(PositionRow) = op%Stau
955 :
956 : !Compute the new M matrix
957 : !op%M(aF)%mat(PositionRow:new_tail,1:new_tail) = &
958 : ! EOSHIFT(op%M(aF)%mat(PositionRow:new_tail,1:new_tail),SHIFT=-1, BOUNDARY=0.d0, DIM=1)
959 : !op%M(aF)%mat(1:n12 characters (ABI_MALLOC) instead of 4 (FREE)ew_tail,PositionCol:new_tail) = &
960 : ! EOSHIFT(op%M(aF)%mat(1:new_tail,PositionCol:new_tail),SHIFT=-1, BOUNDARY=0.d0, DIM=2)
961 : ! ! op%M(aF)%mat(1:new_tail,1:new_tail) = op%M(aF)%mat(1:new_tail,1:new_tail) + &
962 : ! ! Stilde * MATMUL(RESHAPE(op%Q%vec(1:new_tail),(/ new_tail,1 /)),RESHAPE(op%R%vec(1:new_tail),(/ 1,new_tail /)))
963 :
964 : !op%M(aF)%mat_tau(PositionRow:new_tail,1:new_tail) = &
965 : ! EOSHIFT(op%M(aF)%mat_tau(PositionRow:new_tail,1:new_tail),SHIFT=-1, BOUNDARY=0, DIM=1)
966 : !op%M(aF)%mat_tau(1:new_tail,PositionCol:new_tail) = &
967 : ! EOSHIFT(op%M(aF)%mat_tau(1:new_tail,PositionCol:new_tail),SHIFT=-1, BOUNDARY=0, DIM=2)
968 :
969 0 : mbeta_two = -op%beta*0.5d0
970 0 : inv_dt = op%inv_dt
971 :
972 : ! ------ Shift mat_tau and update old M=Ptilde
973 0 : DO col=tail,1,-1 ! decreasing order to avoid overwrite of data
974 0 : col_move = col + ( 1+SIGN(1,col-PositionCol) )/2
975 : ! if col>= PositionCol col_move=col+1
976 : ! if col< PositionCol col_move=col
977 0 : DO row=tail,1,-1
978 0 : row_move = row + ( 1+SIGN(1,row-PositionRow) )/2
979 : ! --- times for Ptilde are kept unchanged. But we have to copy it at the right place
980 : op%M%mat_tau(row_move,col_move) = &
981 0 : op%M%mat_tau(row,col)
982 : ! --- Update Ptilde with the same indices as mat_tau
983 : ! --- M + M*Q Stilde R*M => Ptilde => M
984 : !if(row>=tailb.and.row<=taile.and.col>=tailb.and.col<=taile) then
985 : op%M%mat(row_move,col_move) = &
986 0 : op%M%mat(row,col) + op%Q%vec(row)*op%R%vec(col) * Stilde
987 : !else
988 : ! op%M%mat(row_move,col_move) = op%M%mat(row,col)
989 : !endif
990 : END DO
991 : END DO
992 :
993 : ! ------ Add new stuff for new row
994 0 : DO row = 1, tail
995 0 : row_move = row + ( 1+SIGN(1,row-PositionRow) )/2
996 : ! --- M*Q Stilde => Qtilde => M with the good indices
997 : !if(row>=tailb.and.row<=taile) then
998 0 : op%M%mat(row_move,PositionCol) = -op%Q%vec(row)*Stilde
999 : !else
1000 : ! op%M%mat(row_move,PositionCol) = op%M%mat(row,PositionCol)
1001 : !endif
1002 :
1003 0 : time = op%Rtau%vec(row) ! pourquoi Rtau et pas Qtau ici ?
1004 0 : time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1005 : ! if time>=0 time=time
1006 : ! if time< 0 time=time + beta
1007 : ! --- mat_tau=int(time*L/beta+1.5)
1008 0 : op%M%mat_tau(row,PositionCol) = INT ( (time*inv_dt) +1.5d0 )
1009 : !write(6,*) " setMadd new row", op%Rtau%vec(row),op%M%mat_tau(row,PositionCol)
1010 : ! if(op%M%mat_tau(row,PositionCol)>301) then
1011 : ! !write(6,*) ">301 a", time,inv_dt, op%M%mat_tau(row,PositionCol)
1012 : ! time = op%Rtau%vec(row) ! pourquoi Rtau et pas Qtau ici ?
1013 : ! !write(6,*) time,mbeta_two
1014 : ! time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1015 : ! !write(6,*) time
1016 : ! !write(6,*) INT ( (time*inv_dt) +1.5d0 )
1017 : ! stop
1018 : ! endif
1019 : END DO
1020 : ! Add last time missing in the loops
1021 0 : time = op%Rtau%vec(new_tail)
1022 0 : time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1023 0 : op%M%mat_tau(new_tail,PositionCol) = INT ( (time*inv_dt) +1.5d0 )
1024 : !write(6,*) " setMadd last time", op%Rtau%vec(new_tail),op%M%mat_tau(new_tail,PositionCol)
1025 : ! if(op%M%mat_tau(new_tail,PositionCol)>301) then
1026 : ! !write(6,*) ">301 b", time,inv_dt, op%M%mat_tau(new_tail,PositionCol)
1027 : ! time = op%Rtau%vec(new_tail) ! pourquoi Rtau et pas Qtau ici ?
1028 : ! !write(6,*) time,mbeta_two
1029 : ! time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1030 : ! !write(6,*) time
1031 : ! !write(6,*) INT ( (time*inv_dt) +1.5d0 )
1032 : ! stop
1033 : ! endif
1034 :
1035 : ! Add new stuff for new col
1036 0 : DO col = 1, tail
1037 0 : col_move = col + ( 1+SIGN(1,col-PositionCol) )/2
1038 : ! --- Stilde RN => Rtilde => M
1039 : !if(col>=tailb.and.col<=taile) then
1040 0 : op%M%mat(PositionRow,col_move) = -op%R%vec(col)*Stilde
1041 : !else
1042 : ! op%M%mat(PositionRow,col_move) = op%M%mat(PositionRow,col)
1043 : !endif
1044 0 : time = op%Qtau%vec(col)
1045 0 : time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1046 0 : op%M%mat_tau(PositionRow,col) = INT ( (time*inv_dt) +1.5d0 )
1047 : !write(6,*) " setMadd new col", op%Qtau%vec(col),op%M%mat_tau(PositionRow,col)
1048 : ! if(op%M%mat_tau(PositionRow,col)>301) then
1049 : ! !write(6,*) ">301 c", time,inv_dt, op%M%mat_tau(PositionRow,col)
1050 : ! time = op%Qtau%vec(col) ! pourquoi Rtau et pas Qtau ici ?
1051 : ! !write(6,*) time,mbeta_two
1052 : ! time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1053 : ! !write(6,*) time
1054 : ! !write(6,*) INT ( (time*inv_dt) +1.5d0 )
1055 : ! stop
1056 : ! endif
1057 : END DO
1058 : ! Add last time missing in the loops
1059 0 : time = op%Qtau%vec(new_tail)
1060 0 : time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1061 0 : op%M%mat_tau(PositionRow,new_tail) = INT ( (time*inv_dt) +1.5d0 )
1062 : !write(6,*) " setMadd last time", op%Qtau%vec(new_tail),op%M%mat_tau(PositionRow,new_tail)
1063 : ! if(op%M%mat_tau(PositionRow,new_tail)>301) then
1064 : ! !write(6,*) ">301 d", time,inv_dt, op%M%mat_tau(PositionRow,new_tail)
1065 : ! time = op%Qtau%vec(new_tail) ! pourquoi Rtau et pas Qtau ici ?
1066 : ! !write(6,*) time,mbeta_two
1067 : ! time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1068 : ! !write(6,*) time
1069 : ! !write(6,*) INT ( (time*inv_dt) +1.5d0 )
1070 : ! stop
1071 : ! endif
1072 :
1073 0 : op%M%mat(PositionRow,PositionCol) = Stilde
1074 :
1075 : !CALL MatrixHyb_print(op%M,opt_print=1)
1076 :
1077 : ! DO col = 1, new_tail
1078 : ! time = op%Rtau%vec(col)
1079 : ! time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1080 : ! op%M(aF)%mat_tau(col,PositionCol) = INT ( (time*inv_dt) +1.5d0 )
1081 : ! time = op%Qtau%vec(col)
1082 : ! time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1083 : ! op%M(aF)%mat_tau(PositionRow,Col) = INT ( (time*inv_dt) +1.5d0 )
1084 : ! time = op%R%vec(col)*Stilde
1085 : ! DO row = 1, new_tail
1086 : ! op%M(aF)%mat(row,col) = op%M(aF)%mat(row,col) + op%Q%vec(row)*time
1087 : ! END DO
1088 : ! END DO
1089 :
1090 : !col_move = new_tail
1091 : !col = tail
1092 : !DO col_move = new_tail, 1, -1
1093 : ! IF ( col_move .EQ. positionCol ) THEN
1094 : ! ! on calcule rajoute Q tilde
1095 : ! !row_move = new_tail
1096 : ! row = tail
1097 : ! DO row_move = new_tail, 1, -1
1098 : ! ! calcul itau
1099 : ! IF ( row_move .EQ. positionRow ) THEN
1100 : ! op%M(aF)%mat(row_move,col_move) = Stilde
1101 : ! !time = op%Stau
1102 : ! ELSE
1103 : ! op%M(aF)%mat(row_move,col_move) = -op%Q%vec(row)*Stilde
1104 : ! !time = op%Rtau%vec(row_move)
1105 : ! row = row - 1
1106 : ! END IF
1107 : ! !time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1108 : ! !op%M(aF)%mat_tau(row_move,col_move) = INT ( (time*inv_dt) +1.5d0 )
1109 : ! END DO
1110 : ! ! realignement des indices
1111 : ! ELSE
1112 : ! ! on calcule Ptilde
1113 : ! !row_move = new_tail
1114 : ! row = tail
1115 : ! DO row_move = new_tail, 1, -1
1116 : ! IF ( row_move .EQ. positionRow ) THEN
1117 : ! op%M(aF)%mat(row_move,col_move) = -op%R%vec(col) * Stilde
1118 : ! ! calcul itau
1119 : ! !time = op%Qtau%vec(col_move)
1120 : ! !time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
1121 : ! !op%M(aF)%mat_tau(row_move,col_move) = INT ( (time*inv_dt) +1.5d0 )
1122 : ! ELSE
1123 : ! op%M(aF)%mat(row_move,col_move) = op%M(aF)%mat(row,col) + op%Q%vec(row)*op%R%vec(col)*Stilde
1124 : ! ! copy itau
1125 : ! !op%M(aF)%mat_tau(row_move,col_move) = op%M(aF)%mat_tau(row,col)
1126 : ! row = row - 1
1127 : ! END IF
1128 : ! END DO
1129 : ! col = col - 1
1130 : ! END IF
1131 : !END DO
1132 : ! !write(6,*) "after"
1133 : ! CALL MatrixHyb_print(op%M(aF),opt_print=1)
1134 : !CALL matrix_inverse(M)
1135 : !CALL MatrixHyb_print(M)
1136 : !CALL matrix_inverse(M)
1137 :
1138 0 : IF ( op%antiShift .EQV. .TRUE. ) THEN ! antisegment
1139 : if(3==4) then
1140 : CALL Vector_init(vec_tmp,new_tail)
1141 : CALL VectorInt_init(vecI_tmp,new_tail)
1142 : ! Shift if necessary according to op%antishift
1143 : ! shift DIM=2 (col)
1144 :
1145 : ! For new_tail=4, the following lines transform
1146 : ! M=(a,b,c,d) vith a,b,c,d column vectors into
1147 : ! M=(d,a,b,c)
1148 : p = new_tail - 1 ! = tail
1149 : m = 1
1150 : ! count increases in the loop from 0 to new_tail-1
1151 : count = 0
1152 : DO WHILE ( count .NE. new_tail )
1153 : ! put column b in vec_tmp
1154 : vec_tmp%vec(1:new_tail) = op%M%mat(1:new_tail,m)
1155 : vecI_tmp%vec(1:new_tail) = op%M%mat_tau(1:new_tail,m)
1156 : i = m
1157 : !j = m+p
1158 : MODCYCLE(m+p, new_tail, j) ! j=m+p modulo new_tail
1159 : DO WHILE (j .NE. m)
1160 : op%M%mat(1:new_tail,i) = op%M%mat(1:new_tail,j)
1161 : op%M%mat_tau(1:new_tail,i) = op%M%mat_tau(1:new_tail,j)
1162 : i = j
1163 : MODCYCLE(j+p, new_tail, j)
1164 : count = count+1
1165 : END DO
1166 : op%M%mat(1:new_tail,i) = vec_tmp%vec(1:new_tail)
1167 : op%M%mat_tau(1:new_tail,i) = vecI_tmp%vec(1:new_tail)
1168 : count = count+1
1169 : m = m+1
1170 : END DO
1171 : ! shift DIM=1 (row)
1172 :
1173 : ! below is similar to above but for rows instead of columns.
1174 : p = new_tail - 1
1175 : m = 1
1176 : count = 0
1177 : DO WHILE ( count .NE. new_tail)
1178 : vec_tmp%vec(1:new_tail) = op%M%mat(m,1:new_tail)
1179 : vecI_tmp%vec(1:new_tail) = op%M%mat_tau(m,1:new_tail)
1180 : i = m
1181 : !j = m+p
1182 : MODCYCLE(m+p, new_tail, j)
1183 : DO WHILE ( j .NE. m )
1184 : op%M%mat(i,1:new_tail) = op%M%mat(j,1:new_tail)
1185 : op%M%mat_tau(i,1:new_tail) = op%M%mat_tau(j,1:new_tail)
1186 : i = j
1187 : MODCYCLE(j+p, new_tail, j)
1188 : count = count+1
1189 : END DO
1190 : op%M%mat(i,1:new_tail) = vec_tmp%vec(1:new_tail)
1191 : op%M%mat_tau(i,1:new_tail) = vecI_tmp%vec(1:new_tail)
1192 : count = count+1
1193 : m = m+1
1194 : END DO
1195 : CALL Vector_destroy(vec_tmp)
1196 : CALL VectorInt_destroy(vecI_tmp)
1197 : endif
1198 : !op%M(aF)%mat(1:new_tail,1:new_tail) = CSHIFT(op%M(aF)%mat(1:new_tail,1:new_tail), SHIFT=-1, DIM=1) ! Shift to the bottom
1199 : !op%M(aF)%mat(1:new_tail,1:new_tail) = CSHIFT(op%M(aF)%mat(1:new_tail,1:new_tail), SHIFT=-1, DIM=2) ! Shift to the right
1200 : !op%M(aF)%mat_tau(1:new_tail,1:new_tail) = CSHIFT(op%M(aF)%mat_tau(1:new_tail,1:new_tail), SHIFT=-1, DIM=1) ! Shift to the bottom
1201 : !op%M(aF)%mat_tau(1:new_tail,1:new_tail) = CSHIFT(op%M(aF)%mat_tau(1:new_tail,1:new_tail), SHIFT=-1, DIM=2) ! Shift to the right
1202 : !write(6,*) " setMAdd size M%mat",size(op%M%mat,1),size(op%M%mat,2),new_tail
1203 : !write(6,*) " setMAdd arguement M%mat",aF,op%Fshift(aF)
1204 : !write(6,*) " setMAdd arguement M%mat",aF,op%Fshift(aF),op%Fshift(aF+1)
1205 0 : do it=1,op%sumtails
1206 : !write(6,*) " setMAdd before antishift M%mat_tau",(op%M%mat_tau(it,it1),it1=1,op%sumtails)
1207 : enddo
1208 0 : if (new_tail>0.and.op%Fshift(aF+1)>op%Fshift(aF)) then
1209 : op%M%mat(op%Fshift(aF)+1:op%Fshift(aF+1) , 1:new_tail) = &
1210 0 : CSHIFT( op%M%mat(op%Fshift(aF)+1:op%Fshift(aF+1) , 1:new_tail) , SHIFT=-1 , DIM=1) ! Shift to the bottom
1211 :
1212 : op%M%mat(1:new_tail , op%Fshift(aF)+1:op%Fshift(aF+1)) = &
1213 0 : CSHIFT( op%M%mat(1:new_tail , op%Fshift(aF)+1:op%Fshift(aF+1)) , SHIFT=-1 , DIM=2) ! Shift to the right
1214 :
1215 : op%M%mat_tau(op%Fshift(aF)+1:op%Fshift(aF+1) , 1:new_tail) = &
1216 0 : CSHIFT( op%M%mat_tau(op%Fshift(aF)+1:op%Fshift(aF+1) , 1:new_tail) , SHIFT=-1 , DIM=1) ! Shift to the bottom
1217 :
1218 : op%M%mat_tau(1:new_tail , op%Fshift(aF)+1:op%Fshift(aF+1)) = &
1219 0 : CSHIFT( op%M%mat_tau(1:new_tail , op%Fshift(aF)+1:op%Fshift(aF+1)) , SHIFT=-1 , DIM=2) ! Shift to the right
1220 : end if
1221 : !CALL matrix_print(M)
1222 : END IF
1223 :
1224 : !! do it=1,op%sumtails
1225 : !write(6,*) " setMAdd end M",(op%M%mat(it,it1),it1=1,op%sumtails)
1226 : !! enddo
1227 : !! do it=1,op%sumtails
1228 : !! !write(6,*) " setMAdd end M%mat_tau",(op%M%mat_tau(it,it1),it1=1,op%sumtails)
1229 : !! enddo
1230 0 : IF ( op%doCheck .EQV. .TRUE.) THEN
1231 : !#ifdef CTQMC_CHECK
1232 0 : CALL BathOperatoroffdiag_checkM(op,particle)
1233 : !#endif
1234 : END IF
1235 :
1236 0 : op%MAddFlag = .FALSE.
1237 :
1238 0 : END SUBROUTINE BathOperatoroffdiag_setMAdd
1239 : !!***
1240 :
1241 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_setMRemove
1242 : !! NAME
1243 : !! BathOperatoroffdiag_setMRemove
1244 : !!
1245 : !! FUNCTION
1246 : !! delete one row and one column of the M matrix
1247 : !!
1248 : !! COPYRIGHT
1249 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1250 : !! This file is distributed under the terms of the
1251 : !! GNU General Public License, see ~abinit/COPYING
1252 : !! or http://www.gnu.org/copyleft/gpl.txt .
1253 : !!
1254 : !! INPUTS
1255 : !! op=bath operator
1256 : !! particle=segments of the active flavor
1257 : !!
1258 : !! OUTPUT
1259 : !!
1260 : !! SIDE EFFECTS
1261 : !!
1262 : !! NOTES
1263 : !!
1264 : !! SOURCE
1265 :
1266 0 : SUBROUTINE BathOperatoroffdiag_setMRemove(op,particle)
1267 :
1268 : !Arguments ------------------------------------
1269 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
1270 : TYPE(ListCdagC) , INTENT(IN ) :: particle(:)
1271 : !Local variables ------------------------------
1272 : INTEGER :: tail,tailb,taile
1273 : INTEGER :: new_tail
1274 : INTEGER :: col
1275 : INTEGER :: col_move
1276 : INTEGER :: row_move
1277 : INTEGER :: row
1278 : INTEGER :: positionCol
1279 : INTEGER :: positionRow
1280 : INTEGER :: aF,iaf
1281 : INTEGER :: m
1282 : INTEGER :: count
1283 : INTEGER :: i
1284 : INTEGER :: j,it !,it1
1285 : INTEGER :: p
1286 : DOUBLE PRECISION :: invStilde
1287 : DOUBLE PRECISION :: invStilde2
1288 0 : TYPE(VectorInt) :: vecI_tmp
1289 0 : TYPE(Vector) :: vec_tmp
1290 :
1291 0 : IF ( op%MRemoveFlag .EQV. .FALSE. ) &
1292 0 : CALL ERROR("BathOperatoroffdiag_setMRemove : MRemoveFlag turn off ")
1293 0 : aF = op%activeFlavor
1294 0 : IF ( aF .LE. 0 ) &
1295 0 : CALL ERROR("BathOperatoroffdiag_setMRemove : no active hybrid func ")
1296 0 : do it=1,op%sumtails
1297 : !write(6,*) " setMRemove begin M",(op%M%mat(it,it1),it1=1,op%sumtails)
1298 : enddo
1299 0 : tail = op%sumtails
1300 0 : new_tail = tail - 1
1301 0 : op%tails(af)= op%tails(af) - 1
1302 0 : DO iaf=af+1 , op%flavors+1
1303 0 : op%Fshift(iaf) = op%Fshift(iaf) - 1
1304 : END DO
1305 0 : op%sumtails = op%Fshift(op%flavors) + op%tails(op%flavors)
1306 0 : positionCol = op%updatePosCol + op%Fshift(af)
1307 0 : positionRow = op%updatePosRow + op%Fshift(af)
1308 0 : invStilde = 1.d0 / op%Stilde
1309 : if(op%opt_nondiag==1) then
1310 : tailb = 1
1311 : taile = new_tail
1312 : else
1313 : !sui!write(6,*) "Bathoperator c opt_nondiag=0"
1314 : tailb = op%Fshift(aF)+1
1315 : taile = op%Fshift(aF)+op%tails(aF)
1316 : endif
1317 :
1318 : ! !write(6,*) "before", positionRow, positionCol
1319 : ! CALL MatrixHyb_print(op%M(aF),opt_print=1)
1320 :
1321 : ! IF ( new_tail .EQ. 0 ) THEN
1322 : !! IF ( op%antiShift .EQV. .TRUE. ) THEN
1323 : !! op%M(aF)%mat(1,1) = 1.d0/BathOperatoroffdiag_Hybrid(op, op%beta)
1324 : !! op%MRemoveFlag = .FALSE.
1325 : !! RETURN
1326 : !! END IF
1327 : ! CALL MatrixHyb_clear(op%M(aF))
1328 : ! op%MRemoveFlag = .FALSE.
1329 : ! RETURN
1330 : ! END IF
1331 :
1332 : ! CALL Vector_setSize(op%Q,new_tail)
1333 : ! CALL Vector_setSize(op%R,new_tail)
1334 0 : Vector_QuickResize(op%Q,new_tail)
1335 0 : Vector_QuickResize(op%R,new_tail)
1336 :
1337 : ! We use R and Q as op%R%vec and op%Q%vec
1338 : ! op%R%vec => op%R
1339 : ! op%Q%vec => op%Q
1340 :
1341 0 : row = 1
1342 : !row_move = 1
1343 0 : col = 1
1344 : !col_move = 1
1345 0 : DO row_move = 1, new_tail
1346 0 : IF ( row .EQ. positionRow ) row = row + 1
1347 0 : IF ( col .EQ. positionCol ) col = col + 1
1348 : !col = row_move + (1+SIGN(1,row_move-positionCol))/2
1349 : !row = row_move + (1+SIGN(1,row_move-positionRow))/2
1350 0 : op%R%vec(row_move) = op%M%mat(positionRow,col)
1351 0 : op%Q%vec(row_move) = op%M%mat(row,positionCol)
1352 0 : row = row + 1
1353 0 : col = col + 1
1354 : END DO
1355 : !! op%R%vec(1:positionCol-1) = op%M(aF)%mat(positionRow,1:positionCol-1)
1356 : !! op%R%vec(positionCol:new_tail) = op%M(aF)%mat(positionRow,positionCol+1:tail)
1357 : !! op%Q%vec(1:positionRow-1) = op%M(aF)%mat(1:positionRow-1,positionCol)
1358 : !! op%Q%vec(positionRow:new_tail) = op%M(aF)%mat(positionRow+1:tail,positionCol)
1359 : !write(*,*) positionRow, positionCol
1360 : !CALL MatrixHyb_print(M)
1361 : !CALL Vector_print(op%R)
1362 : !CALL Vector_print(op%Q)
1363 : !CALL ListCdagC_print(op%ListCdagC)
1364 :
1365 : col = 1
1366 0 : DO col_move = 1, new_tail
1367 0 : IF ( col_move .EQ. positionCol ) col = col + 1
1368 : !col = col_move + (1+SIGN(1,col_move-positionCol))/2
1369 0 : row = 1
1370 0 : invStilde2 = invStilde * op%R%vec(col_move)
1371 0 : DO row_move = 1, new_tail
1372 0 : IF ( row_move .EQ. positionRow ) row = row + 1
1373 : !row = row_move + (1+SIGN(1,row_move-positionRow))/2
1374 : ! Compute for all rows and cols M <= M - Q 1/S R
1375 : !if(row_move>=tailb.and.row_move<=taile.and.col_move>=tailb.and.col_move<=taile) then
1376 : op%M%mat(row_move,col_move) = op%M%mat(row,col) &
1377 0 : - op%Q%vec(row_move)*invStilde2
1378 : !else
1379 : ! op%M%mat(row_move,col_move) = op%M%mat(row,col)
1380 : !endif
1381 0 : op%M%mat_tau(row_move,col_move) = op%M%mat_tau(row,col)
1382 0 : row = row + 1
1383 : END DO
1384 0 : col = col + 1
1385 : END DO
1386 0 : CALL MatrixHyb_setSize(op%M,new_tail)
1387 :
1388 0 : IF ( op%antiShift .EQV. .TRUE. ) THEN ! antisegment
1389 : if(3==4) then
1390 : ! Shift if necessary according to op%antishift
1391 : ! shift DIM=2 (col)
1392 : CALL Vector_init(vec_tmp,new_tail)
1393 : CALL VectorInt_init(vecI_tmp,new_tail)
1394 : p = 1
1395 : m = 1
1396 : count = 0
1397 : DO WHILE ( count .NE. new_tail )
1398 : vec_tmp%vec(1:new_tail) = op%M%mat(1:new_tail,m)
1399 : vecI_tmp%vec(1:new_tail) = op%M%mat_tau(1:new_tail,m)
1400 : i = m
1401 : !j = m+p
1402 : MODCYCLE(m+p, new_tail, j)
1403 : DO WHILE (j .NE. m)
1404 : op%M%mat(1:new_tail,i) = op%M%mat(1:new_tail,j)
1405 : op%M%mat_tau(1:new_tail,i) = op%M%mat_tau(1:new_tail,j)
1406 : i = j
1407 : MODCYCLE(j+p, new_tail, j)
1408 : count = count+1
1409 : END DO
1410 : op%M%mat(1:new_tail,i) = vec_tmp%vec(1:new_tail)
1411 : op%M%mat_tau(1:new_tail,i) = vecI_tmp%vec(1:new_tail)
1412 : count = count+1
1413 : m = m+1
1414 : END DO
1415 : CALL Vector_destroy(vec_tmp)
1416 : CALL VectorInt_destroy(vecI_tmp)
1417 : !op%M(aF)%mat(1:new_tail,1:new_tail) = &
1418 : ! CSHIFT(op%M(aF)%mat(1:new_tail,1:new_tail), SHIFT=1, DIM=2) ! Shift to the top
1419 : !op%M(aF)%mat_tau(1:new_tail,1:new_tail) = &
1420 : ! CSHIFT(op%M(aF)%mat_tau(1:new_tail,1:new_tail), SHIFT=1, DIM=2) ! Shift to the top
1421 : endif
1422 0 : if (new_tail>0.and.op%Fshift(af+1)>op%Fshift(af)) then
1423 : op%M%mat(1:new_tail,op%Fshift(af)+1:op%Fshift(af+1)) = &
1424 0 : CSHIFT(op%M%mat(1:new_tail,op%Fshift(af)+1:op%Fshift(af+1)), SHIFT=1, DIM=2) ! Shift to the top
1425 : op%M%mat_tau(1:new_tail,op%Fshift(af)+1:op%Fshift(af+1)) = &
1426 0 : CSHIFT(op%M%mat_tau(1:new_tail,op%Fshift(af)+1:op%Fshift(af+1)), SHIFT=1, DIM=2) ! Shift to the top
1427 : end if
1428 : END IF
1429 : ! !write(6,*) "after "
1430 : ! CALL MatrixHyb_print(op%M(aF),opt_print=1)
1431 :
1432 0 : IF ( op%doCheck .EQV. .TRUE. ) THEN
1433 : !#ifdef CTQMC_CHECK
1434 0 : CALL BathOperatoroffdiag_checkM(op,particle)
1435 : !#endif
1436 : END IF
1437 0 : do it=1,op%sumtails
1438 : !write(6,*) " setMRemove end M",(op%M%mat(it,it1),it1=1,op%sumtails)
1439 : enddo
1440 :
1441 0 : op%MRemoveFlag = .FALSE.
1442 :
1443 0 : END SUBROUTINE BathOperatoroffdiag_setMRemove
1444 : !!***
1445 :
1446 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_swap
1447 : !! NAME
1448 : !! BathOperatoroffdiag_swap
1449 : !!
1450 : !! FUNCTION
1451 : !! Recompute 2 M matrix swaping the segments (used for Global moves)
1452 : !!
1453 : !! COPYRIGHT
1454 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1455 : !! This file is distributed under the terms of the
1456 : !! GNU General Public License, see ~abinit/COPYING
1457 : !! or http://www.gnu.org/copyleft/gpl.txt .
1458 : !!
1459 : !! INPUTS
1460 : !! op=bath operator
1461 : !! iflavor1=flavor to swap with the next one
1462 : !! iflavor2=favor to swap with the previous one
1463 : !!
1464 : !! OUTPUT
1465 : !!
1466 : !! SIDE EFFECTS
1467 : !!
1468 : !! NOTES
1469 : !!
1470 : !! SOURCE
1471 :
1472 0 : SUBROUTINE BathOperatoroffdiag_swap(op, flavor1, flavor2)
1473 :
1474 : !Arguments ------------------------------------
1475 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
1476 : INTEGER , INTENT(IN ) :: flavor1
1477 : INTEGER , INTENT(IN ) :: flavor2
1478 : INTEGER :: ii,iflavort,itmptail,flavora,flavorb
1479 0 : DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:,:) :: mat_temp
1480 0 : INTEGER , ALLOCATABLE, DIMENSION(:,:) :: mat_tau_temp
1481 :
1482 0 : if(flavor1>flavor2) then
1483 : flavora=flavor2
1484 : flavorb=flavor1
1485 : else
1486 0 : flavora=flavor1
1487 0 : flavorb=flavor2
1488 : endif
1489 0 : MALLOC(mat_temp,(1:op%sumtails,1:op%sumtails))
1490 0 : MALLOC(mat_tau_temp,(1:op%sumtails,1:op%sumtails))
1491 : !mat_temp= op%M%mat
1492 : !mat_tau_temp= op%M%mat_tau
1493 : !it1=0
1494 : !do iflav1=1,op%flavors
1495 : ! do ii1=1,op%tails(iflav1)
1496 : ! it1=it1+1
1497 : ! it2=0
1498 : ! do iflav2=1,op%flavors
1499 : ! do ii2=1,op%tails(iflav1)
1500 : ! it2=it2+1
1501 : ! op%M%mat(it1,it2)=
1502 : ! enddo
1503 : ! enddo
1504 : ! enddo
1505 : !enddo
1506 : if(3==3) then
1507 0 : op%M=op%M_update
1508 0 : if (op%sumtails>0) then
1509 : ! shift block flavorb at the place of flavora (column)
1510 0 : if (op%Fshift(flavorb+1)>op%Fshift(flavora)) then
1511 0 : do ii=1, op%tails(flavorb)
1512 : op%M%mat(op%Fshift(flavora)+1:op%Fshift(flavorb+1) , 1:op%sumtails) = &
1513 0 : CSHIFT( op%M%mat(op%Fshift(flavora)+1:op%Fshift(flavorb+1) , 1:op%sumtails) , SHIFT=-1 , DIM=1)
1514 : op%M%mat_tau(op%Fshift(flavora)+1:op%Fshift(flavorb+1) , 1:op%sumtails) = &
1515 0 : CSHIFT( op%M%mat_tau(op%Fshift(flavora)+1:op%Fshift(flavorb+1) , 1:op%sumtails) , SHIFT=-1 , DIM=1)
1516 : enddo
1517 : end if
1518 :
1519 : ! shift block flavora at the place of flavorb (column)
1520 0 : if (op%Fshift(flavorb)>op%Fshift(flavora)) then
1521 0 : do ii=1, op%tails(flavora)
1522 : op%M%mat(op%Fshift(flavora)+op%tails(flavorb)+&
1523 : & 1:op%Fshift(flavorb)+op%tails(flavorb) , 1:op%sumtails) = &
1524 : CSHIFT( op%M%mat( op%Fshift(flavora)+op%tails(flavorb)&
1525 0 : & +1:op%Fshift(flavorb)+op%tails(flavorb) , 1:op%sumtails) , SHIFT=1 , DIM=1)
1526 : op%M%mat_tau(op%Fshift(flavora)+op%tails(flavorb)+1:op%Fshift(flavorb)+&
1527 : & op%tails(flavorb) , 1:op%sumtails) = &
1528 : CSHIFT( op%M%mat_tau( op%Fshift(flavora)+op%tails(flavorb)+&
1529 0 : & 1:op%Fshift(flavorb)+op%tails(flavorb) , 1:op%sumtails) , SHIFT=1 , DIM=1)
1530 : enddo
1531 : end if
1532 :
1533 : ! shift block flavorb at the place of flavora (row)
1534 0 : if (op%Fshift(flavorb+1)>op%Fshift(flavora)) then
1535 0 : do ii=1, op%tails(flavorb)
1536 : op%M%mat(1:op%sumtails , op%Fshift(flavora)+1:op%Fshift(flavorb+1)) = &
1537 0 : CSHIFT( op%M%mat(1:op%sumtails , op%Fshift(flavora)+1:op%Fshift(flavorb+1)) , SHIFT=-1 , DIM=2)
1538 : op%M%mat_tau(1:op%sumtails , op%Fshift(flavora)+1:op%Fshift(flavorb+1)) = &
1539 0 : CSHIFT( op%M%mat_tau(1:op%sumtails , op%Fshift(flavora)+1:op%Fshift(flavorb+1)) , SHIFT=-1 , DIM=2)
1540 : enddo
1541 : end if
1542 :
1543 : ! shift block flavora at the place of flavorb (row)
1544 0 : if (op%Fshift(flavorb)>op%Fshift(flavora)) then
1545 0 : do ii=1, op%tails(flavora)
1546 : op%M%mat(1:op%sumtails , op%Fshift(flavora)+op%tails(flavorb)+1:op%Fshift(flavorb)+op%tails(flavorb)) = &
1547 : CSHIFT( op%M%mat(1:op%sumtails ,op%Fshift(flavora)+op%tails(flavorb)&
1548 0 : & +1:op%Fshift(flavorb)+op%tails(flavorb)) , SHIFT=1 , DIM=2)
1549 : op%M%mat_tau(1:op%sumtails ,op%Fshift(flavora)+op%tails(flavorb)+&
1550 : & 1:op%Fshift(flavorb)+op%tails(flavorb) ) = &
1551 : CSHIFT( op%M%mat_tau(1:op%sumtails ,op%Fshift(flavora)+&
1552 0 : & op%tails(flavorb)+1:op%Fshift(flavorb)+op%tails(flavorb) ) , SHIFT=1 , DIM=2)
1553 : enddo
1554 : end if
1555 : end if
1556 : endif
1557 : if(3==4) then
1558 : op%M=op%M_update
1559 : endif
1560 :
1561 :
1562 0 : do iflavort=flavora+1,flavorb
1563 0 : op%Fshift(iflavort)=op%Fshift(iflavort)+op%tails(flavorb)-op%tails(flavora)
1564 : enddo
1565 :
1566 0 : itmptail=op%tails(flavora)
1567 0 : op%tails(flavora)=op%tails(flavorb)
1568 0 : op%tails(flavorb)=itmptail
1569 0 : FREE(mat_temp)
1570 0 : FREE(mat_tau_temp)
1571 :
1572 0 : END SUBROUTINE BathOperatoroffdiag_swap
1573 : !!***
1574 :
1575 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_initF
1576 : !! NAME
1577 : !! BathOperatoroffdiag_initF
1578 : !!
1579 : !! FUNCTION
1580 : !! Copy input hybridization functions from a file
1581 : !!
1582 : !! COPYRIGHT
1583 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1584 : !! This file is distributed under the terms of the
1585 : !! GNU General Public License, see ~abinit/COPYING
1586 : !! or http://www.gnu.org/copyleft/gpl.txt .
1587 : !!
1588 : !! INPUTS
1589 : !! op=bath operator
1590 : !! ifstream=file stream to read F
1591 : !!
1592 : !! OUTPUT
1593 : !! argout(sizeout)=description
1594 : !!
1595 : !! SIDE EFFECTS
1596 : !!
1597 : !! NOTES
1598 : !!
1599 : !! SOURCE
1600 :
1601 0 : SUBROUTINE BathOperatoroffdiag_initF(op,ifstream)
1602 :
1603 : !Arguments ----------------------
1604 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
1605 : INTEGER , INTENT(IN ) :: ifstream
1606 : !Local variables ----------------
1607 : INTEGER :: iflavor1
1608 : INTEGER :: iflavor2
1609 : INTEGER :: sample
1610 :
1611 0 : IF ( op%set .EQV. .FALSE. ) &
1612 0 : CALL ERROR("BathOperatoroffdiag_initF : BathOperatoroffdiag not set ")
1613 :
1614 0 : DO iflavor1=1,op%flavors
1615 0 : DO iflavor2=2,op%flavors
1616 0 : DO sample = 1, op%sizeHybrid
1617 0 : READ(ifstream,*) op%F(sample,iflavor1,iflavor2)
1618 : END DO
1619 : END DO
1620 : END DO
1621 0 : END SUBROUTINE BathOperatoroffdiag_initF
1622 : !!***
1623 :
1624 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_setF
1625 : !! NAME
1626 : !! BathOperatoroffdiag_setF
1627 : !!
1628 : !! FUNCTION
1629 : !! Copy F from input array
1630 : !!
1631 : !! COPYRIGHT
1632 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1633 : !! This file is distributed under the terms of the
1634 : !! GNU General Public License, see ~abinit/COPYING
1635 : !! or http://www.gnu.org/copyleft/gpl.txt .
1636 : !!
1637 : !! INPUTS
1638 : !! op=bath operator
1639 : !! F=array of the hybridization function
1640 : !!
1641 : !! OUTPUT
1642 : !!
1643 : !! SIDE EFFECTS
1644 : !!
1645 : !! NOTES
1646 : !!
1647 : !! SOURCE
1648 :
1649 0 : SUBROUTINE BathOperatoroffdiag_setF(op,F)
1650 :
1651 : !Arguments ------------------------------------
1652 : TYPE(BathOperatoroffdiag) , INTENT(INOUT) :: op
1653 : DOUBLE PRECISION, DIMENSION(:,:,:) , INTENT(IN ) :: F
1654 : !Arguments ------------------------------------
1655 : INTEGER :: iflavor1
1656 : INTEGER :: iflavor2
1657 : INTEGER :: sample
1658 : INTEGER :: length
1659 :
1660 0 : IF ( op%set .EQV. .FALSE. ) &
1661 0 : CALL ERROR("BathOperatoroffdiag_setF : BathOperatoroffdiag not set ")
1662 :
1663 0 : length = SIZE(F)
1664 0 : IF ( length .NE. (op%flavors * op%flavors * op%sizeHybrid) ) &
1665 0 : CALL ERROR("BathOperatoroffdiag_setF : wrong input F ")
1666 :
1667 0 : DO iflavor1=1,op%flavors
1668 0 : DO iflavor2=1,op%flavors
1669 0 : DO sample = 1, op%sizeHybrid
1670 0 : op%F(sample,iflavor1,iflavor2) = F(sample,iflavor1,iflavor2)
1671 : END DO
1672 : END DO
1673 : END DO
1674 0 : END SUBROUTINE BathOperatoroffdiag_setF
1675 : !!***
1676 :
1677 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_printF
1678 : !! NAME
1679 : !! BathOperatoroffdiag_printF
1680 : !!
1681 : !! FUNCTION
1682 : !! print F function
1683 : !!
1684 : !! COPYRIGHT
1685 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1686 : !! This file is distributed under the terms of the
1687 : !! GNU General Public License, see ~abinit/COPYING
1688 : !! or http://www.gnu.org/copyleft/gpl.txt .
1689 : !!
1690 : !! INPUTS
1691 : !! op=bath operator
1692 : !! ostream=file stream to write in
1693 : !!
1694 : !! OUTPUT
1695 : !!
1696 : !! SIDE EFFECTS
1697 : !!
1698 : !! NOTES
1699 : !!
1700 : !! SOURCE
1701 :
1702 0 : SUBROUTINE BathOperatoroffdiag_printF(op,ostream)
1703 :
1704 : !Arguments ------------------------------------
1705 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
1706 : INTEGER,OPTIONAL , INTENT(IN ) :: ostream
1707 : !Local variables ------------------------------
1708 : CHARACTER(LEN=4) :: aflavor
1709 : CHARACTER(LEN=50) :: string
1710 : INTEGER :: iflavor1
1711 : INTEGER :: iflavor2
1712 : INTEGER :: sample
1713 : INTEGER :: ostream_val
1714 :
1715 0 : IF ( PRESENT(ostream) ) THEN
1716 0 : ostream_val = ostream
1717 : ELSE
1718 0 : ostream_val = 65
1719 0 : OPEN(UNIT=ostream_val, FILE="F.dat")
1720 : END IF
1721 :
1722 0 : WRITE(aflavor,'(I4)') (op%flavors*op%flavors+1)
1723 0 : string = '(1x,'//TRIM(ADJUSTL(aflavor))//'E22.14)'
1724 0 : DO sample = 1, op%sizeHybrid
1725 0 : WRITE(ostream_val,string) (sample-1)*op%dt, ((op%F(sample,iflavor1,iflavor2),&
1726 0 : iflavor1=1,op%flavors),iflavor2=1,op%flavors)
1727 : END DO
1728 : !CALL FLUSH(ostream_val)
1729 :
1730 0 : IF ( .NOT. PRESENT(ostream) ) &
1731 0 : CLOSE(ostream_val)
1732 :
1733 0 : END SUBROUTINE BathOperatoroffdiag_printF
1734 : !!***
1735 :
1736 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_printM
1737 : !! NAME
1738 : !! BathOperatoroffdiag_printM
1739 : !!
1740 : !! FUNCTION
1741 : !! print M =F^{-1} matrix
1742 : !!
1743 : !! COPYRIGHT
1744 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1745 : !! This file is distributed under the terms of the
1746 : !! GNU General Public License, see ~abinit/COPYING
1747 : !! or http://www.gnu.org/copyleft/gpl.txt .
1748 : !!
1749 : !! INPUTS
1750 : !! op=bath operator
1751 : !! ostream=file stream to write in
1752 : !!
1753 : !! OUTPUT
1754 : !! argout(sizeout)=description
1755 : !!
1756 : !! SIDE EFFECTS
1757 : !!
1758 : !! NOTES
1759 : !!
1760 : !! SOURCE
1761 :
1762 0 : SUBROUTINE BathOperatoroffdiag_printM(op,ostream)
1763 :
1764 : !Arguments ------------------------------------
1765 : TYPE(BathOperatoroffdiag), INTENT(IN) :: op
1766 : INTEGER, OPTIONAL , INTENT(IN) :: ostream
1767 : !Local variables ------------------------------
1768 : INTEGER :: ostream_val
1769 :
1770 0 : IF ( op%activeFlavor .LE. 0 ) &
1771 0 : CALL ERROR("BathOperatoroffdiag_printM : no active hybrid function ")
1772 0 : ostream_val = 6
1773 0 : IF ( PRESENT(ostream) ) ostream_val = ostream
1774 0 : CALL MatrixHyb_print(op%M,ostream_val)
1775 0 : END SUBROUTINE BathOperatoroffdiag_printM
1776 : !!***
1777 :
1778 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_printM_matrix
1779 : !! NAME
1780 : !! BathOperatoroffdiag_printM_matrix
1781 : !!
1782 : !! FUNCTION
1783 : !! print M =F^{-1} matrix
1784 : !!
1785 : !! COPYRIGHT
1786 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1787 : !! This file is distributed under the terms of the
1788 : !! GNU General Public License, see ~abinit/COPYING
1789 : !! or http://www.gnu.org/copyleft/gpl.txt .
1790 : !!
1791 : !! INPUTS
1792 : !! op=bath operator
1793 : !! ostream=file stream to write in
1794 : !!
1795 : !! OUTPUT
1796 : !! argout(sizeout)=description
1797 : !!
1798 : !! SIDE EFFECTS
1799 : !!
1800 : !! NOTES
1801 : !!
1802 : !! SOURCE
1803 :
1804 0 : SUBROUTINE BathOperatoroffdiag_printM_matrix(op,ostream)
1805 :
1806 : !Arguments ------------------------------------
1807 : TYPE(BathOperatoroffdiag), INTENT(IN) :: op
1808 : INTEGER, OPTIONAL , INTENT(IN) :: ostream
1809 : !Local variables ------------------------------
1810 : INTEGER :: iflavor1
1811 : INTEGER :: i1,it1,it2
1812 : CHARACTER(LEN=22) :: string
1813 : CHARACTER(LEN=22) :: string2
1814 : CHARACTER(LEN=4 ) :: size
1815 :
1816 : ABI_UNUSED(ostream)
1817 :
1818 0 : WRITE(size,'(I4)') op%sumtails
1819 0 : string ='(i2,x,i3,a,'//TRIM(ADJUSTL(size))//'(E5.2,1x))'
1820 0 : string2 ='(6x,'//TRIM(ADJUSTL(size))//'(i6))'
1821 0 : open(unit=222, file="M_matrix.dat")
1822 0 : open(unit=223, file="M_matrix_tau.dat")
1823 0 : it1=0
1824 0 : write(222,string2) ((i1,i1=1,op%tails(iflavor1)),iflavor1=1,op%flavors)
1825 0 : do iflavor1=1, op%flavors
1826 0 : do i1=1, op%tails(iflavor1)
1827 0 : it1=it1+1
1828 0 : write(222,string) iflavor1,i1,'|',(op%M%mat(it1,it2),it2=1,op%sumtails)
1829 : enddo
1830 : enddo
1831 :
1832 :
1833 0 : END SUBROUTINE BathOperatoroffdiag_printM_matrix
1834 : !!***
1835 :
1836 : !!****f* ABINIT/m_BathOperatoroffdiag/ BathOperatoroffdiag_destroy
1837 : !! NAME
1838 : !! BathOperatoroffdiag_destroy
1839 : !!
1840 : !! FUNCTION
1841 : !! Deallocate and reset every thing
1842 : !!
1843 : !! COPYRIGHT
1844 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1845 : !! This file is distributed under the terms of the
1846 : !! GNU General Public License, see ~abinit/COPYING
1847 : !! or http://www.gnu.org/copyleft/gpl.txt .
1848 : !!
1849 : !! INPUTS
1850 : !! op=bath operator
1851 : !!
1852 : !! OUTPUT
1853 : !!
1854 : !! SIDE EFFECTS
1855 : !!
1856 : !! NOTES
1857 : !!
1858 : !! SOURCE
1859 :
1860 0 : SUBROUTINE BathOperatoroffdiag_destroy(op)
1861 :
1862 : TYPE(BathOperatoroffdiag), INTENT(INOUT) :: op
1863 :
1864 0 : CALL MatrixHyb_destroy(op%M)
1865 0 : CALL MatrixHyb_destroy(op%M_update)
1866 :
1867 0 : CALL Vector_destroy(op%R)
1868 0 : CALL Vector_destroy(op%Q)
1869 0 : CALL Vector_destroy(op%Rtau)
1870 0 : CALL Vector_destroy(op%Qtau)
1871 0 : FREEIF(op%F)
1872 0 : FREEIF(op%Fshift)
1873 0 : FREEIF(op%tails)
1874 :
1875 0 : op%MAddFlag = .FALSE.
1876 0 : op%MRemoveFlag = .FALSE.
1877 0 : op%flavors = 0
1878 0 : op%beta = 0.d0
1879 0 : op%dt = 0.d0
1880 0 : op%inv_dt = 0.d0
1881 0 : op%samples = 0
1882 0 : op%sizeHybrid = 0
1883 0 : op%activeFlavor = 0
1884 0 : op%updatePosRow = 0
1885 0 : op%updatePosCol = 0
1886 :
1887 0 : END SUBROUTINE BathOperatoroffdiag_destroy
1888 : !!***
1889 :
1890 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_doCheck
1891 : !! NAME
1892 : !! BathOperatoroffdiag_doCheck
1893 : !!
1894 : !! FUNCTION
1895 : !! Just store if we perfom check for updates of M
1896 : !!
1897 : !! COPYRIGHT
1898 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1899 : !! This file is distributed under the terms of the
1900 : !! GNU General Public License, see ~abinit/COPYING
1901 : !! or http://www.gnu.org/copyleft/gpl.txt .
1902 : !!
1903 : !! INPUTS
1904 : !! op=bath operator
1905 : !! opt_check=second bit should be one
1906 : !!
1907 : !! OUTPUT
1908 : !!
1909 : !! SIDE EFFECTS
1910 : !!
1911 : !! NOTES
1912 : !!
1913 : !! SOURCE
1914 :
1915 0 : SUBROUTINE BathOperatoroffdiag_doCheck(op,opt_check)
1916 :
1917 : !Arguments ------------------------------------
1918 : TYPE(BathOperatoroffdiag) , INTENT(INOUT) :: op
1919 : INTEGER , INTENT(IN ) :: opt_check
1920 :
1921 0 : IF ( opt_check .GE. 2 ) &
1922 0 : op%doCheck = .TRUE.
1923 0 : END SUBROUTINE BathOperatoroffdiag_doCheck
1924 : !!***
1925 :
1926 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_checkM
1927 : !! NAME
1928 : !! BathOperatoroffdiag_checkM
1929 : !!
1930 : !! FUNCTION
1931 : !! compute from scratch the M matrix and compar it
1932 : !! with the already computed M matrix
1933 : !!
1934 : !! COPYRIGHT
1935 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
1936 : !! This file is distributed under the terms of the
1937 : !! GNU General Public License, see ~abinit/COPYING
1938 : !! or http://www.gnu.org/copyleft/gpl.txt .
1939 : !!
1940 : !! INPUTS
1941 : !! op=bath operator
1942 : !! particle=list of all segments of the active flavor
1943 : !!
1944 : !! OUTPUT
1945 : !!
1946 : !! SIDE EFFECTS
1947 : !!
1948 : !! NOTES
1949 : !!
1950 : !! SOURCE
1951 :
1952 0 : SUBROUTINE BathOperatoroffdiag_checkM(op,particle)
1953 :
1954 : !Arguments ------------------------------------
1955 : TYPE(BathOperatoroffdiag) , INTENT(INOUT) :: op
1956 : TYPE(ListCdagC) , INTENT(IN ) :: particle(:)
1957 : !Local variables ------------------------------
1958 : ! TYPE(MatrixHyb) :: checkMatrix
1959 : LOGICAL :: checkTau
1960 : INTEGER :: tail
1961 : INTEGER :: iC
1962 : INTEGER :: iCdag
1963 : INTEGER :: aF
1964 : INTEGER :: iflavora
1965 : INTEGER :: iflavorb,it !,it1
1966 : CHARACTER(LEN=6) :: a
1967 : DOUBLE PRECISION :: time
1968 : DOUBLE PRECISION :: beta
1969 : DOUBLE PRECISION :: mbeta_two
1970 : DOUBLE PRECISION :: errorabs
1971 : DOUBLE PRECISION :: errormax
1972 : DOUBLE PRECISION :: error1
1973 : DOUBLE PRECISION :: errorrel
1974 : DOUBLE PRECISION :: tc
1975 : DOUBLE PRECISION :: tCdag
1976 : DOUBLE PRECISION :: sumMmat
1977 : DOUBLE PRECISION :: sumCheck
1978 : #include "BathOperatoroffdiag_hybrid.h"
1979 :
1980 0 : aF = op%activeFlavor
1981 : !Construction de la matrix
1982 0 : tail = op%sumtails
1983 : ! CALL MatrixHyb_init(checkMatrix,op%iTech,size=tail,Wmax=op%samples)
1984 : ! CALL MatrixHyb_setSize(checkMatrix,tail)
1985 :
1986 : ! --- set size of the matrix
1987 0 : CALL MatrixHyb_setSize(op%M_update,tail)
1988 :
1989 : ! --- compute useful quantities
1990 0 : beta = op%beta
1991 0 : mbeta_two = -beta*0.5d0
1992 0 : op%checkNumber = op%checkNumber + 1
1993 0 : IF ( tail .NE. op%M%tail ) THEN
1994 0 : CALL WARN("BathOperatoroffdiag_checkM : tails are different ")
1995 0 : RETURN
1996 : END IF
1997 :
1998 0 : do it=1,op%sumtails
1999 : !write(6,*) " checkM begin M_update%mat_tau",(op%M_update%mat_tau(it,it1),it1=1,op%sumtails)
2000 : enddo
2001 : ! --- build matrix
2002 : !CALL ListCdagC_print(particle)
2003 0 : DO iflavora = 1, op%flavors
2004 0 : DO iCdag = 1, op%tails(iflavora)
2005 0 : tCdag = particle(iflavora)%list(iCdag,Cdag_)
2006 : !write(6,*) " checkM a",iflavora,tCdag
2007 0 : DO iflavorb = 1, op%flavors
2008 0 : DO iC = 1, op%tails(iflavorb)
2009 : !tC = particle%list(C_,iC).MOD.beta
2010 0 : MODCYCLE(particle(iflavorb)%list(iC,C_),beta,tC) ! tC is tC, or Tc-Beta if tc>beta
2011 : !write(6,*) " checkM b",iflavorb,tC
2012 0 : time = tC - tCdag ! time is positive or negative but lower than beta
2013 : !write(6,*) " checkM time",time
2014 :
2015 : #include "BathOperatoroffdiag_hybrid"
2016 :
2017 0 : op%M_update%mat(op%Fshift(iflavorb)+iC,op%Fshift(iflavora)+iCdag) = hybrid
2018 :
2019 0 : time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
2020 0 : op%M_update%mat_tau(op%Fshift(iflavora)+iCdag,op%Fshift(iflavorb)+iC) = INT ( (time*op%inv_dt) +1.5d0 )
2021 : !write(6,*) " checkM mat_tau",INT ( (time*op%inv_dt) +1.5d0 )
2022 : !write(6,*) " checkM shifts",op%Fshift(iflavorb),iCdag,op%Fshift(iflavora),iC
2023 : END DO ! iC
2024 : END DO ! iflavorb
2025 : END DO ! iCdag
2026 : END DO ! iflavora
2027 :
2028 : ! CALL MatrixHyb_Print(checkMatrix)
2029 : ! --- Inverse matrix
2030 0 : CALL MatrixHyb_inverse(op%M_update)
2031 :
2032 : ! CALL MatrixHyb_Print(checkMatrix)
2033 0 : do it=1,op%sumtails
2034 : !write(6,*) " checkM end M_update%mat_tau",(op%M_update%mat_tau(it,it1),it1=1,op%sumtails)
2035 : enddo
2036 : do it=1,op%sumtails
2037 : !write(6,*) " checkM end M_update",(op%M%mat(it,it1),it1=1,op%sumtails)
2038 : enddo
2039 :
2040 : ! --- Compare M_update and M to check if calculation of M is correct
2041 : sumMmat =0.d0
2042 : sumCheck=0.d0
2043 : error1 = 0.d0
2044 : errormax = 0.d0
2045 : checkTau = .FALSE.
2046 0 : DO iCdag = 1, tail
2047 0 : Do iC =1, tail
2048 : errorrel= ABS((op%M_update%mat(iC, iCdag) - &
2049 0 : op%M%mat(iC,iCdag))/op%M_update%mat(iC,iCdag))
2050 : errorabs= ABS(op%M_update%mat(iC, iCdag) - &
2051 0 : op%M%mat(iC,iCdag))
2052 0 : IF ( errorrel .gt. errormax .and. errorabs .gt. 0.001d0 ) errormax = errorrel
2053 : ! write(6,*) " checkM ", errorrel,errorabs
2054 0 : IF ( op%M_update%mat_tau(iC,iCdag) .NE. op%M%mat_tau(iC,iCdag) ) then
2055 0 : checkTau = .TRUE.
2056 : !write(6,*) "op%M_update%mat_tau(iC,iCdag), op%M%mat_tau(iC,iCdag)",op%M_update%mat_tau(iC,iCdag), op%M%mat_tau(iC,iCdag)
2057 : !call flush(6)
2058 0 : CALL ERROR("BathOperatoroffdiag_checkM : "//a//"% ")
2059 : ENDIF
2060 :
2061 : END DO
2062 : END DO
2063 :
2064 0 : IF ( checkTau .EQV. .TRUE. ) THEN
2065 0 : CALL WARN("BathOperatoroffdiag_checkM : mat_tau differs should be")
2066 0 : CALL MatrixHyb_print(op%M_update,opt_print=1)
2067 0 : CALL WARN("BathOperatoroffdiag_checkM : whereas it is")
2068 0 : CALL MatrixHyb_print(op%M,opt_print=1)
2069 : END IF
2070 0 : op%meanError = op%meanError + errormax
2071 0 : IF ( errormax .GT. 1.d0 ) THEN
2072 0 : WRITE(a,'(I4)') INT(error1*100.d0)
2073 : !write(6,'(I4)') INT(error1*100.d0)
2074 : ! CALL MatrixHyb_Print(op%M)
2075 0 : CALL WARN("BathOperatoroffdiag_checkM")
2076 : END IF
2077 : ! CALL MatrixHyb_destroy(checkMatrix)
2078 : END SUBROUTINE BathOperatoroffdiag_checkM
2079 : !!***
2080 :
2081 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_recomputeM
2082 : !! NAME
2083 : !! BathOperatoroffdiag_recomputeM
2084 : !!
2085 : !! FUNCTION
2086 : !! compute from scratch the M matrix
2087 : !!
2088 : !! COPYRIGHT
2089 : !! Copyright (C) 2013-2026 ABINIT group (B. Amadon)
2090 : !! This file is distributed under the terms of the
2091 : !! GNU General Public License, see ~abinit/COPYING
2092 : !! or http://www.gnu.org/copyleft/gpl.txt .
2093 : !!
2094 : !! INPUTS
2095 : !! op=bath operator
2096 : !! particle=list of all segments of the active flavor
2097 : !!
2098 : !! OUTPUT
2099 : !!
2100 : !! SIDE EFFECTS
2101 : !!
2102 : !! NOTES
2103 : !!
2104 : !! SOURCE
2105 :
2106 0 : SUBROUTINE BathOperatoroffdiag_recomputeM(op,particle,flav_i,flav_j)
2107 :
2108 : !Arguments ------------------------------------
2109 : TYPE(BathOperatoroffdiag) , INTENT(INOUT) :: op
2110 : TYPE(ListCdagC) , INTENT(IN ) :: particle(:)
2111 : INTEGER :: flav_i,flav_j
2112 : !Local variables ------------------------------
2113 : ! TYPE(MatrixHyb) :: checkMatrix
2114 : INTEGER :: tail
2115 : INTEGER :: iC
2116 : INTEGER :: iCdag
2117 : INTEGER :: aF
2118 : INTEGER :: iflavora
2119 : INTEGER :: iflavorb,it !,it1
2120 : INTEGER :: iflavora_imp
2121 : INTEGER :: iflavorb_imp
2122 : !CHARACTER(LEN=6) :: a
2123 : DOUBLE PRECISION :: time
2124 : DOUBLE PRECISION :: beta
2125 : DOUBLE PRECISION :: mbeta_two
2126 : DOUBLE PRECISION :: tc
2127 : DOUBLE PRECISION :: tCdag
2128 : !DOUBLE PRECISION :: sumMmat
2129 : !DOUBLE PRECISION :: sumCheck
2130 : #include "BathOperatoroffdiag_hybrid.h"
2131 :
2132 0 : aF = op%activeFlavor
2133 : !Construction de la matrix
2134 0 : tail = op%sumtails
2135 : ! CALL MatrixHyb_init(checkMatrix,op%iTech,size=tail,Wmax=op%samples)
2136 : ! CALL MatrixHyb_setSize(checkMatrix,tail)
2137 :
2138 : ! --- set size of the matrix
2139 0 : CALL MatrixHyb_setSize(op%M_update,tail)
2140 :
2141 : ! --- compute useful quantities
2142 0 : beta = op%beta
2143 0 : mbeta_two = -beta*0.5d0
2144 0 : op%checkNumber = op%checkNumber + 1
2145 0 : IF ( tail .NE. op%M%tail ) THEN
2146 0 : CALL WARN("BathOperatoroffdiag_checkM : tails are different ")
2147 0 : RETURN
2148 : END IF
2149 :
2150 0 : do it=1,op%sumtails
2151 : !write(6,*) " checkM begin M_update%mat_tau",(op%M_update%mat_tau(it,it1),it1=1,op%sumtails)
2152 : enddo
2153 : ! --- build matrix
2154 : !CALL ListCdagC_print(particle)
2155 0 : DO iflavora = 1, op%flavors
2156 0 : iflavora_imp=iflavora
2157 0 : if(iflavora==flav_i) iflavora_imp=flav_j
2158 0 : if(iflavora==flav_j) iflavora_imp=flav_i
2159 0 : DO iCdag = 1, op%tails(iflavora_imp)
2160 0 : tCdag = particle(iflavora_imp)%list(iCdag,Cdag_)
2161 : !write(6,*) " checkM a",iflavora,tCdag
2162 0 : DO iflavorb = 1, op%flavors
2163 0 : iflavorb_imp=iflavorb
2164 0 : if(iflavorb==flav_j) iflavorb_imp=flav_i
2165 0 : if(iflavorb==flav_i) iflavorb_imp=flav_j
2166 0 : DO iC = 1, op%tails(iflavorb_imp)
2167 : !tC = particle%list(C_,iC).MOD.beta
2168 0 : MODCYCLE(particle(iflavorb_imp)%list(iC,C_),beta,tC) ! tC is tC, or Tc-Beta if tc>beta
2169 : !write(6,*) " checkM b",iflavorb,tC
2170 0 : time = tC - tCdag ! time is positive or negative but lower than beta
2171 : !write(6,*) " checkM time",time
2172 :
2173 : #include "BathOperatoroffdiag_hybrid"
2174 :
2175 0 : op%M_update%mat(op%Fshift(iflavorb_imp)+iC,op%Fshift(iflavora_imp)+iCdag) = hybrid
2176 :
2177 0 : time = time + ( SIGN(1.d0,time) - 1.d0 )*mbeta_two
2178 0 : op%M_update%mat_tau(op%Fshift(iflavora_imp)+iCdag,op%Fshift(iflavorb_imp)+iC) = INT ( (time*op%inv_dt) +1.5d0 )
2179 : !write(6,*) " checkM mat_tau",INT ( (time*op%inv_dt) +1.5d0 )
2180 : !write(6,*) " checkM shifts",op%Fshift(iflavorb),iCdag,op%Fshift(iflavora),iC
2181 : END DO ! iC
2182 : END DO ! iflavorb
2183 : END DO ! iCdag
2184 : END DO ! iflavora
2185 :
2186 : ! CALL MatrixHyb_Print(checkMatrix)
2187 : ! --- Inverse matrix
2188 0 : CALL MatrixHyb_inverse(op%M_update)
2189 :
2190 : ! CALL MatrixHyb_Print(checkMatrix)
2191 0 : do it=1,op%sumtails
2192 : !write(6,*) " checkM end M_update%mat_tau",(op%M_update%mat_tau(it,it1),it1=1,op%sumtails)
2193 : enddo
2194 : do it=1,op%sumtails
2195 : !write(6,*) " checkM end M_update",(op%M%mat(it,it1),it1=1,op%sumtails)
2196 : enddo
2197 :
2198 : ! --- Compare M_update and M to check if calculation of M is correct
2199 : END SUBROUTINE BathOperatoroffdiag_recomputeM
2200 : !!***
2201 :
2202 : !!****f* ABINIT/m_BathOperatoroffdiag/BathOperatoroffdiag_getError
2203 : !! NAME
2204 : !! BathOperatoroffdiag_getError
2205 : !!
2206 : !! FUNCTION
2207 : !! compute a percentage error / checkM
2208 : !!
2209 : !! COPYRIGHT
2210 : !! Copyright (C) 2013-2026 ABINIT group (J. Bieder)
2211 : !! This file is distributed under the terms of the
2212 : !! GNU General Public License, see ~abinit/COPYING
2213 : !! or http://www.gnu.org/copyleft/gpl.txt .
2214 : !!
2215 : !! INPUTS
2216 : !! op=bath operator
2217 : !!
2218 : !! OUTPUT
2219 : !! BathOperatoroffdiag_getError=Error in percent
2220 : !!
2221 : !! SIDE EFFECTS
2222 : !!
2223 : !! NOTES
2224 : !!
2225 : !! SOURCE
2226 :
2227 0 : DOUBLE PRECISION FUNCTION BathOperatoroffdiag_getError(op)
2228 :
2229 : TYPE(BathOperatoroffdiag), INTENT(IN) :: op
2230 :
2231 0 : IF ( op%doCheck .EQV. .TRUE. ) THEN
2232 0 : BathOperatoroffdiag_getError = op%meanError / DBLE(op%checkNumber)
2233 : ELSE
2234 : BathOperatoroffdiag_getError = 0.d0
2235 : END IF
2236 0 : END FUNCTION BathOperatoroffdiag_getError
2237 : !!***
2238 : !#endif
2239 :
2240 0 : END MODULE m_BathOperatoroffdiag
2241 : !!***
|