Octopus
mesh_function.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
24 use blas_oct_m
25 use comm_oct_m
26 use debug_oct_m
27 use global_oct_m
28 use, intrinsic :: iso_fortran_env
31 use mesh_oct_m
33 use mpi_oct_m
36 use qshep_oct_m
39
40 implicit none
41
42 private
43 public :: &
46 dmf_dotp, &
47 zmf_dotp, &
48 dmf_nrm2, &
49 zmf_nrm2, &
50 dmf_moment, &
51 zmf_moment, &
52 dmf_random, &
53 zmf_random, &
62 dmf_dipole, &
63 zmf_dipole, &
72
73 ! These variables are to be used by the "distdot" function, that is outside the module
74 ! but inside this file.
75 ! FIXME: This is very ugly, at least these values should be set by a function.
76 public :: mesh_aux
77 logical, public :: sp_parallel
78 integer, public :: sp_np, sp_dim, sp_st1, sp_st2, sp_kp1, sp_kp2
79 integer, public :: sp_distdot_mode
80 type(mpi_grp_t), public :: sp_grp
81
82 interface mf_surface_integral
85 end interface mf_surface_integral
86
87 interface mf_line_integral
90 end interface mf_line_integral
91
92 interface dmf_dotp
93 module procedure dmf_dotp_1, dmf_dotp_2
94 end interface dmf_dotp
95
96 interface zmf_dotp
97 module procedure zmf_dotp_1, zmf_dotp_2
98 end interface zmf_dotp
99
100 interface dmf_nrm2
101 module procedure dmf_nrm2_1, dmf_nrm2_2
102 end interface dmf_nrm2
103
104 interface zmf_nrm2
105 module procedure zmf_nrm2_1, zmf_nrm2_2
106 end interface zmf_nrm2
107
109 class(mesh_t), pointer :: mesh_aux => null()
110
111contains
112
116 subroutine mesh_init_mesh_aux(mesh)
117 class(mesh_t), target, intent(in) :: mesh
118
119 push_sub(mesh_init_mesh_aux)
120 mesh_aux => mesh
121
122 pop_sub(mesh_init_mesh_aux)
123 end subroutine mesh_init_mesh_aux
124
132 subroutine zmf_fix_phase(mesh, ff)
133 class(mesh_t), intent(in) :: mesh
134 complex(real64), intent(inout) :: ff(:)
135
136 real(real64), allocatable :: ff_re(:), ff_im(:)
137 real(real64) :: dot_re, dot_im, dot_reim, sol1, sol2, maxv, maxvloc
138 real(real64) :: theta, ctheta, stheta
139 integer :: ip, ipmax
140 complex(real64) :: zval
141
142 push_sub(zmf_fix_phase)
143
144 safe_allocate(ff_re(1:mesh%np))
145 safe_allocate(ff_im(1:mesh%np))
146
147 ff_re = real(ff, real64)
148 ff_im = aimag(ff)
149
150 dot_re = dmf_nrm2(mesh, ff_re)**2
151 dot_im = dmf_nrm2(mesh, ff_im)**2
152 dot_reim = dmf_dotp(mesh, ff_re, ff_im)
153
154 ! We have tan(2\theta) = 2 (\int \psi_R \psi_I)/( \int \psi_R^2-\psi_I^2)
155 if(dot_re+dot_im > 1e-8_real64) then
156 if(m_two*dot_reim/(dot_re-dot_im) > 1e-8_real64) then
157 theta = m_half * atan(m_two*dot_reim/(dot_re-dot_im))
158
159 ! Get the maximum for the real part
160 sol1 = cos(theta)**2 * dot_re + sin(theta)**2 * dot_im + m_two*sin(theta)*cos(theta)*dot_reim
161 sol2 = sin(theta)**2 * dot_re + cos(theta)**2 * dot_re - m_two*sin(theta)*cos(theta)*dot_reim
162 if(sol2>sol1) theta = theta + m_half*m_pi
163
164 ctheta = cos(theta)
165 stheta = sin(theta)
166
167 !We do the rotation
168 !$omp parallel do
169 do ip = 1, mesh%np
170 ff(ip) = cmplx(ctheta*ff_re(ip)-stheta*ff_im(ip), stheta*ff_re(ip)+ctheta*ff_im(ip), real64)
171 end do
173 else ! We do not know what is the direction here
174 ! we set it using the maximum value of the function from rank 0
175 ipmax = 0
176 maxv = m_zero
177 do ip = 1, mesh%np
178 maxvloc = real(ff(ip)*conjg(ff(ip)), real64)
179 if(maxvloc > maxv) then
180 ipmax = ip
181 maxv = maxvloc
182 end if
183 end do
184 zval = ff(ipmax)
186 !We want to use the same phase on all processors
187 if(mesh%parallel_in_domains) then
188 call mesh%mpi_grp%bcast(zval, 1, mpi_double_complex, 0)
189 end if
190
191 call lalg_scal(mesh%np, abs(zval)/zval, ff)
192
193 end if
194 else
195 message(1) = "Internal error fixing phase: mesh function has zero norm."
196 call messages_fatal(1)
197 end if
198
199 safe_deallocate_a(ff_re)
200 safe_deallocate_a(ff_im)
201
203 end subroutine zmf_fix_phase
204
205#include "undef.F90"
206#include "real.F90"
207#include "mesh_function_inc.F90"
208
209#include "undef.F90"
210#include "complex.F90"
211#include "mesh_function_inc.F90"
212
213end module mesh_function_oct_m
214
215#ifdef HAVE_SPARSKIT
216
220real(real64) function distdot(n, x, ix, y, iy)
221 use comm_oct_m
222 use global_oct_m
223 use, intrinsic :: iso_fortran_env
227
228 implicit none
229
230 integer, intent(in) :: n
231 real(real64), intent(in) :: x(n)
232 integer, intent(in) :: ix
233 real(real64), intent(in) :: y(n)
234 integer, intent(in) :: iy
235
236 integer :: j, ik, ist, idim, k
237
238 ! SPARSKIT only calls this function with ix, iy = 1 i.e. no stride.
239 assert(ix == 1)
240 assert(iy == 1)
241
242 select case (sp_distdot_mode)
243 case (1)
244 distdot = dmf_dotp_aux(x(1:n/2), y(1:n/2)) + dmf_dotp_aux(x(n/2+1:n), y(n/2+1:n))
245
246 case (2)
248 j = 1
249 k = n/2+1
250 do ik = sp_kp1, sp_kp2
251 do ist = sp_st1, sp_st2
252 do idim = 1, sp_dim
253 distdot = distdot + dmf_dotp_aux(x(j: j+sp_np-1), y(j:j+sp_np-1))
254 distdot = distdot + dmf_dotp_aux(x(k: k+sp_np-1), y(k:k+sp_np-1))
255 j = j + sp_np
256 k = k + sp_np
257 end do
258 end do
259 end do
261
262 case (3)
264 j = 1
265 k = n/2+1
266 do ik = sp_kp1, sp_kp2
267 do ist = sp_st1, sp_st2
268 do idim = 1, sp_dim
269 distdot = distdot + dmf_dotp_aux(x(j: j+sp_np-1), y(j:j+sp_np-1))
270 distdot = distdot + dmf_dotp_aux(x(k: k+sp_np-1), y(k:k+sp_np-1))
271 j = j + sp_np
272 k = k + sp_np
273 end do
274 end do
275 end do
276 do ik = sp_kp1, sp_kp2
277 do ist = sp_st1, sp_st2
278 do idim = 1, sp_dim
279 distdot = distdot + dmf_dotp_aux(x(j: j+sp_np-1), y(j:j+sp_np-1))
280 distdot = distdot + dmf_dotp_aux(x(k: k+sp_np-1), y(k:k+sp_np-1))
281 j = j + sp_np
282 k = k + sp_np
283 end do
284 end do
285 end do
287
288 end select
289
290end function distdot
291
292#endif /* HAVE_SPARSKIT */
293
294!! Local Variables:
295!! mode: f90
296!! coding: utf-8
297!! End:
scales a vector by a constant
Definition: lalg_basic.F90:156
double sin(double __x) __attribute__((__nothrow__
double atan(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
real(real64) function distdot(n, x, ix, y, iy)
This function will be linked by SPARSKIT to perform dot products. It expects complex numbers as an ar...
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:118
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
real(real64), parameter, public m_half
Definition: global.F90:193
This module defines various routines, operating on mesh functions.
integer, public sp_st2
subroutine, public zmf_random(mesh, ff, pre_shift, post_shift, seed, normalized)
This subroutine fills a function with random values.
real(real64) function zmf_nrm2_2(mesh, dim, ff, reduce)
this function returns the norm of a vector of mesh functions
subroutine, public dmf_random(mesh, ff, pre_shift, post_shift, seed, normalized)
This subroutine fills a function with random values.
subroutine, public zmf_interpolate_points(ndim, npoints_in, x_in, f_in, npoints_out, x_out, f_out)
This function receives a function f_in defined in a mesh, and returns the interpolated values of the ...
complex(real64) function, public zmf_moment(mesh, ff, idir, order)
This function calculates the "order" moment of the function ff.
real(real64) function, public dmf_dotu_aux(f1, f2)
dot product between two vectors (mesh functions) without conjugation
real(real64) function dmf_line_integral_vector(mesh, ff, line)
This subroutine calculates the line integral of a vector function on a given line.
subroutine, public zmf_normalize(mesh, dim, psi, norm)
Normalize a mesh function psi.
complex(real64) function zmf_line_integral_vector(mesh, ff, line)
This subroutine calculates the line integral of a vector function on a given line.
complex(real64) function zmf_dotp_2(mesh, dim, f1, f2, reduce, dotu, np)
dot product for vector valued mesh functions
class(mesh_t), pointer, public mesh_aux
Globally-scoped pointer to the mesh instance.
complex(real64) function, public zmf_dotu_aux(f1, f2)
dot product between two vectors (mesh functions) without conjugation
logical, public sp_parallel
integer, public sp_distdot_mode
real(real64) function dmf_nrm2_2(mesh, dim, ff, reduce)
this function returns the norm of a vector of mesh functions
real(real64) function dmf_surface_integral_scalar(mesh, ff, plane)
This subroutine calculates the surface integral of a scalar function on a given plane.
integer, public sp_dim
complex(real64) function zmf_line_integral_scalar(mesh, ff, line)
This subroutine calculates the line integral of a scalar function on a given line.
subroutine, public dmf_interpolate_points(ndim, npoints_in, x_in, f_in, npoints_out, x_out, f_out)
This function receives a function f_in defined in a mesh, and returns the interpolated values of the ...
real(real64) function dmf_dotp_2(mesh, dim, f1, f2, reduce, dotu, np)
dot product for vector valued mesh functions
integer, public sp_kp2
real(real64) function, public dmf_dotp_aux(f1, f2)
dot product between two vectors (mesh functions)
real(real64) function zmf_nrm2_1(mesh, ff, reduce)
this function returns the norm of a mesh function
real(real64) function dmf_line_integral_scalar(mesh, ff, line)
This subroutine calculates the line integral of a scalar function on a given line.
real(real64) function, public zmf_nrm2_aux(ff)
calculate norm2 of a vector (mesh function)
complex(real64) function, public zmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
subroutine, public dmf_multipoles(mesh, ff, lmax, multipole, mask)
This routine calculates the multipoles of a function ff.
subroutine, public zmf_multipoles(mesh, ff, lmax, multipole, mask)
This routine calculates the multipoles of a function ff.
complex(real64) function zmf_surface_integral_scalar(mesh, ff, plane)
This subroutine calculates the surface integral of a scalar function on a given plane.
integer, public sp_kp1
subroutine, public dmf_normalize(mesh, dim, psi, norm)
Normalize a mesh function psi.
type(mpi_grp_t), public sp_grp
real(real64) function dmf_dotp_1(mesh, f1, f2, reduce, dotu, np)
this function returns the dot product between two mesh functions
real(real64) function dmf_surface_integral_vector(mesh, ff, plane)
This subroutine calculates the surface integral of a vector function on a given plane.
subroutine, public zmf_fix_phase(mesh, ff)
Fix the phase of complex function.
integer, public sp_st1
real(real64) function dmf_nrm2_1(mesh, ff, reduce)
this function returns the norm of a mesh function
complex(real64) function zmf_surface_integral_vector(mesh, ff, plane)
This subroutine calculates the surface integral of a vector function on a given plane.
subroutine, public dmf_dipole(mesh, ff, dipole, mask)
This routine calculates the dipole of a function ff, for arbitrary dimensions.
subroutine, public mesh_init_mesh_aux(mesh)
Initialise a pointer to the grid/mesh, that is globally exposed, such that low level mesh operations ...
real(real64) function, public dmf_moment(mesh, ff, idir, order)
This function calculates the "order" moment of the function ff.
real(real64) function, public dmf_nrm2_aux(ff)
calculate norm2 of a vector (mesh function)
integer, public sp_np
subroutine, public zmf_dipole(mesh, ff, dipole, mask)
This routine calculates the dipole of a function ff, for arbitrary dimensions.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
complex(real64) function zmf_dotp_1(mesh, f1, f2, reduce, dotu, np)
this function returns the dot product between two mesh functions
complex(real64) function, public zmf_dotp_aux(f1, f2)
dot product between two vectors (mesh functions)
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
Some general things and nomenclature:
Definition: par_vec.F90:171