(git:53a46e8)
Loading...
Searching...
No Matches
cp_linked_list_xc_deriv.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8
11#include "../base/base_uses.f90"
12
13
14! **************************************************************************************************
15!> \brief describes a generic linked list template.
16!> Linked list are supposed to always use pointers to the nodes for
17!> basically everything: a pointer to the node is a list, an element of
18!> the list, an iterator between the elment of the list.
19!> An empty list is represented by an unassociated pointer.
20!> \par History
21!> 1.2002 created
22!> 4.2002 changed most of the methods, by making access to the list
23!> always through pointers (identifying pointer, list and iterators)
24!> 6.2004 removed %initialized from list elements
25!> \author Fawzi Mohamed
26! **************************************************************************************************
27 IMPLICIT NONE
28 PRIVATE
29
30 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
31
32
33!API type
35
36!API common methods
37 PUBLIC :: cp_create, cp_dealloc, cp_next
38!API special get
40!API special set
41 PUBLIC :: cp_set_element_at
42!API structure manipulation
44
45 !API underlying routines
46
56
57! creation of an object (from a pointer)
58 INTERFACE cp_create
59 MODULE PROCEDURE cp_sll_xc_deriv_create
60 END INTERFACE
61! destruction of an object (from a pointer)
62 INTERFACE cp_dealloc
63 MODULE PROCEDURE cp_sll_xc_deriv_dealloc
64 END INTERFACE
65! iterates to the next element
66 INTERFACE cp_next
67 MODULE PROCEDURE cp_sll_xc_deriv_next
68 END INTERFACE
69! returns the first element
71 MODULE PROCEDURE cp_sll_xc_deriv_get_first_el
72 END INTERFACE
73! returns the rest of the list
74 INTERFACE cp_get_rest
75 MODULE PROCEDURE cp_sll_xc_deriv_get_rest
76 END INTERFACE
77! returns the length of the list
78 INTERFACE cp_get_length
79 MODULE PROCEDURE cp_sll_xc_deriv_get_length
80 END INTERFACE
81! returns the element at the given position
83 MODULE PROCEDURE cp_sll_xc_deriv_get_el_at
84 END INTERFACE
85! sets the element at the given position
87 MODULE PROCEDURE cp_sll_xc_deriv_set_el_at
88 END INTERFACE
89! inserts one element call cp_insert(list,element,...)
90 INTERFACE cp_insert
91 MODULE PROCEDURE cp_sll_xc_deriv_insert_el
92 END INTERFACE
93 INTERFACE cp_insert_at
94 MODULE PROCEDURE cp_sll_xc_deriv_insert_el_at
95 END INTERFACE
96! removes an element
100 END INTERFACE
101! removes the first el
103 MODULE PROCEDURE cp_sll_xc_deriv_rm_first_el
104 END INTERFACE
105! remove all the elements
107 MODULE PROCEDURE cp_sll_xc_deriv_rm_all_el
108 END INTERFACE
109! transorms the list in array
110 INTERFACE cp_to_array
111 module procedure cp_sll_xc_deriv_to_array
112 END INTERFACE
113
114! **************************************************************************************************
115!> \brief represent a single linked list that stores pointers to the elements
116!> \param first_el the element that is stored in this node.
117!> \param rest the rest of the list
118!>
119!> \param empty true if the list pointer is not associated, if it points to
120!> to a not it is always false (as there is at least the
121!> first_el in the list)
122!> \param length the number of elements in the list
123!> \note
124!> List are alway accessed through pointers, so every node of the
125!> linked list can be seen as a list, its first element
126!> a pointer to the position before itself, in a very natural way:
127!> all the insertions take place before the actual element, and
128!> you still can insert an element at the end.
129!> This way I could identify nodes, lists and pointers between the
130!> elements of the list.
131!> Indexing is 1 based.
132!> \par History
133!> none
134!> \author Fawzi Mohamed
135! **************************************************************************************************
137 TYPE(xc_derivative_type), POINTER :: first_el => null()
138 TYPE(cp_sll_xc_deriv_type), POINTER :: rest => null()
139 END TYPE cp_sll_xc_deriv_type
140
141! **************************************************************************************************
142!> \brief pointer to a linked list (to make arrays of pointers)
143!> \param list the pointer to the list
144!> \par History
145!> none
146!> \author Fawzi Mohamed
147! **************************************************************************************************
149 TYPE(cp_sll_xc_deriv_type), POINTER :: list => null()
151
152 CONTAINS
153
154 ! **************************************************************************************************
155!> \brief private compare function
156!> \param el1 ...
157!> \param el2 ...
158!> \return ...
159! **************************************************************************************************
160 function cp_sll_deriv_less_q(el1, el2) result(res)
161 type(xc_derivative_type), INTENT(IN) :: el1, el2
162 logical :: res
163
164 integer :: i
165
166 res = size(el1%split_desc) < size(el2%split_desc)
167 if (size(el1%split_desc) == size(el2%split_desc)) then
168 do i = 1, size(el1%split_desc)
169 if (el1%split_desc(i) /= el2%split_desc(i)) then
170 res = el1%split_desc(i) < el2%split_desc(i)
171 exit
172 end if
173 end do
174 end if
175 end function cp_sll_deriv_less_q ! this comment prevents trailing whitespace
176
177! =========== creation / destruction ========
178
179! **************************************************************************************************
180!> \brief allocates and initializes a single linked list
181!> \param sll the single linked list to initialize
182!> \param first_el the first element of this list
183!> \param rest the following elements (if not given: empty)
184!> \par History
185!> none
186!> \author Fawzi Mohamed
187! **************************************************************************************************
188 SUBROUTINE cp_sll_xc_deriv_create(sll, first_el, rest)
189 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
190 TYPE(xc_derivative_type), POINTER, OPTIONAL :: first_el
191 TYPE(cp_sll_xc_deriv_type), POINTER, OPTIONAL :: rest
192
193 IF (.NOT. PRESENT(first_el)) THEN
194 NULLIFY (sll)
195 IF (PRESENT(rest)) sll => rest
196 ELSE
197 ALLOCATE (sll)
198 sll%first_el =>first_el
199 NULLIFY (sll%rest)
200 IF (PRESENT(rest)) sll%rest => rest
201 END IF
202 END SUBROUTINE cp_sll_xc_deriv_create
203
204! **************************************************************************************************
205!> \brief deallocates the singly linked list starting at sll.
206!> Does not work if loops are present!
207!> \param sll the list to be deallocated
208!> \par History
209!> none
210!> \author Fawzi Mohamed
211!> \note
212!> does not deallocate the elements that are stored in the list
213!> check more?
214! **************************************************************************************************
216 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
217
219 END SUBROUTINE cp_sll_xc_deriv_dealloc
220
221! * low-level *
222
223! **************************************************************************************************
224!> \brief deallocates a node of a singly linked list (low level)
225!> \param sll the node to be deallocated
226!> \par History
227!> none
228!> \author Fawzi Mohamed
229! **************************************************************************************************
230 SUBROUTINE cp_sll_xc_deriv_dealloc_node(sll)
231 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
232
233 DEALLOCATE (sll)
234 END SUBROUTINE cp_sll_xc_deriv_dealloc_node
235
236! ============= get/set ============
237
238! **************************************************************************************************
239!> \brief returns the first element stored in the list
240!> \param sll the single linked list to get the element from
241!> \return ...
242!> \par History
243!> none
244!> \author Fawzi Mohamed
245! **************************************************************************************************
246 FUNCTION cp_sll_xc_deriv_get_first_el(sll) RESULT(res)
247 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
248 TYPE(xc_derivative_type), POINTER :: res
249
250 res =>sll%first_el
252
253! **************************************************************************************************
254!> \brief returns the rest of the list
255!> \param sll the single linked list to get the rest from
256!> \param iter how many times the call to rest should be iterated,
257!> defaults to 1; -1 means till end of the list.
258!> \return ...
259!> \par History
260!> none
261!> \author Fawzi Mohamed
262!> \note
263!> split the case iter=1 to make it more optimized?
264! **************************************************************************************************
265 FUNCTION cp_sll_xc_deriv_get_rest(sll, iter) RESULT(res)
266 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
267 INTEGER, OPTIONAL :: iter
268
269 TYPE(cp_sll_xc_deriv_type), POINTER :: res
270
271 INTEGER :: i
272
273 IF (.NOT. ASSOCIATED(sll)) THEN
274 NULLIFY (res)
275 ELSE
276 IF (PRESENT(iter)) THEN
277 res => sll
278 DO i = 1, iter
279 IF (ASSOCIATED(res%rest)) THEN
280 res => res%rest
281 ELSE
282 cpabort("tried to go past end")
283 END IF
284 END DO
285 IF (iter == -1) THEN
286 DO
287 IF (.NOT. ASSOCIATED(res%rest)) EXIT
288 res => res%rest
289 END DO
290 END IF
291 ELSE
292 res => sll%rest ! make the common case fast...
293 END IF
294 END IF
295 END FUNCTION cp_sll_xc_deriv_get_rest
296
297! **************************************************************************************************
298!> \brief returns the length of the list
299!> \param sll the list you want to know the length of
300!> \return ...
301!> \par History
302!> none
303!> \author Fawzi Mohamed
304!> \note
305!> slow (O(n))
306! **************************************************************************************************
307 FUNCTION cp_sll_xc_deriv_get_length(sll) RESULT(res)
308 TYPE(cp_sll_xc_deriv_type), pointer :: sll
309 INTEGER ::res
310
311 TYPE(cp_sll_xc_deriv_type), POINTER :: iterator
312
313 res = 0
314 iterator => sll
315 DO
316 IF (ASSOCIATED(iterator)) THEN
317 res = res + 1
318 iterator => iterator%rest
319 ELSE
320 EXIT
321 END IF
322 END DO
323 END FUNCTION cp_sll_xc_deriv_get_length
324
325! **************************************************************************************************
326!> \brief returns the element at the given index
327!> \param sll the list you get the element from
328!> \param index the position of the element (stating at 1)
329!> \return ...
330!> \par History
331!> none
332!> \author Fawzi Mohamed
333!> \note
334!> slow (O(index))
335! **************************************************************************************************
336 FUNCTION cp_sll_xc_deriv_get_el_at(sll, index) RESULT(res)
337 TYPE(xc_derivative_type), POINTER :: res
338 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
339 INTEGER, INTENT(in) :: index
340
341 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
342
343 IF (index == -1) THEN
344 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
345 ELSE
346 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 1)
347 END IF
348 cpassert(ASSOCIATED(pos))
349
350 res =>pos%first_el
351 END FUNCTION cp_sll_xc_deriv_get_el_at
352
353! **************************************************************************************************
354!> \brief sets the element at the given index
355!> \param sll the list you get the element from
356!> \param index the position of the element (stating at 1)
357!> -1 means at the end
358!> \param value the new element
359!> \par History
360!> none
361!> \author Fawzi Mohamed
362!> \note
363!> slow (O(index))
364! **************************************************************************************************
365 SUBROUTINE cp_sll_xc_deriv_set_el_at(sll, index, value)
366 TYPE(xc_derivative_type), POINTER :: value
367 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
368 INTEGER, INTENT(in) :: index
369
370 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
371
372 IF (index == -1) THEN
373 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
374 ELSE
375 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 1)
376 END IF
377 cpassert(ASSOCIATED(pos))
378
379 pos%first_el =>value
380 END SUBROUTINE cp_sll_xc_deriv_set_el_at
381
382! * iteration *
383
384! **************************************************************************************************
385!> \brief returns true if the actual element is valid (i.e. iterator ont at end)
386!> moves the iterator to the next element
387!> \param iterator iterator that moves along the list
388!> \param el_att the actual element (valid only if the function returns true)
389!> \return ...
390!> \par History
391!> none
392!> \author Fawzi Mohamed
393! **************************************************************************************************
394 FUNCTION cp_sll_xc_deriv_next(iterator, el_att) RESULT(res)
395 TYPE(cp_sll_xc_deriv_type), POINTER :: iterator
396 TYPE(xc_derivative_type), POINTER, OPTIONAL :: el_att
397 LOGICAL :: res
398
399 IF (ASSOCIATED(iterator)) THEN
400 res = .true.
401 if (present(el_att)) el_att =>iterator%first_el
402 iterator => iterator%rest
403 ELSE
404 res = .false.
405 END IF
406 END FUNCTION cp_sll_xc_deriv_next
407
408! ============ structure modifications ============
409
410! **************************************************************************************************
411!> \brief insert an element at the beginning of the list
412!> \param sll the single linked list point at the beginning of which
413!> you want to add the element
414!> \param el the element to add
415!> \par History
416!> none
417!> \author Fawzi Mohamed
418!> \note
419!> fast (O(1))
420! **************************************************************************************************
421 SUBROUTINE cp_sll_xc_deriv_insert_el(sll, el)
422 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
423 TYPE(xc_derivative_type), POINTER:: el
424
425 TYPE(cp_sll_xc_deriv_type), POINTER :: newSlot
426
427 NULLIFY (newslot)
428
429 CALL cp_sll_xc_deriv_create(newslot, first_el=el, &
430 rest=sll)
431 sll => newslot
432 END SUBROUTINE cp_sll_xc_deriv_insert_el
433
434! **************************************************************************************************
435!> \brief remove the first element of the linked list
436!> \param sll the list whose first element has to be removed
437!> \par History
438!> none
439!> \author Fawzi Mohamed
440!> \note
441!> fast (O(1))
442! **************************************************************************************************
444 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
445
446 TYPE(cp_sll_xc_deriv_type), POINTER :: node_to_rm
447 node_to_rm => sll
448
449 IF (ASSOCIATED(sll)) THEN
450 sll => sll%rest
451 CALL cp_sll_xc_deriv_dealloc_node(node_to_rm)
452 ELSE
453 cpabort("tried to remove first el of an empty list")
454 END IF
455 END SUBROUTINE cp_sll_xc_deriv_rm_first_el
456
457! **************************************************************************************************
458!> \brief inserts the element at the given index
459!> \param sll the list you get the element from
460!> \param el the new element
461!> \param index the position of the element (stating at 1).
462!> If it is -1, it means at end
463!> \par History
464!> none
465!> \author Fawzi Mohamed
466!> \note
467!> slow (O(index))
468! **************************************************************************************************
469 SUBROUTINE cp_sll_xc_deriv_insert_el_at(sll, el, index)
470 TYPE(xc_derivative_type), POINTER :: el
471 INTEGER, INTENT(in) :: index
472 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
473
474 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
475
476 IF (index == 1) THEN
477 CALL cp_sll_xc_deriv_insert_el(sll, el)
478 ELSE
479 IF (index == -1) THEN
480 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
481 ELSE
482 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 2)
483 END IF
484 cpassert(ASSOCIATED(pos))
485 CALL cp_sll_xc_deriv_insert_el(pos%rest, el)
486 END IF
487 END SUBROUTINE cp_sll_xc_deriv_insert_el_at
488
489! **************************************************************************************************
490!> \brief removes the element at the given index
491!> \param sll the list you get the element from
492!> \param index the position of the element (stating at 1)
493!> \par History
494!> none
495!> \author Fawzi Mohamed
496!> \note
497!> slow (O(index))
498! **************************************************************************************************
499 SUBROUTINE cp_sll_xc_deriv_rm_el_at(sll, index)
500 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
501 INTEGER, INTENT(in)::index
502
503 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
504
505 IF (index == 1) THEN
507 ELSE
508 IF (index == -1) THEN
509 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
510 ELSE
511 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 2)
512 END IF
513 cpassert(ASSOCIATED(pos))
514 CALL cp_sll_xc_deriv_rm_first_el(pos%rest)
515 END IF
516 END SUBROUTINE cp_sll_xc_deriv_rm_el_at
517
518! **************************************************************************************************
519!> \brief removes all the elements from the list
520!> \param sll the list that should be removed
521!> \par History
522!> none
523!> \author Fawzi Mohamed
524!> \note
525!> check more?
526! **************************************************************************************************
528 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
529
530 TYPE(cp_sll_xc_deriv_type), POINTER :: next_node, actual_node
531
532 actual_node => sll
533 DO
534 IF (.NOT. ASSOCIATED(actual_node)) EXIT
535 next_node => actual_node%rest
536 CALL cp_sll_xc_deriv_dealloc_node(actual_node)
537 actual_node => next_node
538 END DO
539 NULLIFY (sll)
540 END SUBROUTINE cp_sll_xc_deriv_rm_all_el
541
542! **************************************************************************************************
543!> \brief returns a newly allocated array with the same contents as
544!> the linked list
545!> \param sll the list to transform in array
546!> \return ...
547!> \par History
548!> 07.2002 created [fawzi]
549!> \author Fawzi Mohamed
550! **************************************************************************************************
551 FUNCTION cp_sll_xc_deriv_to_array(sll) RESULT(res)
552 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
553 type(xc_derivative_p_type), DIMENSION(:), POINTER :: res
554
555 INTEGER :: len, i
556 LOGICAL :: ok
557 TYPE(cp_sll_xc_deriv_type), POINTER :: iter
558
560 ALLOCATE (res(len))
561 iter => sll
562 DO i = 1, len
563 res(i) %deriv=>iter%first_el
564 ok = cp_sll_xc_deriv_next(iter)
565 cpassert(ok .OR. i == len)
566 END DO
567 END FUNCTION cp_sll_xc_deriv_to_array
integer function, public cp_sll_xc_deriv_get_length(sll)
returns the length of the list
subroutine, public cp_sll_xc_deriv_insert_el_at(sll, el, index)
inserts the element at the given index
logical function, public cp_sll_xc_deriv_next(iterator, el_att)
returns true if the actual element is valid (i.e. iterator ont at end) moves the iterator to the next...
type(xc_derivative_type) function, pointer, public cp_sll_xc_deriv_get_el_at(sll, index)
returns the element at the given index
logical function cp_sll_deriv_less_q(el1, el2)
private compare function
subroutine, public cp_sll_xc_deriv_dealloc(sll)
deallocates the singly linked list starting at sll. Does not work if loops are present!
subroutine, public cp_sll_xc_deriv_rm_all_el(sll)
removes all the elements from the list
type(xc_derivative_p_type) function, dimension(:), pointer, public cp_sll_xc_deriv_to_array(sll)
returns a newly allocated array with the same contents as the linked list
type(xc_derivative_type) function, pointer, public cp_sll_xc_deriv_get_first_el(sll)
returns the first element stored in the list
subroutine, public cp_sll_xc_deriv_set_el_at(sll, index, value)
sets the element at the given index
subroutine, public cp_sll_xc_deriv_rm_el_at(sll, index)
removes the element at the given index
subroutine, public cp_sll_xc_deriv_insert_el(sll, el)
insert an element at the beginning of the list
type(cp_sll_xc_deriv_type) function, pointer, public cp_sll_xc_deriv_get_rest(sll, iter)
returns the rest of the list
subroutine, public cp_sll_xc_deriv_rm_first_el(sll)
remove the first element of the linked list
subroutine, public cp_sll_xc_deriv_create(sll, first_el, rest)
allocates and initializes a single linked list
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Definition list.F:24
Provides types for the management of the xc-functionals and their derivatives.
pointer to a linked list (to make arrays of pointers)
represent a single linked list that stores pointers to the elements
represent a pointer to a derivative (to have arrays of derivatives)
represent a derivative of a functional