Commit 6365dcb2 authored by Youngsung Kim's avatar Youngsung Kim
Browse files

added following four mpas ocn kernels

ocn_surface_bulk_forcing_vel
ocn_time_integrator_split_part1
ocn_vel_hadv_coriolis_tend
ocn_vel_vadv_tend
parent 6daa105f
#!/usr/bin/env python
import sys, os, re
workdir = os.path.argpath(sys.argv[1]) if len(sys.argv) > 1 else os.getcwd()
if os.path.isdir(workdir):
print("ERROR: '%s' does not exist." % workdir)
exit(-1)
# TODO: glob to re
for name in glob.glob(os.path.join(workdir, "*")):
print(name)
vi kgen_statefile.lst
:%s/$/\.dat/g
for f in `ls ocn_time_integrator_split_part1.*`; do mv $f $f.dat; done
# Makefile for KGEN-generated kernel
FC_0 := /autofs/nccs-svm1_sw/summit/.swci/0-core/opt/spack/20180914/linux-rhel7-ppc64le/gcc-4.8.5/pgi-19.9-6rlh73dtf3lmbm6v7r3fkh7tnbeq53hc/linuxpower/19.9/bin/pgfortran
ALL_OBJS := mpas_ocn_surface_bulk_forcing.o mpas_kind_types.o kernel_driver.o kgen_utils.o
build: ${ALL_OBJS}
${FC_0} ${FC_FLAGS_SET_0} -o kernel.exe $^
run: build
./kernel.exe
mpas_ocn_surface_bulk_forcing.o: mpas_ocn_surface_bulk_forcing.f90 mpas_kind_types.o kgen_utils.o
${FC_0} ${FC_FLAGS_SET_0} -c -o $@ $<
mpas_kind_types.o: mpas_kind_types.f90 kgen_utils.o
${FC_0} ${FC_FLAGS_SET_0} -c -o $@ $<
kernel_driver.o: kernel_driver.f90 mpas_ocn_surface_bulk_forcing.o mpas_kind_types.o kgen_utils.o
${FC_0} ${FC_FLAGS_SET_0} -c -o $@ $<
kgen_utils.o: kgen_utils.f90
${FC_0} ${FC_FLAGS_SET_0} -c -o $@ $<
${FC_0} ${FC_FLAGS_SET_0} -c -o $@ $<
clean:
rm -f kernel.exe *.mod ${ALL_OBJS}
!KGEN-generated Fortran source file
!Generated at : 2021-02-28 17:07:46
!KGEN version : 0.9.0
PROGRAM kernel_driver
USE kgen_utils_mod, ONLY: kgen_get_newunit, kgen_error_stop, kgen_dp, kgen_array_sumcheck, kgen_rankthreadinvoke
USE ocn_surface_bulk_forcing, ONLY: ocn_surface_bulk_forcing_vel
USE mpas_kind_types, ONLY: rkind
IMPLICIT NONE
LOGICAL :: kgen_isverified
INTEGER :: kgen_ierr_list, kgen_unit_list
INTEGER :: kgen_ierr, kgen_unit, kgen_case_count, kgen_count_verified
CHARACTER(LEN=1024) :: kgen_filepath
REAL(KIND=kgen_dp) :: kgen_measure, kgen_total_time, kgen_min_time, kgen_max_time
REAL(KIND=8) :: kgen_array_sum
INTEGER :: kgen_mpirank, kgen_openmptid, kgen_kernelinvoke
INTEGER :: myrank, mpisize
LOGICAL :: kgen_evalstage, kgen_warmupstage, kgen_mainstage
COMMON / kgen_state / kgen_mpirank, kgen_openmptid, kgen_kernelinvoke, kgen_evalstage, kgen_warmupstage, kgen_mainstage
REAL(KIND=rkind), DIMENSION(:), ALLOCATABLE :: surfacestress
REAL(KIND=rkind), DIMENSION(:), ALLOCATABLE :: surfacestressmagnitude
myrank = 0
mpisize = 1
kgen_total_time = 0.0_kgen_dp
kgen_min_time = HUGE(0.0_kgen_dp)
kgen_max_time = 0.0_kgen_dp
kgen_case_count = 0
kgen_count_verified = 0
kgen_unit_list = kgen_get_newunit()
OPEN (UNIT=kgen_unit_list, FILE="kgen_statefile.lst", STATUS="OLD", IOSTAT=kgen_ierr_list)
IF (kgen_ierr_list .NE. 0) THEN
CALL SYSTEM("ls -1 ocn_surface_bulk_forcing_vel.*.*.* > kgen_statefile.lst")
CALL SLEEP(1)
kgen_unit_list = kgen_get_newunit()
OPEN (UNIT=kgen_unit_list, FILE="kgen_statefile.lst", STATUS="OLD", IOSTAT=kgen_ierr_list)
END IF
IF (kgen_ierr_list .NE. 0) THEN
IF (myrank == 0) THEN
WRITE (*, *) ""
WRITE (*, *) "ERROR: ""kgen_statefile.lst"" is not found in current directory."
END IF
STOP
END IF
DO WHILE ( kgen_ierr_list .EQ. 0 )
READ (UNIT = kgen_unit_list, FMT="(A)", IOSTAT=kgen_ierr_list) kgen_filepath
IF (kgen_ierr_list .EQ. 0) THEN
kgen_unit = kgen_get_newunit()
CALL kgen_rankthreadinvoke(TRIM(ADJUSTL(kgen_filepath)), kgen_mpirank, kgen_openmptid, kgen_kernelinvoke)
OPEN (UNIT=kgen_unit, FILE=TRIM(ADJUSTL(kgen_filepath)), STATUS="OLD", ACCESS="STREAM", FORM="UNFORMATTED", &
&ACTION="READ", CONVERT="BIG_ENDIAN", IOSTAT=kgen_ierr)
IF (kgen_ierr == 0) THEN
IF (myrank == 0) THEN
WRITE (*, *) ""
WRITE (*, *) "***************** Verification against '" // trim(adjustl(kgen_filepath)) // "' &
&*****************"
END IF
kgen_evalstage = .TRUE.
kgen_warmupstage = .FALSE.
kgen_mainstage = .FALSE.
!driver read in arguments
CALL kr_kgen_ocn_surface_bulk_forcing_vel_subp0(surfacestress, kgen_unit, "surfacestress", .FALSE.)
CALL kr_kgen_ocn_surface_bulk_forcing_vel_subp0(surfacestressmagnitude, kgen_unit, "surfacestressmagnitude", &
&.FALSE.)
!extern input variables
!callsite part
CALL ocn_surface_bulk_forcing_vel(kgen_unit, kgen_measure, kgen_isverified, kgen_filepath, surfacestress, &
&surfacestressmagnitude)
REWIND (UNIT=kgen_unit)
kgen_evalstage = .FALSE.
kgen_warmupstage = .TRUE.
kgen_mainstage = .FALSE.
!driver read in arguments
CALL kr_kgen_ocn_surface_bulk_forcing_vel_subp0(surfacestress, kgen_unit, "surfacestress", .FALSE.)
CALL kr_kgen_ocn_surface_bulk_forcing_vel_subp0(surfacestressmagnitude, kgen_unit, "surfacestressmagnitude", &
&.FALSE.)
!extern input variables
!callsite part
CALL ocn_surface_bulk_forcing_vel(kgen_unit, kgen_measure, kgen_isverified, kgen_filepath, surfacestress, &
&surfacestressmagnitude)
REWIND (UNIT=kgen_unit)
kgen_evalstage = .FALSE.
kgen_warmupstage = .FALSE.
kgen_mainstage = .TRUE.
kgen_case_count = kgen_case_count + 1
kgen_isverified = .FALSE.
!driver read in arguments
CALL kr_kgen_ocn_surface_bulk_forcing_vel_subp0(surfacestress, kgen_unit, "surfacestress", .FALSE.)
CALL kr_kgen_ocn_surface_bulk_forcing_vel_subp0(surfacestressmagnitude, kgen_unit, "surfacestressmagnitude", &
&.FALSE.)
!extern input variables
!callsite part
CALL ocn_surface_bulk_forcing_vel(kgen_unit, kgen_measure, kgen_isverified, kgen_filepath, surfacestress, &
&surfacestressmagnitude)
kgen_total_time = kgen_total_time + kgen_measure
kgen_min_time = MIN( kgen_min_time, kgen_measure )
kgen_max_time = MAX( kgen_max_time, kgen_measure )
IF (kgen_isverified) THEN
kgen_count_verified = kgen_count_verified + 1
END IF
END IF
CLOSE (UNIT=kgen_unit)
END IF
END DO
CLOSE (UNIT=kgen_unit_list)
IF (myrank == 0) THEN
WRITE (*, *) ""
WRITE (*, "(A)") "****************************************************"
WRITE (*, "(4X,A)") "kernel execution summary: ocn_surface_bulk_forcing_vel"
WRITE (*, "(A)") "****************************************************"
IF (kgen_case_count == 0) THEN
WRITE (*, *) "No data file is verified."
ELSE
WRITE (*, "(4X, A36, A1, I6)") "Total number of verification cases ", ":", kgen_case_count
WRITE (*, "(4X, A36, A1, I6)") "Number of verification-passed cases ", ":", kgen_count_verified
WRITE (*, *) ""
IF (kgen_case_count == kgen_count_verified) THEN
WRITE (*, "(4X,A)") "kernel: ocn_surface_bulk_forcing_vel: PASSED verification"
ELSE
WRITE (*, "(4X,A)") "kernel: ocn_surface_bulk_forcing_vel: FAILED verification"
END IF
WRITE (*, *) ""
WRITE (*, "(4X,A19,I3)") "number of processes: ", mpisize
WRITE (*, *) ""
WRITE (*, "(4X, A, E10.3)") "Average call time (usec): ", kgen_total_time / DBLE(kgen_case_count)
WRITE (*, "(4X, A, E10.3)") "Minimum call time (usec): ", kgen_min_time
WRITE (*, "(4X, A, E10.3)") "Maximum call time (usec): ", kgen_max_time
END IF
WRITE (*, "(A)") "****************************************************"
END IF
CONTAINS
!read state subroutine for kr_kgen_ocn_surface_bulk_forcing_vel_subp0
SUBROUTINE kr_kgen_ocn_surface_bulk_forcing_vel_subp0(var, kgen_unit, printname, printvar)
REAL(KIND=rkind), INTENT(INOUT), ALLOCATABLE, DIMENSION(:) :: var
INTEGER, INTENT(IN) :: kgen_unit
CHARACTER(LEN=*), INTENT(IN) :: printname
LOGICAL, INTENT(IN), OPTIONAL :: printvar
LOGICAL :: kgen_istrue
REAL(KIND=8) :: kgen_array_sum
INTEGER :: idx1
INTEGER, DIMENSION(2,1) :: kgen_bound
READ (UNIT = kgen_unit) kgen_istrue
IF (kgen_istrue) THEN
IF (ALLOCATED( var )) THEN
DEALLOCATE (var)
END IF
READ (UNIT = kgen_unit) kgen_array_sum
READ (UNIT = kgen_unit) kgen_bound(1, 1)
READ (UNIT = kgen_unit) kgen_bound(2, 1)
ALLOCATE (var(kgen_bound(1,1):kgen_bound(2,1)))
READ (UNIT = kgen_unit) var
CALL kgen_array_sumcheck(printname, kgen_array_sum, DBLE(SUM(var, mask=(var .eq. var))), .TRUE.)
IF (PRESENT( printvar ) .AND. printvar) THEN
WRITE (*, *) "KGEN DEBUG: DBLE(SUM(" // printname // ")) = ", DBLE(SUM(var, mask=(var .eq. var)))
END IF
END IF
END SUBROUTINE kr_kgen_ocn_surface_bulk_forcing_vel_subp0
END PROGRAM
BLOCK DATA KGEN
INTEGER :: kgen_mpirank = 0, kgen_openmptid = 0, kgen_kernelinvoke = 0
LOGICAL :: kgen_evalstage = .TRUE., kgen_warmupstage = .FALSE., kgen_mainstage = .FALSE.
COMMON / kgen_state / kgen_mpirank, kgen_openmptid, kgen_kernelinvoke, kgen_evalstage, kgen_warmupstage, kgen_mainstage
END BLOCK DATA KGEN
\ No newline at end of file
ocn_surface_bulk_forcing_vel.40.0.1.dat
ocn_surface_bulk_forcing_vel.36.0.1.dat
ocn_surface_bulk_forcing_vel.14.0.1.dat
ocn_surface_bulk_forcing_vel.26.0.1.dat
ocn_surface_bulk_forcing_vel.52.0.1.dat
ocn_surface_bulk_forcing_vel.58.0.1.dat
ocn_surface_bulk_forcing_vel.33.0.1.dat
ocn_surface_bulk_forcing_vel.63.0.1.dat
ocn_surface_bulk_forcing_vel.32.0.1.dat
ocn_surface_bulk_forcing_vel.2.0.1.dat
ocn_surface_bulk_forcing_vel.42.0.1.dat
ocn_surface_bulk_forcing_vel.56.0.1.dat
ocn_surface_bulk_forcing_vel.61.0.1.dat
ocn_surface_bulk_forcing_vel.60.0.1.dat
ocn_surface_bulk_forcing_vel.11.0.1.dat
ocn_surface_bulk_forcing_vel.43.0.1.dat
ocn_surface_bulk_forcing_vel.30.0.1.dat
ocn_surface_bulk_forcing_vel.22.0.1.dat
ocn_surface_bulk_forcing_vel.9.0.1.dat
ocn_surface_bulk_forcing_vel.6.0.1.dat
ocn_surface_bulk_forcing_vel.7.0.1.dat
ocn_surface_bulk_forcing_vel.51.0.1.dat
ocn_surface_bulk_forcing_vel.20.0.1.dat
ocn_surface_bulk_forcing_vel.38.0.1.dat
ocn_surface_bulk_forcing_vel.16.0.1.dat
ocn_surface_bulk_forcing_vel.48.0.1.dat
ocn_surface_bulk_forcing_vel.4.0.1.dat
ocn_surface_bulk_forcing_vel.31.0.1.dat
ocn_surface_bulk_forcing_vel.35.0.1.dat
ocn_surface_bulk_forcing_vel.41.0.1.dat
ocn_surface_bulk_forcing_vel.49.0.1.dat
ocn_surface_bulk_forcing_vel.27.0.2.dat
ocn_surface_bulk_forcing_vel.50.0.1.dat
ocn_surface_bulk_forcing_vel.23.0.1.dat
ocn_surface_bulk_forcing_vel.28.0.1.dat
ocn_surface_bulk_forcing_vel.35.0.2.dat
ocn_surface_bulk_forcing_vel.52.0.2.dat
ocn_surface_bulk_forcing_vel.10.0.2.dat
ocn_surface_bulk_forcing_vel.60.0.2.dat
ocn_surface_bulk_forcing_vel.16.0.2.dat
MODULE kgen_utils_mod
INTEGER, PARAMETER :: kgen_dp = selected_real_kind(15, 307)
INTEGER, PARAMETER :: CHECK_IDENTICAL = 1
INTEGER, PARAMETER :: CHECK_IN_TOL = 2
INTEGER, PARAMETER :: CHECK_OUT_TOL = 3
REAL(kind=kgen_dp) :: kgen_tolerance = 1.0D-15, kgen_minvalue = 1.0D-15
INTEGER :: kgen_verboselevel = 1
interface kgen_tostr
module procedure kgen_tostr_args1
module procedure kgen_tostr_args2
module procedure kgen_tostr_args3
module procedure kgen_tostr_args4
module procedure kgen_tostr_args5
module procedure kgen_tostr_args6
end interface
! PERTURB: add following interface
interface kgen_perturb_real
module procedure kgen_perturb_real4_dim1
module procedure kgen_perturb_real4_dim2
module procedure kgen_perturb_real4_dim3
module procedure kgen_perturb_real8_dim1
module procedure kgen_perturb_real8_dim2
module procedure kgen_perturb_real8_dim3
end interface
type check_t
logical :: Passed
integer :: numOutTol
integer :: numTotal
integer :: numIdentical
integer :: numInTol
integer :: rank
end type check_t
public kgen_dp, check_t, kgen_init_verify, kgen_init_check, kgen_tolerance
public kgen_minvalue, kgen_verboselevel, kgen_print_check, kgen_perturb_real
public CHECK_NOT_CHECKED, CHECK_IDENTICAL, CHECK_IN_TOL, CHECK_OUT_TOL
public kgen_get_newunit, kgen_error_stop
CONTAINS
subroutine kgen_array_sumcheck(varname, sum1, sum2, finish)
character(*), intent(in) :: varname
real(kind=8), intent(in) :: sum1, sum2
real(kind=8), parameter :: max_rel_diff = 1.E-10
real(kind=8) :: diff, rel_diff
logical, intent(in), optional :: finish
logical checkresult
if ( sum1 == sum2 ) then
checkresult = .TRUE.
else
checkresult = .FALSE.
diff = ABS(sum2 - sum1)
if ( .NOT. (sum1 == 0._8) ) then
rel_diff = ABS(diff / sum1)
if ( rel_diff > max_rel_diff ) then
print *, ''
print *, 'SUM of array, "', varname, '", is different.'
print *, 'From file : ', sum1
print *, 'From array: ', sum2
print *, 'Difference: ', diff
print *, 'Normalized difference: ', rel_diff
if ( present(finish) .AND. finish ) then
stop
end if
end if
else
print *, ''
print *, 'SUM of array, "', varname, '", is different.'
print *, 'From file : ', sum1
print *, 'From array: ', sum2
print *, 'Difference: ', diff
if ( present(finish) .AND. finish ) then
stop
end if
end if
end if
end subroutine
function kgen_tostr_args1(idx1) result(tostr)
integer, intent(in) :: idx1
character(len=64) :: str_idx1
character(len=64) :: tostr
write(str_idx1, *) idx1
tostr = trim(adjustl(str_idx1))
end function
function kgen_tostr_args2(idx1, idx2) result(tostr)
integer, intent(in) :: idx1, idx2
character(len=64) :: str_idx1, str_idx2
character(len=128) :: tostr
write(str_idx1, *) idx1
write(str_idx2, *) idx2
tostr = trim(adjustl(str_idx1)) // ", " // trim(adjustl(str_idx2))
end function
function kgen_tostr_args3(idx1, idx2, idx3) result(tostr)
integer, intent(in) :: idx1, idx2, idx3
character(len=64) :: str_idx1, str_idx2, str_idx3
character(len=192) :: tostr
write(str_idx1, *) idx1
write(str_idx2, *) idx2
write(str_idx3, *) idx3
tostr = trim(adjustl(str_idx1)) // ", " // trim(adjustl(str_idx2)) &
// ", " // trim(adjustl(str_idx3))
end function
function kgen_tostr_args4(idx1, idx2, idx3, idx4) result(tostr)
integer, intent(in) :: idx1, idx2, idx3, idx4
character(len=64) :: str_idx1, str_idx2, str_idx3, str_idx4
character(len=256) :: tostr
write(str_idx1, *) idx1
write(str_idx2, *) idx2
write(str_idx3, *) idx3
write(str_idx4, *) idx4
tostr = trim(adjustl(str_idx1)) // ", " // trim(adjustl(str_idx2)) &
// ", " // trim(adjustl(str_idx3)) // ", " // trim(adjustl(str_idx4))
end function
function kgen_tostr_args5(idx1, idx2, idx3, idx4, idx5) result(tostr)
integer, intent(in) :: idx1, idx2, idx3, idx4, idx5
character(len=64) :: str_idx1, str_idx2, str_idx3, str_idx4, str_idx5
character(len=320) :: tostr
write(str_idx1, *) idx1
write(str_idx2, *) idx2
write(str_idx3, *) idx3
write(str_idx4, *) idx4
write(str_idx5, *) idx5
tostr = trim(adjustl(str_idx1)) // ", " // trim(adjustl(str_idx2)) &
// ", " // trim(adjustl(str_idx3)) // ", " // trim(adjustl(str_idx4)) &
// ", " // trim(adjustl(str_idx5))
end function
function kgen_tostr_args6(idx1, idx2, idx3, idx4, idx5, idx6) result(tostr)
integer, intent(in) :: idx1, idx2, idx3, idx4, idx5, idx6
character(len=64) :: str_idx1, str_idx2, str_idx3, str_idx4, str_idx5, str_idx6
character(len=384) :: tostr
write(str_idx1, *) idx1
write(str_idx2, *) idx2
write(str_idx3, *) idx3
write(str_idx4, *) idx4
write(str_idx5, *) idx5
write(str_idx6, *) idx6
tostr = trim(adjustl(str_idx1)) // ", " // trim(adjustl(str_idx2)) &
// ", " // trim(adjustl(str_idx3)) // ", " // trim(adjustl(str_idx4)) &
// ", " // trim(adjustl(str_idx5)) // ", " // trim(adjustl(str_idx6))
end function
subroutine kgen_perturb_real4_dim1(var, pertlim)
real*4, intent(inout), dimension(:) :: var
real*4, intent(in) :: pertlim
integer, allocatable :: rndm_seed(:)
integer :: rndm_seed_sz
real*4 :: pertval
integer :: idx1
call random_seed(size=rndm_seed_sz)
allocate(rndm_seed(rndm_seed_sz))
rndm_seed = 121869
call random_seed(put=rndm_seed)
do idx1=1,size(var, dim=1)
call random_number(pertval)
pertval = 2.0_4*pertlim*(0.5_4 - pertval)
var(idx1) = var(idx1)*(1.0_4 + pertval)
end do
deallocate(rndm_seed)
end subroutine
subroutine kgen_perturb_real4_dim2(var, pertlim)
real*4, intent(inout), dimension(:,:) :: var
real*4, intent(in) :: pertlim
integer, allocatable :: rndm_seed(:)
integer :: rndm_seed_sz
real*4 :: pertval
integer :: idx1,idx2
call random_seed(size=rndm_seed_sz)
allocate(rndm_seed(rndm_seed_sz))
rndm_seed = 121869
call random_seed(put=rndm_seed)
do idx1=1,size(var, dim=1)
do idx2=1,size(var, dim=2)
call random_number(pertval)
pertval = 2.0_4*pertlim*(0.5_4 - pertval)
var(idx1,idx2) = var(idx1,idx2)*(1.0_4 + pertval)
end do
end do
deallocate(rndm_seed)
end subroutine
subroutine kgen_perturb_real4_dim3(var, pertlim)
real*4, intent(inout), dimension(:,:,:) :: var
real*4, intent(in) :: pertlim
integer, allocatable :: rndm_seed(:)
integer :: rndm_seed_sz
real*4 :: pertval
integer :: idx1,idx2,idx3
call random_seed(size=rndm_seed_sz)
allocate(rndm_seed(rndm_seed_sz))
rndm_seed = 121869
call random_seed(put=rndm_seed)
do idx1=1,size(var, dim=1)
do idx2=1,size(var, dim=2)
do idx3=1,size(var, dim=3)
call random_number(pertval)
pertval = 2.0_4*pertlim*(0.5_4 - pertval)
var(idx1,idx2,idx3) = var(idx1,idx2,idx3)*(1.0_4 + pertval)
end do
end do
end do
deallocate(rndm_seed)
end subroutine
subroutine kgen_perturb_real8_dim1(var, pertlim)
real*8, intent(inout), dimension(:) :: var
real*8, intent(in) :: pertlim
integer, allocatable :: rndm_seed(:)
integer :: rndm_seed_sz
real*8 :: pertval
integer :: idx1
call random_seed(size=rndm_seed_sz)
allocate(rndm_seed(rndm_seed_sz))
rndm_seed = 121869
call random_seed(put=rndm_seed)
do idx1=1,size(var, dim=1)
call random_number(pertval)
pertval = 2.0_8*pertlim*(0.5_8 - pertval)
var(idx1) = var(idx1)*(1.0_8 + pertval)
end do
deallocate(rndm_seed)
end subroutine
subroutine kgen_perturb_real8_dim2(var, pertlim)
real*8, intent(inout), dimension(:,:) :: var
real*8, intent(in) :: pertlim
integer, allocatable :: rndm_seed(:)
integer :: rndm_seed_sz
real*8 :: pertval
integer :: idx1,idx2
call random_seed(size=rndm_seed_sz)
allocate(rndm_seed(rndm_seed_sz))
rndm_seed = 121869
call random_seed(put=rndm_seed)
do idx1=1,size(var, dim=1)
do idx2=1,size(var, dim=2)
call random_number(pertval)
pertval = 2.0_8*pertlim*(0.5_8 - pertval)
var(idx1,idx2) = var(idx1,idx2)*(1.0_8 + pertval)
end do
end do
deallocate(rndm_seed)
end subroutine
subroutine kgen_perturb_real8_dim3(var, pertlim)
real*8, intent(inout), dimension(:,:,:) :: var
real*8, intent(in) :: pertlim
integer, allocatable :: rndm_seed(:)
integer :: rndm_seed_sz
real*8 :: pertval
integer :: idx1,idx2,idx3