module classes_complete_coordinates_reader use, intrinsic :: iso_fortran_env, only: DP => REAL64 use data_constants, only: num_dimensions use data_strings, only: max_line_length, max_word_length use procedures_errors, only: error_exit use procedures_checks, only: check_file_exists use types_string_wrapper, only: String_Wrapper use classes_periodic_box, only: Abstract_Periodic_Box use classes_box_size_checker, only: Abstract_Box_Size_Checker use procedures_boxes_size_checker_factory, only: boxes_size_checker_destroy => destroy use classes_component_coordinates_reader, only: Component_Coordinates_Reader_wrapper use procedures_component_coordinates_reader_factory, only: component_coordinates_reader_destroy => & destroy implicit none private type, abstract, public :: Abstract_Complete_Coordinates_Reader private class(Abstract_Periodic_Box), pointer :: periodic_boxes(:) => null() class(Abstract_Box_Size_Checker), allocatable :: boxes_size_checker(:) type(Component_Coordinates_Reader_wrapper), allocatable :: components_coordinates(:, :) contains procedure :: construct => Abstract_construct procedure :: destroy => Abstract_destroy procedure :: read => Abstract_read end type Abstract_Complete_Coordinates_Reader type, extends(Abstract_Complete_Coordinates_Reader), public :: & Concrete_Complete_Coordinates_Reader end type Concrete_Complete_Coordinates_Reader contains subroutine Abstract_construct(this, periodic_boxes, boxes_size_checker, components_coordinates) class(Abstract_Complete_Coordinates_Reader), intent(out) :: this class(Abstract_Periodic_Box), target, intent(in) :: periodic_boxes(:) class(Abstract_Box_Size_Checker), intent(in) :: boxes_size_checker(:) type(Component_Coordinates_Reader_wrapper), intent(in) :: components_coordinates(:, :) this%periodic_boxes => periodic_boxes allocate(this%boxes_size_checker, source=boxes_size_checker) allocate(this%components_coordinates, source=components_coordinates) end subroutine Abstract_construct subroutine Abstract_destroy(this) class(Abstract_Complete_Coordinates_Reader), intent(out) :: this call component_coordinates_reader_destroy(this%components_coordinates) call boxes_size_checker_destroy(this%boxes_size_checker) this%periodic_boxes => null() end subroutine Abstract_destroy !> @warning gfortran requires intent(inout) even though this%periodic_boxes is !> implicitly mutable with ifort. subroutine Abstract_read(this, coordinates) class(Abstract_Complete_Coordinates_Reader), intent(inout) :: this type(String_Wrapper), intent(in) :: coordinates(:) real(DP) :: box_size(num_dimensions) integer :: i_box, i_component integer :: nums_particles(size(this%components_coordinates, 1)) character(len=1) :: comment_character character(len=max_word_length) :: field integer :: coordinates_unit if (size(coordinates) /= size(this%components_coordinates, 2)) then call error_exit("Abstract_Complete_Coordinates_Reader: read: the number of boxes is "& //"not correct.") end if do i_box = 1, size(this%components_coordinates, 2) call check_file_exists(coordinates(i_box)%string) open(newunit=coordinates_unit, recl=max_line_length, file=coordinates(i_box)%string, & status="old", action="read") read(coordinates_unit, *) comment_character, field, box_size call this%periodic_boxes(i_box)%set(box_size) call this%boxes_size_checker(i_box)%check() read(coordinates_unit, *) comment_character, field, nums_particles read(coordinates_unit, *) comment_character !components coordinates legend do i_component = 1, size(this%components_coordinates, 1) call this%components_coordinates(i_component, i_box)%reader%read(coordinates_unit, & nums_particles(i_component)) end do close(coordinates_unit) end do end subroutine Abstract_read end module classes_complete_coordinates_reader