33  use, 
intrinsic :: iso_fortran_env
 
   68  integer, 
parameter ::     &
 
   69    OUTPUT_COORDINATES = 1, &
 
   74    type(c_ptr), 
public :: output_handle(2)
 
   75    type(space_t), 
public :: space
 
   77    real(real64), 
allocatable, 
public :: mass(:)
 
   78    real(real64), 
allocatable, 
public :: pos(:,:)
 
   79    real(real64), 
allocatable, 
public :: vel(:,:)
 
   80    real(real64), 
allocatable, 
public :: tot_force(:,:)
 
   81    real(real64), 
allocatable, 
public :: lj_epsilon(:)
 
   82    real(real64), 
allocatable, 
public :: lj_sigma(:)
 
   83    logical, 
allocatable, 
public :: fixed(:)
 
   84    type(propagator_data_t),
public :: prop_data
 
  114    class(classical_particles_t), 
intent(inout) :: this
 
  115    integer,                      
intent(in)    :: np
 
  120    safe_allocate(this%mass(1:np))
 
  122    safe_allocate(this%pos(1:this%space%dim, 1:np))
 
  124    safe_allocate(this%vel(1:this%space%dim, 1:np))
 
  126    safe_allocate(this%tot_force(1:this%space%dim, 1:np))
 
  128    safe_allocate(this%fixed(1:np))
 
  130    safe_allocate(this%lj_epsilon(1:np))
 
  132    safe_allocate(this%lj_sigma(1:np))
 
  137    allocate(this%supported_interactions(0))
 
  138    allocate(this%supported_interactions_as_partner(0))
 
  143    this%quantities(
position)%updated_on_demand = .false.
 
  144    this%quantities(
velocity)%updated_on_demand = .false.
 
  147    this%quantities(
mass)%updated_on_demand = .false.
 
  148    this%quantities(
mass)%always_available = .
true.
 
  155    class(classical_particles_t), 
intent(out) :: this
 
  156    class(classical_particles_t), 
intent(in)  :: cp_in
 
  161    safe_allocate_source_a(this%mass,      cp_in%mass)
 
  162    safe_allocate_source_a(this%pos,       cp_in%pos)
 
  163    safe_allocate_source_a(this%vel,       cp_in%vel)
 
  164    safe_allocate_source_a(this%tot_force, cp_in%tot_force)
 
  165    safe_allocate_source_a(this%fixed,     cp_in%fixed)
 
  167    this%kinetic_energy    = cp_in%kinetic_energy
 
  169    this%quantities = cp_in%quantities
 
  170    this%supported_interactions = cp_in%supported_interactions
 
  172    this%quantities(
mass)%updated_on_demand = .false.
 
  174    this%prop_data = cp_in%prop_data
 
  186    select type (interaction)
 
  188      message(1) = 
"Trying to initialize an unsupported interaction by classical particles." 
  199    integer, 
allocatable,            
intent(out)   :: updated_quantities(:)
 
  202    real(real64), 
allocatable :: tmp_pos(:,:,:), tmp_vel(:,:,:)
 
  203    real(real64) :: factor
 
  209    select type (prop => this%algo)
 
  212      select case (operation%id)
 
  214        this%prop_data%save_pos(:, 1:this%np) = this%pos(:, 1:this%np)
 
  215        this%prop_data%save_vel(:, 1:this%np) = this%vel(:, 1:this%np)
 
  218        if (.not. this%prop_data%initialized) 
then 
  219          call this%prop_data%initialize(prop, this%space%dim, this%np)
 
  221            if (this%fixed(ip)) 
then 
  222              this%prop_data%acc(:, ip) = 
m_zero 
  224              this%prop_data%acc(:, ip) = this%tot_force(:, ip) / this%mass(ip)
 
  230        call this%prop_data%end()
 
  233        call this%prop_data%end()
 
  236        this%pos(:, 1:this%np) = this%pos(:, 1:this%np) + prop%dt * this%vel(:, 1:this%np) &
 
  237          + 
m_half * prop%dt**2 * this%prop_data%acc(:, 1:this%np)
 
  241        do ii = 
size(this%prop_data%prev_acc, dim=3) - 1, 1, -1
 
  242          this%prop_data%prev_acc(:, 1:this%np, ii + 1) = this%prop_data%prev_acc(:, 1:this%np, ii)
 
  245          this%prop_data%prev_acc(:, ip, 1) = this%prop_data%acc(:, ip)
 
  246          if (this%fixed(ip)) 
then 
  249            this%prop_data%acc(:, ip) = this%tot_force(:, ip) / this%mass(ip)
 
  254        this%vel(:, 1:this%np) = this%vel(:, 1:this%np) &
 
  255          + 
m_half * prop%dt * (this%prop_data%prev_acc(:, 1:this%np, 1) + this%prop_data%acc(:, 1:this%np))
 
  259        if (.not. this%prop_data%initialized) 
then 
  260          call this%prop_data%initialize(prop, this%space%dim, this%np)
 
  262            if (this%fixed(ip)) 
then 
  263              this%prop_data%acc(:, ip) = 
m_zero 
  265              this%prop_data%acc(:, ip) = this%tot_force(:, ip) / this%mass(ip)
 
  267            this%prop_data%prev_acc(:, ip, 1) = this%prop_data%acc(:, ip)
 
  272        this%pos(:, 1:this%np) = this%pos(:, 1:this%np) + prop%dt * this%vel(:, 1:this%np) + &
 
  273          m_one/6.0_real64 * prop%dt**2 * (
m_four*this%prop_data%acc(:, 1:this%np) - this%prop_data%prev_acc(:, 1:this%np, 1))
 
  275        if (.not. prop%predictor_corrector) 
then 
  280        this%vel(:, 1:this%np) = this%vel(:, 1:this%np) + &
 
  281          m_one/6.0_real64 * prop%dt * ( 
m_two * this%prop_data%acc(:, 1:this%np) + &
 
  282          5.0_real64 * this%prop_data%prev_acc(:, 1:this%np, 1) - this%prop_data%prev_acc(:, 1:this%np, 2))
 
  286        this%pos(:, 1:this%np) = this%prop_data%save_pos(:, 1:this%np) &
 
  287          + prop%dt * this%prop_data%save_vel(:, 1:this%np) &
 
  288          + 
m_one/6.0_real64 * prop%dt**2 * (this%prop_data%acc(:, 1:this%np) &
 
  289          + 
m_two * this%prop_data%prev_acc(:, 1:this%np, 1))
 
  293        this%vel(:, 1:this%np) = this%prop_data%save_vel(:, 1:this%np) &
 
  294          + 
m_half * prop%dt * (this%prop_data%acc(:, 1:this%np) + this%prop_data%prev_acc(:, 1:this%np, 1))
 
  298        if (.not. this%prop_data%initialized) 
then 
  299          call this%prop_data%initialize(prop, this%space%dim, this%np)
 
  300          this%prop_data%prev_pos(:, 1:this%np, 1) = this%pos(:, 1:this%np)
 
  301          this%prop_data%prev_vel(:, 1:this%np, 1) = this%vel(:, 1:this%np)
 
  305        call this%prop_data%end()
 
  308        this%pos(:, 1:this%np) = 1.5_real64*this%prop_data%save_pos(:, 1:this%np) &
 
  309          - 
m_half*this%prop_data%prev_pos(:, 1:this%np, 1)
 
  310        this%vel(:, 1:this%np) = 1.5_real64*this%prop_data%save_vel(:, 1:this%np) &
 
  311          - 
m_half*this%prop_data%prev_vel(:, 1:this%np, 1)
 
  312        this%prop_data%prev_pos(:, 1:this%np, 1) = this%prop_data%save_pos(:, 1:this%np)
 
  313        this%prop_data%prev_vel(:, 1:this%np, 1) = this%prop_data%save_vel(:, 1:this%np)
 
  318          if (this%fixed(ip)) 
then 
  319            this%prop_data%hamiltonian_elements(:, ip) = 
m_zero 
  321            this%prop_data%hamiltonian_elements(:, ip) = this%tot_force(:, ip) / (this%mass(ip) * this%pos(:, ip) + 
m_epsilon)
 
  326        safe_allocate(tmp_pos(1:this%space%dim, 1:this%np, 1:2))
 
  327        safe_allocate(tmp_vel(1:this%space%dim, 1:this%np, 1:2))
 
  333        tmp_pos(:, 1:this%np, 1) = this%prop_data%save_pos(:, 1:this%np)
 
  334        tmp_vel(:, 1:this%np, 1) = this%prop_data%save_vel(:, 1:this%np)
 
  335        this%pos(:, 1:this%np) = this%prop_data%save_pos(:, 1:this%np)
 
  336        this%vel(:, 1:this%np) = this%prop_data%save_vel(:, 1:this%np)
 
  340          factor = factor * prop%dt / ii
 
  343            tmp_pos(:, ip, 2) = tmp_vel(:, ip, 1)
 
  344            tmp_vel(:, ip, 2) = this%prop_data%hamiltonian_elements(:, ip) * tmp_pos(:, ip, 1)
 
  346            tmp_pos(:, ip, 1) = tmp_pos(:, ip, 2)
 
  347            tmp_vel(:, ip, 1) = tmp_vel(:, ip, 2)
 
  349            this%pos(:, ip) = this%pos(:, ip) + factor * tmp_pos(:, ip, 1)
 
  350            this%vel(:, ip) = this%vel(:, ip) + factor * tmp_vel(:, ip, 1)
 
  353        safe_deallocate_a(tmp_pos)
 
  354        safe_deallocate_a(tmp_vel)
 
  359        if (.not. this%is_tolerance_reached(prop%scf_tol)) 
then 
  360          this%pos(:, 1:this%np) = 
m_half*(this%pos(:, 1:this%np) + this%prop_data%save_pos(:, 1:this%np))
 
  361          this%vel(:, 1:this%np) = 
m_half*(this%vel(:, 1:this%np) + this%prop_data%save_vel(:, 1:this%np))
 
  371    call profiling_out(trim(this%namespace%get())//
":"//trim(operation%id))
 
  378    real(real64),                 
intent(in)    :: tol
 
  381    real(real64) :: change, max_change
 
  388      change = sum((this%prop_data%prev_tot_force(1:this%space%dim, ip) - this%tot_force(1:this%space%dim, ip))**2) / &
 
  390      if (change > max_change) 
then 
  394    converged = max_change < tol**2
 
  397      write(
message(1), 
'(a, e13.6, a, e13.6)') 
"Debug: -- Maximum change in acceleration  ", &
 
  398        sqrt(max_change), 
" and tolerance ", tol
 
  408    integer,                     
intent(in)    :: iq
 
  413    assert(this%quantities(iq)%updated_on_demand)
 
  417      message(1) = 
"Incompatible quantity." 
  431    select type (interaction)
 
  433      message(1) = 
"Unsupported interaction." 
  447    select type (interaction)
 
  449      message(1) = 
"Unsupported interaction." 
  463    select type (prop => this%algo)
 
  465      if (prop%predictor_corrector) 
then 
  466        this%prop_data%prev_tot_force(1:this%space%dim, 1:this%np) = this%tot_force(1:this%space%dim, 1:this%np)
 
  482    this%tot_force(1:this%space%dim, 1:this%np) = 
m_zero 
  483    call iter%start(this%interactions)
 
  484    do while (iter%has_next())
 
  485      select type (interaction => iter%get_next())
 
  487        this%tot_force(1:this%space%dim, 1:this%np) = this%tot_force(1:this%space%dim, 1:this%np) + &
 
  488          interaction%force(1:this%space%dim, 1:this%np)
 
  504    select type (algo => this%algo)
 
  509    iteration = this%iteration%counter()
 
  510    if (iteration > 0) 
then 
  512      iteration = iteration + 1
 
  515    call io_mkdir(
'td.general', this%namespace)
 
  517      call write_iter_init(this%output_handle(output_coordinates), iteration, dt, &
 
  520        trim(
io_workpath(
"td.general/energy", this%namespace)))
 
  524    if (iteration == 0) 
then 
  525      call this%output_write()
 
  549    integer :: idir, ii, ip
 
  550    character(len=50) :: aux
 
  551    real(real64) :: tmp(this%space%dim)
 
  557    if (this%iteration%counter() == 0) 
then 
  561        '############################################################################')
 
  569        do idir = 1, this%space%dim
 
  570          write(aux, 
'(a2,i3,a1,i3,a1)') 
'x(', ip, 
',', idir, 
')' 
  575        do idir = 1, this%space%dim
 
  576          write(aux, 
'(a2,i3,a1,i3,a1)') 
'v(', ip, 
',', idir, 
')' 
  581        do idir = 1, this%space%dim
 
  582          write(aux, 
'(a2,i3,a1,i3,a1)') 
'f(', ip, 
',', idir, 
')' 
  592        do idir = 1, this%space%dim
 
  597        do idir = 1, this%space%dim
 
  602        do idir = 1, this%space%dim
 
  609        '############################################################################')
 
  618      call write_iter_double(this%output_handle(output_coordinates), tmp, this%space%dim)
 
  623      call write_iter_double(this%output_handle(output_coordinates), tmp, this%space%dim)
 
  628      call write_iter_double(this%output_handle(output_coordinates), tmp, this%space%dim)
 
  634    if (this%iteration%counter() == 0) 
then 
  638        '############################################################################')
 
  660        '############################################################################')
 
  678    integer :: restart_file_unit
 
  687    call profiling_in(trim(this%namespace%get())//
":"//
"RESTART_WRITE")
 
  690    restart_file_unit = 
io_open(
'restart/'//
td_dir// 
'restart_classical_particles', this%namespace, action=
'write')
 
  691    write(restart_file_unit, *) this%np
 
  692    write(restart_file_unit, *) this%mass(:)
 
  693    write(restart_file_unit, *) this%pos(:,:)
 
  694    write(restart_file_unit, *) this%vel(:,:)
 
  695    write(restart_file_unit, *) this%tot_force(:,:)
 
  698    if (this%iteration%counter() > 0) 
then 
  700      call this%prop_data%restart_write(this%namespace, this%algo)
 
  703    message(1) = 
"Successfully wrote restart data for system "//trim(this%namespace%get())
 
  706    call profiling_out(trim(this%namespace%get())//
":"//
"RESTART_WRITE")
 
  714    integer :: restart_file_unit
 
  717    call profiling_in(trim(this%namespace%get())//
":"//
"RESTART_READ")
 
  720    restart_file_unit = 
io_open(
'restart/'//
td_dir// 
'restart_classical_particles', this%namespace, action=
'read', die=.false.)
 
  721    if (restart_file_unit > 0) 
then 
  722      read(restart_file_unit, *) this%np
 
  723      read(restart_file_unit, *) this%mass(:)
 
  724      read(restart_file_unit, *) this%pos(:,:)
 
  725      read(restart_file_unit, *) this%vel(:,:)
 
  726      read(restart_file_unit, *) this%tot_force(:,:)
 
  728      call this%prop_data%initialize(this%algo, this%space%dim, this%np)
 
  729      if (this%iteration%counter() > 0) 
then 
  741      message(1) = 
"Successfully read restart data for system "//trim(this%namespace%get())
 
  746    call profiling_out(trim(this%namespace%get())//
":"//
"RESTART_READ")
 
  758    this%kinetic_energy = 
m_zero 
  760      this%kinetic_energy = this%kinetic_energy + 
m_half * this%mass(ip) * sum(this%vel(:, ip)**2)
 
  769    logical,            
optional, 
intent(in) :: mask(:)
 
  770    logical,            
optional, 
intent(in) :: pseudo
 
  771    real(real64) :: pos(this%space%dim)
 
  773    real(real64) :: 
mass, total_mass
 
  778    assert(.not. this%space%is_periodic())
 
  784      if (
present(mask)) 
then 
  785        if (.not. mask(ip)) cycle
 
  790      pos = pos + 
mass*this%pos(:, ip)
 
  791      total_mass = total_mass + 
mass 
  801    real(real64) :: vel(this%space%dim)
 
  803    real(real64) :: 
mass, total_mass
 
  812      total_mass = total_mass + 
mass 
  813      vel = vel + 
mass*this%vel(:, ip)
 
  823    real(real64) :: pos(this%space%dim)
 
  825    real(real64) :: xmin(this%space%dim), xmax(this%space%dim)
 
  833      do idir = 1, this%space%dim
 
  834        if (this%pos(idir, ip) > xmax(idir)) xmax(idir) = this%pos(idir, ip)
 
  835        if (this%pos(idir, ip) < xmin(idir)) xmin(idir) = this%pos(idir, ip)
 
  839    pos = (xmax + xmin)/
m_two 
  847    real(real64),                 
intent(out) :: x(this%space%dim)
 
  848    real(real64),                 
intent(out) :: x2(this%space%dim)
 
  851    real(real64) :: rmax, r, r2
 
  855    assert(.not. this%space%is_periodic())
 
  860      do jp = 1, this%np/2 + 1
 
  861        r = norm2(this%pos(:, ip) - this%pos(:, jp))
 
  864          x = this%pos(:, ip) - this%pos(:, jp)
 
  873      r2 = sum(x * this%pos(:, ip))
 
  874      r = norm2(this%pos(:, ip) - r2*x)
 
  877        x2 = this%pos(:, ip) - r2*x
 
  889    real(real64),                 
intent(out) :: x(this%space%dim)
 
  890    real(real64),                 
intent(out) :: x2(this%space%dim)
 
  891    logical,                      
intent(in)  :: pseudo
 
  893    real(real64) :: 
mass, tinertia(this%space%dim, this%space%dim), eigenvalues(this%space%dim)
 
  894    integer :: ii, jj, ip
 
  899    assert(.not. this%space%is_periodic())
 
  905      if (.not. pseudo) 
mass = this%mass(ip)
 
  906      do ii = 1, this%space%dim
 
  907        tinertia(ii, :) = tinertia(ii, :) - 
mass*this%pos(ii, ip)*this%pos(:, ip)
 
  908        tinertia(ii, ii) = tinertia(ii, ii) + 
mass*sum(this%pos(:, ip)**2)
 
  915      write(
message(1),
'(a)') 
'Moment of pseudo-inertia tensor [' // trim(
units_abbrev(unit)) // 
']' 
  917      write(
message(1),
'(a)') 
'Moment of inertia tensor [amu*' // trim(
units_abbrev(unit)) // 
']' 
  920    call output_tensor(tinertia, this%space%dim, unit, write_average = .
true., namespace=this%namespace)
 
  929      jj = maxloc(abs(tinertia(:,ii)), dim = 1)
 
  930      if (tinertia(jj,ii) < 
m_zero) tinertia(:,ii) = -tinertia(:,ii)
 
  944    safe_deallocate_a(this%mass)
 
  945    safe_deallocate_a(this%pos)
 
  946    safe_deallocate_a(this%vel)
 
  947    safe_deallocate_a(this%tot_force)
 
  948    safe_deallocate_a(this%fixed)
 
  949    safe_deallocate_a(this%lj_epsilon)
 
  950    safe_deallocate_a(this%lj_sigma)
 
Writes to the corresponding file and adds one to the iteration. Must be called after write_iter_init(...
 
This module implements the basic elements defining algorithms.
 
subroutine classical_particles_output_finish(this)
 
subroutine classical_particles_axis_large(this, x, x2)
 
logical function classical_particles_is_tolerance_reached(this, tol)
 
subroutine classical_particles_output_write(this)
 
integer, parameter output_energy
 
logical function classical_particles_do_algorithmic_operation(this, operation, updated_quantities)
 
subroutine classical_particles_update_kinetic_energy(this)
 
subroutine classical_particles_axis_inertia(this, x, x2, pseudo)
This subroutine assumes that the origin of the coordinates is the center of mass of the system.
 
subroutine classical_particles_output_start(this)
 
logical function classical_particles_restart_read_data(this)
 
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_copy(this, cp_in)
 
subroutine classical_particles_update_interactions_finish(this)
 
subroutine, public classical_particles_update_quantity(this, iq)
 
subroutine classical_particles_update_interactions_start(this)
 
subroutine, public classical_particles_copy_quantities_to_interaction(partner, interaction)
 
real(real64) function, dimension(this%space%dim) classical_particles_center_of_mass_vel(this)
 
subroutine, public classical_particles_init_interaction(this, interaction)
 
subroutine, public classical_particles_restart_write_data(this)
 
real(real64) function, dimension(this%space%dim) classical_particles_center_of_mass(this, mask, pseudo)
 
real(real64) function, dimension(this%space%dim) classical_particles_center(this)
 
type(debug_t), save, public debug
 
real(real64), parameter, public m_two
 
real(real64), parameter, public m_huge
 
real(real64), parameter, public m_zero
 
real(real64), parameter, public m_four
 
real(real64), parameter, public m_epsilon
 
character(len= *), parameter, public td_dir
 
real(real64), parameter, public m_half
 
real(real64), parameter, public m_one
 
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
 
subroutine, public io_close(iunit, grp)
 
character(len=max_path_len) function, public io_workpath(path, namespace)
 
subroutine, public io_mkdir(fname, namespace, parents)
 
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
 
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
 
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
 
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
 
logical function mpi_grp_is_root(grp)
 
This module implements the multisystem debug functionality.
 
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
 
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
 
character(len=algo_label_len), parameter, public beeman_start
 
character(len=algo_label_len), parameter, public beeman_finish
 
character(len=algo_label_len), parameter, public beeman_compute_acc
 
character(len=algo_label_len), parameter, public beeman_correct_pos
 
character(len=algo_label_len), parameter, public beeman_predict_pos
 
character(len=algo_label_len), parameter, public beeman_correct_vel
 
character(len=algo_label_len), parameter, public beeman_predict_vel
 
character(len=algo_label_len), parameter, public expmid_2step_predict_dt
 
character(len=algo_label_len), parameter, public expmid_2step_finish
 
character(len=algo_label_len), parameter, public expmid_2step_correct_dt_2
 
character(len=algo_label_len), parameter, public update_hamiltonian
 
character(len=algo_label_len), parameter, public expmid_2step_predict_dt_2
 
character(len=algo_label_len), parameter, public expmid_2step_start
 
This module implements the basic propagator framework.
 
character(len=algo_label_len), parameter, public store_current_status
 
character(len=30), parameter, public verlet_start
 
character(len=30), parameter, public verlet_compute_acc
 
character(len=30), parameter, public verlet_update_pos
 
character(len=30), parameter, public verlet_finish
 
character(len=30), parameter, public verlet_compute_vel
 
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
 
integer, parameter, public velocity
 
integer, parameter, public position
 
integer, parameter, public mass
 
This module implements the abstract system type.
 
subroutine, public system_end(this)
 
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
 
character(len=20) pure function, public units_abbrev(this)
 
This module defines the unit system, used for input and output.
 
type(unit_system_t), public units_out
 
This module is intended to contain simple general-purpose utility functions and procedures.
 
subroutine, public output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
 
Explicit interfaces to C functions, defined in write_iter_low.cc.
 
Descriptor of one algorithmic operation.
 
These class extend the list and list iterator to make an interaction list.
 
surrogate interaction class to avoid circular dependencies between modules.
 
Abstract class implementing propagators.
 
Abstract class for systems.