Initial commit.
This commit is contained in:
commit
ab55f478ba
|
@ -0,0 +1,5 @@
|
||||||
|
/obj/
|
||||||
|
.#*
|
||||||
|
/bin/
|
||||||
|
src/model/
|
||||||
|
/src/parser/keys.f90
|
|
@ -0,0 +1,152 @@
|
||||||
|
SHELL = /bin/bash
|
||||||
|
.SUFFIXES :
|
||||||
|
.SUFFIXES : .f .o
|
||||||
|
src = ./src/
|
||||||
|
build = ./obj/
|
||||||
|
bin = ./bin/
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
version=localdw-1.0
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
#IFORT VERSION (DEFAULT)
|
||||||
|
FC = ifort
|
||||||
|
FFLAGS = -O2 -openmp -mkl -heap-arrays -module $(build) -cpp
|
||||||
|
#-openmp -complex-limited-range -xW -i-static -ip -ftz -no-prec-div -opt-prefetch -heap-arrays -align dcommons -mkl -mcmodel=medium
|
||||||
|
DBGFLAGS = -debug -check -check bounds #-warn uncalled -warn nousage -warn nounused -openmp -warn -warn notruncated_source
|
||||||
|
DBGFLAGS+= -pg
|
||||||
|
|
||||||
|
#MODERN IFORT VERSION (for compiling on laptops)
|
||||||
|
NEWFFLAGS =-O2 -qopenmp -qmkl -heap-arrays -module $(build) -cpp -g
|
||||||
|
|
||||||
|
#GFORTRAN (INVOKED VIA MAKE GFORTRAN)
|
||||||
|
GNUFC = gfortran #You can get newer versions of gfortran, if you perform "scl enable devtoolset-10 bash" in your shell first
|
||||||
|
GNUQFC = /opt/rh/devtoolset-10/root/bin/gfortran
|
||||||
|
GNUFFLAGS = -O3 -ffast-math -march=native -p -opt-prefetch -fopenmp -std=legacy -llapack -cpp -J$(build) #Note that for new version of gfortran you might have to add -std=legacy or -fallow-argument-mismatch to compile random.f without errors!
|
||||||
|
#-fallow-argument-mismatch
|
||||||
|
GNUDBGFLAGS = -fcheck=bounds -fcheck=do -fcheck=mem -fcheck=pointer -p -Og #-gdwarf-5 -O0 -Wall
|
||||||
|
|
||||||
|
#MPI VERSION (INVOKED VIA MAKE MPI)
|
||||||
|
MPIFC=mpif90
|
||||||
|
MPIFFLAGS = -fcx-limited-range -O3 -ffast-math -march=native -p -opt-prefetch -falign-commons -mcmodel=large -fopenmp -J$(build) -llapack -cpp -Dmpi_version #TODO: Check if all these flags are necessary!
|
||||||
|
#Syntax for running mpi calculations:
|
||||||
|
# - 1 machine with 12 cores: mpirun -np 12 genetic test.genetic
|
||||||
|
# - 4 machine with 12 cores: mpirun -np 48 --hostfile nodes.txt genetic test.genetic
|
||||||
|
# - nodes.txt specifies the nodes on which the program will run, the first mentioned note will perform the master thread
|
||||||
|
# - you have to start the calculation from the node with the master thread and have running sleep jobs for the other notes
|
||||||
|
# - TODO: Write a job file / submission script that automatizes this procedure
|
||||||
|
|
||||||
|
#mpirun -np 48 --hostfile nodes.txt genetic s_test-dist9-freeze.genetic > s_test-dist9-freeze.out &
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
#Extend search path for files (both .f and .incl files)
|
||||||
|
VPATH += $(src)
|
||||||
|
VPATH += $(src)parser
|
||||||
|
VPATH += $(src)parser/lib
|
||||||
|
VPATH += $(src)model
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
#Define objects for different Program parts (sorted in order of compilation)
|
||||||
|
parserlib_obj = strings.o long_keyread.o fileread.o keyread.o long_write.o
|
||||||
|
parser_obj = io_parameters.o keys.o dim_parameter.o parameterkeys.o parse_errors.o parser.o
|
||||||
|
|
||||||
|
datamodule_obj = data_module.o #Compile this module before your model files and the genetic files
|
||||||
|
|
||||||
|
model_obj = ptr_structure.o ctrans.o model.o weight.o adia.o
|
||||||
|
|
||||||
|
mod_incl = mod_const.incl so_param.incl
|
||||||
|
|
||||||
|
random_obj = $(addprefix $(build), random.o)
|
||||||
|
|
||||||
|
genetic_obj = data_transform.o init.o write.o funcs.o marq.o lbfgsb.o idxsrt_mod.o fit_MeX.o mpi_fit_MeX.o genetic.o #content of data_transform and write is user specific, interfaces are fixed
|
||||||
|
|
||||||
|
objects = $(addprefix $(build), $(parserlib_obj) $(parser_obj) $(datamodule_obj) $(model_obj) $(genetic_obj) )
|
||||||
|
|
||||||
|
#Note: Since we are using modules, you have carefully choose the order of compilation and take dependencies between modules and subroutines into account!
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# define main goal
|
||||||
|
main = genetic
|
||||||
|
|
||||||
|
|
||||||
|
# define main compilation
|
||||||
|
gfortran: override FC = $(GNUFC)
|
||||||
|
gfortran: override FFLAGS = $(GNUFFLAGS)
|
||||||
|
gfortran: $(main)
|
||||||
|
|
||||||
|
$(main) : dirs $(random_obj) $(objects)
|
||||||
|
$(FC) $(FFLAGS) $(random_obj) $(objects) -o $(bin)$(main)
|
||||||
|
$(build)%.o : %.f
|
||||||
|
$(FC) -c $(FFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
|
||||||
|
$(model_obj) : $(mod_incl)
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# define name of additional recipes
|
||||||
|
.PHONY: clean neat remake debug test mpi gfortran gqfortran profile tar dirs
|
||||||
|
|
||||||
|
# define additionational recipes
|
||||||
|
trash= *__genmod* $(addprefix $(build),*__genmod* *.mod)
|
||||||
|
clean:
|
||||||
|
$(RM) $(objects) $(trash)
|
||||||
|
|
||||||
|
neat: clean
|
||||||
|
$(RM) $(random_obj)
|
||||||
|
|
||||||
|
remake: clean $(main)
|
||||||
|
|
||||||
|
dirs:
|
||||||
|
@mkdir -p $(build) $(bin)
|
||||||
|
|
||||||
|
debug: override FFLAGS += $(DBGFLAGS)
|
||||||
|
debug: clean $(main)
|
||||||
|
cp $(infile) $(bin)
|
||||||
|
$(bin)$(main) $(bin)$(infile) | tee debug.out
|
||||||
|
|
||||||
|
modern: override FFLAGS = $(NEWFFLAGS)
|
||||||
|
modern: $(main)
|
||||||
|
|
||||||
|
gqfortran: override FC = $(GNUQFC)
|
||||||
|
gqfortran: override FFLAGS = $(GNUFFLAGS)
|
||||||
|
gqfortran: $(main)
|
||||||
|
|
||||||
|
gdebug: override FC = $(GNUFC)
|
||||||
|
gdebug: override FFLAGS = $(GNUFFLAGS) $(GNUDBGFLAGS)
|
||||||
|
gdebug: clean $(main)
|
||||||
|
|
||||||
|
mpi: override FC = $(MPIFC)
|
||||||
|
mpi: override FFLAGS = $(MPIFFLAGS)
|
||||||
|
mpi: $(main)
|
||||||
|
|
||||||
|
infile=hi-sing1-sig.genetic
|
||||||
|
|
||||||
|
gtest: override FC = $(GNUFC)
|
||||||
|
gtest: override FFLAGS = $(GNUFFLAGS)
|
||||||
|
gtest: clean $(main)
|
||||||
|
cp $(infile) $(bin)
|
||||||
|
$(bin)$(main) $(bin)$(infile) | tee test.out
|
||||||
|
|
||||||
|
gprofile: override FC = $(GNUFC)
|
||||||
|
gprofile: override FFLAGS = $(GNUFFLAGS) -pg
|
||||||
|
gprofile: clean $(main)
|
||||||
|
cp $(infile) $(bin)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test: clean $(main)
|
||||||
|
cp $(infile) $(bin)
|
||||||
|
$(bin)$(main) $(bin)$(infile) | tee test.out
|
||||||
|
|
||||||
|
profile: override FFLAGS += -pg
|
||||||
|
profile: clean test
|
||||||
|
date > profile
|
||||||
|
gprof $(bin)$(main) gmon.out >> profile
|
||||||
|
|
||||||
|
timestamp=$(shell date +"%FT%H-%M-%S")
|
||||||
|
tar:
|
||||||
|
date > INFO
|
||||||
|
tar --exclude-backups --exclude-vcs -czf tardir/geneticsrc_$(timestamp).tar src/ obj/ bin/ Makefile INFO
|
|
@ -0,0 +1,11 @@
|
||||||
|
module accuracy_constants
|
||||||
|
use iso_fortran_env
|
||||||
|
implicit none
|
||||||
|
! integer, parameter :: racc = real32 !real*4
|
||||||
|
integer, parameter :: racc = real64 !real*8
|
||||||
|
! integer, parameter :: racc = real128 !real*16
|
||||||
|
|
||||||
|
! integer, parameter :: iacc = int16 !int*2
|
||||||
|
integer, parameter :: iacc = int32 !int*4
|
||||||
|
! integer, parameter :: iacc = int64 !int*8
|
||||||
|
end module
|
|
@ -0,0 +1,54 @@
|
||||||
|
module data_module
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
double precision,protected, dimension(:,:), allocatable :: q_m
|
||||||
|
double precision,protected, dimension(:,:), allocatable :: x1_m
|
||||||
|
double precision,protected, dimension(:,:), allocatable :: x2_m
|
||||||
|
double precision,protected, dimension(:,:), allocatable :: y_m
|
||||||
|
double precision,protected, dimension(:,:), allocatable :: wt_m
|
||||||
|
double precision,protected, dimension(:,:), allocatable :: ny_m
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
!------------------------------
|
||||||
|
|
||||||
|
subroutine init_data(numdatpt,q,x1,x2,y,wt,ny)
|
||||||
|
|
||||||
|
use dim_parameter, only: qn, ntot
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
integer i,numdatpt
|
||||||
|
double precision q(qn,*)
|
||||||
|
double precision x1(qn,*)
|
||||||
|
double precision x2(qn,*)
|
||||||
|
double precision y(ntot,*)
|
||||||
|
double precision wt(ntot,*)
|
||||||
|
double precision ny(ntot,*)
|
||||||
|
|
||||||
|
allocate(q_m(qn,numdatpt))
|
||||||
|
allocate(x1_m(qn,numdatpt))
|
||||||
|
allocate(x2_m(qn,numdatpt))
|
||||||
|
allocate(y_m(ntot,numdatpt))
|
||||||
|
allocate(wt_m(ntot,numdatpt))
|
||||||
|
allocate(ny_m(ntot,numdatpt))
|
||||||
|
|
||||||
|
do i=1,numdatpt
|
||||||
|
q_m(1:qn,i)=q(1:qn,i)
|
||||||
|
x1_m(1:qn,i)=x1(1:qn,i)
|
||||||
|
x2_m(1:qn,i)=x2(1:qn,i)
|
||||||
|
y_m(1:ntot,i)=y(1:ntot,i)
|
||||||
|
wt_m(1:ntot,i)=wt(1:ntot,i)
|
||||||
|
ny_m(1:ntot,i)=ny(1:ntot,i)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!------------------------------
|
||||||
|
|
||||||
|
subroutine dealloc_data()
|
||||||
|
deallocate(q_m,x1_m,x2_m,y_m,wt_m,ny_m)
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
end module data_module
|
|
@ -0,0 +1,36 @@
|
||||||
|
module dim_parameter
|
||||||
|
use io_parameters,only: maxpar_keys
|
||||||
|
implicit none
|
||||||
|
integer,parameter :: max_ntot = 200 ,max_par = 600
|
||||||
|
!Standard
|
||||||
|
integer :: qn,qn_read,ntot,numdatpt
|
||||||
|
integer :: nstat,ndiab,nci
|
||||||
|
!Fabian
|
||||||
|
! integer :: numdatpt
|
||||||
|
! integer,parameter :: qn=9,ntot=162,nstat=8,ndiab=22,nci=7
|
||||||
|
|
||||||
|
integer :: sets
|
||||||
|
integer, allocatable :: ndata(:)
|
||||||
|
logical :: hybrid, anagrad,lbfgs
|
||||||
|
integer :: lbfgs_corr
|
||||||
|
double precision :: facspread
|
||||||
|
logical :: log_convergence
|
||||||
|
! Weight Parameter
|
||||||
|
double precision :: wt_en2ci
|
||||||
|
double precision, allocatable :: wt_en(:),wt_ci(:) !< parameters for weightingroutine, nstat or ndiab long
|
||||||
|
! which coord to use for plotting
|
||||||
|
integer, allocatable :: plot_coord(:)
|
||||||
|
|
||||||
|
! pst vector
|
||||||
|
integer pst(2,maxpar_keys)
|
||||||
|
|
||||||
|
! thresholds for error calculation
|
||||||
|
double precision, allocatable :: rms_thr(:)
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
subroutine dealloc_dim()
|
||||||
|
deallocate(ndata,wt_ci,wt_en,rms_thr,plot_coord)
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,500 @@
|
||||||
|
module fit_mod
|
||||||
|
implicit none
|
||||||
|
contains
|
||||||
|
|
||||||
|
|
||||||
|
! > Routine to controll the genetic fitting algorithm
|
||||||
|
subroutine fit(q,x1,x2,y,frms,difper,wt,par,p_spread,mut,
|
||||||
|
> npar,p_act,seed,gtype,nset,nsel,chkpnt,old,iter,maxit,
|
||||||
|
$ micit,ny,filename)
|
||||||
|
use idxsrt_mod, only: idxsrt
|
||||||
|
use dim_parameter,only: qn,numdatpt,ntot
|
||||||
|
use init_mod,only: actinit
|
||||||
|
use write_mod,only: write_output
|
||||||
|
#ifdef mpi_version
|
||||||
|
use mpi
|
||||||
|
#endif
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
! MPI Variables
|
||||||
|
#ifdef mpi_version
|
||||||
|
integer ierror,my_rank,workernum,mpi_control_data(4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
! Input variables (not changed within this subroutine).
|
||||||
|
double precision q(qn,numdatpt),x1(qn,numdatpt),x2(qn,numdatpt)!< coordinates/input values
|
||||||
|
double precision y(ntot,numdatpt),ny(ntot,numdatpt) !< Output/(energie and ci) values
|
||||||
|
double precision wt(ntot,numdatpt) !< weights
|
||||||
|
integer npar !< number of parameters
|
||||||
|
integer nset !< number of parameter sets
|
||||||
|
integer maxit !< maximum number of macroiterations
|
||||||
|
integer micit !< maximum number of microiterations (i.e. LM iterations)
|
||||||
|
|
||||||
|
!Fabian 15.03.2022: Used for babies or parent generation
|
||||||
|
integer gtype!< type of random number generator --> is this ever really used??
|
||||||
|
integer nsel !< number of parents selected for having babies
|
||||||
|
integer seed !< random seed for babies generation
|
||||||
|
double precision p_spread(npar)
|
||||||
|
double precision difper, mut
|
||||||
|
|
||||||
|
!Fabian 15.03.2022: Used for checkfile
|
||||||
|
character(len=80) :: chkpnt
|
||||||
|
character(len=10) :: writer
|
||||||
|
integer iter
|
||||||
|
double precision old !< old rms
|
||||||
|
|
||||||
|
!Fabian 15.03.2022: Used for wrout
|
||||||
|
character(len=80) filename
|
||||||
|
|
||||||
|
!Fabian 15.03.2022: Used in parameter initialization
|
||||||
|
integer p_act(npar) !< array that contains info if a parameter is active or not == equivalent to ma in mrqmin
|
||||||
|
|
||||||
|
|
||||||
|
! Input/output variables (changed/updated within this subroutine)
|
||||||
|
double precision par(npar,nset) !< parameters
|
||||||
|
|
||||||
|
! Output variables
|
||||||
|
double precision frms !< best rms after macro iteration
|
||||||
|
|
||||||
|
! Internal variables
|
||||||
|
integer i
|
||||||
|
! logical conver, ldum !< logicals for checking if calculation is converged
|
||||||
|
logical ldum !< logicals for checking if calculation is converged
|
||||||
|
integer start
|
||||||
|
logical enough_parents
|
||||||
|
integer mfit !< number of active parameters
|
||||||
|
integer flag !< flag for write routine for fitting status(converged,maxiterationsreach,no convergence)
|
||||||
|
|
||||||
|
! Fabian 12.04. These are automatic arrays, maybe make them allocated or static
|
||||||
|
integer idx(nset) !< array for sorting the parameter sets after their rms
|
||||||
|
double precision rms(nset) !< array that contains rms of all parameter sets
|
||||||
|
integer lauf !< counter for macroiteration
|
||||||
|
double precision newpar(npar,nset) !< temporary storage array before parents&babies
|
||||||
|
integer iact(npar) !< array pointing to the position of active parameters
|
||||||
|
|
||||||
|
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||||
|
#ifdef mpi_version
|
||||||
|
call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierror)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
!> Initialize mfit,iact
|
||||||
|
call actinit(p_act,iact,mfit,npar)
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
call bcastact(p_act,npar)
|
||||||
|
call MPI_Bcast(mfit, 1, MPI_INT, 0, MPI_COMM_WORLD,ierror)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
!> Initialize rms vector
|
||||||
|
|
||||||
|
rms=0.d0
|
||||||
|
rms(1:nset)=1d10
|
||||||
|
|
||||||
|
!> Write number of the present iteration and increase start to iter, if it is a restarted fit
|
||||||
|
|
||||||
|
if (iter.ne.1) then
|
||||||
|
write(6,*) 'Genetic restart, proceed with iteration', iter
|
||||||
|
endif
|
||||||
|
start=iter
|
||||||
|
|
||||||
|
!> Start the genetic algorithm that consists of maxit macroiterations
|
||||||
|
|
||||||
|
do lauf=start,maxit
|
||||||
|
|
||||||
|
write(6,*) ''
|
||||||
|
write(6,'(150("#"))')
|
||||||
|
write(6,*) ''
|
||||||
|
write(6,'(''Iteration:'',i5)') lauf
|
||||||
|
|
||||||
|
!ATTENTION: THIS SUBROUTINE IS THE PARALLIZED SECTION !!!
|
||||||
|
|
||||||
|
!Perform optimization for the parameter sets of generation lauf
|
||||||
|
call fit_sets(lauf,nset,npar,par,rms,
|
||||||
|
$ p_act,mfit,micit)
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Sort the rms vector and assign the set number to each rms
|
||||||
|
call idxsrt(rms,idx,nset)
|
||||||
|
|
||||||
|
!write out sorted errors and indicate with which set each error was obtained
|
||||||
|
do i=1,nset
|
||||||
|
write(6,'(A8,I3,A8,F12.8,A8,I3)') 'Rank:', i,'RMS:', rms(i),
|
||||||
|
$ 'Set',idx(i)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!write best rms onto the output variable frms
|
||||||
|
frms=rms(1)
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Resort the parameter array sucht that the parameter sets with the lowest rms are listed first
|
||||||
|
newpar(1:npar,1:nset)=par(1:npar,idx(1:nset))
|
||||||
|
par(1:npar,1:nset)=newpar(1:npar,1:nset)
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Return if maximum number of macro iterations is reached
|
||||||
|
if (lauf.ge.maxit) return
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Prepare next iteration of the genetic algorithm
|
||||||
|
|
||||||
|
!Select the best parameter sets and sufficiently distinct sets as parents for the next iteration
|
||||||
|
!Note: After parents, the first nsel entries of par and rms contain the parents
|
||||||
|
!Note: However, rms is not strictly sorted after this (especially if the best parameter set were too similar)
|
||||||
|
call parents(par,rms,difper,npar,idx,nset,nsel,p_act,mfit
|
||||||
|
$ ,enough_parents)
|
||||||
|
|
||||||
|
!Check for convergence of genetic algorithm, i.e. whether the generation of new parents leads to
|
||||||
|
!a decrease of the rms as well as sufficiently distinct parameter set; return if convergence is reached
|
||||||
|
ldum=conver(old,rms,idx,nsel)
|
||||||
|
|
||||||
|
! initialize flag for write routine
|
||||||
|
flag=1
|
||||||
|
! set converged flag for write routine
|
||||||
|
if (ldum) flag=2
|
||||||
|
! write intermediate output
|
||||||
|
call write_output(q,x1,x2,y,wt,par,p_act,p_spread,
|
||||||
|
> nset,npar,flag,lauf)
|
||||||
|
|
||||||
|
if (ldum) return
|
||||||
|
! call flush
|
||||||
|
! flush(6)
|
||||||
|
|
||||||
|
!Check if there are enough parents for next macro iteration
|
||||||
|
if (enough_parents .eqv. .false.) then
|
||||||
|
write(6,*) "Warning: Found too few different parents
|
||||||
|
$ for next macroiteration, exit genetic algorithm"
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
|
||||||
|
!Generate new parameter sets and proceed to the next iteration
|
||||||
|
call babies(par,p_spread,mut,npar,mfit,nset,nsel,iact,
|
||||||
|
$ seed,gtype)
|
||||||
|
iter=iter+1
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!write checkpoint:
|
||||||
|
! writer='write'
|
||||||
|
! call chkfile(chkpnt,par,npar,p_act,seed,gtype,nset,iter,
|
||||||
|
! & old,writer)
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
write(6,*) "Finished fit, return to main program"
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
C%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
subroutine fit_sets(lauf,nset,npar,par,rms,
|
||||||
|
$ p_act,mfit,micit)
|
||||||
|
use dim_parameter,only: lbfgs
|
||||||
|
use marq_mod,only: mrqmin
|
||||||
|
use lbfgsb_mod,only: lbfgs_driver
|
||||||
|
#ifndef mpi_version
|
||||||
|
use omp_lib
|
||||||
|
#else
|
||||||
|
use mpi
|
||||||
|
integer ierror,my_rank
|
||||||
|
integer workernum
|
||||||
|
#endif
|
||||||
|
! Input variables
|
||||||
|
integer lauf !number of the current macroiteration
|
||||||
|
integer nset !number of parameter sets
|
||||||
|
integer npar !number of parameters
|
||||||
|
|
||||||
|
!Input / output variables
|
||||||
|
double precision par(npar,nset) !< parameters
|
||||||
|
double precision rms(nset) !< array that contains rms of all parameter sets
|
||||||
|
|
||||||
|
! Input variables (necessary solely for mrqmin)
|
||||||
|
integer p_act(npar) !< array that contains info if a parameter is active or not == equivalent to ma in mrqmin
|
||||||
|
integer mfit !< number of active parameters
|
||||||
|
integer micit ! number of microiterations
|
||||||
|
|
||||||
|
! Internal variables in parallel section
|
||||||
|
double precision lrms !< rms for one parameter set
|
||||||
|
double precision lpar(npar) !array for one parameter set !Fabian 31.03.2022: New test to reduce sice of parameters
|
||||||
|
integer i,j
|
||||||
|
|
||||||
|
! Internal variables for OpenMP
|
||||||
|
double precision startzeit,endzeit,start_totzeit,end_totzeit
|
||||||
|
integer thread_num
|
||||||
|
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||||
|
|
||||||
|
|
||||||
|
!> ATTENTION: THIS IS THE PARALLIZED SECTION !!!
|
||||||
|
|
||||||
|
!> Perform non-linear least squares fit for each parameter set:
|
||||||
|
#ifdef mpi_version
|
||||||
|
! write(*,*) 'mpi_version'
|
||||||
|
start_totzeit=MPI_Wtime()
|
||||||
|
call MPI_Comm_size(MPI_COMM_WORLD, workernum, ierror)
|
||||||
|
call workshare(workernum, par, rms, npar, nset)
|
||||||
|
end_totzeit=MPI_Wtime()
|
||||||
|
#else
|
||||||
|
start_totzeit=omp_get_wtime()
|
||||||
|
!$omp parallel do schedule(dynamic)
|
||||||
|
!$omp& default(shared)
|
||||||
|
!$omp& private(i,j,lpar,lrms,thread_num,startzeit,endzeit)
|
||||||
|
do i=lauf,nset
|
||||||
|
! > Fabian 15.03.2022: Variable for timing the duration of optimizing one parameter set
|
||||||
|
startzeit=omp_get_wtime() !Fabian
|
||||||
|
|
||||||
|
!> Write the parameters and the initial rms for this set onto private variables
|
||||||
|
lpar(1:npar)=par(1:npar,i)
|
||||||
|
lrms=rms(i)
|
||||||
|
|
||||||
|
!Fabian 05.04.2022: Here I could separate the active and inactive parameters and perform the LM optimization purely with the active params
|
||||||
|
!Fabian 05.04.2022: However, this would require to store the inactive parameter and the vector that decides if a variable is active onto a module since I need it in funcs then!
|
||||||
|
|
||||||
|
|
||||||
|
!> Levenberg-Marquardt-Optimization of the current parameter set
|
||||||
|
!Fabian 16.03.2022: This version might be MPI compatible since it contains purely of private variables
|
||||||
|
!Fabian 16.03.2022: Use this instead of the above, if the data is declared global via a module and pst is only then used when necessary!
|
||||||
|
|
||||||
|
if(lbfgs) then
|
||||||
|
call lbfgs_driver(lpar,npar,p_act,mfit,
|
||||||
|
& lrms,micit,i)
|
||||||
|
else
|
||||||
|
call mrqmin(lpar,npar,p_act,mfit,
|
||||||
|
& lrms,micit,i)
|
||||||
|
endif
|
||||||
|
|
||||||
|
!> Write the optimized parameters and the optimized rms back onto the arrays that collect all parameters and rms
|
||||||
|
par(1:npar,i)=lpar(1:npar)
|
||||||
|
rms(i)=lrms
|
||||||
|
|
||||||
|
!> Fabian 15.03.2022: Some output for timing the duration of optimizing one parameter set
|
||||||
|
thread_num = omp_get_thread_num()
|
||||||
|
endzeit=omp_get_wtime()
|
||||||
|
write(6,*) 'Thread', thread_num ,'Time:', endzeit-startzeit
|
||||||
|
|
||||||
|
!> Write output for the spezific set of parameters
|
||||||
|
write(6,99) i, rms(i), rms(i)*219474.69d0
|
||||||
|
99 format('Set:',i5,5x,'RMS:',g16.6,3x,'(',f16.6,' cm-1)')
|
||||||
|
|
||||||
|
enddo
|
||||||
|
!$omp end parallel do
|
||||||
|
end_totzeit=omp_get_wtime()
|
||||||
|
#endif
|
||||||
|
write(6,*) 'Total time for Macroiteration: '
|
||||||
|
> ,end_totzeit-start_totzeit
|
||||||
|
|
||||||
|
write(6,*) 'Finished parallel fit for Iteration', lauf
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
|
||||||
|
C%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
C% SUBROUTINE PARENTS(...)
|
||||||
|
C%
|
||||||
|
C% subroutine to select the parent parameter sets according to their
|
||||||
|
C% RMS error
|
||||||
|
C%
|
||||||
|
C % variables:
|
||||||
|
C % par: parameter vector (double[npar,nset])
|
||||||
|
C % rms: error for each set (double[nset])
|
||||||
|
C % difper:
|
||||||
|
C % npar: number of parameters (int)
|
||||||
|
C % idx: sorted indeces according to rms(1..nset) (int[nset])
|
||||||
|
C % nset: number of sets
|
||||||
|
C % nsel: number of selected parents
|
||||||
|
C%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
subroutine parents(par,rms,difper,npar,idx,nset,nsel,p_act,mfit
|
||||||
|
$ ,enough_parents)
|
||||||
|
implicit none
|
||||||
|
integer i, j, k, nset, idx(nset), npar, nsel, p_act(npar), mfit
|
||||||
|
double precision par(npar,nset), dum(npar,nset), rms(nset), last
|
||||||
|
double precision thr
|
||||||
|
double precision difper, drms(nset)
|
||||||
|
integer dum_idx(nset), rank_parent(nsel)
|
||||||
|
! logical difchk
|
||||||
|
logical enough_parents
|
||||||
|
|
||||||
|
thr=1.d-8
|
||||||
|
dum=0.d0
|
||||||
|
dum_idx = 0
|
||||||
|
rank_parent = 0
|
||||||
|
drms=0.d0
|
||||||
|
|
||||||
|
c write the best parameter set on the dummy
|
||||||
|
dum(1:npar,1)=par(1:npar,1)
|
||||||
|
dum_idx(1)=idx(1)
|
||||||
|
rank_parent(1) = 1
|
||||||
|
!Choose exactly (beside the best parameter set) nsel-1 parameter sets as new parents and write them on dum
|
||||||
|
!These parents are selected according to the lowest possible rms AND sufficient dissimilarity
|
||||||
|
!to the overall best parameter sets
|
||||||
|
last=1.d14
|
||||||
|
k=1
|
||||||
|
do i=1,nset
|
||||||
|
if (difchk(dum,par(1:npar,i),difper,k,npar,p_act,mfit,nset))
|
||||||
|
> then
|
||||||
|
k=k+1
|
||||||
|
dum(1:npar,k)=par(1:npar,i)
|
||||||
|
drms(k)=rms(i)
|
||||||
|
dum_idx(k) = idx(i)
|
||||||
|
rank_parent(k) = i
|
||||||
|
endif
|
||||||
|
if (k.eq.nsel) exit
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!Terminate programm if too few parents are found
|
||||||
|
enough_parents=.true.
|
||||||
|
if(k.lt.nsel) then
|
||||||
|
enough_parents=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
!Copy the selected parent parameter sets back to the array par
|
||||||
|
do i=2,nsel
|
||||||
|
par(1:npar,i)=dum(1:npar,i)
|
||||||
|
rms(i)=drms(i)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!Write out some information on the chosen parent parameter sets
|
||||||
|
write(6,*) 'nsel:', nsel
|
||||||
|
write(6,*)
|
||||||
|
write(6,*) 'Selected parents:'
|
||||||
|
do j=1,nsel
|
||||||
|
write(6,201) rank_parent(j), rms(j), dum_idx(j)
|
||||||
|
write(6,200) (par(k,j), k=1,npar)
|
||||||
|
enddo
|
||||||
|
200 format('Par:',6g16.7)
|
||||||
|
201 format('>>> Rank:',i5,' RMS:' ,g14.4,' set:',i5,' <<<' )
|
||||||
|
|
||||||
|
! call flush
|
||||||
|
! flush(6)
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------
|
||||||
|
! function to check whether new parameter set is sufficiently different
|
||||||
|
! from already selected sets:
|
||||||
|
logical function difchk(dum,par,difper,k,npar,p_act,mfit,nset)
|
||||||
|
implicit none
|
||||||
|
integer i, j, k, npar, p_act(npar), mfit,nset
|
||||||
|
double precision dum(npar,nset), par(npar), per, thr, difper
|
||||||
|
double precision epsilon
|
||||||
|
parameter(epsilon=1d-8)
|
||||||
|
|
||||||
|
!.. this threshold specifies that parameter set must have an average
|
||||||
|
! difference of at least 1% with respect to any other selected set.
|
||||||
|
thr=1.d0-difper
|
||||||
|
if (thr.gt.0.99d0) thr=0.99d0 !avoids no difference
|
||||||
|
difchk=.true.
|
||||||
|
do i=1,k
|
||||||
|
per=0.d0
|
||||||
|
!Calculate relative difference between between current set (par) and the already selected sets (dum)
|
||||||
|
do j=1,npar
|
||||||
|
if (p_act(j).ge.1) then !Added flexible value for p_act; Nicole 15.12.2022; only active parameters are counted
|
||||||
|
per=per+(min(dum(j,i),par(j))+epsilon)
|
||||||
|
$ /(max(dum(j,i),par(j))+epsilon)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
per=per/mfit !Modified Version that only active parameters are counted; Fabian 14.12.2021
|
||||||
|
!Discard the current set if it is too similar to one already selected
|
||||||
|
if (per.gt.thr) then
|
||||||
|
difchk=.false.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------
|
||||||
|
! subroutine to create the baby sets of parameters from the selected
|
||||||
|
! parent sets
|
||||||
|
subroutine babies(par,p_spread,mut,npar,mfit,nset,nsel,iact,
|
||||||
|
$ seed,gtype)
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
c functions
|
||||||
|
double precision rn !gets one random number
|
||||||
|
|
||||||
|
integer i, j, k, npar, nset, nsel, mfit, iact(npar)
|
||||||
|
double precision par(npar,nset), p_spread(npar), mut, dum
|
||||||
|
|
||||||
|
integer seed,gtype
|
||||||
|
|
||||||
|
!loop over all dieing sets (only the nsel parent sets survive)
|
||||||
|
do i=nsel+1,nset
|
||||||
|
!loop over all active parameters
|
||||||
|
do j=1,mfit
|
||||||
|
!picking a random parameter set of the first nsel parent sets !(Fabian 16.03.2022: Add feature, to ensure that at least one baby is generated from each parent?)
|
||||||
|
k=int(rn(seed,gtype,0)*nsel)+1 !Fabian 08.04.2022: Even though seed isnt passed here, the rn call is dependent on the earlier initialized seed
|
||||||
|
!writing the j'th parameter of the selected parent set onto the j'th parameter of the i'th of the remaining sets (only the active parameters are copied)
|
||||||
|
!(Fabian 16.03.2022: This way, I recombinate a number of parents to new babies. However, recombination might not be good, if these parent sets are relatively distinct; maybe use only two parent sets for recombination?)
|
||||||
|
par(iact(j),i)=par(iact(j),k)
|
||||||
|
!select whether the j'th parameter of this new set is mutated !(Fabian 16.03.2022: Add feature, to ensure that at least one parameter is mutated?)
|
||||||
|
if (rn(seed,gtype,0).lt.mut) then
|
||||||
|
dum=rn(seed,gtype,0) - 0.5d0
|
||||||
|
dum=dum*p_spread(iact(j))
|
||||||
|
par(iact(j),i)=par(iact(j),i)*(1.d0+dum)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!-----------------------------------------------------------------------
|
||||||
|
! check convergence of genetic algorithm
|
||||||
|
function conver(old,rms,idx,nsel)
|
||||||
|
implicit none
|
||||||
|
integer i, j, nsel, idx(*), baby
|
||||||
|
double precision rms(*), new, old, thresh, percent, thrper
|
||||||
|
logical conver
|
||||||
|
|
||||||
|
!Thresholds and initializiation
|
||||||
|
conver=.false.
|
||||||
|
thresh=old*1.d-3
|
||||||
|
thrper=0.2d0
|
||||||
|
|
||||||
|
! Lets use all values in the selected subset:
|
||||||
|
j=nsel
|
||||||
|
baby=0
|
||||||
|
|
||||||
|
! Calculate average error for the nsel best parameter sets
|
||||||
|
new=0.d0
|
||||||
|
do i=1,j
|
||||||
|
new=new+rms(i)
|
||||||
|
enddo
|
||||||
|
new=new/dble(j)
|
||||||
|
|
||||||
|
! calculate the number of selected parent sets that were originally babies in the previous iteration
|
||||||
|
do i=1,nsel
|
||||||
|
if (idx(i).gt.nsel) baby=baby+1
|
||||||
|
enddo
|
||||||
|
! calculate the percentage
|
||||||
|
percent=dble(baby)/dble(nsel)
|
||||||
|
|
||||||
|
! some output
|
||||||
|
write(6,100) baby
|
||||||
|
write(6,101) new, j
|
||||||
|
write(6,*)
|
||||||
|
100 format('Number of babies in chosen subsets:', i3)
|
||||||
|
101 format('Average RMS error of chosen subsets:', g12.4,
|
||||||
|
$ ' / averaged values:', i4)
|
||||||
|
|
||||||
|
write(6,110) percent*100.d0
|
||||||
|
write(6,111) old, new, old-new
|
||||||
|
110 format('Percent babies:',f6.1)
|
||||||
|
111 format('Old RMS:',d12.4,' New RMS:',d12.4,' Diff:',d12.4)
|
||||||
|
|
||||||
|
!Set convergence to true if
|
||||||
|
!1. too few previous babies are among the new parents
|
||||||
|
!2. or the average rms of the selected parents between the current & previous macro iteration is sufficiently small
|
||||||
|
conver=(percent.le.thrper).and.(abs(new-old).lt.thresh)
|
||||||
|
write(6,*) 'Convergence:', conver
|
||||||
|
|
||||||
|
!Set average rms of this iteration to the comparison variable old for the next iteration
|
||||||
|
old=new
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
||||||
|
end module fit_mod
|
|
@ -0,0 +1,132 @@
|
||||||
|
module funcs_mod
|
||||||
|
implicit none
|
||||||
|
logical,parameter:: dbg =.false.
|
||||||
|
double precision, parameter:: thr_grad_diff = 1.d-3
|
||||||
|
contains
|
||||||
|
|
||||||
|
subroutine funcs(n,p,ymod,dymod,npar,p_act,skip)
|
||||||
|
! use dim_parameter,only:ntot,ndiab,anagrad
|
||||||
|
use dim_parameter,only:ntot,ndiab,anagrad,nstat,nci !Fabian
|
||||||
|
use data_module,only: x1_m
|
||||||
|
use adia_mod,only: adia
|
||||||
|
! In variables
|
||||||
|
integer n, npar, p_act(npar)
|
||||||
|
double precision ymod(ntot)
|
||||||
|
double precision p(npar)
|
||||||
|
logical skip
|
||||||
|
! out variables
|
||||||
|
double precision dymod(ntot,npar)
|
||||||
|
double precision dum_dymod(ntot,npar)
|
||||||
|
logical diff(ntot,npar)
|
||||||
|
! internal varibales
|
||||||
|
double precision ew(ndiab),ev(ndiab,ndiab) ! eigenvalues(ew) and eigenvectors(ev)
|
||||||
|
integer i,j
|
||||||
|
logical,parameter:: dbg =.false.
|
||||||
|
|
||||||
|
skip=.false.
|
||||||
|
diff=.false.
|
||||||
|
! get adiabatic energies:
|
||||||
|
call adia(n,p,npar,ymod,ew,ev,skip)
|
||||||
|
if(skip) return
|
||||||
|
|
||||||
|
if(eigchk(ew,nci)) then !Fabian: since pseudo-inverse is only calculated for first nci eigenvalues and their ci-vectors, if changed the check to nci
|
||||||
|
dymod = 0.d0
|
||||||
|
if(dbg) write(6,*)'funcs skipping point,n: ',n
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
! compute gradient with respect to parameter vector:
|
||||||
|
if(anagrad) then
|
||||||
|
write(6,*) 'ERROR: NOT SUPPORTED.'
|
||||||
|
stop
|
||||||
|
else
|
||||||
|
! compute gradients numerically
|
||||||
|
call num_grad(dymod,n,p,npar,p_act,skip)
|
||||||
|
endif
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------
|
||||||
|
! compute gradient of adiabatic energies nummerically with respect to parameters:
|
||||||
|
subroutine num_grad(dymod,n,p,npar,p_act,skip)
|
||||||
|
use dim_parameter,only: ntot,ndiab
|
||||||
|
use adia_mod,only: adia
|
||||||
|
integer n, i, j, npar
|
||||||
|
integer p_act(npar)
|
||||||
|
double precision ymod(ntot), dymod(ntot,npar), p(npar)
|
||||||
|
double precision dp(npar)
|
||||||
|
logical skip
|
||||||
|
double precision ew(ndiab),ev(ndiab,ndiab)
|
||||||
|
! determine finite differences for each parameter:
|
||||||
|
call pdiff(p,dp,npar)
|
||||||
|
|
||||||
|
! generate numerical gradients for all parameters individually
|
||||||
|
do i=1,npar
|
||||||
|
|
||||||
|
do j=1,ntot
|
||||||
|
dymod(j,i)=0.d0
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! calculate gradient for active parameter, for inactive parameter gradient is always zero
|
||||||
|
! Nicole: added flexible value of p_act
|
||||||
|
if (p_act(i).ge.1) then
|
||||||
|
|
||||||
|
! change parameter in forward direction
|
||||||
|
p(i)=p(i)+dp(i)
|
||||||
|
call adia(n,p,npar,ymod,ew,ev,skip)
|
||||||
|
if (skip) then
|
||||||
|
p(i)=p(i)-dp(i)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
do j=1,ntot
|
||||||
|
dymod(j,i)=ymod(j)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! change parameter in backward direction
|
||||||
|
p(i)=p(i)-2.d0*dp(i)
|
||||||
|
call adia(n,p,npar,ymod,ew,ev,skip)
|
||||||
|
if (skip) then
|
||||||
|
p(i)=p(i)+2.d0*dp(i)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
do j=1,ntot
|
||||||
|
dymod(j,i)=(dymod(j,i)-ymod(j))/(2.d0*dp(i)) !Form symmetric difference quotient
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! restore original parameter
|
||||||
|
p(i)=p(i)+dp(i)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
end subroutine num_grad
|
||||||
|
!----------------------------------------------------------------------
|
||||||
|
! determine appropriate finite differences for each parameter:
|
||||||
|
subroutine pdiff(p,dp,npar)
|
||||||
|
integer i, npar
|
||||||
|
double precision p(npar), dp(npar)
|
||||||
|
! double precision, parameter :: d = 1.d-4
|
||||||
|
double precision, parameter :: d = 1.d-6 !Standard
|
||||||
|
! double precision, parameter :: d = 1.d-8
|
||||||
|
double precision, parameter :: thr = 1.d-12
|
||||||
|
do i=1,npar
|
||||||
|
dp(i)=abs(p(i)*d)
|
||||||
|
if (dp(i).lt.thr) dp(i)=thr
|
||||||
|
enddo
|
||||||
|
end subroutine pdiff
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------------
|
||||||
|
!.. check vector of eigenvalues for (near) degeneragies
|
||||||
|
logical function eigchk(v,n)
|
||||||
|
!.. on input:
|
||||||
|
integer n
|
||||||
|
double precision v(n)
|
||||||
|
!.. local variables:
|
||||||
|
double precision thr
|
||||||
|
parameter (thr=1.d-8) !threshold for degeneracy
|
||||||
|
integer j
|
||||||
|
eigchk=.false.
|
||||||
|
do j=1,n-1
|
||||||
|
if (abs((v(j+1)-v(j))).lt.thr) then
|
||||||
|
eigchk=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
end function eigchk
|
||||||
|
end module funcs_mod
|
|
@ -0,0 +1,163 @@
|
||||||
|
program genetic
|
||||||
|
! module for dimensioning parameters
|
||||||
|
use dim_parameter,only: qn,ntot,numdatpt,dealloc_dim
|
||||||
|
!data module
|
||||||
|
use data_module, only: init_data, dealloc_data
|
||||||
|
! parser module
|
||||||
|
use parser, only: les
|
||||||
|
! matrix derivatives module
|
||||||
|
! use matrix_derivatives, only: dealloc_dw_ptr
|
||||||
|
! monome module
|
||||||
|
! use monome_module, only: dealloc_vwzprec
|
||||||
|
! diab3D precalculate module
|
||||||
|
! use diab3D_precalculate, only: dealloc_diab3D
|
||||||
|
! parameter initialization module
|
||||||
|
use init_mod,only: rinit,pinit
|
||||||
|
! fitting module
|
||||||
|
use fit_mod,only: fit
|
||||||
|
! writing module
|
||||||
|
use write_mod,only: write_output
|
||||||
|
! MPI module
|
||||||
|
#ifdef mpi_version
|
||||||
|
use mpi
|
||||||
|
#endif
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
! Declare Variables
|
||||||
|
! MPI variables
|
||||||
|
#ifdef mpi_version
|
||||||
|
integer my_rank,ierror,threadnum,stopnum,ping(8),i
|
||||||
|
#endif
|
||||||
|
! Data variables
|
||||||
|
double precision, allocatable :: q_in(:,:),x1_in(:,:),x2_in(:,:)
|
||||||
|
double precision, allocatable :: y_in(:,:),wt_in(:,:)
|
||||||
|
! Fiting Model Parameters
|
||||||
|
double precision, allocatable :: p(:),par(:,:) !< vector(npar) for the values of read parameters
|
||||||
|
integer, allocatable :: p_act(:) !< vector(npar) containing 0 or 1 defining if corresponding parameters are activ in Fit
|
||||||
|
double precision, allocatable :: p_spread(:),prange(:,:) !< vector(npar) for the spread values for each parameter
|
||||||
|
integer npar !< read length of parameter arrays
|
||||||
|
! Fit control Parameters
|
||||||
|
integer seed !< Seed for RNG
|
||||||
|
integer nset !< number of diffrent parameter sets
|
||||||
|
logical freeze !< determines if parameters are active
|
||||||
|
double precision mut, difper !< percentage of selected Parents, number of mutations in parents, minimum diffrence between selected parents
|
||||||
|
integer nsel !< number of selected parameter sets for parents
|
||||||
|
integer gtype !< type of RNG used
|
||||||
|
integer maxit, micit !<maximum makro and micro iterations for the genetic program
|
||||||
|
! -----------------------------
|
||||||
|
! Fabian
|
||||||
|
integer iter
|
||||||
|
double precision rms,old
|
||||||
|
character(len=80) filename
|
||||||
|
character(len=80) chkpnt
|
||||||
|
|
||||||
|
! -----------------------------
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
call MPI_Init(ierror)
|
||||||
|
call MPI_Comm_rank(MPI_COMM_WORLD,my_rank,ierror)
|
||||||
|
call MPI_Comm_size(MPI_COMM_WORLD,threadnum,ierror)
|
||||||
|
if(threadnum.lt.2) then
|
||||||
|
write(*,*) 'USING MPI VERSION WITH 1 THREAD: ABORTING'
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
! -----------------------------
|
||||||
|
nsel=0
|
||||||
|
mut=0.d0
|
||||||
|
difper=0.d0
|
||||||
|
call les(q_in,y_in,wt_in,p,p_act,p_spread,npar,
|
||||||
|
> seed,gtype,nset,maxit,micit,nsel,mut,difper,freeze)
|
||||||
|
|
||||||
|
allocate(par(npar,nset),prange(2,npar))
|
||||||
|
allocate(x1_in(qn,numdatpt),x2_in(qn,numdatpt))
|
||||||
|
|
||||||
|
call rinit(p,prange,p_spread,p_act,npar)
|
||||||
|
par=0.d0
|
||||||
|
par(1:npar,1)=p(1:npar)
|
||||||
|
call pinit(par,prange,npar,nset,seed,gtype)
|
||||||
|
|
||||||
|
|
||||||
|
!-------------------------------------------------
|
||||||
|
call data_transform(q_in,x1_in,x2_in,y_in,wt_in,p,npar,p_act)
|
||||||
|
!Fabian: Read data into module
|
||||||
|
call init_data(numdatpt,q_in,x1_in,x2_in,y_in,wt_in,y_in)
|
||||||
|
|
||||||
|
!-------------------------------------------------
|
||||||
|
#ifdef mpi_version
|
||||||
|
if(my_rank.eq.0) then
|
||||||
|
#endif
|
||||||
|
call write_output(q_in,x1_in,x2_in,y_in,wt_in,par,p_act,p_spread,
|
||||||
|
> nset,npar,0,0)
|
||||||
|
#ifdef mpi_version
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
!-------------------------------------------------
|
||||||
|
|
||||||
|
!Fabian: THIS IS THE PLACE WHERE MY ROUTINES START THERE EXECUTION
|
||||||
|
!Fabian: We should either include these into Maiks routines or remove it from the fitting routines
|
||||||
|
chkpnt='test'
|
||||||
|
filename='test2'
|
||||||
|
old=1.e+5
|
||||||
|
iter=1
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
if(my_rank.eq.0) then
|
||||||
|
#endif
|
||||||
|
if(.not.freeze) then
|
||||||
|
call fit(q_in,x1_in,x2_in,y_in,rms,difper,wt_in,
|
||||||
|
$ par,p_spread,mut,npar,p_act,
|
||||||
|
$ seed,gtype,nset,nsel,chkpnt,old,iter,
|
||||||
|
$ maxit,micit,y_in,
|
||||||
|
$ filename)
|
||||||
|
endif
|
||||||
|
#ifdef mpi_version
|
||||||
|
else
|
||||||
|
call mpi_rest_control(micit,npar)
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
if(my_rank.eq.0) then
|
||||||
|
#endif
|
||||||
|
call write_output(q_in,x1_in,x2_in,y_in,wt_in,par,p_act,p_spread,
|
||||||
|
> nset,npar,1,iter)
|
||||||
|
#ifdef mpi_version
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
! Final cleanup of programm (quit MPI, deallocate data, etc.)
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
if(my_rank.eq.0) then
|
||||||
|
call MPI_Comm_size(MPI_COMM_WORLD,threadnum,ierror)
|
||||||
|
stopnum = 0
|
||||||
|
do i = 1,threadnum-1
|
||||||
|
call MPI_Send(stopnum, 1, MPI_INTEGER,
|
||||||
|
$ i, 69, MPI_COMM_WORLD, ping, ierror)
|
||||||
|
enddo
|
||||||
|
call MPI_Barrier(MPI_COMM_WORLD, ierror)
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
deallocate(q_in,x1_in,x2_in,y_in,wt_in,
|
||||||
|
$ p,par,p_act,p_spread,prange)
|
||||||
|
call dealloc_data
|
||||||
|
call dealloc_dim
|
||||||
|
! call dealloc_dw_ptr
|
||||||
|
! call dealloc_vwzprec
|
||||||
|
! call dealloc_diab3D
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
call MPI_Barrier(MPI_COMM_WORLD, ierror)
|
||||||
|
call MPI_Finalize(ierror)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
end program
|
|
@ -0,0 +1,35 @@
|
||||||
|
module idxsrt_mod
|
||||||
|
implicit none
|
||||||
|
contains
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
! % SUBROUTINE IDXSRT(...)
|
||||||
|
! %
|
||||||
|
! % indices are sorted by ascending values of x, that means if you go
|
||||||
|
! % throug x(idx(1..n)) from one to n, you will get an list of growing
|
||||||
|
! % values
|
||||||
|
! %
|
||||||
|
! % variables:
|
||||||
|
! % idx: indeces which are going to be sorted(int[n])
|
||||||
|
! % n: number of indices (int)
|
||||||
|
! % x: array of values (real[n]))
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
subroutine idxsrt(x,idx,n)
|
||||||
|
integer i, j, k, n, idx(n)
|
||||||
|
double precision x(n), dum
|
||||||
|
do i=1,n
|
||||||
|
idx(i)=i
|
||||||
|
enddo
|
||||||
|
do i=1,n
|
||||||
|
do j=i+1,n
|
||||||
|
if (x(j).lt.x(i)) then
|
||||||
|
dum=x(i)
|
||||||
|
x(i)=x(j)
|
||||||
|
x(j)=dum
|
||||||
|
k=idx(i)
|
||||||
|
idx(i)=idx(j)
|
||||||
|
idx(j)=k
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
end subroutine idxsrt
|
||||||
|
end module idxsrt_mod
|
|
@ -0,0 +1,107 @@
|
||||||
|
module init_mod
|
||||||
|
implicit none
|
||||||
|
contains
|
||||||
|
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
!% SUBROUTINE RINIT
|
||||||
|
!%
|
||||||
|
!% Subroutine to define the allowed range for each parameter:
|
||||||
|
!% for the moment this is a distribution around zero with a given width
|
||||||
|
!% for each parameter
|
||||||
|
!%
|
||||||
|
!% Input variables:
|
||||||
|
!% par: Parameter vectot (double[])
|
||||||
|
!% spread: Spread of each parameter (double[])
|
||||||
|
!% ma: Active cards for every parameter (int[])
|
||||||
|
!% npar: Number of Parameters
|
||||||
|
!%
|
||||||
|
!% Output variables
|
||||||
|
!% prange: Spread interval vector (double[])
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
subroutine rinit(par,prange,p_spread,p_act,npar)
|
||||||
|
implicit none
|
||||||
|
integer i,npar,p_act(npar)
|
||||||
|
double precision par(npar), prange(2,npar), p_spread(npar),de,dum
|
||||||
|
!minimum absolute spread
|
||||||
|
double precision minspread
|
||||||
|
parameter(minspread=1.d-4)
|
||||||
|
|
||||||
|
do i=1,npar
|
||||||
|
if (abs(p_act(i)).eq.0) p_spread(i)=0.d0
|
||||||
|
dum=par(i)
|
||||||
|
if (abs(dum).lt.1.d-6) dum=minspread
|
||||||
|
de=abs(dum*p_spread(i)/2.d0)
|
||||||
|
prange(1,i)=par(i)-de
|
||||||
|
prange(2,i)=par(i)+de
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
!% SUBROUTINE PINIT(...)
|
||||||
|
!%
|
||||||
|
!% subroutine to initialize the nset parameter sets with random
|
||||||
|
!% numbers in the range defined by prange
|
||||||
|
!%
|
||||||
|
!% Input Variables:
|
||||||
|
!% par: parameter vector (double[])
|
||||||
|
!% prange: Spread interval vector (double[])
|
||||||
|
!% npar: number of parameters (int)
|
||||||
|
!% nset: number of sets (int)
|
||||||
|
!% seed: seed for random.f (int)
|
||||||
|
!% gtype: selects random number generator (int)
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
subroutine pinit(par,prange,npar,nset,seed,gtype)
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
integer i, j, npar, nset, seed, gtype,cont
|
||||||
|
double precision par(npar,nset), prange(2,npar), rn, dum
|
||||||
|
|
||||||
|
!.. initialize new random number stream:
|
||||||
|
cont=1
|
||||||
|
dum=rn(seed,gtype,cont)
|
||||||
|
|
||||||
|
!.. create all the parameter sets by random numbers
|
||||||
|
!continue with the initialized random number stream
|
||||||
|
cont=0
|
||||||
|
do i=2,nset
|
||||||
|
do j=1,npar
|
||||||
|
par(j,i)=prange(1,j)+rn(seed,gtype,cont) *
|
||||||
|
$ (prange(2,j)-prange(1,j))
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
!% SUBROUTINE ACTINIT(...)
|
||||||
|
!%
|
||||||
|
!% subroutine to select the active parameters and assign their indices
|
||||||
|
!%
|
||||||
|
!% Input Variables:
|
||||||
|
!% p_act: vector of active cards
|
||||||
|
!% npar: total number of parameters
|
||||||
|
!%
|
||||||
|
!% Output Variables:
|
||||||
|
!% iact: list of active parameters
|
||||||
|
!% mfit: number of active parameters
|
||||||
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
subroutine actinit(p_act,iact,mfit,npar)
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
integer i, npar, p_act(npar), iact(npar), mfit
|
||||||
|
|
||||||
|
mfit=0
|
||||||
|
iact=0
|
||||||
|
do i=1,npar
|
||||||
|
! Nicole: added flexible value of p_act
|
||||||
|
if (p_act(i).ge.1) then
|
||||||
|
mfit=mfit+1
|
||||||
|
iact(mfit)=i
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
end module init_mod
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,558 @@
|
||||||
|
module marq_mod
|
||||||
|
implicit none
|
||||||
|
logical, parameter :: dbg = .false.
|
||||||
|
|
||||||
|
!Fabian: Declare visibility of subroutines in this module for other modules
|
||||||
|
private
|
||||||
|
public :: mrqmin
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
|
||||||
|
!> Routine for non linear least-squares fitting by the Marquardt-Levenberg method.
|
||||||
|
!! The current implementation is based on Numerical Recipies pp. 526ff.
|
||||||
|
!! This subroutine is only called by the parent subroutine fit and and itself only calls funcs as a subroutine, which is the interface to the user-specific model routines.
|
||||||
|
!!
|
||||||
|
!! @author Fabian Fritsch
|
||||||
|
!! @version 0.2
|
||||||
|
!! @date 15.03.2022
|
||||||
|
!!
|
||||||
|
!! @todo Implement different versions of the Marquardt-Levenberg method, e.g. MINPACK.
|
||||||
|
|
||||||
|
subroutine mrqmin(par,npar,ma,mfit,rms,micit,set)
|
||||||
|
use dim_parameter, only: log_convergence
|
||||||
|
implicit none
|
||||||
|
! Input variables (not changed within this subroutine).
|
||||||
|
integer npar !< number of parameters
|
||||||
|
integer mfit !< number of active parameters
|
||||||
|
integer ma(npar) !< array that contains info if a parameter is active or not
|
||||||
|
integer micit !< number of microiterations / optimization cycles for the Marquardt Levenberg algorithm
|
||||||
|
integer set !number of current set
|
||||||
|
! Input/output variables (changed/updated within this subroutine)
|
||||||
|
double precision par(npar) !< parameter vector (on input: guess for parameters, on output: optimized parameters)
|
||||||
|
! Output variables
|
||||||
|
|
||||||
|
double precision rms !< root mean square error for the optimized parameter set
|
||||||
|
|
||||||
|
! Internal variables (used at most by subordinated subroutines)
|
||||||
|
!> @param alpha weighted approximation to the Hesse matrix (wt**2 * J^T * J)
|
||||||
|
!> @param covar damped alpha, ie. (wt**2 * J^T * J + alamda * 1)
|
||||||
|
double precision alpha(mfit,mfit) !< weighted approximation to the Hesse matrix (wt**2 * J^T * J) / curvature matrix
|
||||||
|
double precision covar(mfit,mfit) !< damped alpha, ie. (wt**2 * J^T * J + alamda * diag(J^T * J))
|
||||||
|
double precision da(mfit) !< J^T * (difference between y and fitted y)
|
||||||
|
double precision beta(mfit) !< @param[in] beta J^T * (difference between y and fitted y)
|
||||||
|
|
||||||
|
logical skip !< logical: true, if a parameter set must be skipped
|
||||||
|
|
||||||
|
double precision chisq !< chi-squared error (current parameter set)
|
||||||
|
double precision ochisq !< chi-squared error (previous best parameter set)
|
||||||
|
double precision alamda !< Marquardt-Levenberg parameter
|
||||||
|
|
||||||
|
double precision atry(npar) !< work array for temporal storage of the changed parameter vector
|
||||||
|
double precision asave(npar) !< work array for temporal storage of the changed parameter vector
|
||||||
|
|
||||||
|
double precision trust !< trust region parameter
|
||||||
|
double precision ilamda !< initial value for the Marquardt Levenberg parameter alamda
|
||||||
|
|
||||||
|
logical quit
|
||||||
|
|
||||||
|
! Internal variables
|
||||||
|
|
||||||
|
integer i,j,lauf !< iteration variables
|
||||||
|
double precision incr_alamda !< increase factor of alamda
|
||||||
|
double precision decr_alamda !< decrease facotr of alamda
|
||||||
|
|
||||||
|
character(len=80) file_name,fmt
|
||||||
|
integer id_plot
|
||||||
|
integer counter
|
||||||
|
integer rejected
|
||||||
|
|
||||||
|
! Lapack variables (for details,see lapack documentation for the called subroutine)
|
||||||
|
|
||||||
|
integer info
|
||||||
|
double precision work(mfit)
|
||||||
|
integer*8 lwork !important that its 64bit!
|
||||||
|
integer*8 ipiv(mfit)
|
||||||
|
|
||||||
|
!> Open logging files
|
||||||
|
if (log_convergence) then
|
||||||
|
write (file_name,"('.conv_marq_set',i0,'.dat')") set
|
||||||
|
id_plot=6666+set
|
||||||
|
open(id_plot,file=trim(file_name),action='write')
|
||||||
|
write (id_plot,69)
|
||||||
|
69 format ('#Levenberg-Marquardt',/,
|
||||||
|
+ '#it = iteration number',/,
|
||||||
|
+ '#nf = number of function evaluations',/,
|
||||||
|
+ '#stepl = step length used',/,
|
||||||
|
+ '#tstep = norm of the displacement (total step)',/,
|
||||||
|
+ '#projg = norm of the projected gradient',/,
|
||||||
|
+ '#f = function value')
|
||||||
|
write (id_plot,123)
|
||||||
|
123 format ('#',3x,'it',3x,'nf',3x,'stepl',4x,'pstep',5x,
|
||||||
|
$ 'projg',8x,'f')
|
||||||
|
endif
|
||||||
|
!> Initialize skip, Marquardt parameter, error variables and parameter work arrays
|
||||||
|
|
||||||
|
skip=.false.
|
||||||
|
ilamda=0.1d0 !Initial Marquardt parameter
|
||||||
|
alamda=ilamda !Current Marquardt parameter
|
||||||
|
rms=1.d6
|
||||||
|
atry(1:npar)=par(1:npar)
|
||||||
|
asave(1:npar)=par(1:npar)
|
||||||
|
|
||||||
|
!Fabian: Adjusted values (TO-DO: Make this Input-Cards)
|
||||||
|
trust=2.0d+1
|
||||||
|
incr_alamda=1.5d0
|
||||||
|
decr_alamda=1.d0/1.5d0
|
||||||
|
|
||||||
|
counter=0
|
||||||
|
rejected=0
|
||||||
|
alpha=0.d0
|
||||||
|
beta=0.d0
|
||||||
|
chisq=0.d0
|
||||||
|
|
||||||
|
!> Calculate RMS error for the given start parameters
|
||||||
|
|
||||||
|
call mrqcof(par,npar,ma,mfit,
|
||||||
|
$ alpha,beta,chisq,skip)
|
||||||
|
ochisq=chisq
|
||||||
|
|
||||||
|
!Check initial Hessian for (trivial) rank-deficiency
|
||||||
|
!This check reveals for which parameter no data is available, i.e no optimization will occur although the parameter is active
|
||||||
|
!Note: In general, rank deficiency might lead to ambiguous results when solving the normal equations. Here this will not occur due to the regularization in the LM-Algorithm
|
||||||
|
if (dbg) then
|
||||||
|
do i=1,mfit
|
||||||
|
if(all(abs(alpha(i,:)).lt.1E-16)) then
|
||||||
|
write(6,*)
|
||||||
|
$ 'Warning: Rank deficiency of J^T*J for active param',i
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
!> Termination if micit=0, i.e. only genetic algorithm and no LM optimization
|
||||||
|
if (micit.eq.0) then
|
||||||
|
rms=dsqrt(chisq)
|
||||||
|
if (log_convergence) close(id_plot)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
!> Write warning and return if error for initial parameters is large
|
||||||
|
if (skip) then
|
||||||
|
write(6,*) 'WARNING: initial parameter set skipped'
|
||||||
|
! call flush
|
||||||
|
! flush(6)
|
||||||
|
rms=1.e6
|
||||||
|
if (log_convergence) close(id_plot)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!> Start optimization of parameters using the Marquardt-Levenberg algorihm
|
||||||
|
|
||||||
|
do lauf=1,micit
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------o
|
||||||
|
|
||||||
|
!> Scale approximated Hessian (alpha = wt**2 * J^T * J) if necessary
|
||||||
|
call mrqrescale(mfit,alpha)
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!> Calculate covariance matrix and "gradient": wt**2 * J^T * J + alamda * diag(J^T * J) == alpha + alamda * diag(J^T * J)
|
||||||
|
|
||||||
|
!Copy alpha to covar and beta to da
|
||||||
|
covar(1:mfit,1:mfit)=alpha(1:mfit,1:mfit)
|
||||||
|
da(1:mfit)=beta(1:mfit)
|
||||||
|
!Adjust diagonal elements of covar by alamda
|
||||||
|
do i=1,mfit
|
||||||
|
covar(i,i)=covar(i,i)*(1.d0 + alamda)
|
||||||
|
if (dabs(covar(i,i)).lt.1.d-12) then
|
||||||
|
covar(i,i)=1.d-8
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!> Solve set of equations, i.e. covar * vec = da
|
||||||
|
|
||||||
|
!Lapack version (on output: da contains solution the equation, called shift vector)
|
||||||
|
ipiv=0
|
||||||
|
lwork = max(1,mfit)
|
||||||
|
call dsysv('U',mfit,1,covar,mfit,ipiv,da,mfit, !qr decomposition
|
||||||
|
$ work,lwork,info)
|
||||||
|
! call dposv('U',mfit,1,covar,mfit,da,mfit, !cholesky decomposition
|
||||||
|
! $ info)
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!> Calculate trust region of the shift vector, if necessary rescale the entire shift vector
|
||||||
|
|
||||||
|
call mrqtrustregion(trust,npar,ma,par,mfit,da)
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!> Check if the new (rescaled) parameters are better then the previous best (micro)iteration
|
||||||
|
|
||||||
|
!Calculate the new parameters and write them on atry
|
||||||
|
j=0
|
||||||
|
do i=1,npar
|
||||||
|
!Nicole: added flexible value of ma
|
||||||
|
if (ma(i).ge.1) then
|
||||||
|
! if (abs(ma(i)).eq.1) then
|
||||||
|
j=j+1
|
||||||
|
atry(i)=par(i)+da(j)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!Calculate RMS with the new parameters atry
|
||||||
|
call mrqcof(atry,npar,ma,mfit,
|
||||||
|
$ covar,da,chisq,skip)
|
||||||
|
|
||||||
|
! Write warning, if mrqcof (more precisely funcs within mrqcof) yields the skip message
|
||||||
|
if (skip) then
|
||||||
|
write(6,*) 'WARNING: parameter set skipped'
|
||||||
|
! call flush
|
||||||
|
! flush(6)
|
||||||
|
rms=1.e6
|
||||||
|
if (log_convergence) close(id_plot)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
!Compare the new RMS with the RMS of the previous best parameters, if yes: save the parameters
|
||||||
|
if(chisq.lt.ochisq) then
|
||||||
|
counter=counter+1 !number of accepted steps
|
||||||
|
asave(1:npar)=atry(1:npar)
|
||||||
|
!Write logging information
|
||||||
|
if(log_convergence) then
|
||||||
|
write(id_plot,124) counter,lauf,1.d0,sum((atry-par)**2),
|
||||||
|
$ sum(da**2),chisq
|
||||||
|
124 format(1x,2(1x,i4),1p,2(2x,e8.1),1p,2(1x,e10.3))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Perform convergence / error checks
|
||||||
|
quit=.false.
|
||||||
|
call mrqconvergence(lauf,micit,npar,par,mfit,da,asave,
|
||||||
|
$ chisq,ochisq,rms,rejected,quit)
|
||||||
|
if(quit) then
|
||||||
|
if (log_convergence) close(id_plot)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Increase counter of consecutive rejected steps by one
|
||||||
|
rejected=rejected+1
|
||||||
|
|
||||||
|
!Adjust the marquardt parameter (alamda) for the next iteration
|
||||||
|
!If chisq has been reduced: Update alpha, beta, par and ochisq
|
||||||
|
if (chisq.lt.ochisq) then
|
||||||
|
rejected=0 !reset counter of consecutive rejected step
|
||||||
|
alamda=alamda*decr_alamda
|
||||||
|
if(alamda.lt.1E-8) alamda=1E-8
|
||||||
|
alpha(1:mfit,1:mfit)=covar(1:mfit,1:mfit)
|
||||||
|
beta(1:mfit)=da(1:mfit)
|
||||||
|
par(1:npar)=atry(1:npar)
|
||||||
|
ochisq=chisq
|
||||||
|
else
|
||||||
|
alamda=alamda*incr_alamda
|
||||||
|
!If after a certain number of iterations in which the rms is not reduced or convergence occurs,
|
||||||
|
!alamda takes a certain value, then take the result of this iteration as a new input guess !
|
||||||
|
if (alamda.gt.1.d5) then
|
||||||
|
write(6,*) 'Warning: Large alamda, try new parameters'
|
||||||
|
alamda=ilamda
|
||||||
|
par(1:npar)=atry(1:npar)
|
||||||
|
ochisq=chisq
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(log_convergence) close(id_plot)
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
|
||||||
|
c###############################################################
|
||||||
|
|
||||||
|
!> Routine for calculating the residuals, gradients, approximated Hessian for the Marquardt-Levenberg-Algorithm
|
||||||
|
|
||||||
|
subroutine mrqcof(par,npar,ma,mfit,
|
||||||
|
$ alpha,beta,chisq,skip)
|
||||||
|
|
||||||
|
use dim_parameter, only: ntot,qn,numdatpt,nstat,hybrid
|
||||||
|
|
||||||
|
use data_module, only: x1_m,x2_m,y_m,wt_m,ny_m
|
||||||
|
use funcs_mod,only: funcs
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
! Input variables (not changed within this subroutine).
|
||||||
|
! double precision q(*),x1(*),x2(*),y(*),ny(*),wt(*) !< coordinates,data and weights
|
||||||
|
integer npar !< number of parameters
|
||||||
|
double precision par(npar) !< parameter vector (on input: guess for parameters, on output: optimized parameters)
|
||||||
|
integer mfit !< number of active parameters
|
||||||
|
integer ma(npar) !< array that contains info if a parameter is active or not
|
||||||
|
|
||||||
|
! Output variables
|
||||||
|
double precision alpha(mfit,mfit) !< weighted approximation to the Hesse matrix (wt**2 * J^T * J) / curvature matrix
|
||||||
|
double precision beta(mfit) !< weighted J^T * (difference between y and fitted y)
|
||||||
|
double precision chisq !< chisq error
|
||||||
|
logical skip !< logical: true, if a parameter set must be skipped
|
||||||
|
|
||||||
|
! Internal variables (used at most by subordinated subroutines)
|
||||||
|
double precision ymod(ntot) !< fitted datapoints (for one geometry)
|
||||||
|
double precision dy(ntot) !< difference between ab-initio and fitted datapoints
|
||||||
|
double precision dyda(ntot,npar) !gradient of datapoints (for one geometry) with respect to the parameters
|
||||||
|
|
||||||
|
! Internal variables
|
||||||
|
integer i,j,k,l,m,n !< iteration variables
|
||||||
|
integer nloop
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!> Initialize skip, alpha, beta and chisq
|
||||||
|
|
||||||
|
skip=.false.
|
||||||
|
alpha(1:mfit,1:mfit)=0.d0
|
||||||
|
beta(1:mfit)=0.d0
|
||||||
|
chisq=0.d0
|
||||||
|
|
||||||
|
nloop=ntot
|
||||||
|
if(.not.hybrid) nloop=nstat
|
||||||
|
|
||||||
|
do i=1,numdatpt
|
||||||
|
|
||||||
|
call funcs(i,par,ymod,dyda,npar,ma,skip)
|
||||||
|
if (skip) return
|
||||||
|
|
||||||
|
!Idea: Since the quantities dyda,dy and wt_m are rather small, one might consider scaling them
|
||||||
|
!Idea: and then rescale the final quantities alpha,beta,chisq accordingly
|
||||||
|
!Idea: Scale dyda,dy and wt_m by 1D+5; final rescale of alpha,beta and chisq by 1D-10
|
||||||
|
|
||||||
|
do n=1,nloop
|
||||||
|
dy(n)=y_m(n,i)-ymod(n)
|
||||||
|
j=0
|
||||||
|
do l=1,npar
|
||||||
|
! Nicole: values of ma (active parameter) changed
|
||||||
|
if (ma(l).ge.1) then
|
||||||
|
j=j+1
|
||||||
|
k=0
|
||||||
|
do m=1,l
|
||||||
|
! Nicole: values of ma (active parameter) changed
|
||||||
|
if (ma(m).ge.1) then
|
||||||
|
k=k+1
|
||||||
|
!(wt*J)^T*(wt*J)
|
||||||
|
alpha(j,k)=alpha(j,k)+
|
||||||
|
$ (dyda(n,l)*dyda(n,m))*(wt_m(n,i)*wt_m(n,i))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
!(wt*J)^T*(wt*delta_y)
|
||||||
|
beta(j)=beta(j)+
|
||||||
|
$ (dy(n)*dyda(n,l))*(wt_m(n,i)*wt_m(n,i))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
!(wt*delta_y)*(wt*delta_y)
|
||||||
|
chisq=chisq+
|
||||||
|
$ (dy(n)*dy(n))*(wt_m(n,i)*wt_m(n,i))
|
||||||
|
enddo
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
!Fill in missing parts of the symmetric matrix alpha
|
||||||
|
do i=2,mfit
|
||||||
|
do j=1,i-1
|
||||||
|
alpha(j,i)=alpha(i,j)
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
c###############################################################
|
||||||
|
|
||||||
|
!> Scale approximated Hessian (alpha = wt**2 * J^T * J) if necessary
|
||||||
|
subroutine mrqrescale(mfit,alpha)
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
!> Input variables
|
||||||
|
integer mfit
|
||||||
|
|
||||||
|
!> Input/output variables
|
||||||
|
double precision alpha(mfit,mfit)
|
||||||
|
|
||||||
|
!> Internal variables
|
||||||
|
double precision dum !Maik changed to double from int
|
||||||
|
integer i,j
|
||||||
|
|
||||||
|
!> Find largest value of the approximated Hessian alpha
|
||||||
|
dum=0.d0
|
||||||
|
do i=1,mfit
|
||||||
|
do j=1,mfit
|
||||||
|
if (abs(alpha(i,j)).gt.dum) dum=abs(alpha(i,j)) !find largest value of the approximated Hessian
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!> Rescale approximated Hessian if largest value is greater then a threshold (hardcoded)
|
||||||
|
if (dum.gt.1.d30) then
|
||||||
|
dum=1.d3/dum
|
||||||
|
write(6,'(''Warning: Hessian scaled by'',d12.3)') dum
|
||||||
|
write(6,*)
|
||||||
|
do i=1,mfit
|
||||||
|
do j=1,mfit
|
||||||
|
alpha(i,j)=alpha(i,j)*dum
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
c###############################################################
|
||||||
|
|
||||||
|
subroutine mrqtrustregion(trust,npar,ma,par,mfit,da)
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
!> Input variables
|
||||||
|
double precision trust
|
||||||
|
integer npar
|
||||||
|
integer ma(npar)
|
||||||
|
double precision par(npar)
|
||||||
|
integer mfit
|
||||||
|
|
||||||
|
!> Input/output variables
|
||||||
|
double precision da(mfit)
|
||||||
|
|
||||||
|
!> Internal variables
|
||||||
|
integer i,j
|
||||||
|
double precision dum
|
||||||
|
|
||||||
|
!Init
|
||||||
|
dum=0.d0
|
||||||
|
j=0
|
||||||
|
|
||||||
|
!Find the largest relative (magnitude of gradient / magnitude of parameter = da / par ) shift of a parameter
|
||||||
|
!Explanation: For parameters of high scale, their gradients are also of high scale even if the relative change is small
|
||||||
|
do i=1,npar
|
||||||
|
! Nicole: values of ma (active parameter) changed
|
||||||
|
if (ma(i).ge.1) then
|
||||||
|
j=j+1
|
||||||
|
if (abs(par(i)).gt.1.d-4) then
|
||||||
|
if (abs(da(j)/par(i)).gt.dum) then
|
||||||
|
dum=abs(da(j)/par(i))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
!If maximum relative shift exceeds a threshold, scale shift vector
|
||||||
|
if (dum.gt.trust) then
|
||||||
|
dum=trust/dum
|
||||||
|
j=0
|
||||||
|
do i=1,npar
|
||||||
|
! Nicole: values of ma (active parameter) changed
|
||||||
|
if (ma(i).ge.1) then
|
||||||
|
j=j+1
|
||||||
|
da(j)=da(j)*dum
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
c###############################################################
|
||||||
|
|
||||||
|
!> Perform convergence and error checks
|
||||||
|
subroutine mrqconvergence(lauf,micit,npar,par,mfit,da,asave,
|
||||||
|
$ chisq,ochisq,rms,rejected,quit)
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
!> Input variables
|
||||||
|
integer lauf
|
||||||
|
integer micit
|
||||||
|
integer npar
|
||||||
|
integer mfit
|
||||||
|
double precision da(mfit)
|
||||||
|
double precision asave(npar)
|
||||||
|
double precision chisq
|
||||||
|
double precision ochisq
|
||||||
|
integer rejected !number of consecutive rejected steps
|
||||||
|
|
||||||
|
|
||||||
|
!> Input/Output variables
|
||||||
|
double precision par(npar)
|
||||||
|
double precision rms
|
||||||
|
|
||||||
|
!> Output variable
|
||||||
|
logical quit
|
||||||
|
|
||||||
|
!> Internal variables
|
||||||
|
integer i
|
||||||
|
double precision dum
|
||||||
|
double precision check
|
||||||
|
|
||||||
|
|
||||||
|
quit=.false.
|
||||||
|
|
||||||
|
!Negative termination, if rms is too large, quit this iteration
|
||||||
|
if (chisq.gt.1.d3) then
|
||||||
|
write(6,*) 'chi^2 unreasonable!', chisq, lauf
|
||||||
|
rms=dsqrt(ochisq)
|
||||||
|
par(1:npar)=asave(1:npar)
|
||||||
|
quit=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Negative-neutral termination, if maximum number of consecutive not accepted microiterations reached
|
||||||
|
if (rejected.ge.25) then
|
||||||
|
write(6,*) 'Warning: 25 consecutive non accepted steps!'
|
||||||
|
if (chisq.lt.ochisq) rms=dsqrt(chisq)
|
||||||
|
if (chisq.ge.ochisq) rms=dsqrt(ochisq)
|
||||||
|
par(1:npar)=asave(1:npar)
|
||||||
|
quit=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Neutral termination, if number of maximum microiterations reached, quit the LM algorithm
|
||||||
|
if (lauf.eq.micit) then
|
||||||
|
if (chisq.lt.ochisq) rms=dsqrt(chisq)
|
||||||
|
if (chisq.ge.ochisq) rms=dsqrt(ochisq)
|
||||||
|
par(1:npar)=asave(1:npar)
|
||||||
|
write(6,'(''Warning: iterations exceeded: '',I0)') lauf
|
||||||
|
quit=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Neutral-positive termination, if parameter changes are small
|
||||||
|
check=0.d0
|
||||||
|
do i=1,mfit
|
||||||
|
check=check+da(i)**2
|
||||||
|
enddo
|
||||||
|
check=dsqrt(check) !root mean square of gradient
|
||||||
|
if (check.lt.1.d-15) then
|
||||||
|
write(6,*) 'change of parameters converged', check, lauf
|
||||||
|
rms=dsqrt(chisq)
|
||||||
|
par(1:npar)=asave(1:npar)
|
||||||
|
quit=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
!Positive termination, if difference between the previous lowest/optimal chisq (that is ochisq) & the current chisq is small
|
||||||
|
dum=max(chisq,ochisq)/min(chisq,ochisq) - 1.d0
|
||||||
|
if ((dum.lt.1.d-5).and.(lauf.gt.1)) then !change of chi^2 < 0.01%
|
||||||
|
write(6,*) 'change of chi^2 converged', dum, lauf
|
||||||
|
! call flush !Fabian 15.03.2022: Not sure, why this is called
|
||||||
|
! flush(6)
|
||||||
|
rms=dsqrt(chisq)
|
||||||
|
par(1:npar)=asave(1:npar)
|
||||||
|
quit=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
end module marq_mod
|
|
@ -0,0 +1,203 @@
|
||||||
|
#ifdef mpi_version
|
||||||
|
subroutine mpi_rest_control(micit,npar)
|
||||||
|
use mpi
|
||||||
|
implicit none
|
||||||
|
! global permanent data (only transferred once)
|
||||||
|
integer npar
|
||||||
|
integer mfit
|
||||||
|
integer micit
|
||||||
|
integer ma(npar)
|
||||||
|
integer ierror
|
||||||
|
integer i
|
||||||
|
integer mode
|
||||||
|
logical runner
|
||||||
|
integer status(MPI_STATUS_SIZE)
|
||||||
|
|
||||||
|
! do loop around this, checking for next fit or finish
|
||||||
|
call bcastact(ma,npar)
|
||||||
|
call MPI_Bcast(mfit, 1, MPI_INT, 0, MPI_COMM_WORLD,ierror)
|
||||||
|
|
||||||
|
runner=.true.
|
||||||
|
do while(runner)
|
||||||
|
|
||||||
|
call MPI_Recv(mode, 1, MPI_INTEGER, 0, 69, MPI_COMM_WORLD,
|
||||||
|
$ status,ierror)
|
||||||
|
|
||||||
|
if(mode.ne.0) then
|
||||||
|
call mpi_fit_single_set(npar,mfit,micit,ma,mode)
|
||||||
|
else
|
||||||
|
runner=.false.
|
||||||
|
endif
|
||||||
|
end do
|
||||||
|
call MPI_Barrier(MPI_COMM_WORLD, ierror)
|
||||||
|
end
|
||||||
|
|
||||||
|
!-----------------------------------------------
|
||||||
|
|
||||||
|
c this does a single crunch of data
|
||||||
|
subroutine mpi_fit_single_set(npar,mfit,micit,ma,nset)
|
||||||
|
use mpi
|
||||||
|
use dim_parameter, only: lbfgs
|
||||||
|
use marq_mod,only: mrqmin
|
||||||
|
use lbfgsb_mod,only: lbfgs_driver
|
||||||
|
implicit none
|
||||||
|
integer npar,mfit,micit,ierror,ma(*)
|
||||||
|
integer status(MPI_STATUS_SIZE), nset, my_rank
|
||||||
|
double precision par(npar), rms, startzeit, endzeit
|
||||||
|
|
||||||
|
startzeit = MPI_Wtime()
|
||||||
|
|
||||||
|
! receive data via blocking receive
|
||||||
|
call MPI_Recv(par, npar, MPI_DOUBLE_PRECISION, 0, 13,
|
||||||
|
$ MPI_COMM_WORLD, status, ierror)
|
||||||
|
call MPI_Recv(rms, 1, MPI_DOUBLE_PRECISION, 0, 14,
|
||||||
|
$ MPI_COMM_WORLD, status, ierror)
|
||||||
|
|
||||||
|
if(lbfgs) then
|
||||||
|
call lbfgs_driver(par,npar,ma,mfit,
|
||||||
|
& rms,micit,nset)
|
||||||
|
else
|
||||||
|
call mrqmin(par,npar,ma,mfit,
|
||||||
|
& rms,micit,nset)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierror)
|
||||||
|
|
||||||
|
! send back data via blocking send
|
||||||
|
call MPI_Send(par, npar, MPI_DOUBLE_PRECISION, 0, 23,
|
||||||
|
$ MPI_COMM_WORLD, ierror)
|
||||||
|
call MPI_Send(rms, 1, MPI_DOUBLE_PRECISION, 0, 24, MPI_COMM_WORLD,
|
||||||
|
$ ierror)
|
||||||
|
|
||||||
|
|
||||||
|
endzeit = MPI_Wtime()
|
||||||
|
|
||||||
|
write(6,*) 'Thread', my_rank ,'Zeit:', endzeit-startzeit
|
||||||
|
|
||||||
|
!> Write output for the spezific set of parameters
|
||||||
|
write(6,99) nset, rms, rms*219474.69d0
|
||||||
|
99 format('Set:',i5,5x,'RMS:',g16.6,3x,'(',f16.6,' cm-1)')
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
!-----------------------------------------------
|
||||||
|
|
||||||
|
subroutine bcastact(act,len)
|
||||||
|
use mpi
|
||||||
|
implicit none
|
||||||
|
integer len
|
||||||
|
integer act(len)
|
||||||
|
integer ierror
|
||||||
|
|
||||||
|
call MPI_Bcast(act, len, MPI_INT, 0, MPI_COMM_WORLD,ierror)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
!-----------------------------------------------
|
||||||
|
|
||||||
|
subroutine workshare(numthreads, par, rms, npar, nset)
|
||||||
|
use mpi
|
||||||
|
implicit none
|
||||||
|
integer numthreads,ierror,nset,npar
|
||||||
|
double precision, asynchronous :: par(npar,nset),rms(nset)
|
||||||
|
logical working(numthreads-1)
|
||||||
|
logical sent,received_rms,received_par,received
|
||||||
|
integer request_par(8,numthreads-1)
|
||||||
|
integer request_rms(8,numthreads-1)
|
||||||
|
integer ping(8)
|
||||||
|
integer nextworker
|
||||||
|
integer i,j,k
|
||||||
|
integer worksignal
|
||||||
|
integer status(MPI_STATUS_SIZE)
|
||||||
|
integer (kind=MPI_ADDRESS_KIND) :: iadummy
|
||||||
|
|
||||||
|
! init working array
|
||||||
|
do i = 1,numthreads
|
||||||
|
working(i) = .false.
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do i = 1,nset
|
||||||
|
|
||||||
|
! do a round of sending
|
||||||
|
sent=.false.
|
||||||
|
do while(.not.sent)
|
||||||
|
|
||||||
|
do j = 1,numthreads-1
|
||||||
|
if(.not.working(j)) then
|
||||||
|
working(j)=.true.
|
||||||
|
nextworker = j
|
||||||
|
sent=.true.
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(sent) then
|
||||||
|
call MPI_Issend(i, 1, MPI_INTEGER,
|
||||||
|
$ nextworker, 69, MPI_COMM_WORLD, ping(1), ierror)
|
||||||
|
call MPI_Issend(par(1,i), npar, MPI_DOUBLE_PRECISION,
|
||||||
|
$ nextworker, 13, MPI_COMM_WORLD, request_par(1
|
||||||
|
$ ,nextworker), ierror)
|
||||||
|
call MPI_Issend(rms(i), 1, MPI_DOUBLE_PRECISION,
|
||||||
|
$ nextworker, 14, MPI_COMM_WORLD, request_rms(1
|
||||||
|
$ ,nextworker), ierror)
|
||||||
|
|
||||||
|
! wait for Issend to finish (Hannes initial position for these statements --> runs parallel)
|
||||||
|
call MPI_Wait(ping(1), status, ierror)
|
||||||
|
call MPI_Wait(request_par(1,nextworker), status, ierror)
|
||||||
|
call MPI_Wait(request_rms(1,nextworker), status, ierror)
|
||||||
|
|
||||||
|
call MPI_Irecv(par(1,i), npar, MPI_DOUBLE_PRECISION,
|
||||||
|
$ nextworker, 23, MPI_COMM_WORLD, request_par(1
|
||||||
|
$ ,nextworker) , ierror)
|
||||||
|
|
||||||
|
call MPI_Irecv(rms(i), 1, MPI_DOUBLE_PRECISION,
|
||||||
|
$ nextworker, 24, MPI_COMM_WORLD, request_rms(1
|
||||||
|
$ ,nextworker), ierror)
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
! check finished workers
|
||||||
|
do j = 1,numthreads-1
|
||||||
|
if(working(j)) then
|
||||||
|
received_rms=.false.
|
||||||
|
received_par=.false.
|
||||||
|
call MPI_Test(request_par(1,j), received_rms,
|
||||||
|
$ status, ierror)
|
||||||
|
call MPI_Test(request_rms(1,j), received_par,
|
||||||
|
$ status, ierror)
|
||||||
|
if(received_par.and.received_rms) then
|
||||||
|
working(j) = .false.
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
received = .false.
|
||||||
|
do while(.not.received)
|
||||||
|
do j = 1,numthreads-1
|
||||||
|
if(working(j)) then
|
||||||
|
received_rms=.false.
|
||||||
|
received_par=.false.
|
||||||
|
call MPI_Test(request_par(1,j), received_rms,
|
||||||
|
$ MPI_STATUS_IGNORE, ierror)
|
||||||
|
call MPI_Test(request_rms(1,j), received_par,
|
||||||
|
$ MPI_STATUS_IGNORE, ierror)
|
||||||
|
if(received_par.and.received_rms) then
|
||||||
|
working(j) = .false.
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
received=.true.
|
||||||
|
do j = 1,numthreads-1
|
||||||
|
if(working(j)) then
|
||||||
|
received = .false.
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end
|
||||||
|
#endif
|
|
@ -0,0 +1,32 @@
|
||||||
|
**** ERROR CATALOGUE -- this defines what kind of errors parse.f throws
|
||||||
|
|
||||||
|
|
||||||
|
! 1 32 64
|
||||||
|
! v v v
|
||||||
|
! '................................................................'
|
||||||
|
errcat( 1)='ILLOGICALLY SMALL VALUE'
|
||||||
|
errcat( 2)='VALUE EXCEEDS SET MAXIMUM'
|
||||||
|
errcat( 3)='GIVEN DATA STRUCTURE SIZE INCONSISTENT WITH'
|
||||||
|
> // ' PREVIOUS DECLARATION'
|
||||||
|
errcat( 4)='VALUE GREATER THAN SET MAXIMUM'
|
||||||
|
errcat( 5)='VALUE LESS THAN SET MINIMUM'
|
||||||
|
errcat( 6)='IMPLIED DATA POINT NUMBER INCONSISTENT WITH NPAT'
|
||||||
|
errcat( 7)='PERCENTAGE NOT WITHIN MEANINGFUL RANGE (0.0-100.0)'
|
||||||
|
errcat( 8)='MISSING KEY CLASHES WITH PREVIOUS DECLARATION'
|
||||||
|
errcat( 9)='MAXIMUM IDENTICAL TO MINIMUM'
|
||||||
|
errcat(10)='DEPRECATED COMMAND: FEATURE HAS BEEN REMOVED, '
|
||||||
|
> // 'SEE PARSER.'
|
||||||
|
errcat(11)='TOO MANY ARGUMENTS'
|
||||||
|
! errcat(12)=
|
||||||
|
! errcat(13)=
|
||||||
|
! errcat(14)=
|
||||||
|
! errcat(15)=
|
||||||
|
! errcat(16)=
|
||||||
|
! errcat(17)=
|
||||||
|
! errcat(18)=
|
||||||
|
! errcat(19)=
|
||||||
|
! errcat(20)=
|
||||||
|
! errcat(21)=
|
||||||
|
! errcat(22)=
|
||||||
|
! errcat(23)=
|
||||||
|
! errcat(24)=
|
|
@ -0,0 +1,55 @@
|
||||||
|
module io_parameters
|
||||||
|
implicit none
|
||||||
|
! ******************************************************************************
|
||||||
|
! **** I/O-Parameters
|
||||||
|
! ***
|
||||||
|
! *** dnlen: maximum char length of data file path
|
||||||
|
! *** maxlines: maximum input file length
|
||||||
|
! *** llen: character maximum per line
|
||||||
|
! *** maxdat: maximum number of input data values of one kind
|
||||||
|
! *** (e.g. integer values) excluding DATA: block
|
||||||
|
! *** clen: max. character length of string data
|
||||||
|
! *** klen: maximum length of key or typestring
|
||||||
|
! *** maxkeys: max. number of keys
|
||||||
|
! *** maxerrors: max. number of pre-defined error messages.
|
||||||
|
|
||||||
|
integer, parameter :: dnlen = 8192
|
||||||
|
integer, parameter :: maxlines = 3000000,llen = 750
|
||||||
|
integer, parameter :: klen=20,maxkeys=200
|
||||||
|
integer, parameter :: maxdat=2000,clen=1024
|
||||||
|
integer, parameter :: maxerrors=100
|
||||||
|
! Declarations for general Keylist and error massages
|
||||||
|
integer :: keynum !< keynum number of general keys
|
||||||
|
integer :: datpos(3,maxdat) !< datpos Pointer to type, data adress and length for each general key
|
||||||
|
character(len=klen) :: keylist(2,maxkeys) !< list of general program keys for programm control and parameter initialisation defined in keylist.incl
|
||||||
|
character(len=64) :: errcat(maxerrors) !< list of generic error Messages defined in errcat.incl
|
||||||
|
|
||||||
|
! parameter key declaration
|
||||||
|
integer, parameter :: maxpar_keys=400 !<maximum number of parameter keys
|
||||||
|
character(len=klen) :: key(4,maxpar_keys) !<list of parameter keys (1-4: number,value,active?,spread)
|
||||||
|
integer :: parkeynum !< actual number of parameterkeys specified
|
||||||
|
integer :: parkeylen !< lenght of longest parameterkey string
|
||||||
|
|
||||||
|
!**********************************************************
|
||||||
|
!**** Error Codes
|
||||||
|
!*** Codes should be powers of 2. Binary representation of return value
|
||||||
|
!*** should correspond to all exceptions invoked. ec_error should never
|
||||||
|
!*** be invoked with any other.
|
||||||
|
!***
|
||||||
|
!*** ec_error: generic error (catch-all, avoid!)
|
||||||
|
!*** ec_read: parsing error during les()
|
||||||
|
!*** ec_dim: dimensioning error
|
||||||
|
!*** ec_log: logic error
|
||||||
|
!***
|
||||||
|
!**** Inferred error codes
|
||||||
|
!*** ec_dimrd: ec_dim+ec_read
|
||||||
|
|
||||||
|
|
||||||
|
integer, parameter :: ec_error=1, ec_read=2, ec_dim=4, ec_log=8
|
||||||
|
integer, parameter :: ec_dimrd=ec_dim+ec_read
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,301 @@
|
||||||
|
**** KEYLIST -- this defines what kind of keys genANN is able to process syntactially
|
||||||
|
|
||||||
|
keylist=' '
|
||||||
|
|
||||||
|
! The only "special" key in the sense that it terminates input
|
||||||
|
keylist(1, 1)='DATA:'
|
||||||
|
keylist(2, 1)='E!'
|
||||||
|
|
||||||
|
keylist(1, 2)='SEED:'
|
||||||
|
keylist(2, 2)='I1'
|
||||||
|
|
||||||
|
keylist(1, 3)='NSET:'
|
||||||
|
keylist(2, 3)='+I1'
|
||||||
|
|
||||||
|
keylist(1, 4)='FREEZE:'
|
||||||
|
keylist(2, 4)='E'
|
||||||
|
|
||||||
|
keylist(1, 5)='NSTAT:'
|
||||||
|
keylist(2, 5)='+I1!'
|
||||||
|
|
||||||
|
keylist(1, 6)='NCI:'
|
||||||
|
keylist(2, 6)='+I1'
|
||||||
|
|
||||||
|
keylist(1, 7)='NDIAB:'
|
||||||
|
keylist(2, 7)='+I1'
|
||||||
|
|
||||||
|
keylist(1, 8)='HYBRID:'
|
||||||
|
keylist(2, 8)='E'
|
||||||
|
|
||||||
|
keylist(1, 9)='SEL:'
|
||||||
|
keylist(2, 9)='+D1'
|
||||||
|
|
||||||
|
keylist(1,10)='MUT:'
|
||||||
|
keylist(2,10)='+D1'
|
||||||
|
|
||||||
|
keylist(1,11)='DIFPER:'
|
||||||
|
keylist(2,11)='+D1'
|
||||||
|
|
||||||
|
keylist(1,12)='GTYPE:'
|
||||||
|
keylist(2,12)='+I1'
|
||||||
|
|
||||||
|
keylist(1,13)='MAXIT:'
|
||||||
|
keylist(2,13)='+I1'
|
||||||
|
|
||||||
|
keylist(1,14)='MICIT:'
|
||||||
|
keylist(2,14)='+I1'
|
||||||
|
|
||||||
|
keylist(1,15)='GSPREAD:'
|
||||||
|
keylist(2,15)='+D1'
|
||||||
|
|
||||||
|
keylist(1,16)='SETS:'
|
||||||
|
keylist(2,16)='+IN!'
|
||||||
|
|
||||||
|
keylist(1,17)='INPUTS:'
|
||||||
|
keylist(2,17)='+IN!'
|
||||||
|
|
||||||
|
keylist(1,18)='ENCIRATIO:'
|
||||||
|
keylist(2,18)='+D1'
|
||||||
|
|
||||||
|
keylist(1,19)='WTEN:'
|
||||||
|
keylist(2,19)='+DN'
|
||||||
|
|
||||||
|
keylist(1,20)='WTCI:'
|
||||||
|
keylist(2,20)='+DN'
|
||||||
|
|
||||||
|
keylist(1,21)='NPOINTS:'
|
||||||
|
keylist(2,21)='+IN!'
|
||||||
|
|
||||||
|
keylist(1,22)='NTOT:'
|
||||||
|
keylist(2,22)='+I1'
|
||||||
|
|
||||||
|
keylist(1,23)='RMSTHR:'
|
||||||
|
keylist(2,23)='+DN'
|
||||||
|
|
||||||
|
keylist(1,24)='ANAGRAD:'
|
||||||
|
keylist(2,24)='E'
|
||||||
|
|
||||||
|
keylist(1,25)='LBFGS:'
|
||||||
|
keylist(2,25)='E'
|
||||||
|
|
||||||
|
keylist(1,26)='LBFGSCORR:'
|
||||||
|
keylist(2,26)='+I1'
|
||||||
|
|
||||||
|
keylist(1,27)='FACSPREAD:'
|
||||||
|
keylist(2,27)='+D1'
|
||||||
|
|
||||||
|
keylist(1,28)='LOGCONVERGENCE:'
|
||||||
|
keylist(2,28)='E'
|
||||||
|
|
||||||
|
keylist(1,29)='COORD:'
|
||||||
|
keylist(2,29)='IN'
|
||||||
|
|
||||||
|
! keylist(1,30)=
|
||||||
|
! keylist(2,30)=
|
||||||
|
!
|
||||||
|
! keylist(1,31)=
|
||||||
|
! keylist(2,31)=
|
||||||
|
!
|
||||||
|
! keylist(1,32)=
|
||||||
|
! keylist(2,32)=
|
||||||
|
!
|
||||||
|
! keylist(1,33)=
|
||||||
|
! keylist(2,33)=
|
||||||
|
!
|
||||||
|
! keylist(1,34)=
|
||||||
|
! keylist(2,34)=
|
||||||
|
!
|
||||||
|
! keylist(1,35)=
|
||||||
|
! keylist(2,35)=
|
||||||
|
!
|
||||||
|
! keylist(1,36)=
|
||||||
|
! keylist(2,36)=
|
||||||
|
!
|
||||||
|
! keylist(1,37)=
|
||||||
|
! keylist(2,37)=
|
||||||
|
!
|
||||||
|
! keylist(1,38)=
|
||||||
|
! keylist(2,38)=
|
||||||
|
!
|
||||||
|
! keylist(1,39)=
|
||||||
|
! keylist(2,39)=
|
||||||
|
!
|
||||||
|
! keylist(1,40)=
|
||||||
|
! keylist(2,40)=
|
||||||
|
!
|
||||||
|
! keylist(1,41)=
|
||||||
|
! keylist(2,41)=
|
||||||
|
!
|
||||||
|
! keylist(1,42)=
|
||||||
|
! keylist(2,42)=
|
||||||
|
!
|
||||||
|
! keylist(1,43)=
|
||||||
|
! keylist(2,43)=
|
||||||
|
!
|
||||||
|
! keylist(1,44)=
|
||||||
|
! keylist(2,44)=
|
||||||
|
!
|
||||||
|
! keylist(1,45)=
|
||||||
|
! keylist(2,45)=
|
||||||
|
!
|
||||||
|
! keylist(1,46)=
|
||||||
|
! keylist(2,46)=
|
||||||
|
!
|
||||||
|
! keylist(1,47)=
|
||||||
|
! keylist(2,47)=
|
||||||
|
!
|
||||||
|
! keylist(1,48)=
|
||||||
|
! keylist(2,48)=
|
||||||
|
!
|
||||||
|
! keylist(1,49)=
|
||||||
|
! keylist(2,49)=
|
||||||
|
!
|
||||||
|
! keylist(1,50)=
|
||||||
|
! keylist(2,50)=
|
||||||
|
!
|
||||||
|
! keylist(1,51)=
|
||||||
|
! keylist(2,51)=
|
||||||
|
!
|
||||||
|
! keylist(1,52)=
|
||||||
|
! keylist(2,52)=
|
||||||
|
!
|
||||||
|
! keylist(1,53)=
|
||||||
|
! keylist(2,53)=
|
||||||
|
!
|
||||||
|
! keylist(1,54)=
|
||||||
|
! keylist(2,54)=
|
||||||
|
!
|
||||||
|
! keylist(1,55)=
|
||||||
|
! keylist(2,55)=
|
||||||
|
!
|
||||||
|
! keylist(1,56)=
|
||||||
|
! keylist(2,56)=
|
||||||
|
!
|
||||||
|
! keylist(1,57)=
|
||||||
|
! keylist(2,57)=
|
||||||
|
!
|
||||||
|
! keylist(1,58)=
|
||||||
|
! keylist(2,58)=
|
||||||
|
!
|
||||||
|
! keylist(1,59)=
|
||||||
|
! keylist(2,59)=
|
||||||
|
!
|
||||||
|
! keylist(1,60)=
|
||||||
|
! keylist(2,60)=
|
||||||
|
|
||||||
|
! keylist(1,61)=
|
||||||
|
! keylist(2,61)=
|
||||||
|
!
|
||||||
|
! keylist(1,62)=
|
||||||
|
! keylist(2,62)=
|
||||||
|
!
|
||||||
|
! keylist(1,63)=
|
||||||
|
! keylist(2,63)=
|
||||||
|
!
|
||||||
|
! keylist(1,64)=
|
||||||
|
! keylist(2,64)=
|
||||||
|
!
|
||||||
|
! keylist(1,65)=
|
||||||
|
! keylist(2,65)=
|
||||||
|
!
|
||||||
|
! keylist(1,66)=
|
||||||
|
! keylist(2,66)=
|
||||||
|
!
|
||||||
|
! keylist(1,67)=
|
||||||
|
! keylist(2,67)=
|
||||||
|
!
|
||||||
|
! keylist(1,68)=
|
||||||
|
! keylist(2,68)=
|
||||||
|
!
|
||||||
|
! keylist(1,69)=
|
||||||
|
! keylist(2,69)=
|
||||||
|
!
|
||||||
|
! keylist(1,70)=
|
||||||
|
! keylist(2,70)=
|
||||||
|
!
|
||||||
|
! keylist(1,71)=
|
||||||
|
! keylist(2,71)=
|
||||||
|
!
|
||||||
|
! keylist(1,72)=
|
||||||
|
! keylist(2,72)=
|
||||||
|
!
|
||||||
|
! keylist(1,73)=
|
||||||
|
! keylist(2,73)=
|
||||||
|
!
|
||||||
|
! keylist(1,74)=
|
||||||
|
! keylist(2,74)=
|
||||||
|
!
|
||||||
|
! keylist(1,75)=
|
||||||
|
! keylist(2,75)=
|
||||||
|
!
|
||||||
|
! keylist(1,76)=
|
||||||
|
! keylist(2,76)=
|
||||||
|
!
|
||||||
|
! keylist(1,77)=
|
||||||
|
! keylist(2,77)=
|
||||||
|
!
|
||||||
|
! keylist(1,78)=
|
||||||
|
! keylist(2,78)=
|
||||||
|
!
|
||||||
|
! keylist(1,79)=
|
||||||
|
! keylist(2,79)=
|
||||||
|
!
|
||||||
|
! keylist(1,80)=
|
||||||
|
! keylist(2,80)=
|
||||||
|
!
|
||||||
|
! keylist(1,81)=
|
||||||
|
! keylist(2,81)=
|
||||||
|
!
|
||||||
|
! keylist(1,82)=
|
||||||
|
! keylist(2,82)=
|
||||||
|
!
|
||||||
|
! keylist(1,83)=
|
||||||
|
! keylist(2,83)=
|
||||||
|
!
|
||||||
|
! keylist(1,84)=
|
||||||
|
! keylist(2,84)=
|
||||||
|
!
|
||||||
|
! keylist(1,85)=
|
||||||
|
! keylist(2,85)=
|
||||||
|
!
|
||||||
|
! keylist(1,86)=
|
||||||
|
! keylist(2,86)=
|
||||||
|
!
|
||||||
|
! keylist(1,87)=
|
||||||
|
! keylist(2,87)=
|
||||||
|
!
|
||||||
|
! keylist(1,88)=
|
||||||
|
! keylist(2,88)=
|
||||||
|
!
|
||||||
|
! keylist(1,89)=
|
||||||
|
! keylist(2,89)=
|
||||||
|
!
|
||||||
|
! keylist(1,90)=
|
||||||
|
! keylist(2,90)=
|
||||||
|
!
|
||||||
|
! keylist(1,91)=
|
||||||
|
! keylist(2,91)=
|
||||||
|
!
|
||||||
|
! keylist(1,92)=
|
||||||
|
! keylist(2,92)=
|
||||||
|
!
|
||||||
|
! keylist(1,93)=
|
||||||
|
! keylist(2,93)=
|
||||||
|
!
|
||||||
|
! keylist(1,94)=
|
||||||
|
! keylist(2,94)=
|
||||||
|
!
|
||||||
|
! keylist(1,95)=
|
||||||
|
! keylist(2,95)=
|
||||||
|
!
|
||||||
|
! keylist(1,96)=
|
||||||
|
! keylist(2,96)=
|
||||||
|
!
|
||||||
|
! keylist(1,97)=
|
||||||
|
! keylist(2,97)=
|
||||||
|
!
|
||||||
|
! keylist(1,98)=
|
||||||
|
! keylist(2,98)=
|
||||||
|
!
|
||||||
|
! keylist(1,99)=
|
||||||
|
! keylist(2,99)=
|
|
@ -0,0 +1,148 @@
|
||||||
|
module fileread_mod
|
||||||
|
contains
|
||||||
|
!-------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine get_datfile(datnam,dnlen)
|
||||||
|
implicit none
|
||||||
|
! Get name of input data file DATNAM either from the program's first
|
||||||
|
! command line argument or ask the user.
|
||||||
|
|
||||||
|
integer dnlen
|
||||||
|
character(len=dnlen) datnam
|
||||||
|
|
||||||
|
integer argcount
|
||||||
|
|
||||||
|
argcount=iargc()
|
||||||
|
if (argcount.gt.0) then
|
||||||
|
call getarg(1,datnam)
|
||||||
|
else
|
||||||
|
write(6,'(A)') 'Specify input file:'
|
||||||
|
read(*,*) datnam
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (len_trim(datnam).eq.dnlen) then
|
||||||
|
write(6,'(A)') 'ERROR: TRUNCATED FILENAME'
|
||||||
|
write(6,'(A)') '"' // datnam // '"'
|
||||||
|
endif
|
||||||
|
|
||||||
|
end subroutine get_datfile
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine internalize_datfile(datnam,infile,linenum,llen,
|
||||||
|
> maxlines,dnlen)
|
||||||
|
use strings_mod,only:write_oneline,int2string
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
! Read input file located at DATNAM, skipping comments and blank lines.
|
||||||
|
integer dnlen,llen,maxlines
|
||||||
|
integer linenum
|
||||||
|
character(len=dnlen) datnam
|
||||||
|
character(len=llen) infile(maxlines)
|
||||||
|
|
||||||
|
character(len=llen) line
|
||||||
|
|
||||||
|
!character*16 int2string
|
||||||
|
|
||||||
|
integer j
|
||||||
|
|
||||||
|
!Fabian
|
||||||
|
character(len=llen) fmt,fmt2
|
||||||
|
integer,parameter :: std_out = 6
|
||||||
|
integer,parameter :: funit = 10
|
||||||
|
write(fmt,'(A)') 'Reading file ''' // trim(datnam) // ''' ...'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
open(unit=funit,file=datnam)
|
||||||
|
linenum=0
|
||||||
|
do j=1,maxlines
|
||||||
|
!read(funit,fmt='(A<llen>)',end=20) line !<var> works only for ifort, not for gfortran or mpif90
|
||||||
|
write(fmt2,'("(A",I3,")")') llen !Fabian
|
||||||
|
read(funit,fmt=fmt2,end=20) line !Fabian
|
||||||
|
if (line(1:3).eq.'---') then
|
||||||
|
write(fmt,'(A)') 'EOF-mark "---" found at line'
|
||||||
|
> // trim(int2string(j))
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
call internalize_line(linenum,infile,line,llen,maxlines)
|
||||||
|
enddo
|
||||||
|
20 close(funit)
|
||||||
|
|
||||||
|
if (j.ge.maxlines) then
|
||||||
|
write(6,'(A)') 'ERROR: FILE LENGTH EXCEEDING MAXLINES.'
|
||||||
|
stop 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'(A)') 'File read successfully ('
|
||||||
|
> // trim(int2string(linenum)) // ' lines).'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
end subroutine internalize_datfile
|
||||||
|
|
||||||
|
!-------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine internalize_line(linenum,infile,line,llen,maxlines)
|
||||||
|
use strings_mod,only: strip_string,upcase
|
||||||
|
implicit none
|
||||||
|
! Parse a single line of input. Ignore comments ("!..") and blank
|
||||||
|
! lines, and turn all input to uppercase.
|
||||||
|
!
|
||||||
|
! infile: data file's internalized form
|
||||||
|
! line: single verbatim line read from physical file
|
||||||
|
! linenum: current number of non-commentlines read
|
||||||
|
! increased by 1 if read line is not a comment
|
||||||
|
! llen: maximum character length of a single line
|
||||||
|
! maxlines: maximum number of lines in infile
|
||||||
|
|
||||||
|
integer llen,maxlines
|
||||||
|
integer linenum
|
||||||
|
character(len=llen) infile(maxlines)
|
||||||
|
character(len=llen) line
|
||||||
|
|
||||||
|
character(len=llen) strip
|
||||||
|
integer line_pos,text_end
|
||||||
|
|
||||||
|
integer j
|
||||||
|
|
||||||
|
line_pos=linenum+1
|
||||||
|
|
||||||
|
! ignore empty lines
|
||||||
|
if (len_trim(line).eq.0) then
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! strip needless whitespace
|
||||||
|
call strip_string(line,strip,llen)
|
||||||
|
|
||||||
|
! determine EOL
|
||||||
|
! ignore comments
|
||||||
|
text_end=0
|
||||||
|
do j=1,len_trim(strip)
|
||||||
|
if (strip(j:j).eq.'!') then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
text_end=text_end+1
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (text_end.eq.llen) then
|
||||||
|
write(6,'(A,I6)') 'WARNING: POTENTIALLY TRUNCATED LINE:'
|
||||||
|
write(6,'(A)') '"' // strip(1:60) // '"...'
|
||||||
|
endif
|
||||||
|
|
||||||
|
! skip if line is a comment
|
||||||
|
if (text_end.eq.0) then
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
infile(line_pos)=' '
|
||||||
|
|
||||||
|
! turn string to uppercase and write to infile, ignoring comments
|
||||||
|
call upcase(strip,infile(line_pos),text_end)
|
||||||
|
|
||||||
|
! increment line number
|
||||||
|
linenum=linenum+1
|
||||||
|
|
||||||
|
end subroutine internalize_line
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,274 @@
|
||||||
|
module keyread_mod
|
||||||
|
contains
|
||||||
|
|
||||||
|
subroutine keyread(keylist,infile,keynum,idat,ddat,cdat,datpos,
|
||||||
|
> klen,llen,clen,linenum,maxdat)
|
||||||
|
use long_keyread_mod,only:long_intkey,long_realkey,long_strkey
|
||||||
|
use strings_mod,only:int2string,dble2string
|
||||||
|
implicit none
|
||||||
|
! Read all keys from KEYLIST from INFILE and write their associated
|
||||||
|
! data to the corresponding data block. Memory management is
|
||||||
|
! handled by DATPOS.
|
||||||
|
!
|
||||||
|
! keylist: Registry of keys containing the name of the key
|
||||||
|
! and it's type information.
|
||||||
|
! keylist(N,1): keyname. It should be in all-caps.
|
||||||
|
! keylist(N,2): type string of the form "X#"
|
||||||
|
!
|
||||||
|
! Note: Key 1 (keylist(1,1)) has the special property that all
|
||||||
|
! lines of the input file after it's first occurence will be
|
||||||
|
! ignored. This allows for long input files holding non-key
|
||||||
|
! information.
|
||||||
|
!
|
||||||
|
! typestring syntax:
|
||||||
|
! X should be I (Integer), +I (Int >= 0), D (double precision),
|
||||||
|
! C (character string), +D (real >= 0.0d0)
|
||||||
|
! or E (checks whether key exists).
|
||||||
|
! X! (e.g. +I!, D!,..) makes a key non-optional.
|
||||||
|
! E!, while absurd, is a valid option.
|
||||||
|
! # should be either N (meaning variable length) or an integer >0.
|
||||||
|
! it encodes the expected number of read values
|
||||||
|
!
|
||||||
|
! note: the E-type has no associated *dat-array, instead
|
||||||
|
! datpos(2,N) is either -1 or it's last occurence in infile,
|
||||||
|
! depending on whether the key was found. Furthermore,
|
||||||
|
! E-type keys accept no arguments.
|
||||||
|
!
|
||||||
|
! *dat: data arrays for respective items
|
||||||
|
! klen: length of key/typestring
|
||||||
|
! llen: line length of infile
|
||||||
|
! clen: length of read strings
|
||||||
|
! keynum: number of keys
|
||||||
|
! linenum: number of lines the file has
|
||||||
|
! maxdat: maximum number of total input values read
|
||||||
|
! infile: input file
|
||||||
|
! datpos: integer array assigning read values to the keys
|
||||||
|
! datpos(1,N): internalized type (0: I, 1: +I, 2: D, 3: +D,
|
||||||
|
! 4: C, 5: E)
|
||||||
|
! datpos(2,N): starting pos. in respective data array
|
||||||
|
! datpos(3,N): length of data block
|
||||||
|
!
|
||||||
|
|
||||||
|
!? WARNING: *dat() MAY BE WRITTEN BEYOND THEIR LENGTH FOR BAD DIMENSIONS.
|
||||||
|
!? CATCH THIS!
|
||||||
|
|
||||||
|
integer klen, llen, clen
|
||||||
|
integer keynum, linenum, maxdat
|
||||||
|
character(len=klen) keylist(2,keynum)
|
||||||
|
character(len=llen) infile(linenum)
|
||||||
|
integer datpos(3,maxdat)
|
||||||
|
|
||||||
|
integer idat(maxdat)
|
||||||
|
double precision ddat(maxdat)
|
||||||
|
character(len=clen) cdat(maxdat)
|
||||||
|
character(len=klen) key
|
||||||
|
character(len=64) errmsg
|
||||||
|
|
||||||
|
integer intype,inlen,readlen
|
||||||
|
integer cstart,istart,dstart
|
||||||
|
integer key_end
|
||||||
|
integer datnum,inpos,datlen
|
||||||
|
integer file_stop
|
||||||
|
logical optional2
|
||||||
|
|
||||||
|
integer j,k
|
||||||
|
|
||||||
|
cstart=1
|
||||||
|
istart=1
|
||||||
|
dstart=1
|
||||||
|
datnum=0
|
||||||
|
|
||||||
|
file_stop=linenum
|
||||||
|
key=keylist(1,1)
|
||||||
|
key_end=len_trim(key)
|
||||||
|
if (key_end.ne.0) then
|
||||||
|
do k=1,linenum
|
||||||
|
if (infile(k)(1:key_end).eq.trim(key)) then
|
||||||
|
file_stop=k
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
do j=1,keynum
|
||||||
|
key=keylist(1,j)
|
||||||
|
|
||||||
|
! get information needed to read key
|
||||||
|
call get_key_kind(keylist(:,j),intype,optional2,inlen,klen)
|
||||||
|
datpos(1,j)=intype
|
||||||
|
key_end=len_trim(key)
|
||||||
|
|
||||||
|
! find last invocation of key (if present)
|
||||||
|
inpos=0
|
||||||
|
do k=1,file_stop
|
||||||
|
if (infile(k)(1:key_end).eq.trim(key)) then
|
||||||
|
inpos=k
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (inpos.eq.0) then
|
||||||
|
if (.not.optional2) then
|
||||||
|
errmsg='MISSING, NON-OPTIONAL KEY'
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
endif
|
||||||
|
datpos(2,j)=-1
|
||||||
|
datpos(3,j)=0
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
|
||||||
|
! read from last occurence of key
|
||||||
|
readlen=0
|
||||||
|
if (intype.le.1) then
|
||||||
|
datlen=maxdat-istart+1
|
||||||
|
call long_intkey(infile,inpos,key_end,
|
||||||
|
> idat,istart,readlen,llen,maxdat,linenum)
|
||||||
|
else if (intype.le.3) then
|
||||||
|
datlen=maxdat-dstart+1
|
||||||
|
call long_realkey(infile,inpos,key_end,
|
||||||
|
> ddat,dstart,readlen,llen,maxdat,linenum)
|
||||||
|
else if (intype.eq.4) then
|
||||||
|
call long_strkey(infile,inpos,key_end,
|
||||||
|
> cdat,cstart,readlen,llen,maxdat,linenum,clen)
|
||||||
|
else if (intype.eq.5) then
|
||||||
|
! since datpos already encodes whether the key was found,
|
||||||
|
! there is no need to save anything
|
||||||
|
readlen=0
|
||||||
|
else
|
||||||
|
write(6,*) 'ERROR: ENCOUNTERED FAULTY TYPE SPEC.'
|
||||||
|
stop 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
! check validity of input length
|
||||||
|
if (inlen.eq.-1) then
|
||||||
|
inlen=readlen
|
||||||
|
else if (inlen.ne.readlen) then
|
||||||
|
errmsg='WRONG NUMBER OF ARGUMENTS'
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
endif
|
||||||
|
|
||||||
|
! check sign of +X types
|
||||||
|
if (intype.eq.1) then
|
||||||
|
do k=1,inlen
|
||||||
|
if (idat(istart-1+k).lt.0) then
|
||||||
|
errmsg='UNEXPECTED NEGATIVE INTEGER: '
|
||||||
|
> // trim(int2string(idat(istart-1+k)))
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
else if (intype.eq.3) then
|
||||||
|
do k=1,inlen
|
||||||
|
if (ddat(dstart-1+k).lt.0.0d0) then
|
||||||
|
errmsg='UNEXPECTED NEGATIVE REAL: '
|
||||||
|
> // trim(dble2string(ddat(dstart-1+k)))
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (intype.le.1) then
|
||||||
|
datpos(2,j)=istart
|
||||||
|
istart=istart+inlen
|
||||||
|
else if (intype.le.3) then
|
||||||
|
datpos(2,j)=dstart
|
||||||
|
dstart=dstart+inlen
|
||||||
|
else if (intype.eq.4) then
|
||||||
|
datpos(2,j)=cstart
|
||||||
|
dstart=cstart+inlen
|
||||||
|
else if (intype.eq.5) then
|
||||||
|
! remember where you last found the key in infile
|
||||||
|
datpos(2,j)=inpos
|
||||||
|
endif
|
||||||
|
|
||||||
|
datpos(3,j)=inlen
|
||||||
|
|
||||||
|
enddo
|
||||||
|
end subroutine keyread
|
||||||
|
|
||||||
|
|
||||||
|
subroutine get_key_kind(kentry,dattype,optional2,datlen,klen)
|
||||||
|
use strings_mod,only:trimnum,nth_word
|
||||||
|
implicit none
|
||||||
|
! Read typestring from a keylist entry KENTRY and extract the
|
||||||
|
! specific type and expected length of KEYs input.
|
||||||
|
!
|
||||||
|
! dattype: type of the data, encoded as int
|
||||||
|
! optional: true if key does not need to be present
|
||||||
|
! datlen: number of values expected
|
||||||
|
! klen: length of keys
|
||||||
|
|
||||||
|
include 'typedef.incl'
|
||||||
|
|
||||||
|
integer klen
|
||||||
|
integer dattype,datlen
|
||||||
|
character(len=klen) kentry(2)
|
||||||
|
logical optional2
|
||||||
|
|
||||||
|
character(len=klen) typestr,key,tmp,numstr
|
||||||
|
character(len=64) errmsg
|
||||||
|
integer strpos,typelen
|
||||||
|
|
||||||
|
integer j
|
||||||
|
|
||||||
|
key=kentry(1)
|
||||||
|
typestr=kentry(2)
|
||||||
|
strpos=0
|
||||||
|
dattype=-1
|
||||||
|
! check type declaration against defined types in typedef.incl
|
||||||
|
do j=1,typenum
|
||||||
|
typelen=len_trim(types(j))
|
||||||
|
if (typestr(1:typelen).eq.trim(types(j))) then
|
||||||
|
dattype=j-1
|
||||||
|
strpos=typelen+1
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (dattype.eq.-1) then
|
||||||
|
errmsg='INVALID TYPE SPEC: '//'"'//typestr(1:maxtypelen)//'"'
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Any type followed by ! makes the card non-optional, crashing the
|
||||||
|
! program if it is missing.
|
||||||
|
optional2=(typestr(strpos:strpos).ne.'!')
|
||||||
|
if (.not.optional2) then
|
||||||
|
strpos=strpos+1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (dattype.eq.5) then
|
||||||
|
! since only the key's presence is checked, there is no need to
|
||||||
|
! read beyond the key
|
||||||
|
datlen=0
|
||||||
|
else if (typestr(strpos:strpos).eq.'N') then
|
||||||
|
datlen=-1
|
||||||
|
else
|
||||||
|
call trimnum(typestr,tmp,klen)
|
||||||
|
call nth_word(tmp,numstr,1,klen)
|
||||||
|
! crash gracefully if the expected number of values is neither
|
||||||
|
! int nor "N" (hackey version, but i can't think of a cleaner one)
|
||||||
|
do j=1,1
|
||||||
|
read(numstr,*,err=600,end=600) datlen
|
||||||
|
cycle
|
||||||
|
600 errmsg='CORRUPTED NUMBER OF VALUES: '
|
||||||
|
> //'"'//trim(typestr)//'"'
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
enddo
|
||||||
|
if (datlen.le.0) then
|
||||||
|
errmsg='INVALID TYPE SPEC: '//'"'//trim(typestr)//'"'
|
||||||
|
call signal_key_error(key,errmsg,klen)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
end subroutine get_key_kind
|
||||||
|
|
||||||
|
|
||||||
|
subroutine signal_key_error(key,msg,klen)
|
||||||
|
implicit none
|
||||||
|
integer klen
|
||||||
|
character(len=klen) key
|
||||||
|
character(len=*) msg
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(key) // ' ' // trim(msg)
|
||||||
|
stop 1
|
||||||
|
end subroutine signal_key_error
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,601 @@
|
||||||
|
module long_keyread_mod
|
||||||
|
contains
|
||||||
|
|
||||||
|
! NOTE: all routines other than long_intkey and long_intline are
|
||||||
|
! copy-pasted versions of different types.
|
||||||
|
! replacements:
|
||||||
|
! idat -> *dat
|
||||||
|
! ipos -> *pos
|
||||||
|
! istart -> *start
|
||||||
|
! LONG_INT -> LONG_*
|
||||||
|
|
||||||
|
!---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine long_intkey(infile,inpos,key_end,idat,istart,
|
||||||
|
> readlen,linelen,maxdat,maxlines)
|
||||||
|
implicit none
|
||||||
|
! Read an arbitrary number of integers for a single key from infile
|
||||||
|
! and write to idat.
|
||||||
|
!
|
||||||
|
! Data in infile is expected to have the general format
|
||||||
|
!
|
||||||
|
! KEY: ... ... ... ... &
|
||||||
|
! .... ... ... ... ... &
|
||||||
|
! .... ... ... ... ...
|
||||||
|
!
|
||||||
|
! Lines can be continued using the continuation marker arbitrarily
|
||||||
|
! often. A continuation marker at the last line causes the program
|
||||||
|
! to read undefined data following below. If that data is not a
|
||||||
|
! valid line of integers, the program breaks appropiately.
|
||||||
|
!
|
||||||
|
! idat: vector to write read data on
|
||||||
|
! istart: current position in vector idat (first empty entry)
|
||||||
|
! maxdat: length of idat
|
||||||
|
! readlen: the number of read integers for current key
|
||||||
|
!
|
||||||
|
! infile: string vector containing the read input file linewise
|
||||||
|
! key_end: length of key, expected at the first line read
|
||||||
|
! inpos: current position in infile
|
||||||
|
! linelen: max. character length of a single line
|
||||||
|
! maxlines: length of infile
|
||||||
|
!
|
||||||
|
! broken: if true, assume read data to be corrupt
|
||||||
|
! continued: if true, the next input line should continue
|
||||||
|
! the current data block.
|
||||||
|
|
||||||
|
|
||||||
|
integer maxlines,linelen,maxdat
|
||||||
|
integer key_end
|
||||||
|
integer istart,inpos,readlen
|
||||||
|
integer idat(maxdat)
|
||||||
|
character(len=linelen) infile(maxlines)
|
||||||
|
logical continued, broken
|
||||||
|
|
||||||
|
|
||||||
|
integer line_start,ipos
|
||||||
|
character(len=linelen) key
|
||||||
|
|
||||||
|
integer n
|
||||||
|
|
||||||
|
ipos=istart
|
||||||
|
readlen=0
|
||||||
|
|
||||||
|
key=' '
|
||||||
|
key=infile(inpos)(1:key_end)
|
||||||
|
|
||||||
|
! skip key on first line
|
||||||
|
line_start=key_end+1
|
||||||
|
|
||||||
|
call long_intline(infile(inpos),linelen,line_start,
|
||||||
|
> idat,ipos,maxdat,readlen,
|
||||||
|
> continued,broken)
|
||||||
|
|
||||||
|
line_start=1
|
||||||
|
do n=inpos+1,maxlines
|
||||||
|
if (broken) then
|
||||||
|
continued=.false.
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
if (.not.continued) then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
call long_intline(infile(n),linelen,line_start,
|
||||||
|
> idat,ipos,maxdat,readlen,
|
||||||
|
> continued,broken)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (continued) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_INTKEY: '
|
||||||
|
> // trim(key) //' CONTINUATION PAST EOF'
|
||||||
|
write(6,'(A,I5.5)') 'LINE #',n
|
||||||
|
endif
|
||||||
|
if (broken) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_INTKEY: '
|
||||||
|
> // trim(key) //' BROKEN INPUT.'
|
||||||
|
write(6,'(A,I5.5)') 'LINE #',n
|
||||||
|
write(6,'(A,I5.5,A)') 'AFTER ', n-inpos-1, ' CONTINUATIONS'
|
||||||
|
stop 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
end subroutine long_intkey
|
||||||
|
|
||||||
|
!---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine long_intline(inline,linelen,line_start,
|
||||||
|
> idat,ipos,maxdat,readlen,
|
||||||
|
> continued,broken)
|
||||||
|
use strings_mod,only: count_words,nth_word
|
||||||
|
implicit none
|
||||||
|
! Read a single line of string input INLINE encoding integers.
|
||||||
|
!
|
||||||
|
! idat: vector to write read data on
|
||||||
|
! ipos: current position in vector idat (first empty entry)
|
||||||
|
! maxdat: length of idat
|
||||||
|
! inline: string containing line from read input file
|
||||||
|
! linelen: max. character length of a single line
|
||||||
|
! broken: if true, assume read data to be corrupt
|
||||||
|
! continued: if true, the next input line should continue
|
||||||
|
! the current data block.
|
||||||
|
! readlen: increment counting the number of read ints
|
||||||
|
! ASSUMED TO BE INITIALIZED.
|
||||||
|
|
||||||
|
integer linelen,maxdat
|
||||||
|
integer line_start,ipos
|
||||||
|
integer idat(maxdat)
|
||||||
|
integer readlen
|
||||||
|
! character(len=linelen) inline
|
||||||
|
character(len=linelen) inline
|
||||||
|
logical continued, broken
|
||||||
|
|
||||||
|
integer line_end, wordcount
|
||||||
|
character(len=linelen) workline, word
|
||||||
|
|
||||||
|
integer n
|
||||||
|
|
||||||
|
line_end=len_trim(inline)
|
||||||
|
broken=.false.
|
||||||
|
|
||||||
|
! check whether line will be continued
|
||||||
|
if (inline(line_end:line_end).eq.'&') then
|
||||||
|
continued=.true.
|
||||||
|
line_end=line_end-1
|
||||||
|
else
|
||||||
|
continued=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
! create working copy of line
|
||||||
|
workline=' '
|
||||||
|
workline=inline(line_start:line_end)
|
||||||
|
|
||||||
|
! check the number of wordcount on line
|
||||||
|
call count_words(workline,wordcount,linelen)
|
||||||
|
|
||||||
|
! if the number of entries exceeds the length of idat, break
|
||||||
|
if ((wordcount+ipos-1).gt.maxdat) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_INTLINE: PARSER OUT OF MEMORY '
|
||||||
|
> // 'ON READ'
|
||||||
|
write(6,'(A)') 'CURRENT LINE:'
|
||||||
|
write(6,'(A)') trim(inline)
|
||||||
|
broken=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
do n=1,wordcount
|
||||||
|
call nth_word(workline,word,n,linelen)
|
||||||
|
read(word,fmt=*,err=600,end=600) idat(ipos)
|
||||||
|
readlen=readlen+1
|
||||||
|
ipos=ipos+1
|
||||||
|
cycle
|
||||||
|
! avoid segfault in parser at all costs, throw error instead
|
||||||
|
600 write(6,'(A,I4.4)') 'ERROR: LONG_INTLINE: '
|
||||||
|
> // 'A FATAL ERROR OCCURED ON ENTRY #',
|
||||||
|
> n
|
||||||
|
write(6,'(A)') 'CURRENT LINE:'
|
||||||
|
write(6,'(A)') trim(inline)
|
||||||
|
broken=.true.
|
||||||
|
return
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine long_intline
|
||||||
|
|
||||||
|
!---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine long_realkey(infile,inpos,key_end,ddat,dstart,
|
||||||
|
> readlen,linelen,maxdat,maxlines)
|
||||||
|
implicit none
|
||||||
|
! Read an arbitrary number of double precisions for a single key from infile
|
||||||
|
! and write to ddat.
|
||||||
|
!
|
||||||
|
! Data in infile is expected to have the general format
|
||||||
|
!
|
||||||
|
! KEY: ... ... ... ... &
|
||||||
|
! .... ... ... ... ... &
|
||||||
|
! .... ... ... ... ...
|
||||||
|
!
|
||||||
|
! Lines can be continued using the continuation marker arbitrarily
|
||||||
|
! often. A continuation marker at the last line causes the program
|
||||||
|
! to read undefined data following below. If that data is not a
|
||||||
|
! valid line of integers, the program breaks appropiately.
|
||||||
|
!
|
||||||
|
! ddat: vector to write read data on
|
||||||
|
! dstart: current position in vector ddat (first empty entry)
|
||||||
|
! maxdat: length of ddat
|
||||||
|
! readlen: the number of read integers for current key
|
||||||
|
!
|
||||||
|
! infile: string vector containing the read input file linewise
|
||||||
|
! key_end: length of key, expected at the first line read
|
||||||
|
! inpos: current position in infile
|
||||||
|
! linelen: max. character length of a single line
|
||||||
|
! maxlines: length of infile
|
||||||
|
!
|
||||||
|
! broken: if true, assume read data to be corrupt
|
||||||
|
! continued: if true, the next input line should continue
|
||||||
|
! the current data block.
|
||||||
|
|
||||||
|
|
||||||
|
integer maxlines,linelen,maxdat
|
||||||
|
integer key_end
|
||||||
|
integer dstart,inpos,readlen
|
||||||
|
double precision ddat(maxdat)
|
||||||
|
character(len=linelen) infile(maxlines)
|
||||||
|
logical continued, broken
|
||||||
|
|
||||||
|
|
||||||
|
integer line_start,dpos
|
||||||
|
character(len=linelen) key
|
||||||
|
|
||||||
|
integer n
|
||||||
|
|
||||||
|
dpos=dstart
|
||||||
|
readlen=0
|
||||||
|
|
||||||
|
key=' '
|
||||||
|
key=infile(inpos)(1:key_end)
|
||||||
|
|
||||||
|
! skip key on first line
|
||||||
|
line_start=key_end+1
|
||||||
|
|
||||||
|
call long_realline(infile(inpos),linelen,line_start,
|
||||||
|
> ddat,dpos,maxdat,readlen,
|
||||||
|
> continued,broken)
|
||||||
|
|
||||||
|
line_start=1
|
||||||
|
do n=inpos+1,maxlines
|
||||||
|
if (broken) then
|
||||||
|
continued=.false.
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
if (.not.continued) then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
call long_realline(infile(n),linelen,line_start,
|
||||||
|
> ddat,dpos,maxdat,readlen,
|
||||||
|
> continued,broken)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (continued) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_REALKEY: '
|
||||||
|
> // trim(key) //' CONTINUATION PAST EOF'
|
||||||
|
write(6,'(A,I5.5)') 'LINE #',n
|
||||||
|
endif
|
||||||
|
if (broken) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_REALKEY: '
|
||||||
|
> // trim(key) //' BROKEN INPUT.'
|
||||||
|
write(6,'(A,I5.5)') 'LINE #',n
|
||||||
|
write(6,'(A,I5.5,A)') 'AFTER ', n-inpos-1, ' CONTINUATIONS'
|
||||||
|
stop 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
end subroutine long_realkey
|
||||||
|
|
||||||
|
!---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine long_realline(inline,linelen,line_start,
|
||||||
|
> ddat,dpos,maxdat,readlen,
|
||||||
|
> continued,broken)
|
||||||
|
use strings_mod,only: count_words,nth_word
|
||||||
|
implicit none
|
||||||
|
! Read a single line of string input INLINE encoding double precisions.
|
||||||
|
!
|
||||||
|
! ddat: vector to write read data on
|
||||||
|
! dpos: current position in vector ddat (first empty entry)
|
||||||
|
! maxdat: length of ddat
|
||||||
|
! inline: string containing line from read input file
|
||||||
|
! linelen: max. character length of a single line
|
||||||
|
! broken: if true, assume read data to be corrupt
|
||||||
|
! continued: if true, the next input line should continue
|
||||||
|
! the current data block.
|
||||||
|
! readlen: increment counting the number of read ints
|
||||||
|
! ASSUMED TO BE INITIALIZED.
|
||||||
|
|
||||||
|
|
||||||
|
integer linelen,maxdat
|
||||||
|
integer line_start,dpos
|
||||||
|
integer readlen
|
||||||
|
double precision ddat(maxdat)
|
||||||
|
character(len=linelen) inline
|
||||||
|
logical continued, broken
|
||||||
|
|
||||||
|
integer line_end, wordcount
|
||||||
|
character(len=linelen) workline, word
|
||||||
|
|
||||||
|
integer n
|
||||||
|
|
||||||
|
line_end=len_trim(inline)
|
||||||
|
broken=.false.
|
||||||
|
|
||||||
|
! check whether line will be continued
|
||||||
|
if (inline(line_end:line_end).eq.'&') then
|
||||||
|
continued=.true.
|
||||||
|
line_end=line_end-1
|
||||||
|
else
|
||||||
|
continued=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
! create working copy of line
|
||||||
|
workline=' '
|
||||||
|
workline=inline(line_start:line_end)
|
||||||
|
|
||||||
|
! check the number of wordcount on line
|
||||||
|
call count_words(workline,wordcount,linelen)
|
||||||
|
|
||||||
|
! if the number of entries exceeds the length of ddat, break
|
||||||
|
if ((wordcount+dpos-1).gt.maxdat) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_REALLINE: PARSER OUT OF MEMORY '
|
||||||
|
> // 'ON READ'
|
||||||
|
write(6,'(A)') 'CURRENT LINE:'
|
||||||
|
write(6,'(A)') trim(inline)
|
||||||
|
write(6,*) 'wordcount',wordcount
|
||||||
|
write(6,*) 'dpos',dpos
|
||||||
|
write(6,*) 'maxdat',maxdat
|
||||||
|
write(6,*) 'ddat',ddat(1:maxdat)
|
||||||
|
broken=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
do n=1,wordcount
|
||||||
|
call nth_word(workline,word,n,linelen)
|
||||||
|
read(word,fmt=*,err=600,end=600) ddat(dpos)
|
||||||
|
readlen=readlen+1
|
||||||
|
dpos=dpos+1
|
||||||
|
cycle
|
||||||
|
! avoid segfault in parser at all costs, throw error instead
|
||||||
|
600 write(6,'(A,I4.4)') 'ERROR: LONG_REALLINE: '
|
||||||
|
> // 'A FATAL ERROR OCCURED ON ENTRY #',
|
||||||
|
> n
|
||||||
|
write(6,'(A)') 'CURRENT LINE:'
|
||||||
|
write(6,'(A)') trim(inline)
|
||||||
|
broken=.true.
|
||||||
|
return
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine long_realline
|
||||||
|
|
||||||
|
!---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine long_strkey(infile,inpos,key_end,cdat,cstart,
|
||||||
|
> readlen,linelen,datlen,maxlines,clen)
|
||||||
|
implicit none
|
||||||
|
! Read an arbitrary number of strings for a single key from infile
|
||||||
|
! and write to idat.
|
||||||
|
!
|
||||||
|
! Data in infile is expected to have the general format
|
||||||
|
!
|
||||||
|
! KEY: ... ... ... ... &
|
||||||
|
! .... ... ... ... ... &
|
||||||
|
! .... ... ... ... ...
|
||||||
|
!
|
||||||
|
! Lines can be continued using the continuation marker arbitrarily
|
||||||
|
! often. A continuation marker at the last line causes the program
|
||||||
|
! to read undefined data following below. If that data is not a
|
||||||
|
! valid line of strings, the program breaks appropiately.
|
||||||
|
!
|
||||||
|
! cdat: vector to write read data on
|
||||||
|
! cstart: current position in vector idat (first empty entry)
|
||||||
|
! datlen: length of idat
|
||||||
|
! readlen: the number of read integers for current key
|
||||||
|
!
|
||||||
|
! infile: string vector containing the read input file linewise
|
||||||
|
! key_end: length of key, expected at the first line read
|
||||||
|
! inpos: current position in infile
|
||||||
|
! linelen: max. character length of a single line
|
||||||
|
! maxlines: length of infile
|
||||||
|
! clen: maximum length of a given string
|
||||||
|
!
|
||||||
|
! broken: if true, assume read data to be corrupt
|
||||||
|
! continued: if true, the next input line should continue
|
||||||
|
! the current data block.
|
||||||
|
! append: if true, continue appending to an existing string.
|
||||||
|
|
||||||
|
|
||||||
|
integer maxlines,linelen,datlen,clen
|
||||||
|
integer key_end
|
||||||
|
integer cstart,inpos,readlen
|
||||||
|
character(len=linelen) infile(maxlines)
|
||||||
|
character(len=clen) cdat(datlen)
|
||||||
|
|
||||||
|
|
||||||
|
integer line_start,cpos
|
||||||
|
integer strpos
|
||||||
|
character(len=linelen) key
|
||||||
|
logical continued, broken
|
||||||
|
|
||||||
|
integer n
|
||||||
|
|
||||||
|
cpos=cstart
|
||||||
|
readlen=0
|
||||||
|
|
||||||
|
key=' '
|
||||||
|
key=infile(inpos)(1:key_end)
|
||||||
|
|
||||||
|
! skip key on first line
|
||||||
|
line_start=key_end+1
|
||||||
|
|
||||||
|
strpos=0
|
||||||
|
|
||||||
|
call long_strline(infile(inpos),linelen,line_start,
|
||||||
|
> cdat,cpos,datlen,readlen,clen,
|
||||||
|
> continued,broken,strpos)
|
||||||
|
|
||||||
|
line_start=1
|
||||||
|
do n=inpos+1,maxlines
|
||||||
|
if (broken) then
|
||||||
|
continued=.false.
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
if (.not.continued) then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
call long_strline(infile(n),linelen,line_start,
|
||||||
|
> cdat,cpos,datlen,readlen,clen,
|
||||||
|
> continued,broken,strpos)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (continued) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_STRKEY: '
|
||||||
|
> // trim(key) //' CONTINUATION PAST EOF'
|
||||||
|
write(6,'(A,I5.5)') 'LINE #',n
|
||||||
|
endif
|
||||||
|
if (broken) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_STRKEY: '
|
||||||
|
> // trim(key) //' BROKEN INPUT.'
|
||||||
|
write(6,'(A,I5.5)') 'LINE #',n
|
||||||
|
write(6,'(A,I5.5,A)') 'AFTER ', n-inpos-1, ' CONTINUATIONS'
|
||||||
|
stop 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
end subroutine long_strkey
|
||||||
|
|
||||||
|
|
||||||
|
!---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine long_strline(inline,linelen,line_start,
|
||||||
|
> cdat,cpos,datlen,readlen,clen,
|
||||||
|
> continued,broken,strpos)
|
||||||
|
use strings_mod,only:iswhitespace, downcase
|
||||||
|
implicit none
|
||||||
|
! Read a single line of string input INLINE encoding integers.
|
||||||
|
!
|
||||||
|
! cdat: vector to write read data on
|
||||||
|
! cpos: current position in vector cdat (first empty/incomplete entry)
|
||||||
|
! datlen: length of idat
|
||||||
|
! inline: string containing line from read input file
|
||||||
|
! linelen: max. character length of a single line
|
||||||
|
! broken: if true, assume read data to be corrupt
|
||||||
|
! continued: if true, the next input line should continue
|
||||||
|
! the current data block.
|
||||||
|
! readlen: increment counting the number of read strings
|
||||||
|
! ASSUMED TO BE INITIALIZED.
|
||||||
|
! strpos: if 0, create new string. Otherwise, append to string of assumed
|
||||||
|
! length strpos.
|
||||||
|
|
||||||
|
integer :: linelen,datlen,clen
|
||||||
|
integer :: line_start,cpos,strpos
|
||||||
|
integer :: readlen
|
||||||
|
character(len=linelen) :: inline
|
||||||
|
character(len=clen) :: cdat(datlen)
|
||||||
|
logical :: continued, broken
|
||||||
|
|
||||||
|
character,parameter :: esc = ACHAR(92) ! "\"
|
||||||
|
|
||||||
|
integer :: line_end
|
||||||
|
character(len=linelen) :: workline
|
||||||
|
character(len=1) :: char, tmp_char
|
||||||
|
|
||||||
|
logical :: cont_string, escaped
|
||||||
|
|
||||||
|
integer :: j
|
||||||
|
|
||||||
|
! logical :: iswhitespace
|
||||||
|
|
||||||
|
broken=.false.
|
||||||
|
continued=.false.
|
||||||
|
cont_string=.false.
|
||||||
|
escaped=.false.
|
||||||
|
|
||||||
|
! create working copy of line
|
||||||
|
workline=' '
|
||||||
|
workline=inline(line_start:len_trim(inline))
|
||||||
|
line_end=len_trim(workline)
|
||||||
|
|
||||||
|
! If needed, initialize working position in cdat
|
||||||
|
if (strpos.eq.0) then
|
||||||
|
cdat(cpos)=' '
|
||||||
|
endif
|
||||||
|
|
||||||
|
! iterate over characters in line
|
||||||
|
do j=1,line_end
|
||||||
|
char=workline(j:j)
|
||||||
|
if (escaped) then
|
||||||
|
! Insert escaped character and proceed.
|
||||||
|
escaped=.false.
|
||||||
|
! Special escape sequences
|
||||||
|
if (char.eq.'.') then
|
||||||
|
! \. = !
|
||||||
|
char='!'
|
||||||
|
endif
|
||||||
|
else if (char.eq.esc) then
|
||||||
|
! Consider next character escaped, skip char.
|
||||||
|
escaped=.true.
|
||||||
|
cycle
|
||||||
|
else if (char.eq.'&') then
|
||||||
|
continued=.true.
|
||||||
|
if (j.eq.line_end) then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
! Deal with unusual continuations, look at char after "&"
|
||||||
|
char=workline(j+1:j+1)
|
||||||
|
if (char.eq.'&') then
|
||||||
|
! "&&" allows multi-line strings
|
||||||
|
cont_string=.true.
|
||||||
|
if (j+1.eq.line_end) then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
write(6,'(A)') 'WARNING: LONG_STRLINE: IGNORED'
|
||||||
|
> // ' JUNK CHARACTER(S) FOLLOWING'
|
||||||
|
> // ' CONTINUATION CHARACTER.'
|
||||||
|
exit
|
||||||
|
else if (iswhitespace(char)) then
|
||||||
|
! Whitespace separates strings; skip char.
|
||||||
|
if (strpos.gt.0) then
|
||||||
|
! Begin a new string unless the current one is empty.
|
||||||
|
strpos=0
|
||||||
|
cpos=cpos+1
|
||||||
|
cdat(cpos)=' '
|
||||||
|
endif
|
||||||
|
cycle
|
||||||
|
else
|
||||||
|
! assume char to be meant as a downcase char
|
||||||
|
call downcase(char,tmp_char,1)
|
||||||
|
char=tmp_char
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Incorporate new char into string
|
||||||
|
strpos=strpos+1
|
||||||
|
|
||||||
|
! Break if a boundary exception occurs
|
||||||
|
if (cpos.gt.datlen) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_STRLINE: PARSER OUT OF MEMORY'
|
||||||
|
> // ' ON READ'
|
||||||
|
write(6,'(A)') 'CURRENT LINE:'
|
||||||
|
write(6,'(A)') trim(inline)
|
||||||
|
broken=.true.
|
||||||
|
return
|
||||||
|
else if (strpos.gt.clen) then
|
||||||
|
write(6,'(A)') 'ERROR: LONG_STRLINE: PARSER OUT OF MEMORY'
|
||||||
|
> // ' ON READ: STRING ARGUMENT EXCEEDS CLEN'
|
||||||
|
write(6,'(A)') 'CURRENT LINE:'
|
||||||
|
write(6,'(A)') trim(inline)
|
||||||
|
broken=.true.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! insert character
|
||||||
|
cdat(cpos)(strpos:strpos)=char
|
||||||
|
if (strpos.eq.1) then
|
||||||
|
readlen=readlen+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! Fix incomplete escape sequences and deal with continuation
|
||||||
|
if (escaped) then
|
||||||
|
write(6,'(A)') 'WARNING: LONG_STRLINE: ENCOUNTERED ESCAPE'
|
||||||
|
> // ' CHARACTER AT EOL. IGNORED.'
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Unless the line ended with "&&", consider the current, non-empty
|
||||||
|
! string complete.
|
||||||
|
if ((cont_string).or.(strpos.eq.0)) then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
cpos=cpos+1
|
||||||
|
strpos=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
end subroutine long_strline
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,505 @@
|
||||||
|
module strings_mod
|
||||||
|
implicit none
|
||||||
|
contains
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------------
|
||||||
|
subroutine capital(in,str,lauf,mmax,sl)
|
||||||
|
integer mmax,lauf,i,j,sl
|
||||||
|
character in(mmax)*(*), str*(*)
|
||||||
|
|
||||||
|
if (str.eq.'') return
|
||||||
|
|
||||||
|
j=0
|
||||||
|
do i=1,sl
|
||||||
|
if (str(i:i).ne.' ') then
|
||||||
|
j=i-1
|
||||||
|
goto 10
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
10 do i=1,sl-j
|
||||||
|
str(i:i)=str(i+j:i+j)
|
||||||
|
enddo
|
||||||
|
do i=sl-j+1,sl
|
||||||
|
str(i:i)=' '
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if (str(1:1).eq.'!') return
|
||||||
|
|
||||||
|
lauf=lauf+1
|
||||||
|
do i=1,sl
|
||||||
|
in(lauf)(i:i)=str(i:i)
|
||||||
|
if (str(i:i).eq.'a') in(lauf)(i:i)='A'
|
||||||
|
if (str(i:i).eq.'b') in(lauf)(i:i)='B'
|
||||||
|
if (str(i:i).eq.'c') in(lauf)(i:i)='C'
|
||||||
|
if (str(i:i).eq.'d') in(lauf)(i:i)='D'
|
||||||
|
if (str(i:i).eq.'e') in(lauf)(i:i)='E'
|
||||||
|
if (str(i:i).eq.'f') in(lauf)(i:i)='F'
|
||||||
|
if (str(i:i).eq.'g') in(lauf)(i:i)='G'
|
||||||
|
if (str(i:i).eq.'h') in(lauf)(i:i)='H'
|
||||||
|
if (str(i:i).eq.'i') in(lauf)(i:i)='I'
|
||||||
|
if (str(i:i).eq.'j') in(lauf)(i:i)='J'
|
||||||
|
if (str(i:i).eq.'k') in(lauf)(i:i)='K'
|
||||||
|
if (str(i:i).eq.'l') in(lauf)(i:i)='L'
|
||||||
|
if (str(i:i).eq.'m') in(lauf)(i:i)='M'
|
||||||
|
if (str(i:i).eq.'n') in(lauf)(i:i)='N'
|
||||||
|
if (str(i:i).eq.'o') in(lauf)(i:i)='O'
|
||||||
|
if (str(i:i).eq.'p') in(lauf)(i:i)='P'
|
||||||
|
if (str(i:i).eq.'q') in(lauf)(i:i)='Q'
|
||||||
|
if (str(i:i).eq.'r') in(lauf)(i:i)='R'
|
||||||
|
if (str(i:i).eq.'s') in(lauf)(i:i)='S'
|
||||||
|
if (str(i:i).eq.'t') in(lauf)(i:i)='T'
|
||||||
|
if (str(i:i).eq.'u') in(lauf)(i:i)='U'
|
||||||
|
if (str(i:i).eq.'v') in(lauf)(i:i)='V'
|
||||||
|
if (str(i:i).eq.'w') in(lauf)(i:i)='W'
|
||||||
|
if (str(i:i).eq.'x') in(lauf)(i:i)='X'
|
||||||
|
if (str(i:i).eq.'y') in(lauf)(i:i)='Y'
|
||||||
|
if (str(i:i).eq.'z') in(lauf)(i:i)='Z'
|
||||||
|
C..... Addition of the first if-loop
|
||||||
|
if (i-3.gt.0) then
|
||||||
|
if (in(lauf)(i-3:i).eq.'CHK:') then
|
||||||
|
in(lauf)(i+1:sl)=str(i+1:sl)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
! if (i+3.le.sl) then
|
||||||
|
! if (in(lauf)(i:i+3).eq.'CHK:') then
|
||||||
|
! in(lauf)(i+1:sl)=str(i+1:sl)
|
||||||
|
! return
|
||||||
|
! endif
|
||||||
|
! endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine capital
|
||||||
|
|
||||||
|
!-----------------------------------------------------------------------
|
||||||
|
subroutine lcap(str,n)
|
||||||
|
integer i, n
|
||||||
|
character str*(*), dum*750
|
||||||
|
|
||||||
|
dum=''
|
||||||
|
do i=1,n
|
||||||
|
dum(i:i)=str(i:i)
|
||||||
|
if (str(i:i).eq.'a') dum(i:i)='A'
|
||||||
|
if (str(i:i).eq.'b') dum(i:i)='B'
|
||||||
|
if (str(i:i).eq.'c') dum(i:i)='C'
|
||||||
|
if (str(i:i).eq.'d') dum(i:i)='D'
|
||||||
|
if (str(i:i).eq.'e') dum(i:i)='E'
|
||||||
|
if (str(i:i).eq.'f') dum(i:i)='F'
|
||||||
|
if (str(i:i).eq.'g') dum(i:i)='G'
|
||||||
|
if (str(i:i).eq.'h') dum(i:i)='H'
|
||||||
|
if (str(i:i).eq.'i') dum(i:i)='I'
|
||||||
|
if (str(i:i).eq.'j') dum(i:i)='J'
|
||||||
|
if (str(i:i).eq.'k') dum(i:i)='K'
|
||||||
|
if (str(i:i).eq.'l') dum(i:i)='L'
|
||||||
|
if (str(i:i).eq.'m') dum(i:i)='M'
|
||||||
|
if (str(i:i).eq.'n') dum(i:i)='N'
|
||||||
|
if (str(i:i).eq.'o') dum(i:i)='O'
|
||||||
|
if (str(i:i).eq.'p') dum(i:i)='P'
|
||||||
|
if (str(i:i).eq.'q') dum(i:i)='Q'
|
||||||
|
if (str(i:i).eq.'r') dum(i:i)='R'
|
||||||
|
if (str(i:i).eq.'s') dum(i:i)='S'
|
||||||
|
if (str(i:i).eq.'t') dum(i:i)='T'
|
||||||
|
if (str(i:i).eq.'u') dum(i:i)='U'
|
||||||
|
if (str(i:i).eq.'v') dum(i:i)='V'
|
||||||
|
if (str(i:i).eq.'w') dum(i:i)='W'
|
||||||
|
if (str(i:i).eq.'x') dum(i:i)='X'
|
||||||
|
if (str(i:i).eq.'y') dum(i:i)='Y'
|
||||||
|
if (str(i:i).eq.'z') dum(i:i)='Z'
|
||||||
|
enddo
|
||||||
|
str(1:n)=dum(1:n)
|
||||||
|
|
||||||
|
end subroutine lcap
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
! function to test how many entries are on one line:
|
||||||
|
function clen(str,sl)
|
||||||
|
integer clen, i, j, sl
|
||||||
|
character str*(sl)
|
||||||
|
|
||||||
|
clen=0
|
||||||
|
j=0
|
||||||
|
do i=sl,1,-1
|
||||||
|
if ((str(i:i).ne.' ').and.(j.eq.0)) then
|
||||||
|
clen=clen+1
|
||||||
|
j=1
|
||||||
|
endif
|
||||||
|
if (str(i:i).eq.' ') j=0
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end function clen
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logical function isnumeral(char)
|
||||||
|
! Check whether character CHAR is a numeral.
|
||||||
|
|
||||||
|
character char
|
||||||
|
|
||||||
|
character numerals(10)
|
||||||
|
parameter (numerals = ['0','1','2','3','4','5','6','7','8','9'])
|
||||||
|
|
||||||
|
isnumeral=any(numerals.eq.char)
|
||||||
|
|
||||||
|
end function isnumeral
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logical function iswhitespace(char)
|
||||||
|
! Check whether CHAR is tab or spc character
|
||||||
|
|
||||||
|
character char
|
||||||
|
|
||||||
|
character whitespace(2)
|
||||||
|
parameter (whitespace = [' ', ' '])
|
||||||
|
|
||||||
|
iswhitespace=any(whitespace.eq.char)
|
||||||
|
|
||||||
|
end function iswhitespace
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine trimnum(string,outstr,str_len)
|
||||||
|
! Extract numbers in STRING as a space separated list in OUTSTR.
|
||||||
|
integer str_len
|
||||||
|
character(len=str_len) string
|
||||||
|
character(len=str_len) outstr
|
||||||
|
|
||||||
|
integer length
|
||||||
|
logical foundnum
|
||||||
|
|
||||||
|
integer k
|
||||||
|
|
||||||
|
! logical isnumeral
|
||||||
|
|
||||||
|
length=len_trim(string)
|
||||||
|
foundnum=.false.
|
||||||
|
|
||||||
|
outstr=' '
|
||||||
|
|
||||||
|
do k=1,length
|
||||||
|
if (isnumeral(string(k:k))) then
|
||||||
|
if (foundnum) then
|
||||||
|
outstr = trim(outstr) // string(k:k)
|
||||||
|
else if (len_trim(outstr).ne.0) then
|
||||||
|
outstr = trim(outstr) // ' ' // string(k:k)
|
||||||
|
foundnum=.true.
|
||||||
|
else
|
||||||
|
outstr = trim(outstr) // string(k:k)
|
||||||
|
foundnum=.true.
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
foundnum=.false.
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine trimnum
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine strip_string(string,stripped,str_len)
|
||||||
|
! Strip lefthand whitespace of STRING as well as excessive
|
||||||
|
! whitespace and save to STRIPPED.
|
||||||
|
! Example:
|
||||||
|
! " the quick brown fox" -> "the quick brown fox"
|
||||||
|
|
||||||
|
integer str_len
|
||||||
|
character(len=str_len) string,stripped
|
||||||
|
|
||||||
|
character char
|
||||||
|
logical spaced
|
||||||
|
|
||||||
|
! logical iswhitespace
|
||||||
|
|
||||||
|
integer k, trimpos
|
||||||
|
|
||||||
|
stripped=' '
|
||||||
|
trimpos=1
|
||||||
|
|
||||||
|
! spaced indicates whether if a space is found it is the first
|
||||||
|
! (separating the word from the next) or redundant
|
||||||
|
spaced=.true.
|
||||||
|
|
||||||
|
do k=1,len_trim(string)
|
||||||
|
char=string(k:k)
|
||||||
|
if (.not.iswhitespace(char)) then
|
||||||
|
spaced=.false.
|
||||||
|
else if (.not.spaced) then
|
||||||
|
! replace TAB characters if present
|
||||||
|
char=' '
|
||||||
|
spaced=.true.
|
||||||
|
else
|
||||||
|
! ignore redundant spaces
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
stripped(trimpos:trimpos)=char
|
||||||
|
trimpos=trimpos+1
|
||||||
|
enddo
|
||||||
|
|
||||||
|
|
||||||
|
end subroutine strip_string
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine nth_word(string,word,n,str_len)
|
||||||
|
! If STRING is a space separated list of words, return the Nth word.
|
||||||
|
|
||||||
|
integer str_len
|
||||||
|
character(len=str_len) string,word
|
||||||
|
integer n
|
||||||
|
|
||||||
|
character(len=str_len) strip
|
||||||
|
integer wc
|
||||||
|
|
||||||
|
! logical iswhitespace
|
||||||
|
|
||||||
|
integer k,j
|
||||||
|
|
||||||
|
call strip_string(string,strip,str_len)
|
||||||
|
|
||||||
|
word=' '
|
||||||
|
wc=1
|
||||||
|
|
||||||
|
! find the word
|
||||||
|
do k=1,len_trim(strip)
|
||||||
|
if (wc.eq.n) exit
|
||||||
|
if (iswhitespace(strip(k:k))) then
|
||||||
|
wc=wc+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
do j=k,len_trim(strip)
|
||||||
|
if (iswhitespace(strip(j:j))) exit
|
||||||
|
word = trim(word) // strip(j:j)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine nth_word
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine count_words(string,wordcount,str_len)
|
||||||
|
! If STRING is a space separated list of words, return the Nth word.
|
||||||
|
|
||||||
|
integer str_len
|
||||||
|
character(len=str_len) string
|
||||||
|
integer wordcount
|
||||||
|
|
||||||
|
character(len=str_len) strip
|
||||||
|
integer wc
|
||||||
|
|
||||||
|
! logical iswhitespace
|
||||||
|
|
||||||
|
integer k
|
||||||
|
|
||||||
|
call strip_string(string,strip,str_len)
|
||||||
|
|
||||||
|
if (len_trim(strip).gt.0) then
|
||||||
|
wc=1
|
||||||
|
else
|
||||||
|
wordcount=0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! find the word
|
||||||
|
do k=1,len_trim(strip)
|
||||||
|
if (iswhitespace(strip(k:k))) then
|
||||||
|
wc=wc+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
wordcount=wc
|
||||||
|
|
||||||
|
end subroutine count_words
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine upcase(string,upstring,str_len)
|
||||||
|
! Transform arbitrary string to uppercase and save to upstring
|
||||||
|
|
||||||
|
integer str_len
|
||||||
|
character(len=str_len) string,upstring
|
||||||
|
|
||||||
|
integer j
|
||||||
|
|
||||||
|
upstring=' '
|
||||||
|
|
||||||
|
do j=1,len_trim(string)
|
||||||
|
select case (string(j:j))
|
||||||
|
case ('a')
|
||||||
|
upstring(j:j)= 'A'
|
||||||
|
case ('b')
|
||||||
|
upstring(j:j)= 'B'
|
||||||
|
case ('c')
|
||||||
|
upstring(j:j)= 'C'
|
||||||
|
case ('d')
|
||||||
|
upstring(j:j)= 'D'
|
||||||
|
case ('e')
|
||||||
|
upstring(j:j)= 'E'
|
||||||
|
case ('f')
|
||||||
|
upstring(j:j)= 'F'
|
||||||
|
case ('g')
|
||||||
|
upstring(j:j)= 'G'
|
||||||
|
case ('h')
|
||||||
|
upstring(j:j)= 'H'
|
||||||
|
case ('i')
|
||||||
|
upstring(j:j)= 'I'
|
||||||
|
case ('j')
|
||||||
|
upstring(j:j)= 'J'
|
||||||
|
case ('k')
|
||||||
|
upstring(j:j)= 'K'
|
||||||
|
case ('l')
|
||||||
|
upstring(j:j)= 'L'
|
||||||
|
case ('m')
|
||||||
|
upstring(j:j)= 'M'
|
||||||
|
case ('n')
|
||||||
|
upstring(j:j)= 'N'
|
||||||
|
case ('o')
|
||||||
|
upstring(j:j)= 'O'
|
||||||
|
case ('p')
|
||||||
|
upstring(j:j)= 'P'
|
||||||
|
case ('q')
|
||||||
|
upstring(j:j)= 'Q'
|
||||||
|
case ('r')
|
||||||
|
upstring(j:j)= 'R'
|
||||||
|
case ('s')
|
||||||
|
upstring(j:j)= 'S'
|
||||||
|
case ('t')
|
||||||
|
upstring(j:j)= 'T'
|
||||||
|
case ('u')
|
||||||
|
upstring(j:j)= 'U'
|
||||||
|
case ('v')
|
||||||
|
upstring(j:j)= 'V'
|
||||||
|
case ('w')
|
||||||
|
upstring(j:j)= 'W'
|
||||||
|
case ('x')
|
||||||
|
upstring(j:j)= 'X'
|
||||||
|
case ('y')
|
||||||
|
upstring(j:j)= 'Y'
|
||||||
|
case ('z')
|
||||||
|
upstring(j:j)= 'Z'
|
||||||
|
case default
|
||||||
|
upstring(j:j)=string(j:j)
|
||||||
|
end select
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine upcase
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine downcase(string,downstring,str_len)
|
||||||
|
! Transform arbitrary string to downcase and save to downstring
|
||||||
|
|
||||||
|
integer str_len
|
||||||
|
character(len=str_len) string,downstring
|
||||||
|
|
||||||
|
integer j
|
||||||
|
|
||||||
|
downstring=' '
|
||||||
|
|
||||||
|
do j=1,len_trim(string)
|
||||||
|
select case (string(j:j))
|
||||||
|
case ('A')
|
||||||
|
downstring(j:j)= 'a'
|
||||||
|
case ('B')
|
||||||
|
downstring(j:j)= 'b'
|
||||||
|
case ('C')
|
||||||
|
downstring(j:j)= 'c'
|
||||||
|
case ('D')
|
||||||
|
downstring(j:j)= 'd'
|
||||||
|
case ('E')
|
||||||
|
downstring(j:j)= 'e'
|
||||||
|
case ('F')
|
||||||
|
downstring(j:j)= 'f'
|
||||||
|
case ('G')
|
||||||
|
downstring(j:j)= 'g'
|
||||||
|
case ('H')
|
||||||
|
downstring(j:j)= 'h'
|
||||||
|
case ('I')
|
||||||
|
downstring(j:j)= 'i'
|
||||||
|
case ('J')
|
||||||
|
downstring(j:j)= 'j'
|
||||||
|
case ('K')
|
||||||
|
downstring(j:j)= 'k'
|
||||||
|
case ('L')
|
||||||
|
downstring(j:j)= 'l'
|
||||||
|
case ('M')
|
||||||
|
downstring(j:j)= 'm'
|
||||||
|
case ('N')
|
||||||
|
downstring(j:j)= 'n'
|
||||||
|
case ('O')
|
||||||
|
downstring(j:j)= 'o'
|
||||||
|
case ('P')
|
||||||
|
downstring(j:j)= 'p'
|
||||||
|
case ('Q')
|
||||||
|
downstring(j:j)= 'q'
|
||||||
|
case ('R')
|
||||||
|
downstring(j:j)= 'r'
|
||||||
|
case ('S')
|
||||||
|
downstring(j:j)= 's'
|
||||||
|
case ('T')
|
||||||
|
downstring(j:j)= 't'
|
||||||
|
case ('U')
|
||||||
|
downstring(j:j)= 'u'
|
||||||
|
case ('V')
|
||||||
|
downstring(j:j)= 'v'
|
||||||
|
case ('W')
|
||||||
|
downstring(j:j)= 'w'
|
||||||
|
case ('X')
|
||||||
|
downstring(j:j)= 'x'
|
||||||
|
case ('Y')
|
||||||
|
downstring(j:j)= 'y'
|
||||||
|
case ('Z')
|
||||||
|
downstring(j:j)= 'z'
|
||||||
|
case default
|
||||||
|
downstring(j:j)=string(j:j)
|
||||||
|
end select
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine downcase
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
pure function int2string(int) result(string)
|
||||||
|
character(len=:), allocatable :: string
|
||||||
|
integer, intent(in) :: int
|
||||||
|
character(len=100) :: str
|
||||||
|
write(str,'(i0)') int
|
||||||
|
string = trim(adjustl(str))
|
||||||
|
end function int2string
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
pure function dble2string(dble) result(string)
|
||||||
|
character(len=:), allocatable :: string
|
||||||
|
double precision, intent(in) :: dble
|
||||||
|
character(len=100) :: str
|
||||||
|
write(str,'(ES16.9)') dble
|
||||||
|
string = trim(adjustl(str))
|
||||||
|
end function dble2string
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
pure function shortdble2string(dble) result(string)
|
||||||
|
character(len=:), allocatable :: string
|
||||||
|
double precision, intent(in) :: dble
|
||||||
|
character(len=100) :: str
|
||||||
|
write(str,'(ES11.2)') dble
|
||||||
|
string = trim(adjustl(str))
|
||||||
|
end function shortdble2string
|
||||||
|
!----------------------------------------------------------------------------------
|
||||||
|
subroutine write_oneline(string,id_print)
|
||||||
|
#ifdef mpi_version
|
||||||
|
use mpi
|
||||||
|
#endif
|
||||||
|
integer,intent(in) :: id_print
|
||||||
|
character(len=*) string
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
integer my_rank,ierror
|
||||||
|
call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierror)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
if (my_rank.eq.0) then
|
||||||
|
#endif
|
||||||
|
write(id_print,'(A)') adjustl(trim(string))
|
||||||
|
|
||||||
|
#ifdef mpi_version
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
end subroutine write_oneline
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
integer typenum,maxtypelen
|
||||||
|
parameter (typenum=6,maxtypelen=2)
|
||||||
|
character(len=maxtypelen) types(typenum)
|
||||||
|
! parameter (types=['I', '+I', 'D', '+D', 'C', 'E'])
|
||||||
|
parameter (types=['I ', '+I', 'D ', '+D', 'C ', 'E ']) !Fabian
|
|
@ -0,0 +1,103 @@
|
||||||
|
************************************************************************
|
||||||
|
*** long_write
|
||||||
|
*** writing genetic's long input format
|
||||||
|
***
|
||||||
|
************************************************************************
|
||||||
|
module long_write
|
||||||
|
implicit none
|
||||||
|
contains
|
||||||
|
|
||||||
|
subroutine write_longint(f_unit,params,plen,intfmt,maxvals)
|
||||||
|
implicit none
|
||||||
|
! Routine writing long integer output of the form
|
||||||
|
! x1 x2 x3 .... xN &
|
||||||
|
! ... &
|
||||||
|
!
|
||||||
|
! f_unit: UNIT to be written on, directly passed to write
|
||||||
|
! params: integer vector to be written out
|
||||||
|
! plen: number of elements to be printed
|
||||||
|
! maxvals: (maximum) number of values per line
|
||||||
|
! intfmt: format of a single interger, e.g. '(I6)'
|
||||||
|
|
||||||
|
integer f_unit
|
||||||
|
integer params(*)
|
||||||
|
integer plen,maxvals
|
||||||
|
character*16 intfmt
|
||||||
|
|
||||||
|
integer pcount
|
||||||
|
|
||||||
|
integer j,k
|
||||||
|
|
||||||
|
pcount=0 ! count parameters written so far
|
||||||
|
|
||||||
|
! write all values that fill entire lines.
|
||||||
|
do k=1,(plen/maxvals)
|
||||||
|
do j=1,maxvals
|
||||||
|
write(unit=f_unit,fmt=intfmt,advance='NO') params(pcount+j)
|
||||||
|
enddo
|
||||||
|
pcount=pcount+maxvals
|
||||||
|
if (pcount.lt.plen) then
|
||||||
|
write(unit=f_unit,fmt='(A)') ' &'
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
pcount=pcount+1
|
||||||
|
|
||||||
|
! write remaining few
|
||||||
|
do k=pcount,plen
|
||||||
|
write(unit=f_unit,fmt=intfmt,advance='NO') params(k)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
write(f_unit,'(A)') ''
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine write_longreal(f_unit,params,plen,dfmt,maxvals)
|
||||||
|
implicit none
|
||||||
|
! Routine writing long real(*8) output of the form
|
||||||
|
! x1 x2 x3 .... xN &
|
||||||
|
! ... &
|
||||||
|
!
|
||||||
|
! f_unit: UNIT to be written on, directly passed to write
|
||||||
|
! params: integer vector to be written out
|
||||||
|
! plen: number of elements to be printed
|
||||||
|
! maxvals: (maximum) number of values per line
|
||||||
|
! dfmt: format of a single real, e.g. '(ES23.15)'
|
||||||
|
|
||||||
|
real*8 params(*)
|
||||||
|
integer f_unit
|
||||||
|
integer plen,maxvals
|
||||||
|
character*16 dfmt
|
||||||
|
|
||||||
|
integer pcount
|
||||||
|
|
||||||
|
integer j,k
|
||||||
|
|
||||||
|
pcount=0 ! count parameters written so far
|
||||||
|
|
||||||
|
! write all values that fill entire lines.
|
||||||
|
do k=1,(plen/maxvals)
|
||||||
|
do j=1,maxvals
|
||||||
|
write(unit=f_unit,fmt=dfmt,advance='NO') params(pcount+j)
|
||||||
|
enddo
|
||||||
|
pcount=pcount+maxvals
|
||||||
|
if (pcount.lt.plen) then
|
||||||
|
write(unit=f_unit,fmt='(A)') ' &'
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
pcount=pcount+1
|
||||||
|
|
||||||
|
! write remaining few
|
||||||
|
do k=pcount,plen
|
||||||
|
write(unit=f_unit,fmt=dfmt,advance='NO') params(k)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
write(f_unit,'(A)') ''
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,248 @@
|
||||||
|
module parameterkeys
|
||||||
|
use io_parameters, only: llen,klen,
|
||||||
|
> key,maxpar_keys,parkeynum,parkeylen,ec_read,ec_dim
|
||||||
|
use dim_parameter,only: pst,max_par
|
||||||
|
use keys_mod, only: init_keys
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
|
||||||
|
contains
|
||||||
|
! < Subroutine reading the user defined Parameter keys from keys.incl
|
||||||
|
! <returns: the parameter arrays p, p_act, p_spread and their length npar
|
||||||
|
! <needs: internalized file (infile) it's length (linenum), the keylist from keys.incl (key) and the counted number of keys (parkeynum)
|
||||||
|
subroutine parameterkey_read
|
||||||
|
> (infile,linenum,p,p_act,p_spread,npar,gspread,facspread)
|
||||||
|
use strings_mod,only:write_oneline
|
||||||
|
use long_keyread_mod,only:long_intkey,long_realkey,long_strkey
|
||||||
|
! dir$ optimize:1
|
||||||
|
! IN: variables
|
||||||
|
integer linenum !< number of lines in internalized input file (infile)
|
||||||
|
character(len=llen) :: infile(linenum) !< internalized input file
|
||||||
|
double precision gspread !< general parameterspread used to initialize p_spread
|
||||||
|
double precision facspread !< multiplicative factor for spreads
|
||||||
|
|
||||||
|
! OUT: read parameters and their lenght,spread and active state
|
||||||
|
integer npar !< lenght oo parameter vector
|
||||||
|
double precision, allocatable :: p(:) !< vector for the values of read parameters
|
||||||
|
double precision, allocatable :: p_spread(:) !< vector for the spread values for each parameter
|
||||||
|
integer, allocatable :: p_act(:) !< vector containing 0 or 1 defining if corresponding parameters are activ in Fit ! Nicole: added flexible value for nonlinear terms
|
||||||
|
|
||||||
|
! Private: variables
|
||||||
|
integer i,j !< running indicies
|
||||||
|
integer ktype,key_end !< dummys for keytype and keylength
|
||||||
|
integer pcount !< dummy for number of read values
|
||||||
|
logical dbg !< logical for debugging state
|
||||||
|
|
||||||
|
! Fabian
|
||||||
|
character(len=llen) fmt
|
||||||
|
integer,parameter :: std_out = 6
|
||||||
|
|
||||||
|
dbg =.false.
|
||||||
|
|
||||||
|
!Fabian: No need that these are within keys.incl since these are generic statements
|
||||||
|
parkeynum=0
|
||||||
|
parkeylen=0
|
||||||
|
key = ' '
|
||||||
|
|
||||||
|
!Fabian: Include user specific keys
|
||||||
|
call init_keys
|
||||||
|
! include 'keys.incl'
|
||||||
|
|
||||||
|
!Fabian: No need that this is within keys.incl since it is generic
|
||||||
|
do j=1,maxpar_keys
|
||||||
|
if (key(1,j)(1:1).eq.' ') then
|
||||||
|
parkeynum=j-1
|
||||||
|
write(fmt,'("Number of accepted parameter keys: ",I3)')
|
||||||
|
> parkeynum
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do i=1,4
|
||||||
|
do j=1,maxpar_keys
|
||||||
|
if(parkeylen.lt.len_trim(key(i,j))) then
|
||||||
|
parkeylen = len_trim(key(i,j))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
if(parkeylen.ge.klen) then
|
||||||
|
write(fmt,*)
|
||||||
|
> 'WARNING: Lenght of Parameterkey >= Maximum Keylenght'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
! reading cards for the number of parameters'
|
||||||
|
npar =0
|
||||||
|
ktype = 1 !reading number of parameters per key
|
||||||
|
do i=1,linenum
|
||||||
|
do j=1, parkeynum
|
||||||
|
|
||||||
|
! get string length of key
|
||||||
|
key_end=len_trim(key(ktype,j))
|
||||||
|
|
||||||
|
! check if key is present and read values if present
|
||||||
|
if (infile(i)(1:key_end).eq.key(ktype,j)) then
|
||||||
|
if(dbg) write(6,*) key(ktype,j),' read'
|
||||||
|
read (infile(i)(key_end+1:llen),*) pst(2,j)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!.. compute total number of parameters:
|
||||||
|
do i=1, parkeynum
|
||||||
|
npar=npar + pst(2,i)
|
||||||
|
enddo
|
||||||
|
if(npar.gt.max_par) call signal_maxparameter_error(npar,max_par)
|
||||||
|
if(npar.le.0) call signal_noparameters_error(npar)
|
||||||
|
|
||||||
|
write(fmt,'("Number of Expected Parameters: ",I9)') npar
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!.. determine start and end points of parameter blocks:
|
||||||
|
pst(1,1)=1 ! 1 = start of block
|
||||||
|
do i=2,parkeynum
|
||||||
|
pst(1,i)= pst(1,i-1)+pst(2,i-1)
|
||||||
|
if(dbg) write(6,'("pst(1:2,i): ",2i9)') pst(1:2,i)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
|
||||||
|
! allocate parameter arrays
|
||||||
|
allocate(p(npar),p_act(npar),p_spread(npar))
|
||||||
|
! initialize parameter arrays
|
||||||
|
p=0.d0
|
||||||
|
! DW: UNDOCUMENTED BEHAVIOR: What does act=2 do???
|
||||||
|
p_act=10
|
||||||
|
p_spread=gspread
|
||||||
|
|
||||||
|
! read parameter values
|
||||||
|
ktype = 2 !reading value of parameters per key
|
||||||
|
do i=1,linenum
|
||||||
|
do j=1, parkeynum
|
||||||
|
|
||||||
|
! get string length of key
|
||||||
|
key_end=len_trim(key(ktype,j))
|
||||||
|
|
||||||
|
! check if key is present and read values if present
|
||||||
|
if (infile(i)(1:key_end).eq.key(ktype,j)) then
|
||||||
|
if(dbg) write(6,*) key(ktype,j),' read'
|
||||||
|
call long_realkey(infile,i,key_end,
|
||||||
|
> p,pst(1,j),pcount,llen,npar,linenum)
|
||||||
|
|
||||||
|
! check if number of parameters consistent
|
||||||
|
if(pcount.ne.pst(2,j)) then
|
||||||
|
call signal_parameter_error
|
||||||
|
> (key(ktype,j),pcount,pst(2,j))
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
|
||||||
|
! read if parameters are activ
|
||||||
|
ktype = 3 !reading activity of parameter per key
|
||||||
|
do i=1,linenum
|
||||||
|
do j=1, parkeynum
|
||||||
|
|
||||||
|
! get string length of key
|
||||||
|
key_end=len_trim(key(ktype,j))
|
||||||
|
|
||||||
|
! check if key is present and read values if present
|
||||||
|
if (infile(i)(1:key_end).eq.key(ktype,j)) then
|
||||||
|
if(dbg) write(6,*) key(ktype,j),' read'
|
||||||
|
call long_intkey(infile,i,key_end,
|
||||||
|
> p_act,pst(1,j),pcount,llen,npar,linenum)
|
||||||
|
! check if number of parameters consistent
|
||||||
|
if(pcount.ne.pst(2,j)) then
|
||||||
|
call signal_parameter_error
|
||||||
|
> (key(ktype,j),pcount,pst(2,j))
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! check if all values for p_act are in valid range
|
||||||
|
do i=1,npar
|
||||||
|
! Nicole: added flexible p_act values
|
||||||
|
! in my case now up tp 6
|
||||||
|
if((abs(p_act(i)).gt.6)) then
|
||||||
|
write(fmt,*) 'Invalid value for p_act: ', p_act(i), i
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! read spread for parameters
|
||||||
|
ktype = 4 !reading spread of parameters per key
|
||||||
|
do i=1,linenum
|
||||||
|
do j=1, parkeynum
|
||||||
|
|
||||||
|
! get string length of key
|
||||||
|
key_end=len_trim(key(ktype,j))
|
||||||
|
|
||||||
|
! check if key is present and read values if present
|
||||||
|
if (infile(i)(1:key_end).eq.key(ktype,j)) then
|
||||||
|
if(dbg) write(6,*) key(ktype,j),' read'
|
||||||
|
call long_realkey(infile,i,key_end,
|
||||||
|
> p_spread,pst(1,j),pcount,llen,npar,linenum)
|
||||||
|
|
||||||
|
! check if number of parameters consistent
|
||||||
|
if(pcount.ne.pst(2,j)) then
|
||||||
|
call signal_parameter_error
|
||||||
|
> (key(ktype,j),pcount,pst(2,j))
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!Multiply p_spread by facspread
|
||||||
|
!(default facspread=1, unless it is explicitly declared)
|
||||||
|
p_spread=p_spread*facspread
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
!----------------------------------------------------------------------------------------------------
|
||||||
|
! <Subroutine returns error message for inconsistent number of Parameters
|
||||||
|
! <needs: the corresponding key as string (keystr) the number of values read (val) and the expected number (expval)
|
||||||
|
subroutine signal_parameter_error(keystr,val,expval)
|
||||||
|
use strings_mod,only:int2string
|
||||||
|
character(len=klen) :: keystr !< string containing the Card (EXAMPLE:)
|
||||||
|
integer :: val, expval !< number of read and expected number of Parametervalues
|
||||||
|
write(6,'(A)')'ERROR: Reading ' // trim(keystr) // ' counted: '
|
||||||
|
> // trim(int2string(val)) // ' Parameters, but expected: '
|
||||||
|
> // trim(int2string(expval))
|
||||||
|
stop ec_read
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------------------------------------
|
||||||
|
! <Subroutine returns error message for inconsistent number of Parameters
|
||||||
|
! <needs: the corresponding key as string (keystr) the number of values read (val) and the expected number (expval)
|
||||||
|
subroutine signal_maxparameter_error(val,maxval)
|
||||||
|
use strings_mod,only:int2string
|
||||||
|
integer :: val, maxval !< number of read and expected number of Parametervalues
|
||||||
|
|
||||||
|
write(6,'(A)')'ERROR: More Parameters then given maximum counted:'
|
||||||
|
> // trim(int2string(val)) // ' Parameters, but maximum: '
|
||||||
|
> // trim(int2string(maxval))
|
||||||
|
stop ec_dim
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------------------------------------
|
||||||
|
! <Subroutine returns error message for inconsistent number of Parameters
|
||||||
|
! <needs: the corresponding key as string (keystr) the number of values read (val) and the expected number (expval)
|
||||||
|
subroutine signal_noparameters_error(val)
|
||||||
|
use strings_mod,only:int2string
|
||||||
|
integer :: val !< number of read and expected number of Parametervalues
|
||||||
|
write(6,'(A)')'ERROR: No. of counted parameters is <= 0:'
|
||||||
|
> // trim(int2string(val))
|
||||||
|
stop ec_dim
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,117 @@
|
||||||
|
module parse_errors
|
||||||
|
use io_parameters, only:
|
||||||
|
> keylist, errcat, ec_dim, ec_log, ec_read, ec_error
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine signal_p_error(key_id,msg)
|
||||||
|
! Signal generic error with user-defined message MSG.
|
||||||
|
integer key_id
|
||||||
|
character(len=*) msg
|
||||||
|
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(keylist(1,key_id))
|
||||||
|
> // ' ' // trim(msg)
|
||||||
|
stop ec_error
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine signal_dim_error(key_id,msg_code,value,expval)
|
||||||
|
use strings_mod,only:int2string
|
||||||
|
! Signals errors where one specific dimensioning value is ill-set.
|
||||||
|
! If the optional parameter EXPVAL is given, return it as expected
|
||||||
|
! dimensioning value.
|
||||||
|
integer key_id, value
|
||||||
|
integer, optional :: expval
|
||||||
|
integer msg_code
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(keylist(1,key_id))
|
||||||
|
> // ' ' // trim(errcat(msg_code))
|
||||||
|
write(6,'(A)') 'OFFENDING VALUE: ' // trim(int2string(value))
|
||||||
|
if (present(expval)) then
|
||||||
|
write(6,'(A)') 'EXPECTED: ' // trim(int2string(expval))
|
||||||
|
endif
|
||||||
|
stop ec_dim
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine signal_log_error(key_id,msg_code,alt_key)
|
||||||
|
! Signals errors where contradictory settings are provided which
|
||||||
|
! the program cannot resolve. If the optional parameter ALT_KEY
|
||||||
|
! is given, name the explicit key current settings clash with.
|
||||||
|
integer key_id
|
||||||
|
integer, optional :: alt_key
|
||||||
|
integer msg_code
|
||||||
|
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(keylist(1,key_id))
|
||||||
|
> // ' ' // trim(errcat(msg_code))
|
||||||
|
if (present(alt_key)) then
|
||||||
|
write(6,'(A)') 'OFFENDING KEY: ' // trim(keylist(1,alt_key))
|
||||||
|
endif
|
||||||
|
|
||||||
|
stop ec_log
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine signal_val_error(key_id,msg_code,value,expval)
|
||||||
|
use strings_mod,only:int2string
|
||||||
|
! Signals errors where a given value makes no sense in it's given context.
|
||||||
|
! If the optional parameter EXPVAL is given, return it as expected
|
||||||
|
! dimensioning value.
|
||||||
|
integer key_id, value
|
||||||
|
integer, optional :: expval
|
||||||
|
integer msg_code
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(keylist(1,key_id))
|
||||||
|
> // ' ' // trim(errcat(msg_code))
|
||||||
|
write(6,'(A)') 'OFFENDING VALUE: ' // trim(int2string(value))
|
||||||
|
if (present(expval)) then
|
||||||
|
write(6,'(A)') 'EXPECTED: ' // trim(int2string(expval))
|
||||||
|
endif
|
||||||
|
stop ec_read
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine signal_dval_error(key_id,msg_code,value,expval)
|
||||||
|
use strings_mod,only: shortdble2string
|
||||||
|
! Signals errors where a given value makes no sense in it's given context.
|
||||||
|
! If the optional parameter EXPVAL is given, return it as expected
|
||||||
|
! dimensioning value.
|
||||||
|
integer key_id
|
||||||
|
double precision value
|
||||||
|
double precision, optional :: expval
|
||||||
|
integer msg_code
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(keylist(1,key_id))
|
||||||
|
> // ' ' // trim(errcat(msg_code))
|
||||||
|
write(6,'(A)') 'OFFENDING VALUE: '
|
||||||
|
> // trim(shortdble2string(value))
|
||||||
|
if (present(expval)) then
|
||||||
|
write(6,'(A)') 'EXPECTED: ' // trim(shortdble2string(expval))
|
||||||
|
endif
|
||||||
|
stop ec_read
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subroutine signal_meta_error(key_id,msg_code)
|
||||||
|
! Signals errors where a key (or key combinations) is/are not
|
||||||
|
! supported or maintained for reasons outside of the program's
|
||||||
|
! scope (e.g.: deprecation).
|
||||||
|
integer key_id,msg_code
|
||||||
|
|
||||||
|
write(6,'(A)') 'ERROR: ' // trim(keylist(1,key_id))
|
||||||
|
> // ' ' // trim(errcat(msg_code))
|
||||||
|
stop ec_read
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
end module
|
|
@ -0,0 +1,875 @@
|
||||||
|
|
||||||
|
! >Module Containing Subroutines relevant for reading cards and information from an inputfile
|
||||||
|
|
||||||
|
module parser
|
||||||
|
use io_parameters
|
||||||
|
use dim_parameter
|
||||||
|
use parse_errors
|
||||||
|
use parameterkeys, only: parameterkey_read
|
||||||
|
use long_write
|
||||||
|
implicit none
|
||||||
|
contains
|
||||||
|
!--------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
! >Reads Cards and Data from Inputfile
|
||||||
|
! !@param datname name of input file that is readed
|
||||||
|
! !@param infile internalized input file
|
||||||
|
! !@param linenum linenumber of internalized input file
|
||||||
|
! !@param idat
|
||||||
|
subroutine les(x,y,wt,p,p_act,p_spread,npar,
|
||||||
|
> seed,gtype,nset,maxit,micit,nsel,mut,difper,freeze)
|
||||||
|
use strings_mod,only:write_oneline
|
||||||
|
use fileread_mod,only:get_datfile,internalize_datfile
|
||||||
|
use keyread_mod,only:keyread
|
||||||
|
! implicit none
|
||||||
|
! Include Files for needed dimension parameters
|
||||||
|
|
||||||
|
! Declare OUT Variables
|
||||||
|
! Data variables
|
||||||
|
double precision, allocatable :: x(:,:) , y(:,:), wt(:,:)
|
||||||
|
! Fiting Model Parameters
|
||||||
|
double precision, allocatable :: p(:) !< vector(npar) for the values of read parameters
|
||||||
|
integer, allocatable :: p_act(:) !< vector(npar) containing 0 or 1 defining if corresponding parameters are activ in Fit
|
||||||
|
double precision, allocatable :: p_spread(:) !< vector(npar) for the spread values for each parameter
|
||||||
|
integer npar !< read length of parameter arrays
|
||||||
|
! Fit control Parameters
|
||||||
|
integer seed !< Seed for RNG
|
||||||
|
integer nset !< number of diffrent parameter sets
|
||||||
|
logical freeze !< determines if parameters are active
|
||||||
|
double precision mut, difper !< percentage of selected Parents, number of mutations in parents, minimum diffrence between selected parents
|
||||||
|
double precision psel !< percantage of selected parents
|
||||||
|
integer nsel !< number of selected parents , generated from psel and nset by rounding to nearest integer
|
||||||
|
integer gtype !< type of RNG used
|
||||||
|
integer maxit, micit !<maximum makro and micro iterations for the genetic program
|
||||||
|
! weighting parameters
|
||||||
|
|
||||||
|
! Declare INTERNAL variables
|
||||||
|
character(len=dnlen) :: datname, dbgdatname !< name of the input File
|
||||||
|
character(len=llen), dimension(:), allocatable :: infile !< internalized array of capitalized input file without comments, blanklines
|
||||||
|
integer linenum !< linenumber in infile
|
||||||
|
double precision gspread
|
||||||
|
! data arrays
|
||||||
|
integer idat(maxdat)
|
||||||
|
double precision ddat(maxdat)
|
||||||
|
character(len=clen) cdat(maxdat)
|
||||||
|
! minimum ntot (inferred from ndiab etc)
|
||||||
|
integer min_ntot
|
||||||
|
|
||||||
|
|
||||||
|
! running index
|
||||||
|
integer j !< running index
|
||||||
|
|
||||||
|
! general key variables
|
||||||
|
integer key_id !< integer identifying a key from keylist.incl
|
||||||
|
logical legacy_wt
|
||||||
|
|
||||||
|
! length or position variables
|
||||||
|
integer dat_start !< linenumber in infile where DATA: Block starts
|
||||||
|
|
||||||
|
! Fabian
|
||||||
|
character(len=llen) :: fmt,fmt2
|
||||||
|
integer, parameter :: id_internal = 10 ! hardcoded until queue is ready for modern features
|
||||||
|
integer, parameter :: std_out = 6
|
||||||
|
|
||||||
|
! allocate relevant arrays
|
||||||
|
allocate(infile(maxlines))
|
||||||
|
|
||||||
|
! define Error Messages
|
||||||
|
include 'errcat.incl'
|
||||||
|
|
||||||
|
! include general keylist
|
||||||
|
include 'keylist.incl'
|
||||||
|
do j=1,maxkeys
|
||||||
|
if (keylist(1,j)(1:1).eq.' ') then
|
||||||
|
keynum=j-1
|
||||||
|
write(fmt,'("Number of accepted input keys: ",I3)') keynum
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
!############################################################
|
||||||
|
! Read input file
|
||||||
|
!############################################################
|
||||||
|
|
||||||
|
call get_datfile(datname,dnlen)
|
||||||
|
call internalize_datfile
|
||||||
|
> (datname,infile,linenum,llen,maxlines,dnlen)
|
||||||
|
dbgdatname='.internal_input'
|
||||||
|
#ifndef mpi_version
|
||||||
|
write(6,'(A)') 'Writing internalized version of input to '''
|
||||||
|
> // trim(dbgdatname) // '''..'
|
||||||
|
open(unit=id_internal,file=trim(dbgdatname))
|
||||||
|
do j=1,linenum
|
||||||
|
write(id_internal,'(A)') trim(infile(j))
|
||||||
|
enddo
|
||||||
|
close(id_internal)
|
||||||
|
#endif
|
||||||
|
write(fmt,'("Parsing Keys..")')
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
call keyread(keylist,infile,keynum,idat,ddat,cdat,datpos,
|
||||||
|
> klen,llen,clen,linenum,maxdat)
|
||||||
|
|
||||||
|
!############################################################
|
||||||
|
! Read Individual keys for Program Control
|
||||||
|
!############################################################
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! DATA:
|
||||||
|
!************************************************************************
|
||||||
|
! This card separates the data to be fitted from the rest of the
|
||||||
|
! file.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=1
|
||||||
|
! Find where in the input file the DATA:-block begins and
|
||||||
|
! exclude the line of the card itself
|
||||||
|
dat_start=datIdx(2,key_id)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! SEED:
|
||||||
|
!************************************************************************
|
||||||
|
! Random seed for the RNG.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=2
|
||||||
|
seed=8236475
|
||||||
|
|
||||||
|
if (is_present(key_id)) then
|
||||||
|
seed=idat(datIdx(1,key_id))
|
||||||
|
else
|
||||||
|
write(fmt,76) seed
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
76 format('No random seed specified; seed set to',i12)
|
||||||
|
|
||||||
|
if (abs(seed).lt.10**5) then
|
||||||
|
call signal_val_error(key_id,5,seed)
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("Random seed set to: ",I12)') seed
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
seed=-iabs(seed)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! NSET:
|
||||||
|
!************************************************************************
|
||||||
|
! Number of diffrent Parameter sets.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=3
|
||||||
|
nset=1
|
||||||
|
if (is_present(key_id)) then
|
||||||
|
nset=idat(datIdx(1,key_id))
|
||||||
|
if (nset.le.0)
|
||||||
|
> call signal_val_error(key_id,5,nset)
|
||||||
|
else
|
||||||
|
write(fmt,77) nset
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
77 format('No number of Parametersets specified; nset set to',i9)
|
||||||
|
|
||||||
|
write(fmt,'("Number of Parametersets set to: ",I9)') nset
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! FREEZE:
|
||||||
|
!************************************************************************
|
||||||
|
! Determines if All parameters are nonactive if present.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=4
|
||||||
|
freeze=is_present(key_id)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! NSTAT:
|
||||||
|
!************************************************************************
|
||||||
|
! Number of Energievalues in y for each Point
|
||||||
|
!************************************************************************
|
||||||
|
key_id=5
|
||||||
|
nstat = idat(datIdx(1,key_id))
|
||||||
|
|
||||||
|
write(fmt,'("Number of Energie values set to: ",I9 )') nstat
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! NCI:
|
||||||
|
!************************************************************************
|
||||||
|
! Number of CI vectors in y for each Geometry
|
||||||
|
!************************************************************************
|
||||||
|
key_id=6
|
||||||
|
nci = 0
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
nci =idat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
write(fmt,'("Number of CI vectors set to: ",I9 )') nci
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! NDIAB:
|
||||||
|
!************************************************************************
|
||||||
|
! Size of diabatic space = lenght of ci vectors
|
||||||
|
!************************************************************************
|
||||||
|
key_id=7
|
||||||
|
ndiab=nstat
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
ndiab = idat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("Setting ndiab to:",I9)') ndiab
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
|
||||||
|
min_ntot= nstat + (nci*ndiab)
|
||||||
|
if(min_ntot.gt.max_ntot) then
|
||||||
|
write(6,*)'ERROR: ntot exceeds set Maximum: ',min_ntot,max_ntot
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! HYBRID:
|
||||||
|
!************************************************************************
|
||||||
|
! If present then CI vectors are used in Fit
|
||||||
|
!************************************************************************
|
||||||
|
key_id=8
|
||||||
|
hybrid=is_present(key_id)
|
||||||
|
if(hybrid.and.(nci.le.0)) then
|
||||||
|
write(6,*) 'Cant do Hybrid Fit without ci vectors, nci: ',nci
|
||||||
|
stop ec_log
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! SEL:
|
||||||
|
!************************************************************************
|
||||||
|
! Percentage of selected Parameter sets as Parents
|
||||||
|
!************************************************************************
|
||||||
|
key_id=9
|
||||||
|
psel=0.15d0
|
||||||
|
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
psel = ddat(datIdx(1,key_id))
|
||||||
|
if (psel.gt.1.d0) call signal_dval_error(key_id,7,psel*100)
|
||||||
|
endif
|
||||||
|
nsel=max(int(psel*nset),1)
|
||||||
|
|
||||||
|
write(fmt,79) psel*100, nsel
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
79 format(f5.1,'%(#',i5,')of Parameters will be selected as parents')
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! MUT:
|
||||||
|
!************************************************************************
|
||||||
|
! Percentage of how many mutations happen in parameters
|
||||||
|
!************************************************************************
|
||||||
|
key_id=10
|
||||||
|
mut=0.d0
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
mut = ddat(datIdx(1,key_id))
|
||||||
|
if (mut.gt.1.d0) call signal_dval_error(key_id,7,mut*100.d0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,80) mut
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
80 format('MUTATION set to: ',g9.1)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! DIFPER:
|
||||||
|
!************************************************************************
|
||||||
|
! minimum Percentage of diffrence between selected parents
|
||||||
|
!************************************************************************
|
||||||
|
key_id=11
|
||||||
|
difper=0.05d0
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
difper = ddat(datIdx(1,key_id))
|
||||||
|
if (difper.gt.1.d0) then
|
||||||
|
call signal_dval_error(key_id,7,difper*100.d0)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,81) difper
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
81 format('DIFPER set to: ',g9.1)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! GTYPE:
|
||||||
|
!************************************************************************
|
||||||
|
! Type of used RNG
|
||||||
|
!************************************************************************
|
||||||
|
key_id=12
|
||||||
|
gtype=2
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
gtype = idat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("GTYPE set to: ",i9)') gtype
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! MAXIT:
|
||||||
|
!************************************************************************
|
||||||
|
! number of maximum makro Iterations
|
||||||
|
!************************************************************************
|
||||||
|
key_id=13
|
||||||
|
maxit=5
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
maxit=idat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("max. number of makro iterations set to: ",i9)') maxit
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! MICIT:
|
||||||
|
!************************************************************************
|
||||||
|
! number of maximum micro Iterations
|
||||||
|
!************************************************************************
|
||||||
|
key_id=14
|
||||||
|
micit=1000
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
micit=idat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("max. number of micro iterations set to: ",i9)') micit
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! GSPREAD:
|
||||||
|
!************************************************************************
|
||||||
|
! read general Spread for Parameter keys
|
||||||
|
!************************************************************************
|
||||||
|
key_id=15
|
||||||
|
gspread=1.d0
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
gspread = ddat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("General Parameterspread set to: ",f5.2)') gspread
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! SETS:
|
||||||
|
!************************************************************************
|
||||||
|
! Number of seperatly grouped geometries.
|
||||||
|
! With more than one argument, total sets = sum of all entries.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=16
|
||||||
|
sets=-1
|
||||||
|
sets=idat(datIdx(1,key_id))
|
||||||
|
do j=2,datlen(key_id)
|
||||||
|
sets=sets+idat(datIdx(j,key_id))
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(sets.eq.0) call signal_val_error(key_id,5,sets,1)
|
||||||
|
|
||||||
|
write(fmt,'("Number of Data Sets set to: ",i9)') sets
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! INPUTS:
|
||||||
|
!************************************************************************
|
||||||
|
! Dimension of input values.
|
||||||
|
! INPUTS: D [d]
|
||||||
|
! If given the optional second argument d, read d<D coordinates off
|
||||||
|
! the DATA: block.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=17
|
||||||
|
qn=-1
|
||||||
|
qn=idat(datIdx(1,key_id))
|
||||||
|
if (datlen(key_id).eq.1) then
|
||||||
|
qn_read=qn
|
||||||
|
else if (datlen(key_id).eq.2) then
|
||||||
|
qn_read=idat(datIdx(2,key_id))
|
||||||
|
if (qn_read.gt.qn) then
|
||||||
|
call signal_val_error(key_id,4,qn_read,qn)
|
||||||
|
else if (qn_read.le.0) then
|
||||||
|
call signal_val_error(key_id,5,qn_read,1)
|
||||||
|
endif
|
||||||
|
else if (datlen(key_id).gt.2) then
|
||||||
|
call signal_dim_error(key_id,11,datlen(key_id),2)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(qn.le.0) call signal_val_error(key_id,5,qn,1)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! ENCIRATIO
|
||||||
|
!************************************************************************
|
||||||
|
! parameter used for weighting ratio between energies and CI vectors
|
||||||
|
!************************************************************************
|
||||||
|
key_id=18
|
||||||
|
if(nci.gt.0) then
|
||||||
|
wt_en2ci=1./(ndiab+0.d0)
|
||||||
|
else
|
||||||
|
wt_en2ci=1.d0
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
wt_en2ci=ddat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,82) wt_en2ci
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
82 format('Setting Ratio between Energie and CI Weights to:',g9.1)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! WTEN:
|
||||||
|
!************************************************************************
|
||||||
|
! parameter used for weighting states independent
|
||||||
|
!************************************************************************
|
||||||
|
key_id=19
|
||||||
|
allocate(wt_en(nstat))
|
||||||
|
wt_en=1.d0
|
||||||
|
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
if(datlen(key_id).ne.nstat)
|
||||||
|
> call signal_dim_error(key_id,3,datlen(key_id),nstat)
|
||||||
|
do j=1,nstat
|
||||||
|
wt_en(j)=ddat(datIdx(j,key_id))
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! WTCI:
|
||||||
|
!************************************************************************
|
||||||
|
! parameter used for weighting CI vectors independent
|
||||||
|
!************************************************************************
|
||||||
|
key_id=20
|
||||||
|
allocate(wt_ci(nci))
|
||||||
|
wt_ci=1.d0
|
||||||
|
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
if(datlen(key_id).ne.nstat)
|
||||||
|
> call signal_dim_error(key_id,3,datlen(key_id),nci)
|
||||||
|
do j=1,nci
|
||||||
|
wt_ci(j)=ddat(datIdx(j,key_id))
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! RMSTHR:
|
||||||
|
!************************************************************************
|
||||||
|
! Threshhold for RMSE calculation for cutting above the given threshold
|
||||||
|
! one or nstat real expected for each energie one threshold or one for all
|
||||||
|
!************************************************************************
|
||||||
|
key_id=23
|
||||||
|
allocate(rms_thr(nstat))
|
||||||
|
rms_thr = 0.d0
|
||||||
|
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
if(datlen(key_id).eq.nstat) then
|
||||||
|
do j=1,nstat
|
||||||
|
rms_thr(j)=ddat(datIdx(j,key_id))
|
||||||
|
enddo
|
||||||
|
! write(6,'("Setting RMS Threshold for individual States to: ",
|
||||||
|
! ><nstat>g12.4)') rms_thr(1:nstat) !<var> works only for ifort, not for gfortran or mpif90
|
||||||
|
|
||||||
|
write(fmt2,'("(A,",I2,"g12.4)")') nstat
|
||||||
|
write(fmt,fmt2)
|
||||||
|
$ "Set RMS Threshold for individual states to:",
|
||||||
|
$ rms_thr(1:nstat)
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
else if (datlen(key_id).eq.1) then
|
||||||
|
rms_thr = ddat(datIdx(1,key_id))
|
||||||
|
! write(6,'("Setting RMS Threshold for all States to: ",
|
||||||
|
! ><nstat>g12.4)') rms_thr !<var> works only for ifort, not for gfortran or mpif90
|
||||||
|
write(fmt2,'("(A,",I2,"g12.4)")') nstat
|
||||||
|
write(fmt,fmt2)
|
||||||
|
$ "Set RMS Threshold for individual states to:",
|
||||||
|
$ rms_thr(1:nstat)
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
else
|
||||||
|
call signal_dim_error(key_id,3,datlen(key_id),nstat)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! NPOINTS:
|
||||||
|
!************************************************************************
|
||||||
|
! Number of geometries for each set
|
||||||
|
!************************************************************************
|
||||||
|
key_id=21
|
||||||
|
allocate(ndata(sets))
|
||||||
|
ndata=0
|
||||||
|
|
||||||
|
if (is_present(key_id)) then
|
||||||
|
if (datlen(key_id).ne.sets) then
|
||||||
|
call signal_dim_error(key_id,3,datlen(key_id),sets)
|
||||||
|
endif
|
||||||
|
do j=1,sets
|
||||||
|
ndata(j)=idat(datIdx(j,key_id))
|
||||||
|
enddo
|
||||||
|
numdatpt=sum(ndata(1:sets))
|
||||||
|
else
|
||||||
|
write(*,*)'WARNING: NO NPOINTS CARD GIVEN'
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! NTOT:
|
||||||
|
!************************************************************************
|
||||||
|
! Total number of output values.
|
||||||
|
!************************************************************************
|
||||||
|
key_id=22
|
||||||
|
ntot=min_ntot
|
||||||
|
if (is_present(key_id)) then
|
||||||
|
ntot=idat(datIdx(1,key_id))
|
||||||
|
if(ntot.lt.min_ntot) then
|
||||||
|
write(6,*)'ERROR: ntot less than set Minimum: ',
|
||||||
|
> ntot,min_ntot
|
||||||
|
stop
|
||||||
|
elseif(ntot.gt.max_ntot) then
|
||||||
|
write(6,*)'ERROR: ntot exceeds set Maximum: ',ntot,max_ntot
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! ANAGRAD:
|
||||||
|
!************************************************************************
|
||||||
|
! if present analytical gradients are used for eigenvalues and vectors
|
||||||
|
!************************************************************************
|
||||||
|
key_id=24
|
||||||
|
anagrad=is_present(key_id)
|
||||||
|
if(anagrad) then
|
||||||
|
write(fmt,'(A)') 'Using Analytical gradients.'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! LBFGS:
|
||||||
|
!************************************************************************
|
||||||
|
! if present the LBFGS-B algorithm of Nocedal and Wright is used
|
||||||
|
! instead of the default Levenberg-Marquard algorithm
|
||||||
|
!************************************************************************
|
||||||
|
key_id=25
|
||||||
|
lbfgs=is_present(key_id)
|
||||||
|
if(lbfgs) then
|
||||||
|
write(fmt,'(A)') 'Using LBFGS-B algorithm for fit'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
|
||||||
|
key_id=26
|
||||||
|
lbfgs_corr=10 !Standard value
|
||||||
|
if (lbfgs) then
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
lbfgs_corr=idat(datIdx(1,key_id))
|
||||||
|
endif
|
||||||
|
if(lbfgs_corr.eq.0)
|
||||||
|
$ call signal_val_error(key_id,5,lbfgs_corr,1)
|
||||||
|
write(fmt,'("Number of LBFGS corrections set to: ",i9)')
|
||||||
|
$ lbfgs_corr
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! FACSPREAD:
|
||||||
|
!************************************************************************
|
||||||
|
! read multiplicative factor for spreads of all parameters
|
||||||
|
!************************************************************************
|
||||||
|
key_id=27
|
||||||
|
facspread=1.d0
|
||||||
|
if(is_present(key_id)) then
|
||||||
|
facspread = ddat(datIdx(1,key_id))
|
||||||
|
if(facspread.le.0.d0) then
|
||||||
|
write(6,*) 'ERROR: facspread <= 0'
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(fmt,'("Multiplicative factor for parameter spread: ",f5.2)')
|
||||||
|
$ facspread
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! LOGCONVERGENCE:
|
||||||
|
!************************************************************************
|
||||||
|
! If present logging files for convergence are printed
|
||||||
|
!************************************************************************
|
||||||
|
key_id=28
|
||||||
|
log_convergence=is_present(key_id)
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! COORD:
|
||||||
|
!************************************************************************
|
||||||
|
! For each set, specify a coord number N, where
|
||||||
|
! N=0 (default) computes a walk coordinate on q mapped to [0:1]
|
||||||
|
! N>0 plot against q(N)
|
||||||
|
!
|
||||||
|
!************************************************************************
|
||||||
|
key_id=29
|
||||||
|
allocate(plot_coord(sets))
|
||||||
|
plot_coord=0
|
||||||
|
if (is_present(key_id)) then
|
||||||
|
if (datlen(key_id).ne.sets) then
|
||||||
|
call signal_dim_error(key_id,3,datlen(key_id),sets)
|
||||||
|
endif
|
||||||
|
do j=1,sets
|
||||||
|
plot_coord(j)=idat(datIdx(j,key_id))
|
||||||
|
enddo
|
||||||
|
fmt='COORD: Scan file(s) will use the following coordinates:'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
fmt='(I3)'
|
||||||
|
call write_longint(std_out,plot_coord,datlen(key_id),
|
||||||
|
> fmt,16)
|
||||||
|
endif
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! PARMETER KEYS:
|
||||||
|
!************************************************************************
|
||||||
|
! read the parameter keys defined in keys.incl
|
||||||
|
!************************************************************************
|
||||||
|
|
||||||
|
call parameterkey_read
|
||||||
|
> (infile,linenum,p,p_act,p_spread,npar,gspread,facspread)
|
||||||
|
|
||||||
|
if (all(p_act.eq.0)) then
|
||||||
|
write(std_out,'(A)') 'WARNING: No active parameters. '
|
||||||
|
> // 'Setting FREEZE:'
|
||||||
|
freeze=.true.
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
! DATA:
|
||||||
|
!************************************************************************
|
||||||
|
! reading x an y values in the datablock after DATA: card
|
||||||
|
!************************************************************************
|
||||||
|
legacy_wt=.true. !< @TODO consider implementing card for ANN weighting format
|
||||||
|
call read_data(infile,x,y,wt,
|
||||||
|
> legacy_wt,dat_start,linenum,ntot,qn,
|
||||||
|
> qn_read,numdatpt)
|
||||||
|
|
||||||
|
|
||||||
|
deallocate(infile)
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!************************************************************************
|
||||||
|
subroutine read_data(in,x,y,wt,
|
||||||
|
> legacy_wt,st,lauf,y_dim,x_dim,
|
||||||
|
> x_read,ndatapoints)
|
||||||
|
! Routine reading DATA-block.
|
||||||
|
! If ndatapoints is nonzero, only the first ndatapoints pattern pairs are read.
|
||||||
|
!
|
||||||
|
! in: input file as string vector
|
||||||
|
! in(n) nth line of input file
|
||||||
|
! lauf: number of lines in input file
|
||||||
|
! st: starting position of DATA-block
|
||||||
|
!
|
||||||
|
!.....Splitting variables
|
||||||
|
! ndatapoints: number of given pattern pairs
|
||||||
|
! nref: number of reference patterns
|
||||||
|
!.....Data arrays containing the read out and in values
|
||||||
|
! wterr: weight factors for each element of the error vector e
|
||||||
|
! x: input patterns
|
||||||
|
! y: desired output patterns
|
||||||
|
! x/y(i,N): value of ith in-/output neuron for pattern N
|
||||||
|
! x_dim: physical dimension of x(:,N)
|
||||||
|
! x_read: number of read coordinates (rest is 0)
|
||||||
|
!
|
||||||
|
! expected format (for one pattern pair):
|
||||||
|
!.. y1 x1 x2 x3 ... xM
|
||||||
|
!.. y2 x1 x2 x3 ... xM
|
||||||
|
!.. .. .. .. .. ... ..
|
||||||
|
!.. yN x1 x2 x3 ... xM
|
||||||
|
!..
|
||||||
|
!.. WT: w1 w2 ... wN
|
||||||
|
!
|
||||||
|
!... wt-legacy mode format:
|
||||||
|
!.. y1 x1 x2 x3 ... xM
|
||||||
|
!.. WT: w1
|
||||||
|
!.. y2 x1 x2 x3 ... xM
|
||||||
|
!.. WT: w2
|
||||||
|
!.. .. .. .. .. ... ..
|
||||||
|
!.. yN x1 x2 x3 ... xM
|
||||||
|
!.. WT: wN
|
||||||
|
!
|
||||||
|
! where N=inp_out and M=inp_in
|
||||||
|
|
||||||
|
double precision, allocatable :: x(:,:),y(:,:)
|
||||||
|
double precision, allocatable :: wt(:,:)
|
||||||
|
! actual relevant Dimensions
|
||||||
|
integer ndatapoints,st,lauf,y_dim,x_dim
|
||||||
|
integer x_read
|
||||||
|
character(len=llen) in(lauf)
|
||||||
|
logical legacy_wt
|
||||||
|
integer pat_count,line
|
||||||
|
|
||||||
|
integer k
|
||||||
|
|
||||||
|
! allocate arrays
|
||||||
|
allocate(x(x_dim,ndatapoints),y(y_dim,ndatapoints),
|
||||||
|
> wt(y_dim,ndatapoints))
|
||||||
|
|
||||||
|
|
||||||
|
pat_count=0
|
||||||
|
line=st !count lines
|
||||||
|
|
||||||
|
do while (line.le.lauf)
|
||||||
|
if (in(line)(1:3).eq.'WT:') then
|
||||||
|
|
||||||
|
if (legacy_wt .or. (pat_count.eq.0)) then
|
||||||
|
write(6,419) 1
|
||||||
|
write(6,'(A)') '(preceding WT-block)'
|
||||||
|
stop ec_read
|
||||||
|
endif
|
||||||
|
|
||||||
|
read(in(line)(4:llen),*,err=511,end=508)
|
||||||
|
> wt(1:y_dim,pat_count)
|
||||||
|
|
||||||
|
line=line+1
|
||||||
|
|
||||||
|
if (pat_count.eq.ndatapoints) exit
|
||||||
|
|
||||||
|
cycle
|
||||||
|
508 write(6,419) pat_count
|
||||||
|
write(6,'(A)') '(broken WT: input)'
|
||||||
|
stop ec_read
|
||||||
|
511 write(6,418) pat_count
|
||||||
|
write(6,'(A)') 'LINE DUMP:'
|
||||||
|
write(6,'(A)') trim(in(line)(4:llen))
|
||||||
|
stop ec_read
|
||||||
|
else
|
||||||
|
! stop reading if desired number of patterns is read
|
||||||
|
if ((ndatapoints.gt.0).and.(pat_count.eq.ndatapoints)) exit
|
||||||
|
|
||||||
|
! new input set begins
|
||||||
|
pat_count=pat_count+1
|
||||||
|
wt(1:y_dim,pat_count)=1.0D0
|
||||||
|
x(:,pat_count)=0.d0
|
||||||
|
read(in(line)(1:llen),*,err=513,end=510) y(1,pat_count),
|
||||||
|
> x(1:x_read,pat_count)
|
||||||
|
line=line+1
|
||||||
|
! wt-legacy-mode: read single weight
|
||||||
|
if (legacy_wt .and. (in(line)(1:3).eq.'WT:')) then
|
||||||
|
read(in(line)(4:llen),*,err=515,end=514)
|
||||||
|
> wt(1:1,pat_count)
|
||||||
|
line=line+1
|
||||||
|
endif
|
||||||
|
|
||||||
|
do k=2,y_dim
|
||||||
|
! read y(k,pat_count) and copy x-vector for comparison
|
||||||
|
read(in(line)(1:llen),*,err=512,end=509)
|
||||||
|
> y(k,pat_count)
|
||||||
|
|
||||||
|
if (line.lt.lauf) then
|
||||||
|
line=line+1
|
||||||
|
if (legacy_wt .and. (in(line)(1:3).eq.'WT:')) then
|
||||||
|
read(in(line)(4:llen),*,err=515,end=514)
|
||||||
|
> wt(k:k,pat_count)
|
||||||
|
line=line+1
|
||||||
|
endif
|
||||||
|
cycle
|
||||||
|
else if (k.eq.y_dim) then
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
509 write(6,419) pat_count
|
||||||
|
write(6,'(A)') '(reached EOF before completion)'
|
||||||
|
stop ec_read
|
||||||
|
512 write(6,421) pat_count, line
|
||||||
|
write(6,'(A)') 'LINE DUMP:'
|
||||||
|
write(6,'(A)') trim(in(line)(1:llen))
|
||||||
|
stop ec_read
|
||||||
|
enddo
|
||||||
|
|
||||||
|
cycle
|
||||||
|
510 write(6,419) pat_count
|
||||||
|
stop ec_read
|
||||||
|
513 write(6,421) pat_count, line
|
||||||
|
write(6,'(A)') 'LINE DUMP:'
|
||||||
|
write(6,'(A)') trim(in(line)(1:llen))
|
||||||
|
stop ec_read
|
||||||
|
514 write(6,419) pat_count
|
||||||
|
write(6,'(A)') '(broken WT: input)'
|
||||||
|
stop ec_read
|
||||||
|
515 write(6,418) pat_count
|
||||||
|
write(6,'(A)') 'LINE DUMP:'
|
||||||
|
write(6,'(A)') trim(in(line)(4:llen))
|
||||||
|
stop ec_read
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
! pat_count is now actual number of patterns
|
||||||
|
|
||||||
|
if (pat_count.le.0) then
|
||||||
|
write(6,419) 1
|
||||||
|
stop ec_read
|
||||||
|
else if (ndatapoints.ne.pat_count) then
|
||||||
|
write(6,420) ndatapoints,pat_count
|
||||||
|
stop ec_read
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
! 417 format('ERROR: CORRUPTED WEIGHT INPUT (SET #',I9,')')
|
||||||
|
418 format('ERROR: NUMDATPT EXCEEDING MAX_NUMDATPT(',I9,' vs.',I9,')')
|
||||||
|
419 format('ERROR: INCOMPLETE OR MISSING DATA SET. SET #',I9)
|
||||||
|
420 format('ERROR: NUMBER OF DATA POINTS INCONSISTENT
|
||||||
|
> WITH NDATAPOINTS',
|
||||||
|
> '(',I9,' vs.',I9,')')
|
||||||
|
421 format('ERROR: CORRUPTED DATA POINT INPUT (SET #',I9,', LINE,',
|
||||||
|
> I9,')')
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
! Here follow convenience functions defined for this modul only.
|
||||||
|
|
||||||
|
integer function datIdx(j,key_id)
|
||||||
|
! Locate Jth value of KEY_IDth data block on *dat vector(s).
|
||||||
|
|
||||||
|
integer j,key_id
|
||||||
|
|
||||||
|
datIdx=IdxShift(j,datpos(2,key_id))
|
||||||
|
end function
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
integer function IdxShift(j,start)
|
||||||
|
! Map linear index of a logical vector which is embedded in a memory
|
||||||
|
! vector and begins at START.
|
||||||
|
|
||||||
|
integer j,start
|
||||||
|
|
||||||
|
IdxShift=start-1+j
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
||||||
|
!--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logical function is_present(key_id,quiet)
|
||||||
|
use strings_mod,only:write_oneline
|
||||||
|
implicit none
|
||||||
|
! Checks whether optional key has been given in input file.
|
||||||
|
! If optional argument QUIET is true, do not print a message
|
||||||
|
! if the key wasn't found.
|
||||||
|
|
||||||
|
integer key_id
|
||||||
|
logical quiet
|
||||||
|
optional quiet
|
||||||
|
|
||||||
|
character(len=llen) fmt
|
||||||
|
integer,parameter :: std_out = 6
|
||||||
|
|
||||||
|
is_present=(datpos(2,key_id).ne.-1)
|
||||||
|
|
||||||
|
if (present(quiet)) then
|
||||||
|
if (quiet) then
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
else if (.not.is_present) then
|
||||||
|
write(fmt,'(A)') 'No '//trim(keylist(1,key_id))//' card found.'
|
||||||
|
call write_oneline(fmt,std_out)
|
||||||
|
endif
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
||||||
|
!----------------------------------------------------------------------------------
|
||||||
|
integer function datlen(key_id)
|
||||||
|
implicit none
|
||||||
|
integer key_id
|
||||||
|
datlen=datpos(3,key_id)
|
||||||
|
end function
|
||||||
|
|
||||||
|
end module
|
|
@ -0,0 +1,71 @@
|
||||||
|
module ptr_structure
|
||||||
|
use dim_parameter,only: pst,numdatpt,ndiab,qn
|
||||||
|
implicit none
|
||||||
|
public
|
||||||
|
|
||||||
|
type, public :: value_loc_ptr
|
||||||
|
!number of non-zero-elements
|
||||||
|
integer :: nnz=0
|
||||||
|
!row position of non-zero values
|
||||||
|
integer, allocatable :: rowPtr(:)
|
||||||
|
!column position of non-zero values
|
||||||
|
integer, allocatable :: colPtr(:)
|
||||||
|
!holds non-zero values
|
||||||
|
double precision, allocatable :: values(:,:)
|
||||||
|
end type value_loc_ptr
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
|
||||||
|
subroutine init_ptr(ptr,occupation)
|
||||||
|
|
||||||
|
type(value_loc_ptr) :: ptr
|
||||||
|
logical, intent(in) :: occupation(ndiab,ndiab)
|
||||||
|
|
||||||
|
integer :: i,j,k
|
||||||
|
integer :: m,n,nnz
|
||||||
|
|
||||||
|
! Get occupation size for first and second index
|
||||||
|
m = size(occupation,1)
|
||||||
|
n = size(occupation,2)
|
||||||
|
|
||||||
|
!Count number of non-zero occupation elements
|
||||||
|
nnz = count(occupation .eqv. .true.)
|
||||||
|
ptr%nnz = nnz
|
||||||
|
|
||||||
|
!Allocate data for pointer arrays and value array
|
||||||
|
allocate(ptr%rowPtr(nnz),ptr%colPtr(nnz),ptr%values(nnz,numdatpt))
|
||||||
|
|
||||||
|
!Get all non-zero elements of occupation
|
||||||
|
!Write values on values, write positions on rowPtr and colPtr
|
||||||
|
k=1
|
||||||
|
!Loop over rows
|
||||||
|
do i=1,m
|
||||||
|
!Loop over columns
|
||||||
|
do j=1,n
|
||||||
|
!Get non-zero elements and write their values on values & write their positions on rowPtr and colPtr
|
||||||
|
if(occupation(i,j)) then
|
||||||
|
ptr%rowPtr(k)=i
|
||||||
|
ptr%colPtr(k)=j
|
||||||
|
!Increase counter
|
||||||
|
k=k+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine init_ptr
|
||||||
|
|
||||||
|
subroutine init_values(ptr,matrix,pt)
|
||||||
|
|
||||||
|
type(value_loc_ptr) :: ptr
|
||||||
|
double precision matrix(ndiab,ndiab)
|
||||||
|
integer pt
|
||||||
|
integer l
|
||||||
|
|
||||||
|
do l=1,ptr%nnz
|
||||||
|
ptr%values(l,pt)=matrix(ptr%rowPtr(l),ptr%colPtr(l))
|
||||||
|
enddo
|
||||||
|
|
||||||
|
end subroutine init_values
|
||||||
|
|
||||||
|
end module ptr_structure
|
|
@ -0,0 +1,362 @@
|
||||||
|
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||||
|
c interface for genetic to call random generator
|
||||||
|
|
||||||
|
c seed = initialization seed: large integer
|
||||||
|
c ierr=6 : output for error [only for Marius Lewerenz random number generator)
|
||||||
|
c gtype = choose which random number generator is invoked
|
||||||
|
|
||||||
|
c gtype = 1 is the DEFAULT behavior if the GTYPE card is not set within the input file
|
||||||
|
|
||||||
|
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||||
|
function rn(seed,gtype,cont)
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
!INPUT
|
||||||
|
integer seed !seed to initialize random number stream
|
||||||
|
integer gtype !choose which RNG is used (1="standard" genetic version,2=RANLUX)
|
||||||
|
integer cont !initialize random number stream (1) or continue with already initialited stream (0)
|
||||||
|
|
||||||
|
!LOCAL VARIABLES ("standard" genetic)
|
||||||
|
integer ierr,iseed
|
||||||
|
double precision rand
|
||||||
|
save ierr
|
||||||
|
|
||||||
|
!LOCAL VARIABLES (RANLUX)
|
||||||
|
integer lux
|
||||||
|
integer length
|
||||||
|
parameter (length=1)
|
||||||
|
real random_vec(length)
|
||||||
|
|
||||||
|
!OUTPUT VARIABLE
|
||||||
|
double precision rn
|
||||||
|
|
||||||
|
if (gtype.eq.1) then
|
||||||
|
write(6,*) 'ERROR: No longer supported.'
|
||||||
|
stop
|
||||||
|
elseif(gtype.eq.2) then
|
||||||
|
|
||||||
|
!Initialize RANLUX generator
|
||||||
|
if (cont.eq.1) then
|
||||||
|
lux=223 !choice of luxury level; see Documentation of RANLUX
|
||||||
|
call RLUXGO(lux,abs(seed),0,0) !initialize random number stream
|
||||||
|
endif
|
||||||
|
!Get one random number and write it to rn, rn will be returned
|
||||||
|
call RANLUX(random_vec,length)
|
||||||
|
rn=dble(random_vec(1))
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
write(6,*) "No random number generator specified for GTYPE=",
|
||||||
|
$ gtype
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
c###################################################################################
|
||||||
|
|
||||||
|
c INTERFACE TO RANLUX
|
||||||
|
|
||||||
|
c###################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
c ACPRRANLUX. RANLUX, A FORTRAN IMPLEMENTATION OF THE HIGH-QUALITY ACPR0000
|
||||||
|
c PSEUDORANDOM NUMBER GENERATOR OF LUSCHER. F. JAMES. ACPR0000
|
||||||
|
c REF. IN COMP. PHYS. COMMUN. 79 (1994) 111 ACPR0000
|
||||||
|
SUBROUTINE RANLUX(RVEC,LENV) ACPR0001
|
||||||
|
C Subtract-and-borrow random number generator proposed by ACPR0002
|
||||||
|
C Marsaglia and Zaman, implemented by F. James with the name ACPR0003
|
||||||
|
C RCARRY in 1991, and later improved by Martin Luescher ACPR0004
|
||||||
|
C in 1993 to produce "Luxury Pseudorandom Numbers". ACPR0005
|
||||||
|
C Fortran 77 coded by F. James, 1993 ACPR0006
|
||||||
|
C ACPR0007
|
||||||
|
C LUXURY LEVELS. ACPR0008
|
||||||
|
C ------ ------ The available luxury levels are: ACPR0009
|
||||||
|
C ACPR0010
|
||||||
|
C level 0 (p=24): equivalent to the original RCARRY of Marsaglia ACPR0011
|
||||||
|
C and Zaman, very long period, but fails many tests. ACPR0012
|
||||||
|
C level 1 (p=48): considerable improvement in quality over level 0, ACPR0013
|
||||||
|
C now passes the gap test, but still fails spectral test. ACPR0014
|
||||||
|
C level 2 (p=97): passes all known tests, but theoretically still ACPR0015
|
||||||
|
C defective. ACPR0016
|
||||||
|
C level 3 (p=223): DEFAULT VALUE. Any theoretically possible ACPR0017
|
||||||
|
C correlations have very small chance of being observed. ACPR0018
|
||||||
|
C level 4 (p=389): highest possible luxury, all 24 bits chaotic. ACPR0019
|
||||||
|
C ACPR0020
|
||||||
|
C!!! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ACPR0021
|
||||||
|
C!!! Calling sequences for RANLUX: ++ ACPR0022
|
||||||
|
C!!! CALL RANLUX (RVEC, LEN) returns a vector RVEC of LEN ++ ACPR0023
|
||||||
|
C!!! 32-bit random floating point numbers between ++ ACPR0024
|
||||||
|
C!!! zero (not included) and one (also not incl.). ++ ACPR0025
|
||||||
|
C!!! CALL RLUXGO(LUX,INT,K1,K2) initializes the generator from ++ ACPR0026
|
||||||
|
C!!! one 32-bit integer INT and sets Luxury Level LUX ++ ACPR0027
|
||||||
|
C!!! which is integer between zero and MAXLEV, or if ++ ACPR0028
|
||||||
|
C!!! LUX .GT. 24, it sets p=LUX directly. K1 and K2 ++ ACPR0029
|
||||||
|
C!!! should be set to zero unless restarting at a break++ ACPR0030
|
||||||
|
C!!! point given by output of RLUXAT (see RLUXAT). ++ ACPR0031
|
||||||
|
C!!! CALL RLUXAT(LUX,INT,K1,K2) gets the values of four integers++ ACPR0032
|
||||||
|
C!!! which can be used to restart the RANLUX generator ++ ACPR0033
|
||||||
|
C!!! at the current point by calling RLUXGO. K1 and K2++ ACPR0034
|
||||||
|
C!!! specify how many numbers were generated since the ++ ACPR0035
|
||||||
|
C!!! initialization with LUX and INT. The restarting ++ ACPR0036
|
||||||
|
C!!! skips over K1+K2*E9 numbers, so it can be long.++ ACPR0037
|
||||||
|
C!!! A more efficient but less convenient way of restarting is by: ++ ACPR0038
|
||||||
|
C!!! CALL RLUXIN(ISVEC) restarts the generator from vector ++ ACPR0039
|
||||||
|
C!!! ISVEC of 25 32-bit integers (see RLUXUT) ++ ACPR0040
|
||||||
|
C!!! CALL RLUXUT(ISVEC) outputs the current values of the 25 ++ ACPR0041
|
||||||
|
C!!! 32-bit integer seeds, to be used for restarting ++ ACPR0042
|
||||||
|
C!!! ISVEC must be dimensioned 25 in the calling program ++ ACPR0043
|
||||||
|
C!!! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ACPR0044
|
||||||
|
DIMENSION RVEC(LENV) ACPR0045
|
||||||
|
DIMENSION SEEDS(24), ISEEDS(24), ISDEXT(25) ACPR0046
|
||||||
|
PARAMETER (MAXLEV=4, LXDFLT=3) ACPR0047
|
||||||
|
DIMENSION NDSKIP(0:MAXLEV) ACPR0048
|
||||||
|
DIMENSION NEXT(24) ACPR0049
|
||||||
|
PARAMETER (TWOP12=4096., IGIGA=1000000000,JSDFLT=314159265) ACPR0050
|
||||||
|
PARAMETER (ITWO24=2**24, ICONS=2147483563) ACPR0051
|
||||||
|
SAVE NOTYET, I24, J24, CARRY, SEEDS, TWOM24, TWOM12, LUXLEV ACPR0052
|
||||||
|
SAVE NSKIP, NDSKIP, IN24, NEXT, KOUNT, MKOUNT, INSEED ACPR0053
|
||||||
|
INTEGER LUXLEV ACPR0054
|
||||||
|
LOGICAL NOTYET ACPR0055
|
||||||
|
DATA NOTYET, LUXLEV, IN24, KOUNT, MKOUNT /.TRUE., LXDFLT, 0,0,0/ ACPR0056
|
||||||
|
DATA I24,J24,CARRY/24,10,0./ ACPR0057
|
||||||
|
C default ACPR0058
|
||||||
|
C Luxury Level 0 1 2 *3* 4 ACPR0059
|
||||||
|
DATA NDSKIP/0, 24, 73, 199, 365 / ACPR0060
|
||||||
|
Corresponds to p=24 48 97 223 389 ACPR0061
|
||||||
|
C time factor 1 2 3 6 10 on slow workstation ACPR0062
|
||||||
|
C 1 1.5 2 3 5 on fast mainframe ACPR0063
|
||||||
|
C ACPR0064
|
||||||
|
C NOTYET is .TRUE. if no initialization has been performed yet. ACPR0065
|
||||||
|
C Default Initialization by Multiplicative Congruential ACPR0066
|
||||||
|
IF (NOTYET) THEN ACPR0067
|
||||||
|
NOTYET = .FALSE. ACPR0068
|
||||||
|
JSEED = JSDFLT ACPR0069
|
||||||
|
INSEED = JSEED ACPR0070
|
||||||
|
WRITE(6,'(A,I12)') ' RANLUX DEFAULT INITIALIZATION: ',JSEED ACPR0071
|
||||||
|
LUXLEV = LXDFLT ACPR0072
|
||||||
|
NSKIP = NDSKIP(LUXLEV) ACPR0073
|
||||||
|
LP = NSKIP + 24 ACPR0074
|
||||||
|
IN24 = 0 ACPR0075
|
||||||
|
KOUNT = 0 ACPR0076
|
||||||
|
MKOUNT = 0 ACPR0077
|
||||||
|
WRITE(6,'(A,I2,A,I4)') ' RANLUX DEFAULT LUXURY LEVEL = ', ACPR0078
|
||||||
|
+ LUXLEV,' p =',LP ACPR0079
|
||||||
|
TWOM24 = 1. ACPR0080
|
||||||
|
DO 25 I= 1, 24 ACPR0081
|
||||||
|
TWOM24 = TWOM24 * 0.5 ACPR0082
|
||||||
|
K = JSEED/53668 ACPR0083
|
||||||
|
JSEED = 40014*(JSEED-K*53668) -K*12211 ACPR0084
|
||||||
|
IF (JSEED .LT. 0) JSEED = JSEED+ICONS ACPR0085
|
||||||
|
ISEEDS(I) = MOD(JSEED,ITWO24) ACPR0086
|
||||||
|
25 CONTINUE ACPR0087
|
||||||
|
TWOM12 = TWOM24 * 4096. ACPR0088
|
||||||
|
DO 50 I= 1,24 ACPR0089
|
||||||
|
SEEDS(I) = REAL(ISEEDS(I))*TWOM24 ACPR0090
|
||||||
|
NEXT(I) = I-1 ACPR0091
|
||||||
|
50 CONTINUE ACPR0092
|
||||||
|
NEXT(1) = 24 ACPR0093
|
||||||
|
I24 = 24 ACPR0094
|
||||||
|
J24 = 10 ACPR0095
|
||||||
|
CARRY = 0. ACPR0096
|
||||||
|
IF (SEEDS(24) .EQ. 0.) CARRY = TWOM24 ACPR0097
|
||||||
|
ENDIF ACPR0098
|
||||||
|
C ACPR0099
|
||||||
|
C The Generator proper: "Subtract-with-borrow", ACPR0100
|
||||||
|
C as proposed by Marsaglia and Zaman, ACPR0101
|
||||||
|
C Florida State University, March, 1989 ACPR0102
|
||||||
|
C ACPR0103
|
||||||
|
DO 100 IVEC= 1, LENV ACPR0104
|
||||||
|
UNI = SEEDS(J24) - SEEDS(I24) - CARRY ACPR0105
|
||||||
|
IF (UNI .LT. 0.) THEN ACPR0106
|
||||||
|
UNI = UNI + 1.0 ACPR0107
|
||||||
|
CARRY = TWOM24 ACPR0108
|
||||||
|
ELSE ACPR0109
|
||||||
|
CARRY = 0. ACPR0110
|
||||||
|
ENDIF ACPR0111
|
||||||
|
SEEDS(I24) = UNI ACPR0112
|
||||||
|
I24 = NEXT(I24) ACPR0113
|
||||||
|
J24 = NEXT(J24) ACPR0114
|
||||||
|
RVEC(IVEC) = UNI ACPR0115
|
||||||
|
C small numbers (with less than 12 "significant" bits) are "padded". ACPR0116
|
||||||
|
IF (UNI .LT. TWOM12) THEN ACPR0117
|
||||||
|
RVEC(IVEC) = RVEC(IVEC) + TWOM24*SEEDS(J24) ACPR0118
|
||||||
|
C and zero is forbidden in case someone takes a logarithm ACPR0119
|
||||||
|
IF (RVEC(IVEC) .EQ. 0.) RVEC(IVEC) = TWOM24*TWOM24 ACPR0120
|
||||||
|
ENDIF ACPR0121
|
||||||
|
C Skipping to luxury. As proposed by Martin Luscher. ACPR0122
|
||||||
|
IN24 = IN24 + 1 ACPR0123
|
||||||
|
IF (IN24 .EQ. 24) THEN ACPR0124
|
||||||
|
IN24 = 0 ACPR0125
|
||||||
|
KOUNT = KOUNT + NSKIP ACPR0126
|
||||||
|
DO 90 ISK= 1, NSKIP ACPR0127
|
||||||
|
UNI = SEEDS(J24) - SEEDS(I24) - CARRY ACPR0128
|
||||||
|
IF (UNI .LT. 0.) THEN ACPR0129
|
||||||
|
UNI = UNI + 1.0 ACPR0130
|
||||||
|
CARRY = TWOM24 ACPR0131
|
||||||
|
ELSE ACPR0132
|
||||||
|
CARRY = 0. ACPR0133
|
||||||
|
ENDIF ACPR0134
|
||||||
|
SEEDS(I24) = UNI ACPR0135
|
||||||
|
I24 = NEXT(I24) ACPR0136
|
||||||
|
J24 = NEXT(J24) ACPR0137
|
||||||
|
90 CONTINUE ACPR0138
|
||||||
|
ENDIF ACPR0139
|
||||||
|
100 CONTINUE ACPR0140
|
||||||
|
KOUNT = KOUNT + LENV ACPR0141
|
||||||
|
IF (KOUNT .GE. IGIGA) THEN ACPR0142
|
||||||
|
MKOUNT = MKOUNT + 1 ACPR0143
|
||||||
|
KOUNT = KOUNT - IGIGA ACPR0144
|
||||||
|
ENDIF ACPR0145
|
||||||
|
RETURN ACPR0146
|
||||||
|
C ACPR0147
|
||||||
|
C Entry to input and float integer seeds from previous run ACPR0148
|
||||||
|
ENTRY RLUXIN(ISDEXT) ACPR0149
|
||||||
|
TWOM24 = 1. ACPR0150
|
||||||
|
DO 195 I= 1, 24 ACPR0151
|
||||||
|
NEXT(I) = I-1 ACPR0152
|
||||||
|
195 TWOM24 = TWOM24 * 0.5 ACPR0153
|
||||||
|
NEXT(1) = 24 ACPR0154
|
||||||
|
TWOM12 = TWOM24 * 4096. ACPR0155
|
||||||
|
WRITE(6,'(A)') ' FULL INITIALIZATION OF RANLUX WITH 25 INTEGERS:' ACPR0156
|
||||||
|
WRITE(6,'(5X,5I12)') ISDEXT ACPR0157
|
||||||
|
DO 200 I= 1, 24 ACPR0158
|
||||||
|
SEEDS(I) = REAL(ISDEXT(I))*TWOM24 ACPR0159
|
||||||
|
200 CONTINUE ACPR0160
|
||||||
|
CARRY = 0. ACPR0161
|
||||||
|
IF (ISDEXT(25) .LT. 0) CARRY = TWOM24 ACPR0162
|
||||||
|
ISD = IABS(ISDEXT(25)) ACPR0163
|
||||||
|
I24 = MOD(ISD,100) ACPR0164
|
||||||
|
ISD = ISD/100 ACPR0165
|
||||||
|
J24 = MOD(ISD,100) ACPR0166
|
||||||
|
ISD = ISD/100 ACPR0167
|
||||||
|
IN24 = MOD(ISD,100) ACPR0168
|
||||||
|
ISD = ISD/100 ACPR0169
|
||||||
|
LUXLEV = ISD ACPR0170
|
||||||
|
IF (LUXLEV .LE. MAXLEV) THEN ACPR0171
|
||||||
|
NSKIP = NDSKIP(LUXLEV) ACPR0172
|
||||||
|
WRITE (6,'(A,I2)') ' RANLUX LUXURY LEVEL SET BY RLUXIN TO: ', ACPR0173
|
||||||
|
+ LUXLEV ACPR0174
|
||||||
|
ELSE IF (LUXLEV .GE. 24) THEN ACPR0175
|
||||||
|
NSKIP = LUXLEV - 24 ACPR0176
|
||||||
|
WRITE (6,'(A,I5)') ' RANLUX P-VALUE SET BY RLUXIN TO:',LUXLEV ACPR0177
|
||||||
|
ELSE ACPR0178
|
||||||
|
NSKIP = NDSKIP(MAXLEV) ACPR0179
|
||||||
|
WRITE (6,'(A,I5)') ' RANLUX ILLEGAL LUXURY RLUXIN: ',LUXLEV ACPR0180
|
||||||
|
LUXLEV = MAXLEV ACPR0181
|
||||||
|
ENDIF ACPR0182
|
||||||
|
INSEED = -1 ACPR0183
|
||||||
|
RETURN ACPR0184
|
||||||
|
C ACPR0185
|
||||||
|
C Entry to ouput seeds as integers ACPR0186
|
||||||
|
ENTRY RLUXUT(ISDEXT) ACPR0187
|
||||||
|
DO 300 I= 1, 24 ACPR0188
|
||||||
|
ISDEXT(I) = INT(SEEDS(I)*TWOP12*TWOP12) ACPR0189
|
||||||
|
300 CONTINUE ACPR0190
|
||||||
|
ISDEXT(25) = I24 + 100*J24 + 10000*IN24 + 1000000*LUXLEV ACPR0191
|
||||||
|
IF (CARRY .GT. 0.) ISDEXT(25) = -ISDEXT(25) ACPR0192
|
||||||
|
RETURN ACPR0193
|
||||||
|
C ACPR0194
|
||||||
|
C Entry to output the "convenient" restart point ACPR0195
|
||||||
|
ENTRY RLUXAT(LOUT,INOUT,K1,K2) ACPR0196
|
||||||
|
LOUT = LUXLEV ACPR0197
|
||||||
|
INOUT = INSEED ACPR0198
|
||||||
|
K1 = KOUNT ACPR0199
|
||||||
|
K2 = MKOUNT ACPR0200
|
||||||
|
RETURN ACPR0201
|
||||||
|
C ACPR0202
|
||||||
|
C Entry to initialize from one or three integers ACPR0203
|
||||||
|
ENTRY RLUXGO(LUX,INS,K1,K2) ACPR0204
|
||||||
|
IF (LUX .LT. 0) THEN ACPR0205
|
||||||
|
LUXLEV = LXDFLT ACPR0206
|
||||||
|
ELSE IF (LUX .LE. MAXLEV) THEN ACPR0207
|
||||||
|
LUXLEV = LUX ACPR0208
|
||||||
|
ELSE IF (LUX .LT. 24 .OR. LUX .GT. 2000) THEN ACPR0209
|
||||||
|
LUXLEV = MAXLEV ACPR0210
|
||||||
|
WRITE (6,'(A,I7)') ' RANLUX ILLEGAL LUXURY RLUXGO: ',LUX ACPR0211
|
||||||
|
ELSE ACPR0212
|
||||||
|
LUXLEV = LUX ACPR0213
|
||||||
|
DO 310 ILX= 0, MAXLEV ACPR0214
|
||||||
|
IF (LUX .EQ. NDSKIP(ILX)+24) LUXLEV = ILX ACPR0215
|
||||||
|
310 CONTINUE ACPR0216
|
||||||
|
ENDIF ACPR0217
|
||||||
|
IF (LUXLEV .LE. MAXLEV) THEN ACPR0218
|
||||||
|
NSKIP = NDSKIP(LUXLEV) ACPR0219
|
||||||
|
WRITE(6,'(A,I2,A,I4)') ' RANLUX LUXURY LEVEL SET BY RLUXGO :', ACPR0220
|
||||||
|
+ LUXLEV,' P=', NSKIP+24 ACPR0221
|
||||||
|
ELSE ACPR0222
|
||||||
|
NSKIP = LUXLEV - 24 ACPR0223
|
||||||
|
WRITE (6,'(A,I5)') ' RANLUX P-VALUE SET BY RLUXGO TO:',LUXLEV ACPR0224
|
||||||
|
ENDIF ACPR0225
|
||||||
|
IN24 = 0 ACPR0226
|
||||||
|
IF (INS .LT. 0) WRITE (6,'(A)') ACPR0227
|
||||||
|
+ ' Illegal initialization by RLUXGO, negative input seed' ACPR0228
|
||||||
|
IF (INS .GT. 0) THEN ACPR0229
|
||||||
|
JSEED = INS ACPR0230
|
||||||
|
WRITE(6,'(A,3I12)') ' RANLUX INITIALIZED BY RLUXGO FROM SEEDS', ACPR0231
|
||||||
|
+ JSEED, K1,K2 ACPR0232
|
||||||
|
ELSE ACPR0233
|
||||||
|
JSEED = JSDFLT ACPR0234
|
||||||
|
WRITE(6,'(A)')' RANLUX INITIALIZED BY RLUXGO FROM DEFAULT SEED' ACPR0235
|
||||||
|
ENDIF ACPR0236
|
||||||
|
INSEED = JSEED ACPR0237
|
||||||
|
NOTYET = .FALSE. ACPR0238
|
||||||
|
TWOM24 = 1. ACPR0239
|
||||||
|
DO 325 I= 1, 24 ACPR0240
|
||||||
|
TWOM24 = TWOM24 * 0.5 ACPR0241
|
||||||
|
K = JSEED/53668 ACPR0242
|
||||||
|
JSEED = 40014*(JSEED-K*53668) -K*12211 ACPR0243
|
||||||
|
IF (JSEED .LT. 0) JSEED = JSEED+ICONS ACPR0244
|
||||||
|
ISEEDS(I) = MOD(JSEED,ITWO24) ACPR0245
|
||||||
|
325 CONTINUE ACPR0246
|
||||||
|
TWOM12 = TWOM24 * 4096. ACPR0247
|
||||||
|
DO 350 I= 1,24 ACPR0248
|
||||||
|
SEEDS(I) = REAL(ISEEDS(I))*TWOM24 ACPR0249
|
||||||
|
NEXT(I) = I-1 ACPR0250
|
||||||
|
350 CONTINUE ACPR0251
|
||||||
|
NEXT(1) = 24 ACPR0252
|
||||||
|
I24 = 24 ACPR0253
|
||||||
|
J24 = 10 ACPR0254
|
||||||
|
CARRY = 0. ACPR0255
|
||||||
|
IF (SEEDS(24) .EQ. 0.) CARRY = TWOM24 ACPR0256
|
||||||
|
C If restarting at a break point, skip K1 + IGIGA*K2 ACPR0257
|
||||||
|
C Note that this is the number of numbers delivered to ACPR0258
|
||||||
|
C the user PLUS the number skipped (if luxury .GT. 0). ACPR0259
|
||||||
|
KOUNT = K1 ACPR0260
|
||||||
|
MKOUNT = K2 ACPR0261
|
||||||
|
IF (K1+K2 .NE. 0) THEN ACPR0262
|
||||||
|
DO 500 IOUTER= 1, K2+1 ACPR0263
|
||||||
|
INNER = IGIGA ACPR0264
|
||||||
|
IF (IOUTER .EQ. K2+1) INNER = K1 ACPR0265
|
||||||
|
DO 450 ISK= 1, INNER ACPR0266
|
||||||
|
UNI = SEEDS(J24) - SEEDS(I24) - CARRY ACPR0267
|
||||||
|
IF (UNI .LT. 0.) THEN ACPR0268
|
||||||
|
UNI = UNI + 1.0 ACPR0269
|
||||||
|
CARRY = TWOM24 ACPR0270
|
||||||
|
ELSE ACPR0271
|
||||||
|
CARRY = 0. ACPR0272
|
||||||
|
ENDIF ACPR0273
|
||||||
|
SEEDS(I24) = UNI ACPR0274
|
||||||
|
I24 = NEXT(I24) ACPR0275
|
||||||
|
J24 = NEXT(J24) ACPR0276
|
||||||
|
450 CONTINUE ACPR0277
|
||||||
|
500 CONTINUE ACPR0278
|
||||||
|
C Get the right value of IN24 by direct calculation ACPR0279
|
||||||
|
IN24 = MOD(KOUNT, NSKIP+24) ACPR0280
|
||||||
|
IF (MKOUNT .GT. 0) THEN ACPR0281
|
||||||
|
IZIP = MOD(IGIGA, NSKIP+24) ACPR0282
|
||||||
|
IZIP2 = MKOUNT*IZIP + IN24 ACPR0283
|
||||||
|
IN24 = MOD(IZIP2, NSKIP+24) ACPR0284
|
||||||
|
ENDIF ACPR0285
|
||||||
|
C Now IN24 had better be between zero and 23 inclusive ACPR0286
|
||||||
|
IF (IN24 .GT. 23) THEN ACPR0287
|
||||||
|
WRITE (6,'(A/A,3I11,A,I5)') ACPR0288
|
||||||
|
+ ' Error in RESTARTING with RLUXGO:',' The values', INS, ACPR0289
|
||||||
|
+ K1, K2, ' cannot occur at luxury level', LUXLEV ACPR0290
|
||||||
|
IN24 = 0 ACPR0291
|
||||||
|
ENDIF ACPR0292
|
||||||
|
ENDIF ACPR0293
|
||||||
|
RETURN ACPR0294
|
||||||
|
END ACPR0295
|
|
@ -0,0 +1,50 @@
|
||||||
|
c---------------------------- ranlfg.inc -------------------------------
|
||||||
|
c---+----|----+----|----+----|----+----|----+----|----+----|----+----|--
|
||||||
|
c
|
||||||
|
c parameters for lagged fibonacci generators and common block with
|
||||||
|
c generator state
|
||||||
|
c
|
||||||
|
c-----------------------------------------------------------------------
|
||||||
|
c
|
||||||
|
c possible (np,nq) values, (np,np-nq) is also valid:
|
||||||
|
c (17,5), (250,103), (521,158), (1279,418),
|
||||||
|
c (2281,715), (4423,1393), (1279,1063)
|
||||||
|
c ref.: Bhanot et al., phys. rev b 33, 7841 (1986);
|
||||||
|
c Zierler, inf. control 15, 67 (1961)
|
||||||
|
c
|
||||||
|
c mersenne prime primitive trinomials:
|
||||||
|
c (heringa et al. int.j.mod.phys.c 3, 561 (1992))
|
||||||
|
c
|
||||||
|
c (89,38)
|
||||||
|
c (127,1), (127,7), (127,15), (127,30), (127,63)
|
||||||
|
c (521,32), (521,48), (521,158), (521,168)
|
||||||
|
c (607,105), (607,147), (607, 273)
|
||||||
|
c (1279,216), (1279,418)
|
||||||
|
c (2281,715), (2281,915), (2281,1029)
|
||||||
|
c (3217,67), (3217,576)
|
||||||
|
c (4423,271), (4423,369), (4423,370), (4423,649), (4424,1393),
|
||||||
|
c (4423,1419), (4423,2098)
|
||||||
|
c (9689,84), (9689,471), (9689,1836), (9689,2444), (9689,4187)
|
||||||
|
c (19937,881), (19937,7083), (19937,9842)
|
||||||
|
c (23209,1530), (23209,6619), (23209,9739)
|
||||||
|
c (44497,8575), (44497,21034)
|
||||||
|
c (110503,25230), (110503,53719)
|
||||||
|
c (132049,7000), (132049,33912), (132049,41469), (132049,52549),
|
||||||
|
c (132049,54454)
|
||||||
|
c
|
||||||
|
c another pair from brent92 who recommends q=0.618p : (258,175)
|
||||||
|
c brent's ranu4 uses (132049,79500)
|
||||||
|
c
|
||||||
|
c-----------------------------------------------------------------------
|
||||||
|
c parameter (np=250,nq=103)
|
||||||
|
integer np,nq
|
||||||
|
parameter (np=1279,nq=418)
|
||||||
|
c parameter (np=2281,nq=715)
|
||||||
|
c parameter (np=274674,nq=67874)
|
||||||
|
integer init
|
||||||
|
integer last
|
||||||
|
double precision x(np) !???
|
||||||
|
save /xrandf/
|
||||||
|
common /xrandf/ x,last,init
|
||||||
|
c---+----|----+----|----+----|----+----|----+----|----+----|----+----|--
|
||||||
|
c----------------------------- last line -------------------------------
|
Loading…
Reference in New Issue