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 :: &
48 dmf_dotp, &
49 zmf_dotp, &
50 dmf_nrm2, &
51 zmf_nrm2, &
52 dmf_moment, &
53 zmf_moment, &
54 dmf_random, &
55 zmf_random, &
64 dmf_dipole, &
65 zmf_dipole, &
76
77 ! These variables are to be used by the "distdot" function, that is outside the module
78 ! but inside this file.
79 ! FIXME: This is very ugly, at least these values should be set by a function.
80 public :: mesh_aux
81 logical, public :: sp_parallel
82 integer, public :: sp_np, sp_dim, sp_st1, sp_st2, sp_kp1, sp_kp2
83 integer, public :: sp_distdot_mode
84 type(mpi_grp_t), public :: sp_grp
85
86 interface mf_surface_integral
89 end interface mf_surface_integral
90
91 interface mf_line_integral
94 end interface mf_line_integral
95
96 interface dmf_dotp
97 module procedure dmf_dotp_1, dmf_dotp_2
98 end interface dmf_dotp
99
100 interface zmf_dotp
101 module procedure zmf_dotp_1, zmf_dotp_2
102 end interface zmf_dotp
103
104 interface dmf_nrm2
105 module procedure dmf_nrm2_1, dmf_nrm2_2
106 end interface dmf_nrm2
107
108 interface zmf_nrm2
109 module procedure zmf_nrm2_1, zmf_nrm2_2
110 end interface zmf_nrm2
111
112 interface dmf_integrate
113 module procedure dmf_integrate_1, dmf_integrate_2
114 end interface dmf_integrate
115
116 interface zmf_integrate
117 module procedure zmf_integrate_1, zmf_integrate_2
118 end interface zmf_integrate
119
120
122 class(mesh_t), pointer :: mesh_aux => null()
123
124contains
125
129 subroutine mesh_init_mesh_aux(mesh)
130 class(mesh_t), target, intent(in) :: mesh
131
132 push_sub(mesh_init_mesh_aux)
133 mesh_aux => mesh
134
135 pop_sub(mesh_init_mesh_aux)
136 end subroutine mesh_init_mesh_aux
137
145 subroutine zmf_fix_phase(mesh, ff)
146 class(mesh_t), intent(in) :: mesh
147 complex(real64), intent(inout) :: ff(:)
148
149 real(real64), allocatable :: ff_re(:), ff_im(:)
150 real(real64) :: dot_re, dot_im, dot_reim, sol1, sol2, maxv, maxvloc
151 real(real64) :: theta, ctheta, stheta
152 integer :: ip, ipmax
153 complex(real64) :: zval
154
155 push_sub(zmf_fix_phase)
156
157 safe_allocate(ff_re(1:mesh%np))
158 safe_allocate(ff_im(1:mesh%np))
159
160 ff_re(:) = real(ff(:), real64)
161 ff_im(:) = aimag(ff(:))
162
163 dot_re = dmf_nrm2(mesh, ff_re)**2
164 dot_im = dmf_nrm2(mesh, ff_im)**2
165 dot_reim = dmf_dotp(mesh, ff_re, ff_im)
166
167 ! We have tan(2\theta) = 2 (\int \psi_R \psi_I)/( \int \psi_R^2-\psi_I^2)
168 if(dot_re+dot_im > 1e-8_real64) then
169 if(m_two*dot_reim/(dot_re-dot_im) > 1e-8_real64) then
170 theta = m_half * atan(m_two*dot_reim/(dot_re-dot_im))
171
172 ! Get the maximum for the real part
173 sol1 = cos(theta)**2 * dot_re + sin(theta)**2 * dot_im + m_two*sin(theta)*cos(theta)*dot_reim
174 sol2 = sin(theta)**2 * dot_re + cos(theta)**2 * dot_re - m_two*sin(theta)*cos(theta)*dot_reim
175 if(sol2>sol1) theta = theta + m_half*m_pi
177 ctheta = cos(theta)
178 stheta = sin(theta)
180 !We do the rotation
181 !$omp parallel do
182 do ip = 1, mesh%np
183 ff(ip) = cmplx(ctheta*ff_re(ip)-stheta*ff_im(ip), stheta*ff_re(ip)+ctheta*ff_im(ip), real64)
184 end do
185
186 else ! We do not know what is the direction here
187 ! we set it using the maximum value of the function from rank 0
188 ipmax = 0
189 maxv = m_zero
190 do ip = 1, mesh%np
191 maxvloc = real(ff(ip)*conjg(ff(ip)), real64)
192 if(maxvloc > maxv) then
193 ipmax = ip
194 maxv = maxvloc
195 end if
196 end do
197 zval = ff(ipmax)
198
199 !We want to use the same phase on all processors
200 if(mesh%parallel_in_domains) then
201 call mesh%mpi_grp%bcast(zval, 1, mpi_double_complex, 0)
202 end if
204 call lalg_scal(mesh%np, abs(zval)/zval, ff)
205
206 end if
207 else
208 message(1) = "Internal error fixing phase: mesh function has zero norm."
209 call messages_fatal(1)
210 end if
212 safe_deallocate_a(ff_re)
213 safe_deallocate_a(ff_im)
214
215 pop_sub(zmf_fix_phase)
216 end subroutine zmf_fix_phase
218#include "undef.F90"
219#include "real.F90"
220#include "mesh_function_inc.F90"
221
222#include "undef.F90"
223#include "complex.F90"
224#include "mesh_function_inc.F90"
225
226end module mesh_function_oct_m
227
228#ifdef HAVE_SPARSKIT
229
233real(real64) function distdot(n, x, ix, y, iy)
234 use comm_oct_m
235 use global_oct_m
236 use, intrinsic :: iso_fortran_env
241 implicit none
242
243 integer, intent(in) :: n
244 real(real64), intent(in) :: x(n)
245 integer, intent(in) :: ix
246 real(real64), intent(in) :: y(n)
247 integer, intent(in) :: iy
248
249 integer :: j, ik, ist, idim, k
250
251 ! SPARSKIT only calls this function with ix, iy = 1 i.e. no stride.
252 assert(ix == 1)
253 assert(iy == 1)
254
255 select case (sp_distdot_mode)
256 case (1)
257 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))
258
259 case (2)
260 distdot = m_zero
261 j = 1
262 k = n/2+1
263 do ik = sp_kp1, sp_kp2
264 do ist = sp_st1, sp_st2
265 do idim = 1, sp_dim
266 distdot = distdot + dmf_dotp_aux(x(j: j+sp_np-1), y(j:j+sp_np-1))
267 distdot = distdot + dmf_dotp_aux(x(k: k+sp_np-1), y(k:k+sp_np-1))
268 j = j + sp_np
269 k = k + sp_np
270 end do
271 end do
272 end do
273 if (sp_parallel) call comm_allreduce(sp_grp, distdot)
274
275 case (3)
276 distdot = m_zero
277 j = 1
278 k = n/2+1
279 do ik = sp_kp1, sp_kp2
280 do ist = sp_st1, sp_st2
281 do idim = 1, sp_dim
282 distdot = distdot + dmf_dotp_aux(x(j: j+sp_np-1), y(j:j+sp_np-1))
283 distdot = distdot + dmf_dotp_aux(x(k: k+sp_np-1), y(k:k+sp_np-1))
284 j = j + sp_np
285 k = k + sp_np
286 end do
287 end do
288 end do
289 do ik = sp_kp1, sp_kp2
290 do ist = sp_st1, sp_st2
291 do idim = 1, sp_dim
292 distdot = distdot + dmf_dotp_aux(x(j: j+sp_np-1), y(j:j+sp_np-1))
293 distdot = distdot + dmf_dotp_aux(x(k: k+sp_np-1), y(k:k+sp_np-1))
294 j = j + sp_np
295 k = k + sp_np
296 end do
297 end do
298 end do
299 if (sp_parallel) call comm_allreduce(sp_grp, distdot)
300
301 end select
302
303end function distdot
304
305#endif /* HAVE_SPARSKIT */
306
307!! Local Variables:
308!! mode: f90
309!! coding: utf-8
310!! End:
scales a vector by a constant
Definition: lalg_basic.F90:159
double sin(double __x) __attribute__((__nothrow__
double atan(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:120
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:198
real(real64), parameter, public m_half
Definition: global.F90:206
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.
real(real64) function, dimension(1:dim) dmf_integrate_2(mesh, dim, ff, mask, reduce)
Integrate of a vector of functins.
complex(real64) function zmf_dotp_2(mesh, dim, f1, f2, reduce, dotu, np)
dot product for vector valued mesh functions
real(real64) function dmf_integrate_1(mesh, ff, mask, reduce)
Integrate a function on the mesh.
class(mesh_t), pointer, public mesh_aux
Globally-scoped pointer to the mesh instance.
complex(real64) function, dimension(1:dim) zmf_integrate_2(mesh, dim, ff, mask, reduce)
Integrate of a vector of functins.
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.
subroutine, public zmf_remove_average(mesh, ff, reduce)
Remove the average value of a mesh function.
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)
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.
subroutine, public zmf_remove_average_aux(f)
Interface for nullspace removal in linear solvers.
subroutine, public dmf_remove_average(mesh, ff, reduce)
Remove the average value of a mesh 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.
subroutine, public dmf_remove_average_aux(f)
Interface for nullspace removal in linear solvers.
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.
complex(real64) function zmf_integrate_1(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:120
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
Some general things and nomenclature:
Definition: par_vec.F90:173