(git:374b731)
Loading...
Searching...
No Matches
hfx_compression_methods.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! **************************************************************************************************
9!> \brief routines and types for Hartree-Fock-Exchange
10!> \par History
11!> 11.2006 created [Manuel Guidon]
12!> \author Manuel Guidon
13! **************************************************************************************************
15 USE cp_files, ONLY: close_file,&
19 USE hfx_types, ONLY: hfx_cache_type,&
21 USE kinds, ONLY: dp,&
22 int_8
23#include "./base/base_uses.f90"
24
25 IMPLICIT NONE
26 PRIVATE
31
32#define CACHE_SIZE 1024
33
34 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'hfx_compression_methods'
35
36 INTEGER(kind=int_8), PARAMETER :: ugly_duck = ishft(1_int_8, 63)
37 INTEGER(int_8), PARAMETER :: shifts(0:63) = &
38 (/1_int_8, 2_int_8, 4_int_8, 8_int_8, 16_int_8, 32_int_8, 64_int_8, 128_int_8, 256_int_8, &
39 512_int_8, 1024_int_8, 2048_int_8, 4096_int_8, 8192_int_8, 16384_int_8, 32768_int_8, &
40 65536_int_8, 131072_int_8, 262144_int_8, 524288_int_8, 1048576_int_8, 2097152_int_8, &
41 4194304_int_8, 8388608_int_8, 16777216_int_8, 33554432_int_8, 67108864_int_8, &
42 134217728_int_8, 268435456_int_8, 536870912_int_8, 1073741824_int_8, 2147483648_int_8, &
43 4294967296_int_8, 8589934592_int_8, 17179869184_int_8, 34359738368_int_8, 68719476736_int_8, &
44 137438953472_int_8, 274877906944_int_8, 549755813888_int_8, 1099511627776_int_8, 2199023255552_int_8, &
45 4398046511104_int_8, 8796093022208_int_8, 17592186044416_int_8, 35184372088832_int_8, 70368744177664_int_8, &
46 140737488355328_int_8, 281474976710656_int_8, 562949953421312_int_8, 1125899906842624_int_8, &
47 2251799813685248_int_8, 4503599627370496_int_8, 9007199254740992_int_8, 18014398509481984_int_8, &
48 36028797018963968_int_8, 72057594037927936_int_8, 144115188075855872_int_8, 288230376151711744_int_8, &
49 576460752303423488_int_8, 1152921504606846976_int_8, 2305843009213693952_int_8, &
50 4611686018427387904_int_8, ugly_duck/)
51
52!***
53
54CONTAINS
55
56! **************************************************************************************************
57!> \brief - This routine adds an int_8 value to a cache. If the cache is full
58!> a compression routine is invoked and the cache is cleared
59!> \param value value to be added to the cache
60!> \param nbits number of bits to be stored
61!> \param cache cache to which we want to add
62!> \param container container that contains the compressed elements
63!> \param memory_usage ...
64!> \param use_disk_storage ...
65!> \param max_val_memory ...
66!> \par History
67!> 10.2007 created [Manuel Guidon]
68!> \author Manuel Guidon
69! **************************************************************************************************
70 SUBROUTINE hfx_add_single_cache_element(value, nbits, cache, container, memory_usage, use_disk_storage, &
71 max_val_memory)
72 INTEGER(int_8) :: value
73 INTEGER :: nbits
74 TYPE(hfx_cache_type) :: cache
75 TYPE(hfx_container_type) :: container
76 INTEGER :: memory_usage
77 LOGICAL :: use_disk_storage
78 INTEGER(int_8), OPTIONAL :: max_val_memory
79
80 INTEGER(int_8) :: int_val
81
82 int_val = value + shifts(nbits - 1)
83
84 IF (cache%element_counter /= cache_size) THEN
85 cache%data(cache%element_counter) = int_val
86 cache%element_counter = cache%element_counter + 1
87 ELSE
88 cache%data(cache_size) = int_val
89 CALL hfx_compress_cache(cache%data(1), container, nbits, memory_usage, use_disk_storage, &
90 max_val_memory)
91 cache%element_counter = 1
92 END IF
93 END SUBROUTINE hfx_add_single_cache_element
94
95! **************************************************************************************************
96!> \brief - This routine compresses a full cache and stores its values
97!> in a container. If necessary, a new list entry is allocated
98!> \param full_array values from the cache
99!> \param container linked list, that stores the compressed values
100!> \param nbits number of bits to be stored
101!> \param memory_usage ...
102!> \param use_disk_storage ...
103!> \param max_val_memory ...
104!> \par History
105!> 10.2007 created [Manuel Guidon]
106!> \author Manuel Guidon
107! **************************************************************************************************
108 SUBROUTINE hfx_compress_cache(full_array, container, nbits, memory_usage, use_disk_storage, &
109 max_val_memory)
110 INTEGER(int_8) :: full_array(*)
111 TYPE(hfx_container_type) :: container
112 INTEGER, INTENT(IN) :: nbits
113 INTEGER :: memory_usage
114 LOGICAL :: use_disk_storage
115 INTEGER(int_8), OPTIONAL :: max_val_memory
116
117 INTEGER :: end_idx, increment_counter, start_idx, &
118 tmp_elements, tmp_nints
119
120 start_idx = container%element_counter
121 increment_counter = (nbits*cache_size + 63)/64
122 end_idx = start_idx + increment_counter - 1
123 IF (end_idx < cache_size) THEN
124 CALL ints2bits_specific(nbits, cache_size, container%current%data(start_idx), full_array(1))
125 container%element_counter = container%element_counter + increment_counter
126 ELSE
127 !! We have to fill the container first with the remaining number of bits
128 tmp_elements = cache_size - start_idx + 1
129 tmp_nints = (tmp_elements*64)/nbits
130 CALL ints2bits_specific(nbits, tmp_nints, container%current%data(start_idx), full_array(1))
131 IF (use_disk_storage) THEN
132 !! write to file
133 WRITE (container%unit) container%current%data
134!$OMP ATOMIC
135 memory_usage = memory_usage + 1
136 container%file_counter = container%file_counter + 1
137 ELSE
138 !! Allocate new list entry
139 ALLOCATE (container%current%next)
140!$OMP ATOMIC
141 memory_usage = memory_usage + 1
142 container%current%next%next => null()
143 container%current => container%current%next
144 IF (PRESENT(max_val_memory)) max_val_memory = max_val_memory + 1
145 END IF
146 !! compress remaining ints
147 CALL ints2bits_specific(nbits, cache_size - tmp_nints, container%current%data(1), full_array(tmp_nints + 1))
148 container%element_counter = 1 + (nbits*(cache_size - tmp_nints) + 63)/64
149 END IF
150
151 END SUBROUTINE hfx_compress_cache
152
153! **************************************************************************************************
154!> \brief - This routine returns an int_8 value from a cache. If the cache is empty
155!> a decompression routine is invoked and the cache is refilled with decompressed
156!> values from a container
157!> \param value value to be retained from the cache
158!> \param nbits number of bits with which the value has been compressed
159!> \param cache cache from which we get the value
160!> \param container container that contains the compressed elements
161!> \param memory_usage ...
162!> \param use_disk_storage ...
163!> \par History
164!> 10.2007 created [Manuel Guidon]
165!> \author Manuel Guidon
166! **************************************************************************************************
167 SUBROUTINE hfx_get_single_cache_element(value, nbits, cache, container, memory_usage, use_disk_storage)
168 INTEGER(int_8) :: value
169 INTEGER :: nbits
170 TYPE(hfx_cache_type) :: cache
171 TYPE(hfx_container_type) :: container
172 INTEGER :: memory_usage
173 LOGICAL :: use_disk_storage
174
175 IF (cache%element_counter /= cache_size) THEN
176 value = cache%data(cache%element_counter)
177 cache%element_counter = cache%element_counter + 1
178 ELSE
179 value = cache%data(cache_size)
180 CALL hfx_decompress_cache(cache%data(1), container, nbits, memory_usage, use_disk_storage)
181 cache%element_counter = 1
182 END IF
183
184 value = value - shifts(nbits - 1)
185
186 END SUBROUTINE hfx_get_single_cache_element
187
188! **************************************************************************************************
189!> \brief - This routine decompresses data from a container in order to fill
190!> a cache.
191!> \param full_array values to be retained from container
192!> \param container linked list, that stores the compressed values
193!> \param nbits number of bits with which the values have been stored
194!> \param memory_usage ...
195!> \param use_disk_storage ...
196!> \par History
197!> 10.2007 created [Manuel Guidon]
198!> \author Manuel Guidon
199! **************************************************************************************************
200 SUBROUTINE hfx_decompress_cache(full_array, container, nbits, memory_usage, use_disk_storage)
201 INTEGER(int_8) :: full_array(*)
202 TYPE(hfx_container_type) :: container
203 INTEGER, INTENT(IN) :: nbits
204 INTEGER :: memory_usage
205 LOGICAL :: use_disk_storage
206
207 INTEGER :: end_idx, increment_counter, start_idx, &
208 stat, tmp_elements, tmp_nints
209
210 start_idx = container%element_counter
211 increment_counter = (nbits*cache_size + 63)/64
212 end_idx = start_idx + increment_counter - 1
213 IF (end_idx < cache_size) THEN
214 CALL bits2ints_specific(nbits, cache_size, container%current%data(start_idx), full_array(1))
215 container%element_counter = container%element_counter + increment_counter
216 ELSE
217 !! We have to fill the container first with the remaining number of bits
218 tmp_elements = cache_size - start_idx + 1
219 tmp_nints = (tmp_elements*64)/nbits
220 CALL bits2ints_specific(nbits, tmp_nints, container%current%data(start_idx), full_array(1))
221 IF (use_disk_storage) THEN
222 !! it could happen, that we are at the end of a file and we try to read
223 !! This happens in case a container has fully been filled in the compression step
224 !! but no other was needed for the current bit size
225 !! Therefore we can safely igonore an eof error
226 READ (container%unit, iostat=stat) container%current%data
227 memory_usage = memory_usage + 1
228 container%file_counter = container%file_counter + 1
229 ELSE
230 container%current => container%current%next
231 memory_usage = memory_usage + 1
232 END IF
233 !! decompress remaining ints
234 CALL bits2ints_specific(nbits, cache_size - tmp_nints, container%current%data(1), full_array(tmp_nints + 1))
235 container%element_counter = 1 + (nbits*(cache_size - tmp_nints) + 63)/64
236 END IF
237 END SUBROUTINE hfx_decompress_cache
238
239! **************************************************************************************************
240!> \brief - This routine resets the containers list pointer to the first element and
241!> moves the element counters of container and cache to the beginning
242!> \param cache cache from which we get the value
243!> \param container container that contains the compressed elements
244!> \param memory_usage ...
245!> \param do_disk_storage ...
246!> \par History
247!> 10.2007 created [Manuel Guidon]
248!> \author Manuel Guidon
249! **************************************************************************************************
250 SUBROUTINE hfx_reset_cache_and_container(cache, container, memory_usage, do_disk_storage)
251 TYPE(hfx_cache_type) :: cache
252 TYPE(hfx_container_type) :: container
253 INTEGER :: memory_usage
254 LOGICAL :: do_disk_storage
255
256 cache%element_counter = 1
257 container%current => container%first
258 container%element_counter = 1
259 memory_usage = 1
260 container%file_counter = 1
261 IF (do_disk_storage) THEN
262 CALL close_file(container%unit)
263 CALL open_file(file_name=container%filename, file_status="OLD", file_form="UNFORMATTED", file_action="READ", &
264 unit_number=container%unit)
265 READ (container%unit) container%current%data
266 END IF
267 END SUBROUTINE hfx_reset_cache_and_container
268
269! **************************************************************************************************
270!> \brief - This routine decompresses the first bunch of data in a container and
271!> copies them into a cache
272!> \param nbits number of bits with which the data has been stored
273!> \param cache array where we want to decompress the data
274!> \param container container that contains the compressed elements
275!> \param memory_usage ...
276!> \param use_disk_storage ...
277!> \par History
278!> 10.2007 created [Manuel Guidon]
279!> \author Manuel Guidon
280! **************************************************************************************************
281 SUBROUTINE hfx_decompress_first_cache(nbits, cache, container, memory_usage, use_disk_storage)
282 INTEGER :: nbits
283 TYPE(hfx_cache_type) :: cache
284 TYPE(hfx_container_type) :: container
285 INTEGER :: memory_usage
286 LOGICAL :: use_disk_storage
287
288 CALL hfx_decompress_cache(cache%data(1), container, nbits, memory_usage, use_disk_storage)
289 cache%element_counter = 1
290 END SUBROUTINE hfx_decompress_first_cache
291
292! **************************************************************************************************
293!> \brief - This routine compresses the last probably not yet compressed cache into
294!> a container
295!> \param nbits number of bits with which the data has been stored
296!> \param cache array where we want to decompress the data
297!> \param container container that contains the compressed elements
298!> \param memory_usage ...
299!> \param use_disk_storage ...
300!> \par History
301!> 10.2007 created [Manuel Guidon]
302!> \author Manuel Guidon
303! **************************************************************************************************
304 SUBROUTINE hfx_flush_last_cache(nbits, cache, container, memory_usage, use_disk_storage)
305 INTEGER :: nbits
306 TYPE(hfx_cache_type) :: cache
307 TYPE(hfx_container_type) :: container
308 INTEGER :: memory_usage
309 LOGICAL :: use_disk_storage
310
311 CALL hfx_compress_cache(cache%data(1), container, nbits, memory_usage, use_disk_storage)
312
313 !!If we store to file, we have to make sure, that the last container is also written to disk
314 IF (use_disk_storage) THEN
315 IF (container%element_counter /= 1) THEN
316 WRITE (container%unit) container%current%data
317 memory_usage = memory_usage + 1
318 container%file_counter = container%file_counter + 1
319 END IF
320 END IF
321 END SUBROUTINE hfx_flush_last_cache
322
323! **************************************************************************************************
324!> \brief - This routine adds an a few real values to a cache. If the cache is full
325!> a compression routine is invoked and the cache is cleared
326!> \param values values to be added to the cache
327!> \param nints ...
328!> \param nbits number of bits to be stored
329!> \param cache cache to which we want to add
330!> \param container container that contains the compressed elements
331!> \param eps_schwarz ...
332!> \param pmax_entry ...
333!> \param memory_usage ...
334!> \param use_disk_storage ...
335!> \par History
336!> 10.2007 created [Manuel Guidon]
337!> \author Manuel Guidon
338! **************************************************************************************************
339 SUBROUTINE hfx_add_mult_cache_elements(values, nints, nbits, cache, container, eps_schwarz, pmax_entry, memory_usage, &
340 use_disk_storage)
341 REAL(dp) :: values(*)
342 INTEGER, INTENT(IN) :: nints, nbits
343 TYPE(hfx_cache_type) :: cache
344 TYPE(hfx_container_type) :: container
345 REAL(dp), INTENT(IN) :: eps_schwarz, pmax_entry
346 INTEGER :: memory_usage
347 LOGICAL :: use_disk_storage
348
349 INTEGER :: end_idx, i, start_idx, tmp_elements
350 INTEGER(int_8) :: shift, tmp
351 REAL(dp) :: eps_schwarz_inv, factor
352
353 eps_schwarz_inv = 1.0_dp/eps_schwarz
354 factor = eps_schwarz/pmax_entry
355
356 shift = shifts(nbits - 1)
357
358 start_idx = cache%element_counter
359 end_idx = start_idx + nints - 1
360 IF (end_idx < cache_size) THEN
361 DO i = 1, nints
362 values(i) = values(i)*pmax_entry
363 IF (abs(values(i)) > eps_schwarz) THEN
364 tmp = nint(values(i)*eps_schwarz_inv, kind=int_8)
365 cache%data(i + start_idx - 1) = tmp + shift
366 values(i) = tmp*factor
367 ELSE
368 values(i) = 0.0_dp
369 cache%data(i + start_idx - 1) = shift
370 END IF
371 END DO
372 cache%element_counter = end_idx + 1
373 ELSE
374 tmp_elements = cache_size - start_idx + 1
375 DO i = 1, tmp_elements
376 values(i) = values(i)*pmax_entry
377 IF (abs(values(i)) > eps_schwarz) THEN
378 tmp = nint(values(i)*eps_schwarz_inv, kind=int_8)
379 cache%data(i + start_idx - 1) = tmp + shift
380 values(i) = tmp*factor
381 ELSE
382 values(i) = 0.0_dp
383 cache%data(i + start_idx - 1) = shift
384 END IF
385 END DO
386 CALL hfx_compress_cache(cache%data(1), container, nbits, memory_usage, use_disk_storage)
387 DO i = tmp_elements + 1, nints
388 values(i) = values(i)*pmax_entry
389 IF (abs(values(i)) > eps_schwarz) THEN
390 tmp = nint(values(i)*eps_schwarz_inv, kind=int_8)
391 cache%data(i - tmp_elements) = tmp + shift
392 values(i) = tmp*factor
393 ELSE
394 values(i) = 0.0_dp
395 cache%data(i - tmp_elements) = shift
396 END IF
397 END DO
398 cache%element_counter = nints - tmp_elements + 1
399 END IF
400 END SUBROUTINE hfx_add_mult_cache_elements
401
402! **************************************************************************************************
403!> \brief - This routine returns a bunch real values from a cache. If the cache is empty
404!> a decompression routine is invoked and the cache is refilled with decompressed
405!> values from a container
406!> \param values value to be retained from the cache
407!> \param nints number of values to be retained
408!> \param nbits number of bits with which the value has been compressed
409!> \param cache cache from which we get the value
410!> \param container container that contains the compressed elements
411!> \param eps_schwarz threshold for storage
412!> \param pmax_entry multiplication factor for values
413!> \param memory_usage ...
414!> \param use_disk_storage ...
415!> \par History
416!> 10.2007 created [Manuel Guidon]
417!> \author Manuel Guidon
418! **************************************************************************************************
419 SUBROUTINE hfx_get_mult_cache_elements(values, nints, nbits, cache, container, eps_schwarz, pmax_entry, memory_usage, &
420 use_disk_storage)
421 REAL(dp) :: values(*)
422 INTEGER, INTENT(IN) :: nints, nbits
423 TYPE(hfx_cache_type) :: cache
424 TYPE(hfx_container_type) :: container
425 REAL(dp), INTENT(IN) :: eps_schwarz, pmax_entry
426 INTEGER :: memory_usage
427 LOGICAL :: use_disk_storage
428
429 INTEGER :: end_idx, i, start_idx, tmp_elements
430 INTEGER(int_8) :: shift
431 REAL(dp) :: factor
432
433 factor = eps_schwarz/pmax_entry
434
435 shift = shifts(nbits - 1)
436
437 start_idx = cache%element_counter
438 end_idx = start_idx + nints - 1
439
440 IF (end_idx < cache_size) THEN
441 DO i = 1, nints
442 values(i) = factor*real(cache%data(i + start_idx - 1) - shift, dp)
443 END DO
444 cache%element_counter = end_idx + 1
445 ELSE
446 tmp_elements = cache_size - start_idx + 1
447 DO i = 1, tmp_elements
448 values(i) = factor*real(cache%data(i + start_idx - 1) - shift, dp)
449 END DO
450 CALL hfx_decompress_cache(cache%data(1), container, nbits, memory_usage, use_disk_storage)
451 DO i = tmp_elements + 1, nints
452 values(i) = factor*real(cache%data(i - tmp_elements) - shift, dp)
453 END DO
454 cache%element_counter = nints - tmp_elements + 1
455 END IF
456 END SUBROUTINE hfx_get_mult_cache_elements
457
459
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
Contains routines for data compression. PLEASE DO NOT MODIFY.
subroutine, public bits2ints_specific(nbits, ndata, packed_data, full_data)
...
subroutine, public ints2bits_specific(nbits, ndata, packed_data, full_data)
...
routines and types for Hartree-Fock-Exchange
subroutine, public hfx_add_single_cache_element(value, nbits, cache, container, memory_usage, use_disk_storage, max_val_memory)
This routine adds an int_8 value to a cache. If the cache is full a compression routine is invoked an...
subroutine, public hfx_get_mult_cache_elements(values, nints, nbits, cache, container, eps_schwarz, pmax_entry, memory_usage, use_disk_storage)
This routine returns a bunch real values from a cache. If the cache is empty a decompression routine ...
subroutine, public hfx_flush_last_cache(nbits, cache, container, memory_usage, use_disk_storage)
This routine compresses the last probably not yet compressed cache into a container
subroutine, public hfx_get_single_cache_element(value, nbits, cache, container, memory_usage, use_disk_storage)
This routine returns an int_8 value from a cache. If the cache is empty a decompression routine is in...
subroutine, public hfx_decompress_first_cache(nbits, cache, container, memory_usage, use_disk_storage)
This routine decompresses the first bunch of data in a container and copies them into a cache
subroutine, public hfx_add_mult_cache_elements(values, nints, nbits, cache, container, eps_schwarz, pmax_entry, memory_usage, use_disk_storage)
This routine adds an a few real values to a cache. If the cache is full a compression routine is invo...
subroutine, public hfx_reset_cache_and_container(cache, container, memory_usage, do_disk_storage)
This routine resets the containers list pointer to the first element and moves the element counters o...
Types and set/get functions for HFX.
Definition hfx_types.F:15
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34