RMPCDMD
polar_fields.f90
Go to the documentation of this file.
1 ! This file is part of RMPCDMD
2 ! Copyright (c) 2016-2017 Pierre de Buyl and contributors
3 ! License: BSD 3-clause (see file LICENSE)
4 
30 
32  use common
33  use particle_system
34  use cell_system
35  use neighbor_list
36  implicit none
37 
38  private
39 
40  public :: polar_fields_t
41 
43  integer, allocatable :: count(:,:,:)
44  double precision, allocatable :: v(:,:,:,:)
45  double precision :: r_min
46  double precision :: r_max
47  double precision :: dr
48  double precision :: dtheta
49  type(timer_t), pointer :: time_polar_update
50  contains
51  procedure :: init
52  procedure :: update
53  end type polar_fields_t
54 
55 contains
56 
58  subroutine init(this, N_species, N_r, r_min, r_max, N_theta)
59  class(polar_fields_t), intent(out) :: this
60  integer, intent(in) :: N_species
61  integer, intent(in) :: N_r
62  double precision, intent(in) :: r_min
63  double precision, intent(in) :: r_max
64  integer, intent(in) :: N_theta
65 
66  allocate(this%count(n_species, n_theta, n_r))
67  allocate(this%v(2, n_species, n_theta, n_r))
68 
69  this%count = 0
70  this%v = 0
71 
72  this%r_min = r_min
73  this%r_max = r_max
74  this%dr = (r_max - r_min) / n_r
75  this%dtheta = pi/n_theta
76 
77  allocate(this%time_polar_update)
78  call this%time_polar_update%init('polar_update')
79 
80  end subroutine init
81 
83  subroutine update(this, x, v, unit_r, solvent, cells)
84  class(polar_fields_t), intent(inout) :: this
85  double precision, intent(in) :: x(3)
86  double precision, intent(in) :: v(3)
87  double precision, intent(in) :: unit_r(3)
88  type(particle_system_t), intent(in) :: solvent
89  type(cell_system_t), intent(in) :: cells
90 
91  double precision :: r_min, r_min_sq, r_max, r_max_sq, dr, dtheta
92  double precision :: r_sq, v_r, v_th, r, theta
93  double precision, dimension(3) :: d, one_r, out_of_plane, one_theta, L
94  double precision, dimension(3) :: solvent_v
95  integer :: idx, s2, i_r, i_th
96 
97  integer, allocatable :: this_count(:,:,:)
98  double precision, allocatable :: this_v(:,:,:,:)
99 
100  integer :: cell_idx, start, n
101  integer :: n_species, n_theta, n_r
102 
103  r_min = this%r_min
104  r_min_sq = r_min**2
105  r_max = this%r_max
106  r_max_sq = r_max**2
107  dr = this%dr
108  dtheta = this%dtheta
109  l = cells%edges
110 
111  n_species = size(this%count, dim=1)
112  n_theta = size(this%count, dim=2)
113  n_r = size(this%count, dim=3)
114 
115  allocate(this_v(2, n_species, n_theta, n_r))
116  allocate(this_count(n_species, n_theta, n_r))
117  this_v = 0
118  this_count = 0
119 
120  call this%time_polar_update%tic()
121  !$omp parallel do &
122  !$omp private(cell_idx, idx, start, n, s2, d, r_sq, r, i_r, theta, i_th, one_r, &
123  !$omp out_of_plane, one_theta, solvent_v, v_th, v_r) &
124  !$omp reduction(+:this_v) reduction(+:this_count)
125  do cell_idx = 1, cells%N
126 
127  ! TODO: check if minimum distance from x to cell corners is below r_max
128 
129  start = cells% cell_start(cell_idx)
130  n = cells% cell_count(cell_idx)
131 
132  do idx = start, start + n - 1
133  s2 = solvent%species(idx)
134  if (s2 <= 0) cycle
135  d = rel_pos(solvent%pos(:,idx), x, l)
136  r_sq = sum(d**2)
137  if (( r_sq >= r_min_sq ) .and. ( r_sq < r_max_sq )) then
138  ! compute r, i_r, theta, i_theta
139  r = sqrt(r_sq)
140  i_r = floor((r-r_min)/dr) + 1
141  theta = acos( dot_product(unit_r,d)/r )
142  i_th = floor(theta/dtheta) + 1
143  one_r = d/r
144  ! compute v_r, v_theta
145  out_of_plane = cross(unit_r, one_r)
146  one_theta = cross(out_of_plane, one_r)
147  one_theta = one_theta/norm2(one_theta)
148  solvent_v = solvent%vel(:,idx) - v
149  v_r = dot_product(solvent_v, one_r)
150  v_th = dot_product(solvent_v, one_theta)
151  this_v(:, s2, i_th, i_r) = this_v(:, s2, i_th, i_r) + [v_r, v_th]
152  this_count(s2, i_th, i_r) = this_count(s2, i_th, i_r) + 1
153  end if
154  end do
155  end do
156 
157  this%v = this%v + this_v
158  this%count = this%count + this_count
159 
160  deallocate(this_v)
161  deallocate(this_count)
162 
163  call this%time_polar_update%tac()
164 
165  end subroutine update
166 
167 end module polar_fields
Derived type and routines for neighbor listing.
Data for particles.
pure double precision function, dimension(3), public cross(x1, x2)
Definition: common.f90:405
subroutine init(this, L, a, has_walls)
Definition: cell_system.f90:50
Utility routines.
Definition: common.f90:12
subroutine update(this, x, v, unit_r, solvent, cells)
Update the fields.
pure double precision function, dimension(3), public rel_pos(x, y, L)
Return x-y distance with minimum image convention.
Definition: common.f90:163
Spatial cells.
Definition: cell_system.f90:11
Routines to compute polar concentration and velocity profiles.
double precision, parameter, public pi
Definition: common.f90:47