TABLE OF CONTENTS
- ABINIT/m_eph_double_grid
- m_eph_double_grid/eph_double_grid_t
- m_sigmaph/eph_double_grid_bz2ibz
- m_sigmaph/eph_double_grid_free
- m_sigmaph/eph_double_grid_get_index
- m_sigmaph/eph_double_grid_get_mapping
- m_sigmaph/eph_double_grid_new
ABINIT/m_eph_double_grid [ Modules ]
NAME
m_eph_double_grid
FUNCTION
Structure and functions to create a double grid mapping
COPYRIGHT
Copyright (C) 2008-2024 ABINIT group (HM) This file is distributed under the terms of the GNU General Public License, see ~abinit/COPYING or http://www.gnu.org/copyleft/gpl.txt .
SOURCE
16 #if defined HAVE_CONFIG_H 17 #include "config.h" 18 #endif 19 20 #include "abi_common.h" 21 22 module m_eph_double_grid 23 24 use defs_basis 25 use m_errors 26 use m_ebands 27 use m_abicore 28 29 use defs_datatypes, only : ebands_t 30 use m_numeric_tools, only : wrap2_pmhalf 31 use m_symtk, only : mati3inv 32 use m_crystal, only : crystal_t 33 use m_kpts, only : kpts_timrev_from_kptopt !, listkk 34 use m_fstrings, only : itoa, sjoin 35 36 implicit none 37 38 private
m_eph_double_grid/eph_double_grid_t [ Types ]
[ Top ] [ m_eph_double_grid ] [ Types ]
NAME
eph_double_grid_t
FUNCTION
Double grid datatype for electron-phonon
SOURCE
52 type,public :: eph_double_grid_t 53 54 type(ebands_t) :: ebands_dense 55 ! ebands structure with the eigenvalues on the dense grid 56 ! TODO: Should be replaced by ebands_dense%eig to reduce memory requirements (occ, kpts ...) 57 58 integer :: coarse_nbz, dense_nbz, dense_nibz 59 60 real(dp),allocatable :: weights_dense(:) 61 !weights in the dense grid 62 63 integer,allocatable :: bz2ibz_coarse(:) 64 ! map full Brillouin zone to ibz (in the coarse grid) 65 66 integer,allocatable :: bz2ibz_dense(:) 67 ! map full Brillouin zone to ibz (in the dense grid) 68 69 integer :: nkpt_coarse(3), nkpt_dense(3) 70 ! size of the coarse and dense meshes 71 72 integer :: interp_kmult(3) 73 ! multiplicity of the meshes 74 75 integer :: ndiv = 1 76 ! ndiv = interp_kmult(1)*interp_kmult(2)*interp_kmult(3) 77 78 ! the integer indexes for the coarse grid are calculated for kk(3) with: 79 ! [mod(nint((kpt(1)+1)*self%nkpt_coarse(1)),self%nkpt_coarse(1))+1, 80 ! mod(nint((kpt(2)+1)*self%nkpt_coarse(2)),self%nkpt_coarse(2))+1, 81 ! mod(nint((kpt(3)+1)*self%nkpt_coarse(3)),self%nkpt_coarse(3))+1] 82 83 integer,allocatable :: indexes_to_coarse(:,:,:) 84 ! given integer indexes get the array index of the kpoint (coarse) 85 86 integer,allocatable :: coarse_to_indexes(:,:) 87 ! given the array index get the integer indexes of the kpoints (coarse) 88 89 integer,allocatable :: indexes_to_dense(:,:,:) 90 ! given integer indexes get the array index of the kpoint (dense) 91 92 integer,allocatable :: dense_to_indexes(:,:) 93 ! given the array index get the integer indexes of the kpoint (dense) 94 95 integer,allocatable :: coarse_to_dense(:,:) 96 ! map coarse to dense mesh (nbz_coarse,mult(interp_kmult)) 97 98 integer,allocatable :: bz2lgkibz(:) 99 ! map full brillouin zone of dense grid to a little group of k 100 101 integer,allocatable :: mapping(:,:) 102 ! map k, k+q and q in the IBZ and FBZ of the double grid structure 103 104 contains 105 106 procedure :: free => eph_double_grid_free 107 ! Free the double grid structure 108 109 procedure :: get_index => eph_double_grid_get_index 110 ! Get the index of the the kpoint in the double grid 111 112 procedure :: bz2ibz => eph_double_grid_bz2ibz 113 ! Map BZ to IBZ using the double grid structure 114 115 procedure :: get_mapping => eph_double_grid_get_mapping 116 ! Get a mapping of k, k+q and q to the BZ and IBZ of the double grid 117 118 end type eph_double_grid_t
m_sigmaph/eph_double_grid_bz2ibz [ Functions ]
[ Top ] [ m_sigmaph ] [ Functions ]
NAME
eph_double_grid_bz2ibz
FUNCTION
Map the points of the full to the irreducible Brillouin zone using the indexes grid used in the double grid structure
INPUTS
kpt_ibz: list of kpoints coordinated in the irreducible Brillouin zone nibz: number of points in the irreducible Brillouin zone symmat: symmetry operations nsym: number of symmetry operations bz2ibz: indexes mapping bz to ibz
OUTPUT
SOURCE
453 subroutine eph_double_grid_bz2ibz(self,kpt_ibz,nibz,symmat,nsym,bz2ibz,timrev,mapping,use_symrec) 454 455 class(eph_double_grid_t),intent(in) :: self 456 integer,intent(in) :: nibz, nsym 457 real(dp),intent(in) :: kpt_ibz(3,nibz) 458 integer,intent(in) :: symmat(3,3,nsym) 459 integer,intent(out):: bz2ibz(self%dense_nbz) 460 integer,intent(in) :: timrev 461 logical,optional,intent(in) :: use_symrec 462 integer,optional,intent(inout) :: mapping(self%dense_nbz,3) 463 464 !Local variables ------------------------ 465 integer :: isym, ik_ibz, ik_bz 466 real(dp) :: kpt(3), kpt_sym(3), wrap_kpt(3), shift 467 integer :: itimrev, timrev_used, counter 468 logical :: do_use_symrec 469 470 !************************************************************************ 471 472 timrev_used=timrev 473 474 do_use_symrec=.False. 475 if (present(use_symrec)) then 476 if (use_symrec) then 477 do_use_symrec=.True. 478 end if 479 end if 480 481 !call cwtime(cpu,wall,gflops,"start") 482 bz2ibz = 0 483 ! Loop over the star of q 484 counter = 0 485 outer: do itimrev=0,timrev_used 486 do isym=1,nsym 487 do ik_ibz=1,nibz 488 ! get coordinates of k point 489 kpt(:) = kpt_ibz(:,ik_ibz) 490 ! Get the symmetric of q 491 if (do_use_symrec) then 492 kpt_sym(:) = (1-2*itimrev)*matmul(symmat(:,:,isym),kpt) 493 else 494 kpt_sym(:) = (1-2*itimrev)*matmul(transpose(symmat(:,:,isym)),kpt) 495 endif 496 ! get the index of the ibz point in bz 497 call wrap2_pmhalf(kpt_sym(1),wrap_kpt(1),shift) 498 call wrap2_pmhalf(kpt_sym(2),wrap_kpt(2),shift) 499 call wrap2_pmhalf(kpt_sym(3),wrap_kpt(3),shift) 500 ik_bz = self%get_index(wrap_kpt, 2) 501 502 ! check if applying this symmetry operation to kpt gives kpt_dense 503 if (bz2ibz(ik_bz)==0) then 504 !if (((self%kpts_dense(1,ik_bz)-wrap_kpt(1))**2+& 505 ! (self%kpts_dense(2,ik_bz)-wrap_kpt(2))**2+& 506 ! (self%kpts_dense(3,ik_bz)-wrap_kpt(3))**2)<tol6) then 507 bz2ibz(ik_bz) = ik_ibz 508 if (present(mapping)) then 509 mapping(ik_bz,1) = isym 510 mapping(ik_bz,2) = itimrev 511 endif 512 counter = counter + 1 513 if (counter==self%dense_nbz) exit outer 514 !end if 515 end if 516 end do 517 end do 518 end do outer 519 520 !check 521 do ik_bz=1,self%dense_nbz 522 ABI_CHECK(bz2ibz(ik_bz).ne.0,'Mapping not found') 523 end do 524 525 end subroutine eph_double_grid_bz2ibz
m_sigmaph/eph_double_grid_free [ Functions ]
[ Top ] [ m_sigmaph ] [ Functions ]
NAME
FUNCTION
Free memory
INPUTS
SOURCE
367 subroutine eph_double_grid_free(self) 368 369 class(eph_double_grid_t),intent(inout) :: self 370 371 ABI_SFREE(self%weights_dense) 372 ABI_SFREE(self%bz2ibz_dense) 373 ABI_SFREE(self%coarse_to_dense) 374 ABI_SFREE(self%dense_to_indexes) 375 ABI_SFREE(self%indexes_to_dense) 376 ABI_SFREE(self%coarse_to_indexes) 377 ABI_SFREE(self%indexes_to_coarse) 378 ABI_SFREE(self%bz2lgkibz) 379 ABI_SFREE(self%mapping) 380 381 call ebands_free(self%ebands_dense) 382 383 end subroutine eph_double_grid_free
m_sigmaph/eph_double_grid_get_index [ Functions ]
[ Top ] [ m_sigmaph ] [ Functions ]
NAME
FUNCTION
Get the indeex of a certain k-point in the double grid
INPUTS
kpt=kpoint to be mapped (reduced coordinates) opt=Map to the coarse (1) or dense grid (2)
SOURCE
400 integer function eph_double_grid_get_index(self,kpt,opt) result(ikpt) 401 402 class(eph_double_grid_t),intent(in) :: self 403 integer,intent(in) :: opt 404 real(dp),intent(in) :: kpt(3) 405 406 !Local variables ------------------------ 407 real(dp) :: wrap_kpt(3), shift 408 409 ! ************************************************************************* 410 411 call wrap2_pmhalf(kpt(1),wrap_kpt(1),shift) 412 call wrap2_pmhalf(kpt(2),wrap_kpt(2),shift) 413 call wrap2_pmhalf(kpt(3),wrap_kpt(3),shift) 414 415 if (opt==1) then 416 ikpt = self%indexes_to_coarse(& 417 mod(nint((wrap_kpt(1)+2)*self%nkpt_coarse(1)),self%nkpt_coarse(1))+1,& 418 mod(nint((wrap_kpt(2)+2)*self%nkpt_coarse(2)),self%nkpt_coarse(2))+1,& 419 mod(nint((wrap_kpt(3)+2)*self%nkpt_coarse(3)),self%nkpt_coarse(3))+1) 420 else if (opt==2) then 421 ikpt = self%indexes_to_dense(& 422 mod(nint((wrap_kpt(1)+2)*self%nkpt_dense(1)),self%nkpt_dense(1))+1,& 423 mod(nint((wrap_kpt(2)+2)*self%nkpt_dense(2)),self%nkpt_dense(2))+1,& 424 mod(nint((wrap_kpt(3)+2)*self%nkpt_dense(3)),self%nkpt_dense(3))+1) 425 else 426 ABI_ERROR(sjoin("Error in eph_double_grid_get_index opt. Possible values are 1 or 2. Got", itoa(opt))) 427 endif 428 429 end function eph_double_grid_get_index
m_sigmaph/eph_double_grid_get_mapping [ Functions ]
[ Top ] [ m_sigmaph ] [ Functions ]
NAME
eph_double_grid_get_mapping
FUNCTION
Campute mapping of k, k+q and q to the indexes in the double grid structure
INPUTS
kk, kq, qpt: reduced coordinates of k, k+q and q to be mapped
OUTPUT
mapping: array with the mapping of k, k+q and q to the BZ and IBZ of the double grid structure
SOURCE
545 subroutine eph_double_grid_get_mapping(self,kk,kq,qpt) 546 547 !Arguments -------------------------------- 548 class(eph_double_grid_t),intent(inout) :: self 549 real(dp),intent(in) :: kk(3), kq(3), qpt(3) 550 551 !Variables -------------------------------- 552 integer :: jj 553 integer :: ik_bz, ikq_bz, iq_bz 554 integer :: ik_ibz_fine,iq_ibz_fine,ikq_ibz_fine,ik_bz_fine,ikq_bz_fine,iq_bz_fine 555 556 ik_bz = self%get_index(kk, 1) 557 ikq_bz = self%get_index(kq, 1) 558 iq_bz = self%get_index(qpt, 1) 559 560 ik_bz_fine = self%coarse_to_dense(ik_bz,1) 561 ik_ibz_fine = self%bz2ibz_dense(ik_bz_fine) 562 563 !fine grid around kq 564 do jj=1,self%ndiv 565 566 !kq 567 ikq_bz_fine = self%coarse_to_dense(ikq_bz,jj) 568 ikq_ibz_fine = self%bz2ibz_dense(ikq_bz_fine) 569 570 !qq 571 iq_bz_fine = self%coarse_to_dense(iq_bz,jj) 572 iq_ibz_fine = self%bz2ibz_dense(iq_bz_fine) 573 574 self%mapping(:, jj) = & 575 [ik_bz_fine, ikq_bz_fine, iq_bz_fine,& 576 ik_ibz_fine, ikq_ibz_fine, iq_ibz_fine] 577 enddo 578 579 end subroutine eph_double_grid_get_mapping
m_sigmaph/eph_double_grid_new [ Functions ]
[ Top ] [ m_sigmaph ] [ Functions ]
NAME
FUNCTION
Prepare Double grid integration double grid: ----------------- interp_kmult 2 |. .|.|.|.|. . .| side 1 |. x|.|x|.|. x .| size 3 (2*side+1) |. .|.|.|.|. . .| ----------------- triple grid: ------------------- interp_kmult 3 |. . .|. . .|. . .| side 1 |. x .|. x .|. x .| size 3 (2*side+1) |. . .|. . .|. . .| ------------------- quadruple grid: --------------------------- interp_kmult 4 |. . . .|.|. . .|.|. . . .| side 2 |. . . .|.|. . .|.|. . . .| size 5 (2*side+1) |. . x .|.|. x .|.|. x . .| |. . . .|.|. . .|.|. . . .| |. . . .|.|. . .|.|. . . .| --------------------------- . = double grid x = coarse grid The fine grid is used to evaluate the weights on the coarse grid The points of the fine grid are associated to the points of the coarse grid according to proximity The integration weights are returned on the coarse grid. Steps of the implementation 1. Get the fine k grid from file or interpolation (ebands_dense) 2. Find the matching between the k_coarse and k_dense using the double_grid object 3. Calculate the phonon frequencies on the dense mesh and store them on a array 4. Create an array to bring the points in the full brillouin zone to the irreducible brillouin zone 5. Create a scatter array between the points in the fine grid
INPUTS
SOURCE
176 type(eph_double_grid_t) function eph_double_grid_new(cryst, ebands_dense, kptrlatt_coarse, kptrlatt_dense) result(eph_dg) 177 178 !Arguments------------------------------- 179 type(crystal_t), intent(in) :: cryst 180 type(ebands_t), intent(in) :: ebands_dense 181 integer, intent(in) :: kptrlatt_coarse(3,3), kptrlatt_dense(3,3) 182 183 !Local variables ------------------------ 184 !integer,parameter :: sppoldbl1 = 1 185 integer :: i_dense,i_coarse,this_dense,i_subdense,i1,i2,i3,ii,jj,kk,timrev 186 integer :: nkpt_coarse(3), nkpt_dense(3), interp_kmult(3), interp_side(3) 187 !integer,allocatable :: indkk(:,:) 188 189 ! ************************************************************************* 190 191 timrev = kpts_timrev_from_kptopt(ebands_dense%kptopt) 192 193 nkpt_coarse(1) = kptrlatt_coarse(1,1) 194 nkpt_coarse(2) = kptrlatt_coarse(2,2) 195 nkpt_coarse(3) = kptrlatt_coarse(3,3) 196 nkpt_dense(1) = kptrlatt_dense(1,1) 197 nkpt_dense(2) = kptrlatt_dense(2,2) 198 nkpt_dense(3) = kptrlatt_dense(3,3) 199 200 eph_dg%dense_nbz = nkpt_dense(1)*nkpt_dense(2)*nkpt_dense(3) 201 eph_dg%coarse_nbz = nkpt_coarse(1)*nkpt_coarse(2)*nkpt_coarse(3) 202 interp_kmult = nkpt_dense/nkpt_coarse 203 eph_dg%interp_kmult = interp_kmult 204 eph_dg%nkpt_coarse = nkpt_coarse 205 eph_dg%nkpt_dense = nkpt_dense 206 call ebands_copy(ebands_dense, eph_dg%ebands_dense) 207 208 ! A microzone is the set of points in the fine grid belonging to a certain coarse point 209 ! we have to consider a side of a certain size around the coarse point 210 ! to make sure the microzone is centered around its point. 211 ! The fine points shared by multiple microzones should have weights 212 ! according to in how many microzones they appear 213 ! 214 ! this is integer division 215 interp_side = interp_kmult/2 216 217 eph_dg%ndiv = (2*interp_side(1)+1)*& 218 (2*interp_side(2)+1)*& 219 (2*interp_side(3)+1) 220 221 write(std_out,*) 'coarse: ', nkpt_coarse 222 write(std_out,*) 'fine: ', nkpt_dense 223 write(std_out,*) 'interp_kmult:', interp_kmult 224 write(std_out,*) 'ndiv: ', eph_dg%ndiv 225 226 ABI_CHECK(all(nkpt_dense(:) >= nkpt_coarse(:)), 'fine mesh is smaller than coarse mesh.') 227 228 ABI_MALLOC(eph_dg%coarse_to_dense, (eph_dg%coarse_nbz, eph_dg%ndiv)) 229 230 ABI_MALLOC(eph_dg%dense_to_indexes, (3, eph_dg%dense_nbz)) 231 ABI_MALLOC(eph_dg%indexes_to_dense, (nkpt_dense(1), nkpt_dense(2), nkpt_dense(3))) 232 233 ABI_MALLOC(eph_dg%coarse_to_indexes, (3, eph_dg%dense_nbz)) 234 ABI_MALLOC(eph_dg%indexes_to_coarse, (nkpt_coarse(1), nkpt_coarse(2), nkpt_coarse(3))) 235 236 ABI_MALLOC(eph_dg%bz2lgkibz, (eph_dg%dense_nbz)) 237 ABI_MALLOC(eph_dg%mapping, (6, eph_dg%ndiv)) 238 ABI_MALLOC(eph_dg%weights_dense, (eph_dg%dense_nbz)) 239 240 write(std_out,*) 'create fine to coarse mapping' 241 ! generate mapping of points in dense bz to the dense bz 242 ! coarse loop 243 i_dense = 0 244 i_coarse = 0 245 do kk=1,nkpt_coarse(3) 246 do jj=1,nkpt_coarse(2) 247 do ii=1,nkpt_coarse(1) 248 i_coarse = i_coarse + 1 249 !calculate reduced coordinates of point in coarse mesh 250 !eph_dg%kpts_coarse(:,i_coarse) = [dble(ii-1)/nkpt_coarse(1),& 251 ! dble(jj-1)/nkpt_coarse(2),& 252 ! dble(kk-1)/nkpt_coarse(3)] 253 !call wrap2_pmhalf(dble(ii-1)/nkpt_coarse(1),eph_dg%kpts_coarse(1,i_coarse),shift) 254 !call wrap2_pmhalf(dble(jj-1)/nkpt_coarse(2),eph_dg%kpts_coarse(2,i_coarse),shift) 255 !call wrap2_pmhalf(dble(kk-1)/nkpt_coarse(3),eph_dg%kpts_coarse(3,i_coarse),shift) 256 257 !create the fine mesh 258 do i3=1,interp_kmult(3) 259 do i2=1,interp_kmult(2) 260 do i1=1,interp_kmult(1) 261 i_dense = i_dense + 1 262 !calculate reduced coordinates of point in dense mesh 263 !eph_dg%kpts_dense(:,i_dense) = & 264 ! [dble((ii-1)*interp_kmult(1)+i1-1)/(nkpt_coarse(1)*interp_kmult(1)),& 265 ! dble((jj-1)*interp_kmult(2)+i2-1)/(nkpt_coarse(2)*interp_kmult(2)),& 266 ! dble((kk-1)*interp_kmult(3)+i3-1)/(nkpt_coarse(3)*interp_kmult(3))] 267 !call wrap2_pmhalf((dble(ii-1)*interp_kmult(1)+i1-1)/(nkpt_coarse(1)*interp_kmult(1)), & 268 ! eph_dg%kpts_dense(1,i_dense),shift) 269 !call wrap2_pmhalf((dble(jj-1)*interp_kmult(2)+i2-1)/(nkpt_coarse(2)*interp_kmult(2)), & 270 ! eph_dg%kpts_dense(2,i_dense),shift) 271 !call wrap2_pmhalf((dble(kk-1)*interp_kmult(3)+i3-1)/(nkpt_coarse(3)*interp_kmult(3)), & 272 ! eph_dg%kpts_dense(3,i_dense),shift) 273 274 !integer indexes mapping 275 eph_dg%indexes_to_dense((ii-1)*interp_kmult(1)+i1,& 276 (jj-1)*interp_kmult(2)+i2,& 277 (kk-1)*interp_kmult(3)+i3) = i_dense 278 eph_dg%dense_to_indexes(:,i_dense) = [(ii-1)*interp_kmult(1)+i1,& 279 (jj-1)*interp_kmult(2)+i2,& 280 (kk-1)*interp_kmult(3)+i3] 281 enddo 282 enddo 283 enddo 284 eph_dg%indexes_to_coarse(ii,jj,kk) = i_coarse 285 eph_dg%coarse_to_indexes(:,i_coarse) = [ii, jj, kk] 286 enddo 287 enddo 288 enddo 289 290 ! here we need to iterate again because we can have points of the dense grid 291 ! belonging to multiple coarse points 292 i_coarse = 0 293 do kk=1,nkpt_coarse(3) 294 do jj=1,nkpt_coarse(2) 295 do ii=1,nkpt_coarse(1) 296 i_coarse = i_coarse + 1 297 298 !create a mapping from coarse to dense 299 i_subdense = 0 300 do i3=-interp_side(3),interp_side(3) 301 do i2=-interp_side(2),interp_side(2) 302 do i1=-interp_side(1),interp_side(1) 303 i_subdense = i_subdense + 1 304 !integer indexes mapping 305 this_dense = eph_dg%indexes_to_dense(& 306 mod((ii-1)*interp_kmult(1)+i1+nkpt_dense(1),nkpt_dense(1))+1,& 307 mod((jj-1)*interp_kmult(2)+i2+nkpt_dense(2),nkpt_dense(2))+1,& 308 mod((kk-1)*interp_kmult(3)+i3+nkpt_dense(3),nkpt_dense(3))+1) 309 310 !array indexes mapping 311 eph_dg%coarse_to_dense(i_coarse,i_subdense) = this_dense 312 enddo 313 enddo 314 enddo 315 enddo 316 enddo 317 enddo 318 319 ABI_CHECK(i_dense == eph_dg%dense_nbz, 'fine mesh mapping is incomplete') 320 321 !calculate the weights of each fine point 322 !different methods to distribute the weights might lead to better convergence 323 !loop over coarse points 324 eph_dg%weights_dense = 0 325 do ii=1,eph_dg%coarse_nbz 326 !loop over points in the microzone 327 do jj=1,eph_dg%ndiv 328 i_dense = eph_dg%coarse_to_dense(ii,jj) 329 eph_dg%weights_dense(i_dense) = eph_dg%weights_dense(i_dense) + 1 330 end do 331 end do 332 !weights_dense is array, ndiv is scalar 333 eph_dg%weights_dense = 1/eph_dg%weights_dense/(interp_kmult(1)*interp_kmult(2)*interp_kmult(3)) 334 335 !3. 336 eph_dg%dense_nibz = ebands_dense%nkpt 337 338 !4. 339 write(std_out,*) 'map bz -> ibz' 340 ABI_MALLOC(eph_dg%bz2ibz_dense,(eph_dg%dense_nbz)) 341 call eph_double_grid_bz2ibz(eph_dg, ebands_dense%kptns, eph_dg%dense_nibz,& 342 cryst%symrel, cryst%nsym, eph_dg%bz2ibz_dense, timrev) 343 344 !ABI_MALLOC(indkk,(eph_dg%dense_nbz,6)) 345 !call listkk(dksqmax, cryst%gmet, indkk, ebands_dense%kptns, eph_dg%kpts_dense,& 346 ! eph_dg%dense_nibz, eph_dg%dense_nbz, cryst%nsym,& 347 ! sppoldbl1, cryst%symafm, cryst%symrel, timrev, use_symrec=.False.) 348 349 !do ii=1,eph_dg%dense_nbz 350 ! ABI_CHECK((indkk(ii,1)==eph_dg%bz2ibz_dense(ii)),'Unmatching indexes') 351 !end do 352 !ABI_FREE(indkk) 353 354 end function eph_double_grid_new