allocates fragments for MM part
too many arguments - consider factory
break into several routines - this one does too much stuff now
Some extraodinary ugly code here - refactor ASAP
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(subsystem_type), | intent(inout), | dimension(:) | :: | subsystems | array of subsystems associated with client codes  | 
|
| real(kind=dp), | intent(in), | dimension(:) | :: | factors | factors applied to forces contribution (by code) Todoclarify if this is also for energies, potential, etc.  | 
|
| real(kind=dp), | intent(in), | dimension(:,:,:) | :: | tau | coordinate matrix of CPMD  | 
|
| real(kind=dp), | intent(in), | dimension(:,:,:) | :: | force | force matrix of CPMD  | 
|
| integer, | dimension(:) | :: | num_qm_atoms | number of quantum atoms per species  | 
||
| integer, | intent(in) | :: | total_species | total number of species  | 
||
| real(kind=dp), | intent(in), | dimension(:) | :: | cov_radii | covalent radius of each species  | 
|
| type(sizes_type), | intent(in) | :: | sizes | sizes data  | 
||
| type(system_type), | intent(inout) | :: | system_data | system data  | 
subroutine mimic_allocate_mm_struct(subsystems, factors, tau, force, num_qm_atoms,&
                                  total_species, cov_radii, sizes, system_data)
    !> array of subsystems associated with client codes
    type(subsystem_type), dimension(:), intent(inout) :: subsystems
    !> factors applied to forces contribution (by code)
    !> @todo clarify if this is also for energies, potential, etc.
    real(dp), dimension(:), intent(in) :: factors
    !> coordinate matrix of CPMD
    real(dp), dimension(:,:,:), intent(in) :: tau
    !> force matrix of CPMD
    real(dp), dimension(:,:,:), intent(in) :: force
    !> number of quantum atoms per species
    integer, dimension(:) :: num_qm_atoms
    !> total number of species
    integer, intent(in) :: total_species
    !> covalent radius of each species
    real(dp), dimension(:), intent(in) :: cov_radii
    !> sizes data
    type(sizes_type), intent(in) :: sizes
    !> system data
    type(system_type), intent(inout) :: system_data
    integer :: n_atoms, n_code, n_atom, n_species, n_fragment, n_map, n_bond, n_angle
    integer :: atom_index
    integer :: id_offset
    integer :: spid, atid, id
    integer :: sp_offset, atom_species
    integer :: target_code
    integer :: alloc_stat
    integer, dimension(communicator%num_clients) :: code_offset
    integer, dimension(total_species) :: species_counters
    integer, dimension(:,:), allocatable :: species_unique
    integer, dimension(:,:,:), allocatable :: at_sp_id
    integer, dimension(:), allocatable :: fragment_atoms
    real(dp) :: charge
    real(dp), dimension(3) :: origin
    logical :: found
    logical :: overlapped
    type(atom_type), dimension(:), allocatable :: subsystem_atoms
    type(multipoles_type), allocatable :: multipoles
    type(map_type) :: map
    type(bond_type), dimension(:,:), allocatable :: temp_bonds
    type(angle_type), dimension(:,:), allocatable :: temp_angles
    call timer_start("mimic_allocate_mm_struct")
    origin(:) = 0
    allocate(temp_bonds(maxval(sizes%nbonds_pcode), communicator%num_clients), stat=alloc_stat)
    if (alloc_stat /= 0) then
        call handle_error(SEVERITY_FATAL, &
                          TYPE_MEM, &
                          "temp_bonds", &
                          __FILE__, __LINE__)
    endif
    allocate(temp_angles(maxval(sizes%nangles_pcode), communicator%num_clients), stat=alloc_stat)
    if (alloc_stat /= 0) then
        call handle_error(SEVERITY_FATAL, &
                          TYPE_MEM, &
                          "temp_angles", &
                          __FILE__, __LINE__)
    endif
    if (allocated(system_data%bonds)) then
        temp_bonds(:,:) = system_data%bonds(:,:)
    end if
    if (allocated(system_data%angles)) then
        temp_angles(:,:) = system_data%angles(:,:)
    end if
    call unique_entries(system_data%species, species_unique)
    species_counters(:) = 1
    if (size(species_unique) > 0) then
        sp_offset = size(num_qm_atoms)
        do n_code = 1, communicator%num_clients
            code_offset(n_code) = sp_offset
            sp_offset = sp_offset + size(pack(species_unique(:, n_code), mask = (species_unique(:, n_code) /= -1)))
        end do
    endif
    allocate(at_sp_id(2, maxval(sizes%atoms_pcode, 1), communicator%num_clients + 1), stat=alloc_stat)
    if (alloc_stat /= 0) then
        call handle_error(SEVERITY_FATAL, &
                          TYPE_MEM, &
                          "at_sp_id", &
                          __FILE__, __LINE__)
    endif
    at_sp_id(:,:,:) = 0
    id_offset = 1
    do n_species = 1, size(num_qm_atoms)
        do n_atom = 1, num_qm_atoms(n_species)
            at_sp_id(2, id_offset, 1) = n_atom
            at_sp_id(1, id_offset, 1) = n_species
            id_offset = id_offset + 1
        end do
    end do
    do n_code = 1, communicator%num_clients
        do n_atom = 1, sizes%atoms_pcode(n_code)
            found = .false.
            atom_species = system_data%species(n_atom, n_code)
            if (atom_species == -1) then
                cycle
            end if
            do n_species = 1, size(species_unique(:, n_code))
                if (species_unique(n_species, n_code) /= -1 &
                    .and. atom_species == species_unique(n_species, n_code)) then
                    found = .true.
                    spid = system_data%species_map(atom_species, n_code) + code_offset(1)
                    atid = species_counters(spid)
                    species_counters(spid) =  species_counters(spid) + 1
                    at_sp_id(1, n_atom, n_code + 1) = spid
                    at_sp_id(2, n_atom, n_code + 1) = atid
                    exit
                end if
            end do ! n_species
            if (.not. found) then
                call handle_error(SEVERITY_FATAL, &
                                  TYPE_INCORRECT_ARG, &
                                  "Unrecognized atom type is encountered", &
                                  __FILE__, __LINE__)
            endif
        end do ! n_atom
    end do ! n_code
    do n_code = 1, communicator%num_clients
        allocate(fragment_atoms(0:sizes%frag_num(n_code)), stat=alloc_stat)
        if (alloc_stat /= 0) then
            call handle_error(SEVERITY_FATAL, &
                              TYPE_MEM, &
                              "fragment_atoms", &
                              __FILE__, __LINE__)
        endif
        allocate(subsystem_atoms(sizes%atoms_pcode(n_code)), stat=alloc_stat)
        if (alloc_stat /= 0) then
            call handle_error(SEVERITY_FATAL, &
                              TYPE_MEM, &
                              "subsystem_atoms", &
                              __FILE__, __LINE__)
        endif
        fragment_atoms(0) = 0
        atom_index = 1
        id_offset = 0
        do n_fragment = 1, sizes%frag_num(n_code)
            n_atoms = sizes%atoms_pfragment(n_fragment, n_code)
            spid = -1
            do n_atom = 1, n_atoms
                id = system_data%atom_fragment_ids(n_atom, n_fragment, n_code)
                atom_species = system_data%species(id, n_code)
                overlapped = .false.
                if (atom_species == -1) then
                    do n_map = 1, size(communicator%overlap_maps(n_code)%maps)
                        if (id == communicator%overlap_maps(n_code)%maps(n_map)%id) then
                            target_code = communicator%overlap_maps(n_code)%maps(n_map)%codes(1)
                            map = communicator%overlap_maps(n_code)%maps(n_map)
                            spid = at_sp_id(1, map%atoms(1), target_code)
                            atid = at_sp_id(2, map%atoms(1), target_code)
                            overlapped = .true.
                        end if
                    end do ! n_map
                else
                    spid = at_sp_id(1, id, n_code + 1)
                    atid = at_sp_id(2, id, n_code + 1)
                end if
                charge = system_data%multipole_values(1, id, n_code)
                allocate(multipoles)
                call multipoles%init(n_atom, origin, sizes%multipoles_order(n_code), system_data%multipole_values(1:sizes%multipoles_patom(n_code), id_offset + n_atom, n_code))
                call subsystem_atoms(atom_index)%init(system_data%atom_fragment_ids(n_atom, n_fragment, n_code), &
                                                      spid, n_atom, charge, cov_radii(spid), &
                                                      tau(:, atid, spid), force(:, atid, spid), multipoles, overlapped)
                deallocate(multipoles)
                fragment_atoms(n_fragment) = atom_index
                atom_index = atom_index + 1
                !! @todo Some extraodinary ugly code here - refactor ASAP
                do n_bond = 1, sizes%nbonds_pcode(n_code)
                    if (system_data%bonds(n_bond, n_code)%atom_i == id) then
                        if (spid > size(num_qm_atoms)) then
                            temp_bonds(n_bond, n_code)%atom_i = sum(num_qm_atoms) + &
                                        sum(sizes%atoms_pspecies(1:spid - size(num_qm_atoms) - 1), n_code) + &
                                        atid
                        else
                            temp_bonds(n_bond, n_code)%atom_i = sum(num_qm_atoms(1:spid - 1)) + atid
                        end if
                    end if
                    if (system_data%bonds(n_bond, n_code)%atom_j == id) then
                        if (spid > size(num_qm_atoms)) then
                            temp_bonds(n_bond, n_code)%atom_j = sum(num_qm_atoms) + &
                                        sum(sizes%atoms_pspecies(1:spid - size(num_qm_atoms) - 1), n_code) + &
                                        atid
                        else
                            temp_bonds(n_bond, n_code)%atom_j = sum(num_qm_atoms(1:spid - 1)) + atid
                        end if
                    end if
                end do !n_bond
                do n_angle = 1, sizes%nangles_pcode(n_code)
                    if (system_data%angles(n_angle, n_code)%atom_i == id) then
                        if (spid > size(num_qm_atoms)) then
                            temp_angles(n_angle, n_code)%atom_i = sum(num_qm_atoms) + &
                                        sum(sizes%atoms_pspecies(1:spid - size(num_qm_atoms) - 1), n_code) + &
                                        atid
                        else
                            temp_angles(n_angle, n_code)%atom_i = sum(num_qm_atoms(1:spid - 1)) + atid
                        end if
                    end if
                    if (system_data%angles(n_angle, n_code)%atom_j == id) then
                        if (spid > size(num_qm_atoms)) then
                            temp_angles(n_angle, n_code)%atom_j = sum(num_qm_atoms) + &
                                        sum(sizes%atoms_pspecies(1:spid - size(num_qm_atoms) - 1), n_code) + &
                                        atid
                        else
                            temp_angles(n_angle, n_code)%atom_j = sum(num_qm_atoms(1:spid - 1)) + atid
                        end if
                    end if
                    if (system_data%angles(n_angle, n_code)%atom_k == id) then
                        if (spid > size(num_qm_atoms)) then
                            temp_angles(n_angle, n_code)%atom_k = sum(num_qm_atoms) + &
                                        sum(sizes%atoms_pspecies(1:spid - size(num_qm_atoms) - 1), n_code) + &
                                        atid
                        else
                            temp_angles(n_angle, n_code)%atom_k = sum(num_qm_atoms(1:spid - 1)) + atid
                        end if
                    end if
                end do ! n_angle
            end do ! n_atom
            id_offset = id_offset + n_atoms
        end do ! n_fragment
        call subsystems(n_code)%init(n_code, factors(n_code), subsystem_atoms)
        call subsystems(n_code)%define_fragments(sizes%frag_num(n_code), fragment_atoms)
        deallocate(fragment_atoms)
        deallocate(subsystem_atoms)
    end do ! n_client
    if (maxval(sizes%nbonds_pcode) > 0) then
        system_data%bonds = temp_bonds
    end if
    if (maxval(sizes%nangles_pcode) > 0) then
        system_data%angles = temp_angles
    end if
    call timer_stop
end subroutine mimic_allocate_mm_struct