Octopus
classical_particle.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 N. Tancogne-Dejean
2!! Copyright (C) 2020 M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
25 use debug_oct_m
27 use global_oct_m
32 use io_oct_m
36 use parser_oct_m
41 use space_oct_m
42 use system_oct_m
43 use unit_oct_m
45
46 implicit none
47
48 private
49 public :: &
52
53 integer, parameter :: &
54 OUTPUT_COORDINATES = 1, &
56
60 contains
61 procedure :: init_interaction => classical_particle_init_interaction
62 procedure :: initialize => classical_particle_initialize
63 procedure :: update_quantity => classical_particle_update_quantity
64 procedure :: init_interaction_as_partner => classical_particle_init_interaction_as_partner
65 procedure :: copy_quantities_to_interaction => classical_particle_copy_quantities_to_interaction
68
69 interface classical_particle_t
70 procedure classical_particle_constructor
71 end interface classical_particle_t
72
73contains
74
75 ! ---------------------------------------------------------
80 function classical_particle_constructor(namespace) result(sys)
81 class(classical_particle_t), pointer :: sys
82 type(namespace_t), intent(in) :: namespace
83
85
86 allocate(sys)
87
88 call classical_particle_init(sys, namespace)
89
92
93 ! ---------------------------------------------------------
98 ! ---------------------------------------------------------
99 subroutine classical_particle_init(this, namespace)
100 class(classical_particle_t), intent(inout) :: this
101 type(namespace_t), intent(in) :: namespace
102
104
105 this%namespace = namespace
106
107 this%space = space_t(namespace)
108 if (this%space%is_periodic()) then
109 call messages_not_implemented('Classical particle for periodic systems')
110 end if
111
112 call messages_print_with_emphasis(msg="Classical Particle", namespace=namespace)
113
114 call classical_particles_init(this, 1)
115
116 !%Variable ParticleMass
117 !%Type float
118 !%Section ClassicalParticles
119 !%Description
120 !% Mass of classical particle in Kg.
121 !%End
122 call parse_variable(namespace, 'ParticleMass', m_one, this%mass(1))
123 call messages_print_var_value('ParticleMass', this%mass(1), namespace=namespace)
124
125 this%supported_interactions = [this%supported_interactions, gravity, lennard_jones]
126 this%supported_interactions_as_partner = [this%supported_interactions_as_partner, gravity, lennard_jones]
127
128 !%Variable LennardJonesEpsilon
129 !%Type float
130 !%Section ClassicalParticles
131 !%Description
132 !% Epsilon parameter (dispersion energy) of Lennard-Jones interaction for this species.
133 !% In case two particles have a different epsilon, the combination rule will be computed
134 !% <math>\epsilon_{12} = \sqrt{\epsilon_1 + \epsilon_2}</math>.
135 !%End
136 call parse_variable(namespace, 'LennardJonesEpsilon', m_one, this%lj_epsilon(1))
137 call messages_print_var_value('LennardJonesEpsilon', this%lj_epsilon(1), namespace=namespace)
138
139 !%Variable LennardJonesSigma
140 !%Type float
141 !%Section ClassicalParticles
142 !%Description
143 !% Sigma parameter (particle size) of Lennard-Jones interaction for this species.
144 !% In case two particles have a different sigma, the combination rule will be computed
145 !% <math>\sigma_{12} = (\sigma_1 + \sigma_2) / 2</math>.
146 !%End
147 call parse_variable(namespace, 'LennardJonesSigma', m_one, this%lj_sigma(1))
148 call messages_print_var_value('LennardJonesSigma', this%lj_sigma(1), namespace=namespace)
149
150 call messages_print_with_emphasis(namespace=namespace)
151
153 end subroutine classical_particle_init
155 ! ---------------------------------------------------------
156 subroutine classical_particle_init_interaction(this, interaction)
157 class(classical_particle_t), target, intent(inout) :: this
158 class(interaction_t), intent(inout) :: interaction
162 select type (interaction)
163 type is (gravity_t)
164 call interaction%init(this%space%dim, 1, this%mass, this%pos)
165 type is (lennard_jones_t)
166 if (.not. (parse_is_defined(this%namespace, 'LennardJonesSigma') .and. &
167 parse_is_defined(this%namespace, 'LennardJonesEpsilon') )) then
168 write(message(1),'(a,es9.2)') 'Using default value for Lennard-Jones parameter.'
169 call messages_warning(1, namespace=this%namespace)
170 end if
171
172 call interaction%init(this%space%dim, 1, this%pos, this%lj_epsilon(1), this%lj_sigma(1))
173 class default
174 call classical_particles_init_interaction(this, interaction)
175 end select
176
179
180 ! ---------------------------------------------------------
181 subroutine classical_particle_initialize(this)
182 class(classical_particle_t), intent(inout) :: this
183
184 integer :: n_rows, idir
185 type(block_t) :: blk
186
187 real(real64) :: random_pos(1:this%space%dim), width_pos(1:this%space%dim)
188 real(real64) :: random_vel(1:this%space%dim), width_vel(1:this%space%dim)
189 integer(int64) :: seed
190 logical :: in_ensemble
191
193
194 in_ensemble = parse_is_defined(this%namespace, "NumberOfReplicas")
195
196 !%Variable ParticleInitialPosition
197 !%Type block
198 !%Section ClassicalParticles
199 !%Description
200 !% Initial position of classical particle, in Km.
201 !%End
202 this%pos = m_zero
203 if (parse_block(this%namespace, 'ParticleInitialPosition', blk) == 0) then
204 n_rows = parse_block_n(blk)
205 if (n_rows > 1) call messages_input_error(this%namespace, 'ParticleInitialPosition')
206
207 do idir = 1, this%space%dim
208 call parse_block_float(blk, 0, idir - 1, this%pos(idir, 1))
209 end do
210 call parse_block_end(blk)
211 end if
212 call messages_print_var_value('ParticleInitialPosition', this%pos(1:this%space%dim, 1), namespace=this%namespace)
213
214 !%Variable ParticleInitialVelocity
215 !%Type block
216 !%Section ClassicalParticles
217 !%Description
218 !% Initial velocity of classical particle in Km/s.
219 !%End
220 this%vel = m_zero
221 if (parse_block(this%namespace, 'ParticleInitialVelocity', blk) == 0) then
222 n_rows = parse_block_n(blk)
223 if (n_rows > 1) call messages_input_error(this%namespace, 'ParticleInitialVelocity')
224 do idir = 1, this%space%dim
225 call parse_block_float(blk, 0, idir - 1, this%vel(idir, 1))
226 end do
227 call parse_block_end(blk)
228 end if
229 call messages_print_var_value('ParticleInitialVelocity', this%vel(1:this%space%dim, 1), namespace=this%namespace)
230
231 if (in_ensemble) then
232
233 seed = this%namespace%get_hash32()
234 width_pos = m_zero
235 width_vel = m_zero
236
237 !%Variable ParticlePositionDistributionWidth
238 !%Type block
239 !%Section ClassicalParticles
240 !%Description
241 !% Width of the position random displacements of classical particle in Km.
242 !%End
243 if (parse_block(this%namespace, 'ParticlePositionDistributionWidth', blk) == 0) then
244 n_rows = parse_block_n(blk)
245 if (n_rows > 1) call messages_input_error(this%namespace, 'ParticlePositionDistributionWidth')
246 do idir = 1, this%space%dim
247 call parse_block_float(blk, 0, idir - 1, width_pos(idir))
248 end do
249 call parse_block_end(blk)
250 end if
251 call messages_print_var_value('ParticlePositionDistributionWidth', width_pos(1:this%space%dim), namespace=this%namespace)
252
253 !%Variable ParticleVelocityDistributionWidth
254 !%Type block
255 !%Section ClassicalParticles
256 !%Description
257 !% Width of the velocity random distribution of classical particle in Km/s.
258 !%End
259 if (parse_block(this%namespace, 'ParticleVelocityDistributionWidth', blk) == 0) then
260 n_rows = parse_block_n(blk)
261 if (n_rows > 1) call messages_input_error(this%namespace, 'ParticleVelocityDistributionWidth')
262 do idir = 1, this%space%dim
263 call parse_block_float(blk, 0, idir - 1, width_vel(idir))
264 end do
265 call parse_block_end(blk)
266 end if
267 call messages_print_var_value('ParticleVelocityDistributionWidth', width_vel(1:this%space%dim), namespace=this%namespace)
268
269 call shiftseed(seed, 1000_int64)
270 call quickrnd(seed, this%space%dim, random_pos)
271 call quickrnd(seed, this%space%dim, random_vel)
272
273
274 this%pos(:,1) = this%pos(:,1) + (random_pos - 0.5_real64) * width_pos
275 this%vel(:,1) = this%vel(:,1) + (random_vel - 0.5_real64) * width_vel
277 end if
278
280 end subroutine classical_particle_initialize
281
282 ! ---------------------------------------------------------
283 subroutine classical_particle_update_quantity(this, label)
284 class(classical_particle_t), intent(inout) :: this
285 character(len=*), intent(in) :: label
286
288
289 select case (label)
290 case default
291 ! Other quantities should be handled by the parent class
293 end select
294
297
298 ! ---------------------------------------------------------
299 subroutine classical_particle_init_interaction_as_partner(partner, interaction)
300 class(classical_particle_t), intent(in) :: partner
301 class(interaction_surrogate_t), intent(inout) :: interaction
302
304
305 select type (interaction)
306 type is (gravity_t)
307 interaction%partner_np = 1
308 safe_allocate(interaction%partner_mass(1))
309 safe_allocate(interaction%partner_pos(1:partner%space%dim, 1))
310 interaction%partner_pos = m_zero
311
312 type is (lennard_jones_t)
313 interaction%partner_np = 1
314 safe_allocate(interaction%partner_pos(1:partner%space%dim, 1))
315 ! in case the LennardJones epsilon and sigma of system and partner are different,
316 ! we compute the combination rules with arithmetic and geometric means:
317 ! (they give back the original parameters if they happen to be equal):
318 ! sigma_12 = (sigma_1 + sigma_2)/2, epsilon_12 = sqrt(epsilon_1 * epsilon_2)
319 interaction%lj_sigma = m_half * (partner%lj_sigma(1) + interaction%lj_sigma)
320 interaction%lj_epsilon = sqrt(partner%lj_epsilon(1) * interaction%lj_epsilon)
321
322 class default
323 ! Other interactions should be handled by the parent class
324 call classical_particles_init_interaction_as_partner(partner, interaction)
325 end select
326
329
330 ! ---------------------------------------------------------
331 subroutine classical_particle_copy_quantities_to_interaction(partner, interaction)
332 class(classical_particle_t), intent(inout) :: partner
333 class(interaction_surrogate_t), intent(inout) :: interaction
334
336
337 select type (interaction)
338 type is (gravity_t)
339 interaction%partner_mass(1) = partner%mass(1)
340 interaction%partner_pos(:,1) = partner%pos(:,1)
341
342 type is (lennard_jones_t)
343 interaction%partner_pos(:,1) = partner%pos(:,1)
344
345 class default
346 message(1) = "Unsupported interaction."
347 call messages_fatal(1, namespace=partner%namespace)
348 end select
349
352
353 ! ---------------------------------------------------------
354 subroutine classical_particle_finalize(this)
355 type(classical_particle_t), intent(inout) :: this
356
358
359 call classical_particles_end(this)
360
362 end subroutine classical_particle_finalize
363
365
366!! Local Variables:
367!! mode: f90
368!! coding: utf-8
369!! End:
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:182
This module implements the basic elements defining algorithms.
Definition: algorithm.F90:143
subroutine, public classical_particle_init(this, namespace)
The init routine is a module level procedure This has the advantage that different classes can have d...
subroutine classical_particle_init_interaction_as_partner(partner, interaction)
subroutine classical_particle_finalize(this)
integer, parameter output_energy
class(classical_particle_t) function, pointer classical_particle_constructor(namespace)
The factory routine (or constructor) allocates a pointer of the corresponding type and then calls the...
subroutine classical_particle_initialize(this)
subroutine classical_particle_update_quantity(this, label)
subroutine classical_particle_init_interaction(this, interaction)
subroutine classical_particle_copy_quantities_to_interaction(partner, interaction)
subroutine, public classical_particles_update_quantity(this, label)
subroutine, public classical_particles_init_interaction_as_partner(partner, interaction)
subroutine, public classical_particles_end(this)
subroutine, public classical_particles_init(this, np)
The init routine is a module level procedure This has the advantage that different classes can have d...
subroutine, public classical_particles_init_interaction(this, interaction)
This module provides a random number generator for a normalized gaussian distribution.
real(real64), parameter, public m_zero
Definition: global.F90:191
real(real64), parameter, public m_half
Definition: global.F90:197
real(real64), parameter, public m_one
Definition: global.F90:192
integer, parameter, public lennard_jones
integer, parameter, public gravity
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
Definition: io.F90:116
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1091
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
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
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:455
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:615
This module implements the basic propagator framework.
Definition: propagator.F90:119
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:140
subroutine, public shiftseed(iseed, n)
Definition: quickrnd.F90:260
This module implements the abstract system type.
Definition: system.F90:120
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
class for a neutral classical particle
Gravity interaction between two systems of particles. This should be used for testing purposes only....
Definition: gravity.F90:136
abstract interaction class
surrogate interaction class to avoid circular dependencies between modules.
Lennard-Jones interaction between two systems of particles.