38#include "./base/base_uses.f90"
47 INTEGER :: degree = -1
49 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: color_present
50 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: neighbors => null()
54 TYPE(vertex),
POINTER :: vertex => null()
55 END TYPE vertex_p_type
57 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'kg_vertex_coloring_methods'
68 SUBROUTINE kg_create_graph(kg_env, pairs, graph)
69 TYPE(kg_environment_type),
POINTER :: kg_env
70 INTEGER(KIND=int_4),
ALLOCATABLE, &
71 DIMENSION(:, :),
INTENT(IN) :: pairs
72 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: graph
74 CHARACTER(len=*),
PARAMETER :: routineN =
'kg_create_graph'
76 INTEGER :: handle, i, imol, ineighbor, jmol, kmol, &
77 maxdegree, nneighbors, nnodes
79 CALL timeset(routinen, handle)
89 nnodes =
SIZE(kg_env%molecule_set)
92 ALLOCATE (graph(nnodes))
96 ALLOCATE (graph(i)%vertex)
97 graph(i)%vertex%id = i
98 graph(i)%vertex%color = 0
99 graph(i)%vertex%dsat = 0
100 graph(i)%vertex%degree = 0
108 DO i = 1,
SIZE(pairs, 2)
111 IF (jmol .NE. imol)
THEN
112 IF (imol .NE. 0)
THEN
113 ALLOCATE (graph(imol)%vertex%neighbors(nneighbors))
114 graph(imol)%vertex%degree = nneighbors
115 IF (nneighbors .GT. maxdegree) maxdegree = nneighbors
120 nneighbors = nneighbors + 1
123 IF (imol .NE. 0)
THEN
124 ALLOCATE (graph(imol)%vertex%neighbors(nneighbors))
125 graph(imol)%vertex%degree = nneighbors
126 IF (nneighbors .GT. maxdegree) maxdegree = nneighbors
129 kg_env%maxdegree = maxdegree
138 DO i = 1,
SIZE(pairs, 2)
140 IF (jmol .NE. imol)
THEN
144 ineighbor = ineighbor + 1
146 graph(imol)%vertex%neighbors(ineighbor)%vertex => graph(kmol)%vertex
149 DO i = 1,
SIZE(graph)
150 IF (graph(i)%vertex%degree > 0)
THEN
151 ALLOCATE (graph(i)%vertex%color_present(100))
152 graph(i)%vertex%color_present(:) = .false.
156 CALL timestop(handle)
167 SUBROUTINE color_graph_greedy(graph, maxdegree, ncolors)
168 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: graph
169 INTEGER,
INTENT(in) :: maxdegree
170 INTEGER,
INTENT(out) :: ncolors
172 CHARACTER(len=*),
PARAMETER :: routineN =
'color_graph_greedy'
174 INTEGER :: color, handle, i, j, newcolor, &
176 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: color_present
178 CALL timeset(routinen, handle)
184 ALLOCATE (color_present(maxdegree + 1))
187 color_present(:) = .false.
188 IF (
ASSOCIATED(graph(i)%vertex%neighbors))
THEN
189 nneighbors =
SIZE(graph(i)%vertex%neighbors)
191 color = graph(i)%vertex%neighbors(j)%vertex%color
192 IF (color .NE. 0) color_present(color) = .true.
195 DO j = 1, maxdegree + 1
196 IF (color_present(j) .EQV. .false.)
THEN
201 IF (newcolor .GT. ncolors) ncolors = newcolor
202 graph(i)%vertex%color = newcolor
205 DEALLOCATE (color_present)
207 CALL timestop(handle)
219 SUBROUTINE print_subsets(graph, ncolors, unit_nr)
220 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: graph
221 INTEGER,
INTENT(IN) :: ncolors, unit_nr
223 CHARACTER(len=*),
PARAMETER :: routineN =
'print_subsets'
225 INTEGER :: counter, handle, i, j, nnodes
227 CALL timeset(routinen, handle)
229 IF (unit_nr > 0)
THEN
231 WRITE (unit_nr,
'(T2,A,T10,A)')
"Color |",
"Molecules in this subset (IDs start from 0)"
236 WRITE (unit_nr,
'(T2,I5,1X,A)', advance=
'NO') i,
"|"
239 IF (graph(j)%vertex%color .EQ. i)
THEN
240 counter = counter + 1
241 IF (mod(counter, 13) .EQ. 0)
THEN
242 counter = counter + 1
243 WRITE (unit_nr,
'()')
244 WRITE (unit_nr,
'(6X,A)', advance=
'NO')
" |"
246 WRITE (unit_nr,
'(I5,1X)', advance=
'NO') graph(j)%vertex%id - 1
249 WRITE (unit_nr,
'()')
254 CALL timestop(handle)
264 ELEMENTAL FUNCTION kg_get_value(dsat, degree)
RESULT(value)
265 INTEGER,
INTENT(IN) :: dsat, degree
266 INTEGER(KIND=valt) :: value
268 INTEGER,
PARAMETER :: huge_4 = 2_int_4**30
273 value = (huge_4 - int(dsat, kind=
int_8))*huge_4 + huge_4 - degree
282 SUBROUTINE kg_cp_heap_fill(heap, graph)
283 TYPE(cp_heap_type),
INTENT(INOUT) :: heap
284 TYPE(vertex_p_type),
DIMENSION(:),
INTENT(IN), &
288 INTEGER(kind=valt),
ALLOCATABLE,
DIMENSION(:) :: values
292 ALLOCATE (values(nnodes))
295 values(i) = kg_get_value(0, graph(i)%vertex%degree)
310 SUBROUTINE kg_update_node(heap, node)
311 TYPE(cp_heap_type) :: heap
312 TYPE(vertex),
INTENT(IN),
POINTER :: node
314 INTEGER :: degree, dsat, id
315 INTEGER(KIND=valt) :: value
320 IF (heap%index(id) > 0)
THEN
325 value = kg_get_value(dsat, degree)
340 SUBROUTINE kg_dsatur(kg_env, graph, ncolors)
341 TYPE(kg_environment_type),
POINTER :: kg_env
342 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: graph
343 INTEGER(KIND=int_4),
INTENT(OUT) :: ncolors
345 CHARACTER(len=*),
PARAMETER :: routineN =
'kg_dsatur'
347 INTEGER :: color_limit, handle, i, j, key, &
348 maxdegree, nneighbors, nnodes
349 INTEGER(KIND=valt) :: value
351 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: color_present
352 TYPE(cp_heap_type) :: heap
353 TYPE(vertex),
POINTER :: neighbor, this
355 CALL timeset(routinen, handle)
361 maxdegree = kg_env%maxdegree
364 IF (kg_env%maxdegree .EQ. 0)
THEN
371 graph(i)%vertex%color = 1
379 CALL kg_cp_heap_fill(heap, graph)
381 DO WHILE (heap%n > 0)
385 this => graph(key)%vertex
389 IF (
ASSOCIATED(this%neighbors))
THEN
390 nneighbors =
SIZE(this%neighbors)
395 DO i = 1, this%degree + 1
396 IF (this%color_present(i) .EQV. .false.)
THEN
401 IF (this%color .GT. ncolors) ncolors = this%color
405 neighbor => this%neighbors(i)%vertex
406 IF (neighbor%color_present(this%color)) cycle
407 neighbor%color_present(this%color) = .true.
408 neighbor%dsat = neighbor%dsat + 1
409 IF (neighbor%color /= 0) cycle
410 CALL kg_update_node(heap, neighbor)
414 IF (this%color == color_limit)
THEN
415 ALLOCATE (color_present(color_limit))
417 IF (graph(i)%vertex%degree == 0) cycle
418 color_present(:) = graph(i)%vertex%color_present
419 DEALLOCATE (graph(i)%vertex%color_present)
420 ALLOCATE (graph(i)%vertex%color_present(color_limit*2))
421 DO j = 1, color_limit
422 graph(i)%vertex%color_present(j) = color_present(j)
424 DO j = color_limit + 1, 2*color_limit
425 graph(i)%vertex%color_present(j) = .false.
428 DEALLOCATE (color_present)
429 color_limit = color_limit*2
439 CALL timestop(handle)
455 SUBROUTINE kg_check_switch(this, neighbor, low_col, switchable, ncolors, color_present)
457 TYPE(vertex),
POINTER :: this, neighbor
458 INTEGER,
INTENT(OUT) :: low_col
459 LOGICAL :: switchable
461 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: color_present
466 low_col = ncolors + 1
468 DO i = 1, this%degree
469 IF (this%neighbors(i)%vertex%id == neighbor%id) cycle
470 IF (this%neighbors(i)%vertex%color == neighbor%color)
THEN
475 IF (.NOT. switchable)
RETURN
477 color_present(:) = .false.
478 color_present(neighbor%color) = .true.
479 DO i = 1, neighbor%degree
480 IF (neighbor%neighbors(i)%vertex%id == this%id) cycle
481 color_present(neighbor%neighbors(i)%vertex%color) = .true.
484 IF (.NOT. color_present(i))
THEN
502 SUBROUTINE kg_pair_switching(graph, ncolors)
503 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: graph
506 CHARACTER(LEN=*),
PARAMETER :: routineN =
'kg_pair_switching'
508 INTEGER :: depth, handle, i, iter, j, low_col, &
509 low_col_neigh, maxdepth, &
510 maxiterations, nnodes, partner
511 LOGICAL :: switchable
512 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: color_present
513 TYPE(vertex),
POINTER :: neighbor, this
515 CALL timeset(routinen, handle)
517 ALLOCATE (color_present(ncolors))
523 DO iter = 1, maxiterations
524 DO depth = 1, maxdepth
527 this => graph(i)%vertex
528 IF (.NOT.
ASSOCIATED(this%neighbors)) cycle
529 IF (graph(i)%vertex%color < ncolors - depth + 1) cycle
532 low_col = this%color + 1
534 DO j = 1, this%degree
535 neighbor => this%neighbors(j)%vertex
536 IF (neighbor%color > this%color) cycle
537 CALL kg_check_switch(this, neighbor, low_col_neigh, switchable, ncolors, color_present)
538 IF (switchable .AND. low_col_neigh < low_col)
THEN
540 low_col = low_col_neigh
543 IF (partner == 0) cycle
545 this%color = this%neighbors(partner)%vertex%color
546 this%neighbors(partner)%vertex%color = low_col
551 IF (graph(j)%vertex%color > ncolors)
THEN
552 ncolors = graph(j)%vertex%color
558 DEALLOCATE (color_present)
559 CALL timestop(handle)
568 SUBROUTINE check_coloring(graph, valid)
569 TYPE(vertex_p_type),
DIMENSION(:),
INTENT(in), &
571 LOGICAL,
INTENT(out) :: valid
573 CHARACTER(len=*),
PARAMETER :: routineN =
'check_coloring'
575 INTEGER :: handle, i, j, nneighbors, nnodes
576 TYPE(vertex),
POINTER :: neighbor, node
578 CALL timeset(routinen, handle)
584 node => graph(i)%vertex
585 IF (
ASSOCIATED(node%neighbors))
THEN
586 nneighbors =
SIZE(node%neighbors)
588 neighbor => node%neighbors(j)%vertex
589 IF (neighbor%color == node%color)
THEN
597 CALL timestop(handle)
605 SUBROUTINE deallocate_graph(graph)
606 TYPE(vertex_p_type),
DIMENSION(:),
POINTER :: graph
613 IF (
ASSOCIATED(graph(i)%vertex%neighbors))
DEALLOCATE (graph(i)%vertex%neighbors)
614 DEALLOCATE (graph(i)%vertex)
629 INTEGER(KIND=int_4),
ALLOCATABLE, &
630 DIMENSION(:, :),
INTENT(IN) :: pairs
631 INTEGER(KIND=int_4),
INTENT(OUT) :: ncolors
632 INTEGER(KIND=int_4),
ALLOCATABLE,
DIMENSION(:), &
633 INTENT(out) :: color_of_node
635 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kg_vertex_coloring'
637 INTEGER :: color, handle, i, nnodes, unit_nr
640 TYPE(vertex_p_type),
DIMENSION(:),
POINTER ::
graph
645 IF (logger%para_env%is_source())
THEN
651 CALL timeset(routinen, handle)
653 CALL kg_create_graph(kg_env, pairs,
graph)
655 SELECT CASE (kg_env%coloring_method)
658 CALL color_graph_greedy(
graph, kg_env%maxdegree, ncolors)
661 CALL kg_dsatur(kg_env,
graph, ncolors)
663 cpabort(
"Coloring method not known.")
666 CALL kg_pair_switching(
graph, ncolors)
669 CALL check_coloring(
graph, valid)
671 cpabort(
"Coloring not valid.")
673 nnodes =
SIZE(kg_env%molecule_set)
675 ALLOCATE (color_of_node(nnodes))
679 color =
graph(i)%vertex%color
680 color_of_node(i) = color
683 IF (unit_nr > 0)
THEN
685 WRITE (unit_nr,
'(T2,A,A,A)') repeat(
"-", 30),
" KG coloring result ", repeat(
"-", 29)
687 WRITE (unit_nr,
'()')
688 CALL print_subsets(
graph, ncolors, unit_nr)
689 WRITE (unit_nr,
'()')
691 WRITE (unit_nr,
'(T2, A16,50X,I6,1X,A6)')
'Number of colors', ncolors,
'colors'
692 IF (valid)
WRITE (unit_nr,
'(T2, A17,59X,A3)')
'Coloring verified',
'yes'
693 WRITE (unit_nr,
'(T2,A)') repeat(
"-", 79)
697 CALL deallocate_graph(
graph)
699 CALL timestop(handle)
program graph
Program to Map on grid the hills spawned during a metadynamics run.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public andermatt2016
integer, save, public brelaz1979
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
subroutine, public cp_heap_pop(heap, key, value, found)
Returns and removes the first heap element and rebalances the heap.
subroutine, public cp_heap_fill(heap, values)
Fill heap with given values.
subroutine, public cp_heap_new(heap, n)
...
integer, parameter, public valt
subroutine, public cp_heap_release(heap)
...
subroutine, public cp_heap_reset_node(heap, key, value)
Changes the value of the heap element with given key and rebalances the heap.
Types needed for a Kim-Gordon-like partitioning into molecular subunits.
Routines for a Kim-Gordon-like partitioning into molecular subunits unsing a vertex coloring algorith...
subroutine, public kg_vertex_coloring(kg_env, pairs, ncolors, color_of_node)
...
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public int_4
type of a logger, at the moment it contains just a print level starting at which level it should be l...
Contains all the info needed for KG runs...