(git:374b731)
Loading...
Searching...
No Matches
rs_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 numerical operations on real-space grid
10!> \par History
11!> 12.2014 created [Hossein Bani-Hashemian]
12!> \author Mohammad Hossein Bani-Hashemian
13! **************************************************************************************************
15
16 USE kinds, ONLY: dp
19 pw_scale,&
23 USE pw_types, ONLY: pw_c1d_gs_type,&
32#include "../base/base_uses.f90"
33
34 IMPLICIT NONE
35 PRIVATE
36 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rs_methods'
37
38 PUBLIC derive_fdm_cd3, &
43
44 REAL(dp), PARAMETER, PRIVATE :: small_value = 1.0e-8_dp
45
46CONTAINS
47
48! **************************************************************************************************
49!> \brief 2nd order finite difference derivative of a function on realspace grid
50!> \param f input function
51!> \param df derivative of f
52!> \param rs_grid real-space grid
53!> \par History:
54!> - Creation (15.11.2013,MK)
55!> - Refactored and moved here from qs_sccs.F (12.2014, Hossein Bani-Hashemian)
56!> \author Matthias Krack (MK)
57!> \version 1.0
58! **************************************************************************************************
59 SUBROUTINE derive_fdm_cd3(f, df, rs_grid)
60
61 TYPE(pw_r3d_rs_type), INTENT(IN) :: f
62 TYPE(pw_r3d_rs_type), DIMENSION(3), INTENT(INOUT) :: df
63 TYPE(realspace_grid_type), INTENT(IN) :: rs_grid
64
65 CHARACTER(LEN=*), PARAMETER :: routinen = 'derive_fdm_cd3'
66
67 INTEGER :: handle, i, j, k
68 INTEGER, DIMENSION(3) :: lb, ub
69 REAL(kind=dp), DIMENSION(3) :: h
70 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: drdx, drdy, drdz, r
71 TYPE(realspace_grid_desc_type), POINTER :: rs_desc
72 TYPE(realspace_grid_type), DIMENSION(3) :: drs_grid
73
74 CALL timeset(routinen, handle)
75
76 ! Setup
77 rs_desc => rs_grid%desc
78 CALL transfer_pw2rs(rs_grid, f)
79 DO i = 1, 3
80 CALL rs_grid_create(drs_grid(i), rs_desc)
81 CALL rs_grid_zero(drs_grid(i))
82 END DO
83
84 lb(1:3) = rs_grid%lb_real(1:3)
85 ub(1:3) = rs_grid%ub_real(1:3)
86 r => rs_grid%r
87 drdx => drs_grid(1)%r
88 drdy => drs_grid(2)%r
89 drdz => drs_grid(3)%r
90
91 ! 3-point stencil central differences
92 h(1:3) = 2.0_dp*f%pw_grid%dr(1:3)
93!$OMP PARALLEL DO DEFAULT(NONE) &
94!$OMP PRIVATE(i,j,k) &
95!$OMP SHARED(drdx,drdy,drdz,h,lb,r,ub)
96 DO k = lb(3), ub(3)
97 DO j = lb(2), ub(2)
98 DO i = lb(1), ub(1)
99 drdx(i, j, k) = (r(i + 1, j, k) - r(i - 1, j, k))/h(1)
100 drdy(i, j, k) = (r(i, j + 1, k) - r(i, j - 1, k))/h(2)
101 drdz(i, j, k) = (r(i, j, k + 1) - r(i, j, k - 1))/h(3)
102 END DO
103 END DO
104 END DO
105!$OMP END PARALLEL DO
106
107 ! Cleanup
108 DO i = 1, 3
109 CALL transfer_rs2pw(drs_grid(i), df(i))
110 CALL rs_grid_release(drs_grid(i))
111 END DO
112
113 CALL timestop(handle)
114
115 END SUBROUTINE derive_fdm_cd3
116
117! **************************************************************************************************
118!> \brief 4th order finite difference derivative of a function on realspace grid
119!> \param f input function
120!> \param df derivative of f
121!> \param rs_grid real-space grid
122!> \par History:
123!> - Creation (15.11.2013,MK)
124!> - Refactored and moved here from qs_sccs.F (12.2014, Hossein Bani-Hashemian)
125!> \author Matthias Krack (MK)
126!> \version 1.0
127! **************************************************************************************************
128 SUBROUTINE derive_fdm_cd5(f, df, rs_grid)
129
130 TYPE(pw_r3d_rs_type), INTENT(IN) :: f
131 TYPE(pw_r3d_rs_type), DIMENSION(3), INTENT(INOUT) :: df
132 TYPE(realspace_grid_type), INTENT(IN) :: rs_grid
133
134 CHARACTER(LEN=*), PARAMETER :: routinen = 'derive_fdm_cd5'
135
136 INTEGER :: handle, i, j, k
137 INTEGER, DIMENSION(3) :: lb, ub
138 REAL(kind=dp), DIMENSION(3) :: h
139 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: drdx, drdy, drdz, r
140 TYPE(realspace_grid_desc_type), POINTER :: rs_desc
141 TYPE(realspace_grid_type), DIMENSION(3) :: drs_grid
142
143 CALL timeset(routinen, handle)
144
145 ! Setup
146 rs_desc => rs_grid%desc
147 CALL transfer_pw2rs(rs_grid, f)
148 DO i = 1, 3
149 CALL rs_grid_create(drs_grid(i), rs_desc)
150 CALL rs_grid_zero(drs_grid(i))
151 END DO
152
153 lb(1:3) = rs_grid%lb_real(1:3)
154 ub(1:3) = rs_grid%ub_real(1:3)
155 r => rs_grid%r
156 drdx => drs_grid(1)%r
157 drdy => drs_grid(2)%r
158 drdz => drs_grid(3)%r
159
160 ! 5-point stencil central differences
161 h(1:3) = 12.0_dp*f%pw_grid%dr(1:3)
162!$OMP PARALLEL DO DEFAULT(NONE) &
163!$OMP PRIVATE(i,j,k) &
164!$OMP SHARED(drdx,drdy,drdz,h,lb,r,ub)
165 DO k = lb(3), ub(3)
166 DO j = lb(2), ub(2)
167 DO i = lb(1), ub(1)
168 drdx(i, j, k) = (r(i - 2, j, k) - r(i + 2, j, k) + 8.0_dp*(r(i + 1, j, k) - r(i - 1, j, k)))/h(1)
169 drdy(i, j, k) = (r(i, j - 2, k) - r(i, j + 2, k) + 8.0_dp*(r(i, j + 1, k) - r(i, j - 1, k)))/h(2)
170 drdz(i, j, k) = (r(i, j, k - 2) - r(i, j, k + 2) + 8.0_dp*(r(i, j, k + 1) - r(i, j, k - 1)))/h(3)
171 END DO
172 END DO
173 END DO
174!$OMP END PARALLEL DO
175
176 ! Cleanup
177 DO i = 1, 3
178 CALL transfer_rs2pw(drs_grid(i), df(i))
179 CALL rs_grid_release(drs_grid(i))
180 END DO
181
182 CALL timestop(handle)
183
184 END SUBROUTINE derive_fdm_cd5
185
186! **************************************************************************************************
187!> \brief 6th order finite difference derivative of a function on realspace grid
188!> \param f input function
189!> \param df derivative of f
190!> \param rs_grid real-space grid
191!> \par History:
192!> - Creation (15.11.2013,MK)
193!> - Refactored and moved here from qs_sccs.F (12.2014, Hossein Bani-Hashemian)
194!> \author Matthias Krack (MK)
195!> \version 1.0
196! **************************************************************************************************
197 SUBROUTINE derive_fdm_cd7(f, df, rs_grid)
198
199 TYPE(pw_r3d_rs_type), INTENT(IN) :: f
200 TYPE(pw_r3d_rs_type), DIMENSION(3), INTENT(INOUT) :: df
201 TYPE(realspace_grid_type), INTENT(IN) :: rs_grid
202
203 CHARACTER(LEN=*), PARAMETER :: routinen = 'derive_fdm_cd7'
204
205 INTEGER :: handle, i, j, k
206 INTEGER, DIMENSION(3) :: lb, ub
207 REAL(kind=dp), DIMENSION(3) :: h
208 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: drdx, drdy, drdz, r
209 TYPE(realspace_grid_desc_type), POINTER :: rs_desc
210 TYPE(realspace_grid_type), DIMENSION(3) :: drs_grid
211
212 CALL timeset(routinen, handle)
213
214 ! Setup
215 rs_desc => rs_grid%desc
216 CALL transfer_pw2rs(rs_grid, f)
217 DO i = 1, 3
218 CALL rs_grid_create(drs_grid(i), rs_desc)
219 CALL rs_grid_zero(drs_grid(i))
220 END DO
221
222 lb(1:3) = rs_grid%lb_real(1:3)
223 ub(1:3) = rs_grid%ub_real(1:3)
224 r => rs_grid%r
225 drdx => drs_grid(1)%r
226 drdy => drs_grid(2)%r
227 drdz => drs_grid(3)%r
228
229 ! 7-point stencil central differences
230 h(1:3) = 60.0_dp*f%pw_grid%dr(1:3)
231!$OMP PARALLEL DO DEFAULT(NONE) &
232!$OMP PRIVATE(i,j,k) &
233!$OMP SHARED(drdx,drdy,drdz,h,lb,r,ub)
234 DO k = lb(3), ub(3)
235 DO j = lb(2), ub(2)
236 DO i = lb(1), ub(1)
237 drdx(i, j, k) = (r(i + 3, j, k) - r(i - 3, j, k) + 9.0_dp*(r(i - 2, j, k) - r(i + 2, j, k)) + &
238 45.0_dp*(r(i + 1, j, k) - r(i - 1, j, k)))/h(1)
239 drdy(i, j, k) = (r(i, j + 3, k) - r(i, j - 3, k) + 9.0_dp*(r(i, j - 2, k) - r(i, j + 2, k)) + &
240 45.0_dp*(r(i, j + 1, k) - r(i, j - 1, k)))/h(2)
241 drdz(i, j, k) = (r(i, j, k + 3) - r(i, j, k - 3) + 9.0_dp*(r(i, j, k - 2) - r(i, j, k + 2)) + &
242 45.0_dp*(r(i, j, k + 1) - r(i, j, k - 1)))/h(3)
243 END DO
244 END DO
245 END DO
246!$OMP END PARALLEL DO
247
248 ! Cleanup
249 DO i = 1, 3
250 CALL transfer_rs2pw(drs_grid(i), df(i))
251 CALL rs_grid_release(drs_grid(i))
252 END DO
253
254 CALL timestop(handle)
255
256 END SUBROUTINE derive_fdm_cd7
257
258! **************************************************************************************************
259!> \brief returns the global axes and the portion of the axes that are local to
260!> the current mpi rank
261!> \param pw_grid plane wave grid
262!> \param x_glbl x grid vector of the simulation box
263!> \param y_glbl y grid vector of the simulation box
264!> \param z_glbl z grid vector of the simulation box
265!> \param x_locl x grid vector of the simulation box local to this process
266!> \param y_locl y grid vector of the simulation box local to this process
267!> \param z_locl z grid vector of the simulation box local to this process
268!> \par History
269!> 07.2014 created [Hossein Bani-Hashemian]
270!> 07.2015 moved here from dirichlet_bc_utils.F [Hossein Bani-Hashemian]
271!> \author Mohammad Hossein Bani-Hashemian
272! **************************************************************************************************
273 SUBROUTINE setup_grid_axes(pw_grid, x_glbl, y_glbl, z_glbl, x_locl, y_locl, z_locl)
274
275 TYPE(pw_grid_type), INTENT(IN) :: pw_grid
276 REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: x_glbl, y_glbl, z_glbl, x_locl, y_locl, &
277 z_locl
278
279 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_grid_axes'
280
281 INTEGER :: glb1, glb2, glb3, gub1, gub2, gub3, &
282 handle, i, lb1, lb2, lb3, ub1, ub2, ub3
283 INTEGER, ALLOCATABLE, DIMENSION(:) :: gindx, gindy, gindz, lindx, lindy, lindz
284 INTEGER, DIMENSION(2, 3) :: bounds, bounds_local
285 INTEGER, DIMENSION(3) :: npts, npts_local
286 REAL(dp), DIMENSION(3) :: dr
287
288 CALL timeset(routinen, handle)
289
290 dr = pw_grid%dr
291 bounds = pw_grid%bounds
292 bounds_local = pw_grid%bounds_local
293 npts = pw_grid%npts
294 npts_local = pw_grid%npts_local
295
296! local and global lower and upper bounds
297 glb1 = bounds(1, 1); gub1 = bounds(2, 1)
298 glb2 = bounds(1, 2); gub2 = bounds(2, 2)
299 glb3 = bounds(1, 3); gub3 = bounds(2, 3)
300 lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
301 lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
302 lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
303
304 ALLOCATE (lindx(lb1:ub1), lindy(lb2:ub2), lindz(lb3:ub3))
305 ALLOCATE (gindx(glb1:gub1), gindy(glb2:gub2), gindz(glb3:gub3))
306 ALLOCATE (x_locl(lb1:ub1), y_locl(lb2:ub2), z_locl(lb3:ub3))
307 ALLOCATE (x_glbl(glb1:gub1), y_glbl(glb2:gub2), z_glbl(glb3:gub3))
308
309 gindx(:) = (/(i, i=0, npts(1) - 1)/)
310 gindy(:) = (/(i, i=0, npts(2) - 1)/)
311 gindz(:) = (/(i, i=0, npts(3) - 1)/)
312 lindx(:) = (/(i, i=0, npts_local(1) - 1)/)
313 lindy(:) = (/(i, i=0, npts_local(2) - 1)/)
314 lindz(:) = (/(i, i=0, npts_local(3) - 1)/)
315
316 x_glbl(:) = gindx*dr(1)
317 y_glbl(:) = gindy*dr(2)
318 z_glbl(:) = gindz*dr(3)
319
320! map [0 .. (npts_local-1)] --> [lb .. ub]
321 IF (lb1 .EQ. ub1) THEN
322 lindx(:) = lb1
323 ELSE
324 lindx(:) = lindx(:)*((ub1 - lb1)/(npts_local(1) - 1)) + lb1
325 END IF
326 IF (lb2 .EQ. ub2) THEN
327 lindy(:) = lb2
328 ELSE
329 lindy(:) = lindy(:)*((ub2 - lb2)/(npts_local(2) - 1)) + lb2
330 END IF
331 IF (lb3 .EQ. ub3) THEN
332 lindz(:) = lb3
333 ELSE
334 lindz(:) = lindz(:)*((ub3 - lb3)/(npts_local(3) - 1)) + lb3
335 END IF
336
337 x_locl(:) = x_glbl(lindx)
338 y_locl(:) = y_glbl(lindy)
339 z_locl(:) = z_glbl(lindz)
340
341 CALL timestop(handle)
342
343 END SUBROUTINE setup_grid_axes
344
345! **************************************************************************************************
346!> \brief convolutes a function with a smoothing kernel K_\zeta
347!> v * K_\zeta
348!> K_\zeta is the standard mollifier defined as:
349!> K_\zeta(x) = \frac{1}{\zeta^3} K(\frac{x}{\zeta})
350!> where
351!> K(x) = \kappa \exp (\frac{1}{|x|^2 - 1}), if |x| <= 1
352!> = 0, otherwise
353!> \param pw_pool pool of pw grid
354!> \param zeta parameter \zeta defining the width of the mollifier
355!> \param x_glbl x grid vector of the simulation box
356!> \param y_glbl y grid vector of the simulation box
357!> \param z_glbl z grid vector of the simulation box
358!> \param pw_in the input function
359!> \param pw_out the convoluted function
360!> \par History
361!> 10.2014 created [Hossein Bani-Hashemian]
362!> 07.2015 moved here from ps_implicit_methods.F [Hossein Bani-Hashemian]
363!> \author Mohammad Hossein Bani-Hashemian
364! **************************************************************************************************
365 SUBROUTINE pw_mollifier(pw_pool, zeta, x_glbl, y_glbl, z_glbl, pw_in, pw_out)
366
367 TYPE(pw_pool_type), INTENT(IN), POINTER :: pw_pool
368 REAL(dp), INTENT(IN) :: zeta
369 REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(IN) :: x_glbl, y_glbl, z_glbl
370 TYPE(pw_r3d_rs_type), INTENT(IN) :: pw_in
371 TYPE(pw_r3d_rs_type), INTENT(INOUT) :: pw_out
372
373 CHARACTER(LEN=*), PARAMETER :: routinen = 'pw_mollifier'
374
375 INTEGER :: handle, i, j, k, lb1, lb2, lb3, ub1, &
376 ub2, ub3
377 INTEGER, DIMENSION(2, 3) :: bounds, bounds_local
378 REAL(dp) :: normfact, xi, xmax, xmin, yj, ymax, &
379 ymin, zk, zmax, zmin
380 REAL(dp), DIMENSION(3, 3) :: dh
381 TYPE(pw_c1d_gs_type) :: g_gs, pw_in_gs, pw_out_gs
382 TYPE(pw_grid_type), POINTER :: pw_grid
383 TYPE(pw_r3d_rs_type) :: g
384
385 CALL timeset(routinen, handle)
386
387 pw_grid => pw_in%pw_grid
388 dh = pw_grid%dh
389 bounds_local = pw_grid%bounds_local
390 bounds = pw_grid%bounds
391
392 lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
393 lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
394 lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
395
396 CALL pw_pool%create_pw(g)
397 CALL pw_pool%create_pw(g_gs)
398 CALL pw_pool%create_pw(pw_in_gs)
399 CALL pw_pool%create_pw(pw_out_gs)
400
401 CALL pw_zero(g)
402 xmin = x_glbl(bounds(1, 1)); xmax = x_glbl(bounds(2, 1))
403 ymin = y_glbl(bounds(1, 2)); ymax = y_glbl(bounds(2, 2))
404 zmin = z_glbl(bounds(1, 3)); zmax = z_glbl(bounds(2, 3))
405
406 DO k = lb3, ub3
407 DO j = lb2, ub2
408 DO i = lb1, ub1
409 xi = x_glbl(i); yj = y_glbl(j); zk = z_glbl(k)
410 IF (norm2((/(xi - xmin), (yj - ymin), (zk - zmin)/)) .LT. zeta - small_value) THEN
411 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmin), (yj - ymin), (zk - zmin)/)/zeta)**2 - 1))
412 ELSE IF (norm2((/(xi - xmax), (yj - ymax), (zk - zmax)/)) .LT. zeta - small_value) THEN
413 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmax), (yj - ymax), (zk - zmax)/)/zeta)**2 - 1))
414 ELSE IF (norm2((/(xi - xmin), (yj - ymax), (zk - zmax)/)) .LT. zeta - small_value) THEN
415 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmin), (yj - ymax), (zk - zmax)/)/zeta)**2 - 1))
416 ELSE IF (norm2((/(xi - xmax), (yj - ymin), (zk - zmax)/)) .LT. zeta - small_value) THEN
417 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmax), (yj - ymin), (zk - zmax)/)/zeta)**2 - 1))
418 ELSE IF (norm2((/(xi - xmax), (yj - ymax), (zk - zmin)/)) .LT. zeta - small_value) THEN
419 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmax), (yj - ymax), (zk - zmin)/)/zeta)**2 - 1))
420 ELSE IF (norm2((/(xi - xmin), (yj - ymin), (zk - zmax)/)) .LT. zeta - small_value) THEN
421 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmin), (yj - ymin), (zk - zmax)/)/zeta)**2 - 1))
422 ELSE IF (norm2((/(xi - xmin), (yj - ymax), (zk - zmin)/)) .LT. zeta - small_value) THEN
423 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmin), (yj - ymax), (zk - zmin)/)/zeta)**2 - 1))
424 ELSE IF (norm2((/(xi - xmax), (yj - ymin), (zk - zmin)/)) .LT. zeta - small_value) THEN
425 g%array(i, j, k) = exp(1.0_dp/(norm2((/(xi - xmax), (yj - ymin), (zk - zmin)/)/zeta)**2 - 1))
426 END IF
427 END DO
428 END DO
429 END DO
430 CALL pw_scale(g, (1.0_dp/zeta)**3)
431 normfact = pw_integrate_function(g)
432 CALL pw_scale(g, 1.0_dp/normfact)
433
434 CALL pw_transfer(g, g_gs)
435 CALL pw_transfer(pw_in, pw_in_gs)
436 pw_out_gs%array = g_gs%array*pw_in_gs%array
437 CALL pw_transfer(pw_out_gs, pw_out)
438
439 ! multiply by the reciprocal of the forward Fourier transform normalization prefactor (here 1/N, by convention)
440 CALL pw_scale(pw_out, real(pw_grid%ngpts, kind=dp))
441 ! from discrete convolution to continuous convolution
442 CALL pw_scale(pw_out, pw_grid%dvol)
443
444 DO k = lb3, ub3
445 DO j = lb2, ub2
446 DO i = lb1, ub1
447 IF (abs(pw_out%array(i, j, k)) .LE. 1.0e-10_dp) pw_out%array(i, j, k) = 0.0_dp
448 END DO
449 END DO
450 END DO
451
452 CALL pw_pool%give_back_pw(g)
453 CALL pw_pool%give_back_pw(g_gs)
454 CALL pw_pool%give_back_pw(pw_in_gs)
455 CALL pw_pool%give_back_pw(pw_out_gs)
456 CALL timestop(handle)
457
458 END SUBROUTINE pw_mollifier
459
460END MODULE rs_methods
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
subroutine, public rs_grid_create(rs, desc)
...
subroutine, public transfer_pw2rs(rs, pw)
...
subroutine, public transfer_rs2pw(rs, pw)
...
subroutine, public rs_grid_release(rs_grid)
releases the given rs grid (see doc/ReferenceCounting.html)
subroutine, public rs_grid_zero(rs)
Initialize grid to zero.
numerical operations on real-space grid
Definition rs_methods.F:14
subroutine, public setup_grid_axes(pw_grid, x_glbl, y_glbl, z_glbl, x_locl, y_locl, z_locl)
returns the global axes and the portion of the axes that are local to the current mpi rank
Definition rs_methods.F:274
subroutine, public derive_fdm_cd7(f, df, rs_grid)
6th order finite difference derivative of a function on realspace grid
Definition rs_methods.F:198
subroutine, public pw_mollifier(pw_pool, zeta, x_glbl, y_glbl, z_glbl, pw_in, pw_out)
convolutes a function with a smoothing kernel K_\zeta v * K_\zeta K_\zeta is the standard mollifier d...
Definition rs_methods.F:366
subroutine, public derive_fdm_cd5(f, df, rs_grid)
4th order finite difference derivative of a function on realspace grid
Definition rs_methods.F:129
subroutine, public derive_fdm_cd3(f, df, rs_grid)
2nd order finite difference derivative of a function on realspace grid
Definition rs_methods.F:60
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...