First commit for the rep of L-matrix
This commit is contained in:
commit
fc9159bc32
|
|
@ -0,0 +1,6 @@
|
|||
# Author: jnshuti
|
||||
# Created: 2025-10-06 11:46:14
|
||||
# Last modified: 2025-10-06 12:56:39 jnshuti
|
||||
|
||||
./bin/
|
||||
./obj/
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
SHELL = /bin/bash
|
||||
.SUFFIXES :
|
||||
.SUFFIXES : .f .o .f90
|
||||
src = ./src/
|
||||
build = ./obj/
|
||||
bin = ./bin/
|
||||
|
||||
######################################################################
|
||||
version=localdw-1.0
|
||||
######################################################################
|
||||
|
||||
#IFORT VERSION (DEFAULT)
|
||||
FC = ifort
|
||||
#MODERN IFORT VERSION (for compiling on laptops)
|
||||
FFLAGS =-O2 -qopenmp -qmkl -heap-arrays -module $(build) -cpp -g -diag-disable=10448
|
||||
#-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
|
||||
|
||||
|
||||
#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 -O0 #-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 accuracy_constants.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 Potential_no3_5s_jcp2021_cart_corrected.o surface_mod.o matrix_form.o ctrans.o model.o weight.o adia.o
|
||||
|
||||
#model_obj = ptr_structure.o Potential_no3_5s_jcp2021_cart_corrected.o select_monom_mod.o maik_ctrans.o surface_mod.o matrix_form.o model.o weight.o adia.o
|
||||
model_obj = ptr_structure.o ctrans.o surface_mod.o matrix_form.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) )
|
||||
|
||||
|
||||
#plot_dip_obj = $(addprefix $(build), io_parameters.o accuracy_constants.o dim_parameter.oi model.o)
|
||||
#Note: Since we are using modules, you have carefully choose the order of compilation and take dependencies between modules and subroutines into account!
|
||||
|
||||
######################################################################
|
||||
# Lib path to pes libray
|
||||
PATH_PES = $(HOME)/Documents/work/NO3/NO3_PES/NO3_PES_FABIAN/
|
||||
PES_LIB = $(PATH_PES)libno3_pes_ffabian.a
|
||||
|
||||
FFLAGS += -I$(PATH_PES)
|
||||
LDFLAGS = -L$(PATH_PES) -lno3_pes_ffabian
|
||||
# define main goal
|
||||
main = genetic
|
||||
|
||||
|
||||
main1 = plot_dipole
|
||||
.PHONY: ifort gfortran
|
||||
|
||||
ifort: $(main)
|
||||
|
||||
# define main compilation
|
||||
gfortran: override FC = $(GNUFC)
|
||||
gfortran: override FFLAGS = $(GNUFFLAGS)
|
||||
gfortran: $(main)
|
||||
|
||||
$(main) : dirs $(random_obj) $(objects) $(PES_LIB)
|
||||
$(FC) $(FFLAGS) $(random_obj) $(objects) $(LDFLAGS) -o $(bin)$(main)
|
||||
|
||||
|
||||
|
||||
parser.o : io_parameters.o keys.o dim_parameter.o parameterkeys.o parse_errors.o
|
||||
$(FC) -c $(FFLAGS) $^ -o $@
|
||||
|
||||
$(build)%.o : %.f
|
||||
$(FC) -c $(FFLAGS) $^ -o $@
|
||||
|
||||
$(build)%.o : %.f90
|
||||
$(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 *.o)
|
||||
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,12 @@
|
|||
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 :: idp= int32
|
||||
integer,parameter :: dp = real64
|
||||
! 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,563 @@
|
|||
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 ! commented out by JP on 08.10.2025
|
||||
! In fitting dipole nstat is meaningless, I always go with ntot
|
||||
! and send to zero the unused parts of y_m and ymod
|
||||
|
||||
do i=1,numdatpt
|
||||
|
||||
call funcs(i,par,ymod,dyda,npar,ma,skip)
|
||||
write(58,*) "ymod ",i,nloop,ymod(1:ntot)
|
||||
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)
|
||||
!write(58,*) "dy ",n,i,ymod(n),y_m(n,i),dy(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,38 @@
|
|||
!*** Relevant parameters for the analytic model
|
||||
!*** offsets:
|
||||
!*** offsets(1): morse equilibrium (N-H, Angström)
|
||||
!*** offsets(2): reference angle (H-N-H)
|
||||
!*** offsets(3): --
|
||||
!*** pat_index: vector giving the position of the
|
||||
!*** various coordinates (see below)
|
||||
!*** ppars: polynomial parameters for tmcs
|
||||
!*** vcfs: coefficients for V expressions.
|
||||
!*** wzcfs: coefficients for W & Z expressions.
|
||||
!*** ifc: inverse factorials.
|
||||
|
||||
integer matdim
|
||||
parameter (matdim=5) ! matrix is (matdim)x(matdim)
|
||||
|
||||
real*8 offsets(2)
|
||||
integer pat_index(maxnin)
|
||||
|
||||
! NH3 params
|
||||
parameter (offsets=[2.344419d0,120.d0])
|
||||
|
||||
!##########################################################################
|
||||
! coordinate order; the first #I number of coords are given to the
|
||||
! ANN, where #I is the number of input neurons. The position i in
|
||||
! pat_index corresponds to a coordinate, the value of pat_index(i)
|
||||
! signifies its position.
|
||||
!
|
||||
! The vector is ordered as follows:
|
||||
! a,xs,ys,xb,yb,b,rs**2,rb**2,b**2,
|
||||
! es*eb, es**3, eb**3,es**2*eb, es*eb**2
|
||||
! ri**2 := xi**2+yi**2 = ei**2; ei := (xi,yi), i = s,b
|
||||
!
|
||||
! parts not supposed to be read by ANN are marked by ';' for your
|
||||
! convenience.
|
||||
!##########################################################################
|
||||
! a,rs**2,rb**2,es*eb,es**3,eb**3,es**2*eb,es*eb**2,b**2 #I=9 (6D)
|
||||
parameter (pat_index=[1,2,3,4,5,6,7,8,9,10,11,12,13,14])
|
||||
!**************************************************************************
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! % SUBROUTINE CTRANS(...)
|
||||
! %
|
||||
! % M. Vossel 21.03.2023
|
||||
! %
|
||||
! % Routine to transform symmetryinput coordinates to symmetrized
|
||||
! % coordinates. Distances Are discribet by Morse coordinates or
|
||||
! % TMC depending on Set Parameters in the Genetic Input.
|
||||
! %
|
||||
! % input variables
|
||||
! % q:
|
||||
! % q(1): H1x
|
||||
! % q(2): y
|
||||
! % q(3): z
|
||||
! % q(4): H2x
|
||||
! % q(5): y
|
||||
! % q(6): z
|
||||
! % q(7): H3x
|
||||
! % q(8): y
|
||||
! % q(9): z
|
||||
!
|
||||
!
|
||||
!
|
||||
! % Internal variables:
|
||||
! % t: primitive coordinates (double[qn])
|
||||
! % t(1):
|
||||
! % t(2):
|
||||
! % t(3):
|
||||
! % t(4):
|
||||
! % t(5):
|
||||
! % t(6):
|
||||
! % t(7):
|
||||
! % t(8):
|
||||
! % t(9):
|
||||
! % t: dummy (double[qn])
|
||||
! % p: parameter vector
|
||||
! % npar: length of parameter vector
|
||||
! %
|
||||
! % Output variables
|
||||
! % s: symmetrized coordinates (double[qn])
|
||||
! % s(1): CH-symetric streatch
|
||||
! % s(2): CH-asymetric streatch-ex
|
||||
! % s(3): CH-asymetric streatch-ey
|
||||
! % s(4): CH-bend-ex
|
||||
! % s(5): CH-bend-ey
|
||||
! % s(6): CH-umbrella
|
||||
! % s(7): CH-umbrella**2
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
module ctrans_mod
|
||||
use accuracy_constants, only: dp, idp
|
||||
implicit none
|
||||
! precalculate pi, 2*pi and angle to radian conversion
|
||||
real(dp), parameter :: pi = 4.0_dp*datan(1.0_dp)
|
||||
real(dp), parameter :: pi2 = 2.0_dp*pi
|
||||
real(dp), parameter :: ang2rad = pi/180.0_dp
|
||||
! precalculate roots
|
||||
real(dp), parameter:: sq2 = 1.0_dp/dsqrt(2.0_dp)
|
||||
real(dp), parameter:: sq3 = 1.0_dp/dsqrt(3.0_dp)
|
||||
real(dp), parameter:: sq6 = 1.0_dp/dsqrt(6.0_dp)
|
||||
! change distances for equilibrium
|
||||
!real(dp), parameter :: dchequi = 1.02289024_dp
|
||||
real(dp), parameter :: dchequi = 2.344419_dp ! NO3
|
||||
!real(dp), parameter :: dchequi = 2.34451900_dp
|
||||
|
||||
! see changes
|
||||
|
||||
contains
|
||||
subroutine ctrans(q, x1,x2, invariants)
|
||||
use dim_parameter, only: qn
|
||||
integer(idp) k !running indices
|
||||
real(dp), intent(in) :: q(qn) !given coordinates
|
||||
real(dp), intent(out) :: x1(qn) !output coordinates symmetry adapted and scaled
|
||||
real(dp), intent(out) :: x2(qn) !output coordinates symmetry adapted but not scaled
|
||||
! ANN Variables
|
||||
real(dp), optional, intent(out) :: invariants(:)
|
||||
real(dp) :: s(qn),t(qn)
|
||||
! kartesian coordianates copy from MeF+ so substitute c by n and removed f
|
||||
real(dp) ch1(3), ch2(3), ch3(3), c_atom(3)
|
||||
real(dp) nh1(3), nh2(3), nh3(3)
|
||||
real(dp) zaxis(3), xaxis(3), yaxis(3)
|
||||
real(dp) ph1(3), ph2(3), ph3(3)
|
||||
! primitive coordinates
|
||||
real(dp) dch1, dch2, dch3 !nh-distances
|
||||
real(dp) umb !Umbrella Angle from xy-plane
|
||||
|
||||
! Symmetry coordinates
|
||||
real(dp) aR !a1-modes H-Dist.,
|
||||
real(dp) exR, exAng !ex components H-Dist., H-Ang.
|
||||
real(dp) eyR, eyAng !ey components H-Dist., H-Ang.
|
||||
! debugging
|
||||
logical, parameter :: dbg = .false.
|
||||
|
||||
! initialize coordinate vectors
|
||||
s = 0.0_dp
|
||||
t = 0.0_dp
|
||||
|
||||
! write kartesian coords for readability
|
||||
c_atom(1:3) = q(1:3)
|
||||
do k = 1, 3
|
||||
ch1(k) = q(k + 3)
|
||||
ch2(k) = q(k + 6)
|
||||
ch3(k) = q(k + 9)
|
||||
end do
|
||||
|
||||
! construct z-axis
|
||||
nh1 = normalized(ch1)
|
||||
nh2 = normalized(ch2)
|
||||
nh3 = normalized(ch3)
|
||||
zaxis = create_plane(nh1, nh2, nh3)
|
||||
|
||||
! calculate bonding distance
|
||||
dch1 = norm(ch1)
|
||||
dch2 = norm(ch2)
|
||||
dch3 = norm(ch3)
|
||||
|
||||
! construct symmertic and antisymmetric strech
|
||||
aR = symmetrize(dch1 - dchequi, dch2 - dchequi, dch3 - dchequi, 'a')
|
||||
exR = symmetrize(dch1, dch2, dch3, 'x')
|
||||
eyR = symmetrize(dch1, dch2, dch3, 'y')
|
||||
|
||||
! construc x-axis and y axis
|
||||
ph1 = normalized(project_point_into_plane(nh1, zaxis, c_atom))
|
||||
xaxis = normalized(ph1)
|
||||
yaxis = xproduct(zaxis, xaxis) ! right hand side koordinates
|
||||
|
||||
! project H atoms into C plane
|
||||
ph2 = normalized(project_point_into_plane(nh2, zaxis, c_atom))
|
||||
ph3 = normalized(project_point_into_plane(nh3, zaxis, c_atom))
|
||||
|
||||
call construct_HBend(exAng, eyAng, ph1, ph2, ph3, xaxis, yaxis)
|
||||
umb = construct_umbrella(nh1, nh2, nh3, zaxis)
|
||||
|
||||
! set symmetry coordinates and even powers of umbrella
|
||||
!s(1) = dch1- dchequi !aR
|
||||
!s(2) = dch2 - dchequi !exR
|
||||
!s(3) = dch3 - dchequi !eyR
|
||||
s(1) = aR
|
||||
s(2) = exR
|
||||
s(3) = eyR
|
||||
s(4) = exAng
|
||||
s(5) = eyAng
|
||||
s(6) = umb
|
||||
s(7) = umb**2
|
||||
s(8) = 0
|
||||
s(9) = 0
|
||||
! pairwise distances as second coordinate set
|
||||
t = 0._dp
|
||||
call pair_distance(q, t(1:6))
|
||||
|
||||
if (dbg) write (6, '("sym coords s=",9f16.8)') s(1:qn)
|
||||
if (dbg) write (6, '("sym coords t=",9f16.8)') t(1:qn)
|
||||
if (present(invariants)) then
|
||||
call get_invariants(s, invariants)
|
||||
end if
|
||||
|
||||
! transform s and t to x1 and x2
|
||||
x1(1:qn)=s(1:qn)
|
||||
x1(5)=x1(5)
|
||||
! set other x coordinate to zero other than strech
|
||||
!X1(4:qn)=0.0d0
|
||||
x2(1:qn)=t(1:qn)
|
||||
end subroutine ctrans
|
||||
|
||||
subroutine pair_distance(q, r)
|
||||
real(dp), intent(in) :: q(9)
|
||||
real(dp), intent(out) :: r(6)
|
||||
real(dp) :: atom(3, 4)
|
||||
integer :: n, k, count
|
||||
|
||||
!atom order: H1 H2 H3 N
|
||||
atom(:, 1:3) = reshape(q, [3, 3])
|
||||
atom(:, 4) = (/0.0_dp, 0.0_dp, 0.0_dp/)
|
||||
|
||||
! disntace order 12 13 14 23 24 34
|
||||
count = 0
|
||||
do n = 1, size(atom, 2)
|
||||
do k = n + 1, size(atom, 2)
|
||||
count = count + 1
|
||||
r(count) = sqrt(sum((atom(:, k) - atom(:, n))**2))
|
||||
end do
|
||||
end do
|
||||
end subroutine pair_distance
|
||||
|
||||
function morse_and_symmetrize(x,p,pst) result(s)
|
||||
real(dp), intent(in),dimension(3) :: x
|
||||
real(dp), intent(in),dimension(11) :: p
|
||||
integer, intent(in),dimension(2) :: pst
|
||||
integer :: k
|
||||
real(dp), dimension(3) :: s
|
||||
real(dp), dimension(3) :: t
|
||||
|
||||
! Morse transform
|
||||
do k=1,3
|
||||
t(k) = morse_transform(x(k), p, pst)
|
||||
end do
|
||||
s(1) = symmetrize(t(1), t(2), t(3), 'a')
|
||||
s(2) = symmetrize(t(1), t(2), t(3), 'x')
|
||||
s(3) = symmetrize(t(1), t(2), t(3), 'y')
|
||||
end function morse_and_symmetrize
|
||||
|
||||
subroutine get_invariants(s, inv_out)
|
||||
use dim_parameter, only: qn
|
||||
use select_monom_mod, only: v_e_monom, v_ee_monom
|
||||
real(dp), intent(in) :: s(qn)
|
||||
real(dp), intent(out) :: inv_out(:)
|
||||
! real(dp), parameter :: ck = 1.0_dp, dk = 1.0_dp/ck ! scaling for higher order invariants
|
||||
real(dp) inv(24)
|
||||
integer, parameter :: inv_order(12) = & ! the order in which the invariants are selected
|
||||
& [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
real(dp) Rch, umb, xR, yR, xAng, yAng
|
||||
! for readability
|
||||
Rch = s(1)
|
||||
xR = s(2)
|
||||
yR = s(3)
|
||||
xAng = s(4)
|
||||
yAng = s(5)
|
||||
umb = s(6)**2
|
||||
! invarianten
|
||||
! a moden
|
||||
inv(1) = Rch
|
||||
inv(2) = umb
|
||||
! invariante e pairs
|
||||
inv(3) = v_e_monom(xR, yR, 1)
|
||||
inv(4) = v_e_monom(xAng, yAng, 1)
|
||||
! third order e pairs
|
||||
inv(5) = v_e_monom(xR, yR, 2)
|
||||
inv(6) = v_e_monom(xAng, yAng, 2)
|
||||
! invariant ee coupling
|
||||
inv(7) = v_ee_monom(xR, yR, xAng, yAng, 1)
|
||||
! mode combinations
|
||||
inv(8) = Rch*umb
|
||||
|
||||
inv(9) = Rch*v_e_monom(xR, yR, 1)
|
||||
inv(10) = umb*v_e_monom(xR, yR, 1)
|
||||
|
||||
inv(11) = Rch*v_e_monom(xAng, yAng, 1)
|
||||
inv(12) = umb*v_e_monom(xAng, yAng, 1)
|
||||
|
||||
! damp coordinates because of second order and higher invariants
|
||||
inv(3) = sign(sqrt(abs(inv(3))), inv(3))
|
||||
inv(4) = sign(sqrt(abs(inv(4))), inv(4))
|
||||
inv(5) = sign((abs(inv(5))**(1./3.)), inv(5))
|
||||
inv(6) = sign((abs(inv(6))**(1./3.)), inv(6))
|
||||
inv(7) = sign((abs(inv(7))**(1./3.)), inv(7))
|
||||
inv(8) = sign(sqrt(abs(inv(8))), inv(8))
|
||||
inv(9) = sign((abs(inv(9))**(1./3.)), inv(9))
|
||||
inv(10) = sign((abs(inv(10))**(1./3.)), inv(10))
|
||||
inv(11) = sign((abs(inv(11))**(1./3.)), inv(11))
|
||||
inv(12) = sign((abs(inv(12))**(1./3.)), inv(12))
|
||||
|
||||
inv_out(:) = inv(inv_order(1:size(inv_out, 1)))
|
||||
|
||||
end subroutine get_invariants
|
||||
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! % real part of spherical harmonics
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! Ylm shifted to 0 for theta=0
|
||||
real(dp) function ylm(theta, phi, l, m)
|
||||
implicit none
|
||||
real(dp) theta, phi
|
||||
integer(idp) l, m
|
||||
ylm = plm2(dcos(theta), l, m)*cos(m*phi) - plm2(1.0_dp, l, m)
|
||||
end function ylm
|
||||
!----------------------------------------------------------
|
||||
real(dp) function plm2(x, l, n)
|
||||
implicit none
|
||||
real(dp) x
|
||||
integer(idp) l, m, n
|
||||
|
||||
real(dp) pmm, p_mp1m, pllm
|
||||
integer(idp) ll
|
||||
|
||||
! negative m und bereich von x abfangen
|
||||
if ((l .lt. 0)&
|
||||
&.or. (abs(n) .gt. abs(l))&
|
||||
&.or. (abs(x) .gt. 1.)) then
|
||||
write (6, '(''bad arguments in legendre'')')
|
||||
stop
|
||||
end if
|
||||
|
||||
! fix sign of m to compute the positiv m
|
||||
m = abs(n)
|
||||
|
||||
pmm = (-1)**m*dsqrt(fac(2*m))*1./((2**m)*fac(m))& !compute P(m,m) not P(l,l)
|
||||
&*(dsqrt(1.-x**2))**m
|
||||
|
||||
if (l .eq. m) then
|
||||
plm2 = pmm !P(l,m)=P(m,m)
|
||||
else
|
||||
p_mp1m = x*dsqrt(dble(2*m + 1))*pmm !compute P(m+1,m)
|
||||
if (l .eq. m + 1) then
|
||||
plm2 = p_mp1m !P(l,m)=P(m+1,m)
|
||||
else
|
||||
do ll = m + 2, l
|
||||
pllm = x*(2*l - 1)/dsqrt(dble(l**2 - m**2))*p_mp1m& ! compute P(m+2,m) up to P(l,m) recursively
|
||||
&- dsqrt(dble((l - 1)**2 - m**2))&
|
||||
&/dsqrt(dble(l**2 - m**2))*pmm
|
||||
! schreibe m+2 und m+1 jeweils fuer die naechste iteration
|
||||
pmm = p_mp1m !P(m,m) = P(m+1,m)
|
||||
p_mp1m = pllm !P(m+1,m) = P(m+2,m)
|
||||
end do
|
||||
plm2 = pllm !P(l,m)=P(m+k,m), k element N
|
||||
end if
|
||||
end if
|
||||
|
||||
! sets the phase of -m term right (ignored to gurantee Ylm=(Yl-m)* for JT terms
|
||||
! if(n.lt.0) then
|
||||
! plm2 = (-1)**m * plm2 !* fac(l-m)/fac(l+m)
|
||||
! endif
|
||||
|
||||
end function
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
real(dp) function fac(i)
|
||||
integer(idp) i
|
||||
select case (i)
|
||||
case (0)
|
||||
fac = 1.0_dp
|
||||
case (1)
|
||||
fac = 1.0_dp
|
||||
case (2)
|
||||
fac = 2.0_dp
|
||||
case (3)
|
||||
fac = 6.0_dp
|
||||
case (4)
|
||||
fac = 24.0_dp
|
||||
case (5)
|
||||
fac = 120.0_dp
|
||||
case (6)
|
||||
fac = 720.0_dp
|
||||
case (7)
|
||||
fac = 5040.0_dp
|
||||
case (8)
|
||||
fac = 40320.0_dp
|
||||
case (9)
|
||||
fac = 362880.0_dp
|
||||
case (10)
|
||||
fac = 3628800.0_dp
|
||||
case (11)
|
||||
fac = 39916800.0_dp
|
||||
case (12)
|
||||
fac = 479001600.0_dp
|
||||
case default
|
||||
write (*, *) 'ERROR: no case for given faculty, Max is 12!'
|
||||
stop
|
||||
end select
|
||||
end function fac
|
||||
|
||||
! Does the simplest morse transform possible
|
||||
! one skaling factor + shift
|
||||
function morse_transform(x, p, pst) result(t)
|
||||
real(dp), intent(in) :: x
|
||||
real(dp), intent(in) :: p(11)
|
||||
integer, intent(in) :: pst(2)
|
||||
real(dp) :: t
|
||||
if (pst(2) == 11) then
|
||||
t = 1.0_dp - exp(-abs(p(2))*(x - p(1)))
|
||||
else
|
||||
error stop 'in morse_transform key required or wrong number of parameters'
|
||||
end if
|
||||
end function morse_transform
|
||||
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! % FUNCTION F(...) ! MAIK DEPRICATING OVER THE TOP MORSE FUNCTION FOR MYSELF
|
||||
! %
|
||||
! % Returns exponent of tunable Morse coordinate
|
||||
! % exponent is polynomial * gaussian (skewed)
|
||||
! % ilabel = 1 or 2 selects the parameters a and sfac to be used
|
||||
! %
|
||||
! % Background: better representation of the prefector in the
|
||||
! % exponend of the morse function.
|
||||
! % Formular: f(r) = lest no3 paper
|
||||
! %
|
||||
! % Variables:
|
||||
! % x: distance of atoms (double)
|
||||
! % p: parameter vector (double[20])
|
||||
! % ii: 1 for CCl and 2 for CCH (int)
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
pure function f(x, p, ii)
|
||||
integer(idp), intent(in) :: ii !1 for CCL and 2 for CCH
|
||||
real(dp), intent(in) :: x !coordinate
|
||||
real(dp), intent(in) :: p(11) !parameter-vector
|
||||
|
||||
integer(idp) i !running index
|
||||
|
||||
real(dp) r !equilibrium distance
|
||||
real(dp) gaus !gaus part of f
|
||||
real(dp) poly !polynom part of f
|
||||
real(dp) skew !tanh part of f
|
||||
|
||||
real(dp) f !prefactor of exponent and returned value
|
||||
|
||||
integer(idp) npoly(2) !order of polynom
|
||||
|
||||
! Maximum polynom order
|
||||
npoly(1) = 5
|
||||
npoly(2) = 5
|
||||
|
||||
! p(1): position of equilibrium
|
||||
! p(2): constant of exponent
|
||||
! p(3): constant for skewing the gaussian
|
||||
! p(4): tuning for skewing the gaussian
|
||||
! p(5): Gaussian exponent
|
||||
! p(6): Shift of Gaussian maximum
|
||||
! p(7)...: polynomial coefficients
|
||||
! p(8+n)...: coefficients of Morse Power series
|
||||
|
||||
! 1-exp{[p(2)+exp{-p(5)[x-p(6)]^2}[Taylor{p(7+n)}(x-p(6))]][x-p(1)]}
|
||||
|
||||
! Tunable Morse function
|
||||
! Power series in Tunable Morse coordinates of order m
|
||||
! exponent is polynomial of order npoly * gaussian + switching function
|
||||
|
||||
! set r r-r_e
|
||||
r = x
|
||||
r = r - p(1)
|
||||
|
||||
! set up skewing function:
|
||||
skew = 0.5_dp*p(3)*(dtanh(dabs(p(4))*(r - p(6))) + 1.0_dp)
|
||||
|
||||
! set up gaussian function:
|
||||
gaus = dexp(-dabs(p(5))*(r - p(6))**2)
|
||||
|
||||
! set up power series:
|
||||
poly = 0.0_dp
|
||||
do i = 0, npoly(ii) - 1
|
||||
poly = poly + p(7 + i)*(r - p(6))**i
|
||||
end do
|
||||
! set up full exponent function:
|
||||
f = dabs(p(2)) + skew + gaus*poly
|
||||
|
||||
end function
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
pure function xproduct(a, b) result(axb)
|
||||
real(dp), intent(in) :: a(3), b(3)
|
||||
real(dp) :: axb(3) !crossproduct a x b
|
||||
axb(1) = a(2)*b(3) - a(3)*b(2)
|
||||
axb(2) = a(3)*b(1) - a(1)*b(3)
|
||||
axb(3) = a(1)*b(2) - a(2)*b(1)
|
||||
end function xproduct
|
||||
|
||||
pure function normalized(v) result(r)
|
||||
real(dp), intent(in) :: v(:)
|
||||
real(dp) :: r(size(v))
|
||||
r = v/norm(v)
|
||||
end function normalized
|
||||
|
||||
pure function norm(v) result(n)
|
||||
real(dp), intent(in) :: v(:)
|
||||
real(dp) n
|
||||
n = dsqrt(sum(v(:)**2))
|
||||
end function norm
|
||||
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! % FUNCTION Project_Point_Into_Plane(x,n,r0) result(p)
|
||||
! % return the to n orthogonal part of a vector x-r0
|
||||
! % p: projected point in plane
|
||||
! % x: point being projected
|
||||
! % n: normalvector of plane
|
||||
! % r0: Point in plane
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
pure function project_point_into_plane(x, n, r0) result(p)
|
||||
real(dp), intent(in) :: x(:), n(:), r0(:)
|
||||
real(dp) :: p(size(x)), xs(size(x))
|
||||
xs = x - r0
|
||||
p = xs - plane_to_point(x, n, r0)
|
||||
end function project_point_into_plane
|
||||
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! % Function Plane_To_Point(x,n,r0) result(p)
|
||||
! % p: part of n in x
|
||||
! % x: point being projected
|
||||
! % n: normalvector of plane
|
||||
! % r0: Point in plane
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
pure function plane_to_point(x, n, r0) result(p)
|
||||
real(dp), intent(in) :: x(:), n(:), r0(:)
|
||||
real(dp) p(size(x)), xs(size(x)), nn(size(n))
|
||||
nn = normalized(n)
|
||||
xs = x - r0
|
||||
p = dot_product(nn, xs)*nn
|
||||
end function plane_to_point
|
||||
|
||||
subroutine check_coordinates(q)
|
||||
! check for faulty kartesain coordinates
|
||||
real(dp), intent(in) :: q(:)
|
||||
integer(idp) :: i
|
||||
if (all(abs(q) <= epsilon(0.0_dp))) then
|
||||
stop 'Error (ctrans): all kartesian coordinates are<=1d-8'
|
||||
end if
|
||||
do i = 1, 9, 3
|
||||
if (all(abs(q(i:i + 2)) <= epsilon(0.0_dp))) then
|
||||
write (*, *) q
|
||||
stop 'Error(ctrans):kartesian coordinates zero for one atom'
|
||||
end if
|
||||
end do
|
||||
end subroutine
|
||||
|
||||
pure function rotor_a_to_z(a, z) result(r)
|
||||
real(dp), intent(in) :: a(3), z(3)
|
||||
real(dp) :: r(3, 3)
|
||||
real(dp) :: alpha
|
||||
real(dp) :: s1(3), s(3, 3), rotor(3, 3)
|
||||
s1 = xproduct(normalized(a), normalized(z))
|
||||
alpha = asin(norm(s1))
|
||||
s(:, 1) = normalized(s1)
|
||||
s(:, 2) = normalized(z)
|
||||
s(:, 3) = xproduct(s1, z)
|
||||
rotor = init_rotor(alpha, 0.0_dp, 0.0_dp)
|
||||
r = matmul(s, matmul(rotor, transpose(s)))
|
||||
end function
|
||||
|
||||
! function returning Rz(gamma) * Ry(beta) * Rx(alpha) for basis order xyz
|
||||
pure function init_rotor(alpha, beta, gamma) result(rotor)
|
||||
real(dp), intent(in) :: alpha, beta, gamma
|
||||
real(dp) :: rotor(3, 3)
|
||||
rotor = 0.0_dp
|
||||
rotor(1, 1) = dcos(beta)*dcos(gamma)
|
||||
rotor(1, 2) = dsin(alpha)*dsin(beta)*dcos(gamma)&
|
||||
&- dcos(alpha)*dsin(gamma)
|
||||
rotor(1, 3) = dcos(alpha)*dsin(beta)*dcos(gamma)&
|
||||
&+ dsin(alpha)*dsin(gamma)
|
||||
|
||||
rotor(2, 1) = dcos(beta)*dsin(gamma)
|
||||
rotor(2, 2) = dsin(alpha)*dsin(beta)*dsin(gamma)&
|
||||
&+ dcos(alpha)*dcos(gamma)
|
||||
rotor(2, 3) = dcos(alpha)*dsin(beta)*dsin(gamma)&
|
||||
&- dsin(alpha)*dcos(gamma)
|
||||
|
||||
rotor(3, 1) = -dsin(beta)
|
||||
rotor(3, 2) = dsin(alpha)*dcos(beta)
|
||||
rotor(3, 3) = dcos(alpha)*dcos(beta)
|
||||
end function init_rotor
|
||||
|
||||
pure function create_plane(a, b, c) result(n)
|
||||
real(dp), intent(in) :: a(3), b(3), c(3)
|
||||
real(dp) :: n(3)
|
||||
real(dp) :: axb(3), bxc(3), cxa(3)
|
||||
axb = xproduct(a, b)
|
||||
bxc = xproduct(b, c)
|
||||
cxa = xproduct(c, a)
|
||||
n = normalized(axb + bxc + cxa)
|
||||
end function create_plane
|
||||
|
||||
function symmetrize(q1, q2, q3, sym) result(s)
|
||||
real(dp), intent(in) :: q1, q2, q3
|
||||
character, intent(in) :: sym
|
||||
real(dp) :: s
|
||||
select case (sym)
|
||||
case ('a')
|
||||
s = (q1 + q2 + q3)*sq3
|
||||
case ('x')
|
||||
s = sq6*(2.0_dp*q1 - q2 - q3)
|
||||
case ('y')
|
||||
s = sq2*(q2 - q3)
|
||||
case default
|
||||
write (*, *) 'ERROR: no rule for symmetrize with sym=', sym
|
||||
stop
|
||||
end select
|
||||
end function symmetrize
|
||||
|
||||
subroutine construct_HBend(ex, ey, ph1, ph2, ph3, x_axis, y_axis)
|
||||
real(dp), intent(in) :: ph1(3), ph2(3), ph3(3)
|
||||
real(dp), intent(in) :: x_axis(3), y_axis(3)
|
||||
real(dp), intent(out) :: ex, ey
|
||||
real(dp) :: x1, y1, alpha1
|
||||
real(dp) :: x2, y2, alpha2
|
||||
real(dp) :: x3, y3, alpha3
|
||||
! get x and y components of projected points
|
||||
x1 = dot_product(ph1, x_axis)
|
||||
y1 = dot_product(ph1, y_axis)
|
||||
x2 = dot_product(ph2, x_axis)
|
||||
y2 = dot_product(ph2, y_axis)
|
||||
x3 = dot_product(ph3, x_axis)
|
||||
y3 = dot_product(ph3, y_axis)
|
||||
! -> calculate H deformation angles
|
||||
alpha3 = datan2(y2, x2)
|
||||
alpha2 = -datan2(y3, x3) !-120*ang2rad
|
||||
! write(*,*)' atan2'
|
||||
! write(*,*) 'alpha2:' , alpha2/ang2rad
|
||||
! write(*,*) 'alpha3:' , alpha3/ang2rad
|
||||
if (alpha2 .lt. 0) alpha2 = alpha2 + pi2
|
||||
if (alpha3 .lt. 0) alpha3 = alpha3 + pi2
|
||||
alpha1 = (pi2 - alpha2 - alpha3)
|
||||
! write(*,*)' fixed break line'
|
||||
! write(*,*) 'alpha1:' , alpha1/ang2rad
|
||||
! write(*,*) 'alpha2:' , alpha2/ang2rad
|
||||
! write(*,*) 'alpha3:' , alpha3/ang2rad
|
||||
alpha1 = alpha1 !- 120.0_dp*ang2rad
|
||||
alpha2 = alpha2 !- 120.0_dp*ang2rad
|
||||
alpha3 = alpha3 !- 120.0_dp*ang2rad
|
||||
! write(*,*)' delta alpha'
|
||||
! write(*,*) 'alpha1:' , alpha1/ang2rad
|
||||
! write(*,*) 'alpha2:' , alpha2/ang2rad
|
||||
! write(*,*) 'alpha3:' , alpha3/ang2rad
|
||||
! write(*,*)
|
||||
|
||||
! construct symmetric and antisymmetric H angles
|
||||
ex = symmetrize(alpha1, alpha2, alpha3, 'x')
|
||||
ey = symmetrize(alpha1, alpha2, alpha3, 'y')
|
||||
end subroutine construct_HBend
|
||||
|
||||
pure function construct_umbrella(nh1, nh2, nh3, n)&
|
||||
&result(umb)
|
||||
real(dp), intent(in) :: nh1(3), nh2(3), nh3(3)
|
||||
real(dp), intent(in) :: n(3)
|
||||
real(dp) :: umb
|
||||
real(dp) :: theta(3)
|
||||
! calculate projections for umberella angle
|
||||
theta(1) = dacos(dot_product(n, nh1))
|
||||
theta(2) = dacos(dot_product(n, nh2))
|
||||
theta(3) = dacos(dot_product(n, nh3))
|
||||
! construct umberella angle
|
||||
umb = sum(theta(1:3))/3.0_dp - 90.0_dp*ang2rad
|
||||
end function construct_umbrella
|
||||
|
||||
pure subroutine construct_sphericals&
|
||||
&(theta, phi, cf, xaxis, yaxis, zaxis)
|
||||
real(dp), intent(in) :: cf(3), xaxis(3), yaxis(3), zaxis(3)
|
||||
real(dp), intent(out) :: theta, phi
|
||||
real(dp) :: x, y, z, v(3)
|
||||
v = normalized(cf)
|
||||
x = dot_product(v, normalized(xaxis))
|
||||
y = dot_product(v, normalized(yaxis))
|
||||
z = dot_product(v, normalized(zaxis))
|
||||
theta = dacos(z)
|
||||
phi = -datan2(y, x)
|
||||
end subroutine construct_sphericals
|
||||
|
||||
subroutine int2kart(internal, kart)
|
||||
real(dp), intent(in) :: internal(6)
|
||||
real(dp), intent(out) :: kart(9)
|
||||
real(dp) :: h1x, h1y, h1z
|
||||
real(dp) :: h2x, h2y, h2z
|
||||
real(dp) :: h3x, h3y, h3z
|
||||
real(dp) :: dch0, dch1, dch2, dch3
|
||||
real(dp) :: a1, a2, a3, wci
|
||||
|
||||
kart = 0.0_dp
|
||||
dch1 = dchequi + sq3*internal(1) + 2*sq6*internal(2)
|
||||
dch2 = dchequi + sq3*internal(1) - sq6*internal(2) + sq2*internal(3)
|
||||
dch3 = dchequi + sq3*internal(1) - sq6*internal(2) - sq2*internal(3)
|
||||
a1 = 2*sq6*internal(4)
|
||||
a2 = -sq6*internal(4) + sq2*internal(5)
|
||||
a3 = -sq6*internal(4) - sq2*internal(5)
|
||||
wci = internal(6)
|
||||
|
||||
! Berechnung kartesische Koordinaten
|
||||
! -----------------------
|
||||
h1x = dch1*cos(wci*ang2rad)
|
||||
h1y = 0.0
|
||||
h1z = -dch1*sin(wci*ang2rad)
|
||||
|
||||
h3x = dch2*cos((a2 + 120)*ang2rad)*cos(wci*ang2rad)
|
||||
h3y = dch2*sin((a2 + 120)*ang2rad)*cos(wci*ang2rad)
|
||||
h3z = -dch2*sin(wci*ang2rad)
|
||||
|
||||
h2x = dch3*cos((-a3 - 120)*ang2rad)*cos(wci*ang2rad)
|
||||
h2y = dch3*sin((-a3 - 120)*ang2rad)*cos(wci*ang2rad)
|
||||
h2z = -dch3*sin(wci*ang2rad)
|
||||
|
||||
kart(1) = h1x
|
||||
kart(2) = h1y
|
||||
kart(3) = h1z
|
||||
kart(4) = h2x
|
||||
kart(5) = h2y
|
||||
kart(6) = h2z
|
||||
kart(7) = h3x
|
||||
kart(8) = h3y
|
||||
kart(9) = h3z
|
||||
end subroutine int2kart
|
||||
|
||||
end module ctrans_mod
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,575 @@
|
|||
! Module contains the spherical harmonics up to l=5 m=-l,..,0,..,l listed on https://en.wikipedia.org/wiki/Table_of_spherical_harmonics from 19.07.2022
|
||||
! the functions are implementde by calling switch case function for given m or l value and return the corresdpondig value for given theta and phi
|
||||
! the functions are split for diffrent l values and are named by P_lm.
|
||||
! example for l=1 and m=-1 the realpart of the spherical harmonic for given theta and phi
|
||||
! is returned by calling Re_Y_lm(1,-1,theta,phi) which itself calls the corresponding function P_1m(m,theta) and multilpies it by cos(m*phi) to account for the real part of exp(m*phi*i)
|
||||
! Attention the legendre polynoms are shifted to account for the missing zero order term in spherical harmonic expansions
|
||||
module sphericalharmonics_mod
|
||||
use accuracy_constants, only: dp, idp
|
||||
implicit none
|
||||
real(kind=dp), parameter :: PI = 4.0_dp * atan( 1.0_dp )
|
||||
contains
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Y_lm( l , m , theta , phi ) result( y )
|
||||
integer(kind=idp), intent( in ) :: l , m
|
||||
real(kind=dp), intent( in ) :: theta , phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( l )
|
||||
case (1)
|
||||
y = Y_1m( m , theta , phi )
|
||||
case (2)
|
||||
y = Y_2m( m , theta , phi )
|
||||
case (3)
|
||||
y = Y_3m( m , theta , phi )
|
||||
case (4)
|
||||
y = Y_4m( m , theta , phi )
|
||||
case (5)
|
||||
y = Y_5m( m , theta , phi )
|
||||
case default
|
||||
write(errmesg,'(A,i0)')&
|
||||
&'order of spherical harmonics not implemented', l
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
end select
|
||||
end function Y_lm
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Re_Y_lm( l , m , theta , phi ) result( y )
|
||||
integer(kind=idp), intent( in ) :: l , m
|
||||
real(kind=dp), intent( in ) :: theta , phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( l )
|
||||
case (1)
|
||||
y = P_1m( m , theta ) * cos(m*phi)
|
||||
case (2)
|
||||
y = P_2m( m , theta ) * cos(m*phi)
|
||||
case (3)
|
||||
y = P_3m( m , theta ) * cos(m*phi)
|
||||
case (4)
|
||||
y = P_4m( m , theta ) * cos(m*phi)
|
||||
case (5)
|
||||
y = P_5m( m , theta ) * cos(m*phi)
|
||||
case (6)
|
||||
y = P_6m( m , theta ) * cos(m*phi)
|
||||
case default
|
||||
write(errmesg,'(A,i0)')&
|
||||
&'order of spherical harmonics not implemented', l
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
end select
|
||||
end function Re_Y_lm
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Im_Y_lm( l , m , theta , phi ) result( y )
|
||||
integer(kind=idp), intent( in ) :: l , m
|
||||
real(kind=dp), intent( in ) :: theta , phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( l )
|
||||
case (1)
|
||||
y = P_1m( m , theta ) * sin(m*phi)
|
||||
case (2)
|
||||
y = P_2m( m , theta ) * sin(m*phi)
|
||||
case (3)
|
||||
y = P_3m( m , theta ) * sin(m*phi)
|
||||
case (4)
|
||||
y = P_4m( m , theta ) * sin(m*phi)
|
||||
case (5)
|
||||
y = P_5m( m , theta ) * sin(m*phi)
|
||||
case (6)
|
||||
y = P_6m( m , theta ) * sin(m*phi)
|
||||
case default
|
||||
write(errmesg,'(a,i0)')&
|
||||
&'order of spherical harmonics not implemented',l
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
end select
|
||||
end function Im_Y_lm
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Y_1m( m , theta , phi ) result( y )
|
||||
integer(kind=idp),intent( in ):: m
|
||||
real(kind=dp),intent( in ):: theta , phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-1)
|
||||
y = 0.5_dp*sqrt(3.0_dp/(PI*2.0_dp))*sin(theta)*cos(phi)
|
||||
|
||||
case (0)
|
||||
y = 0.5_dp*sqrt(3.0_dp/PI)*cos(theta)
|
||||
|
||||
case (1)
|
||||
y = -0.5_dp*sqrt(3.0_dp/(PI*2.0_dp))*sin(theta)*cos(phi)
|
||||
|
||||
case default
|
||||
write(errmesg,'(a,i0)') 'in y_1m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
end select
|
||||
end function Y_1m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Y_2m(m,theta,phi) result(y)
|
||||
integer(kind=idp),intent(in):: m
|
||||
real(kind=dp),intent(in):: theta,phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case (m)
|
||||
case (-2)
|
||||
y=0.25_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*cos(2.0_dp*phi)
|
||||
|
||||
case (-1)
|
||||
y=0.5_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)*cos(theta)*cos(phi)
|
||||
|
||||
case (0)
|
||||
y=0.25_dp*sqrt(5.0_dp/PI)&
|
||||
&*(3.0_dp*cos(theta)**2-1.0_dp)
|
||||
|
||||
case (1)
|
||||
y=-0.5_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)*cos(theta)*cos(phi)
|
||||
|
||||
case (2)
|
||||
y=0.25_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*cos(2.0_dp*phi)
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in y_2m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function Y_2m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Y_3m(m,theta,phi) result(y)
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta,phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case (m)
|
||||
case (-3)
|
||||
y=0.125_dp*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3*cos(3.0_dp*phi)
|
||||
|
||||
case (-2)
|
||||
y=0.25_dp*sqrt(105.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*cos(theta)*cos(2.0_dp*phi)
|
||||
|
||||
case (-1)
|
||||
y=0.125_dp*sqrt(21.0_dp/(PI))&
|
||||
&*sin(theta)*(5.0_dp*cos(theta)**2-1.0_dp)*cos(phi)
|
||||
|
||||
case (0)
|
||||
y=0.25_dp*sqrt(7.0_dp/PI)&
|
||||
&*(5.0_dp*cos(theta)**3-3.0_dp*cos(theta))
|
||||
|
||||
case (1)
|
||||
y=-0.125_dp*sqrt(21.0_dp/(PI))&
|
||||
&*sin(theta)*(5.0_dp*cos(theta)**2-1.0_dp)*cos(phi)
|
||||
|
||||
case (2)
|
||||
y=0.25_dp*sqrt(105.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*cos(theta)*cos(2.0_dp*phi)
|
||||
|
||||
case (3)
|
||||
y=-0.125_dp*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3*cos(3.0_dp*phi)
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in y_3m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function Y_3m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Y_4m(m,theta,phi) result(y)
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta,phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case (m)
|
||||
case (-4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(35.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4*cos(4.0_dp*phi)
|
||||
|
||||
case (-3)
|
||||
y=0.375_dp*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3*cos(theta)*cos(3.0_dp*phi)
|
||||
|
||||
case (-2)
|
||||
y=0.375_dp*sqrt(5.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2&
|
||||
&*(7.0_dp*cos(theta)**2-1)*cos(2.0_dp*phi)
|
||||
|
||||
case (-1)
|
||||
y=0.375_dp*sqrt(5.0_dp/(PI))&
|
||||
&*sin(theta)*(7.0_dp*cos(theta)**3&
|
||||
&-3.0_dp*cos(theta))*cos(phi)
|
||||
|
||||
case (0)
|
||||
y=(3.0_dp/16.0_dp)/sqrt(PI)&
|
||||
&*(35.0_dp*cos(theta)**4&
|
||||
&-30.0_dp*cos(theta)**2+3.0_dp)
|
||||
|
||||
case (1)
|
||||
y=-0.375_dp*sqrt(5.0_dp/(PI))&
|
||||
&*sin(theta)*(7.0_dp*cos(theta)**3&
|
||||
&-3.0_dp*cos(theta))*cos(phi)
|
||||
|
||||
case (2)
|
||||
y=0.375_dp*sqrt(5.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(7.0_dp*cos(theta)**2-1.0_dp)&
|
||||
&*cos(2*phi)
|
||||
|
||||
case (3)
|
||||
y=-0.375_dp*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3*cos(theta)*cos(3.0_dp*phi)
|
||||
|
||||
case (4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(35.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4*cos(4.0_dp*phi)
|
||||
|
||||
case default
|
||||
write(errmesg,'(a,i0)')'in y_4m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function Y_4m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function Y_5m(m,theta,phi) result(y)
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta,phi
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case (m)
|
||||
case (-5)
|
||||
y=(3.0_dp/32.0_dp)*sqrt(77.0_dp/PI)&
|
||||
&*sin(theta)**5*cos(5*phi)
|
||||
|
||||
case (-4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(385.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4*cos(theta)*cos(4*phi)
|
||||
|
||||
case (-3)
|
||||
y=(1.0_dp/32.0_dp)*sqrt(385.0_dp/PI)&
|
||||
&*sin(theta)**3*(9*cos(theta)**2-1.0_dp)*cos(3*phi)
|
||||
|
||||
case (-2)
|
||||
y=0.125*sqrt(1155.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(3*cos(theta)**3-cos(theta))*cos(2*phi)
|
||||
|
||||
case (-1)
|
||||
y=(1.0_dp/16.0_dp)*sqrt(165.0_dp/(2.0_dp*PI))&
|
||||
&*sin(theta)*(21.0_dp*cos(theta)**4&
|
||||
&-14.0_dp*cos(theta)**2+1.0_dp)*cos(phi)
|
||||
|
||||
case (0)
|
||||
y=(1.0_dp/16.0_dp)/sqrt(11.0_dp/PI)&
|
||||
&*(63.0_dp*cos(theta)**5-70.0_dp*cos(theta)**3&
|
||||
&+15.0_dp*cos(theta))
|
||||
|
||||
case (1)
|
||||
y=(-1.0_dp/16.0_dp)*sqrt(165.0_dp/(2.0_dp*PI))&
|
||||
&*sin(theta)*(21.0_dp*cos(theta)**4&
|
||||
&-14.0_dp*cos(theta)**2+1.0_dp)*cos(phi)
|
||||
|
||||
case (2)
|
||||
y=0.125*sqrt(1155.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(3*cos(theta)**3-cos(theta))*cos(2*phi)
|
||||
|
||||
case (3)
|
||||
y=(-1.0_dp/32.0_dp)*sqrt(385.0_dp/PI)&
|
||||
&*sin(theta)**3*(9.0_dp*cos(theta)**2-1.0_dp)&
|
||||
&*cos(3.0_dp*phi)
|
||||
|
||||
case (4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(385.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4*cos(theta)*cos(4.0_dp*phi)
|
||||
|
||||
case (5)
|
||||
y=(-3.0_dp/32.0_dp)*sqrt(77.0_dp/PI)&
|
||||
&*sin(theta)**5*cos(5.0_dp*phi)
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in y_5m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function Y_5m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function P_1m( m , theta ) result( y )
|
||||
! >Function returns the value of the corresponding normalized Associated legendre polynom for l=1 and given m and theta
|
||||
integer(kind=idp),intent( in ):: m
|
||||
real(kind=dp),intent( in ):: theta
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-1)
|
||||
y = 0.5_dp*sqrt(3.0_dp/(PI*2.0_dp))*sin(theta)
|
||||
|
||||
case (0)
|
||||
y = 0.5_dp*sqrt(3.0_dp/PI)*(cos(theta)-1.0_dp) ! -1 is subtracted to shift so that for theta=0 y=0
|
||||
|
||||
case (1)
|
||||
y = -0.5_dp*sqrt(3.0_dp/(PI*2.0_dp))*sin(theta)
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in p_1m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function P_1m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function P_2m( m , theta ) result( y )
|
||||
! >Function returns the value of the corresponding normalized Associated legendre polynom for l=2 and given m and theta
|
||||
integer(kind=idp),intent(in):: m
|
||||
real(kind=dp),intent(in):: theta
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-2)
|
||||
y=0.25_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2
|
||||
|
||||
case (-1)
|
||||
y=0.5_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)*cos(theta)
|
||||
|
||||
case (0)
|
||||
y = (3.0_dp*cos(theta)**2-1.0_dp)
|
||||
y = y - 2.0_dp !2.0 is subtracted to shift so that for theta=0 y=0
|
||||
y = y * 0.25_dp*sqrt(5.0_dp/PI) ! normalize
|
||||
|
||||
case (1)
|
||||
y = -0.5_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)*cos(theta)
|
||||
|
||||
case (2)
|
||||
y = 0.25_dp*sqrt(15.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in p_2m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function P_2m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function P_3m( m , theta ) result( y )
|
||||
! >Function returns the value of the corresponding normalized Associated legendre polynom for l=3 and given m and theta
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-3)
|
||||
y=0.125_dp*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3
|
||||
|
||||
case (-2)
|
||||
y=0.25_dp*sqrt(105.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*cos(theta)
|
||||
|
||||
case (-1)
|
||||
y=0.125_dp*sqrt(21.0_dp/(PI))&
|
||||
&*sin(theta)*(5*cos(theta)**2-1.0_dp)
|
||||
|
||||
case (0)
|
||||
y=(5.0_dp*cos(theta)**3-3*cos(theta))
|
||||
y=y-2.0_dp ! 2.0 is subtracted to shift so that for theta=0 y=0
|
||||
y=y*0.25_dp*sqrt(7.0_dp/PI) ! normalize
|
||||
|
||||
case (1)
|
||||
y=-0.125_dp*sqrt(21.0_dp/(PI))&
|
||||
&*sin(theta)*(5.0_dp*cos(theta)**2-1.0_dp)
|
||||
|
||||
case (2)
|
||||
y=0.25*sqrt(105.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*cos(theta)
|
||||
|
||||
case (3)
|
||||
y=-0.125*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in p_3m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function P_3m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function P_4m(m,theta) result(y)
|
||||
! >Function returns the value of the corresponding normalized Associated legendre polynom for l=4 and given m and theta
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(35.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4
|
||||
|
||||
case (-3)
|
||||
y=0.375*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3*cos(theta)
|
||||
|
||||
case (-2)
|
||||
y=0.375*sqrt(5.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(7*cos(theta)**2-1)
|
||||
|
||||
case (-1)
|
||||
y=0.375*sqrt(5.0_dp/(PI))&
|
||||
&*sin(theta)*(7*cos(theta)**3-3*cos(theta))
|
||||
|
||||
|
||||
case (0)
|
||||
y=(35*cos(theta)**4-30*cos(theta)**2+3)
|
||||
y = y - 8.0_dp !8.0 is subtracted to shift so that for theta=0 y=0
|
||||
y = y * (3.0_dp/16.0_dp)/sqrt(PI)
|
||||
|
||||
case (1)
|
||||
y=-0.375*sqrt(5.0_dp/(PI))&
|
||||
&*sin(theta)*(7*cos(theta)**3-3*cos(theta))
|
||||
|
||||
case (2)
|
||||
y=0.375*sqrt(5.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(7*cos(theta)**2-1)
|
||||
|
||||
case (3)
|
||||
y=-0.375*sqrt(35.0_dp/PI)&
|
||||
&*sin(theta)**3*cos(theta)
|
||||
|
||||
case (4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(35.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in p_4m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function P_4m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function P_5m(m,theta) result(y)
|
||||
! >Function returns the value of the corresponding normalized Associated legendre polynom for l=5 and given m and theta
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta
|
||||
real(kind=dp) y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-5)
|
||||
y=(3.0_dp/32.0_dp)*sqrt(77.0_dp/PI)&
|
||||
&*sin(theta)**5
|
||||
|
||||
case (-4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(385.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4*cos(theta)
|
||||
|
||||
case (-3)
|
||||
y=(1.0_dp/32.0_dp)*sqrt(385.0_dp/PI)&
|
||||
&*sin(theta)**3*(9*cos(theta)**2-1.0_dp)
|
||||
|
||||
case (-2)
|
||||
y=0.125*sqrt(1155.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(3*cos(theta)**3-cos(theta))
|
||||
|
||||
case (-1)
|
||||
y=(1.0_dp/16.0_dp)*sqrt(165.0_dp/(2.0_dp*PI))&
|
||||
&*sin(theta)*(21*cos(theta)**4-14*cos(theta)**2+1)
|
||||
|
||||
|
||||
case (0)
|
||||
y = (63*cos(theta)**5-70*cos(theta)**3+15*cos(theta))
|
||||
y = y - 8.0_dp !8.0 is subtracted to shift so that for theta=0 y=0
|
||||
y = y * (1.0_dp/16.0_dp)/sqrt(11.0_dp/PI)
|
||||
|
||||
case (1)
|
||||
y=(-1.0_dp/16.0_dp)*sqrt(165.0_dp/(2.0_dp*PI))&
|
||||
&*sin(theta)*(21*cos(theta)**4-14*cos(theta)**2+1)
|
||||
|
||||
case (2)
|
||||
y=0.125*sqrt(1155.0_dp/(PI*2.0_dp))&
|
||||
&*sin(theta)**2*(3*cos(theta)**3-cos(theta))
|
||||
|
||||
case (3)
|
||||
y=(-1.0_dp/32.0_dp)*sqrt(385.0_dp/PI)&
|
||||
&*sin(theta)**3*(9*cos(theta)**2-1.0_dp)
|
||||
|
||||
case (4)
|
||||
y=(3.0_dp/16.0_dp)*sqrt(385.0_dp/2.0_dp*PI)&
|
||||
&*sin(theta)**4*cos(theta)
|
||||
|
||||
case (5)
|
||||
y=(-3.0_dp/32.0_dp)*sqrt(77.0_dp/PI)&
|
||||
&*sin(theta)**5
|
||||
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in p_5m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function P_5m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
function P_6m(m,theta) result(y)
|
||||
! >Function returns the value of the corresponding normalized Associated legendre polynom for l=6 and given m and theta
|
||||
integer(kind=idp), intent(in) :: m
|
||||
real(kind=dp), intent(in) :: theta
|
||||
real(kind=dp):: y
|
||||
character(len=70) :: errmesg
|
||||
select case ( m )
|
||||
case (-6)
|
||||
y = (1.0_dp/64.0_dp)*sqrt(3003.0_dp/PI)&
|
||||
&* sin(theta)**6
|
||||
case (-5)
|
||||
y = (3.0_dp/32.0_dp)*sqrt(1001.0_dp/PI)&
|
||||
&* sin(theta)**5&
|
||||
&* cos(theta)
|
||||
case (-4)
|
||||
y= (3.0_dp/32.0_dp)*sqrt(91.0_dp/(2.0_dp*PI))&
|
||||
&* sin(theta)**4&
|
||||
&* (11*cos(theta)**2 - 1 )
|
||||
case (-3)
|
||||
y= (1.0_dp/32.0_dp)*sqrt(1365.0_dp/PI)&
|
||||
&* sin(theta)**3&
|
||||
&* (11*cos(theta)**3 - 3*cos(theta) )
|
||||
case (-2)
|
||||
y= (1.0_dp/64.0_dp)*sqrt(1365.0_dp/PI)&
|
||||
&* sin(theta)**2&
|
||||
&* (33*cos(theta)**4 - 18*cos(theta)**2 + 1 )
|
||||
case (-1)
|
||||
y= (1.0_dp/16.0_dp)*sqrt(273.0_dp/(2.0_dp*PI))&
|
||||
&* sin(theta)&
|
||||
&* (33*cos(theta)**5 - 30*cos(theta)**3 + 5*cos(theta) )
|
||||
case (0)
|
||||
y = 231*cos(theta)**6 - 315*cos(theta)**4 + 105*cos(theta)**2-5
|
||||
y = y - 16.0_dp !16.0 is subtracted to shift so that for theta=0 y=0
|
||||
y = y * (1.0_dp/32.0_dp)*sqrt(13.0_dp/PI)
|
||||
case (1)
|
||||
y= -(1.0_dp/16.0_dp)*sqrt(273.0_dp/(2.0_dp*PI))&
|
||||
&* sin(theta)&
|
||||
&* (33*cos(theta)**5 - 30*cos(theta)**3 + 5*cos(theta) )
|
||||
case (2)
|
||||
y= (1.0_dp/64.0_dp)*sqrt(1365.0_dp/PI)&
|
||||
&* sin(theta)**2&
|
||||
&* (33*cos(theta)**4 - 18*cos(theta)**2 + 1 )
|
||||
case (3)
|
||||
y= -(1.0_dp/32.0_dp)*sqrt(1365.0_dp/PI)&
|
||||
&* sin(theta)**3&
|
||||
&* (11*cos(theta)**3 - 3*cos(theta) )
|
||||
case (4)
|
||||
y= (3.0_dp/32.0_dp)*sqrt(91.0_dp/(2.0_dp*PI))&
|
||||
&* sin(theta)**4&
|
||||
&* (11*cos(theta)**2 - 1 )
|
||||
case (5)
|
||||
y= -(3.0_dp/32.0_dp)*sqrt(1001.0_dp/PI)&
|
||||
&* sin(theta)**5 * cos(theta)
|
||||
case (6)
|
||||
y = (1.0_dp/64.0_dp)*sqrt(3003.0_dp/PI)&
|
||||
&* sin(theta)**6
|
||||
case default
|
||||
write(errmesg,'(A,i0)')'in p_6m given m not logic, ', m
|
||||
error stop 'error in spherical harmonics' !error stop errmesg
|
||||
|
||||
end select
|
||||
end function P_6m
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
|
||||
end module
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
module adia_mod
|
||||
implicit none
|
||||
contains
|
||||
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
! % SUBROUTINE ADIA(N,P,NPAR,ymod,v,u,SKIP)
|
||||
! %
|
||||
! % determines the adiabatic energies by diagonalizing diabatic matrix.
|
||||
! % The Eingenvalues are sorted according to the best fitting ordering
|
||||
! % of the CI vectors.
|
||||
! %
|
||||
! % ATTENTION: The interface has changed. To sort by the ci's,
|
||||
! % the datavalue of the current points are given
|
||||
! %
|
||||
! % input variables:
|
||||
! % n: number of point (int)
|
||||
! % p: parameter evector(double[npar])
|
||||
! % npar: number of parameters (int)
|
||||
! % skip: .false. if everything should be done
|
||||
! %
|
||||
! % output variables:
|
||||
! % ymod: firtst nstat energies and than nci*ndiab ci's (double[ntot])
|
||||
! % v: eigenvalues (double[ndiab])
|
||||
! % u: eigenvectors (double[ndiab,ndiab])
|
||||
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
subroutine adia(n,p,npar,ymod,vx,u,skip)
|
||||
use dim_parameter,only: ndiab,nstat,ntot,nci,pst
|
||||
use data_module,only: q_m,x1_m,x2_m,y_m
|
||||
use diabmodel, only:diab
|
||||
use data_matrix
|
||||
!use dipole, only: diab
|
||||
implicit none
|
||||
|
||||
integer i,j !running indices
|
||||
|
||||
integer iref !getting correction or refference
|
||||
|
||||
double precision e(ndiab,ndiab) !full diabatic matrix
|
||||
double precision mx(ndiab,ndiab)
|
||||
double precision my(ndiab,ndiab)
|
||||
double precision vxs,vys,vxb,vyb
|
||||
|
||||
integer n !current point
|
||||
integer npar !number of parameters
|
||||
double precision p(npar) !parameters
|
||||
|
||||
double precision u(ndiab,ndiab),ut(ndiab,ndiab) !ci-vectors
|
||||
double precision ymod(ntot) !fitted data
|
||||
double precision vx(ndiab),vy(nstat) !eigen values
|
||||
double precision,allocatable,dimension(:,:):: mat
|
||||
logical skip,dbg
|
||||
parameter (dbg=.false.)
|
||||
double precision,dimension(2,2):: T,TT,TX,TY
|
||||
! lapack variables
|
||||
integer,parameter :: lwork = 1000
|
||||
double precision work(lwork)
|
||||
integer info
|
||||
integer TYPES, BLK ! TYPE OF THE CALCULATION
|
||||
! variabke for dgemm
|
||||
|
||||
double precision,dimension(ndiab,ndiab):: ex,ey
|
||||
double precision:: alpha
|
||||
integer:: lda,ldb,beta,ldc
|
||||
double precision,dimension(ndiab,ndiab):: temp1,temp2
|
||||
call diab(ex,ey,n,x1_m(:,n),x2_m(:,n),p)
|
||||
|
||||
|
||||
! init eigenvector matrix
|
||||
TYPES = int(p(pst(1,28)))
|
||||
|
||||
BLK = int(p(pst(1,28)+1)) ! BLOCK IF TYPE IS 3
|
||||
u = 0.d0
|
||||
vx=0.0d0
|
||||
skip=.false.
|
||||
ymod=0.0d0
|
||||
if (TYPES .eq.1 ) then
|
||||
! Trace of the potential
|
||||
call trace_mat(ex,ey,ymod)
|
||||
else if (TYPES .eq.2) then
|
||||
! Eigenvalue decomposition of the potential
|
||||
call Eigen(ex,ey,ymod)
|
||||
|
||||
else if (TYPES .eq.3) then
|
||||
CALL BLOCK_DIAB(ex,ey,ymod,BLK)
|
||||
else if (TYPES .EQ.4) then
|
||||
call Full_diab_upper(ex,ey,ymod)
|
||||
else if (TYPES .eq.5) then
|
||||
call Transformation_mat(ex,vx,ymod)
|
||||
ymod=0.0d0
|
||||
else
|
||||
write(*,*) "Error in TYPE of calculation here",TYPES
|
||||
|
||||
stop
|
||||
end if
|
||||
if (dbg) then
|
||||
do i=1,ndiab
|
||||
write(*,'(5f14.6)') (ex(i,j),j=1,ndiab)
|
||||
enddo
|
||||
write(*,*)""
|
||||
endif
|
||||
|
||||
end subroutine
|
||||
subroutine matrix_mult(C,A,B,N)
|
||||
implicit none
|
||||
integer:: n,i,j,k
|
||||
double precision,dimension(n,n):: A,B,C
|
||||
do i = 1, n ! Rows of C
|
||||
do j = 1, n ! Columns of C
|
||||
C(i,j) = 0.0 ! Initialize element
|
||||
do k = 1, n ! Dot product
|
||||
C(i,j) = C(i,j) + A(i,k) * B(k,j)
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
end subroutine
|
||||
|
||||
end module adia_mod
|
||||
|
|
@ -0,0 +1,386 @@
|
|||
module ctrans_mod
|
||||
use dim_parameter, only: qn
|
||||
contains
|
||||
!! subroutine ctrans
|
||||
|
||||
subroutine ctrans(q,x1,x2)
|
||||
implicit none
|
||||
include 'nnparams.incl'
|
||||
include 'JTmod.incl'
|
||||
double precision,intent(in):: q(qn)
|
||||
double precision,intent(out):: x1(qn),x2(qn)
|
||||
double precision:: cart(3,4),qint(maxnin)
|
||||
integer i
|
||||
!cart(:,1)=0.0d0
|
||||
|
||||
!cart(1:3,2:4) = reshape([ q(4:12) ], shape(cart(1:3,2:4)))
|
||||
cart(1,1)=q(1)
|
||||
cart(2,1)=q(2)
|
||||
cart(3,1)=q(3)
|
||||
cart(1,2)=q(4)
|
||||
cart(2,2)=q(5)
|
||||
cart(3,2)=q(6)
|
||||
cart(1,3)=q(7)
|
||||
cart(2,3)=q(8)
|
||||
cart(3,3)=q(9)
|
||||
cart(1,4)=q(10)
|
||||
cart(2,4)=q(11)
|
||||
cart(3,4)=q(12)
|
||||
call cart2int(cart,qint)
|
||||
do i=1,qn
|
||||
if (abs(qint(i)) .lt. 1.0d-5) qint(i) =0.0d0
|
||||
enddo
|
||||
x1(1:qn)=qint(1:qn)
|
||||
!x1(2)=0.0d0
|
||||
x1(5)=-x1(5)
|
||||
x1(3)=-x1(3)
|
||||
!x1(6)=0.0d0
|
||||
x2(1:qn)=0.0d0 !qint(1:qn)
|
||||
end subroutine ctrans
|
||||
|
||||
|
||||
subroutine cart2int(cart,qint)
|
||||
implicit none
|
||||
! This version merges both coordinate transformation routines into
|
||||
! one. JTmod's sscales(2:3) are ignored.
|
||||
! This is the first version to be compatible with one of my proper 6D fits
|
||||
! Time-stamp: <2024-10-22 13:52:59 dwilliams>
|
||||
|
||||
! Input (cartesian, in Angström)
|
||||
! cart(:,1): N
|
||||
! cart(:,1+i): Hi
|
||||
! Output
|
||||
! qint(i): order defined in JTmod.
|
||||
! Internal Variables
|
||||
! no(1:3): NO distances 1-3
|
||||
! pat_in: temporary coordinates
|
||||
! axis: main axis of NO3
|
||||
include 'nnparams.incl'
|
||||
include 'JTmod.incl'
|
||||
|
||||
|
||||
real*8 cart(3,4),qint(maxnin)
|
||||
|
||||
real*8 no(3), r1, r2, r3
|
||||
real*8 v1(3), v2(3), v3(3)
|
||||
real*8 n1(3), n2(3), n3(3), tr(3)
|
||||
real*8 ortho(3)
|
||||
real*8 pat_in(maxnin)
|
||||
logical ignore_umbrella,dbg_umbrella
|
||||
logical dbg_distances
|
||||
|
||||
!.. Debugging parameters
|
||||
!.. set umbrella to 0
|
||||
parameter (ignore_umbrella=.false.)
|
||||
! parameter (ignore_umbrella=.true.)
|
||||
|
||||
!.. break if umbrella is not 0
|
||||
parameter (dbg_umbrella=.false.)
|
||||
! parameter (dbg_umbrella=.true.)
|
||||
|
||||
!.. break for tiny distances
|
||||
parameter (dbg_distances=.false.)
|
||||
! parameter (dbg_distances=.true.)
|
||||
|
||||
integer k
|
||||
|
||||
!.. get N-O vectors and distances:
|
||||
do k=1,3
|
||||
v1(k)=cart(k,2)-cart(k,1)
|
||||
v2(k)=cart(k,3)-cart(k,1)
|
||||
v3(k)=cart(k,4)-cart(k,1)
|
||||
enddo
|
||||
no(1)=norm(v1,3)
|
||||
no(2)=norm(v2,3)
|
||||
no(3)=norm(v3,3)
|
||||
|
||||
!.. temporarily store displacements
|
||||
do k=1,3
|
||||
pat_in(k)=no(k)-offsets(1)
|
||||
enddo
|
||||
|
||||
do k=1,3
|
||||
v1(k)=v1(k)/no(1)
|
||||
v2(k)=v2(k)/no(2)
|
||||
v3(k)=v3(k)/no(3)
|
||||
enddo
|
||||
|
||||
!.. compute three normal vectors for the ONO planes:
|
||||
call xprod(n1,v1,v2)
|
||||
call xprod(n2,v2,v3)
|
||||
call xprod(n3,v3,v1)
|
||||
|
||||
do k=1,3
|
||||
tr(k)=(n1(k)+n2(k)+n3(k))/3.d0
|
||||
enddo
|
||||
r1=norm(tr,3)
|
||||
do k=1,3
|
||||
tr(k)=tr(k)/r1
|
||||
enddo
|
||||
|
||||
! rotate trisector
|
||||
call rot_trisec(tr,v1,v2,v3)
|
||||
|
||||
!.. determine trisector angle:
|
||||
if (ignore_umbrella) then
|
||||
pat_in(7)=0.0d0
|
||||
else
|
||||
pat_in(7)=pi/2.0d0 - acos(scalar(v1,tr,3))
|
||||
pat_in(7)=sign(pat_in(7),cart(1,2))
|
||||
endif
|
||||
|
||||
!.. molecule now lies in yz plane, compute projected ONO angles:
|
||||
v1(1)=0.d0
|
||||
v2(1)=0.d0
|
||||
v3(1)=0.d0
|
||||
r1=norm(v1,3)
|
||||
r2=norm(v2,3)
|
||||
r3=norm(v3,3)
|
||||
do k=2,3
|
||||
v1(k)=v1(k)/r1
|
||||
v2(k)=v2(k)/r2
|
||||
v3(k)=v3(k)/r3
|
||||
enddo
|
||||
|
||||
! make orthogonal vector to v3
|
||||
ortho(1)=0.0d0
|
||||
ortho(2)=v3(3)
|
||||
ortho(3)=-v3(2)
|
||||
|
||||
!.. projected ONO angles in radians
|
||||
pat_in(4)=get_ang(v2,v3,ortho)
|
||||
pat_in(5)=get_ang(v1,v3,ortho)
|
||||
|
||||
pat_in(6)=dabs(pat_in(5)-pat_in(4))
|
||||
|
||||
!.. account for rotational order of atoms
|
||||
if (pat_in(4).le.pat_in(5)) then
|
||||
pat_in(5)=2*pi-pat_in(4)-pat_in(6)
|
||||
else
|
||||
pat_in(4)=2*pi-pat_in(5)-pat_in(6)
|
||||
endif
|
||||
|
||||
pat_in(4)=rad2deg*pat_in(4)-offsets(2)
|
||||
pat_in(5)=rad2deg*pat_in(5)-offsets(2)
|
||||
pat_in(6)=rad2deg*pat_in(6)-offsets(2)
|
||||
pat_in(7)=rad2deg*pat_in(7)
|
||||
|
||||
call genANN_ctrans(pat_in)
|
||||
|
||||
qint(:)=pat_in(:)
|
||||
|
||||
contains
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! compute vector product n1 of vectors v1 x v2
|
||||
subroutine xprod(n1,v1,v2)
|
||||
implicit none
|
||||
|
||||
real*8 n1(3), v1(3), v2(3)
|
||||
|
||||
n1(1) = v1(2)*v2(3) - v1(3)*v2(2)
|
||||
n1(2) = v1(3)*v2(1) - v1(1)*v2(3)
|
||||
n1(3) = v1(1)*v2(2) - v1(2)*v2(1)
|
||||
|
||||
end subroutine
|
||||
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! compute scalar product of vectors v1 and v2:
|
||||
real*8 function scalar(v1,v2,n)
|
||||
implicit none
|
||||
integer i, n
|
||||
real*8 v1(*), v2(*)
|
||||
|
||||
scalar=0.d0
|
||||
do i=1,n
|
||||
scalar=scalar+v1(i)*v2(i)
|
||||
enddo
|
||||
|
||||
end function
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! compute norm of vector:
|
||||
real*8 function norm(x,n)
|
||||
implicit none
|
||||
integer i, n
|
||||
real*8 x(*)
|
||||
|
||||
norm=0.d0
|
||||
do i=1,n
|
||||
norm=norm+x(i)**2
|
||||
enddo
|
||||
norm=sqrt(norm)
|
||||
|
||||
end function
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
|
||||
subroutine rot_trisec(tr,v1,v2,v3)
|
||||
implicit none
|
||||
|
||||
real*8 tr(3),v1(3),v2(3),v3(3)
|
||||
|
||||
real*8 vrot(3)
|
||||
real*8 rot_ax(3)
|
||||
real*8 cos_phi,sin_phi
|
||||
|
||||
! evaluate cos(-phi) and sin(-phi), where phi is the angle between
|
||||
! tr and (1,0,0)
|
||||
cos_phi=tr(1)
|
||||
sin_phi=dsqrt(tr(2)**2+tr(3)**2)
|
||||
|
||||
if (sin_phi.lt.1.0d-12) then
|
||||
return
|
||||
endif
|
||||
|
||||
! determine rotational axis
|
||||
rot_ax(1) = 0.0d0
|
||||
rot_ax(2) = tr(3)
|
||||
rot_ax(3) = -tr(2)
|
||||
! normalize
|
||||
rot_ax=rot_ax/sin_phi
|
||||
|
||||
! now the rotation can be done using Rodrigues' rotation formula
|
||||
! v'=v*cos(p) + (k x v)sin(p) + k (k*v) (1-cos(p))
|
||||
! for v=tr k*v vanishes by construction:
|
||||
|
||||
! check that the rotation does what it should
|
||||
call rodrigues(vrot,tr,rot_ax,cos_phi,sin_phi)
|
||||
if (dsqrt(vrot(2)**2+vrot(3)**2).gt.1.0d-12) then
|
||||
write(6,*) "ERROR: BROKEN TRISECTOR"
|
||||
stop
|
||||
endif
|
||||
tr=vrot
|
||||
|
||||
call rodrigues(vrot,v1,rot_ax,cos_phi,sin_phi)
|
||||
v1=vrot
|
||||
call rodrigues(vrot,v2,rot_ax,cos_phi,sin_phi)
|
||||
v2=vrot
|
||||
call rodrigues(vrot,v3,rot_ax,cos_phi,sin_phi)
|
||||
v3=vrot
|
||||
|
||||
|
||||
end subroutine
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
|
||||
subroutine rodrigues(vrot,v,axis,cos_phi,sin_phi)
|
||||
implicit none
|
||||
real*8 vrot(3),v(3),axis(3)
|
||||
real*8 cos_phi,sin_phi
|
||||
|
||||
real*8 ortho(3)
|
||||
|
||||
call xprod(ortho,axis,v)
|
||||
vrot = v*cos_phi + ortho*sin_phi+axis*scalar(axis,v,3)*(1-cos_phi)
|
||||
|
||||
end subroutine
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
|
||||
real*8 function get_ang(v,xaxis,yaxis)
|
||||
implicit none
|
||||
! get normalized [0:2pi) angle from vectors in the yz plane
|
||||
real*8 v(3),xaxis(3),yaxis(3)
|
||||
|
||||
real*8 phi
|
||||
|
||||
real*8 pi
|
||||
parameter (pi=3.141592653589793d0)
|
||||
|
||||
phi=atan2(scalar(yaxis,v,3),scalar(xaxis,v,3))
|
||||
if (phi.lt.0.0d0) then
|
||||
phi=2*pi+phi
|
||||
endif
|
||||
get_ang=phi
|
||||
|
||||
end function
|
||||
|
||||
end subroutine cart2int
|
||||
subroutine genANN_ctrans(pat_in)
|
||||
implicit none
|
||||
|
||||
include 'nnparams.incl'
|
||||
include 'JTmod.incl'
|
||||
|
||||
real*8 pat_in(maxnin)
|
||||
|
||||
real*8 raw_in(maxnin),off_in(maxnin),ptrans_in(7)
|
||||
real*8 r0
|
||||
real*8 a,b,xs,ys,xb,yb
|
||||
|
||||
integer k
|
||||
|
||||
off_in(1:7)=pat_in(1:7)
|
||||
r0=offsets(1)
|
||||
|
||||
! transform primitives
|
||||
! recover raw distances from offset coords
|
||||
do k=1,3
|
||||
raw_in(k)=off_in(k)+offsets(1)
|
||||
enddo
|
||||
|
||||
do k=1,3
|
||||
ptrans_in(k)=off_in(k)
|
||||
enddo
|
||||
|
||||
! rescale ONO angles
|
||||
ptrans_in(4)=deg2rad*off_in(4)
|
||||
ptrans_in(5)=deg2rad*off_in(5)
|
||||
ptrans_in(6)=deg2rad*off_in(6)
|
||||
! rescale umbrella
|
||||
ptrans_in(7)=off_in(7)*deg2rad
|
||||
|
||||
! compute symmetry coordinates
|
||||
|
||||
! A (breathing)
|
||||
a=(ptrans_in(1)+ptrans_in(2)+ptrans_in(3))/dsqrt(3.0d0)
|
||||
! ES
|
||||
call prim2emode(ptrans_in(1:3),xs,ys)
|
||||
! EB
|
||||
call prim2emode(ptrans_in(4:6),xb,yb)
|
||||
! B (umbrella)
|
||||
b=ptrans_in(7)
|
||||
|
||||
! overwrite input with output
|
||||
|
||||
pat_in(pat_index(1))=a ! 1
|
||||
pat_in(pat_index(2))=xs
|
||||
pat_in(pat_index(3))=ys
|
||||
pat_in(pat_index(4))=xb
|
||||
pat_in(pat_index(5))=yb
|
||||
pat_in(pat_index(6))=b
|
||||
! totally symmetric monomials
|
||||
pat_in(pat_index(7))=xs**2 + ys**2 ! 2
|
||||
pat_in(pat_index(8))=xb**2 + yb**2 ! 3
|
||||
pat_in(pat_index(9))=b**2 ! 9
|
||||
pat_in(pat_index(10))=xs*xb+ys*yb ! 4
|
||||
! S^3, B^3
|
||||
pat_in(pat_index(11))=xs*(xs**2-3*ys**2) ! 5
|
||||
pat_in(pat_index(12))=xb*(xb**2-3*yb**2) ! 6
|
||||
! S^2 B, S B^2
|
||||
pat_in(pat_index(13))=xb*(xs**2-ys**2) - 2*yb*xs*ys ! 7
|
||||
pat_in(pat_index(14))=xs*(xb**2-yb**2) - 2*ys*xb*yb ! 8
|
||||
|
||||
do k=11,14
|
||||
pat_in(pat_index(k))=tanh(0.1d0*pat_in(pat_index(k)))*10.0d0
|
||||
enddo
|
||||
|
||||
|
||||
|
||||
|
||||
end subroutine
|
||||
subroutine prim2emode(prim,ex,ey)
|
||||
implicit none
|
||||
! Takes a 2D-vector prim and returns the degenerate modes x and y
|
||||
! following our standard conventions.
|
||||
|
||||
real*8 prim(3),ex,ey
|
||||
|
||||
ex=(2.0d0*prim(1)-prim(2)-prim(3))/dsqrt(6.0d0)
|
||||
ey=(prim(2)-prim(3))/dsqrt(2.0d0)
|
||||
|
||||
end
|
||||
end module ctrans_mod
|
||||
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
! <subroutine for manipulating the input Data before the Fit
|
||||
subroutine data_transform(q,x1,x2,y,wt,p,npar,p_act)
|
||||
use dim_parameter,only : nstat,pst,ntot,qn,numdatpt,ndiab,ndata,sets
|
||||
use ctrans_mod, only: ctrans
|
||||
|
||||
use surface_mod, only: eval_surface
|
||||
use data_matrix
|
||||
! use david_ctrans_mod, only: ctrans_d
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer npar
|
||||
double precision q(qn,numdatpt),x1(qn,numdatpt),x2(qn,numdatpt)
|
||||
double precision y(ntot,numdatpt),wt(ntot,numdatpt)
|
||||
double precision p(npar),mat_x(ndiab,ndiab),mat_y(ndiab,ndiab)
|
||||
double precision v(ndiab,ndiab),E(nstat), energies(nstat)
|
||||
integer p_act(npar), pt
|
||||
logical dbg
|
||||
parameter (dbg=.false.)
|
||||
integer TYPES,BLK ! TYPE OF THE CALCULATION AND THE BLOCK IF TYEPE IS 3
|
||||
double precision U(ndiab,ndiab), U_ref(ndiab,ndiab) ! Transformation matrix
|
||||
integer:: i,j,k,l
|
||||
|
||||
|
||||
if (pst(2,28) .ne. 2) then
|
||||
|
||||
write(*,*) "Error in Paramater Keys, TYPE_CAL should be 2 parameter", pst(2,28)
|
||||
stop
|
||||
end if
|
||||
|
||||
TYPES = int(p(pst(1,28)))! TYPE OF THE CALCULATION
|
||||
BLK= int(p(pst(1,28)+1))! BLOCK IF TYPE IS 3
|
||||
write(*,*) "TYPE of calculation:",TYPES
|
||||
|
||||
pt=1
|
||||
|
||||
do i=1,sets ! loop over the number of sets
|
||||
do j=1,ndata(i) ! loop over the nbr of points in each sets
|
||||
! remember to increment pt at the end of the loop
|
||||
call ctrans(q(1:qn,pt),x1(:,pt),x2(:,pt)) ! transform the coordinate
|
||||
|
||||
! get the reference U matrix
|
||||
|
||||
!if (j .eq. 3) then
|
||||
! call eval_surface(E,V,U_ref,q(1:qn,pt))
|
||||
! call transform_U(U_ref)
|
||||
!endif
|
||||
|
||||
|
||||
|
||||
|
||||
!do pt=1,numdatpt
|
||||
!call ctrans(q(1:qn,pt),x1(:,pt),x2(:,pt))! ctrans the dipole cooordinate.
|
||||
write(7,'(I3,*(E17.8))') pt,x1(:,pt)
|
||||
|
||||
call eval_surface(E,V,U,q(1:qn,pt))
|
||||
|
||||
|
||||
! Transform U mmatrix
|
||||
call transform_U(U) ! Transform the U matrix
|
||||
! write U matrix on f16
|
||||
if (dbg) then
|
||||
!write(7,*) "U matrix at point", pt
|
||||
do k=1,ndiab
|
||||
write(50+i,'(2E17.8,5X,5E17.8)')x1(2:3,pt),(U(k,l),l=1,ndiab)
|
||||
enddo
|
||||
write(50+i,*) ""
|
||||
endif
|
||||
!call overlap(U_ref,U)
|
||||
call Y2mat(y(1:ntot,pt),mat_x,mat_y)
|
||||
mat_y=-mat_y
|
||||
if (ntot .ne. ndiab*(ndiab+1)) then
|
||||
energies(1:nstat)= y(31:ntot,pt)
|
||||
end if
|
||||
|
||||
if (TYPES .eq.1 ) then
|
||||
!call adiabatic_transform(mat_x,mat_y,U)
|
||||
! Trace of the potential
|
||||
call trace_mat(mat_x,mat_y,y(1:ntot,pt))
|
||||
else if (TYPES .eq.2) then
|
||||
! Eigenvalue decomposition of the potential
|
||||
call Eigen(mat_x,mat_y,y(1:ntot,pt))
|
||||
else if (TYPES .eq.3) then
|
||||
! Adiabatic transformation of the potential
|
||||
call adiabatic_transform(mat_x,mat_y,U)
|
||||
call block_diab(mat_x,mat_y,y(1:ntot,pt),BLK)
|
||||
|
||||
else if (TYPES .eq.4) then
|
||||
! Write the full upper diabatic matrix
|
||||
call adiabatic_transform(mat_x,mat_y,U)
|
||||
! and write the full diabatic matrix to y
|
||||
! This is the full diabatic matrix
|
||||
call Full_diab_upper(mat_x,mat_y,y(1:ntot,pt))
|
||||
else if (TYPES .eq.5) then
|
||||
call adiabatic_transform(mat_x,mat_y,U)
|
||||
call Transformation_mat(mat_x,E,y(1:ntot,pt))
|
||||
if (dbg) then
|
||||
do k=1,ndiab
|
||||
write(34,'(5f14.6)') (mat_x(k,l),l=1,ndiab)
|
||||
enddo
|
||||
write(34,*) ""
|
||||
endif
|
||||
!y(31:ntot,pt)=energies(1:nstat)
|
||||
else
|
||||
write(*,*) "Error in TYPE of calculationss",TYPES
|
||||
write(*,*) "the value:,", p(pst(1,28))
|
||||
stop
|
||||
end if
|
||||
pt=pt+1
|
||||
enddo ! j
|
||||
write(34,*) "#---- End of set ", i
|
||||
|
||||
write(7,*) "#---- End of set ", i
|
||||
|
||||
enddo ! i
|
||||
|
||||
!enddo
|
||||
|
||||
call weight(wt,y)
|
||||
end subroutine
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
module keys_mod
|
||||
implicit none
|
||||
contains
|
||||
!program gen_key
|
||||
! implicit none
|
||||
! call init_keys()
|
||||
!end program gen_key
|
||||
subroutine init_keys
|
||||
use io_parameters, only: key
|
||||
character(len=1) prefix(4)
|
||||
parameter (prefix=['N','P','A','S'])
|
||||
!character (len=20) key(4,25)
|
||||
integer,parameter:: np=34
|
||||
character(len=16) parname(np)
|
||||
integer i,j
|
||||
! Defining keys for potential
|
||||
! the electronic state of NO3 A2' E" E'
|
||||
! Naming convention
|
||||
! the keys for Lx and Ly
|
||||
! the coupling between A2' and A2"
|
||||
parname(1)='LXYVA2O1'
|
||||
parname(2)='LXYVE1O1'
|
||||
parname(3)='LXYVE2O1'
|
||||
parname(4)='LXYVA2O2'
|
||||
parname(5)='LXYVE1O2'
|
||||
parname(6)='LXYVE2O2'
|
||||
parname(7)='LXYVA2O3'
|
||||
parname(8)='LXYVE1O3'
|
||||
parname(9)='LXYVE2O3'
|
||||
! W & Z of E1
|
||||
parname(10)='LXYWZE1O0'
|
||||
parname(11)='LXYWZE1O1'
|
||||
parname(12)='LXYWZE1O2'
|
||||
parname(13)='LXYWZE1O3'
|
||||
parname(14)='LXYWZE2O0'
|
||||
parname(15)='LXYWZE2O1'
|
||||
parname(16)='LXYWZE2O2'
|
||||
parname(17)='LXYWZE2O3'
|
||||
|
||||
! WW and Z Pseudo between E1 and E2
|
||||
! p STANDS FOR PSEUDO JAHN-TELLER
|
||||
parname(18)='LXYPE1E2O0'
|
||||
parname(19)='LXYPE1E2O1'
|
||||
parname(20)='LXYPE1E2O2'
|
||||
! no order 3
|
||||
|
||||
! PSEUDO A2 & E1
|
||||
parname(21)='LXYPA2E1O0'
|
||||
parname(22)='LXYPA2E1O1'
|
||||
parname(23)='LXYPA2E1O2'
|
||||
|
||||
! Pseudo JAHN-TELLER BETWEEN A2 AND E1
|
||||
|
||||
parname(24)='LXYPA2E2O0'
|
||||
parname(25)='LXYPA2E2O1'
|
||||
parname(26)='LXYPA2E2O2'
|
||||
parname(27)='LXYPA2E2O3'
|
||||
|
||||
! keys for lz
|
||||
|
||||
parname(28)='LZWZE1O1'
|
||||
parname(29)='LZWZE1O2'
|
||||
parname(30)='LZWZE2O1'
|
||||
parname(31)='LZWZE2O2'
|
||||
parname(33)='LZPE1E2O0'
|
||||
parname(34)='LZPE1E2O1'
|
||||
parname(35)='LZPE1E2O2'
|
||||
parname(36)='LZPA2E1O1'
|
||||
parname(37)='LZPA2E2O2'
|
||||
parname(39)='LZPA2E2O1'
|
||||
|
||||
|
||||
parname(34)='TYPE_CAL'! TYPE OF THE CALCULATION WHETHER IT IS THE TRACE OR SOMETHING ELSE
|
||||
|
||||
do i=1,np
|
||||
do j=1,4
|
||||
key(j, i)=prefix(j)//trim(parname(i))//':' ! first 86 keys are the potential keys
|
||||
|
||||
enddo
|
||||
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
end module keys_mod
|
||||
|
|
@ -0,0 +1,358 @@
|
|||
module data_matrix
|
||||
use dim_parameter, only:ndiab,nstat,ntot,pst
|
||||
! use surface_mod, only: eval_surface
|
||||
contains
|
||||
! subroutine trace
|
||||
|
||||
subroutine trace_mat(mx,my,y)
|
||||
IMPLICIT NONE
|
||||
integer::i
|
||||
double precision,intent(inout):: y(:)
|
||||
double precision, intent(in):: mx(:,:),my(:,:)
|
||||
y=0.0d0
|
||||
!y(1)=mx(4,4)+mx(5,5)
|
||||
|
||||
do i=2,3
|
||||
y(1)=y(1)+mx(i,i)
|
||||
y(2)=y(2)+my(i,i)
|
||||
enddo
|
||||
|
||||
END SUBROUTINE trace_mat
|
||||
!! subroutine Ydata to matrix
|
||||
|
||||
subroutine Y2mat(Y,Mx,My)
|
||||
IMPLICIT NONE
|
||||
integer:: ii,i,j
|
||||
double precision, intent(in):: y(:)
|
||||
double precision,intent(out):: Mx(ndiab,ndiab),My(ndiab,ndiab)
|
||||
|
||||
!if (ndiab .ne. 4 ) then
|
||||
!write(*,*) " NDIAB should be equal to 4",NDIAB
|
||||
!write(*,*) "CHECK DATA_TRANSFORM TO MAKE IT ADAPTABLE"
|
||||
!stop
|
||||
!endif
|
||||
ii=1
|
||||
do i=1,ndiab
|
||||
do j=1,i
|
||||
! !mx
|
||||
|
||||
mx(i,j)=y(ii)
|
||||
! ! My
|
||||
if (ntot .eq. ndiab*(ndiab+1)) then
|
||||
my(i,j)=y( (ntot/2)+ii)
|
||||
else
|
||||
my(i,j)=y(15+ii)
|
||||
end if
|
||||
! remember to adjust here I added the energy
|
||||
!
|
||||
ii=ii+1
|
||||
enddo
|
||||
enddo
|
||||
call copy_2_upper(mx)
|
||||
call copy_2_upper(my)
|
||||
end subroutine
|
||||
|
||||
subroutine Full_diab_upper(mx,my,y)
|
||||
implicit none
|
||||
double precision,intent(inout) :: y(:)
|
||||
double precision, intent(in) :: mx(ndiab,ndiab), my(ndiab,ndiab)
|
||||
integer i,j,ii
|
||||
ii=1
|
||||
y=0.0d0
|
||||
|
||||
do i=1,ndiab
|
||||
do j=i,ndiab
|
||||
! mx
|
||||
y(ii) = mx(i,j)
|
||||
! my
|
||||
y((ntot/2)+ii) = my(i,j)
|
||||
! increment the index
|
||||
ii=ii+1
|
||||
enddo
|
||||
enddo
|
||||
end subroutine Full_diab_upper
|
||||
|
||||
|
||||
Subroutine adiabatic_transform(mx,my,U)
|
||||
implicit none
|
||||
double precision, intent(inout) :: mx(ndiab,ndiab), my(ndiab,ndiab)
|
||||
double precision, dimension(:,:), intent(inout) :: U
|
||||
double precision, dimension(ndiab,ndiab) :: temp1, temp2
|
||||
integer i, j
|
||||
|
||||
!call transform_U(U) ! Transform the U matrix
|
||||
|
||||
! Transform mx and my to adiabatic basis
|
||||
temp1 = matmul(mx, transpose(U))
|
||||
mx = matmul(U, temp1)
|
||||
temp2 = matmul(my, transpose(U))
|
||||
my = matmul(U, temp2)
|
||||
|
||||
end subroutine adiabatic_transform
|
||||
|
||||
! the eigenvalue of the dipole
|
||||
|
||||
SUBROUTINE Eigen(mx,my,Yres)
|
||||
implicit none
|
||||
double precision,dimension(:,:),intent(inout) :: mx,my
|
||||
double precision,dimension(:),intent(out) :: Yres
|
||||
double precision,dimension(ndiab) :: vx,vy
|
||||
double precision,dimension(size(mx,1),size(my,2)) :: temp
|
||||
! create a temorary matrix fo the eigenvctors
|
||||
|
||||
double precision, allocatable :: mux(:,:), muy(:,:)
|
||||
|
||||
! Lapak parameters
|
||||
integer :: n,info,i
|
||||
integer,parameter :: lwork = 100
|
||||
double precision :: work(lwork)
|
||||
! temporary
|
||||
double precision:: max_row
|
||||
Yres = 0.0d0
|
||||
Allocate(mux,source=mx)
|
||||
call DSYEV('V', 'U', size(mx,1), mux, size(mx,1), vx, work, lwork, info)
|
||||
mx=mux
|
||||
if (info /= 0) then
|
||||
write(*,*) "Error in Eigenvalue decomposition of mx info = ", info
|
||||
stop
|
||||
end if
|
||||
deallocate(mux)
|
||||
Allocate(muy,source=my)
|
||||
call DSYEV('V', 'U', size(my,1), muy, size(my,1), vy, work, lwork, info)
|
||||
if (info /= 0) then
|
||||
write(*,*) "Error in Eigenvalue decomposition of my info = ", info
|
||||
stop
|
||||
end if
|
||||
deallocate(muy)
|
||||
Yres(1:size(mx,1)) = vx(1:size(mx,1))
|
||||
do i=1,size(mx,1)
|
||||
max_row=maxloc(abs(mx(:,i)),1)
|
||||
!yres(size(mx,1)+i)=(mx(max_row,i))**2
|
||||
!yres(size(mx,1)+i)=real(max_row)
|
||||
enddo
|
||||
|
||||
!Yres(size(mx,1)+1:2*size(mx,1)) = vy(1:size(my,1))
|
||||
end subroutine
|
||||
|
||||
subroutine copy_2_upper(m)
|
||||
implicit none
|
||||
double precision, intent(inout) :: m(:,:)
|
||||
integer :: i,j
|
||||
! copy the lower part of the matrix to the upper part
|
||||
do i=1,size(m,1)
|
||||
do j=1,i-1
|
||||
m(j,i) = m(i,j)
|
||||
enddo
|
||||
enddo
|
||||
end subroutine copy_2_upper
|
||||
|
||||
subroutine coppy_2_low(m)
|
||||
implicit none
|
||||
double precision, intent(inout) :: m(:,:)
|
||||
integer :: i,j
|
||||
! copy the upper part of the matrix to the lower part
|
||||
do i=1,size(m,1)
|
||||
do j=i+1,size(m,2)
|
||||
m(j,i) = m(i,j)
|
||||
enddo
|
||||
enddo
|
||||
end subroutine coppy_2_low
|
||||
|
||||
|
||||
!1 SUBROUTNE BLOCKS
|
||||
!! EACH BLOCK OF dIABTIC MATRIX
|
||||
SUBROUTINE block_diab(mx,my,Y,block)
|
||||
implicit none
|
||||
double precision, intent(inout):: Y(:)
|
||||
double precision, intent(in) :: mx(ndiab,ndiab), my(ndiab,ndiab)
|
||||
integer, intent(in) :: block
|
||||
integer i,j,ii,nn
|
||||
y=0.0d0
|
||||
|
||||
select case (block)
|
||||
case(1)
|
||||
! fill the first E1 block state 2 &3
|
||||
y(1)=mx(2,2)
|
||||
y(2)=mx(2,3)
|
||||
!y(3)=mx(3,2)
|
||||
y(4)=mx(3,3)
|
||||
!y(5)=my(2,2)
|
||||
!y(6)=my(2,3)
|
||||
!y(7)=my(3,2)
|
||||
!y(8)=my(3,3)
|
||||
|
||||
case(2)
|
||||
! fill the second E2 block state 4 & 5
|
||||
y(1)=mx(4,4)
|
||||
y(2)=mx(4,5)
|
||||
!y(3)=mx(5,4)
|
||||
y(4)=mx(5,5)
|
||||
y(5)=my(4,4)
|
||||
y(6)=my(4,5)
|
||||
!y(7)=my(5,4)
|
||||
y(8)=my(5,5)
|
||||
case(3)
|
||||
! Filling the pseudo block E1 and E2
|
||||
y(1)=mx(2,4)
|
||||
y(2)=mx(2,5)
|
||||
y(3)=mx(3,4)
|
||||
y(4)=mx(3,5)
|
||||
y(5)=my(2,4)
|
||||
y(6)=my(2,5)
|
||||
y(7)=my(3,4)
|
||||
y(8)=my(3,5)
|
||||
case(4)
|
||||
! filling the block of A2 coupling with E1
|
||||
y(1)=mx(1,2)
|
||||
y(2)=mx(1,3)
|
||||
y(3)=mx(2,1)
|
||||
y(4)=mx(3,1)
|
||||
!y(5)=my(1,2)
|
||||
!y(6)=my(1,3)
|
||||
!y(7)=my(2,1)
|
||||
!y(8)=my(3,1)
|
||||
|
||||
|
||||
case(5)
|
||||
! couplinng A2 with E2
|
||||
Y(1)=mx(1,4)
|
||||
Y(2)=mx(1,5)
|
||||
!Y(3)=mx(4,1)
|
||||
!Y(4)=mx(5,1)
|
||||
Y(5)=my(1,4)
|
||||
Y(6)=my(1,5)
|
||||
!Y(7)=my(4,1)
|
||||
!Y(8)=my(5,1)
|
||||
case(6)
|
||||
! Filling A only
|
||||
y(1)=mx(1,1)
|
||||
y(5)=my(1,1)
|
||||
|
||||
case default
|
||||
write(*,*) "Error in block_diab subroutine, block not recognized"
|
||||
write(*,*) "The block is:", block
|
||||
stop
|
||||
end select
|
||||
end subroutine block_diab
|
||||
subroutine ident(A)
|
||||
implicit none
|
||||
integer i,j
|
||||
double precision,intent(inout)::A(:,:)
|
||||
do i=1,size(A,1)
|
||||
do j=1,size(A,1)
|
||||
if (i==j) then
|
||||
A(i,j)=1.0d0
|
||||
else
|
||||
A(i,j)=0.0d0
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
end subroutine
|
||||
|
||||
|
||||
! subroutine trasform the U matrix
|
||||
subroutine transform_U(U)
|
||||
implicit none
|
||||
double precision, intent(inout) :: U(ndiab,ndiab)
|
||||
|
||||
double precision :: U_ref(ndiab,ndiab), V(ndiab,ndiab), E(nstat)
|
||||
integer i,max_row
|
||||
double precision:: dot_prod,q_ref(9)
|
||||
logical,parameter:: dbg_sign =.true.
|
||||
|
||||
!q_ref= [1.000174,0.000000,0.000000,-0.503595,-0.872253,0.000000,-0.530624,0.919068,0.000000]
|
||||
!call eval_surface(E,V,U_ref,q_ref,p) ! get the reference transformation matrix
|
||||
do i=1,ndiab
|
||||
max_row = maxloc(abs(U(:,i)),1)
|
||||
if (U(max_row,i) .lt. 0) then
|
||||
U(:,i) = -1*U(:,i)
|
||||
endif
|
||||
enddo
|
||||
!dot_prod=dot_product(U(2:3,4),U_ref(2:3,4))
|
||||
!if (dot_prod .lt. 0.0d0) then
|
||||
! U(:,4) = -1.0d0*U(:,4)
|
||||
!endif
|
||||
|
||||
|
||||
end subroutine transform_U
|
||||
|
||||
subroutine write_type_calc(p,id_write)
|
||||
! Subroutine to write the type of calculation
|
||||
implicit none
|
||||
double precision, intent(in) :: p(:)
|
||||
integer, intent(in) :: id_write
|
||||
integer :: type_calc, blk
|
||||
type_calc = int(p(pst(1,28)))
|
||||
blk = int(p(pst(1,28)+1))
|
||||
|
||||
if (type_calc ==1) then
|
||||
write(id_write,*) "Type of calculation: TRACE"
|
||||
else if (type_calc ==2) then
|
||||
write(id_write,*) "Type of calculation: EIGENVALUE"
|
||||
else if (type_calc ==3) then
|
||||
IF (blk == 1) then
|
||||
write(id_write,*) "Type of calculation: E1 BLOCK"
|
||||
ELSE IF (BLK ==2) THEN
|
||||
write(id_write,*) "Type of calculation: E2 BLOCK"
|
||||
ELSE IF (BLK ==3) THEN
|
||||
write(id_write,*) "Type of calculation: Pseudo E1 and E2 BLOCK"
|
||||
ELSE IF (BLK ==4) THEN
|
||||
write(id_write,*) "Type of calculation: COUPLING A2 with E1 BLOCK"
|
||||
ELSE IF (BLK ==5) THEN
|
||||
write(id_write,*) "Type of calculation: COUPLING A2 with E2 BLOCK"
|
||||
ELSE IF (BLK ==6) THEN
|
||||
write(id_write,*) "Type of calculation: A2 ONLY"
|
||||
ELSE
|
||||
write(id_write,*) "Type of calculation: Diabatic transformation with unknown block size", blk
|
||||
END IF
|
||||
|
||||
else if (type_calc ==4) then
|
||||
write(id_write,*) "Type of calculation: Full Diabatic Matrix"
|
||||
else if (type_calc ==5) then
|
||||
write(id_write,*) "Type of calculation: Transformation matrix U"
|
||||
else
|
||||
write(id_write,*) "Error in type of calculation:", type_calc
|
||||
stop
|
||||
end if
|
||||
END SUBROUTINE write_type_calc
|
||||
|
||||
!! subroutine for writting the transformtion matrix U
|
||||
subroutine Transformation_mat(temp,v,y)
|
||||
implicit none
|
||||
double precision, intent(in) :: temp(ndiab,ndiab), v(:)
|
||||
double precision, intent(inout) :: y(:)
|
||||
double precision :: U(ndiab,ndiab )
|
||||
integer i,j,ii
|
||||
U(1:ndiab,1:ndiab) = temp(1:ndiab,1:ndiab)
|
||||
!call transform_U(U,P)
|
||||
|
||||
y=0.0d0
|
||||
!y(1:4) = v(1:4) ! copy the first 4 elements of v to y
|
||||
ii=1
|
||||
do i=1,ndiab
|
||||
do j=1,ndiab
|
||||
y(ii) = U(i,j)
|
||||
ii=ii+1
|
||||
enddo
|
||||
enddo
|
||||
y(ii:30)=v(:)
|
||||
end subroutine
|
||||
! compute the overlap between U matrix
|
||||
subroutine overlap(U_ref,U)
|
||||
implicit none
|
||||
double precision, intent(in):: U_ref(ndiab,ndiab)
|
||||
double precision, intent(inout):: U(ndiab,ndiab)
|
||||
double precision:: over
|
||||
integer i
|
||||
do i=1,ndiab
|
||||
|
||||
over=dot_product(U_ref(:,i),U(:,i))
|
||||
if (over .lt. 0.0d0 ) then
|
||||
U(:,i)=-U(:,i)
|
||||
endif
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
|
||||
end module
|
||||
|
|
@ -0,0 +1,523 @@
|
|||
! Author: jnshuti
|
||||
! Created: 2025-10-03 14:09:49
|
||||
! Last modified: 2025-10-03 14:10:10 jnshuti
|
||||
! model for L-matrix of NO3 radical
|
||||
|
||||
module diab_mod:
|
||||
use accuracy_constants, only: dp, idp
|
||||
use dim_parameter, only: ndiab, nstat, ntot,npar,qn,pst
|
||||
implicit none
|
||||
contains
|
||||
|
||||
subroutine Lx_diab(E,q,t,p)
|
||||
implicit none
|
||||
real(dp),dimension(ndiab,ndiab), intent(out):: E
|
||||
real(dp),dimension(:),intent(in):: q,t
|
||||
real(dp),dimension(npar),intent(in):: p
|
||||
real(dp):: xs,ys,xb,yb,a,b
|
||||
real(dp):: v3_vec(8)
|
||||
integer(idp):: i,j,id
|
||||
|
||||
! check the dimension of the matrix
|
||||
if (size(E,1) .ne. ndiab) then
|
||||
write(*,*) " Error in Lx_diab: wrong dimension of L matrix ", size(E,1)
|
||||
stop
|
||||
endif
|
||||
|
||||
! rewrite the coordinate array q into symmetry adapted coordinates
|
||||
call rewrite_coord(q,a,xs,ys,xb,yb,b,1)
|
||||
|
||||
e(1,1)=e(1,1)+p(pst(1,id))*xs+p(pst(1,id)+1)*xb ! 2 param
|
||||
id=id+1 ! 2
|
||||
e(2,2)=e(2,2)+p(pst(1,id))*xs+p(pst(1,id)+1)*xb ! 2 p
|
||||
e(3,3)=e(3,3)+p(pst(1,id))*xs+p(pst(1,id)+1)*xb
|
||||
id =id+1 ! 3
|
||||
e(4,4)=e(4,4)+p(pst(1,id))*xs+p(pst(1,id)+1)*xb ! 2 p
|
||||
e(5,5)=e(5,5)+p(pst(1,id))*xs+p(pst(1,id)+1)*xb
|
||||
|
||||
|
||||
id=id+1 ! 4
|
||||
! order 2
|
||||
e(1,1)=e(1,1)+p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) & ! 5 p
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb)
|
||||
id =id+1 ! 5
|
||||
e(2,2)=e(2,2)+p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb)
|
||||
e(3,3)=e(3,3)+p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb)
|
||||
id =id+1 ! 6
|
||||
e(4,4)=e(4,4)+p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb)
|
||||
e(5,5)=e(5,5)+p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb)
|
||||
! order 3
|
||||
id=id+1 ! 7
|
||||
e(1,1)=e(1,1)+p(pst(1,id))*xs*ss+p(pst(1,id)+1)*xb *sb ! 2 param
|
||||
id=id+1 ! 8
|
||||
e(2,2)=e(2,2)+p(pst(1,id))*xs*ss+p(pst(1,id)+1)*xb *sb ! 2 p
|
||||
e(3,3)=e(3,3)+p(pst(1,id))*xs*ss+p(pst(1,id)+1)*xb*sb
|
||||
id =id+1 ! 9
|
||||
e(4,4)=e(4,4)+p(pst(1,id))*xs*ss+p(pst(1,id)+1)*xb*sb ! 2 p
|
||||
e(5,5)=e(5,5)+p(pst(1,id))*xs*ss+p(pst(1,id)+1)*xb*sb
|
||||
|
||||
|
||||
! W and Z term of E1
|
||||
! order 0
|
||||
id=id+1 ! 10
|
||||
e(2,2)=e(2,2)+p(pst(1,id))
|
||||
e(3,3)=e(3,3)-p(pst(1,id))
|
||||
!e(2,3)=e(2,3)
|
||||
|
||||
! order 1
|
||||
id=id+1 ! 11 ! 2 param
|
||||
e(2,2)=e(2,2)+ p(pst(1,id))*xs+p(pst(1,id)+1)*xb
|
||||
e(3,3)=e(3,3)- (p(pst(1,id))*xs+p(pst(1,id)+1)*xb)
|
||||
e(2,3)=e(2,3)- p(pst(1,id))*ys -p(pst(1,id)+1)*yb
|
||||
! order 2
|
||||
id=id+1 ! 12 ! 3p
|
||||
do i=1,3
|
||||
e(2,2)=e(2,2)+p(pst(1,id)+(i-1))*v2(i)
|
||||
e(3,3)=e(3,3)-p(pst(1,id)+(i-1))*v2(i)
|
||||
e(2,3)=e(2,3)+ p(pst(1,id)+(i-1))*v2(i+3)
|
||||
enddo
|
||||
! order 3
|
||||
id=id+1 ! 13 ! 8 param
|
||||
do i=1,4
|
||||
e(2,2)=e(2,2)+(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
e(3,3)=e(3,3)-(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
e(2,3)=e(2,3)+(-p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
enddo
|
||||
|
||||
! try the testing of higher order terms
|
||||
!e(2,3)=e(2,3)- p(pst(1,id))*ys*ss +p(pst(1,id)+1)*ss*2*xs*ys
|
||||
|
||||
|
||||
|
||||
|
||||
! W and Z for E2
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
id=id+1 ! 14
|
||||
e(4,4)=e(4,4)+p(pst(1,id))
|
||||
e(5,5)=e(5,5)-p(pst(1,id))
|
||||
e(4,5)=e(4,5)
|
||||
|
||||
! order 1
|
||||
id=id+1 ! 2 param 15
|
||||
e(4,4)=e(4,4)+ p(pst(1,id))*xs+p(pst(1,id)+1)*xb
|
||||
e(5,5)=e(5,5)- (p(pst(1,id))*xs+p(pst(1,id)+1)*xb)
|
||||
e(4,5)=e(4,5)- p(pst(1,id))*ys-p(pst(1,id)+1)*yb
|
||||
! order 2
|
||||
id=id+1 ! 16 ! 3p
|
||||
do i=1,3
|
||||
e(4,4)=e(4,4)+p(pst(1,id)+(i-1))*v2(i)
|
||||
e(5,5)=e(5,5)-p(pst(1,id)+(i-1))*v2(i)
|
||||
e(4,5)=e(4,5)+ p(pst(1,id)+(i-1))*v2(i+3)
|
||||
enddo
|
||||
|
||||
! order 3
|
||||
id=id+1 ! 17 ! 8 param
|
||||
do i=1,4
|
||||
e(4,4)=e(4,4)+(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
e(5,5)=e(5,5)-(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
e(4,5)=e(4,5)+(-p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
enddo
|
||||
|
||||
! make the dipole E = b* E
|
||||
|
||||
e = b * e
|
||||
|
||||
! E1 X E2
|
||||
! WW and ZZ
|
||||
|
||||
|
||||
id =id+1 ! 18
|
||||
e(2,4)=e(2,4)+p(pst(1,id))*b
|
||||
e(3,5)=e(3,5)-p(pst(1,id))*b
|
||||
|
||||
! ORDER 1
|
||||
id=id+1 ! 19 ! 6 parama
|
||||
e(2,4)=e(2,4)+b*((p(pst(1,id))+p(pst(1,id)+1)+p(pst(1,id)+2))*xs+(p(pst(1,id)+3)+p(pst(1,id)+4)+p(pst(1,id)+5))*xb)
|
||||
e(3,5)=e(3,5)+b*((p(pst(1,id))+p(pst(1,id)+1)-p(pst(1,id)+2))*xs+(p(pst(1,id)+3)+p(pst(1,id)+4)-p(pst(1,id)+5))*xb)
|
||||
e(2,5)=e(2,5)+b*((p(pst(1,id))-p(pst(1,id)+1)-p(pst(1,id)+2))*ys+(p(pst(1,id)+3)-p(pst(1,id)+4)-p(pst(1,id)+5))*yb)
|
||||
e(3,4)=e(3,4)+b*((-p(pst(1,id))+p(pst(1,id)+1)-p(pst(1,id)+2))*ys+(-p(pst(1,id)+3)+p(pst(1,id)+4)-p(pst(1,id)+5))*yb)
|
||||
! order 2
|
||||
id=id+1 ! 20
|
||||
|
||||
do i=1,3 ! 9 param
|
||||
e(2,4)=e(2,4)+b*(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+2))+p(pst(1,id)+(i+5)))*v2(i)
|
||||
e(3,5)=e(3,5)+b*(-p(pst(1,id)+(i-1))+p(pst(1,id)+(i+2))+p(pst(1,id)+(i+5)))*v2(i)
|
||||
e(2,5)=e(2,5)+b*(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+2))-p(pst(1,id)+(i+5)))*v2(i+3)
|
||||
e(3,4)=e(3,4)+b*(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+2))+p(pst(1,id)+(i+5)))*v2(i+3)
|
||||
enddo
|
||||
|
||||
! pseudo A2 & E1
|
||||
! ##################################################
|
||||
!###################################################
|
||||
! order 0
|
||||
id=id+1 ! 1 param ! 21
|
||||
|
||||
e(1,3)=e(1,3)+b*(p(pst(1,id)))
|
||||
|
||||
! order 1
|
||||
id = id +1 ! 22
|
||||
e(1,2)=e(1,2)-b*(p(pst(1,id))*ys + p(pst(1,id)+1)*yb)
|
||||
e(1,3)=e(1,3)+b*(p(pst(1,id))*xs + p(pst(1,id)+1)*xb)
|
||||
|
||||
! order 2
|
||||
id=id+1 ! 23
|
||||
|
||||
e(1,2)=e(1,2)+b*(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
e(1,3)=e(1,3)+b*(p(pst(1,id))*(xs**2-ys**2) + p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb))
|
||||
|
||||
! COUPLING OF A2 WITH E2
|
||||
|
||||
!##########################################################################################################
|
||||
|
||||
! order 0
|
||||
id =id+1 !24
|
||||
e(1,5)=e(1,5)+p(pst(1,id))
|
||||
|
||||
! order 1
|
||||
id = id +1 ! 25
|
||||
e(1,4)=e(1,4)-(p(pst(1,id))*ys + p(pst(1,id)+1)*yb)
|
||||
e(1,5)=e(1,5)+(p(pst(1,id))*xs + p(pst(1,id)+1)*xb)
|
||||
|
||||
! order 2
|
||||
id=id+1 ! 26
|
||||
|
||||
e(1,4)=e(1,4)+p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys)
|
||||
e(1,5)=e(1,5)+p(pst(1,id))*(xs**2-ys**2) + p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb)
|
||||
|
||||
! order 3
|
||||
id=id+1 ! 27 ! 8 param
|
||||
do i=1,4
|
||||
e(1,4)=e(1,4)+(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
e(1,5)=e(1,5)+(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
|
||||
enddo
|
||||
e(1,4:5) = b* e(1,4:5)
|
||||
|
||||
|
||||
call copy_2_lower_triangle(e)
|
||||
end subroutine Lx_diab
|
||||
|
||||
! Ly matrix
|
||||
subroutine Ly_diab(e,q,t,p)
|
||||
implicit none
|
||||
real(dp),dimension(ndiab,ndiab), intent(out):: e
|
||||
real(dp),dimension(:),intent(in):: q,t
|
||||
real(dp),dimension(npar),intent(in):: p
|
||||
real(dp):: xs,ys,xb,yb,a,b
|
||||
real(dp):: v3_vec(8)
|
||||
integer(idp):: i,j,id
|
||||
|
||||
! check the dimension of the matrix
|
||||
if (size(e,1) .ne. ndiab) then
|
||||
write(*,*) " Error in Ly_diab: wrong dimension of L matrix ", size(e,1)
|
||||
stop
|
||||
endif
|
||||
|
||||
! rewrite the coordinate array q into symmetry adapted coordinates
|
||||
call rewrite_coord(q,a,xs,ys,xb,yb,b,1)
|
||||
e=0.0d0
|
||||
ss=xs**2+ys**2 ! totaly symmetric term
|
||||
sb=xb**2+yb**2
|
||||
|
||||
v3( 1) = xs*(xs**2-3*ys**2)
|
||||
v3( 2) = xb*(xb**2-3*yb**2)
|
||||
v3( 3) = xb*(xs**2-ys**2) - 2*yb*xs*ys
|
||||
v3( 4) = xs*(xb**2-yb**2) - 2*ys*xb*yb
|
||||
v3( 5) = ys*(3*xs**2-ys**2)
|
||||
v3( 6) = yb*(3*xb**2-yb**2)
|
||||
v3( 7) = yb*(xs**2-ys**2)+2*xb*xs*ys
|
||||
v3( 8) = ys*(xb**2-yb**2)+2*xs*xb*yb
|
||||
|
||||
e=0.0d0
|
||||
! V-term
|
||||
|
||||
id=1 ! 1
|
||||
! order 1
|
||||
e(1,1)=e(1,1)+p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
id=id+1 ! 2
|
||||
e(2,2)=e(2,2)+p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
e(3,3)=e(3,3)+p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
id =id+1 ! 3
|
||||
e(4,4)=e(4,4)+p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
e(5,5)=e(5,5)+p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
|
||||
id=id+1 ! 4b*(
|
||||
e(1,1)=e(1,1)-(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
id =id+1 ! 5
|
||||
e(2,2)=e(2,2)-(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
e(3,3)=e(3,3)-(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
id=id+1 ! 6
|
||||
e(4,4)=e(4,4)-(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
e(5,5)=e(5,5)-(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
! order 3
|
||||
id=id+1 ! 7
|
||||
|
||||
e(1,1)=e(1,1)+p(pst(1,id))*ys*ss + p(pst(1,id)+1)*yb*sb
|
||||
id=id+1 ! 2
|
||||
e(2,2)=e(2,2)+p(pst(1,id))*ys*ss + p(pst(1,id)+1)*yb*sb
|
||||
e(3,3)=e(3,3)+p(pst(1,id))*ys*ss + p(pst(1,id)+1)*yb*sb
|
||||
id =id+1 ! 3
|
||||
e(4,4)=e(4,4)+p(pst(1,id))*ys*ss + p(pst(1,id)+1)*yb*sb
|
||||
e(5,5)=e(5,5)+p(pst(1,id))*ys*ss + p(pst(1,id)+1)*yb*sb
|
||||
|
||||
! W and Z of E1
|
||||
! order 0
|
||||
id=id+1 ! 10
|
||||
e(2,3)=e(2,3)+p(pst(1,id))
|
||||
! order 1
|
||||
id=id+1 !
|
||||
e(2,2)=e(2,2)-p(pst(1,id))*ys -p(pst(1,id)+1)*yb
|
||||
e(3,3)=e(3,3)+p(pst(1,id))*ys+ p(pst(1,id)+1)*yb
|
||||
e(2,3)=e(2,3)-p(pst(1,id))*xs -p(pst(1,id)+1)*xb
|
||||
! order 2
|
||||
id=id+1 ! 12
|
||||
do i=1,3
|
||||
e(2,2)=e(2,2)+p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(3,3)=e(3,3)-p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(2,3)=e(2,3)-p(pst(1,id)+(i-1))*v2(i)
|
||||
enddo
|
||||
|
||||
id=id+1 ! 8
|
||||
do i=1,4
|
||||
e(2,2)=e(2,2)+(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
e(3,3)=e(3,3)-(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
e(2,3)=e(2,3)+(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
enddo
|
||||
|
||||
|
||||
!! W and Z of E2
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
! order 0
|
||||
id=id+1 ! 14
|
||||
e(4,5)=e(4,5)+p(pst(1,id))
|
||||
! order 1
|
||||
id=id+1 ! 15
|
||||
e(4,4)=e(4,4)-p(pst(1,id))*ys -p(pst(1,id)+1)*yb
|
||||
e(5,5)=e(5,5)+p(pst(1,id))*ys+ p(pst(1,id)+1)*yb
|
||||
e(4,5)=e(4,5)-p(pst(1,id))*xs -p(pst(1,id)+1)*xb
|
||||
! order 2
|
||||
id=id+1 ! 16
|
||||
do i=1,3
|
||||
e(4,4)=e(4,4)+p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(5,5)=e(5,5)-p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(4,5)=e(4,5)-p(pst(1,id)+(i-1))*v2(i)
|
||||
enddo
|
||||
|
||||
id=id+1 ! 17
|
||||
do i=1,4
|
||||
e(4,4)=e(4,4)+(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
e(5,5)=e(5,5)-(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+3)))*v3(i+4)
|
||||
e(4,5)=e(4,5)+(p(pst(1,id)+(i-1))+p(pst(1,id)+(i+3)))*v3(i)
|
||||
enddo
|
||||
! PSEUDO JAHN-TELLER E1 AND E2
|
||||
|
||||
e = b* e
|
||||
|
||||
!ORDER 0
|
||||
id=id+1 ! 18
|
||||
|
||||
e(2,5)=e(2,5)+p(pst(1,id))
|
||||
e(3,4)=e(3,4)+p(pst(1,id))
|
||||
! order 1
|
||||
|
||||
id=id+1
|
||||
e(2,4)=e(2,4)+((p(pst(1,id))+p(pst(1,id)+1)-p(pst(1,id)+2))*ys+(p(pst(1,id)+3)+p(pst(1,id)+4)-p(pst(1,id)+5))*yb)
|
||||
e(3,5)=e(3,5)+((p(pst(1,id))+p(pst(1,id)+1)+p(pst(1,id)+2))*ys+(p(pst(1,id)+3)+p(pst(1,id)+4)+p(pst(1,id)+5))*yb)
|
||||
e(2,5)=e(2,5)+((-p(pst(1,id))+p(pst(1,id)+1)-p(pst(1,id)+2))*xs+(-p(pst(1,id)+3)+p(pst(1,id)+4)-p(pst(1,id)+5))*xb)
|
||||
e(3,4)=e(3,4)+((p(pst(1,id))-p(pst(1,id)+1)-p(pst(1,id)+2))*xs+(+p(pst(1,id)+3)-p(pst(1,id)+4)-p(pst(1,id)+5))*xb)
|
||||
|
||||
! order 2
|
||||
id=id+1
|
||||
|
||||
e(2,4)=e(2,4)+(p(pst(1,id)+(i-1))-p(pst(1,id)+(i+2))-p(pst(1,id)+(i+5)))*v2(i+3)
|
||||
e(3,5)=e(3,5)+(-p(pst(1,id)+(i-1))-p(pst(1,id)+(i+2))-p(pst(1,id)+(i+5)))*v2(i+3)
|
||||
e(2,5)=e(2,5)+(-p(pst(1,id)+(i-1))+p(pst(1,id)+(i+2))-p(pst(1,id)+(i+5)))*v2(i)
|
||||
e(3,4)=e(3,4)+(-p(pst(1,id)+(i-1))-p(pst(1,id)+(i+2))+p(pst(1,id)+(i+5)))*v2(i)
|
||||
|
||||
! no order 3
|
||||
!!!!!!!!!!!!!!!!
|
||||
|
||||
! the coupling A2 & E1
|
||||
! #####################
|
||||
! order 0
|
||||
|
||||
id=id+1
|
||||
e(1,2)=e(1,2)+(p(pst(1,id)))
|
||||
! order 1
|
||||
|
||||
id=id+1
|
||||
e(1,2)=e(1,2)-(p(pst(1,id))*xs + p(pst(1,id)+1)*xb)
|
||||
e(1,3)=e(1,3)-(p(pst(1,id))*ys + p(pst(1,id)+1)*yb)
|
||||
|
||||
! order 2
|
||||
id=id+1
|
||||
e(1,2)=e(1,2)-(p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb))
|
||||
e(1,3)=e(1,3)+(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+ &
|
||||
+p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
|
||||
! COUPLING OF A2 WITH E2
|
||||
!#######################################################################################
|
||||
!###############################################################################
|
||||
! order 0
|
||||
|
||||
id = id+1
|
||||
e(1,4)=e(1,4)+p(pst(1,id))
|
||||
! order 1
|
||||
|
||||
id=id+1
|
||||
e(1,4)=e(1,4)-(p(pst(1,id))*xs + p(pst(1,id)+1)*xb)
|
||||
e(1,5)=e(1,5)-(p(pst(1,id))*ys + p(pst(1,id)+1)*yb)
|
||||
|
||||
! order 2
|
||||
id=id+1
|
||||
e(1,4)=e(1,4)-(p(pst(1,id))*(xs**2-ys**2)+p(pst(1,id)+1)*(xb**2-yb**2) &
|
||||
+p(pst(1,id)+2)*(xs*xb-ys*yb))
|
||||
e(1,5)=e(1,5)+(p(pst(1,id))*(2*xs*ys)+p(pst(1,id)+1)*(2*xb*yb)+ &
|
||||
p(pst(1,id)+2)*(xs*yb+xb*ys))
|
||||
|
||||
!write(*,*)'idy=',id
|
||||
e(1:4,5) = b * e(1:4,5)
|
||||
|
||||
|
||||
call copy_2_lower_triangle(e)
|
||||
|
||||
end subroutine Ly_diab
|
||||
! Lz matrix
|
||||
subroutine Lz_diab(e,q,t,p)
|
||||
implicit none
|
||||
real(dp),dimension(ndiab,ndiab), intent(out):: e
|
||||
real(dp),dimension(:),intent(in):: q,t
|
||||
real(dp),dimension(npar),intent(in):: p
|
||||
real(dp):: xs,ys,xb,yb,a,b
|
||||
real(dp):: v3_vec(8)
|
||||
integer(idp):: i,j
|
||||
|
||||
! check the dimension of the matrix
|
||||
if (size(e,1) .ne. ndiab) then
|
||||
write(*,*) " Error in Lz_diab: wrong dimension of e matrix ", size(e,1)
|
||||
stop
|
||||
endif
|
||||
call rewrite_coord(q,a,xs,xb,yb,b,1)
|
||||
e = 0.0_dp
|
||||
! id for lz
|
||||
id = ! has to be
|
||||
! the diagonal terms
|
||||
|
||||
! the v-term is 0th order and 3rd order.
|
||||
! There is no zeroth order for diagonal
|
||||
|
||||
! w and z of E''
|
||||
! order 1
|
||||
id =id +1
|
||||
e(2,2) = e(2,2) + p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
e(3,3) = e(3,3) - p(pst(1,id))*ys - p(pst(1,id)+1)*yb
|
||||
e(2,3) = e(2,3) - p(pst(1,id))*xs -p(pst(1,id)+1)*xb
|
||||
|
||||
! order 2
|
||||
id = id +1
|
||||
do i =1,3
|
||||
e(2,2) = e(2,2) + p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(3,3) = e(3,3) - p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(2,3) = e(2,3) + p(pst(1,id)+(i-1))*v2(i)
|
||||
enddo
|
||||
|
||||
! W and Z of E'
|
||||
! order 1
|
||||
|
||||
id = id +1
|
||||
e(4,4) = e(4,4) + p(pst(1,id))*ys + p(pst(1,id)+1)*yb
|
||||
e(5,5) = e(5,5) - p(pst(1,id))*ys - p(pst(1,id)+1)*yb
|
||||
e(4,5) = e(4,5) - p(pst(1,id))*xs -p(pst(1,id)+1)*xb
|
||||
|
||||
! order 2
|
||||
id = id +1
|
||||
do i =1,3
|
||||
e(4,4) = e(4,4) + p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(5,5) = e(5,5) - p(pst(1,id)+(i-1))*v2(i+3)
|
||||
e(4,5) = e(4,5) + p(pst(1,id)+(i-1))*v2(i)
|
||||
enddo
|
||||
! the coupling
|
||||
! Pseudo of E' and E''
|
||||
! it must have odd power of b
|
||||
|
||||
id = id +1
|
||||
! order 0
|
||||
e(2,4) = e(2,4)
|
||||
e(3,5) = e(3,5)
|
||||
e(2,5) = e(2,5) + b*(p(pst(1,id)))
|
||||
e(3,4) = e(3,4) - b*(p(pst(1,id)))
|
||||
|
||||
! order 1
|
||||
id = id +1
|
||||
e(2,4) = e(2,4) + b*(p(pst(1,id))*ys + p(pst(1,id)+1)*yb)
|
||||
e(3,5) = e(3,5) + b*(p(pst(1,id))*ys + p(pst(1,id)+1)*yb)
|
||||
e(2,5) = e(2,5) - b*(p(pst(1,id))*xs + p(pst(1,id)+1)*xb)
|
||||
e(3,4) = e(3,4) + b*(p(pst(1,id))*xs + p(pst(1,id)+1)*xb)
|
||||
! order 2
|
||||
id = id +1
|
||||
do i=1,3
|
||||
e(2,4) = e(2,4) + b*(p(pst(1,id)+(i-1)))*v2(i+3)
|
||||
e(3,5) = e(3,5) + b*(p(pst(1,id)+(i-1)))*v2(i+3)
|
||||
e(2,5) = e(2,5) + b*(p(pst(1,id)+(i-1)))*v2(i)
|
||||
e(3,4) = e(3,4) - b*(p(pst(1,id)+(i-1)))*v2(i)
|
||||
enddo
|
||||
! no third order
|
||||
|
||||
! the coupling between A2' and E''
|
||||
! order 1
|
||||
id = id +1
|
||||
e(1,2) = e(1,2) + b*(p(pst(1,id))*xs + p(pst(1,id)*xb))
|
||||
e(1,3) = e(1,3) - b*(p(pst(1,id))*ys + p(pst(1,id)*yb))
|
||||
|
||||
id = id +1
|
||||
! order 2
|
||||
do i=1,3
|
||||
e(1,2) = e(1,2) + b*(p(pst(1,id)+(i-1)))*v2(i)
|
||||
e(1,3) = e(1,3) + b*(p(pst(1,id)+(i-1)))*v2(i+3)
|
||||
enddo
|
||||
|
||||
! the coupling of A2' and E'
|
||||
|
||||
! order 1
|
||||
id = id +1
|
||||
e(1,2) = e(1,2) + (p(pst(1,id))*xs + p(pst(1,id)*xb))
|
||||
e(1,3) = e(1,3) - (p(pst(1,id))*ys + p(pst(1,id)*yb))
|
||||
|
||||
id = id +1
|
||||
! order 2
|
||||
do i=1,3
|
||||
e(1,2) = e(1,2) + (p(pst(1,id)+(i-1)))*v2(i)
|
||||
e(1,3) = e(1,3) + (p(pst(1,id)+(i-1)))*v2(i+3)
|
||||
enddo
|
||||
call copy_2_lower_triangle(e)
|
||||
|
||||
|
||||
|
||||
end subroutine Lz_diab
|
||||
|
||||
subroutine rewrite_coord(q,a,xs,ys,xb,yb,b,start)
|
||||
implicit none
|
||||
real(dp),dimension(:),intent(in):: q
|
||||
real(dp),intent(out):: xs,ys,xb,yb,a,b
|
||||
integer(idp),intent(in):: start
|
||||
integer(idp):: i,j
|
||||
|
||||
a= q(start)
|
||||
xs = q(start+1)
|
||||
ys = q(start+2)
|
||||
xb = q(start+3)
|
||||
yb = q(start+4)
|
||||
b = q(start+5)
|
||||
end subroutine rewrite_coord
|
||||
|
||||
end module diab_mod
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
!**** Declarations
|
||||
|
||||
real*8 pi
|
||||
real*8 hart2eV, eV2hart
|
||||
real*8 hart2icm, icm2hart
|
||||
real*8 eV2icm, icm2eV
|
||||
real*8 deg2rad, rad2deg
|
||||
integer maxnin,maxnout
|
||||
|
||||
!**********************************************************
|
||||
!**** Parameters
|
||||
!*** maxnin: max. number of neurons in input layer
|
||||
!*** maxnout: max. number of neurons in output layer
|
||||
|
||||
parameter (maxnin=14,maxnout=15)
|
||||
|
||||
!**********************************************************
|
||||
!**** Numerical Parameters
|
||||
!*** infty: largest possible double precision real value.
|
||||
!*** iinfty: largest possible integer value.
|
||||
|
||||
! 3.14159265358979323846264338327950...
|
||||
parameter (pi=3.1415926536D0)
|
||||
|
||||
!**********************************************************
|
||||
!**** Unit Conversion Parameters
|
||||
!*** X2Y: convert from X to Y.
|
||||
!***
|
||||
!*** hart: hartree
|
||||
!*** eV: electron volt
|
||||
!*** icm: inverse centimeters (h*c/cm)
|
||||
!****
|
||||
!*** deg: degree
|
||||
!*** rad: radians
|
||||
|
||||
parameter (hart2icm=219474.69d0)
|
||||
parameter (hart2eV=27.211385d0)
|
||||
parameter (eV2icm=hart2icm/hart2eV)
|
||||
parameter (icm2hart=1.0d0/hart2icm)
|
||||
parameter (eV2hart=1.0d0/hart2eV)
|
||||
parameter (icm2eV=1.0d0/eV2icm)
|
||||
parameter (deg2rad=pi/180.0d0)
|
||||
parameter (rad2deg=1.0d0/deg2rad)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
module surface_mod
|
||||
use accuracy_constants, only: dp
|
||||
implicit none
|
||||
private
|
||||
public eval_surface
|
||||
contains
|
||||
subroutine eval_surface(e, w, u, x1)
|
||||
|
||||
use accuracy_constants, only: dp, idp
|
||||
use dim_parameter, only: ndiab
|
||||
implicit none
|
||||
real(dp), dimension(:, :), intent(out) :: w, u
|
||||
real(dp), dimension(:), intent(out) :: e
|
||||
real(dp), dimension(:), intent(in) :: x1
|
||||
real(dp), allocatable, dimension(:, :) :: Mat
|
||||
|
||||
! debug parameter
|
||||
|
||||
logical, parameter:: dbg=.false.
|
||||
integer(kind=idp):: i,j
|
||||
! lapack variables
|
||||
integer(kind=idp), parameter :: lwork = 1000
|
||||
real(kind=dp) work(lwork)
|
||||
integer(kind=idp) info
|
||||
|
||||
|
||||
!write(*,*)"# Calling the potential routine "
|
||||
call init_pot_para
|
||||
call potentialno35s(W,X1)
|
||||
|
||||
allocate (Mat, source=w)
|
||||
call dsyev('V', 'U', ndiab, Mat, ndiab, e, work, lwork, info)
|
||||
if( info .ne. 0) then
|
||||
write(*,*) " Error in eigenvalues decomposition routine of potential info=", info
|
||||
stop
|
||||
endif
|
||||
u(:, :) = Mat(:, :)
|
||||
deallocate (Mat)
|
||||
|
||||
if (dbg) then
|
||||
do i=1,ndiab
|
||||
|
||||
write(19,99) e(i),(U(i,j),j=1,ndiab)
|
||||
enddo
|
||||
write(19,*)""
|
||||
endif
|
||||
99 format(2x,f16.8,2X,5f16.8)
|
||||
|
||||
end subroutine eval_surface
|
||||
|
||||
! subroutine init_surface(p)
|
||||
! use dim_parameter, only: ndiab, nstat, ntot, nci ,qn
|
||||
! use parameterkeys, only: parameterkey_read
|
||||
! use fileread_mod, only: get_datfile, internalize_datfile
|
||||
! use io_parameters, only: llen
|
||||
! use accuracy_constants, only: dp
|
||||
! implicit none
|
||||
! real(dp), dimension(:), allocatable, intent(out) :: p
|
||||
! character(len=llen), allocatable, dimension(:) :: infile
|
||||
!
|
||||
! qn = 9
|
||||
! ndiab = 4
|
||||
! nstat = 4
|
||||
! nci = 4
|
||||
! ntot = ndiab + nstat + nci
|
||||
!
|
||||
! block
|
||||
! character(len=:),allocatable :: datnam
|
||||
! integer :: linenum
|
||||
! !get parameter file
|
||||
! call get_datfile(datnam)
|
||||
! !internalize datfile
|
||||
! call internalize_datfile(datnam, infile, linenum, llen)
|
||||
! end block
|
||||
!
|
||||
! !read parameters from file
|
||||
! block
|
||||
! real(dp), dimension(:), allocatable :: p_spread
|
||||
! integer,dimension(:),allocatable :: p_act
|
||||
! integer :: npar
|
||||
! real(dp), parameter :: facspread = 1.0_dp, gspread = 1.0_dp
|
||||
! call parameterkey_read(infile, size(infile, 1), p, p_act, p_spread, npar, gspread, facspread)
|
||||
! end block
|
||||
! end subroutine init_surface
|
||||
end module surface_mod
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
!*** Relevant parameters for the analytic model
|
||||
!*** offsets:
|
||||
!*** offsets(1): morse equilibrium (N-H, Angström)
|
||||
!*** offsets(2): reference angle (H-N-H)
|
||||
!*** offsets(3): --
|
||||
!*** pat_index: vector giving the position of the
|
||||
!*** various coordinates (see below)
|
||||
!*** ppars: polynomial parameters for tmcs
|
||||
!*** vcfs: coefficients for V expressions.
|
||||
!*** wzcfs: coefficients for W & Z expressions.
|
||||
!*** ifc: inverse factorials.
|
||||
|
||||
integer matdim
|
||||
parameter (matdim=5) ! matrix is (matdim)x(matdim)
|
||||
|
||||
real*8 offsets(2)
|
||||
integer pat_index(maxnin)
|
||||
|
||||
! NH3 params
|
||||
parameter (offsets=[1.0228710942d0,120.d0])
|
||||
|
||||
!##########################################################################
|
||||
! coordinate order; the first #I number of coords are given to the
|
||||
! ANN, where #I is the number of input neurons. The position i in
|
||||
! pat_index corresponds to a coordinate, the value of pat_index(i)
|
||||
! signifies its position.
|
||||
!
|
||||
! The vector is ordered as follows:
|
||||
! a,xs,ys,xb,yb,b,rs**2,rb**2,b**2,
|
||||
! es*eb, es**3, eb**3,es**2*eb, es*eb**2
|
||||
! ri**2 := xi**2+yi**2 = ei**2; ei := (xi,yi), i = s,b
|
||||
!
|
||||
! parts not supposed to be read by ANN are marked by ';' for your
|
||||
! convenience.
|
||||
!##########################################################################
|
||||
! a,rs**2,rb**2,es*eb,es**3,eb**3,es**2*eb,es*eb**2,b**2 #I=9 (6D)
|
||||
parameter (pat_index=[1,2,3,4,5,6,7,8,9,10,11,12,13,14])
|
||||
!**************************************************************************
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
subroutine cart2int(cart,qint)
|
||||
implicit none
|
||||
! This version merges both coordinate transformation routines into
|
||||
! one. JTmod's sscales(2:3) are ignored.
|
||||
! This is the first version to be compatible with one of my proper 6D fits
|
||||
! Time-stamp: <2024-10-22 13:52:59 dwilliams>
|
||||
|
||||
! Input (cartesian, in Angström)
|
||||
! cart(:,1): N
|
||||
! cart(:,1+i): Hi
|
||||
! Output
|
||||
! qint(i): order defined in JTmod.
|
||||
! Internal Variables
|
||||
! no(1:3): NO distances 1-3
|
||||
! pat_in: temporary coordinates
|
||||
! axis: main axis of NO3
|
||||
include 'nnparams.incl'
|
||||
include 'JTmod.incl'
|
||||
|
||||
|
||||
real*8 cart(3,4),qint(maxnin)
|
||||
|
||||
real*8 no(3), r1, r2, r3
|
||||
real*8 v1(3), v2(3), v3(3)
|
||||
real*8 n1(3), n2(3), n3(3), tr(3)
|
||||
real*8 ortho(3)
|
||||
real*8 pat_in(maxnin)
|
||||
logical ignore_umbrella,dbg_umbrella
|
||||
logical dbg_distances
|
||||
|
||||
!.. Debugging parameters
|
||||
!.. set umbrella to 0
|
||||
parameter (ignore_umbrella=.false.)
|
||||
! parameter (ignore_umbrella=.true.)
|
||||
|
||||
!.. break if umbrella is not 0
|
||||
parameter (dbg_umbrella=.false.)
|
||||
! parameter (dbg_umbrella=.true.)
|
||||
|
||||
!.. break for tiny distances
|
||||
parameter (dbg_distances=.false.)
|
||||
! parameter (dbg_distances=.true.)
|
||||
|
||||
integer k
|
||||
|
||||
!.. get N-O vectors and distances:
|
||||
do k=1,3
|
||||
v1(k)=cart(k,2)-cart(k,1)
|
||||
v2(k)=cart(k,3)-cart(k,1)
|
||||
v3(k)=cart(k,4)-cart(k,1)
|
||||
enddo
|
||||
no(1)=norm(v1,3)
|
||||
no(2)=norm(v2,3)
|
||||
no(3)=norm(v3,3)
|
||||
|
||||
!.. temporarily store displacements
|
||||
do k=1,3
|
||||
pat_in(k)=no(k)-offsets(1)
|
||||
enddo
|
||||
|
||||
do k=1,3
|
||||
v1(k)=v1(k)/no(1)
|
||||
v2(k)=v2(k)/no(2)
|
||||
v3(k)=v3(k)/no(3)
|
||||
enddo
|
||||
|
||||
!.. compute three normal vectors for the ONO planes:
|
||||
call xprod(n1,v1,v2)
|
||||
call xprod(n2,v2,v3)
|
||||
call xprod(n3,v3,v1)
|
||||
|
||||
do k=1,3
|
||||
tr(k)=(n1(k)+n2(k)+n3(k))/3.d0
|
||||
enddo
|
||||
r1=norm(tr,3)
|
||||
do k=1,3
|
||||
tr(k)=tr(k)/r1
|
||||
enddo
|
||||
|
||||
! rotate trisector
|
||||
call rot_trisec(tr,v1,v2,v3)
|
||||
|
||||
!.. determine trisector angle:
|
||||
if (ignore_umbrella) then
|
||||
pat_in(7)=0.0d0
|
||||
else
|
||||
pat_in(7)=pi/2.0d0 - acos(scalar(v1,tr,3))
|
||||
pat_in(7)=sign(pat_in(7),cart(1,2))
|
||||
endif
|
||||
|
||||
!.. molecule now lies in yz plane, compute projected ONO angles:
|
||||
v1(1)=0.d0
|
||||
v2(1)=0.d0
|
||||
v3(1)=0.d0
|
||||
r1=norm(v1,3)
|
||||
r2=norm(v2,3)
|
||||
r3=norm(v3,3)
|
||||
do k=2,3
|
||||
v1(k)=v1(k)/r1
|
||||
v2(k)=v2(k)/r2
|
||||
v3(k)=v3(k)/r3
|
||||
enddo
|
||||
|
||||
! make orthogonal vector to v3
|
||||
ortho(1)=0.0d0
|
||||
ortho(2)=v3(3)
|
||||
ortho(3)=-v3(2)
|
||||
|
||||
!.. projected ONO angles in radians
|
||||
pat_in(4)=get_ang(v2,v3,ortho)
|
||||
pat_in(5)=get_ang(v1,v3,ortho)
|
||||
|
||||
pat_in(6)=dabs(pat_in(5)-pat_in(4))
|
||||
|
||||
!.. account for rotational order of atoms
|
||||
if (pat_in(4).le.pat_in(5)) then
|
||||
pat_in(5)=2*pi-pat_in(4)-pat_in(6)
|
||||
else
|
||||
pat_in(4)=2*pi-pat_in(5)-pat_in(6)
|
||||
endif
|
||||
|
||||
pat_in(4)=rad2deg*pat_in(4)-offsets(2)
|
||||
pat_in(5)=rad2deg*pat_in(5)-offsets(2)
|
||||
pat_in(6)=rad2deg*pat_in(6)-offsets(2)
|
||||
pat_in(7)=rad2deg*pat_in(7)
|
||||
|
||||
call genANN_ctrans(pat_in)
|
||||
|
||||
qint(:)=pat_in(:)
|
||||
|
||||
contains
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! compute vector product n1 of vectors v1 x v2
|
||||
subroutine xprod(n1,v1,v2)
|
||||
implicit none
|
||||
|
||||
real*8 n1(3), v1(3), v2(3)
|
||||
|
||||
n1(1) = v1(2)*v2(3) - v1(3)*v2(2)
|
||||
n1(2) = v1(3)*v2(1) - v1(1)*v2(3)
|
||||
n1(3) = v1(1)*v2(2) - v1(2)*v2(1)
|
||||
|
||||
end subroutine
|
||||
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! compute scalar product of vectors v1 and v2:
|
||||
real*8 function scalar(v1,v2,n)
|
||||
implicit none
|
||||
integer i, n
|
||||
real*8 v1(*), v2(*)
|
||||
|
||||
scalar=0.d0
|
||||
do i=1,n
|
||||
scalar=scalar+v1(i)*v2(i)
|
||||
enddo
|
||||
|
||||
end function
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! compute norm of vector:
|
||||
real*8 function norm(x,n)
|
||||
implicit none
|
||||
integer i, n
|
||||
real*8 x(*)
|
||||
|
||||
norm=0.d0
|
||||
do i=1,n
|
||||
norm=norm+x(i)**2
|
||||
enddo
|
||||
norm=sqrt(norm)
|
||||
|
||||
end function
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
|
||||
subroutine rot_trisec(tr,v1,v2,v3)
|
||||
implicit none
|
||||
|
||||
real*8 tr(3),v1(3),v2(3),v3(3)
|
||||
|
||||
real*8 vrot(3)
|
||||
real*8 rot_ax(3)
|
||||
real*8 cos_phi,sin_phi
|
||||
|
||||
! evaluate cos(-phi) and sin(-phi), where phi is the angle between
|
||||
! tr and (1,0,0)
|
||||
cos_phi=tr(1)
|
||||
sin_phi=dsqrt(tr(2)**2+tr(3)**2)
|
||||
|
||||
if (sin_phi.lt.1.0d-12) then
|
||||
return
|
||||
endif
|
||||
|
||||
! determine rotational axis
|
||||
rot_ax(1) = 0.0d0
|
||||
rot_ax(2) = tr(3)
|
||||
rot_ax(3) = -tr(2)
|
||||
! normalize
|
||||
rot_ax=rot_ax/sin_phi
|
||||
|
||||
! now the rotation can be done using Rodrigues' rotation formula
|
||||
! v'=v*cos(p) + (k x v)sin(p) + k (k*v) (1-cos(p))
|
||||
! for v=tr k*v vanishes by construction:
|
||||
|
||||
! check that the rotation does what it should
|
||||
call rodrigues(vrot,tr,rot_ax,cos_phi,sin_phi)
|
||||
if (dsqrt(vrot(2)**2+vrot(3)**2).gt.1.0d-12) then
|
||||
write(6,*) "ERROR: BROKEN TRISECTOR"
|
||||
stop
|
||||
endif
|
||||
tr=vrot
|
||||
|
||||
call rodrigues(vrot,v1,rot_ax,cos_phi,sin_phi)
|
||||
v1=vrot
|
||||
call rodrigues(vrot,v2,rot_ax,cos_phi,sin_phi)
|
||||
v2=vrot
|
||||
call rodrigues(vrot,v3,rot_ax,cos_phi,sin_phi)
|
||||
v3=vrot
|
||||
|
||||
|
||||
end subroutine
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
|
||||
subroutine rodrigues(vrot,v,axis,cos_phi,sin_phi)
|
||||
implicit none
|
||||
real*8 vrot(3),v(3),axis(3)
|
||||
real*8 cos_phi,sin_phi
|
||||
|
||||
real*8 ortho(3)
|
||||
|
||||
call xprod(ortho,axis,v)
|
||||
vrot = v*cos_phi + ortho*sin_phi
|
||||
> + axis*scalar(axis,v,3)*(1-cos_phi)
|
||||
|
||||
end subroutine
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
|
||||
real*8 function get_ang(v,xaxis,yaxis)
|
||||
implicit none
|
||||
! get normalized [0:2pi) angle from vectors in the yz plane
|
||||
real*8 v(3),xaxis(3),yaxis(3)
|
||||
|
||||
real*8 phi
|
||||
|
||||
real*8 pi
|
||||
parameter (pi=3.141592653589793d0)
|
||||
|
||||
phi=atan2(scalar(yaxis,v,3),scalar(xaxis,v,3))
|
||||
if (phi.lt.0.0d0) then
|
||||
phi=2*pi+phi
|
||||
endif
|
||||
get_ang=phi
|
||||
|
||||
end function
|
||||
|
||||
end subroutine cart2int
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
!-------------------------------------------------------------------
|
||||
! Time-stamp: "2024-10-09 13:33:50 dwilliams"
|
||||
|
||||
subroutine genANN_ctrans(pat_in)
|
||||
implicit none
|
||||
|
||||
include 'nnparams.incl'
|
||||
include 'JTmod.incl'
|
||||
|
||||
real*8 pat_in(maxnin)
|
||||
|
||||
real*8 raw_in(maxnin),off_in(maxnin),ptrans_in(7)
|
||||
real*8 r0
|
||||
real*8 a,b,xs,ys,xb,yb
|
||||
|
||||
integer k
|
||||
|
||||
off_in(1:7)=pat_in(1:7)
|
||||
r0=offsets(1)
|
||||
|
||||
! transform primitives
|
||||
! recover raw distances from offset coords
|
||||
do k=1,3
|
||||
raw_in(k)=off_in(k)+offsets(1)
|
||||
enddo
|
||||
|
||||
do k=1,3
|
||||
ptrans_in(k)=off_in(k)
|
||||
enddo
|
||||
|
||||
! rescale ONO angles
|
||||
ptrans_in(4)=deg2rad*off_in(4)
|
||||
ptrans_in(5)=deg2rad*off_in(5)
|
||||
ptrans_in(6)=deg2rad*off_in(6)
|
||||
! rescale umbrella
|
||||
ptrans_in(7)=off_in(7)*deg2rad
|
||||
|
||||
! compute symmetry coordinates
|
||||
|
||||
! A (breathing)
|
||||
a=(ptrans_in(1)+ptrans_in(2)+ptrans_in(3))/dsqrt(3.0d0)
|
||||
! ES
|
||||
call prim2emode(ptrans_in(1:3),xs,ys)
|
||||
! EB
|
||||
call prim2emode(ptrans_in(4:6),xb,yb)
|
||||
! B (umbrella)
|
||||
b=ptrans_in(7)
|
||||
|
||||
! overwrite input with output
|
||||
|
||||
pat_in(pat_index(1))=a ! 1
|
||||
pat_in(pat_index(2))=xs
|
||||
pat_in(pat_index(3))=ys
|
||||
pat_in(pat_index(4))=xb
|
||||
pat_in(pat_index(5))=yb
|
||||
pat_in(pat_index(6))=b
|
||||
! totally symmetric monomials
|
||||
pat_in(pat_index(7))=xs**2 + ys**2 ! 2
|
||||
pat_in(pat_index(8))=xb**2 + yb**2 ! 3
|
||||
pat_in(pat_index(9))=b**2 ! 9
|
||||
pat_in(pat_index(10))=xs*xb+ys*yb ! 4
|
||||
! S^3, B^3
|
||||
pat_in(pat_index(11))=xs*(xs**2-3*ys**2) ! 5
|
||||
pat_in(pat_index(12))=xb*(xb**2-3*yb**2) ! 6
|
||||
! S^2 B, S B^2
|
||||
pat_in(pat_index(13))=xb*(xs**2-ys**2) - 2*yb*xs*ys ! 7
|
||||
pat_in(pat_index(14))=xs*(xb**2-yb**2) - 2*ys*xb*yb ! 8
|
||||
|
||||
do k=11,14
|
||||
pat_in(pat_index(k))=tanh(0.1d0*pat_in(pat_index(k)))*10.0d0
|
||||
enddo
|
||||
|
||||
contains
|
||||
|
||||
subroutine prim2emode(prim,ex,ey)
|
||||
implicit none
|
||||
! Takes a 2D-vector prim and returns the degenerate modes x and y
|
||||
! following our standard conventions.
|
||||
|
||||
real*8 prim(3),ex,ey
|
||||
|
||||
ex=(2.0d0*prim(1)-prim(2)-prim(3))/dsqrt(6.0d0)
|
||||
ey=(prim(2)-prim(3))/dsqrt(2.0d0)
|
||||
|
||||
end
|
||||
|
||||
|
||||
end subroutine
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
!**** Declarations
|
||||
|
||||
real*8 pi
|
||||
real*8 hart2eV, eV2hart
|
||||
real*8 hart2icm, icm2hart
|
||||
real*8 eV2icm, icm2eV
|
||||
real*8 deg2rad, rad2deg
|
||||
integer maxnin,maxnout
|
||||
|
||||
!**********************************************************
|
||||
!**** Parameters
|
||||
!*** maxnin: max. number of neurons in input layer
|
||||
!*** maxnout: max. number of neurons in output layer
|
||||
|
||||
parameter (maxnin=14,maxnout=15)
|
||||
|
||||
!**********************************************************
|
||||
!**** Numerical Parameters
|
||||
!*** infty: largest possible double precision real value.
|
||||
!*** iinfty: largest possible integer value.
|
||||
|
||||
! 3.14159265358979323846264338327950...
|
||||
parameter (pi=3.1415926536D0)
|
||||
|
||||
!**********************************************************
|
||||
!**** Unit Conversion Parameters
|
||||
!*** X2Y: convert from X to Y.
|
||||
!***
|
||||
!*** hart: hartree
|
||||
!*** eV: electron volt
|
||||
!*** icm: inverse centimeters (h*c/cm)
|
||||
!****
|
||||
!*** deg: degree
|
||||
!*** rad: radians
|
||||
|
||||
parameter (hart2icm=219474.69d0)
|
||||
parameter (hart2eV=27.211385d0)
|
||||
parameter (eV2icm=hart2icm/hart2eV)
|
||||
parameter (icm2hart=1.0d0/hart2icm)
|
||||
parameter (eV2hart=1.0d0/hart2eV)
|
||||
parameter (icm2eV=1.0d0/eV2icm)
|
||||
parameter (deg2rad=pi/180.0d0)
|
||||
parameter (rad2deg=1.0d0/deg2rad)
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
! <Subroutine weight(wt,y,ntot,numdatpt)
|
||||
subroutine weight(wt,y)
|
||||
use dim_parameter, only: nstat,ndiab,nci,ntot,numdatpt,
|
||||
> hybrid,wt_en2ci,wt_en,wt_ci
|
||||
implicit none
|
||||
! data arrays and their dimensions
|
||||
double precision wt(ntot,numdatpt),y(ntot,numdatpt)
|
||||
! loop index
|
||||
integer i,j,k,n
|
||||
|
||||
do i=1,numdatpt
|
||||
wt(1,i)=1.d0
|
||||
enddo
|
||||
|
||||
call norm_weight(wt,ntot,numdatpt)
|
||||
|
||||
end
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine norm_weight(wt,ntot,numdatpt)
|
||||
subroutine norm_weight(wt,ntot,numdatpt)
|
||||
implicit none
|
||||
integer ntot,numdatpt
|
||||
double precision norm,wt(ntot,numdatpt)
|
||||
integer i,j,count
|
||||
|
||||
write(6,*) 'Normalizing Weights...'
|
||||
norm=0.d0
|
||||
count = 0
|
||||
do i=1,numdatpt
|
||||
do j=1,ntot
|
||||
norm = norm + wt(j,i)*wt(j,i)
|
||||
if (wt(j,i).gt.0.d0) count=count+1
|
||||
enddo
|
||||
enddo
|
||||
|
||||
norm = dsqrt(norm)
|
||||
if(norm.gt.0.d0) then
|
||||
do i=1,numdatpt
|
||||
do j=1,ntot
|
||||
wt(j,i) = wt(j,i)/norm
|
||||
enddo
|
||||
enddo
|
||||
else
|
||||
write(6,*) 'Warning: Norm of Weights is Zero'
|
||||
endif
|
||||
|
||||
Write(6,'(''No. of weigthed data points:'',i0)') count
|
||||
|
||||
end subroutine
|
||||
|
|
@ -0,0 +1,763 @@
|
|||
module write_mod
|
||||
implicit none
|
||||
! unit conversion
|
||||
double precision ,parameter :: h2icm = 219474.69d0
|
||||
double precision, parameter :: au2Debye = 2.541746d0
|
||||
character(len=250), parameter :: sep_line = '(250("-"))'
|
||||
character(len=250), parameter :: block_line = '(250("="))'
|
||||
|
||||
contains
|
||||
|
||||
! <Subroutine for writing the Output
|
||||
subroutine write_output
|
||||
> (q,x1,x2,y,wt,par,p_act,p_spread,nset,npar,
|
||||
> flag,lauf)
|
||||
use adia_mod, only: adia
|
||||
use dim_parameter,only: qn,ntot,numdatpt,ndiab
|
||||
use ctrans_mod,only: ctrans
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer lauf
|
||||
integer flag !< 0= initial output 1=fit not converged 2= Fit Converged, 3= max iteration reached
|
||||
integer npar,nset
|
||||
double precision par(npar,nset),p_spread(npar)
|
||||
integer p_act(npar)
|
||||
double precision q(qn,numdatpt),x1(qn,numdatpt),x2(qn,numdatpt)
|
||||
double precision y(ntot,numdatpt),wt(ntot,numdatpt)
|
||||
|
||||
! INTERNAL: Variables
|
||||
integer,parameter :: id_out = 20 , std_out = 6
|
||||
integer pt
|
||||
integer i, id_print
|
||||
double precision, allocatable :: ymod(:,:)
|
||||
double precision, allocatable :: ew(:,:)
|
||||
double precision, allocatable :: ev(:,:,:)
|
||||
|
||||
logical skip
|
||||
|
||||
allocate(ymod(ntot,numdatpt))
|
||||
allocate(ew(ndiab,numdatpt))
|
||||
allocate(ev(ndiab,ndiab,numdatpt))
|
||||
|
||||
skip=.false.
|
||||
|
||||
! get Model Outputs for all geometries for current best parameter set par(:,1)
|
||||
do pt=1,numdatpt
|
||||
call adia(pt,par(1:npar,1),npar,ymod(1:ntot,pt),
|
||||
> ew(1:ndiab,pt),ev(1:ndiab,1:ndiab,pt),skip)
|
||||
call ctrans(q(:,pt),x1(:,pt),x2(:,pt))
|
||||
enddo
|
||||
|
||||
! Initial write print everything you want to see before the fit and return
|
||||
if(flag.eq.0) then
|
||||
call print_parameterstate(std_out,par(:,1),p_act,npar)
|
||||
call print_ErrorSummary(std_out,y,ymod,wt)
|
||||
! print Data into the plotfiles
|
||||
return
|
||||
endif
|
||||
! open output files for individual makro iterations
|
||||
call open_outfile(id_out,lauf)
|
||||
! print Data into the plotfiles
|
||||
call print_plotfiles(x1,y,wt,ymod)
|
||||
|
||||
! print Genetic output into files
|
||||
do i=1, 2
|
||||
if (i.eq.1) then
|
||||
id_print= std_out
|
||||
else
|
||||
id_print= id_out
|
||||
endif
|
||||
write(id_print,'("Writing Iteration: ",i4)') lauf
|
||||
write(id_print,block_line)
|
||||
! write data information only in outfile
|
||||
if(i.eq.2) then
|
||||
call print_data(id_print,x1,y,ymod,wt)
|
||||
call print_Set_Errors(id_print,y,ymod,wt)
|
||||
endif
|
||||
call print_parameterblock
|
||||
> (id_print,par(:,1),p_act,p_spread,npar)
|
||||
call print_ErrorSummary(id_print,y,ymod,wt)
|
||||
|
||||
enddo
|
||||
|
||||
call print_fortranfile(par(:,1),npar)
|
||||
|
||||
! write the type of calc at the end of the output
|
||||
|
||||
|
||||
close (id_out)
|
||||
deallocate(ymod,ev,ew)
|
||||
end subroutine
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <subroutine for scan seperated Error analysis>
|
||||
subroutine print_Set_Errors(id_out,y, ymod, wt)
|
||||
use io_parameters,only: llen
|
||||
use dim_parameter,only: ndata,nstat,ntot,numdatpt,sets
|
||||
integer , intent(in) :: id_out
|
||||
double precision, intent(in) :: y(ntot,numdatpt),
|
||||
> ymod(ntot,numdatpt), wt(ntot,numdatpt)
|
||||
integer :: set, setpoint, pt
|
||||
double precision :: Set_rms(sets,ntot), Set_num(sets,ntot)
|
||||
double precision :: Total_rms, Total_Energy_rms,Energy_rms(nstat)
|
||||
character(len=llen) fmt
|
||||
write(id_out,'(A)') 'Errors in icm for individual Sets' //
|
||||
> '(specified by sets: and npoints:)'
|
||||
write(id_out,'(A5,3A16)')'Set','Total',
|
||||
> 'Total_Energy', 'Energy[nstat]'
|
||||
write(id_out,sep_line)
|
||||
write(fmt,'("(I5,2f16.1,",I2,"f16.1)")') nstat
|
||||
Set_rms = 0.d0
|
||||
pt = 0
|
||||
do set=1, sets
|
||||
do setpoint=1, ndata(set)
|
||||
pt = pt + 1
|
||||
where(wt(:,pt) > 0.d0)
|
||||
Set_rms(set,:) = Set_rms(set,:)+(ymod(:,pt)-y(:,pt))**2
|
||||
Set_num(set,:) = Set_num(set,:) + 1
|
||||
end where
|
||||
enddo
|
||||
Total_rms
|
||||
> = dsqrt(sum(Set_rms(set,:))
|
||||
> / (sum(Set_num(set,:))))
|
||||
Total_Energy_rms
|
||||
> = dsqrt(sum(Set_rms(set,1:nstat))
|
||||
> / (sum(Set_num(set,1:nstat))))
|
||||
Energy_rms(1:nstat)
|
||||
> = dsqrt(Set_rms(set,1:nstat)
|
||||
> / (Set_num(set,1:nstat)))
|
||||
write(id_out,fmt) set, Total_rms*h2icm, Total_Energy_rms*h2icm,
|
||||
> Energy_rms(1:nstat)*h2icm
|
||||
enddo
|
||||
write(id_out,block_line)
|
||||
write(id_out,*) ''
|
||||
end subroutine print_Set_Errors
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <subroutine for printing the parameter and the pst vector in fortran readable style for including the fitted parameters in other programs
|
||||
subroutine print_fortranfile(p,npar)
|
||||
use io_parameters,only: maxpar_keys
|
||||
use dim_parameter,only: pst
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer npar
|
||||
double precision p(npar)
|
||||
! INTERNAL: variables
|
||||
integer i
|
||||
integer, parameter :: id_out = 49
|
||||
character(len=32), parameter :: fname ='fit_genric_bend_no3.f90'
|
||||
|
||||
open(id_out,file=fname)
|
||||
|
||||
30 format(6x,A2,i3,A2,d18.9)
|
||||
31 format(6x,A6,i3,A2,i3)
|
||||
|
||||
write(id_out,'(2X,A)') "Module dip_param"
|
||||
write(id_out,'(5X,A)') "IMPLICIT NONE"
|
||||
write(id_out,'(5X,A,I0)') "Integer,parameter :: np=",npar
|
||||
write(id_out,'(5X,A,I0,A)') "Double precision :: p(",npar,")"
|
||||
write(id_out,'(5X,A,I0,A)') "integer :: pst(2,",maxpar_keys,")"
|
||||
write(id_out,'(5X,A)') "contains"
|
||||
write(id_out,*)''
|
||||
|
||||
write (id_out,'(5x,a)') "SUBROUTINE init_dip_planar_data()"
|
||||
write (id_out,'(8X,A)') "implicit none"
|
||||
do i=1,npar
|
||||
write(id_out,30) 'p(',i,')=',p(i)
|
||||
enddo
|
||||
do i=1,maxpar_keys
|
||||
write(id_out,31) 'pst(1,',i,')=',pst(1,i)
|
||||
write(id_out,31) 'pst(2,',i,')=',pst(2,i)
|
||||
enddo
|
||||
|
||||
|
||||
write(id_out,"(A)") "End SUBROUTINE init_dip_planar_data"
|
||||
write(id_out,"(A)") "End Module dip_param"
|
||||
|
||||
close(id_out)
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <subroutine print_ErrorSummary: calculates the rms errros and prints them in the corresponding file
|
||||
subroutine print_ErrorSummary(id_out,y,ymod,wt)
|
||||
use dim_parameter,only: nstat,rms_thr,ntot,numdatpt
|
||||
use io_parameters,only: llen
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer id_out
|
||||
double precision y(ntot,numdatpt),ymod(ntot,numdatpt)
|
||||
double precision wt(ntot,numdatpt)
|
||||
! INTERNAL: variables
|
||||
! Counter and RMS variables
|
||||
double precision Cut_thr(nstat)
|
||||
double precision Output_rms(ntot),Cut_rms(nstat),Weighted_rms
|
||||
integer Output_num(ntot),Cut_num(nstat)
|
||||
double precision Weighted_wt
|
||||
double precision Total_rms,Total_Weighted_rms
|
||||
double precision Total_Energie_rms,Total_State_rms(nstat)
|
||||
double precision Cut_Energie_rms, Cut_State_rms(nstat)
|
||||
|
||||
! Variables for computing the NRMSE
|
||||
!double precision:: ymean(ntot),ysum(ntot),NRMSE
|
||||
|
||||
! loop control
|
||||
integer j,pt
|
||||
|
||||
! Fabian
|
||||
character(len=llen) fmt
|
||||
! initialize RMS variables
|
||||
Output_rms(1:ntot) = 0.d0
|
||||
Output_num(1:ntot) = 0
|
||||
Weighted_rms = 0.d0
|
||||
Weighted_wt = 0.d0
|
||||
Cut_rms(1:nstat)= 0.d0
|
||||
Cut_num(1:nstat)= 0
|
||||
|
||||
! Define Threshold for Cut_* RMS Values
|
||||
Cut_thr(1:nstat) = rms_thr(1:nstat)
|
||||
! SUMM!
|
||||
! Loop over all Datapoints
|
||||
do pt=1,numdatpt
|
||||
! get unweighted rms for each output value and count their number
|
||||
do j=1,ntot
|
||||
if(wt(j,pt).gt.0.d0) then
|
||||
Output_rms(j) = Output_rms(j) +
|
||||
> (ymod(j,pt)-y(j,pt))**2
|
||||
Output_num(j)=Output_num(j) + 1
|
||||
endif
|
||||
enddo
|
||||
! get the unweighted rms under the given threshold and count their number
|
||||
do j=1,nstat
|
||||
if(wt(j,pt).gt.0.d0) then
|
||||
if(y(j,pt).le.Cut_thr(j)) then
|
||||
Cut_rms(j) = Cut_rms(j) +
|
||||
> (ymod(j,pt)-y(j,pt))**2
|
||||
Cut_num(j) = Cut_num(j) + 1
|
||||
endif
|
||||
endif
|
||||
enddo
|
||||
! get the weighted rms over all output values
|
||||
Weighted_rms = Weighted_rms +
|
||||
> sum(((ymod(1:ntot,pt)-y(1:ntot,pt))**2)
|
||||
> *(wt(1:ntot,pt)**2))
|
||||
Weighted_wt = Weighted_wt + sum(wt(1:ntot,pt)**2)
|
||||
enddo
|
||||
|
||||
! NORM!
|
||||
! TOTAL RMS:
|
||||
! unweighted
|
||||
Total_rms =
|
||||
> dsqrt(sum(Output_rms(1:ntot)) /(sum(Output_num(1:ntot))))
|
||||
|
||||
! Weighted
|
||||
Total_Weighted_rms = dsqrt(Weighted_rms/Weighted_wt)
|
||||
|
||||
! unweighted, considering only first nstat values
|
||||
Total_Energie_rms =
|
||||
> dsqrt(sum(Output_rms(1:nstat)) /(sum(Output_num(1:nstat))))
|
||||
|
||||
! unweighted,for each of the first nstat values separatly
|
||||
Total_State_rms(1:nstat) =
|
||||
> dsqrt(Output_rms(1:nstat) / Output_num(1:nstat))
|
||||
|
||||
! unweighted,first nstat values only counting points under given threshold
|
||||
Cut_Energie_rms =
|
||||
> dsqrt(sum(Cut_rms(1:nstat)) /(sum(Cut_num(1:nstat))))
|
||||
|
||||
! unweighted,each nstat values seperatly only counting points under threshold
|
||||
Cut_State_rms(1:nstat) =
|
||||
> dsqrt(Cut_rms(1:nstat)/Cut_num(1:nstat))
|
||||
|
||||
! WRITE!
|
||||
! make the actual writing into the file
|
||||
write(id_out,39)
|
||||
write(id_out,40)
|
||||
write(id_out,41) Total_rms, Total_rms*au2Debye!Total_rms*h2icm
|
||||
write(id_out,42) sum(Output_num(1:ntot))
|
||||
write(id_out,43) Total_Weighted_rms, Total_Weighted_rms*h2icm
|
||||
write(id_out,44) Weighted_wt
|
||||
write(id_out,45) Total_Energie_rms, Total_Energie_rms*h2icm
|
||||
write(id_out,42) sum(Output_num(1:nstat))
|
||||
write(fmt,'("(A,10x,A,",I2,"f8.1)")') nstat
|
||||
write(id_out,fmt) '#','State resolved RMS(icm): ',
|
||||
$ Total_State_rms(1:nstat)*h2icm
|
||||
write(fmt,'("(A,10x,A,",I2,"i8)")') nstat
|
||||
write(id_out,fmt) '#','No. of Points per State: ',
|
||||
$ Output_num(1:nstat)
|
||||
write(id_out,51)
|
||||
|
||||
! write the errors under a given threshold if there were any points
|
||||
if(any(Cut_num(1:nstat).gt.0)) then
|
||||
write(id_out,48) Cut_Energie_rms, Cut_Energie_rms*h2icm
|
||||
write(id_out,42) sum(Cut_num(1:nstat))
|
||||
|
||||
write(fmt,'("(A,10x,A,",I2,"f8.1,A)")') nstat
|
||||
write(id_out,fmt) '#','Red. State resolved RMS: ',
|
||||
$ Cut_State_rms(1:nstat)*h2icm,' icm'
|
||||
write(fmt,'("(A,10x,A,",I2,"i8)")') nstat
|
||||
write(id_out,fmt) '#','No. of Points per State: ',
|
||||
$ Cut_num(1:nstat)
|
||||
write(fmt,'("(A,10x,A,",I2,"f8.1,A)")') nstat
|
||||
write(id_out,fmt) '#','Threshold per State: ',
|
||||
$ Cut_thr(1:nstat)*h2icm,' icm above Reference Point.'
|
||||
|
||||
endif
|
||||
write(id_out,39)
|
||||
|
||||
! FORMAT! specifications for the writing
|
||||
39 format(250('#'))
|
||||
40 format('#',10x,'ERROR SUMMARY: ')
|
||||
41 format('#',10x,'Total RMS: ',g16.8, '(',g16.8,
|
||||
> ' Debye)')
|
||||
42 format('#',10x,'No. of Points: ',i10)
|
||||
43 format('#',10x,'Total weighted RMS: ',g16.8, '(',f8.1,' icm)')
|
||||
44 format('#',10x,'Sum of point weights: ',f16.8)
|
||||
45 format('#',10x,'Total Energie RMS: ',g16.8, '(',f8.1,' icm)')
|
||||
|
||||
48 format('#',10x,'Red. Energie RMS: ',g16.8,'(',f8.1,' icm)')
|
||||
51 format('#')
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
subroutine print_plotfiles(x,y,wt,ymod)
|
||||
use dim_parameter,only: ndata,sets,qn,ntot,numdatpt,plot_coord
|
||||
implicit none
|
||||
! IN: variables
|
||||
double precision x(qn,numdatpt),y(ntot,numdatpt)
|
||||
double precision wt(ntot,numdatpt), ymod(ntot,numdatpt)
|
||||
! INTERNAL: variables
|
||||
integer sstart,ssend,set,id_plot
|
||||
|
||||
! Initialize position pointer
|
||||
ssend=0
|
||||
! loop over datasets and print the plotfiles
|
||||
do set=1 ,sets
|
||||
if(ndata(set).eq.0) cycle
|
||||
id_plot=50+set
|
||||
call open_plotfile(id_plot,set)
|
||||
write(id_plot,'(A)') '# -*- truncate-lines: t -*-'
|
||||
! get start and end point of each set
|
||||
sstart=ssend+1
|
||||
ssend=ssend+ndata(set)
|
||||
if (plot_coord(set).eq.0) then
|
||||
call print_plotwalk(x(:,sstart:ssend),y(:,sstart:ssend),
|
||||
> wt(:,sstart:ssend),ymod(:,sstart:ssend),
|
||||
> ndata(set),id_plot,set)
|
||||
else
|
||||
call print_plotcoord(plot_coord(set),
|
||||
> x(:,sstart:ssend),y(:,sstart:ssend),
|
||||
> wt(:,sstart:ssend),ymod(:,sstart:ssend),
|
||||
> ndata(set),id_plot,set)
|
||||
endif
|
||||
close(id_plot)
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
subroutine print_plotwalk(x,y,wt,ymod,npt,id_plot,set)
|
||||
use dim_parameter,only: qn,ntot
|
||||
use io_parameters,only: llen
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer id_plot,npt,set
|
||||
double precision x(qn,npt),y(ntot,npt),ymod(ntot,npt),wt(ntot,npt)
|
||||
! INTERNAL: variables
|
||||
double precision xdiff(qn),walktime
|
||||
double precision walknorm
|
||||
! loop control
|
||||
integer i,j
|
||||
|
||||
character(len=llen) fmt
|
||||
j=ntot-1
|
||||
|
||||
call print_plotheader(id_plot,0,npt,set)
|
||||
|
||||
call getwalknorm(x,walknorm,npt)
|
||||
walktime = 0.d0
|
||||
do i=1,npt
|
||||
if(i.gt.1) then
|
||||
xdiff(1:qn) = x(1:qn,i) - x(1:qn,i-1)
|
||||
walktime = walktime + dsqrt(sum(xdiff(1:qn)**2))/walknorm
|
||||
endif
|
||||
write(id_plot,"(ES16.8,*(3(ES16.8),:))")
|
||||
> walktime ,ymod(:,i),y(:,i),(wt(:,i))
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
subroutine print_plotcoord(coord,x,y,wt,ymod,npt,id_plot,set)
|
||||
use dim_parameter,only: qn,ntot
|
||||
use io_parameters,only: llen
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer, intent(in) :: id_plot,npt,set,coord
|
||||
double precision, intent(in) :: x(qn,npt),y(ntot,npt)
|
||||
double precision, intent(in) :: ymod(ntot,npt),wt(ntot,npt)
|
||||
! loop control
|
||||
integer i
|
||||
|
||||
call print_plotheader(id_plot,coord,npt,set)
|
||||
do i=1,npt
|
||||
write(id_plot,"(ES16.8,*(3(ES16.8),:))")
|
||||
> x(coord,i), ymod(:,i),y(:,i),(wt(:,i))
|
||||
! write(id_plot,"(2ES16.8,*(3(ES16.8),:))")
|
||||
! > x(coord,i), x(coord+1,i),y(:,i)
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
subroutine print_plotheader(id_plot,coord,npt,set)
|
||||
use dim_parameter,only: qn,ntot
|
||||
use io_parameters,only: llen
|
||||
implicit none
|
||||
integer, intent(in) :: id_plot,npt,set,coord
|
||||
|
||||
character(len=llen) fmt
|
||||
|
||||
write(id_plot,'("#SET: ",i5)') set
|
||||
write(id_plot,'("#OUTPUT VALUES",i4)') ntot
|
||||
write(id_plot,'("#DATA POINTS: ",i4)') npt
|
||||
if (coord.le.0) then
|
||||
write(id_plot,'("#t(x) = WALK")')
|
||||
else
|
||||
write(id_plot,'("#t(x) = x(",I0,")")') coord
|
||||
endif
|
||||
write(id_plot,'("#UNIT: hartree")')
|
||||
write(id_plot,'()')
|
||||
write(id_plot,'("#",A15)',advance='no') "t(x)"
|
||||
write(fmt,'("(3(7X,A9,",I3,"(16x)))")') ntot-1
|
||||
write(id_plot,fmt) 'ymod(p,x)','y(x) ','wt(x) '
|
||||
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <subroutine walknorm calulates the distance in coordinate space for each set
|
||||
subroutine getwalknorm(x,walknorm,npt)
|
||||
use dim_parameter,only: qn
|
||||
implicit none
|
||||
! IN: variables
|
||||
integer npt
|
||||
double precision x(qn,npt)
|
||||
double precision walknorm
|
||||
! INTERNAL: variables
|
||||
double precision xdiff(qn)
|
||||
integer i
|
||||
|
||||
walknorm =0.d0
|
||||
do i=2,npt
|
||||
xdiff(1:qn) = x(1:qn,i) - x(1:qn,i-1)
|
||||
walknorm = walknorm + dsqrt(sum(xdiff(1:qn)**2))
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine for generating output filenames and openeing the correspondign files
|
||||
subroutine open_plotfile(id_plot,set)
|
||||
implicit none
|
||||
! IN: Variables
|
||||
integer id_plot,set
|
||||
! INTERNAL: Variables
|
||||
character(len=30) name !name of output file
|
||||
|
||||
! define name sheme for plot files
|
||||
if (set .lt. 10 ) then
|
||||
write(name,203) set
|
||||
else
|
||||
write(name,202) set
|
||||
endif
|
||||
|
||||
202 format('scan',I2,'.dat')
|
||||
203 format('scan0',I1,'.dat')
|
||||
!write (name,202) set
|
||||
|
||||
c open plotfile
|
||||
open(id_plot,file=name)
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine for generating output filenames and openeing the correspondign files
|
||||
subroutine open_outfile(id_out,it_makro)
|
||||
implicit none
|
||||
integer id_out,it_makro
|
||||
character(len=30) outname !name of output file
|
||||
|
||||
543 format('mnlfit-',i1,'.out')
|
||||
544 format('mnlfit-',i2,'.out')
|
||||
545 format('mnlfit-',i3,'.out')
|
||||
|
||||
if(it_makro.lt.10) then
|
||||
write(outname,543) it_makro
|
||||
else if (it_makro.lt.100) then
|
||||
write(outname,544) it_makro
|
||||
else if (it_makro.lt.1000) then
|
||||
write(outname,545) it_makro
|
||||
else
|
||||
write(6,*)
|
||||
> 'ERROR: No rule for Outputfile naming for MAXIT >= 1000'
|
||||
stop
|
||||
endif
|
||||
|
||||
open (id_out,file=outname)
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine for printing the Parameterkeys for use in Input File
|
||||
! < prints the keystring given in keys.incl and the corresponding parameters when there was atleast one parameter given in the input for the spcific key
|
||||
! < how many parameters and spreads per line are printed can be specified with the hardcoded parameters np and nsp but they must be atleast >=2
|
||||
! <@param id_out specifies the file in which the Parameters are Printed
|
||||
! <@param p vector containing one set of parameter values
|
||||
! <@param p_act vector containing the active state 0 (inactive) or 1 (active) for each parameter
|
||||
! <@param p_spread vector containing the spreads for each parameter
|
||||
! <@param npar lenght of the parmeter vectors (p,p_act,p_spread)
|
||||
! <@TODO extract subroutine for printing the multiline values, would make this more readable
|
||||
subroutine print_parameterblock(id_out,p,p_act,p_spread,npar)
|
||||
use dim_parameter,only: pst, facspread
|
||||
use io_parameters,only: key, parkeynum,parkeylen,llen
|
||||
implicit none
|
||||
! IN: Variables
|
||||
integer id_out,npar,p_act(npar)
|
||||
double precision p(npar),p_spread(npar)
|
||||
|
||||
! INTERNAL: variables
|
||||
! loop index
|
||||
integer i,k,l,t,n !< internal variables for loops and positions in parameter vectors
|
||||
|
||||
! number of values per line, values must be atleast 2 set this to personal preference
|
||||
integer, parameter :: np=5,nsp=5
|
||||
|
||||
character(len=llen) fmt
|
||||
|
||||
|
||||
! Write header for Parameter block
|
||||
1 format('!',200('='))
|
||||
write(id_out,1)
|
||||
write(id_out,'(A2,5x,A11,i3)') '! ','PARAMETER: ',npar
|
||||
write(id_out,1)
|
||||
|
||||
! loop over all Parameter Keys
|
||||
do i = 1, parkeynum
|
||||
! save start and end of parameter block for specific key
|
||||
k = pst(1,i)
|
||||
l = pst(1,i)+pst(2,i)-1
|
||||
! print only used keys with atleast one parameter
|
||||
if(pst(2,i).gt.0) then
|
||||
write(fmt,'("(a",I3,"'' ''i3)")') parkeylen
|
||||
write(id_out,fmt) adjustl(key(1,i)), pst(2,i)
|
||||
|
||||
! write the actual parameters -> subroutine print_parameterlines()?
|
||||
if(l-k.le.(np-1)) then
|
||||
write(fmt,'("(a",I3,"'' ''",I3,"g24.15)")') parkeylen,np
|
||||
write(id_out,fmt) key(2,i),(p(n), n=k,l)
|
||||
|
||||
else
|
||||
! start of multi line parameter print, number of values per line specified by np
|
||||
write(fmt,'("(a",I3,"'' ''",I3,"g24.15'' &'')")')
|
||||
$ parkeylen,np
|
||||
write(id_out,fmt) key(2,i),(p(n), n=k,k+(np-1))
|
||||
|
||||
t=k+np
|
||||
! write continuation lines till left parameters fit on last line
|
||||
do while(t.le.l)
|
||||
if(l-t.le.(np-1)) then
|
||||
write(fmt,'("(",I3,"x'' ''",I3,"g24.15)")')
|
||||
$ parkeylen,np
|
||||
write(id_out,fmt) (p(n), n=t, l)
|
||||
|
||||
else
|
||||
write(fmt,'("(",I3,"x'' ''",I3,"g24.15'' &'')")')
|
||||
$ parkeylen,np
|
||||
write(id_out,fmt) (p(n), n=t, t+(np-1))
|
||||
|
||||
endif
|
||||
t=t+np
|
||||
enddo
|
||||
|
||||
endif !-> end subroutine print_parameterlines
|
||||
|
||||
! write parameter active state in one line
|
||||
write(fmt,'("(a",I3,"'' ''","50i3)")') parkeylen
|
||||
write(id_out,fmt) key(3,i),(p_act(n),n=k,l)
|
||||
|
||||
! write the spreads for each parameter
|
||||
if(l-k.le.(np-1)) then
|
||||
write(fmt,'("(a",I3,"'' ''",I3,"g24.8)")') parkeylen,nsp
|
||||
write(id_out,fmt) key(4,i),(p_spread(n)/facspread, n=k,l)
|
||||
|
||||
else
|
||||
! start of multiline spread values
|
||||
write(fmt,'("(a",I3,"'' ''",I3,"g24.8'' &'')")')
|
||||
$ parkeylen,nsp
|
||||
write(id_out,fmt) key(4,i),(p_spread(n)/facspread, n=k,k
|
||||
> +(np-1))
|
||||
|
||||
t=k+nsp
|
||||
! write continuation lines till left spreads fit on last line
|
||||
do while(t.le.l)
|
||||
if(l-t.le.(np-1)) then
|
||||
write(fmt,'("(",I3,"x'' ''",I3,"g24.8)")')
|
||||
$ parkeylen,nsp
|
||||
write(id_out,fmt) (p_spread(n)/facspread, n=t, l)
|
||||
else
|
||||
write(fmt,'("(",I3,"x'' ''",I3,"g24.8'' &'')")')
|
||||
$ parkeylen,nsp
|
||||
write(id_out,fmt) (p_spread(n)/facspread, n=t, t
|
||||
> +(np-1))
|
||||
|
||||
endif
|
||||
t=t+np
|
||||
enddo
|
||||
|
||||
endif
|
||||
! print empty line between diffrent parameter blocks for better readability
|
||||
write(id_out,'(" ")')
|
||||
endif
|
||||
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine for printing the current Parameters and their active state
|
||||
! < prints only the numeric values of the parameters and does not specify the corresponding key
|
||||
! <@param npar number of parameter
|
||||
! <@param id_out specifies the output file
|
||||
! <@param p,p_act parameter vectors containing the values and the activity state of parameters
|
||||
subroutine print_parameterstate(id_out,p,p_act,npar)
|
||||
implicit none
|
||||
|
||||
! IN: Variables
|
||||
integer npar,id_out
|
||||
double precision p(npar)
|
||||
integer p_act(npar)
|
||||
|
||||
! INTERNAL: Variables
|
||||
integer i !< loop control
|
||||
integer nopt !< number of counted active parameters
|
||||
character(len=16) opt(npar) !< string for optimisation state
|
||||
|
||||
! initialize number of opt parameters and the string vector opt
|
||||
nopt=0
|
||||
opt = ' not opt. '
|
||||
! loop over all parameters and check their active state count if active and set string to opt
|
||||
do i=1,npar
|
||||
! Nicole: change due to value 2 of p_act
|
||||
! if(p_act(i).eq.1) then
|
||||
if(p_act(i).ge.1) then
|
||||
opt(i) = ' opt. '
|
||||
nopt=nopt+1
|
||||
endif
|
||||
enddo
|
||||
! print the Parameters and their active state within separating lines
|
||||
write(id_out,*)''
|
||||
write(id_out,block_line)
|
||||
write(id_out,*) 'Parameters:'
|
||||
write(id_out,sep_line)
|
||||
write(id_out,'(5g14.6)') (p(i),i=1,npar)
|
||||
write(id_out,'(5a14)') (opt(i),i=1,npar)
|
||||
write(id_out,sep_line)
|
||||
write(id_out,'("No. of optimized parameters: ",i6)') nopt
|
||||
write(id_out,block_line)
|
||||
write(id_out,*)''
|
||||
end subroutine
|
||||
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine for printing coordinates,refdata,modeldata,diffrence between them and the weights
|
||||
! <@param id_out identiefies the output file
|
||||
! <@param x vector of input pattern for each datapoint
|
||||
! <@param y vector of expected output patterns for each datapoint
|
||||
! <@param ymod vector of output patterns generated by the model depending on paramerters
|
||||
! <@param wt vector of weights for each datapoint
|
||||
! <@param qn number of input patterns
|
||||
! <@param ntot total number of output patterns for each datapoint
|
||||
! <@param numdatpt number of totatl datapoints
|
||||
! <@param sets number of sets the datapoints are divided into
|
||||
! <@param ndata vector containing the number of included datapoints for each set
|
||||
! <@param i,j,point internal variables for loop controll and datapoint counting
|
||||
subroutine print_data(id_out,x,y,ymod,wt)
|
||||
use dim_parameter,only: sets,ndata,qn,ntot,numdatpt,qn_read
|
||||
implicit none
|
||||
! IN: Variables
|
||||
integer id_out
|
||||
double precision x(qn,numdatpt)
|
||||
double precision y(ntot,numdatpt),ymod(ntot,numdatpt)
|
||||
double precision wt(ntot,numdatpt)
|
||||
|
||||
! INTERNAL: Variables
|
||||
integer i,j,point
|
||||
|
||||
18 format(A8,i6)
|
||||
19 format (3(A15,3x), 2x, A18 , 4x, A12)
|
||||
|
||||
! print seperating line and header for Data output
|
||||
write(id_out,*) 'Printing Data Sets:'
|
||||
|
||||
write(id_out,19) adjustl('y(x)'),adjustl('ymod(x)'),
|
||||
> adjustl('y(x)-ymod(x)'),adjustl('weight'),
|
||||
> adjustl('x(1:qn_read) ')
|
||||
write(id_out,sep_line)
|
||||
! loop over all datapoints for each set and count the actual datapointnumber with point
|
||||
point=0
|
||||
do i=1,sets
|
||||
write(id_out,18) 'Set: ', i
|
||||
do j=1,ndata(i)
|
||||
write(id_out,18) 'Point: ', j
|
||||
point=point+1
|
||||
! print all data for one datapoint
|
||||
call print_datapoint(id_out,x(:,point),y(:,point),
|
||||
> ymod(:,point),wt(:,point))
|
||||
write(id_out,sep_line)
|
||||
|
||||
enddo
|
||||
enddo
|
||||
! write end of data statement and two seperating lines
|
||||
write(id_out,block_line)
|
||||
write(id_out,*) ''
|
||||
end subroutine
|
||||
!----------------------------------------------------------------------------------------------------
|
||||
! <Subroutine prints a single Datapoint splits Data in nstat nci(ndiab) blocks for readability
|
||||
! <@param id_out identiefies the output file
|
||||
! <@param x vector of input pattern for each datapoint
|
||||
! <@param y vector of expected output patterns for each datapoint
|
||||
! <@param ymod vector of output patterns generated by the model depending on paramerters
|
||||
! <@param wt vector of weights for each datapoint
|
||||
! <@param qn number of input patterns
|
||||
! <@param ntot total number of output patterns for each datapoint
|
||||
! <@param i,j,k internal variables for loop controll and counting
|
||||
subroutine print_datapoint(id_out,x,y,ymod,wt)
|
||||
use dim_parameter,only: nstat,ndiab,nci,qn,ntot,qn_read
|
||||
use io_parameters,only: llen
|
||||
implicit none
|
||||
integer id_out
|
||||
double precision x(qn),y(ntot),ymod(ntot),wt(ntot)
|
||||
|
||||
integer i,j,k
|
||||
|
||||
18 format(A10,i3)
|
||||
19 format(3F18.8, 2X, F18.6, 4X,*(F12.6))
|
||||
|
||||
! print the nstat output patterns
|
||||
do i=1,nstat
|
||||
write(id_out,19)y(i),ymod(i),ymod(i)-y(i), wt(i), x(1:qn)
|
||||
enddo
|
||||
! loop over number (nci) of metadata with lenght (ndiab)
|
||||
do i=1,nci
|
||||
write(id_out,18) 'nci: ',i
|
||||
do j=1,ndiab
|
||||
k=nstat + (i-1)*ndiab + j
|
||||
write(id_out,19) y(k),ymod(k),(ymod(k)-y(k)),
|
||||
> wt(k), x(1:qn_read)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
end subroutine
|
||||
|
||||
|
||||
|
||||
end module write_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 @@
|
|||
../model/keys.f90
|
||||
|
|
@ -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,246 @@
|
|||
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: Unsupported legacy RNG.'
|
||||
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