Amoeba as I once used it is described in ..\optimization\amoeba\AMOEBA.htm. It starts from the main code
void main(void)
{int nvar=4,itype,nvec,iter,itmax,nrefl;
double d2[47],d1[47][48],value[48], d0[47],pert,temp;
and it always sets
value[i]=ftbm(d2);
In this same document there is reference to the amoeba as a subroutine amsub. This came about because in subsequent work, I found the business of going to a main program awkward. The subroutine amsub, however, was written on the fly without consideration of some problems. These are
The routines tloc and loc are in loc.zip. The first part of tloc uses a Fortran equivaence statement to make D1, a one dimensional array and D2 a two dimensional array occupy the same locations in memory. Then
PARAMETER (MAXVAR=5)
DIMENSION D2(MAXVAR,MAXVAR)
DIMENSION D1(MAXVAR*MAXVAR)
DIMENSION KLOC(MAXVAR)
EQUIVALENCE (D1(1),D2(1,1))
LOGICAL IVORF(MAXVAR),LC
C *** test array order
DO I=1,MAXVAR
DO J=1,MAXVAR
D2(I,J)=100*I+J
ENDDO
ENDDO
D2 is set with the first variable moving fastest.
PRINT*,' D2 '
PRINT'(5G15.7)',((D2(I,J),I=1,MAXVAR),J=1,MAXVAR)
D2 is printed out in this same order
run
D2
101.0000 201.0000 301.0000 401.0000 501.0000
102.0000 202.0000 302.0000 402.0000 502.0000
103.0000 203.0000 303.0000 403.0000 503.0000
104.0000 204.0000 304.0000 404.0000 504.0000
105.0000 205.0000 305.0000 405.0000 505.0000
PRINT*,' D1 '
PRINT'(5G15.7)',D1
Then D1 is printed out in the order that the array is stored in memory
D1
101.0000 201.0000 301.0000 401.0000 501.0000
102.0000 202.0000 302.0000 402.0000 502.0000
103.0000 203.0000 303.0000 403.0000 503.0000
104.0000 204.0000 304.0000 404.0000 504.0000
105.0000 205.0000 305.0000 405.0000 505.0000
If these were not the same, I would still be working on the code.
In the next section the logical ivorf is set to true for the variables 2, 3, and 5 that are to be varied and left false for 1 and 4. Then D1 is filled with the relevant parts of D2, but packed so that only the relevant 2,3, and 5 parts of the array are stored.
D1 packed
202.0000 203.0000 205.0000
302.0000 303.0000 305.0000
502.0000 503.0000 505.0000
C TESTING LOOK UP
DO I=1,MAXVAR
IVORF(I)=.FALSE.
ENDDO
IVORF(2)=.TRUE.
IVORF(3)=.TRUE.
IVORF(5)=.TRUE.
K=0
DO I=1,MAXVAR
DO J=1,MAXVAR
D2(J,I)=0
IF(IVORF(I).AND.IVORF(J))THEN
K=K+1
D1(K)=J+100*I
ENDIF
ENDDO
ENDDO
NVAR2=K
p
LC=.FALSE.
5 CONTINUE
PRINT*,' ENTER I,J OR 0,0 TO STOP'
READ(*,*)I,J
IF(I.EQ.0)GOTO 10
KT=LOC(I,J,KLOC,IVORF,MAXVAR,NVAR,LC)
PRINT*,' KT, NVAR, LC ',KT,NVAR,LC
IF(KT.GT.0)PRINT*,' D2(',I,J,' )',D1(KT)
GOTO 5
10 STOP
END
The rest of the routine tests the function loc
ENTER I,J OR 0,0 TO STOP
1,1
2,1
2,2
D2(2,2) 202.0000000
3,2
D2(3,2) 203.0000000
2,5
D2(2,5) 502.0000000
5,2
D2(5,2) 205.0000000
C$INCLUDE LOC
The routine loc takes I,J and returns the K in the packed D1 corresponding to the unpacked D2(I,J). It uses a supplementary vector KLOC that lists the number of variable elements up to I. LOC is calculated using the standard Fortran formula. I have in mind that this will frequently be called with 0,0 .false. simply to find NVAR and set LC. This could be done externally, but I would argue …
FUNCTION LOC(IT,JT,KLOC,LVORF,MAXVAR, NVAR,LC)
LOGICAL LVORF(*),LC
DIMENSION KLOC(*)
IF(.NOT.LC)THEN
LC=.TRUE.
NVAR=0
DO I=1,MAXVAR
KLOC(I)=0
IF(LVORF(I))THEN
NVAR=NVAR+1
KLOC(I)=NVAR
ENDIF
ENDDO
ENDIF
IF(KLOC(IT).EQ.0.OR.KLOC(JT).EQ.0)THEN
LOC=0
ELSE
LOC=(KLOC(JT)-1)*NVAR+KLOC(IT)[1]
ENDIF
RETURN
END
[1] Note that in C where the natural order is from 0 up, and where the last member of the array varies first, that this line would be LOC=KLOC(IT)*NVAR+KLOC(JT)