19 USE ieee_arithmetic,
ONLY: ieee_is_finite
22#include "./base/base_uses.f90"
26 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'spectral_localizer_dbcsr'
56 shifted_hamiltonian, periodic_cosines)
59 REAL(
dp),
INTENT(IN) :: point(3), energy, kappa
63 TYPE(
dbcsr_p_type),
INTENT(IN),
OPTIONAL :: periodic_cosines(:)
65 COMPLEX(dp),
PARAMETER :: ii = cmplx(0.0_dp, 1.0_dp,
dp)
67 COMPLEX(dp) :: factors(2, 2), identity(4, 4), &
72 cpassert(
SIZE(positions) == 3)
76 identity(i, i) = 1.0_dp
79 pauli(i, i + 2, 1) = 1.0_dp
80 pauli(i + 2, i, 1) = 1.0_dp
81 pauli(i, i + 2, 2) = -ii
82 pauli(i + 2, i, 2) = ii
83 pauli(i, i, 3) = 1.0_dp
84 pauli(i + 2, i + 2, 3) = -1.0_dp
86 CALL create_operator(s, 4, block)
87 CALL create_operator(s, 4, metric)
88 CALL add_real_blocks(s, identity, metric)
90 factors(1, 1) = 1.0_dp
91 factors(2, 2) = 1.0_dp
92 IF (
PRESENT(shifted_hamiltonian))
THEN
93 cpassert(energy == 0.0_dp)
94 CALL add_real_blocks(shifted_hamiltonian%real_part, factors, block)
95 CALL add_real_blocks(shifted_hamiltonian%imaginary_part, ii*factors, block)
98 CALL add_real_blocks(physical(1)%real_part, factors, block)
99 CALL add_real_blocks(physical(1)%imaginary_part, ii*factors, block)
102 CALL add_real_blocks(s, -energy*identity, block)
104 IF (
PRESENT(periodic_cosines))
THEN
105 cpassert(
SIZE(periodic_cosines) == 3)
106 CALL add_real_blocks(s, -3.0_dp*kappa*identity, block)
108 CALL add_real_blocks(periodic_cosines(i)%matrix, &
109 kappa*(cos(point(i))*identity + ii*sin(point(i))*pauli(:, :, i)), block)
110 CALL add_real_blocks(positions(i)%matrix, &
111 kappa*(sin(point(i))*identity - ii*cos(point(i))*pauli(:, :, i)), block)
115 CALL add_real_blocks(positions(i)%matrix, -ii*kappa*pauli(:, :, i), block)
116 CALL add_real_blocks(s, ii*kappa*point(i)*pauli(:, :, i), block)
130 COMPLEX(dp) :: factors(2, 2)
133 CALL create_operator(matrix%real_part, 2, expanded)
134 factors = reshape([1.0_dp, 0.0_dp, 0.0_dp, 1.0_dp], [2, 2])
135 CALL add_real_blocks(matrix%real_part, factors, expanded)
136 factors = reshape([0.0_dp, 1.0_dp, -1.0_dp, 0.0_dp], [2, 2])
137 CALL add_real_blocks(matrix%imaginary_part, factors, expanded)
138 CALL dbcsr_create(realified, template=expanded%real_part)
139 CALL dbcsr_copy(realified, expanded%real_part)
154 INTEGER :: blocks, col, nblocks, row
155 LOGICAL :: transposed
156 REAL(
dp),
POINTER :: block(:, :)
161 cpassert(nblocks == 2*blocks)
162 CALL create_operator(template%real_part, 1, matrix)
166 cpassert(.NOT. transposed)
167 IF (col > blocks) cycle
168 IF (row <= blocks)
THEN
185 SUBROUTINE create_operator(source, components, matrix)
187 INTEGER,
INTENT(IN) :: components
191 INTEGER,
POINTER :: col_dist(:), expanded_cols(:), &
192 expanded_rows(:), expanded_sizes(:), &
193 row_dist(:), sizes(:)
196 CALL dbcsr_get_info(source, distribution=distribution, row_blk_size=sizes)
199 ALLOCATE (expanded_sizes(blocks*components), expanded_rows(blocks*components), expanded_cols(blocks*components))
200 expanded_sizes = reshape(spread(sizes, 2, components), [blocks*components])
201 expanded_rows = reshape(spread(row_dist, 2, components), [blocks*components])
202 expanded_cols = reshape(spread(col_dist, 2, components), [blocks*components])
204 row_dist=expanded_rows, col_dist=expanded_cols)
205 CALL dbcsr_create(matrix%real_part,
'FINITE AO RE', expanded_distribution, &
206 dbcsr_type_no_symmetry, expanded_sizes, expanded_sizes)
207 CALL dbcsr_create(matrix%imaginary_part, template=matrix%real_part, name=
'FINITE AO IM')
209 DEALLOCATE (expanded_sizes, expanded_rows, expanded_cols)
210 END SUBROUTINE create_operator
227 COMPLEX(dp),
ALLOCATABLE :: factors(:, :), identity(:, :)
230 cpassert(
SIZE(operators) ==
SIZE(positions) + 1)
232 IF (
PRESENT(soc)) nspin = 2
233 ALLOCATE (identity(nspin, nspin), factors(nspin, nspin))
234 identity = cmplx(0.0_dp, 0.0_dp,
dp)
236 identity(i, i) = 1.0_dp
238 CALL create_operator(s, nspin, metric)
239 CALL add_real_blocks(s, identity, metric)
240 DO i = 1,
SIZE(operators)
241 CALL create_operator(s, nspin, operators(i))
243 CALL add_real_blocks(h, identity, operators(1))
244 DO i = 1,
SIZE(positions)
245 CALL add_real_blocks(positions(i)%matrix, identity, operators(i + 1))
247 IF (
PRESENT(soc))
THEN
248 factors = cmplx(0.0_dp, 0.0_dp,
dp)
249 factors(1, 2) = cmplx(0.0_dp, 1.0_dp,
dp)
250 factors(2, 1) = cmplx(0.0_dp, 1.0_dp,
dp)
251 CALL add_real_blocks(soc(1, 1)%matrix, factors, operators(1))
252 factors(1, 2) = -1.0_dp
253 factors(2, 1) = 1.0_dp
254 CALL add_real_blocks(soc(2, 1)%matrix, factors, operators(1))
255 factors = cmplx(0.0_dp, 0.0_dp,
dp)
256 factors(1, 1) = cmplx(0.0_dp, 1.0_dp,
dp)
257 factors(2, 2) = cmplx(0.0_dp, -1.0_dp,
dp)
258 CALL add_real_blocks(soc(3, 1)%matrix, factors, operators(1))
272 REAL(
dp),
INTENT(IN) :: energy
275 COMPLEX(dp),
PARAMETER :: imaginary = cmplx(0.0_dp, 1.0_dp,
dp)
277 COMPLEX(dp) :: factors(2, 2)
279 CALL create_operator(s%real_part, 2, pencil)
280 CALL create_operator(s%real_part, 2, metric)
281 factors = reshape([1.0_dp, 0.0_dp, 0.0_dp, -1.0_dp], [2, 2])
282 CALL add_real_blocks(h%real_part, factors, pencil)
283 CALL add_real_blocks(h%imaginary_part, imaginary*factors, pencil)
284 CALL add_real_blocks(s%real_part, -energy*factors, pencil)
285 CALL add_real_blocks(s%imaginary_part, -energy*imaginary*factors, pencil)
286 factors(2, 2) = 1.0_dp
287 CALL add_real_blocks(s%real_part, factors, metric)
288 CALL add_real_blocks(s%imaginary_part, imaginary*factors, metric)
309 SUBROUTINE localizer_dbcsr_build(h, s, x, y, point, energy, kappa, localizer, metric, soc, periodic_cosines, &
312 REAL(kind=
dp),
INTENT(IN) :: point(2), energy, kappa
314 TYPE(
dbcsr_p_type),
INTENT(IN),
OPTIONAL :: soc(:, :), periodic_cosines(:)
317 COMPLEX(KIND=dp),
PARAMETER :: imaginary = cmplx(0.0_dp, 1.0_dp,
dp)
319 COMPLEX(dp) :: signs(2, 2)
320 COMPLEX(KIND=dp),
ALLOCATABLE :: factors(:, :), identity(:, :), sx(:, :), &
322 INTEGER :: blocks, component, components, nspin, &
324 INTEGER,
POINTER :: col_dist(:), expanded_cols(:), &
325 expanded_rows(:), expanded_sizes(:), &
326 row_dist(:), sizes(:)
330 IF (
PRESENT(soc)) nspin = 2
332 CALL dbcsr_get_info(s, distribution=distribution, row_blk_size=sizes)
335 ALLOCATE (expanded_sizes(blocks*components), expanded_rows(blocks*components), expanded_cols(blocks*components))
336 expanded_sizes = reshape(spread(sizes, 2, components), [blocks*components])
337 expanded_rows = reshape(spread(row_dist, 2, components), [blocks*components])
338 expanded_cols = reshape(spread(col_dist, 2, components), [blocks*components])
340 row_dist=expanded_rows, col_dist=expanded_cols)
341 CALL dbcsr_create(localizer%real_part,
'SPECTRAL LOCALIZER RE', expanded_distribution, &
342 dbcsr_type_no_symmetry, expanded_sizes, expanded_sizes)
343 CALL dbcsr_create(localizer%imaginary_part, template=localizer%real_part, name=
'SPECTRAL LOCALIZER IM')
344 CALL dbcsr_create(metric%real_part, template=localizer%real_part, name=
'LOCALIZER METRIC RE')
345 CALL dbcsr_create(metric%imaginary_part, template=localizer%real_part, name=
'LOCALIZER METRIC IM')
347 DEALLOCATE (expanded_sizes, expanded_rows, expanded_cols)
348 ALLOCATE (factors(components, components), identity(components, components), &
349 sx(components, components), sy(components, components), sz(components, components))
354 DO component = 1, nspin
355 identity(component, component) = 1.0_dp
356 identity(nspin + component, nspin + component) = 1.0_dp
357 sz(component, component) = 1.0_dp
358 sz(nspin + component, nspin + component) = -1.0_dp
359 sx(component, nspin + component) = 1.0_dp
360 sx(nspin + component, component) = 1.0_dp
361 sy(component, nspin + component) = -imaginary
362 sy(nspin + component, component) = imaginary
364 CALL add_real_blocks(s, identity, metric)
365 IF (
PRESENT(shifted_hamiltonian))
THEN
366 cpassert(energy == 0.0_dp)
367 CALL dbcsr_get_info(shifted_hamiltonian%real_part, nblkrows_total=physical_blocks)
368 cpassert(physical_blocks == nspin*blocks)
369 signs = reshape([1.0_dp, 0.0_dp, 0.0_dp, -1.0_dp], [2, 2])
370 CALL add_real_blocks(shifted_hamiltonian%real_part, signs, localizer)
371 CALL add_real_blocks(shifted_hamiltonian%imaginary_part, imaginary*signs, localizer)
373 CALL add_real_blocks(h, sz, localizer)
375 IF (
PRESENT(periodic_cosines))
THEN
376 cpassert(
SIZE(periodic_cosines) == 2)
377 CALL add_real_blocks(s, -(energy + 2.0_dp*kappa)*sz, localizer)
378 CALL add_real_blocks(periodic_cosines(1)%matrix, kappa*(cos(point(1))*sz - sin(point(1))*sx), localizer)
379 CALL add_real_blocks(periodic_cosines(2)%matrix, kappa*(cos(point(2))*sz - sin(point(2))*sy), localizer)
380 CALL add_real_blocks(x, kappa*(sin(point(1))*sz + cos(point(1))*sx), localizer)
381 CALL add_real_blocks(y, kappa*(sin(point(2))*sz + cos(point(2))*sy), localizer)
383 CALL add_real_blocks(s, -energy*sz - kappa*(point(1)*sx + point(2)*sy), localizer)
384 CALL add_real_blocks(x, kappa*sx, localizer)
385 CALL add_real_blocks(y, kappa*sy, localizer)
387 IF (
PRESENT(soc) .AND. .NOT.
PRESENT(shifted_hamiltonian))
THEN
390 factors(1, 2) = imaginary
391 factors(2, 1) = imaginary
392 factors(3, 4) = -imaginary
393 factors(4, 3) = -imaginary
394 CALL add_real_blocks(soc(1, 1)%matrix, factors, localizer)
396 factors(1, 2) = -1.0_dp
397 factors(2, 1) = 1.0_dp
398 factors(3, 4) = 1.0_dp
399 factors(4, 3) = -1.0_dp
400 CALL add_real_blocks(soc(2, 1)%matrix, factors, localizer)
402 factors(1, 1) = imaginary
403 factors(2, 2) = -imaginary
404 factors(3, 3) = -imaginary
405 factors(4, 4) = imaginary
406 CALL add_real_blocks(soc(3, 1)%matrix, factors, localizer)
416 SUBROUTINE add_real_blocks(source, factors, destination)
418 COMPLEX(KIND=dp),
INTENT(IN) :: factors(:, :)
421 COMPLEX(KIND=dp),
ALLOCATABLE :: values(:, :)
422 INTEGER :: blocks, col, i, j, row
423 LOGICAL :: transposed
424 REAL(kind=
dp),
POINTER :: block(:, :)
429 CALL dbcsr_create(full, template=source, matrix_type=dbcsr_type_no_symmetry)
434 cpassert(.NOT. transposed)
435 ALLOCATE (values(
SIZE(block, 1),
SIZE(block, 2)))
436 DO j = 1,
SIZE(factors, 2)
437 DO i = 1,
SIZE(factors, 1)
438 IF (abs(factors(i, j)) == 0.0_dp) cycle
439 values(:, :) = factors(i, j)*block
440 IF (real(factors(i, j),
dp) /= 0.0_dp)
THEN
441 CALL dbcsr_put_block(destination%real_part, row + (i - 1)*blocks, col + (j - 1)*blocks, &
442 REAL(values,
dp), summation=.true.)
444 IF (aimag(factors(i, j)) /= 0.0_dp)
THEN
445 CALL dbcsr_put_block(destination%imaginary_part, row + (i - 1)*blocks, col + (j - 1)*blocks, &
446 aimag(values), summation=.true.)
456 END SUBROUTINE add_real_blocks
467 COMPLEX(KIND=dp),
ALLOCATABLE,
INTENT(OUT) :: dense(:, :)
469 INTEGER :: col, n, row
470 LOGICAL :: transposed
471 REAL(kind=
dp),
POINTER :: block(:, :)
475 ALLOCATE (dense(n, n))
480 transposed=transposed)
481 cpassert(.NOT. transposed)
482 dense(row:row +
SIZE(block, 1) - 1, col:col +
SIZE(block, 2) - 1) = block
488 transposed=transposed)
489 cpassert(.NOT. transposed)
490 dense(row:row +
SIZE(block, 1) - 1, col:col +
SIZE(block, 2) - 1) = &
491 dense(row:row +
SIZE(block, 1) - 1, col:col +
SIZE(block, 2) - 1) + cmplx(0.0_dp, 1.0_dp,
dp)*block
494 CALL para_env%sum(dense)
509 REAL(kind=
dp),
INTENT(IN) :: tolerance
510 LOGICAL,
INTENT(OUT) :: valid
511 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: relative_error
513 LOGICAL :: valid_real, valid_imaginary
514 REAL(kind=
dp) :: real_norm, imaginary_norm, real_error, imaginary_error
516 CALL check_component(matrix%real_part, -1.0_dp, real_norm, real_error, valid_real)
517 CALL check_component(matrix%imaginary_part, 1.0_dp, imaginary_norm, imaginary_error, valid_imaginary)
518 valid = valid_real .AND. valid_imaginary
519 valid = valid .AND. max(real_error, imaginary_error) <= &
520 tolerance*max(tiny(1.0_dp), real_norm, imaginary_norm)
521 IF (
PRESENT(relative_error))
THEN
522 relative_error = huge(1.0_dp)
523 IF (valid_real .AND. valid_imaginary)
THEN
524 relative_error = max(real_error, imaginary_error)/max(tiny(1.0_dp), real_norm, imaginary_norm)
538 SUBROUTINE check_component(component, sign, norm, error, ok)
540 REAL(kind=
dp),
INTENT(IN) :: sign
541 REAL(kind=
dp),
INTENT(OUT) :: norm, error
542 LOGICAL,
INTENT(OUT) :: ok
545 REAL(kind=
dp),
POINTER :: block(:, :)
556 IF (.NOT. all(ieee_is_finite(block)))
THEN
559 norm = max(norm, maxval(abs(block)))
563 CALL para_env%max(invalid)
565 IF (invalid /= 0)
RETURN
566 CALL para_env%max(norm)
568 CALL dbcsr_transposed(difference, component, shallow_data_copy=.false., use_distribution=distribution)
569 CALL dbcsr_add(difference, component, sign, 1.0_dp)
574 IF (.NOT. all(ieee_is_finite(block)))
THEN
577 error = max(error, maxval(abs(block)))
582 CALL para_env%max(invalid)
583 CALL para_env%max(error)
585 END SUBROUTINE check_component
subroutine, public dbcsr_transposed(transposed, normal, shallow_data_copy, transpose_distribution, use_distribution)
...
subroutine, public dbcsr_distribution_release(dist)
...
subroutine, public dbcsr_distribution_new(dist, template, group, pgrid, row_dist, col_dist, reuse_arrays)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_desymmetrize(matrix_a, matrix_b)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_put_block(matrix, row, col, block, summation)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
subroutine, public dbcsr_distribution_get(dist, row_dist, col_dist, nrows, ncols, has_threads, group, mynode, numnodes, nprows, npcols, myprow, mypcol, pgrid, subgroups_defined, prow_group, pcol_group)
...
Defines the basic variable types.
integer, parameter, public dp
Interface to the message passing library MPI.
Distributed block-sparse finite localizers, retaining the covariant AO metric.
subroutine, public localizer_dbcsr_from_real(realified, template, matrix)
Extract the two left quadrants of R(A); does not average away structure errors.
subroutine, public localizer_ao_operators(h, s, positions, operators, metric, soc)
Shared AO Hamiltonian, Hermitian scalar observables and optional GTH physical-spin SOC.
subroutine, public localizer_dbcsr_dense(matrix, para_env, dense)
Collect the size-limited dense oracle; sparse solvers must not call this routine.
subroutine, public localizer_dbcsr_gap_pencil(h, s, energy, pencil, metric)
Pair H-E*S with its negative to reuse the metric-aware localizer gap solvers.
subroutine, public localizer_dbcsr_release(matrix)
Release both real components of a complex sparse operator.
subroutine, public localizer_dbcsr_check(matrix, para_env, tolerance, valid, relative_error)
Check both components before a sparse solver discards the upper triangle.
subroutine, public localizer_dbcsr_realify(matrix, realified)
Distributed real matrix R(A)=[Re(A),-Im(A);Im(A),Re(A)].
subroutine, public localizer_dbcsr_build(h, s, x, y, point, energy, kappa, localizer, metric, soc, periodic_cosines, shifted_hamiltonian)
Assemble L and B=diag(S,S), including optional physical spin and SOC, without dense AOs.
subroutine, public localizer_dbcsr_3d_build(h, s, positions, point, energy, kappa, block, metric, soc, shifted_hamiltonian, periodic_cosines)
Build the 3D AII chiral block in DBCSR; not a Hermitian 2D localizer.
stores all the informations relevant to an mpi environment