(git:374b731)
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-2024 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
176! =========== creation / destruction ========
177
178! **************************************************************************************************
179!> \brief allocates and initializes a single linked list
180!> \param sll the single linked list to initialize
181!> \param first_el the first element of this list
182!> \param rest the following elements (if not given: empty)
183!> \par History
184!> none
185!> \author Fawzi Mohamed
186! **************************************************************************************************
187 SUBROUTINE cp_sll_xc_deriv_create(sll, first_el, rest)
188 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
189 TYPE(xc_derivative_type), POINTER, OPTIONAL :: first_el
190 TYPE(cp_sll_xc_deriv_type), POINTER, OPTIONAL :: rest
191
192 IF (.NOT. PRESENT(first_el)) THEN
193 NULLIFY (sll)
194 IF (PRESENT(rest)) sll => rest
195 ELSE
196 ALLOCATE (sll)
197 sll%first_el =>first_el
198 NULLIFY (sll%rest)
199 IF (PRESENT(rest)) sll%rest => rest
200 END IF
201 END SUBROUTINE cp_sll_xc_deriv_create
202
203! **************************************************************************************************
204!> \brief deallocates the singly linked list starting at sll.
205!> Does not work if loops are present!
206!> \param sll the list to be deallocated
207!> \par History
208!> none
209!> \author Fawzi Mohamed
210!> \note
211!> does not deallocate the elements that are stored in the list
212!> check more?
213! **************************************************************************************************
215 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
216
218 END SUBROUTINE cp_sll_xc_deriv_dealloc
219
220! * low-level *
221
222! **************************************************************************************************
223!> \brief deallocates a node of a singly linked list (low level)
224!> \param sll the node to be deallocated
225!> \par History
226!> none
227!> \author Fawzi Mohamed
228! **************************************************************************************************
229 SUBROUTINE cp_sll_xc_deriv_dealloc_node(sll)
230 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
231
232 DEALLOCATE (sll)
233 END SUBROUTINE cp_sll_xc_deriv_dealloc_node
234
235! ============= get/set ============
236
237! **************************************************************************************************
238!> \brief returns the first element stored in the list
239!> \param sll the single linked list to get the element from
240!> \return ...
241!> \par History
242!> none
243!> \author Fawzi Mohamed
244! **************************************************************************************************
245 FUNCTION cp_sll_xc_deriv_get_first_el(sll) RESULT(res)
246 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
247 TYPE(xc_derivative_type), POINTER :: res
248
249 res =>sll%first_el
251
252! **************************************************************************************************
253!> \brief returns the rest of the list
254!> \param sll the single linked list to get the rest from
255!> \param iter how many times the call to rest should be iterated,
256!> defaults to 1; -1 means till end of the list.
257!> \return ...
258!> \par History
259!> none
260!> \author Fawzi Mohamed
261!> \note
262!> split the case iter=1 to make it more optimized?
263! **************************************************************************************************
264 FUNCTION cp_sll_xc_deriv_get_rest(sll, iter) RESULT(res)
265 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
266 INTEGER, OPTIONAL :: iter
267
268 TYPE(cp_sll_xc_deriv_type), POINTER :: res
269
270 INTEGER :: i
271
272 IF (.NOT. ASSOCIATED(sll)) THEN
273 NULLIFY (res)
274 ELSE
275 IF (PRESENT(iter)) THEN
276 res => sll
277 DO i = 1, iter
278 IF (ASSOCIATED(res%rest)) THEN
279 res => res%rest
280 ELSE
281 cpabort("tried to go past end")
282 END IF
283 END DO
284 IF (iter == -1) THEN
285 DO
286 IF (.NOT. ASSOCIATED(res%rest)) EXIT
287 res => res%rest
288 END DO
289 END IF
290 ELSE
291 res => sll%rest ! make the common case fast...
292 END IF
293 END IF
294 END FUNCTION cp_sll_xc_deriv_get_rest
295
296! **************************************************************************************************
297!> \brief returns the length of the list
298!> \param sll the list you want to know the length of
299!> \return ...
300!> \par History
301!> none
302!> \author Fawzi Mohamed
303!> \note
304!> slow (O(n))
305! **************************************************************************************************
306 FUNCTION cp_sll_xc_deriv_get_length(sll) RESULT(res)
307 TYPE(cp_sll_xc_deriv_type), pointer :: sll
308 INTEGER ::res
309
310 TYPE(cp_sll_xc_deriv_type), POINTER :: iterator
311
312 res = 0
313 iterator => sll
314 DO
315 IF (ASSOCIATED(iterator)) THEN
316 res = res + 1
317 iterator => iterator%rest
318 ELSE
319 EXIT
320 END IF
321 END DO
322 END FUNCTION cp_sll_xc_deriv_get_length
323
324! **************************************************************************************************
325!> \brief returns the element at the given index
326!> \param sll the list you get the element from
327!> \param index the position of the element (stating at 1)
328!> \return ...
329!> \par History
330!> none
331!> \author Fawzi Mohamed
332!> \note
333!> slow (O(index))
334! **************************************************************************************************
335 FUNCTION cp_sll_xc_deriv_get_el_at(sll, index) RESULT(res)
336 TYPE(xc_derivative_type), POINTER :: res
337 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
338 INTEGER, INTENT(in) :: index
339
340 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
341
342 IF (index == -1) THEN
343 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
344 ELSE
345 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 1)
346 END IF
347 cpassert(ASSOCIATED(pos))
348
349 res =>pos%first_el
350 END FUNCTION cp_sll_xc_deriv_get_el_at
351
352! **************************************************************************************************
353!> \brief sets the element at the given index
354!> \param sll the list you get the element from
355!> \param index the position of the element (stating at 1)
356!> -1 means at the end
357!> \param value the new element
358!> \par History
359!> none
360!> \author Fawzi Mohamed
361!> \note
362!> slow (O(index))
363! **************************************************************************************************
364 SUBROUTINE cp_sll_xc_deriv_set_el_at(sll, index, value)
365 TYPE(xc_derivative_type), POINTER :: value
366 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
367 INTEGER, INTENT(in) :: index
368
369 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
370
371 IF (index == -1) THEN
372 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
373 ELSE
374 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 1)
375 END IF
376 cpassert(ASSOCIATED(pos))
377
378 pos%first_el =>value
379 END SUBROUTINE cp_sll_xc_deriv_set_el_at
380
381! * iteration *
382
383! **************************************************************************************************
384!> \brief returns true if the actual element is valid (i.e. iterator ont at end)
385!> moves the iterator to the next element
386!> \param iterator iterator that moves along the list
387!> \param el_att the actual element (valid only if the function returns true)
388!> \return ...
389!> \par History
390!> none
391!> \author Fawzi Mohamed
392! **************************************************************************************************
393 FUNCTION cp_sll_xc_deriv_next(iterator, el_att) RESULT(res)
394 TYPE(cp_sll_xc_deriv_type), POINTER :: iterator
395 TYPE(xc_derivative_type), POINTER, OPTIONAL :: el_att
396 LOGICAL :: res
397
398 IF (ASSOCIATED(iterator)) THEN
399 res = .true.
400 if (present(el_att)) el_att =>iterator%first_el
401 iterator => iterator%rest
402 ELSE
403 res = .false.
404 END IF
405 END FUNCTION cp_sll_xc_deriv_next
406
407! ============ structure modifications ============
408
409! **************************************************************************************************
410!> \brief insert an element at the beginning of the list
411!> \param sll the single linked list point at the beginning of which
412!> you want to add the element
413!> \param el the element to add
414!> \par History
415!> none
416!> \author Fawzi Mohamed
417!> \note
418!> fast (O(1))
419! **************************************************************************************************
420 SUBROUTINE cp_sll_xc_deriv_insert_el(sll, el)
421 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
422 TYPE(xc_derivative_type), POINTER:: el
423
424 TYPE(cp_sll_xc_deriv_type), POINTER :: newSlot
425
426 NULLIFY (newslot)
427
428 CALL cp_sll_xc_deriv_create(newslot, first_el=el, &
429 rest=sll)
430 sll => newslot
431 END SUBROUTINE cp_sll_xc_deriv_insert_el
432
433! **************************************************************************************************
434!> \brief remove the first element of the linked list
435!> \param sll the list whose first element has to be removed
436!> \par History
437!> none
438!> \author Fawzi Mohamed
439!> \note
440!> fast (O(1))
441! **************************************************************************************************
443 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
444
445 TYPE(cp_sll_xc_deriv_type), POINTER :: node_to_rm
446 node_to_rm => sll
447
448 IF (ASSOCIATED(sll)) THEN
449 sll => sll%rest
450 CALL cp_sll_xc_deriv_dealloc_node(node_to_rm)
451 ELSE
452 cpabort("tried to remove first el of an empty list")
453 END IF
454 END SUBROUTINE cp_sll_xc_deriv_rm_first_el
455
456! **************************************************************************************************
457!> \brief inserts the element at the given index
458!> \param sll the list you get the element from
459!> \param el the new element
460!> \param index the position of the element (stating at 1).
461!> If it is -1, it means at end
462!> \par History
463!> none
464!> \author Fawzi Mohamed
465!> \note
466!> slow (O(index))
467! **************************************************************************************************
468 SUBROUTINE cp_sll_xc_deriv_insert_el_at(sll, el, index)
469 TYPE(xc_derivative_type), POINTER :: el
470 INTEGER, INTENT(in) :: index
471 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
472
473 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
474
475 IF (index == 1) THEN
476 CALL cp_sll_xc_deriv_insert_el(sll, el)
477 ELSE
478 IF (index == -1) THEN
479 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
480 ELSE
481 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 2)
482 END IF
483 cpassert(ASSOCIATED(pos))
484 CALL cp_sll_xc_deriv_insert_el(pos%rest, el)
485 END IF
486 END SUBROUTINE cp_sll_xc_deriv_insert_el_at
487
488! **************************************************************************************************
489!> \brief removes the element at the given index
490!> \param sll the list you get the element from
491!> \param index the position of the element (stating at 1)
492!> \par History
493!> none
494!> \author Fawzi Mohamed
495!> \note
496!> slow (O(index))
497! **************************************************************************************************
498 SUBROUTINE cp_sll_xc_deriv_rm_el_at(sll, index)
499 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
500 INTEGER, INTENT(in)::index
501
502 TYPE(cp_sll_xc_deriv_type), POINTER :: pos
503
504 IF (index == 1) THEN
506 ELSE
507 IF (index == -1) THEN
508 pos => cp_sll_xc_deriv_get_rest(sll, iter=-1)
509 ELSE
510 pos => cp_sll_xc_deriv_get_rest(sll, iter=index - 2)
511 END IF
512 cpassert(ASSOCIATED(pos))
513 CALL cp_sll_xc_deriv_rm_first_el(pos%rest)
514 END IF
515 END SUBROUTINE cp_sll_xc_deriv_rm_el_at
516
517! **************************************************************************************************
518!> \brief removes all the elements from the list
519!> \param sll the list that should be removed
520!> \par History
521!> none
522!> \author Fawzi Mohamed
523!> \note
524!> check more?
525! **************************************************************************************************
527 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
528
529 TYPE(cp_sll_xc_deriv_type), POINTER :: next_node, actual_node
530
531 actual_node => sll
532 DO
533 IF (.NOT. ASSOCIATED(actual_node)) EXIT
534 next_node => actual_node%rest
535 CALL cp_sll_xc_deriv_dealloc_node(actual_node)
536 actual_node => next_node
537 END DO
538 NULLIFY (sll)
539 END SUBROUTINE cp_sll_xc_deriv_rm_all_el
540
541! **************************************************************************************************
542!> \brief returns a newly allocated array with the same contents as
543!> the linked list
544!> \param sll the list to transform in array
545!> \return ...
546!> \par History
547!> 07.2002 created [fawzi]
548!> \author Fawzi Mohamed
549! **************************************************************************************************
550 FUNCTION cp_sll_xc_deriv_to_array(sll) RESULT(res)
551 TYPE(cp_sll_xc_deriv_type), POINTER :: sll
552 type(xc_derivative_p_type), DIMENSION(:), POINTER :: res
553
554 INTEGER :: len, i
555 LOGICAL :: ok
556 TYPE(cp_sll_xc_deriv_type), POINTER :: iter
557
559 ALLOCATE (res(len))
560 iter => sll
561 DO i = 1, len
562 res(i) %deriv=>iter%first_el
563 ok = cp_sll_xc_deriv_next(iter)
564 cpassert(ok .OR. i == len)
565 END DO
566 END FUNCTION cp_sll_xc_deriv_to_array
567END MODULE
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