Octopus
derivatives_test.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22
24 use batch_oct_m
27 use debug_oct_m
29 use global_oct_m
30 use, intrinsic :: iso_fortran_env
33 use loct_oct_m
34 use mesh_oct_m
38 use parser_oct_m
40 use space_oct_m
41 use utils_oct_m
42
43 implicit none
44
45 private
46 public :: &
50
51contains
52
54 subroutine derivatives_advanced_benchmark(this, namespace)
55 type(derivatives_t), intent(in) :: this
56 type(namespace_t), intent(in) :: namespace
57
58 real(real64), allocatable :: ff(:), grad(:,:), resgrad(:, :), lapl(:), reslapl(:)
59 real(real64) :: kvec(3)
60
61 safe_allocate(ff(1:this%mesh%np_part))
62 safe_allocate(grad(1:this%mesh%np, 1:this%mesh%box%dim))
63 safe_allocate(lapl(1:this%mesh%np))
64 safe_allocate(reslapl(1:this%mesh%np))
65 safe_allocate(resgrad(1:this%mesh%np, 1:this%mesh%box%dim))
66
67 ! Testing on some planewaves
68 kvec = [0.5_real64, 0.0_real64, 0.0_real64] ! low frequency
69 call testfunc_plane_wave(this%mesh, ff, grad, lapl, kvec)
70 call test_function("Testing Planewave k=(0.5,0.0,0.0)")
71
72 kvec = [1.0_real64, 1.0_real64, 0.0_real64] ! diagonal
73 call testfunc_plane_wave(this%mesh, ff, grad, lapl, kvec)
74 call test_function("Testing Planewave k=(1.0,1.0,0.0)")
75
76 kvec = [m_pi/this%mesh%spacing(1), 0.0_real64, 0.0_real64] ! Nyquist
77 call testfunc_plane_wave(this%mesh, ff, grad, lapl, kvec)
78 call test_function("Testing Planewave k=(\pi/dr,0.0,0.0)")
79
80 kvec = [m_pi/this%mesh%spacing(1), m_pi/this%mesh%spacing(2), 0.0_real64] ! diagonal Nyquist
81 call testfunc_plane_wave(this%mesh, ff, grad, lapl, kvec)
82 call test_function("Testing Planewave k=(\pi/dr,\pi/dr,0.0)")
83
84 ! Testing on some polynomials
85 call testfunc_polynomial(this%mesh, ff, grad, lapl, p=2)
86 call test_function("Testing degree-2 polynomial")
87
88 call testfunc_polynomial(this%mesh, ff, grad, lapl, p=3)
89 call test_function("Testing degree-3 polynomial")
90
91 call testfunc_polynomial(this%mesh, ff, grad, lapl, p=4)
92 call test_function("Testing degree-4 polynomial")
93
94 call testfunc_polynomial(this%mesh, ff, grad, lapl, p=6)
95 call test_function("Testing degree-6 polynomial")
96
97 call testfunc_polynomial(this%mesh, ff, grad, lapl, p=8)
98 call test_function("Testing degree-8 polynomial")
99
100
101 safe_deallocate_a(ff)
102 safe_deallocate_a(grad)
103 safe_deallocate_a(lapl)
104 safe_deallocate_a(resgrad)
105 safe_deallocate_a(reslapl)
106
107 contains
108 subroutine test_function(label)
109 character(len=*), intent(in) :: label
110
111 message(1) = trim(label)
112
113 call dderivatives_grad(this, ff, resgrad, set_bc=.false.)
114 resgrad = resgrad - grad
115 write(message(2), '(a, es17.10)') 'Gradient err = ', dmf_nrm2(this%mesh, this%mesh%box%dim, resgrad)
116
117 call dderivatives_lapl(this, ff, reslapl, set_bc=.false.)
118 reslapl = reslapl - lapl
119 write(message(3), '(a, es17.10)') 'Laplacian err = ', dmf_nrm2(this%mesh, reslapl)
120
121 call messages_info(3, namespace=namespace)
122 end subroutine test_function
123 end subroutine derivatives_advanced_benchmark
124
126 subroutine testfunc_plane_wave(mesh, ff, grad, lapl, kvec)
127 type(mesh_t), intent(in) :: mesh
128 real(real64), intent(out) :: ff(:), grad(:, :), lapl(:)
129 real(real64), intent(in) :: kvec(3)
130
131 integer :: ip, dim, idir
132 real(real64) :: phase, kdotx, kk
133
134 dim = mesh%box%dim
135
136 kk = dot_product(kvec(1:dim), kvec(1:dim))
137 do ip = 1, mesh%np
138 kdotx = dot_product(kvec(1:dim), mesh%x(1:dim, ip))
139 phase = cos(kdotx)
140
141 ff(ip) = phase
142
143 ! exact gradient
144 do idir = 1, mesh%box%dim
145 grad(ip, idir) = -kvec(idir)*sin(kdotx)
146 end do
147
148 ! exact Laplacian
149 lapl(ip) = -kk * phase
150 end do
151
152 do ip = mesh%np+1, mesh%np_part
153 kdotx = dot_product(kvec(1:dim), mesh%x(1:dim, ip))
154 phase = cos(kdotx)
155
156 ff(ip) = phase
157 end do
158 end subroutine testfunc_plane_wave
159
161 subroutine testfunc_polynomial(mesh, ff, grad, lapl, p)
162 type(mesh_t), intent(in) :: mesh
163 real(real64), intent(out) :: ff(:), grad(:, :), lapl(:)
164 integer, intent(in) :: p
165 integer :: ip, d, dim
166 real(real64) :: x(3), r2
167
168 dim = mesh%box%dim
169
170 do ip = 1, mesh%np
171 x = 0.0_real64
172 x(1:dim) = mesh%x(1:dim, ip)
173
174 ! f = (x^2 + y^2 + z^2)^(p/2)
175 r2 = dot_product(x(1:dim), x(1:dim))
176 ff(ip) = r2**(0.5_real64*p)
177
178 ! gradient: grad(f) = p * r^(p-2) * x
179 if (p >= 2) then
180 do d = 1, dim
181 grad(ip,d) = p * r2**(0.5_real64*p - 1.0_real64) * x(d)
182 end do
183 else
184 grad(ip,:) = 0.0_real64
185 end if
186
187 ! Laplacian: ∇² r^n = n (n + d - 2) r^(n-2)
188 if (p >= 2) then
189 lapl(ip) = p * (p + dim - 2) * r2**(0.5_real64*p - 1.0_real64)
190 else
191 lapl(ip) = 0.0_real64
192 end if
193 end do
194
195 do ip = mesh%np+1, mesh%np_part
196 x = 0.0_real64
197 x(1:dim) = mesh%x(1:dim, ip)
198
199 ! f = (x^2 + y^2 + z^2)^(p/2)
200 r2 = dot_product(x(1:dim), x(1:dim))
201 ff(ip) = r2**(0.5_real64*p)
202 end do
203 end subroutine testfunc_polynomial
204
205
206#include "undef.F90"
207#include "real.F90"
208#include "derivatives_test_inc.F90"
209
210#include "undef.F90"
211#include "complex.F90"
212#include "derivatives_test_inc.F90"
213
214end module derivatives_test_oct_m
215
216!! Local Variables:
217!! mode: f90
218!! coding: utf-8
219!! End:
subroutine test_function(label)
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:124
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public dderivatives_lapl(der, ff, op_ff, ghost_update, set_bc, factor)
apply the Laplacian to a mesh function
This module provides unit tests for the derivatives.
subroutine, public zderivatives_test(this, namespace, repetitions, min_blocksize, max_blocksize)
unit test for derivatives
subroutine testfunc_plane_wave(mesh, ff, grad, lapl, kvec)
Generate a plane-wave given its momentum, as well as the gradient and the Laplacian.
subroutine testfunc_polynomial(mesh, ff, grad, lapl, p)
Generate a polyomial of degree p, as well as the gradient and the Laplacian.
subroutine, public dderivatives_test(this, namespace, repetitions, min_blocksize, max_blocksize)
unit test for derivatives
subroutine, public derivatives_advanced_benchmark(this, namespace)
Further unit tests design to challenge numerical stability of the finite differences.
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:189
System information (time, memory, sysname)
Definition: loct.F90:117
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
Describes mesh distribution to nodes.
Definition: mesh.F90:187