Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/.void_file
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/.void_file	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/.void_file	(revision 329)
@@ -0,0 +1,1 @@
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.README
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.README	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.README	(revision 329)
@@ -0,0 +1,16 @@
+# To setup environment variables on NCAR Bluefire SP6
+# Change your shell to bash : 
+# see http://www2.cisl.ucar.edu/docs/bluefire/getting-started
+# tab 'Shell and environment'
+# then put the following lines in your ~/.profile
+
+. /contrib/Modules/3.2.6/init/bash
+module load emacs
+module load netcdf
+module load svn-1.5
+
+export TERM=xterm
+export PATH=${HOME}/bin:/usr/local/bin/:$PATH
+
+# NB : The above PATH lets FCM find GNU make and GNU cpp
+# which are in /usr/local/bin. 
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            xlf
+%LINK                xlf
+%AR                  ar
+%MAKE                /usr/local/bin/gmake
+%FPP_FLAGS           
+%FPP_DEF             
+%BASE_FFLAGS         -qlanglvl=2003pure -u -qintsize=4 -qrealsize=8
+%PROD_FFLAGS         -O3
+%DEV_FFLAGS          -p -g -O3 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -p -g -traceback
+%MPI_FFLAGS
+%OMP_FFLAGS          
+%BASE_LD             -qintsize=4 -qrealsize=8
+%MPI_LD
+%OMP_LD
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-SP6_BLUEFIRE.path	(revision 329)
@@ -0,0 +1,10 @@
+NETCDF_LIBDIR="-L$LIB_NETCDF -lnetcdff"
+NETCDF_INCDIR="-I$NETCDF/include"
+IOIPSL_INCDIR=$LMDGCM/../../lib
+IOIPSL_LIBDIR=$LMDGCM/../../lib
+ORCH_INCDIR=$LMDGCM/../../lib
+ORCH_LIBDIR=$LMDGCM/../../lib
+OASIS_INCDIR=$LMDGCM/../../prism/X64/build/lib/psmile.$couple
+OASIS_LIBDIR=$LMDGCM/../../prism/X64/lib
+INCA_LIBDIR=$LMDGCM/../INCA3/config/lib
+INCA_INCDIR=$LMDGCM/../INCA3/config/lib
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.env	(revision 329)
@@ -0,0 +1,6 @@
+module unload compilerwrappers
+module unload netcdf
+module unload hdf5
+
+module load netcdf/mpi/4.1.3
+module load hdf5/mpi/1.8.9
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.fcm	(revision 329)
@@ -0,0 +1,16 @@
+%COMPILER            mpiifort
+%LINK                mpiifort
+%FPP                 mpiifort -E
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -i4 -r8 -auto -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -g -traceback -O3 -vec-report2
+%DEV_FFLAGS          -g -O1 -traceback
+%DEBUG_FFLAGS        -g -traceback -check bounds -fp-model strict
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp -openmp-threadprivate compat
+%BASE_LD             -i4 -r8 -auto ${MKL_LIBS} -L/smplocal/pub/FFTW/3.3.3_dyn/lib -lfftw3 -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread -Wl,-rpath=/smplocal/pub/NetCDF/4.1.3/mpi/lib:/smplocal/pub/HDF5/1.8.9/par/lib:/smplocal/pub/FFTW/3.3.3_dyn/lib -L../../LMDZ.COMMON/lib -llmdz 
+%MPI_LD
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_ADA.path	(revision 329)
@@ -0,0 +1,15 @@
+#NETCDF_INCDIR="-I $NETCDF_INC_DIR"
+#NETCDF_LIBDIR="-L $NETCDF_LIB_DIR"
+#NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+#HDF5_INCDIR="-I $HDF5_INC_DIR"
+#HDF5_LIBDIR="-L $HDF5_LIB_DIR"
+#HDF5_LIB="-lhdf5_hl -lhdf5 -lhdf5 -lz -lcurl"
+
+XIOS_INCDIR="-I../../XIOS/inc"
+XIOS_LIBDIR="-L../../XIOS/lib"
+XIOS_LIB="-lxios -lstdc++"
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.env	(revision 329)
@@ -0,0 +1,12 @@
+module unload netcdf
+module unload hdf5
+module load netcdf/4.2_hdf5_parallel
+module load  hdf5/1.8.9_parallel
+module load vampir
+module load vampirtrace
+
+#export HDF5_INC_DIR=$WORKDIR/hdf5/include
+#export HDF5_LIB_DIR=$WORKDIR/hdf5/lib
+
+#export NETCDF_INC_DIR=$WORKDIR/netcdf4/include
+#export NETCDF_LIB_DIR=$WORKDIR/netcdf4/lib
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.fcm	(revision 329)
@@ -0,0 +1,16 @@
+%COMPILER            mpif90 
+%LINK                mpif90 
+%FPP                 mpif90 -E
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -i4 -r8 -auto -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -g -traceback -O3 -vec-report2 -xAVX
+%DEV_FFLAGS          -g -O1 -traceback
+%DEBUG_FFLAGS        -g -traceback -check stack -check bounds -fp-model strict
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp -openmp-threadprivate compat
+%BASE_LD             -i4 -r8 -auto $MKL_LIBS
+%MPI_LD
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE.path	(revision 329)
@@ -0,0 +1,15 @@
+NETCDF_INCDIR="-I $NETCDF_INC_DIR"
+NETCDF_LIBDIR="-Wl,-rpath=$NETCDF_LIB_DIR -L$NETCDF_LIB_DIR"
+NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR="-I $HDF5_INC_DIR"
+HDF5_LIBDIR="-Wl,-rpath=$HDF5_LIB_DIR -L$HDF5_LIB_DIR"
+HDF5_LIB="-lhdf5_hl -lhdf5 -lhdf5 -lz -lcurl"
+
+XIOS_INCDIR="-I../../XIOS/inc"
+XIOS_LIBDIR="-L../../XIOS/lib"
+XIOS_LIB="-lxios -lstdc++"
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.env	(revision 329)
@@ -0,0 +1,14 @@
+module unload netcdf
+module unload hdf5
+module load netcdf/4.2_hdf5_parallel
+module load  hdf5/1.8.9_parallel
+module unload vampir
+module unload vampirtrace
+module load vampir
+module load vampirtrace
+
+#export HDF5_INC_DIR=$WORKDIR/hdf5/include
+#export HDF5_LIB_DIR=$WORKDIR/hdf5/lib
+
+#export NETCDF_INC_DIR=$WORKDIR/netcdf4/include
+#export NETCDF_LIB_DIR=$WORKDIR/netcdf4/lib
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.fcm	(revision 329)
@@ -0,0 +1,23 @@
+%COMPILER            vtf90 -vt:f90 "mpif90 -openmp -openmp-threadprivate compat -fno-instrument-functions " -vt:noopari -vt:inst manual -DVTRACE
+%LINK                vtf90 -vt:f90 "mpif90 -openmp -openmp-threadprivate compat -fno-instrument-functions" -vt:noopari -vt:inst manual -DVTRACE 
+%FPP                 vtf90 -vt:f90 "mpif90 -E  -fno-instrument-functions" -vt:noopari -vt:inst manual -DVTRACE
+#%COMPILER            vtf90 -vt:f90 "mpif90 " -vt:inst manual -DVTRACE
+#%LINK                vtf90 -vt:f90 "mpif90" -vt:inst manual -DVTRACE 
+#%FPP                 vtf90 -vt:f90 "mpif90 -E" -vt:inst manual -DVTRACE
+#%COMPILER           ifort
+#%LINK               ifort 
+#%FPP                ifort -E
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P
+%FPP_DEF             KEY_NONE VTRACE CPP_NETCDF4
+#%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -i4 -r8 -auto -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -p -g -traceback -O3 -vec-report2 -xAVX 
+%DEV_FFLAGS          -g -O3 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -g  -fp-model strict -traceback -check bounds
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp
+%BASE_LD             -i4 -r8 -auto $MKL_LIBS
+%MPI_LD
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_CURIE_VAMPIR.path	(revision 329)
@@ -0,0 +1,15 @@
+NETCDF_INCDIR="-I $NETCDF_INC_DIR"
+NETCDF_LIBDIR="-Wl,-rpath=$NETCDF_LIB_DIR -L$NETCDF_LIB_DIR"
+NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR="-I $HDF5_INC_DIR"
+HDF5_LIBDIR="-Wl,-rpath=$HDF5_LIB_DIR -L$HDF5_LIB_DIR"
+HDF5_LIB="-lhdf5_hl -lhdf5 -lhdf5 -lz -lcurl"
+
+XIOS_INCDIR="-I$WORKDIR/XIOS_COMMIT_V1.7/inc"
+XIOS_LIBDIR="-L$WORKDIR/XIOS_COMMIT_V1.7/lib"
+XIOS_LIB="-lxios -lstdc++"
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_HORUS.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_HORUS.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_HORUS.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            mpif90
+%LINK                mpif90
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -fdefault-real-8
+%PROD_FFLAGS         -O3 
+%DEV_FFLAGS          -p -g -O 
+%DEBUG_FFLAGS        -p -g  -fbacktrace -fbounds-check
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp
+%BASE_LD             -p 
+%OMP_LD              -openmp
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_HORUS.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_HORUS.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_HORUS.path	(revision 329)
@@ -0,0 +1,3 @@
+NETCDF_LIBDIR='-L/usr/local/lib -lnetcdff'
+NETCDF_INCDIR=-I/usr/local/include
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.env	(revision 329)
@@ -0,0 +1,4 @@
+module unload PrgEnv-pgi
+module load PrgEnv-intel
+
+module load netcdf
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            ftn 
+%LINK                ftn 
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -i4 -r8 -automatic -align all
+%PROD_FFLAGS         -O3
+%DEV_FFLAGS          -p -g -O3 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -p -g -traceback -check bounds
+%MPI_FFLAGS
+%OMP_FFLAGS          
+%BASE_LD              -i4 -r8 -automatic
+%MPI_LD
+%OMP_LD              
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_LYNX.path	(revision 329)
@@ -0,0 +1,11 @@
+NETCDF_INCDIR="-I$CRAY_NETCDF_DIR/include"
+NETCDF_LIBDIR="-L$CRAY_NETCDF_DIR/lib"
+NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR=""
+HDF5_LIBDIR=""
+HDF5_LIB=""
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.env	(revision 329)
@@ -0,0 +1,10 @@
+#module unload netcdf
+#module unload hdf5
+#module load netcdf/3.6.3
+"module load hdf5
+
+export HDF5_INC_DIR=$WORKDIR/hdf5/include
+export HDF5_LIB_DIR=$WORKDIR/hdf5/lib
+
+export NETCDF_INC_DIR=/fs/local/apps/netcdf-4.1.3_intel/include 
+export NETCDF_LIB_DIR=/fs/local/apps/netcdf-4.1.3_intel/lib
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            ifort 
+%LINK                ifort 
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -i4 -r8 -automatic -align all
+%PROD_FFLAGS         -O3
+%DEV_FFLAGS          -p -g -O3 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -p -g -traceback -check bounds
+%MPI_FFLAGS
+%OMP_FFLAGS          
+%BASE_LD              -i4 -r8 -automatic
+%MPI_LD
+%OMP_LD              
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_MIRAGE.path	(revision 329)
@@ -0,0 +1,11 @@
+NETCDF_INCDIR="-I/fs/local/apps/netcdf-4.1.3_intel/include"
+NETCDF_LIBDIR="-L/fs/local/apps/netcdf-4.1.3_intel/lib"
+NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR=""
+HDF5_LIBDIR=""
+HDF5_LIB=""
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.env	(revision 329)
@@ -0,0 +1,10 @@
+#!/bin/bash
+module unload netcdf
+module unload hdf5
+export NETCDF_INC_DIR="$PWD/../NETCDF4/include"
+export NETCDF_LIB_DIR="$PWD/../NETCDF4/lib"
+export HDF5_INC_DIR="/opt/software/libraries/hdf5/hdf51.8.14/include"
+export HDF5_LIB_DIR="/opt/software/libraries/hdf5/hdf51.8.14/lib"
+module load intel/14.0.4.211
+module load bullmpi/1.2.8.1
+module load hdf5/1.8.14_parallel
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.fcm	(revision 329)
@@ -0,0 +1,16 @@
+%COMPILER            mpif90 
+%LINK                mpif90 
+%FPP                 mpif90 -E
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -i4 -r8 -auto -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -g -traceback -O3 -vec-report2 -xAVX
+%DEV_FFLAGS          -g -O1 -traceback
+%DEBUG_FFLAGS        -g -traceback -check stack -check bounds -fp-model strict
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp -openmp-threadprivate compat
+%BASE_LD             -i4 -r8 -auto $MKL_LIBS
+%MPI_LD
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OCCIGEN.path	(revision 329)
@@ -0,0 +1,15 @@
+NETCDF_INCDIR="-I$NETCDF_INC_DIR"
+NETCDF_LIBDIR="-L$NETCDF_LIB_DIR"
+NETCDF_LIB="-lnetcdff -lnetcdf "
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR="-I$HDF5_INC_DIR"
+HDF5_LIBDIR="-L$HDF5_LIB_DIR"
+HDF5_LIB="-lhdf5_hl -lhdf5 -lhdf5 -lz"
+
+XIOS_INCDIR="-I../../XIOS/inc"
+XIOS_LIBDIR="-L../../XIOS/lib"
+XIOS_LIB="-lxios -lstdc++"
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.README
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.README	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.README	(revision 329)
@@ -0,0 +1,12 @@
+# MacPorts environment :
+# sudo port install gcc45
+# sudo port select gcc mp-gcc45
+# sudo port install netcdf-fortran +gcc45
+
+# for VTKMapper
+# sudo port install python27
+# sudo port select python python27
+# sudo port install vtk5 +python27
+# sudo port install hdf5-18 +gcc45
+# compile python->NetCDF interface netCDF4-0.9.3
+#      sudo python setup.py install
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.fcm	(revision 329)
@@ -0,0 +1,16 @@
+%COMPILER            gfortran
+%LINK                gfortran
+%AR                  ar
+%MAKE                gmake
+%FPP                 gfortran -E
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE CPP_NETCDF4
+%BASE_FFLAGS         -I /opt/local/include -fdefault-real-8 -ffree-line-length-none
+%PROD_FFLAGS         -O3 
+%DEV_FFLAGS          -p -g -O 
+%DEBUG_FFLAGS        -p -g  -fbacktrace -fbounds-check
+%MPI_FFLAGS
+%OMP_FFLAGS          
+%BASE_LD             -p -L/opt/local/lib  -lnetcdff -lnetcdf
+%OMP_LD              
+%OMP_LD              
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_OSX.path	(revision 329)
@@ -0,0 +1,11 @@
+NETCDF_LIBDIR=
+NETCDF_INCDIR=
+IOIPSL_INCDIR=$LMDGCM/../IOIPSL/src/
+IOIPSL_LIBDIR=$LMDGCM/../IOIPSL/src/
+ORCH_INCDIR=/work/cont003/p86yann/ORCHIDEE_1_9_2_OMP_MEM/lib_cpl
+ORCH_LIBDIR=/work/cont003/p86yann/ORCHIDEE_1_9_2_OMP_MEM/lib_cpl
+OASIS_INCDIR=$LMDGCM/../../prism/IA64/build/lib/psmile.$couple
+OASIS_LIBDIR=$LMDGCM/../../prism/IA64/lib
+INCA_LIBDIR=$LMDGCM/../INCA3/config/lib
+INCA_INCDIR=$LMDGCM/../INCA3/config/lib
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.env	(revision 329)
@@ -0,0 +1,10 @@
+module unload netcdf
+module unload hdf5
+module load netcdf/3.6.3
+module load hdf5
+
+#export HDF5_INC_DIR=$WORKDIR/hdf5/include
+#export HDF5_LIB_DIR=$WORKDIR/hdf5/lib
+
+#export NETCDF_INC_DIR=$WORKDIR/netcdf4/include
+#export NETCDF_LIB_DIR=$WORKDIR/netcdf4/lib
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            mpif90
+%LINK                mpif90
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE 
+%BASE_FFLAGS         -i4 -r8 -automatic -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -O3 -openmp
+%DEV_FFLAGS          -p -g -O3 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -p -g -traceback -check bounds
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp
+%BASE_LD             -openmp -i4 -r8 -automatic $MKL_LIBS
+%MPI_LD
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE.path	(revision 329)
@@ -0,0 +1,11 @@
+NETCDF_INCDIR="-I $NETCDF_INC_DIR"
+NETCDF_LIBDIR="-L $NETCDF_LIB_DIR"
+NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR="-I $HDF5_INC_DIR"
+HDF5_LIBDIR="-L $HDF5_LIB_DIR"
+HDF5_LIB="-lhdf5_hl -lhdf5 -lhdf5 -lz -lcurl"
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.env
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.env	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.env	(revision 329)
@@ -0,0 +1,4 @@
+module unload netcdf
+module unload hdf5
+module load netcdf/3.6.3
+module load hdf5
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            ifort
+%LINK                ifort
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE 
+%BASE_FFLAGS         -i4 -r8 -automatic -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -O3 -openmp
+%DEV_FFLAGS          -p -g -O3 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -p -g -traceback -check bounds
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp
+%BASE_LD             -openmp -i4 -r8 -automatic $MKL_LIBS
+%MPI_LD
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-X64_TITANE_SEQ.path	(revision 329)
@@ -0,0 +1,11 @@
+NETCDF_INCDIR="-I $NETCDF_INC_DIR"
+NETCDF_LIBDIR="-L $NETCDF_LIB_DIR"
+NETCDF_LIB="-lnetcdff -lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
+
+HDF5_INCDIR="-I $HDF5_INC_DIR"
+HDF5_LIBDIR="-L $HDF5_LIB_DIR"
+HDF5_LIB="-lhdf5_hl -lhdf5 -lhdf5 -lz -lcurl"
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skd.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skd.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skd.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            gfortran 
+%LINK                gfortran
+%AR                  ar
+%MAKE                make
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE
+%BASE_FFLAGS         -I/home/sarvesh/LMDZS/netcdf-4.0.1/include -fdefault-real-8
+%PROD_FFLAGS         -O3 
+%DEV_FFLAGS          -p -g -O 
+%DEBUG_FFLAGS        -p -g  -fbacktrace -fbounds-check
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp
+%BASE_LD             -p  -L/home/sarvesh/LMDZS/netcdf-4.0.1/lib  -lnetcdf  -lblas -llapack
+%MPI_LD             
+%OMP_LD              -openmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skd.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skd.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skd.path	(revision 329)
@@ -0,0 +1,9 @@
+#NETCDF_LIBDIR='/usr/lib -lnetcdf'
+#NETCDF_INCDIR='/usr/include'
+NETCDF_LIBDIR="-L /home/sarvesh/LMDZS/netcdf-4.0.1/lib"
+NETCDF_INCDIR="-I /home/sarvesh/LMDZS/netcdf-4.0.1/include"
+NETCDF_LIB="-lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skdmpi.fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skdmpi.fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skdmpi.fcm	(revision 329)
@@ -0,0 +1,15 @@
+%COMPILER            mpif90 
+%LINK                mpif90
+%AR                  ar
+%MAKE                make
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             KEY_NONE
+%BASE_FFLAGS         -I/home/sarvesh/LMDZS/netcdf-4.0.1/include -fdefault-real-8
+%PROD_FFLAGS         -O3 
+%DEV_FFLAGS          -p -g -O 
+%DEBUG_FFLAGS        -p -g  -fbacktrace -fbounds-check
+%MPI_FFLAGS
+%OMP_FFLAGS          -fopenmp
+%BASE_LD             -p  -L/home/sarvesh/LMDZS/netcdf-4.0.1/lib  -lnetcdf  -lblas -llapack
+%MPI_LD             
+%OMP_LD              -fopenmp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skdmpi.path
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skdmpi.path	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/arch/arch-x86_skdmpi.path	(revision 329)
@@ -0,0 +1,9 @@
+#NETCDF_LIBDIR='/usr/lib -lnetcdf'
+#NETCDF_INCDIR='/usr/include'
+NETCDF_LIBDIR="-L /home/sarvesh/LMDZS/netcdf-4.0.1/lib"
+NETCDF_INCDIR="-I /home/sarvesh/LMDZS/netcdf-4.0.1/include"
+NETCDF_LIB="-lnetcdf"
+
+MPI_INCDIR=""
+MPI_LIBDIR=""
+MPI_LIB=""
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/bld.cfg
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/bld.cfg	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/bld.cfg	(revision 329)
@@ -0,0 +1,46 @@
+# ----------------------- FCM extract configuration file -----------------------
+cfg::type                           bld
+cfg::version                        1.0
+
+
+# ------------------------------------------------------------------------------
+# Build information
+# ------------------------------------------------------------------------------
+
+inc arch.fcm
+inc config.fcm
+
+%FFLAGS           %BASE_FFLAGS %COMPIL_FFLAGS
+
+#dest   $PWD
+dir::root            $PWD
+
+src::src	src
+src::ioipsl	tools/ioipsl
+search_src           false
+bld::lib::ioipsl ioipsl
+bld::target libioipsl.a
+bld::target icosa_gcm.exe
+
+bld::tool::fc        %COMPILER
+bld::tool::ld        %LINK
+bld::tool::ldflags   %LD_FLAGS  -L../../LMDZ.COMMON/lib -llmdz %LIB 
+bld::tool::fflags    %FFLAGS 
+bld::tool::fppkeys   %CPP_KEY %FPP_DEF
+bld::tool::fpp       %FPP
+bld::tool::fppflags  %FPP_FLAGS
+
+#bld::tool::fflags::src::transfert_mpi  %BASE_FFLAGS  %DEBUG_FFLAGS %OMP_FFLAGS -I/ccc/work/cont003/dsm/p86yann/XIOS_COMMIT_V1.7/inc -I /usr/local/netcdf-4.2_hdf5_parallel/include
+#bld::tool::fflags::src::check_conserve %BASE_FFLAGS  %DEBUG_FFLAGS %OMP_FFLAGS -I/ccc/work/cont003/dsm/p86yann/XIOS_COMMIT_V1.7/inc -I /usr/local/netcdf-4.2_hdf5_parallel/include
+
+
+# Pre-process code before analysing dependencies
+bld::pp              false
+
+bld::excl_dep        use::netcdf
+bld::excl_dep        use::omp_lib
+bld::excl_dep        inc::mpif.h
+bld::excl_dep        use::xios
+
+bld::tool::SHELL   /bin/bash
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/build
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/build	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/build	(revision 329)
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+export PATH=$PWD/../tools/FCM/bin:$PATH
+fcm build  $*
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/clean
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/clean	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/clean	(revision 329)
@@ -0,0 +1,10 @@
+rm -rf ./obj
+rm -rf ./done
+rm -rf ./inc
+rm -rf ./flags
+rm -rf ./ppsrc
+rm -rf ./lib
+rm -rf ./bin
+rm -rf ./bld
+rm -rf ./etc
+rm  ./config.fcm  ./fcm_env.ksh  ./arch.env ./arch.fcm ./arch.path 
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_curie
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_curie	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_curie	(revision 329)
@@ -0,0 +1,3 @@
+./make_icosa -prod -parallel mpi_omp -with_xios -arch X64_CURIE -job 8  
+#./make_icosa -prod -arch X64_CURIE  -job 8 
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_ada
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_ada	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_ada	(revision 329)
@@ -0,0 +1,6 @@
+cd ../LMDZ.COMMON
+#rm -rf libo
+./makelmdz_fcm -s 1 -d 32x24x64 -b 20x30 -io none -arch X64_ADA -parallel mpi -p std -j 8 -full gcm
+cd ../ICOSAGCM
+rm bin/icosa_gcm.exe
+./make_icosa -arch X64_ADA -parallel mpi -job 8 -full -with_xios
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_curie
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_curie	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_curie	(revision 329)
@@ -0,0 +1,5 @@
+cd ../LMDZ.COMMON
+./compile_curie
+cd ../ICOSAGCM
+rm bin/icosa_gcm.exe
+./compile_curie
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_occigen
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_occigen	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_dynlmdz_occigen	(revision 329)
@@ -0,0 +1,5 @@
+cd ../LMDZ.COMMON
+./compile_occigen
+cd ../ICOSAGCM
+rm bin/icosa_gcm.exe
+./compile_occigen
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_occigen
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_occigen	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/compile_occigen	(revision 329)
@@ -0,0 +1,3 @@
+./make_icosa -prod -parallel mpi_omp -with_xios -arch X64_OCCIGEN -job 8  
+#./make_icosa -prod -arch X64_CURIE  -job 8 
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/make_icosa
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/make_icosa	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/make_icosa	(revision 329)
@@ -0,0 +1,139 @@
+#!/bin/bash
+set -x
+export PATH=$PWD/tools/FCM/bin:$PATH
+
+compil_mode_defined="FALSE"
+compil_mode="prod"
+
+job=1
+full_defined="FALSE"
+with_xios_defined="FALSE"
+arch_defined="FALSE"
+parallel_defined="FALSE"
+arch=""
+parallel="none"
+CPP_KEY="CPP_NONE" 
+ICOSA_LIB=""
+
+while (($# > 0))
+  do
+  case $1 in
+      "-h") cat <<fin
+Usage :
+makegcm [options] -m arch exec
+[-h]                       : help
+[-prod / -dev / -debug]    : compilation en mode production (default) / developpement / debug .
+ -arch nom_arch            : nom de l\'architecture cible
+fin
+	  exit;;
+
+      "-prod")
+	  compil_mode="prod" ; shift ;;
+
+      "-dev")
+	  compil_mode="dev" ; shift ;;
+
+      "-debug")
+	  compil_mode="debug" ; shift ;;
+
+      "-arch")
+	  arch=$2 ; arch_defined="TRUE"; shift ; shift ;;
+
+      "-parallel")
+	  parallel=$2 ; parallel_defined="TRUE"; shift ; shift ;;
+
+      "-job")
+	  job=$2 ; shift ; shift;;
+
+      "-full")
+	  full_defined="TRUE" ; shift ;;
+
+      "-with_xios")
+	  with_xios_defined="TRUE" ; shift ;;
+
+      *)
+	  code="$1" ; shift ;;
+  esac
+done
+
+rm -f .void_file
+echo > .void_file
+rm -rf .void_dir
+mkdir .void_dir
+
+if [[ "$arch_defined" == "TRUE" ]]
+then
+  rm -f arch.path
+  rm -f arch.fcm
+  rm -f arch.env
+  ln -s arch/arch-${arch}.path ./arch.path
+  ln -s arch/arch-${arch}.fcm  ./arch.fcm
+  if test -f arch/arch-${arch}.env
+    then
+      ln -s arch/arch-${arch}.env arch.env
+    else
+      ln -s .void_file arch.env
+    fi
+  source arch.env
+  source arch.path
+else
+  echo "Veuillez definir une architecture cible"
+  exit 1
+fi
+
+LD_FLAGS="%BASE_LD"
+
+if [[ "$compil_mode" == "prod" ]]
+then
+  COMPIL_FFLAGS="%PROD_FFLAGS"
+elif [[ "$compil_mode" == "dev" ]]
+then
+  COMPIL_FFLAGS="%DEV_FFLAGS"
+elif [[ "$compil_mode" == "debug" ]]
+then
+  COMPIL_FFLAGS="%DEBUG_FFLAGS"
+fi
+
+if [[ "$parallel" == "mpi" ]]
+then
+  CPP_KEY="$CPP_KEY CPP_USING_MPI"
+elif [[ "$parallel" == "omp" ]]
+then
+  CPP_KEY="$CPP_KEY CPP_USING_OMP"
+  COMPIL_FFLAGS="$COMPIL_FFLAGS %OMP_FFLAGS"
+  LD_FLAGS="$LD_FLAGS %OMP_LD"
+elif [[ "$parallel" == "mpi_omp" ]]
+then
+  CPP_KEY="$CPP_KEY CPP_USING_MPI CPP_USING_OMP"
+  COMPIL_FFLAGS="$COMPIL_FFLAGS %OMP_FFLAGS"
+  LD_FLAGS="$LD_FLAGS %OMP_LD"
+elif [[ "$parallel" == "none" ]]
+then
+  parallel="none"
+else 
+  echo "-parallel value $parallel is invalid, only permited <none>, <mpi>, <omp> or <mpi_omp>"
+  exit 1
+fi
+
+if [[ "$with_xios_defined" == "TRUE" ]]
+then
+  CPP_KEY="$CPP_KEY CPP_USING_XIOS"
+  COMPIL_FFLAGS="$COMPIL_FFLAGS $XIOS_INCDIR"
+  ICOSA_LIB="$ICOSA_LIB $XIOS_LIBDIR $XIOS_LIB"
+fi  
+
+ICOSA_LIB="$ICOSA_LIB $NETCDF_LIBDIR $NETCDF_LIB $HDF5_LIBDIR $HDF5_LIB"
+
+rm -f config.fcm
+
+echo "%COMPIL_FFLAGS $COMPIL_FFLAGS $NETCDF_INCDIR" >> config.fcm
+echo "%LD_FLAGS $LD_FLAGS" >> config.fcm
+echo "%CPP_KEY $CPP_KEY" >> config.fcm
+echo "%LIB $ICOSA_LIB">> config.fcm
+
+if [[ "$full_defined" == "TRUE" ]]
+then
+  ./build --job $job --full
+else
+  ./build --job $job
+fi
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/climate/Held_Suarez/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/climate/Held_Suarez/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/climate/Held_Suarez/earth_const.def	(revision 329)
@@ -0,0 +1,17 @@
+#planetary radius : real (default=37122E6)
+radius=6.4E6   #6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5 
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.
+
+# Reference pressure : real (default=101325.)
+preff=100000.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/climate/Held_Suarez/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/climate/Held_Suarez/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/climate/Held_Suarez/run.def	(revision 329)
@@ -0,0 +1,96 @@
+INCLUDEDEF=earth_const.def
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1.
+
+# ------------------------------- Mesh ---------------------------------
+# nbp                 20  40  80 160
+# T-edge length (km) 500 250 120  60
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=40
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=2
+nsplit_j=3
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=19
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=std
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=1000
+
+# ---------------------------------- Time --------------------------------
+
+# scheme type : string ( default='runge_kutta') euler, leapfrog_matsuno, runge_kutta )
+scheme = runge_kutta
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# advection called every itau_adv time steps : integer (default 2)
+# standard : umax=100m/s vs c=340m/s (ratio 1:3)
+# in JW06 umax=35m/s vs c=340m/s (ratio 1:10)
+itau_adv= 1
+
+# time_style
+time_style=lmd 
+
+# Number of days
+ndays=1200
+
+# NUBER of day_step
+day_step= 180
+
+# output field period : integer (default none)
+write_period=86400
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=1
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, dcmip[1-4] ,heldsz
+etat0=held_suarez 
+
+# ------------------------------ Dynamics --------------------------------
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+caldyn_conserv=energy
+caldyn_exner=direct
+caldyn_hydrostat=direct
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 50000
+
+# number of iteration for graddiv : integer (default=1)
+nitergdiv = 2
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 50000
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad= 50000
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# Rayleigh friction : string (default=none) : none, dcmip2_schaer_noshear, dcmip2_schaer_shear
+rayleigh_friction_type=none
+
+#----------------------------physics-------------------------------------
+physics=automatic
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test1/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test1/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test1/earth_const.def	(revision 329)
@@ -0,0 +1,17 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=0.
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test1/run11.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test1/run11.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test1/run11.def	(revision 329)
@@ -0,0 +1,119 @@
+INCLUDEDEF=earth_const.def
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1.
+
+# ------------------------------- Mesh ---------------------------------
+
+# nbp                 20  40  80 160
+# T-edge length (km) 500 250 120  60
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=80
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=2
+nsplit_j=2
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=60
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncar
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=200.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=100
+
+# ---------------------------------- Time --------------------------------
+
+# scheme type : string ( default='runge_kutta') euler, leapfrog_matsuno, runge_kutta )
+scheme = runge_kutta
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# timestep : real (default=480s)
+dt = 180.
+
+# advection called every itau_adv time steps : integer (default 2)
+# standard : umax=100m/s vs c=340m/s (ratio 1:3)
+# in JW06 umax=35m/s vs c=340m/s (ratio 1:10)
+itau_adv=1
+
+# number of timestep (default 100)
+itaumax = 10
+
+# run length : real (default=dt*itaumax)
+run_length=1036800
+
+# output field period : integer (default none)
+write_period=86400
+
+# ---------------------------------- Misc --------------------------------
+
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=5
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, dcmip[1-4]
+etat0=dcmip1
+
+# ------------------------------ Dynamics --------------------------------
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=adv
+
+# guided_type : string (default=none) : none, ncar
+guided_type=dcmip1
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 1800
+
+# number of iteration for graddiv : integer (default=1)
+nitergdiv = 1
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 1800
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=1800
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# Rayleigh friction : string (default=none) : none, dcmip2_schaer_noshear, dcmip2_schaer_shear
+rayleigh_friction_type=none
+
+# -------------------- Parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley, dcmip11
+dcmip1_shape=dcmip11
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+dcmip1_wind=deform
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test2/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test2/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test2/earth_const.def	(revision 329)
@@ -0,0 +1,17 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=0.
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test2/run21.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test2/run21.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test2/run21.def	(revision 329)
@@ -0,0 +1,125 @@
+INCLUDEDEF=earth_const.def
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=500.
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=60
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=1
+nsplit_j=1
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=60
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncar
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=500.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=1
+
+# timestep : real (default=90s for nbp=40)
+dt = 60.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=3.6e6
+
+# output field period : integer (default none)
+write_period=50000
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip2_schaer_noshear
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 1800
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 1800
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=1800
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=complement
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=deform
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/earth_const.def	(revision 329)
@@ -0,0 +1,20 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=0.
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=125.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=60          
+##PBS -l mppnppn=12              
+#PBS -l walltime=00:30:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 60 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test3/run.def	(revision 329)
@@ -0,0 +1,138 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=80
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=2
+nsplit_j=3
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=10
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncar
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=1
+
+# timestep : real (default=90s)
+dt = 45.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=450000
+
+# output field period : integer (default none)
+write_period=12500
+
+# pression value to interpolate output : real (default=0, no output)
+out_pression_level=0.
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip3
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 900
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 900
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad= 900
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- physics ------------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=dcmip
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=complement
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=deform
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=1
+
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/earth_const.def	(revision 329)
@@ -0,0 +1,23 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1.
+
+# Precision of NetCDF output
+netcdf_prec = float
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=160          
+##PBS -l mppnppn=12              
+#PBS -l walltime=01:00:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 160 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-0/run.def	(revision 329)
@@ -0,0 +1,141 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=40
+
+# nbp                 20  40  80 160
+# T-edge length (km) 500 250 120  60
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=1
+nsplit_j=1
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=30
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncarl30
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+#optim_it=1000
+optim_it=0
+
+# ---------------------------------- Time---------------------------------
+
+# scheme type : string ( default='runge_kutta') euler, leapfrog_matsuno, runge_kutta )
+scheme = runge_kutta   leapfrog_matsuno 
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# timestep : real (default=480s)
+dt = 480.
+
+# advection called every itau_adv time steps : integer (default 2)
+# standard : umax=100m/s vs c=340m/s (ratio 1:3)
+# in JW06 umax=35m/s vs c=340m/s (ratio 1:10)
+itau_adv=3
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=2592000
+#run_length=432000
+#run_length=86400
+
+# output field period : integer (default none)
+write_period=86400
+# write_period=14400
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=2
+
+# pression value where output is interpolated : real (default=0, no output)
+out_pression_level=85000
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip4
+
+# ------------------------------ Dynamics --------------------------------
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# caldyn_conserv : string (default=energy) : energy,enstrophy
+caldyn_conserv=energy
+
+# caldyn_exner : scheme for computing Exner function : string (default=direct) : direct,lmdz
+caldyn_exner=direct
+
+# caldyn_hydrostat : scheme for computing geopotential : string (default=direct) : direct,lmdz
+caldyn_hydrostat=direct
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ---------------------------------- Dissipation ---------------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 5000
+
+# number of iteration for graddiv : integer (default=1)
+nitergdiv = 2
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 5000
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad= 5000
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# Rayleigh friction : string (default=none) : none, dcmip2_schaer_noshear, dcmip2_schaer_shear
+rayleigh_friction_type=none
+
+# -------------------------------- Physics -------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=none
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=1
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/earth_const.def	(revision 329)
@@ -0,0 +1,20 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=10.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=60          
+##PBS -l mppnppn=12              
+#PBS -l walltime=00:30:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 60 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-1/run.def	(revision 329)
@@ -0,0 +1,138 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=80
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=4
+nsplit_j=4
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=30
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncarl30
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=2
+
+# timestep : real (default=90s)
+dt = 45.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=2592000
+
+# output field period : integer (default none)
+write_period=86400
+
+# pression value whera output is interpolated : real (default=0, no output)
+out_pression_level=85000
+
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip4
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 350
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 350
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=350
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- physics ------------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=none
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -----------------------------------------------------------------------
+
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=1
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/earth_const.def	(revision 329)
@@ -0,0 +1,20 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=100.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=60          
+##PBS -l mppnppn=12              
+#PBS -l walltime=00:30:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 60 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-2/run.def	(revision 329)
@@ -0,0 +1,138 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=80
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=4
+nsplit_j=4
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=30
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncarl30
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=2
+
+# timestep : real (default=90s)
+dt = 45.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=2592000
+
+# output field period : integer (default none)
+write_period=86400
+
+# pression value whera output is interpolated : real (default=0, no output)
+out_pression_level=85000
+
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip4
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 350
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 350
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=350
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- physics ------------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=none
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -----------------------------------------------------------------------
+
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=1
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/earth_const.def	(revision 329)
@@ -0,0 +1,20 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1000.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=60          
+##PBS -l mppnppn=12              
+#PBS -l walltime=00:30:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 60 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.1/test4.1-3/run.def	(revision 329)
@@ -0,0 +1,138 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=80
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=4
+nsplit_j=4
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=30
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncarl30
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=2
+
+# timestep : real (default=90s)
+dt = 45.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=2592000
+
+# output field period : integer (default none)
+write_period=86400
+
+# pression value whera output is interpolated : real (default=0, no output)
+out_pression_level=85000
+
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip4
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 350
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 350
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=350
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- physics ------------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=none
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -----------------------------------------------------------------------
+
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=1
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/earth_const.def	(revision 329)
@@ -0,0 +1,20 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=60          
+##PBS -l mppnppn=12              
+#PBS -l walltime=00:30:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 60 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-0/run.def	(revision 329)
@@ -0,0 +1,134 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=80
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=2
+nsplit_j=3
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=30
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncarl30
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=2
+
+# timestep : real (default=90s)
+dt = 45.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=1296000
+
+# output field period : integer (default none)
+write_period=21600
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip4
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 1800
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 1800
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=1800
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- physics ------------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=dcmip
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -----------------------------------------------------------------------
+
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=2
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/earth_const.def	(revision 329)
@@ -0,0 +1,20 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/job_lynx
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/job_lynx	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/job_lynx	(revision 329)
@@ -0,0 +1,14 @@
+#!/bin/bash
+#PBS -N icosagcm              
+#PBS -q workshop                 
+#PBS -l mppwidth=160          
+##PBS -l mppnppn=12              
+#PBS -l walltime=00:30:00      
+#PBS -e icosagcm.out             
+#PBS -j eo                     
+#PBS -V                        
+cd $PBS_O_WORKDIR    
+
+export MPICH_MAX_SHORT_MSG_SIZE=1024
+	           
+aprun -n 160 ./icosa_gcm.exe > out         
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/dcmip2012/test4/test4.2/test4.2-1/run.def	(revision 329)
@@ -0,0 +1,134 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=160
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=4
+nsplit_j=4
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=30
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=ncarl30
+
+# ncar_dz : model layer thickness in meters: real (default=400) 
+# used if disvert=ncar
+ncar_dz=1000.
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+optim_it=0
+
+# ------------------------------------------------------------------------
+
+
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=2
+
+# timestep : real (default=90s)
+dt = 22.
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=1296000
+
+# output field period : integer (default none)
+write_period=21600
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=dcmip4
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# ----------------------------------------------------------------------
+
+
+
+
+# ------------------------------ Dynamics --------------------------------
+
+# scheme type : string ( default='adam_bashforth') euler, leapfrog, leapfrog_matsuno, adam_bashforth)
+scheme = adam_bashforth
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ----------------------------------------------------------------------
+
+
+
+# ------------------------------ Dissipation ---------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 900
+
+# number of iteration for graddiv : integer (default=1)
+ nitergdiv = 1
+
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 900
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad= 900
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# -----------------------------------------------------------------------
+
+
+# -------------------- physics ------------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=dcmip
+
+# testcase physics for dcmip : INTEGER : 1, 2 (default=1)
+dcmip_physics=1
+
+# -----------------------------------------------------------------------
+
+
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=2
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/make_rundefs.sh
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/make_rundefs.sh	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/make_rundefs.sh	(revision 329)
@@ -0,0 +1,245 @@
+#!/bin/bash
+
+function print()
+{
+    # prints one comment line followed by any number of "key = value" lines
+    echo "# $1 : $2 (default=$3)"
+    shift; shift; shift;
+    while (($# > 0)) ; do
+	echo "$1 = $2"
+	shift; shift;
+    done
+    echo
+}
+
+################################### Planet #######################################
+ 
+function radius { print 'Planetary radius' real 37122E6 radius $1 
+}
+function g      { print Gravity real 9.80616 g $1 
+}
+function omega { print 'Planetary rotation rate' real 7.292E-5 omega $1 
+}
+function kappa { print 'kappa=Rd/cpp' real 0.2857143 kappa $1 
+}
+function cpp	 { print 'Heat capacity at constant pressure' real 1004.70885 cpp $1
+}
+function preff { print 'Reference pressure' real 101325 preff $1 
+}
+function scale_factor { print 'Scale factor for small planet experiment' real 1. scale_factor $1 
+}
+
+##################################### Mesh #####################################
+
+function nbp   { print 'Number of subdivisions on a main triangle' integer 40 nbp $1 
+}
+function split { print 'Sub splitting of main rhombus' integer 1 nsplit_i $1 nsplit_j $2 
+}
+function llm   { print 'Number of vertical layers' integer 19 llm $1 
+}
+function disvert { print 'Vertical grid' '[std|ncar|ncarl30]' std disvert $1 
+}
+function ncar_dz { print 'Model layer thickness in m, used if disvert=ncar' real 300 ncar_dz $1
+}
+function optim_it { print 'Mesh optimisation : number of iterations' integer 0 optim_it $1 
+}
+
+################################# Numerics ###################################
+
+function scheme { print 'Time-stepping scheme' '[euler|leapfrog_matsuno|runge_kutta]' runge_kutta scheme $1 
+}
+function time_step { print 'Time step in s' real 480 dt $1 
+}
+function matsuno { print 'Matsuno period' integer 5 matsuno_period $1 
+}
+function itau_adv { print 'Advection called every itau_adv time steps' integer 2 itau_adv $1 
+}
+function nqtot { print 'Number of tracers' integer 1 nqtot $1 
+}
+function caldyn { print 'Equations solved' '[gcm|adv]' gcm caldyn $1 
+}
+function caldyn_conserv { print 'Discretization of Coriolis term' '[energy|enstophy]' energy caldyn_conserv $1 
+}
+function caldyn_eta { print 'Vertical coordinate' '[eta_mass|eta_lag]' mass caldyn_eta $1 
+}
+function boussinesq { print 'Boussinesq approximation, requires eta_lag' '[.FALSE.|.TRUE.]' .FALSE. boussinesq $1
+}
+############################### Time and output ###############################
+
+function time_style() { print 'Time style' '[none|lmd]' lmd time_style $1 
+}
+function ndays() { print 'Number of days' integer ?? ndays $1 
+}
+function run_length() { print 'Run length in s' real ?? run_length $1 
+}
+function day_step { print 'Number of time steps per day' integer ?? day_step $1 
+}
+function write_period { print 'Interval in s between two outputs' integer ?? write_period $1 
+}
+function out_pressure_level { print 'Pressure level to which interpolate T' real 0 out_pression_level $1
+}
+
+################################ Physics ######################################
+
+function etat0 { 
+    OPTS=$(printf '\n#   [jablonowsky06|academic|dcmip[1-4]|heldsz|dcmip2_schaer_noshear|dcmip3]')
+    print 'Initial state' "$OPTS" jablonowsky06 etat0 $1 
+}
+function dissip
+{
+    print 'Dissipation time for grad(div)' real 5000 tau_graddiv $1
+    print 'Exponent of grad(div) disspation' integer 1 nitergdiv $2
+    print 'Dissipation time for curl(curl)' real 5000 tau_gradrot $3
+    print 'Exponent of curl(curl) disspation' integer 1 nitergrot $4
+    print 'Dissipation time for div(grad)' real 5000 tau_divgrad $5
+    print 'Exponent of div(grad) disspation' integer 1 niterdivgrad $6
+}
+function guided_type { print 'Type of guiding terms' '[none|dcmip1]' none guided_type $1 
+}
+
+function physics { print 'Physics package' '[automatic|dcmip]' automatic physics $1
+}
+
+#################################### DCMIP #################################
+
+function dcmip1_def()
+{
+    OPTS=$(printf '\n#    [const|slotted_cyl|cos_bell|dbl_cos_bell_q1|dbl_cos_bell_q2|complement|hadley|dcmip11]')
+    print 'DCMIP 1.1 advection test, initial tracer field' "$OPTS" cos_bell dcmip1_shape $1
+    print 'DCMIP 1.1 advection test, wind field' '[solid|deform|hadley]' deform dcmip1_shape $2
+}
+function dcmip_refs()
+{
+    print 'Reference temperature T0 for DCMIP test cases' real 300 ncar_T0 $1
+    print 'Reference pressure p0 for DCMIP test cases, used by disvert if disver=ncar' real 1e5 ncar_p0 $2
+    print 'Exponent for B(eta), used by disvert if disvert=ncar' integer 1 ncar_disvert_c $3
+}
+function dcmip_physics()
+{
+    physics dcmip
+    print 'DCMIP physics' '[0|1]' 1 dcmip_physics $1
+}
+function dcmip4_testcase { print 'DCMIP 4 Test case' '[1|2]' 1 dcmip4_testcase $1 
+}
+
+####################### Functions generating parameter files ####################
+
+function params {
+    # executes any number of "command arg" commands
+    while (($# > 0)) ; do
+	$1 $2
+	shift; shift;
+    done
+}
+
+function group { 
+    # prints one separation line then executes any number of "command arg" commands
+    echo
+    echo "#---------------- $1 ----------------"
+    echo
+    shift
+    params $*
+}
+
+function williamson91()
+{
+    group 'Mesh' nbp 40 llm 1 optim_it 100 ; split 2 2
+    group 'Numerics' time_step 480 caldyn_conserv enstrophy
+    group 'Time and output' out_pressure_level 85000 write_period 21600 run_length 864000
+    group 'Physical parameters' radius 6.37122e6 g 9.80616 caldyn_eta eta_lag boussinesq .TRUE. etat0 williamson91.6
+    dissip 5000 2 5000 2 5000 2    
+}
+
+function held_suarez()
+{
+    group 'Mesh' nbp 40 llm 19 disvert std optim_it 1000 ; split 2 2
+    group 'Numerics' itau_adv 1 day_step 180
+    group 'Time' time_style lmd ndays 1200 write_period 86400
+    group 'Planet' radius 6.371e6 g 9.8 omega 7.292e-5 kappa 0.2857143 cpp 1004 preff 1e5
+    group 'Physical parameters' etat0 held_suarez nqtot 1
+    dissip 50000 2 50000 2 50000 2
+}
+
+function const_dcmip
+{
+    group 'Planet' radius 6.37122e6 g 9.80616 kappa 0.2857143 cpp 1004.5 preff 1e5 omega $1 
+    group 'Constants' ; dcmip_refs 300 1e5 1
+}
+
+function dcmip11
+{
+    echo 'INCLUDEDEF = const.def'
+    group 'Mesh' nbp 80 llm 60 disvert ncar ncar_dz 200 optim_it 100 ; split 2 2
+    group 'Numerics' caldyn adv time_step 180
+    group 'Time' run_length 1036800 write_period 86400
+    group 'Physical parameters' guided_type dcmip1 ; dcmip1_def dcmip11 deform
+}
+
+function dcmip21
+{
+    echo 'INCLUDEDEF = const.def'
+    group 'Mesh' nbp 64 llm 60 disvert ncar ncar_dz 500 optim_it 100 ; split 2 2
+    group 'Numerics' time_step 300
+    dissip 1800 1 1800 2 1800 2
+    group 'Time' run_length 3.6e6 write_period 50000
+    group 'Physical parameters' scale_factor 500 guided_type dcmip1 nqtot 1 etat0 dcmip2_schaer_noshear
+}
+
+function dcmip3
+{
+    const_dcmip 0
+    group 'Mesh' nbp 80 llm 10 disvert ncar ncar_dz 1000 optim_it 100 ; split 2 2
+    group 'Numerics' time_step 240
+    dissip 1800 1 1800 2 1800 2
+    group 'Time' run_length 4.5e5 write_period 12500
+    group 'Physical parameters' omega 0 scale_factor 125 nqtot 1 etat0 dcmip3
+}
+
+function dcmip4x
+{
+    echo 'INCLUDEDEF = const.def'
+    group 'Mesh' nbp 80 llm 30 disvert ncarl30 optim_it 100 ; split 2 2
+    group 'Numerics' time_step 240
+    dissip 1800 1 1800 2 1800 2
+    group 'Time' run_length 3.6e6 write_period 21600
+    group 'Physical parameters' nqtot 2 etat0 dcmip4 dcmip4_testcase $1
+}
+
+function dcmip42
+{
+    dcmip4x 2
+    dcmip_physics 1
+}
+
+function dcmip51
+{
+    echo 'INCLUDEDEF = const.def'
+    group 'Mesh' nbp 64 llm 30 disvert ncarl30 optim_it 1000 ; split 2 2
+    group 'Numerics' time_step 300
+    dissip 10800 1 10800 2 10800 2
+    group 'Time' run_length 864000 write_period 7200
+    group 'Physical parameters' nqtot 1 etat0 dcmip5 dcmip_physics 0
+}
+    
+########## Main program : generate all *.def files in param_sets ##############
+
+function mkcd { cd $ROOT ; mkdir -p $1 ; cd $1
+}
+
+set -o errexit
+ROOT=$PWD
+
+mkcd climate/Held_Suarez
+held_suarez > run.def
+
+mkcd shallow_water/williamson91
+williamson91 > run6.def
+
+mkcd dcmip2012
+const_dcmip 7.292e-5 > const.def
+dcmip11 > run11.def
+dcmip21 > run21.def
+dcmip3 > run3.def
+dcmip4x 1 > run41.def
+dcmip42 > run42.def
+dcmip51 > run51.def
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/shallow_water/williamson91/test6/earth_const.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/shallow_water/williamson91/test6/earth_const.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/shallow_water/williamson91/test6/earth_const.def	(revision 329)
@@ -0,0 +1,23 @@
+#planetary radius : real (default=37122E6)
+radius=6.37122E6
+
+# gravity : real (default=9.80616)
+g=9.80616
+
+#planetary rotation rate (default=7.292E-5)
+omega=7.292E-5
+
+# kappa=Rd/cpp (default=0.2857143)
+kappa=0.2857143
+  
+# Heat capacity at constant pressure real (default=1004.70885)
+cpp=1004.5
+
+# Reference pressure : real (default=101325.)
+preff=100000.
+
+# Scale factor for small planet experiment : real (default=1.)
+scale_factor=1.
+
+# Precision of NetCDF output
+netcdf_prec = float
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/shallow_water/williamson91/test6/run.def
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/shallow_water/williamson91/test6/run.def	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/param_sets/shallow_water/williamson91/test6/run.def	(revision 329)
@@ -0,0 +1,141 @@
+INCLUDEDEF=earth_const.def
+
+# ------------------------------- Mesh ---------------------------------
+
+# Number of subdivision on a main triangle (nbp) : integer (default=40)
+nbp=160
+#nbp=40
+
+# Schmidt tranform (default=1.,0,90.)
+#schmidt_factor=4.
+#schmidt_lon=180.
+#schmidt_lat=50.
+
+# nbp                 20  40  80 160
+# T-edge length (km) 500 250 120  60
+
+# sub splitting of main rhombus : integer (default=1)
+nsplit_i=2
+nsplit_j=3
+
+# Number of vertical layer (llm) : integer (default=19)
+llm=1
+
+# Vertical coordinate : eta_mass (mass-based hybrid, default) or eta_lag (Lagrangian)
+caldyn_eta=eta_lag
+boussinesq=.TRUE.
+
+# disvert : vertical discretisation : string (default='std') : std, ncar, ncar30l
+disvert=none
+
+# optim_it : mesh optimisation : number of iteration : integer (default=0)
+#optim_it=1000
+optim_it=100
+
+# ---------------------------------- Time---------------------------------
+
+# scheme type : string ( default='runge_kutta') euler, leapfrog_matsuno, runge_kutta )
+scheme = runge_kutta
+
+# matsuno period : integer ( default=5)
+matsuno_period = 5
+
+# timestep : real (default=480s)
+dt = 120
+
+# advection called every itau_adv time steps : integer (default 2)
+# standard : umax=100m/s vs c=340m/s (ratio 1:3)
+# in JW06 umax=35m/s vs c=340m/s (ratio 1:10)
+itau_adv=30
+
+# number of timestep (default 100)
+# itaumax = 10000
+
+# run length : real (default=dt*itaumax)
+run_length=2592000
+#run_length=864000
+#run_length=86400
+#run_length=7200
+
+# output field period : integer (default none)
+#write_period=7200
+write_period=86400
+#write_period=480
+
+# ---------------------------------- Misc --------------------------------
+
+# number of tracer (nqtot) : integer (default 1)
+nqtot=1
+
+# pression value where output is interpolated : real (default=0, no output)
+out_pression_level=85000
+
+# etat0 : initial state : string (default=jablonowsky06) : 
+# jablonowsky06, academic, ncar
+etat0=williamson91.6
+
+# ------------------------------ Dynamics --------------------------------
+
+# caldyn : computation type for gcm equation : string (default=gcm) : gcm, adv
+caldyn=gcm
+
+# caldyn_conserv : string (default=energy) : energy,enstrophy
+caldyn_conserv=energy
+
+# guided_type : string (default=none) : none, ncar
+guided_type=none
+
+# ---------------------------------- Dissipation ---------------------------------
+
+# dissipation time graddiv : real (default=5000)
+tau_graddiv = 5000
+
+# number of iteration for graddiv : integer (default=1)
+nitergdiv = 2
+
+# dissipation time nxgradrot (default=5000)
+tau_gradrot = 500
+
+# number of iteration for nxgradrot : integer (default=1)
+nitergrot=2
+
+# dissipation time divgrad (theta) (default=5000)
+tau_divgrad=5000
+
+# number of iteration for divgrad : integer (default=1)
+niterdivgrad=2
+
+# Rayleigh friction : string (default=none) : none, dcmip2_schaer_noshear, dcmip2_schaer_shear
+rayleigh_friction_type=none
+
+# -------------------------------- Physics -------------------------------------
+
+# kind of physics : string : none, dcmip (default=none)
+physics=none
+
+# -------------------- parameters for NCAR test cases ------------------------
+
+# NCAR advection test, initial tracer : string ( default='cos_bell')
+# const, slotted_cyl, cos_bell, dbl_cos_bell_q1, dbl_cos_bell_q2, complement, hadley
+ncar_adv_shape=cos_bell
+
+# NCAR advection test, wind field : string (default='deform') : solid, deform, hadley
+ncar_adv_wind=solid
+
+# ncar_T0 : reference temperature for NCAR test cases : real (default=300) 
+# also used by disvert if disvert=ncar
+ncar_T0=300
+
+# ncar_p0 : reference pressure for NCAR test cases : real (default=1e5) 
+# also used by disvert if disvert=ncar
+ncar_p0=1e5
+
+# ncar_disvert_c : exponent for B(eta) : integer (default=1)
+# used by disvert if disvert=ncar
+
+ncar_disvert_c=1
+
+# dcmip 4 testcase : integer (default=1) : 1, 2
+dcmip4_testcase=1
+
+#-----------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/advect.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/advect.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/advect.f90	(revision 329)
@@ -0,0 +1,521 @@
+MODULE advect_mod
+  USE icosa
+  IMPLICIT NONE 
+
+  PRIVATE
+  
+  PUBLIC :: init_advect, compute_backward_traj, compute_gradq3d, compute_advect_horiz
+
+CONTAINS
+
+  !==========================================================================
+
+  SUBROUTINE init_advect(normal,tangent,sqrt_leng)
+    IMPLICIT NONE
+    REAL(rstd),INTENT(OUT) :: normal(3*iim*jjm,3)
+    REAL(rstd),INTENT(OUT) :: tangent(3*iim*jjm,3)
+    REAL(rstd),INTENT(OUT) :: sqrt_leng(iim*jjm)
+
+    INTEGER :: ij
+
+!$SIMD
+      DO ij=ij_begin,ij_end
+
+          CALL cross_product2(xyz_v(ij+z_rdown,:),xyz_v(ij+z_rup,:),normal(ij+u_right,:))
+          normal(ij+u_right,:)=normal(ij+u_right,:)/sqrt(sum(normal(ij+u_right,:)**2)+1e-50)*ne(ij,right)
+
+          CALL cross_product2(xyz_v(ij+z_up,:),xyz_v(ij+z_lup,:),normal(ij+u_lup,:))
+          normal(ij+u_lup,:)=normal(ij+u_lup,:)/sqrt(sum(normal(ij+u_lup,:)**2)+1e-50)*ne(ij,lup)
+
+          CALL cross_product2(xyz_v(ij+z_ldown,:),xyz_v(ij+z_down,:),normal(ij+u_ldown,:))	 
+          normal(ij+u_ldown,:)=normal(ij+u_ldown,:)/sqrt(sum(normal(ij+u_ldown,:)**2)+1e-50)*ne(ij,ldown)
+
+          tangent(ij+u_right,:)=xyz_v(ij+z_rup,:)-xyz_v(ij+z_rdown,:) 
+          tangent(ij+u_right,:)=tangent(ij+u_right,:)/sqrt(sum(tangent(ij+u_right,:)**2)+1e-50)
+
+          tangent(ij+u_lup,:)=xyz_v(ij+z_lup,:)-xyz_v(ij+z_up,:) 
+          tangent(ij+u_lup,:)=tangent(ij+u_lup,:)/sqrt(sum(tangent(ij+u_lup,:)**2)+1e-50)
+
+          tangent(ij+u_ldown,:)=xyz_v(ij+z_down,:)-xyz_v(ij+z_ldown,:)
+          tangent(ij+u_ldown,:)=tangent(ij+u_ldown,:)/sqrt(sum(tangent(ij+u_ldown,:)**2)+1e-50)
+
+          sqrt_leng(ij) = sqrt(max(sum((xyz_v(ij+z_up,:) - xyz_i(ij,:))**2),sum((xyz_v(ij+z_down,:) - xyz_i(ij,:))**2), &
+                                   sum((xyz_v(ij+z_rup,:) - xyz_i(ij,:))**2),sum((xyz_v(ij+z_rdown,:) - xyz_i(ij,:))**2),  &
+                                   sum((xyz_v(ij+z_lup,:) - xyz_i(ij,:))**2),sum((xyz_v(ij+z_ldown,:) - xyz_i(ij,:))**2)) )
+    ENDDO
+
+  END SUBROUTINE init_advect
+
+  !=======================================================================================
+
+  SUBROUTINE compute_gradq3d(qi_in,sqrt_leng_in,gradq3d_out,xyz_i,xyz_v)
+    USE trace
+    USE omp_para
+    IMPLICIT NONE
+    REAL(rstd),INTENT(IN)  :: qi_in(iim*jjm,llm)
+    REAL(rstd),INTENT(IN)  :: sqrt_leng_in(iim*jjm)
+    REAL(rstd),INTENT(IN)  :: xyz_i(iim*jjm,3)
+    REAL(rstd),INTENT(IN)  :: xyz_v(2*iim*jjm,3)
+    REAL(rstd),INTENT(OUT) :: gradq3d_out(iim*jjm,llm,3) 
+    REAL(rstd) :: maxq,minq,minq_c,maxq_c 
+    REAL(rstd) :: alphamx,alphami,alpha	,maggrd
+    REAL(rstd) :: leng1,leng2
+    REAL(rstd) :: arr(2*iim*jjm)
+    REAL(rstd) :: ar(iim*jjm)
+    REAL(rstd) :: gradtri(2*iim*jjm,llm,3) 
+    INTEGER :: ij,k,ind,l
+    REAL(rstd)  :: qi(iim*jjm,llm)
+    REAL(rstd)  :: sqrt_leng(iim*jjm)
+    REAL(rstd) :: gradq3d(iim*jjm,llm,3) 
+    REAL(rstd) :: detx,dety,detz,det
+    REAL(rstd) :: A(3,3), a11,a12,a13,a21,a22,a23,a31,a32,a33
+    REAL(rstd) :: x1,x2,x3
+    REAL(rstd) :: dq(3)
+
+    qi=qi_in
+    sqrt_leng=sqrt_leng_in
+    
+    CALL trace_start("compute_gradq3d1")
+
+    ! TODO : precompute ar, drop arr as output argument of gradq ?
+
+    !========================================================================================== GRADIENT 
+    ! Compute gradient at triangles solving a linear system
+    ! arr = area of triangle joining centroids of hexagons
+!     DO l = ll_begin,ll_end 
+!!$SIMD
+!      DO ij=ij_begin_ext,ij_end_ext
+!!             CALL gradq(ij,l,ij+t_rup,ij+t_lup,ij+z_up,qi,gradtri(ij+z_up,l,:),arr(ij+z_up))
+!!             CALL gradq(ij,l,ij+t_ldown,ij+t_rdown,ij+z_down,qi,gradtri(ij+z_down,l,:),arr(ij+z_down))
+!             CALL gradq(ij,l,ij+t_rup,ij+t_lup,ij+z_up,qi,gradtri(ij+z_up,l,1),gradtri(ij+z_up,l,2),gradtri(ij+z_up,l,3),arr(ij+z_up))
+!             CALL gradq(ij,l,ij+t_ldown,ij+t_rdown,ij+z_down,qi,gradtri(ij+z_down,l,1),gradtri(ij+z_down,l,2),gradtri(ij+z_down,l,3),arr(ij+z_down))
+!       END DO
+!    END DO
+
+     DO l = ll_begin,ll_end 
+!$SIMD
+      DO ij=ij_begin_ext,ij_end_ext
+!       CALL gradq(ij,l,ij+t_rup,ij+t_lup,ij+z_up,qi,gradtri(ij+z_up,l,1),gradtri(ij+z_up,l,2),gradtri(ij+z_up,l,3),arr(ij+z_up))
+
+        
+        A(1,1)=xyz_i(ij+t_rup,1)-xyz_i(ij,1);  A(1,2)=xyz_i(ij+t_rup,2)-xyz_i(ij,2); A(1,3)=xyz_i(ij+t_rup,3)-xyz_i(ij,3) 
+        A(2,1)=xyz_i(ij+t_lup,1)-xyz_i(ij,1);  A(2,2)=xyz_i(ij+t_lup,2)-xyz_i(ij,2); A(2,3)=xyz_i(ij+t_lup,3)-xyz_i(ij,3) 
+        A(3,1)=xyz_v(ij+z_up,1);               A(3,2)= xyz_v(ij+z_up,2);             A(3,3)=xyz_v(ij+z_up,3)
+    
+        dq(1) = qi(ij+t_rup,l)-qi(ij,l)
+        dq(2) = qi(ij+t_lup,l)-qi(ij,l)
+        dq(3) = 0.0
+
+
+!        CALL determinant(A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),A(1,3),A(2,3),A(3,3),det)
+
+         a11=A(1,1) ; a12=A(2,1) ; a13=A(3,1)
+         a21=A(1,2) ; a22=A(2,2) ; a23=A(3,2)
+         a31=A(1,3) ; a32=A(2,3) ; a33=A(3,3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         det =  x1 - x2 + x3
+                 
+!        CALL determinant(dq(1),dq(2),dq(3),A(1,2),A(2,2),A(3,2),A(1,3),A(2,3),A(3,3),detx)
+
+         a11=dq(1)  ; a12=dq(2)  ; a13=dq(3)
+         a21=A(1,2) ; a22=A(2,2) ; a23=A(3,2)
+         a31=A(1,3) ; a32=A(2,3) ; a33=A(3,3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         detx =  x1 - x2 + x3
+        
+!        CALL determinant(A(1,1),A(2,1),A(3,1),dq(1),dq(2),dq(3),A(1,3),A(2,3),A(3,3),dety)
+
+         a11=A(1,1) ; a12=A(2,1) ; a13=A(3,1)
+         a21=dq(1)  ; a22=dq(2)  ; a23=dq(3)
+         a31=A(1,3) ; a32=A(2,3) ; a33=A(3,3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         dety =  x1 - x2 + x3
+
+!        CALL determinant(A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),dq(1),dq(2),dq(3),detz)
+
+         a11=A(1,1) ; a12=A(2,1) ; a13=A(3,1)
+         a21=A(1,2) ; a22=A(2,2) ; a23=A(3,2)
+         a31=dq(1)  ; a32=dq(2)  ; a33=dq(3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         detz =  x1 - x2 + x3
+
+        gradtri(ij+z_up,l,1) = detx
+        gradtri(ij+z_up,l,2) = dety
+        gradtri(ij+z_up,l,3) = detz
+        arr(ij+z_up) = det
+        
+      ENDDO
+      
+      DO ij=ij_begin_ext,ij_end_ext
+
+
+!        CALL gradq(ij,l,ij+t_ldown,ij+t_rdown,ij+z_down,qi,gradtri(ij+z_down,l,1),gradtri(ij+z_down,l,2),gradtri(ij+z_down,l,3),arr(ij+z_down))
+
+        A(1,1)=xyz_i(ij+t_ldown,1)-xyz_i(ij,1);  A(1,2)=xyz_i(ij+t_ldown,2)-xyz_i(ij,2); A(1,3)=xyz_i(ij+t_ldown,3)-xyz_i(ij,3) 
+        A(2,1)=xyz_i(ij+t_rdown,1)-xyz_i(ij,1);  A(2,2)=xyz_i(ij+t_rdown,2)-xyz_i(ij,2); A(2,3)=xyz_i(ij+t_rdown,3)-xyz_i(ij,3) 
+        A(3,1)=xyz_v(ij+z_down,1);               A(3,2)= xyz_v(ij+z_down,2);             A(3,3)=xyz_v(ij+z_down,3)
+ 
+        dq(1) = qi(ij+t_ldown,l)-qi(ij,l)
+        dq(2) = qi(ij+t_rdown,l)-qi(ij,l)
+        dq(3) = 0.0
+
+
+!        CALL determinant(A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),A(1,3),A(2,3),A(3,3),det)
+
+         a11=A(1,1) ; a12=A(2,1) ; a13=A(3,1)
+         a21=A(1,2) ; a22=A(2,2) ; a23=A(3,2)
+         a31=A(1,3) ; a32=A(2,3) ; a33=A(3,3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         det =  x1 - x2 + x3
+                 
+!        CALL determinant(dq(1),dq(2),dq(3),A(1,2),A(2,2),A(3,2),A(1,3),A(2,3),A(3,3),detx)
+
+         a11=dq(1)  ; a12=dq(2)  ; a13=dq(3)
+         a21=A(1,2) ; a22=A(2,2) ; a23=A(3,2)
+         a31=A(1,3) ; a32=A(2,3) ; a33=A(3,3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         detx =  x1 - x2 + x3
+        
+!        CALL determinant(A(1,1),A(2,1),A(3,1),dq(1),dq(2),dq(3),A(1,3),A(2,3),A(3,3),dety)
+
+         a11=A(1,1) ; a12=A(2,1) ; a13=A(3,1)
+         a21=dq(1)  ; a22=dq(2)  ; a23=dq(3)
+         a31=A(1,3) ; a32=A(2,3) ; a33=A(3,3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         dety =  x1 - x2 + x3
+
+!        CALL determinant(A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),dq(1),dq(2),dq(3),detz)
+
+         a11=A(1,1) ; a12=A(2,1) ; a13=A(3,1)
+         a21=A(1,2) ; a22=A(2,2) ; a23=A(3,2)
+         a31=dq(1)  ; a32=dq(2)  ; a33=dq(3)
+
+         x1 =  a11 * (a22 * a33 - a23 * a32)
+         x2 =  a12 * (a21 * a33 - a23 * a31)
+         x3 =  a13 * (a21 * a32 - a22 * a31)
+         detz =  x1 - x2 + x3
+
+         gradtri(ij+z_down,l,1) = detx
+         gradtri(ij+z_down,l,2) = dety
+         gradtri(ij+z_down,l,3) = detz
+         arr(ij+z_down) = det
+
+      END DO
+    END DO
+
+!$SIMD
+    DO ij=ij_begin,ij_end
+       ar(ij) = arr(ij+z_up)+arr(ij+z_lup)+arr(ij+z_ldown)+arr(ij+z_down)+arr(ij+z_rdown)+arr(ij+z_rup)+1.e-50
+    ENDDO
+    CALL trace_end("compute_gradq3d1")
+    CALL trace_start2("compute_gradq3d2")
+      
+    DO k=1,3
+      DO l =ll_begin,ll_end
+!$SIMD
+      DO ij=ij_begin,ij_end
+              gradq3d(ij,l,k) = ( gradtri(ij+z_up,l,k) + gradtri(ij+z_down,l,k)   +   &
+                                 gradtri(ij+z_rup,l,k) +  gradtri(ij+z_ldown,l,k)   +   & 
+                                 gradtri(ij+z_lup,l,k)+    gradtri(ij+z_rdown,l,k) ) / ar(ij)  
+        END DO
+      END DO
+    ENDDO
+    CALL trace_end2("compute_gradq3d2")
+    CALL trace_start("compute_gradq3d3")
+
+    !============================================================================================= LIMITING 
+    DO l =ll_begin,ll_end
+!$SIMD
+      DO ij=ij_begin,ij_end
+!             maggrd =  dot_product(gradq3d(ij,l,:),gradq3d(ij,l,:))
+             maggrd = gradq3d(ij,l,1)*gradq3d(ij,l,1) + gradq3d(ij,l,2)*gradq3d(ij,l,2) + gradq3d(ij,l,3)*gradq3d(ij,l,3) 
+             maggrd = sqrt(maggrd) 
+             maxq_c = qi(ij,l) + maggrd*sqrt_leng(ij)
+             minq_c = qi(ij,l) - maggrd*sqrt_leng(ij)
+             maxq = max(qi(ij,l),qi(ij+t_right,l),qi(ij+t_lup,l),qi(ij+t_rup,l),qi(ij+t_left,l), &
+                  qi(ij+t_rdown,l),qi(ij+t_ldown,l))
+             minq = min(qi(ij,l),qi(ij+t_right,l),qi(ij+t_lup,l),qi(ij+t_rup,l),qi(ij+t_left,l), &
+                  qi(ij+t_rdown,l),qi(ij+t_ldown,l))
+             alphamx = (maxq - qi(ij,l)) ; alphamx = alphamx/(maxq_c - qi(ij,l) )
+             alphamx = max(alphamx,0.0)
+             alphami = (minq - qi(ij,l)); alphami = alphami/(minq_c - qi(ij,l))
+             alphami = max(alphami,0.0) 
+             alpha   = min(alphamx,alphami,1.0)
+!             gradq3d(ij,l,:) = alpha*gradq3d(ij,l,:)
+             gradq3d(ij,l,1) = alpha*gradq3d(ij,l,1)
+             gradq3d(ij,l,2) = alpha*gradq3d(ij,l,2)
+             gradq3d(ij,l,3) = alpha*gradq3d(ij,l,3)
+       END DO
+    END DO
+
+  CALL trace_end("compute_gradq3d3")
+  
+  gradq3d_out=gradq3d
+  
+  CONTAINS
+
+    SUBROUTINE gradq(n0,l,n1,n2,n3,q,dq1,dq2,dq3,det)
+    IMPLICIT NONE
+    INTEGER, INTENT(IN) :: n0,l,n1,n2,n3
+    REAL(rstd), INTENT(IN)     :: q(iim*jjm,llm)
+!    REAL(rstd), INTENT(OUT)    :: dq(3), det
+    REAL(rstd), INTENT(OUT)    :: dq1,dq2,dq3,det
+    REAL(rstd)    :: dq(3)
+    
+    REAL(rstd)  ::detx,dety,detz
+    INTEGER    :: info
+    INTEGER    :: IPIV(3)
+
+    REAL(rstd) :: A(3,3)
+    REAL(rstd) :: B(3)
+    
+    ! TODO : replace A by A1,A2,A3
+    A(1,1)=xyz_i(n1,1)-xyz_i(n0,1);  A(1,2)=xyz_i(n1,2)-xyz_i(n0,2); A(1,3)=xyz_i(n1,3)-xyz_i(n0,3) 
+    A(2,1)=xyz_i(n2,1)-xyz_i(n0,1);  A(2,2)=xyz_i(n2,2)-xyz_i(n0,2); A(2,3)=xyz_i(n2,3)-xyz_i(n0,3) 
+    A(3,1)=xyz_v(n3,1);              A(3,2)= xyz_v(n3,2);            A(3,3)=xyz_v(n3,3)
+
+    dq(1) = q(n1,l)-q(n0,l)
+    dq(2) = q(n2,l)-q(n0,l)
+    dq(3) = 0.0
+
+    !    CALL DGESV(3,1,A,3,IPIV,dq(:),3,info)
+!    CALL determinant(A(:,1),A(:,2),A(:,3),det)
+!    CALL determinant(dq,A(:,2),A(:,3),detx)
+!    CALL determinant(A(:,1),dq,A(:,3),dety)
+!    CALL determinant(A(:,1),A(:,2),dq,detz)
+!    dq(1) = detx
+!    dq(2) = dety
+!    dq(3) = detz 
+
+    CALL determinant(A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),A(1,3),A(2,3),A(3,3),det)
+    CALL determinant(dq(1),dq(2),dq(3),A(1,2),A(2,2),A(3,2),A(1,3),A(2,3),A(3,3),dq1)
+    CALL determinant(A(1,1),A(2,1),A(3,1),dq(1),dq(2),dq(3),A(1,3),A(2,3),A(3,3),dq2)
+    CALL determinant(A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),dq(1),dq(2),dq(3),dq3)
+
+  END SUBROUTINE gradq
+
+  !==========================================================================
+!  PURE SUBROUTINE determinant(a1,a2,a3,det)
+!    IMPLICIT NONE
+!    REAL(rstd), DIMENSION(3), INTENT(IN) :: a1,a2,a3
+!    REAL(rstd), INTENT(OUT) :: det
+!    REAL(rstd) ::  x1,x2,x3
+!    x1 =  a1(1) * (a2(2) * a3(3) - a2(3) * a3(2))
+!    x2 =  a1(2) * (a2(1) * a3(3) - a2(3) * a3(1))
+!    x3 =  a1(3) * (a2(1) * a3(2) - a2(2) * a3(1))
+!    det =  x1 - x2 + x3
+!  END SUBROUTINE determinant
+
+   SUBROUTINE determinant(a11,a12,a13,a21,a22,a23,a31,a32,a33,det)
+    IMPLICIT NONE
+    REAL(rstd), INTENT(IN) :: a11,a12,a13,a21,a22,a23,a31,a32,a33
+    REAL(rstd), INTENT(OUT) :: det
+    REAL(rstd) ::  x1,x2,x3
+    x1 =  a11 * (a22 * a33 - a23 * a32)
+    x2 =  a12 * (a21 * a33 - a23 * a31)
+    x3 =  a13 * (a21 * a32 - a22 * a31)
+    det =  x1 - x2 + x3
+  END SUBROUTINE determinant
+
+
+  END SUBROUTINE compute_gradq3d
+
+  ! Backward trajectories, for use with Miura approach
+  SUBROUTINE compute_backward_traj(normal,tangent,ue,tau, cc)
+    USE trace
+    USE omp_para
+    IMPLICIT NONE
+    REAL(rstd),INTENT(IN)    :: normal(3*iim*jjm,3)
+    REAL(rstd),INTENT(IN)    :: tangent(3*iim*jjm,3)
+    REAL(rstd),INTENT(IN)    :: ue(iim*3*jjm,llm)
+    REAL(rstd),INTENT(OUT)   :: cc(3*iim*jjm,llm,3) ! start of backward trajectory
+    REAL(rstd),INTENT(IN)    :: tau
+
+    REAL(rstd) :: v_e(3), up_e, qe, ed(3)    
+    INTEGER :: ij,l
+
+    CALL trace_start("compute_backward_traj")
+
+    ! TODO : compute normal displacement ue*tau as hfluxt / mass(upwind) then reconstruct tangential displacement
+    
+    ! reconstruct tangential wind then 3D wind at edge then cc = edge midpoint - u*tau
+    DO l = ll_begin,ll_end
+!$SIMD
+      DO ij=ij_begin,ij_end
+             up_e =1/de(ij+u_right)*(                                                   &
+                  wee(ij+u_right,1,1)*le(ij+u_rup)*ue(ij+u_rup,l)+                        &
+                  wee(ij+u_right,2,1)*le(ij+u_lup)*ue(ij+u_lup,l)+                        &
+                  wee(ij+u_right,3,1)*le(ij+u_left)*ue(ij+u_left,l)+                      &
+                  wee(ij+u_right,4,1)*le(ij+u_ldown)*ue(ij+u_ldown,l)+                    &
+                  wee(ij+u_right,5,1)*le(ij+u_rdown)*ue(ij+u_rdown,l)+                    & 
+                  wee(ij+u_right,1,2)*le(ij+t_right+u_ldown)*ue(ij+t_right+u_ldown,l)+    &
+                  wee(ij+u_right,2,2)*le(ij+t_right+u_rdown)*ue(ij+t_right+u_rdown,l)+    &
+                  wee(ij+u_right,3,2)*le(ij+t_right+u_right)*ue(ij+t_right+u_right,l)+    &
+                  wee(ij+u_right,4,2)*le(ij+t_right+u_rup)*ue(ij+t_right+u_rup,l)+        &
+                  wee(ij+u_right,5,2)*le(ij+t_right+u_lup)*ue(ij+t_right+u_lup,l)         &
+                  )
+             v_e = ue(ij+u_right,l)*normal(ij+u_right,:) + up_e*tangent(ij+u_right,:)
+             cc(ij+u_right,l,:) = xyz_e(ij+u_right,:) - v_e*tau
+
+             up_e=1/de(ij+u_lup)*(                                                      &
+                  wee(ij+u_lup,1,1)*le(ij+u_left)*ue(ij+u_left,l)+                        &
+                  wee(ij+u_lup,2,1)*le(ij+u_ldown)*ue(ij+u_ldown,l)+                      &
+                  wee(ij+u_lup,3,1)*le(ij+u_rdown)*ue(ij+u_rdown,l)+                      &
+                  wee(ij+u_lup,4,1)*le(ij+u_right)*ue(ij+u_right,l)+                      &
+                  wee(ij+u_lup,5,1)*le(ij+u_rup)*ue(ij+u_rup,l)+                          & 
+                  wee(ij+u_lup,1,2)*le(ij+t_lup+u_right)*ue(ij+t_lup+u_right,l)+          &
+                  wee(ij+u_lup,2,2)*le(ij+t_lup+u_rup)*ue(ij+t_lup+u_rup,l)+              &
+                  wee(ij+u_lup,3,2)*le(ij+t_lup+u_lup)*ue(ij+t_lup+u_lup,l)+              &
+                  wee(ij+u_lup,4,2)*le(ij+t_lup+u_left)*ue(ij+t_lup+u_left,l)+            &
+                  wee(ij+u_lup,5,2)*le(ij+t_lup+u_ldown)*ue(ij+t_lup+u_ldown,l)           &
+                  )
+             v_e = ue(ij+u_lup,l)*normal(ij+u_lup,:) + up_e*tangent(ij+u_lup,:)
+             cc(ij+u_lup,l,:) = xyz_e(ij+u_lup,:) - v_e*tau
+            
+
+             up_e=1/de(ij+u_ldown)*(                                                    &
+                  wee(ij+u_ldown,1,1)*le(ij+u_rdown)*ue(ij+u_rdown,l)+                    &
+                  wee(ij+u_ldown,2,1)*le(ij+u_right)*ue(ij+u_right,l)+                    &
+                  wee(ij+u_ldown,3,1)*le(ij+u_rup)*ue(ij+u_rup,l)+                        &
+                  wee(ij+u_ldown,4,1)*le(ij+u_lup)*ue(ij+u_lup,l)+                        &
+                  wee(ij+u_ldown,5,1)*le(ij+u_left)*ue(ij+u_left,l)+                      & 
+                  wee(ij+u_ldown,1,2)*le(ij+t_ldown+u_lup)*ue(ij+t_ldown+u_lup,l)+        &
+                  wee(ij+u_ldown,2,2)*le(ij+t_ldown+u_left)*ue(ij+t_ldown+u_left,l)+      &
+                  wee(ij+u_ldown,3,2)*le(ij+t_ldown+u_ldown)*ue(ij+t_ldown+u_ldown,l)+    &
+                  wee(ij+u_ldown,4,2)*le(ij+t_ldown+u_rdown)*ue(ij+t_ldown+u_rdown,l)+    &
+                  wee(ij+u_ldown,5,2)*le(ij+t_ldown+u_right)*ue(ij+t_ldown+u_right,l)     &
+                  )
+             v_e = ue(ij+u_ldown,l)*normal(ij+u_ldown,:) + up_e*tangent(ij+u_ldown,:)
+             cc(ij+u_ldown,l,:) = xyz_e(ij+u_ldown,:) - v_e*tau
+       ENDDO
+    END DO
+
+    CALL trace_end("compute_backward_traj")
+
+  END SUBROUTINE compute_backward_traj
+
+  ! Horizontal transport (S. Dubey, T. Dubos)
+  ! Slope-limited van Leer approach with hexagons
+  SUBROUTINE compute_advect_horiz(update_mass,hfluxt,cc,gradq3d, mass,qi) 
+    USE trace
+    USE omp_para
+    IMPLICIT NONE
+    LOGICAL, INTENT(IN)       :: update_mass
+    REAL(rstd), INTENT(IN)    :: gradq3d(iim*jjm,llm,3) 
+    REAL(rstd), INTENT(IN)    :: hfluxt(3*iim*jjm,llm) ! mass flux
+    REAL(rstd), INTENT(IN)    :: cc(3*iim*jjm,llm,3)   ! barycenter of quadrilateral, where q is evaluated (1-point quadrature)
+    REAL(rstd), INTENT(INOUT) :: mass(iim*jjm,llm)
+    REAL(rstd), INTENT(INOUT) :: qi(iim*jjm,llm)
+
+    REAL(rstd) :: dq,dmass,qe,ed(3), newmass
+    REAL(rstd) :: qflux(3*iim*jjm,llm)
+    INTEGER :: ij,k,l
+
+    CALL trace_start("compute_advect_horiz")
+
+    ! evaluate tracer field at point cc using piecewise linear reconstruction
+    ! q(cc)= q0 + gradq.(cc-xyz_i)  with xi centroid of hexagon
+    ! ne*hfluxt>0 iff outgoing
+    DO l = ll_begin,ll_end
+
+!$SIMD
+      DO ij=ij_begin_ext,ij_end_ext
+
+             IF (ne(ij,right)*hfluxt(ij+u_right,l)>0) THEN 
+                ed = cc(ij+u_right,l,:) - xyz_i(ij,:)
+!                qe = qi(ij,l)+sum2(gradq3d(ij,l,:),ed) 
+                 qe = qi(ij,l)+gradq3d(ij,l,1)*ed(1)+gradq3d(ij,l,2)*ed(2)+gradq3d(ij,l,3)*ed(3) 
+             ELSE
+                ed = cc(ij+u_right,l,:) - xyz_i(ij+t_right,:)
+!                qe = qi(ij+t_right,l)+sum2(gradq3d(ij+t_right,l,:),ed) 
+                qe = qi(ij+t_right,l) + gradq3d(ij+t_right,l,1)*ed(1)+gradq3d(ij+t_right,l,2)*ed(2)+gradq3d(ij+t_right,l,3)*ed(3) 
+             ENDIF
+             qflux(ij+u_right,l) = hfluxt(ij+u_right,l)*qe
+             
+             IF (ne(ij,lup)*hfluxt(ij+u_lup,l)>0) THEN 
+                ed = cc(ij+u_lup,l,:) - xyz_i(ij,:)
+!                qe = qi(ij,l)+sum2(gradq3d(ij,l,:),ed)
+                qe = qi(ij,l)  + gradq3d(ij,l,1)*ed(1)+gradq3d(ij,l,2)*ed(2)+gradq3d(ij,l,3)*ed(3) 
+             ELSE
+                ed = cc(ij+u_lup,l,:) - xyz_i(ij+t_lup,:)
+!                qe = qi(ij+t_lup,l)+sum2(gradq3d(ij+t_lup,l,:),ed) 
+                qe = qi(ij+t_lup,l) + gradq3d(ij+t_lup,l,1)*ed(1)+gradq3d(ij+t_lup,l,2)*ed(2)+gradq3d(ij+t_lup,l,3)*ed(3) 
+             ENDIF
+             qflux(ij+u_lup,l) = hfluxt(ij+u_lup,l)*qe 
+
+             IF (ne(ij,ldown)*hfluxt(ij+u_ldown,l)>0) THEN 
+                ed = cc(ij+u_ldown,l,:) - xyz_i(ij,:)
+!                qe = qi(ij,l)+sum2(gradq3d(ij,l,:),ed) 
+                qe = qi(ij,l) + gradq3d(ij,l,1)*ed(1)+gradq3d(ij,l,2)*ed(2)+gradq3d(ij,l,3)*ed(3) 
+             ELSE
+                ed = cc(ij+u_ldown,l,:) - xyz_i(ij+t_ldown,:)
+!                qe = qi(ij+t_ldown,l)+sum2(gradq3d(ij+t_ldown,l,:),ed) 
+                qe = qi(ij+t_ldown,l)+gradq3d(ij+t_ldown,l,1)*ed(1)+gradq3d(ij+t_ldown,l,2)*ed(2)+gradq3d(ij+t_ldown,l,3)*ed(3) 
+             ENDIF
+             qflux(ij+u_ldown,l) = hfluxt(ij+u_ldown,l)*qe
+       END DO
+    END DO
+
+    ! update q and, if update_mass, update mass
+    DO l = ll_begin,ll_end
+!$SIMD
+      DO ij=ij_begin,ij_end
+             ! sign convention as Ringler et al. (2010) eq. 21
+             dmass =   hfluxt(ij+u_right,l)*ne(ij,right)   &
+                     + hfluxt(ij+u_lup,l)  *ne(ij,lup)     &
+                     + hfluxt(ij+u_ldown,l)*ne(ij,ldown)   &
+                     + hfluxt(ij+u_rup,l)  *ne(ij,rup)     &
+                     + hfluxt(ij+u_left,l) *ne(ij,left)    &
+                     + hfluxt(ij+u_rdown,l)*ne(ij,rdown)
+
+             dq    =   qflux(ij+u_right,l) *ne(ij,right)   &
+                     + qflux(ij+u_lup,l)   *ne(ij,lup)     &
+                     + qflux(ij+u_ldown,l) *ne(ij,ldown)   &
+                     + qflux(ij+u_rup,l)   *ne(ij,rup)     &
+                     + qflux(ij+u_left,l)  *ne(ij,left)    &
+                     + qflux(ij+u_rdown,l) *ne(ij,rdown)
+
+             
+             newmass = mass(ij,l) - dmass/Ai(ij)
+             qi(ij,l) = (qi(ij,l)*mass(ij,l) - dq/Ai(ij) ) / newmass
+             IF(update_mass) mass(ij,l) = newmass
+
+       END DO
+    END DO
+
+    CALL trace_end("compute_advect_horiz")
+  CONTAINS
+
+    !====================================================================================
+    PURE REAL(rstd) FUNCTION sum2(a1,a2)
+      IMPLICIT NONE
+      REAL(rstd),INTENT(IN):: a1(3), a2(3)
+      sum2 = a1(1)*a2(1)+a1(2)*a2(2)+a1(3)*a2(3)
+      ! sum2 = 0. ! Godunov scheme
+    END FUNCTION sum2
+
+  END SUBROUTINE compute_advect_horiz
+
+
+END MODULE advect_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/advect_tracer.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/advect_tracer.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/advect_tracer.f90	(revision 329)
@@ -0,0 +1,322 @@
+MODULE advect_tracer_mod
+  USE icosa
+  IMPLICIT NONE
+  PRIVATE
+
+  TYPE(t_field),SAVE,POINTER :: f_normal(:)
+  TYPE(t_field),SAVE,POINTER :: f_tangent(:)
+  TYPE(t_field),SAVE,POINTER :: f_gradq3d(:)
+  TYPE(t_field),SAVE,POINTER :: f_cc(:)  ! starting point of backward-trajectory (Miura approach)
+  TYPE(t_field),SAVE,POINTER :: f_sqrt_leng(:)
+
+  TYPE(t_message),SAVE :: req_u, req_cc, req_wfluxt, req_q, req_rhodz, req_gradq3d
+
+  REAL(rstd), PARAMETER :: pente_max=2.0 ! for vlz
+
+! temporary shared variable for vlz
+  TYPE(t_field),SAVE,POINTER :: f_dzqw(:)   ! vertical finite difference of q 
+  TYPE(t_field),SAVE,POINTER :: f_adzqw(:)  ! abs(dzqw)
+  TYPE(t_field),SAVE,POINTER :: f_dzq(:)    ! limited slope of q
+  TYPE(t_field),SAVE,POINTER :: f_wq(:)     ! time-integrated flux of q
+
+  PUBLIC init_advect_tracer, advect_tracer
+
+CONTAINS
+
+  SUBROUTINE init_advect_tracer
+    USE advect_mod
+    REAL(rstd),POINTER :: tangent(:,:)
+    REAL(rstd),POINTER :: normal(:,:)
+    REAL(rstd),POINTER :: sqrt_leng(:)
+    INTEGER :: ind
+
+    CALL allocate_field(f_normal,field_u,type_real,3, name='normal')
+    CALL allocate_field(f_tangent,field_u,type_real,3, name='tangent')
+    CALL allocate_field(f_gradq3d,field_t,type_real,llm,3, name='gradq3d')
+    CALL allocate_field(f_cc,field_u,type_real,llm,3, name='cc')
+    CALL allocate_field(f_sqrt_leng,field_t,type_real, name='sqrt_leng')
+    CALL allocate_field(f_dzqw, field_t, type_real, llm, name='dzqw')
+    CALL allocate_field(f_adzqw, field_t, type_real, llm, name='adzqw')
+    CALL allocate_field(f_dzq, field_t, type_real, llm, name='dzq')
+    CALL allocate_field(f_wq, field_t, type_real, llm+1, name='wq')
+    
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       normal=f_normal(ind)
+       tangent=f_tangent(ind)
+       sqrt_leng=f_sqrt_leng(ind)
+       CALL init_advect(normal,tangent,sqrt_leng)
+    END DO
+
+  END SUBROUTINE init_advect_tracer
+
+  SUBROUTINE advect_tracer(f_hfluxt, f_wfluxt,f_u, f_q,f_rhodz)
+    USE advect_mod
+    USE mpipara
+    USE trace
+    USE write_field
+    IMPLICIT NONE
+    
+    TYPE(t_field),POINTER :: f_hfluxt(:)   ! time-integrated horizontal mass flux
+    TYPE(t_field),POINTER :: f_wfluxt(:)   ! time-integrated vertical mass flux
+    TYPE(t_field),POINTER :: f_u(:)        ! velocity (for back-trajectories)
+    TYPE(t_field),POINTER :: f_q(:)        ! tracer
+    TYPE(t_field),POINTER :: f_rhodz(:)    ! mass field at beginning of macro time step
+
+    REAL(rstd),POINTER :: q(:,:,:), normal(:,:), tangent(:,:), sqrt_leng(:), gradq3d(:,:,:), cc(:,:,:)
+    REAL(rstd),POINTER :: hfluxt(:,:), wfluxt(:,:)
+    REAL(rstd),POINTER :: rhodz(:,:), u(:,:) 
+! temporary shared variable for vlz
+    REAL(rstd),POINTER ::  dzqw(:,:)         ! vertical finite difference of q 
+    REAL(rstd),POINTER ::  adzqw(:,:)        ! abs(dzqw)
+    REAL(rstd),POINTER ::  dzq(:,:)          ! limited slope of q
+    REAL(rstd),POINTER ::  wq(:,:)           ! time-integrated flux of q
+    
+     INTEGER :: ind,k
+    LOGICAL,SAVE :: first=.TRUE.
+!$OMP THREADPRIVATE(first)
+
+    IF (first) THEN
+      first=.FALSE.
+      CALL init_message(f_u,req_e1_vect,req_u)
+      CALL init_message(f_cc,req_e1_scal,req_cc)
+      CALL init_message(f_wfluxt,req_i1,req_wfluxt)
+      CALL init_message(f_q,req_i1,req_q)
+      CALL init_message(f_rhodz,req_i1,req_rhodz)
+      CALL init_message(f_gradq3d,req_i1,req_gradq3d)
+    ENDIF
+    
+!!$OMP BARRIER
+
+    CALL trace_start("advect_tracer") 
+
+    CALL send_message(f_u,req_u)
+    CALL wait_message(req_u)
+    CALL send_message(f_wfluxt,req_wfluxt)
+    CALL wait_message(req_wfluxt)
+    CALL send_message(f_q,req_q)
+    CALL wait_message(req_q)
+    CALL send_message(f_rhodz,req_rhodz)
+    CALL wait_message(req_rhodz)
+
+!    CALL wait_message(req_u)
+!    CALL wait_message(req_wfluxt)
+!    CALL wait_message(req_q)
+!    CALL wait_message(req_rhodz)
+    
+    ! 1/2 vertical transport + back-trajectories
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       normal  = f_normal(ind)
+       tangent = f_tangent(ind)
+       cc      = f_cc(ind)
+       u       = f_u(ind)
+       q       = f_q(ind)
+       rhodz   = f_rhodz(ind)
+       wfluxt  = f_wfluxt(ind) 
+       dzqw    = f_dzqw(ind)
+       adzqw   = f_adzqw(ind)
+       dzq     = f_dzq(ind)
+       wq      = f_wq(ind) 
+
+       DO k = 1, nqtot
+          CALL vlz(k==nqtot,0.5, wfluxt,rhodz,q(:,:,k),1,dzqw, adzqw, dzq, wq)
+       END DO
+
+       CALL compute_backward_traj(tangent,normal,u,0.5*dt*itau_adv, cc) 
+
+    END DO
+
+    CALL send_message(f_cc,req_cc)
+    CALL wait_message(req_cc)
+
+
+    ! horizontal transport - split in two to place transfer of gradq3d
+!!$OMP BARRIER
+    DO k = 1, nqtot
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          q       = f_q(ind)
+          gradq3d = f_gradq3d(ind)
+          sqrt_leng=f_sqrt_leng(ind)
+          CALL compute_gradq3d(q(:,:,k),sqrt_leng,gradq3d,xyz_i,xyz_v)
+       END DO
+
+       CALL send_message(f_gradq3d,req_gradq3d)
+!       CALL wait_message(req_cc)
+       CALL wait_message(req_gradq3d)
+
+
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          cc      = f_cc(ind)
+          q       = f_q(ind)
+          rhodz   = f_rhodz(ind)
+          hfluxt  = f_hfluxt(ind) 
+          gradq3d = f_gradq3d(ind)
+          CALL compute_advect_horiz(k==nqtot,hfluxt,cc,gradq3d, rhodz,q(:,:,k))
+       END DO
+    END DO 
+    
+    ! 1/2 vertical transport
+!!$OMP BARRIER
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       q       = f_q(ind)
+       rhodz   = f_rhodz(ind)
+       wfluxt  = f_wfluxt(ind) 
+       dzqw    = f_dzqw(ind)
+       adzqw   = f_adzqw(ind)
+       dzq     = f_dzq(ind)
+       wq      = f_wq(ind) 
+
+       DO k = 1,nqtot
+          CALL vlz(k==nqtot, 0.5,wfluxt,rhodz, q(:,:,k),0, dzqw, adzqw, dzq, wq)
+       END DO
+
+    END DO
+
+    CALL trace_end("advect_tracer")
+
+!!$OMP BARRIER
+
+  END SUBROUTINE advect_tracer
+
+  SUBROUTINE vlz(update_mass, fac,wfluxt,mass, q, halo, dzqw, adzqw, dzq, wq)
+    !
+    !     Auteurs:   P.Le Van, F.Hourdin, F.Forget, T. Dubos
+    !
+    !    ********************************************************************
+    !     Update tracers using vertical mass flux only
+    !     Van Leer scheme with minmod limiter
+    !     wfluxt >0 for upward transport
+    !    ********************************************************************
+    USE trace
+    USE omp_para
+    IMPLICIT NONE
+    LOGICAL, INTENT(IN)       :: update_mass
+    REAL(rstd), INTENT(IN)    :: fac, wfluxt(iim*jjm,llm+1) ! vertical mass flux
+    REAL(rstd), INTENT(INOUT) :: mass(iim*jjm,llm)
+    REAL(rstd), INTENT(INOUT) :: q(iim*jjm,llm)
+    INTEGER, INTENT(IN) :: halo
+
+! temporary shared variable
+    REAL(rstd),INTENT(INOUT) :: dzqw(iim*jjm,llm),        & ! vertical finite difference of q 
+                                adzqw(iim*jjm,llm),       & ! abs(dzqw)
+                                dzq(iim*jjm,llm),         & ! limited slope of q
+                                wq(iim*jjm,llm+1)           ! time-integrated flux of q
+
+
+    REAL(rstd) :: dzqmax, newmass, sigw, qq, w
+    INTEGER :: i,ij,l,j,ijb,ije
+
+    CALL trace_start("vlz")
+     
+     ijb=((jj_begin-halo)-1)*iim+ii_begin-halo
+     ije = ((jj_end+halo)-1)*iim+ii_end+halo
+
+    ! finite difference of q
+
+     DO l=ll_beginp1,ll_end
+!$SIMD
+       DO ij=ijb,ije
+         dzqw(ij,l)=q(ij,l)-q(ij,l-1)
+         adzqw(ij,l)=abs(dzqw(ij,l))
+       ENDDO
+    ENDDO
+
+!--> flush dzqw, adzqw
+!!$OMP BARRIER
+
+    ! minmod-limited slope of q
+    ! dzq = slope*dz, i.e. the reconstructed q varies by dzq inside level l
+
+     DO l=ll_beginp1,ll_endm1
+!$SIMD
+       DO ij=ijb,ije 
+         IF(dzqw(ij,l)*dzqw(ij,l+1).gt.0.) THEN
+             dzq(ij,l) = 0.5*( dzqw(ij,l)+dzqw(ij,l+1) )
+             dzqmax    = pente_max * min( adzqw(ij,l),adzqw(ij,l+1) )
+             dzq(ij,l) = sign( min(abs(dzq(ij,l)),dzqmax) , dzq(ij,l) )  ! NB : sign(a,b)=a*sign(b)
+          ELSE
+             dzq(ij,l)=0.
+          ENDIF
+       ENDDO
+    ENDDO
+
+
+    ! 0 slope in top and bottom layers
+    IF (omp_first) THEN
+      DO ij=ijb,ije
+           dzq(ij,1)=0.
+      ENDDO
+    ENDIF
+      
+    IF (omp_last) THEN
+      DO ij=ijb,ije
+          dzq(ij,llm)=0.
+      ENDDO
+    ENDIF
+
+!---> flush dzq
+!!$OMP BARRIER  
+
+    ! sigw = fraction of mass that leaves level l/l+1
+    ! then amount of q leaving level l/l+1 = wq = w * qq
+     DO l=ll_beginp1,ll_end
+!$SIMD
+       DO ij=ijb,ije
+             w = fac*wfluxt(ij,l)
+             IF(w>0.) THEN  ! upward transport, upwind side is at level l 
+                sigw       = w/mass(ij,l-1)
+                qq         = q(ij,l-1)+0.5*(1.-sigw)*dzq(ij,l-1) ! qq = q if sigw=1 , qq = q+dzq/2 if sigw=0
+             ELSE           ! downward transport, upwind side is at level l+1
+                sigw       = w/mass(ij,l)
+                qq         = q(ij,l)-0.5*(1.+sigw)*dzq(ij,l) ! qq = q if sigw=-1 , qq = q-dzq/2 if sigw=0                
+             ENDIF
+             wq(ij,l) = w*qq
+       ENDDO
+    END DO
+    ! wq = 0 at top and bottom
+    IF (omp_first) THEN
+       DO ij=ijb,ije
+            wq(ij,1)=0.
+      END DO
+    ENDIF
+    
+    IF (omp_last) THEN
+      DO ij=ijb,ije
+            wq(ij,llm+1)=0.
+      END DO
+    ENDIF
+
+! --> flush wq
+!!$OMP BARRIER
+
+
+    ! update q, mass is updated only after all q's have been updated
+    DO l=ll_begin,ll_end
+!$SIMD
+       DO ij=ijb,ije
+             newmass = mass(ij,l) + fac*(wfluxt(ij,l)-wfluxt(ij,l+1))
+             q(ij,l) = ( q(ij,l)*mass(ij,l) + wq(ij,l)-wq(ij,l+1) ) / newmass
+             IF(update_mass) mass(ij,l)=newmass
+       ENDDO
+    END DO
+
+    CALL trace_end("vlz")
+
+  END SUBROUTINE vlz
+
+END MODULE advect_tracer_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn.f90	(revision 329)
@@ -0,0 +1,74 @@
+MODULE caldyn_mod
+  USE icosa
+  PRIVATE
+  CHARACTER(LEN=255),SAVE :: caldyn_type
+!$OMP THREADPRIVATE(caldyn_type)
+  
+  PUBLIC init_caldyn, caldyn, caldyn_BC
+  
+CONTAINS
+
+  SUBROUTINE init_caldyn
+  USE icosa
+  USE caldyn_gcm_mod, ONLY : init_caldyn_gcm=>init_caldyn
+  USE caldyn_adv_mod, ONLY : init_caldyn_adv=>init_caldyn
+  IMPLICIT NONE
+  
+    caldyn_type="gcm"
+    CALL getin('caldyn',caldyn_type)
+    
+    SELECT CASE (TRIM(caldyn_type))
+      CASE('gcm')
+        CALL init_caldyn_gcm
+      CASE('adv')
+        CALL init_caldyn_adv
+      CASE DEFAULT
+        PRINT*,'Bad selector for variable caldyn : <', TRIM(caldyn_type),'> options are <gcm>, <adv>'
+        STOP
+    END SELECT
+        
+      
+  END SUBROUTINE init_caldyn
+
+  SUBROUTINE caldyn_BC(f_phis, f_wflux)
+    USE caldyn_gcm_mod, ONLY : caldyn_gcm_BC=>caldyn_BC
+    IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_phis(:), f_wflux(:)
+    SELECT CASE (TRIM(caldyn_type))
+    CASE('gcm')
+       CALL caldyn_gcm_BC(f_phis, f_wflux)
+    END SELECT
+  END SUBROUTINE caldyn_BC
+  
+  SUBROUTINE caldyn(write_out,f_phis, f_ps, f_mass, f_theta_rhodz, f_u, f_q, &
+       f_hflux, f_wflux, f_dps, f_dmass, f_dtheta_rhodz, f_du)
+  USE icosa
+  USE caldyn_gcm_mod, ONLY : caldyn_gcm=>caldyn
+  USE caldyn_adv_mod, ONLY : caldyn_adv=>caldyn
+  IMPLICIT NONE
+  LOGICAL,INTENT(IN)    :: write_out
+  TYPE(t_field),POINTER :: f_phis(:)
+  TYPE(t_field),POINTER :: f_ps(:)
+  TYPE(t_field),POINTER :: f_mass(:)
+  TYPE(t_field),POINTER :: f_theta_rhodz(:)
+  TYPE(t_field),POINTER :: f_u(:)
+  TYPE(t_field),POINTER :: f_q(:)
+  TYPE(t_field),POINTER :: f_hflux(:)
+  TYPE(t_field),POINTER :: f_wflux(:)
+  TYPE(t_field),POINTER :: f_dps(:)
+  TYPE(t_field),POINTER :: f_dmass(:)
+  TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
+  TYPE(t_field),POINTER :: f_du(:)
+
+    SELECT CASE (TRIM(caldyn_type))
+      CASE('gcm')
+        CALL caldyn_gcm(write_out,f_phis, f_ps, f_mass, f_theta_rhodz, f_u, f_q, &
+             f_hflux, f_wflux, f_dps, f_dmass, f_dtheta_rhodz, f_du)
+      CASE('adv')
+        CALL caldyn_adv(write_out,f_phis, f_ps, f_theta_rhodz, f_u, f_q, &
+             f_hflux, f_wflux, f_dps, f_dtheta_rhodz, f_du)
+    END SELECT
+  
+  END SUBROUTINE caldyn  
+
+END MODULE caldyn_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn_adv.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn_adv.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn_adv.f90	(revision 329)
@@ -0,0 +1,202 @@
+MODULE caldyn_adv_mod
+  USE icosa
+
+  IMPLICIT NONE
+  PRIVATE
+  PUBLIC :: init_caldyn, caldyn
+
+CONTAINS
+
+  SUBROUTINE init_caldyn
+  END SUBROUTINE init_caldyn
+
+  SUBROUTINE check_mass_conservation(f_ps,f_dps)
+    USE icosa
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_dps(:)
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: dps(:)
+    REAL(rstd) :: mass_tot,dmass_tot
+    INTEGER :: ind,i,j,ij
+
+    mass_tot=0
+    dmass_tot=0
+
+    CALL transfert_request(f_dps,req_i1)
+    CALL transfert_request(f_ps,req_i1)
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+
+       ps=f_ps(ind)
+       dps=f_dps(ind)
+
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             IF (domain(ind)%own(i,j)) THEN
+                mass_tot=mass_tot+ps(ij)*Ai(ij)/g
+                dmass_tot=dmass_tot+dps(ij)*Ai(ij)/g
+             ENDIF
+          ENDDO
+       ENDDO
+
+    ENDDO
+    PRINT*, "mass_tot ", mass_tot,"      dmass_tot ",dmass_tot        
+
+  END SUBROUTINE check_mass_conservation
+
+
+  SUBROUTINE caldyn(write_out,f_phis, f_ps, f_theta_rhodz, f_u, f_q, &
+       f_hflux, f_wflux, f_dps, f_dtheta_rhodz, f_du)
+    USE icosa
+    USE vorticity_mod
+    USE kinetic_mod
+    USE theta2theta_rhodz_mod
+    IMPLICIT NONE
+    LOGICAL,INTENT(IN)    :: write_out
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    TYPE(t_field),POINTER :: f_hflux(:), f_wflux(:)
+    TYPE(t_field),POINTER :: f_dps(:)
+    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
+    TYPE(t_field),POINTER :: f_du(:)
+
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: dps(:)
+    REAL(rstd),POINTER :: hflux(:,:), wflux(:,:)
+    REAL(rstd),POINTER :: dtheta_rhodz(:,:), du(:,:)  ! set to 0
+    INTEGER :: ind
+
+    CALL transfert_request(f_ps,req_i1) 
+    CALL transfert_request(f_u,req_e1_vect)
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       ps=f_ps(ind)
+       u=f_u(ind)
+       dps=f_dps(ind)
+       hflux=f_hflux(ind)
+       wflux=f_wflux(ind)
+       dtheta_rhodz=f_dtheta_rhodz(ind)
+       du=f_du(ind)
+
+!       !$OMP PARALLEL DEFAULT(SHARED)
+       CALL compute_caldyn(ps,u,hflux, wflux, dps, dtheta_rhodz, du)
+!       !$OMP END PARALLEL
+    ENDDO
+
+    IF (write_out) THEN
+       CALL writefield("ps",f_ps)
+       CALL writefield("wflux",f_wflux)
+    ENDIF
+    !    CALL check_mass_conservation(f_ps,f_dps)
+
+  END SUBROUTINE caldyn
+
+
+  SUBROUTINE compute_caldyn(ps,u, hflux,wflux,dps, dtheta_rhodz,du)
+    USE icosa
+    USE disvert_mod
+    IMPLICIT NONE
+    REAL(rstd),INTENT(IN)  :: ps(iim*jjm)
+    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: du(iim*3*jjm,llm), hflux(iim*3*jjm,llm) ! hflux in kg/s
+    REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: dps(iim*jjm)
+    REAL(rstd),INTENT(OUT) :: wflux(iim*jjm,llm+1) ! vertical mass flux (kg/m2/s)
+
+    REAL(rstd),ALLOCATABLE :: rhodz(:,:)
+    REAL(rstd),ALLOCATABLE :: divm(:,:)  ! mass flux divergence
+
+    INTEGER :: i,j,ij,l    
+    LOGICAL,SAVE :: first=.TRUE.
+
+    ALLOCATE(rhodz(iim*jjm,llm))
+    ALLOCATE(divm(iim*jjm,llm))    ! mass flux divergence
+
+    dtheta_rhodz(:,:)=0.
+    du(:,:)=0.
+
+!!! Compute mass
+    DO l = 1, llm
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             rhodz(ij,l) = (ap(l)-ap(l+1) + ps(ij)*(bp(l)-bp(l+1)) )/g
+          ENDDO
+       ENDDO
+    ENDDO
+
+    DO l = 1, llm
+!!!  Mass fluxes
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             hflux(ij+u_right,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)*le(ij+u_right)
+             hflux(ij+u_lup,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)*le(ij+u_lup)
+             hflux(ij+u_ldown,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)*le(ij+u_ldown)
+          ENDDO
+       ENDDO
+!!! Horizontal divergence of fluxes
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i  
+             ! divm = +div(mass flux), sign convention as in Ringler et al. 2012, eq. 21
+             divm(ij,l)= 1./Ai(ij)*(ne(ij,right)*hflux(ij+u_right,l)   +  &
+                  ne(ij,rup)*hflux(ij+u_rup,l)       +  &  
+                  ne(ij,lup)*hflux(ij+u_lup,l)       +  &  
+                  ne(ij,left)*hflux(ij+u_left,l)     +  &  
+                  ne(ij,ldown)*hflux(ij+u_ldown,l)   +  &  
+                  ne(ij,rdown)*hflux(ij+u_rdown,l))
+          ENDDO
+       ENDDO
+    ENDDO
+
+!!! cumulate mass flux divergence from top to bottom
+    DO  l = llm-1, 1, -1
+       !$OMP DO
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             divm(ij,l) = divm(ij,l) + divm(ij,l+1)
+          ENDDO
+       ENDDO
+    ENDDO
+
+!!! Compute vertical mass flux
+    DO l = 1,llm-1
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             ! w = int(z,ztop,div(flux)dz) + B(eta)dps/dt
+             ! => w>0 for upward transport
+             wflux( ij, l+1 ) = divm( ij, l+1 ) - bp(l+1) * divm( ij, 1 )
+          ENDDO
+       ENDDO
+    ENDDO
+
+    ! compute dps, set vertical mass flux at the surface to 0
+    DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          wflux(ij,1)  = 0.
+          ! dps/dt = -int(div flux)dz
+          dps(ij)=-divm(ij,1) * g 
+       ENDDO
+    ENDDO
+
+    DEALLOCATE(rhodz)
+    DEALLOCATE(divm)
+    
+  END SUBROUTINE compute_caldyn
+
+END MODULE caldyn_adv_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn_gcm.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn_gcm.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/caldyn_gcm.f90	(revision 329)
@@ -0,0 +1,1061 @@
+MODULE caldyn_gcm_mod
+  USE icosa
+  USE transfert_mod
+  PRIVATE
+
+  INTEGER, PARAMETER :: energy=1, enstrophy=2
+  TYPE(t_field),POINTER :: f_out_u(:), f_qu(:), f_qv(:)
+  REAL(rstd),SAVE,POINTER :: out_u(:,:), p(:,:), qu(:,:)
+  !$OMP THREADPRIVATE(out_u, p, qu)
+
+  TYPE(t_field),POINTER :: f_buf_i(:), f_buf_ulon(:), f_buf_ulat(:), f_buf_u3d(:)
+  TYPE(t_field),POINTER :: f_buf_v(:), f_buf_s(:), f_buf_p(:)
+
+! temporary shared variable for caldyn
+  TYPE(t_field),POINTER :: f_theta(:)
+  TYPE(t_field),POINTER :: f_pk(:)
+  TYPE(t_field),POINTER :: f_geopot(:)
+  TYPE(t_field),POINTER :: f_wwuu(:)
+  TYPE(t_field),POINTER :: f_planetvel(:)
+   
+  INTEGER :: caldyn_conserv
+ !$OMP THREADPRIVATE(caldyn_conserv) 
+ 
+  TYPE(t_message) :: req_ps, req_mass, req_theta_rhodz, req_u, req_qu
+
+  PUBLIC init_caldyn, caldyn_BC, caldyn, write_output_fields, &
+       req_ps, req_mass
+
+CONTAINS
+  
+  SUBROUTINE init_caldyn
+    USE icosa
+    USE exner_mod
+    USE mpipara
+    USE omp_para, ONLY: omp_master
+    IMPLICIT NONE
+    CHARACTER(len=255) :: def
+    INTEGER            :: ind
+    REAL(rstd),POINTER :: planetvel(:)
+  
+    def='energy'
+    CALL getin('caldyn_conserv',def)
+    SELECT CASE(TRIM(def))
+    CASE('energy')
+       caldyn_conserv=energy
+    CASE('enstrophy')
+       caldyn_conserv=enstrophy
+    CASE DEFAULT
+       IF (is_mpi_root) PRINT *,'Bad selector for variable caldyn_conserv : <', &
+            TRIM(def),'> options are <energy>, <enstrophy>'
+       STOP
+    END SELECT
+    IF (is_mpi_root .AND. omp_master) PRINT *, 'caldyn_conserv=',def
+
+    CALL allocate_caldyn
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       planetvel=f_planetvel(ind)
+       CALL compute_planetvel(planetvel)
+    END DO
+
+  END SUBROUTINE init_caldyn
+
+  SUBROUTINE allocate_caldyn
+  USE icosa
+  IMPLICIT NONE
+
+    CALL allocate_field(f_out_u,field_u,type_real,llm) 
+    CALL allocate_field(f_qu,field_u,type_real,llm) 
+    CALL allocate_field(f_qv,field_z,type_real,llm) 
+  
+    CALL allocate_field(f_buf_i,   field_t,type_real,llm)
+    CALL allocate_field(f_buf_p,   field_t,type_real,llm+1) 
+    CALL allocate_field(f_buf_u3d, field_t,type_real,3,llm)  ! 3D vel at cell centers
+    CALL allocate_field(f_buf_ulon,field_t,type_real,llm)
+    CALL allocate_field(f_buf_ulat,field_t,type_real,llm)
+    CALL allocate_field(f_buf_v,   field_z,type_real,llm)
+    CALL allocate_field(f_buf_s,   field_t,type_real)
+
+    CALL allocate_field(f_theta, field_t,type_real,llm,  name='theta')   ! potential temperature
+    CALL allocate_field(f_pk,    field_t,type_real,llm,  name='pk')
+    CALL allocate_field(f_geopot,field_t,type_real,llm+1,name='geopot')  ! geopotential
+    CALL allocate_field(f_wwuu,  field_u,type_real,llm+1,name='wwuu')
+    CALL allocate_field(f_planetvel,  field_u,type_real, name='planetvel') ! planetary velocity at r=a
+
+  END SUBROUTINE allocate_caldyn
+
+  SUBROUTINE caldyn_BC(f_phis, f_wflux)
+    USE icosa
+    USE mpipara
+    USE omp_para
+    IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_wflux(:)
+    REAL(rstd),POINTER  :: phis(:)
+    REAL(rstd),POINTER  :: wflux(:,:)
+    REAL(rstd),POINTER  :: geopot(:,:)
+    REAL(rstd),POINTER  :: wwuu(:,:)
+
+    INTEGER :: ind,i,j,ij,l
+
+    IF (omp_first) THEN
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          geopot=f_geopot(ind)
+          phis=f_phis(ind)
+          wflux=f_wflux(ind)
+          wwuu=f_wwuu(ind)
+          
+          DO ij=ij_begin_ext,ij_end_ext
+              ! lower BCs : geopot=phis, wflux=0, wwuu=0
+              geopot(ij,1) = phis(ij)
+              wflux(ij,1) = 0.
+              wwuu(ij+u_right,1)=0   
+              wwuu(ij+u_lup,1)=0   
+              wwuu(ij+u_ldown,1)=0
+              ! top BCs : wflux=0, wwuu=0
+              wflux(ij,llm+1)  = 0.
+              wwuu(ij+u_right,llm+1)=0   
+              wwuu(ij+u_lup,llm+1)=0   
+              wwuu(ij+u_ldown,llm+1)=0
+          ENDDO
+       END DO
+    ENDIF
+
+!    !$OMP BARRIER
+  END SUBROUTINE caldyn_BC
+   
+  SUBROUTINE caldyn(write_out,f_phis, f_ps, f_mass, f_theta_rhodz, f_u, f_q, &
+       f_hflux, f_wflux, f_dps, f_dmass, f_dtheta_rhodz, f_du)
+    USE icosa
+    USE disvert_mod, ONLY : caldyn_eta, eta_mass
+    USE vorticity_mod
+    USE kinetic_mod
+    USE theta2theta_rhodz_mod
+    USE wind_mod
+    USE mpipara
+    USE trace
+    USE omp_para
+    USE output_field_mod
+    IMPLICIT NONE
+    LOGICAL,INTENT(IN)    :: write_out
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_mass(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    TYPE(t_field),POINTER :: f_hflux(:), f_wflux(:)
+    TYPE(t_field),POINTER :: f_dps(:)
+    TYPE(t_field),POINTER :: f_dmass(:)
+    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
+    TYPE(t_field),POINTER :: f_du(:)
+    
+    REAL(rstd),POINTER :: ps(:), dps(:)
+    REAL(rstd),POINTER :: mass(:,:), theta_rhodz(:,:), dtheta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:), du(:,:), hflux(:,:), wflux(:,:)
+    REAL(rstd),POINTER :: qu(:,:)
+    REAL(rstd),POINTER :: qv(:,:)
+
+! temporary shared variable
+    REAL(rstd),POINTER  :: theta(:,:)  
+    REAL(rstd),POINTER  :: pk(:,:)
+    REAL(rstd),POINTER  :: geopot(:,:)
+    REAL(rstd),POINTER  :: convm(:,:) 
+    REAL(rstd),POINTER  :: wwuu(:,:)
+        
+    INTEGER :: ind
+    LOGICAL,SAVE :: first=.TRUE.
+!$OMP THREADPRIVATE(first)
+    
+    ! MPI messages need to be sent at first call to caldyn
+    ! This is needed only once : the next ones will be sent by timeloop
+    IF (first) THEN 
+      first=.FALSE.
+      IF(caldyn_eta==eta_mass) THEN
+         CALL init_message(f_ps,req_i1,req_ps)
+      ELSE
+         CALL init_message(f_mass,req_i1,req_mass)
+      END IF
+      CALL init_message(f_theta_rhodz,req_i1,req_theta_rhodz)
+      CALL init_message(f_u,req_e1_vect,req_u)
+      CALL init_message(f_qu,req_e1_scal,req_qu)
+!      IF(caldyn_eta==eta_mass) THEN
+!         CALL send_message(f_ps,req_ps) 
+!         CALL wait_message(req_ps)  
+!      ELSE
+!         CALL send_message(f_mass,req_mass) 
+!         CALL wait_message(req_mass)  
+!      END IF
+    ENDIF
+    
+    CALL trace_start("caldyn")
+
+      IF(caldyn_eta==eta_mass) THEN
+         CALL send_message(f_ps,req_ps) 
+         CALL wait_message(req_ps)  
+      ELSE
+         CALL send_message(f_mass,req_mass) 
+         CALL wait_message(req_mass)  
+      END IF
+
+    CALL send_message(f_u,req_u)
+    CALL wait_message(req_u)
+    CALL send_message(f_theta_rhodz,req_theta_rhodz) 
+    CALL wait_message(req_theta_rhodz) 
+    
+!    CALL wait_message(req_u)
+!    CALL wait_message(req_theta_rhodz) 
+
+    SELECT CASE(caldyn_conserv)
+    CASE(energy) ! energy-conserving
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          ps=f_ps(ind)
+          u=f_u(ind)
+          theta_rhodz = f_theta_rhodz(ind)
+          mass=f_mass(ind)
+          theta = f_theta(ind)
+          qu=f_qu(ind)
+          qv=f_qv(ind)
+          CALL compute_pvort(ps,u,theta_rhodz, mass,theta,qu,qv)
+       ENDDO
+
+       CALL send_message(f_qu,req_qu)
+       CALL wait_message(req_qu)
+
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          ps=f_ps(ind)
+          u=f_u(ind)
+          theta_rhodz=f_theta_rhodz(ind)
+          mass=f_mass(ind)
+          theta = f_theta(ind)
+          qu=f_qu(ind)
+          pk = f_pk(ind)
+          geopot = f_geopot(ind)  
+          CALL compute_geopot(ps,mass,theta, pk,geopot)
+          hflux=f_hflux(ind)
+          convm = f_dmass(ind)
+          dtheta_rhodz=f_dtheta_rhodz(ind)
+          du=f_du(ind)
+          CALL compute_caldyn_horiz(u,mass,qu,theta,pk,geopot, hflux,convm,dtheta_rhodz,du)
+          IF(caldyn_eta==eta_mass) THEN
+             wflux=f_wflux(ind)
+             wwuu=f_wwuu(ind)
+             dps=f_dps(ind)
+             CALL compute_caldyn_vert(u,theta,mass,convm, wflux,wwuu, dps, dtheta_rhodz, du)
+          END IF
+       ENDDO       
+       
+    CASE(enstrophy) ! enstrophy-conserving
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          ps=f_ps(ind)
+          u=f_u(ind)
+          theta_rhodz=f_theta_rhodz(ind)
+          mass=f_mass(ind)
+          theta = f_theta(ind)
+          qu=f_qu(ind)
+          qv=f_qv(ind)
+          CALL compute_pvort(ps,u,theta_rhodz, mass,theta,qu,qv)
+          pk = f_pk(ind)
+          geopot = f_geopot(ind)  
+          CALL compute_geopot(ps,mass,theta, pk,geopot)
+          hflux=f_hflux(ind)
+          convm = f_dmass(ind)
+          dtheta_rhodz=f_dtheta_rhodz(ind)
+          du=f_du(ind)
+          CALL compute_caldyn_horiz(u,mass,qu,theta,pk,geopot, hflux,convm,dtheta_rhodz,du)
+          IF(caldyn_eta==eta_mass) THEN
+             wflux=f_wflux(ind)
+             wwuu=f_wwuu(ind)
+             dps=f_dps(ind)
+             CALL compute_caldyn_vert(u,theta,mass,convm, wflux,wwuu, dps, dtheta_rhodz, du)
+          END IF
+       ENDDO
+       
+    CASE DEFAULT
+       STOP
+    END SELECT
+
+!!$OMP BARRIER
+    IF (write_out) THEN
+
+!       IF (is_mpi_root) PRINT *,'CALL write_output_fields'
+
+! ---> for openMP test to fix later
+!       CALL write_output_fields(f_ps, f_phis, f_dps, f_u, f_theta_rhodz, f_q, &
+!            f_buf_i, f_buf_v, f_buf_u3d, f_buf_ulon, f_buf_ulat, f_buf_s, f_buf_p)
+       CALL un2ulonlat(f_u, f_buf_ulon, f_buf_ulat)
+       CALL output_field("ulon",f_buf_ulon)
+       CALL output_field("ulat",f_buf_ulat)
+
+       CALL output_field("ps",f_ps)
+       CALL output_field("dps",f_dps)
+       CALL output_field("mass",f_mass)
+       CALL output_field("dmass",f_dmass)
+       CALL output_field("vort",f_qv)
+       CALL output_field("theta",f_theta)
+       CALL output_field("exner",f_pk)
+       CALL output_field("pv",f_qv)
+ 
+    END IF
+    
+    !    CALL check_mass_conservation(f_ps,f_dps)
+    CALL trace_end("caldyn")
+!!$OMP BARRIER
+    
+END SUBROUTINE caldyn
+
+SUBROUTINE compute_planetvel(planetvel)
+  USE wind_mod
+  REAL(rstd),INTENT(OUT)  :: planetvel(iim*3*jjm)
+  REAL(rstd) :: ulon(iim*3*jjm)
+  REAL(rstd) :: ulat(iim*3*jjm)
+  REAL(rstd) :: lon,lat
+  INTEGER :: ij
+  DO ij=ij_begin_ext,ij_end_ext
+     CALL xyz2lonlat(xyz_e(ij+u_right,:),lon,lat)
+     ulon(ij+u_right)=a*omega*cos(lat)
+     ulat(ij+u_right)=0
+
+     CALL xyz2lonlat(xyz_e(ij+u_lup,:),lon,lat)
+     ulon(ij+u_lup)=a*omega*cos(lat)
+     ulat(ij+u_lup)=0
+
+     CALL xyz2lonlat(xyz_e(ij+u_ldown,:),lon,lat)
+     ulon(ij+u_ldown)=a*omega*cos(lat)
+     ulat(ij+u_ldown)=0
+  END DO
+  CALL compute_wind2D_perp_from_lonlat_compound(ulon, ulat, planetvel)
+END SUBROUTINE compute_planetvel
+    
+SUBROUTINE compute_pvort(ps,u,theta_rhodz, rhodz,theta,qu,qv)
+  USE icosa
+  USE disvert_mod, ONLY : mass_dak, mass_dbk, caldyn_eta, eta_mass
+  USE exner_mod
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+  REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)
+  REAL(rstd),INTENT(IN)  :: ps(iim*jjm)
+  REAL(rstd),INTENT(IN)  :: theta_rhodz(iim*jjm,llm)
+  REAL(rstd),INTENT(INOUT) :: rhodz(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: theta(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: qu(iim*3*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: qv(iim*2*jjm,llm)
+  
+  INTEGER :: i,j,ij,l
+  REAL(rstd) :: etav,hv, m
+!  REAL(rstd) :: qv(2*iim*jjm,llm)     ! potential velocity  
+  
+  CALL trace_start("compute_pvort")  
+
+  IF(caldyn_eta==eta_mass) THEN
+!     CALL wait_message(req_ps)  
+  ELSE
+!     CALL wait_message(req_mass)
+  END IF
+!  CALL wait_message(req_theta_rhodz) 
+
+  IF(caldyn_eta==eta_mass) THEN ! Compute mass & theta
+     DO l = ll_begin,ll_end
+!        CALL test_message(req_u) 
+!DIR$ SIMD
+        DO ij=ij_begin_ext,ij_end_ext
+           m = ( mass_dak(l)+ps(ij)*mass_dbk(l) )/g
+           rhodz(ij,l) = m
+           theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l)
+        ENDDO
+     ENDDO
+  ELSE ! Compute only theta
+     DO l = ll_begin,ll_end
+!        CALL test_message(req_u) 
+!DIR$ SIMD
+       DO ij=ij_begin_ext,ij_end_ext
+         theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l)
+       ENDDO
+     ENDDO
+  END IF
+
+!  CALL wait_message(req_u)   
+  
+!!! Compute shallow-water potential vorticity
+  DO l = ll_begin,ll_end
+!DIR$ SIMD
+     DO ij=ij_begin_ext,ij_end_ext
+          etav= 1./Av(ij+z_up)*(  ne_rup        * u(ij+u_rup,l)        * de(ij+u_rup)         &
+                                + ne_left * u(ij+t_rup+u_left,l) * de(ij+t_rup+u_left)  &
+                                - ne_lup        * u(ij+u_lup,l)        * de(ij+u_lup) )                               
+
+          hv =  Riv2(ij,vup)          * rhodz(ij,l)            &
+              + Riv2(ij+t_rup,vldown) * rhodz(ij+t_rup,l)     &
+              + Riv2(ij+t_lup,vrdown) * rhodz(ij+t_lup,l)
+     
+          qv(ij+z_up,l) = ( etav+fv(ij+z_up) )/hv
+          
+          etav = 1./Av(ij+z_down)*(  ne_ldown         * u(ij+u_ldown,l)          * de(ij+u_ldown)          &
+                                   + ne_right * u(ij+t_ldown+u_right,l)  * de(ij+t_ldown+u_right)  &
+                                   - ne_rdown         * u(ij+u_rdown,l)          * de(ij+u_rdown) )
+       
+          hv =  Riv2(ij,vdown)        * rhodz(ij,l)          &
+              + Riv2(ij+t_ldown,vrup) * rhodz(ij+t_ldown,l)  &
+              + Riv2(ij+t_rdown,vlup) * rhodz(ij+t_rdown,l)
+                       
+          qv(ij+z_down,l) =( etav+fv(ij+z_down) )/hv
+
+      ENDDO
+
+!DIR$ SIMD
+      DO ij=ij_begin,ij_end
+         qu(ij+u_right,l) = 0.5*(qv(ij+z_rdown,l)+qv(ij+z_rup,l))  
+         qu(ij+u_lup,l) = 0.5*(qv(ij+z_up,l)+qv(ij+z_lup,l))  
+         qu(ij+u_ldown,l) = 0.5*(qv(ij+z_ldown,l)+qv(ij+z_down,l))  
+      END DO
+      
+   ENDDO
+
+   CALL trace_end("compute_pvort")
+                                                       
+  END SUBROUTINE compute_pvort
+  
+  SUBROUTINE compute_geopot(ps,rhodz,theta, pk,geopot) 
+  USE icosa
+  USE disvert_mod
+  USE exner_mod
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    REAL(rstd),INTENT(INOUT) :: ps(iim*jjm)
+    REAL(rstd),INTENT(IN)    :: rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm)    ! potential temperature
+    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm)       ! Exner function
+    REAL(rstd),INTENT(INOUT) :: geopot(iim*jjm,llm+1) ! geopotential
+    
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: p_ik, exner_ik
+
+    CALL trace_start("compute_geopot")
+
+    IF(caldyn_eta==eta_mass) THEN
+
+!!! Compute exner function and geopotential
+       DO l = 1,llm
+!         !$OMP DO SCHEDULE(STATIC) 
+          !DIR$ SIMD
+          DO ij=ij_begin_ext,ij_end_ext         
+             p_ik = ptop + mass_ak(l) + mass_bk(l)*ps(ij) ! FIXME : leave ps for the moment ; change ps to Ms later
+             !         p_ik = ptop + g*(mass_ak(l)+ mass_bk(l)*ps(i,j))
+             exner_ik = cpp * (p_ik/preff) ** kappa
+             pk(ij,l) = exner_ik
+             ! specific volume v = kappa*theta*pi/p = dphi/g/rhodz
+             geopot(ij,l+1) = geopot(ij,l) + (g*kappa)*rhodz(ij,l)*theta(ij,l)*exner_ik/p_ik
+          ENDDO
+       ENDDO
+
+    ELSE 
+       ! We are using a Lagrangian vertical coordinate
+       ! Pressure must be computed first top-down (temporarily stored in pk)
+       ! Then Exner pressure and geopotential are computed bottom-up
+       ! Notice that the computation below should work also when caldyn_eta=eta_mass          
+
+       IF(boussinesq) THEN ! compute only geopotential : pressure pk will be computed in compute_caldyn_horiz
+          ! specific volume 1 = dphi/g/rhodz
+          DO l = 1,llm
+!             !$OMP DO SCHEDULE(STATIC) 
+             !DIR$ SIMD
+             DO ij=ij_begin_ext,ij_end_ext         
+                geopot(ij,l+1) = geopot(ij,l) + g*rhodz(ij,l)
+             ENDDO
+          ENDDO
+       ELSE ! non-Boussinesq, compute geopotential and Exner pressure
+          ! uppermost layer
+          !DIR$ SIMD
+          DO ij=ij_begin_ext,ij_end_ext         
+             pk(ij,llm) = ptop + (.5*g)*rhodz(ij,llm)
+          END DO
+          ! other layers
+          DO l = llm-1, 1, -1
+
+!          !$OMP DO SCHEDULE(STATIC) 
+             !DIR$ SIMD
+             DO ij=ij_begin_ext,ij_end_ext         
+                pk(ij,l) = pk(ij,l+1) + (.5*g)*(rhodz(ij,l)+rhodz(ij,l+1))
+             END DO
+          END DO
+          ! surface pressure (for diagnostics)
+          DO ij=ij_begin_ext,ij_end_ext         
+             ps(ij) = pk(ij,1) + (.5*g)*rhodz(ij,1)
+          END DO
+
+          ! specific volume v = kappa*theta*pi/p = dphi/g/rhodz
+          DO l = 1,llm
+
+!             !$OMP DO SCHEDULE(STATIC) 
+             !DIR$ SIMD
+             DO ij=ij_begin_ext,ij_end_ext         
+                p_ik = pk(ij,l)
+                exner_ik = cpp * (p_ik/preff) ** kappa
+                geopot(ij,l+1) = geopot(ij,l) + (g*kappa)*rhodz(ij,l)*theta(ij,l)*exner_ik/p_ik 
+                pk(ij,l) = exner_ik
+             ENDDO
+          ENDDO
+       END IF
+
+    END IF
+
+  CALL trace_end("compute_geopot")
+
+  END SUBROUTINE compute_geopot
+
+  SUBROUTINE compute_caldyn_horiz(u,rhodz,qu,theta,pk,geopot, hflux,convm, dtheta_rhodz, du)
+  USE icosa
+  USE disvert_mod
+  USE exner_mod
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)    ! prognostic "velocity"
+    REAL(rstd),INTENT(IN)  :: rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(IN)  :: qu(iim*3*jjm,llm)
+    REAL(rstd),INTENT(IN)  :: theta(iim*jjm,llm)  ! potential temperature
+    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm) ! Exner function
+    REAL(rstd),INTENT(IN)  :: geopot(iim*jjm,llm+1)    ! geopotential
+
+    REAL(rstd),INTENT(OUT) :: hflux(iim*3*jjm,llm) ! hflux in kg/s
+    REAL(rstd),INTENT(OUT) :: convm(iim*jjm,llm)  ! mass flux convergence
+    REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: du(iim*3*jjm,llm)
+
+    REAL(rstd) :: cor_NT(iim*jjm,llm)  ! NT coriolis force u.(du/dPhi)
+    REAL(rstd) :: urel(3*iim*jjm,llm)  ! relative velocity
+    REAL(rstd) :: Ftheta(3*iim*jjm,llm) ! theta flux
+    REAL(rstd) :: berni(iim*jjm,llm)  ! Bernoulli function
+    
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: ww,uu
+
+    CALL trace_start("compute_caldyn_horiz")
+
+!    CALL wait_message(req_theta_rhodz) 
+
+  DO l = ll_begin, ll_end
+!!!  Compute mass and theta fluxes
+!    IF (caldyn_conserv==energy) CALL test_message(req_qu) 
+!DIR$ SIMD
+    DO ij=ij_begin_ext,ij_end_ext         
+        hflux(ij+u_right,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)*le(ij+u_right)
+        hflux(ij+u_lup,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)*le(ij+u_lup)
+        hflux(ij+u_ldown,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)*le(ij+u_ldown)
+
+        Ftheta(ij+u_right,l)=0.5*(theta(ij,l)+theta(ij+t_right,l))*hflux(ij+u_right,l)
+        Ftheta(ij+u_lup,l)=0.5*(theta(ij,l)+theta(ij+t_lup,l))*hflux(ij+u_lup,l)
+        Ftheta(ij+u_ldown,l)=0.5*(theta(ij,l)+theta(ij+t_ldown,l))*hflux(ij+u_ldown,l)
+    ENDDO
+
+!!! compute horizontal divergence of fluxes
+!DIR$ SIMD
+    DO ij=ij_begin,ij_end         
+        ! convm = -div(mass flux), sign convention as in Ringler et al. 2012, eq. 21
+        convm(ij,l)= -1./Ai(ij)*(ne_right*hflux(ij+u_right,l)   +  &
+                                ne_rup*hflux(ij+u_rup,l)       +  &  
+                                ne_lup*hflux(ij+u_lup,l)       +  &  
+                                ne_left*hflux(ij+u_left,l)     +  &  
+                                ne_ldown*hflux(ij+u_ldown,l)   +  &  
+                                ne_rdown*hflux(ij+u_rdown,l))    
+
+        ! signe ? attention d (rho theta dz)
+        ! dtheta_rhodz =  -div(flux.theta)
+        dtheta_rhodz(ij,l)=-1./Ai(ij)*(ne_right*Ftheta(ij+u_right,l)    +  &
+                                 ne_rup*Ftheta(ij+u_rup,l)        +  &  
+                                 ne_lup*Ftheta(ij+u_lup,l)        +  &  
+                                 ne_left*Ftheta(ij+u_left,l)      +  &  
+                                 ne_ldown*Ftheta(ij+u_ldown,l)    +  &  
+                                 ne_rdown*Ftheta(ij+u_rdown,l))
+    ENDDO
+
+ END DO
+
+!!! Compute potential vorticity (Coriolis) contribution to du
+ 
+    SELECT CASE(caldyn_conserv)
+    CASE(energy) ! energy-conserving TRiSK
+
+!       CALL wait_message(req_qu)
+
+        DO l=ll_begin,ll_end
+!DIR$ SIMD
+          DO ij=ij_begin,ij_end         
+    
+                uu = wee(ij+u_right,1,1)*hflux(ij+u_rup,l)*(qu(ij+u_right,l)+qu(ij+u_rup,l))+                             &
+                     wee(ij+u_right,2,1)*hflux(ij+u_lup,l)*(qu(ij+u_right,l)+qu(ij+u_lup,l))+                             &
+                     wee(ij+u_right,3,1)*hflux(ij+u_left,l)*(qu(ij+u_right,l)+qu(ij+u_left,l))+                           &
+                     wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+u_ldown,l))+                         &
+                     wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+u_rdown,l))+                         & 
+                     wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_ldown,l))+         &
+                     wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_rdown,l))+         &
+                     wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_right,l))+         &
+                     wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_rup,l))+             &
+                     wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l)*(qu(ij+u_right,l)+qu(ij+t_right+u_lup,l))
+                du(ij+u_right,l) = .5*uu/de(ij+u_right)
+                
+                uu = wee(ij+u_lup,1,1)*hflux(ij+u_left,l)*(qu(ij+u_lup,l)+qu(ij+u_left,l)) +                        &
+                     wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+u_ldown,l)) +                      &
+                     wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)*(qu(ij+u_lup,l)+qu(ij+u_rdown,l)) +                      &
+                     wee(ij+u_lup,4,1)*hflux(ij+u_right,l)*(qu(ij+u_lup,l)+qu(ij+u_right,l)) +                      &
+                     wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+u_rup,l)) +                          & 
+                     wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_right,l)) +          &
+                     wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_rup,l)) +              &
+                     wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_lup,l)) +              &
+                     wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_left,l)) +            &
+                     wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l)*(qu(ij+u_lup,l)+qu(ij+t_lup+u_ldown,l))
+                du(ij+u_lup,l) = .5*uu/de(ij+u_lup)
+
+                
+                uu = wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+u_rdown,l)) +                      &
+                     wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+u_right,l)) +                      &
+                     wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)*(qu(ij+u_ldown,l)+qu(ij+u_rup,l)) +                          &
+                     wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+u_lup,l)) +                          &
+                     wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+u_left,l)) +                        & 
+                     wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_lup,l)) +          &
+                     wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_left,l)) +        &
+                     wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_ldown,l)) +      &
+                     wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_rdown,l)) +      &
+                     wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l)*(qu(ij+u_ldown,l)+qu(ij+t_ldown+u_right,l))
+                du(ij+u_ldown,l) = .5*uu/de(ij+u_ldown)
+                
+          ENDDO
+       ENDDO
+       
+    CASE(enstrophy) ! enstrophy-conserving TRiSK
+  
+        DO l=ll_begin,ll_end
+!DIR$ SIMD
+          DO ij=ij_begin,ij_end         
+
+                uu = wee(ij+u_right,1,1)*hflux(ij+u_rup,l)+                           &
+                     wee(ij+u_right,2,1)*hflux(ij+u_lup,l)+                           &
+                     wee(ij+u_right,3,1)*hflux(ij+u_left,l)+                          &
+                     wee(ij+u_right,4,1)*hflux(ij+u_ldown,l)+                         &
+                     wee(ij+u_right,5,1)*hflux(ij+u_rdown,l)+                         & 
+                     wee(ij+u_right,1,2)*hflux(ij+t_right+u_ldown,l)+                 &
+                     wee(ij+u_right,2,2)*hflux(ij+t_right+u_rdown,l)+                 &
+                     wee(ij+u_right,3,2)*hflux(ij+t_right+u_right,l)+                 &
+                     wee(ij+u_right,4,2)*hflux(ij+t_right+u_rup,l)+                   &
+                     wee(ij+u_right,5,2)*hflux(ij+t_right+u_lup,l)
+                du(ij+u_right,l) = qu(ij+u_right,l)*uu/de(ij+u_right)
+                
+                
+                uu = wee(ij+u_lup,1,1)*hflux(ij+u_left,l)+                        &
+                     wee(ij+u_lup,2,1)*hflux(ij+u_ldown,l)+                       &
+                     wee(ij+u_lup,3,1)*hflux(ij+u_rdown,l)+                       &
+                     wee(ij+u_lup,4,1)*hflux(ij+u_right,l)+                       &
+                     wee(ij+u_lup,5,1)*hflux(ij+u_rup,l)+                         & 
+                     wee(ij+u_lup,1,2)*hflux(ij+t_lup+u_right,l)+                 &
+                     wee(ij+u_lup,2,2)*hflux(ij+t_lup+u_rup,l)+                   &
+                     wee(ij+u_lup,3,2)*hflux(ij+t_lup+u_lup,l)+                   &
+                     wee(ij+u_lup,4,2)*hflux(ij+t_lup+u_left,l)+                  &
+                     wee(ij+u_lup,5,2)*hflux(ij+t_lup+u_ldown,l)
+                du(ij+u_lup,l) = qu(ij+u_lup,l)*uu/de(ij+u_lup)
+
+                uu = wee(ij+u_ldown,1,1)*hflux(ij+u_rdown,l)+                      &
+                     wee(ij+u_ldown,2,1)*hflux(ij+u_right,l)+                      &
+                     wee(ij+u_ldown,3,1)*hflux(ij+u_rup,l)+                        &
+                     wee(ij+u_ldown,4,1)*hflux(ij+u_lup,l)+                        &
+                     wee(ij+u_ldown,5,1)*hflux(ij+u_left,l)+                       & 
+                     wee(ij+u_ldown,1,2)*hflux(ij+t_ldown+u_lup,l)+                &
+                     wee(ij+u_ldown,2,2)*hflux(ij+t_ldown+u_left,l)+               &
+                     wee(ij+u_ldown,3,2)*hflux(ij+t_ldown+u_ldown,l)+              &
+                     wee(ij+u_ldown,4,2)*hflux(ij+t_ldown+u_rdown,l)+              &
+                     wee(ij+u_ldown,5,2)*hflux(ij+t_ldown+u_right,l)
+                du(ij+u_ldown,l) = qu(ij+u_ldown,l)*uu/de(ij+u_ldown)
+     
+          ENDDO
+       ENDDO
+       
+    CASE DEFAULT
+       STOP
+    END SELECT
+  
+!!! Compute bernouilli term = Kinetic Energy + geopotential
+    IF(boussinesq) THEN
+       ! first use hydrostatic balance with theta*rhodz to find pk (Lagrange multiplier=pressure) 
+       ! uppermost layer
+       !DIR$ SIMD
+       DO ij=ij_begin_ext,ij_end_ext         
+          pk(ij,llm) = ptop + (.5*g)*theta(ij,llm)*rhodz(ij,llm)
+       END DO
+       ! other layers
+       DO l = llm-1, 1, -1
+!          !$OMP DO SCHEDULE(STATIC) 
+          !DIR$ SIMD
+          DO ij=ij_begin_ext,ij_end_ext         
+             pk(ij,l) = pk(ij,l+1) + (.5*g)*(theta(ij,l)*rhodz(ij,l)+theta(ij,l+1)*rhodz(ij,l+1))
+          END DO
+       END DO
+       ! surface pressure (for diagnostics) FIXME
+       ! DO ij=ij_begin_ext,ij_end_ext         
+       !   ps(ij) = pk(ij,1) + (.5*g)*theta(ij,1)*rhodz(ij,1)
+       ! END DO
+       ! now pk contains the Lagrange multiplier (pressure)
+
+       DO l=ll_begin,ll_end
+!DIR$ SIMD
+          DO ij=ij_begin,ij_end         
+                
+                berni(ij,l) = pk(ij,l) + &
+                       1/(4*Ai(ij))*(le(ij+u_right)*de(ij+u_right)*u(ij+u_right,l)**2 +    &
+                                     le(ij+u_rup)*de(ij+u_rup)*u(ij+u_rup,l)**2 +          &
+                                     le(ij+u_lup)*de(ij+u_lup)*u(ij+u_lup,l)**2 +          &
+                                     le(ij+u_left)*de(ij+u_left)*u(ij+u_left,l)**2 +       &
+                                     le(ij+u_ldown)*de(ij+u_ldown)*u(ij+u_ldown,l)**2 +    &
+                                     le(ij+u_rdown)*de(ij+u_rdown)*u(ij+u_rdown,l)**2 )  
+                ! from now on pk contains the vertically-averaged geopotential
+                pk(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
+          ENDDO
+       ENDDO
+
+    ELSE ! compressible
+
+       DO l=ll_begin,ll_end
+!DIR$ SIMD
+            DO ij=ij_begin,ij_end         
+                
+                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
+                     + 1/(4*Ai(ij))*(le(ij+u_right)*de(ij+u_right)*u(ij+u_right,l)**2 +    &
+                                     le(ij+u_rup)*de(ij+u_rup)*u(ij+u_rup,l)**2 +          &
+                                     le(ij+u_lup)*de(ij+u_lup)*u(ij+u_lup,l)**2 +          &
+                                     le(ij+u_left)*de(ij+u_left)*u(ij+u_left,l)**2 +       &
+                                     le(ij+u_ldown)*de(ij+u_ldown)*u(ij+u_ldown,l)**2 +    &
+                                     le(ij+u_rdown)*de(ij+u_rdown)*u(ij+u_rdown,l)**2 )  
+          ENDDO
+       ENDDO
+
+    END IF ! Boussinesq/compressible
+
+!!! Add gradients of Bernoulli and Exner functions to du
+    DO l=ll_begin,ll_end
+!DIR$ SIMD
+       DO ij=ij_begin,ij_end         
+        
+             du(ij+u_right,l) = du(ij+u_right,l) + 1/de(ij+u_right) * (             &
+                               0.5*(theta(ij,l)+theta(ij+t_right,l))                &
+                                  *( ne_right*pk(ij,l)+ne_left*pk(ij+t_right,l))    &
+                                   + ne_right*berni(ij,l)+ne_left*berni(ij+t_right,l) )
+        
+        
+             du(ij+u_lup,l) = du(ij+u_lup,l) +  1/de(ij+u_lup) * (                  &
+                               0.5*(theta(ij,l)+theta(ij+t_lup,l))                  &
+                                  *( ne_lup*pk(ij,l)+ne_rdown*pk(ij+t_lup,l))       &
+                                   + ne_lup*berni(ij,l)+ne_rdown*berni(ij+t_lup,l) )
+                
+             du(ij+u_ldown,l) = du(ij+u_ldown,l) + 1/de(ij+u_ldown) * (             &
+                               0.5*(theta(ij,l)+theta(ij+t_ldown,l))                &
+                                  *( ne_ldown*pk(ij,l)+ne_rup*pk(ij+t_ldown,l))     &
+                                   + ne_ldown*berni(ij,l)+ne_rup*berni(ij+t_ldown,l) )
+
+       ENDDO
+    ENDDO
+ 
+    CALL trace_end("compute_caldyn_horiz")
+
+END SUBROUTINE compute_caldyn_horiz
+
+SUBROUTINE compute_caldyn_vert(u,theta,rhodz,convm, wflux,wwuu, dps,dtheta_rhodz,du)
+  USE icosa
+  USE disvert_mod
+  USE exner_mod
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN)  :: u(iim*3*jjm,llm)
+    REAL(rstd),INTENT(IN)  :: theta(iim*jjm,llm)
+    REAL(rstd),INTENT(IN)  :: rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(INOUT)  :: convm(iim*jjm,llm)  ! mass flux convergence
+
+    REAL(rstd),INTENT(INOUT) :: wflux(iim*jjm,llm+1) ! vertical mass flux (kg/m2/s)
+    REAL(rstd),INTENT(INOUT) :: wwuu(iim*3*jjm,llm+1)
+    REAL(rstd),INTENT(OUT) :: du(iim*3*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: dtheta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: dps(iim*jjm)
+
+! temporary variable    
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: p_ik, exner_ik
+
+!    REAL(rstd) :: wwuu(iim*3*jjm,llm+1) ! tmp var, don't know why but gain 30% on the whole code in opemp
+                                        ! need to be understood
+
+!    wwuu=wwuu_out
+  CALL trace_start("compute_caldyn_vert")
+
+!!$OMP BARRIER   
+!!! cumulate mass flux convergence from top to bottom
+  DO  l = llm-1, 1, -1
+!    IF (caldyn_conserv==energy) CALL test_message(req_qu) 
+
+!!$OMP DO SCHEDULE(STATIC) 
+!DIR$ SIMD
+    DO ij=ij_begin,ij_end         
+        convm(ij,l) = convm(ij,l) + convm(ij,l+1)
+    ENDDO
+  ENDDO
+
+! IMPLICIT FLUSH on convm
+!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! compute dps
+  IF (omp_first) THEN
+!DIR$ SIMD
+     DO ij=ij_begin,ij_end         
+        ! dps/dt = -int(div flux)dz
+        dps(ij) = convm(ij,1) * g 
+    ENDDO
+  ENDIF
+  
+!!! Compute vertical mass flux (l=1,llm+1 done by caldyn_BC)
+  DO l=ll_beginp1,ll_end
+!    IF (caldyn_conserv==energy) CALL test_message(req_qu) 
+!DIR$ SIMD
+      DO ij=ij_begin,ij_end         
+        ! w = int(z,ztop,div(flux)dz) + B(eta)dps/dt
+        ! => w>0 for upward transport
+        wflux( ij, l ) = bp(l) * convm( ij, 1 ) - convm( ij, l ) 
+    ENDDO
+  ENDDO
+
+  DO l=ll_begin,ll_endm1
+!DIR$ SIMD
+     DO ij=ij_begin,ij_end         
+        dtheta_rhodz(ij, l ) = dtheta_rhodz(ij, l )  -   0.5 * (  wflux(ij,l+1) * (theta(ij,l) + theta(ij,l+1)))
+    ENDDO
+  ENDDO
+  
+  DO l=ll_beginp1,ll_end
+!DIR$ SIMD
+      DO ij=ij_begin,ij_end         
+        dtheta_rhodz(ij, l ) = dtheta_rhodz(ij, l )  +   0.5 * ( wflux(ij,l  ) * (theta(ij,l-1) + theta(ij,l) ) )
+    ENDDO
+  ENDDO
+  
+! Compute vertical transport
+  DO l=ll_beginp1,ll_end
+!DIR$ SIMD
+      DO ij=ij_begin,ij_end         
+        wwuu(ij+u_right,l) = 0.5*( wflux(ij,l) + wflux(ij+t_right,l)) * (u(ij+u_right,l) - u(ij+u_right,l-1))
+        wwuu(ij+u_lup,l) = 0.5* ( wflux(ij,l) + wflux(ij+t_lup,l)) * (u(ij+u_lup,l) - u(ij+u_lup,l-1))
+        wwuu(ij+u_ldown,l) = 0.5*( wflux(ij,l) + wflux(ij+t_ldown,l)) * (u(ij+u_ldown,l) - u(ij+u_ldown,l-1))
+     ENDDO
+   ENDDO
+
+ !--> flush wwuu  
+ ! !$OMP BARRIER
+
+! Add vertical transport to du
+  DO l=ll_begin,ll_end
+!DIR$ SIMD
+     DO ij=ij_begin,ij_end         
+        du(ij+u_right, l )   = du(ij+u_right,l)  - (wwuu(ij+u_right,l+1)+ wwuu(ij+u_right,l)) / (rhodz(ij,l)+rhodz(ij+t_right,l))
+        du(ij+u_lup, l )     = du(ij+u_lup,l)    - (wwuu(ij+u_lup,l+1)  + wwuu(ij+u_lup,l))   / (rhodz(ij,l)+rhodz(ij+t_lup,l))
+        du(ij+u_ldown, l )   = du(ij+u_ldown,l)  - (wwuu(ij+u_ldown,l+1)+ wwuu(ij+u_ldown,l)) / (rhodz(ij,l)+rhodz(ij+t_ldown,l))
+    ENDDO
+  ENDDO      
+
+!  DO l=ll_beginp1,ll_end
+!!DIR$ SIMD
+!      DO ij=ij_begin,ij_end         
+!        wwuu_out(ij+u_right,l) = wwuu(ij+u_right,l)
+!        wwuu_out(ij+u_lup,l)   = wwuu(ij+u_lup,l)
+!        wwuu_out(ij+u_ldown,l) = wwuu(ij+u_ldown,l)
+!     ENDDO
+!   ENDDO
+  
+  CALL trace_end("compute_caldyn_vert")
+
+  END SUBROUTINE compute_caldyn_vert
+
+!-------------------------------- Diagnostics ----------------------------
+
+  SUBROUTINE check_mass_conservation(f_ps,f_dps)
+  USE icosa
+  USE mpipara
+  USE omp_para, ONLY: omp_master
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_dps(:)
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: dps(:)
+    REAL(rstd) :: mass_tot,dmass_tot
+    INTEGER :: ind,i,j,ij
+    
+    mass_tot=0
+    dmass_tot=0
+    
+    CALL transfert_request(f_dps,req_i1)
+    CALL transfert_request(f_ps,req_i1)
+
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+
+      ps=f_ps(ind)
+      dps=f_dps(ind)
+
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          IF (domain(ind)%own(i,j)) THEN
+            mass_tot=mass_tot+ps(ij)*Ai(ij)/g
+            dmass_tot=dmass_tot+dps(ij)*Ai(ij)/g
+          ENDIF
+        ENDDO
+      ENDDO
+   
+    ENDDO
+    IF (is_mpi_root .AND. omp_master) PRINT*, "mass_tot ", mass_tot,"      dmass_tot ",dmass_tot        
+
+  END SUBROUTINE check_mass_conservation  
+  
+  SUBROUTINE write_output_fields(f_ps, f_phis, f_dps, f_u, f_theta_rhodz, f_q, &
+       f_buf_i, f_buf_v, f_buf_i3, f_buf1_i, f_buf2_i, f_buf_s, f_buf_p)
+    USE icosa
+    USE vorticity_mod
+    USE theta2theta_rhodz_mod
+    USE pression_mod
+    USE omega_mod
+    USE write_field
+    USE vertical_interp_mod
+    USE wind_mod
+    TYPE(t_field),POINTER :: f_ps(:), f_phis(:), f_u(:), f_theta_rhodz(:), f_q(:), f_dps(:), &
+         f_buf_i(:), f_buf_v(:), f_buf_i3(:), f_buf1_i(:), f_buf2_i(:), f_buf_s(:), f_buf_p(:)
+    
+    REAL(rstd) :: out_pression_lev
+    CHARACTER(LEN=255) :: str_pression
+    CHARACTER(LEN=255) :: physics_type
+    
+    out_pression_level=0
+    CALL getin("out_pression_level",out_pression_level) 
+    WRITE(str_pression,*) INT(out_pression_level/100)
+    str_pression=ADJUSTL(str_pression)
+    
+    CALL writefield("ps",f_ps)
+    CALL writefield("dps",f_dps)
+    CALL writefield("phis",f_phis)
+    CALL vorticity(f_u,f_buf_v)
+    CALL writefield("vort",f_buf_v)
+
+    CALL w_omega(f_ps, f_u, f_buf_i)
+    CALL writefield('omega', f_buf_i)
+    IF (out_pression_level<=preff .AND. out_pression_level > 0) THEN
+      CALL vertical_interp(f_ps,f_buf_i,f_buf_s,out_pression_level)
+      CALL writefield("omega"//TRIM(str_pression),f_buf_s)
+    ENDIF
+    
+    ! Temperature
+!    CALL theta_rhodz2temperature(f_ps,f_theta_rhodz,f_buf_i) ; ! FIXME
+     
+    CALL getin('physics',physics_type)
+    IF (TRIM(physics_type)=='dcmip') THEN
+      CALL Tv2T(f_buf_i,f_q,f_buf1_i) 
+      CALL writefield("T",f_buf1_i)
+      IF (out_pression_level<=preff .AND. out_pression_level > 0) THEN
+        CALL vertical_interp(f_ps,f_buf1_i,f_buf_s,out_pression_level)
+        CALL writefield("T"//TRIM(str_pression),f_buf_s)
+      ENDIF
+    ELSE
+      CALL writefield("T",f_buf_i)
+      IF (out_pression_level<=preff .AND. out_pression_level > 0) THEN
+        CALL vertical_interp(f_ps,f_buf_i,f_buf_s,out_pression_level)
+        CALL writefield("T"//TRIM(str_pression),f_buf_s)
+      ENDIF
+    ENDIF
+   
+    ! velocity components
+    CALL un2ulonlat(f_u, f_buf1_i, f_buf2_i)
+    CALL writefield("ulon",f_buf1_i)
+    CALL writefield("ulat",f_buf2_i)
+
+    IF (out_pression_level<=preff .AND. out_pression_level > 0) THEN
+      CALL vertical_interp(f_ps,f_buf1_i,f_buf_s,out_pression_level)
+      CALL writefield("ulon"//TRIM(str_pression),f_buf_s)
+      CALL vertical_interp(f_ps,f_buf2_i,f_buf_s,out_pression_level)
+      CALL writefield("ulat"//TRIM(str_pression),f_buf_s)
+    ENDIF
+    
+    ! geopotential ! FIXME
+    CALL thetarhodz2geopot(f_ps,f_phis,f_theta_rhodz, f_buf_s,f_buf_p,f_buf1_i,f_buf2_i,f_buf_i)
+    CALL writefield("p",f_buf_p)
+    CALL writefield("phi",f_geopot)   ! geopotential
+    CALL writefield("theta",f_buf1_i) ! potential temperature
+    CALL writefield("pk",f_buf2_i)    ! Exner pressure
+  
+  END SUBROUTINE write_output_fields
+  
+  SUBROUTINE thetarhodz2geopot(f_ps,f_phis,f_theta_rhodz, f_pks,f_p,f_theta,f_pk,f_phi) 
+    USE field_mod
+    USE pression_mod
+    USE exner_mod
+    USE geopotential_mod
+    USE theta2theta_rhodz_mod
+    TYPE(t_field), POINTER :: f_ps(:), f_phis(:), f_theta_rhodz(:), &  ! IN
+         f_pks(:), f_p(:), f_theta(:), f_pk(:), f_phi(:)               ! OUT
+    REAL(rstd),POINTER :: pk(:,:), p(:,:), theta(:,:), theta_rhodz(:,:), &
+         phi(:,:), phis(:), ps(:), pks(:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       ps = f_ps(ind)
+       p  = f_p(ind)
+       CALL compute_pression(ps,p,0)
+       pk = f_pk(ind)
+       pks = f_pks(ind)
+       CALL compute_exner(ps,p,pks,pk,0)
+       theta_rhodz = f_theta_rhodz(ind)
+       theta = f_theta(ind)
+       CALL compute_theta_rhodz2theta(ps, theta_rhodz,theta,0)
+       phis = f_phis(ind)
+       phi = f_phi(ind)
+       CALL compute_geopotential(phis,pks,pk,theta,phi,0)
+    END DO
+
+  END SUBROUTINE thetarhodz2geopot
+  
+  SUBROUTINE Tv2T(f_Tv, f_q, f_T)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_TV(:)
+    TYPE(t_field), POINTER :: f_q(:)
+    TYPE(t_field), POINTER :: f_T(:)
+    
+    REAL(rstd),POINTER :: Tv(:,:), q(:,:,:), T(:,:)
+    INTEGER :: ind
+    
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       Tv=f_Tv(ind)
+       q=f_q(ind)
+       T=f_T(ind)
+       T=Tv/(1+0.608*q(:,:,1))
+    END DO
+    
+  END SUBROUTINE Tv2T
+  
+END MODULE caldyn_gcm_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/check_conserve.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/check_conserve.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/check_conserve.f90	(revision 329)
@@ -0,0 +1,352 @@
+MODULE check_conserve_mod
+  USE icosa 
+  IMPLICIT NONE 
+
+  PRIVATE 
+    TYPE(t_field),POINTER,SAVE :: f_pk(:), f_pks(:), f_p(:)
+    TYPE(t_field),POINTER,SAVE :: f_vort(:)
+    TYPE(t_field),POINTER,SAVE :: f_rhodz(:) 
+   
+  PUBLIC init_check_conserve, check_conserve 
+    REAL(rstd),SAVE:: mtot0,ztot0,etot0,ang0,stot0,rmsv0
+!$OMP THREADPRIVATE(mtot0,ztot0,etot0,ang0,stot0,rmsv0)
+    REAL(rstd),SAVE:: etot,ang,stot,rmsv
+!$OMP THREADPRIVATE(etot,ang,stot,rmsv)
+    REAL(rstd),SAVE:: ztot
+!$OMP THREADPRIVATE(ztot)	
+     
+CONTAINS 
+
+!---------------------------------------------------------------------
+
+  SUBROUTINE init_check_conserve
+  USE icosa
+  IMPLICIT NONE
+    CALL allocate_field(f_pk,field_t,type_real,llm)
+    CALL allocate_field(f_p,field_t,type_real,llm+1)
+    CALL allocate_field(f_pks,field_t,type_real)
+    CALL allocate_field(f_rhodz,field_t,type_real,llm)
+    CALL allocate_field(f_vort,field_z,type_real,llm)
+  END SUBROUTINE init_check_conserve
+
+  SUBROUTINE check_conserve(f_ps,f_dps,f_ue,f_theta_rhodz,f_phis,it) 
+  USE icosa 
+  USE pression_mod
+  USE vorticity_mod
+  USE caldyn_gcm_mod
+  USE exner_mod 
+  USE mpipara, ONLY : is_mpi_root, comm_icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_dps(:)
+    TYPE(t_field),POINTER :: f_ue(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    INTEGER::it
+
+    REAL(rstd),POINTER :: p(:,:),rhodz(:,:) 
+    INTEGER::ind,ierr
+    REAL(rstd) :: mtot, rmsdpdt
+
+    etot=0.0; ang=0.0;stot=0.0;rmsv=0.0 
+    ztot = 0.0 
+
+    CALL pression(f_ps,f_p)
+
+    DO ind=1,ndomain 
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      p=f_p(ind) 
+      rhodz=f_rhodz(ind)
+      CALL compute_rhodz(p,rhodz) 
+    END DO
+
+    CALL vorticity(f_ue,f_vort)
+    CALL check_mass_conserve(f_ps,f_dps,mtot,rmsdpdt)
+    CALL check_PV 
+    CALL exner(f_ps,f_p,f_pks,f_pk)
+    CALL check_EN(f_ue,f_theta_rhodz,f_phis) 
+
+    IF (is_mpi_root) THEN 
+!$OMP MASTER       
+       IF ( it == itau0  ) Then 
+          ztot0 = ztot
+          mtot0 = mtot
+          etot0 = etot 
+          ang0  = ang 
+          stot0 = stot 
+       END IF
+
+       rmsv=SQRT(rmsv/mtot) 
+       ztot=ztot/ztot0-1. ; mtot=mtot/mtot0-1. 
+       etot=etot/etot0-1. ; ang=ang/ang0-1. ; stot=stot/stot0-1. 
+       rmsdpdt= daysec*1.e-2*sqrt(rmsdpdt/ncell_glo)  
+       
+       OPEN(134,file="checkconsicosa.txt",position='append')
+       WRITE(134,4000)mtot,rmsdpdt,etot,ztot,stot,rmsv,ang
+       WRITE(134,*)mtot,rmsdpdt,etot,ztot,stot,rmsv,ang 
+       WRITE(134,*)"=================================================="
+!       WRITE(*,4000)mtot,rmsdpdt,etot,ztot,stot,rmsv,ang
+       
+4000   FORMAT(10x,'masse',5x,'rmsdpdt',5x,'energie',5x,'enstrophie'  &
+            ,5x,'entropie',5x,'rmsv',5x,'mt.ang',/,'GLOB  '                &
+            ,e10.3,e13.6,5e10.3/)     
+       close(134)
+!$OMP END MASTER 
+    END IF
+  END SUBROUTINE check_conserve
+  
+!---------------------------------------------------------------------
+
+  SUBROUTINE check_mass_conserve(f_ps,f_dps,mtot,rmsdpdt)
+  USE mpi_mod
+  USE mpipara
+  USE transfert_omp_mod
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_dps(:)
+    REAL(rstd),POINTER :: ps(:),dps(:) 
+    REAL(rstd), INTENT(OUT) :: mtot, rmsdpdt
+
+    INTEGER :: ind,i,j,ij  
+    REAL :: mloc, rmsloc
+    REAL :: mloc_mpi, rmsloc_mpi
+
+    mloc=0.0; rmsloc=0.0
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      dps=f_dps(ind) 
+      ps=f_ps(ind)
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          IF (domain(ind)%own(i,j)) THEN
+             mloc=mloc+ps(ij)*Ai(ij)
+             rmsloc=rmsloc+dps(ij)*dps(ij)
+	  ENDIF
+        ENDDO
+      ENDDO
+    ENDDO
+
+    IF (using_mpi) THEN
+        CALL reduce_sum_omp(mloc, mloc_mpi)
+        CALL reduce_sum_omp(rmsloc, rmsloc_mpi)
+!$OMP MASTER    
+      CALL MPI_REDUCE(mloc_mpi, mtot, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
+      CALL MPI_REDUCE(rmsloc_mpi, rmsdpdt, 1, MPI_REAL8, MPI_SUM, 0, comm_icosa, ierr)
+!$OMP END MASTER
+    ELSE
+      
+    ENDIF
+    
+  END SUBROUTINE check_mass_conserve
+
+!---------------------------------------------------------------------
+
+  SUBROUTINE check_en(f_ue,f_theta_rhodz,f_phis) 
+  USE icosa
+  USE pression_mod
+  USE vorticity_mod
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ue(:)
+    TYPE(t_field), POINTER :: f_theta_rhodz(:)
+    TYPE(t_field), POINTER :: f_phis(:)
+    REAL(rstd), POINTER :: ue(:,:)
+    REAL(rstd), POINTER :: p(:,:) 
+    REAL(rstd), POINTER :: theta_rhodz(:,:) 
+    REAL(rstd), POINTER :: pk(:,:) 
+    REAL(rstd), POINTER :: phis(:) 
+    REAL(rstd), POINTER :: rhodz(:,:) 
+    INTEGER :: ind
+
+
+    DO ind=1,ndomain 
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ue=f_ue(ind) 
+      p=f_p(ind)
+      rhodz=f_rhodz(ind) 
+      theta_rhodz=f_theta_rhodz(ind) 
+      pk=f_pk(ind) 
+      phis=f_phis(ind) 
+      CALL compute_en(ind,ue,p,rhodz,theta_rhodz,pk,phis)
+    END DO 
+ 
+  END SUBROUTINE check_en 
+
+  SUBROUTINE compute_en(ind,u,p,rhodz,theta_rhodz,pk,phis)
+  USE icosa
+  USE disvert_mod
+  USE wind_mod
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)::ind 
+    REAL(rstd),INTENT(IN) :: u(3*iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: p(iim*jjm,llm+1)
+    REAL(rstd),INTENT(IN) :: rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: pk(iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: phis(iim*jjm)
+    REAL(rstd):: theta(iim*jjm,llm)
+    REAL(rstd)::KE(iim*jjm,llm) 
+    REAL(rstd) :: ucenter(iim*jjm,3,llm)
+    REAL(rstd) :: ulon(iim*jjm,llm)
+    REAL(rstd) :: ulat(iim*jjm,llm)
+
+    REAL(rstd)::masse(iim*jjm,llm)  
+    REAL(rstd)::rad,radomeg,lat,lon
+    REAL(rstd) ::xyz(3)
+    INTEGER :: i,j,ij,l,ij2
+
+  
+    DO l = 1, llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+	  ij=(j-1)*iim+i
+	  masse(ij,l) = rhodz(ij,l)*Ai(ij) 
+          theta(ij,l) = theta_rhodz(ij,l)/rhodz(ij,l)
+          IF (domain(ind)%own(i,j)) THEN
+	    stot = stot + Ai(ij)*theta_rhodz(ij,l)
+          END IF 
+        END DO 
+      END DO
+    END DO 
+
+    DO l = 1, llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          IF (domain(ind)%own(i,j)) THEN
+	    KE(ij,l)=   1/(4*Ai(ij))*(le(ij+u_right)*de(ij+u_right)*u(ij+u_right,l)**2 +   &
+                                      le(ij+u_rup)*de(ij+u_rup)*u(ij+u_rup,l)**2 +           &
+                                      le(ij+u_lup)*de(ij+u_lup)*u(ij+u_lup,l)**2 +           &
+                                      le(ij+u_left)*de(ij+u_left)*u(ij+u_left,l)**2 +        &
+                                      le(ij+u_ldown)*de(ij+u_ldown)*u(ij+u_ldown,l)**2 +     &
+                                      le(ij+u_rdown)*de(ij+u_rdown)*u(ij+u_rdown,l)**2 )  
+            rmsv = rmsv + 2*masse(ij,l)*KE(ij,l) 
+          END IF 
+        END DO
+      END DO 
+    END DO  
+
+    DO l = 1, llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+	  ij=(j-1)*iim+i
+          IF (domain(ind)%own(i,j)) THEN
+	    etot = etot + masse(ij,l)*(phis(ij)+theta(ij,l)*pk(ij,l)+KE(ij,l))
+          END IF 
+        END DO 
+      END DO 
+    END DO 
+
+!------------------------------ ANGULAR VELOCITY 
+    CALL compute_wind_centered(u,ucenter)
+    CALL compute_wind_centered_lonlat_compound(ucenter,ulon,ulat)
+    rad = radius 
+    radomeg = rad*omega
+
+    DO l = 1, llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+	  ij=(j-1)*iim+i
+          IF (domain(ind)%own(i,j)) THEN
+!            CALL xyz2lonlat(xyz_i(ij,:),lon,lat) 
+! very bad inlining with intel compiler (>14 ?)
+             xyz(:)=xyz_i(ij,:)
+             xyz(:)=xyz(:)/sqrt(sum(xyz(:)**2))
+             lat=asin(xyz(3))
+             lon=atan2(xyz(2),xyz(1))
+  
+            ang=ang+rad*cos(lat)*masse(ij,l)*(ulon(ij,l)+ radomeg*cos(lat))
+          END IF 
+        END DO
+      END DO
+    END DO    
+          
+  END SUBROUTINE compute_en
+
+!---------------------------------------------------------------------
+
+  SUBROUTINE check_PV 
+  USE icosa
+  IMPLICIT NONE
+     REAL(rstd), POINTER :: vort(:,:)
+     REAL(rstd), POINTER :: rhodz(:,:) 
+     INTEGER :: ind
+
+     DO ind=1,ndomain 
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       vort=f_vort(ind)
+       rhodz=f_rhodz(ind) 
+       CALL compute_PV(vort,rhodz) 
+     ENDDO
+ 
+  END SUBROUTINE check_PV 
+
+  SUBROUTINE compute_PV(vort,rhodz) 
+  USE icosa
+  USE disvert_mod
+  IMPLICIT NONE 
+    REAL(rstd),INTENT(IN) :: vort(2*iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: rhodz(iim*jjm,llm) 
+    REAL(rstd)::qv1,qv2 
+    REAL(rstd)::hv1,hv2  
+    INTEGER :: i,j,ij,l,ij2
+
+    hv1 = 0.0 ; hv2 = 0.0 
+   
+    DO l = 1,llm
+      DO j=jj_begin+1,jj_end-1
+        DO i=ii_begin+1,ii_end-1
+          ij=(j-1)*iim+i
+          hv1 =  Riv2(ij,vup)        * rhodz(ij,l)           &
+            + Riv2(ij+t_rup,vldown) * rhodz(ij+t_rup,l)     &
+            + Riv2(ij+t_lup,vrdown) * rhodz(ij+t_lup,l)
+    
+          qv1 = ( vort(ij+z_up,l)+fv(ij+z_up) )/hv1
+          
+          hv2  =  Riv2(ij,vdown)     * rhodz(ij,l)          &
+            + Riv2(ij+t_ldown,vrup) * rhodz(ij+t_ldown,l)  &
+            + Riv2(ij+t_rdown,vlup) * rhodz(ij+t_rdown,l)
+                     
+          qv2 =( vort(ij+z_down,l)+fv(ij+z_down) )/hv2
+
+          ztot = ztot + (qv1*qv1*hv1 + qv2*qv2*hv2) 
+
+        ENDDO
+      ENDDO
+    ENDDO
+
+  END SUBROUTINE compute_PV
+!---------------------------------------------------------------------
+
+   SUBROUTINE compute_rhodz(p,rhodz) 
+   USE icosa 
+   IMPLICIT NONE 
+     REAL(rstd),INTENT(IN) :: p(iim*jjm,llm+1)
+     REAL(rstd),INTENT(OUT):: rhodz(iim*jjm,llm)
+     REAL(rstd) ::mass(iim*jjm,llm)
+     INTEGER :: i,j,ij,l 
+	
+     DO l = 1, llm
+      DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         mass(ij,l) = ( p(ij,l) - p(ij,l+1) ) * Ai(ij)/g
+         rhodz(ij,l) = mass(ij,l) / Ai(ij)
+       ENDDO
+      ENDDO
+     ENDDO
+
+   END SUBROUTINE compute_rhodz
+!====================================================================
+
+
+ END MODULE check_conserve_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dcmip_initial_conditions_test_1_2_3_v5.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dcmip_initial_conditions_test_1_2_3_v5.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dcmip_initial_conditions_test_1_2_3_v5.f90	(revision 329)
@@ -0,0 +1,1347 @@
+MODULE dcmip_initial_conditions_test_1_2_3
+
+  !=======================================================================
+  !
+  !  Functions for setting up initial conditions for the dynamical core tests:
+  !
+  !  11 - Deformational Advection Test
+  !  12 - Hadley Cell Advection Test
+  !  13 - Orography Advection Test
+  !  20 - Impact of orography on a steady-state at rest
+  !  21 and 22 - Non-Hydrostatic Mountain Waves Over A Schaer-Type Mountain without and with vertical wind shear
+  !  31 - Non-Hydrostatic Gravity Waves
+  !
+  !  Given a point specified by: 
+  !  	lon	longitude (radians) 
+  ! 	lat	latitude (radians) 
+  ! 	p/z	pressure/height
+  !  the functions will return:
+  !	u	zonal wind (m s^-1)
+  !	v	meridional wind (m s^-1)
+  !	w	vertical velocity (m s^-1)
+  !	t	temperature (K)
+  !	phis	surface geopotential (m^2 s^-2)
+  !	ps	surface pressure (Pa)
+  !	rho	density (kj m^-3)
+  !	q	specific humidity (kg/kg)
+  !	qi	tracers (kg/kg)
+  !     p       pressure if height based (Pa)
+  !
+  !
+  !  Authors: James Kent, Paul Ullrich, Christiane Jablonowski 
+  !		(University of Michigan, dcmip@ucar.edu)
+  !          version 4
+  !          July/8/2012
+  !
+  ! Change log: (v3, June/8/2012, v4 July/8/2012, v5 July/20/2012)
+  !
+  ! v2: bug fixes in the tracer initialization for height-based models
+  ! v3: test 3-1: the density is now initialized with the unperturbed background temperature (not the perturbed temperature)
+  ! v3: constants converted to double precision
+  ! v4: modified tracers in test 1-1, now with cutoff altitudes. Outside of the vertical domain all tracers are set to 0
+  ! v4: modified cos-term in vertical velocity (now cos(2 pi t/tau)) in test 1-1, now completing one full up and down cycle
+  ! v4: added subroutine test1_advection_orography for test 1-3
+  ! v4: added subroutine test2_steady_state_mountain for test 2-0
+  ! v4: modified parameter list for tests 2-1 and 2-2 (routine test2_schaer_mountain): addition of parameters hybrid_eta, hyam, hybm
+  !     if the logical flag hybrid_eta is true then the pressure in pressure-based model with hybrid sigma-p (eta) coordinates is 
+  !     computed internally. In that case the hybrid coefficients hyam and hybm need to be supplied via the parameter list, 
+  !     otherwise they are not used.
+  ! v5: Change in test 11 - change to u and w, cutoff altitudes (introduced in v4) are removed again
+  ! v5: Change in test 12 - velocities multiplies by rho0/rho, different w0 and vertical location of the initial tracer
+  !
+  !
+  !=======================================================================
+
+  USE prec
+
+  IMPLICIT NONE
+
+  PRIVATE
+  PUBLIC :: test3_gravity_wave, & ! (lon,lat,p,z,zcoords,u,v,w,t,phis,ps,rho,q)
+       test2_steady_state_mountain, &
+       test2_schaer_mountain
+!-----------------------------------------------------------------------
+!     Physical Parameters
+!-----------------------------------------------------------------------
+
+  REAL(rstd), parameter ::	&
+       a	= 6371220.0d0,	&	! Earth's Radius (m)
+       Rd 	= 287.0d0,	&	! Ideal gas const dry air (J kg^-1 K^1)
+       g	= 9.80616d0,	&	! Gravity (m s^2)
+       cp	= 1004.5d0,	&	! Specific heat capacity (J kg^-1 K^1)
+       pi	= 4.d0*atan(1.d0)       ! pi
+
+!-----------------------------------------------------------------------
+!     Additional constants
+!-----------------------------------------------------------------------
+
+  real(rstd), parameter ::	p0	= 100000.d0		! reference pressure (Pa)
+
+
+CONTAINS
+
+!==========================================================================================
+! TEST CASE 11 - PURE ADVECTION - 3D DEFORMATIONAL FLOW
+!==========================================================================================
+
+! The 3D deformational flow test is based on the deformational flow test of Nair and Lauritzen (JCP 2010), 
+! with a prescribed vertical wind velocity which makes the test truly 3D. An unscaled planet (with scale parameter
+! X = 1) is selected. 
+
+SUBROUTINE test1_advection_deformation (lon,lat,p,z,zcoords,u,v,w,t,phis,ps,rho,q,q1,q2,q3,q4)
+
+IMPLICIT NONE
+!-----------------------------------------------------------------------
+!     input/output params parameters at given location
+!-----------------------------------------------------------------------
+
+	real(rstd), intent(in)  :: lon, &		! Longitude (radians)
+				lat, &		! Latitude (radians)
+				z		! Height (m)
+
+	real(rstd), intent(inout) :: p		! Pressure  (Pa)				
+
+	integer,  intent(in) :: zcoords 	! 0 or 1 see below
+
+	real(rstd), intent(out) :: u, & 		! Zonal wind (m s^-1)
+				v, &		! Meridional wind (m s^-1)
+				w, &		! Vertical Velocity (m s^-1)
+				t, & 		! Temperature (K)
+				phis, & 	! Surface Geopotential (m^2 s^-2)
+				ps, & 		! Surface Pressure (Pa)
+				rho, & 		! density (kg m^-3)
+				q, & 		! Specific Humidity (kg/kg)
+				q1, & 		! Tracer q1 (kg/kg)
+				q2, & 		! Tracer q2 (kg/kg)
+				q3, & 		! Tracer q3 (kg/kg)
+				q4		! Tracer q4 (kg/kg)
+
+	! if zcoords = 1, then we use z and output p
+	! if zcoords = 0, then we use p 
+
+!-----------------------------------------------------------------------
+!     test case parameters
+!----------------------------------------------------------------------- 
+	real(rstd), parameter :: 	tau     = 12.d0 * 86400.d0,	&	! period of motion 12 days
+			    	u0      = (2.d0*pi*a)/tau,	&	! 2 pi a / 12 days
+			    	k0	= (10.d0*a)/tau,	&	! Velocity Magnitude
+			    	omega0	= (23000.d0*pi)/tau,	&	! Velocity Magnitude
+                            	T0      = 300.d0,		&	! temperature
+                            	H       = Rd * T0 / g,		&	! scale height
+                            	RR      = 1.d0/2.d0,		&	! horizontal half width divided by 'a'
+                            	ZZ      = 1000.d0,		&	! vertical half width
+                            	z0      = 5000.d0,		&	! center point in z
+                            	lambda0 = 5.d0*pi/6.d0,		&	! center point in longitudes
+                            	lambda1 = 7.d0*pi/6.d0,		&	! center point in longitudes
+                            	phi0    = 0.d0,			&	! center point in latitudes
+                            	phi1    = 0.d0                      
+                            
+      real(rstd) :: height							! The height of the model levels
+      real(rstd) :: ptop							! Model top in p
+      real(rstd) :: sin_tmp, cos_tmp, sin_tmp2, cos_tmp2			! Calculate great circle distances
+      real(rstd) :: d1, d2, r, r2, d3, d4					! For tracer calculations 
+      real(rstd) :: s, bs							! Shape function, and parameter
+      real(rstd) :: lonp							! Translational longitude, depends on time
+      real(rstd) :: ud							! Divergent part of u
+      real(rstd) :: time							! Initially set to zero seconds, needs
+									! to be modified when used in dycore
+
+!-----------------------------------------------------------------------
+!    HEIGHT AND PRESSURE
+!-----------------------------------------------------------------------
+	
+	! Height and pressure are aligned (p = p0 exp(-z/H))
+
+	if (zcoords .eq. 1) then
+
+		height = z
+		p = p0 * exp(-z/H)
+
+	else
+
+		height = H * log(p0/p)
+
+	endif
+
+	! Model top in p
+
+	ptop    = p0*exp(-12000.d0/H)	
+
+!-----------------------------------------------------------------------
+!    THE VELOCITIES ARE TIME DEPENDENT AND THEREFORE MUST BE UPDATED
+!    IN THE DYNAMICAL CORE
+!-----------------------------------------------------------------------
+
+	! These are initial conditions hence time = 0
+
+	time = 0.d0
+
+	! Translational longitude = longitude when time = 0
+
+	lonp = lon - 2.d0*pi*time/tau
+
+	! Shape function
+!********
+! change in version 5: shape function 
+!********
+	bs = 0.2
+	s = 1.0 + exp( (ptop-p0)/(bs*ptop) ) - exp( (p-p0)/(bs*ptop)) - exp( (ptop-p)/(bs*ptop))
+
+	! Zonal Velocity
+!********
+! change in version 5: ud 
+!********
+
+	ud = (omega0*a)/(bs*ptop) * cos(lonp) * (cos(lat)**2.0) * cos(2.0*pi*time/tau) * &
+		( - exp( (p-p0)/(bs*ptop)) + exp( (ptop-p)/(bs*ptop))  )
+
+	u = k0*sin(lonp)*sin(lonp)*sin(2.d0*lat)*cos(pi*time/tau) + u0*cos(lat) + ud
+
+	! Meridional Velocity
+
+	v = k0*sin(2.d0*lonp)*cos(lat)*cos(pi*time/tau)
+
+	! Vertical Velocity - can be changed to vertical pressure velocity by 
+	! omega = -(g*p)/(Rd*T0)*w
+        !
+!********
+! change in version 4: cos(2.0*pi*time/tau) is now used instead of cos(pi*time/tau)
+!********
+!********
+! change in version 5: shape function in w
+!********
+	w = -((Rd*T0)/(g*p))*omega0*sin(lonp)*cos(lat)*cos(2.0*pi*time/tau)*s
+
+!-----------------------------------------------------------------------
+!    TEMPERATURE IS CONSTANT 300 K
+!-----------------------------------------------------------------------
+
+	t = T0
+
+!-----------------------------------------------------------------------
+!    PHIS (surface geopotential) 
+!-----------------------------------------------------------------------
+      
+	phis = 0.d0
+
+!-----------------------------------------------------------------------
+!    PS (surface pressure)
+!-----------------------------------------------------------------------
+
+	ps = p0
+
+!-----------------------------------------------------------------------
+!    RHO (density)
+!-----------------------------------------------------------------------
+
+	rho = p/(Rd*t)
+
+!-----------------------------------------------------------------------
+!     initialize Q, set to zero 
+!-----------------------------------------------------------------------
+
+	q = 0.d0
+
+!-----------------------------------------------------------------------
+!     initialize tracers
+!-----------------------------------------------------------------------
+
+	! Tracer 1 - Cosine Bells
+
+		! To calculate great circle distance
+
+	sin_tmp = sin(lat) * sin(phi0)
+	cos_tmp = cos(lat) * cos(phi0)
+	sin_tmp2 = sin(lat) * sin(phi1)
+	cos_tmp2 = cos(lat) * cos(phi1)
+
+		! great circle distance without 'a'
+	
+	r  = ACOS (sin_tmp + cos_tmp*cos(lon-lambda0)) 
+	r2  = ACOS (sin_tmp2 + cos_tmp2*cos(lon-lambda1)) 
+	d1 = min( 1., (r/RR)**2 + ((height-z0)/ZZ)**2 )
+	d2 = min( 1., (r2/RR)**2 + ((height-z0)/ZZ)**2 )
+	
+	q1 = 0.5d0 * (1.d0 + cos(pi*d1)) + 0.5d0 * (1.d0 + cos(pi*d2))
+
+	! Tracer 2 - Correlated Cosine Bells
+
+	q2 = 0.9d0 - 0.8d0*q1**2
+
+	! Tracer 3 - Slotted Ellipse
+
+		! Make the ellipse
+
+	if (d1 .le. RR) then
+		q3 = 1.d0
+	elseif (d2 .le. RR) then
+		q3 = 1.d0
+	else
+		q3 = 0.1d0
+	endif
+
+		! Put in the slot
+	
+	if (height .gt. z0 .and. abs(lat) .lt. 0.125d0) then 
+
+		q3 = 0.1d0      
+
+	endif
+
+	! Tracer 4: q4 is chosen so that, in combination with the other three tracer
+        !           fields with weight (3/10), the sum is equal to one
+
+	q4 = 1.d0 - 0.3d0*(q1+q2+q3)
+
+!************	
+! change in version 4: added cutoff altitudes, tracers are set to zero outside this region
+! prevents tracers from being trapped near the bottom and top of the domain
+!************
+        ! use a cutoff altitude for
+	! tracer 2 3 and 4
+	! Set them to zero outside `buffer zone'
+!************	
+! change in version 5: change from v4 reversed, no cutoff altitudes due to continuity equation being satisfied
+!       commented out below
+!************
+
+	!if (height .gt. (z0+1.25*ZZ) .or. height .lt. (z0-1.25*ZZ)) then 
+
+	!	q2 = 0.0
+	!	q3 = 0.0
+	!	q4 = 0.0
+
+	!endif
+
+
+
+
+END SUBROUTINE test1_advection_deformation
+
+
+
+
+
+!==========================================================================================
+! TEST CASE 12 - PURE ADVECTION - 3D HADLEY-LIKE FLOW
+!==========================================================================================
+
+SUBROUTINE test1_advection_hadley (lon,lat,p,z,zcoords,u,v,w,t,phis,ps,rho,q,q1)
+
+IMPLICIT NONE
+!-----------------------------------------------------------------------
+!     input/output params parameters at given location
+!-----------------------------------------------------------------------
+
+	real(rstd), intent(in)  :: lon, &		! Longitude (radians)
+				lat, &		! Latitude (radians)
+				z		! Height (m)
+
+	real(rstd), intent(inout) :: p		! Pressure  (Pa)
+				
+	integer,  intent(in) :: zcoords 	! 0 or 1 see below
+
+	real(rstd), intent(out) :: u, & 		! Zonal wind (m s^-1)
+				v, &		! Meridional wind (m s^-1)
+				w, &		! Vertical Velocity (m s^-1)
+				t, & 		! Temperature (K)
+				phis, & 	! Surface Geopotential (m^2 s^-2)
+				ps, & 		! Surface Pressure (Pa)
+				rho, & 		! density (kg m^-3)
+				q, & 		! Specific Humidity (kg/kg)
+				q1 		! Tracer q1 (kg/kg)
+
+	! if zcoords = 1, then we use z and output p
+	! if zcoords = 0, then we use p
+
+!-----------------------------------------------------------------------
+!     test case parameters
+!----------------------------------------------------------------------- 
+	real(rstd), parameter :: 	tau     = 1.d0 * 86400.d0,	&	! period of motion 1 day (in s)
+			    	u0      = 40.d0,		&	! Zonal velocity magnitude (m/s)
+			    	w0	= 0.15d0,		&	! Vertical velocity magnitude (m/s), changed in v5
+                            	T0      = 300.d0,		&	! temperature (K)
+                            	H       = Rd * T0 / g,		&	! scale height
+                            	K       = 5.d0,			&	! number of Hadley-like cells
+                            	z1      = 2000.d0,		&	! position of lower tracer bound (m), changed in v5       
+                            	z2      = 5000.d0,		&	! position of upper tracer bound (m), changed in v5       
+                            	z0      = 0.5d0*(z1+z2),	&	! midpoint (m)       
+                            	ztop    = 12000.d0			! model top (m)       
+                            
+      real(rstd) :: rho0							! reference density at z=0 m
+      real(rstd) :: height							! Model level heights
+      real(rstd) :: time							! Initially set to zero seconds, needs
+									! to be modified when used in dycore
+
+!-----------------------------------------------------------------------
+!    HEIGHT AND PRESSURE
+!-----------------------------------------------------------------------
+
+	! Height and pressure are aligned (p = p0 exp(-z/H))
+
+	if (zcoords .eq. 1) then
+
+		height = z
+		p = p0 * exp(-z/H)
+
+	else
+
+		height = H * log(p0/p)
+
+	endif
+
+!-----------------------------------------------------------------------
+!    TEMPERATURE IS CONSTANT 300 K
+!-----------------------------------------------------------------------
+
+	t = T0
+
+!-----------------------------------------------------------------------
+!    PHIS (surface geopotential)
+!-----------------------------------------------------------------------
+      
+	phis = 0.d0
+
+!-----------------------------------------------------------------------
+!    PS (surface pressure)
+!-----------------------------------------------------------------------
+
+	ps = p0
+
+!-----------------------------------------------------------------------
+!    RHO (density)
+!-----------------------------------------------------------------------
+
+	rho = p/(Rd*t)
+	rho0 = p0/(Rd*t)
+
+!-----------------------------------------------------------------------
+!    THE VELOCITIES ARE TIME DEPENDENT AND THEREFORE MUST BE UPDATED
+!    IN THE DYNAMICAL CORE
+!-----------------------------------------------------------------------
+
+	time = 0.d0
+
+	! Zonal Velocity
+
+	u = u0*cos(lat)
+
+	! Meridional Velocity
+
+!************	
+! change in version 5: multiply v and w by rho0/rho 
+!************
+
+	v = -(rho0/rho) * (a*w0*pi)/(K*ztop) *cos(lat)*sin(K*lat)*cos(pi*height/ztop)*cos(pi*time/tau)
+
+	! Vertical Velocity - can be changed to vertical pressure velocity by 
+	! omega = -g*rho*w
+
+	w = (rho0/rho) *(w0/K)*(-2.d0*sin(K*lat)*sin(lat) + K*cos(lat)*cos(K*lat)) &
+		*sin(pi*height/ztop)*cos(pi*time/tau)
+
+
+!-----------------------------------------------------------------------
+!     initialize Q, set to zero 
+!-----------------------------------------------------------------------
+
+	q = 0.d0
+
+!-----------------------------------------------------------------------
+!     initialize tracers
+!-----------------------------------------------------------------------
+
+	! Tracer 1 - Layer
+
+	if (height .lt. z2 .and. height .gt. z1) then
+	
+		q1 = 0.5d0 * (1.d0 + cos( 2.d0*pi*(height-z0)/(z2-z1) ) )
+
+	else
+
+		q1 = 0.d0
+
+	endif
+
+END SUBROUTINE test1_advection_hadley
+
+
+
+!==========================================================================================
+! TEST CASE 13 - HORIZONTAL ADVECTION OF THIN CLOUD-LIKE TRACERS IN THE PRESENCE OF OROGRAPHY
+!==========================================================================================
+
+SUBROUTINE test1_advection_orography (lon,lat,p,z,zcoords,cfv,hybrid_eta,hyam,hybm,gc,u,v,w,t,phis,ps,rho,q,q1,q2,q3,q4)
+
+IMPLICIT NONE
+!-----------------------------------------------------------------------
+!     input/output params parameters at given location
+!-----------------------------------------------------------------------
+
+	real(rstd), intent(in)  :: lon, &		! Longitude (radians)
+				lat, &		! Latitude (radians)
+				z, &		! Height (m)
+				hyam, &		! A coefficient for hybrid-eta coordinate, at model level midpoint
+				hybm, &		! B coefficient for hybrid-eta coordinate, at model level midpoint
+				gc		! bar{z} for Gal-Chen coordinate 
+
+	logical, intent(in)  :: hybrid_eta      ! flag to indicate whether the hybrid sigma-p (eta) coordinate is used
+                                                ! if set to .true., then the pressure will be computed via the 
+                                                !    hybrid coefficients hyam and hybm, they need to be initialized
+                                                ! if set to .false. (for pressure-based models): the pressure is already pre-computed
+                                                !    and is an input value for this routine 
+                                                ! for height-based models: pressure will always be computed based on the height and
+                                                !    hybrid_eta is not used
+
+	! Note that we only use hyam and hybm for the hybrid-eta coordiantes, and we only use
+	! gc for the Gal-Chen coordinates. If not required then they become dummy variables
+
+	real(rstd), intent(inout) :: p		! Pressure  (Pa)
+				
+	integer,  intent(in) :: zcoords 	! 0 or 1 see below
+	integer,  intent(in) :: cfv 		! 0, 1 or 2 see below
+
+	real(rstd), intent(out) :: u, & 		! Zonal wind (m s^-1)
+				v, &		! Meridional wind (m s^-1)
+				w, &		! Vertical Velocity (m s^-1)
+				t, & 		! Temperature (K)
+				phis, & 	! Surface Geopotential (m^2 s^-2)
+				ps, & 		! Surface Pressure (Pa)
+				rho, & 		! density (kg m^-3)
+				q, & 		! Specific Humidity (kg/kg)
+				q1, & 		! Tracer q1 (kg/kg)
+				q2, & 		! Tracer q2 (kg/kg)
+				q3, & 		! Tracer q3 (kg/kg)
+				q4 		! Tracer q4 (kg/kg)
+
+	! if zcoords = 1, then we use z and output p
+	! if zcoords = 0, then we use p
+
+	! if cfv = 0 we assume that our horizontal velocities are not coordinate following
+	! if cfv = 1 then our velocities follow hybrid eta coordinates and we need to specify w
+	! if cfv = 2 then our velocities follow Gal-Chen coordinates and we need to specify w
+
+	! In hybrid-eta coords: p = hyam p0 + hybm ps
+	! In Gal-Chen coords: z = zs + (gc/ztop)*(ztop - zs)
+
+        ! if other orography-following coordinates are used, the w wind needs to be newly derived for them
+
+!-----------------------------------------------------------------------
+!     test case parameters
+!----------------------------------------------------------------------- 
+	real(rstd), parameter :: 	tau     = 12.d0 * 86400.d0,	&	! period of motion 12 days (s)
+			    	u0      = 2.d0*pi*a/tau,	&	! Velocity Magnitude (m/s)
+                            	T0      = 300.d0,		&	! temperature (K)
+                            	H       = Rd * T0 / g,		&	! scale height (m)
+                            	alpha   = pi/6.d0,		&	! rotation angle (radians), 30 degrees   
+                            	lambdam = 3.d0*pi/2.d0,		&	! mountain longitude center point (radians)   
+                            	phim    = 0.d0,			&	! mountain latitude center point (radians)    
+                            	h0      = 2000.d0,		&	! peak height of the mountain range (m)
+                            	Rm      = 3.d0*pi/4.d0,		&	! mountain radius (radians)
+                            	zetam   = pi/16.d0,		&	! mountain oscillation half-width (radians) 
+                            	lambdap = pi/2.d0,		&	! cloud-like tracer longitude center point (radians) 
+                            	phip    = 0.d0,   		&	! cloud-like tracer latitude center point (radians)    
+                            	Rp      = pi/4.d0,		&	! cloud-like tracer radius (radians)    
+                            	zp1     = 3050.d0,		&	! midpoint of first (lowermost) tracer (m)           
+                            	zp2     = 5050.d0,		&	! midpoint of second tracer (m)          
+                            	zp3     = 8200.d0,		&	! midpoint of third (topmost) tracer (m)    
+                            	dzp1    = 1000.d0,		&	! thickness of first (lowermost) tracer (m)           
+                            	dzp2    = 1000.d0,		&	! thickness of second tracer (m)
+                            	dzp3    = 400.d0,		&	! thickness of third (topmost) tracer (m)       
+                            	ztop    = 12000.d0			! model top (m)         
+                            
+      real(rstd) :: height							! Model level heights (m)
+      real(rstd) :: r							! Great circle distance (radians)
+      real(rstd) :: rz							! height differences 
+      real(rstd) :: zs							! Surface elevation (m)
+
+
+
+!-----------------------------------------------------------------------
+!    PHIS (surface geopotential)
+!-----------------------------------------------------------------------
+      
+	r = acos( sin(phim)*sin(lat) + cos(phim)*cos(lat)*cos(lon - lambdam) )
+
+	if (r .lt. Rm) then
+
+		zs = (h0/2.d0)*(1.d0+cos(pi*r/Rm))*cos(pi*r/zetam)**2.d0
+
+	else
+
+		zs = 0.d0
+
+	endif
+
+	phis = g*zs
+
+!-----------------------------------------------------------------------
+!    PS (surface pressure)
+!-----------------------------------------------------------------------
+
+	ps = p0 * exp(-zs/H)
+
+
+!-----------------------------------------------------------------------
+!    HEIGHT AND PRESSURE
+!-----------------------------------------------------------------------
+
+	! Height and pressure are aligned (p = p0 exp(-z/H))
+
+	if (zcoords .eq. 1) then
+
+		height = z
+		p = p0 * exp(-z/H)
+
+	else
+
+                if (hybrid_eta) p = hyam*p0 + hybm*ps   ! compute the pressure based on the surface pressure and hybrid coefficients
+		height = H * log(p0/p)
+
+	endif
+
+!-----------------------------------------------------------------------
+!    THE VELOCITIES ARE TIME INDEPENDENT 
+!-----------------------------------------------------------------------
+
+	! Zonal Velocity
+
+	u = u0*(cos(lat)*cos(alpha)+sin(lat)*cos(lon)*sin(alpha))
+
+	! Meridional Velocity
+
+	v = -u0*(sin(lon)*sin(alpha))
+
+!-----------------------------------------------------------------------
+!    TEMPERATURE IS CONSTANT 300 K
+!-----------------------------------------------------------------------
+
+	t = T0
+
+!-----------------------------------------------------------------------
+!    RHO (density)
+!-----------------------------------------------------------------------
+
+	rho = p/(Rd*t)
+
+!-----------------------------------------------------------------------
+!     initialize Q, set to zero 
+!-----------------------------------------------------------------------
+
+	q = 0.d0
+
+!-----------------------------------------------------------------------
+!    VERTICAL VELOCITY IS TIME INDEPENDENT 
+!-----------------------------------------------------------------------
+
+	! Vertical Velocity - can be changed to vertical pressure velocity by 
+	! omega = -(g*p)/(Rd*T0)*w
+
+	! NOTE that if orography-following coordinates are used then the vertical 
+	! velocity needs to be translated into the new coordinate system due to
+	! the variation of the height along coordinate surfaces
+	! See section 1.3 and the appendix of the test case document
+
+	if (cfv .eq. 0) then
+
+		! if the horizontal velocities do not follow the vertical coordinate
+
+		w = 0.d0
+
+	elseif (cfv .eq. 1) then
+
+		! if the horizontal velocities follow hybrid eta coordinates then
+		! the perceived vertical velocity is
+
+		call test1_advection_orograph_hybrid_eta_velocity(w)
+
+	elseif (cfv .eq. 2) then
+
+		! if the horizontal velocities follow Gal Chen coordinates then
+		! the perceived vertical velocity is	
+
+		call test1_advection_orograph_Gal_Chen_velocity(w)	
+
+!        else
+!               compute your own vertical velocity if other orography-following 
+!               vertical coordinate is used
+!
+	endif
+
+
+
+!-----------------------------------------------------------------------
+!     initialize tracers
+!-----------------------------------------------------------------------
+
+	! Tracer 1 - Cloud Layer
+      
+	r = acos( sin(phip)*sin(lat) + cos(phip)*cos(lat)*cos(lon - lambdap) )
+
+	rz = abs(height - zp1)
+
+	if (rz .lt. 0.5d0*dzp1 .and. r .lt. Rp) then
+
+		q1 = 0.25d0*(1.d0+cos(2.d0*pi*rz/dzp1))*(1.d0+cos(pi*r/Rp))
+
+	else
+
+		q1 = 0.d0
+
+	endif
+
+	rz = abs(height - zp2)
+
+	if (rz .lt. 0.5d0*dzp2 .and. r .lt. Rp) then
+
+		q2 = 0.25d0*(1.d0+cos(2.d0*pi*rz/dzp2))*(1.d0+cos(pi*r/Rp))
+
+	else
+
+		q2 = 0.d0
+
+	endif
+
+	rz = abs(height - zp3)
+
+	if (rz .lt. 0.5d0*dzp3 .and. r .lt. Rp) then
+
+		q3 = 1.d0
+
+	else
+
+		q3 = 0.d0
+
+	endif
+
+	q4 = q1 + q2 + q3
+
+
+	CONTAINS
+
+	!-----------------------------------------------------------------------
+	!    SUBROUTINE TO CALCULATE THE PERCEIVED VERTICAL VELOCITY 
+	!    		UNDER HYBRID-ETA COORDINATES
+	!-----------------------------------------------------------------------
+
+	SUBROUTINE test1_advection_orograph_hybrid_eta_velocity(w)
+	IMPLICIT NONE
+	real(rstd), intent(out) ::	w
+
+	real(rstd) :: 	press, &		! hyam *p0 + hybm *ps
+			r, &			! Great Circle Distance
+			dzsdx, &		! Part of surface height derivative
+			dzsdlambda, & 		! Derivative of zs w.r.t lambda
+			dzsdphi, & 		! Derivative of zs w.r.t phi
+			dzdlambda, & 		! Derivative of z w.r.t lambda
+			dzdphi, & 		! Derivative of z w.r.t phi
+			dpsdlambda, & 		! Derivative of ps w.r.t lambda
+			dpsdphi 		! Derivative of ps w.r.t phi
+
+		! Calculate pressure and great circle distance to mountain center
+
+		press = hyam*p0 + hybm*ps
+
+		r = acos( sin(phim)*sin(lat) + cos(phim)*cos(lat)*cos(lon - lambdam) )
+
+		! Derivatives of surface height
+
+		if (r .lt. Rm) then
+			dzsdx = -h0*pi/(2.d0*Rm)*sin(pi*r/Rm)*cos(pi*r/zetam)**2 - &
+				(h0*pi/zetam)*(1.d0+cos(pi*r/Rm))*cos(pi*r/zetam)*sin(pi*r/zetam)
+		else
+			dzsdx = 0.d0
+		endif
+
+		! Prevent division by zero
+
+		if (1.d0-cos(r)**2 .gt. 0.d0) then
+			dzsdlambda = dzsdx * (cos(phim)*cos(lat)*sin(lon-lambdam)) &
+					/sqrt(1.d0-cos(r)**2)
+			dzsdphi    = dzsdx * (-sin(phim)*cos(lat) + cos(phim)*sin(lat)*cos(lon-lambdam)) & 
+					/sqrt(1.d0-cos(r)**2)
+		else
+			dzsdlambda = 0.d0
+			dzsdphi    = 0.d0
+		endif
+
+		! Derivatives of surface pressure
+
+		dpsdlambda = -(g*p0/(Rd*T0))*exp(-g*zs/(Rd*T0))*dzsdlambda
+		dpsdphi    = -(g*p0/(Rd*T0))*exp(-g*zs/(Rd*T0))*dzsdphi
+
+		! Derivatives of coordinate height
+
+		dzdlambda = -(Rd*T0/(g*press))*hybm*dpsdlambda
+		dzdphi    = -(Rd*T0/(g*press))*hybm*dpsdphi
+
+		! Prevent division by zero
+
+		if (abs(lat) .lt. pi/2.d0) then
+			w = - (u/(a*cos(lat)))*dzdlambda - (v/a)*dzdphi
+		else
+			w = 0.d0
+		endif
+
+	END SUBROUTINE test1_advection_orograph_hybrid_eta_velocity
+
+
+
+	!-----------------------------------------------------------------------
+	!    SUBROUTINE TO CALCULATE THE PERCEIVED VERTICAL VELOCITY 
+	!    		UNDER GAL-CHEN COORDINATES
+	!-----------------------------------------------------------------------
+
+	SUBROUTINE test1_advection_orograph_Gal_Chen_velocity(w)
+	IMPLICIT NONE
+	real(rstd), intent(out) ::	w
+
+	real(rstd) :: 	r, &			! Great Circle Distance
+			dzsdx, &		! Part of surface height derivative
+			dzsdlambda, & 		! Derivative of zs w.r.t lambda
+			dzsdphi, & 		! Derivative of zs w.r.t phi
+			dzdlambda, & 		! Derivative of z w.r.t lambda
+			dzdphi	 		! Derivative of z w.r.t phi
+
+		! Calculate great circle distance to mountain center
+
+		r = acos( sin(phim)*sin(lat) + cos(phim)*cos(lat)*cos(lon - lambdam) )
+
+		! Derivatives of surface height
+
+		if (r .lt. Rm) then
+			dzsdx = -h0*pi/(2.d0*Rm)*sin(pi*r/Rm)*cos(pi*r/zetam)**2 - &
+				(h0*pi/zetam)*(1.d0+cos(pi*r/Rm))*cos(pi*r/zetam)*sin(pi*r/zetam)
+		else
+			dzsdx = 0.d0
+		endif
+
+		! Prevent division by zero
+
+		if (1.d0-cos(r)**2 .gt. 0.d0) then
+			dzsdlambda = dzsdx * (cos(phim)*cos(lat)*sin(lon-lambdam)) &
+					/sqrt(1.d0-cos(r)**2)
+			dzsdphi    = dzsdx * (-sin(phim)*cos(lat) + cos(phim)*sin(lat)*cos(lon-lambdam)) & 
+					/sqrt(1.d0-cos(r)**2)
+		else
+			dzsdlambda = 0.d0
+			dzsdphi    = 0.d0
+		endif
+
+		! Derivatives of coordinate height
+
+		dzdlambda = (1.d0-gc/ztop)*dzsdlambda
+		dzdphi    = (1.d0-gc/ztop)*dzsdphi
+
+		! Prevent division by zero
+
+		if (abs(lat) .lt. pi/2.d0) then
+			w = - (u/(a*cos(lat)))*dzdlambda - (v/a)*dzdphi
+		else
+			w = 0.d0
+		endif
+
+	END SUBROUTINE test1_advection_orograph_Gal_Chen_velocity
+
+END SUBROUTINE test1_advection_orography
+
+
+
+
+!==========================================================================================
+! TEST CASE 2X - IMPACT OF OROGRAPHY ON A NON-ROTATING PLANET
+!==========================================================================================
+! The tests in section 2-x examine the impact of 3D Schaer-like circular mountain profiles on an 
+! atmosphere at rest (2-0), and on flow fields with wind shear (2-1) and without vertical wind shear (2-2).  
+! A non-rotating planet is used for all configurations. Test 2-0 is conducted on an unscaled regular-size 
+! planet and primarily examines the accuracy of the pressure gradient calculation in a steady-state 
+! hydrostatically-balanced atmosphere at rest. This test is especially appealing for models with 
+! orography-following vertical coordinates. It increases the complexity of test 1-3, that investigated 
+! the impact of the same Schaer-type orographic profile on the accuracy of purely-horizontal passive 
+! tracer advection.
+!
+! Tests 2-1 and 2-2 increase the complexity even further since non-zero flow fields are now prescribed 
+! with and without vertical wind shear. In order to trigger non-hydrostatic responses the two tests are 
+! conducted on a reduced-size planet with reduction factor $X=500$ which makes the horizontal and 
+! vertical grid spacing comparable. This test clearly discriminates between non-hydrostatic and hydrostatic 
+! models since the expected response is in the non-hydrostatic regime. Therefore, the flow response is 
+! captured differently by hydrostatic models.
+
+
+
+
+!=========================================================================
+! Test 2-0:  Steady-State Atmosphere at Rest in the Presence of Orography
+!=========================================================================
+SUBROUTINE test2_steady_state_mountain (lon,lat,p,z,zcoords,hybrid_eta,hyam,hybm,u,v,w,t,phis,ps,rho,q)
+
+IMPLICIT NONE
+!-----------------------------------------------------------------------
+!     input/output params parameters at given location
+!-----------------------------------------------------------------------
+
+	real(rstd), intent(in)  :: lon, &		! Longitude (radians)
+				lat, &		! Latitude (radians)
+				z, &		! Height (m)
+				hyam, &		! A coefficient for hybrid-eta coordinate, at model level midpoint
+				hybm		! B coefficient for hybrid-eta coordinate, at model level midpoint
+
+	logical, intent(in)  :: hybrid_eta      ! flag to indicate whether the hybrid sigma-p (eta) coordinate is used
+                                                ! if set to .true., then the pressure will be computed via the 
+                                                !    hybrid coefficients hyam and hybm, they need to be initialized
+                                                ! if set to .false. (for pressure-based models): the pressure is already pre-computed
+                                                !    and is an input value for this routine 
+                                                ! for height-based models: pressure will always be computed based on the height and
+                                                !    hybrid_eta is not used
+
+	real(rstd), intent(inout) :: p		! Pressure  (Pa)
+				
+	integer,  intent(in) :: zcoords 	! 0 or 1 see below
+
+	real(rstd), intent(out) :: u, & 		! Zonal wind (m s^-1)
+				v, &		! Meridional wind (m s^-1)
+				w, &		! Vertical Velocity (m s^-1)
+				t, & 		! Temperature (K)
+				phis, & 	! Surface Geopotential (m^2 s^-2)
+				ps, & 		! Surface Pressure (Pa)
+				rho, & 		! density (kg m^-3)
+				q 		! Specific Humidity (kg/kg)
+
+	! if zcoords = 1, then we use z and output p
+	! if zcoords = 0, then we compute or use p
+        !
+	! In hybrid-eta coords: p = hyam p0 + hybm ps
+        !
+        ! The grid-point based initial data are computed in this routine. 
+
+!-----------------------------------------------------------------------
+!     test case parameters
+!----------------------------------------------------------------------- 
+	real(rstd), parameter :: 	T0      = 300.d0,		&	! temperature (K)
+                                gamma   = 0.0065d0,             &       ! temperature lapse rate (K/m)      
+                            	lambdam = 3.d0*pi/2.d0,		&	! mountain longitude center point (radians)   
+                            	phim    = 0.d0,			&	! mountain latitude center point (radians)    
+                            	h0      = 2000.d0,		&	! peak height of the mountain range (m)
+                            	Rm      = 3.d0*pi/4.d0,		&	! mountain radius (radians)
+                            	zetam   = pi/16.d0,		&	! mountain oscillation half-width (radians) 
+                            	ztop    = 12000.d0			! model top (m)         
+                            
+      real(rstd) :: height							! Model level heights (m)
+      real(rstd) :: r							! Great circle distance (radians)
+      real(rstd) :: zs							! Surface elevation (m)
+      real(rstd) :: exponent                                               ! exponent: g/(Rd * gamma)
+      real(rstd) :: exponent_rev                                           ! reversed exponent
+
+
+!-----------------------------------------------------------------------
+!    compute exponents 
+!-----------------------------------------------------------------------
+     exponent     = g/(Rd*gamma)
+     exponent_rev = 1.d0/exponent
+
+!-----------------------------------------------------------------------
+!    PHIS (surface geopotential)
+!-----------------------------------------------------------------------
+      
+	r = acos( sin(phim)*sin(lat) + cos(phim)*cos(lat)*cos(lon - lambdam) )
+
+	if (r .lt. Rm) then
+
+		zs = (h0/2.d0)*(1.d0+cos(pi*r/Rm))*cos(pi*r/zetam)**2.d0   ! mountain height
+
+	else
+
+		zs = 0.d0
+
+	endif
+
+	phis = g*zs
+
+!-----------------------------------------------------------------------
+!    PS (surface pressure)
+!-----------------------------------------------------------------------
+
+	ps = p0 * (1.d0 - gamma/T0*zs)**exponent
+
+
+!-----------------------------------------------------------------------
+!    HEIGHT AND PRESSURE
+!-----------------------------------------------------------------------
+
+	! Height and pressure are aligned (p = p0 * (1.d0 - gamma/T0*z)**exponent)
+
+	if (zcoords .eq. 1) then
+
+		height = z
+		p = p0 * (1.d0 - gamma/T0*z)**exponent
+
+	else
+
+                if (hybrid_eta) p = hyam*p0 + hybm*ps              ! compute the pressure based on the surface pressure and hybrid coefficients
+		height = T0/gamma * (1.d0 - (p/p0)**exponent_rev)  ! compute the height at this pressure
+
+	endif
+
+!-----------------------------------------------------------------------
+!    THE VELOCITIES ARE ZERO (STATE AT REST)
+!-----------------------------------------------------------------------
+
+	! Zonal Velocity
+
+	u = 0.d0
+
+	! Meridional Velocity
+
+	v = 0.d0
+
+        ! Vertical Velocity
+
+        w = 0.d0
+
+!-----------------------------------------------------------------------
+!    TEMPERATURE WITH CONSTANT LAPSE RATE
+!-----------------------------------------------------------------------
+
+	t = T0 - gamma*height
+
+!-----------------------------------------------------------------------
+!    RHO (density)
+!-----------------------------------------------------------------------
+
+	rho = p/(Rd*t)
+
+!-----------------------------------------------------------------------
+!     initialize Q, set to zero 
+!-----------------------------------------------------------------------
+
+	q = 0.d0
+
+END SUBROUTINE test2_steady_state_mountain
+
+
+
+!=====================================================================================
+! Tests 2-1 and 2-2:  Non-hydrostatic Mountain Waves over a Schaer-type Mountain
+!=====================================================================================
+
+SUBROUTINE test2_schaer_mountain (lon,lat,p,z,zcoords,hybrid_eta,hyam,hybm,shear,u,v,w,t,phis,ps,rho,q)
+
+IMPLICIT NONE
+!-----------------------------------------------------------------------
+!     input/output params parameters at given location
+!-----------------------------------------------------------------------
+
+	real(rstd), intent(in)  :: lon, &		! Longitude (radians)
+				lat, &		! Latitude (radians)
+				z,   &		! Height (m)
+				hyam, &		! A coefficient for hybrid-eta coordinate, at model level midpoint
+				hybm		! B coefficient for hybrid-eta coordinate, at model level midpoint
+
+	logical, intent(in)  :: hybrid_eta      ! flag to indicate whether the hybrid sigma-p (eta) coordinate is used
+                                                ! if set to .true., then the pressure will be computed via the 
+                                                !    hybrid coefficients hyam and hybm, they need to be initialized
+                                                ! if set to .false. (for pressure-based models): the pressure is already pre-computed
+                                                !    and is an input value for this routine 
+                                                ! for height-based models: pressure will always be computed based on the height and
+                                                !    hybrid_eta is not used
+
+	real(rstd), intent(inout) :: p		! Pressure  (Pa)
+				
+
+	integer,  intent(in) :: zcoords, &	! 0 or 1 see below
+				shear	 	! 0 or 1 see below
+
+	real(rstd), intent(out) :: u, & 		! Zonal wind (m s^-1)
+				v, &		! Meridional wind (m s^-1)
+				w, &		! Vertical Velocity (m s^-1)
+				t, & 		! Temperature (K)
+				phis, & 	! Surface Geopotential (m^2 s^-2)
+				ps, & 		! Surface Pressure (Pa)
+				rho, & 		! density (kg m^-3)
+				q 		! Specific Humidity (kg/kg)
+
+	! if zcoords = 1, then we use z and output p
+	! if zcoords = 0, then we either compute or use p
+
+	! if shear = 1, then we use shear flow
+	! if shear = 0, then we use constant u
+
+!-----------------------------------------------------------------------
+!     test case parameters
+!----------------------------------------------------------------------- 
+	real(rstd), parameter :: 	X       = 500.d0,		&	! Reduced Earth reduction factor
+			    	Om      = 0.d0,			&	! Rotation Rate of Earth
+                            	as      = a/X,			&	! New Radius of small Earth     
+			    	ueq     = 20.d0,		&	! Reference Velocity 
+                            	Teq     = 300.d0,		&	! Temperature at Equator    
+			    	Peq     = 100000.d0,		&	! Reference PS at Equator
+                            	ztop    = 30000.d0,		&	! Model Top       
+				lambdac = pi/4.d0, 		& 	! Lon of Schar Mountain Center
+				phic    = 0.d0,	 		& 	! Lat of Schar Mountain Center
+				h0      = 250.d0, 		& 	! Height of Mountain
+				d       = 5000.d0, 		& 	! Mountain Half-Width
+				xi      = 4000.d0, 		& 	! Mountain Wavelength
+				cs      = 0.00025d0 		 	! Wind Shear (shear=1)
+                            
+      real(rstd) :: height							! Model level heights
+      real(rstd) :: sin_tmp, cos_tmp					! Calculation of great circle distance
+      real(rstd) :: r							! Great circle distance
+      real(rstd) :: zs							! Surface height
+      real(rstd) :: c							! Shear
+
+!-----------------------------------------------------------------------
+!    PHIS (surface geopotential)
+!-----------------------------------------------------------------------
+
+	sin_tmp = sin(lat) * sin(phic)
+	cos_tmp = cos(lat) * cos(phic)
+	
+	! great circle distance with 'a/X'  
+
+	r  = as * ACOS (sin_tmp + cos_tmp*cos(lon-lambdac))     
+	zs   = h0 * exp(-(r**2)/(d**2))*(cos(pi*r/xi)**2)
+	phis = g*zs
+
+!-----------------------------------------------------------------------
+!    SHEAR FLOW OR CONSTANT FLOW
+!-----------------------------------------------------------------------
+
+	if (shear .eq. 1) then
+
+		c = cs
+
+	else
+
+		c = 0.d0
+
+	endif
+
+!-----------------------------------------------------------------------
+!    TEMPERATURE 
+!-----------------------------------------------------------------------
+
+	t = Teq *(1.d0 - (c*ueq*ueq/(g))*(sin(lat)**2) )
+
+!-----------------------------------------------------------------------
+!    PS (surface pressure)
+!-----------------------------------------------------------------------
+
+	ps = peq*exp( -(ueq*ueq/(2.d0*Rd*Teq))*(sin(lat)**2) - phis/(Rd*t)    )
+
+!-----------------------------------------------------------------------
+!    HEIGHT AND PRESSURE 
+!-----------------------------------------------------------------------
+
+	if (zcoords .eq. 1) then
+
+		height = z
+		p = peq*exp( -(ueq*ueq/(2.d0*Rd*Teq))*(sin(lat)**2) - g*height/(Rd*t)    )
+
+	else
+                if (hybrid_eta) p = hyam*p0 + hybm*ps ! compute the pressure based on the surface pressure and hybrid coefficients
+		height = (Rd*t/(g))*log(peq/p) - (t*ueq*ueq/(2.d0*Teq*g))*(sin(lat)**2)
+
+	endif
+
+!-----------------------------------------------------------------------
+!    THE VELOCITIES
+!-----------------------------------------------------------------------
+
+	! Zonal Velocity
+
+	u = ueq * cos(lat) * sqrt( (2.d0*Teq/(t))*c*height + t/(Teq) )
+
+	! Meridional Velocity
+
+	v = 0.d0
+
+	! Vertical Velocity = Vertical Pressure Velocity = 0
+
+	w = 0.d0
+
+!-----------------------------------------------------------------------
+!    RHO (density)
+!-----------------------------------------------------------------------
+
+	rho = p/(Rd*t)
+
+!-----------------------------------------------------------------------
+!     initialize Q, set to zero 
+!-----------------------------------------------------------------------
+
+	q = 0.d0
+
+END SUBROUTINE test2_schaer_mountain
+
+
+
+
+
+
+
+
+
+
+!==========================================================================================
+! TEST CASE 3 - GRAVITY WAVES
+!==========================================================================================
+
+! The non-hydrostatic gravity wave test examines the response of models to short time-scale wavemotion
+! triggered by a localized perturbation. The formulation presented in this document is new,
+! but is based on previous approaches by Skamarock et al. (JAS 1994), Tomita and Satoh (FDR 2004), and
+! Jablonowski et al. (NCAR Tech Report 2008) 
+
+
+!==========
+! Test 3-1
+!==========
+SUBROUTINE test3_gravity_wave (lon,lat,p,z,zcoords,u,v,w,t,phis,ps,rho,q)
+
+IMPLICIT NONE
+!-----------------------------------------------------------------------
+!     input/output params parameters at given location
+!-----------------------------------------------------------------------
+
+	real(rstd), intent(in)  :: lon, &		! Longitude (radians)
+				lat, &		! Latitude (radians)
+				z		! Height (m)
+
+	real(rstd), intent(inout) :: p		! Pressure  (Pa)
+				
+
+	integer,  intent(in) :: zcoords 	! 0 or 1 see below
+
+	real(rstd), intent(out) :: u, & 		! Zonal wind (m s^-1)
+				v, &		! Meridional wind (m s^-1)
+				w, &		! Vertical Velocity (m s^-1)
+				t, & 		! Temperature (K)
+				phis, & 	! Surface Geopotential (m^2 s^-2)
+				ps, & 		! Surface Pressure (Pa)
+				rho, & 		! density (kg m^-3)
+				q 		! Specific Humidity (kg/kg)
+
+	! if zcoords = 1, then we use z and output z
+	! if zcoords = 0, then we use p
+
+!-----------------------------------------------------------------------
+!     test case parameters
+!----------------------------------------------------------------------- 
+	real(rstd), parameter :: 	X       = 125.d0,		&	! Reduced Earth reduction factor
+			    	Om      = 0.d0,			&	! Rotation Rate of Earth
+                            	as      = a/X,			&	! New Radius of small Earth     
+			    	u0      = 20.d0,		&	! Reference Velocity 
+                            	Teq     = 300.d0,		&	! Temperature at Equator    
+			    	Peq     = 100000.d0,		&	! Reference PS at Equator
+                            	ztop    = 10000.d0,		&	! Model Top       
+				lambdac = 2.d0*pi/3.d0, 	& 	! Lon of Pert Center
+				d       = 5000.d0, 		& 	! Width for Pert
+				phic    = 0.d0,	 		& 	! Lat of Pert Center
+				delta_theta = 1.d0, 		& 	! Max Amplitude of Pert
+				Lz      = 20000.d0, 		& 	! Vertical Wavelength of Pert
+				N       = 0.01d0, 		& 	! Brunt-Vaisala frequency
+				N2      = N*N, 		 	&	! Brunt-Vaisala frequency Squared
+				bigG    = (g*g)/(N2*cp)			! Constant
+                            
+      real(rstd) :: height							! Model level height
+      real(rstd) :: sin_tmp, cos_tmp					! Calculation of great circle distance
+      real(rstd) :: r, s							! Shape of perturbation
+      real(rstd) :: TS 							! Surface temperature
+      real(rstd) :: t_mean, t_pert						! Mean and pert parts of temperature
+      real(rstd) :: theta_pert						! Pot-temp perturbation
+
+!-----------------------------------------------------------------------
+!    THE VELOCITIES
+!-----------------------------------------------------------------------
+
+	! Zonal Velocity 
+
+	u = u0 * cos(lat)
+
+	! Meridional Velocity
+
+	v = 0.d0
+
+	! Vertical Velocity = Vertical Pressure Velocity = 0
+
+	w = 0.d0
+
+!-----------------------------------------------------------------------
+!    PHIS (surface geopotential)
+!-----------------------------------------------------------------------
+
+	phis = 0.d0
+
+!-----------------------------------------------------------------------
+!    SURFACE TEMPERATURE 
+!-----------------------------------------------------------------------
+
+	TS = bigG + (Teq-bigG)*exp( -(u0*N2/(4.d0*g*g))*(u0+2.d0*om*as)*(cos(2.d0*lat)-1.d0)    ) 
+
+!-----------------------------------------------------------------------
+!    PS (surface pressure)
+!-----------------------------------------------------------------------
+
+	ps = peq*exp( (u0/(4.0*bigG*Rd))*(u0+2.0*Om*as)*(cos(2.0*lat)-1.0)  ) &
+		* (TS/Teq)**(cp/Rd)
+
+!-----------------------------------------------------------------------
+!    HEIGHT AND PRESSURE AND MEAN TEMPERATURE
+!-----------------------------------------------------------------------
+
+	if (zcoords .eq. 1) then
+
+		height = z
+		p = ps*( (bigG/TS)*exp(-N2*height/g)+1.d0 - (bigG/TS)  )**(cp/Rd)
+
+	else
+
+		height = (-g/N2)*log( (TS/bigG)*( (p/ps)**(Rd/cp) - 1.d0  ) + 1.d0 )
+
+	endif
+
+	t_mean = bigG*(1.d0 - exp(N2*height/g))+ TS*exp(N2*height/g)
+
+!-----------------------------------------------------------------------
+!    rho (density), unperturbed using the background temperature t_mean
+!-----------------------------------------------------------------------
+
+!***********
+!       change in version 3: density is now initialized with unperturbed background temperature,
+!                            temperature perturbation is added afterwards
+!***********
+	rho = p/(Rd*t_mean)
+
+!-----------------------------------------------------------------------
+!    POTENTIAL TEMPERATURE PERTURBATION, 
+!    here: converted to temperature and added to the temperature field
+!    models with a prognostic potential temperature field can utilize
+!    the potential temperature perturbation theta_pert directly and add it
+!    to the background theta field (not included here)
+!-----------------------------------------------------------------------
+
+	sin_tmp = sin(lat) * sin(phic)
+	cos_tmp = cos(lat) * cos(phic)
+
+		! great circle distance with 'a/X' 
+
+	r  = as * ACOS (sin_tmp + cos_tmp*cos(lon-lambdac)) 
+
+	s = (d**2)/(d**2 + r**2)
+
+	theta_pert = delta_theta*s*sin(2.d0*pi*height/Lz)
+
+	t_pert = theta_pert*(p/p0)**(Rd/cp)
+
+	t = t_mean + t_pert
+
+!-----------------------------------------------------------------------
+!     initialize Q, set to zero 
+!-----------------------------------------------------------------------
+
+	q = 0.d0
+
+END SUBROUTINE test3_gravity_wave
+
+
+END MODULE dcmip_initial_conditions_test_1_2_3
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dimensions.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dimensions.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dimensions.f90	(revision 329)
@@ -0,0 +1,127 @@
+MODULE dimensions
+
+    INTEGER,SAVE :: iim
+!$OMP THREADPRIVATE(iim)
+    INTEGER,SAVE :: jjm
+!$OMP THREADPRIVATE(jjm)
+    INTEGER,SAVE :: ii_begin
+!$OMP THREADPRIVATE(ii_begin)
+    INTEGER,SAVE :: jj_begin
+!$OMP THREADPRIVATE(jj_begin)
+    INTEGER,SAVE :: ii_end
+!$OMP THREADPRIVATE(ii_end)
+    INTEGER,SAVE :: jj_end
+!$OMP THREADPRIVATE(jj_end)
+    INTEGER,SAVE :: ii_nb
+!$OMP THREADPRIVATE(ii_nb)
+    INTEGER,SAVE :: jj_nb
+!$OMP THREADPRIVATE(jj_nb)
+    INTEGER,SAVE :: ij_begin
+!$OMP THREADPRIVATE(ij_begin)
+    INTEGER,SAVE :: ij_end
+!$OMP THREADPRIVATE(ij_end)
+    INTEGER,SAVE :: ij_begin_ext
+!$OMP THREADPRIVATE(ij_begin_ext)
+    INTEGER,SAVE :: ij_end_ext
+!$OMP THREADPRIVATE(ij_end_ext)
+        
+    INTEGER,SAVE :: t_right
+!$OMP THREADPRIVATE(t_right)
+    INTEGER,SAVE :: t_rup
+!$OMP THREADPRIVATE(t_rup)
+    INTEGER,SAVE :: t_lup
+!$OMP THREADPRIVATE(t_lup)
+    INTEGER,SAVE :: t_left
+!$OMP THREADPRIVATE(t_left)
+    INTEGER,SAVE :: t_ldown
+!$OMP THREADPRIVATE(t_ldown)
+    INTEGER,SAVE :: t_rdown
+!$OMP THREADPRIVATE(t_rdown)
+
+    INTEGER,SAVE :: u_right
+!$OMP THREADPRIVATE(u_right)
+    INTEGER,SAVE :: u_rup
+!$OMP THREADPRIVATE(u_rup)
+    INTEGER,SAVE :: u_lup
+!$OMP THREADPRIVATE(u_lup)
+    INTEGER,SAVE :: u_left
+!$OMP THREADPRIVATE(u_left)
+    INTEGER,SAVE :: u_ldown
+!$OMP THREADPRIVATE(u_ldown)
+    INTEGER,SAVE :: u_rdown
+!$OMP THREADPRIVATE(u_rdown)
+
+    INTEGER,SAVE :: z_rup
+!$OMP THREADPRIVATE(z_rup)
+    INTEGER,SAVE :: z_up
+!$OMP THREADPRIVATE(z_up)
+    INTEGER,SAVE :: z_lup
+!$OMP THREADPRIVATE(z_lup)
+    INTEGER,SAVE :: z_ldown
+!$OMP THREADPRIVATE(z_ldown)
+    INTEGER,SAVE :: z_down
+!$OMP THREADPRIVATE(z_down)
+    INTEGER,SAVE :: z_rdown
+!$OMP THREADPRIVATE(z_rdown)
+
+    INTEGER,SAVE :: t_pos(6)
+!$OMP THREADPRIVATE(t_pos)
+    INTEGER,SAVE :: u_pos(6)
+!$OMP THREADPRIVATE(u_pos)
+    INTEGER,SAVE :: z_pos(6)
+!$OMP THREADPRIVATE(z_pos)
+        
+CONTAINS
+
+  SUBROUTINE swap_dimensions(ind)
+  USE domain_mod
+  IMPLICIT NONE
+    INTEGER,INTENT(IN) :: ind
+    
+    TYPE(t_domain),POINTER :: d
+    
+    d=>domain(ind)
+     
+     iim=d%iim
+     jjm=d%jjm
+     ii_begin=d%ii_begin
+     jj_begin=d%jj_begin
+     ii_end=d%ii_end
+     jj_end=d%jj_end
+     ii_nb=d%ii_nb
+     jj_nb=d%jj_nb
+    
+     ij_begin=(jj_begin-1)*iim+ii_begin
+     ij_end=(jj_end-1)*iim+ii_end 
+     ij_begin_ext=((jj_begin-1)-1)*iim+ii_begin-1
+     ij_end_ext = ((jj_end+1)-1)*iim+ii_end+1
+        
+     t_right=d%t_right
+     t_rup=d%t_rup
+     t_lup=d%t_lup
+     t_left=d%t_left
+     t_ldown=d%t_ldown
+     t_rdown=d%t_rdown
+
+     u_right=d%u_right
+     u_rup=d%u_rup
+     u_lup=d%u_lup
+     u_left=d%u_left
+     u_ldown=d%u_ldown
+     u_rdown=d%u_rdown
+
+     z_rup=d%z_rup
+     z_up=d%z_up
+     z_lup=d%z_lup
+     z_ldown=d%z_ldown
+     z_down=d%z_down
+     z_rdown=d%z_rdown
+     
+     t_pos(:)=d%t_pos(:)
+     u_pos(:)=d%u_pos(:)
+     z_pos(:)=d%z_pos(:)
+
+   END SUBROUTINE swap_dimensions
+   
+END MODULE dimensions   
+    
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dimphys.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dimphys.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dimphys.f90	(revision 329)
@@ -0,0 +1,27 @@
+MODULE dimphys_mod
+        USE ICOSA
+      INTEGER::nsoilmx=10,offset
+      INTEGER::ngridmx,nlayermx
+      LOGICAL::callrad,calldifv,calladj,callcond,callsoil
+      LOGICAL::season,diurnal,lverbose
+      INTEGER:: iradia
+      REAL:: period_sort,timeperi
+      REAL:: aphelie,periheli,year_day,peri_day,obliquit
+      REAL::e_elips,p_elips,unitastr
+      REAL:: coefvis,coefir
+
+      REAL,ALLOCATABLE:: albedo(:),emissiv(:),inertie(:)
+      REAL,ALLOCATABLE:: tsurf(:),tsoil(:,:)
+      REAL,ALLOCATABLE:: z0(:),rnatur(:)
+      REAL,ALLOCATABLE:: dtrad(:,:) ,fluxrad(:)
+      REAL,ALLOCATABLE:: capcal(:)  ,fluxgrd(:)
+      REAL,ALLOCATABLE:: q2(:,:),q2l(:,:)
+
+
+!      REAL,allocatable:: albedo(:),emissiv(:),inertie(:)
+!      REAL,allocatable:: z0(:),rnatur(:)
+
+!      REAL,allocatable::tsurf(:),tsoil(:,:)
+!      REAL,allocatable::fluxrad(:),fluxgrd(:)
+!      REAL,ALLOCATABLE::capcal(:)
+END MODULE dimphys_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dissip_gcm.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dissip_gcm.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dissip_gcm.f90	(revision 329)
@@ -0,0 +1,917 @@
+MODULE dissip_gcm_mod
+  USE icosa
+
+  PRIVATE
+
+  TYPE(t_field),POINTER,SAVE :: f_due_diss1(:)
+  TYPE(t_field),POINTER,SAVE :: f_due_diss2(:)
+
+  TYPE(t_field),POINTER,SAVE :: f_theta(:), f_phi(:), f_pk(:), f_pks(:), f_p(:)
+  TYPE(t_field),POINTER,SAVE :: f_dtheta_diss(:)
+  TYPE(t_field),POINTER,SAVE :: f_dtheta_rhodz_diss(:)
+  TYPE(t_message),SAVE :: req_due, req_dtheta 
+ 
+  INTEGER,SAVE :: nitergdiv=1
+!$OMP THREADPRIVATE(nitergdiv)
+  INTEGER,SAVE :: nitergrot=1
+!$OMP THREADPRIVATE(nitergrot)
+  INTEGER,SAVE :: niterdivgrad=1
+!$OMP THREADPRIVATE(niterdivgrad)
+
+  REAL,ALLOCATABLE,SAVE :: tau_graddiv(:)
+!$OMP THREADPRIVATE(tau_graddiv)
+  REAL,ALLOCATABLE,SAVE :: tau_gradrot(:)
+!$OMP THREADPRIVATE(tau_gradrot)
+  REAL,ALLOCATABLE,SAVE :: tau_divgrad(:)
+!$OMP THREADPRIVATE(tau_divgrad)
+  
+  REAL,SAVE :: cgraddiv
+!$OMP THREADPRIVATE(cgraddiv)
+  REAL,SAVE :: cgradrot
+!$OMP THREADPRIVATE(cgradrot)
+  REAL,SAVE :: cdivgrad
+!$OMP THREADPRIVATE(cdivgrad)
+
+  INTEGER, SAVE :: rayleigh_friction_type, rayleigh_shear
+!$OMP THREADPRIVATE(rayleigh_friction_type)
+  REAL, SAVE    :: rayleigh_tau
+!$OMP THREADPRIVATE(rayleigh_shear)
+  
+  REAL,SAVE    :: dtdissip
+!$OMP THREADPRIVATE(dtdissip)
+ 
+  PUBLIC init_dissip, dissip
+CONTAINS
+
+  SUBROUTINE allocate_dissip
+  USE icosa
+  IMPLICIT NONE  
+    CALL allocate_field(f_due_diss1,field_u,type_real,llm)
+    CALL allocate_field(f_due_diss2,field_u,type_real,llm)
+    CALL allocate_field(f_theta,field_t,type_real,llm)
+    CALL allocate_field(f_dtheta_diss,field_t,type_real,llm)
+    CALL allocate_field(f_dtheta_rhodz_diss,field_t,type_real,llm)
+
+    CALL allocate_field(f_phi,field_t,type_real,llm)
+    CALL allocate_field(f_pk,field_t,type_real,llm)
+    CALL allocate_field(f_p,field_t,type_real,llm+1)
+    CALL allocate_field(f_pks,field_t,type_real)
+    
+    ALLOCATE(tau_graddiv(llm))
+    ALLOCATE(tau_gradrot(llm))    
+    ALLOCATE(tau_divgrad(llm))
+  END SUBROUTINE allocate_dissip
+ 
+  SUBROUTINE init_dissip
+  USE icosa
+  USE disvert_mod
+  USE mpi_mod
+  USE mpipara
+  USE omp_para, ONLY: omp_master
+  USE transfert_mod
+  USE time_mod
+  USE transfert_omp_mod
+  IMPLICIT NONE
+  
+  TYPE(t_field),POINTER,SAVE  :: f_u(:)
+  TYPE(t_field),POINTER,SAVE  :: f_du(:)
+  REAL(rstd),POINTER     :: u(:)
+  REAL(rstd),POINTER     :: du(:)
+  TYPE(t_field),POINTER,SAVE  :: f_theta(:)
+  TYPE(t_field),POINTER ,SAVE :: f_dtheta(:)
+  REAL(rstd),POINTER    :: theta(:)
+  REAL(rstd),POINTER    :: dtheta(:)
+  REAL(rstd)            :: dumax,dumax1
+  REAL(rstd)            :: dthetamax,dthetamax1
+  REAL(rstd)            :: r
+  REAL(rstd)            :: tau
+  REAL(rstd)            :: zz, zvert, fact
+  INTEGER               :: l
+  CHARACTER(len=255)    :: rayleigh_friction_key
+  REAL(rstd)            :: mintau
+  INTEGER               :: seed_size
+  INTEGER,ALLOCATABLE   :: seed(:)
+  
+            
+  INTEGER :: i,j,ij,ind,it,iter
+
+   rayleigh_friction_key='none'
+   CALL getin("rayleigh_friction_type",rayleigh_friction_key)
+   SELECT CASE(TRIM(rayleigh_friction_key))
+   CASE('none')
+      rayleigh_friction_type=0
+      IF (is_mpi_root .AND. omp_master) PRINT *, 'No Rayleigh friction'
+   CASE('dcmip2_schaer_noshear')
+      rayleigh_friction_type=1
+      rayleigh_shear=0
+      IF (is_mpi_root .AND. omp_master) PRINT *, 'Rayleigh friction : Schaer-like mountain without shear DCMIP2.1'
+   CASE('dcmip2_schaer_shear')
+      rayleigh_shear=1
+      rayleigh_friction_type=2
+      IF (is_mpi_root .AND. omp_master) PRINT *, 'Rayleigh friction : Schaer-like mountain with shear DCMIP2.2'
+   CASE DEFAULT
+      IF (is_mpi_root .AND. omp_master) PRINT *, 'Bad selector : rayleigh_friction_type =', TRIM(rayleigh_friction_key), ' in dissip_gcm.f90/init_dissip'
+      STOP
+   END SELECT
+
+   IF(rayleigh_friction_type>0) THEN
+      rayleigh_tau=0.
+      CALL getin("rayleigh_friction_tau",rayleigh_tau)
+      rayleigh_tau = rayleigh_tau / scale_factor
+      IF(rayleigh_tau<=0) THEN
+         IF (is_mpi_root .AND. omp_master) PRINT *, 'Forbidden : negative value for rayleigh_friction_tau =',rayleigh_tau
+         STOP
+      END IF
+   END IF
+
+    CALL allocate_dissip
+    CALL allocate_field(f_u,field_u,type_real)
+    CALL allocate_field(f_du,field_u,type_real)
+    CALL allocate_field(f_theta,field_t,type_real)
+    CALL allocate_field(f_dtheta,field_t,type_real)
+    
+    CALL init_message(f_due_diss1,req_e1_vect,req_due)
+    CALL init_message(f_dtheta_diss,req_i1,req_dtheta)
+
+    tau_graddiv(:)=5000
+    CALL getin("tau_graddiv",tau)
+    tau_graddiv(:)=tau/scale_factor
+
+    CALL getin("nitergdiv",nitergdiv)
+    
+    tau_gradrot(:)=5000
+    CALL getin("tau_gradrot",tau)
+    tau_gradrot(:)=tau/scale_factor
+
+    CALL getin("nitergrot",nitergrot)
+    
+
+    tau_divgrad(:)=5000
+    CALL getin("tau_divgrad",tau)
+    tau_divgrad(:)=tau/scale_factor
+
+    CALL getin("niterdivgrad",niterdivgrad)
+
+
+    cgraddiv=-1
+    cdivgrad=-1
+    cgradrot=-1
+    
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      u=f_u(ind)
+
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i   
+          CALL RANDOM_NUMBER(r)
+          u(ij+u_right)=r-0.5
+          CALL RANDOM_NUMBER(r)
+          u(ij+u_lup)=r-0.5
+          CALL RANDOM_NUMBER(r)
+          u(ij+u_ldown)=r-0.5
+        ENDDO
+      ENDDO        
+    ENDDO
+  
+
+
+    DO it=1,20
+      
+      dumax=0
+      DO iter=1,nitergdiv
+        CALL transfert_request(f_u,req_e1_vect)
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          u=f_u(ind)
+          du=f_du(ind)
+          CALL compute_gradiv(u,du,1,1)
+          u=du
+        ENDDO
+      ENDDO
+
+      CALL transfert_request(f_du,req_e1_vect)
+      
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        u=f_u(ind)
+        du=f_du(ind)
+         
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i   
+            if (le(ij+u_right)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_right)))
+            if (le(ij+u_lup)>1e-100)   dumax=MAX(dumax,ABS(du(ij+u_lup)))
+            if (le(ij+u_ldown)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_ldown)))
+          ENDDO
+        ENDDO
+      ENDDO
+
+      IF (using_mpi) THEN 
+        CALL reduce_sum_omp(dumax,dumax1)
+!$OMP MASTER        
+        CALL MPI_ALLREDUCE(dumax1,dumax,1,MPI_REAL8,MPI_MAX,comm_icosa,ierr)
+!$OMP END MASTER     
+        CALL bcast_omp(dumax)  
+      ELSE
+        CALL allreduce_sum_omp(dumax,dumax1)
+        dumax=dumax1
+      ENDIF  
+			
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        u=f_u(ind)
+        du=f_du(ind)
+        u=du/dumax
+      ENDDO
+      IF (is_mpi_root .AND. omp_master) PRINT *,"gradiv : it :",it ,": dumax",dumax
+
+    ENDDO 
+    IF (is_mpi_root .AND. omp_master) PRINT *,"gradiv : dumax",dumax
+    IF (is_mpi_root .AND. omp_master) PRINT *, 'mean T-cell edge size (km)', 1.45*radius/iim_glo/1000., &
+                              'effective T-cell half-edge size (km)', dumax**(-.5/nitergdiv)/1000
+    IF (is_mpi_root .AND. omp_master)  PRINT *, 'Max. time step assuming c=340 m/s and Courant number=2.8 :', &
+                               2.8/340.*dumax**(-.5/nitergdiv)
+
+    cgraddiv=dumax**(-1./nitergdiv)
+    IF (is_mpi_root .AND. omp_master) PRINT *,"cgraddiv : ",cgraddiv
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      u=f_u(ind)
+
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i   
+          CALL RANDOM_NUMBER(r)
+          u(ij+u_right)=r-0.5
+          CALL RANDOM_NUMBER(r)
+          u(ij+u_lup)=r-0.5
+          CALL RANDOM_NUMBER(r)
+          u(ij+u_ldown)=r-0.5
+        ENDDO
+      ENDDO        
+    ENDDO
+
+
+    DO it=1,20
+ 
+      dumax=0
+      DO iter=1,nitergrot
+        CALL transfert_request(f_u,req_e1_vect)
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          u=f_u(ind)
+          du=f_du(ind)
+          CALL compute_gradrot(u,du,1,1)
+          u=du
+        ENDDO
+      ENDDO
+
+      CALL transfert_request(f_du,req_e1_vect)
+      
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        u=f_u(ind)
+        du=f_du(ind)
+        
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i   
+            if (le(ij+u_right)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_right)))
+            if (le(ij+u_lup)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_lup)))
+            if (le(ij+u_ldown)>1e-100) dumax=MAX(dumax,ABS(du(ij+u_ldown)))
+          ENDDO
+        ENDDO
+      ENDDO
+
+      IF (using_mpi) THEN 
+        CALL reduce_sum_omp(dumax,dumax1)
+!$OMP MASTER        
+        CALL MPI_ALLREDUCE(dumax1,dumax,1,MPI_REAL8,MPI_MAX,comm_icosa,ierr)
+!$OMP END MASTER     
+        CALL bcast_omp(dumax)  
+      ELSE
+        CALL allreduce_sum_omp(dumax,dumax1)
+        dumax=dumax1
+      ENDIF  
+
+      
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        u=f_u(ind)
+        du=f_du(ind)
+        u=du/dumax
+      ENDDO
+      
+      IF (is_mpi_root .AND. omp_master) PRINT *,"gradrot : it :",it ,": dumax",dumax
+
+    ENDDO 
+    IF (is_mpi_root .AND. omp_master) PRINT *,"gradrot : dumax",dumax
+  
+    cgradrot=dumax**(-1./nitergrot) 
+    IF (is_mpi_root .AND. omp_master) PRINT *,"cgradrot : ",cgradrot
+   
+
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      theta=f_theta(ind)
+ 
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i   
+          CALL RANDOM_NUMBER(r)
+          theta(ij)=r-0.5
+        ENDDO
+      ENDDO  
+    ENDDO
+
+    DO it=1,20
+
+      dthetamax=0
+      DO iter=1,niterdivgrad
+        CALL transfert_request(f_theta,req_i1)
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          theta=f_theta(ind)
+          dtheta=f_dtheta(ind)
+          CALL compute_divgrad(theta,dtheta,1,1)
+          theta=dtheta
+        ENDDO
+      ENDDO
+
+      CALL transfert_request(f_dtheta,req_i1)
+      
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        theta=f_theta(ind)
+        dtheta=f_dtheta(ind)
+        
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i   
+            dthetamax=MAX(dthetamax,ABS(dtheta(ij)))
+          ENDDO
+        ENDDO
+      ENDDO
+
+      IF (using_mpi) THEN 
+        CALL reduce_sum_omp(dthetamax ,dthetamax1)
+!$OMP MASTER        
+        CALL MPI_ALLREDUCE(dthetamax1,dthetamax,1,MPI_REAL8,MPI_MAX,comm_icosa,ierr)
+!$OMP END MASTER     
+        CALL bcast_omp(dthetamax)  
+      ELSE
+        CALL allreduce_sum_omp(dthetamax,dthetamax1)
+        dumax=dumax1
+      ENDIF  
+      
+      IF (is_mpi_root .AND. omp_master) PRINT *,"divgrad : it :",it ,": dthetamax",dthetamax
+
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        theta=f_theta(ind)
+        dtheta=f_dtheta(ind)
+        theta=dtheta/dthetamax
+      ENDDO
+    ENDDO 
+
+    IF (is_mpi_root .AND. omp_master) PRINT *,"divgrad : divgrad",dthetamax
+  
+    cdivgrad=dthetamax**(-1./niterdivgrad) 
+    IF (is_mpi_root .AND. omp_master) PRINT *,"cdivgrad : ",cdivgrad
+
+     
+    fact=2
+    DO l=1,llm
+       IF(ap_bp_present) THEN ! height-dependent dissipation
+          zz= 1. - preff/presnivs(l)
+       ELSE
+          zz = 0.
+       END IF
+       zvert=fact-(fact-1)/(1+zz*zz)
+       tau_graddiv(l) = tau_graddiv(l)/zvert
+       tau_gradrot(l) = tau_gradrot(l)/zvert
+       tau_divgrad(l) = tau_divgrad(l)/zvert
+    ENDDO
+
+    mintau=tau_graddiv(1)
+    DO l=1,llm
+      mintau=MIN(mintau,tau_graddiv(l))
+      mintau=MIN(mintau,tau_gradrot(l))
+      mintau=MIN(mintau,tau_divgrad(l))
+    ENDDO
+       
+    IF(mintau>0) THEN
+       itau_dissip=INT(mintau/dt)
+       dtdissip=itau_dissip*dt
+    ELSE
+       IF (is_mpi_root .AND. omp_master) PRINT *,"No dissipation time set, setting itau_dissip to 1000000000"
+       itau_dissip=100000000
+    END IF
+    itau_dissip=MAX(1,itau_dissip)
+    IF (is_mpi_root .AND. omp_master) PRINT *,"mintau ",mintau,"itau_dissip",itau_dissip," dtdissip ",dtdissip
+
+  END SUBROUTINE init_dissip 
+ 
+  
+  SUBROUTINE dissip(f_ue,f_due,f_mass,f_phis,f_theta_rhodz,f_dtheta_rhodz)
+  USE icosa
+  USE theta2theta_rhodz_mod
+  USE pression_mod
+  USE exner_mod
+  USE geopotential_mod
+  USE trace
+  USE time_mod
+  USE omp_para
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ue(:)
+    TYPE(t_field),POINTER :: f_due(:)
+    TYPE(t_field),POINTER :: f_mass(:), f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
+
+    REAL(rstd),POINTER         :: due(:,:)
+    REAL(rstd),POINTER         :: phi(:,:), ue(:,:)
+    REAL(rstd),POINTER         :: due_diss1(:,:)
+    REAL(rstd),POINTER         :: due_diss2(:,:)
+    REAL(rstd),POINTER         :: dtheta_rhodz(:,:)
+    REAL(rstd),POINTER         :: dtheta_rhodz_diss(:,:)
+
+    INTEGER :: ind, shear
+    INTEGER :: l,ij
+
+!$OMP BARRIER
+    
+    CALL trace_start("dissip")
+    CALL gradiv(f_ue,f_due_diss1)
+    CALL gradrot(f_ue,f_due_diss2)
+
+    CALL divgrad_theta_rhodz(f_mass,f_theta_rhodz,f_dtheta_rhodz_diss)
+    
+! later for openmp    
+!    IF(rayleigh_friction_type>0) THEN
+!       CALL pression(f_ps, f_p)
+!       CALL exner(f_ps, f_p, f_pks, f_pk)
+!       CALL geopotential(f_phis,f_pks,f_pk,f_theta,f_phi)
+!    END IF
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      due=f_due(ind) 
+      due_diss1=f_due_diss1(ind)
+      due_diss2=f_due_diss2(ind)
+      dtheta_rhodz=f_dtheta_rhodz(ind)
+      dtheta_rhodz_diss=f_dtheta_rhodz_diss(ind)
+
+      DO l=ll_begin,ll_end
+!$SIMD
+        DO ij=ij_begin,ij_end
+
+            due(ij+u_right,l) = -0.5*( due_diss1(ij+u_right,l)/tau_graddiv(l) + due_diss2(ij+u_right,l)/tau_gradrot(l))*itau_dissip 
+            due(ij+u_lup,l)   = -0.5*( due_diss1(ij+u_lup,l)  /tau_graddiv(l) + due_diss2(ij+u_lup,l)  /tau_gradrot(l))*itau_dissip
+            due(ij+u_ldown,l) = -0.5*( due_diss1(ij+u_ldown,l)/tau_graddiv(l) + due_diss2(ij+u_ldown,l)/tau_gradrot(l))*itau_dissip
+
+            dtheta_rhodz(ij,l) = -0.5*dtheta_rhodz_diss(ij,l)/tau_divgrad(l)*itau_dissip
+        ENDDO
+      ENDDO
+
+!      dtheta_rhodz=0
+!      due=0
+
+! later for openmp  
+!      IF(rayleigh_friction_type>0) THEN
+!         phi=f_phi(ind)
+!         ue=f_ue(ind)
+!         DO l=1,llm
+!            DO j=jj_begin,jj_end
+!               DO i=ii_begin,ii_end
+!                  n=(j-1)*iim+i
+!                  CALL relax(t_right, u_right)
+!                  CALL relax(t_lup,   u_lup)
+!                  CALL relax(t_ldown, u_ldown)
+!               ENDDO
+!            ENDDO
+!         END DO
+!      END IF
+   END DO
+
+   CALL trace_end("dissip")
+
+!$OMP BARRIER
+
+    CONTAINS
+      SUBROUTINE relax(shift_t, shift_u)
+        USE dcmip_initial_conditions_test_1_2_3
+        REAL(rstd) :: z, ulon,ulat, lon,lat, & ! input to test2_schaer_mountain
+             p,hyam,hybm,w,t,phis,ps,rho,q, &   ! unused input/output to test2_schaer_mountain
+             fz, u3d(3), uref
+        REAL(rstd), PARAMETER :: zh=2e4,ztop=3e4  ! DCMIP values
+        LOGICAL :: hybrid_eta
+        INTEGER :: shift_u, shift_t, zcoords, nn
+        z = (phi(ij,l)+phi(ij+shift_t,l))/(2.*g)
+        IF(z>zh) THEN  ! relax only in the sponge layer z>zh
+
+           nn = ij+shift_u
+           CALL xyz2lonlat(xyz_e(nn,:),lon,lat)
+           zcoords = 1 ; hybrid_eta = .FALSE. ! use z instead of p or hyam/hybm
+           CALL test2_schaer_mountain(lon,lat,p,z,zcoords,hybrid_eta, &
+                hyam,hybm,shear,ulon,ulat,w,t,phis,ps,rho,q)
+!           u3d = ulon*elon_e(nn,:) + ulat*elat_e(nn,:)
+           u3d = ulon*elon_e(nn,:) ! ulat=0
+           uref = sum(u3d*ep_e(nn,:))
+
+           fz = sin((pi/2)*(z-zh)/(ztop-zh))
+           fz = fz*fz/rayleigh_tau
+!           fz = 1/rayleigh_tau
+           due(nn,l) = due(nn,l) - fz*(ue(nn,l)-uref)
+!           due(nn,l) = due(nn,l) - fz*ue(nn,l)
+         END IF
+       END SUBROUTINE relax
+      
+  END SUBROUTINE dissip
+
+  SUBROUTINE gradiv(f_ue,f_due)
+  USE icosa
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ue(:)
+    TYPE(t_field),POINTER :: f_due(:)
+    REAL(rstd),POINTER    :: ue(:,:)
+    REAL(rstd),POINTER    :: due(:,:)
+    INTEGER :: ind
+    INTEGER :: it,l,ij
+       
+    CALL trace_start("gradiv")
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ue=f_ue(ind)
+      due=f_due(ind) 
+      DO  l = ll_begin, ll_end
+!$SIMD
+        DO ij=ij_begin,ij_end
+             due(ij+u_right,l)=ue(ij+u_right,l)
+             due(ij+u_lup,l)=ue(ij+u_lup,l)
+             due(ij+u_ldown,l)=ue(ij+u_ldown,l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+    DO it=1,nitergdiv
+        
+      CALL send_message(f_due,req_due)
+      CALL wait_message(req_due)
+        
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        due=f_due(ind) 
+        CALL compute_gradiv(due,due,ll_begin,ll_end)
+      ENDDO
+    ENDDO
+
+   CALL trace_end("gradiv")
+
+  END SUBROUTINE gradiv
+  
+
+  SUBROUTINE gradrot(f_ue,f_due)
+  USE icosa
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ue(:)
+    TYPE(t_field),POINTER :: f_due(:)
+    REAL(rstd),POINTER    :: ue(:,:)
+    REAL(rstd),POINTER    :: due(:,:)
+    INTEGER :: ind
+    INTEGER :: it,l,ij
+       
+    CALL trace_start("gradrot")
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ue=f_ue(ind)
+      due=f_due(ind) 
+      DO  l = ll_begin, ll_end
+!$SIMD
+        DO ij=ij_begin,ij_end
+             due(ij+u_right,l)=ue(ij+u_right,l)
+             due(ij+u_lup,l)=ue(ij+u_lup,l)
+             due(ij+u_ldown,l)=ue(ij+u_ldown,l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+    DO it=1,nitergrot
+        
+      CALL send_message(f_due,req_due)
+      CALL wait_message(req_due)
+        
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        due=f_due(ind) 
+        CALL compute_gradrot(due,due,ll_begin,ll_end)
+      ENDDO
+
+    ENDDO
+
+    CALL trace_end("gradrot")
+
+  END SUBROUTINE gradrot
+  
+  SUBROUTINE divgrad(f_theta,f_dtheta)
+  USE icosa
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_theta(:)
+    TYPE(t_field),POINTER :: f_dtheta(:)
+    REAL(rstd),POINTER    :: theta(:,:)
+    REAL(rstd),POINTER    :: dtheta(:,:)
+    INTEGER :: ind
+    INTEGER :: it
+
+    CALL trace_start("divgrad")
+       
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      theta=f_theta(ind)
+      dtheta=f_dtheta(ind) 
+      dtheta=theta
+    ENDDO
+
+    DO it=1,niterdivgrad
+        
+      CALL transfert_request(f_dtheta,req_i1)
+        
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        dtheta=f_dtheta(ind) 
+        CALL compute_divgrad(dtheta,dtheta,ll_begin,ll_end)
+      ENDDO
+
+    ENDDO
+
+    CALL trace_end("divgrad")
+
+  END SUBROUTINE divgrad
+   
+  SUBROUTINE divgrad_theta_rhodz(f_mass,f_theta_rhodz,f_dtheta_rhodz)
+  USE icosa
+  USE trace
+  USE omp_para
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_mass(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
+    
+    REAL(rstd),POINTER :: mass(:,:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: dtheta_rhodz(:,:)
+
+    INTEGER :: ind
+    INTEGER :: it,l,ij
+
+    CALL trace_start("divgrad")
+       
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      mass=f_mass(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      dtheta_rhodz=f_dtheta_rhodz(ind) 
+      DO  l = ll_begin, ll_end
+!$SIMD
+        DO ij=ij_begin,ij_end
+            dtheta_rhodz(ij,l) = theta_rhodz(ij,l) / mass(ij,l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+    DO it=1,niterdivgrad
+        
+      CALL send_message(f_dtheta_rhodz,req_dtheta)
+      CALL wait_message(req_dtheta)
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        dtheta_rhodz=f_dtheta_rhodz(ind) 
+        CALL compute_divgrad(dtheta_rhodz,dtheta_rhodz,ll_begin,ll_end)
+      ENDDO
+
+    ENDDO
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      dtheta_rhodz=f_dtheta_rhodz(ind) 
+      mass=f_mass(ind)
+    
+      DO  l = ll_begin, ll_end
+!$SIMD
+        DO ij=ij_begin,ij_end
+            dtheta_rhodz(ij,l) = dtheta_rhodz(ij,l) * mass(ij,l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+
+    CALL trace_end("divgrad")
+
+  END SUBROUTINE divgrad_theta_rhodz  
+  
+  SUBROUTINE compute_gradiv(ue,gradivu_e,llb,lle)
+  USE icosa
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)     :: llb
+    INTEGER,INTENT(IN)     :: lle
+    REAL(rstd),INTENT(IN)  :: ue(iim*3*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: gradivu_e(iim*3*jjm,llm)
+    REAL(rstd) :: divu_i(iim*jjm,llb:lle)
+    
+    INTEGER :: ij,l
+
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin,ij_end
+          divu_i(ij,l)=1./Ai(ij)*(ne(ij,right)*ue(ij+u_right,l)*le(ij+u_right)  +  &
+                             ne(ij,rup)*ue(ij+u_rup,l)*le(ij+u_rup)        +  &  
+                             ne(ij,lup)*ue(ij+u_lup,l)*le(ij+u_lup)        +  &  
+                             ne(ij,left)*ue(ij+u_left,l)*le(ij+u_left)     +  &  
+                             ne(ij,ldown)*ue(ij+u_ldown,l)*le(ij+u_ldown)  +  &  
+                             ne(ij,rdown)*ue(ij+u_rdown,l)*le(ij+u_rdown))
+      ENDDO
+    ENDDO
+    
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin,ij_end
+ 
+          gradivu_e(ij+u_right,l)=-1/de(ij+u_right)*(ne(ij,right)*divu_i(ij,l)+ ne(ij+t_right,left)*divu_i(ij+t_right,l) )       
+
+          gradivu_e(ij+u_lup,l)=-1/de(ij+u_lup)*(ne(ij,lup)*divu_i(ij,l)+ ne(ij+t_lup,rdown)*divu_i(ij+t_lup,l))       
+    
+          gradivu_e(ij+u_ldown,l)=-1/de(ij+u_ldown)*(ne(ij,ldown)*divu_i(ij,l)+ne(ij+t_ldown,rup)*divu_i(ij+t_ldown,l) )
+
+      ENDDO
+    ENDDO
+
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin,ij_end
+          gradivu_e(ij+u_right,l)=-gradivu_e(ij+u_right,l)*cgraddiv
+          gradivu_e(ij+u_lup,l)=-gradivu_e(ij+u_lup,l)*cgraddiv
+          gradivu_e(ij+u_ldown,l)=-gradivu_e(ij+u_ldown,l)*cgraddiv
+      ENDDO
+    ENDDO
+
+   
+  END SUBROUTINE compute_gradiv
+  
+  SUBROUTINE compute_divgrad(theta,divgrad_i,llb,lle)
+  USE icosa
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)     :: llb
+    INTEGER,INTENT(IN)     :: lle
+    REAL(rstd),INTENT(IN)  :: theta(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: divgrad_i(iim*jjm,llm)
+    REAL(rstd)  :: grad_e(3*iim*jjm,llb:lle)
+
+    INTEGER :: ij,l
+
+       
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin_ext,ij_end_ext
+ 
+          grad_e(ij+u_right,l)=-1/de(ij+u_right)*(ne(ij,right)*theta(ij,l)+ ne(ij+t_right,left)*theta(ij+t_right,l) )        
+
+          grad_e(ij+u_lup,l)=-1/de(ij+u_lup)*(ne(ij,lup)*theta(ij,l)+ ne(ij+t_lup,rdown)*theta(ij+t_lup,l ))       
+    
+          grad_e(ij+u_ldown,l)=-1/de(ij+u_ldown)*(ne(ij,ldown)*theta(ij,l)+ne(ij+t_ldown,rup)*theta(ij+t_ldown,l) )
+
+      ENDDO
+    ENDDO
+    
+    
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin,ij_end
+
+          divgrad_i(ij,l)=1./Ai(ij)*(ne(ij,right)*grad_e(ij+u_right,l)*le(ij+u_right)  +  &
+                             ne(ij,rup)*grad_e(ij+u_rup,l)*le(ij+u_rup)              +  &  
+                             ne(ij,lup)*grad_e(ij+u_lup,l)*le(ij+u_lup)              +  &  
+                             ne(ij,left)*grad_e(ij+u_left,l)*le(ij+u_left)           +  &  
+                             ne(ij,ldown)*grad_e(ij+u_ldown,l)*le(ij+u_ldown)        +  &  
+                             ne(ij,rdown)*grad_e(ij+u_rdown,l)*le(ij+u_rdown))
+      ENDDO
+    ENDDO
+   
+    DO l=llb,lle
+      DO ij=ij_begin,ij_end
+          divgrad_i(ij,l)=-divgrad_i(ij,l)*cdivgrad
+      ENDDO
+    ENDDO
+
+  END SUBROUTINE compute_divgrad
+
+    
+  SUBROUTINE compute_gradrot(ue,gradrot_e,llb,lle)
+  USE icosa
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)     :: llb
+    INTEGER,INTENT(IN)     :: lle
+    REAL(rstd),INTENT(IN)  :: ue(iim*3*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: gradrot_e(iim*3*jjm,llm)
+    REAL(rstd) :: rot_v(2*iim*jjm,llb:lle)
+
+    INTEGER :: ij,l
+     
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin_ext,ij_end_ext
+        
+          rot_v(ij+z_up,l)= 1./Av(ij+z_up)*(  ne(ij,rup)*ue(ij+u_rup,l)*de(ij+u_rup)                     &
+                                + ne(ij+t_rup,left)*ue(ij+t_rup+u_left,l)*de(ij+t_rup+u_left)          &
+                                - ne(ij,lup)*ue(ij+u_lup,l)*de(ij+u_lup) ) 
+                              
+          rot_v(ij+z_down,l) = 1./Av(ij+z_down)*( ne(ij,ldown)*ue(ij+u_ldown,l)*de(ij+u_ldown)                 &
+                                     + ne(ij+t_ldown,right)*ue(ij+t_ldown+u_right,l)*de(ij+t_ldown+u_right)  &
+                                     - ne(ij,rdown)*ue(ij+u_rdown,l)*de(ij+u_rdown) )
+  
+      ENDDO
+    ENDDO                              
+  
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin,ij_end
+  
+          gradrot_e(ij+u_right,l)=1/le(ij+u_right)*ne(ij,right)*(rot_v(ij+z_rdown,l)-rot_v(ij+z_rup,l)) 
+         
+          gradrot_e(ij+u_lup,l)=1/le(ij+u_lup)*ne(ij,lup)*(rot_v(ij+z_up,l)-rot_v(ij+z_lup,l)) 
+        
+          gradrot_e(ij+u_ldown,l)=1/le(ij+u_ldown)*ne(ij,ldown)*(rot_v(ij+z_ldown,l)-rot_v(ij+z_down,l))
+        
+      ENDDO
+    ENDDO
+
+    DO l=llb,lle
+!$SIMD
+      DO ij=ij_begin,ij_end
+    
+          gradrot_e(ij+u_right,l)=-gradrot_e(ij+u_right,l)*cgradrot       
+          gradrot_e(ij+u_lup,l)=-gradrot_e(ij+u_lup,l)*cgradrot
+          gradrot_e(ij+u_ldown,l)=-gradrot_e(ij+u_ldown,l)*cgradrot
+        
+      ENDDO
+    ENDDO  
+   
+  END SUBROUTINE compute_gradrot
+
+
+END MODULE dissip_gcm_mod
+       
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert.f90	(revision 329)
@@ -0,0 +1,255 @@
+MODULE disvert_mod
+  USE icosa
+  REAL(rstd), SAVE, POINTER :: ap(:)
+!$OMP THREADPRIVATE(ap) 
+  REAL(rstd), SAVE, POINTER :: bp(:)
+!$OMP THREADPRIVATE(bp) 
+  REAL(rstd), SAVE, POINTER :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs) 
+  REAL(rstd), SAVE, POINTER :: mass_al(:), mass_bl(:), mass_ak(:), mass_bk(:), mass_dak(:), mass_dbk(:)
+!$OMP THREADPRIVATE(mass_al, mass_bl, mass_ak, mass_bk, mass_dak, mass_dbk) 
+
+  REAL(rstd) :: ptop ! pressure at top of atmosphere l=llm+1
+!$OMP THREADPRIVATE(ptop) 
+  ! vertical coordinate : Lagrangian or mass-based
+  INTEGER, SAVE :: caldyn_eta
+!$OMP THREADPRIVATE(caldyn_eta) 
+  INTEGER, PARAMETER :: eta_mass=1, eta_lag=2
+  LOGICAL,SAVE :: ap_bp_present
+!$OMP THREADPRIVATE(ap_bp_present) 
+
+CONTAINS
+
+  SUBROUTINE init_disvert
+  USE disvert_std_mod, ONLY: ap_std=>ap, bp_std=>bp, presnivs_std=>presnivs, init_disvert_std=>init_disvert
+  USE disvert_apbp_mod, ONLY: ap_apbp=>ap, bp_apbp=>bp, presnivs_apbp=>presnivs, init_disvert_apbp=>init_disvert
+  USE disvert_ncar_mod, ONLY: ap_ncar=>ap, bp_ncar=>bp, presnivs_ncar=>presnivs, init_disvert_ncar=>init_disvert
+  USE disvert_ncarl30_mod, ONLY: ap_ncarl30=>ap, bp_ncarl30=>bp, presnivs_ncarl30=>presnivs, init_disvert_ncarl30=>init_disvert
+  USE disvert_dcmip31_mod, ONLY: ap_dcmip31=>ap, bp_dcmip31=>bp, presnivs_dcmip31=>presnivs, init_disvert_dcmip31=>init_disvert
+  USE disvert_dcmip200_mod, ONLY: ap_dcmip200=>ap, bp_dcmip200=>bp, presnivs_dcmip200=>presnivs, init_disvert_dcmip200=>init_disvert
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+    CHARACTER(len=255) :: def
+    INTEGER :: l
+
+    def='eta_mass'
+    CALL getin('caldyn_eta',def)
+    SELECT CASE(TRIM(def))
+    CASE('eta_mass')
+       caldyn_eta=eta_mass
+    CASE('eta_lag')
+       caldyn_eta=eta_lag
+    CASE DEFAULT
+       IF (is_mpi_root) PRINT *,'Bad selector for variable caldyn_eta : <', TRIM(def),'> options are <eta_mass>, <eta_lag>'
+       STOP
+    END SELECT
+    IF (is_mpi_root) PRINT *, 'caldyn_eta=',TRIM(def), caldyn_eta, eta_lag, eta_mass
+
+    def='std'
+    ap_bp_present=.TRUE.
+    CALL getin("disvert",def)
+
+    SELECT CASE (TRIM(def))
+      CASE('none')
+         IF(caldyn_eta/=eta_lag) THEN
+            IF(is_mpi_root) PRINT *,'disvert_type=none must be used with caldyn_eta=eta_lag'
+            STOP
+         END IF
+         ap_bp_present=.FALSE.
+      CASE('std')
+    
+        CALL init_disvert_std
+        ap=>ap_std
+        bp=>bp_std
+        presnivs=>presnivs_std
+      
+      CASE('read_apbp')
+    
+        CALL init_disvert_apbp
+        ap=>ap_apbp
+        bp=>bp_apbp
+        presnivs=>presnivs_apbp
+        
+      CASE ('ncar')
+
+        CALL init_disvert_ncar
+        ap=>ap_ncar
+        bp=>bp_ncar
+        presnivs=>presnivs_ncar
+
+      CASE ('dcmip31')
+
+        CALL init_disvert_dcmip31
+        ap=>ap_dcmip31
+        bp=>bp_dcmip31
+        presnivs=>presnivs_dcmip31
+
+      CASE ('dcmip200')
+
+        CALL init_disvert_dcmip200
+        ap=>ap_dcmip200
+        bp=>bp_dcmip200
+        presnivs=>presnivs_dcmip200
+
+      CASE ('ncarl30')
+
+        CALL init_disvert_ncarl30
+        ap=>ap_ncarl30
+        bp=>bp_ncarl30
+        presnivs=>presnivs_ncarl30
+      CASE default
+        IF (is_mpi_root) PRINT*,'Bad selector for variable disvert : <', TRIM(def),"> options are <std>, <ncar>, <ncarl30>" 
+        STOP
+        
+    END SELECT
+
+    IF(ap_bp_present) THEN
+       ! Convert from pressure coordinate to mass coordinate
+       ! pk = ap(k) + bp(k)*ps(ij) = ptop + g*( mass_ak(k) + mass_bk(k)*ms(ij) )
+       ptop = ap(llm+1)
+       ALLOCATE(mass_al(llm+1))
+       ALLOCATE(mass_bl(llm+1))
+       ALLOCATE(mass_ak(llm))
+       ALLOCATE(mass_bk(llm))
+       ALLOCATE(mass_dak(llm))
+       ALLOCATE(mass_dbk(llm))
+
+       ! FIXME : leave ps for the moment ; change ps to ms later
+       DO l=1,llm+1
+          !       mass_al(l) = (ap(l)-ptop)/g
+          !       mass_bl(l) = bp(l)/g
+          mass_al(l) = (ap(l)-ptop)
+          mass_bl(l) = bp(l)
+       END DO
+       DO l=1,llm
+          mass_ak(l) = .5*(mass_al(l)+mass_al(l+1))
+          mass_bk(l) = .5*(mass_bl(l)+mass_bl(l+1))
+          mass_dak(l) = mass_al(l)-mass_al(l+1)  ! >0
+          mass_dbk(l) = mass_bl(l)-mass_bl(l+1)  ! >0
+       END DO
+    END IF
+
+  END SUBROUTINE init_disvert  
+  
+  SUBROUTINE compute_rhodz(comp, ps, rhodz)
+    USE icosa
+    USE omp_para
+    LOGICAL, INTENT(IN) :: comp ! .TRUE. to compute, .FALSE. to check
+    REAL(rstd), INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd), INTENT(INOUT) :: rhodz(iim*jjm,llm)
+    REAL(rstd) :: m, err
+    INTEGER :: l,i,j,ij,dd
+    err=0.
+
+    IF(comp) THEN
+       dd=1
+    ELSE
+       dd=0
+    END IF
+
+    DO l = ll_begin, ll_end
+       DO j=jj_begin-dd,jj_end+dd
+          DO i=ii_begin-dd,ii_end+dd
+             ij=(j-1)*iim+i
+             m = ( ap(l) - ap(l+1) + (bp(l)-bp(l+1))*ps(ij) )/g 
+             IF(comp) THEN
+                rhodz(ij,l) = m
+             ELSE
+                err = MAX(err,abs(m-rhodz(ij,l)))
+             END IF
+          ENDDO
+       ENDDO
+    ENDDO
+
+    IF(.NOT. comp) THEN
+       IF(err>1e-10) THEN
+          PRINT *, 'Discrepancy between ps and rhodz detected', err
+          STOP
+       ELSE
+!          PRINT *, 'No discrepancy between ps and rhodz detected'
+       END IF
+    END IF
+
+  END SUBROUTINE compute_rhodz
+
+ 
+  SUBROUTINE write_apbp
+  USE icosa
+  USE netcdf_mod
+  IMPLICIT NONE
+    REAL(rstd) :: val(llm)
+    INTEGER :: status
+    INTEGER :: lev,ilev
+    INTEGER :: ncid,levid,ilevid,hyaiid,hybiid,hyamid,hybmid,P0id
+    INTEGER :: l
+
+!$OMP BARRIER
+!$OMP MASTER    
+    status = NF90_CREATE('apbp.nc', NF90_CLOBBER, ncid)
+    status = NF90_DEF_DIM(ncid,'lev',llm,lev)
+    status = NF90_DEF_DIM(ncid,'ilev',llm+1,ilev)
+    
+    status = NF90_DEF_VAR(ncid,'lev',NF90_DOUBLE,(/ lev /),levid)
+    status = NF90_PUT_ATT(ncid,levid,"long_name","hybrid level at midpoints (1000*(A+B))")
+    status = NF90_PUT_ATT(ncid,levid,"units","Pa")
+    status = NF90_PUT_ATT(ncid,levid,"positive","up")
+    status = NF90_PUT_ATT(ncid,levid,"standard_name","atmosphere_hybrid_sigma_pressure_coordinate")
+    status = NF90_PUT_ATT(ncid,levid,"formula_terms","a: hyam b: hybm p0: P0 ps: PS")
+
+    status = NF90_DEF_VAR(ncid,'ilev',NF90_DOUBLE,(/ ilev /),ilevid)
+    status = NF90_PUT_ATT(ncid,ilevid,"long_name","hybrid level at interfaces (1000*(A+B))")
+    status = NF90_PUT_ATT(ncid,ilevid,"units","Pa")
+    status = NF90_PUT_ATT(ncid,ilevid,"positive","up")
+    status = NF90_PUT_ATT(ncid,ilevid,"standard_name","atmosphere_hybrid_sigma_pressure_coordinate")
+    status = NF90_PUT_ATT(ncid,ilevid,"formula_terms","a: hyai b: hybi p0: P0 ps: PS")
+   
+    status = NF90_DEF_VAR(ncid,'hyai',NF90_DOUBLE,(/ ilev /),hyaiid)
+    status = NF90_PUT_ATT(ncid,hyaiid,"long_name","hybrid A coefficient at layer interfaces")
+
+    status = NF90_DEF_VAR(ncid,'hybi',NF90_DOUBLE,(/ ilev /),hybiid)
+    status = NF90_PUT_ATT(ncid,hybiid,"long_name","hybrid B coefficient at layer interfaces")
+
+    status = NF90_DEF_VAR(ncid,'hyam',NF90_DOUBLE,(/ lev /),hyamid)
+    status = NF90_PUT_ATT(ncid,hyamid,"long_name","hybrid A coefficient at midpoint interfaces")
+
+    status = NF90_DEF_VAR(ncid,'hybm',NF90_DOUBLE,(/ lev /),hybmid)
+    status = NF90_PUT_ATT(ncid,hybmid,"long_name","hybrid B coefficient at midpoint interfaces")
+    
+    status = NF90_DEF_VAR(ncid,'P0',NF90_DOUBLE,varid=P0id)
+
+    status = NF90_ENDDEF(ncid)   
+
+    IF(ap_bp_present) THEN
+    
+    status=NF90_PUT_VAR(ncid,ilevid, ap(:)+bp(:)*Preff)
+    
+    DO l=1,llm
+      val(l)= 0.5*(ap(l+1)+ap(l)+Preff*(bp(l)+bp(l+1)))
+    ENDDO
+    
+    status=NF90_PUT_VAR(ncid,levid, val)
+
+    status=NF90_PUT_VAR(ncid,hyaiid, ap(:)/Preff)
+    status=NF90_PUT_VAR(ncid,hybiid, bp(:))
+    
+    DO l=1,llm
+      val(l)= 0.5*(ap(l+1)+ap(l))
+    ENDDO
+    status=NF90_PUT_VAR(ncid,hyamid, val(:)/Preff)
+   
+    DO l=1,llm
+      val(l)= 0.5*(bp(l+1)+bp(l))
+    ENDDO
+    status=NF90_PUT_VAR(ncid,hybmid, val(:))
+ 
+    status=NF90_PUT_VAR(ncid,P0id, Preff)
+   
+    END IF
+
+    status=NF90_CLOSE(ncid)
+!$OMP END MASTER
+!$OMP BARRIER
+  END SUBROUTINE write_apbp
+
+END MODULE disvert_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_apbp.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_apbp.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_apbp.f90	(revision 329)
@@ -0,0 +1,88 @@
+MODULE disvert_apbp_mod
+  USE icosa
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: ap(:)
+!$OMP THREADPRIVATE(ap)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: bp(:)
+!$OMP THREADPRIVATE(bp)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs)
+
+CONTAINS
+
+  SUBROUTINE init_disvert
+!  USE icosa
+  IMPLICIT NONE
+  
+    ALLOCATE(ap(llm+1))
+    ALLOCATE(bp(llm+1))
+    ALLOCATE(presnivs(llm))
+
+    CALL disvert(ap,bp,presnivs)    
+
+  END SUBROUTINE init_disvert  
+
+
+  SUBROUTINE disvert(ap,bp,presnivs)
+!  USE icosa
+  USE mpipara, ONLY: is_mpi_root
+  USE omp_para, ONLY: omp_in_parallel
+  USE transfert_omp_mod, ONLY: bcast_omp
+  USE free_unit_mod, ONLY : free_unit
+  IMPLICIT NONE
+  REAL(rstd),INTENT(OUT) :: ap(:)
+  REAL(rstd),INTENT(OUT) :: bp(:)
+  REAL(rstd),INTENT(OUT) :: presnivs(:)
+  INTEGER :: unit
+  CHARACTER(len=255) :: filename
+  INTEGER :: l,ok
+  
+    filename="apbp.txt" !file to read
+    ! but users may want to use some other file name
+    CALL getin('read_apbp_file',filename)
+    
+!$OMP MASTER
+    unit=free_unit()
+    OPEN(unit,file=filename,status="old",action="read",iostat=ok)
+    IF (ok/=0) THEN
+      WRITE(*,*) "disvert_ap_bp error: input file ",trim(filename)," not found!"
+      CALL ABORT
+    ENDIF
+    ! read in ap() and b() line by line, starting from surface up
+    ! to model top
+    DO l=1,llm+1
+      READ(unit,fmt=*,iostat=ok) ap(l),bp(l)
+      IF (ok/=0) THEN
+        WRITE(*,*) "disvert_ap_bp error: failed reading ap(l) and bp(l) for l=",l
+        CALL ABORT
+      ENDIF
+    ENDDO
+    
+    CLOSE(unit)
+!$OMP END MASTER
+    IF (omp_in_parallel()) THEN
+      CALL bcast_omp(ap)
+      CALL bcast_omp(bp)
+    ENDIF
+    
+    ! build presnivs(), approximative mid-layer pressures
+    DO l=1,llm
+      presnivs(l)=0.5*(ap(l)+bp(l)*preff+ap(l+1)+bp(l+1)*preff)
+    ENDDO
+    
+    ! tell the world about it
+    IF (is_mpi_root) THEN
+!$OMP MASTER
+      WRITE(*,*) "ap()=",ap
+      WRITE(*,*) "bp()=",bp
+      WRITE(*,*) "Approximative mid-layer pressure, assuming a surface pressure preff=",preff," Pa"
+      WRITE(*,*) "and approximative mid-layer height, assuming an atmospheric scale height of ",scale_height/1000," (km)"
+      DO l=1,llm
+        WRITE(*,*) 'PRESNIVS(',l,')=',presnivs(l),'  Z ~ ',log(preff/presnivs(l))*scale_height/1000,       &
+                   ' DZ ~ ',scale_height/1000*log((ap(l)+bp(l)*preff)/ max(ap(l+1)+bp(l+1)*preff,1.e-10))
+      ENDDO
+!$OMP END MASTER
+    ENDIF
+  
+  END SUBROUTINE disvert
+  
+END MODULE disvert_apbp_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_dcmip200.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_dcmip200.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_dcmip200.f90	(revision 329)
@@ -0,0 +1,71 @@
+  MODULE disvert_dcmip200_mod
+  USE icosa
+ 
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: ap(:)
+!$OMP THREADPRIVATE(ap)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: bp(:)
+!$OMP THREADPRIVATE(bp)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs)
+
+CONTAINS
+!=========================================================================
+
+  SUBROUTINE init_disvert
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+  
+    ALLOCATE(ap(llm+1))
+    ALLOCATE(bp(llm+1))
+    ALLOCATE(presnivs(llm))
+    
+    CALL disvert(ap,bp,presnivs)    
+
+  END SUBROUTINE init_disvert  
+
+  SUBROUTINE disvert(ap,bp,presnivs)
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+  REAL(rstd),INTENT(OUT) :: ap(:)
+  REAL(rstd),INTENT(OUT) :: bp(:)
+  REAL(rstd),INTENT(OUT) :: presnivs(:)
+  ! reads from run.def : ncar_dz, ncar_T0, ncar_p0, ncar_disvert_c
+  INTEGER :: l,cindx
+  REAL(rstd) ::  eta_top, eta
+  REAL(rstd),PARAMETER :: N=0.01         ! Brunt-Vaisala frequency (s-1)
+  REAL(rstd),PARAMETER :: T0=300.       ! Surface temperature at the equator (K)
+  REAL(rstd) :: Rd       
+  REAL(rstd), PARAMETER :: Gamma=0.0065       
+
+  Rd=cpp*kappa
+  ncar_dz=400 ; CALL getin('ncar_dz',ncar_dz);
+  cindx=1 ; CALL getin('ncar_disvert_c',cindx)
+
+  
+    
+  eta_top = (1-Gamma/T0*llm*ncar_dz)**(g/(Rd*Gamma))  
+  do l = 1,llm+1
+     eta = (1-Gamma/T0*(l-1)*ncar_dz)**(g/(Rd*Gamma))
+     PRINT *,'eta ->', eta
+     bp(l) = ((eta - eta_top)/(1 - eta_top))**cindx
+     ap(l) = preff * ( eta - bp(l) )
+  ENDDO
+  bp(1)=1.
+  ap(1)=0.
+  bp(llm+1) = 0
+  
+  DO l = 1, llm
+     presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+  ENDDO
+
+!$OMP MASTER  
+  IF (is_mpi_root) PRINT *, 'Vertical placement of model levels according to DCMIP Appendix E.3'
+  IF (is_mpi_root) PRINT *, 'Parameters : ncar_dz=', ncar_dz, '  ncar_p0=',ncar_p0, '  ncar_disvert_c=',cindx
+  IF (is_mpi_root) PRINT *, 'Isothermal amtosphere with ncar_T0=',ncar_T0 
+!$OMP END MASTER  
+
+END SUBROUTINE disvert
+
+END  MODULE disvert_dcmip200_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_dcmip3.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_dcmip3.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_dcmip3.f90	(revision 329)
@@ -0,0 +1,70 @@
+  MODULE disvert_dcmip31_mod
+  USE icosa
+ 
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: ap(:)
+!$OMP THREADPRIVATE(ap)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: bp(:)
+!$OMP THREADPRIVATE(bp)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs)
+
+CONTAINS
+!=========================================================================
+
+  SUBROUTINE init_disvert
+  USE icosa
+  IMPLICIT NONE
+  
+    ALLOCATE(ap(llm+1))
+    ALLOCATE(bp(llm+1))
+    ALLOCATE(presnivs(llm))
+    
+    CALL disvert(ap,bp,presnivs)    
+
+  END SUBROUTINE init_disvert  
+
+  SUBROUTINE disvert(ap,bp,presnivs)
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+  REAL(rstd),INTENT(OUT) :: ap(:)
+  REAL(rstd),INTENT(OUT) :: bp(:)
+  REAL(rstd),INTENT(OUT) :: presnivs(:)
+  ! reads from run.def : ncar_dz, ncar_T0, ncar_p0, ncar_disvert_c
+  INTEGER :: l,cindx
+  REAL(rstd) :: GG, eta_top, eta
+  REAL(rstd),PARAMETER :: N=0.01         ! Brunt-Vaisala frequency (s-1)
+  REAL(rstd),PARAMETER :: Teq=300.       ! Surface temperature at the equator (K)
+  REAL(rstd),PARAMETER :: Peq=1e5        ! Reference surface pressure at the equator (hPa)
+
+  ncar_dz=400 ; CALL getin('ncar_dz',ncar_dz);
+  cindx=1 ; CALL getin('ncar_disvert_c',cindx)
+
+  GG=(g/N)**2/cpp
+  
+  eta_top = (GG/Teq*exp(-N**2*llm*ncar_dz/g)+1-GG/Teq)**(1./kappa)
+  IF (is_mpi_root) PRINT *,'eta_top ->', eta_top
+  do l = 1,llm+1
+     eta = (GG/Teq*exp(-N**2*(l-1)*ncar_dz/g)+1-GG/Teq)**(1./kappa)
+     IF (is_mpi_root) PRINT *,'eta ->', eta
+     bp(l) = ((eta - eta_top)/(1 - eta_top))**cindx
+     ap(l) = preff * ( eta - bp(l) )
+  ENDDO
+  IF (is_mpi_root) PRINT *,'eta ->', eta
+  bp(1)=1.
+  ap(1)=0.
+  bp(llm+1) = 0
+  
+  DO l = 1, llm
+     presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+  ENDDO
+
+!$OMP MASTER  
+  IF (is_mpi_root) PRINT *, 'Vertical placement of model levels according to DCMIP Appendix E.3'
+  IF (is_mpi_root) PRINT *, 'Parameters : ncar_dz=', ncar_dz, '  ncar_p0=',ncar_p0, '  ncar_disvert_c=',cindx
+  IF (is_mpi_root) PRINT *, 'Isothermal amtosphere with ncar_T0=',ncar_T0 
+!$OMP END MASTER  
+
+END SUBROUTINE disvert
+
+END  MODULE disvert_dcmip31_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_ncar.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_ncar.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_ncar.f90	(revision 329)
@@ -0,0 +1,71 @@
+  MODULE disvert_ncar_mod
+  USE icosa
+ 
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: ap(:)
+!$OMP THREADPRIVATE(ap)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: bp(:)
+!$OMP THREADPRIVATE(bp)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs)
+
+CONTAINS
+!=========================================================================
+
+  SUBROUTINE init_disvert
+  USE icosa
+  IMPLICIT NONE
+  
+    ALLOCATE(ap(llm+1))
+    ALLOCATE(bp(llm+1))
+    ALLOCATE(presnivs(llm))
+    
+    CALL disvert(ap,bp,presnivs)    
+
+  END SUBROUTINE init_disvert  
+
+  SUBROUTINE disvert(ap,bp,presnivs)
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+  REAL(rstd),INTENT(OUT) :: ap(:)
+  REAL(rstd),INTENT(OUT) :: bp(:)
+  REAL(rstd),INTENT(OUT) :: presnivs(:)
+  ! reads from run.def : ncar_dz, ncar_T0, ncar_p0, ncar_disvert_c
+  INTEGER :: l,cindx
+  REAL(rstd) :: H, eta_top, eta
+
+  ncar_dz=400 ; CALL getin('ncar_dz',ncar_dz);
+
+! SELECT CASE( 
+! pressure profile depends on test case
+! coded here for 1-x (transport)
+
+  ncar_T0=300; CALL getin('ncar_T0',ncar_T0)
+  ncar_p0=1e5; CALL getin('ncar_p0',ncar_p0)
+  cindx=1 ; CALL getin('ncar_disvert_c',cindx)
+
+  H = ncar_T0*cpp*kappa/g ! height scale R.T0/g with R=cpp*kappa
+  eta_top = exp(-llm*ncar_dz/H)
+ 
+  do l = 1,llm+1
+     eta = exp(-(l-1)*ncar_dz/H)
+     bp(l) = ((eta - eta_top)/(1 - eta_top))**cindx
+     ap(l) = ncar_p0 * ( eta - bp(l) )
+  ENDDO
+  bp(1)=1.
+  ap(1)=0.
+  bp(llm+1) = 0
+  
+  DO l = 1, llm
+     presnivs(l) = 0.5 *( ap(l)+bp(l)*ncar_p0 + ap(l+1)+bp(l+1)*ncar_p0 )
+  ENDDO
+
+!$OMP MASTER  
+  IF (is_mpi_root) PRINT *, 'Vertical placement of model levels according to DCMIP Appendix E.3'
+  IF (is_mpi_root) PRINT *, 'Parameters : ncar_dz=', ncar_dz, '  ncar_p0=',ncar_p0, '  ncar_disvert_c=',cindx
+  PRINT *, 'Isothermal amtosphere with ncar_T0=',ncar_T0 
+!$OMP END MASTER  
+
+END SUBROUTINE disvert
+
+END  MODULE disvert_ncar_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_ncarl30.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_ncarl30.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_ncarl30.f90	(revision 329)
@@ -0,0 +1,113 @@
+MODULE disvert_ncarl30_mod
+  USE icosa
+
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: ap(:)
+!$OMP THREADPRIVATE(ap)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: bp(:)
+!$OMP THREADPRIVATE(bp)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs)
+
+CONTAINS
+
+  SUBROUTINE init_disvert
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+  
+    IF (llm/=30) STOP 'ERROR, the initialisation of this vertical discretisation must be done with 30 levels'
+    ALLOCATE(ap(llm+1))
+    ALLOCATE(bp(llm+1))
+    ALLOCATE(presnivs(llm))
+
+    CALL disvert(ap,bp,presnivs)    
+
+  END SUBROUTINE init_disvert  
+
+
+  SUBROUTINE disvert(ap,bp,presnivs)
+  USE icosa
+  USE mpipara
+  IMPLICIT NONE
+  REAL(rstd),INTENT(OUT) :: ap(:)
+  REAL(rstd),INTENT(OUT) :: bp(:)
+  REAL(rstd),INTENT(OUT) :: presnivs(:)
+  INTEGER :: l
+  REAL(rstd) :: a(31)=(/ 0.00225523952394724, &
+                         0.00503169186413288, &
+                         0.0101579474285245 , &
+                         0.0185553170740604 , &
+                         0.0306691229343414 , &
+                         0.0458674766123295 , &
+                         0.0633234828710556 , &
+                         0.0807014182209969 , &
+                         0.0949410423636436 , &
+                         0.11169321089983   , &
+                         0.131401270627975  , &
+                         0.154586806893349  , &
+                         0.181863352656364  , &
+                         0.17459799349308   , &
+                         0.166050657629967  , &
+                         0.155995160341263  , &
+                         0.14416541159153   , &
+                         0.130248308181763  , &
+                         0.113875567913055  , &
+                         0.0946138575673103 , &
+                         0.0753444507718086 , &
+                         0.0576589405536652 , &
+                         0.0427346378564835 , &
+                         0.0316426791250706 , &
+                         0.0252212174236774 , &
+                         0.0191967375576496 , &
+                         0.0136180268600583 , &
+                         0.00853108894079924, &
+                         0.00397881818935275, &
+                         0.                 , &
+                         0. /)  
+                         
+  REAL(rstd) :: b(31)=(/ 0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.                 , &
+                         0.0393548272550106 , &
+                         0.0856537595391273 , &
+                         0.140122056007385  , &
+                         0.204201176762581  , &
+                         0.279586911201477  , &
+                         0.368274360895157  , &
+                         0.47261056303978   , &
+                         0.576988518238068  , &
+                         0.672786951065063  , &
+                         0.753628432750702  , &
+                         0.813710987567902  , &
+                         0.848494648933411  , &
+                         0.881127893924713  , &
+                         0.911346435546875  , &
+                         0.938901245594025  , &
+                         0.963559806346893  , &
+                         0.985112190246582  , &
+                         1. /)                         
+                    
+    ap(:)=a(31:1:-1)*preff
+    bp(:)=b(31:1:-1) 
+    DO l = 1, llm
+      presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+
+!$OMP MASTER  
+     IF (is_mpi_root)  PRINT*, 'PRESNIVS(',l,')=',presnivs(l),'  Z ~ ',log(preff/presnivs(l))*8.,       &
+                               ' DZ ~ ',8.*log((ap(l)+bp(l)*preff)/ max(ap(l+1)+bp(l+1)*preff,1.e-10))
+!$OMP END MASTER
+    ENDDO
+  
+  END SUBROUTINE disvert
+  
+END MODULE disvert_ncarl30_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_std.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_std.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/disvert_std.f90	(revision 329)
@@ -0,0 +1,82 @@
+MODULE disvert_std_mod
+  USE icosa
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: ap(:)
+!$OMP THREADPRIVATE(ap)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: bp(:)
+!$OMP THREADPRIVATE(bp)
+  REAL(rstd), SAVE, ALLOCATABLE,TARGET :: presnivs(:)
+!$OMP THREADPRIVATE(presnivs)
+
+CONTAINS
+
+  SUBROUTINE init_disvert
+  USE icosa
+  IMPLICIT NONE
+  
+    ALLOCATE(ap(llm+1))
+    ALLOCATE(bp(llm+1))
+    ALLOCATE(presnivs(llm))
+
+    CALL disvert(ap,bp,presnivs)    
+
+  END SUBROUTINE init_disvert  
+
+
+  SUBROUTINE disvert(ap,bp,presnivs)
+  USE icosa
+  USE mpipara
+  USE earth_const
+  IMPLICIT NONE
+  REAL(rstd),INTENT(OUT) :: ap(:)
+  REAL(rstd),INTENT(OUT) :: bp(:)
+  REAL(rstd),INTENT(OUT) :: presnivs(:)
+  
+  REAL(rstd) :: dsig(llm)
+  REAL(rstd) :: sig(llm+1)
+  REAL(rstd) :: snorm
+  INTEGER :: l
+  
+    snorm  = 0.
+    DO l = 1, llm
+      dsig(l) = 1.0 + 7.0 * SIN( Pi*(l-0.5)/(llm+1) )**2
+      snorm = snorm + dsig(l)
+    ENDDO    
+    
+    DO l = 1, llm
+      dsig(l) = dsig(l)/snorm
+    ENDDO
+
+    sig(llm+1) = 0.
+    DO l = llm, 1, -1
+      sig(l) = sig(l+1) + dsig(l)
+    ENDDO
+
+    bp(llm+1) =   0.
+    DO l = 1, llm
+      bp(l) = EXP( 1. -1./( sig(l)*sig(l)) )
+      ap(l) = pa * ( sig(l) - bp(l) )
+    ENDDO
+    bp(1)=1.
+    ap(1)=0.
+    ap(llm+1) = pa * ( sig(llm+1) - bp(llm+1) )
+    DO l = 1, llm
+      presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+    ENDDO
+    
+    ! tell the world about it
+    IF (is_mpi_root) THEN
+!$OMP MASTER
+      WRITE(*,*) "ap()=",ap
+      WRITE(*,*) "bp()=",bp
+      WRITE(*,*) "Approximative mid-layer pressure, assuming a surface pressure preff=",preff," Pa"
+      WRITE(*,*) "and approximative mid-layer height, assuming an atmospheric scale height of ",scale_height/1000," (km)"
+      DO l=1,llm
+        WRITE(*,*) 'PRESNIVS(',l,')=',presnivs(l),'  Z ~ ',log(preff/presnivs(l))*scale_height/1000,       &
+                   ' DZ ~ ',scale_height/1000*log((ap(l)+bp(l)*preff)/ max(ap(l+1)+bp(l+1)*preff,1.e-10))
+      ENDDO
+!$OMP END MASTER
+    ENDIF
+  
+  END SUBROUTINE disvert
+  
+END MODULE disvert_std_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/domain.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/domain.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/domain.f90	(revision 329)
@@ -0,0 +1,483 @@
+MODULE domain_mod
+  USE domain_param
+
+  TYPE t_domain
+    INTEGER :: face
+    INTEGER :: iim
+    INTEGER :: jjm
+    INTEGER :: ii_begin
+    INTEGER :: jj_begin
+    INTEGER :: ii_end
+    INTEGER :: jj_end
+    INTEGER :: ii_nb
+    INTEGER :: jj_nb
+    INTEGER :: ii_begin_glo
+    INTEGER :: jj_begin_glo
+    INTEGER :: ii_end_glo
+    INTEGER :: jj_end_glo
+    INTEGER,POINTER  :: assign_domain(:,:)
+    INTEGER,POINTER  :: assign_cell_glo(:,:)
+    INTEGER,POINTER  :: assign_i(:,:)
+    INTEGER,POINTER  :: assign_j(:,:)
+    INTEGER,POINTER  :: edge_assign_domain(:,:,:)
+    INTEGER,POINTER  :: edge_assign_i(:,:,:)
+    INTEGER,POINTER  :: edge_assign_j(:,:,:)
+    INTEGER,POINTER  :: edge_assign_pos(:,:,:)
+    INTEGER,POINTER  :: edge_assign_sign(:,:,:)
+    REAL,POINTER     :: xyz(:,:,:)
+    REAL,POINTER     :: neighbour(:,:,:,:)
+    INTEGER,POINTER  :: delta(:,:)
+    REAL,POINTER     :: vertex(:,:,:,:)
+    LOGICAL,POINTER  :: own(:,:)
+    INTEGER,POINTER  :: ne(:,:,:)
+    
+    INTEGER :: t_right
+    INTEGER :: t_rup
+    INTEGER :: t_lup
+    INTEGER :: t_left
+    INTEGER :: t_ldown
+    INTEGER :: t_rdown
+
+    INTEGER :: u_right
+    INTEGER :: u_rup
+    INTEGER :: u_lup
+    INTEGER :: u_left
+    INTEGER :: u_ldown
+    INTEGER :: u_rdown
+
+    INTEGER :: z_rup
+    INTEGER :: z_up
+    INTEGER :: z_lup
+    INTEGER :: z_ldown
+    INTEGER :: z_down
+    INTEGER :: z_rdown
+   
+    INTEGER :: t_pos(6)
+    INTEGER :: u_pos(6)
+    INTEGER :: z_pos(6)
+     
+  END TYPE t_domain
+
+  INTEGER,SAVE :: ndomain
+  INTEGER,SAVE :: ndomain_glo
+
+  TYPE(t_domain),SAVE,ALLOCATABLE,TARGET :: domain(:)
+  TYPE(t_domain),SAVE,ALLOCATABLE,TARGET :: domain_glo(:)
+
+  INTEGER,ALLOCATABLE,SAVE :: domglo_rank(:)  ! size : ndomain_glo : mpi rank assigned to a domain 
+  INTEGER,ALLOCATABLE,SAVE :: domglo_loc_ind(:) ! size : ndomain_glo : corresponding local indice for a global domain indice
+  INTEGER,ALLOCATABLE,SAVE :: domloc_glo_ind(:) ! size : ndomain : corresponding global indice for a local domain indice
+
+  LOGICAL, ALLOCATABLE, SAVE :: assigned_domain(:) ! size : ndomain : is an omp task is assigned to this domain
+!$OMP THREADPRIVATE(assigned_domain)
+    
+CONTAINS
+
+  SUBROUTINE create_domain
+  USE grid_param
+  USE mpipara
+  USE IOIPSL
+  IMPLICIT NONE
+  INTEGER :: ind,nf,ni,nj,i,j
+  INTEGER :: quotient, rest
+  INTEGER :: halo_i,halo_j
+  
+  TYPE(t_domain),POINTER :: d
+ 
+    ndomain_glo=nsplit_i*nsplit_j*nb_face
+    ALLOCATE(domain_glo(ndomain_glo))
+    ALLOCATE(domglo_rank(ndomain_glo))
+    ALLOCATE(domglo_loc_ind(ndomain_glo))
+   
+    halo_i=0
+    CALL getin("halo_i",halo_i)
+    halo_j=1
+    CALL getin("halo_j",halo_j)
+
+    ind=0
+    DO nf=1,nb_face
+      DO nj=1,nsplit_j
+        DO ni=1,nsplit_i
+          ind=ind+1
+          d=>domain_glo(ind)
+          quotient=(iim_glo/nsplit_i)
+          rest=MOD(iim_glo,nsplit_i)
+          IF (ni-1 < rest) THEN
+            d%ii_nb=quotient+1
+            d%ii_begin_glo=(quotient+1)*(ni-1)+1
+          ELSE 
+            d%ii_nb=quotient
+            d%ii_begin_glo=(quotient+1)*rest+(ni-1-rest) * quotient+1
+          ENDIF
+          d%ii_end_glo=d%ii_begin_glo+d%ii_nb-1
+ 
+          IF (ni/=1) THEN 
+            d%ii_nb=d%ii_nb+1
+            d%ii_begin_glo=d%ii_begin_glo-1
+          ENDIF
+         
+        
+          quotient=(jjm_glo/nsplit_j)
+          rest=MOD(jjm_glo,nsplit_j)
+          IF (nj-1 < rest) THEN
+            d%jj_nb=quotient+1
+            d%jj_begin_glo=(quotient+1)*(nj-1)+1
+          ELSE
+            d%jj_nb=quotient
+            d%jj_begin_glo=(quotient+1)*rest+(nj-1-rest) * quotient+1
+          ENDIF
+          d%jj_end_glo=d%jj_begin_glo+d%jj_nb-1
+
+          IF (nj/=1) THEN 
+            d%jj_nb=d%jj_nb+1
+            d%jj_begin_glo=d%jj_begin_glo-1
+          ENDIF
+
+
+          d%iim=d%ii_nb+2*halo  + halo_i*2
+          d%jjm=d%jj_nb+2*halo  + halo_j*2
+          d%ii_begin=halo+1  + halo_i
+          d%jj_begin=halo+1  + halo_j
+          d%ii_end=d%ii_begin+d%ii_nb-1
+          d%jj_end=d%jj_begin+d%jj_nb-1
+          d%face=nf        
+          ALLOCATE(d%assign_domain(d%iim,d%jjm))
+          ALLOCATE(d%assign_cell_glo(d%iim,d%jjm))
+          ALLOCATE(d%assign_i(d%iim,d%jjm))
+          ALLOCATE(d%assign_j(d%iim,d%jjm))
+          ALLOCATE(d%edge_assign_domain(0:5,d%iim,d%jjm))
+          ALLOCATE(d%edge_assign_i(0:5,d%iim,d%jjm))
+          ALLOCATE(d%edge_assign_j(0:5,d%iim,d%jjm))
+          ALLOCATE(d%edge_assign_pos(0:5,d%iim,d%jjm))
+          ALLOCATE(d%edge_assign_sign(0:5,d%iim,d%jjm))
+          ALLOCATE(d%delta(d%iim,d%jjm))
+          ALLOCATE(d%xyz(3,d%iim,d%jjm))
+          ALLOCATE(d%vertex(3,0:5,d%iim,d%jjm))
+          ALLOCATE(d%neighbour(3,0:5,d%iim,d%jjm))
+          ALLOCATE(d%own(d%iim,d%jjm))
+          ALLOCATE(d%ne(0:5,d%iim,d%jjm))
+          
+          IF (is_mpi_root) PRINT *,"Domain ",ind," : size ",d%ii_nb,"x",d%jj_nb
+          
+        END DO
+      END DO
+    END DO
+    
+  END SUBROUTINE create_domain
+  
+  SUBROUTINE copy_domain(d1,d2)
+  IMPLICIT NONE
+  INTEGER :: face
+  TYPE(t_domain),TARGET,INTENT(IN) :: d1
+  TYPE(t_domain), INTENT(OUT) :: d2
+  
+    d2%iim = d1%iim
+    d2%jjm = d1%jjm
+    d2%ii_begin = d1%ii_begin
+    d2%jj_begin = d1%jj_begin
+    d2%ii_end = d1%ii_end
+    d2%jj_end = d1%jj_end
+    d2%ii_nb =  d1%ii_nb
+    d2%jj_nb = d1%jj_nb
+    d2%ii_begin_glo = d1%ii_begin_glo
+    d2%jj_begin_glo = d1%jj_begin_glo
+    d2%ii_end_glo = d1%ii_end_glo
+    d2%jj_end_glo = d1%jj_end_glo
+    d2%assign_domain => d1%assign_domain
+    d2%assign_cell_glo => d1%assign_cell_glo
+    d2%assign_i => d1%assign_i
+    d2%assign_j => d1%assign_j
+    d2%edge_assign_domain => d1%edge_assign_domain
+    d2%edge_assign_i => d1%edge_assign_i
+    d2%edge_assign_j => d1%edge_assign_j
+    d2%edge_assign_pos => d1%edge_assign_pos
+    d2%edge_assign_sign => d1%edge_assign_sign
+    d2%xyz => d1%xyz
+    d2%neighbour => d1%neighbour
+    d2%delta => d1%delta
+    d2%vertex => d1%vertex
+    d2%own => d1%own
+    d2%ne => d1%ne
+    
+    d2%t_right = d1%t_right
+    d2%t_rup = d1%t_rup
+    d2%t_lup = d1%t_lup
+    d2%t_left = d1%t_left
+    d2%t_ldown = d1%t_ldown
+    d2%t_rdown = d1%t_rdown
+
+    d2%u_right = d1%u_right
+    d2%u_rup = d1%u_rup
+    d2%u_lup = d1%u_lup
+    d2%u_left = d1%u_left
+    d2%u_ldown = d1%u_ldown
+    d2%u_rdown = d1%u_rdown
+
+    d2%z_rup = d1%z_rup
+    d2%z_up = d1%z_up
+    d2%z_lup = d1%z_lup
+    d2%z_ldown = d1%z_ldown
+    d2%z_down = d1%z_down
+    d2%z_rdown = d1%z_rdown
+   
+    d2%t_pos = d1%t_pos
+    d2%u_pos = d1%u_pos
+    d2%z_pos = d1%z_pos
+    
+  END SUBROUTINE copy_domain
+  
+  
+  SUBROUTINE assign_cell
+  USE metric
+  IMPLICIT NONE
+    INTEGER :: ind_d,ind,ind2,e
+    INTEGER :: nf,nf2
+    INTEGER :: i,j,k,ii,jj
+    TYPE(t_domain),POINTER :: d
+    INTEGER :: delta
+     
+    
+    DO ind_d=1,ndomain_glo
+      d=>domain_glo(ind_d)
+      nf=d%face
+      DO j=d%jj_begin,d%jj_end
+        DO i=d%ii_begin,d%ii_end
+          ii=d%ii_begin_glo-d%ii_begin+i
+          jj=d%jj_begin_glo-d%jj_begin+j
+          ind=vertex_glo(ii,jj,nf)%ind
+          delta=vertex_glo(ii,jj,nf)%delta
+          IF (cell_glo(ind)%assign_face==nf) THEN 
+            cell_glo(ind)%assign_domain=ind_d
+            cell_glo(ind)%assign_i=i
+            cell_glo(ind)%assign_j=j
+          ENDIF
+          IF ( i+1 <= d%ii_end ) CALL assign_edge(ind_d,ind,i,j,delta,0)
+          IF ( j+1 <= d%jj_end ) CALL assign_edge(ind_d,ind,i,j,delta,1)
+          IF ( i-1 >= d%ii_begin .AND. j+1<=d%jj_end ) CALL assign_edge(ind_d,ind,i,j,delta,2)
+          IF ( i-1 >= d%ii_begin ) CALL assign_edge(ind_d,ind,i,j,delta,3)
+          IF ( j-1 >= d%jj_begin ) CALL assign_edge(ind_d,ind,i,j,delta,4)
+          IF ( i+1 <= d%ii_end .AND. j-1 >=d%jj_begin ) CALL assign_edge(ind_d,ind,i,j,delta,5)
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    
+    DO ind_d=1,ndomain_glo
+      d=>domain_glo(ind_d)
+      nf=d%face
+      DO j=d%jj_begin-1,d%jj_end+1
+        DO i=d%ii_begin-1,d%ii_end+1
+          ii=d%ii_begin_glo-d%ii_begin+i
+          jj=d%jj_begin_glo-d%jj_begin+j
+          ind=vertex_glo(ii,jj,nf)%ind
+          d%assign_cell_glo(i,j) = ind  
+          d%assign_domain(i,j)=cell_glo(ind)%assign_domain
+          d%assign_i(i,j)=cell_glo(ind)%assign_i
+          d%assign_j(i,j)=cell_glo(ind)%assign_j
+          delta=vertex_glo(ii,jj,nf)%delta
+          d%delta(i,j)=vertex_glo(ii,jj,nf)%delta
+          DO k=0,5
+            ind2=vertex_glo(ii,jj,nf)%neighbour(k)
+            d%neighbour(:,k,i,j)=cell_glo(ind2)%xyz(:)
+
+            d%ne(k,i,j)=1-2*MOD(k,2)
+
+            e=cell_glo(ind)%edge(MOD(k+delta+6,6))
+            d%edge_assign_domain(k,i,j)=edge_glo(e)%assign_domain
+            d%edge_assign_i(k,i,j)=edge_glo(e)%assign_i
+            d%edge_assign_j(k,i,j)=edge_glo(e)%assign_j
+            d%edge_assign_pos(k,i,j)=edge_glo(e)%assign_pos
+            nf2=domain_glo(edge_glo(e)%assign_domain)%face
+            d%edge_assign_sign(k,i,j)=1-2*MOD(12+tab_index(nf,nf2,0),2)
+            IF (MOD(6+k+tab_index(nf,nf2,0),6)/=edge_glo(e)%assign_pos .AND. MOD(6+k+tab_index(nf,nf2,0),6) & 
+                /= MOD(edge_glo(e)%assign_pos+3,6)) THEN
+              d%edge_assign_sign(k,i,j)=-d%edge_assign_sign(k,i,j)
+            ENDIF
+             
+          ENDDO
+          d%xyz(:,i,j)=cell_glo(ind)%xyz(:)
+          IF (d%assign_domain(i,j)==ind_d) THEN
+           d%own(i,j)=.TRUE.
+          ELSE
+           d%own(i,j)=.FALSE.
+          ENDIF
+        ENDDO
+      ENDDO
+    ENDDO
+
+  CONTAINS
+
+    SUBROUTINE assign_edge(ind_d,ind,i,j,delta,k)
+      INTEGER :: ind_d,ind,i,j,delta,k
+      INTEGER :: e
+      e=cell_glo(ind)%edge(MOD(k+delta+6,6))
+      edge_glo(e)%assign_domain=ind_d
+      edge_glo(e)%assign_i=i
+      edge_glo(e)%assign_j=j
+      edge_glo(e)%assign_pos=k
+      edge_glo(e)%assign_delta=delta
+
+     END  SUBROUTINE assign_edge
+         
+  END SUBROUTINE assign_cell
+
+  SUBROUTINE compute_boundary
+  USE spherical_geom_mod
+  IMPLICIT NONE
+    INTEGER :: ind_d
+    INTEGER :: i,j,k
+    TYPE(t_domain),POINTER :: d 
+    REAL(rstd) :: ng1(3),ng2(3) 
+
+    DO ind_d=1,ndomain_glo
+      d=>domain_glo(ind_d)
+      DO j=d%jj_begin-1,d%jj_end+1
+        DO i=d%ii_begin-1,d%ii_end+1
+          DO k=0,5
+            ng1=d%neighbour(:,MOD(k,6),i,j)
+            ng2=d%neighbour(:,MOD(k+1,6),i,j)
+            IF (sqrt(sum((ng1-ng2)**2))<1e-16) ng2=d%neighbour(:,MOD(k+2,6),i,j)
+            CALL circumcenter(d%xyz(:,i,j),ng1,ng2,d%vertex(:,k,i,j))
+          ENDDO
+        ENDDO
+      ENDDO
+    ENDDO        
+  END SUBROUTINE compute_boundary
+
+  SUBROUTINE set_neighbour_indice
+  USE metric
+  IMPLICIT NONE
+    INTEGER :: ind_d
+    TYPE(t_domain),POINTER :: d 
+    
+    DO ind_d=1,ndomain_glo
+      d=>domain_glo(ind_d)
+      d%t_right=1
+      d%t_left=-1
+      d%t_rup=d%iim
+      d%t_lup=d%iim-1
+      d%t_ldown=-d%iim
+      d%t_rdown=-d%iim+1
+      
+      d%u_right=0
+      d%u_lup=d%iim*d%jjm
+      d%u_ldown=2*d%iim*d%jjm
+      
+      d%u_rup=d%t_rup+d%u_ldown
+      d%u_left=d%t_left+d%u_right
+      d%u_rdown=d%t_rdown+d%u_lup
+      
+      d%z_up=0
+      d%z_down=d%iim*d%jjm
+      d%z_rup=d%t_rup+d%z_down
+      d%z_lup=d%t_lup+d%z_down
+      d%z_ldown=d%t_ldown+d%z_up
+      d%z_rdown=d%t_rdown+d%z_up
+      
+      d%t_pos(right)=d%t_right
+      d%t_pos(rup)=d%t_rup
+      d%t_pos(lup)=d%t_lup
+      d%t_pos(left)=d%t_left
+      d%t_pos(ldown)=d%t_ldown
+      d%t_pos(rdown)=d%t_rdown
+
+      d%u_pos(right)=d%u_right
+      d%u_pos(rup)=d%u_rup
+      d%u_pos(lup)=d%u_lup
+      d%u_pos(left)=d%u_left
+      d%u_pos(ldown)=d%u_ldown
+      d%u_pos(rdown)=d%u_rdown
+      
+      d%z_pos(vrup)=d%z_rup
+      d%z_pos(vup)=d%z_up
+      d%z_pos(vlup)=d%z_lup
+      d%z_pos(vldown)=d%z_ldown
+      d%z_pos(vdown)=d%z_down
+      d%z_pos(vrdown)=d%z_rdown
+      
+    ENDDO  
+  
+  END SUBROUTINE set_neighbour_indice
+      
+  SUBROUTINE assign_domain
+  USE mpipara
+  IMPLICIT NONE
+    INTEGER :: nb_domain(0:mpi_size-1)
+    INTEGER :: rank, ind,ind_glo
+    
+    DO rank=0,mpi_size-1
+      nb_domain(rank)=ndomain_glo/mpi_size
+      IF ( rank < MOD(ndomain_glo,mpi_size) ) nb_domain(rank)=nb_domain(rank)+1
+    ENDDO
+    
+    ndomain=nb_domain(mpi_rank)
+    ALLOCATE(domain(ndomain))
+    ALLOCATE(domloc_glo_ind(ndomain))
+    
+    rank=0
+    ind=0
+    DO ind_glo=1,ndomain_glo
+      ind=ind+1
+      domglo_rank(ind_glo)=rank
+      domglo_loc_ind(ind_glo)=ind
+      IF (rank==mpi_rank) THEN 
+        CALL copy_domain(domain_glo(ind_glo),domain(ind))
+        domloc_glo_ind(ind)=ind_glo
+      ENDIF
+      
+      IF (ind==nb_domain(rank)) THEN
+        rank=rank+1
+        ind=0
+      ENDIF
+    ENDDO
+
+!$OMP PARALLEL
+    CALL assign_domain_omp
+!$OMP END PARALLEL
+        
+    
+  END SUBROUTINE  assign_domain      
+   
+  SUBROUTINE assign_domain_omp
+  USE omp_para
+  USE mpipara
+  IMPLICIT NONE
+    INTEGER :: nb_domain
+    INTEGER :: rank, ind, i
+
+    ALLOCATE(assigned_domain(ndomain))
+    
+    ind=0
+    DO rank=0,omp_size-1
+      nb_domain=ndomain/omp_size
+      IF ( rank < MOD(ndomain,omp_size) ) nb_domain=nb_domain+1
+    
+      DO i=1,nb_domain
+       ind=ind+1
+       IF (rank==omp_rank) THEN 
+         assigned_domain(ind)=.TRUE.
+         PRINT *,"Rank ",mpi_rank," task ",rank," local domain : ",ind," global domain ",domloc_glo_ind(ind)
+       ELSE
+         assigned_domain(ind)=.FALSE.
+       ENDIF  
+      ENDDO
+    
+    ENDDO
+    
+  END SUBROUTINE assign_domain_omp
+    
+
+          
+  SUBROUTINE compute_domain
+  IMPLICIT NONE
+    CALL init_domain_param
+    CALL create_domain
+    CALL assign_cell
+    CALL compute_boundary
+    CALL set_neighbour_indice
+    CALL assign_domain
+      
+  END SUBROUTINE compute_domain
+          
+END MODULE domain_mod 
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/domain_param.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/domain_param.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/domain_param.f90	(revision 329)
@@ -0,0 +1,36 @@
+MODULE domain_param
+
+INTEGER :: nsplit_i
+INTEGER :: nsplit_j
+INTEGER :: halo=1
+
+INTEGER, PARAMETER :: default_nsplit_i=1
+INTEGER, PARAMETER :: default_nsplit_j=1
+
+CONTAINS
+  
+  SUBROUTINE init_domain_param
+  USE ioipsl, ONLY: getin
+  USE mpipara, ONLY: using_mpi, mpi_size, is_mpi_master
+  USE omp_para, ONLY: using_openmp
+  IMPLICIT NONE
+    nsplit_i=default_nsplit_i
+    nsplit_j=default_nsplit_j
+    CALL getin('nsplit_i',nsplit_i)
+    CALL getin('nsplit_j',nsplit_j)
+
+    IF (using_mpi.and.(.not.using_openmp).and.(nsplit_i*nsplit_j*10<mpi_size)) THEN
+    ! Check that nsplit_i*nsplit_j*10>=mpi_size
+      IF (is_mpi_master) THEN
+        WRITE(*,*) "Error: Number of MPI processes must be"
+        WRITE(*,*) "       <= 10*nsplit_i_nsplit_j"
+        WRITE(*,*) " but nsplit_i=",nsplit_i," , nsplit_j=",nsplit_j
+        WRITE(*,*) " while using ",mpi_size," MPI processes"
+      ENDIF
+      STOP
+    ENDIF
+
+    ! TODO : same kind of test for OpenMP or mixed MPI/OpenMP cases
+  END SUBROUTINE init_domain_param
+  
+END MODULE domain_param
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dynetat0_gcm_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dynetat0_gcm_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dynetat0_gcm_mod.f90	(revision 329)
@@ -0,0 +1,364 @@
+MODULE dynetat0_gcm_mod 
+  USE genmod
+  USE icosa
+  USE caldyn_gcm_mod 
+ 	IMPLICIT NONE 
+	  PRIVATE
+
+       PUBLIC  etat0
+	 INTEGER,SAVE::ncell
+	 TYPE(t_field),POINTER:: f_iu(:)
+      TYPE(t_field),POINTER:: f_iv(:) 
+	 TYPE(t_field),POINTER:: f_iue(:)
+      TYPE(t_field),POINTER:: f_ive(:) 
+	 REAL(rstd),POINTER :: iu(:,:),iv(:,:)
+      REAL(rstd),POINTER :: iue(:,:),ive(:,:) 
+
+	  
+CONTAINS
+
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u,f_q) 
+  USE icosa
+  USE write_field  
+  USE maxicosa
+	IMPLICIT NONE
+	TYPE(t_domain),POINTER :: d 
+	TYPE(t_field),POINTER:: f_ps(:)
+	TYPE(t_field),POINTER:: f_phis(:)
+	TYPE(t_field),POINTER:: f_u(:)
+	TYPE(t_field),POINTER:: f_q(:)
+	TYPE(t_field),POINTER:: f_theta_rhodz(:) 
+     TYPE(t_field),POINTER::  f_buf_i3(:), f_buf1_i(:), f_buf2_i(:)
+     REAL(rstd),POINTER :: ps(:)
+     REAL(rstd),POINTER :: phis(:)
+     REAL(rstd),POINTER :: theta_rhodz(:,:)
+     REAL(rstd),POINTER :: u(:,:) 
+     REAL(rstd),POINTER :: q(:,:,:)
+	REAL(rstd):: maxff,minff,maxuu,minuu
+	INTEGER :: ind
+ 
+	CALL allocate_field(f_iu,field_t,type_real,llm) 
+     CALL allocate_field(f_iv,field_t,type_real,llm)
+	CALL allocate_field(f_iue,field_u,type_real,llm) 
+     CALL allocate_field(f_ive,field_u,type_real,llm)
+	CALL allocate_field(f_u,field_u,type_real,llm) 
+	CALL allocate_field(f_buf1_i,field_t,type_real,llm) 
+	CALL allocate_field(f_buf2_i,field_t,type_real,llm) 
+	CALL allocate_field(f_buf_i3,field_u,type_real,3,llm) 
+  
+	PRINT*,"IN NETCDF READ"
+!------------------------------------zero 
+	DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+	  iu = f_iu(ind) 
+	  iv = f_iv(ind) 
+      iue = f_iue(ind) 
+	 ive = f_ive(ind) 	
+	  iu = 0.0 
+	  iv = 0.0 
+        u = f_u(ind) 
+	   u = 0.0 
+	 iue = 0.0	
+	 ive = 0.0 
+     END DO 
+!--------------------------------------------
+	 ncell = 0
+     DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+	 d => domain_glo(ind)
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      q=f_q(ind)
+      iu=f_iu(ind) 
+	 iv=f_iv(ind) 
+      CALL compute_dynetat0(ind,d,ps,phis,theta_rhodz,iu,iv,q)
+	ENDDO
+
+     CALL transfert_request(f_ps,req_i1)
+	CALL transfert_request(f_phis,req_i1)
+	CALL transfert_request(f_theta_rhodz,req_i1)
+	CALL transfert_request(f_q,req_i1)
+	CALL transfert_request(f_iu,req_i1)
+	CALL transfert_request(f_iv,req_i1)
+!------------------------------------------
+	DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+	 u=f_u(ind)
+	 iu=f_iu(ind) 
+	 iv=f_iv(ind) 
+	 iue=f_iue(ind) 
+	 ive=f_ive(ind) 
+  	 CALL compute_dynetatu(iu,iv,iue,ive,u)
+	ENDDO
+!----------------------------------------------------
+!------------- OUTPUT OF Variables 
+  END SUBROUTINE etat0
+
+!==================================================================
+  SUBROUTINE compute_dynetat0(ind,d,ps,phis,theta_rhodz,iu,iv,q) 
+   use icosa
+   use netcdf
+   use wind_mod 
+   USE disvert_mod
+ 	IMPLICIT NONE 
+   TYPE(t_domain),POINTER :: d 
+   CHARACTER*20::dimname 
+   REAL(rstd), INTENT(OUT) :: ps(iim*jjm)
+   REAL(rstd), INTENT(OUT) :: phis(iim*jjm)
+   REAL(rstd), INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+   REAL(rstd), INTENT(OUT) :: q(iim*jjm,llm,nqtot)
+   REAL(rstd),ALLOCATABLE :: mass(:,:)   ! mass    
+   REAL(rstd),ALLOCATABLE :: rhodz(:,:)   ! mass density  
+   REAL(rstd),ALLOCATABLE :: theta(:,:) 
+   REAL(rstd),ALLOCATABLE :: p(:,:)  ! pression
+   REAL(rstd),POINTER :: iu(:,:),iv(:,:)
+   REAL(rstd),POINTER :: icops(:)
+   REAL(rstd),POINTER :: icophis(:)
+   REAL(rstd),POINTER :: icou(:,:),icov(:,:)
+   REAL(rstd),POINTER :: icotheta(:,:)
+   REAL(rstd),POINTER :: icoq(:,:,:)
+
+   INTEGER length,iq,ind,l
+   PARAMETER (length = 100)
+   REAL tab_cntrl(length) ! tableau des parametres du run
+   INTEGER::ierr,nid,ncid,nvarid,dimid,nind
+   INTEGER::ncells  
+   INTEGER::halo_size,i,j,k,ij
+   LOGICAL::single 
+   INTEGER::nDims,nVars,nGlobalAtts,unlimdimid
+   INTEGER:: len
+   CHARACTER(LEN=200):: iqq 
+   
+!	OPEN NETCDF FILE 
+	 ierr = NF90_OPEN ("start_icosa25.nc",NF90_NOWRITE,nid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)'dynetat0: with file start_icosa.nc'
+        write(*,*)' ierr = ', ierr
+        STOP 
+      ENDIF
+
+     ierr= nf90_inquire(nid,nDims,nVars,nGlobalAtts,unlimdimid)
+	IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)'Problem in inquire'
+        write(*,*)' ierr = ', ierr
+        STOP 
+      ENDIF
+
+!	PRINT*,"nDims,nVars,nGlobalAtts,unlimdimid"
+!	PRINT*,nDims,nVars,nGlobalAtts,unlimdimid
+
+
+	 ierr = NF90_INQ_DIMID(nid,"ncells",dimid)
+	 IF (ierr .NE. NF90_NOERR ) THEN 
+	   write(*,*)'ncells is not present in start_icosa.nc'
+        write(*,*)' ierr = ', ierr
+	   STOP 
+	 ENDIF 
+	   
+	 ierr = nf90_inquire_dimension(nid,dimid,dimname,ncells)
+	 IF (ierr .NE. NF90_NOERR ) THEN 
+	   write(*,*)'ncells  in start_icosa.nc'
+        write(*,*)' ierr = ', ierr
+	   STOP 
+	 ENDIF
+
+	  ALLOCATE(icops(ncells))
+	  ALLOCATE(icophis(ncells))
+	  ALLOCATE(icou(ncells,llm))
+	  ALLOCATE(icov(ncells,llm))
+	  ALLOCATE(icotheta(ncells,llm))
+	  ALLOCATE(icoq(ncells,llm,nqtot))
+	  ALLOCATE(p(iim*jjm,llm+1))
+	  ALLOCATE(theta(iim*jjm,llm)) 
+       ALLOCATE(mass(iim*jjm,llm))   ! mass    
+       ALLOCATE(rhodz(iim*jjm,llm))   ! mass density   
+!============================================================
+      ierr = NF90_INQ_VARID(nid, "phisinit", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: phisinit is absent"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid, icophis)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN PHIS"
+         STOP
+      ENDIF
+!==============================================================
+	  ierr = NF90_INQ_VARID(nid, "ps", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ps is absent"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid, icops)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN PS"
+         STOP
+      ENDIF
+!================================================================
+	  ierr = NF90_INQ_VARID(nid, "teta", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: teta is not available in start.nc"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icotheta)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN Teta"
+         STOP
+      ENDIF
+!================================================================
+	DO iq = 1,nqtot   
+		write(iqq,*)INT(iq)
+		iqq=ADJUSTL(iqq)  
+     	ierr = NF90_INQ_VARID(nid,"q"//iqq, nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ","q"//iqq,"not here"
+	   write(*,*)' ierr = ', ierr
+!         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icoq(:,:,iq))
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN Q"
+!         STOP
+      ENDIF
+	END DO
+!================================================================
+	GO TO 121
+	  ierr = NF90_INQ_VARID(nid, "q01", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: q1 is not available in start.nc"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icoq(:,:,1))
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN Q01"
+         STOP
+      ENDIF
+121	CONTINUE 
+!================================================================
+	  ierr = NF90_INQ_VARID(nid, "ucov", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ucov is not available in start.nc"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icou)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN ucov"
+         STOP
+      ENDIF
+	PRINT*,"UCOV is read using start_icosa.nc" 
+!================================================================
+	  ierr = NF90_INQ_VARID(nid, "vcov", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: PROBLEM in VCOV"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icov)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN vcov"
+         STOP
+      ENDIF
+!================================================================
+			iu = 0.0 ; iv = 0.0 
+             DO j=d%jj_begin,d%jj_end
+              DO i=d%ii_begin,d%ii_end
+                  k=d%iim*(j-1)+i
+                 IF (d%assign_domain(i,j)==ind ) THEN
+                     ncell=ncell+1
+		           phis(k)=  0.0  !icophis(ncell) 
+	                ps(k)= icops(ncell) 
+	                theta(k,:) = icotheta(ncell,:) 
+	                q(k,:,1)= icoq(ncell,:,1) 
+	                iu(k,:) = icou(ncell,:)
+				 iv(k,:) = icov(ncell,:) 
+	         ENDIF
+                ENDDO
+              ENDDO
+
+    DO    l    = 1, llm+1
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          p(ij,l) = ap(l) + bp(l) * ps(ij)
+        ENDDO
+      ENDDO
+    ENDDO
+
+   DO l = 1, llm
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         mass(ij,l) = ( p(ij,l) - p(ij,l+1) )*Ai(ij)/g
+         rhodz(ij,l) = mass(ij,l) / Ai(ij)
+       ENDDO
+     ENDDO
+   ENDDO
+
+    DO    l    = 1, llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          theta_rhodz(ij,l) = theta(ij,l)*rhodz(ij,l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+	  DEALLOCATE(icops)
+	  DEALLOCATE(icophis)
+	  DEALLOCATE(icou)
+	  DEALLOCATE(icov)
+	  DEALLOCATE(icotheta)
+	  DEALLOCATE(p)
+	  DEALLOCATE(theta) 
+       DEALLOCATE(mass)   ! mass    
+       DEALLOCATE(rhodz)   !
+	END SUBROUTINE compute_dynetat0
+
+!==================================================================
+	  SUBROUTINE compute_dynetatu(iu,iv,iue,ive,u) 
+   use icosa
+   use wind_mod 
+    	IMPLICIT NONE 
+   CHARACTER*20::dimname 
+   REAL(rstd),INTENT(OUT):: u(3*iim*jjm,llm)
+   REAL(rstd) :: iu(iim*jjm,llm),iv(iim*jjm,llm)
+   REAL(rstd) :: iue(3*iim*jjm,llm),ive(3*iim*jjm,llm)
+   INTEGER::halo_size,i,j,k,ij,l
+
+
+  Do l = 1, llm
+   DO j=jj_begin-1,jj_end+1
+      DO i=ii_begin-1,ii_end+1
+         k=iim*(j-1)+i
+	   iue(k+u_right,l)=0.5*(iu(k,l)+iu(k+t_right,l))
+        iue(k+u_lup,l)  =0.5*(iu(k,l)+iu(k+t_lup,l))
+        iue(k+u_ldown,l)=0.5*(iu(k,l)+iu(k+t_ldown,l)) 
+!------------------------------------------------------ 
+	   ive(k+u_right,l)=0.5*(iv(k,l)+iv(k+t_right,l))
+        ive(k+u_lup,l)  =0.5*(iv(k,l)+iv(k+t_lup,l))
+        ive(k+u_ldown,l)=0.5*(iv(k,l)+iv(k+t_ldown,l)) 
+	 END DO
+    END DO 
+  END DO 
+	CALL compute_wind_perp_from_lonlat_compound(iue,ive,u) 
+
+	END SUBROUTINE compute_dynetatu
+
+
+ END MODULE dynetat0_gcm_mod 
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dynetat0_hz_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dynetat0_hz_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/dynetat0_hz_mod.f90	(revision 329)
@@ -0,0 +1,348 @@
+MODULE dynetat0_hz_mod 
+  USE genmod
+  USE icosa
+  IMPLICIT NONE 
+  PRIVATE
+
+       PUBLIC  etat0
+       INTEGER,SAVE::ncell
+       TYPE(t_field),POINTER:: f_iu(:)
+       TYPE(t_field),POINTER:: f_iv(:) 
+       TYPE(t_field),POINTER:: f_iue(:)
+       TYPE(t_field),POINTER:: f_ive(:) 
+       REAL(rstd),POINTER :: iu(:,:),iv(:,:)
+       REAL(rstd),POINTER :: iue(:,:),ive(:,:) 
+
+ 
+CONTAINS
+
+    SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u,f_q) 
+  USE icosa
+  USE caldyn_mod
+  USE write_field  
+  USE maxicosa
+  USE wind_mod
+        IMPLICIT NONE
+     TYPE(t_domain),POINTER :: d 
+     TYPE(t_field),POINTER:: f_ps(:)
+     TYPE(t_field),POINTER:: f_phis(:)
+     TYPE(t_field),POINTER:: f_u(:)
+     TYPE(t_field),POINTER:: f_q(:)
+     TYPE(t_field),POINTER:: f_theta_rhodz(:) 
+     TYPE(t_field),POINTER::  f_buf_i3(:), f_buf1_i(:), f_buf2_i(:)
+     REAL(rstd),POINTER :: ps(:)
+     REAL(rstd),POINTER :: phis(:)
+     REAL(rstd),POINTER :: theta_rhodz(:,:)
+     REAL(rstd),POINTER :: u(:,:) 
+     REAL(rstd),POINTER :: q(:,:,:)
+     REAL(rstd):: maxff,minff,maxuu,minuu
+     INTEGER :: ind
+ 
+     CALL allocate_field(f_iu,field_t,type_real,llm) 
+     CALL allocate_field(f_iv,field_t,type_real,llm)
+     CALL allocate_field(f_iue,field_u,type_real,llm) 
+     CALL allocate_field(f_ive,field_u,type_real,llm)
+     CALL allocate_field(f_u,field_u,type_real,llm) 
+     CALL allocate_field(f_buf1_i,field_t,type_real,llm) 
+     CALL allocate_field(f_buf2_i,field_t,type_real,llm) 
+     CALL allocate_field(f_buf_i3,field_u,type_real,3,llm) 
+  
+     PRINT*,"IN NETCDF READ"
+!------------------------------------zero 
+	DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+	  iu = f_iu(ind) 
+	  iv = f_iv(ind) 
+      iue = f_iue(ind) 
+	 ive = f_ive(ind) 	
+	   u = f_u(ind) 
+	  iu = 0.0 
+	  iv = 0.0 
+	   u = 0.0 
+	 iue = 0.0	
+	 ive = 0.0 
+     END DO 
+!--------------------------------------------
+     ncell = 0
+     DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      d => domain_glo(ind)
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      q=f_q(ind)
+      iu=f_iu(ind) 
+      iv=f_iv(ind) 
+      CALL compute_dynetat0(ind,d,ps,phis,theta_rhodz,iu,iv,q)
+      ENDDO
+
+     CALL transfert_request(f_ps,req_i1)
+	CALL transfert_request(f_phis,req_i1)
+	CALL transfert_request(f_theta_rhodz,req_i1)
+	CALL transfert_request(f_q,req_i1)
+	CALL transfert_request(f_iu,req_i1)
+	CALL transfert_request(f_iv,req_i1)
+!------------------------------------------
+	DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+	 u=f_u(ind)
+	 iu=f_iu(ind) 
+	 iv=f_iv(ind) 
+	 iue=f_iue(ind) 
+	 ive=f_ive(ind) 
+  	 CALL compute_dynetatu(iu,iv,iue,ive,u)
+	ENDDO
+!------------- OUTPUT OF Variables 
+	CALL un2ulonlat(f_u,f_buf1_i,f_buf2_i) 
+	CALL writefield("buf1",f_buf1_i)
+  END SUBROUTINE etat0
+
+!==================================================================
+  SUBROUTINE compute_dynetat0(ind,d,ps,phis,theta_rhodz,iu,iv,q) 
+   use icosa
+   use netcdf
+   use wind_mod 
+   USE disvert_mod
+ 	IMPLICIT NONE 
+   TYPE(t_domain),POINTER :: d 
+   CHARACTER*20::dimname 
+   REAL(rstd), INTENT(OUT) :: ps(iim*jjm)
+   REAL(rstd), INTENT(OUT) :: phis(iim*jjm)
+   REAL(rstd), INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+   REAL(rstd), INTENT(OUT) :: q(iim*jjm,llm,nqtot)
+   REAL(rstd),ALLOCATABLE :: mass(:,:)   ! mass    
+   REAL(rstd),ALLOCATABLE :: rhodz(:,:)   ! mass density  
+   REAL(rstd),ALLOCATABLE :: theta(:,:) 
+   REAL(rstd),ALLOCATABLE :: p(:,:)  ! pression
+   REAL(rstd),POINTER :: iu(:,:),iv(:,:)
+   REAL(rstd),POINTER :: icops(:)
+   REAL(rstd),POINTER :: icophis(:)
+   REAL(rstd),POINTER :: icou(:,:),icov(:,:)
+   REAL(rstd),POINTER :: icotheta(:,:)
+   REAL(rstd),POINTER :: icoq(:,:,:)
+   
+   INTEGER length,iq,ind,l
+   PARAMETER (length = 1)
+   CHARACTER(LEN=200):: iqq ! tableau des parametres du run
+   INTEGER::ierr,nid,ncid,nvarid,dimid,nind
+   INTEGER::ncells  
+   INTEGER::halo_size,i,j,k,ij
+   LOGICAL::single 
+   INTEGER::nDims,nVars,nGlobalAtts,unlimdimid
+   INTEGER:: len
+   
+!	OPEN NETCDF FILE 
+	 ierr = NF90_OPEN ("icosa_hz30.nc",NF90_NOWRITE,nid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)'dynetat0: with file icosa_hz30.nc'
+        write(*,*)' ierr = ', ierr
+        STOP 
+      ENDIF
+
+     ierr= nf90_inquire(nid,nDims,nVars,nGlobalAtts,unlimdimid)
+	IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)'Problem in inquire'
+        write(*,*)' ierr = ', ierr
+        STOP 
+      ENDIF
+
+	PRINT*,"nDims,nVars,nGlobalAtts,unlimdimid"
+	PRINT*,nDims,nVars,nGlobalAtts,unlimdimid
+
+
+	 ierr = NF90_INQ_DIMID(nid,"ncells",dimid)
+	 IF (ierr .NE. NF90_NOERR ) THEN 
+	   write(*,*)'ncells is not present in hzdy_30.nc'
+        write(*,*)' ierr = ', ierr
+	   STOP 
+	 ENDIF 
+	   
+	 ierr = nf90_inquire_dimension(nid,dimid,dimname,ncells)
+	 IF (ierr .NE. NF90_NOERR ) THEN 
+	   write(*,*)'ncells  in hzdy_30.nc'
+        write(*,*)' ierr = ', ierr
+	   STOP 
+	 ENDIF
+
+	  ALLOCATE(icops(ncells))
+	  ALLOCATE(icophis(ncells))
+	  ALLOCATE(icou(ncells,llm))
+	  ALLOCATE(icov(ncells,llm))
+	  ALLOCATE(icotheta(ncells,llm))
+	  ALLOCATE(icoq(ncells,llm,nqtot))
+       ALLOCATE(p(iim*jjm,llm+1))
+	  ALLOCATE(theta(iim*jjm,llm)) 
+       ALLOCATE(mass(iim*jjm,llm))   ! mass    
+       ALLOCATE(rhodz(iim*jjm,llm))   ! mass density   
+!============================================================
+      ierr = NF90_INQ_VARID(nid, "phis", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: phis is absent"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid, icophis)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN PHIS"
+         STOP
+      ENDIF
+!==============================================================
+	  ierr = NF90_INQ_VARID(nid, "ps", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ps is absent"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid, icops)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN PS"
+         STOP
+      ENDIF
+!================================================================
+	  ierr = NF90_INQ_VARID(nid, "theta", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: teta is not available in start.nc"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icotheta)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN Teta"
+         STOP
+      ENDIF
+!================================================================
+	DO iq = 1,nqtot   
+		write(iqq,*)INT(iq)
+		iqq=ADJUSTL(iqq)  
+     	ierr = NF90_INQ_VARID(nid,"q"//iqq, nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ","q"//iqq,"not here"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icoq(:,:,iq))
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN Q"
+         STOP
+      ENDIF
+	END DO
+!===============================================================
+	 ierr = NF90_INQ_VARID(nid, "ulon", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ulon is not in file"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+	
+      ierr = NF90_GET_VAR(nid, nvarid,icou)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN ucov"
+         STOP
+      ENDIF
+!================================================================
+	  ierr = NF90_INQ_VARID(nid, "ulat", nvarid)
+      IF (ierr .NE. NF90_NOERR) THEN
+        write(*,*)"dynetat0: ulat is not available in start.nc"
+	   write(*,*)' ierr = ', ierr
+         STOP       
+      ENDIF
+
+      ierr = NF90_GET_VAR(nid, nvarid,icov)
+      IF (ierr .NE. NF90_NOERR) THEN
+         write(*,*)"dynetat0: PROBLEM IN vlat"
+         STOP
+      ENDIF
+!================================================================
+			iu = 0.0 ; iv = 0.0 
+             DO j=d%jj_begin,d%jj_end
+              DO i=d%ii_begin,d%ii_end
+                  k=d%iim*(j-1)+i
+                 IF (d%assign_domain(i,j)==ind ) THEN
+                     ncell=ncell+1
+				 phis(k)= icophis(ncell) 
+	                ps(k)= icops(ncell) 
+	                theta(k,:) = icotheta(ncell,:) 
+	                q(k,:,:)= icoq(ncell,:,:) 
+	                iu(k,:) = icou(ncell,:)
+				 iv(k,:) = icov(ncell,:)
+			   ENDIF
+                ENDDO
+              ENDDO
+
+    DO    l    = 1, llm+1
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          p(ij,l) = ap(l) + bp(l) * ps(ij)
+        ENDDO
+      ENDDO
+    ENDDO
+
+   DO l = 1, llm
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         mass(ij,l) = ( p(ij,l) - p(ij,l+1) )*Ai(ij)/g
+         rhodz(ij,l) = mass(ij,l) / Ai(ij)
+       ENDDO
+     ENDDO
+   ENDDO
+
+    DO    l    = 1, llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          theta_rhodz(ij,l) = theta(ij,l)*rhodz(ij,l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+	  DEALLOCATE(icops)
+	  DEALLOCATE(icophis)
+	  DEALLOCATE(icou)
+	  DEALLOCATE(icov)
+	  DEALLOCATE(icotheta)
+	  DEALLOCATE(p)
+	  DEALLOCATE(theta) 
+       DEALLOCATE(mass)   ! mass    
+       DEALLOCATE(rhodz)   !
+	END SUBROUTINE compute_dynetat0
+!==================================================================
+	  SUBROUTINE compute_dynetatu(iu,iv,iue,ive,u) 
+   use icosa
+   use wind_mod 
+    	IMPLICIT NONE 
+   CHARACTER*20::dimname 
+   REAL(rstd),INTENT(OUT):: u(3*iim*jjm,llm)
+   REAL(rstd) :: iu(iim*jjm,llm),iv(iim*jjm,llm)
+   REAL(rstd) :: iue(3*iim*jjm,llm),ive(3*iim*jjm,llm)
+   INTEGER::halo_size,i,j,k,ij,l
+
+
+  Do l = 1, llm
+   DO j=jj_begin-1,jj_end+1
+      DO i=ii_begin-1,ii_end+1
+         k=iim*(j-1)+i
+	   iue(k+u_right,l)=0.5*(iu(k,l)+iu(k+t_right,l))
+        iue(k+u_lup,l)  =0.5*(iu(k,l)+iu(k+t_lup,l))
+        iue(k+u_ldown,l)=0.5*(iu(k,l)+iu(k+t_ldown,l)) 
+!------------------------------------------------------ 
+	   ive(k+u_right,l)=0.5*(iv(k,l)+iv(k+t_right,l))
+        ive(k+u_lup,l)  =0.5*(iv(k,l)+iv(k+t_lup,l))
+        ive(k+u_ldown,l)=0.5*(iv(k,l)+iv(k+t_ldown,l)) 
+	 END DO
+    END DO 
+  END DO 
+	CALL compute_wind_perp_from_lonlat_compound(iue,ive,u) 
+
+	END SUBROUTINE compute_dynetatu
+
+
+ END MODULE dynetat0_hz_mod 
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/earth_const.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/earth_const.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/earth_const.f90	(revision 329)
@@ -0,0 +1,47 @@
+MODULE earth_const
+  USE prec
+  USE math_const
+  
+  REAL(rstd),SAVE :: radius=6.37122E6
+  REAL(rstd),SAVE :: g=9.80616
+  REAL(rstd),PARAMETER :: daysec=86400
+  REAL(rstd),SAVE :: omega=7.292E-5
+  REAL(rstd),SAVE :: kappa=0.2857143
+  REAL(rstd),SAVE :: cpp=1004.70885
+  REAL(rstd),SAVE :: preff=101325.
+  REAL(rstd),SAVE :: pa=50000.
+  REAL(rstd),SAVE :: scale_height=8000. ! atmospheric scale height (m)
+  REAL(rstd),SAVE :: scale_factor=1.
+  REAL(rstd),SAVE :: gas_constant = 8.3144621 
+  REAL(rstd),SAVE :: mu                 ! molar mass of the atmosphere
+
+  LOGICAL, SAVE :: boussinesq
+
+CONTAINS
+  
+  SUBROUTINE init_earth_const
+  USE getin_mod
+  IMPLICIT NONE
+  REAL(rstd) :: X=1
+  
+    CALL getin("radius",radius)
+    CALL getin("g",g)
+    CALL getin("scale_factor",scale_factor)
+    CALL getin("omega",omega)  
+    CALL getin("kappa",kappa)  
+    CALL getin("cpp",cpp)  
+    CALL getin("preff",preff)  
+    CALL getin("scale_height",scale_height)
+    
+    mu=kappa/cpp
+    boussinesq=.FALSE.
+    CALL getin("boussinesq",boussinesq)  
+    
+    radius=radius/scale_factor
+    omega=omega*scale_factor
+    
+  END SUBROUTINE init_earth_const
+  
+  
+END MODULE earth_const
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0.f90	(revision 329)
@@ -0,0 +1,248 @@
+MODULE etat0_mod
+  USE icosa
+  PRIVATE
+
+    CHARACTER(len=255),SAVE :: etat0_type
+!$OMP THREADPRIVATE(etat0_type)
+
+    REAL(rstd) :: etat0_temp
+
+    PUBLIC :: etat0, etat0_type
+
+CONTAINS
+  
+  SUBROUTINE etat0(f_ps,f_mass,f_phis,f_theta_rhodz,f_u, f_q)
+    USE mpipara, ONLY : is_mpi_root
+    USE disvert_mod
+    ! New interface
+    USE etat0_dcmip5_mod, ONLY : getin_etat0_dcmip5=>getin_etat0
+    USE etat0_williamson_mod, ONLY : getin_etat0_williamson=>getin_etat0
+    USE etat0_temperature_mod, ONLY: getin_etat0_temperature=>getin_etat0
+    ! Old interface
+    USE etat0_academic_mod, ONLY : etat0_academic=>etat0  
+    USE etat0_dcmip1_mod, ONLY : etat0_dcmip1=>etat0
+    USE etat0_dcmip2_mod, ONLY : etat0_dcmip2=>etat0
+    USE etat0_dcmip3_mod, ONLY : etat0_dcmip3=>etat0  
+    USE etat0_dcmip4_mod, ONLY : etat0_dcmip4=>etat0  
+    USE etat0_heldsz_mod, ONLY : etat0_heldsz=>etat0  
+    USE dynetat0_gcm_mod, ONLY : dynetat0_start=>etat0 
+    USE dynetat0_hz_mod,  ONLY : dynetat0_hz=>etat0 
+    USE etat0_start_file_mod, ONLY : etat0_start_file=>etat0  
+
+    IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_mass(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    
+    REAL(rstd),POINTER :: ps(:), mass(:,:)
+    LOGICAL :: init_mass
+    INTEGER :: ind,i,j,ij,l
+
+    ! most etat0 routines set ps and not mass
+    ! in that case and if caldyn_eta == eta_lag
+    ! the initial distribution of mass is taken to be the same
+    ! as what the mass coordinate would dictate
+    ! however if etat0_XXX defines mass then the flag init_mass must be set to .FALSE.
+    ! otherwise mass will be overwritten 
+    init_mass = (caldyn_eta == eta_lag)
+
+    etat0_type='jablonowsky06'
+    CALL getin("etat0",etat0_type)
+    
+    SELECT CASE (TRIM(etat0_type))
+       !------------------- New interface ---------------------
+    CASE ('isothermal')
+       CALL getin_etat0_isothermal
+       CALL etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q)
+    CASE ('temperature_profile')
+       CALL getin_etat0_temperature
+       CALL etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q)
+    CASE ('jablonowsky06')
+       CALL etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q)
+     CASE ('dcmip5')
+        CALL getin_etat0_dcmip5
+        CALL etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q)
+    CASE ('williamson91.6')
+       init_mass=.FALSE.
+       CALL getin_etat0_williamson
+       CALL etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q)
+       !------------------- Old interface --------------------
+    CASE ('start_file')
+       CALL etat0_start_file(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    CASE ('academic')
+       CALL etat0_academic(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    CASE ('held_suarez')
+       PRINT *,"Held & Suarez (1994) test case"
+       CALL etat0_heldsz(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    CASE ('dcmip1')
+       CALL etat0_dcmip1(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    CASE ('dcmip2_mountain','dcmip2_schaer_noshear','dcmip2_schaer_shear')
+       CALL etat0_dcmip2(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    CASE ('dcmip3')
+       CALL etat0_dcmip3(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+     CASE ('dcmip4')
+        IF(nqtot<2) THEN
+           IF (is_mpi_root)  THEN
+              PRINT *, "nqtot must be at least 2 for test case DCMIP4"
+           END IF
+           STOP
+        END IF
+       CALL etat0_dcmip4(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+     CASE ('readnf_start') 
+	  print*,"readnf_start used"	
+       CALL dynetat0_start(f_ps,f_phis,f_theta_rhodz,f_u,f_q) 
+	CASE ('readnf_hz') 
+	  print*,"readnf_hz used"
+       CALL dynetat0_hz(f_ps,f_phis,f_theta_rhodz,f_u,f_q) 
+   CASE DEFAULT
+       PRINT*, 'Bad selector for variable etat0 <',etat0_type, &
+            '> options are <jablonowsky06>, <academic>, <dcmip[1-4]> '
+       STOP
+    END SELECT
+
+    IF(init_mass) THEN ! initialize mass distribution using ps
+!       !$OMP BARRIER
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          mass=f_mass(ind); ps=f_ps(ind)
+          CALL compute_rhodz(.TRUE., ps, mass)
+       END DO
+    END IF
+
+  END SUBROUTINE etat0
+
+  SUBROUTINE etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q)
+    IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_mass(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: mass(:,:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      mass=f_mass(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      q=f_q(ind)
+      CALL compute_etat0_collocated(ps,mass, phis, theta_rhodz, u, q)
+    ENDDO
+  END SUBROUTINE etat0_collocated
+
+  SUBROUTINE compute_etat0_collocated(ps,mass, phis, theta_rhodz, u, q)
+    USE theta2theta_rhodz_mod
+    USE wind_mod
+    USE etat0_jablonowsky06_mod, ONLY : compute_jablonowsky06 => compute_etat0
+    USE etat0_dcmip5_mod, ONLY : compute_dcmip5 => compute_etat0
+    USE etat0_williamson_mod, ONLY : compute_w91_6 => compute_etat0
+    USE etat0_temperature_mod, ONLY: compute_etat0_temperature => compute_etat0
+    IMPLICIT NONE
+    REAL(rstd),INTENT(INOUT) :: ps(iim*jjm)
+    REAL(rstd),INTENT(INOUT) :: mass(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: phis(iim*jjm)
+    REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: u(3*iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: q(iim*jjm,llm,nqtot)
+
+    REAL(rstd) :: lon_i(iim*jjm)
+    REAL(rstd) :: lat_i(iim*jjm)
+    REAL(rstd) :: temp_i(iim*jjm,llm)
+    REAL(rstd) :: ulon_i(iim*jjm,llm)
+    REAL(rstd) :: ulat_i(iim*jjm,llm)
+
+    REAL(rstd) :: lon_e(3*iim*jjm)
+    REAL(rstd) :: lat_e(3*iim*jjm)
+    REAL(rstd) :: ps_e(3*iim*jjm)
+    REAL(rstd) :: mass_e(3*iim*jjm,llm)
+    REAL(rstd) :: phis_e(3*iim*jjm)
+    REAL(rstd) :: temp_e(3*iim*jjm,llm)
+    REAL(rstd) :: ulon_e(3*iim*jjm,llm)
+    REAL(rstd) :: ulat_e(3*iim*jjm,llm)
+    REAL(rstd) :: q_e(3*iim*jjm,llm,nqtot)
+
+    INTEGER :: l,i,j,ij
+
+    DO l=1,llm
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             CALL xyz2lonlat(xyz_i(ij,:)/radius,lon_i(ij),lat_i(ij))
+             CALL xyz2lonlat(xyz_e(ij+u_right,:)/radius,lon_e(ij+u_right),lat_e(ij+u_right))
+             CALL xyz2lonlat(xyz_e(ij+u_lup,:)/radius,lon_e(ij+u_lup),lat_e(ij+u_lup))
+             CALL xyz2lonlat(xyz_e(ij+u_ldown,:)/radius,lon_e(ij+u_ldown),lat_e(ij+u_ldown))
+          END DO
+       END DO
+    END DO
+
+    SELECT CASE (TRIM(etat0_type))
+    CASE ('isothermal')
+       CALL compute_etat0_isothermal(iim*jjm, phis, ps, temp_i, ulon_i, ulat_i, q)
+       CALL compute_etat0_isothermal(3*iim*jjm, phis_e, ps_e, temp_e, ulon_e, ulat_e, q_e)
+    CASE ('temperature_profile')
+       CALL compute_etat0_temperature(iim*jjm, phis, ps, temp_i, ulon_i, ulat_i, q)
+       CALL compute_etat0_temperature(3*iim*jjm, phis_e, ps_e, temp_e, ulon_e, ulat_e, q_e)
+    CASE('jablonowsky06')
+       CALL compute_jablonowsky06(iim*jjm,lon_i,lat_i, phis, ps, temp_i, ulon_i, ulat_i)
+       CALL compute_jablonowsky06(3*iim*jjm,lon_e,lat_e, phis_e, ps_e, temp_e, ulon_e, ulat_e)
+    CASE('dcmip5')
+       CALL compute_dcmip5(iim*jjm,lon_i,lat_i, phis, ps, temp_i, ulon_i, ulat_i, q)
+       CALL compute_dcmip5(3*iim*jjm,lon_e,lat_e, phis_e, ps_e, temp_e, ulon_e, ulat_e, q_e)
+    CASE('williamson91.6')
+       CALL compute_w91_6(iim*jjm,lon_i,lat_i, phis, mass(:,1), theta_rhodz(:,1), ulon_i(:,1), ulat_i(:,1))
+       CALL compute_w91_6(3*iim*jjm,lon_e,lat_e, phis_e, mass_e(:,1), temp_e(:,1), ulon_e(:,1), ulat_e(:,1))
+    END SELECT
+
+    SELECT CASE (TRIM(etat0_type))
+    CASE('williamson91.6')
+       ! Do nothing
+    CASE DEFAULT
+       CALL compute_temperature2theta_rhodz(ps,temp_i,theta_rhodz,0)    
+    END SELECT
+ 
+    CALL compute_wind_perp_from_lonlat_compound(ulon_e, ulat_e, u)
+
+  END SUBROUTINE compute_etat0_collocated
+
+!----------------------------- Resting isothermal state --------------------------------
+
+  SUBROUTINE getin_etat0_isothermal
+    etat0_temp=300
+    CALL getin("etat0_isothermal_temp",etat0_temp)
+  END SUBROUTINE getin_etat0_isothermal
+
+  SUBROUTINE compute_etat0_isothermal(ngrid, phis, ps, temp, ulon, ulat, q)
+    IMPLICIT NONE  
+    INTEGER, INTENT(IN)    :: ngrid
+    REAL(rstd),INTENT(OUT) :: phis(ngrid)
+    REAL(rstd),INTENT(OUT) :: ps(ngrid)
+    REAL(rstd),INTENT(OUT) :: temp(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulon(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulat(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: q(ngrid,llm,nqtot)
+    phis(:)=0
+    ps(:)=preff
+    temp(:,:)=etat0_temp
+    ulon(:,:)=0
+    ulat(:,:)=0
+    q(:,:,:)=0
+  END SUBROUTINE compute_etat0_isothermal
+
+END MODULE etat0_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_academic.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_academic.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_academic.f90	(revision 329)
@@ -0,0 +1,248 @@
+MODULE etat0_academic_mod
+
+
+
+
+CONTAINS
+  
+  SUBROUTINE test_etat0_academic
+  USE icosa
+  USE kinetic_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER,SAVE :: f_ps(:)
+    TYPE(t_field),POINTER,SAVE :: f_phis(:)
+    TYPE(t_field),POINTER,SAVE :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER,SAVE :: f_u(:)
+    TYPE(t_field),POINTER,SAVE :: f_q(:)
+    TYPE(t_field),POINTER,SAVE :: f_Ki(:)
+    TYPE(t_field),POINTER,SAVE :: f_temp(:)
+  
+    REAL(rstd),POINTER :: Ki(:,:)
+    REAL(rstd),POINTER :: temp(:)
+    INTEGER :: ind
+    
+    
+    CALL allocate_field(f_ps,field_t,type_real)
+    CALL allocate_field(f_phis,field_t,type_real)
+    CALL allocate_field(f_theta_rhodz,field_t,type_real,llm)
+    CALL allocate_field(f_u,field_u,type_real,llm)
+    CALL allocate_field(f_Ki,field_t,type_real,llm)
+    CALL allocate_field(f_temp,field_t,type_real)
+    
+    CALL etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+
+    CALL kinetic(f_u,f_Ki)
+
+    CALL writefield('ps',f_ps)
+    CALL writefield('theta',f_theta_rhodz)
+
+    CALL writefield('Ki',f_Ki)
+    
+  END SUBROUTINE test_etat0_academic
+   
+    
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    INTEGER :: ind
+    
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      CALL compute_etat0_academic(ps, phis, theta_rhodz, u)
+    ENDDO
+
+  END SUBROUTINE etat0
+  
+  SUBROUTINE compute_etat0_academic(ps, phis, theta_rhodz, u)
+  USE icosa
+  USE disvert_mod
+  USE pression_mod
+  USE exner_mod
+  USE geopotential_mod
+  USE theta2theta_rhodz_mod
+  IMPLICIT NONE  
+  REAL(rstd),INTENT(OUT) :: ps(iim*jjm)
+  REAL(rstd),INTENT(OUT) :: phis(iim*jjm)
+  REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: u(3*iim*jjm,llm)
+  
+  INTEGER :: i,j,l,ij
+  REAL(rstd) :: r
+  REAL(rstd) :: theta(iim*jjm,llm)
+  REAL(rstd) :: zsig
+  INTEGER    :: lsup
+  REAL(rstd) :: ddsin
+  REAL(rstd) :: thetarappel
+  REAL(rstd) :: lon,lat
+  REAL(rstd) :: p(iim*jjm,llm+1)
+  REAL(rstd) :: alpha(iim*jjm,llm),beta(iim*jjm,llm)
+  REAL(rstd) :: delta
+  REAL(rstd) :: pks(iim*jjm),pk(iim*jjm,llm)
+  REAL(rstd) :: phi(iim*jjm,llm)
+  REAL(rstd) :: x  
+  REAL(rstd) :: fact(3*iim*jjm)
+  REAL(rstd) :: ut(3*iim*jjm,llm)
+  
+  
+    DO l=1,llm
+       zsig=ap(l)/preff+bp(l)
+       IF (zsig.gt.0.3) THEN
+         lsup=l
+         thetarappel=1./8.*(-log(zsig)-.5)
+         DO j=jj_begin-1,jj_end+1
+           DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             CALL xyz2lonlat(xyz_i(ij,:),lon,lat)
+             ddsin=sin(lat)-sin(pi/20.)
+             theta(ij,l)=300.*(1+1./18.*(1.-3.*ddsin*ddsin)+thetarappel)
+            ENDDO
+         ENDDO
+       ELSE
+!   Choix isotherme au-dessus de 300 mbar
+         DO j=jj_begin-1,jj_end+1
+           DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             theta(ij,l)=theta(ij,lsup)*(0.3/zsig)**kappa
+           ENDDO
+         ENDDO
+       ENDIF 
+     ENDDO
+     
+     
+     DO j=jj_begin-1,jj_end+1
+       DO i=ii_begin-1,ii_end+1
+         ij=(j-1)*iim+i
+         ps(ij)=1.e5
+         phis(ij)=0
+       ENDDO
+     ENDDO
+     
+
+    CALL compute_pression(ps,p,1)     
+    CALL compute_exner(ps,p,pks,pk,1)  
+    CALL compute_geopotential(phis,pks,pk,theta,phi,1)
+
+
+     DO j=jj_begin-1,jj_end+1
+       DO i=ii_begin-1,ii_end+1
+         ij=(j-1)*iim+i
+
+         CALL xyz2lonlat(xyz_e(ij+u_right,:),lon,lat)
+         IF (abs(sin(lat))<1.e-4) lat=1e-4
+         x=cos(lat) ; x=x*x ; x=x*x ; x=x*x
+         fact(ij+u_right)=(1.-x)/(2.*omega*sin(lat))
+
+         CALL xyz2lonlat(xyz_e(ij+u_lup,:),lon,lat)
+         IF (abs(sin(lat))<1.e-4) lat=1e-4
+         x=cos(lat) ; x=x*x ; x=x*x ; x=x*x
+         fact(ij+u_lup)=(1.-x)/(2.*omega*sin(lat))
+
+         CALL xyz2lonlat(xyz_e(ij+u_ldown,:),lon,lat)
+         IF (abs(sin(lat))<1.e-4) lat=1e-4
+         x=cos(lat) ; x=x*x ; x=x*x ; x=x*x
+         fact(ij+u_ldown)=(1.-x)/(2.*omega*sin(lat))
+
+!         fact(ij+u_right)=-1
+!         fact(ij+u_lup)=-1
+!         fact(ij+u_ldown)=-1
+
+!         CALL xyz2lonlat(xyz_e(ij+u_ldown,:),lon,lat)
+!         ps(ij)=lat
+       ENDDO
+     ENDDO
+
+ ! gradient ==> tangential component     
+     DO l=1,llm   
+       DO j=jj_begin-1,jj_end+1
+         DO i=ii_begin-1,ii_end+1
+           ij=(j-1)*iim+i
+           ut(ij+u_right,l)=1/de(ij+u_right)*(ne(ij,right)*phi(ij,l)+ ne(ij+t_right,left)*phi(ij+t_right,l) )
+           ut(ij+u_lup,l)=1/de(ij+u_lup)*(ne(ij,lup)*phi(ij,l)+ ne(ij+t_lup,rdown)*phi(ij+t_lup,l) )
+           ut(ij+u_ldown,l)=1/de(ij+u_ldown)*(ne(ij,ldown)*phi(ij,l)+ ne(ij+t_ldown,rup)*phi(ij+t_ldown,l) )
+         ENDDO
+       ENDDO
+     ENDDO
+     
+! attention au signe ??
+! reconstruction of perpendicular component              
+     DO l=1,llm   
+       DO j=jj_begin,jj_end
+         DO i=ii_begin,ii_end
+           ij=(j-1)*iim+i
+           u(ij+u_right,l) =  -fact(ij+u_right)/de(ij+u_right) *                                        &  
+                              ( wee(ij+u_right,1,1)*le(ij+u_rup)*ut(ij+u_rup,l)+                        &
+                                wee(ij+u_right,2,1)*le(ij+u_lup)*ut(ij+u_lup,l)+                        &
+                                wee(ij+u_right,3,1)*le(ij+u_left)*ut(ij+u_left,l)+                      &
+                                wee(ij+u_right,4,1)*le(ij+u_ldown)*ut(ij+u_ldown,l)+                    &
+                                wee(ij+u_right,5,1)*le(ij+u_rdown)*ut(ij+u_rdown,l)+                    & 
+                                wee(ij+u_right,1,2)*le(ij+t_right+u_ldown)*ut(ij+t_right+u_ldown,l)+    &
+                                wee(ij+u_right,2,2)*le(ij+t_right+u_rdown)*ut(ij+t_right+u_rdown,l)+    &
+                                wee(ij+u_right,3,2)*le(ij+t_right+u_right)*ut(ij+t_right+u_right,l)+    &
+                                wee(ij+u_right,4,2)*le(ij+t_right+u_rup)*ut(ij+t_right+u_rup,l)+        &
+                                wee(ij+u_right,5,2)*le(ij+t_right+u_lup)*ut(ij+t_right+u_lup,l) )
+                                
+           u(ij+u_lup,l) = -fact(ij+u_lup)/de(ij+u_lup) *                                        &  
+                       ( wee(ij+u_lup,1,1)*le(ij+u_left)*ut(ij+u_left,l)+                        &
+                         wee(ij+u_lup,2,1)*le(ij+u_ldown)*ut(ij+u_ldown,l)+                      &
+                         wee(ij+u_lup,3,1)*le(ij+u_rdown)*ut(ij+u_rdown,l)+                      &
+                         wee(ij+u_lup,4,1)*le(ij+u_right)*ut(ij+u_right,l)+                      &
+                         wee(ij+u_lup,5,1)*le(ij+u_rup)*ut(ij+u_rup,l)+                          & 
+                         wee(ij+u_lup,1,2)*le(ij+t_lup+u_right)*ut(ij+t_lup+u_right,l)+          &
+                         wee(ij+u_lup,2,2)*le(ij+t_lup+u_rup)*ut(ij+t_lup+u_rup,l)+              &
+                         wee(ij+u_lup,3,2)*le(ij+t_lup+u_lup)*ut(ij+t_lup+u_lup,l)+              &
+                         wee(ij+u_lup,4,2)*le(ij+t_lup+u_left)*ut(ij+t_lup+u_left,l)+            &
+                         wee(ij+u_lup,5,2)*le(ij+t_lup+u_ldown)*ut(ij+t_lup+u_ldown,l) )
+
+
+           u(ij+u_ldown,l) = -fact(ij+u_ldown)/de(ij+u_ldown) *                                  &  
+                       ( wee(ij+u_ldown,1,1)*le(ij+u_rdown)*ut(ij+u_rdown,l)+                    &
+                         wee(ij+u_ldown,2,1)*le(ij+u_right)*ut(ij+u_right,l)+                    &
+                         wee(ij+u_ldown,3,1)*le(ij+u_rup)*ut(ij+u_rup,l)+                        &
+                         wee(ij+u_ldown,4,1)*le(ij+u_lup)*ut(ij+u_lup,l)+                        &
+                         wee(ij+u_ldown,5,1)*le(ij+u_left)*ut(ij+u_left,l)+                      & 
+                         wee(ij+u_ldown,1,2)*le(ij+t_ldown+u_lup)*ut(ij+t_ldown+u_lup,l)+        &
+                         wee(ij+u_ldown,2,2)*le(ij+t_ldown+u_left)*ut(ij+t_ldown+u_left,l)+      &
+                         wee(ij+u_ldown,3,2)*le(ij+t_ldown+u_ldown)*ut(ij+t_ldown+u_ldown,l)+    &
+                         wee(ij+u_ldown,4,2)*le(ij+t_ldown+u_rdown)*ut(ij+t_ldown+u_rdown,l)+    &
+                         wee(ij+u_ldown,5,2)*le(ij+t_ldown+u_right)*ut(ij+t_ldown+u_right,l) )
+                                
+!           u(ij+u_right,l)=fact(ij+u_right)*ut(ij+u_right,l)
+!           u(ij+u_lup,l)=fact(ij+u_lup)*ut(ij+u_lup,l)
+!           u(ij+u_ldown,l)=fact(ij+u_ldown)*ut(ij+u_ldown,l)
+!            ps(ij)=phi(ij,1)
+         ENDDO
+       ENDDO
+     ENDDO
+   
+     DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          CALL RANDOM_NUMBER(r) ;r=0
+          theta(ij,l)=theta(ij,l)*(1-0.0005*r)
+       ENDDO
+     ENDDO
+    ENDDO
+
+    CALL compute_theta2theta_rhodz(ps,theta,theta_rhodz,1)
+       
+
+  END SUBROUTINE compute_etat0_academic
+  
+END MODULE etat0_academic_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip1.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip1.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip1.f90	(revision 329)
@@ -0,0 +1,299 @@
+MODULE etat0_dcmip1_mod
+  USE icosa
+  PRIVATE
+
+  REAL(rstd), SAVE  :: h0=1.
+!$OMP THREADPRIVATE(h0)
+  REAL(rstd), SAVE  :: lon0=3*pi/2
+!$OMP THREADPRIVATE(lon0)
+  REAL(rstd), SAVE  :: lat0=0.0
+!$OMP THREADPRIVATE(lat0)
+  REAL(rstd), SAVE  :: alpha=0.0
+!$OMP THREADPRIVATE(alpha)
+  REAL(rstd), SAVE  :: R0 
+!$OMP THREADPRIVATE(R0)
+  REAL(rstd), SAVE  :: lat1=0.
+!$OMP THREADPRIVATE(lat1)
+  REAL(rstd), SAVE  :: lat2=0.
+!$OMP THREADPRIVATE(lat2)
+  REAL(rstd), SAVE  :: lon1=pi/6
+!$OMP THREADPRIVATE(lon1)
+  REAL(rstd), SAVE  :: lon2=-pi/6
+!$OMP THREADPRIVATE(lon2)
+  REAL(rstd), SAVE  :: latc1=0.
+!$OMP THREADPRIVATE(latc1)
+  REAL(rstd), SAVE  :: latc2=0.
+!$OMP THREADPRIVATE(latc2)
+  REAL(rstd), SAVE  :: lonc1=5*pi/6
+!$OMP THREADPRIVATE(lonc1)
+  REAL(rstd), SAVE  :: lonc2=7*pi/6
+!$OMP THREADPRIVATE(lonc2)
+  REAL(rstd), SAVE  :: zt=1000.0
+!$OMP THREADPRIVATE(zt)
+  REAL(rstd), SAVE  :: rt
+!$OMP THREADPRIVATE(rt)
+  REAL(rstd), SAVE  :: zc=5000.0
+!$OMP THREADPRIVATE(zc)
+
+  PUBLIC etat0
+  
+CONTAINS
+  
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u,f_q)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    CHARACTER(len=255) :: dcmip1_adv_shape
+    INTEGER :: ind
+    
+    R0=radius*0.5
+    rt=radius*0.5
+    dcmip1_adv_shape='cos_bell'
+    CALL getin('dcmip1_shape',dcmip1_adv_shape)
+    
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      q=f_q(ind)
+
+
+      SELECT CASE(TRIM(dcmip1_adv_shape))
+      CASE('const')
+         CALL compute_etat0_ncar(1,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('cos_bell')
+         CALL compute_etat0_ncar(2,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('slotted_cyl')
+         CALL compute_etat0_ncar(3,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('dbl_cos_bell_q1')
+         CALL compute_etat0_ncar(4,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('dbl_cos_bell_q2')
+         CALL compute_etat0_ncar(5,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('complement')
+         CALL compute_etat0_ncar(6,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('hadley')  ! hadley like meridional circulation 
+         CALL compute_etat0_ncar(7,ps, phis, theta_rhodz, u, q(:,:,1))
+      CASE('dcmip11')
+         IF(nqtot==5) THEN
+            CALL compute_etat0_ncar(4,ps, phis, theta_rhodz, u, q(:,:,1))
+            CALL compute_etat0_ncar(5,ps, phis, theta_rhodz, u, q(:,:,2))
+            CALL compute_etat0_ncar(3,ps, phis, theta_rhodz, u, q(:,:,3))
+            CALL compute_etat0_ncar(6,ps, phis, theta_rhodz, u, q(:,:,4))
+            CALL compute_etat0_ncar(1,ps, phis, theta_rhodz, u, q(:,:,5))
+         ELSE
+            PRINT *,'Error : etat0_dcmip=dcmip11 and nqtot = ',nqtot,' .'
+            PRINT *,'nqtot must be equal to 5 when etat0_dcmip=dcmip11'
+            STOP
+         END IF
+      CASE DEFAULT
+         PRINT *, 'Bad selector for variable dcmip1_adv_shape : <', TRIM(dcmip1_adv_shape),   &
+              '> options are <const>, <slotted_cyl>, <cos_bell>, <dbl_cos_bell_q1>', &
+              '<dbl_cos_bell_q2>, <complement>, <hadley>'
+         STOP
+      END SELECT
+
+    ENDDO
+
+  END SUBROUTINE etat0
+  
+  SUBROUTINE compute_etat0_ncar(icase, ps, phis, theta_rhodz, u, q)
+  USE icosa
+  USE disvert_mod
+  USE pression_mod
+  USE exner_mod
+  USE geopotential_mod
+  USE theta2theta_rhodz_mod
+  IMPLICIT NONE  
+  INTEGER, INTENT(in) :: icase
+  REAL(rstd),INTENT(OUT) :: ps(iim*jjm)
+  REAL(rstd),INTENT(OUT) :: phis(iim*jjm)
+  REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: u(3*iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: q(iim*jjm,llm)  
+
+  REAL(rstd) :: qxt1(iim*jjm,llm)
+  REAL(rstd) :: lon, lat
+  REAL(rstd) ::dd1,dd2,dd1t1,dd1t2,dd2t1
+  REAL(rstd) :: pr, zr(llm+1), zrl(llm)
+  REAL(rstd) :: rr1,rr2,bb,cc,aa,hmx
+  REAL(rstd) :: X2(3),X1(3)
+  INTEGER :: i,j,n,l
+
+  u = 0.0 ; phis = 0 ; theta_rhodz = 0 ; ps = ncar_p0
+  
+  DO l=1, llm+1
+     pr = ap(l) + bp(l)*ncar_p0
+     zr(l) = -kappa*cpp*ncar_T0/g*log(pr/ncar_p0) 
+  ENDDO
+  
+  DO l=1, llm 
+     zrl(l) = 0.5*(zr(l) + zr(l+1)) 
+  END DO
+  
+  SELECT CASE(icase)
+  CASE(1)
+     q=1
+  CASE(2)
+     !--------------------------------------------- SINGLE COSINE BELL
+     CALL cosine_bell_1(q)      
+  CASE(3)
+     CALL slotted_cylinders(q) 	
+  CASE(4)
+     PRINT *, 'Double cosine bell'
+     CALL cosine_bell_2(q)      
+  CASE(5)
+     CALL cosine_bell_2(q) 
+     DO l=1,llm
+        q(:,l)= 0.9 - 0.8*q(:,l)*q(:,l)
+     END DO     
+  CASE(6)
+     ! tracer such that, in combination with the other tracer fields 
+     ! with weight (3/10), the sum is equal to one
+     CALL cosine_bell_2(qxt1)
+     DO l = 1,llm
+        q(:,l) = 0.9 - 0.8*qxt1(:,l)*qxt1(:,l)  
+     END DO
+     q = q + qxt1 
+     CALL slotted_cylinders(qxt1)
+     q = q + qxt1 
+     q = 1. - q*0.3
+  CASE(7)  ! hadley like meridional circulation 
+     CALL hadleyq(q) 
+  END SELECT
+      
+CONTAINS
+
+!======================================================================
+
+    SUBROUTINE cosine_bell_1(hx)
+    IMPLICIT NONE 
+    REAL(rstd) :: hx(iim*jjm,llm)
+    
+      DO l=1,llm 
+        DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+            n=(j-1)*iim+i
+            CALL xyz2lonlat(xyz_i(n,:),lon,lat)
+            CALL dist_lonlat(lon0,lat0,lon,lat,rr1)  ! GC distance from center 
+            rr1 = radius*rr1
+            IF ( rr1 .LT. R0 ) then 
+              hx(n,l)= 0.5*h0*(1+cos(pi*rr1/R0)) 
+	    ELSE
+              hx(n,l)=0.0
+	    END IF
+	  END DO
+        END DO
+      END DO
+   
+    END SUBROUTINE cosine_bell_1
+
+!==============================================================================
+
+    SUBROUTINE   cosine_bell_2(hx) 
+    IMPLICIT NONE 	
+    REAL(rstd) :: hx(iim*jjm,llm)
+   
+      DO l=1,llm
+        DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+            n=(j-1)*iim+i
+            CALL xyz2lonlat(xyz_i(n,:),lon,lat)
+            CALL dist_lonlat(lonc1,latc1,lon,lat,rr1)  ! GC distance from center 
+            rr1 = radius*rr1
+            CALL dist_lonlat(lonc2,latc2,lon,lat,rr2)  ! GC distance from center 
+            rr2 = radius*rr2
+            dd1t1 = rr1/rt
+            dd1t1 = dd1t1*dd1t1
+            dd1t2 = (zrl(l) - zc)/zt
+            dd1t2 = dd1t2*dd1t2 
+            dd1 = dd1t1 + dd1t2 
+            dd1 = Min(1.0,dd1)  
+            dd2t1 = rr2/rt
+            dd2t1 = dd2t1*dd2t1
+            dd2 = dd2t1 + dd1t2 
+            dd2 = Min(1.0,dd2) 
+            hx(n,l)= 0.5*(1. + cos(pi*dd1))+0.5*(1.+cos(pi*dd2))
+          END DO
+        END DO
+      END DO
+
+    END SUBROUTINE cosine_bell_2
+
+!=============================================================================
+
+    SUBROUTINE slotted_cylinders(hx) 
+    IMPLICIT NONE
+    REAL(rstd) :: hx(iim*jjm,llm)
+    
+      DO l=1,llm
+        DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+            n=(j-1)*iim+i
+            CALL xyz2lonlat(xyz_i(n,:),lon,lat)
+            CALL dist_lonlat(lonc1,latc1,lon,lat,rr1)  ! GC distance from center 
+            rr1 = radius*rr1
+            CALL dist_lonlat(lonc2,latc2,lon,lat,rr2)  ! GC distance from center 
+            rr2 = radius*rr2
+            dd1t1 = rr1/rt
+            dd1t1 = dd1t1*dd1t1
+            dd1t2 = (zrl(l) - zc)/zt
+            dd1t2 = dd1t2*dd1t2 
+            dd1 = dd1t1 + dd1t2  
+            dd2t1 = rr2/rt
+            dd2t1 = dd2t1*dd2t1
+            dd2 = dd2t1 + dd1t2
+            
+            IF ( dd1 .LT. 0.5 ) Then 
+              hx(n,l) = 1.0
+            ELSEIF ( dd2 .LT. 0.5 ) Then 
+              hx(n,l) = 1.0
+            ELSE
+	      hx(n,l) = 0.1 
+            END IF  
+    
+            IF ( zrl(l) .GT. zc ) Then 
+              IF ( ABS(latc1 - lat) .LT. 0.125 ) Then 
+                hx(n,l)= 0.1
+ 	      ENDIF 
+            ENDIF  
+  
+          ENDDO
+       END DO
+      END DO
+
+    END SUBROUTINE slotted_cylinders 
+
+!==============================================================================
+
+    SUBROUTINE hadleyq(hx) 
+    IMPLICIT NONE 
+    REAL(rstd)::hx(iim*jjm,llm) 
+    REAL(rstd),PARAMETER:: zz1=3500.,zz2=6500.,zz0=0.5*(zz1+zz2)
+   
+      DO l=1,llm
+        IF ( ( zz1 .LT. zrl(l) ) .and. ( zrl(l) .LT. zz2 ) )  THEN 
+          hx(:,l) = 0.5*(1. + cos(0.002*pi*(zrl(l)-zz0)/3.))  
+        ELSE
+	  hx(:,l) = 0.0 
+        END IF
+      END DO
+    END SUBROUTINE hadleyq 
+
+  END SUBROUTINE compute_etat0_ncar
+  
+
+END MODULE etat0_dcmip1_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip2.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip2.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip2.f90	(revision 329)
@@ -0,0 +1,137 @@
+MODULE etat0_dcmip2_mod
+
+! test cases DCMIP 2012, category 2 : Orographic gravity waves
+
+  USE genmod
+
+  PRIVATE
+
+  PUBLIC  etat0
+
+CONTAINS
+
+
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+
+    INTEGER :: ind, icase
+    CHARACTER(len=255) :: etat0_type
+    etat0_type='jablonowsky06'
+    CALL getin("etat0",etat0_type)
+
+    SELECT CASE (TRIM(etat0_type))
+    CASE('dcmip2_mountain')
+       icase=0
+    CASE('dcmip2_schaer_noshear')
+       icase=1
+    CASE('dcmip2_schaer_shear')
+       icase=2
+    CASE DEFAULT
+       PRINT *, 'This should not happen : etat0_type =', TRIM(etat0_type), ' in etat0_dcmip2.f90/etat0'
+       STOP
+    END SELECT
+    PRINT *, 'Orographic gravity-wave test case :', TRIM(etat0_type)
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      u=f_u(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      q=f_q(ind)
+      CALL compute_etat0_DCMIP2(icase,ps,phis,u,theta_rhodz,q)
+    ENDDO
+            
+  END SUBROUTINE etat0
+  
+  SUBROUTINE compute_etat0_DCMIP2(icase, ps, phis, u, theta_rhodz,q)
+    USE icosa
+    USE disvert_mod, ONLY : ap,bp
+    USE pression_mod
+    USE theta2theta_rhodz_mod
+    USE wind_mod
+    IMPLICIT NONE
+    INTEGER, INTENT(IN) :: icase
+    REAL(rstd), INTENT(OUT) :: ps(iim*jjm)
+    REAL(rstd), INTENT(OUT) :: phis(iim*jjm)
+    REAL(rstd), INTENT(OUT) :: u(3*iim*jjm,llm)
+    REAL(rstd), INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd), INTENT(OUT) :: q(iim*jjm,llm)
+    REAL(rstd) :: ulon(3*iim*jjm,llm), ulat(3*iim*jjm,llm), temp(iim*jjm,llm)
+    
+    INTEGER :: i,j,l,ij
+    REAL(rstd) :: hyam, hybm, pp, dummy1, dummy2, dummy3  
+    
+    ! Hexagons : ps,phis,temp
+    DO l=1,llm
+       ! The surface pressure is not set yet so we provide the hybrid coefficients
+       hyam = .5*(ap(l)+ap(l+1))/preff
+       hybm = .5*(bp(l)+bp(l+1))
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             CALL comp_all(xyz_i(ij,:), ps(ij),phis(ij),temp(ij,l), dummy1,dummy2)
+          END DO
+       END DO
+    END DO
+    CALL compute_temperature2theta_rhodz(ps,temp,theta_rhodz,1)
+    
+    ! Edges : ulon,ulat
+    DO l=1,llm
+       ! The surface pressure is not set yet so we provide the hybrid coefficients
+       hyam = .5*(ap(l)+ap(l+1))/preff
+       hybm = .5*(bp(l)+bp(l+1))
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             CALL comp_all(xyz_e(ij+u_right,:), dummy1,dummy2,dummy3, ulon(ij+u_right,l),ulat(ij+u_right,l))
+             CALL comp_all(xyz_e(ij+u_lup,:), dummy1,dummy2,dummy3, ulon(ij+u_lup,l),ulat(ij+u_lup,l))
+             CALL comp_all(xyz_e(ij+u_ldown,:), dummy1,dummy2,dummy3, ulon(ij+u_ldown,l),ulat(ij+u_ldown,l))
+          END DO
+       END DO
+    END DO
+    CALL compute_wind_perp_from_lonlat_compound(ulon,ulat,u)
+
+    q=1.
+
+    CONTAINS
+      
+      SUBROUTINE comp_all(xyz, psj,phisj,tempj, ulonj,ulatj)
+        USE dcmip_initial_conditions_test_1_2_3
+        REAL(rstd), INTENT(IN) :: xyz(3)
+        REAL(rstd), INTENT(OUT) :: psj,phisj,tempj,ulonj,ulatj
+        REAL :: lon,lat, dummy
+        dummy=0.
+        CALL xyz2lonlat(xyz,lon,lat)
+        SELECT CASE (icase)
+        CASE(0)
+           CALL test2_steady_state_mountain(lon,lat,dummy,dummy,0,.TRUE.,hyam,hybm, &
+                ulonj,ulatj,dummy,tempj,phisj,psj,dummy,dummy)
+        CASE(1)
+           CALL test2_schaer_mountain(lon,lat,dummy,dummy,0,.TRUE.,hyam,hybm,0,&
+                ulonj,ulatj,dummy,tempj,phisj,psj,dummy,dummy)
+        CASE(2)
+           CALL test2_schaer_mountain(lon,lat,dummy,dummy,0,.TRUE.,hyam,hybm,1, &
+                ulonj,ulatj,dummy,tempj,phisj,psj,dummy,dummy)
+        END SELECT
+      END SUBROUTINE comp_all
+
+  END SUBROUTINE compute_etat0_DCMIP2
+
+
+END MODULE etat0_dcmip2_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip3.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip3.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip3.f90	(revision 329)
@@ -0,0 +1,198 @@
+MODULE etat0_dcmip3_mod
+
+! test cases DCMIP 2012, category 3 : Non-hydrostatic gravity waves
+
+! Questions
+! Replace ps0 by preff ??
+
+  USE genmod
+  USE dcmip_initial_conditions_test_1_2_3
+
+  PRIVATE
+
+  PUBLIC  etat0
+
+CONTAINS
+
+
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      u=f_u(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      q=f_q(ind)
+      CALL compute_etat0_DCMIP3(ps,phis,u,theta_rhodz,q)
+    ENDDO
+            
+  END SUBROUTINE etat0
+  
+
+  SUBROUTINE compute_etat0_DCMIP3(ps, phis, u, theta_rhodz,q)
+  USE icosa
+  USE pression_mod
+  USE theta2theta_rhodz_mod
+  USE wind_mod
+  IMPLICIT NONE
+  REAL(rstd),PARAMETER :: u0=20.         ! Maximum amplitude of the zonal wind (m.s-1)
+  REAL(rstd),PARAMETER :: N=0.01         ! Brunt-Vaisala frequency (s-1)
+  REAL(rstd),PARAMETER :: Teq=300.       ! Surface temperature at the equator (K)
+  REAL(rstd),PARAMETER :: Peq=1e5        ! Reference surface pressure at the equator (hPa)
+  REAL(rstd),PARAMETER :: d=5000.        ! Witdth parameter for theta
+  REAL(rstd),PARAMETER :: lonc=2*pi/3    ! Longitudinal centerpoint of theta
+  REAL(rstd),PARAMETER :: latc=0         ! Longitudinal centerpoint of theta
+  REAL(rstd),PARAMETER :: dtheta=1.      ! Maximum amplitude of theta (K)
+  REAL(rstd),PARAMETER :: Lz=20000.      ! Vertical wave lenght of the theta perturbation
+
+  REAL(rstd), INTENT(OUT) :: ps(iim*jjm)
+  REAL(rstd), INTENT(OUT) :: phis(iim*jjm)
+  REAL(rstd), INTENT(OUT) :: u(3*iim*jjm,llm)
+  REAL(rstd), INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+  REAL(rstd), INTENT(OUT) :: q(iim*jjm,llm,nqtot)
+  
+  REAL(rstd) :: Ts(iim*jjm)
+  REAL(rstd) :: s(iim*jjm)
+  REAL(rstd) :: T(iim*jjm,llm)
+  REAL(rstd) :: p(iim*jjm,llm+1)
+  REAL(rstd) :: theta(iim*jjm,llm)
+  REAL(rstd) :: ulon(3*iim*jjm,llm)
+  REAL(rstd) :: ulat(3*iim*jjm,llm)
+  
+  
+  INTEGER :: i,j,l,ij
+  REAL(rstd) :: Rd        ! gas constant of dry air, P=rho.Rd.T
+  REAL(rstd) :: alpha, rm
+  REAL(rstd) :: lon,lat, C0, C1, GG
+  REAL(rstd) :: p0psk, pspsk,r,zz, thetab, thetap
+  REAL(rstd) :: dummy, pp
+  LOGICAL    :: use_dcmip_routine
+  
+  Rd=cpp*kappa
+  
+  GG=(g/N)**2/cpp
+  C0=0.25*u0*(u0+2.*Omega*radius)
+  
+  q(:,:,:)=0
+  
+!  use_dcmip_routine=.TRUE.
+  use_dcmip_routine=.FALSE.
+  dummy=0.
+
+  pp=peq
+  DO j=jj_begin,jj_end
+     DO i=ii_begin,ii_end
+        ij=(j-1)*iim+i
+        CALL xyz2lonlat(xyz_i(ij,:),lon,lat)
+
+        IF(use_dcmip_routine) THEN
+           CALL test3_gravity_wave(lon,lat,pp,dummy,0, dummy,dummy,dummy,dummy,phis(ij),ps(ij),dummy,dummy)
+        ELSE
+           C1=C0*(cos(2*lat)-1)
+           
+           !--- GROUND GEOPOTENTIAL
+           phis(ij)=0.
+           
+           !--- GROUND TEMPERATURE
+           Ts(ij) = GG+(Teq-GG)*EXP(-C1*(N/g)**2)
+           
+           !--- GROUND PRESSURE
+           Ps(ij) = peq*EXP(C1/GG/Rd)*(Ts(ij)/Teq)**(1/kappa)
+           
+           
+           r=radius*acos(sin(latc)*sin(lat)+cos(latc)*cos(lat)*cos(lon-lonc))
+           s(ij)= d**2/(d**2+r**2)
+        END IF
+     END DO
+  END DO
+  
+  CALL compute_pression(ps,p,0)
+  
+  DO l=1,llm
+     DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+           ij=(j-1)*iim+i
+           pp=0.5*(p(ij,l+1)+p(ij,l))  ! full-layer pressure
+           IF(use_dcmip_routine) THEN
+              CALL xyz2lonlat(xyz_i(ij,:),lon,lat)
+              CALL test3_gravity_wave(lon,lat,pp,dummy,0,dummy,dummy,dummy,T(ij,l),dummy,dummy,dummy,dummy)
+           ELSE
+              pspsk=(pp/ps(ij))**kappa
+              p0psk=(Peq/ps(ij))**kappa
+              thetab = Ts(ij)*p0psk / ( Ts(ij) / GG * ( pspsk-1) +1)  ! background pot. temp.
+              zz     = -g/N**2*log( Ts(ij)/GG * (pspsk -1)+1)         ! altitude
+              thetap = dtheta *sin(2*Pi*zz/Lz) * s(ij)                ! perturbation pot. temp.
+              theta(ij,l) = thetab + thetap
+              T(ij,l) = theta(ij,l)* ((pp/peq)**kappa)
+              ! T(ij,l) = Ts(ij)*pspsk / ( Ts(ij) / GG * ( pspsk-1) +1)  ! background temp.
+           END IF
+        ENDDO
+     ENDDO
+  ENDDO
+  
+  IF(use_dcmip_routine) THEN
+     CALL compute_temperature2theta_rhodz(ps,T,theta_rhodz,0)
+  ELSE
+     CALL compute_temperature2theta_rhodz(ps,T,theta_rhodz,0)
+  END IF
+  
+  pp=peq
+  DO l=1,llm
+     DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+           ij=(j-1)*iim+i
+           IF(use_dcmip_routine) THEN
+              CALL xyz2lonlat(xyz_e(ij+u_right,:),lon,lat)
+              CALL test3_gravity_wave(lon,lat,pp,0.,0, &
+                   ulon(ij+u_right,l),ulat(ij+u_right,l),&
+                   dummy,dummy,dummy,dummy,dummy,dummy)
+              CALL xyz2lonlat(xyz_e(ij+u_lup,:),lon,lat)
+              CALL test3_gravity_wave(lon,lat,pp,0.,0,&
+                   ulon(ij+u_lup,l),ulat(ij+u_lup,l),&
+                   dummy,dummy,dummy,dummy,dummy,dummy)
+              CALL xyz2lonlat(xyz_e(ij+u_ldown,:),lon,lat)
+              CALL test3_gravity_wave(lon,lat,pp,0.,0,&
+                   ulon(ij+u_ldown,l),ulat(ij+u_ldown,l),&
+                   dummy,dummy,dummy,dummy,dummy,dummy)
+           ELSE
+              CALL xyz2lonlat(xyz_e(ij+u_right,:),lon,lat)
+              ulon(ij+u_right,l)=u0*cos(lat)
+              ulat(ij+u_right,l)=0
+              
+              CALL xyz2lonlat(xyz_e(ij+u_lup,:),lon,lat)
+              ulon(ij+u_lup,l)=u0*cos(lat)
+              ulat(ij+u_lup,l)=0
+              
+              CALL xyz2lonlat(xyz_e(ij+u_ldown,:),lon,lat)
+              ulon(ij+u_ldown,l)=u0*cos(lat)
+              ulat(ij+u_ldown,l)=0
+           END IF
+        ENDDO
+     ENDDO
+  ENDDO
+  
+  CALL compute_wind_perp_from_lonlat_compound(ulon,ulat,u)    
+  
+END SUBROUTINE compute_etat0_DCMIP3
+
+
+END MODULE etat0_DCMIP3_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip4.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip4.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip4.f90	(revision 329)
@@ -0,0 +1,233 @@
+MODULE etat0_dcmip4_mod
+  USE icosa
+  PRIVATE
+  REAL(rstd),PARAMETER :: eta0=0.252
+  REAL(rstd),PARAMETER :: etat=0.2
+  REAL(rstd),PARAMETER :: ps0=1e5
+  REAL(rstd),PARAMETER :: u0=35
+  REAL(rstd),PARAMETER :: T0=288
+  REAL(rstd),PARAMETER :: DeltaT=4.8e5
+  REAL(rstd),PARAMETER :: Rd=287
+  REAL(rstd),PARAMETER :: Gamma=0.005
+  REAL(rstd),PARAMETER :: up0=1
+  REAL(rstd) :: latw=2*Pi/9
+!$OMP THREADPRIVATE(latw)
+  REAL(rstd) :: pw=34000
+!$OMP THREADPRIVATE(pw)
+  REAL(rstd) :: q0=0.021
+!$OMP THREADPRIVATE(q0)
+  REAL(rstd) :: lonc
+!$OMP THREADPRIVATE(lonc)
+  REAL(rstd) :: latc
+!$OMP THREADPRIVATE(latc)
+
+  INTEGER,SAVE :: testcase
+!$OMP THREADPRIVATE(testcase)  
+
+  PUBLIC  etat0
+CONTAINS
+  
+   
+    
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    INTEGER :: ind
+
+    testcase=1
+    CALL getin("dcmip4_testcase",testcase)
+    
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      q=f_q(ind)
+      CALL compute_etat0_dcmip4(ps, phis, theta_rhodz, u, q)
+    ENDDO
+
+  END SUBROUTINE etat0
+  
+  SUBROUTINE compute_etat0_dcmip4(ps, phis, theta_rhodz, u, q)
+  USE icosa
+  USE disvert_mod
+  USE pression_mod
+  USE exner_mod
+  USE geopotential_mod
+  USE theta2theta_rhodz_mod
+  IMPLICIT NONE  
+  REAL(rstd),INTENT(OUT) :: ps(iim*jjm)
+  REAL(rstd),INTENT(OUT) :: phis(iim*jjm)
+  REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: u(3*iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: q(iim*jjm,llm,nqtot)
+  
+  INTEGER :: i,j,l,ij
+  REAL(rstd) :: theta(iim*jjm,llm)
+  REAL(rstd) :: Y(iim*jjm,llm)
+  REAL(rstd) :: vort
+  REAL(rstd) :: eta(llm)
+  REAL(rstd) :: etav(llm)
+  REAL(rstd) :: etas, etavs
+  REAL(rstd) :: lon,lat
+  REAL(rstd) :: ulon(3)
+  REAL(rstd) :: ep(3), norm_ep
+  REAL(rstd) :: Tave, T
+  REAL(rstd) :: phis_ave
+  REAL(rstd) :: V0(3)
+  REAL(rstd) :: r2
+  REAL(rstd) :: utot
+  REAL(rstd) :: lonx,latx
+  REAL(rstd) :: dthetaodeta_ave, dthetaodeta, dthetaodlat, duodeta, K, r
+  
+    lonc=Pi/9
+    latc=2*Pi/9 
+  
+    DO l=1,llm
+      eta(l)= 0.5 *( ap(l)/preff+bp(l) + ap(l+1)/preff+bp(l+1) )
+      etav(l)=(eta(l)-eta0)*Pi/2
+    ENDDO
+    etas=ap(1)/preff+bp(1)
+    etavs=(etas-eta0)*Pi/2
+
+    DO j=jj_begin,jj_end
+      DO i=ii_begin,ii_end
+        ij=(j-1)*iim+i
+        ps(ij)=ps0
+      ENDDO
+    ENDDO
+    
+    
+    CALL lonlat2xyz(lonc,latc,V0)
+
+    u(:,:)=1e10      
+    DO l=1,llm
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+          
+          CALL xyz2lonlat(xyz_e(ij+u_right,:)/radius,lon,lat)
+          K=sin(latc)*sin(lat)+cos(latc)*cos(lat)*cos(lon-lonc)
+          r=radius*acos(K)
+          utot=u0*cos(etav(l))**1.5*sin(2*lat)**2 + up0*exp(-(r/(0.1*radius))**2)
+          u(ij+u_right,l) = utot * sum(elon_e(ij+u_right,:) * ep_e(ij+u_right,:))
+
+
+          CALL xyz2lonlat(xyz_e(ij+u_lup,:)/radius,lon,lat)
+          K=sin(latc)*sin(lat)+cos(latc)*cos(lat)*cos(lon-lonc)
+          r=radius*acos(K)
+          utot=u0*cos(etav(l))**1.5*sin(2*lat)**2 + up0*exp(-(r/(0.1*radius))**2)
+          u(ij+u_lup,l) = utot * sum(elon_e(ij+u_lup,:) * ep_e(ij+u_lup,:))
+
+          CALL xyz2lonlat(xyz_e(ij+u_ldown,:)/radius,lon,lat)
+          K=sin(latc)*sin(lat)+cos(latc)*cos(lat)*cos(lon-lonc)
+          r=radius*acos(K)
+          utot=u0*cos(etav(l))**1.5*sin(2*lat)**2 + up0*exp(-(r/(0.1*radius))**2)
+          u(ij+u_ldown,l) = utot * sum(elon_e(ij+u_ldown,:) * ep_e(ij+u_ldown,:))
+
+       ENDDO
+     ENDDO
+    ENDDO 
+     
+     
+     DO l=1,llm
+       Tave=T0*eta(l)**(Rd*Gamma/g)
+       IF (etat>eta(l)) Tave=Tave+DeltaT*(etat-eta(l))**5
+       DO j=jj_begin-1,jj_end+1
+         DO i=ii_begin-1,ii_end+1
+           ij=(j-1)*iim+i
+           CALL xyz2lonlat(xyz_i(ij,:)/radius,lon,lat)
+            
+            Y(ij,l)=((-2*sin(lat)**6*(cos(lat)**2+1./3)+10./63)*2*u0*cos(etav(l))**1.5     &
+                                + (8./5*cos(lat)**3*(sin(lat)**2+2./3)-Pi/4)*radius*Omega)
+            T=Tave+ 0.75*(eta(l)*Pi*u0/Rd)*sin(etav(l))*cos(etav(l))**0.5 * Y(ij,l)
+            
+            theta(ij,l)=T*eta(l)**(-kappa)
+
+          ENDDO
+       ENDDO
+     ENDDO
+     
+     
+     phis_ave=T0*g/Gamma*(1-etas**(Rd*Gamma/g))
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         CALL xyz2lonlat(xyz_i(ij,:)/radius,lon,lat)
+         phis(ij)=phis_ave+u0*cos(etavs)**1.5*( (-2*sin(lat)**6 * (cos(lat)**2+1./3) + 10./63 )*u0*cos(etavs)**1.5  &
+                                           +(8./5*cos(lat)**3 * (sin(lat)**2 + 2./3) - Pi/4)*radius*Omega )
+!         phis(ij)=phis_ave+u0*cos(etavs)**1.5
+
+       ENDDO
+     ENDDO
+
+    CALL compute_theta2theta_rhodz(ps,theta,theta_rhodz,0)
+
+
+    IF (testcase==1) THEN
+    
+      q(:,:,1)=theta(:,:)
+      IF(nqtot>2) q(:,:,3)=1.
+
+      DO l=1,llm
+         dthetaodeta_ave = T0 *( Rd*Gamma/g - kappa)* eta(l)**(Rd*Gamma/g-kappa-1)
+         IF (etat>eta(l)) dthetaodeta_ave = dthetaodeta_ave - DeltaT * ( 5*(etat-eta(l))**4 * eta(l)**(-kappa)  &
+                                                          + kappa * (etat-eta(l))**5 * eta(l)**(-kappa-1))
+         DO j=jj_begin,jj_end
+           DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             CALL xyz2lonlat(xyz_i(ij,:)/radius,lon,lat)
+             dthetaodeta=dthetaodeta_ave + 3./4. * Pi * u0/Rd*(1-kappa)*eta(l)**(-kappa)*sin(etav(l))*cos(etav(l))**0.5 * Y(ij,l) & 
+                                        + 3/8. * Pi**2*u0/Rd * eta(l)**(1-kappa) * cos(etav(l))**1.5 * Y(ij,l)                    & 
+                                   - 3./16. * Pi**2 * u0 /Rd * eta(l)**(1-kappa) * sin(etav(l))**2 * cos(etav(l))**(-0.5) *Y(ij,l)&
+                                   - 9./8.  * Pi**2 * u0 /Rd * eta(l)**(1-kappa) * sin(etav(l))**2 * cos(etav(l))   &
+                                                                                  * (-2*sin(lat)**6*(cos(lat)**2+1./3.)+10./63.) 
+             dthetaodlat=3./4.*Pi*u0/Rd*eta(l)**(1-kappa)*sin(etav(l))*cos(etav(l))**0.5                                   &
+                         *( 2*u0*cos(etav(l))**1.5 * ( -12 * cos(lat)*sin(lat)**5*(cos(lat)**2+1./3.)+4*cos(lat)*sin(lat)**7) &
+                        + radius*omega*(-24./5. * sin(lat) * cos(lat)**2 * (sin(lat)**2 + 2./3.) + 16./5. * cos(lat)**4 * sin(lat)))
+                          
+             duodeta=-u0 * sin(2*lat)**2 * 3./4.*Pi * cos(etav(l))**0.5 * sin(etav(l))
+           
+             K=sin(latc)*sin(lat)+cos(latc)*cos(lat)*cos(lon-lonc)
+             r=radius*acos(K)
+             vort = -4*u0/radius*cos(etav(l))**1.5 * sin(lat) * cos(lat) * (2.-5.*sin(lat)**2)                  & 
+                    + up0/radius*exp(-(r/(0.1*radius))**2) * (tan(lat)-2*(radius/(0.1*radius))**2 * acos(K) * (sin(latc)*cos(lat) &
+                                                            -cos(latc)*sin(lat)*cos(lon-lonc))/(sqrt(1-K**2)))
+             q(ij,l,2)=ABS(g/preff*(-1./radius*duodeta*dthetaodlat-(2*sin(lat)*omega+vort)*dthetaodeta))
+             IF(nqtot>3) q(ij,l,4)=cos(lon)*cos(lat)
+           ENDDO
+         ENDDO
+       ENDDO       
+
+    ELSE IF (testcase==2) THEN
+    
+      DO l=1,llm
+         DO j=jj_begin,jj_end
+           DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             CALL xyz2lonlat(xyz_i(ij,:)/radius,lon,lat)
+             q(ij,l,1)=q0*exp(-(lat/latw)**4)*exp(-((eta(l)-1)*preff/pw)**2)
+           ENDDO
+         ENDDO
+       ENDDO
+    
+    ENDIF       
+
+        
+  END SUBROUTINE compute_etat0_dcmip4
+  
+END MODULE etat0_dcmip4_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip5.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip5.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_dcmip5.f90	(revision 329)
@@ -0,0 +1,138 @@
+MODULE etat0_dcmip5_mod
+  USE icosa
+  PRIVATE
+  REAL(rstd),PARAMETER :: zt=15000
+  REAL(rstd),PARAMETER :: q0=0.021
+  REAL(rstd),PARAMETER :: qt=1e-11
+  REAL(rstd),PARAMETER :: T0=302.15
+  REAL(rstd),PARAMETER :: Ts=302.15
+  REAL(rstd),PARAMETER :: zq1=3000
+  REAL(rstd),PARAMETER :: zq2=8000
+  REAL(rstd),PARAMETER :: Gamma=0.007
+  REAL(rstd),PARAMETER :: pb=101500
+  REAL(rstd),PARAMETER :: Deltap=1115
+  REAL(rstd),PARAMETER :: rp=282000
+  REAL(rstd),PARAMETER :: zp=7000
+  REAL(rstd),PARAMETER :: epsilon=1e-25
+  REAL(rstd),PARAMETER :: Rd=287
+  
+  REAL(rstd), PARAMETER :: lonc=Pi, latc=Pi/18, &
+       Tv0=T0*(1+0.608*q0), Tvt=Tv0-Gamma*zt
+
+  INTEGER, SAVE :: dcmip5_testcase
+
+  PUBLIC getin_etat0, compute_etat0
+
+CONTAINS
+  
+  SUBROUTINE getin_etat0
+    dcmip5_testcase=1
+    CALL getin("dcmip5_testcase",dcmip5_testcase)
+  END SUBROUTINE getin_etat0
+
+  SUBROUTINE compute_etat0(ngrid,lon,lat, phis, ps, Temp, ulon, ulat, q)
+    USE disvert_mod
+    IMPLICIT NONE
+    INTEGER, INTENT(IN)    :: ngrid
+    REAL(rstd),INTENT(IN)  :: lon(ngrid)
+    REAL(rstd),INTENT(IN)  :: lat(ngrid)
+    REAL(rstd),INTENT(OUT) :: ps(ngrid)
+    REAL(rstd),INTENT(OUT) :: phis(ngrid)
+    REAL(rstd),INTENT(OUT) :: Temp(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulon(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulat(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: q(ngrid,llm,nqtot)
+
+    INTEGER :: l,ij
+    REAL(rstd) :: r, d, d1,d2, zz, Tave, Tp, vt, aa, bb
+
+    phis(:)=0.
+
+    DO ij=1,ngrid
+       r=radius*arc(lonc,latc, lon(ij),lat(ij))
+       ps(ij)=pb-DeltaP*exp(-(r/rp)**1.5)
+    END DO
+
+    DO l=1,llm
+       aa=.5*(ap(l)+ap(l+1))
+       bb=.5*(bp(l)+bp(l+1))
+       DO ij=1,ngrid
+          r=radius*arc(lonc,latc, lon(ij),lat(ij))
+          CALL compute_z(aa+bb*ps(ij),ps(ij),r,zz)
+          IF (zz<=zt) THEN
+             q(ij,l,1)=q0*exp(-zz/zq1)*exp(-(zz/zq2)**2)
+             Tave=Tv0-Gamma*zz
+             Tp=(Tv0-Gamma*zz) * ( ( 1 + 2*Rd*(Tv0-Gamma*zz)*zz /                          &
+                  (g*zp**2*(1-pb/Deltap*exp((r/rp)**1.5+(zz/zp)**2))))**(-1) - 1) 
+             vt=-omega*sin(latc)*r+sqrt( (omega*sin(latc)*r)**2 -  1.5*(r/rp)**1.5 * (Tv0-Gamma*zz)*Rd    &
+                  / (1 + 2*Rd*(Tv0-Gamma*zz)*zz/(g*zp**2)        &
+                  - pb/Deltap * exp((r/rp)**1.5 + (zz/zp)**2 )))
+          ELSE
+             q(ij,l,1)=qt
+             Tave=Tvt
+             Tp=0
+             vt=0
+          ENDIF
+          Temp(ij,l)=Tave+Tp 
+
+          d1=sin(latc)*cos(lat(ij))-cos(latc)*sin(lat(ij))*cos(lon(ij)-lonc)
+          d2=cos(latc)*sin(lon(ij)-lonc)
+          d=MAX(1e-25,sqrt(d1**2+d2**2))
+          ulon(ij+u_right,l)=vt*d1/d
+          ulat(ij+u_right,l)=vt*d2/d
+       END DO
+    ENDDO
+  END SUBROUTINE compute_etat0
+  
+  SUBROUTINE compute_z(pmodel,ps,r,z)
+  USE icosa
+  IMPLICIT NONE
+     REAL(rstd),PARAMETER   :: epsilon0=2e-13
+     REAL(rstd),INTENT(IN)  :: pmodel
+     REAL(rstd),INTENT(IN)  :: ps
+     REAL(rstd),INTENT(IN)  :: r
+     REAL(rstd),INTENT(OUT) :: z
+     
+     REAL(rstd) :: pt, pave, pp, dpdz
+     REAL(rstd) :: znp1
+     REAL(rstd) :: epsilon
+     REAL(rstd) :: p
+     INTEGER  :: n     
+
+     pt=pb*(Tvt/Tv0)**(g/(Rd*Gamma))
+
+     IF (pmodel>pt) THEN
+       z=Tv0/Gamma*(1-(pmodel/ps)**(Rd*Gamma/g))
+     ELSE
+       z=zt+Rd*Tvt/g*log(Pt/pmodel)
+     ENDIF
+     
+     IF (z>zt .OR. r>1000000) return
+     
+     epsilon=1
+     n=0
+     
+     DO WHILE(epsilon>epsilon0 .AND. n<20)
+  
+       IF (z<zt) THEN
+         pave=pb*((Tv0-Gamma*z)/Tv0)**(g/(Rd*Gamma))
+         pp= -Deltap * exp(-(r/rp)**1.5-(z/zp)**2) *  ( (Tv0-Gamma*z)/Tv0 )**(g/(Rd*Gamma))
+       ELSE
+         pave=pt*exp(g*(zt-z)/(Rd*Tvt))
+         pp=0
+       ENDIF
+       p=pave+pp
+     
+       dpdz =  2*Deltap*z/zp**2 * exp(-(r/rp)**1.5) * exp(-(z/zp)**2) * ((Tv0-Gamma*z)/Tv0)**(g/(Rd*Gamma))  &
+             - g/(Rd*Tv0) * (preff - Deltap*exp(-(r/rp)**1.5) * exp(-(z/zp)**2)) * ( (Tv0-Gamma*z)/Tv0 )**(g/(Rd*Gamma)-1)
+           
+       znp1 = z - ( pmodel - p ) / (-dpdz)
+       
+       epsilon=ABS( (znp1-z)/znp1 )
+       z=znp1
+       n=n+1
+     ENDDO  
+   
+   END SUBROUTINE compute_z
+
+END MODULE etat0_dcmip5_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_heldsz.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_heldsz.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_heldsz.f90	(revision 329)
@@ -0,0 +1,282 @@
+MODULE etat0_heldsz_mod
+  USE icosa
+  IMPLICIT NONE
+  PRIVATE
+
+  TYPE(t_field),POINTER :: f_theta_eq(:)
+  TYPE(t_field),POINTER :: f_theta(:)
+  TYPE(t_field),POINTER :: f_clat(:) ! FIXME, duplication
+
+  REAL(rstd),ALLOCATABLE,SAVE :: knewt_t(:),kfrict(:)
+!$OMP THREADPRIVATE(knewt_t,kfrict)
+  LOGICAL, SAVE :: done=.FALSE.
+!$OMP THREADPRIVATE(done)
+
+  REAL(rstd),SAVE :: teta0,ttp,delt_y,delt_z,eps
+!$OMP THREADPRIVATE(teta0,ttp,delt_y,delt_z,eps)
+
+  REAL(rstd),SAVE :: knewt_g, k_f,k_c_a,k_c_s
+!$OMP THREADPRIVATE(knewt_g, k_f,k_c_a,k_c_s)
+
+  PUBLIC :: etat0, held_suarez
+  
+CONTAINS
+
+  SUBROUTINE test_etat0_heldsz
+    USE icosa
+    USE kinetic_mod
+    IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    TYPE(t_field),POINTER :: f_Ki(:)
+
+    REAL(rstd),POINTER :: Ki(:,:)
+    INTEGER :: ind
+
+    CALL allocate_field(f_ps,field_t,type_real)
+    CALL allocate_field(f_phis,field_t,type_real)
+    CALL allocate_field(f_theta_rhodz,field_t,type_real,llm)
+    CALL allocate_field(f_u,field_u,type_real,llm)
+    CALL allocate_field(f_Ki,field_t,type_real,llm)
+
+    CALL etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    CALL kinetic(f_u,f_Ki)
+
+    CALL writefield('ps',f_ps)
+    CALL writefield('theta',f_theta_rhodz)
+  END SUBROUTINE test_etat0_heldsz
+
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+    USE icosa
+    USE theta2theta_rhodz_mod
+    IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    REAL(rstd),POINTER :: clat(:) 
+    REAL(rstd),POINTER :: theta_eq(:,:) 
+    REAL(rstd),POINTER :: theta(:,:) 
+
+    INTEGER :: ind
+
+    CALL Init_Teq
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+
+       theta_eq=f_theta_eq(ind) 
+       clat=f_clat(ind) 
+       CALL compute_Teq(clat,theta_eq) ! FIXME : already done by Init_Teq
+
+       ps=f_ps(ind)
+       phis=f_phis(ind)
+       u=f_u(ind)
+       ps(:)=1e5
+       phis(:)=0.
+       u(:,:)=0
+
+       theta_rhodz=f_theta_rhodz(ind)
+       theta=f_theta(ind)
+       CALL compute_etat0_heldsz(theta_eq,theta)
+       CALL compute_theta2theta_rhodz(ps,theta,theta_rhodz,1)
+       q=f_q(ind)
+       q(:,:,:)=1e2
+    ENDDO
+  END SUBROUTINE etat0
+
+  SUBROUTINE init_Teq
+    USE icosa
+    USE disvert_mod, ONLY : ap,bp
+    IMPLICIT NONE
+    REAL(rstd),POINTER :: clat(:) 
+    REAL(rstd),POINTER :: theta_eq(:,:) 
+    REAL(rstd) :: zsig
+    INTEGER :: ind, l
+
+    IF(.NOT.done) THEN
+       done = .TRUE.
+       
+       CALL allocate_field(f_theta,field_t,type_real,llm)
+       CALL allocate_field(f_theta_eq,field_t,type_real,llm)
+       CALL allocate_field(f_clat,field_t,type_real)
+       ALLOCATE(knewt_t(llm)); ALLOCATE( kfrict(llm)) 
+
+       k_f=1.                !friction 
+       CALL getin('k_j',k_f)
+       k_f=1./(daysec*k_f)
+       k_c_s=4.  !cooling surface
+       CALL getin('k_c_s',k_c_s)
+       k_c_s=1./(daysec*k_c_s)
+       k_c_a=40. !cooling free atm
+       CALL getin('k_c_a',k_c_a)
+       k_c_a=1./(daysec*k_c_a)
+       ! Constants for Teta equilibrium profile
+       teta0=315.     ! mean Teta (S.H. 315K)
+       CALL getin('teta0',teta0)
+       ttp=200.       ! Tropopause temperature (S.H. 200K)
+       CALL getin('ttp',ttp)
+       eps=0.         ! Deviation to N-S symmetry(~0-20K)
+       CALL getin('eps',eps)
+       delt_y=60.     ! Merid Temp. Gradient (S.H. 60K)
+       CALL getin('delt_y',delt_y)
+       delt_z=10.     ! Vertical Gradient (S.H. 10K)
+       CALL getin('delt_z',delt_z)
+
+       !-----------------------------------------------------------
+       knewt_g=k_c_a 
+       DO l=1,llm
+          zsig=ap(l)/preff+bp(l)
+          knewt_t(l)=(k_c_s-k_c_a)*MAX(0.,(zsig-0.7)/0.3) 
+          kfrict(l)=k_f*MAX(0.,(zsig-0.7)/0.3) 
+       ENDDO
+
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+          clat=f_clat(ind)
+          theta_eq=f_theta_eq(ind)
+          CALL compute_Teq(clat,theta_eq)
+       ENDDO
+
+    ELSE
+       PRINT *, 'Init_Teq called twice'
+       CALL ABORT
+    END IF
+
+  END SUBROUTINE init_Teq
+
+  SUBROUTINE compute_Teq(clat,theta_eq)
+    USE icosa
+    USE disvert_mod
+    IMPLICIT NONE  
+    REAL(rstd),INTENT(OUT) :: clat(iim*jjm)
+    REAL(rstd),INTENT(OUT) :: theta_eq(iim*jjm,llm) 
+
+    REAL(rstd) :: lon, lat, r, zsig, ddsin, tetastrat, tetajl
+    REAL(rstd) :: slat(iim*jjm) 
+    INTEGER :: i,j,l,ij
+
+    DO j=jj_begin-1,jj_end+1
+       DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+          CALL xyz2lonlat(xyz_i(ij,:),lon,lat)
+          clat(ij)=cos(lat) 
+          slat(ij)=sin(lat) 
+       ENDDO
+    ENDDO
+
+    DO l=1,llm
+       zsig=ap(l)/preff+bp(l)
+       tetastrat=ttp*zsig**(-kappa)
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+	     ddsin=slat(ij) 
+	     tetajl=teta0-delt_y*ddsin*ddsin+eps*ddsin &
+                  -delt_z*(1.-ddsin*ddsin)*log(zsig)
+	     theta_eq(ij,l)=MAX(tetajl,tetastrat) 
+          ENDDO
+       ENDDO
+    ENDDO
+  END SUBROUTINE compute_Teq
+
+  SUBROUTINE compute_etat0_heldsz(theta_eq, theta)
+    USE icosa
+    USE disvert_mod
+    USE pression_mod
+    USE exner_mod
+    USE geopotential_mod
+    USE theta2theta_rhodz_mod
+    IMPLICIT NONE  
+    REAL(rstd),INTENT(IN) :: theta_eq(iim*jjm,llm) 
+    REAL(rstd),INTENT(OUT) :: theta(iim*jjm,llm) 
+
+    REAL(rstd) :: r  ! random number
+    INTEGER :: i,j,l,ij
+
+    DO l=1,llm
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             CALL RANDOM_NUMBER(r); r = 0.0 
+             theta(ij,l)=theta_eq(ij,l)*(1.+0.0005*r)
+          ENDDO
+       ENDDO
+    ENDDO
+
+  END SUBROUTINE compute_etat0_heldsz
+
+
+  SUBROUTINE held_suarez(f_ps,f_theta_rhodz,f_u) 
+    USE icosa
+    IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_ps(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: theta_eq(:,:)
+    REAL(rstd),POINTER :: theta(:,:)
+    REAL(rstd),POINTER :: clat(:)
+    INTEGER::ind
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       theta_rhodz=f_theta_rhodz(ind)
+       u=f_u(ind)
+       ps=f_ps(ind) 
+       theta_eq=f_theta_eq(ind) 
+       theta=f_theta(ind) 
+       clat=f_clat(ind) 
+       CALL compute_heldsz(ps,theta_eq,clat, theta_rhodz,u, theta) 
+    ENDDO
+  END SUBROUTINE held_suarez
+
+  SUBROUTINE compute_heldsz(ps,theta_eq,clat, theta_rhodz,u, theta) 
+    USE icosa
+    USE theta2theta_rhodz_mod
+    IMPLICIT NONE
+    REAL(rstd),INTENT(IN)    :: ps(iim*jjm) 
+    REAL(rstd),INTENT(IN)    :: theta_eq(iim*jjm,llm) 
+    REAL(rstd),INTENT(IN)    :: clat(iim*jjm) 
+    REAL(rstd),INTENT(INOUT) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(INOUT) :: u(3*iim*jjm,llm)
+    REAL(rstd),INTENT(OUT)   :: theta(iim*jjm,llm) 
+
+    INTEGER :: i,j,l,ij
+
+    CALL compute_theta_rhodz2theta(ps,theta_rhodz,theta,1)
+    DO l=1,llm
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             theta(ij,l)=theta(ij,l) - dt*(theta(ij,l)-theta_eq(ij,l))* &
+                  (knewt_g+knewt_t(l)*clat(ij)**4 )
+          ENDDO
+       ENDDO
+    ENDDO
+    CALL compute_theta2theta_rhodz(ps,theta,theta_rhodz,1)
+
+    Do l=1,llm
+       u(:,l)=u(:,l)*(1.-dt*kfrict(l))
+    END DO
+
+  END SUBROUTINE compute_heldsz
+
+END MODULE etat0_heldsz_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_jablonowsky06.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_jablonowsky06.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_jablonowsky06.f90	(revision 329)
@@ -0,0 +1,65 @@
+MODULE etat0_jablonowsky06_mod
+  USE icosa
+  PRIVATE
+  REAL(rstd),PARAMETER :: eta0=0.252
+  REAL(rstd),PARAMETER :: etat=0.2
+  REAL(rstd),PARAMETER :: ps0=1e5
+  REAL(rstd),PARAMETER :: u0=35
+  REAL(rstd),PARAMETER :: T0=288
+  REAL(rstd),PARAMETER :: DeltaT=4.8e5
+  REAL(rstd),PARAMETER :: Rd=287
+  REAL(rstd),PARAMETER :: Gamma=0.005
+  REAL(rstd),PARAMETER :: up0=1
+
+  PUBLIC compute_etat0
+
+CONTAINS
+  
+  SUBROUTINE compute_etat0(ngrid,lon,lat, phis, ps, temp, ulon, ulat)
+    USE disvert_mod
+    IMPLICIT NONE  
+    INTEGER, INTENT(IN) :: ngrid
+    REAL(rstd),INTENT(IN) :: lat(ngrid)
+    REAL(rstd),INTENT(IN) :: lon(ngrid)
+    REAL(rstd),INTENT(OUT) :: phis(ngrid)
+    REAL(rstd),INTENT(OUT) :: ps(ngrid)
+    REAL(rstd),INTENT(OUT) :: temp(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulon(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulat(ngrid,llm)
+    
+    INTEGER :: l,ij
+    REAL(rstd) :: eta(llm)
+    REAL(rstd) :: etav(llm)
+    REAL(rstd) :: etas, etavs, Tave, phis_ave, r2
+    
+    DO l=1,llm
+       eta(l)  = 0.5 *( ap(l)/ps0+bp(l) + ap(l+1)/ps0+bp(l+1) )
+       etav(l) = (eta(l)-eta0)*Pi/2
+    ENDDO
+    etas  = ap(1)+bp(1)
+    etavs = (etas-eta0)*Pi/2
+        
+    phis_ave=T0*g/Gamma*(1-etas**(Rd*Gamma/g))
+    DO ij=1,ngrid
+       ps(ij)=ps0
+       phis(ij) = phis_ave + u0*cos(etavs)**1.5*( (-2*sin(lat(ij))**6 * (cos(lat(ij))**2+1./3) + 10./63 )*u0*cos(etavs)**1.5  &
+            +(8./5*cos(lat(ij))**3 * (sin(lat(ij))**2 + 2./3) - Pi/4)*radius*Omega )
+    ENDDO
+
+    DO l=1,llm
+       Tave=T0*eta(l)**(Rd*Gamma/g)
+       IF (etat>eta(l)) Tave=Tave+DeltaT*(etat-eta(l))**5
+       DO ij=1,ngrid
+          r2 = arc(Pi/9.,2.*Pi/9., lon(ij),lat(ij))**2
+          temp(ij,l) = Tave + 0.75*(eta(l)*Pi*u0/Rd)*sin(etav(l))*cos(etav(l))**0.5  &
+               * ( (-2*sin(lat(ij))**6*(cos(lat(ij))**2+1./3)+10./63)*2*u0*cos(etav(l))**1.5 &
+               + (8./5*cos(lat(ij))**3*(sin(lat(ij))**2+2./3)-Pi/4)*radius*Omega)
+          ulon(ij,l) = u0*cos(etav(l))**1.5*sin(2*lat(ij))**2 + up0*exp(-r2/0.01)
+          ulat(ij,l) = 0
+       ENDDO
+    ENDDO
+    
+    
+  END SUBROUTINE compute_etat0
+  
+END MODULE etat0_jablonowsky06_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_start_file.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_start_file.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_start_file.f90	(revision 329)
@@ -0,0 +1,71 @@
+MODULE etat0_start_file_mod
+
+
+
+
+CONTAINS
+  
+   
+  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  USE restart_mod
+  USE wind_mod
+  USE write_field
+  USE time_mod
+  USE transfert_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    TYPE(t_field),POINTER,SAVE :: f_ulon(:)
+    TYPE(t_field),POINTER,SAVE :: f_ulat(:)
+
+    LOGICAL :: etat0_start_file_colocated=.FALSE.
+    INTEGER :: ind
+
+      CALL getin("etat0_start_file_colocated",etat0_start_file_colocated)  
+
+      IF (.NOT. etat0_start_file_colocated) THEN    
+        CALL allocate_field(f_ulon,field_t,type_real,llm,name='ulon')
+        CALL allocate_field(f_ulat,field_t,type_real,llm,name='ulat')
+        CALL read_start(itau0,f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+        CALL transfert_request(f_ps,req_i1)
+        CALL transfert_request(f_phis,req_i1)
+        CALL transfert_request(f_theta_rhodz,req_i1)
+        CALL transfert_request(f_q,req_i1)
+        CALL transfert_request(f_u,req_e1_vect)
+        CALL transfert_request(f_u,req_e0_vect)
+        CALL un2ulonlat(f_u,f_ulon,f_ulat)
+
+        CALL deallocate_field(f_ulon)
+        CALL deallocate_field(f_ulat)
+
+      ELSE
+        CALL allocate_field(f_ulon,field_t,type_real,llm,name='ulon')
+        CALL allocate_field(f_ulat,field_t,type_real,llm,name='ulat')
+        CALL read_start(itau0,f_ps,f_phis,f_theta_rhodz,f_ulon,f_ulat, f_q)
+        CALL transfert_request(f_ulat,req_i1)
+        CALL transfert_request(f_ulon,req_i1)
+
+        CALL ulonlat2un(f_ulon,f_ulat,f_u)
+
+        CALL transfert_request(f_ps,req_i1)
+        CALL transfert_request(f_phis,req_i1)
+        CALL transfert_request(f_theta_rhodz,req_i1)
+        CALL transfert_request(f_q,req_i1)
+        CALL transfert_request(f_u,req_e1_vect)
+        
+        CALL deallocate_field(f_ulon)
+        CALL deallocate_field(f_ulat)
+      ENDIF
+
+      CALL bcast(itau0)
+      CALL getin("etat0_start_iteration",itau0)        
+
+  END SUBROUTINE etat0
+  
+  
+END MODULE etat0_start_file_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_temperature.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_temperature.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_temperature.f90	(revision 329)
@@ -0,0 +1,80 @@
+MODULE etat0_temperature_mod
+  USE prec
+  USE icosa, ONLY: llm,nqtot
+  IMPLICIT NONE
+  REAL(rstd), SAVE, ALLOCATABLE :: t_profile(:)
+!$OMP THREADPRIVATE(t_profile)
+CONTAINS
+  
+  SUBROUTINE getin_etat0
+    USE getin_mod, ONLY: getin
+    USE mpipara, ONLY: is_mpi_root
+    USE omp_para, ONLY: omp_in_parallel
+    USE transfert_omp_mod, ONLY: bcast_omp
+    USE free_unit_mod, ONLY : free_unit
+    IMPLICIT NONE
+    INTEGER :: unit,ok
+    INTEGER :: l
+    CHARACTER(len=255) :: temperature_file
+  
+    temperature_file="profile.in" ! default file name
+    ! but users may want to use some other file name
+    CALL getin("temperature_profile_file",temperature_file)
+    
+    ALLOCATE(t_profile(llm))
+ 
+ !$OMP MASTER
+    unit=free_unit()
+    OPEN(unit,file=temperature_file,status="old",action="read",iostat=ok)
+    IF (ok/=0) THEN
+      WRITE(*,*) "getin_etat0 error: input file ",trim(temperature_file)," not found!"
+      CALL ABORT
+    ENDIF
+    ! read in t_profile() line by line, starting from first atmospheric
+    ! layer, up to model top
+    DO l=1,llm
+      READ(unit,fmt=*,iostat=ok) t_profile(l)
+      IF (ok/=0) THEN
+        WRITE(*,*) "getin_etat0 error: failed reading t_profile(l) for l=",l
+        CALL ABORT
+      ENDIF
+    ENDDO
+    
+    CLOSE(unit)
+    IF (is_mpi_root) THEN
+      WRITE(*,*) "Using input temperature profile from file ",trim(temperature_file),":"
+      DO l=1,llm
+         WRITE(*,*) "  TEMP(l=",l,")=",t_profile(l)
+      ENDDO
+    ENDIF
+!$OMP END MASTER
+
+    IF (omp_in_parallel()) THEN
+      CALL bcast_omp(t_profile)
+    ENDIF
+    
+  END SUBROUTINE getin_etat0
+
+  SUBROUTINE compute_etat0(ngrid, phis, ps, temp, ulon, ulat, q)
+    USE earth_const, ONLY: preff
+    IMPLICIT NONE  
+    INTEGER, INTENT(IN)    :: ngrid
+    REAL(rstd),INTENT(OUT) :: phis(ngrid)
+    REAL(rstd),INTENT(OUT) :: ps(ngrid)
+    REAL(rstd),INTENT(OUT) :: temp(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulon(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: ulat(ngrid,llm)
+    REAL(rstd),INTENT(OUT) :: q(ngrid,llm,nqtot)
+    INTEGER :: l
+    phis(:)=0
+    ps(:)=preff
+    DO l=1,llm
+      temp(:,l)=t_profile(l)
+    ENDDO
+    ulon(:,:)=0
+    ulat(:,:)=0
+    q(:,:,:)=0
+
+  END SUBROUTINE compute_etat0
+
+END MODULE etat0_temperature_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_williamson.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_williamson.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/etat0_williamson.f90	(revision 329)
@@ -0,0 +1,59 @@
+MODULE etat0_williamson_mod
+  USE icosa
+  PRIVATE
+  REAL(rstd), PARAMETER :: h0=8.E3
+  REAL(rstd), PARAMETER :: R0=4
+  REAL(rstd), PARAMETER :: K0=7.848E-6
+  REAL(rstd), PARAMETER :: omega0=K0
+  
+  PUBLIC getin_etat0, compute_etat0
+  
+CONTAINS
+
+  SUBROUTINE getin_etat0
+    USE mpipara, ONLY : is_mpi_root
+    USE disvert_mod, ONLY : caldyn_eta, eta_lag
+    IF(caldyn_eta /= eta_lag) THEN
+       IF(is_mpi_root) PRINT *, 'etat0_type=williamson91.6 (Williamson,1991) must be used with caldyn_eta=eta_lag'
+       STOP
+    END IF
+
+    IF(llm>1) THEN
+       IF(is_mpi_root) PRINT *, 'etat0_type=williamson91.6 (Williamson,1991) must be used with llm=1 but llm =',llm
+       STOP
+    END IF
+  END SUBROUTINE getin_etat0
+
+  SUBROUTINE compute_etat0(ngrid,lon,lat, phis,mass,rhodz,ulon,ulat)
+    IMPLICIT NONE  
+    INTEGER, INTENT(IN)    :: ngrid
+    REAL(rstd),INTENT(IN)  :: lon(ngrid)
+    REAL(rstd),INTENT(IN)  :: lat(ngrid)
+    REAL(rstd),INTENT(OUT) :: phis(ngrid)
+    REAL(rstd),INTENT(OUT) :: mass(ngrid)
+    REAL(rstd),INTENT(OUT) :: rhodz(ngrid)
+    REAL(rstd),INTENT(OUT) :: ulon(ngrid)
+    REAL(rstd),INTENT(OUT) :: ulat(ngrid)
+
+    REAL(rstd) :: coslat,sinlat, A,B,C    
+    INTEGER :: ij
+    
+    DO ij=1,ngrid
+       coslat=cos(lat(ij))
+       sinlat=sin(lat(ij))
+       A = 0.5*omega0*(2*omega+omega0)*coslat**2   &
+            + 0.25*K0**2*coslat**(2*R0)*((R0+1)*coslat**2+(2*R0**2-R0-2)-2*R0**2/coslat**2)
+       B = 2*(omega+omega0)*K0/((R0+1)*(R0+2))*coslat**R0*((R0**2+2*R0+2)-(R0+1)**2*coslat**2)
+       C = 0.25*K0**2*coslat**(2*R0)*((R0+1)*coslat**2-(R0+2))
+       
+       mass(ij) = (g*h0+radius**2*A+radius**2*B*cos(R0*lon(ij))+radius**2*C*cos(2*R0*lon(ij)))/g
+       ulon(ij) = radius*omega0*coslat+radius*K0*coslat**(R0-1)*(R0*sinlat**2-coslat**2)*cos(R0*lon(ij))
+       ulat(ij) = -radius*K0*R0*coslat**(R0-1)*sinlat*sin(R0*lon(ij))
+    ENDDO
+
+    phis(:)=0.
+    rhodz(:)=mass(:)
+
+  END SUBROUTINE compute_etat0
+  
+END MODULE etat0_williamson_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/exner.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/exner.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/exner.f90	(revision 329)
@@ -0,0 +1,120 @@
+MODULE exner_mod
+
+  INTEGER,SAVE :: caldyn_exner
+!$OMP THREADPRIVATE(caldyn_exner)
+
+  INTEGER, PARAMETER :: lmdz=3, direct=4
+
+CONTAINS
+  
+  SUBROUTINE exner(f_ps,f_p,f_pks,f_pk)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ps(:)
+    TYPE(t_field), POINTER :: f_p(:)
+    TYPE(t_field), POINTER :: f_pks(:)
+    TYPE(t_field), POINTER :: f_pk(:)
+  
+    REAL(rstd), POINTER :: ps(:)
+    REAL(rstd), POINTER :: p(:,:)
+    REAL(rstd), POINTER :: pks(:)
+    REAL(rstd), POINTER :: pk(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      p=f_p(ind)
+      pks=f_pks(ind)
+      pk=f_pk(ind)
+      CALL compute_exner(ps, p, pks, pk, 0)
+    ENDDO
+  
+  END SUBROUTINE exner
+  
+  SUBROUTINE compute_exner(ps,p,pks,pk,offset)
+  USE icosa
+  USE disvert_mod
+  USE pression_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd),INTENT(IN) :: p(iim*jjm,llm+1)
+    REAL(rstd),INTENT(OUT) :: pks(iim*jjm)
+    REAL(rstd),INTENT(OUT) :: pk(iim*jjm,llm)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: alpha(iim*jjm,llm),beta(iim*jjm,llm)
+    REAL(rstd) :: delta 
+    
+    IF(caldyn_exner == lmdz) THEN          ! LMD-Z style calculation of Exner pressure
+       !! Compute Alpha and Beta
+       
+       ! for llm layer
+       DO j=jj_begin-offset,jj_end+offset
+          DO i=ii_begin-offset,ii_end+offset
+             ij=(j-1)*iim+i
+             alpha(ij,llm) = 0.
+             beta (ij,llm) = 1./ (1+ 2*kappa)
+          ENDDO
+       ENDDO
+       
+       ! for other layer   
+       DO l = llm-1 , 2 , -1
+          DO j=jj_begin-offset,jj_end+offset
+             DO i=ii_begin-offset,ii_end+offset
+                ij=(j-1)*iim+i
+                delta = p(ij,l)* (1+2*kappa) + p(ij,l+1)* ( beta(ij,l+1)- (1+2*kappa) )
+                alpha(ij,l)  = - p(ij,l+1) / delta * alpha(ij,l+1)
+                beta (ij,l)  =   p(ij,l  ) / delta   
+             ENDDO
+          ENDDO
+       ENDDO
+       
+       !! Compute pk
+       
+       ! for first layer
+       DO j=jj_begin-offset,jj_end+offset
+          DO i=ii_begin-offset,ii_end+offset
+             ij=(j-1)*iim+i
+             pks(ij) = cpp * ( ps(ij)/preff ) ** kappa
+             pk(ij,1) = ( p(ij,1)*pks(ij) - 0.5*alpha(ij,2)*p(ij,2) )     /    &
+                  (  p(ij,1)* (1.+kappa) + 0.5*( beta(ij,2)-(1.+2*kappa) )* p(ij,2) )
+          ENDDO
+       ENDDO
+       
+       ! for other layers
+       
+       DO l = 2, llm
+          DO j=jj_begin-offset,jj_end+offset
+             DO i=ii_begin-offset,ii_end+offset
+                ij=(j-1)*iim+i
+                pk(ij,l) = alpha(ij,l) + beta(ij,l) * pk(ij,l-1)
+             ENDDO
+          ENDDO
+       ENDDO
+       
+    ELSE ! Simple calculation of Exner pressure based on centered average
+       ! surface : pks
+       DO j=jj_begin-offset,jj_end+offset
+          DO i=ii_begin-offset,ii_end+offset
+             ij=(j-1)*iim+i
+             pks(ij) = cpp * ( ps(ij)/preff ) ** kappa
+          ENDDO
+       ENDDO
+
+       ! 3D : pk
+       DO l = 1, llm
+          DO j=jj_begin-offset,jj_end+offset
+             DO i=ii_begin-offset,ii_end+offset
+                ij=(j-1)*iim+i
+                pk(ij,l) = cpp * ((.5/preff)*(p(ij,l)+p(ij,l+1))) ** kappa
+             ENDDO
+          ENDDO
+       ENDDO
+    END IF
+    
+  END SUBROUTINE compute_exner
+  
+END MODULE exner_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/field.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/field.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/field.f90	(revision 329)
@@ -0,0 +1,339 @@
+MODULE field_mod
+  USE genmod
+  
+  INTEGER,PARAMETER :: field_T=1
+  INTEGER,PARAMETER :: field_U=2
+  INTEGER,PARAMETER :: field_Z=3
+
+  INTEGER,PARAMETER :: type_integer=1
+  INTEGER,PARAMETER :: type_real=2
+  INTEGER,PARAMETER :: type_logical=3
+    
+  TYPE t_field
+    CHARACTER(30)      :: name
+    REAL(rstd),POINTER :: rval2d(:)
+    REAL(rstd),POINTER :: rval3d(:,:)
+    REAL(rstd),POINTER :: rval4d(:,:,:)
+
+    INTEGER,POINTER :: ival2d(:)
+    INTEGER,POINTER :: ival3d(:,:)
+    INTEGER,POINTER :: ival4d(:,:,:)
+    
+    LOGICAL,POINTER :: lval2d(:)
+    LOGICAL,POINTER :: lval3d(:,:)
+    LOGICAL,POINTER :: lval4d(:,:,:)
+
+    INTEGER :: ndim
+    INTEGER :: field_type
+    INTEGER :: data_type 
+    INTEGER :: dim3
+    INTEGER :: dim4
+  END TYPE t_field   
+
+  INTERFACE get_val
+    MODULE PROCEDURE getval_r2d,getval_r3d,getval_r4d, &
+                     getval_i2d,getval_i3d,getval_i4d, &
+                     getval_l2d,getval_l3d,getval_l4d
+  END INTERFACE
+                   
+  INTERFACE ASSIGNMENT(=)
+    MODULE PROCEDURE getval_r2d,getval_r3d,getval_r4d, &
+                     getval_i2d,getval_i3d,getval_i4d, &
+                     getval_l2d,getval_l3d,getval_l4d 
+  END INTERFACE
+
+
+CONTAINS
+
+  SUBROUTINE allocate_field(field,field_type,data_type,dim1,dim2,name)
+  USE domain_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER,INTENT(IN) :: field_type
+    INTEGER,INTENT(IN) :: data_type
+    INTEGER,OPTIONAL :: dim1,dim2
+    CHARACTER(*), OPTIONAL :: name
+    INTEGER :: ind
+    INTEGER :: ii_size,jj_size
+
+!$OMP BARRIER
+!$OMP MASTER
+    ALLOCATE(field(ndomain))
+!$OMP END MASTER
+!$OMP BARRIER
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+
+      IF(PRESENT(name)) THEN
+         field(ind)%name = name
+      ELSE
+         field(ind)%name = '(undefined)'
+      END IF
+
+      IF (PRESENT(dim2)) THEN
+        field(ind)%ndim=4 
+        field(ind)%dim4=dim2 
+        field(ind)%dim3=dim1
+      ELSE IF (PRESENT(dim1)) THEN
+        field(ind)%ndim=3
+        field(ind)%dim3=dim1
+      ELSE
+        field(ind)%ndim=2
+      ENDIF
+    
+    
+      field(ind)%data_type=data_type
+      field(ind)%field_type=field_type
+    
+      IF (field_type==field_T) THEN 
+        jj_size=domain(ind)%jjm
+      ELSE IF (field_type==field_U) THEN 
+        jj_size=3*domain(ind)%jjm
+      ELSE IF (field_type==field_Z) THEN 
+        jj_size=2*domain(ind)%jjm
+      ENDIF
+      
+      ii_size=domain(ind)%iim
+        
+      IF (field(ind)%ndim==4) THEN
+        IF (data_type==type_integer) ALLOCATE(field(ind)%ival4d(ii_size*jj_size,dim1,dim2))
+        IF (data_type==type_real)    ALLOCATE(field(ind)%rval4d(ii_size*jj_size,dim1,dim2))
+        IF (data_type==type_logical) ALLOCATE(field(ind)%lval4d(ii_size*jj_size,dim1,dim2))
+      ELSE IF (field(ind)%ndim==3) THEN
+        IF (data_type==type_integer) ALLOCATE(field(ind)%ival3d(ii_size*jj_size,dim1))
+        IF (data_type==type_real)    ALLOCATE(field(ind)%rval3d(ii_size*jj_size,dim1))
+        IF (data_type==type_logical) ALLOCATE(field(ind)%lval3d(ii_size*jj_size,dim1))
+      ELSE IF (field(ind)%ndim==2) THEN
+        IF (data_type==type_integer) ALLOCATE(field(ind)%ival2d(ii_size*jj_size))
+        IF (data_type==type_real)    ALLOCATE(field(ind)%rval2d(ii_size*jj_size))
+        IF (data_type==type_logical) ALLOCATE(field(ind)%lval2d(ii_size*jj_size))
+      ENDIF
+      
+   ENDDO
+!$OMP BARRIER
+   
+  END SUBROUTINE allocate_field
+
+  SUBROUTINE allocate_field_glo(field,field_type,data_type,dim1,dim2,name)
+  USE domain_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER,INTENT(IN) :: field_type
+    INTEGER,INTENT(IN) :: data_type
+    INTEGER,OPTIONAL :: dim1,dim2
+    CHARACTER(*), OPTIONAL :: name
+    INTEGER :: ind
+    INTEGER :: ii_size,jj_size
+
+    ALLOCATE(field(ndomain_glo))    
+
+    DO ind=1,ndomain_glo
+  
+      IF (PRESENT(dim2)) THEN
+        field(ind)%ndim=4 
+        field(ind)%dim4=dim2 
+        field(ind)%dim3=dim1 
+      ELSE IF (PRESENT(dim1)) THEN
+        field(ind)%ndim=3
+        field(ind)%dim3=dim1 
+      ELSE
+        field(ind)%ndim=2
+      ENDIF
+    
+      IF(PRESENT(name)) THEN
+         field(ind)%name = name
+      ELSE
+         field(ind)%name = '(undefined)'
+      END IF
+    
+      field(ind)%data_type=data_type
+      field(ind)%field_type=field_type
+    
+      IF (field_type==field_T) THEN 
+        jj_size=domain_glo(ind)%jjm
+      ELSE IF (field_type==field_U) THEN 
+        jj_size=3*domain_glo(ind)%jjm
+      ELSE IF (field_type==field_Z) THEN 
+        jj_size=2*domain_glo(ind)%jjm
+      ENDIF
+      
+      ii_size=domain_glo(ind)%iim
+        
+      IF (field(ind)%ndim==4) THEN
+        IF (data_type==type_integer) ALLOCATE(field(ind)%ival4d(ii_size*jj_size,dim1,dim2))
+        IF (data_type==type_real)    ALLOCATE(field(ind)%rval4d(ii_size*jj_size,dim1,dim2))
+        IF (data_type==type_logical) ALLOCATE(field(ind)%lval4d(ii_size*jj_size,dim1,dim2))
+      ELSE IF (field(ind)%ndim==3) THEN
+        IF (data_type==type_integer) ALLOCATE(field(ind)%ival3d(ii_size*jj_size,dim1))
+        IF (data_type==type_real)    ALLOCATE(field(ind)%rval3d(ii_size*jj_size,dim1))
+        IF (data_type==type_logical) ALLOCATE(field(ind)%lval3d(ii_size*jj_size,dim1))
+      ELSE IF (field(ind)%ndim==2) THEN
+        IF (data_type==type_integer) ALLOCATE(field(ind)%ival2d(ii_size*jj_size))
+        IF (data_type==type_real)    ALLOCATE(field(ind)%rval2d(ii_size*jj_size))
+        IF (data_type==type_logical) ALLOCATE(field(ind)%lval2d(ii_size*jj_size))
+      ENDIF
+      
+   ENDDO
+  
+  END SUBROUTINE allocate_field_glo
+
+  SUBROUTINE deallocate_field(field)
+  USE domain_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER :: data_type
+    INTEGER :: ind
+
+!$OMP BARRIER
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+
+      data_type=field(ind)%data_type
+        
+      IF (field(ind)%ndim==4) THEN
+        IF (data_type==type_integer) DEALLOCATE(field(ind)%ival4d)
+        IF (data_type==type_real)    DEALLOCATE(field(ind)%rval4d)
+        IF (data_type==type_logical) DEALLOCATE(field(ind)%lval4d)
+      ELSE IF (field(ind)%ndim==3) THEN
+        IF (data_type==type_integer) DEALLOCATE(field(ind)%ival3d)
+        IF (data_type==type_real)    DEALLOCATE(field(ind)%rval3d)
+        IF (data_type==type_logical) DEALLOCATE(field(ind)%lval3d)
+      ELSE IF (field(ind)%ndim==2) THEN
+        IF (data_type==type_integer) DEALLOCATE(field(ind)%ival2d)
+        IF (data_type==type_real)    DEALLOCATE(field(ind)%rval2d)
+        IF (data_type==type_logical) DEALLOCATE(field(ind)%lval2d)
+      ENDIF
+      
+   ENDDO
+!$OMP BARRIER
+!$OMP MASTER
+   DEALLOCATE(field)
+!$OMP END MASTER
+!$OMP BARRIER
+       
+  END SUBROUTINE deallocate_field
+
+  SUBROUTINE deallocate_field_glo(field)
+  USE domain_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER :: data_type
+    INTEGER :: ind
+
+    DO ind=1,ndomain_glo
+
+      data_type=field(ind)%data_type
+        
+      IF (field(ind)%ndim==4) THEN
+        IF (data_type==type_integer) DEALLOCATE(field(ind)%ival4d)
+        IF (data_type==type_real)    DEALLOCATE(field(ind)%rval4d)
+        IF (data_type==type_logical) DEALLOCATE(field(ind)%lval4d)
+      ELSE IF (field(ind)%ndim==3) THEN
+        IF (data_type==type_integer) DEALLOCATE(field(ind)%ival3d)
+        IF (data_type==type_real)    DEALLOCATE(field(ind)%rval3d)
+        IF (data_type==type_logical) DEALLOCATE(field(ind)%lval3d)
+      ELSE IF (field(ind)%ndim==2) THEN
+        IF (data_type==type_integer) DEALLOCATE(field(ind)%ival2d)
+        IF (data_type==type_real)    DEALLOCATE(field(ind)%rval2d)
+        IF (data_type==type_logical) DEALLOCATE(field(ind)%lval2d)
+      ENDIF
+      
+   ENDDO
+   DEALLOCATE(field)
+       
+  END SUBROUTINE deallocate_field_glo
+    
+  SUBROUTINE getval_r2d(field_pt,field)
+  IMPLICIT NONE  
+    REAL(rstd),POINTER,INTENT(INOUT) :: field_pt(:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=2 .OR. field%data_type/=type_real) THEN
+       PRINT *, 'get_val_r2d : bad pointer assignment with ' // TRIM(field%name) 
+       STOP
+    END IF
+    field_pt=>field%rval2d
+  END SUBROUTINE  getval_r2d
+
+  SUBROUTINE getval_r3d(field_pt,field)
+  IMPLICIT NONE  
+    REAL(rstd),POINTER,INTENT(INOUT) :: field_pt(:,:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=3 .OR. field%data_type/=type_real) THEN
+       PRINT *, 'get_val_r3d : bad pointer assignment with ' // TRIM(field%name) 
+       STOP
+!       CALL ABORT
+    END IF
+    field_pt=>field%rval3d
+  END SUBROUTINE  getval_r3d
+
+  SUBROUTINE getval_r4d(field_pt,field)
+  IMPLICIT NONE  
+    REAL(rstd),POINTER,INTENT(INOUT) :: field_pt(:,:,:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=4 .OR. field%data_type/=type_real) THEN
+       PRINT *, 'get_val_r4d : bad pointer assignment with ' // TRIM(field%name)
+       STOP
+    END IF
+    field_pt=>field%rval4d
+  END SUBROUTINE  getval_r4d  
+
+  
+  SUBROUTINE getval_i2d(field_pt,field)
+  IMPLICIT NONE  
+    INTEGER,POINTER,INTENT(INOUT) :: field_pt(:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=2 .OR. field%data_type/=type_integer) STOP 'get_val_i2d : bad pointer assignment'        
+    field_pt=>field%ival2d
+  END SUBROUTINE  getval_i2d
+
+  SUBROUTINE getval_i3d(field_pt,field)
+  IMPLICIT NONE  
+    INTEGER,POINTER,INTENT(INOUT) :: field_pt(:,:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=3 .OR. field%data_type/=type_integer) STOP 'get_val_i3d : bad pointer assignment'        
+    field_pt=>field%ival3d
+  END SUBROUTINE  getval_i3d
+
+  SUBROUTINE getval_i4d(field_pt,field)
+  IMPLICIT NONE  
+    INTEGER,POINTER,INTENT(INOUT) :: field_pt(:,:,:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=4 .OR. field%data_type/=type_integer) STOP 'get_val_i4d : bad pointer assignment'        
+    field_pt=>field%ival4d
+  END SUBROUTINE  getval_i4d
+
+  SUBROUTINE getval_l2d(field_pt,field)
+  IMPLICIT NONE  
+    LOGICAL,POINTER,INTENT(INOUT) :: field_pt(:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=2 .OR. field%data_type/=type_logical) STOP 'get_val_l2d : bad pointer assignment'        
+    field_pt=>field%lval2d
+  END SUBROUTINE  getval_l2d
+
+  SUBROUTINE getval_l3d(field_pt,field)
+  IMPLICIT NONE  
+    LOGICAL,POINTER,INTENT(INOUT) :: field_pt(:,:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=3 .OR. field%data_type/=type_logical) STOP 'get_val_l3d : bad pointer assignment'        
+    field_pt=>field%lval3d
+  END SUBROUTINE  getval_l3d
+
+  SUBROUTINE getval_l4d(field_pt,field)
+  IMPLICIT NONE  
+    LOGICAL,POINTER,INTENT(INOUT) :: field_pt(:,:,:)
+    TYPE(t_field),INTENT(IN) :: field
+    
+    IF (field%ndim/=4 .OR. field%data_type/=type_logical) STOP 'get_val_l4d : bad pointer assignment'        
+    field_pt=>field%lval4d
+  END SUBROUTINE  getval_l4d    
+
+END MODULE field_mod   
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/free_unit_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/free_unit_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/free_unit_mod.f90	(revision 329)
@@ -0,0 +1,26 @@
+MODULE free_unit_mod
+
+  PRIVATE 
+
+  INTEGER, PARAMETER :: start_unit=1000
+
+  PUBLIC :: free_unit
+
+CONTAINS
+
+  FUNCTION free_unit
+    INTEGER :: free_unit
+    LOGICAL :: out
+    
+    out=.FALSE.
+    free_unit=start_unit
+    
+    DO WHILE (.NOT. out)
+      free_unit=free_unit+1
+      INQUIRE(unit=free_unit, exist=out)
+    END DO
+    
+  END FUNCTION free_unit
+  
+END MODULE free_unit_mod
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/genmod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/genmod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/genmod.f90	(revision 329)
@@ -0,0 +1,5 @@
+MODULE genmod
+  USE prec
+  USE math_const
+  USE earth_const
+END MODULE genmod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/geometry.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/geometry.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/geometry.f90	(revision 329)
@@ -0,0 +1,576 @@
+MODULE geometry
+  USE field_mod
+  
+  TYPE t_geometry
+    TYPE(t_field),POINTER :: xyz_i(:)
+    TYPE(t_field),POINTER :: centroid(:)
+    TYPE(t_field),POINTER :: xyz_e(:)
+    TYPE(t_field),POINTER :: xyz_v(:)
+    TYPE(t_field),POINTER :: ep_e(:)
+    TYPE(t_field),POINTER :: et_e(:)
+    TYPE(t_field),POINTER :: elon_i(:)
+    TYPE(t_field),POINTER :: elat_i(:)
+    TYPE(t_field),POINTER :: elon_e(:)
+    TYPE(t_field),POINTER :: elat_e(:)
+    TYPE(t_field),POINTER :: Ai(:)
+    TYPE(t_field),POINTER :: Av(:)
+    TYPE(t_field),POINTER :: de(:)
+    TYPE(t_field),POINTER :: le(:)
+    TYPE(t_field),POINTER :: Riv(:)
+    TYPE(t_field),POINTER :: Riv2(:)
+    TYPE(t_field),POINTER :: ne(:)
+    TYPE(t_field),POINTER :: Wee(:)
+    TYPE(t_field),POINTER :: bi(:)
+    TYPE(t_field),POINTER :: fv(:)
+  END TYPE t_geometry    
+
+  TYPE(t_geometry),SAVE,TARGET :: geom
+
+  
+  REAL(rstd),POINTER :: Ai(:)          ! area of a cell
+!$OMP THREADPRIVATE(Ai)
+  REAL(rstd),POINTER :: xyz_i(:,:)     ! coordinate of the center of the cell (voronoi)
+!$OMP THREADPRIVATE(xyz_i)
+  REAL(rstd),POINTER :: centroid(:,:)  ! coordinate of the centroid of the cell
+!$OMP THREADPRIVATE(centroid)
+  REAL(rstd),POINTER :: xyz_e(:,:)     ! coordinate of a wind point on the cell on a edge
+!$OMP THREADPRIVATE(xyz_e)
+  REAL(rstd),POINTER :: ep_e(:,:)      ! perpendicular unit vector of a edge (outsider)
+!$OMP THREADPRIVATE(ep_e)
+  REAL(rstd),POINTER :: et_e(:,:)      ! tangeantial unit vector of a edge
+!$OMP THREADPRIVATE(et_e)
+  REAL(rstd),POINTER :: elon_i(:,:)    ! unit longitude vector on the center 
+!$OMP THREADPRIVATE(elon_i)
+  REAL(rstd),POINTER :: elat_i(:,:)    ! unit latitude vector on the center 
+!$OMP THREADPRIVATE(elat_i)
+  REAL(rstd),POINTER :: elon_e(:,:)    ! unit longitude vector on a wind point 
+!$OMP THREADPRIVATE(elon_e)
+  REAL(rstd),POINTER :: elat_e(:,:)    ! unit latitude vector on a wind point
+!$OMP THREADPRIVATE(elat_e)
+  REAL(rstd),POINTER :: xyz_v(:,:)     ! coordinate of a vertex (center of the dual mesh)
+!$OMP THREADPRIVATE(xyz_v)
+  REAL(rstd),POINTER :: Av(:)          ! area of dual mesk cell
+!$OMP THREADPRIVATE(Av)
+  REAL(rstd),POINTER :: de(:)          ! distance from a neighbour == lenght of an edge of the dual mesh
+!$OMP THREADPRIVATE(de)
+  REAL(rstd),POINTER :: le(:)          ! lenght of a edge
+!$OMP THREADPRIVATE(le)
+  REAL(rstd),POINTER :: Riv(:,:)       ! weight
+!$OMP THREADPRIVATE(Riv)
+  REAL(rstd),POINTER :: Riv2(:,:)      ! weight
+!$OMP THREADPRIVATE(Riv2)
+  INTEGER,POINTER    :: ne(:,:)        ! convention for the way on the normal wind on an edge 
+!$OMP THREADPRIVATE(ne)
+  REAL(rstd),POINTER :: Wee(:,:,:)     ! weight
+!$OMP THREADPRIVATE(Wee)
+  REAL(rstd),POINTER :: bi(:)          ! orographie
+!$OMP THREADPRIVATE(bi)
+  REAL(rstd),POINTER :: fv(:)          ! coriolis (evaluted on a vertex)
+!$OMP THREADPRIVATE(fv)
+     
+
+  INTEGER, PARAMETER :: ne_right=1
+  INTEGER, PARAMETER :: ne_rup=-1
+  INTEGER, PARAMETER :: ne_lup=1
+  INTEGER, PARAMETER :: ne_left=-1
+  INTEGER, PARAMETER :: ne_ldown=1
+  INTEGER, PARAMETER :: ne_rdown=-1
+
+CONTAINS
+
+  SUBROUTINE allocate_geometry
+  USE field_mod
+  IMPLICIT NONE
+  
+    CALL allocate_field(geom%Ai,field_t,type_real,name='Ai')
+    CALL allocate_field(geom%xyz_i,field_t,type_real,3)
+    CALL allocate_field(geom%centroid,field_t,type_real,3)
+    CALL allocate_field(geom%xyz_e,field_u,type_real,3)
+    CALL allocate_field(geom%ep_e,field_u,type_real,3)
+    CALL allocate_field(geom%et_e,field_u,type_real,3)
+    CALL allocate_field(geom%elon_i,field_t,type_real,3)
+    CALL allocate_field(geom%elat_i,field_t,type_real,3)
+    CALL allocate_field(geom%elon_e,field_u,type_real,3)
+    CALL allocate_field(geom%elat_e,field_u,type_real,3)
+    CALL allocate_field(geom%xyz_v,field_z,type_real,3)
+    CALL allocate_field(geom%de,field_u,type_real)
+    CALL allocate_field(geom%le,field_u,type_real)
+    CALL allocate_field(geom%bi,field_t,type_real)
+    CALL allocate_field(geom%Av,field_z,type_real)
+    CALL allocate_field(geom%Riv,field_t,type_real,6)
+    CALL allocate_field(geom%Riv2,field_t,type_real,6)
+    CALL allocate_field(geom%ne,field_t,type_integer,6)
+    CALL allocate_field(geom%Wee,field_u,type_real,5,2)
+    CALL allocate_field(geom%bi,field_t,type_real)
+    CALL allocate_field(geom%fv,field_z,type_real)
+
+  END SUBROUTINE allocate_geometry
+  
+  
+  SUBROUTINE swap_geometry(ind)
+  USE field_mod
+  IMPLICIT NONE
+    INTEGER,INTENT(IN) :: ind
+!!$OMP MASTER
+    Ai=geom%Ai(ind)
+    xyz_i=geom%xyz_i(ind)
+    centroid=geom%centroid(ind)
+    xyz_e=geom%xyz_e(ind)
+    ep_e=geom%ep_e(ind)
+    et_e=geom%et_e(ind)
+    elon_i=geom%elon_i(ind)
+    elat_i=geom%elat_i(ind)
+    elon_e=geom%elon_e(ind)
+    elat_e=geom%elat_e(ind)
+    xyz_v=geom%xyz_v(ind)
+    de=geom%de(ind)
+    le=geom%le(ind)
+    Av=geom%Av(ind)
+    Riv=geom%Riv(ind)
+    Riv2=geom%Riv2(ind)
+    ne=geom%ne(ind)
+    Wee=geom%Wee(ind)
+    bi=geom%bi(ind)
+    fv=geom%fv(ind)
+!!$OMP END MASTER
+!!$OMP BARRIER    
+  END SUBROUTINE swap_geometry
+
+  SUBROUTINE update_circumcenters 
+    USE domain_mod
+    USE dimensions
+    USE spherical_geom_mod
+    USE vector
+    USE transfert_mod
+
+    IMPLICIT NONE
+    REAL(rstd) :: x1(3),x2(3)
+    REAL(rstd) :: vect(3,6)
+    REAL(rstd) :: centr(3)
+    INTEGER :: ind,i,j,n,k
+    TYPE(t_message),SAVE :: message1,message0
+    LOGICAL, SAVE :: first=.TRUE.
+!$OMP THREADPRIVATE(first)    
+    
+    IF (first) THEN
+      CALL init_message(geom%xyz_i, req_i1 ,message1)
+      CALL init_message(geom%xyz_i,req_i0, message0)
+      first=.FALSE.
+    ENDIF
+    
+    CALL transfert_message(geom%xyz_i,message0)
+    CALL transfert_message(geom%xyz_i,message1)
+        
+    
+!    CALL transfert_request(geom%xyz_i,req_i1)
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          n=(j-1)*iim+i
+          DO k=0,5
+            x1(:) = xyz_i(n+t_pos(k+1),:)
+            x2(:) = xyz_i(n+t_pos(MOD(k+1,6)+1),:)
+            if (norm(x1-x2)<1e-16) x2(:) = xyz_i(n+t_pos(MOD(k+2,6)+1),:)
+            CALL circumcenter(xyz_i(n,:), x1, x2, xyz_v(n+z_pos(k+1),:))
+          ENDDO
+        ENDDO
+      ENDDO
+    ENDDO
+
+  END SUBROUTINE update_circumcenters
+
+  SUBROUTINE optimize_geometry
+  USE metric
+  USE spherical_geom_mod
+  USE domain_mod
+  USE dimensions
+  USE transfert_mod
+  USE vector
+  USE getin_mod
+  USE mpipara
+  IMPLICIT NONE
+    INTEGER :: nb_it=0
+    TYPE(t_domain),POINTER :: d
+    INTEGER :: ind,it,i,j,n,k
+    REAL(rstd) :: x1(3),x2(3)
+    REAL(rstd) :: vect(3,6)
+    REAL(rstd) :: centr(3)
+    REAL(rstd) :: sum
+    LOGICAL    :: check
+    
+    
+    CALL getin('optim_it',nb_it)
+    
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      d=>domain(ind)
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          n=(j-1)*iim+i
+          xyz_i(n,:)=d%xyz(:,i,j) 
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    CALL update_circumcenters
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      d=>domain(ind)
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          n=(j-1)*iim+i
+          DO k=0,5
+            x1(:) = xyz_v(n+z_pos(k+1),:)
+            x2(:) = d%vertex(:,k,i,j) 
+            IF (norm(x1-x2)>1e-10) THEN
+              PRINT*,"vertex diff ",ind,i,j,k
+              PRINT*,x1
+              PRINT*,x2
+            ENDIF
+          ENDDO
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    
+    DO it=1,nb_it
+      IF (MOD(it,100)==0) THEN 
+        check=.TRUE.
+      ELSE
+        check=.FALSE.
+      ENDIF
+      
+      sum=0
+      DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            n=(j-1)*iim+i
+            vect(:,1)=xyz_v(n+z_rup,:)
+            vect(:,2)=xyz_v(n+z_up,:)
+            vect(:,3)=xyz_v(n+z_lup,:)
+            vect(:,4)=xyz_v(n+z_ldown,:)
+            vect(:,5)=xyz_v(n+z_down,:)
+            vect(:,6)=xyz_v(n+z_rdown,:)
+            CALL compute_centroid(vect,6,centr)
+            IF (check) THEN
+              sum=MAX(sum,norm(xyz_i(n,:)-centr(:)))
+            ENDIF
+            xyz_i(n,:)=centr(:)
+          ENDDO
+        ENDDO
+        
+      ENDDO
+
+      IF (check) THEN
+!$OMP MASTER
+        IF (is_mpi_master) PRINT *,"it = ",it,"  diff centroid circumcenter ",sum
+!$OMP END MASTER
+      ENDIF 
+
+     CALL update_circumcenters
+
+    ENDDO
+    
+  END SUBROUTINE optimize_geometry
+
+  SUBROUTINE set_geometry
+  USE metric
+  USE vector
+  USE spherical_geom_mod
+  USE domain_mod
+  USE dimensions
+  USE transfert_mod
+  USE getin_mod
+  IMPLICIT NONE
+
+    REAL(rstd) :: surf(6)
+    REAL(rstd) :: surf_v(6)
+    REAL(rstd) :: vect(3,6)
+    REAL(rstd) :: centr(3)
+    REAL(rstd) :: vet(3),vep(3), vertex(3)
+    INTEGER :: ind,i,j,k,n
+    TYPE(t_domain),POINTER :: d
+    REAL(rstd) ::  S
+    REAL(rstd) :: w(6)
+    REAL(rstd) :: lon,lat
+    INTEGER :: ii_glo,jj_glo
+    REAL(rstd) :: S1,S2
+          
+      
+    CALL optimize_geometry
+ 
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      d=>domain(ind)
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          n=(j-1)*iim+i
+
+          DO k=0,5
+            ne(n,k+1)=d%ne(k,i,j)
+          ENDDO
+
+          vect(:,1)=xyz_v(n+z_rup,:)
+          vect(:,2)=xyz_v(n+z_up,:)
+          vect(:,3)=xyz_v(n+z_lup,:)
+          vect(:,4)=xyz_v(n+z_ldown,:)
+          vect(:,5)=xyz_v(n+z_down,:)
+          vect(:,6)=xyz_v(n+z_rdown,:)
+          CALL compute_centroid(vect,6,centr)
+          centroid(n,:)=centr(:)
+
+               
+          CALL xyz2lonlat(xyz_v(n+z_up,:),lon,lat)
+          fv(n+z_up)=2*sin(lat)*omega
+          CALL xyz2lonlat(xyz_v(n+z_down,:),lon,lat)
+          fv(n+z_down)=2*sin(lat)*omega
+          
+          bi(n)=0. 
+        
+          CALL dist_cart(xyz_i(n,:),xyz_i(n+t_right,:),de(n+u_right))
+          CALL dist_cart(xyz_i(n,:),xyz_i(n+t_lup,:),de(n+u_lup))
+          CALL dist_cart(xyz_i(n,:),xyz_i(n+t_ldown,:),de(n+u_ldown))
+          
+          CALL div_arc_bis(xyz_i(n,:),xyz_i(n+t_right,:),0.5,xyz_e(n+u_right,:))
+          CALL div_arc_bis(xyz_i(n,:),xyz_i(n+t_lup,:),0.5,xyz_e(n+u_lup,:))
+          CALL div_arc_bis(xyz_i(n,:),xyz_i(n+t_ldown,:),0.5,xyz_e(n+u_ldown,:))
+
+          CALL dist_cart(xyz_v(n+z_rdown,:), xyz_v(n+z_rup,:),le(n+u_right))
+          CALL dist_cart(xyz_v(n+z_up,:), xyz_v(n+z_lup,:),le(n+u_lup))
+          CALL dist_cart(xyz_v(n+z_ldown,:), xyz_v(n+z_down,:),le(n+u_ldown))
+         
+          Ai(n)=0
+          DO k=0,5
+            CALL surf_triangle(xyz_i(n,:),xyz_i(n+t_pos(k+1),:),xyz_i(n+t_pos(MOD((k+1+6),6)+1),:),surf_v(k+1))
+            CALL surf_triangle(xyz_i(n,:),xyz_v(n+z_pos(MOD((k-1+6),6)+1),:),xyz_v(n+z_pos(k+1),:),surf(k+1))
+            Ai(n)=Ai(n)+surf(k+1)
+            IF (i==ii_end .AND. j==jj_begin) THEN
+              IF (Ai(n)<1e20) THEN
+              ELSE
+                PRINT *,"PB !!",Ai(n),k,surf(k+1)
+                PRINT*,xyz_i(n,:),xyz_v(n+z_pos(MOD((k-1+6),6)+1),:),xyz_v(n+z_pos(k+1),:)
+              ENDIF
+            ENDIF
+          ENDDO
+
+          ! Sign convention : Ringler et al., JCP 2010, eq. 21 p. 3071
+          ! Normal component is along outgoing normal vector if ne=1
+
+          CALL cross_product2(xyz_v(n+z_rdown,:),xyz_v(n+z_rup,:),vep)
+          IF (norm(vep)>1e-30) THEN
+            vep(:)=vep(:)/norm(vep)                         ! Inward normal vector
+            CALL cross_product2(vep,xyz_e(n+u_right,:),vet) ! Counter-clockwise tangent vector 
+            vet(:)=vet(:)/norm(vet)
+            ep_e(n+u_right,:)=-vep(:)*ne(n,right)
+            et_e(n+u_right,:)=vet(:)*ne(n,right)
+          ENDIF
+
+          CALL cross_product2(xyz_v(n+z_up,:),xyz_v(n+z_lup,:),vep)
+          IF (norm(vep)>1e-30) THEN
+            vep(:)=vep(:)/norm(vep)
+            CALL cross_product2(vep,xyz_e(n+u_lup,:),vet)
+            vet(:)=vet(:)/norm(vet)
+            ep_e(n+u_lup,:)=-vep(:)*ne(n,lup)
+            et_e(n+u_lup,:)=vet(:)*ne(n,lup)
+          ENDIF
+
+          CALL cross_product2(xyz_v(n+z_ldown,:),xyz_v(n+z_down,:),vep)
+          IF (norm(vep)>1e-30) THEN
+            vep(:)=vep(:)/norm(vep)
+            CALL cross_product2(vep,xyz_e(n+u_ldown,:),vet)
+            vet(:)=vet(:)/norm(vet)
+            ep_e(n+u_ldown,:)=-vep(:)*ne(n,ldown)
+            et_e(n+u_ldown,:)=vet(:)*ne(n,ldown)
+          ENDIF
+
+          CALL xyz2lonlat(xyz_i(n,:),lon,lat)
+          elon_i(n,1) = -sin(lon)
+          elon_i(n,2) = cos(lon)
+          elon_i(n,3) = 0
+          elat_i(n,1) = -cos(lon)*sin(lat)
+          elat_i(n,2) = -sin(lon)*sin(lat)
+          elat_i(n,3) = cos(lat)
+
+          
+          CALL xyz2lonlat(xyz_e(n+u_right,:),lon,lat)
+          elon_e(n+u_right,1) = -sin(lon)
+          elon_e(n+u_right,2) = cos(lon)
+          elon_e(n+u_right,3) = 0
+          elat_e(n+u_right,1) = -cos(lon)*sin(lat)
+          elat_e(n+u_right,2) = -sin(lon)*sin(lat)
+          elat_e(n+u_right,3) = cos(lat)
+          
+          CALL xyz2lonlat(xyz_e(n+u_lup,:),lon,lat)
+          elon_e(n+u_lup,1) = -sin(lon)
+          elon_e(n+u_lup,2) = cos(lon)
+          elon_e(n+u_lup,3) = 0
+          elat_e(n+u_lup,1) = -cos(lon)*sin(lat)
+          elat_e(n+u_lup,2) = -sin(lon)*sin(lat)
+          elat_e(n+u_lup,3) = cos(lat)
+ 
+          CALL xyz2lonlat(xyz_e(n+u_ldown,:),lon,lat)
+          elon_e(n+u_ldown,1) = -sin(lon)
+          elon_e(n+u_ldown,2) = cos(lon)
+          elon_e(n+u_ldown,3) = 0
+          elat_e(n+u_ldown,1) = -cos(lon)*sin(lat)
+          elat_e(n+u_ldown,2) = -sin(lon)*sin(lat)
+          elat_e(n+u_ldown,3) = cos(lat)
+ 
+          
+          DO k=0,5
+            CALL surf_triangle(xyz_i(n,:), xyz_v(n+z_pos(k+1),:), xyz_i(n+t_pos(k+1),:),S1)
+            CALL surf_triangle(xyz_i(n,:), xyz_v(n+z_pos(k+1),:), xyz_i(n+t_pos(MOD(k+1+6,6)+1),:),S2)
+            Riv(n,k+1)=0.5*(S1+S2)/Ai(n)
+            Riv2(n,k+1)=0.5*(S1+S2)/surf_v(k+1)
+          ENDDO
+
+          DO k=1,6
+            IF (ABS(surf_v(k))<1e-30) THEN
+              Riv(n,k)=0.
+            ENDIF
+          ENDDO
+          
+          Av(n+z_up)=surf_v(vup)+1e-100
+          Av(n+z_down)=surf_v(vdown)+1e-100
+        
+        ENDDO
+      ENDDO
+      
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          n=(j-1)*iim+i
+   
+          CALL compute_wee(n,right,w)
+          Wee(n+u_right,:,1)=w(1:5)
+
+          CALL compute_wee(n+t_right,left,w)
+          Wee(n+u_right,:,2)=w(1:5)
+
+
+          CALL compute_wee(n,lup,w)
+          Wee(n+u_lup,:,1)=w(1:5)
+
+          CALL compute_wee(n+t_lup,rdown,w)
+          Wee(n+u_lup,:,2)=w(1:5)
+
+
+          CALL compute_wee(n,ldown,w)
+          Wee(n+u_ldown,:,1)=w(1:5)
+
+          CALL compute_wee(n+t_ldown,rup,w)
+          Wee(n+u_ldown,:,2)=w(1:5)
+
+        ENDDO
+      ENDDO
+      
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          n=(j-1)*iim+i
+          ii_glo=d%ii_begin_glo-d%ii_begin+i
+          jj_glo=d%jj_begin_glo-d%jj_begin+j
+          
+          IF (ii_glo==1 .AND. jj_glo==1) THEN
+            le(n+u_ldown)=0
+            xyz_v(n+z_ldown,:)=xyz_v(n+z_down,:)
+                       
+          ENDIF
+
+          IF (ii_glo==iim_glo .AND. jj_glo==1) THEN
+            le(n+u_right)=0
+            xyz_v(n+z_rdown,:)=xyz_v(n+z_rup,:)
+          ENDIF
+
+          IF (ii_glo==iim_glo .AND. jj_glo==jjm_glo) THEN
+            le(n+u_rup)=0
+            xyz_v(n+z_rup,:)=xyz_v(n+z_up,:)
+          ENDIF
+
+          IF (ii_glo==1 .AND. jj_glo==jjm_glo) THEN
+            le(n+u_lup)=0
+            xyz_v(n+z_up,:)=xyz_v(n+z_lup,:)
+          ENDIF
+          
+        ENDDO
+      ENDDO
+
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          n=(j-1)*iim+i
+          xyz_i(n,:)=xyz_i(n,:) * radius
+          xyz_v(n+z_up,:)=xyz_v(n+z_up,:) * radius
+          xyz_v(n+z_down,:)=xyz_v(n+z_down,:) *radius
+          de(n+u_right)=de(n+u_right) * radius
+          de(n+u_lup)=de(n+u_lup)*radius
+          de(n+u_ldown)=de(n+u_ldown)*radius
+          xyz_e(n+u_right,:)=xyz_e(n+u_right,:)*radius
+          xyz_e(n+u_lup,:)=xyz_e(n+u_lup,:)*radius
+          xyz_e(n+u_ldown,:)=xyz_e(n+u_ldown,:)*radius
+          le(n+u_right)=le(n+u_right)*radius
+          le(n+u_lup)=le(n+u_lup)*radius
+          le(n+u_ldown)=le(n+u_ldown)*radius
+          Ai(n)=Ai(n)*radius**2
+          Av(n+z_up)=Av(n+z_up)*radius**2
+          Av(n+z_down)=Av(n+z_down)*radius**2
+        ENDDO
+      ENDDO
+                 
+    ENDDO
+
+    CALL transfert_request(geom%Ai,req_i1)
+    CALL transfert_request(geom%centroid,req_i1)
+
+    CALL surf_triangle(d%xyz(:,ii_begin,jj_begin),d%xyz(:,ii_begin,jj_end),d%xyz(:,ii_end,jj_begin),S)
+ 
+  END SUBROUTINE set_geometry
+  
+  SUBROUTINE compute_wee(n,pos,w)
+  IMPLICIT NONE
+    INTEGER,INTENT(IN) :: n
+    INTEGER,INTENT(IN) :: pos
+    REAL(rstd),INTENT(OUT) ::w(6)
+
+    REAL(rstd) :: ne_(0:5)
+    REAL(rstd) :: Riv_(6)
+    INTEGER    :: k
+    
+    
+    DO k=0,5
+      ne_(k)=ne(n,MOD(pos-1+k+6,6)+1)  
+      Riv_(k+1)=Riv(n,MOD(pos-1+k+6,6)+1)
+    ENDDO
+          
+    w(1)=-ne_(0)*ne_(1)*(Riv_(1)-0.5)
+    w(2)=-ne_(2)*(ne_(0)*Riv_(2)-w(1)*ne_(1))
+    w(3)=-ne_(3)*(ne_(0)*Riv_(3)-w(2)*ne_(2))
+    w(4)=-ne_(4)*(ne_(0)*Riv_(4)-w(3)*ne_(3))
+    w(5)=-ne_(5)*(ne_(0)*Riv_(5)-w(4)*ne_(4))
+    w(6)=ne_(0)*ne_(5)*(Riv_(6)-0.5)
+    
+!    IF ( ABS(w(5)-w(6))>1e-20) PRINT *, "pb pour wee : w(5)!=w(6)",sum(Riv_(:))
+
+   END SUBROUTINE compute_wee
+            
+
+  
+  SUBROUTINE compute_geometry
+  IMPLICIT NONE
+    CALL allocate_geometry
+    CALL set_geometry
+    
+  END SUBROUTINE compute_geometry
+  
+END MODULE geometry
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/geopotential_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/geopotential_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/geopotential_mod.f90	(revision 329)
@@ -0,0 +1,73 @@
+MODULE geopotential_mod
+
+CONTAINS
+
+  SUBROUTINE geopotential(f_phis,f_pks,f_pk,f_theta,f_phi)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_phis(:)
+    TYPE(t_field), POINTER :: f_pks(:)
+    TYPE(t_field), POINTER :: f_pk(:)
+    TYPE(t_field), POINTER :: f_theta(:)
+    TYPE(t_field), POINTER :: f_phi(:)
+  
+    REAL(rstd), POINTER :: phis(:)
+    REAL(rstd), POINTER :: pks(:)
+    REAL(rstd), POINTER :: pk(:,:)
+    REAL(rstd), POINTER :: theta(:,:)
+    REAL(rstd), POINTER :: phi(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      phis=f_phis(ind)
+      pks=f_pks(ind)
+      pk=f_pk(ind)
+      theta=f_theta(ind)
+      phi=f_phi(ind)
+      CALL compute_geopotential(phis,pks,pk,theta,phi,0)
+    ENDDO
+  
+  END SUBROUTINE geopotential
+  
+  SUBROUTINE compute_geopotential(phis,pks,pk,theta,phi,offset)
+  USE icosa
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: phis(iim*jjm)
+    REAL(rstd),INTENT(IN) :: pks(iim*jjm)
+    REAL(rstd),INTENT(IN) :: pk(iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: theta(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: phi(iim*jjm,llm)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+
+!!! Compute geopotential
+  ! LMD-Z : dh=pi.dtheta-vdp  => (1/rho) dp = pi.dtheta - d(h=pi.theta) = -dtheta.gradpi
+  ! g.dz =  -(1/rho)dp =  theta.gradpi
+  ! direct (variational)
+  ! dz = -(1/rho.g)dp, rho = RT/p = (R/C_p).theta.pi/p
+   
+  ! for first layer
+   DO j=jj_begin-offset,jj_end+offset
+     DO i=ii_begin-offset,ii_end+offset
+       ij=(j-1)*iim+i
+       phi( ij,1 ) = phis( ij ) + theta(ij,1) * ( pks(ij) - pk(ij,1) )
+     ENDDO
+   ENDDO
+          
+  ! for other layers
+   DO l = 2, llm
+     DO j=jj_begin-offset,jj_end+offset
+       DO i=ii_begin-offset,ii_end+offset
+         ij=(j-1)*iim+i
+         phi(ij,l) = phi(ij,l-1) + 0.5 * ( theta(ij,l)  + theta(ij,l-1) )  & 
+                                       * (  pk(ij,l-1) -  pk(ij,l)    )
+       ENDDO
+     ENDDO
+   ENDDO
+   
+  END SUBROUTINE compute_geopotential
+
+END MODULE geopotential_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/getin.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/getin.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/getin.f90	(revision 329)
@@ -0,0 +1,78 @@
+MODULE getin_mod
+
+PRIVATE
+
+  INTERFACE getin
+    MODULE PROCEDURE getin_c , getin_l, getin_i, getin_r
+  END INTERFACE getin
+ 
+PUBLIC getin
+  
+CONTAINS
+
+  SUBROUTINE getin_c(name,value)
+  USE ioipsl, ONLY : getin_=>getin
+  USE transfert_omp_mod
+  USE omp_para
+  USE mpipara
+  IMPLICIT NONE
+    CHARACTER(LEN=*) :: name
+    CHARACTER(LEN=*) :: value
+
+!$OMP MASTER    
+    CALL getin_(name,value)
+    IF(is_mpi_root) PRINT *,'GETIN ',TRIM(name),' = ', TRIM(value)
+!$OMP END MASTER
+    IF (omp_in_parallel()) CALL bcast_omp(value)
+  END SUBROUTINE getin_c
+
+  SUBROUTINE getin_l(name,value)
+  USE ioipsl, ONLY : getin_=>getin
+  USE transfert_omp_mod
+  USE omp_para
+  USE mpipara
+  IMPLICIT NONE
+    CHARACTER(LEN=*) :: name
+    LOGICAL          :: value
+
+!$OMP MASTER    
+    CALL getin_(name,value)
+    IF(is_mpi_root) PRINT *,'GETIN ',TRIM(name),' = ', value
+!$OMP END MASTER
+    IF (omp_in_parallel()) CALL bcast_omp(value)
+  END SUBROUTINE getin_l
+
+  SUBROUTINE getin_i(name,value)
+  USE ioipsl, ONLY : getin_=>getin
+  USE transfert_omp_mod
+  USE omp_para
+  USE mpipara
+  IMPLICIT NONE
+    CHARACTER(LEN=*) :: name
+    INTEGER          :: value
+
+!$OMP MASTER    
+    CALL getin_(name,value)
+    IF(is_mpi_root) PRINT *,'GETIN ',TRIM(name), ' = ', value
+!$OMP END MASTER
+    IF (omp_in_parallel()) CALL bcast_omp(value)
+  END SUBROUTINE getin_i
+  
+  
+  SUBROUTINE getin_r(name,value)
+  USE ioipsl, ONLY : getin_=>getin
+  USE omp_para
+  USE mpipara
+  USE transfert_omp_mod
+  IMPLICIT NONE
+    CHARACTER(LEN=*) :: name
+    REAL             :: value
+
+!$OMP MASTER    
+    CALL getin_(name,value)
+    IF(is_mpi_root) PRINT *,'GETIN ',TRIM(name), ' = ', value
+!$OMP END MASTER
+    IF (omp_in_parallel()) CALL bcast_omp(value)
+  END SUBROUTINE getin_r
+ 
+END MODULE getin_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/grid_param.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/grid_param.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/grid_param.f90	(revision 329)
@@ -0,0 +1,23 @@
+MODULE grid_param
+  INTEGER  :: iim_glo=40
+  INTEGER  :: jjm_glo
+  INTEGER,PARAMETER  :: nb_face=10
+  INTEGER  :: llm=19
+  INTEGER  :: nqtot
+
+CONTAINS
+
+  SUBROUTINE init_grid_param
+  USE IOIPSL
+  IMPLICIT NONE
+    CALL getin('nbp',iim_glo)
+    jjm_glo=iim_glo
+    CALL getin('llm',llm)
+    
+    nqtot=1
+    CALL getin('nqtot',nqtot)
+    
+  END SUBROUTINE  init_grid_param
+
+END MODULE grid_param
+    
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/guided_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/guided_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/guided_mod.f90	(revision 329)
@@ -0,0 +1,54 @@
+MODULE guided_mod
+
+  CHARACTER(LEN=255),SAVE :: guided_type
+!$OMP THREADPRIVATE(guided_type)
+
+CONTAINS
+
+
+  SUBROUTINE init_guided
+  USE icosa
+  USE guided_ncar_mod, ONLY : init_guided_ncar => init_guided
+  IMPLICIT NONE
+    
+    guided_type='none'
+    CALL getin("guided_type",guided_type)
+    
+    SELECT CASE(TRIM(guided_type))
+      CASE ('none')
+      
+      CASE ('dcmip1')
+        CALL init_guided_ncar
+        
+      CASE DEFAULT
+         PRINT*,"Bad selector for varaible guided_type >",TRIM(guided_type),"> option are <none>, <dcmip1>"
+         STOP
+    END SELECT 
+    
+  END SUBROUTINE init_guided
+
+  
+  SUBROUTINE guided(tt, f_ps, f_theta_rhodz, f_u, f_q)
+  USE icosa
+  USE guided_ncar_mod, ONLY : guided_ncar => guided
+  IMPLICIT NONE
+    REAL(rstd), INTENT(IN):: tt
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)  
+    TYPE(t_field),POINTER :: f_q(:)  
+
+    SELECT CASE(TRIM(guided_type))
+      CASE ('none')
+      CASE ('dcmip1')
+        CALL guided_ncar(tt, f_ps, f_theta_rhodz, f_u, f_q)
+      CASE DEFAULT
+         PRINT*,"Bad selector for varaible guided_type >",TRIM(guided_type),"> option are <none>, <dcmip1>"
+         STOP
+    END SELECT 
+  
+  END SUBROUTINE guided
+  
+END MODULE guided_mod
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/guided_ncar_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/guided_ncar_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/guided_ncar_mod.f90	(revision 329)
@@ -0,0 +1,164 @@
+MODULE guided_ncar_mod
+  USE icosa
+  PRIVATE
+  
+  INTEGER,SAVE :: case_wind
+!$OMP THREADPRIVATE(case_wind)
+  
+  REAL(rstd), PARAMETER :: alpha=0.0 ! tilt of solid-body rotation
+  REAL(rstd), PARAMETER :: tau_hadley=daysec, tau = 12*daysec ! 12 days               ! see p. 16
+  REAL(rstd), PARAMETER :: w0_deform = 23000*pi/tau, b=0.2, ptop=25494.4  ! see p. 16 
+  REAL(rstd), PARAMETER :: u0_hadley=40.,w0_hadley=0.15 ,ztop= 12000. 
+  INTEGER, PARAMETER    :: K_hadley=5
+
+  PUBLIC init_guided, guided
+
+CONTAINS
+
+  SUBROUTINE init_guided
+    IMPLICIT NONE
+    CHARACTER(LEN=255) :: wind
+    wind='deform'
+    CALL getin('dcmip1_wind',wind)
+    SELECT CASE(TRIM(wind))
+    CASE('solid')
+       case_wind=0
+    CASE('deform')
+       case_wind=1
+    CASE('hadley')
+       case_wind=2
+    CASE DEFAULT
+       PRINT*,'Bad selector for variable ncar_adv_wind : <', TRIM(wind),'> options are <solid>, <deform>, <hadley>'
+       END SELECT
+  END SUBROUTINE init_guided
+  
+  SUBROUTINE guided(tt, f_ps, f_theta_rhodz, f_u, f_q)
+  USE icosa
+    IMPLICIT NONE
+    REAL(rstd), INTENT(IN):: tt
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)  
+    TYPE(t_field),POINTER :: f_q(:)  
+    
+    REAL(rstd),POINTER :: ue(:,:)
+    INTEGER :: ind
+    
+    DO ind = 1 , ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind) 
+      ue = f_u(ind)  
+      CALL wind_profile(tt,ue)
+    END DO    
+
+  END SUBROUTINE guided
+  
+
+  SUBROUTINE wind_profile(tt,ue)
+    USE icosa
+    USE disvert_mod
+    IMPLICIT NONE
+    REAL(rstd),INTENT(IN)  :: tt ! current time 
+    REAL(rstd),INTENT(OUT) :: ue(iim*3*jjm,llm)
+    REAL(rstd) :: lon, lat
+    REAL(rstd) :: nx(3),n_norm,Velocity(3,llm)
+    REAL(rstd) :: rr1,rr2,bb,cc,aa,hmx
+    REAL(rstd) :: v1(3),v2(3),ny(3)
+    INTEGER :: i,j,n,l
+    REAL(rstd) :: pitbytau,kk, pr, zr, u0, u1, v0
+
+    pitbytau = pi*tt/tau
+    kk = 10*radius/tau
+    u0 = 2*pi*radius/tau ! for solid-body rotation
+!---------------------------------------------------------
+    DO l = 1,llm 
+       pr = presnivs(l)
+       zr = -kappa*cpp*ncar_T0/g*log(pr/ncar_p0)  ! reciprocal of (1) p. 13, isothermal atmosphere
+       u1 = w0_deform*radius/b/ptop*cos(2*pitbytau)*(exp((ptop-pr)/b/ptop)-exp((pr-ncar_p0)/b/ptop))
+       v0 = -radius*w0_hadley*pi/(5.0*ztop)*(ncar_p0/pr)*cos(pi*zr/ztop)*cos(pi*tt/tau_hadley) ! for Hadley cell
+
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             n=(j-1)*iim+i
+             CALL compute_velocity(xyz_e(n+u_right,:),l,velocity(:,l))
+             CALL cross_product2(xyz_v(n+z_rdown,:)/radius,xyz_v(n+z_rup,:)/radius,nx)       
+             ue(n+u_right,l)=1e-10
+             n_norm=sqrt(sum(nx(:)**2))
+             IF (n_norm>1e-30) THEN
+                nx=-nx/n_norm*ne(n,right)
+                ue(n+u_right,l)=sum(nx(:)*velocity(:,l))
+                IF (ABS(ue(n+u_right,l))<1e-100) PRINT *,"ue(n+u_right)==0",i,j,velocity(:,1)
+             ENDIF
+             
+             CALL compute_velocity(xyz_e(n+u_lup,:),l,velocity(:,l))
+             CALL cross_product2(xyz_v(n+z_up,:)/radius,xyz_v(n+z_lup,:)/radius,nx)
+             
+             ue(n+u_lup,l)=1e-10
+             n_norm=sqrt(sum(nx(:)**2))
+             IF (n_norm>1e-30) THEN
+                nx=-nx/n_norm*ne(n,lup)
+                ue(n+u_lup,l)=sum(nx(:)*velocity(:,l))
+             ENDIF
+             
+             CALL compute_velocity(xyz_e(n+u_ldown,:),l,velocity(:,l))
+             CALL cross_product2(xyz_v(n+z_ldown,:)/radius,xyz_v(n+z_down,:)/radius,nx)
+             
+             ue(n+u_ldown,l)=1e-10
+             n_norm=sqrt(sum(nx(:)**2))
+             IF (n_norm>1e-30) THEN
+                nx=-nx/n_norm*ne(n,ldown)
+                ue(n+u_ldown,l)=sum(nx(:)*velocity(:,l))
+                IF (ABS(ue(n+u_ldown,l))<1e-100) PRINT *,"ue(n+u_ldown)==0",i,j
+             ENDIF
+          ENDDO
+       ENDDO
+    END DO
+    
+  CONTAINS
+	   
+    SUBROUTINE compute_velocity(x,l,velocity)
+      IMPLICIT NONE
+      REAL(rstd),INTENT(IN)  :: x(3)
+      INTEGER,INTENT(IN)::l
+      REAL(rstd),INTENT(OUT) :: velocity(3)
+      REAL(rstd) :: e_lat(3), e_lon(3)
+      REAL(rstd) :: lon,lat
+      REAL(rstd) :: u,v
+	      
+      CALL xyz2lonlat(x/radius,lon,lat)
+      e_lat(1) = -cos(lon)*sin(lat)
+      e_lat(2) = -sin(lon)*sin(lat)
+      e_lat(3) = cos(lat)
+        
+      e_lon(1) = -sin(lon)
+      e_lon(2) = cos(lon)
+      e_lon(3) = 0
+
+      u = 0.0 ; v = 0.0
+    
+      SELECT CASE(case_wind) 
+      CASE(0)  ! Solid-body rotation
+         u=u0*(cos(lat)*cos(alpha)+sin(lat)*sin(alpha)*cos(lon))
+         v=-u0*sin(lon)*sin(alpha)
+      CASE(1)  ! 3D Deformational flow - 
+         lon = lon-2*pitbytau
+         u = kk*sin(lon)*sin(lon)*sin(2*lat)*cos(pitbytau)+ u0*cos(lat)
+         u = u + u1*cos(lon)*cos(lat)**2
+         v = kk*sin(2*lon)*cos(lat)*cos(pitbytau) 
+      CASE(2) ! Hadley-like flow
+         u = u0_hadley*cos(lat)
+         v = v0*cos(lat)*sin(5.*lat)    ! Eq. 37 p. 19
+      CASE DEFAULT 
+         PRINT*,"not valid choice of wind" 
+      END SELECT
+      
+      Velocity(:)=(u*e_lon(:)+v*e_lat(:)+1e-50)
+      
+    END SUBROUTINE compute_velocity
+    
+  END SUBROUTINE  wind_profile
+
+
+END MODULE guided_ncar_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/icosa_gcm.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/icosa_gcm.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/icosa_gcm.f90	(revision 329)
@@ -0,0 +1,98 @@
+PROGRAM ICOSA_GCM
+  USE icosa
+  USE timeloop_gcm_mod
+  USE disvert_mod
+  USE etat0_mod
+  USE wind_mod
+  USE mpipara
+  USE omp_para
+  USE vertical_interp_mod
+  USE trace
+  USE output_field_mod
+  USE xios_mod
+  USE write_field
+  USE physics_mod
+
+!  USE getin_mod
+  IMPLICIT NONE
+  
+  CALL init_mpipara
+  CALL trace_off
+  CALL xios_init
+  CALL init_earth_const 
+  CALL init_grid_param
+  CALL init_omp_para
+  CALL compute_metric
+  CALL compute_domain
+  CALL init_transfert
+  CALL init_writefield
+  CALL init_trace
+
+!$OMP PARALLEL  
+  CALL compute_geometry
+  CALL check_total_area
+  
+  CALL init_disvert 
+  CALL init_vertical_interp
+
+  CALL WriteField("Ai",geom%Ai)
+  
+  IF (is_mpi_root) CALL write_apbp
+  CALL init_time
+
+  CALL output_field_init
+  CALL init_timeloop
+!$OMP END PARALLEL
+ 
+  CALL init_physics
+   
+!$OMP PARALLEL  
+  CALL timeloop
+
+!$OMP END PARALLEL
+
+  CALL output_field_finalize
+  CALL close_files
+  CALL close_time_counter
+  CALL finalize_mpipara
+
+CONTAINS
+  
+  SUBROUTINE check_total_area
+    IMPLICIT NONE
+    TYPE(t_field),POINTER,SAVE :: sum_ne(:)
+    TYPE(t_field),POINTER,SAVE :: sum_ne_glo(:)
+    REAL(rstd),POINTER :: pt_sum_ne(:)
+    
+    INTEGER :: ind,i,j,k,n
+    REAL(rstd) :: vect(3,6)
+    REAL(rstd) :: centr(3),dist    
+    REAL(rstd) :: tot_sum=0
+    CALL allocate_field(sum_ne,field_T,type_real)
+    
+    !$OMP BARRIER
+    !$OMP MASTER
+    DO ind=1,ndomain
+       
+       pt_sum_ne=sum_ne(ind)
+       
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             n=(j-1)*iim+i
+             pt_sum_ne(n)=0
+             DO k=1,6
+                pt_sum_ne(n)=pt_sum_ne(n)+ne(n,k)
+             ENDDO
+             IF (domain(ind)%own(i,j)) tot_sum=tot_sum+Ai(n)
+          ENDDO
+       ENDDO
+    ENDDO
+    
+    IF (is_mpi_root) PRINT *," Diff surf",1-tot_sum/(4*Pi*radius*radius)
+    !$OMP END MASTER
+    
+  END SUBROUTINE check_total_area
+END PROGRAM ICOSA_gcm
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/icosa_mod.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/icosa_mod.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/icosa_mod.f90	(revision 329)
@@ -0,0 +1,23 @@
+MODULE icosa
+
+  USE genmod
+!  USE ioipsl, ONLY : getin
+  USE getin_mod, ONLY : getin
+  USE grid_param
+  USE metric
+  USE domain_mod
+  USE dimensions
+  USE grid_param
+  USE geometry
+  USE spherical_geom_mod
+  USE vector
+  USE field_mod
+  USE write_field
+  USE transfert_mod
+  USE time_mod
+  
+  ! Variables defined by run.def
+
+  REAL(rstd) :: ncar_dz, ncar_p0, ncar_T0 ! read from run.def by disvert
+
+END MODULE icosa
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/kinetic.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/kinetic.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/kinetic.f90	(revision 329)
@@ -0,0 +1,56 @@
+MODULE kinetic_mod
+
+
+CONTAINS
+  
+  SUBROUTINE kinetic(f_ue,f_Ki)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ue(:)
+    TYPE(t_field), POINTER :: f_Ki(:)
+  
+    REAL(rstd), POINTER :: ue(:,:)
+    REAL(rstd), POINTER :: Ki(:,:)
+    INTEGER :: ind
+  
+    CALL transfert_request(f_ue,req_e1_vect)
+    CALL transfert_request(f_ue,req_e1_vect)
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ue=f_ue(ind)
+      Ki=f_Ki(ind)
+      CALL compute_kinetic(ue, Ki)
+    ENDDO
+  
+  END SUBROUTINE kinetic
+  
+  SUBROUTINE compute_kinetic(ue, Ki)
+  USE icosa
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ue(3*iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: Ki(iim*jjm,llm)
+    INTEGER :: i,j,ij,l
+    
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+
+          Ki(ij,l)=1/(4*Ai(ij))*(le(ij+u_right)*de(ij+u_right)*ue(ij+u_right,l)**2 +  &
+                               le(ij+u_rup)*de(ij+u_rup)*ue(ij+u_rup,l)**2 +        &
+                               le(ij+u_lup)*de(ij+u_lup)*ue(ij+u_lup,l)**2 +        &
+                               le(ij+u_left)*de(ij+u_left)*ue(ij+u_left,l)**2 +     &
+                               le(ij+u_ldown)*de(ij+u_ldown)*ue(ij+u_ldown,l)**2 +  &
+                               le(ij+u_rdown)*de(ij+u_rdown)*ue(ij+u_rdown,l)**2 )  
+       
+        ENDDO
+      ENDDO
+    ENDDO
+    
+  
+  END SUBROUTINE compute_kinetic
+        
+END MODULE kinetic_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/math_const.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/math_const.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/math_const.f90	(revision 329)
@@ -0,0 +1,7 @@
+MODULE math_const
+  USE PREC
+  
+  REAL(rstd),PARAMETER :: Pi=acos(-1._rstd)
+  COMPLEX(cstd), PARAMETER :: Imag=(0,1)
+  
+END MODULE math_const
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/maxico.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/maxico.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/maxico.f90	(revision 329)
@@ -0,0 +1,218 @@
+ MODULE maxicosa
+contains
+    SUBROUTINE maxis(f_fl,maxff,minff) 
+     USE icosa
+     IMPLICIT NONE
+ INTEGER::i,j,ij,l,ind
+ TYPE(t_field),POINTER::f_fl(:) 
+ REAL(rstd),POINTER::fl(:)  
+ REAL(rstd)::maxf,minf 
+ REAL(rstd),INTENT(OUT)::maxff,minff 
+ 
+    maxff=-1e50
+    minff=1e50 
+    DO ind=1,ndomain 
+     CALL swap_dimensions(ind)
+     CALL swap_geometry(ind) 
+     fl=f_fl(ind) 
+     CALL compute_maxis(fl,maxf,minf)  
+     maxff=max(maxff,maxf) 
+     minff=min(minff,minf) 
+    ENDDO 
+   END SUBROUTINE maxis
+!------------------------------------------------------------
+	    SUBROUTINE maxiv(f_fu,maxuu,minuu) 
+     USE icosa
+     IMPLICIT NONE
+ INTEGER::i,j,ij,l,ind
+ TYPE(t_field),POINTER::f_fu(:) 
+ REAL(rstd),POINTER::fu(:,:)  
+ REAL(rstd)::maxu,minu 
+ REAL(rstd),INTENT(OUT)::maxuu,minuu 
+ 
+    maxuu=-1e50
+    minuu=1e50 
+    DO ind=1,ndomain 
+     CALL swap_dimensions(ind)
+     CALL swap_geometry(ind) 
+     fu=f_fu(ind) 
+     CALL compute_maxiv(fu,maxu,minu)  
+	maxuu=max(maxuu,maxu) 
+	minuu=min(minuu,minu) 
+    ENDDO 
+	END SUBROUTINE maxiv
+
+    SUBROUTINE errornorms(f_ref,f_sim,norml1,norml2,normlf) 
+     USE icosa
+     IMPLICIT NONE
+ INTEGER::i,j,ij,l,ind
+ TYPE(t_field),POINTER::f_ref(:),f_sim(:) 
+ REAL(rstd),POINTER::ref(:),sim(:)  
+ REAL(rstd),INTENT(OUT)::norml1,norml2,normlf 
+ REAL(rstd)::maxf,minf
+ REAL(rstd)::maxff,minff
+ 
+    norml1 = 0.0 ; norml2 = 0.0 ; normlf = 0.0
+    DO ind=1,ndomain 
+     CALL swap_dimensions(ind)
+     CALL swap_geometry(ind) 
+      ref=f_ref(ind) 
+      sim=f_sim(ind) 
+     CALL compute_maxis(sim,maxf,minf)  
+     maxff=max(maxff,maxf) 
+     minff=min(minff,minf) 
+    ENDDO 
+	END SUBROUTINE errornorms
+
+	SUBROUTINE compute_maxis(fl,maxf,minf) 
+	USE icosa
+	IMPLICIT NONE 
+	REAL(rstd),INTENT(IN)::fl(iim*jjm)
+	REAL(rstd),INTENT(OUT)::maxf,minf 
+	INTEGER::i,j,ij 
+
+	maxf=-1e50
+	minf= 1e50 
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+           ij=(j-1)*iim+i
+          IF ( maxf .LT. fl(ij) ) Then 
+	      maxf = fl(ij) 
+	     ENDIF 
+	    IF ( minf .GT. fl(ij) ) Then 
+	     minf = fl(ij) 
+	    ENDIF 
+	   ENDDO
+      ENDDO
+	END SUBROUTINE compute_maxis
+!------------------------------------------------------
+		SUBROUTINE compute_maxiv(fu,maxu,minu) 
+	USE icosa
+	IMPLICIT NONE 
+	REAL(rstd),INTENT(IN)::fu(3*iim*jjm,llm) 
+	REAL(rstd),INTENT(OUT)::maxu,minu  
+	INTEGER::i,j,ij 
+
+     maxu=-1e50
+     minu=1e50 
+	DO j=jj_begin-1,jj_end+1
+         DO i=ii_begin-1,ii_end+1
+           ij=(j-1)*iim+i
+          IF ( maxu .LT. fu(ij+u_right,llm) ) Then 
+	      maxu = fu(ij+u_right,llm) 
+	     ENDIF 
+		IF ( maxu .LT. fu(ij+u_lup,llm) ) Then 
+	      maxu = fu(ij+u_lup,llm) 
+	     ENDIF
+	     IF ( maxu .LT. fu(ij+u_ldown,llm) ) Then 
+	      maxu = fu(ij+u_ldown,llm) 
+	     ENDIF
+!------------------------------
+		IF ( minu .GT. fu(ij+u_right,llm) ) Then 
+	      minu = fu(ij+u_right,llm) 
+	     ENDIF 
+		IF ( minu .GT. fu(ij+u_lup,llm) ) Then 
+	      minu = fu(ij+u_lup,llm) 
+	     ENDIF
+	     IF ( maxu .GT. fu(ij+u_ldown,llm) ) Then 
+	      minu = fu(ij+u_ldown,llm) 
+	     ENDIF 
+	   ENDDO
+      ENDDO
+	END SUBROUTINE compute_maxiv
+!--------------------------------------------------
+	Subroutine compute_l1(reference,simulated,nrml1)
+	use icosa
+	IMPLICIT NONE 
+	REAL(rstd),INTENT(IN)::reference(iim*jjm) 
+	REAL(rstd),INTENT(IN)::simulated(iim*jjm) 
+	REAL(rstd),INTENT(OUT)::nrml1
+	REAL(rstd) :: temp1,temp2
+	INTEGER::i,j,ij 
+
+	temp1 = 0.0 ; temp2 = 0.0 
+	nrml1 = 0.0 
+	DO j=jj_begin,jj_end
+         DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+	  temp1 = temp1 + abs(simulated(ij) - reference(ij))*Ai(ij) 
+	  temp2 = temp2 + abs(reference(ij))*Ai(ij) 
+	 END DO
+	END DO
+	  nrml1 = temp1/temp2 
+	END SUBROUTINE compute_l1 
+
+	Subroutine compute_l2(reference,simulated,nrml2)
+	use icosa
+	IMPLICIT NONE 
+	REAL(rstd),INTENT(IN)::reference(iim*jjm) 
+	REAL(rstd),INTENT(IN)::simulated(iim*jjm) 
+	REAL(rstd),INTENT(OUT)::nrml2
+	REAL(rstd) :: temp1,temp2
+	INTEGER::i,j,ij 
+
+	temp1 = 0.0 ; temp2 = 0.0 
+	nrml2 = 0.0 
+	DO j=jj_begin,jj_end
+         DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+	  temp1 = temp1 + (simulated(ij) - reference(ij))*(simulated(ij) - reference(ij))*Ai(ij) 
+	  temp2 = temp2 + reference(ij)*reference(ij)*Ai(ij) 
+	 END DO
+	END DO
+	  temp1 = sqrt(temp1) 
+	  temp2 = sqrt(temp2)  
+	  nrml2 = temp1/temp2 
+	END SUBROUTINE compute_l2 
+
+	Subroutine compute_lf(reference,simulated,nrmlf)
+	use icosa
+	IMPLICIT NONE 
+	REAL(rstd),INTENT(IN)::reference(iim*jjm) 
+	REAL(rstd),INTENT(IN)::simulated(iim*jjm) 
+	REAL(rstd),INTENT(OUT)::nrmlf
+	REAL(rstd):: difference(iim*jjm) 
+	REAL(rstd) :: temp1,temp2
+	INTEGER::i,j,ij 
+
+	temp1 = 0.0 ; temp2 = 0.0 
+	nrmlf = 0.0 
+	
+	temp1 = maxval(ABS(difference))
+	temp2 = maxval(ABS(reference)) 
+	  nrmlf = temp1/temp2 
+	END SUBROUTINE compute_lf 
+!================================================== initial0 
+	 SUBROUTINE initial0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    INTEGER :: ind
+       
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      phis=f_phis(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      q=f_q(ind)
+      q=0.0
+      ps=0.0
+	 phis=0.0
+      theta_rhodz = 0.0
+	 u = 0.0
+    ENDDO
+  END SUBROUTINE initial0
+
+	END MODULE maxicosa
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/metric.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/metric.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/metric.f90	(revision 329)
@@ -0,0 +1,870 @@
+MODULE metric
+  USE genmod
+  USE grid_param
+  USE domain_param
+  
+  TYPE t_cell_glo
+    INTEGER :: neighbour(0:5)
+    INTEGER :: edge(0:5)
+    INTEGER :: assign_face
+    INTEGER :: assign_i
+    INTEGER :: assign_j
+    INTEGER :: assign_domain
+    REAL(rstd) :: xyz(3)
+  END TYPE t_cell_glo
+  
+  TYPE t_vertex_glo
+    REAL(rstd) :: xyz(3)
+    INTEGER    :: neighbour(0:5)
+    INTEGER    :: ne(0:5)
+    INTEGER    :: ind
+    INTEGER    :: delta
+  END TYPE t_vertex_glo
+  
+  TYPE t_edge_glo
+   INTEGER :: e1
+   INTEGER :: e2
+   INTEGER :: assign_domain
+   INTEGER :: assign_i
+   INTEGER :: assign_j
+   INTEGER :: assign_pos
+   INTEGER :: assign_delta
+  END TYPE t_edge_glo
+    
+ 
+  TYPE(t_vertex_glo),ALLOCATABLE,SAVE :: vertex_glo(:,:,:)
+  TYPE(t_cell_glo),ALLOCATABLE,SAVE :: cell_glo(:)
+  TYPE(t_edge_glo),ALLOCATABLE,SAVE :: edge_glo(:)
+  INTEGER :: ncell_glo
+  
+  INTEGER,ALLOCATABLE,SAVE :: Tab_index(:,:,:)  
+  INTEGER,PARAMETER :: right=1
+  INTEGER,PARAMETER :: rup=2
+  INTEGER,PARAMETER :: lup=3
+  INTEGER,PARAMETER :: left=4
+  INTEGER,PARAMETER :: ldown=5
+  INTEGER,PARAMETER :: rdown=6
+  
+  INTEGER,PARAMETER :: vrup=1
+  INTEGER,PARAMETER :: vup=2
+  INTEGER,PARAMETER :: vlup=3
+  INTEGER,PARAMETER :: vldown=4
+  INTEGER,PARAMETER :: vdown=5
+  INTEGER,PARAMETER :: vrdown=6
+  
+CONTAINS
+
+  SUBROUTINE remap_schmidt
+    USE spherical_geom_mod
+    USE ioipsl
+    IMPLICIT NONE
+    INTEGER :: nf,i,j
+    REAL(rstd) :: schmidt_factor, schmidt_lon, schmidt_lat
+
+    ! Schmidt transform parameters
+    schmidt_factor = 1.
+    CALL getin('schmidt_factor', schmidt_factor)
+    schmidt_factor =  schmidt_factor**2.
+    
+    schmidt_lon = 0.
+    CALL getin('schmidt_lon', schmidt_lon)
+    schmidt_lon = schmidt_lon * pi/180.
+
+    schmidt_lat = 45.
+    CALL getin('schmidt_lat', schmidt_lat)
+    schmidt_lat = schmidt_lat * pi/180.
+
+    DO nf=1,nb_face
+       DO j=1,jjm_glo
+          DO i=1,iim_glo
+             CALL schmidt_transform(vertex_glo(i,j,nf)%xyz, schmidt_factor, schmidt_lon, schmidt_lat)
+          END DO
+       END DO
+    END DO
+  END SUBROUTINE remap_schmidt
+
+  SUBROUTINE allocate_metric
+  IMPLICIT NONE
+    INTEGER :: ind
+    
+    ALLOCATE(vertex_glo(1-halo:iim_glo+halo,1-halo:jjm_glo+halo,nb_face))
+    ncell_glo=10*(iim_glo-2)*(jjm_glo-2)+(iim_glo-2)*20+12
+    ALLOCATE(cell_glo(ncell_glo))
+    ALLOCATE(tab_index(nb_face,nb_face,0:5))
+    ALLOCATE(edge_glo(ncell_glo*3))
+    
+    DO ind=1,ncell_glo
+      cell_glo(ind)%neighbour(:)=0
+    ENDDO
+    
+  END SUBROUTINE allocate_metric
+  
+  SUBROUTINE Compute_face
+  USE spherical_geom_mod
+  IMPLICIT NONE
+    
+    REAL(rstd) :: len_edge
+    REAL(rstd) :: rot=0.
+    INTEGER :: nf,i,j
+    REAL(rstd),DIMENSION(3) :: p1,p2,p3
+    REAL(rstd) :: d1,d2,d3
+  
+  
+   len_edge=acos(cos(Pi/5)*cos(2*Pi/5)/(sin(Pi/5)*sin(2*Pi/5)))
+   
+   DO nf=1,nb_face/2
+     CALL lonlat2xyz(0.,Pi/2,vertex_glo(1,1,nf)%xyz)
+     CALL lonlat2xyz(rot+(nf-1)*2*Pi/5,Pi/2-len_edge,vertex_glo(iim_glo,1,nf)%xyz)
+     CALL lonlat2xyz(rot+2*Pi/5+(nf-1)*2*Pi/5,Pi/2-len_edge,vertex_glo(1,jjm_glo,nf)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+(nf-1)*2*Pi/5,-Pi/2+len_edge,vertex_glo(iim_glo,jjm_glo,nf)%xyz)
+
+     CALL lonlat2xyz(0.,-Pi/2,vertex_glo(1,1,nf+nb_face/2)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+(nf-1)*2*Pi/5,-(Pi/2-len_edge),vertex_glo(1,jjm_glo,nf+nb_face/2)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+2*Pi/5+(nf-1)*2*Pi/5,-(Pi/2-len_edge),vertex_glo(iim_glo,1,nf+nb_face/2)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+Pi/5+(nf-1)*2*Pi/5,-(-Pi/2+len_edge),vertex_glo(iim_glo,jjm_glo,nf+nb_face/2)%xyz)
+   ENDDO
+
+   DO nf=1,nb_face
+     DO i=2,iim_glo-1
+       CALL div_arc(vertex_glo(1,1,nf)%xyz,vertex_glo(iim_glo,1,nf)%xyz,(i-1)*1./(iim_glo-1),vertex_glo(i,1,nf)%xyz)
+       CALL div_arc(vertex_glo(1,jjm_glo,nf)%xyz,vertex_glo(iim_glo,jjm_glo,nf)%xyz,                                 &
+                               (i-1)*1./(iim_glo-1),vertex_glo(i,jjm_glo,nf)%xyz)
+     ENDDO
+      DO j=2,jjm_glo-1
+       CALL div_arc(vertex_glo(1,1,nf)%xyz,vertex_glo(1,jjm_glo,nf)%xyz,(j-1)*1./(jjm_glo-1),vertex_glo(1,j,nf)%xyz)
+       CALL div_arc(vertex_glo(iim_glo,1,nf)%xyz,vertex_glo(iim_glo,jjm_glo,nf)%xyz,(j-1)*1./(jjm_glo-1),            &
+                    vertex_glo(iim_glo,j,nf)%xyz)
+     ENDDO
+    
+     DO j=2,jjm_glo-1
+       DO i=2,iim_glo-1
+         IF (i+j-1 > iim_glo) THEN
+           CALL div_arc(vertex_glo(iim_glo,i+j-iim_glo,nf)%xyz,vertex_glo(i+j-jjm_glo,jjm_glo,nf)%xyz,    &
+                        (iim_glo-i)*1./(2*iim_glo-(i+j)),vertex_glo(i,j,nf)%xyz) 
+         ELSE
+           CALL div_arc(vertex_glo(i+j-1,1,nf)%xyz,vertex_glo(1,i+j-1,nf)%xyz,(j-1)*1./(i+j-2),vertex_glo(i,j,nf)%xyz)
+         ENDIF
+       ENDDO
+     ENDDO
+   ENDDO
+
+  CALL dist_cart(vertex_glo(1,1,1)%xyz,vertex_glo(2,1,1)%xyz,d1) 
+  CALL dist_cart(vertex_glo(2,1,1)%xyz,vertex_glo(3,1,1)%xyz,d2) 
+  CALL dist_cart(vertex_glo(3,1,1)%xyz,vertex_glo(4,1,1)%xyz,d3) 
+  CALL div_arc(vertex_glo(1,1,1)%xyz,vertex_glo(3,1,1)%xyz,0.5,p1)
+
+  CALL circumcenter(vertex_glo(1,1,1)%xyz,vertex_glo(2,1,1)%xyz,vertex_glo(1,2,1)%xyz,p1)
+!  CALL Centroide(vertex_glo(1,2,1)%xyz,vertex_glo(2,1,1)%xyz,vertex_glo(1,1,1)%xyz,p1)
+!  CALL Centroide(vertex_glo(1,2,1)%xyz,vertex_glo(1,1,1)%xyz,vertex_glo(2,1,1)%xyz,p1)
+  CALL dist_cart(vertex_glo(1,1,1)%xyz,p1,d1) 
+  CALL dist_cart(vertex_glo(2,1,1)%xyz,p1,d2) 
+  CALL dist_cart(vertex_glo(1,2,1)%xyz,p1,d3) 
+
+  END SUBROUTINE compute_face
+
+  SUBROUTINE Compute_face_projection
+  USE spherical_geom_mod
+  IMPLICIT NONE
+    
+    REAL(rstd) :: len_edge
+    REAL(rstd) :: rot=0.
+    INTEGER :: nf,i,j
+    REAL(rstd),DIMENSION(3) :: p1,p2,p3
+    REAL(rstd) :: d1,d2,d3
+  
+   len_edge=acos(cos(Pi/5)*cos(2*Pi/5)/(sin(Pi/5)*sin(2*Pi/5)))
+   
+   DO nf=1,nb_face/2
+     CALL lonlat2xyz(0.,Pi/2,vertex_glo(1,1,nf)%xyz)
+     CALL lonlat2xyz(rot+(nf-1)*2*Pi/5,Pi/2-len_edge,vertex_glo(iim_glo,1,nf)%xyz)
+     CALL lonlat2xyz(rot+2*Pi/5+(nf-1)*2*Pi/5,Pi/2-len_edge,vertex_glo(1,jjm_glo,nf)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+(nf-1)*2*Pi/5,-Pi/2+len_edge,vertex_glo(iim_glo,jjm_glo,nf)%xyz)
+
+     CALL lonlat2xyz(0.,-Pi/2,vertex_glo(1,1,nf+nb_face/2)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+(nf-1)*2*Pi/5,-(Pi/2-len_edge),vertex_glo(1,jjm_glo,nf+nb_face/2)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+2*Pi/5+(nf-1)*2*Pi/5,-(Pi/2-len_edge),vertex_glo(iim_glo,1,nf+nb_face/2)%xyz)
+     CALL lonlat2xyz(rot+Pi/5+Pi/5+(nf-1)*2*Pi/5,-(-Pi/2+len_edge),vertex_glo(iim_glo,jjm_glo,nf+nb_face/2)%xyz)
+   ENDDO
+
+   DO nf=1,nb_face
+     DO i=2,iim_glo-1
+       CALL div_arc_bis(vertex_glo(1,1,nf)%xyz,vertex_glo(iim_glo,1,nf)%xyz,(i-1)*1./(iim_glo-1),vertex_glo(i,1,nf)%xyz)
+       CALL div_arc_bis(vertex_glo(1,jjm_glo,nf)%xyz,vertex_glo(iim_glo,jjm_glo,nf)%xyz,                                 &
+                               (i-1)*1./(iim_glo-1),vertex_glo(i,jjm_glo,nf)%xyz)
+     ENDDO
+      DO j=2,jjm_glo-1
+       CALL div_arc_bis(vertex_glo(1,1,nf)%xyz,vertex_glo(1,jjm_glo,nf)%xyz,(j-1)*1./(jjm_glo-1),vertex_glo(1,j,nf)%xyz)
+       CALL div_arc_bis(vertex_glo(iim_glo,1,nf)%xyz,vertex_glo(iim_glo,jjm_glo,nf)%xyz,(j-1)*1./(jjm_glo-1),            &
+                    vertex_glo(iim_glo,j,nf)%xyz)
+     ENDDO
+    
+     DO j=2,jjm_glo-1
+       DO i=2,iim_glo-1
+         IF (i+j-1 > iim_glo) THEN
+           CALL div_arc_bis(vertex_glo(iim_glo,i+j-iim_glo,nf)%xyz,vertex_glo(i+j-jjm_glo,jjm_glo,nf)%xyz,    &
+                        (iim_glo-i)*1./(2*iim_glo-(i+j)),vertex_glo(i,j,nf)%xyz) 
+         ELSE
+           CALL div_arc_bis(vertex_glo(i+j-1,1,nf)%xyz,vertex_glo(1,i+j-1,nf)%xyz,(j-1)*1./(i+j-2),vertex_glo(i,j,nf)%xyz)
+         ENDIF
+       ENDDO
+     ENDDO
+     
+!     DO j=1,jjm_glo
+!       DO i=1,iim_glo
+!         vertex_glo(i,j,nf)%xyz=vertex_glo(i,j,nf)%xyz/sqrt(sum(vertex_glo(i,j,nf)%xyz**2))
+!       ENDDO
+!     ENDDO
+   ENDDO
+
+!  CALL dist_cart(vertex_glo(1,1,1)%xyz,vertex_glo(2,1,1)%xyz,d1) 
+!  CALL dist_cart(vertex_glo(2,1,1)%xyz,vertex_glo(3,1,1)%xyz,d2) 
+!  CALL dist_cart(vertex_glo(3,1,1)%xyz,vertex_glo(4,1,1)%xyz,d3) 
+!  CALL div_arc(vertex_glo(1,1,1)%xyz,vertex_glo(3,1,1)%xyz,0.5,p1)
+!  CALL div_arc(vertex_glo(2,1,1)%xyz,vertex_glo(1,3,1)%xyz,1./3,p1)
+!  CALL div_arc(vertex_glo(1,2,1)%xyz,vertex_glo(3,1,1)%xyz,1./3,p2)
+!  CALL div_arc(vertex_glo(2,2,1)%xyz,vertex_glo(1,1,1)%xyz,1./3,p3)
+!  PRINT *, "dist",d1
+!  PRINT *, "dist",d2
+!  PRINT *, "dist",d3
+!  PRINT *,"dist",vertex_glo(2,1,1)%xyz
+!  PRINT *,"dist",p1/sqrt(sum(p1**2))
+!  CALL Centroide(vertex_glo(1,1,1)%xyz,vertex_glo(2,1,1)%xyz,vertex_glo(1,2,1)%xyz,p1)
+!  CALL Centroide(vertex_glo(1,2,1)%xyz,vertex_glo(2,1,1)%xyz,vertex_glo(1,1,1)%xyz,p1)
+!  CALL Centroide(vertex_glo(1,2,1)%xyz,vertex_glo(1,1,1)%xyz,vertex_glo(2,1,1)%xyz,p1)
+!  CALL dist_cart(vertex_glo(1,1,1)%xyz,p1,d1) 
+!  CALL dist_cart(vertex_glo(2,1,1)%xyz,p1,d2) 
+!  CALL dist_cart(vertex_glo(1,2,1)%xyz,p1,d3) 
+!  PRINT *, "dist",d1
+!  PRINT *, "dist",d2
+!  PRINT *, "dist",d3
+
+  END SUBROUTINE compute_face_projection
+
+
+  SUBROUTINE compute_extended_face_bis
+  IMPLICIT NONE
+  
+    INTEGER :: nf
+    INTEGER :: i,j
+    INTEGER :: delta
+    INTEGER :: ind
+    INTEGER :: k,ng
+
+    DO nf=1,nb_face
+      DO i=2,iim_glo-1
+
+        CALL set_neighbour(i,1,nf,ldown-1)
+        CALL set_neighbour(i,1,nf,rdown-1)
+
+        CALL set_neighbour(i,jjm_glo,nf,lup-1)
+        CALL set_neighbour(i,jjm_glo,nf,rup-1)
+      
+      ENDDO    
+     
+      DO j=2,jjm_glo-1
+        
+        CALL set_neighbour(1,j,nf,left-1)
+        CALL set_neighbour(1,j,nf,lup-1)
+
+        CALL set_neighbour(iim_glo,j,nf,rdown-1)
+        CALL set_neighbour(iim_glo,j,nf,right-1)
+
+      ENDDO
+      
+      CALL set_neighbour(2,0,nf,left-1)
+      CALL set_neighbour(iim_glo,0,nf,right-1)
+      CALL set_neighbour(iim_glo+1,jjm_glo-1,nf,rup-1)
+      CALL set_neighbour(iim_glo-1,jjm_glo+1,nf,right-1)
+      CALL set_neighbour(1,jjm_glo+1,nf,left-1)
+      CALL set_neighbour(0,2,nf,ldown-1)
+      
+      CALL set_neighbour(1,0,nf,left-1)
+      CALL set_neighbour(iim_glo,0,nf,right-1)
+      CALL set_neighbour(0,jjm_glo,nf,rup-1)
+      CALL set_neighbour(iim_glo+1,jjm_glo,nf,rup-1)
+    ENDDO
+
+    DO nf=1,nb_face
+      DO j=0,jjm_glo+1
+        DO i=0,iim_glo+1
+          ind=vertex_glo(i,j,nf)%ind
+          delta=vertex_glo(i,j,nf)%delta
+          DO k=0,5
+            ng=MOD(delta+k+6,6)
+            vertex_glo(i,j,nf)%neighbour(k)=cell_glo(ind)%neighbour(ng)
+          ENDDO
+        ENDDO
+      ENDDO
+ 
+      i=1 ; j=1
+      vertex_glo(i,j,nf)%neighbour(0)=vertex_glo(i+1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(1)=vertex_glo(i,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(2)=vertex_glo(i-1,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(3)=vertex_glo(i-1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(4)=vertex_glo(i,j-1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(5)=vertex_glo(i+1,j-1,nf)%ind
+
+      i=iim_glo ; j=1
+      vertex_glo(i,j,nf)%neighbour(0)=vertex_glo(i+1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(1)=vertex_glo(i,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(2)=vertex_glo(i-1,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(3)=vertex_glo(i-1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(4)=vertex_glo(i,j-1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(5)=vertex_glo(i+1,j-1,nf)%ind
+
+      i=1 ; j=jjm_glo
+      vertex_glo(i,j,nf)%neighbour(0)=vertex_glo(i+1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(1)=vertex_glo(i,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(2)=vertex_glo(i-1,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(3)=vertex_glo(i-1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(4)=vertex_glo(i,j-1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(5)=vertex_glo(i+1,j-1,nf)%ind
+
+      i=iim_glo ; j=jjm_glo
+      vertex_glo(i,j,nf)%neighbour(0)=vertex_glo(i+1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(1)=vertex_glo(i,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(2)=vertex_glo(i-1,j+1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(3)=vertex_glo(i-1,j,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(4)=vertex_glo(i,j-1,nf)%ind
+      vertex_glo(i,j,nf)%neighbour(5)=vertex_glo(i+1,j-1,nf)%ind
+   ENDDO      
+  
+  CONTAINS
+  
+    SUBROUTINE set_neighbour(i,j,nf,neighbour)
+    IMPLICIT NONE
+      INTEGER :: i,j,nf,neighbour
+      INTEGER :: in,jn
+      INTEGER :: k,ng
+      INTEGER :: delta
+      INTEGER :: ind,ind2
+    
+       SELECT CASE (neighbour)
+         CASE(right-1)
+           in=i+1 ; jn=j
+         CASE(rup-1)
+           in=i ; jn=j+1
+         CASE(lup-1)
+           in=i-1 ; jn=j+1
+         CASE(left-1)
+           in=i-1 ; jn=j
+         CASE(ldown-1)
+           in=i ; jn=j-1
+         CASE(rdown-1)
+           in=i+1; jn=j-1
+        END SELECT
+         
+        ind=vertex_glo(i,j,nf)%ind
+        delta=MOD(vertex_glo(i,j,nf)%delta+neighbour+6,6)
+        ind2=cell_glo(ind)%neighbour(delta)
+        DO k=0,5
+          IF (cell_glo(ind2)%neighbour(k)==ind) ng=k
+        ENDDO
+        vertex_glo(in,jn,nf)%ind=ind2
+        vertex_glo(in,jn,nf)%delta=MOD(ng-neighbour+3+6,6)    
+      END SUBROUTINE set_neighbour    
+  
+  END SUBROUTINE compute_extended_face_bis
+    
+    
+  SUBROUTINE compute_extended_face
+  IMPLICIT NONE
+  
+    INTEGER :: nf,nf2
+    INTEGER :: ind,ind2
+    INTEGER :: i,j,h
+    
+
+    DO h=1,halo
+      DO nf=1,nb_face
+        DO i=1-h+1,iim_glo+h-1
+          j=1-h+1
+          ind=vertex_glo(i,j,nf)%ind
+          nf2=cell_glo(ind)%assign_face
+          ind2=cell_glo(ind)%neighbour(tab_index(nf,nf2,ldown-1))
+          vertex_glo(i,j-1,nf)%ind=ind2
+          vertex_glo(i,j-1,nf)%xyz=cell_glo(ind2)%xyz
+        ENDDO
+      
+        DO j=1-h,jjm_glo+h-1
+          i=iim_glo+h-1
+          ind=vertex_glo(i,j,nf)%ind
+          nf2=cell_glo(ind)%assign_face
+          ind2=cell_glo(ind)%neighbour(tab_index(nf,nf2,right-1))
+          vertex_glo(i+1,j,nf)%ind=ind2
+          vertex_glo(i+1,j,nf)%xyz=cell_glo(ind2)%xyz
+        ENDDO
+      
+        DO i=iim_glo+h,1-h+1,-1
+          j=jjm_glo+h-1
+          ind=vertex_glo(i,j,nf)%ind
+          nf2=cell_glo(ind)%assign_face
+          ind2=cell_glo(ind)%neighbour(tab_index(nf,nf2,rup-1))
+          vertex_glo(i,j+1,nf)%ind=ind2
+          vertex_glo(i,j+1,nf)%xyz=cell_glo(ind2)%xyz
+        ENDDO
+
+         DO j=jjm_glo+h,1-h,-1
+          i=1-h+1
+          ind=vertex_glo(i,j,nf)%ind
+          nf2=cell_glo(ind)%assign_face
+          ind2=cell_glo(ind)%neighbour(tab_index(nf,nf2,left-1))
+          vertex_glo(i-1,j,nf)%ind=ind2
+          vertex_glo(i-1,j,nf)%xyz=cell_glo(ind2)%xyz
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    
+  END SUBROUTINE compute_extended_face
+  
+  SUBROUTINE Set_index
+  IMPLICIT NONE
+    INTEGER :: delta
+    INTEGER :: n1,n2,i
+   
+    DO n1=1,5
+     DO delta=-2,2
+        DO i=0,5
+          n2=MOD(n1-1-delta+5,5)+1
+          tab_index(n1,n2,i)=MOD(delta+i+6,6)
+          n2=MOD(n1-1+delta+5,5)+1
+          tab_index(n1+5,n2+5,i)=MOD(delta+i+6,6)
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    DO n1=1,5
+      DO i=0,5
+        delta=3
+
+        n2=5+n1
+        Tab_index(n1,n2,i)=MOD(delta+i+6,6)
+        Tab_index(n2,n1,i)=MOD(delta+i+6,6)
+      
+        n2=5+n1-1
+        IF (n2==5) n2=10
+        Tab_index(n1,n2,i)=MOD(delta+i+6,6)
+        Tab_index(n2,n1,i)=MOD(delta+i+6,6)
+      ENDDO
+    ENDDO
+
+  END SUBROUTINE set_index
+  
+  
+  SUBROUTINE set_cell
+  IMPLICIT NONE
+    INTEGER :: ind,ind2
+    INTEGER :: nf,nf2,nfm1,nfp1
+    INTEGER :: i,j,k
+    INTEGER :: delta
+    
+    ind=0
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Association des cellules !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! interieur des faces
+    DO nf=1,nb_face     
+      DO i=2,iim_glo-1
+        DO j=2,jjm_glo-1
+          ind=ind+1
+          vertex_glo(i,j,nf)%ind=ind
+          cell_glo(ind)%assign_face=nf
+          cell_glo(ind)%assign_i=i
+          cell_glo(ind)%assign_j=j
+        ENDDO
+      ENDDO
+    ENDDO
+
+! frontieres faces nord
+    DO nf=1,nb_face/2
+
+      nfm1=nf-1
+      IF (nfm1==0) nfm1=nb_face/2
+      
+      nf2=nf+nb_face/2
+
+      DO i=2,iim_glo-1
+        ind=ind+1
+        vertex_glo(i,1,nf)%ind=ind
+        vertex_glo(1,i,nfm1)%ind=ind
+        cell_glo(ind)%assign_face=nf
+        cell_glo(ind)%assign_i=i
+        cell_glo(ind)%assign_j=1
+      ENDDO
+
+      DO i=2,iim_glo-1
+        ind=ind+1
+        vertex_glo(i,jjm_glo,nf)%ind=ind
+        vertex_glo(iim_glo-i+1,jjm_glo,nf2)%ind=ind
+        
+        cell_glo(ind)%assign_face=nf
+        cell_glo(ind)%assign_i=i
+        cell_glo(ind)%assign_j=jjm_glo
+      ENDDO
+     ENDDO
+
+! frontieres faces sud
+
+    DO nf=nb_face/2+1,nb_face
+      
+      nfp1=nf+1
+      IF (nfp1==nb_face+1) nfp1=nb_face/2+1
+      
+      nf2=nf-nb_face/2+1
+      IF (nf2==nb_face/2+1) nf2=1
+      
+      DO i=2,iim_glo-1
+        ind=ind+1
+        vertex_glo(i,1,nf)%ind=ind
+        vertex_glo(1,i,nfp1)%ind=ind
+        cell_glo(ind)%assign_face=nf
+        cell_glo(ind)%assign_i=i
+        cell_glo(ind)%assign_j=1
+      ENDDO
+
+      DO j=2,jjm_glo-1
+        ind=ind+1
+        vertex_glo(iim_glo,j,nf)%ind=ind
+        vertex_glo(iim_glo,jjm_glo-j+1,nf2)%ind=ind
+        
+        cell_glo(ind)%assign_face=nf
+        cell_glo(ind)%assign_i=iim_glo
+        cell_glo(ind)%assign_j=j
+      ENDDO
+    ENDDO
+
+! vertex nord (sur 3 faces)
+
+    DO nf=1,nb_face/2
+
+      nfp1=nf+1
+      IF (nfp1==nb_face/2+1) nfp1=1
+      
+      nf2=nf+nb_face/2
+
+      ind=ind+1
+      vertex_glo(1,jjm_glo,nf)%ind=ind
+      vertex_glo(iim_glo,1,nfp1)%ind=ind
+      vertex_glo(iim_glo,jjm_glo,nf2)%ind=ind
+      cell_glo(ind)%assign_face=nf
+      cell_glo(ind)%assign_i=1
+      cell_glo(ind)%assign_j=jjm_glo
+     ENDDO
+
+! vertex sud (sur 3 faces)
+
+    DO nf=nb_face/2+1,nb_face
+
+      nfp1=nf+1
+      IF (nfp1==nb_face+1) nfp1=nb_face/2+1
+      
+      nf2=nf-nb_face/2+1
+      IF (nf2==nb_face/2+1) nf2=1
+
+      ind=ind+1
+      vertex_glo(iim_glo,1,nf)%ind=ind
+      vertex_glo(1,jjm_glo,nfp1)%ind=ind
+      vertex_glo(iim_glo,jjm_glo,nf2)%ind=ind
+      cell_glo(ind)%assign_face=nf
+      cell_glo(ind)%assign_i=iim_glo
+      cell_glo(ind)%assign_j=1
+    ENDDO
+
+
+! vertex nord (sur 5 faces)
+
+    ind=ind+1
+    vertex_glo(1,1,1)%ind=ind
+    vertex_glo(1,1,2)%ind=ind
+    vertex_glo(1,1,3)%ind=ind
+    vertex_glo(1,1,4)%ind=ind
+    vertex_glo(1,1,5)%ind=ind
+    cell_glo(ind)%assign_face=1
+    cell_glo(ind)%assign_i=1
+    cell_glo(ind)%assign_j=1
+      
+! vertex sud (sur 5 faces)
+
+    ind=ind+1    
+    vertex_glo(1,1,6)%ind=ind
+    vertex_glo(1,1,7)%ind=ind
+    vertex_glo(1,1,8)%ind=ind
+    vertex_glo(1,1,9)%ind=ind
+    vertex_glo(1,1,10)%ind=ind
+    cell_glo(ind)%assign_face=6
+    cell_glo(ind)%assign_i=1
+    cell_glo(ind)%assign_j=1
+
+! assignation des coordonnees xyz
+
+  DO ind=1,ncell_glo
+    nf=cell_glo(ind)%assign_face
+    i=cell_glo(ind)%assign_i
+    j=cell_glo(ind)%assign_j
+    cell_glo(ind)%xyz=vertex_glo(i,j,nf)%xyz
+  ENDDO
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Association des voisins !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! interieur des faces
+  
+    DO nf=1,nb_face
+      DO j=2,jjm_glo-1
+        DO i=2,iim_glo-1
+          ind=vertex_glo(i,j,nf)%ind
+! right          
+          ind2=vertex_glo(i+1,j,nf)%ind   
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(right-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,left-1))=ind
+          
+! rup          
+          ind2=vertex_glo(i,j+1,nf)%ind   
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(rup-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,ldown-1))=ind
+              
+! lup          
+          ind2=vertex_glo(i-1,j+1,nf)%ind  
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(lup-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,rdown-1))=ind
+          
+! left          
+          ind2=vertex_glo(i-1,j,nf)%ind   
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(left-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,right-1))=ind
+! ldown          
+          ind2=vertex_glo(i,j-1,nf)%ind   
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(ldown-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,rup-1))=ind
+          
+! rdown          
+          ind2=vertex_glo(i+1,j-1,nf)%ind   
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(rdown-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,lup-1))=ind
+        ENDDO
+      ENDDO
+    ENDDO
+
+! frontiere face nord
+    
+    DO nf=1,nb_face/2
+      DO i=2,iim_glo-1
+        j=1
+        ind=vertex_glo(i,j,nf)%ind
+! right          
+        ind2=vertex_glo(i+1,j,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(right-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,left-1))=ind
+! left          
+        ind2=vertex_glo(i-1,j,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(left-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,right-1))=ind
+! lup          
+          ind2=vertex_glo(i-1,j+1,nf)%ind  
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(lup-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,rdown-1))=ind
+
+      ENDDO
+
+      DO i=2,iim_glo-1
+        j=jjm_glo
+        ind=vertex_glo(i,j,nf)%ind
+! right          
+        ind2=vertex_glo(i+1,j,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(right-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,left-1))=ind
+! left          
+        ind2=vertex_glo(i-1,j,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(left-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,right-1))=ind
+! rdown          
+          ind2=vertex_glo(i+1,j-1,nf)%ind   
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(rdown-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,lup-1))=ind
+      ENDDO
+    ENDDO
+    
+
+! frontiere face sud
+
+    DO nf=nb_face/2+1,nb_face
+      DO i=2,iim_glo-1
+        j=1
+        ind=vertex_glo(i,j,nf)%ind
+! right          
+        ind2=vertex_glo(i+1,j,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(right-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,left-1))=ind
+! left          
+        ind2=vertex_glo(i-1,j,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(left-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,right-1))=ind
+! lup          
+          ind2=vertex_glo(i-1,j+1,nf)%ind  
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(lup-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,rdown-1))=ind
+      ENDDO
+
+      DO j=2,jjm_glo-1
+        i=iim_glo
+        ind=vertex_glo(i,j,nf)%ind
+! rup          
+        ind2=vertex_glo(i,j+1,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(rup-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,ldown-1))=ind
+! ldown          
+        ind2=vertex_glo(i,j-1,nf)%ind   
+        nf2=cell_glo(ind2)%assign_face
+        cell_glo(ind)%neighbour(ldown-1)=ind2
+        cell_glo(ind2)%neighbour(tab_index(nf,nf2,rup-1))=ind
+! lup          
+          ind2=vertex_glo(i-1,j+1,nf)%ind  
+          nf2=cell_glo(ind2)%assign_face
+          cell_glo(ind)%neighbour(lup-1)=ind2
+          cell_glo(ind2)%neighbour(tab_index(nf,nf2,rdown-1))=ind
+
+      ENDDO
+    ENDDO          
+
+   
+! vertex nord (sur 3 faces)
+
+    DO nf=1,nb_face/2
+      ind=vertex_glo(1,jjm_glo,nf)%ind
+      cell_glo(ind)%neighbour(2)=cell_glo(ind)%neighbour(1)
+    ENDDO
+
+! vertex sud (sur 3 faces)
+
+    DO nf=nb_face/2+1,nb_face
+
+      ind=vertex_glo(iim_glo,1,nf)%ind
+      cell_glo(ind)%neighbour(5)=cell_glo(ind)%neighbour(0)
+    ENDDO
+
+
+! vertex nord (sur 5 faces)
+
+    ind=vertex_glo(1,1,1)%ind
+    cell_glo(ind)%neighbour(3)=cell_glo(ind)%neighbour(4)
+      
+! vertex sud (sur 5 faces)
+
+    ind=vertex_glo(1,1,6)%ind
+    cell_glo(ind)%neighbour(3)=cell_glo(ind)%neighbour(2)
+      
+    
+ !! assignation des delta 
+    DO nf=1,nb_face
+      DO j=1,jjm_glo
+        DO i=1,iim_glo 
+          ind=vertex_glo(i,j,nf)%ind
+          nf2=cell_glo(ind)%assign_face
+          vertex_glo(i,j,nf)%delta=tab_index(nf,nf2,0)
+        ENDDO
+      ENDDO
+    ENDDO    
+
+     
+  END SUBROUTINE set_cell
+      
+          
+  SUBROUTINE set_cell_edge
+  IMPLICIT NONE
+    INTEGER :: ind,k,ind2,ng,ne
+    
+    DO ind=1,ncell_glo
+      cell_glo(ind)%edge(:)=0
+    ENDDO
+    
+    ne=0
+    DO ind=1,ncell_glo
+      DO k=0,5
+        IF (cell_glo(ind)%edge(k)==0) THEN
+          ind2=cell_glo(ind)%neighbour(k)
+          DO ng=0,5
+            IF (cell_glo(ind2)%neighbour(ng)==ind) THEN
+              IF (cell_glo(ind2)%edge(ng)==0) THEN
+                ne=ne+1
+                cell_glo(ind)%edge(k)=ne
+                edge_glo(ne)%e1=ind
+                edge_glo(ne)%e2=ind2
+                cell_glo(ind2)%edge(ng)=ne
+              ELSE 
+                ne=cell_glo(ind2)%edge(ng)
+                cell_glo(ind)%edge(k)=ne
+              ENDIF    
+              EXIT            
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDDO
+    
+  END SUBROUTINE  set_cell_edge    
+        
+  SUBROUTINE set_vertex_edge
+  IMPLICIT NONE
+    INTEGER :: nf
+    INTEGER :: i,j
+    INTEGER :: ind,ind2
+    INTEGER :: ne
+    INTEGER :: k,l     
+  
+    DO nf=1,nb_face
+      DO j=0,jjm_glo+1
+        DO i=0,iim_glo+1
+          ind=vertex_glo(i,j,nf)%ind
+          DO k=0,5
+            ind2=vertex_glo(i,j,nf)%neighbour(k)
+            DO l=0,5
+              ne=cell_glo(ind)%edge(l)
+              IF (edge_glo(ne)%e1==ind .AND. edge_glo(ne)%e2==ind2) THEN
+                vertex_glo(i,j,nf)%ne(k)=1
+              ELSE IF (edge_glo(ne)%e1==ind2 .AND. edge_glo(ne)%e2==ind) THEN
+                vertex_glo(i,j,nf)%ne(k)=-1
+              ENDIF
+            ENDDO
+          ENDDO
+        ENDDO
+      ENDDO
+    ENDDO
+  END SUBROUTINE set_vertex_edge 
+     
+  SUBROUTINE compute_metric
+  IMPLICIT NONE
+  
+    CALL allocate_metric
+!    CALL compute_face
+    CALL compute_face_projection
+    CALL remap_schmidt
+
+    CALL set_index
+    CALL set_cell
+    CALL compute_extended_face_bis
+    CALL set_cell_edge
+    CALL set_vertex_edge
+    
+  END SUBROUTINE compute_metric
+
+END MODULE metric
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/mpi_mod.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/mpi_mod.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/mpi_mod.F90	(revision 329)
@@ -0,0 +1,83 @@
+MODULE mpi_mod
+
+#ifdef CPP_USING_MPI
+  INCLUDE 'mpif.h'
+#else
+  INTEGER :: MPI_COMM_WORLD
+  INTEGER :: MPI_REAL8
+  INTEGER :: MPI_INTEGER
+  INTEGER :: MPI_CHARACTER
+  INTEGER :: MPI_LOGICAL
+  INTEGER :: MPI_ANY_SOURCE
+  INTEGER :: MPI_MAX
+  INTEGER :: MPI_INFO_NULL
+  INTEGER :: MPI_STATUS_SIZE 
+  INTEGER :: MPI_SUM
+  INTEGER :: MPI_THREAD_SINGLE, MPI_THREAD_FUNNELED
+  INTEGER :: MPI_THREAD_SERIALIZED, MPI_THREAD_MULTIPLE
+  
+  INTEGER,PARAMETER :: MPI_ADDRESS_KIND=KIND(INTEGER)
+#endif
+
+END MODULE mpi_mod
+
+
+#ifndef CPP_USING_MPI
+
+ SUBROUTINE  MPI_INIT
+   PRINT *, 'Compiled without MPI'
+ END
+
+ SUBROUTINE  MPI_INIT_THREAD
+   PRINT *, 'Compiled without MPI'
+ END
+ 
+ SUBROUTINE  MPI_COMM_SIZE
+ END
+
+ SUBROUTINE  MPI_COMM_RANK
+ END
+ 
+ SUBROUTINE MPI_FINALIZE
+ END
+ 
+ SUBROUTINE MPI_ALLREDUCE
+ END
+
+ SUBROUTINE MPI_REDUCE
+ END
+
+ SUBROUTINE MPI_ALLTOALL
+ END
+
+ SUBROUTINE MPI_ISEND
+ END
+
+ SUBROUTINE MPI_ISSEND
+ END
+
+ SUBROUTINE MPI_IRECV
+ END
+
+ SUBROUTINE MPI_WAITALL
+ END
+
+ SUBROUTINE MPI_TESTALL
+ END
+
+ SUBROUTINE MPI_BARRIER
+ END
+
+ SUBROUTINE MPI_ALLGATHER
+ END
+ 
+ SUBROUTINE MPI_TYPE_EXTENT
+ END
+ 
+ SUBROUTINE MPI_ALLOC_MEM
+ END
+
+ SUBROUTINE MPI_FREE_MEM
+ END
+
+#endif
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/mpipara.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/mpipara.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/mpipara.F90	(revision 329)
@@ -0,0 +1,235 @@
+MODULE mpipara
+
+  INTEGER,SAVE :: mpi_rank
+  INTEGER,SAVE :: mpi_size
+  INTEGER,SAVE :: mpi_threading_mode
+  
+  INTEGER,SAVE :: comm_icosa
+  INTEGER,SAVE :: ierr
+  LOGICAL,SAVE :: using_mpi
+  LOGICAL,SAVE :: is_mpi_root
+  LOGICAL,SAVE :: is_mpi_master
+  LOGICAL,SAVE :: mpi_master
+  
+  
+  INTERFACE allocate_mpi_buffer
+    MODULE PROCEDURE allocate_mpi_buffer_r2, allocate_mpi_buffer_r3,allocate_mpi_buffer_r4
+  END INTERFACE allocate_mpi_buffer
+
+  INTERFACE free_mpi_buffer
+    MODULE PROCEDURE free_mpi_buffer_r2, free_mpi_buffer_r3, free_mpi_buffer_r4
+  END INTERFACE free_mpi_buffer
+
+  PRIVATE :: getin
+
+CONTAINS
+
+  SUBROUTINE getin(name,value) ! Copied from getin.f90 to avoid circular dependency
+  USE ioipsl, ONLY : getin_=>getin
+  USE transfert_omp_mod
+  USE omp_para
+  IMPLICIT NONE
+    CHARACTER(LEN=*) :: name
+    CHARACTER(LEN=*) :: value
+
+!$OMP MASTER    
+    CALL getin_(name,value)
+    IF(is_mpi_root) PRINT *,'GETIN ',TRIM(name),' = ', TRIM(value)
+!$OMP END MASTER
+    IF (omp_in_parallel()) CALL bcast_omp(value)
+  END SUBROUTINE getin
+
+  SUBROUTINE init_mpipara
+  USE mpi_mod
+#ifdef CPP_USING_XIOS
+  USE xios
+#endif
+  IMPLICIT NONE
+    CHARACTER(LEN=256) :: required_mode_str
+    INTEGER :: required_mode
+
+    using_mpi=.FALSE.
+#ifdef CPP_USING_MPI
+    using_mpi=.TRUE. 
+#endif 
+    
+    IF (using_mpi) THEN
+    
+      required_mode_str='multiple'
+      CALL getin('mpi_threading_mode',required_mode_str)
+      
+      SELECT CASE(TRIM(required_mode_str))
+        CASE ('single')
+          required_mode=MPI_THREAD_SINGLE
+        CASE ('funneled')
+          required_mode=MPI_THREAD_FUNNELED
+        CASE ('serialized')
+          required_mode=MPI_THREAD_SERIALIZED
+        CASE ('multiple')
+          required_mode=MPI_THREAD_MULTIPLE
+        CASE DEFAULT
+          PRINT*,'Bad selector for variable mpi_threading_mode  : <', TRIM(required_mode_str),  &
+                 '>  => options are <single>, <funneled>, <serialized>, <multiple>'
+          STOP
+      END SELECT
+      
+
+      IF (required_mode==MPI_THREAD_SINGLE)     PRINT*,'MPI_INIT_THREAD : MPI_SINGLE_THREAD required'
+      IF (required_mode==MPI_THREAD_FUNNELED)   PRINT*,'MPI_INIT_THREAD : MPI_THREAD_FUNNELED required'
+      IF (required_mode==MPI_THREAD_SERIALIZED) PRINT*,'MPI_INIT_THREAD : MPI_THREAD_SERIALIZED required'
+      IF (required_mode==MPI_THREAD_MULTIPLE)   PRINT*,'MPI_INIT_THREAD : MPI_THREAD_MULTIPLE required'
+
+      
+      CALL MPI_INIT_THREAD(MPI_THREAD_MULTIPLE,mpi_threading_mode,ierr)
+      
+      IF (mpi_threading_mode==MPI_THREAD_SINGLE)     PRINT*,'MPI_INIT_THREAD : MPI_SINGLE_THREAD provided'
+      IF (mpi_threading_mode==MPI_THREAD_FUNNELED)   PRINT*,'MPI_INIT_THREAD : MPI_THREAD_FUNNELED provided'
+      IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) PRINT*,'MPI_INIT_THREAD : MPI_THREAD_SERIALIZED provided'
+      IF (mpi_threading_mode==MPI_THREAD_MULTIPLE)   PRINT*,'MPI_INIT_THREAD : MPI_THREAD_MULTIPLE provided'
+
+      IF (mpi_threading_mode > required_mode) mpi_threading_mode=required_mode
+
+      IF (mpi_threading_mode==MPI_THREAD_SINGLE) THEN
+         PRINT*,'MPI_INIT_THREAD : MPI_SINGLE_THREAD used : Warning : openMP is not garanted to work'
+      ENDIF
+      IF (mpi_threading_mode==MPI_THREAD_FUNNELED)   PRINT*,'MPI_INIT_THREAD : MPI_THREAD_FUNNELED used'
+      IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) PRINT*,'MPI_INIT_THREAD : MPI_THREAD_SERIALIZED used'
+      IF (mpi_threading_mode==MPI_THREAD_MULTIPLE)   PRINT*,'MPI_INIT_THREAD : MPI_THREAD_MULTIPLE used'
+          
+#ifdef CPP_USING_XIOS
+      CALL xios_initialize("icosagcm",return_comm=comm_icosa)
+#else
+     comm_icosa=MPI_COMM_WORLD
+#endif
+      CALL MPI_COMM_SIZE(comm_icosa,mpi_size,ierr)
+      CALL MPI_COMM_RANK(comm_icosa,mpi_rank,ierr)
+      PRINT *, 'MPI Process ', mpi_rank, '/', mpi_size
+    ELSE
+      comm_icosa=-1
+      mpi_size=1
+      mpi_rank=0
+    ENDIF
+    
+    mpi_master=0
+    IF (mpi_rank==0) THEN 
+      is_mpi_root=.TRUE.
+      is_mpi_master=.TRUE.
+    ELSE
+      is_mpi_root=.FALSE.
+      is_mpi_master=.FALSE.
+    ENDIF
+    
+  END SUBROUTINE  init_mpipara
+
+  SUBROUTINE finalize_mpipara
+  USE mpi_mod
+#ifdef CPP_USING_XIOS
+  USE xios
+#endif
+  IMPLICIT NONE
+    
+#ifdef CPP_USING_XIOS
+      CALL xios_finalize
+#endif
+    IF (using_mpi) CALL MPI_FINALIZE(ierr)
+    
+   END SUBROUTINE  finalize_mpipara
+   
+
+  SUBROUTINE allocate_mpi_buffer_r2(buffer,length)
+  USE ISO_C_BINDING
+  USE mpi_mod
+  USE prec
+  IMPLICIT NONE
+    REAL(rstd), POINTER :: buffer(:)
+    INTEGER,INTENT(IN)  :: length
+
+    TYPE(C_PTR)         :: base_ptr
+    INTEGER(KIND=MPI_ADDRESS_KIND) :: size
+    INTEGER :: real_size,ierr
+    
+    CALL MPI_TYPE_EXTENT(MPI_REAL8, real_size, ierr)
+    size=length*real_size
+    
+    CALL MPI_ALLOC_MEM(size,MPI_INFO_NULL,base_ptr,ierr)
+    CALL C_F_POINTER(base_ptr, buffer, (/ length /))
+
+  END SUBROUTINE allocate_mpi_buffer_r2
+
+  SUBROUTINE free_mpi_buffer_r2(buffer)
+  USE ISO_C_BINDING
+  USE mpi_mod
+  USE prec
+  IMPLICIT NONE
+    REAL(rstd), POINTER :: buffer(:)
+
+    CALL MPI_FREE_MEM(buffer,ierr)
+
+   END SUBROUTINE free_mpi_buffer_r2
+
+  SUBROUTINE allocate_mpi_buffer_r3(buffer,length,dim3)
+  USE ISO_C_BINDING
+  USE mpi_mod
+  USE prec
+    IMPLICIT NONE
+    REAL(rstd), POINTER :: buffer(:,:)
+    INTEGER,INTENT(IN)  :: length
+    INTEGER,INTENT(IN)  :: dim3
+
+    TYPE(C_PTR)         :: base_ptr
+    INTEGER(KIND=MPI_ADDRESS_KIND) :: size
+    INTEGER :: real_size,ierr
+    
+    CALL MPI_TYPE_EXTENT(MPI_REAL8, real_size, ierr)
+    size=length*real_size*dim3
+    
+    CALL MPI_ALLOC_MEM(size,MPI_INFO_NULL,base_ptr,ierr)
+    CALL C_F_POINTER(base_ptr, buffer, (/ length,dim3 /))
+    
+  END SUBROUTINE allocate_mpi_buffer_r3
+
+  SUBROUTINE free_mpi_buffer_r3(buffer)
+  USE ISO_C_BINDING
+  USE mpi_mod
+  USE prec
+  IMPLICIT NONE
+    REAL(rstd), POINTER :: buffer(:,:)
+
+    CALL MPI_FREE_MEM(buffer,ierr)
+
+  END SUBROUTINE free_mpi_buffer_r3
+
+  SUBROUTINE allocate_mpi_buffer_r4(buffer,length,dim3,dim4)
+  USE ISO_C_BINDING
+  USE mpi_mod
+  USE prec
+  IMPLICIT NONE
+    REAL(rstd), POINTER :: buffer(:,:,:)
+    INTEGER,INTENT(IN)  :: length
+    INTEGER,INTENT(IN)  :: dim3
+    INTEGER,INTENT(IN)  :: dim4
+
+    TYPE(C_PTR)         :: base_ptr
+    INTEGER(KIND=MPI_ADDRESS_KIND) :: size
+    INTEGER :: real_size,ierr
+    
+    CALL MPI_TYPE_EXTENT(MPI_REAL8, real_size, ierr)
+    size=length*real_size*dim3*dim4
+    
+    CALL MPI_ALLOC_MEM(size,MPI_INFO_NULL,base_ptr,ierr)
+    CALL C_F_POINTER(base_ptr, buffer, (/ length, dim3, dim4 /))
+    
+   END SUBROUTINE allocate_mpi_buffer_r4
+
+  SUBROUTINE free_mpi_buffer_r4(buffer)
+  USE ISO_C_BINDING
+  USE mpi_mod
+  USE prec
+  IMPLICIT NONE
+    REAL(rstd), POINTER :: buffer(:,:,:)
+
+    CALL MPI_FREE_MEM(buffer,ierr)
+
+  END SUBROUTINE free_mpi_buffer_r4
+   
+END MODULE mpipara
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/netcdf_mod.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/netcdf_mod.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/netcdf_mod.F90	(revision 329)
@@ -0,0 +1,20 @@
+MODULE netcdf_mod
+  USE netcdf
+#ifndef CPP_NETCDF4
+  INTEGER ::  NF90_NETCDF4
+  INTEGER ::  NF90_MPIIO
+  INTEGER ::  NF90_CHUNKED
+  
+  INTEGER,EXTERNAL :: NF90_CREATE_PAR
+  INTEGER,EXTERNAL :: NF90_DEF_VAR_CHUNKING 
+#endif
+
+END MODULE netcdf_mod
+
+#ifndef CPP_NETCDF4
+   SUBROUTINE NF90_CREATE_PAR
+   END
+   
+   SUBROUTINE NF90_DEF_VAR_CHUNKING
+   END
+#endif
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/omega.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/omega.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/omega.f90	(revision 329)
@@ -0,0 +1,147 @@
+MODULE omega_mod
+
+  USE icosa
+  PRIVATE
+
+  PUBLIC :: w_omega, compute_omega
+
+CONTAINS
+
+  SUBROUTINE w_omega(f_ps, f_u, f_omega) ! Compute omega = Dp/Dt
+    TYPE(t_field),POINTER :: f_ps(:), f_u(:), f_omega(:)
+    INTEGER :: ind
+    REAL(rstd),POINTER :: ps(:), u(:,:), om(:,:)
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       ps=f_ps(ind)
+       u=f_u(ind)
+       om=f_omega(ind)
+       CALL compute_omega(ps,u,om)
+    END DO
+  END SUBROUTINE W_omega
+
+  SUBROUTINE compute_omega(ps,u, w)
+    USE disvert_mod, ONLY : ap,bp
+    REAL(rstd),INTENT(IN) :: u(iim*3*jjm,llm), ps(iim*jjm)
+    REAL(rstd),INTENT(OUT):: w(iim*jjm,llm)
+    REAL(rstd):: convm(iim*jjm,llm+1)
+    REAL(rstd):: p(iim*jjm,llm+1), rhodz(iim*jjm,llm), Fe(iim*3*jjm,llm)
+    REAL(rstd):: ugradps
+    DO    l    = 1, llm+1
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             p(ij,l) = ap(l) + bp(l) * ps(ij)
+          ENDDO
+       ENDDO
+    ENDDO
+    
+!!! Compute mass
+    DO l = 1, llm
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             rhodz(ij,l) = ( p(ij,l) - p(ij,l+1) ) / g
+          ENDDO
+       ENDDO
+    ENDDO
+    
+!!!  Compute mass flux
+    DO l = 1, llm
+       DO j=jj_begin-1,jj_end+1
+          DO i=ii_begin-1,ii_end+1
+             ij=(j-1)*iim+i
+             Fe(ij+u_right,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_right,l))*u(ij+u_right,l)*le(ij+u_right)
+             Fe(ij+u_lup,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_lup,l))*u(ij+u_lup,l)*le(ij+u_lup)
+             Fe(ij+u_ldown,l)=0.5*(rhodz(ij,l)+rhodz(ij+t_ldown,l))*u(ij+u_ldown,l)*le(ij+u_ldown)
+          ENDDO
+       ENDDO
+    ENDDO
+    
+!!! mass flux convergence computation  
+    
+    ! horizontal convergence
+    DO l = 1, llm
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             ! convm = +div(mass flux), sign convention as in Ringler et al. 2012, eq. 21
+             convm(ij,l)= 1./Ai(ij)*(ne(ij,right)*Fe(ij+u_right,l)   +  &
+                  ne(ij,rup)*Fe(ij+u_rup,l)       +  &  
+                  ne(ij,lup)*Fe(ij+u_lup,l)       +  &  
+                  ne(ij,left)*Fe(ij+u_left,l)     +  &  
+                  ne(ij,ldown)*Fe(ij+u_ldown,l)   +  &  
+                  ne(ij,rdown)*Fe(ij+u_rdown,l))
+          ENDDO
+       ENDDO
+    ENDDO
+    
+    ! vertical integration from up to down
+    DO  l = llm-1, 1, -1
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             convm(ij,l) = convm(ij,l) + convm(ij,l+1)
+          ENDDO
+       ENDDO
+    ENDDO
+    convm(:,llm+1)=0.
+
+!!! Compute dps
+    !  DO j=jj_begin,jj_end
+    !    DO i=ii_begin,ii_end
+    !      ij=(j-1)*iim+i
+    !      ! dps/dt = -int(div flux)dz
+    !      dps(ij)=-convm(ij,1) * g 
+    !      convm(ij,llm+1)=0.
+    !    ENDDO
+    !  ENDDO
+    
+    ! Compute Omega = Dp/Dt
+    ! with p = A(eta)+B(eta)ps
+    !      Dp/Dt = dp/deta.Deta/Dt + B(eta)Dps/Dt
+    !            = -mg.Deta/Dt + B.Dps/Dt
+    ! By definition the mass flux through model levels is W=m.Deta/Dt with m=-1/g dp/deta
+    ! therefore 
+    !  Dp/Dt = -g.W + B.dps/dt + Bu.grad ps
+    !        = B.u.grad ps - g*convm
+    
+!!! Compute vertical flux through model layers
+    !  DO l = 1,llm-1
+    !    DO j=jj_begin,jj_end
+    !      DO i=ii_begin,ii_end
+    !        ij=(j-1)*iim+i
+    !        ! w = int(z,ztop,div(flux)dz) + B(eta)dps/dt
+    !        ! => w>0 for upward transport
+    !        w( ij, l+1 ) = convm( ij, l+1 ) - bp(l+1) * convm( ij, 1 ) ! g.W = g.convm + B dps/dt
+    !      ENDDO
+    !    ENDDO
+    !  ENDDO
+    
+    
+!!! Compute omega
+    ! -grad ps : ( ne(ij,ldown)*ps(ij,l) + ne(ij+t_ldown,rup)*ps(ij+t_ldown,l) ) ) / de(ij+u_ldown)
+
+    DO l = 1,llm
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             toto = 1
+             ij=(j-1)*iim+i
+             ugradps = &
+                  le(ij+u_right)*u(ij+u_right,l)*( ne(ij,right)*ps(ij) + ne(ij+t_right,left)*ps(ij+t_right) )  &
+                  + le(ij+u_rup)*u(ij+u_rup,l)*( ne(ij,rup)*ps(ij) + ne(ij+t_rup,ldown)*ps(ij+t_rup) )  &
+                  + le(ij+u_lup)*u(ij+u_lup,l)*( ne(ij,lup)*ps(ij) + ne(ij+t_lup,rdown)*ps(ij+t_lup) )         &
+                  + le(ij+u_left)*u(ij+u_left,l)*( ne(ij,left)*ps(ij) + ne(ij+t_left,right)*ps(ij+t_left) )    &
+                  + le(ij+u_ldown)*u(ij+u_ldown,l)*( ne(ij,ldown)*ps(ij) + ne(ij+t_ldown,rup)*ps(ij+t_ldown) ) &
+                  + le(ij+u_rdown)*u(ij+u_rdown,l)*( ne(ij,rdown)*ps(ij) + ne(ij+t_rdown,lup)*ps(ij+t_rdown) )
+             ugradps = .5*(bp(l)+bp(l+1)) *ugradps/(-4*Ai(ij))  ! sign convention as in Ringler et al. 2010, Eq. 22 p.3072
+             w( ij, l) =  ugradps - .5*(convm( ij,l+1)+convm(ij,l)) 
+          ENDDO
+       ENDDO
+    ENDDO
+    
+  END SUBROUTINE compute_omega
+  
+END MODULE omega_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/omp_para.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/omp_para.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/omp_para.F90	(revision 329)
@@ -0,0 +1,135 @@
+MODULE omp_para
+
+  INTEGER,SAVE :: omp_size
+  INTEGER,SAVE :: omp_rank
+!$OMP THREADPRIVATE(omp_rank)
+
+  LOGICAL,SAVE :: omp_first
+  LOGICAL,SAVE :: omp_last
+  LOGICAL,SAVE :: omp_master
+!$OMP THREADPRIVATE(omp_first, omp_last,omp_master)
+
+  INTEGER,SAVE :: ll_begin
+  INTEGER,SAVE :: ll_beginp1
+  INTEGER,SAVE :: ll_end
+  INTEGER,SAVE :: ll_endm1
+  INTEGER,SAVE :: ll_endp1
+!$OMP THREADPRIVATE(ll_begin,ll_beginp1,ll_end,ll_endm1,ll_endp1)
+  LOGICAL,SAVE :: using_openmp
+
+  LOGICAL,PARAMETER :: omp_by_domain=.TRUE. 
+
+CONTAINS
+
+
+  SUBROUTINE init_omp_para
+  USE grid_param
+#ifdef CPP_USING_OMP
+  USE omp_lib
+#endif
+  IMPLICIT NONE
+  INTEGER :: ll_nb,i
+
+#ifdef CPP_USING_OMP
+  using_openmp=.TRUE.
+#else
+  using_openmp=.FALSE.
+#endif
+
+  IF (using_openmp) THEN    
+!$OMP PARALLEL PRIVATE(ll_nb,i)
+  
+!$OMP MASTER
+#ifdef CPP_USING_OMP
+    omp_size=OMP_GET_NUM_THREADS()
+#endif
+!$OMP END MASTER
+!$OMP BARRIER
+#ifdef CPP_USING_OMP
+    omp_rank=OMP_GET_THREAD_NUM()
+#endif
+
+    IF (omp_by_domain) THEN
+      omp_first=.TRUE.
+      omp_last=.TRUE.
+      IF (omp_rank==0) THEN
+        omp_master=.TRUE.
+      ELSE
+        omp_master=.FALSE.
+      ENDIF
+     
+      ll_begin=1
+      ll_beginp1=2
+      ll_end=llm
+      ll_endm1=llm-1
+      ll_endp1=llm+1
+     
+    ELSE    
+    
+      omp_first=.FALSE.
+      omp_last=.FALSE.
+      omp_master=.FALSE.
+    
+      IF (omp_rank==0) THEN
+        omp_first=.TRUE.
+        omp_master=.TRUE.
+      ENDIF
+    
+      IF (omp_rank==omp_size-1) omp_last=.TRUE.
+    
+      ll_end=0
+      DO i=0,omp_rank
+        ll_begin=ll_end+1
+        ll_nb=llm/omp_size
+        IF (MOD(llm,omp_size)>i) ll_nb=ll_nb+1
+        ll_end=ll_begin+ll_nb-1
+      ENDDO
+    
+      ll_beginp1=ll_begin
+      ll_endp1=ll_end
+      ll_endm1=ll_end
+
+      IF (omp_first) ll_beginp1=ll_begin+1
+      IF (omp_last) ll_endp1=ll_endp1+1
+      IF (omp_last) ll_endm1=ll_endm1-1
+    
+    ENDIF
+!$OMP END PARALLEL
+
+   ELSE
+     omp_size=1
+     omp_rank=0
+     omp_first=.TRUE.
+     omp_last=.TRUE.
+     omp_master=.TRUE.
+     ll_begin=1
+     ll_beginp1=2
+     ll_end=llm
+     ll_endm1=llm-1
+     ll_endp1=llm+1
+   ENDIF
+   
+  END SUBROUTINE init_omp_para
+
+  FUNCTION omp_in_parallel()
+#ifdef CPP_USING_OMP
+  USE omp_lib, ONLY : omp_in_parallel_=>omp_in_parallel
+#endif
+  IMPLICIT NONE
+    LOGICAL :: omp_in_parallel
+    
+#ifdef CPP_USING_OMP
+    omp_in_parallel=omp_in_parallel_()
+#else
+    omp_in_parallel=.FALSE.
+#endif
+
+  END FUNCTION  omp_in_parallel  
+      
+END MODULE omp_para
+    
+    
+      
+             
+  
+    
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/output_field.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/output_field.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/output_field.f90	(revision 329)
@@ -0,0 +1,64 @@
+MODULE output_field_mod
+USE genmod
+  PRIVATE
+  LOGICAL,SAVE :: xios_output 
+!$OMP THREADPRIVATE(xios_output)     
+  LOGICAL,SAVE :: enable_io    
+!$OMP THREADPRIVATE(enable_io)     
+
+  PUBLIC enable_io,xios_output,output_field_init,output_field,output_field_finalize
+
+CONTAINS 
+  
+  SUBROUTINE output_field_init
+  USE getin_mod
+  USE xios_mod
+  USE write_field
+  IMPLICIT NONE
+
+    enable_io=.TRUE.
+    CALL getin('enable_io',enable_io)
+
+    IF (using_xios) THEN
+      xios_output=.TRUE.
+      CALL getin('xios_output',xios_output)
+    ELSE
+      xios_output=.FALSE.
+    ENDIF
+    
+    IF (xios_output) THEN
+      CALL xios_init_write_field
+    ENDIF
+
+    
+  END SUBROUTINE output_field_init
+
+  SUBROUTINE output_field(name_in,field)
+    USE field_mod
+    USE xios_mod
+    USE write_field
+    IMPLICIT NONE  
+     CHARACTER(LEN=*),INTENT(IN) :: name_in
+      TYPE(t_field),POINTER :: field(:)
+
+      IF (xios_output) THEN
+        CALL xios_write_field(name_in,field)
+      ELSE
+       CALL writeField(name_in,field)
+      ENDIF
+
+  END SUBROUTINE output_field
+
+  SUBROUTINE output_field_finalize
+  USE IOIPSL
+  USE xios_mod
+  IMPLICIT NONE
+    
+    IF (xios_output) THEN
+      CALL xios_write_field_finalize
+    ENDIF
+    
+  END SUBROUTINE output_field_finalize
+
+END MODULE output_field_mod
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics.f90	(revision 329)
@@ -0,0 +1,212 @@
+MODULE physics_mod
+
+  USE field_mod
+
+  PRIVATE
+
+  INTEGER, PARAMETER :: phys_none=0, phys_HS94=1, phys_DCMIP=2, phys_lmdz_generic=3
+
+  INTEGER :: nb_extra_physics_2D, nb_extra_physics_3D, phys_type
+  TYPE(t_field),POINTER :: f_extra_physics_2D(:), f_extra_physics_3D(:)
+
+  CHARACTER(LEN=255) :: physics_type="automatic"
+!$OMP THREADPRIVATE(physics_type)
+
+  PUBLIC :: physics, init_physics
+CONTAINS
+
+  SUBROUTINE init_physics
+    USE mpipara
+    USE etat0_mod
+    USE icosa
+    USE physics_interface_mod
+    USE physics_dcmip_mod, ONLY : init_physics_dcmip=>init_physics
+    USE physics_lmdz_generic_mod, ONLY : init_physics_lmdz_generic=>init_physics
+    IMPLICIT NONE
+
+    physics_type='automatic'
+    CALL getin("physics",physics_type)
+
+    SELECT CASE(TRIM(physics_type))
+    CASE ('automatic')
+       etat0_type='jablonowsky06'
+       CALL getin("etat0",etat0_type)
+       SELECT CASE(TRIM(etat0_type))
+       CASE('held_suarez')
+          phys_type = phys_HS94
+       CASE DEFAULT
+          IF(is_mpi_root) PRINT*,"NO PHYSICAL PACKAGE USED"
+          phys_type = phys_none
+       END SELECT
+    CASE ('phys_lmdz_generic')
+       CALL init_physics_lmdz_generic
+       phys_type=phys_lmdz_generic
+    CASE ('dcmip')
+       CALL init_physics_dcmip
+       nb_extra_physics_2D=1 ! precl
+       nb_extra_physics_3D=0
+       phys_type = phys_DCMIP
+    CASE DEFAULT
+       IF(is_mpi_root) PRINT*, 'init_physics : Bad selector for variable physics <',&
+            TRIM(physics_type), '> options are <automatic>, <dcmip>, <dry>'
+       STOP
+    END SELECT
+
+    IF(is_mpi_root) THEN
+       PRINT *, 'phys_type = ',phys_type
+       PRINT *, 'nb_extra_physics_2D = ', nb_extra_physics_2D
+       PRINT *, 'nb_extra_physics_3D = ', nb_extra_physics_3D
+    END IF
+    IF(nb_extra_physics_2D>0) CALL allocate_field(f_extra_physics_2D,field_t,type_real,nb_extra_physics_2D)
+    IF(nb_extra_physics_3D>0) CALL allocate_field(f_extra_physics_3D,field_t,type_real,llm,nb_extra_physics_3D)
+
+  END SUBROUTINE init_physics
+
+  SUBROUTINE physics(it,f_phis, f_ps, f_theta_rhodz, f_ue, f_wflux, f_q)
+    USE icosa
+    USE physics_interface_mod
+    USE physics_lmdz_generic_mod, ONLY : physics_lmdz_generic => physics
+ !   USE etat0_mod
+    USE etat0_heldsz_mod
+    IMPLICIT NONE
+    INTEGER, INTENT(IN)   :: it
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_ue(:)
+    TYPE(t_field),POINTER :: f_wflux(:)
+    TYPE(t_field),POINTER :: f_q(:)
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: ue(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+
+    LOGICAL:: firstcall,lastcall
+    INTEGER :: ind
+    TYPE(physics_inout) :: args
+
+    SELECT CASE(phys_type)
+    CASE (phys_none)
+       ! No physics, do nothing
+    CASE(phys_HS94)
+       CALL held_suarez(f_ps,f_theta_rhodz,f_ue)
+    CASE (phys_lmdz_generic)
+       CALL physics_lmdz_generic(it ,f_phis, f_ps, f_theta_rhodz, f_ue, f_wflux, f_q)
+    CASE DEFAULT
+       CALL transfert_request(f_ps,req_i1)
+       CALL transfert_request(f_theta_rhodz,req_i1)
+       CALL transfert_request(f_ue,req_e1_vect)
+       CALL transfert_request(f_q,req_i1)
+       
+       args%dt_phys = dt
+       DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          CALL swap_dimensions(ind)
+          CALL swap_geometry(ind)
+      
+          phis=f_phis(ind)
+          ps=f_ps(ind)
+          theta_rhodz=f_theta_rhodz(ind)
+          ue=f_ue(ind)
+          q=f_q(ind)
+
+          IF(nb_extra_physics_2D>0) args%extra_2D=f_extra_physics_2D(ind)
+          IF(nb_extra_physics_3D>0) args%extra_3D=f_extra_physics_3D(ind)
+          CALL physics_column(args, phis, ps, theta_rhodz, ue, q)
+       ENDDO
+
+       IF (mod(it,itau_out)==0 ) THEN
+          IF(nb_extra_physics_2D>0) CALL writefield("extra_physics_2D",f_extra_physics_2D)
+          IF(nb_extra_physics_3D>0) CALL writefield("extra_physics_3D",f_extra_physics_3D)
+       ENDIF
+    END SELECT
+
+  END SUBROUTINE physics
+
+  SUBROUTINE physics_column(args, phis, ps, theta_rhodz, ue, q)
+    USE icosa
+    USE wind_mod
+    USE pression_mod
+    USE theta2theta_rhodz_mod
+    USE physics_interface_mod
+    USE physics_dcmip_mod
+    IMPLICIT NONE
+    TYPE(physics_inout) :: args    
+    REAL(rstd) :: phis(iim*jjm)
+    REAL(rstd) :: ps(iim*jjm)
+    REAL(rstd) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd) :: ue(3*iim*jjm,llm)
+    REAL(rstd), TARGET :: q(iim*jjm,llm,nqtot)
+    ! local arrays
+    REAL(rstd), TARGET :: lat(iim*jjm)
+    REAL(rstd), TARGET :: lon(iim*jjm)
+    REAL(rstd), TARGET :: p(iim*jjm,llm+1)
+    REAL(rstd), TARGET :: Temp(iim*jjm,llm)
+    REAL(rstd), TARGET :: ulon(iim*jjm,llm)
+    REAL(rstd), TARGET :: ulat(iim*jjm,llm)
+    REAL(rstd), TARGET :: dTemp(iim*jjm,llm)
+    REAL(rstd), TARGET :: dulon(iim*jjm,llm)
+    REAL(rstd), TARGET :: dulat(iim*jjm,llm)
+    REAL(rstd), TARGET :: dq(iim*jjm,llm,nqtot)
+    REAL(rstd) :: uc(iim*jjm,3,llm)  ! 3D velocity at cell centers
+
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: due, dt2
+
+    DO j=jj_begin,jj_end
+      DO i=ii_begin,ii_end
+        ij=(j-1)*iim+i
+        CALL xyz2lonlat(xyz_i(ij,:),lon(ij),lat(ij)) 
+      ENDDO
+    ENDDO
+
+    ! Reconstruct wind vector at hexagons
+    CALL compute_pression(ps,p,0)
+    CALL compute_theta_rhodz2temperature(ps,theta_rhodz,Temp,0)
+    CALL compute_wind_centered(ue,uc)
+    CALL compute_wind_centered_lonlat_compound(uc, ulon, ulat)
+    args%ngrid = iim*jjm
+    args%lon => lon
+    args%lat => lat
+    args%p => p
+    args%Temp => Temp
+    args%ulon => ulon
+    args%ulat => ulat
+    args%q => q
+    args%dTemp => dTemp
+    args%dulon => dulon
+    args%dulat => dulat
+    args%dq => dq
+
+    SELECT CASE(phys_type)
+      CASE (phys_DCMIP)
+         CALL compute_phys_wrap(args)
+    END SELECT
+
+    q = q + args%dt_phys * dq
+    Temp = Temp + args%dt_phys * dTemp
+    CALL compute_temperature2theta_rhodz(ps,Temp,theta_rhodz,0)
+    
+    ! Reconstruct wind tendencies at edges and add
+    CALL compute_wind_centered_from_lonlat_compound(dulon,dulat,uc)
+    dt2=.5*args%dt_phys
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          due = sum((uc(ij,:,l) + uc(ij+t_right,:,l))*ep_e(ij+u_right,:) )
+          ue(ij+u_right,l) = ue(ij+u_right,l) + dt2*due
+
+          due = sum( (uc(ij,:,l) + uc(ij+t_lup,:,l))*ep_e(ij+u_lup,:) )
+          ue(ij+u_lup,l)=ue(ij+u_lup,l) + dt2*due
+
+          due = sum( (uc(ij,:,l) + uc(ij+t_ldown,:,l))*ep_e(ij+u_ldown,:) )
+          ue(ij+u_ldown,l)=ue(ij+u_ldown,l) + dt2*due
+        ENDDO
+      ENDDO
+    ENDDO
+
+  END SUBROUTINE physics_column
+
+END MODULE physics_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_dcmip.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_dcmip.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_dcmip.f90	(revision 329)
@@ -0,0 +1,564 @@
+MODULE physics_dcmip_mod
+  USE ICOSA
+  PRIVATE
+  
+  INTEGER,SAVE :: testcase
+!$OMP THREADPRIVATE(testcase)
+
+  TYPE(t_field),POINTER :: f_out_i(:)
+  TYPE(t_field),POINTER :: f_precl(:)
+  REAL(rstd),POINTER :: out_i(:,:)
+
+  PUBLIC :: compute_phys_wrap, init_physics
+
+CONTAINS
+
+  SUBROUTINE init_physics
+    IMPLICIT NONE
+    testcase=1 ! OK for 4.2 (moist baroclinic instability)
+    CALL getin("dcmip_physics",testcase)
+  END SUBROUTINE init_physics
+
+  SUBROUTINE compute_phys_wrap(args)
+    USE physics_interface_mod
+    TYPE(physics_inout) :: args
+    CALL compute_physics(args%ngrid, args%dt_phys, args%lat, &
+         args%p, args%Temp, args%ulon, args%ulat, args%q(:,:,1), &
+         args%dTemp, args%dulon, args%dulat, args%dq(:,:,1), args%extra_2D(:,1))
+  END SUBROUTINE compute_phys_wrap
+
+  SUBROUTINE compute_physics(ngrid,dt_phys,lat, p,Temp,u,v,q, dTemp,du,dv,dq, precl)
+    USE icosa
+    IMPLICIT NONE
+    INTEGER    :: ngrid
+    REAL(rstd) :: lat(ngrid)
+    REAL(rstd) :: ps(ngrid)
+    REAL(rstd) :: precl(ngrid)
+    ! arguments with bottom-up indexing (DYNAMICO)
+    REAL(rstd) :: p(ngrid,llm+1)
+    REAL(rstd) :: Temp(ngrid,llm)
+    REAL(rstd) :: u(ngrid,llm)
+    REAL(rstd) :: v(ngrid,llm)
+    REAL(rstd) :: q(ngrid,llm)
+    REAL(rstd) :: dTemp(ngrid,llm)
+    REAL(rstd) :: du(ngrid,llm)
+    REAL(rstd) :: dv(ngrid,llm)
+    REAL(rstd) :: dq(ngrid,llm)
+    ! local arrays with top-down vertical indexing (DCMIP)
+    REAL(rstd) :: pint(ngrid,llm+1)
+    REAL(rstd) :: pmid(ngrid,llm)
+    REAL(rstd) :: pdel(ngrid,llm)
+    REAL(rstd) :: Tfi(ngrid,llm)
+    REAL(rstd) :: ufi(ngrid,llm)
+    REAL(rstd) :: vfi(ngrid,llm)
+    REAL(rstd) :: qfi(ngrid,llm)
+
+    INTEGER :: i,j,l,ll,ij
+    REAL(rstd) :: dt_phys, inv_dt
+
+    ! prepare input fields and mirror vertical index      
+    ps(:) = p(:,1) ! surface pressure
+
+    DO l=1,llm+1
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          pint(ij,l)=p(ij,llm+2-l)
+        ENDDO
+      ENDDO
+    ENDDO
+
+    DO l=1,llm
+       ll=llm+1-l
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             pmid(ij,l)=0.5*(pint(ij,l)+pint(ij,l+1)) ! Pressure inside layers
+             pdel(ij,l)=pint(ij,l+1)-pint(ij,l)       ! Pressure difference between two layers
+             ufi(ij,l)=u(ij,ll)
+             vfi(ij,l)=v(ij,ll)
+             qfi(ij,l)=q(ij,ll)
+             Tfi(ij,l)=Temp(ij,ll)/(1+0.608*qfi(ij,l))
+          ENDDO
+       ENDDO
+    ENDDO
+    
+    CALL simple_physics(ngrid, llm, dt_phys, lat, tfi, qfi , ufi, vfi, pmid, pint, pdel, 1./pdel, ps, precl, testcase) 
+    
+    ! Mirror vertical index and compute tendencies
+    inv_dt = 1./dt_phys
+    DO l=1,llm
+       ll=llm+1-l
+       DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+             ij=(j-1)*iim+i
+             dTemp(ij,l) = inv_dt * ( Tfi(ij,ll)*(1+0.608*qfi(ij,ll)) - Temp(ij,l) )
+             du(ij,l) = inv_dt * (ufi(ij,ll) - u(ij,l))
+             dv(ij,l) = inv_dt * (vfi(ij,ll) - v(ij,l))
+             dq(ij,l)  = inv_dt * (qfi(ij,ll) - q(ij,l))
+          ENDDO
+       ENDDO
+    ENDDO
+
+  END SUBROUTINE compute_physics
+   
+END MODULE physics_dcmip_mod
+
+subroutine simple_physics (pcols, pver, dtime, lat, t, q, u, v, pmid, pint, pdel, rpdel, ps, precl, test)
+!----------------------------------------------------------------------- 
+! 
+! Purpose: Simple Physics Package
+!
+! Author: K. A. Reed (University of Michigan, kareed@umich.edu)
+!         version 5 
+!         July/8/2012
+!
+!  Change log:
+!  v2: removal of some NCAR CAM-specific 'use' associations
+!  v3: corrected precl(i) computation, the precipitation rate is now computed via a vertical integral, the previous single-level computation in v2 was a bug
+!  v3: corrected dtdt(i,1) computation, the term '-(i,1)' was missing the temperature variable: '-t(i,1)'
+!  v4: modified and enhanced parameter list to make the routine truly standalone, the number of columns and vertical levels have been added: pcols, pver
+!  v4: 'ncol' has been removed, 'pcols' is used instead
+!  v5: the sea surface temperature (SST) field Tsurf is now an array, the SST now depends on the latitude
+!  v5: addition of the latitude array 'lat' and the flag 'test' in the parameter list
+!      if test = 0: constant SST is used, correct setting for the tropical cyclone test case 5-1
+!      if test = 1: newly added latitude-dependent SST is used, correct setting for the moist baroclinic wave test with simple-physics (test 4-3)
+! 
+! Description: Includes large-scale precipitation, surface fluxes and
+!              boundary-leyer mixing. The processes are time-split
+!              in that order. A partially implicit formulation is
+!              used to foster numerical stability.
+!              The routine assumes that the model levels are ordered
+!              in a top-down approach, e.g. level 1 denotes the uppermost
+!              full model level.
+!
+!              This routine is based on an implementation which was
+!              developed for the NCAR Community Atmosphere Model (CAM).
+!              Adjustments for other models will be necessary.
+!
+!              The routine provides both updates of the state variables
+!              u, v, T, q (these are local copies of u,v,T,q within this physics
+!              routine) and also collects their time tendencies.
+!              The latter might be used to couple the physics and dynamics
+!              in a process-split way. For a time-split coupling, the final
+!              state should be given to the dynamical core for the next time step.
+! Test:      0 = Reed and Jablonowski (2011) tropical cyclone test case (test 5-1)
+!            1 = Moist baroclinic instability test (test 4-3)
+!
+!
+! Reference: Reed, K. A. and C. Jablonowski (2012), Idealized tropical cyclone 
+!            simulations of intermediate complexity: A test case for AGCMs, 
+!            J. Adv. Model. Earth Syst., Vol. 4, M04001, doi:10.1029/2011MS000099
+!-----------------------------------------------------------------------
+  ! use physics_types     , only: physics_dme_adjust   ! This is for CESM/CAM
+  ! use cam_diagnostics,    only: diag_phys_writeout   ! This is for CESM/CAM
+
+   implicit none
+
+   integer, parameter :: r8 = selected_real_kind(12)
+
+!
+! Input arguments - MODEL DEPENDENT
+!
+   integer, intent(in)  :: pcols        ! Set number of atmospheric columns       
+   integer, intent(in)  :: pver         ! Set number of model levels
+   real(r8), intent(in) :: dtime        ! Set model physics timestep
+   real(r8), intent(in) :: lat(pcols)   ! Latitude 
+   integer, intent(in)  :: test         ! Test number
+   
+!
+! Input/Output arguments 
+!
+!  pcols is the maximum number of vertical columns per 'chunk' of atmosphere
+!
+   real(r8), intent(inout) :: t(pcols,pver)      ! Temperature at full-model level (K)
+   real(r8), intent(inout) :: q(pcols,pver)      ! Specific Humidity at full-model level (kg/kg)
+   real(r8), intent(inout) :: u(pcols,pver)      ! Zonal wind at full-model level (m/s)
+   real(r8), intent(inout) :: v(pcols,pver)      ! Meridional wind at full-model level (m/s)
+   real(r8), intent(inout) :: pmid(pcols,pver)   ! Pressure is full-model level (Pa)
+   real(r8), intent(inout) :: pint(pcols,pver+1) ! Pressure at model interfaces (Pa)
+   real(r8), intent(inout) :: pdel(pcols,pver)   ! Layer thickness (Pa)
+   real(r8), intent(in) :: rpdel(pcols,pver)  ! Reciprocal of layer thickness (1/Pa)
+   real(r8), intent(inout) :: ps(pcols)          ! Surface Pressue (Pa)
+
+!
+! Output arguments 
+!
+   real(r8), intent(out) :: precl(pcols)         ! Precipitation rate (m_water / s)
+
+!
+!---------------------------Local workspace-----------------------------
+!
+
+! Integers for loops
+
+   integer  i,k                         ! Longitude, level indices
+
+! Physical Constants - Many of these may be model dependent
+
+   real(r8) gravit                      ! Gravity
+   real(r8) rair                        ! Gas constant for dry air
+   real(r8) cpair                       ! Specific heat of dry air 
+   real(r8) latvap                      ! Latent heat of vaporization
+   real(r8) rh2o                        ! Gas constant for water vapor
+   real(r8) epsilo                      ! Ratio of gas constant for dry air to that for vapor
+   real(r8) zvir                        ! Constant for virtual temp. calc. =(rh2o/rair) - 1
+   real(r8) a                           ! Reference Earth's Radius (m)
+   real(r8) omega                       ! Reference rotation rate of the Earth (s^-1)
+   real(r8) pi                          ! pi
+
+! Simple Physics Specific Constants 
+
+!++++++++                     
+   real(r8) Tsurf(pcols)                ! Sea Surface Temperature (constant for tropical cyclone)
+!++++++++                                 Tsurf needs to be dependent on latitude for the
+                                        ! moist baroclinic wave test 4-3 with simple-physics, adjust
+
+   real(r8) SST_tc                      ! Sea Surface Temperature for tropical cyclone test
+   real(r8) T0                          ! Control temp for calculation of qsat
+   real(r8) e0                          ! Saturation vapor pressure at T0 for calculation of qsat
+   real(r8) rhow                        ! Density of Liquid Water
+   real(r8) p0                          ! Constant for calculation of potential temperature
+   real(r8) Cd0                         ! Constant for calculating Cd from Smith and Vogl 2008
+   real(r8) Cd1                         ! Constant for calculating Cd from Smith and Vogl 2008
+   real(r8) Cm                          ! Constant for calculating Cd from Smith and Vogl 2008
+   real(r8) v20                         ! Threshold wind speed for calculating Cd from Smith and Vogl 2008
+   real(r8) C                           ! Drag coefficient for sensible heat and evaporation
+   real(r8) T00                         ! Horizontal mean T at surface for moist baro test
+   real(r8) u0                          ! Zonal wind constant for moist baro test
+   real(r8) latw                        ! halfwidth for  for baro test
+   real(r8) eta0                        ! Center of jets (hybrid) for baro test
+   real(r8) etav                        ! Auxiliary variable for baro test
+   real(r8) q0                          ! Maximum specific humidity for baro test
+
+! Physics Tendency Arrays
+  real(r8) dtdt(pcols,pver)             ! Temperature tendency 
+  real(r8) dqdt(pcols,pver)             ! Specific humidity tendency
+  real(r8) dudt(pcols,pver)             ! Zonal wind tendency
+  real(r8) dvdt(pcols,pver)             ! Meridional wind tendency
+
+! Temporary variables for tendency calculations
+
+   real(r8) tmp                         ! Temporary
+   real(r8) qsat                        ! Saturation vapor pressure
+   real(r8) qsats                       ! Saturation vapor pressure of SST
+
+! Variables for Boundary Layer Calculation
+
+   real(r8) wind(pcols)                 ! Magnitude of Wind
+   real(r8) Cd(pcols)                   ! Drag coefficient for momentum
+   real(r8) Km(pcols,pver+1)            ! Eddy diffusivity for boundary layer calculations 
+   real(r8) Ke(pcols,pver+1)            ! Eddy diffusivity for boundary layer calculations
+   real(r8) rho                         ! Density at lower/upper interface
+   real(r8) za(pcols)                   ! Heights at midpoints of first model level
+   real(r8) dlnpint                     ! Used for calculation of heights
+   real(r8) pbltop                      ! Top of boundary layer
+   real(r8) pblconst                    ! Constant for the calculation of the decay of diffusivity 
+   real(r8) CA(pcols,pver)              ! Matrix Coefficents for PBL Scheme 
+   real(r8) CC(pcols,pver)              ! Matrix Coefficents for PBL Scheme 
+   real(r8) CE(pcols,pver+1)            ! Matrix Coefficents for PBL Scheme
+   real(r8) CAm(pcols,pver)             ! Matrix Coefficents for PBL Scheme
+   real(r8) CCm(pcols,pver)             ! Matrix Coefficents for PBL Scheme
+   real(r8) CEm(pcols,pver+1)           ! Matrix Coefficents for PBL Scheme
+   real(r8) CFu(pcols,pver+1)           ! Matrix Coefficents for PBL Scheme
+   real(r8) CFv(pcols,pver+1)           ! Matrix Coefficents for PBL Scheme
+   real(r8) CFt(pcols,pver+1)           ! Matrix Coefficents for PBL Scheme
+   real(r8) CFq(pcols,pver+1)           ! Matrix Coefficents for PBL Scheme
+
+
+! Variable for Dry Mass Adjustment, this dry air adjustment is necessary to
+! conserve the mass of the dry air
+
+   real(r8) qini(pcols,pver)            ! Initial specific humidity
+
+!===============================================================================
+!
+! Physical Constants - MAY BE MODEL DEPENDENT 
+!
+!===============================================================================
+   gravit = 9.80616_r8                   ! Gravity (9.80616 m/s^2)
+   rair   = 287.0_r8                     ! Gas constant for dry air: 287 J/(kg K)
+   cpair  = 1.0045e3_r8                  ! Specific heat of dry air: here we use 1004.5 J/(kg K)
+   latvap = 2.5e6_r8                     ! Latent heat of vaporization (J/kg)
+   rh2o   = 461.5_r8                     ! Gas constant for water vapor: 461.5 J/(kg K)
+   epsilo = rair/rh2o                    ! Ratio of gas constant for dry air to that for vapor
+   zvir   = (rh2o/rair) - 1._r8          ! Constant for virtual temp. calc. =(rh2o/rair) - 1 is approx. 0.608
+   a      = 6371220.0_r8                 ! Reference Earth's Radius (m)
+   omega  = 7.29212d-5                   ! Reference rotation rate of the Earth (s^-1)
+   pi     = 4._r8*atan(1._r8)            ! pi
+
+!===============================================================================
+!
+! Local Constants for Simple Physics
+!
+!===============================================================================
+      C        = 0.0011_r8      ! From Smith and Vogl 2008
+      SST_tc   = 302.15_r8      ! Constant Value for SST for tropical cyclone test
+      T0       = 273.16_r8      ! control temp for calculation of qsat
+      e0       = 610.78_r8      ! saturation vapor pressure at T0 for calculation of qsat
+      rhow     = 1000.0_r8      ! Density of Liquid Water 
+      Cd0      = 0.0007_r8      ! Constant for Cd calc. Smith and Vogl 2008
+      Cd1      = 0.000065_r8    ! Constant for Cd calc. Smith and Vogl 2008
+      Cm       = 0.002_r8       ! Constant for Cd calc. Smith and Vogl 2008
+      v20      = 20.0_r8        ! Threshold wind speed for calculating Cd from Smith and Vogl 2008
+      p0       = 100000.0_r8    ! Constant for potential temp calculation
+      pbltop   = 85000._r8      ! Top of boundary layer
+      pblconst = 10000._r8      ! Constant for the calculation of the decay of diffusivity
+      T00      = 288.0_r8         ! Horizontal mean T at surface for moist baro test
+      u0       = 35.0_r8          ! Zonal wind constant for moist baro test
+      latw     = 2.0_r8*pi/9.0_r8 ! Halfwidth for  for baro test
+      eta0     = 0.252_r8         ! Center of jets (hybrid) for baro test
+      etav     = (1._r8-eta0)*0.5_r8*pi ! Auxiliary variable for baro test
+      q0       = 0.021            ! Maximum specific humidity for baro test
+
+!===============================================================================
+!
+! Definition of local arrays
+!
+!===============================================================================
+!
+! Calculate hydrostatic height za of the lowest model level
+!
+     do i=1,pcols 
+        dlnpint = log(ps(i)) - log(pint(i,pver))                 ! ps(i) is identical to pint(i,pver+1), note: this is the correct sign (corrects typo in JAMES paper)
+        za(i) = rair/gravit*t(i,pver)*(1._r8+zvir*q(i,pver))*0.5_r8*dlnpint
+     end do
+!
+! Set Initial Specific Humidity - For dry mass adjustment at the end
+!
+     qini(:pcols,:pver) = q(:pcols,:pver)
+!--------------------------------------------------------------
+! Set Sea Surface Temperature (constant for tropical cyclone)
+! Tsurf needs to be dependent on latitude for the
+! moist baroclinic wave test 4-3 with simple-physics 
+!--------------------------------------------------------------
+     if (test .eq. 1) then     ! moist baroclinic wave with simple-physics
+        do i=1,pcols
+           Tsurf(i) = (T00 + pi*u0/rair * 1.5_r8 * sin(etav) * (cos(etav))**0.5_r8 *                 &
+                     ((-2._r8*(sin(lat(i)))**6 * ((cos(lat(i)))**2 + 1._r8/3._r8) + 10._r8/63._r8)* &
+                     u0 * (cos(etav))**1.5_r8  +                                                    &
+                     (8._r8/5._r8*(cos(lat(i)))**3 * ((sin(lat(i)))**2 + 2._r8/3._r8) - pi/4._r8)*a*omega*0.5_r8 ))/ &
+                     (1._r8+zvir*q0*exp(-(lat(i)/latw)**4))
+
+        end do
+     else
+        do i=1,pcols          ! constant SST for the tropical cyclone test case
+           Tsurf(i) = SST_tc
+        end do
+     end if
+
+!===============================================================================
+!
+! Set initial physics time tendencies and precipitation field to zero
+!
+!===============================================================================
+     dtdt(:pcols,:pver)  = 0._r8            ! initialize temperature tendency with zero
+     dqdt(:pcols,:pver)  = 0._r8            ! initialize specific humidity tendency with zero
+     dudt(:pcols,:pver)  = 0._r8            ! initialize zonal wind tendency with zero
+     dvdt(:pcols,:pver)  = 0._r8            ! initialize meridional wind tendency with zero
+     precl(:pcols) = 0._r8                  ! initialize precipitation rate with zero
+
+!===============================================================================
+!
+! Large-Scale Condensation and Precipitation Rate
+!
+!===============================================================================
+!
+! Calculate Tendencies
+!
+      do k=1,pver
+         do i=1,pcols
+            qsat = epsilo*e0/pmid(i,k)*exp(-latvap/rh2o*((1._r8/t(i,k))-1._r8/T0))  ! saturation specific humidity
+!            out_i(i,llm+1-k)=q(i,k)-qsat
+            if (q(i,k) > qsat) then                                                 ! saturated?
+               tmp  = 1._r8/dtime*(q(i,k)-qsat)/(1._r8+(latvap/cpair)*(epsilo*latvap*qsat/(rair*t(i,k)**2)))
+               dtdt(i,k) = dtdt(i,k)+latvap/cpair*tmp
+               dqdt(i,k) = dqdt(i,k)-tmp
+               precl(i) = precl(i) + tmp*pdel(i,k)/(gravit*rhow)                    ! precipitation rate, computed via a vertical integral
+                                                                                    ! corrected in version 1.3
+            end if
+         end do
+      end do
+!
+! Update moisture and temperature fields from Large-Scale Precipitation Scheme
+!
+      do k=1,pver
+         do i=1,pcols
+            t(i,k) =  t(i,k) + dtdt(i,k)*dtime    ! update the state variables T and q
+            q(i,k) =  q(i,k) + dqdt(i,k)*dtime
+         end do
+      end do
+
+!===============================================================================
+! Send variables to history file - THIS PROCESS WILL BE MODEL SPECIFIC
+!
+! note: The variables, as done in many GCMs, are written to the history file
+!       after the moist physics process.  This ensures that the moisture fields
+!       are somewhat in equilibrium.
+!===============================================================================
+  !  call diag_phys_writeout(state)   ! This is for CESM/CAM
+
+!===============================================================================
+!
+! Turbulent mixing coefficients for the PBL mixing of horizontal momentum,
+! sensible heat and latent heat
+!
+! We are using Simplified Ekman theory to compute the diffusion coefficients 
+! Kx for the boundary-layer mixing. The Kx values are calculated at each time step
+! and in each column.
+!
+!===============================================================================
+!
+! Compute magnitude of the wind and drag coeffcients for turbulence scheme:
+! they depend on the conditions at the lowest model level and stay constant
+! up to the 850 hPa level. Above this level the coefficients are decreased
+! and tapered to zero. At the 700 hPa level the strength of the K coefficients
+! is about 10% of the maximum strength. 
+!
+     do i=1,pcols
+        wind(i) = sqrt(u(i,pver)**2+v(i,pver)**2)    ! wind magnitude at the lowest level
+     end do
+     do i=1,pcols
+        Ke(i,pver+1) = C*wind(i)*za(i)
+        if( wind(i) .lt. v20) then
+           Cd(i) = Cd0+Cd1*wind(i) 
+           Km(i,pver+1) = Cd(i)*wind(i)*za(i)
+        else
+           Cd(i) = Cm
+           Km(i,pver+1) = Cm*wind(i)*za(i)
+        endif
+     end do
+
+      do k=1,pver
+         do i=1,pcols
+            if( pint(i,k) .ge. pbltop) then
+               Km(i,k) = Km(i,pver+1)                 ! constant Km below 850 hPa level
+               Ke(i,k) = Ke(i,pver+1)                 ! constant Ke below 850 hPa level
+            else
+               Km(i,k) = Km(i,pver+1)*exp(-(pbltop-pint(i,k))**2/(pblconst)**2)  ! Km tapered to 0
+               Ke(i,k) = Ke(i,pver+1)*exp(-(pbltop-pint(i,k))**2/(pblconst)**2)  ! Ke tapered to 0
+            end if 
+         end do
+      end do     
+
+
+!===============================================================================
+! Update the state variables u, v, t, q with the surface fluxes at the
+! lowest model level, this is done with an implicit approach
+! see Reed and Jablonowski (JAMES, 2012)
+!
+! Sea Surface Temperature Tsurf is constant for tropical cyclone test 5-1
+! Tsurf needs to be dependent on latitude for the
+! moist baroclinic wave test 4-3 with simple-physics, adjust
+!===============================================================================
+
+     do i=1,pcols
+        qsats = epsilo*e0/ps(i)*exp(-latvap/rh2o*((1._r8/Tsurf(i))-1._r8/T0))  ! saturation specific humidity at the surface
+        dudt(i,pver) = dudt(i,pver) + (u(i,pver) &
+                            /(1._r8+Cd(i)*wind(i)*dtime/za(i))-u(i,pver))/dtime
+        dvdt(i,pver) = dvdt(i,pver) + (v(i,pver) &
+                            /(1._r8+Cd(i)*wind(i)*dtime/za(i))-v(i,pver))/dtime
+        u(i,pver)   = u(i,pver)/(1._r8+Cd(i)*wind(i)*dtime/za(i))
+        v(i,pver)   = v(i,pver)/(1._r8+Cd(i)*wind(i)*dtime/za(i))
+        dtdt(i,pver) = dtdt(i,pver) +((t(i,pver)+C*wind(i)*Tsurf(i)*dtime/za(i)) &
+                            /(1._r8+C*wind(i)*dtime/za(i))-t(i,pver))/dtime 
+        t(i,pver)   = (t(i,pver)+C*wind(i)*Tsurf(i)*dtime/za(i)) &
+                            /(1._r8+C*wind(i)*dtime/za(i))  
+        dqdt(i,pver) = dqdt(i,pver) +((q(i,pver)+C*wind(i)*qsats*dtime/za(i)) &
+                            /(1._r8+C*wind(i)*dtime/za(i))-q(i,pver))/dtime
+        q(i,pver) = (q(i,pver)+C*wind(i)*qsats*dtime/za(i))/(1._r8+C*wind(i)*dtime/za(i))
+     end do
+!===============================================================================
+
+
+!===============================================================================
+! Boundary layer mixing, see Reed and Jablonowski (JAMES, 2012)
+!===============================================================================
+! Calculate Diagonal Variables for Implicit PBL Scheme
+!
+      do k=1,pver-1
+         do i=1,pcols
+            rho = (pint(i,k+1)/(rair*(t(i,k+1)+t(i,k))/2.0_r8))
+            CAm(i,k)   = rpdel(i,k)*dtime*gravit*gravit*Km(i,k+1)*rho*rho   &
+                         /(pmid(i,k+1)-pmid(i,k))    
+            CCm(i,k+1) = rpdel(i,k+1)*dtime*gravit*gravit*Km(i,k+1)*rho*rho &
+                         /(pmid(i,k+1)-pmid(i,k))
+            CA(i,k)    = rpdel(i,k)*dtime*gravit*gravit*Ke(i,k+1)*rho*rho   &
+                         /(pmid(i,k+1)-pmid(i,k))
+            CC(i,k+1)  = rpdel(i,k+1)*dtime*gravit*gravit*Ke(i,k+1)*rho*rho &
+                         /(pmid(i,k+1)-pmid(i,k))
+         end do
+      end do
+      do i=1,pcols
+         CAm(i,pver) = 0._r8
+         CCm(i,1) = 0._r8
+         CEm(i,pver+1) = 0._r8
+         CA(i,pver) = 0._r8
+         CC(i,1) = 0._r8
+         CE(i,pver+1) = 0._r8
+         CFu(i,pver+1) = 0._r8
+         CFv(i,pver+1) = 0._r8
+         CFt(i,pver+1) = 0._r8
+         CFq(i,pver+1) = 0._r8 
+      end do
+      do i=1,pcols
+         do k=pver,1,-1
+            CE(i,k)  = CC(i,k)/(1._r8+CA(i,k)+CC(i,k)-CA(i,k)*CE(i,k+1)) 
+            CEm(i,k) = CCm(i,k)/(1._r8+CAm(i,k)+CCm(i,k)-CAm(i,k)*CEm(i,k+1))
+            CFu(i,k) = (u(i,k)+CAm(i,k)*CFu(i,k+1)) &
+                       /(1._r8+CAm(i,k)+CCm(i,k)-CAm(i,k)*CEm(i,k+1))
+            CFv(i,k) = (v(i,k)+CAm(i,k)*CFv(i,k+1)) &
+                       /(1._r8+CAm(i,k)+CCm(i,k)-CAm(i,k)*CEm(i,k+1))
+            CFt(i,k) = ((p0/pmid(i,k))**(rair/cpair)*t(i,k)+CA(i,k)*CFt(i,k+1)) &
+                       /(1._r8+CA(i,k)+CC(i,k)-CA(i,k)*CE(i,k+1)) 
+            CFq(i,k) = (q(i,k)+CA(i,k)*CFq(i,k+1)) &
+                       /(1._r8+CA(i,k)+CC(i,k)-CA(i,k)*CE(i,k+1))
+        end do
+      end do
+
+!
+! Calculate the updated temperature, specific humidity and horizontal wind
+!
+! First we need to calculate the updates at the top model level
+!
+      do i=1,pcols
+            dudt(i,1)  = dudt(i,1)+(CFu(i,1)-u(i,1))/dtime
+            dvdt(i,1)  = dvdt(i,1)+(CFv(i,1)-v(i,1))/dtime
+            u(i,1)    = CFu(i,1)
+            v(i,1)    = CFv(i,1)
+            dtdt(i,1)  = dtdt(i,1)+(CFt(i,1)*(pmid(i,1)/p0)**(rair/cpair)-t(i,1))/dtime  ! corrected in version 1.3
+            t(i,1)    = CFt(i,1)*(pmid(i,1)/p0)**(rair/cpair)
+            dqdt(i,1)  = dqdt(i,1)+(CFq(i,1)-q(i,1))/dtime
+            q(i,1)  = CFq(i,1)
+      end do
+!
+! Loop over the remaining level
+!
+      do i=1,pcols
+         do k=2,pver
+            dudt(i,k)  = dudt(i,k)+(CEm(i,k)*u(i,k-1)+CFu(i,k)-u(i,k))/dtime
+            dvdt(i,k)  = dvdt(i,k)+(CEm(i,k)*v(i,k-1)+CFv(i,k)-v(i,k))/dtime
+            u(i,k)    = CEm(i,k)*u(i,k-1)+CFu(i,k) 
+            v(i,k)    = CEm(i,k)*v(i,k-1)+CFv(i,k)
+            dtdt(i,k)  = dtdt(i,k)+((CE(i,k)*t(i,k-1) &
+                              *(p0/pmid(i,k-1))**(rair/cpair)+CFt(i,k)) &
+                              *(pmid(i,k)/p0)**(rair/cpair)-t(i,k))/dtime 
+            t(i,k)    = (CE(i,k)*t(i,k-1)*(p0/pmid(i,k-1))**(rair/cpair)+CFt(i,k)) &
+                              *(pmid(i,k)/p0)**(rair/cpair)
+            dqdt(i,k)  = dqdt(i,k)+(CE(i,k)*q(i,k-1)+CFq(i,k)-q(i,k))/dtime
+            q(i,k)  = CE(i,k)*q(i,k-1)+CFq(i,k)
+         end do
+      end do
+
+!===============================================================================
+!
+! Dry Mass Adjustment - THIS PROCESS WILL BE MODEL SPECIFIC 
+!
+! note: Care needs to be taken to ensure that the model conserves the total
+!       dry air mass. Add your own routine here.
+!===============================================================================
+  !  call physics_dme_adjust(state, tend, qini, dtime)   ! This is for CESM/CAM
+
+   return
+end subroutine simple_physics 
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_interface.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_interface.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_interface.f90	(revision 329)
@@ -0,0 +1,24 @@
+MODULE physics_interface_mod
+
+  USE prec
+
+  PRIVATE
+
+  TYPE :: physics_inout
+     ! Input
+     INTEGER :: ngrid
+     REAL(rstd) :: dt_phys
+     REAL(rstd), DIMENSION(:), POINTER :: lon, lat
+     REAL(rstd), DIMENSION(:,:), POINTER :: p, Temp, ulon, ulat
+     REAL(rstd), DIMENSION(:,:,:), POINTER :: q
+     ! Output arrays
+     REAL(rstd), DIMENSION(:,:), POINTER :: dTemp, dulon, dulat
+     REAL(rstd), DIMENSION(:,:,:), POINTER :: dq
+     ! extra output arrays (physics diagnostics)
+     REAL(rstd), DIMENSION(:,:), POINTER :: extra_2D
+     REAL(rstd), DIMENSION(:,:,:), POINTER :: extra_3D
+  END TYPE physics_inout
+
+  PUBLIC :: physics_inout
+
+END MODULE physics_interface_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_lmdz5.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_lmdz5.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_lmdz5.f90	(revision 329)
@@ -0,0 +1,527 @@
+MODULE physics_lmdz5_mod
+  USE field_mod
+  USE transfert_mod
+  
+  INTEGER,SAVE :: nbp_phys
+  TYPE(t_message) :: req_u
+
+  TYPE(t_field),POINTER :: f_p(:) 
+  TYPE(t_field),POINTER :: f_pks(:)  
+  TYPE(t_field),POINTER :: f_pk(:)  
+  TYPE(t_field),POINTER :: f_p_layer(:)    
+  TYPE(t_field),POINTER :: f_theta(:)   
+  TYPE(t_field),POINTER :: f_phi(:)   
+  TYPE(t_field),POINTER :: f_Temp(:)    
+  TYPE(t_field),POINTER :: f_ulon(:)    
+  TYPE(t_field),POINTER :: f_ulat(:)   
+  TYPE(t_field),POINTER :: f_dulon(:)
+  TYPE(t_field),POINTER :: f_dulat(:)
+  TYPE(t_field),POINTER :: f_dTemp(:)
+  TYPE(t_field),POINTER :: f_dq(:)
+  TYPE(t_field),POINTER :: f_dps(:)
+  TYPE(t_field),POINTER :: f_duc(:)
+
+  INTEGER :: start_clock
+  INTEGER :: stop_clock
+  INTEGER :: count_clock=0
+
+CONTAINS
+
+  SUBROUTINE init_physics
+  USE icosa
+  USE domain_mod
+  USE dimensions
+  USE mpi_mod
+  USE mpipara
+  IMPLICIT NONE
+  INTEGER  :: distrib(0:mpi_size-1)
+  INTEGER  :: ind,i,j,ij,pos
+
+  REAL(rstd),ALLOCATABLE :: latfi(:)
+  REAL(rstd),ALLOCATABLE :: lonfi(:)
+  REAL(rstd),ALLOCATABLE :: airefi(:)
+   
+
+    CALL allocate_field(f_p,field_t,type_real,llm+1)
+    CALL allocate_field(f_pks,field_t,type_real)
+    CALL allocate_field(f_pk,field_t,type_real,llm)
+    CALL allocate_field(f_p_layer,field_t,type_real,llm)
+    CALL allocate_field(f_theta,field_t,type_real,llm)
+    CALL allocate_field(f_phi,field_t,type_real,llm)
+    CALL allocate_field(f_Temp,field_t,type_real,llm)
+    CALL allocate_field(f_ulon,field_t,type_real,llm)
+    CALL allocate_field(f_ulat,field_t,type_real,llm)
+    CALL allocate_field(f_dulon,field_t,type_real,llm)
+    CALL allocate_field(f_dulat,field_t,type_real,llm)
+    CALL allocate_field(f_dTemp,field_t,type_real,llm)
+    CALL allocate_field(f_dq,field_t,type_real,llm,nqtot)
+    CALL allocate_field(f_dps,field_t,type_real)
+    CALL allocate_field(f_duc,field_t,type_real,3,llm)    
+    
+    
+    nbp_phys=0
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      nbp_phys=nbp_phys+ii_nb*jj_nb
+    ENDDO
+    
+    CALL MPI_ALLGATHER(nbp_phys,1,MPI_INTEGER,distrib,1,MPI_INTEGER,comm_icosa,ierr)
+    
+    ALLOCATE(latfi(nbp_phys))
+    ALLOCATE(lonfi(nbp_phys))
+    ALLOCATE(airefi(nbp_phys))
+    
+    pos=0
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          pos=pos+1
+          CALL xyz2lonlat(xyz_i(ij,:),lonfi(pos),latfi(pos))
+          airefi(pos)=Ai(ij)  
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    CALL init_gcm_lmdz(nbp_phys,mpi_size,distrib,latfi,lonfi,airefi)
+    
+  END SUBROUTINE init_physics
+  
+  SUBROUTINE physics(it,f_phis, f_ps, f_theta_rhodz, f_u, f_wflux, f_q)
+  USE ICOSA
+  USE time_mod
+  USE disvert_mod
+  USE transfert_mod
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)    :: it
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_wflux(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: wflux(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    REAL(rstd),POINTER :: p(:,:)
+    REAL(rstd),POINTER :: pks(:)
+    REAL(rstd),POINTER :: pk(:,:)
+    REAL(rstd),POINTER :: p_layer(:,:)
+    REAL(rstd),POINTER :: theta(:,:)
+    REAL(rstd),POINTER :: phi(:,:)
+    REAL(rstd),POINTER :: Temp(:,:)
+    REAL(rstd),POINTER :: ulon(:,:)
+    REAL(rstd),POINTER :: ulat(:,:)
+    REAL(rstd),POINTER :: dulon(:,:)
+    REAL(rstd),POINTER :: dulat(:,:)
+    REAL(rstd),POINTER :: dTemp(:,:)
+    REAL(rstd),POINTER :: dq(:,:,:)
+    REAL(rstd),POINTER :: dps(:)
+    REAL(rstd),POINTER :: duc(:,:,:)
+
+
+    INTEGER :: ind
+    
+    REAL(rstd),ALLOCATABLE,SAVE :: ps_phy(:)
+    REAL(rstd),ALLOCATABLE,SAVE :: p_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: p_layer_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: Temp_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: phis_phy(:)
+    REAL(rstd),ALLOCATABLE,SAVE :: phi_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: ulon_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: ulat_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: q_phy(:,:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: wflux_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dulon_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dulat_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dTemp_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dq_phy(:,:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dps_phy(:)
+    REAL :: dtphy 
+    INTEGER,SAVE :: offset
+!$OMP THREADPRIVATE(offset)
+    LOGICAL :: lafin=.FALSE.
+    LOGICAL,SAVE :: first=.TRUE.
+!$OMP THREADPRIVATE(first)
+
+    
+    IF (first) THEN
+      first=.FALSE.
+      CALL init_message(f_u,req_e1_vect,req_u)
+!$OMP MASTER
+      ALLOCATE(ps_phy(nbp_phys))
+      ALLOCATE(p_phy(nbp_phys,llm+1))
+      ALLOCATE(p_layer_phy(nbp_phys,llm))
+      ALLOCATE(Temp_phy(nbp_phys,llm))
+      ALLOCATE(phis_phy(nbp_phys))
+      ALLOCATE(phi_phy(nbp_phys,llm))
+      ALLOCATE(ulon_phy(nbp_phys,llm))
+      ALLOCATE(ulat_phy(nbp_phys,llm))
+      ALLOCATE(q_phy(nbp_phys,llm,nqtot))
+      ALLOCATE(wflux_phy(nbp_phys,llm))
+      ALLOCATE(dulon_phy(nbp_phys,llm))
+      ALLOCATE(dulat_phy(nbp_phys,llm))
+      ALLOCATE(dTemp_phy(nbp_phys,llm))
+      ALLOCATE(dq_phy(nbp_phys,llm,nqtot))
+      ALLOCATE(dps_phy(nbp_phys))
+!$OMP END MASTER
+!$OMP BARRIER
+    ENDIF
+
+!$OMP MASTER        
+    CALL update_calendar(it)
+!$OMP END MASTER
+!$OMP BARRIER
+    dtphy=itau_physics*dt
+    IF(it==itaumax) THEN 
+      lafin=.TRUE.
+    ELSE 
+      lafin=.FALSE.
+    ENDIF
+    CALL transfert_message(f_u,req_u)
+    offset=0
+    
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      
+      phis=f_phis(ind)
+      ps=f_ps(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      q=f_q(ind)
+      wflux=f_wflux(ind)
+      p=f_p(ind)
+      pks=f_pks(ind)
+      pk=f_pk(ind)
+      p_layer=f_p_layer(ind)
+      theta=f_theta(ind)
+      phi=f_phi(ind)
+      Temp=f_Temp(ind)
+      ulon=f_ulon(ind)
+      ulat=f_ulat(ind)
+            
+      CALL grid_icosa_to_physics
+      
+    ENDDO
+
+!$OMP BARRIER
+!$OMP MASTER
+    CALL SYSTEM_CLOCK(start_clock)
+!$OMP END MASTER
+    CALL calfis_icosa(current_time, dtphy, lafin, presnivs,      &
+                      p_phy, p_layer_phy, phi_phy, phis_phy, ulon_phy, ulat_phy, Temp_phy, q_phy, wflux_phy, &
+                      dulon_phy, dulat_phy, dTemp_phy, dq_phy, dps_phy  )
+
+
+!$OMP MASTER
+    CALL SYSTEM_CLOCK(stop_clock)
+    count_clock=count_clock+stop_clock-start_clock
+!$OMP END MASTER
+
+!$OMP BARRIER                       
+    offset=0 
+
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      
+      theta_rhodz=f_theta_rhodz(ind)
+      u=f_u(ind)
+      q=f_q(ind)
+      ps=f_ps(ind)
+      dulon=f_dulon(ind)
+      dulat=f_dulat(ind)
+      Temp=f_temp(ind)
+      dTemp=f_dTemp(ind)
+      dq=f_dq(ind)
+      dps=f_dps(ind)
+      duc=f_duc(ind)
+      p=f_p(ind)
+      pks=f_pks(ind)
+      pk=f_pk(ind)
+      
+      CALL grid_physics_to_icosa
+    ENDDO
+
+!$OMP BARRIER
+     
+  CONTAINS
+   
+    SUBROUTINE grid_physics_to_icosa
+    USE theta2theta_rhodz_mod
+    USE omp_para
+    IMPLICIT NONE
+      INTEGER :: i,j,ij,l,iq
+          
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          offset=offset+1
+          
+          dulon(ij,ll_begin:ll_end)=dulon_phy(offset,ll_begin:ll_end)
+          dulat(ij,ll_begin:ll_end)=dulat_phy(offset,ll_begin:ll_end)
+          dTemp(ij,ll_begin:ll_end)=dTemp_phy(offset,ll_begin:ll_end)
+          Temp(ij,ll_begin:ll_end) = Temp_phy(offset,ll_begin:ll_end)
+          dq(ij,ll_begin:ll_end,:)=dq_phy(offset,ll_begin:ll_end,:)
+          if (omp_first) dps(ij)=dps_phy(offset)
+        ENDDO
+      ENDDO
+    
+      DO l=ll_begin,ll_end
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            duc(ij,:,l)=dulon(ij,l)*elon_i(ij,:)+dulat(ij,l)*elat_i(ij,:)
+          ENDDO
+        ENDDO
+      ENDDO
+
+      DO l=ll_begin,ll_end
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            u(ij+u_right,l) = u(ij+u_right,l) + dtphy * sum( 0.5*(duc(ij,:,l) + duc(ij+t_right,:,l))*ep_e(ij+u_right,:) )
+            u(ij+u_lup,l) = u(ij+u_lup,l) + dtphy * sum( 0.5*(duc(ij,:,l) + duc(ij+t_lup,:,l))*ep_e(ij+u_lup,:) )
+            u(ij+u_ldown,l) = u(ij+u_ldown,l) + dtphy*sum( 0.5*(duc(ij,:,l) + duc(ij+t_ldown,:,l))*ep_e(ij+u_ldown,:) )
+          ENDDO
+        ENDDO
+      ENDDO          
+
+      DO l=ll_begin,ll_end
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            Temp(ij,l)=Temp(ij,l)+ dtphy * dTemp(ij,l)
+          ENDDO
+        ENDDO
+      ENDDO          
+      
+      DO iq=1,nqtot
+        DO l=ll_begin,ll_end
+          DO j=jj_begin,jj_end
+            DO i=ii_begin,ii_end
+              ij=(j-1)*iim+i
+              q(ij,l,iq)=q(ij,l,iq)+ dtphy * dq(ij,l,iq)
+            ENDDO
+          ENDDO
+        ENDDO 
+      ENDDO
+
+!$OMP BARRIER
+      
+     IF (omp_first) THEN
+       DO j=jj_begin,jj_end
+         DO i=ii_begin,ii_end
+           ij=(j-1)*iim+i
+           ps(ij)=ps(ij)+ dtphy * dps(ij)
+          ENDDO
+       ENDDO
+     ENDIF
+
+!     CALL compute_temperature2theta_rhodz(ps,Temp,theta_rhodz,0)
+
+! compute pression
+!$OMP BARRIER
+      DO    l    = ll_begin,ll_endp1
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            p(ij,l) = ap(l) + bp(l) * ps(ij)
+          ENDDO
+        ENDDO
+      ENDDO
+
+!$OMP BARRIER
+
+! compute exner
+       
+       IF (omp_first) THEN
+         DO j=jj_begin,jj_end
+            DO i=ii_begin,ii_end
+               ij=(j-1)*iim+i
+               pks(ij) = cpp * ( ps(ij)/preff ) ** kappa
+            ENDDO
+         ENDDO
+       ENDIF
+
+       ! 3D : pk
+       DO l = ll_begin,ll_end
+          DO j=jj_begin,jj_end
+             DO i=ii_begin,ii_end
+                ij=(j-1)*iim+i
+                pk(ij,l) = cpp * ((.5/preff)*(p(ij,l)+p(ij,l+1))) ** kappa
+             ENDDO
+          ENDDO
+       ENDDO
+
+!$OMP BARRIER
+
+!   compute theta, temperature and pression at layer
+    DO    l    = ll_begin, ll_end
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          theta_rhodz(ij,l) = temp(ij,l) * ((p(ij,l)-p(ij,l+1))/g) / (pk(ij,l) / cpp )
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    END SUBROUTINE grid_physics_to_icosa
+    
+    
+    SUBROUTINE grid_icosa_to_physics
+    USE pression_mod
+    USE exner_mod
+    USE theta2theta_rhodz_mod
+    USE geopotential_mod
+    USE wind_mod
+    USE omp_para
+    IMPLICIT NONE
+    
+    REAL(rstd) :: uc(3)
+    INTEGER :: i,j,ij,l
+    
+
+! compute pression
+
+      DO    l    = ll_begin,ll_endp1
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            p(ij,l) = ap(l) + bp(l) * ps(ij)
+          ENDDO
+        ENDDO
+      ENDDO
+
+!$OMP BARRIER
+
+! compute exner
+       
+       IF (omp_first) THEN
+         DO j=jj_begin,jj_end
+            DO i=ii_begin,ii_end
+               ij=(j-1)*iim+i
+               pks(ij) = cpp * ( ps(ij)/preff ) ** kappa
+            ENDDO
+         ENDDO
+       ENDIF
+
+       ! 3D : pk
+       DO l = ll_begin,ll_end
+          DO j=jj_begin,jj_end
+             DO i=ii_begin,ii_end
+                ij=(j-1)*iim+i
+                pk(ij,l) = cpp * ((.5/preff)*(p(ij,l)+p(ij,l+1))) ** kappa
+             ENDDO
+          ENDDO
+       ENDDO
+
+!$OMP BARRIER
+
+!   compute theta, temperature and pression at layer
+    DO    l    = ll_begin, ll_end
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          theta(ij,l) = theta_rhodz(ij,l) / ((p(ij,l)-p(ij,l+1))/g)
+          Temp(ij,l) = theta(ij,l) * pk(ij,l) / cpp
+          p_layer(ij,l)=preff*(pk(ij,l)/cpp)**(1./kappa) 
+        ENDDO
+      ENDDO
+    ENDDO
+
+
+!!! Compute geopotential
+       
+  ! for first layer
+  IF (omp_first) THEN
+    DO j=jj_begin,jj_end
+      DO i=ii_begin,ii_end
+        ij=(j-1)*iim+i
+        phi( ij,1 ) = phis( ij ) + theta(ij,1) * ( pks(ij) - pk(ij,1) )
+      ENDDO
+    ENDDO
+  ENDIF
+!!-> implicit flush on phi(:,1)
+          
+  ! for other layers
+   DO l = ll_beginp1, ll_end
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         phi(ij,l) =  0.5 * ( theta(ij,l)  + theta(ij,l-1) )  & 
+                          * (  pk(ij,l-1) -  pk(ij,l)    )
+       ENDDO
+     ENDDO
+   ENDDO       
+
+!$OMP BARRIER
+
+   DO l = 2, llm
+!$OMP DO
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         phi(ij,l) = phi(ij,l)+ phi(ij,l-1)
+       ENDDO
+     ENDDO
+   ENDDO
+! --> IMPLICIT FLUSH on phi
+
+
+
+! compute wind centered lon lat compound
+    DO l=ll_begin,ll_end
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          uc(:)=1/Ai(ij)*                                                                                                &
+                        ( ne(ij,right)*u(ij+u_right,l)*le(ij+u_right)*((xyz_v(ij+z_rdown,:)+xyz_v(ij+z_rup,:))/2-centroid(ij,:))  &
+                         + ne(ij,rup)*u(ij+u_rup,l)*le(ij+u_rup)*((xyz_v(ij+z_rup,:)+xyz_v(ij+z_up,:))/2-centroid(ij,:))          &
+                         + ne(ij,lup)*u(ij+u_lup,l)*le(ij+u_lup)*((xyz_v(ij+z_up,:)+xyz_v(ij+z_lup,:))/2-centroid(ij,:))          &
+                         + ne(ij,left)*u(ij+u_left,l)*le(ij+u_left)*((xyz_v(ij+z_lup,:)+xyz_v(ij+z_ldown,:))/2-centroid(ij,:))    &
+                         + ne(ij,ldown)*u(ij+u_ldown,l)*le(ij+u_ldown)*((xyz_v(ij+z_ldown,:)+xyz_v(ij+z_down,:))/2-centroid(ij,:))&
+                         + ne(ij,rdown)*u(ij+u_rdown,l)*le(ij+u_rdown)*((xyz_v(ij+z_down,:)+xyz_v(ij+z_rdown,:))/2-centroid(ij,:)))
+          ulon(ij,l)=sum(uc(:)*elon_i(ij,:))
+          ulat(ij,l)=sum(uc(:)*elat_i(ij,:)) 
+        ENDDO
+      ENDDO
+    ENDDO
+
+!$OMP BARRIER
+
+
+      
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          offset=offset+1
+
+          IF (omp_first) ps_phy(offset) = ps(ij)
+          p_phy(offset,ll_begin:ll_endp1) = p(ij,ll_begin:ll_endp1)
+          p_layer_phy(offset,ll_begin:ll_end) = p_layer(ij,ll_begin:ll_end)
+          Temp_phy(offset,ll_begin:ll_end) = Temp(ij,ll_begin:ll_end)
+          IF (omp_first) phis_phy(offset) = phis(ij)
+          phi_phy(offset,ll_begin:ll_end) = phi(ij,ll_begin:ll_end)-phis(ij)
+          ulon_phy(offset,ll_begin:ll_end) = ulon(ij,ll_begin:ll_end)
+          ulat_phy(offset,ll_begin:ll_end) = ulat(ij,ll_begin:ll_end)
+          q_phy(offset,ll_begin:ll_end,:) = q(ij,ll_begin:ll_end,:)
+          wflux_phy(offset,ll_begin:ll_end) = wflux(ij,ll_begin:ll_end)
+        ENDDO
+      ENDDO
+     
+     END SUBROUTINE grid_icosa_to_physics
+
+  END SUBROUTINE physics
+  
+  
+END MODULE physics_lmdz5_mod
+    
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_lmdz_generic.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_lmdz_generic.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/physics_lmdz_generic.f90	(revision 329)
@@ -0,0 +1,603 @@
+MODULE physics_lmdz_generic_mod
+  USE field_mod
+  USE transfert_mod
+  
+  INTEGER,SAVE :: nbp_phys
+  TYPE(t_message) :: req_u
+
+  TYPE(t_field),POINTER :: f_p(:) 
+  TYPE(t_field),POINTER :: f_pks(:)  
+  TYPE(t_field),POINTER :: f_pk(:)  
+  TYPE(t_field),POINTER :: f_p_layer(:)    
+  TYPE(t_field),POINTER :: f_theta(:)   
+  TYPE(t_field),POINTER :: f_phi(:)   
+  TYPE(t_field),POINTER :: f_Temp(:)    
+  TYPE(t_field),POINTER :: f_ulon(:)    
+  TYPE(t_field),POINTER :: f_ulat(:)   
+  TYPE(t_field),POINTER :: f_dulon(:)
+  TYPE(t_field),POINTER :: f_dulat(:)
+  TYPE(t_field),POINTER :: f_dTemp(:)
+  TYPE(t_field),POINTER :: f_dq(:)
+  TYPE(t_field),POINTER :: f_dps(:)
+  TYPE(t_field),POINTER :: f_duc(:)
+
+  INTEGER :: start_clock
+  INTEGER :: stop_clock
+  INTEGER :: count_clock=0
+  
+  REAL :: start_day
+  REAL :: day_length
+  REAL :: year_length
+  
+ INTEGER,ALLOCATABLE,SAVE :: domain_offset(:)
+
+  
+
+CONTAINS
+
+  SUBROUTINE init_physics
+  USE icosa
+  USE domain_mod
+  USE dimensions
+  USE mpi_mod
+  USE mpipara
+  USE disvert_mod
+  USE xios_mod
+  
+  IMPLICIT NONE
+  INTEGER  :: distrib(0:mpi_size-1)
+  INTEGER  :: ind,i,j,ij,pos
+
+  REAL(rstd),ALLOCATABLE :: latfi(:)
+  REAL(rstd),ALLOCATABLE :: lonfi(:)
+  REAL(rstd),ALLOCATABLE :: airefi(:)
+  REAL(rstd),ALLOCATABLE :: bounds_latfi(:,:)
+  REAL(rstd),ALLOCATABLE :: bounds_lonfi(:,:)
+  INTEGER :: time0
+
+    start_day=0
+    day_length=86400
+    year_length=86400*365.25
+    
+    CALL getin('start_day',start_day)
+    CALL getin('day_length',day_length)
+    CALL getin('year_length',year_length)
+
+!$OMP PARALLEL
+    CALL allocate_field(f_p,field_t,type_real,llm+1)
+    CALL allocate_field(f_pks,field_t,type_real)
+    CALL allocate_field(f_pk,field_t,type_real,llm)
+    CALL allocate_field(f_p_layer,field_t,type_real,llm)
+    CALL allocate_field(f_theta,field_t,type_real,llm)
+    CALL allocate_field(f_phi,field_t,type_real,llm)
+    CALL allocate_field(f_Temp,field_t,type_real,llm)
+    CALL allocate_field(f_ulon,field_t,type_real,llm)
+    CALL allocate_field(f_ulat,field_t,type_real,llm)
+    CALL allocate_field(f_dulon,field_t,type_real,llm)
+    CALL allocate_field(f_dulat,field_t,type_real,llm)
+    CALL allocate_field(f_dTemp,field_t,type_real,llm)
+    CALL allocate_field(f_dq,field_t,type_real,llm,nqtot)
+    CALL allocate_field(f_dps,field_t,type_real)
+    CALL allocate_field(f_duc,field_t,type_real,3,llm)    
+!$OMP END PARALLEL    
+
+    ALLOCATE(domain_offset(ndomain))
+    nbp_phys=0
+    domain_offset(1)=0
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      IF (ind<ndomain) THEN 
+        domain_offset(ind+1)=domain_offset(ind)+ii_nb*jj_nb
+      ENDIF
+      nbp_phys=nbp_phys+ii_nb*jj_nb
+    ENDDO
+    
+    CALL MPI_ALLGATHER(nbp_phys,1,MPI_INTEGER,distrib,1,MPI_INTEGER,comm_icosa,ierr)
+    
+    ALLOCATE(latfi(nbp_phys))
+    ALLOCATE(lonfi(nbp_phys))
+    ALLOCATE(airefi(nbp_phys))
+    ALLOCATE(bounds_latfi(nbp_phys,6))
+    ALLOCATE(bounds_lonfi(nbp_phys,6))
+    
+    pos=0
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          pos=pos+1
+          CALL xyz2lonlat(xyz_i(ij,:),lonfi(pos),latfi(pos))
+          CALL xyz2lonlat(xyz_v(ij+z_rup,:), bounds_lonfi(pos,1), bounds_latfi(pos,1))
+          CALL xyz2lonlat(xyz_v(ij+z_up,:), bounds_lonfi(pos,2), bounds_latfi(pos,2))
+          CALL xyz2lonlat(xyz_v(ij+z_lup,:), bounds_lonfi(pos,3), bounds_latfi(pos,3))
+          CALL xyz2lonlat(xyz_v(ij+z_ldown,:), bounds_lonfi(pos,4), bounds_latfi(pos,4))
+          CALL xyz2lonlat(xyz_v(ij+z_down,:), bounds_lonfi(pos,5), bounds_latfi(pos,5))
+          CALL xyz2lonlat(xyz_v(ij+z_rdown,:), bounds_lonfi(pos,6), bounds_latfi(pos,6))
+          airefi(pos)=Ai(ij)  
+        ENDDO
+      ENDDO
+    ENDDO
+
+    time0=itau0*dt
+    CALL initialize_unstructured_physics(nbp_phys,llm, comm_icosa, mpi_size,distrib,            &
+                                         day_length,start_day,time0,itau_physics*dt,                  &
+                                         6,latfi,lonfi,airefi,bounds_lonfi,bounds_latfi,         &
+                                         radius,g, gas_constant/mu, cpp,                        &
+                                         preff, ap, bp)                                         
+    
+    CALL xios_set_context    
+    
+!    CALL init_phys_lmdz(128,97,llm, comm_icosa, mpi_size, distrib)
+    
+    CALL init_gcm_lmdz(nbp_phys,mpi_size,distrib,latfi,lonfi,airefi)
+!    CALL init_phys_lmdz(128,97,llm, comm_icosa, mpi_size, distrib)
+!    CALL iniphysiq(llm,day_length,start_day,itau_physics*dt,     &
+!                   latfi,lonfi,airefi,radius,g, gas_constant/mu, cpp,     &
+!                   ap, bp)
+    
+    
+    
+  END SUBROUTINE init_physics
+  
+  SUBROUTINE physics(it,f_phis, f_ps, f_theta_rhodz, f_u, f_wflux, f_q)
+  USE ICOSA
+  USE time_mod
+  USE disvert_mod
+  USE transfert_mod
+  USE mpipara
+  USE xios_mod
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)    :: it
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_wflux(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    REAL(rstd),POINTER :: phis(:)
+    REAL(rstd),POINTER :: ps(:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:)
+    REAL(rstd),POINTER :: u(:,:)
+    REAL(rstd),POINTER :: wflux(:,:)
+    REAL(rstd),POINTER :: q(:,:,:)
+    REAL(rstd),POINTER :: p(:,:)
+    REAL(rstd),POINTER :: pks(:)
+    REAL(rstd),POINTER :: pk(:,:)
+    REAL(rstd),POINTER :: p_layer(:,:)
+    REAL(rstd),POINTER :: theta(:,:)
+    REAL(rstd),POINTER :: phi(:,:)
+    REAL(rstd),POINTER :: Temp(:,:)
+    REAL(rstd),POINTER :: ulon(:,:)
+    REAL(rstd),POINTER :: ulat(:,:)
+    REAL(rstd),POINTER :: dulon(:,:)
+    REAL(rstd),POINTER :: dulat(:,:)
+    REAL(rstd),POINTER :: dTemp(:,:)
+    REAL(rstd),POINTER :: dq(:,:,:)
+    REAL(rstd),POINTER :: dps(:)
+    REAL(rstd),POINTER :: duc(:,:,:)
+
+
+    INTEGER :: ind
+    
+    REAL(rstd),ALLOCATABLE,SAVE :: ps_phy(:)
+    REAL(rstd),ALLOCATABLE,SAVE :: p_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: p_layer_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: Temp_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: phis_phy(:)
+    REAL(rstd),ALLOCATABLE,SAVE :: phi_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: ulon_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: ulat_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: q_phy(:,:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: wflux_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dulon_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dulat_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dTemp_phy(:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dq_phy(:,:,:)
+    REAL(rstd),ALLOCATABLE,SAVE :: dps_phy(:)
+    REAL(rstd) :: dtphy 
+    REAL(rstd) :: time
+    REAL(rstd) :: day
+    REAL(rstd) :: real_time
+    INTEGER    :: offset
+    LOGICAL :: lafin=.FALSE.
+    LOGICAL,SAVE :: first=.TRUE.
+!$OMP THREADPRIVATE(first)
+
+    
+    IF (first) THEN
+      first=.FALSE.
+      CALL init_message(f_u,req_e1_vect,req_u)
+!$OMP MASTER
+      ALLOCATE(ps_phy(nbp_phys))
+      ALLOCATE(p_phy(nbp_phys,llm+1))
+      ALLOCATE(p_layer_phy(nbp_phys,llm))
+      ALLOCATE(Temp_phy(nbp_phys,llm))
+      ALLOCATE(phis_phy(nbp_phys))
+      ALLOCATE(phi_phy(nbp_phys,llm))
+      ALLOCATE(ulon_phy(nbp_phys,llm))
+      ALLOCATE(ulat_phy(nbp_phys,llm))
+      ALLOCATE(q_phy(nbp_phys,llm,nqtot))
+      ALLOCATE(wflux_phy(nbp_phys,llm))
+      ALLOCATE(dulon_phy(nbp_phys,llm))
+      ALLOCATE(dulat_phy(nbp_phys,llm))
+      ALLOCATE(dTemp_phy(nbp_phys,llm))
+      ALLOCATE(dq_phy(nbp_phys,llm,nqtot))
+      ALLOCATE(dps_phy(nbp_phys))
+      
+!$OMP END MASTER
+!$OMP BARRIER
+    ENDIF
+
+    IF(it==itau0+itaumax .OR. it+itau_physics > itau0+itaumax) THEN 
+      lafin=.TRUE.
+    ELSE 
+      lafin=.FALSE.
+    ENDIF
+
+!$OMP MASTER        
+!    CALL update_calendar(it)
+!$OMP END MASTER
+!$OMP BARRIER
+    dtphy=itau_physics*dt
+    real_time=start_day*day_length+it*dt
+    day  = INT( MODULO(real_time,year_length) / day_length) 
+    time = MODULO(real_time,day_length) / day_length
+
+!$OMP MASTER    
+    IF (is_mpi_root) PRINT*,"Enterring in physic : day", day, "  time : ",time 
+!$OMP END MASTER    
+    
+    
+    
+    
+    CALL transfert_message(f_u,req_u)
+    
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      IF (assigned_domain(ind)) THEN
+        offset=domain_offset(ind)
+        CALL swap_geometry(ind)
+      
+        phis=f_phis(ind)
+        ps=f_ps(ind)
+        theta_rhodz=f_theta_rhodz(ind)
+        u=f_u(ind)
+        q=f_q(ind)
+        wflux=f_wflux(ind)
+        p=f_p(ind)
+        pks=f_pks(ind)
+        pk=f_pk(ind)
+        p_layer=f_p_layer(ind)
+        theta=f_theta(ind)
+        phi=f_phi(ind)
+        Temp=f_Temp(ind)
+        ulon=f_ulon(ind)
+        ulat=f_ulat(ind)
+            
+        CALL grid_icosa_to_physics
+
+      ENDIF
+    ENDDO
+
+!$OMP BARRIER
+!$OMP MASTER
+    CALL SYSTEM_CLOCK(start_clock)
+!$OMP END MASTER
+    CALL calfis_icosa(dtphy, lafin, day, time, presnivs,      &
+                      p_phy, p_layer_phy, phi_phy, phis_phy, ulon_phy, ulat_phy, Temp_phy, q_phy, wflux_phy, &
+                      dulon_phy, dulat_phy, dTemp_phy, dq_phy, dps_phy  )
+
+
+!$OMP MASTER
+    CALL SYSTEM_CLOCK(stop_clock)
+    count_clock=count_clock+stop_clock-start_clock
+!$OMP END MASTER
+
+!$OMP BARRIER                       
+
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      IF (assigned_domain(ind)) THEN
+        CALL swap_geometry(ind)
+        offset=domain_offset(ind)
+      
+        theta_rhodz=f_theta_rhodz(ind)
+        u=f_u(ind)
+        q=f_q(ind)
+        ps=f_ps(ind)
+        dulon=f_dulon(ind)
+        dulat=f_dulat(ind)
+        Temp=f_temp(ind)
+        dTemp=f_dTemp(ind)
+        dq=f_dq(ind)
+        dps=f_dps(ind)
+        duc=f_duc(ind)
+        p=f_p(ind)
+        pks=f_pks(ind)
+        pk=f_pk(ind)
+      
+        CALL grid_physics_to_icosa
+      ENDIF
+    ENDDO
+
+!$OMP BARRIER
+    CALL xios_set_context    
+     
+  CONTAINS
+   
+    SUBROUTINE grid_physics_to_icosa
+    USE theta2theta_rhodz_mod
+    USE omp_para
+    IMPLICIT NONE
+      INTEGER :: i,j,ij,l,iq
+          
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          offset=offset+1
+          
+          dulon(ij,ll_begin:ll_end)=dulon_phy(offset,ll_begin:ll_end)
+          dulat(ij,ll_begin:ll_end)=dulat_phy(offset,ll_begin:ll_end)
+          dTemp(ij,ll_begin:ll_end)=dTemp_phy(offset,ll_begin:ll_end)
+          Temp(ij,ll_begin:ll_end) = Temp_phy(offset,ll_begin:ll_end)
+          dq(ij,ll_begin:ll_end,:)=dq_phy(offset,ll_begin:ll_end,:)
+          if (omp_first) dps(ij)=dps_phy(offset)
+        ENDDO
+      ENDDO
+    
+      DO l=ll_begin,ll_end
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            duc(ij,:,l)=dulon(ij,l)*elon_i(ij,:)+dulat(ij,l)*elat_i(ij,:)
+          ENDDO
+        ENDDO
+      ENDDO
+
+      DO l=ll_begin,ll_end
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            u(ij+u_right,l) = u(ij+u_right,l) + dtphy * sum( 0.5*(duc(ij,:,l) + duc(ij+t_right,:,l))*ep_e(ij+u_right,:) )
+            u(ij+u_lup,l) = u(ij+u_lup,l) + dtphy * sum( 0.5*(duc(ij,:,l) + duc(ij+t_lup,:,l))*ep_e(ij+u_lup,:) )
+            u(ij+u_ldown,l) = u(ij+u_ldown,l) + dtphy*sum( 0.5*(duc(ij,:,l) + duc(ij+t_ldown,:,l))*ep_e(ij+u_ldown,:) )
+          ENDDO
+        ENDDO
+      ENDDO          
+
+      DO l=ll_begin,ll_end
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            Temp(ij,l)=Temp(ij,l)+ dtphy * dTemp(ij,l)
+          ENDDO
+        ENDDO
+      ENDDO          
+      
+      DO iq=1,nqtot
+        DO l=ll_begin,ll_end
+          DO j=jj_begin,jj_end
+            DO i=ii_begin,ii_end
+              ij=(j-1)*iim+i
+              q(ij,l,iq)=q(ij,l,iq)+ dtphy * dq(ij,l,iq)
+            ENDDO
+          ENDDO
+        ENDDO 
+      ENDDO
+
+!$OMP BARRIER
+      
+     IF (omp_first) THEN
+       DO j=jj_begin,jj_end
+         DO i=ii_begin,ii_end
+           ij=(j-1)*iim+i
+           ps(ij)=ps(ij)+ dtphy * dps(ij)
+          ENDDO
+       ENDDO
+     ENDIF
+
+!     CALL compute_temperature2theta_rhodz(ps,Temp,theta_rhodz,0)
+
+! compute pression
+!$OMP BARRIER
+      DO    l    = ll_begin,ll_endp1
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            p(ij,l) = ap(l) + bp(l) * ps(ij)
+          ENDDO
+        ENDDO
+      ENDDO
+
+!$OMP BARRIER
+
+! compute exner
+       
+       IF (omp_first) THEN
+         DO j=jj_begin,jj_end
+            DO i=ii_begin,ii_end
+               ij=(j-1)*iim+i
+               pks(ij) = cpp * ( ps(ij)/preff ) ** kappa
+            ENDDO
+         ENDDO
+       ENDIF
+
+       ! 3D : pk
+       DO l = ll_begin,ll_end
+          DO j=jj_begin,jj_end
+             DO i=ii_begin,ii_end
+                ij=(j-1)*iim+i
+                pk(ij,l) = cpp * ((.5/preff)*(p(ij,l)+p(ij,l+1))) ** kappa
+             ENDDO
+          ENDDO
+       ENDDO
+
+!$OMP BARRIER
+
+!   compute theta, temperature and pression at layer
+    DO    l    = ll_begin, ll_end
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          theta_rhodz(ij,l) = temp(ij,l) * ((p(ij,l)-p(ij,l+1))/g) / (pk(ij,l) / cpp )
+        ENDDO
+      ENDDO
+    ENDDO
+    
+    END SUBROUTINE grid_physics_to_icosa
+    
+    
+    SUBROUTINE grid_icosa_to_physics
+    USE pression_mod
+    USE exner_mod
+    USE theta2theta_rhodz_mod
+    USE geopotential_mod
+    USE wind_mod
+    USE omp_para
+    IMPLICIT NONE
+    
+    REAL(rstd) :: uc(3)
+    INTEGER :: i,j,ij,l
+    
+
+! compute pression
+
+      DO    l    = ll_begin,ll_endp1
+        DO j=jj_begin,jj_end
+          DO i=ii_begin,ii_end
+            ij=(j-1)*iim+i
+            p(ij,l) = ap(l) + bp(l) * ps(ij)
+          ENDDO
+        ENDDO
+      ENDDO
+
+!$OMP BARRIER
+
+! compute exner
+       
+       IF (omp_first) THEN
+         DO j=jj_begin,jj_end
+            DO i=ii_begin,ii_end
+               ij=(j-1)*iim+i
+               pks(ij) = cpp * ( ps(ij)/preff ) ** kappa
+            ENDDO
+         ENDDO
+       ENDIF
+
+       ! 3D : pk
+       DO l = ll_begin,ll_end
+          DO j=jj_begin,jj_end
+             DO i=ii_begin,ii_end
+                ij=(j-1)*iim+i
+                pk(ij,l) = cpp * ((.5/preff)*(p(ij,l)+p(ij,l+1))) ** kappa
+             ENDDO
+          ENDDO
+       ENDDO
+
+!$OMP BARRIER
+
+!   compute theta, temperature and pression at layer
+    DO    l    = ll_begin, ll_end
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          theta(ij,l) = theta_rhodz(ij,l) / ((p(ij,l)-p(ij,l+1))/g)
+          Temp(ij,l) = theta(ij,l) * pk(ij,l) / cpp
+          p_layer(ij,l)=preff*(pk(ij,l)/cpp)**(1./kappa) 
+        ENDDO
+      ENDDO
+    ENDDO
+
+
+!!! Compute geopotential
+       
+  ! for first layer
+  IF (omp_first) THEN
+    DO j=jj_begin,jj_end
+      DO i=ii_begin,ii_end
+        ij=(j-1)*iim+i
+        phi( ij,1 ) = phis( ij ) + theta(ij,1) * ( pks(ij) - pk(ij,1) )
+      ENDDO
+    ENDDO
+  ENDIF
+!!-> implicit flush on phi(:,1)
+          
+  ! for other layers
+   DO l = ll_beginp1, ll_end
+     DO j=jj_begin,jj_end
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         phi(ij,l) =  0.5 * ( theta(ij,l)  + theta(ij,l-1) )  & 
+                          * (  pk(ij,l-1) -  pk(ij,l)    )
+       ENDDO
+     ENDDO
+   ENDDO       
+
+!$OMP BARRIER
+
+   DO l = 2, llm
+     DO j=jj_begin,jj_end
+! ---> Bug compilo intel ici en openmp
+! ---> Couper la boucle
+       if (j==jj_end+1) PRINT*,"this message must not be printed"
+       DO i=ii_begin,ii_end
+         ij=(j-1)*iim+i
+         phi(ij,l) = phi(ij,l)+ phi(ij,l-1)
+       ENDDO
+     ENDDO
+   ENDDO
+! --> IMPLICIT FLUSH on phi
+
+
+
+! compute wind centered lon lat compound
+    DO l=ll_begin,ll_end
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          uc(:)=1/Ai(ij)*                                                                                                &
+                        ( ne(ij,right)*u(ij+u_right,l)*le(ij+u_right)*((xyz_v(ij+z_rdown,:)+xyz_v(ij+z_rup,:))/2-centroid(ij,:))  &
+                         + ne(ij,rup)*u(ij+u_rup,l)*le(ij+u_rup)*((xyz_v(ij+z_rup,:)+xyz_v(ij+z_up,:))/2-centroid(ij,:))          &
+                         + ne(ij,lup)*u(ij+u_lup,l)*le(ij+u_lup)*((xyz_v(ij+z_up,:)+xyz_v(ij+z_lup,:))/2-centroid(ij,:))          &
+                         + ne(ij,left)*u(ij+u_left,l)*le(ij+u_left)*((xyz_v(ij+z_lup,:)+xyz_v(ij+z_ldown,:))/2-centroid(ij,:))    &
+                         + ne(ij,ldown)*u(ij+u_ldown,l)*le(ij+u_ldown)*((xyz_v(ij+z_ldown,:)+xyz_v(ij+z_down,:))/2-centroid(ij,:))&
+                         + ne(ij,rdown)*u(ij+u_rdown,l)*le(ij+u_rdown)*((xyz_v(ij+z_down,:)+xyz_v(ij+z_rdown,:))/2-centroid(ij,:)))
+          ulon(ij,l)=sum(uc(:)*elon_i(ij,:))
+          ulat(ij,l)=sum(uc(:)*elat_i(ij,:)) 
+        ENDDO
+      ENDDO
+    ENDDO
+
+!$OMP BARRIER
+
+
+      
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          offset=offset+1
+
+          IF (omp_first) ps_phy(offset) = ps(ij)
+          p_phy(offset,ll_begin:ll_endp1) = p(ij,ll_begin:ll_endp1)
+          p_layer_phy(offset,ll_begin:ll_end) = p_layer(ij,ll_begin:ll_end)
+          Temp_phy(offset,ll_begin:ll_end) = Temp(ij,ll_begin:ll_end)
+          IF (omp_first) phis_phy(offset) = phis(ij)
+          phi_phy(offset,ll_begin:ll_end) = phi(ij,ll_begin:ll_end)-phis(ij)
+          ulon_phy(offset,ll_begin:ll_end) = ulon(ij,ll_begin:ll_end)
+          ulat_phy(offset,ll_begin:ll_end) = ulat(ij,ll_begin:ll_end)
+          q_phy(offset,ll_begin:ll_end,:) = q(ij,ll_begin:ll_end,:)
+          wflux_phy(offset,ll_begin:ll_end) = wflux(ij,ll_begin:ll_end)
+        ENDDO
+      ENDDO
+     
+     END SUBROUTINE grid_icosa_to_physics
+
+  END SUBROUTINE physics
+  
+  
+END MODULE physics_lmdz_generic_mod
+    
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/prec.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/prec.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/prec.f90	(revision 329)
@@ -0,0 +1,14 @@
+MODULE prec
+  INTEGER, PARAMETER :: i4=selected_int_kind(10)
+  INTEGER, PARAMETER :: i8=selected_int_kind(18)
+  INTEGER, PARAMETER :: r4=selected_real_kind(7)
+  INTEGER, PARAMETER :: r8=selected_real_kind(15)
+  INTEGER, PARAMETER :: c4=r4
+  INTEGER, PARAMETER :: c8=r8
+  INTEGER, PARAMETER :: istd=i4
+  INTEGER, PARAMETER :: rstd=r8
+  INTEGER, PARAMETER :: cstd=c8
+END MODULE prec
+  
+ 
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/pression.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/pression.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/pression.f90	(revision 329)
@@ -0,0 +1,47 @@
+MODULE pression_mod
+
+CONTAINS
+
+  SUBROUTINE pression(f_ps,f_p)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ps(:)
+    TYPE(t_field), POINTER :: f_p(:)
+  
+    REAL(rstd), POINTER :: ps(:)
+    REAL(rstd), POINTER :: p(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      p=f_p(ind)
+      CALL compute_pression(ps, p,0)
+    ENDDO
+  
+  END SUBROUTINE pression
+  
+  SUBROUTINE compute_pression(ps,p,offset)
+  USE icosa
+  USE disvert_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd),INTENT(OUT) :: p(iim*jjm,llm+1)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+
+    IF(ap_bp_present) THEN
+    DO    l    = 1, llm+1
+      DO j=jj_begin-offset,jj_end+offset
+        DO i=ii_begin-offset,ii_end+offset
+          ij=(j-1)*iim+i
+          p(ij,l) = ap(l) + bp(l) * ps(ij)
+        ENDDO
+      ENDDO
+    ENDDO
+    END IF
+  END SUBROUTINE compute_pression
+
+END MODULE pression_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/restart.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/restart.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/restart.f90	(revision 329)
@@ -0,0 +1,623 @@
+MODULE restart_mod
+  USE field_mod
+
+  TYPE t_field_array
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER               :: id
+  END TYPE t_field_array
+
+  TYPE(t_field_array),SAVE :: field_array(20)
+!$OMP THREADPRIVATE(field_array)
+  
+  INTEGER,SAVE :: ncid
+  INTEGER,SAVE :: itid
+
+
+  PRIVATE :: ncid
+  
+CONTAINS
+  
+  SUBROUTINE write_restart(it,field0 ,field1 ,field2 ,field3 ,field4 ,field5 ,field6 ,field7 ,field8 ,field9,   &
+                           field10,field11,field12,field13,field14,field15,field16,field17,field18,field19 )
+  USE prec
+  USE metric
+  USE field_mod
+  USE domain_mod
+  USE netcdf_mod
+  USE mpipara
+  USE getin_mod
+  USE spherical_geom_mod
+  USE transfert_mod
+  USE disvert_mod
+ 
+  IMPLICIT NONE 
+  INTEGER,INTENT(IN)     :: it
+
+  TYPE(t_field),POINTER,OPTIONAL,DIMENSION(:) :: field0 ,field1 ,field2 ,field3 ,field4 ,field5 ,field6 ,field7 ,field8 ,field9
+  TYPE(t_field),POINTER,OPTIONAL,DIMENSION(:) :: field10,field11,field12,field13,field14,field15,field16,field17,field18,field19
+
+  TYPE(t_field_array) :: field_array(20)
+  INTEGER             :: nfield
+   
+  TYPE(t_domain),POINTER :: d
+  TYPE(t_field),POINTER :: field_glo(:)
+  TYPE(t_field),POINTER :: field(:)
+  
+  CHARACTER(LEN=255) :: restart_file_name
+  INTEGER,PARAMETER  :: nvert=6
+  INTEGER    ::  cellId, levId, edgeId,  vertid, lonId, latId, bounds_lonId, bounds_latId, nqId, levAxisId
+  INTEGER    :: ind,ind_glo,i,j,k,nf
+  INTEGER    :: status
+  REAL(rstd),ALLOCATABLE :: lon(:),lat(:),bounds_lon(:,:),bounds_lat(:,:)
+  LOGICAL,SAVE :: first=.TRUE.
+  CHARACTER(LEN=16) :: str_it
+!$OMP THREADPRIVATE(first)
+   
+    restart_file_name="restart"
+    CALL getin("restart_file_name",restart_file_name)
+
+!$OMP BARRIER
+!$OMP MASTER
+
+    nfield=0
+    IF (PRESENT(field0))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field0  ; ENDIF
+    IF (PRESENT(field1))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field1  ; ENDIF
+    IF (PRESENT(field2))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field2  ; ENDIF
+    IF (PRESENT(field3))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field3  ; ENDIF
+    IF (PRESENT(field4))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field4  ; ENDIF
+    IF (PRESENT(field5))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field5  ; ENDIF
+    IF (PRESENT(field6))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field6  ; ENDIF
+    IF (PRESENT(field7))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field7  ; ENDIF
+    IF (PRESENT(field8))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field8  ; ENDIF
+    IF (PRESENT(field9))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field9  ; ENDIF
+    IF (PRESENT(field10)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field10 ; ENDIF
+    IF (PRESENT(field11)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field11 ; ENDIF
+    IF (PRESENT(field12)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field12 ; ENDIF
+    IF (PRESENT(field13)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field13 ; ENDIF
+    IF (PRESENT(field14)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field14 ; ENDIF
+    IF (PRESENT(field15)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field15 ; ENDIF
+    IF (PRESENT(field16)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field16 ; ENDIF
+    IF (PRESENT(field17)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field17 ; ENDIF
+    IF (PRESENT(field18)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field18 ; ENDIF
+    IF (PRESENT(field19)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field19 ; ENDIF
+    
+      
+
+    IF (is_mpi_root) THEN
+      WRITE(str_it,*) it
+      status = NF90_CREATE(TRIM(ADJUSTL(restart_file_name))//"_"//TRIM(ADJUSTL(str_it))//'.nc', IOR(NF90_CLOBBER,NF90_NETCDF4), ncid)
+      IF (status/=NF90_NOERR) THEN
+        WRITE(*,*) "write_restart error: failed to create ",TRIM(ADJUSTL(restart_file_name))//"_"//TRIM(ADJUSTL(str_it))//'.nc'
+        WRITE(*,*) TRIM(NF90_STRERROR(status))
+      ELSE
+        WRITE(*,*) "write_restart: created ",TRIM(ADJUSTL(restart_file_name))//"_"//TRIM(ADJUSTL(str_it))//'.nc'
+      ENDIF
+      status = NF90_DEF_DIM(ncid,'cell',ncell_glo,cellId)
+      status = NF90_DEF_DIM(ncid,'edge',3*ncell_glo,edgeId)
+      status = NF90_DEF_DIM(ncid,'lev',llm,levId)
+      status = NF90_DEF_DIM(ncid,'nvert',nvert,vertId)
+      status = NF90_DEF_DIM(ncid,'nq',nqtot,nqId)
+!      status = NF90_PUT_ATT(ncid,NF90_GLOBAL,"iteration",it)
+      status = NF90_DEF_VAR(ncid,"iteration",NF90_INT,varid=itid)
+      
+      status = NF90_DEF_VAR(ncid,'lon',NF90_DOUBLE,(/ cellId /),lonId)
+      status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+      status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+      status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon")
+      status = NF90_DEF_VAR(ncid,'lat',NF90_DOUBLE,(/ cellId /),latId)
+      status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+      status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+      status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat")
+      status = NF90_DEF_VAR(ncid,'bounds_lon',NF90_DOUBLE,(/ vertId,cellId /),bounds_lonId)
+      status = NF90_DEF_VAR(ncid,'bounds_lat',NF90_DOUBLE,(/ vertId,cellId /),bounds_latId)
+      status = NF90_DEF_VAR(ncid,'lev',NF90_DOUBLE,(/ levId /),levAxisId)
+      status = NF90_PUT_ATT(ncid,levAxisId,"axis","Z")
+      status = NF90_PUT_ATT(ncid,levAxisId,"units","Pa")
+      status = NF90_PUT_ATT(ncid,levAxisId,"positive","down")
+      
+      DO nf=1,nfield
+        field=>field_array(nf)%field
+        IF (field(1)%field_type==field_T) THEN
+          IF (field(1)%ndim==2) THEN
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name)),NF90_DOUBLE,(/ cellId /),field_array(nf)%id)
+            status = NF90_PUT_ATT(ncid,field_array(nf)%id,"coordinates","lon lat")
+          ELSE IF (field(1)%ndim==3) THEN
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name)),NF90_DOUBLE,(/ cellId, levId /),field_array(nf)%id)
+            status = NF90_PUT_ATT(ncid,field_array(nf)%id,"coordinates","lev lon lat")
+          ELSE IF (field(1)%ndim==4) THEN
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name)),NF90_DOUBLE,(/ cellId, levId,nqId /),field_array(nf)%id)
+            status = NF90_PUT_ATT(ncid,field_array(nf)%id,"coordinates","nq lev lon lat")
+          ENDIF
+        ELSE IF (field(1)%field_type==field_U) THEN
+          IF (field(1)%ndim==2) THEN
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name)),NF90_DOUBLE,(/ edgeId /),field_array(nf)%id)
+          ELSE IF (field(1)%ndim==3) THEN
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name)),NF90_DOUBLE,(/ edgeId, levId /),field_array(nf)%id)
+          ELSE IF (field(1)%ndim==4) THEN
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name)),NF90_DOUBLE,(/ edgeId, levId, nqId /),field_array(nf)%id)
+          ENDIF
+        ENDIF
+        IF (status/=NF90_NOERR) THEN
+          WRITE(*,*) "write_restart error: for ",TRIM(ADJUSTL(field(1)%name))
+          WRITE(*,*) TRIM(NF90_STRERROR(status))
+        ENDIF
+      ENDDO
+          
+      
+      status = NF90_ENDDEF(ncid)
+      IF (status/=NF90_NOERR) THEN
+         WRITE(*,*) "write_restart error: failed to switch out of netcdf define mode"
+         WRITE(*,*) TRIM(NF90_STRERROR(status))
+         STOP
+      ENDIF
+      
+      ALLOCATE(lon(ncell_glo),lat(ncell_glo),bounds_lon(0:nvert-1,ncell_glo),bounds_lat(0:nvert-1,ncell_glo))
+      DO ind=1,ndomain_glo
+        d=>domain_glo(ind)
+        DO j=d%jj_begin,d%jj_end
+          DO i=d%ii_begin,d%ii_end
+             ind_glo=d%assign_cell_glo(i,j)
+             CALL xyz2lonlat(d%xyz(:,i,j),lon(ind_glo),lat(ind_glo))
+             lon(ind_glo)=lon(ind_glo)*180/Pi
+             lat(ind_glo)=lat(ind_glo)*180/Pi
+             DO k=0,5
+                 CALL xyz2lonlat(d%vertex(:,k,i,j),bounds_lon(k,ind_glo), bounds_lat(k,ind_glo))
+                 bounds_lat(k,ind_glo)=bounds_lat(k,ind_glo)*180/Pi
+                 bounds_lon(k,ind_glo)=bounds_lon(k,ind_glo)*180/Pi
+             ENDDO
+          ENDDO
+        ENDDO
+      ENDDO
+
+      status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ 1 /),count=(/ ncell_glo /))
+      status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ 1 /),count=(/ ncell_glo /))
+      status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,1 /),count=(/ nvert,ncell_glo /))
+      status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,1 /),count=(/ nvert,ncell_glo /))
+      status=NF90_PUT_VAR(ncid,levAxisId,REAL(presnivs,r8),start=(/ 1 /),count=(/ llm /))
+      first=.FALSE.
+      
+    ENDIF ! of IF (is_mpi_root)
+
+    IF (is_mpi_root) status=NF90_PUT_VAR(ncid,itid,it)
+    DO nf=1,nfield
+      field=>field_array(nf)%field
+      CALL write_restart_field(field,field_array(nf)%id,ncid)
+    ENDDO
+          
+!          status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name),NF90_DOUBLE,(/ ncellId /),fieldId(nf))
+!        ELSE IF (field(1)%ndim==3) THEN
+!          status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(field(1)%name),NF90_DOUBLE,(/ ncellId, levId /),fieldId(nf))
+!        ENDIF
+!      ENDDO
+
+
+    IF (is_mpi_root) THEN
+      status = NF90_CLOSE(ncid)      
+      IF (status/=NF90_NOERR) THEN
+         WRITE(*,*) "write_restart error: failed to close ",TRIM(ADJUSTL(restart_file_name))//"_"//TRIM(ADJUSTL(str_it))//'.nc'
+         WRITE(*,*) TRIM(NF90_STRERROR(status))
+         STOP
+      ELSE
+         WRITE(*,*) "write_restart: finished writing ",TRIM(ADJUSTL(restart_file_name))//"_"//TRIM(ADJUSTL(str_it))//'.nc'
+      ENDIF
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+  
+  END SUBROUTINE write_restart
+  
+  SUBROUTINE write_restart_field(field,fieldId,ncid)
+  USE prec
+  USE metric
+  USE field_mod
+  USE domain_mod
+  USE netcdf_mod
+  USE mpipara
+  USE getin_mod
+  USE spherical_geom_mod
+  USE transfert_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER,INTENT(IN)     :: fieldId
+    INTEGER,INTENT(IN)     :: ncid
+
+    TYPE(t_domain),POINTER :: d
+    TYPE(t_field),POINTER :: field_glo(:)
+    REAL(rstd),ALLOCATABLE :: global_field2d(:)
+    REAL(rstd),ALLOCATABLE :: global_field3d(:,:)
+    REAL(rstd),ALLOCATABLE :: global_field4d(:,:,:)
+    INTEGER :: i,j,ij,k,e,ind,ind_glo
+    INTEGER :: ndim, field_type
+    INTEGER :: status
+    
+      ndim=field(1)%ndim
+      field_Type= field(1)%field_type
+      
+      IF (is_mpi_root) THEN
+ 
+        IF (ndim==2) THEN
+          CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,name=field(1)%name)
+        ELSE IF (ndim==3) THEN
+          CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,field(1)%dim3,name=field(1)%name)
+        ELSE IF (ndim==4) THEN
+          CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,field(1)%dim3,field(1)%dim4,name=field(1)%name)
+        ENDIF
+      ENDIF
+      
+      CALL gather_field(field,field_glo)
+      
+
+      IF (is_mpi_root) THEN
+
+        IF (field_type==field_T) THEN
+          IF (ndim==2) THEN
+            ALLOCATE(global_field2d(ncell_glo))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  IF (d%own(i,j)) THEN 
+                    ij=(j-1)*d%iim+i
+                    ind_glo=d%assign_cell_glo(i,j)
+                    global_field2d(ind_glo)=field_glo(ind)%rval2d(ij)
+                  ENDIF 
+                ENDDO
+              ENDDO
+            ENDDO
+            status=NF90_PUT_VAR(ncid,fieldid,global_field2d,start=(/ 1 /),count=(/ ncell_glo /))
+          
+          ELSE IF (ndim==3) THEN
+            ALLOCATE(global_field3d(ncell_glo,llm))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  IF (d%own(i,j)) THEN 
+                    ij=(j-1)*d%iim+i
+                    ind_glo=d%assign_cell_glo(i,j)
+                    global_field3d(ind_glo,:)=field_glo(ind)%rval3d(ij,:)
+                  ENDIF
+                ENDDO
+              ENDDO
+            ENDDO
+            status=NF90_PUT_VAR(ncid,fieldid,global_field3d,start=(/ 1,1 /),count=(/ ncell_glo,llm /))
+          ELSE IF (ndim==4) THEN
+            ALLOCATE(global_field4d(ncell_glo,llm,nqtot))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  IF (d%own(i,j)) THEN 
+                    ij=(j-1)*d%iim+i
+                    ind_glo=d%assign_cell_glo(i,j)
+                    global_field4d(ind_glo,:,:)=field_glo(ind)%rval4d(ij,:,:)
+                  ENDIF
+                ENDDO
+              ENDDO
+            ENDDO
+            status=NF90_PUT_VAR(ncid,fieldid,global_field4d,start=(/ 1,1,1 /),count=(/ ncell_glo,llm,nqtot /))
+          ENDIF
+        
+        ELSE IF (field_type==field_U) THEN
+        
+          IF (ndim==2) THEN
+            ALLOCATE(global_field2d(3*ncell_glo))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  DO k=0,5
+                   IF (d%edge_assign_domain(k,i,j)==ind .AND. d%edge_assign_i(k,i,j)==i .AND. d%edge_assign_j(k,i,j)==j .AND. d%edge_assign_pos(k,i,j)==k) THEN
+                       ij=(j-1)*d%iim+i
+                      ind_glo=d%assign_cell_glo(i,j)
+                      e=cell_glo(ind_glo)%edge(MOD(k+d%delta(i,j)+6,6))  
+                      global_field2d(ind_glo)=d%edge_assign_sign(k,i,j)*field_glo(ind)%rval2d(ij+d%u_pos(k))
+                    ENDIF
+                  ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+            status=NF90_PUT_VAR(ncid,fieldid,REAL(global_field2d,r8),start=(/ 1 /),count=(/ 3*ncell_glo /))
+          ELSE IF (ndim==3) THEN
+            ALLOCATE(global_field3d(3*ncell_glo,llm))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  DO k=0,5
+                   IF (d%edge_assign_domain(k,i,j)==ind .AND. d%edge_assign_i(k,i,j)==i .AND. d%edge_assign_j(k,i,j)==j .AND. d%edge_assign_pos(k,i,j)==k) THEN
+                       ij=(j-1)*d%iim+i
+                      ind_glo=d%assign_cell_glo(i,j)
+                      e=cell_glo(ind_glo)%edge(MOD(k+d%delta(i,j)+6,6))  
+                      global_field3d(e,:)=d%edge_assign_sign(k,i,j)*field_glo(ind)%rval3d(ij+d%u_pos(k+1),:)
+                    ENDIF
+                  ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+            status=NF90_PUT_VAR(ncid,fieldid,global_field3d,start=(/ 1,1 /),count=(/ 3*ncell_glo,llm /))
+          ELSE IF (ndim==4) THEN
+            ALLOCATE(global_field4d(3*ncell_glo,llm,nqtot))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  DO k=0,5
+                    IF (d%edge_assign_domain(k,i,j)==ind .AND. d%edge_assign_i(k,i,j)==i .AND. d%edge_assign_j(k,i,j)==j .AND. d%edge_assign_pos(k,i,j)==k) THEN
+                      ij=(j-1)*d%iim+i
+                      ind_glo=d%assign_cell_glo(i,j)
+                      e=cell_glo(ind_glo)%edge(MOD(k+d%delta(i,j)+6,6))  
+                      global_field4d(e,:,:)=d%edge_assign_sign(k,i,j)*field_glo(ind)%rval4d(ij+d%u_pos(k+1),:,:)
+                    ENDIF
+                  ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+            status=NF90_PUT_VAR(ncid,fieldid,global_field3d,start=(/ 1,1,1 /),count=(/ 3*ncell_glo,llm,nqtot /))
+          ENDIF
+
+        ENDIF
+        
+        CALL deallocate_field_glo(field_glo)
+      
+      ENDIF
+      
+      
+  END SUBROUTINE write_restart_field
+
+
+  SUBROUTINE read_start(it,field0 ,field1 ,field2 ,field3 ,field4 ,field5 ,field6 ,field7 ,field8 ,field9,   &
+                           field10,field11,field12,field13,field14,field15,field16,field17,field18,field19 )
+  USE prec
+  USE metric
+  USE field_mod
+  USE domain_mod
+  USE netcdf_mod
+  USE mpipara
+  USE getin_mod
+  USE spherical_geom_mod
+  USE transfert_mod
+ 
+  IMPLICIT NONE
+  INTEGER, INTENT(OUT)  :: it
+  TYPE(t_field),POINTER,OPTIONAL,DIMENSION(:) :: field0 ,field1 ,field2 ,field3 ,field4 ,field5 ,field6 ,field7 ,field8 ,field9
+  TYPE(t_field),POINTER,OPTIONAL,DIMENSION(:) :: field10,field11,field12,field13,field14,field15,field16,field17,field18,field19
+
+  TYPE(t_field_array) :: field_array(20)
+  INTEGER             :: nfield
+  INTEGER             :: fieldId(20)
+   
+  TYPE(t_domain),POINTER :: d
+  TYPE(t_field),POINTER :: field_glo(:)
+  TYPE(t_field),POINTER :: field(:)
+  
+  CHARACTER(LEN=255) :: start_file_name
+  INTEGER,PARAMETER  :: nvert=6
+  INTEGER    ::  ncid, cellId, levId, edgeId,  vertid, lonId, latId, bounds_lonId, bounds_latId
+  INTEGER    :: ind,ind_glo,i,j,k,nf
+  INTEGER    :: status
+  REAL(rstd),ALLOCATABLE :: lon(:),lat(:),bounds_lon(:,:),bounds_lat(:,:)
+   
+    start_file_name="start"
+    CALL getin("start_file_name",start_file_name)
+
+!$OMP BARRIER
+!$OMP MASTER
+
+    nfield=0
+    IF (PRESENT(field0))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field0  ; ENDIF
+    IF (PRESENT(field1))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field1  ; ENDIF
+    IF (PRESENT(field2))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field2  ; ENDIF
+    IF (PRESENT(field3))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field3  ; ENDIF
+    IF (PRESENT(field4))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field4  ; ENDIF
+    IF (PRESENT(field5))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field5  ; ENDIF
+    IF (PRESENT(field6))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field6  ; ENDIF
+    IF (PRESENT(field7))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field7  ; ENDIF
+    IF (PRESENT(field8))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field8  ; ENDIF
+    IF (PRESENT(field9))  THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field9  ; ENDIF
+    IF (PRESENT(field10)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field10 ; ENDIF
+    IF (PRESENT(field11)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field11 ; ENDIF
+    IF (PRESENT(field12)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field12 ; ENDIF
+    IF (PRESENT(field13)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field13 ; ENDIF
+    IF (PRESENT(field14)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field14 ; ENDIF
+    IF (PRESENT(field15)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field15 ; ENDIF
+    IF (PRESENT(field16)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field16 ; ENDIF
+    IF (PRESENT(field17)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field17 ; ENDIF
+    IF (PRESENT(field18)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field18 ; ENDIF
+    IF (PRESENT(field19)) THEN ; nfield=nfield+1 ; field_array(nfield)%field=>field19 ; ENDIF
+    
+      
+
+    IF (is_mpi_root) THEN
+      status = NF90_OPEN(TRIM(ADJUSTL(start_file_name))//'.nc', NF90_NOWRITE, ncid)
+      status = nf90_inq_varid(ncid, "iteration",itid)
+      IF (status==NF90_NOERR) THEN 
+        status = nf90_get_var(ncid, itid, it)
+      ELSE
+        status = nf90_get_att(ncid, NF90_GLOBAL, "iteration", it)
+      ENDIF
+    ENDIF
+    
+    DO nf=1,nfield
+      field=>field_array(nf)%field
+       IF (is_mpi_root) status = nf90_inq_varid(ncid, TRIM(ADJUSTL(field(1)%name)), fieldId(nf))
+      CALL read_start_field(field,fieldId(nf),ncid)
+    ENDDO
+
+
+    IF (is_mpi_root) THEN
+      status = NF90_CLOSE(ncid)      
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+  
+  END SUBROUTINE read_start
+
+
+  SUBROUTINE read_start_field(field,fieldId,ncid)
+  USE prec
+  USE metric
+  USE field_mod
+  USE domain_mod
+  USE netcdf_mod
+  USE mpipara
+  USE getin_mod
+  USE spherical_geom_mod
+  USE transfert_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    INTEGER,INTENT(IN)     :: fieldId
+    INTEGER,INTENT(IN)     :: ncid
+
+    TYPE(t_domain),POINTER :: d
+    TYPE(t_field),POINTER :: field_glo(:)
+    REAL(rstd),ALLOCATABLE :: global_field2d(:)
+    REAL(rstd),ALLOCATABLE :: global_field3d(:)
+    REAL(rstd),ALLOCATABLE :: global_field4d(:)
+    INTEGER :: i,j,l,q,ij,k,e,ind,ind_glo
+    INTEGER :: ndim, field_type
+    INTEGER :: status
+    
+      ndim=field(1)%ndim
+      field_Type= field(1)%field_type
+      
+      IF (is_mpi_root) THEN
+ 
+        IF (ndim==2) THEN
+          CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,name=field(1)%name)
+        ELSE IF (ndim==3) THEN
+          CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,field(1)%dim3,name=field(1)%name)
+        ELSE IF (ndim==4) THEN
+          CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,field(1)%dim3,field(1)%dim4,name=field(1)%name)
+        ENDIF
+      ENDIF
+      
+      IF (is_mpi_root) THEN
+
+        IF (field_type==field_T) THEN
+          IF (ndim==2) THEN
+            ALLOCATE(global_field2d(ncell_glo))
+            status=NF90_GET_VAR(ncid,fieldid, global_field2d, start=(/ 1 /), count=(/ ncell_glo /))
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                    ij=(j-1)*d%iim+i
+                    ind_glo=d%assign_cell_glo(i,j)
+                    field_glo(ind)%rval2d(ij)=global_field2d(ind_glo)
+                ENDDO
+              ENDDO
+            ENDDO
+          
+          ELSE IF (ndim==3) THEN
+
+            ALLOCATE(global_field3d(ncell_glo))
+       
+            DO l=1,llm
+              status=NF90_GET_VAR(ncid,fieldid,global_field3d,start=(/ 1,l /),count=(/ ncell_glo,1 /))
+              DO ind=1,ndomain_glo
+                d=>domain_glo(ind)
+                DO j=d%jj_begin,d%jj_end
+                 DO i=d%ii_begin,d%ii_end
+                    ij=(j-1)*d%iim+i
+                    ind_glo=d%assign_cell_glo(i,j)
+                    field_glo(ind)%rval3d(ij,l) = global_field3d(ind_glo)
+                  ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+          ELSE IF (ndim==4) THEN
+            ALLOCATE(global_field4d(ncell_glo))
+            
+            DO q=1,nqtot
+              DO l=1,llm         
+                status=NF90_GET_VAR(ncid,fieldid,global_field4d,start=(/ 1,l,q /),count=(/ ncell_glo,1,1 /))
+                  DO ind=1,ndomain_glo
+                    d=>domain_glo(ind)
+                    DO j=d%jj_begin,d%jj_end
+                      DO i=d%ii_begin,d%ii_end
+                        ij=(j-1)*d%iim+i
+                        ind_glo=d%assign_cell_glo(i,j)
+                        field_glo(ind)%rval4d(ij,l,q) = global_field4d(ind_glo)
+                      ENDDO
+                    ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+          ENDIF
+        
+        ELSE IF (field_type==field_U) THEN
+        
+          IF (ndim==2) THEN
+            ALLOCATE(global_field2d(3*ncell_glo))
+            status=NF90_GET_VAR(ncid,fieldid,global_field2d,start=(/ 1 /),count=(/ 3*ncell_glo /))
+
+            DO ind=1,ndomain_glo
+              d=>domain_glo(ind)
+              DO j=d%jj_begin,d%jj_end
+                DO i=d%ii_begin,d%ii_end
+                  DO k=0,5
+                    ij=(j-1)*d%iim+i
+                    ind_glo=d%assign_cell_glo(i,j)
+                    e=cell_glo(ind_glo)%edge(MOD(k+d%delta(i,j)+6,6))  
+                    field_glo(ind)%rval2d(ij+d%u_pos(k))= global_field2d(ind_glo)*d%edge_assign_sign(k,i,j)
+                  ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+          ELSE IF (ndim==3) THEN
+          
+            ALLOCATE(global_field3d(3*ncell_glo))
+            DO l=1,llm
+              status=NF90_GET_VAR(ncid,fieldid,global_field3d,start=(/ 1,l /),count=(/ 3*ncell_glo,1 /))
+              DO ind=1,ndomain_glo
+                d=>domain_glo(ind)
+                DO j=d%jj_begin,d%jj_end
+                  DO i=d%ii_begin,d%ii_end
+                    DO k=0,5
+                      ij=(j-1)*d%iim+i
+                      ind_glo=d%assign_cell_glo(i,j)
+                      e=cell_glo(ind_glo)%edge(MOD(k+d%delta(i,j)+6,6))  
+                      field_glo(ind)%rval3d(ij+d%u_pos(k+1),l)=global_field3d(e)*d%edge_assign_sign(k,i,j)
+                    ENDDO
+                  ENDDO
+                ENDDO
+              ENDDO
+            ENDDO
+          ELSE IF (ndim==4) THEN
+
+            ALLOCATE(global_field4d(3*ncell_glo))
+            DO q=1,nqtot
+              DO l=1,llm
+               status=NF90_GET_VAR(ncid,fieldid,global_field4d,start=(/ 1,l,q /),count=(/ 3*ncell_glo,1,1 /))
+               DO ind=1,ndomain_glo
+                 d=>domain_glo(ind)
+                 DO j=d%jj_begin,d%jj_end
+                   DO i=d%ii_begin,d%ii_end
+                     DO k=0,5
+                       ij=(j-1)*d%iim+i
+                       ind_glo=d%assign_cell_glo(i,j)
+                       e=cell_glo(ind_glo)%edge(MOD(k+d%delta(i,j)+6,6))  
+                       field_glo(ind)%rval4d(ij+d%u_pos(k+1),l,q)=global_field4d(e)*d%edge_assign_sign(k,i,j)
+                     ENDDO
+                   ENDDO
+                 ENDDO
+               ENDDO
+              ENDDO
+            ENDDO
+          ENDIF
+
+        ENDIF
+      ENDIF
+      
+      CALL scatter_field(field_glo,field)
+        
+      IF (is_mpi_root) THEN
+        CALL deallocate_field_glo(field_glo)
+      ENDIF
+      
+      
+  END SUBROUTINE read_start_field      
+    
+END MODULE restart_mod
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/spherical_geom.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/spherical_geom.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/spherical_geom.f90	(revision 329)
@@ -0,0 +1,249 @@
+MODULE spherical_geom_mod
+USE genmod
+
+
+
+CONTAINS
+
+
+
+
+SUBROUTINE lonlat2xyz(lon,lat,xyz)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN) :: lon
+  REAL(rstd),INTENT(IN) :: lat
+  REAL(rstd),INTENT(OUT) :: xyz(3)
+  
+  xyz(1)=cos(lon)*cos(lat)
+  xyz(2)=sin(lon)*cos(lat)
+  xyz(3)=sin(lat)
+
+END SUBROUTINE lonlat2xyz
+
+
+SUBROUTINE xyz2lonlat(xyz,lon,lat)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN) :: xyz(3)
+  REAL(rstd),INTENT(OUT) :: lon
+  REAL(rstd),INTENT(OUT) :: lat
+  
+  REAL(rstd) :: coslat
+  REAL(rstd) :: xyzn(3)
+  
+  xyzn(:)=xyz(:)/sqrt(sum(xyz(:)**2))
+  
+  lat=asin(xyzn(3))
+  lon=atan2(xyzn(2),xyzn(1))
+END SUBROUTINE xyz2lonlat
+
+! lat/lon with respect to a displaced pole (rotated basis) :
+!  ( cos(lon0)*sin(lat0), sin(lon0)*sin(lat0), -cos(lat0)) 
+!  (-sin(lon0),           cos(lon0),           0)
+!  ( cos(lon0)*cos(lat0), sin(lon0)*cos(lat0), sin(lat0))
+
+SUBROUTINE lonlat2xyz_relative(lon,lat,lon0,lat0, xyz)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN) :: lon0, lat0, lon,lat
+  REAL(rstd),INTENT(OUT) :: xyz(3)
+  REAL(rstd) :: xx,yy,zz
+  xx = cos(lon)*cos(lat)
+  yy = sin(lon)*cos(lat)
+  zz = sin(lat)
+  xyz(1) = cos(lon0)*(sin(lat0)*xx+cos(lat0)*zz)-sin(lon0)*yy
+  xyz(2) = sin(lon0)*(sin(lat0)*yy+cos(lat0)*zz)+cos(lon0)*yy
+  xyz(3) = sin(lat0)*zz-cos(lat0)*xx
+END SUBROUTINE lonlat2xyz_relative
+
+SUBROUTINE xyz2lonlat_relative(xyz,lon0,lat0, lon,lat)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN) :: xyz(3), lon0, lat0
+  REAL(rstd),INTENT(OUT) :: lon,lat
+  REAL(rstd) :: xx,yy,zz
+  xx = sin(lat0)*(xyz(1)*cos(lon0)+xyz(2)*sin(lon0))-cos(lat0)*xyz(3)
+  yy = xyz(2)*cos(lon0)-xyz(1)*sin(lon0)
+  zz = cos(lat0)*(xyz(1)*cos(lon0)+xyz(2)*sin(lon0))+sin(lat0)*xyz(3)
+  lon = atan2(yy,xx)
+  lat = asin(zz)
+END SUBROUTINE xyz2lonlat_relative
+
+SUBROUTINE schmidt_transform(xyz,cc, lon0, lat0)
+  ! Based on formula (12) from Guo & Drake, JCP 2005
+  IMPLICIT NONE
+  REAL(rstd),INTENT(INOUT) :: xyz(3)
+  REAL(rstd), INTENT(IN) :: cc, lon0, lat0  ! stretching factor>0, lon/lat of zoomed area
+  REAL(rstd) :: lat,lon,mu
+  CALL xyz2lonlat_relative(xyz,lon0,lat0, lon,lat)
+  mu = sin(lat)
+  mu = ((cc-1)+mu*(cc+1)) / ((cc+1)+mu*(cc-1))
+  lat = asin(mu)
+  CALL lonlat2xyz_relative(lon,lat, lon0,lat0, xyz)
+END SUBROUTINE schmidt_transform
+
+SUBROUTINE dist_cart(A,B,d)
+USE vector
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN)  :: A(3)
+  REAL(rstd),INTENT(IN)  :: B(3)
+  REAL(rstd),INTENT(OUT) :: d
+  
+   REAL(rstd)  :: n(3)
+   CALL cross_product2(A,B,n)
+   d=asin(sqrt(sum(n**2)))
+
+END SUBROUTINE dist_cart
+
+
+SUBROUTINE dist_lonlat(lonA,latA,lonB,latB,d)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN)  :: lonA
+  REAL(rstd),INTENT(IN)  :: latA
+  REAL(rstd),INTENT(IN)  :: lonB
+  REAL(rstd),INTENT(IN)  :: latB
+  REAL(rstd),INTENT(OUT) :: d
+  
+  d=acos(MAX(MIN(sin(latA)*sin(latB)+cos(latA)*cos(latB)*cos(lonA-lonB),1.),-1.))
+ 
+END SUBROUTINE dist_lonlat
+
+SUBROUTINE surf_triangle(A,B,C,surf)
+  REAL(rstd),INTENT(IN)  :: A(3)
+  REAL(rstd),INTENT(IN)  :: B(3)
+  REAL(rstd),INTENT(IN)  :: C(3)
+  REAL(rstd),INTENT(OUT) :: Surf
+
+  REAL(rstd)  :: AB,AC,BC
+  REAL(rstd)  :: s,x
+  
+  CALL dist_cart(A,B,AB)
+  CALL dist_cart(A,C,AC)
+  CALL dist_cart(B,C,BC)
+  
+  s=(AB+AC+BC)/2
+  x=tan(s/2) * tan((s-AB)/2)  * tan((s-AC)/2) * tan((s-BC)/2)
+  IF (x<0) x=0.
+  surf=4*atan(sqrt( x))
+  
+END SUBROUTINE surf_triangle 
+
+
+SUBROUTINE div_arc(A,B,frac,C)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN)  :: A(3)
+  REAL(rstd),INTENT(IN)  :: B(3)
+  REAL(rstd),INTENT(IN)  :: frac
+  REAL(rstd),INTENT(OUT)  :: C(3)
+  
+  REAL(rstd) :: d
+  REAL(rstd) :: M(3,3)
+  REAL(rstd) :: alpha(3,3)
+  INTEGER    :: IPIV(3)
+  INTEGER    :: info
+  REAL(rstd) :: xa,xb,xc
+  REAL(rstd) :: ya,yb,yc
+  REAL(rstd) :: za,zb,zc
+  REAL(rstd) :: alpha_A,alpha_B,alpha_C
+  REAL(rstd) :: x,y,z
+  REAL(rstd) :: a1,a2,a3
+  REAL(rstd) :: b1,b2,b3
+  
+  
+  xa=A(1) ; ya=A(2) ; za=A(3)
+  xb=B(1) ; yb=B(2) ; zb=B(3)
+
+  CALL dist_cart(A,B,d)
+
+  C(1)=cos(frac*d) 
+  C(2)=cos((1-frac)*d)
+  C(3)=0.
+
+  xc=ya*zb-yb*za ; yc=-(xa*zb-xb*za) ; zc=xa*yb-xb*ya
+  
+  M(1,1)=xa ; M(1,2)=ya ; M(1,3)=za
+  M(2,1)=xb ; M(2,2)=yb ; M(2,3)=zb
+  M(3,1)=xc ; M(3,2)=yc ; M(3,3)=zc
+  stop 'STOP'
+!  CALL DGESV(3,1,M,3,IPIV,C,3,info)
+  
+END SUBROUTINE div_arc
+
+SUBROUTINE div_arc_bis(A,B,frac,C)
+IMPLICIT NONE
+  REAL(rstd),INTENT(IN)  :: A(3)
+  REAL(rstd),INTENT(IN)  :: B(3)
+  REAL(rstd),INTENT(IN)  :: frac
+  REAL(rstd),INTENT(OUT)  :: C(3)
+  
+   C=A*(1-frac)+B*frac  
+   C=C/sqrt(sum(C**2))
+END SUBROUTINE div_arc_bis
+
+
+  SUBROUTINE circumcenter(A0,B0,C0,center)
+  USE vector
+  IMPLICIT NONE
+    REAL(rstd), INTENT(IN)  :: A0(3),B0(3),C0(3)
+    REAL(rstd), INTENT(OUT) :: Center(3)
+    
+    REAL(rstd)  :: a(3),b(3),c(3), ac(3), ab(3), p1(3), q(3), p2(3)
+    
+    a=A0/sqrt(sum(A0**2))
+    b=B0/sqrt(sum(B0**2))
+    c=C0/sqrt(sum(C0**2))
+    
+    ab=b-a
+    ac=c-a
+    CALL Cross_product2(ab,ac,p1)
+    IF(.FALSE.) THEN ! Direct solution, round-off error
+       center=p1/norm(p1)
+    ELSE ! Two-step solution, stable
+       q = SUM(ac**2)*ab-SUM(ab**2)*ac
+       CALL Cross_product2(p1,q,p2)
+       p2 = a + p2/(2.*SUM(p1**2))
+       center = p2/norm(p2)
+    END IF
+  END SUBROUTINE circumcenter
+    
+
+  SUBROUTINE compute_centroid(points,n,centr)
+  USE vector
+  IMPLICIT NONE
+    INTEGER :: n
+    REAL(rstd), INTENT(IN)  :: points(3,n)
+    REAL(rstd), INTENT(OUT) :: Centr(3)
+    
+    REAL(rstd) :: p1(3),p2(3),cross(3), cc(3)
+    REAL(rstd) :: norm_cross, area
+    INTEGER :: i,j
+
+    centr(:)=0
+    IF(.FALSE.) THEN 
+       ! Gauss formula (subject to round-off error)
+       DO i=1,n
+          j=MOD(i,n)+1
+          p1=points(:,i)/norm(points(:,i))
+          p2=points(:,j)/norm(points(:,j))
+          CALL cross_product2(p1,p2,cross)
+          norm_cross=norm(cross)
+          if (norm_cross<1e-10) CYCLE 
+          centr(:)=centr(:)+asin(norm_cross)*cross(:)/norm_cross
+       ENDDO       
+    ELSE
+       ! Simple area-weighted average (second-order accurate, stable)
+       cc=SUM(points,2) ! arithmetic average used as center
+       cc=cc/norm(cc)
+       DO i=1,n
+          j=MOD(i,n)+1
+          p1=points(:,i)/norm(points(:,i))
+          p2=points(:,j)/norm(points(:,j))
+          CALL surf_triangle(cc,p1,p2,area)
+          centr(:)=centr(:)+area*(p1+p2+cc)
+       ENDDO
+    END IF
+    
+    centr(:)=centr(:)/norm(centr(:))
+
+  END SUBROUTINE compute_centroid
+
+END MODULE spherical_geom_mod
+
+
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/sponge.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/sponge.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/sponge.f90	(revision 329)
@@ -0,0 +1,156 @@
+MODULE sponge_mod
+  USE icosa
+
+  PRIVATE
+  
+  REAL,SAVE :: tau_sponge !inverse of charactericstic relaxation time scale at the topmost layer (Hz)
+  INTEGER,SAVE :: iflag_sponge !0 --> for no sponge
+			       !1 --> for sponge over 4 topmost layers
+			       !2 --> for sponge from top to ~1% of top layer pressure
+                               !3 --> for sponge over topmost nb_sponge_layers
+  INTEGER,SAVE :: mode_sponge !1 --> u and v relax towards 0
+                              !2 --> u and v relax towards their zonal mean
+                              !3 --> u,v and pot. temp. relax towards their zonal mean
+  INTEGER,SAVE :: nb_sponge_layers ! number of layers over which the sponge extends
+!$OMP THREADPRIVATE(tau_sponge,iflag_sponge,mode_sponge,nb_sponge_layers)
+  REAL,ALLOCATABLE,SAVE :: rdamp(:) ! quenching coefficient
+  REAL,ALLOCATABLE,SAVE:: lambda(:) ! inverse or quenching time scale (Hz)
+
+  PUBLIC sponge, init_sponge, iflag_sponge
+
+CONTAINS
+
+  SUBROUTINE init_sponge
+  USE icosa
+  USE disvert_mod
+  USE omp_para
+  USE mpipara, ONLY: is_mpi_master
+  IMPLICIT NONE
+    INTEGER :: l
+
+    tau_sponge = 1.e-4
+    CALL getin("tau_sponge",tau_sponge)
+    PRINT*,'tau_sponge = ',tau_sponge
+
+    iflag_sponge = 0
+    CALL getin("iflag_sponge",iflag_sponge)
+    PRINT*,'iflag_sponge = ',iflag_sponge
+    
+    mode_sponge = 1
+    CALL getin("mode_sponge",mode_sponge)
+    PRINT*,'mode_sponge = ',mode_sponge
+
+    IF (iflag_sponge==3) THEN
+      nb_sponge_layers=1
+      call getin("nb_sponge_layers",nb_sponge_layers)
+    ENDIF
+
+    IF (iflag_sponge == 0) THEN
+      PRINT*,'init_sponge: no sponge'
+      RETURN
+    ENDIF
+
+!$OMP MASTER
+    ALLOCATE(rdamp(llm))
+    ALLOCATE(lambda(llm))
+
+    IF (iflag_sponge == 1) THEN
+! sponge quenching over the topmost 4 atmospheric layers
+        lambda(:)=0.
+        lambda(llm)=tau_sponge
+        lambda(llm-1)=tau_sponge/2.
+        lambda(llm-2)=tau_sponge/4.
+        lambda(llm-3)=tau_sponge/8.
+    ELSE IF (iflag_sponge == 2) THEN
+! sponge quenching over topmost layers down to pressures which are
+! higher than 100 times the topmost layer pressure
+        lambda(:)=tau_sponge*max(presnivs(llm)/presnivs(:)-0.01,0.)
+    ELSE IF (iflag_sponge == 3) THEN
+        lambda(:)=0.
+        DO l = llm,llm-nb_sponge_layers+1,-1
+          lambda(l)=tau_sponge/(2.**(llm-l))
+        ENDDO
+    ELSE
+      PRINT*,'Bad selector for variable iflag_sponge : <',iflag_sponge,             &
+            '> options are 0,1,2,3'
+      STOP
+    ENDIF
+
+! quenching coefficient rdamp(:)
+!         rdamp(:)=dt*lambda(:) ! Explicit Euler approx.
+!      rdamp(:)=1.-exp(-lambda(:)*dt)
+    rdamp(:)=itau_dissip*lambda(:)
+
+
+    IF (is_mpi_master) THEN
+      PRINT*,'init_sponge: l, lambda(l), rdamp(l):'
+      DO l=ll_begin,ll_end
+        PRINT*,l,lambda(l),rdamp(l)
+      ENDDO
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+
+  END SUBROUTINE init_sponge
+
+  SUBROUTINE sponge(f_ue,f_due,f_theta_rhodz,f_dtheta_rhodz)
+  USE icosa
+  USE theta2theta_rhodz_mod
+  USE pression_mod
+  USE exner_mod
+  USE geopotential_mod
+  USE trace
+  USE time_mod
+  USE omp_para
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ue(:)
+    TYPE(t_field),POINTER :: f_due(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_dtheta_rhodz(:)
+
+    REAL(rstd),POINTER         :: due(:,:)!,due_sponge(:,:)
+    REAL(rstd),POINTER         :: ue(:,:)
+    REAL(rstd),POINTER         :: theta_rhodz(:,:)
+    REAL(rstd),POINTER         :: dtheta_rhodz(:,:)!,dtheta_sponge(:,:)
+
+    INTEGER :: ind
+    INTEGER :: l,ij
+
+!$OMP BARRIER
+    
+    CALL trace_start("sponge")
+
+    IF (mode_sponge == 1) THEN
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+        ue=f_ue(ind) 
+        due=f_due(ind) 
+        theta_rhodz=f_theta_rhodz(ind)
+        dtheta_rhodz=f_dtheta_rhodz(ind)
+
+        DO l=ll_begin,ll_end
+!$SIMD
+          DO ij=ij_begin,ij_end
+
+            due(ij+u_right,l) = -rdamp(l)*ue(ij+u_right,l)
+            due(ij+u_lup,l)   = -rdamp(l)*ue(ij+u_lup,l)
+            due(ij+u_ldown,l) = -rdamp(l)*ue(ij+u_ldown,l)
+
+            dtheta_rhodz(ij,l) = 0.0
+          ENDDO
+        ENDDO
+      END DO
+    ELSE
+      PRINT*,'Bad selector for variable mode_sponge : <',mode_sponge,             &
+            '> options 2 and 3 not available for the moment!'
+      STOP
+    ENDIF
+
+   CALL trace_end("sponge")
+
+!$OMP BARRIER
+  END SUBROUTINE sponge
+
+END MODULE sponge_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/theta_rhodz.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/theta_rhodz.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/theta_rhodz.f90	(revision 329)
@@ -0,0 +1,190 @@
+MODULE theta2theta_rhodz_mod
+
+CONTAINS
+  
+  SUBROUTINE theta_rhodz2theta(f_ps,f_theta_rhodz,f_theta)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ps(:)
+    TYPE(t_field), POINTER :: f_theta_rhodz(:)
+    TYPE(t_field), POINTER :: f_theta(:)
+  
+    REAL(rstd), POINTER :: ps(:)
+    REAL(rstd), POINTER :: theta_rhodz(:,:)
+    REAL(rstd), POINTER :: theta(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      theta=f_theta(ind)
+      CALL compute_theta_rhodz2theta(ps, theta_rhodz,theta,0)
+    ENDDO
+  
+  END SUBROUTINE theta_rhodz2theta
+
+  SUBROUTINE theta_rhodz2temperature(f_ps,f_theta_rhodz,f_temp)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ps(:)
+    TYPE(t_field), POINTER :: f_theta_rhodz(:)
+    TYPE(t_field), POINTER :: f_temp(:)
+  
+    REAL(rstd), POINTER :: ps(:)
+    REAL(rstd), POINTER :: theta_rhodz(:,:)
+    REAL(rstd), POINTER :: temp(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      temp=f_temp(ind)
+      CALL compute_theta_rhodz2temperature(ps, theta_rhodz,temp,0)
+    ENDDO
+  
+  END SUBROUTINE theta_rhodz2temperature
+    
+  SUBROUTINE theta2theta_rhodz(f_ps,f_theta,f_theta_rhodz)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ps(:)
+    TYPE(t_field), POINTER :: f_theta(:)
+    TYPE(t_field), POINTER :: f_theta_rhodz(:)
+  
+    REAL(rstd), POINTER :: ps(:)
+    REAL(rstd), POINTER :: theta(:,:)
+    REAL(rstd), POINTER :: theta_rhodz(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ps=f_ps(ind)
+      theta=f_theta(ind)
+      theta_rhodz=f_theta_rhodz(ind)
+      CALL compute_theta2theta_rhodz(ps, theta, theta_rhodz,0)
+    ENDDO
+  
+  END SUBROUTINE theta2theta_rhodz
+  
+  SUBROUTINE compute_theta2theta_rhodz(ps,theta, theta_rhodz,offset)
+  USE icosa
+  USE pression_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd),INTENT(IN) :: theta(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+    REAL(rstd),ALLOCATABLE,SAVE :: p(:,:)
+!$OMP THREADPRIVATE(p)
+
+    ALLOCATE( p(iim*jjm,llm+1))
+    CALL compute_pression(ps,p,offset)
+    
+    DO    l    = 1, llm
+      DO j=jj_begin-offset,jj_end+offset
+        DO i=ii_begin-offset,ii_end+offset
+          ij=(j-1)*iim+i
+          theta_rhodz(ij,l) = theta(ij,l) * (p(ij,l)-p(ij,l+1))/g
+        ENDDO
+      ENDDO
+    ENDDO
+
+    DEALLOCATE( p)
+
+  END SUBROUTINE compute_theta2theta_rhodz
+
+  SUBROUTINE compute_theta_rhodz2theta(ps,theta_rhodz,theta,offset)
+  USE icosa
+  USE pression_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd),INTENT(IN) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: theta(iim*jjm,llm)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+    REAL(rstd),SAVE,ALLOCATABLE :: p(:,:)
+!$OMP THREADPRIVATE(p)
+
+    ALLOCATE( p(iim*jjm,llm+1))
+
+    CALL compute_pression(ps,p,offset)
+    
+    DO    l    = 1, llm
+      DO j=jj_begin-offset,jj_end+offset
+        DO i=ii_begin-offset,ii_end+offset
+          ij=(j-1)*iim+i
+          theta(ij,l) = theta_rhodz(ij,l) / ((p(ij,l)-p(ij,l+1))/g)
+        ENDDO
+      ENDDO
+    ENDDO
+
+    DEALLOCATE( p)
+    
+  END SUBROUTINE compute_theta_rhodz2theta
+
+  SUBROUTINE compute_theta_rhodz2temperature(ps,theta_rhodz,temp,offset)
+  USE icosa
+  USE pression_mod
+  USE exner_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd),INTENT(IN) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: temp(iim*jjm,llm)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: p(iim*jjm,llm+1)
+    REAL(rstd) :: pk(iim*jjm,llm)
+    REAL(rstd) :: pks(iim*jjm)
+
+    CALL compute_pression(ps,p,offset)
+    CALL compute_exner(ps,p,pks,pk,offset)
+        
+    DO    l    = 1, llm
+      DO j=jj_begin-offset,jj_end+offset
+        DO i=ii_begin-offset,ii_end+offset
+          ij=(j-1)*iim+i
+          temp(ij,l) = ( theta_rhodz(ij,l) / ((p(ij,l)-p(ij,l+1))/g) ) * pk(ij,l) / cpp
+        ENDDO
+      ENDDO
+    ENDDO
+    
+  END SUBROUTINE compute_theta_rhodz2temperature
+
+  SUBROUTINE compute_temperature2theta_rhodz(ps,temp,theta_rhodz,offset)
+  USE icosa
+  USE pression_mod
+  USE exner_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: ps(iim*jjm)
+    REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
+    REAL(rstd),INTENT(IN) :: temp(iim*jjm,llm)
+    INTEGER,INTENT(IN) :: offset
+    INTEGER :: i,j,ij,l
+    REAL(rstd) :: p(iim*jjm,llm+1)
+    REAL(rstd) :: pk(iim*jjm,llm)
+    REAL(rstd) :: pks(iim*jjm)
+
+    CALL compute_pression(ps,p,offset)
+    CALL compute_exner(ps,p,pks,pk,offset)
+        
+    DO    l    = 1, llm
+      DO j=jj_begin-offset,jj_end+offset
+        DO i=ii_begin-offset,ii_end+offset
+          ij=(j-1)*iim+i
+          theta_rhodz(ij,l) = temp(ij,l) * ((p(ij,l)-p(ij,l+1))/g) / (pk(ij,l) / cpp )
+        ENDDO
+      ENDDO
+    ENDDO
+    
+  END SUBROUTINE compute_temperature2theta_rhodz
+   
+END MODULE theta2theta_rhodz_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/time.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/time.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/time.f90	(revision 329)
@@ -0,0 +1,177 @@
+MODULE time_mod
+  use prec
+  PRIVATE
+
+  INTEGER,SAVE :: ncid
+!$OMP THREADPRIVATE(ncid)  
+  INTEGER,SAVE :: time_counter_id
+!$OMP THREADPRIVATE(time_counter_id)  
+  INTEGER,SAVE :: it
+!$OMP THREADPRIVATE(it)  
+
+  INTEGER,SAVE :: itau0=0
+!$OMP THREADPRIVATE(itau0)  
+
+  REAL(rstd),SAVE :: dt
+!$OMP THREADPRIVATE(dt)  
+  REAL(rstd),SAVE :: write_period
+!$OMP THREADPRIVATE(write_period)  
+  INTEGER,SAVE    :: itau_out, itau_adv, itau_dissip, itau_physics, itaumax, itau_write_etat0
+!$OMP THREADPRIVATE(itau_out, itau_adv, itau_dissip, itau_physics, itaumax, itau_write_etat0)  
+  
+  INTEGER,SAVE :: day_step,ndays
+!$OMP THREADPRIVATE(day_step,ndays)  
+  REAL(rstd),SAVE :: jD_ref,jH_ref
+!$OMP THREADPRIVATE(jD_ref,jH_ref)  
+  INTEGER,SAVE :: day_ini,day_end,annee_ref,day_ref
+!$OMP THREADPRIVATE(day_ini,day_end,annee_ref,day_ref)  
+  REAL(rstd),SAVE::start_time
+!$OMP THREADPRIVATE(start_time)  
+  CHARACTER(LEN=255) :: time_style
+!$OMP THREADPRIVATE(time_style)  
+  INTEGER,SAVE:: an, mois, jour
+!$OMP THREADPRIVATE(an, mois, jour)  
+  REAL(rstd),SAVE:: heure
+!$OMP THREADPRIVATE(heure)  
+  CHARACTER (LEN=10):: calend
+!$OMP THREADPRIVATE(calend)  
+
+  PUBLIC create_time_counter_header, update_time_counter, close_time_counter, init_time,  &
+         dt, write_period, itau_out, itau_adv, itau_dissip, itau_physics,itau_write_etat0, itaumax, & 
+day_step,ndays,jD_ref,jH_ref,day_ini,day_end,annee_ref,day_ref,an, mois, jour,heure, &
+            calend,time_style,itau0
+
+
+
+
+CONTAINS
+  
+  SUBROUTINE init_time
+  USE earth_const
+  USE getin_mod
+  USE mpipara
+  USE omp_para, ONLY: omp_master
+  IMPLICIT NONE
+  REAL(rstd) :: run_length
+
+
+   time_style='dcmip'
+   CALL getin('time_style',time_style)
+
+   IF (TRIM(time_style)=='dcmip')  Then
+    dt=90.
+    CALL getin('dt',dt)
+
+    itaumax=100
+    CALL getin('itaumax',itaumax)
+
+    run_length=dt*itaumax
+    CALL getin('run_length',run_length)
+    itaumax=run_length/dt
+    dt=dt/scale_factor
+
+    write_period=0
+    CALL getin('write_period',write_period)
+    write_period=write_period/scale_factor
+    itau_out=FLOOR(.5+write_period/dt)
+    IF (is_mpi_root .AND. omp_master) PRINT *, 'Output frequency (scaled) set to ',write_period, ' : itau_out = ',itau_out
+    ENDIF 
+
+    itau_adv=1
+    CALL getin('itau_adv',itau_adv)
+
+    itau_dissip=1
+    CALL getin('itau_dissip',itau_dissip)
+
+    itau_physics=1
+    CALL getin('itau_physics',itau_physics)
+
+    itau_write_etat0=HUGE(itau_write_etat0)
+    CALL getin('itau_write_etat0',itau_write_etat0)
+    itau_write_etat0=itau_write_etat0/dt
+
+    IF (is_mpi_root .AND. omp_master)  THEN
+       PRINT *, 'itaumax=',itaumax
+       PRINT *, 'itau_adv=',itau_adv, 'itau_dissip=',itau_dissip, 'itau_physics=',itau_physics
+    END IF
+    
+    CALL create_time_counter_header
+    
+  END SUBROUTINE init_time
+
+  SUBROUTINE create_time_counter_header
+  USE netcdf_mod
+  USE prec
+  USE getin_mod
+  USE mpipara
+  IMPLICIT NONE
+  INTEGER :: status
+  INTEGER :: timeid, dtid
+  REAL(rstd) :: dt
+  CHARACTER(LEN=255) :: time_frequency
+
+  CALL getin("dt",dt)
+
+!$OMP BARRIER
+!$OMP MASTER  
+    IF (is_mpi_root) THEN 
+      status = NF90_CREATE('time_counter.nc', NF90_CLOBBER, ncid)
+      status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeid)
+      status = NF90_DEF_VAR(ncid,'time_counter',NF90_DOUBLE,(/ timeid /),time_counter_id)
+      status = NF90_PUT_ATT(ncid,time_counter_id,"long_name","time")
+      status = NF90_PUT_ATT(ncid,time_counter_id,"units","seconds since 2000-01-01 00:00:00")
+      status = NF90_PUT_ATT(ncid,time_counter_id,"calendar","noleap")
+      status = NF90_DEF_VAR(ncid,'mdt',NF90_DOUBLE,varid=dtid)
+
+      WRITE(time_frequency,*) write_period
+      PRINT*,TRIM(time_frequency)
+      status = NF90_PUT_ATT(ncid,NF90_GLOBAL,"time_frequency",TRIM(time_frequency)//"s")
+
+      status = NF90_ENDDEF(ncid) 
+
+      status=NF90_PUT_VAR(ncid,dtid, dt)
+    ENDIF
+    it=0
+!$OMP END MASTER
+!$OMP BARRIER
+
+  END SUBROUTINE create_time_counter_header
+  
+  SUBROUTINE update_time_counter(time)
+  USE netcdf_mod
+  USE mpipara
+  USE prec
+  IMPLICIT NONE
+  REAL(rstd),INTENT(IN) ::time
+  INTEGER :: status
+  REAL(rstd) ::time_array(1)
+
+!$OMP BARRIER
+!$OMP MASTER
+    time_array(1)=time
+  
+    it=it+1
+    IF (is_mpi_root) THEN 
+      status=NF90_PUT_VAR(ncid,time_counter_id,time_array,start=(/ it /),count=(/ 1 /))
+      status=NF90_SYNC(ncid)
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+
+  END SUBROUTINE update_time_counter    
+  
+  SUBROUTINE close_time_counter
+  USE netcdf_mod
+  USE mpipara
+  IMPLICIT NONE
+    INTEGER :: status
+    
+!$OMP BARRIER
+!$OMP MASTER
+     IF (is_mpi_root) status=NF90_CLOSE(ncid)
+!$OMP END MASTER
+!$OMP BARRIER
+    
+  END SUBROUTINE  close_time_counter 
+
+END MODULE time_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/timeloop_gcm.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/timeloop_gcm.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/timeloop_gcm.f90	(revision 329)
@@ -0,0 +1,632 @@
+MODULE timeloop_gcm_mod
+  USE transfert_mod
+  USE icosa
+  PRIVATE
+  
+  PUBLIC :: init_timeloop, timeloop
+
+  INTEGER, PARAMETER :: euler=1, rk4=2, mlf=3
+  INTEGER, PARAMETER :: itau_sync=10
+
+  TYPE(t_message),SAVE :: req_ps0, req_mass0, req_theta_rhodz0, req_u0, req_q0
+
+  TYPE(t_field),POINTER,SAVE :: f_q(:)
+  TYPE(t_field),POINTER,SAVE :: f_rhodz(:), f_mass(:), f_massm1(:), f_massm2(:), f_dmass(:)
+  TYPE(t_field),POINTER,SAVE :: f_phis(:), f_ps(:),f_psm1(:), f_psm2(:), f_dps(:)
+  TYPE(t_field),POINTER,SAVE :: f_u(:),f_um1(:),f_um2(:), f_du(:)
+  TYPE(t_field),POINTER,SAVE :: f_theta_rhodz(:),f_theta_rhodzm1(:),f_theta_rhodzm2(:), f_dtheta_rhodz(:)
+  TYPE(t_field),POINTER,SAVE :: f_hflux(:), f_wflux(:), f_hfluxt(:), f_wfluxt(:)  
+
+  INTEGER,SAVE :: nb_stage, matsuno_period, scheme    
+!$OMP THREADPRIVATE(nb_stage, matsuno_period, scheme)
+
+CONTAINS
+  
+  SUBROUTINE init_timeloop
+  USE icosa
+  USE dissip_gcm_mod
+  USE caldyn_mod
+  USE etat0_mod
+  USE disvert_mod
+  USE guided_mod
+  USE advect_tracer_mod
+  USE physics_mod
+  USE mpipara
+  USE omp_para
+  USE trace
+  USE transfert_mod
+  USE check_conserve_mod
+  USE output_field_mod
+  USE write_field
+  USE sponge_mod
+  IMPLICIT NONE
+
+    CHARACTER(len=255) :: def
+
+
+   IF (xios_output) itau_out=1
+   IF (.NOT. enable_io) itau_out=HUGE(itau_out)
+
+! Time-independant orography
+    CALL allocate_field(f_phis,field_t,type_real,name='phis')
+! Trends
+    CALL allocate_field(f_du,field_u,type_real,llm,name='du')
+    CALL allocate_field(f_dtheta_rhodz,field_t,type_real,llm,name='dtheta_rhodz')
+! Model state at current time step (RK/MLF/Euler)
+    CALL allocate_field(f_ps,field_t,type_real, name='ps')
+    CALL allocate_field(f_mass,field_t,type_real,llm,name='mass')
+    CALL allocate_field(f_u,field_u,type_real,llm,name='u')
+    CALL allocate_field(f_theta_rhodz,field_t,type_real,llm,name='theta_rhodz')
+! Model state at previous time step (RK/MLF)
+    CALL allocate_field(f_um1,field_u,type_real,llm,name='um1')
+    CALL allocate_field(f_theta_rhodzm1,field_t,type_real,llm,name='theta_rhodzm1')
+! Tracers
+    CALL allocate_field(f_q,field_t,type_real,llm,nqtot,'q')
+    CALL allocate_field(f_rhodz,field_t,type_real,llm,name='rhodz')
+! Mass fluxes
+    CALL allocate_field(f_hflux,field_u,type_real,llm)    ! instantaneous mass fluxes
+    CALL allocate_field(f_hfluxt,field_u,type_real,llm)   ! mass "fluxes" accumulated in time
+    CALL allocate_field(f_wflux,field_t,type_real,llm+1)  ! vertical mass fluxes
+    CALL allocate_field(f_dmass,field_t,type_real,llm, name='dmass')
+
+    IF(caldyn_eta == eta_mass) THEN ! eta = mass coordinate (default)
+       CALL allocate_field(f_dps,field_t,type_real,name='dps')
+       CALL allocate_field(f_psm1,field_t,type_real,name='psm1')
+       CALL allocate_field(f_wfluxt,field_t,type_real,llm+1,name='wfluxt')
+       ! the following are unused but must point to something
+!       f_massm1 => f_mass
+    ELSE ! eta = Lagrangian vertical coordinate
+       CALL allocate_field(f_massm1,field_t,type_real,llm, name='massm1')
+       ! the following are unused but must point to something
+       f_wfluxt => f_wflux
+       f_dps  => f_phis
+       f_psm1 => f_phis
+    END IF
+
+    def='runge_kutta'
+    CALL getin('scheme',def)
+
+    SELECT CASE (TRIM(def))
+      CASE('euler')
+        scheme=euler
+        nb_stage=1
+      CASE ('runge_kutta')
+        scheme=rk4
+        nb_stage=4
+      CASE ('leapfrog_matsuno')
+        scheme=mlf
+        matsuno_period=5
+        CALL getin('matsuno_period',matsuno_period)
+        nb_stage=matsuno_period+1
+     ! Model state 2 time steps ago (MLF)
+        CALL allocate_field(f_theta_rhodzm2,field_t,type_real,llm)
+        CALL allocate_field(f_um2,field_u,type_real,llm)
+        IF(caldyn_eta == eta_mass) THEN ! eta = mass coordinate (default)
+           CALL allocate_field(f_psm2,field_t,type_real)
+           ! the following are unused but must point to something
+           f_massm2 => f_mass
+        ELSE ! eta = Lagrangian vertical coordinate
+           CALL allocate_field(f_massm2,field_t,type_real,llm)
+           ! the following are unused but must point to something
+           f_psm2 => f_phis
+        END IF
+      CASE ('none')
+        nb_stage=0
+
+    CASE default
+       PRINT*,'Bad selector for variable scheme : <', TRIM(def),             &
+            ' > options are <euler>, <runge_kutta>, <leapfrog_matsuno>'
+       STOP
+    END SELECT
+
+
+    CALL init_dissip
+    CALL init_sponge
+    CALL init_caldyn
+    CALL init_guided
+    CALL init_advect_tracer
+    CALL init_check_conserve
+
+    CALL etat0(f_ps,f_mass,f_phis,f_theta_rhodz,f_u, f_q)
+
+    CALL transfert_request(f_phis,req_i0) 
+    CALL transfert_request(f_phis,req_i1) 
+    CALL writefield("phis",f_phis,once=.TRUE.)
+
+    CALL init_message(f_ps,req_i0,req_ps0)
+    CALL init_message(f_mass,req_i0,req_mass0)
+    CALL init_message(f_theta_rhodz,req_i0,req_theta_rhodz0)
+    CALL init_message(f_u,req_e0_vect,req_u0)
+    CALL init_message(f_q,req_i0,req_q0)
+
+  END SUBROUTINE init_timeloop
+  
+  SUBROUTINE timeloop
+  USE icosa
+  USE dissip_gcm_mod
+  USE sponge_mod
+  USE disvert_mod
+  USE caldyn_mod
+  USE caldyn_gcm_mod, ONLY : req_ps, req_mass
+  USE etat0_mod
+  USE guided_mod
+  USE advect_tracer_mod
+  USE physics_mod
+  USE mpipara
+  USE omp_para
+  USE trace
+  USE transfert_mod
+  USE check_conserve_mod
+  USE xios_mod
+  USE output_field_mod
+  USE write_etat0_mod
+  IMPLICIT NONE  
+    REAL(rstd),POINTER :: q(:,:,:)
+    REAL(rstd),POINTER :: phis(:), ps(:) ,psm1(:), psm2(:), dps(:)
+    REAL(rstd),POINTER :: u(:,:) , um1(:,:), um2(:,:), du(:,:)
+    REAL(rstd),POINTER :: rhodz(:,:), mass(:,:), massm1(:,:), massm2(:,:), dmass(:,:)
+    REAL(rstd),POINTER :: theta_rhodz(:,:) , theta_rhodzm1(:,:), theta_rhodzm2(:,:), dtheta_rhodz(:,:)
+    REAL(rstd),POINTER :: hflux(:,:),wflux(:,:),hfluxt(:,:),wfluxt(:,:)
+
+    INTEGER :: ind
+    INTEGER :: it,i,j,n,  stage
+    LOGICAL :: fluxt_zero(ndomain) ! set to .TRUE. to start accumulating fluxes in time
+    LOGICAL, PARAMETER :: check=.FALSE.
+    INTEGER :: start_clock
+    INTEGER :: stop_clock
+    INTEGER :: rate_clock
+    
+    
+!    CALL write_etat0(f_ps, f_phis,f_theta_rhodz,f_u,f_q) 
+!    CALL read_start(f_ps,f_mass,f_phis,f_theta_rhodz,f_u,f_q) 
+!    CALL write_restart(f_ps,f_mass,f_phis,f_theta_rhodz,f_u,f_q) 
+    
+    CALL caldyn_BC(f_phis, f_wflux) ! set constant values in first/last interfaces
+
+!!$OMP BARRIER
+  DO ind=1,ndomain
+     IF (.NOT. assigned_domain(ind)) CYCLE
+     CALL swap_dimensions(ind)
+     CALL swap_geometry(ind)
+     rhodz=f_rhodz(ind); mass=f_mass(ind); ps=f_ps(ind)
+     IF(caldyn_eta==eta_mass) THEN
+        CALL compute_rhodz(.TRUE., ps, rhodz) ! save rhodz for transport scheme before dynamics update ps
+     ELSE
+        rhodz(:,:)=mass(:,:)
+     END IF
+  END DO
+  fluxt_zero=.TRUE.
+
+!$OMP MASTER
+  CALL SYSTEM_CLOCK(start_clock)
+!$OMP END MASTER   
+
+  CALL check_conserve(f_ps,f_dps,f_u,f_theta_rhodz,f_phis,itau0)  
+
+  CALL trace_on
+  
+  DO it=itau0+1,itau0+itaumax
+    
+    IF (xios_output) CALL xios_update_calendar(it)
+    IF (it==itau0+1 .OR. MOD(it,itau_sync)==0) THEN
+      CALL send_message(f_ps,req_ps0)
+      CALL wait_message(req_ps0)
+      CALL send_message(f_mass,req_mass0)
+      CALL wait_message(req_mass0)
+      CALL send_message(f_theta_rhodz,req_theta_rhodz0) 
+      CALL wait_message(req_theta_rhodz0) 
+      CALL send_message(f_u,req_u0)
+      CALL wait_message(req_u0)
+      CALL send_message(f_q,req_q0) 
+      CALL wait_message(req_q0) 
+
+!      CALL wait_message(req_ps0)
+!      CALL wait_message(req_mass0)
+!      CALL wait_message(req_theta_rhodz0) 
+!      CALL wait_message(req_u0)
+!      CALL wait_message(req_q0) 
+    ENDIF
+
+!$OMP MASTER    
+    IF (is_mpi_root) PRINT *,"It No :",It,"   t :",dt*It
+!$OMP END MASTER    
+    IF (mod(it,itau_out)==0 ) THEN
+      CALL update_time_counter(dt*it)
+      CALL output_field("q",f_q)
+      CALL check_conserve(f_ps,f_dps,f_u,f_theta_rhodz,f_phis,it)  
+    ENDIF
+    
+    CALL guided(it*dt,f_ps,f_theta_rhodz,f_u,f_q)
+
+    DO stage=1,nb_stage
+       CALL caldyn((stage==1) .AND. (MOD(it,itau_out)==0), &
+            f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_q, &
+            f_hflux, f_wflux, f_dps, f_dmass, f_dtheta_rhodz, f_du)
+       SELECT CASE (scheme)
+       CASE(euler)
+          CALL euler_scheme(.TRUE.)
+       CASE (rk4)
+          CALL rk_scheme(stage)
+       CASE (mlf)
+          CALL  leapfrog_matsuno_scheme(stage)
+       CASE DEFAULT
+          STOP
+       END SELECT
+    END DO
+
+    IF (MOD(it,itau_dissip)==0) THEN
+!         CALL send_message(f_ps,req_ps)
+!         CALL wait_message(req_ps)  
+       
+       IF(caldyn_eta==eta_mass) THEN
+          DO ind=1,ndomain
+             IF (.NOT. assigned_domain(ind)) CYCLE
+             CALL swap_dimensions(ind)
+             CALL swap_geometry(ind)
+             mass=f_mass(ind); ps=f_ps(ind);
+             CALL compute_rhodz(.TRUE., ps, mass)
+          END DO
+       ENDIF
+!       CALL send_message(f_mass,req_mass)
+!       CALL wait_message(req_mass)  
+       CALL dissip(f_u,f_du,f_mass,f_phis, f_theta_rhodz,f_dtheta_rhodz)
+!       CALL send_message(f_mass,req_mass)
+!       CALL wait_message(req_mass)  
+       CALL euler_scheme(.FALSE.)  ! update only u, theta
+       IF (iflag_sponge > 0) THEN
+         CALL sponge(f_u,f_du,f_theta_rhodz,f_dtheta_rhodz)
+         CALL euler_scheme(.FALSE.)  ! update only u, theta
+       ENDIF
+    END IF
+
+    IF(MOD(it,itau_adv)==0) THEN
+
+       CALL advect_tracer(f_hfluxt,f_wfluxt,f_u, f_q,f_rhodz)  ! update q and rhodz after RK step
+       fluxt_zero=.TRUE.
+
+       ! FIXME : check that rhodz is consistent with ps
+       IF (check) THEN
+         DO ind=1,ndomain
+            IF (.NOT. assigned_domain(ind)) CYCLE
+            CALL swap_dimensions(ind)
+            CALL swap_geometry(ind)
+            rhodz=f_rhodz(ind); ps=f_ps(ind);
+            CALL compute_rhodz(.FALSE., ps, rhodz)   
+         END DO
+       ENDIF
+
+    END IF
+
+
+    IF (MOD(it,itau_physics)==0) THEN
+      CALL physics(it,f_phis, f_ps, f_theta_rhodz, f_u, f_wflux, f_q)
+    ENDIF
+
+    IF (MOD(it,itau_write_etat0)==0 .OR. it==itau0+itaumax) THEN
+      CALL write_etat0(it,f_ps, f_phis,f_theta_rhodz,f_u,f_q)
+    ENDIF
+    
+  ENDDO
+
+!  CALL write_etat0(itau0+itaumax,f_ps, f_phis,f_theta_rhodz,f_u,f_q) 
+
+  CALL check_conserve(f_ps,f_dps,f_u,f_theta_rhodz,f_phis,it)  
+
+!$OMP MASTER
+  CALL SYSTEM_CLOCK(stop_clock)
+  CALL SYSTEM_CLOCK(count_rate=rate_clock)
+    
+  IF (mpi_rank==0) THEN 
+    PRINT *,"Time elapsed : ",(stop_clock-start_clock)*1./rate_clock 
+  ENDIF  
+!$OMP END MASTER 
+ 
+ CONTAINS
+
+    SUBROUTINE Euler_scheme(with_dps)
+    IMPLICIT NONE
+    LOGICAL :: with_dps
+    INTEGER :: ind
+    INTEGER :: i,j,ij,l
+    CALL trace_start("Euler_scheme")  
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+
+       IF(with_dps) THEN ! update ps/mass
+          IF(caldyn_eta==eta_mass) THEN ! update ps
+             ps=f_ps(ind) ; dps=f_dps(ind) ;              
+             IF (omp_first) THEN
+!$SIMD
+                DO ij=ij_begin,ij_end
+                    ps(ij)=ps(ij)+dt*dps(ij)
+                ENDDO
+             ENDIF 
+          ELSE ! update mass
+             mass=f_mass(ind) ; dmass=f_dmass(ind) ;              
+             DO l=1,llm
+!$SIMD
+                DO ij=ij_begin,ij_end
+                    mass(ij,l)=mass(ij,l)+dt*dmass(ij,l)
+                ENDDO
+             END DO
+          END IF
+
+          hflux=f_hflux(ind);     hfluxt=f_hfluxt(ind)
+          wflux=f_wflux(ind);     wfluxt=f_wfluxt(ind)
+          CALL accumulate_fluxes(hflux,wflux,hfluxt,wfluxt,dt,fluxt_zero(ind))
+       END IF ! update ps/mass
+       
+       u=f_u(ind) ; theta_rhodz=f_theta_rhodz(ind)
+       du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
+
+       DO l=ll_begin,ll_end
+!$SIMD
+         DO ij=ij_begin,ij_end
+             u(ij+u_right,l)=u(ij+u_right,l)+dt*du(ij+u_right,l)
+             u(ij+u_lup,l)=u(ij+u_lup,l)+dt*du(ij+u_lup,l)
+             u(ij+u_ldown,l)=u(ij+u_ldown,l)+dt*du(ij+u_ldown,l)
+             theta_rhodz(ij,l)=theta_rhodz(ij,l)+dt*dtheta_rhodz(ij,l)
+         ENDDO
+       ENDDO
+    ENDDO
+
+    CALL trace_end("Euler_scheme")  
+
+    END SUBROUTINE Euler_scheme
+
+    SUBROUTINE RK_scheme(stage)
+      IMPLICIT NONE
+      INTEGER :: ind, stage
+      REAL(rstd), DIMENSION(4), PARAMETER :: coef = (/ .25, 1./3., .5, 1. /)
+      REAL(rstd) :: tau
+      INTEGER :: i,j,ij,l
+  
+      CALL trace_start("RK_scheme")  
+
+      tau = dt*coef(stage)
+
+      ! if mass coordinate, deal with ps first on one core
+      IF(caldyn_eta==eta_mass) THEN
+         IF (omp_first) THEN
+
+            DO ind=1,ndomain
+               IF (.NOT. assigned_domain(ind)) CYCLE
+               CALL swap_dimensions(ind)
+               CALL swap_geometry(ind)
+               ps=f_ps(ind) ; psm1=f_psm1(ind) ; dps=f_dps(ind) 
+               
+               IF (stage==1) THEN ! first stage : save model state in XXm1
+!$SIMD
+                 DO ij=ij_begin,ij_end
+                   psm1(ij)=ps(ij)
+                 ENDDO
+               ENDIF
+            
+               ! updates are of the form x1 := x0 + tau*f(x1)
+!$SIMD
+               DO ij=ij_begin,ij_end
+                   ps(ij)=psm1(ij)+tau*dps(ij)
+               ENDDO
+            ENDDO
+         ENDIF
+!         CALL send_message(f_ps,req_ps)
+!ym no overlap for now         
+!         CALL wait_message(req_ps)  
+      
+      ELSE ! Lagrangian coordinate, deal with mass
+         DO ind=1,ndomain
+            IF (.NOT. assigned_domain(ind)) CYCLE
+            CALL swap_dimensions(ind)
+            CALL swap_geometry(ind)
+            mass=f_mass(ind); dmass=f_dmass(ind); massm1=f_massm1(ind)
+
+            IF (stage==1) THEN ! first stage : save model state in XXm1
+               DO l=ll_begin,ll_end
+!$SIMD
+                 DO ij=ij_begin,ij_end
+                    massm1(ij,l)=mass(ij,l)
+                 ENDDO
+               ENDDO
+            END IF
+
+            ! updates are of the form x1 := x0 + tau*f(x1)
+            DO l=ll_begin,ll_end
+!$SIMD
+               DO ij=ij_begin,ij_end
+                   mass(ij,l)=massm1(ij,l)+tau*dmass(ij,l)
+               ENDDO
+            ENDDO
+         END DO
+!         CALL send_message(f_mass,req_mass)
+!ym no overlap for now         
+!         CALL wait_message(req_mass)  
+
+      END IF
+
+      ! now deal with other prognostic variables
+      DO ind=1,ndomain
+         IF (.NOT. assigned_domain(ind)) CYCLE
+         CALL swap_dimensions(ind)
+         CALL swap_geometry(ind)
+         u=f_u(ind)      ; du=f_du(ind)      ; um1=f_um1(ind) 
+         theta_rhodz=f_theta_rhodz(ind)
+         theta_rhodzm1=f_theta_rhodzm1(ind)
+         dtheta_rhodz=f_dtheta_rhodz(ind)
+         
+         IF (stage==1) THEN ! first stage : save model state in XXm1
+           DO l=ll_begin,ll_end
+!$SIMD
+                DO ij=ij_begin,ij_end
+                 um1(ij+u_right,l)=u(ij+u_right,l)
+                 um1(ij+u_lup,l)=u(ij+u_lup,l)
+                 um1(ij+u_ldown,l)=u(ij+u_ldown,l)
+                 theta_rhodzm1(ij,l)=theta_rhodz(ij,l)
+             ENDDO
+           ENDDO
+         END IF        
+
+         DO l=ll_begin,ll_end
+!$SIMD
+           DO ij=ij_begin,ij_end
+               u(ij+u_right,l)=um1(ij+u_right,l)+tau*du(ij+u_right,l)
+               u(ij+u_lup,l)=um1(ij+u_lup,l)+tau*du(ij+u_lup,l)
+               u(ij+u_ldown,l)=um1(ij+u_ldown,l)+tau*du(ij+u_ldown,l)
+               theta_rhodz(ij,l)=theta_rhodzm1(ij,l)+tau*dtheta_rhodz(ij,l)
+           ENDDO
+         ENDDO
+
+         IF(stage==nb_stage) THEN ! accumulate mass fluxes at last stage
+            hflux=f_hflux(ind);     hfluxt=f_hfluxt(ind)
+            wflux=f_wflux(ind);     wfluxt=f_wfluxt(ind)
+            CALL accumulate_fluxes(hflux,wflux, hfluxt,wfluxt, dt,fluxt_zero(ind))
+         END IF
+      END DO
+      
+      CALL trace_end("RK_scheme")
+      
+    END SUBROUTINE RK_scheme
+
+    SUBROUTINE leapfrog_matsuno_scheme(stage)
+    IMPLICIT NONE
+    INTEGER :: ind, stage
+    REAL :: tau
+
+      CALL trace_start("leapfrog_matsuno_scheme")
+    
+      tau = dt/nb_stage
+      DO ind=1,ndomain
+        IF (.NOT. assigned_domain(ind)) CYCLE
+        CALL swap_dimensions(ind)
+        CALL swap_geometry(ind)
+
+        ps=f_ps(ind)   ; u=f_u(ind)   ; theta_rhodz=f_theta_rhodz(ind)
+        psm1=f_psm1(ind) ; um1=f_um1(ind) ; theta_rhodzm1=f_theta_rhodzm1(ind)
+        psm2=f_psm2(ind) ; um2=f_um2(ind) ; theta_rhodzm2=f_theta_rhodzm2(ind)
+        dps=f_dps(ind) ; du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
+
+        
+        IF (stage==1) THEN
+          psm1(:)=ps(:) ; um1(:,:)=u(:,:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:)
+          ps(:)=psm1(:)+tau*dps(:)
+          u(:,:)=um1(:,:)+tau*du(:,:)
+          theta_rhodz(:,:)=theta_rhodzm1(:,:)+tau*dtheta_rhodz(:,:)
+
+        ELSE IF (stage==2) THEN
+
+          ps(:)=psm1(:)+tau*dps(:)
+          u(:,:)=um1(:,:)+tau*du(:,:)
+          theta_rhodz(:,:)=theta_rhodzm1(:,:)+tau*dtheta_rhodz(:,:)
+
+          psm2(:)=psm1(:) ; theta_rhodzm2(:,:)=theta_rhodzm1(:,:) ; um2(:,:)=um1(:,:) 
+          psm1(:)=ps(:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:) ; um1(:,:)=u(:,:) 
+
+        ELSE 
+
+          ps(:)=psm2(:)+2*tau*dps(:)
+          u(:,:)=um2(:,:)+2*tau*du(:,:)
+          theta_rhodz(:,:)=theta_rhodzm2(:,:)+2*tau*dtheta_rhodz(:,:)
+
+          psm2(:)=psm1(:) ; theta_rhodzm2(:,:)=theta_rhodzm1(:,:) ; um2(:,:)=um1(:,:) 
+          psm1(:)=ps(:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:) ; um1(:,:)=u(:,:) 
+
+        ENDIF
+      
+      ENDDO
+      CALL trace_end("leapfrog_matsuno_scheme")
+      
+    END SUBROUTINE leapfrog_matsuno_scheme  
+         
+  END SUBROUTINE timeloop    
+
+ SUBROUTINE accumulate_fluxes(hflux,wflux, hfluxt,wfluxt, tau,fluxt_zero)
+    USE icosa
+    USE omp_para
+    USE disvert_mod
+    IMPLICIT NONE
+    REAL(rstd), INTENT(IN)    :: hflux(3*iim*jjm,llm), wflux(iim*jjm,llm+1)
+    REAL(rstd), INTENT(INOUT) :: hfluxt(3*iim*jjm,llm), wfluxt(iim*jjm,llm+1)
+    REAL(rstd), INTENT(IN) :: tau
+    LOGICAL, INTENT(INOUT) :: fluxt_zero
+    INTEGER :: l,i,j,ij
+
+    IF(fluxt_zero) THEN
+
+       fluxt_zero=.FALSE.
+
+       DO l=ll_begin,ll_end
+!$SIMD
+         DO ij=ij_begin_ext,ij_end_ext
+             hfluxt(ij+u_right,l) = tau*hflux(ij+u_right,l)
+             hfluxt(ij+u_lup,l) = tau*hflux(ij+u_lup,l)
+             hfluxt(ij+u_ldown,l) = tau*hflux(ij+u_ldown,l)
+         ENDDO
+       ENDDO
+
+       IF(caldyn_eta==eta_mass) THEN ! no need for vertical fluxes if eta_lag
+          DO l=ll_begin,ll_endp1
+!$SIMD
+             DO ij=ij_begin,ij_end
+                wfluxt(ij,l) = tau*wflux(ij,l)
+             ENDDO
+          ENDDO
+       END IF
+
+    ELSE
+
+       DO l=ll_begin,ll_end
+!$SIMD
+         DO ij=ij_begin_ext,ij_end_ext
+             hfluxt(ij+u_right,l) = hfluxt(ij+u_right,l)+tau*hflux(ij+u_right,l)
+             hfluxt(ij+u_lup,l) = hfluxt(ij+u_lup,l)+tau*hflux(ij+u_lup,l)
+             hfluxt(ij+u_ldown,l) = hfluxt(ij+u_ldown,l)+tau*hflux(ij+u_ldown,l)
+         ENDDO
+       ENDDO
+
+       IF(caldyn_eta==eta_mass) THEN ! no need for vertical fluxes if eta_lag
+          DO l=ll_begin,ll_endp1
+!$SIMD
+             DO ij=ij_begin,ij_end
+                   wfluxt(ij,l) = wfluxt(ij,l)+tau*wflux(ij,l)
+             ENDDO
+          ENDDO
+       END IF
+
+   END IF
+
+  END SUBROUTINE accumulate_fluxes
+  
+!  FUNCTION maxval_i(p)
+!    USE icosa
+!    IMPLICIT NONE
+!    REAL(rstd), DIMENSION(iim*jjm) :: p
+!    REAL(rstd) :: maxval_i
+!    INTEGER :: j, ij
+!    
+!    maxval_i=p((jj_begin-1)*iim+ii_begin)
+!    
+!    DO j=jj_begin-1,jj_end+1
+!       ij=(j-1)*iim
+!       maxval_i = MAX(maxval_i, MAXVAL(p(ij+ii_begin:ij+ii_end)))
+!    END DO
+!  END FUNCTION maxval_i
+
+!  FUNCTION maxval_ik(p)
+!    USE icosa
+!    IMPLICIT NONE
+!    REAL(rstd) :: p(iim*jjm, llm)
+!    REAL(rstd) :: maxval_ik(llm)
+!    INTEGER :: l,j, ij
+!    
+!    DO l=1,llm
+!       maxval_ik(l)=p((jj_begin-1)*iim+ii_begin,l)
+!       DO j=jj_begin-1,jj_end+1
+!          ij=(j-1)*iim
+!          maxval_ik(l) = MAX(maxval_ik(l), MAXVAL(p(ij+ii_begin:ij+ii_end,l)))
+!       END DO
+!    END DO
+!  END FUNCTION maxval_ik
+
+END MODULE timeloop_gcm_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/trace.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/trace.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/trace.F90	(revision 329)
@@ -0,0 +1,125 @@
+MODULE trace
+
+  INTEGER,SAVE :: markId
+  
+CONTAINS
+
+  SUBROUTINE init_trace
+  IMPLICIT NONE
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+#ifdef VTRACE
+     VT_MARKER_DEF("marker", VT_MARKER_TYPE_HINT, markId)
+#endif
+  
+  END SUBROUTINE init_trace
+  
+  SUBROUTINE trace_on
+  IMPLICIT NONE
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+!$OMP MASTER
+#ifdef VTRACE
+     VT_ON()
+#endif
+!$OMP END MASTER
+     
+  END SUBROUTINE trace_on
+  
+  SUBROUTINE trace_off
+  IMPLICIT NONE
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+!$OMP MASTER
+#ifdef VTRACE
+   VT_OFF()
+#endif
+!$OMP END MASTER
+     
+  END SUBROUTINE trace_off
+    
+  SUBROUTINE trace_start(name)
+  IMPLICIT NONE
+    CHARACTER(LEN=*),INTENT(IN) :: name 
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+!$OMP MASTER
+#ifdef VTRACE
+     VT_USER_START(name)
+#endif
+!$OMP END MASTER
+
+  END SUBROUTINE trace_start    
+
+  SUBROUTINE trace_end(name)
+  IMPLICIT NONE
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+    CHARACTER(LEN=*),INTENT(IN) :: name
+
+!$OMP MASTER
+#ifdef VTRACE
+     VT_USER_END(name)
+#endif
+!$OMP END MASTER
+
+  END SUBROUTINE trace_end    
+
+  SUBROUTINE trace_start2(name)
+  IMPLICIT NONE
+    CHARACTER(LEN=*),INTENT(IN) :: name 
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+!$OMP MASTER
+#ifdef VTRACE
+     VT_USER_START(name)
+#endif
+!$OMP END MASTER
+
+  END SUBROUTINE trace_start2    
+
+  SUBROUTINE trace_end2(name)
+  IMPLICIT NONE
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+    CHARACTER(LEN=*),INTENT(IN) :: name
+
+!$OMP MASTER
+#ifdef VTRACE
+     VT_USER_END(name)
+#endif
+!$OMP END MASTER
+
+  END SUBROUTINE trace_end2    
+
+
+
+  SUBROUTINE Marker(name)
+  IMPLICIT NONE
+  CHARACTER(LEN=*),INTENT(IN) :: name
+#ifdef VTRACE
+#include <vt_user.inc>
+#endif 
+
+!$OMP MASTER
+#ifdef VTRACE
+     VT_MARKER(markId,name)
+#endif
+!$OMP END MASTER
+
+  END SUBROUTINE Marker
+
+END MODULE trace
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert.F90	(revision 329)
@@ -0,0 +1,229 @@
+MODULE transfert_mod
+
+#ifdef CPP_USING_MPI
+  USE transfert_mpi_mod, ONLY : init_transfert, transfert_request=>transfert_request_mpi, req_i1,req_e1_vect, &
+                                req_e1_scal, req_i0, req_e0_vect, req_e0_scal, request_add_point, create_request, gather_field, scatter_field, &
+                                t_message,init_message=>init_message_mpi,transfert_message=>transfert_message_mpi,  &
+                                send_message=>send_message_mpi,test_message=>test_message_mpi,wait_message=>wait_message_mpi,barrier, &
+                                bcast_mpi
+#else 
+  USE transfert_mpi_mod, ONLY : init_transfert, transfert_request=>transfert_request_seq, req_i1,req_e1_vect, &
+                                req_e1_scal,req_i0, req_e0_vect, req_e0_scal, request_add_point, create_request, gather_field, scatter_field,&
+                                t_message,init_message=>init_message_seq,transfert_message=>transfert_message_seq,  &
+                                send_message=>send_message_seq,test_message=>test_message_seq,wait_message=>wait_message_seq,barrier, &
+                                bcast_mpi
+#endif
+
+  USE transfert_omp_mod
+  
+  INTERFACE bcast
+    MODULE PROCEDURE bcast_c,                                     &
+                     bcast_i,bcast_i1,bcast_i2,bcast_i3,bcast_i4, &
+                     bcast_r,bcast_r1,bcast_r2,bcast_r3,bcast_r4, &
+		     bcast_l,bcast_l1,bcast_l2,bcast_l3,bcast_l4
+
+  END INTERFACE
+
+
+CONTAINS
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! Definition des Broadcast --> 4D   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+!! -- Les chaine de charactère -- !!
+
+  SUBROUTINE bcast_c(var)
+  IMPLICIT NONE
+    CHARACTER(LEN=*),INTENT(INOUT) :: Var
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_c
+
+!! -- Les entiers -- !!
+  
+  SUBROUTINE bcast_i(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_i
+
+  SUBROUTINE bcast_i1(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_i1
+
+
+  SUBROUTINE bcast_i2(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_i2
+
+
+  SUBROUTINE bcast_i3(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_i3
+
+
+  SUBROUTINE bcast_i4(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:,:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_i4
+
+ 
+!! -- Les reels -- !!
+  
+  SUBROUTINE bcast_r(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var
+
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_r
+
+  SUBROUTINE bcast_r1(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_r1
+
+
+  SUBROUTINE bcast_r2(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_r2
+
+
+  SUBROUTINE bcast_r3(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_r3
+
+
+  SUBROUTINE bcast_r4(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:,:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_r4 
+
+
+!! -- Les booleens -- !!
+  
+  SUBROUTINE bcast_l(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_l
+
+  SUBROUTINE bcast_l1(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_l1
+
+
+  SUBROUTINE bcast_l2(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_l2
+
+
+  SUBROUTINE bcast_l3(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_l3
+
+
+  SUBROUTINE bcast_l4(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:,:,:)
+   
+!$OMP MASTER
+    CALL bcast_mpi(Var)
+!$OMP END MASTER
+    CALL bcast_omp(Var)
+    
+  END SUBROUTINE bcast_l4
+
+  
+END MODULE transfert_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert_mpi.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert_mpi.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert_mpi.f90	(revision 329)
@@ -0,0 +1,2214 @@
+MODULE transfert_mpi_mod
+USE genmod
+USE field_mod
+  
+  TYPE array
+    INTEGER,POINTER :: value(:)
+    INTEGER,POINTER :: sign(:)
+    INTEGER         :: domain
+    INTEGER         :: rank
+    INTEGER         :: tag
+    INTEGER         :: size
+    INTEGER         :: offset
+    INTEGER         :: ireq
+    INTEGER,POINTER :: buffer(:)
+    REAL,POINTER    :: buffer_r(:)
+    INTEGER,POINTER :: src_value(:)
+  END TYPE array
+  
+  TYPE t_buffer
+    REAL,POINTER    :: r(:)
+    INTEGER         :: size
+    INTEGER         :: rank
+  END TYPE t_buffer    
+    
+  TYPE t_request
+    INTEGER :: type_field
+    INTEGER :: max_size
+    INTEGER :: size
+    LOGICAL :: vector
+    INTEGER,POINTER :: src_domain(:)
+    INTEGER,POINTER :: src_i(:)
+    INTEGER,POINTER :: src_j(:)
+    INTEGER,POINTER :: src_ind(:)
+    INTEGER,POINTER :: target_ind(:)
+    INTEGER,POINTER :: target_i(:)
+    INTEGER,POINTER :: target_j(:)
+    INTEGER,POINTER :: target_sign(:)
+    INTEGER :: nrecv
+    TYPE(ARRAY),POINTER :: recv(:)
+    INTEGER :: nsend
+    INTEGER :: nreq_mpi
+    INTEGER :: nreq_send
+    INTEGER :: nreq_recv
+    TYPE(ARRAY),POINTER :: send(:)
+  END TYPE t_request
+  
+  TYPE(t_request),SAVE,POINTER :: req_i1(:)
+  TYPE(t_request),SAVE,POINTER :: req_e1_scal(:)
+  TYPE(t_request),SAVE,POINTER :: req_e1_vect(:)
+  
+  TYPE(t_request),SAVE,POINTER :: req_i0(:)
+  TYPE(t_request),SAVE,POINTER :: req_e0_scal(:)
+  TYPE(t_request),SAVE,POINTER :: req_e0_vect(:)
+
+  TYPE t_reorder
+    INTEGER :: ind
+    INTEGER :: rank
+    INTEGER :: tag
+    INTEGER :: isend
+  END TYPE t_reorder  
+  
+  TYPE t_message
+    TYPE(t_request), POINTER :: request(:)
+    INTEGER :: nreq
+    INTEGER :: nreq_send
+    INTEGER :: nreq_recv
+    TYPE(t_reorder), POINTER :: reorder(:)
+    INTEGER, POINTER :: mpi_req(:)
+    INTEGER, POINTER :: status(:,:)
+    TYPE(t_buffer),POINTER :: buffers(:) 
+    TYPE(t_field),POINTER :: field(:)
+    LOGICAL :: completed
+    LOGICAL :: pending
+    INTEGER :: number
+  END TYPE t_message
+
+
+  INTERFACE bcast_mpi
+    MODULE PROCEDURE bcast_mpi_c,                                                     &
+                     bcast_mpi_i,bcast_mpi_i1,bcast_mpi_i2,bcast_mpi_i3,bcast_mpi_i4, &
+                     bcast_mpi_r,bcast_mpi_r1,bcast_mpi_r2,bcast_mpi_r3,bcast_mpi_r4, &
+		     bcast_mpi_l,bcast_mpi_l1,bcast_mpi_l2,bcast_mpi_l3,bcast_mpi_l4
+  END INTERFACE
+
+
+  
+CONTAINS
+       
+      
+  SUBROUTINE init_transfert
+  USE domain_mod
+  USE dimensions
+  USE field_mod
+  USE metric
+  USE mpipara
+  USE mpi_mod
+  IMPLICIT NONE
+  INTEGER :: ind,i,j
+  LOGICAL ::ok
+ 
+    CALL create_request(field_t,req_i1)
+
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      DO i=ii_begin,ii_end+1
+        CALL request_add_point(ind,i,jj_begin-1,req_i1)
+      ENDDO
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_end+1,j,req_i1)
+      ENDDO    
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_end+1,req_i1)
+      ENDDO    
+
+      DO j=jj_begin,jj_end+1
+        CALL request_add_point(ind,ii_begin-1,j,req_i1)
+      ENDDO    
+    
+    ENDDO
+  
+    CALL finalize_request(req_i1)
+
+
+    CALL create_request(field_t,req_i0)
+
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+    
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_begin,req_i0)
+      ENDDO
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_end,j,req_i0)
+      ENDDO    
+    
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_end,req_i0)
+      ENDDO    
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_begin,j,req_i0)
+      ENDDO    
+    
+    ENDDO
+ 
+    CALL finalize_request(req_i0)  
+
+
+    CALL create_request(field_u,req_e1_scal)
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_begin-1,req_e1_scal,rup)
+        CALL request_add_point(ind,i+1,jj_begin-1,req_e1_scal,lup)
+      ENDDO
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_end+1,j,req_e1_scal,left)
+        CALL request_add_point(ind,ii_end+1,j-1,req_e1_scal,lup)
+      ENDDO    
+    
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_end+1,req_e1_scal,ldown)
+        CALL request_add_point(ind,i-1,jj_end+1,req_e1_scal,rdown)
+      ENDDO    
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_begin-1,j,req_e1_scal,right)
+        CALL request_add_point(ind,ii_begin-1,j+1,req_e1_scal,rdown)
+      ENDDO   
+
+    ENDDO
+
+    CALL finalize_request(req_e1_scal)
+
+
+    CALL create_request(field_u,req_e0_scal)
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+
+
+      DO i=ii_begin+1,ii_end-1
+        CALL request_add_point(ind,i,jj_begin,req_e0_scal,right)
+        CALL request_add_point(ind,i,jj_end,req_e0_scal,right)
+      ENDDO
+    
+      DO j=jj_begin+1,jj_end-1
+        CALL request_add_point(ind,ii_begin,j,req_e0_scal,rup)
+        CALL request_add_point(ind,ii_end,j,req_e0_scal,rup)
+      ENDDO   
+
+      CALL request_add_point(ind,ii_begin+1,jj_begin,req_e0_scal,left)
+      CALL request_add_point(ind,ii_begin,jj_begin+1,req_e0_scal,ldown)
+      CALL request_add_point(ind,ii_begin+1,jj_end,req_e0_scal,left)
+      CALL request_add_point(ind,ii_end,jj_begin+1,req_e0_scal,ldown)
+
+    ENDDO
+
+    CALL finalize_request(req_e0_scal)
+
+
+    
+    CALL create_request(field_u,req_e1_vect,.TRUE.)
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_begin-1,req_e1_vect,rup)
+        CALL request_add_point(ind,i+1,jj_begin-1,req_e1_vect,lup)
+      ENDDO
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_end+1,j,req_e1_vect,left)
+        CALL request_add_point(ind,ii_end+1,j-1,req_e1_vect,lup)
+      ENDDO    
+    
+      DO i=ii_begin,ii_end
+        CALL request_add_point(ind,i,jj_end+1,req_e1_vect,ldown)
+        CALL request_add_point(ind,i-1,jj_end+1,req_e1_vect,rdown)
+      ENDDO    
+
+      DO j=jj_begin,jj_end
+        CALL request_add_point(ind,ii_begin-1,j,req_e1_vect,right)
+        CALL request_add_point(ind,ii_begin-1,j+1,req_e1_vect,rdown)
+      ENDDO   
+
+  
+    ENDDO  
+
+    CALL finalize_request(req_e1_vect)
+    
+    
+    CALL create_request(field_u,req_e0_vect,.TRUE.)
+    DO ind=1,ndomain
+      CALL swap_dimensions(ind)
+ 
+      DO i=ii_begin+1,ii_end-1
+        CALL request_add_point(ind,i,jj_begin,req_e0_vect,right)
+        CALL request_add_point(ind,i,jj_end,req_e0_vect,right)
+      ENDDO
+    
+      DO j=jj_begin+1,jj_end-1
+        CALL request_add_point(ind,ii_begin,j,req_e0_vect,rup)
+        CALL request_add_point(ind,ii_end,j,req_e0_vect,rup)
+      ENDDO   
+
+      CALL request_add_point(ind,ii_begin+1,jj_begin,req_e0_vect,left)
+      CALL request_add_point(ind,ii_begin,jj_begin+1,req_e0_vect,ldown)
+      CALL request_add_point(ind,ii_begin+1,jj_end,req_e0_vect,left)
+      CALL request_add_point(ind,ii_end,jj_begin+1,req_e0_vect,ldown)
+  
+    ENDDO  
+
+    CALL finalize_request(req_e0_vect)
+
+
+  END SUBROUTINE init_transfert
+  
+  SUBROUTINE create_request(type_field,request,vector)
+  USE domain_mod
+  USE field_mod
+  IMPLICIT NONE
+    INTEGER :: type_field
+    TYPE(t_request),POINTER :: request(:)
+    LOGICAL,OPTIONAL :: vector
+    
+    TYPE(t_request),POINTER :: req
+    TYPE(t_domain),POINTER :: d
+    INTEGER :: ind
+    INTEGER :: max_size
+       
+    ALLOCATE(request(ndomain))
+
+    DO ind=1,ndomain
+      req=>request(ind)
+      d=>domain(ind)
+      IF (type_field==field_t) THEN
+        Max_size=2*(d%iim+2)+2*(d%jjm+2)
+      ELSE IF (type_field==field_u) THEN
+        Max_size=3*(2*(d%iim+2)+2*(d%jjm+2))
+      ELSE IF (type_field==field_z) THEN
+        Max_size=2*(2*(d%iim+2)+2*(d%jjm+2))
+      ENDIF
+
+      req%type_field=type_field
+      req%max_size=max_size*2
+      req%size=0
+      req%vector=.FALSE.
+      IF (PRESENT(vector)) req%vector=vector
+      ALLOCATE(req%src_domain(req%max_size))
+      ALLOCATE(req%src_ind(req%max_size))
+      ALLOCATE(req%target_ind(req%max_size))
+      ALLOCATE(req%src_i(req%max_size))
+      ALLOCATE(req%src_j(req%max_size))
+      ALLOCATE(req%target_i(req%max_size))
+      ALLOCATE(req%target_j(req%max_size))
+      ALLOCATE(req%target_sign(req%max_size))
+    ENDDO
+  
+  END SUBROUTINE create_request
+
+  SUBROUTINE reallocate_request(req)
+  IMPLICIT NONE
+    TYPE(t_request),POINTER :: req
+      
+    INTEGER,POINTER :: src_domain(:)
+    INTEGER,POINTER :: src_ind(:)
+    INTEGER,POINTER :: target_ind(:)
+    INTEGER,POINTER :: src_i(:)
+    INTEGER,POINTER :: src_j(:)
+    INTEGER,POINTER :: target_i(:)
+    INTEGER,POINTER :: target_j(:)
+    INTEGER,POINTER :: target_sign(:)
+
+    PRINT *,"REALLOCATE_REQUEST"
+    src_domain=>req%src_domain
+    src_ind=>req%src_ind
+    target_ind=>req%target_ind
+    src_i=>req%src_i
+    src_j=>req%src_j
+    target_i=>req%target_i
+    target_j=>req%target_j
+    target_sign=>req%target_sign
+
+    ALLOCATE(req%src_domain(req%max_size*2))
+    ALLOCATE(req%src_ind(req%max_size*2))
+    ALLOCATE(req%target_ind(req%max_size*2))
+    ALLOCATE(req%src_i(req%max_size*2))
+    ALLOCATE(req%src_j(req%max_size*2))
+    ALLOCATE(req%target_i(req%max_size*2))
+    ALLOCATE(req%target_j(req%max_size*2))
+    ALLOCATE(req%target_sign(req%max_size*2))
+    
+    req%src_domain(1:req%max_size)=src_domain(:)
+    req%src_ind(1:req%max_size)=src_ind(:)
+    req%target_ind(1:req%max_size)=target_ind(:)
+    req%src_i(1:req%max_size)=src_i(:)
+    req%src_j(1:req%max_size)=src_j(:)
+    req%target_i(1:req%max_size)=target_i(:)
+    req%target_j(1:req%max_size)=target_j(:)
+    req%target_sign(1:req%max_size)=target_sign(:)
+    
+    req%max_size=req%max_size*2
+         
+    DEALLOCATE(src_domain)
+    DEALLOCATE(src_ind)
+    DEALLOCATE(target_ind)
+    DEALLOCATE(src_i)
+    DEALLOCATE(src_j)
+    DEALLOCATE(target_i)
+    DEALLOCATE(target_j)
+    DEALLOCATE(target_sign)
+
+  END SUBROUTINE reallocate_request
+
+      
+    SUBROUTINE request_add_point(ind,i,j,request,pos)
+    USE domain_mod
+    USE field_mod
+    IMPLICIT NONE
+      INTEGER,INTENT(IN)            ::  ind
+      INTEGER,INTENT(IN)            :: i
+      INTEGER,INTENT(IN)            :: j
+      TYPE(t_request),POINTER :: request(:)
+      INTEGER,INTENT(IN),OPTIONAL  :: pos
+      
+      INTEGER :: src_domain
+      INTEGER :: src_iim,src_i,src_j,src_n,src_pos,src_delta
+      TYPE(t_request),POINTER :: req
+      TYPE(t_domain),POINTER :: d
+      
+      req=>request(ind)
+      d=>domain(ind)
+      
+      IF (req%max_size==req%size) CALL reallocate_request(req)
+      req%size=req%size+1
+      IF (req%type_field==field_t) THEN
+        src_domain=domain(ind)%assign_domain(i,j)
+        src_iim=domain_glo(src_domain)%iim
+        src_i=domain(ind)%assign_i(i,j)
+        src_j=domain(ind)%assign_j(i,j)
+
+        req%target_ind(req%size)=(j-1)*d%iim+i
+        req%target_sign(req%size)=1
+        req%src_domain(req%size)=src_domain
+        req%src_ind(req%size)=(src_j-1)*src_iim+src_i
+      ELSE IF (req%type_field==field_u) THEN
+        IF (.NOT. PRESENT(pos)) STOP 'argument request_add_point non conforme'
+
+        src_domain=domain(ind)%edge_assign_domain(pos-1,i,j)
+        src_iim=domain_glo(src_domain)%iim
+        src_i=domain(ind)%edge_assign_i(pos-1,i,j)
+        src_j=domain(ind)%edge_assign_j(pos-1,i,j)
+        src_n=(src_j-1)*src_iim+src_i
+        src_delta=domain(ind)%delta(i,j)
+        src_pos=domain(ind)%edge_assign_pos(pos-1,i,j)+1
+                
+        req%target_ind(req%size)=(j-1)*d%iim+i+d%u_pos(pos)
+
+        req%target_sign(req%size)= 1
+        IF (req%vector) req%target_sign(req%size)= domain(ind)%edge_assign_sign(pos-1,i,j)
+
+        req%src_domain(req%size)=src_domain
+        req%src_ind(req%size)=src_n+domain_glo(src_domain)%u_pos(src_pos)
+
+      ELSE IF (req%type_field==field_z) THEN
+        IF (.NOT. PRESENT(pos)) STOP 'argument request_add_point non conforme'
+
+        src_domain=domain(ind)%assign_domain(i,j)
+        src_iim=domain_glo(src_domain)%iim
+        src_i=domain(ind)%assign_i(i,j)
+        src_j=domain(ind)%assign_j(i,j)
+        src_n=(src_j-1)*src_iim+src_i
+        src_delta=domain(ind)%delta(i,j)
+        
+        src_pos=MOD(pos-1+src_delta+6,6)+1
+        
+        req%target_ind(req%size)=(j-1)*d%iim+i+d%z_pos(pos)
+        req%target_sign(req%size)=1
+        req%src_domain(req%size)=src_domain
+        req%src_ind(req%size)=src_n+domain_glo(src_domain)%z_pos(src_pos)
+      ENDIF
+  END SUBROUTINE request_add_point
+  
+  
+  SUBROUTINE Finalize_request(request)
+  USE mpipara
+  USE domain_mod
+  USE mpi_mod
+  IMPLICIT NONE
+    TYPE(t_request),POINTER :: request(:)
+    TYPE(t_request),POINTER :: req, req_src
+    INTEGER :: nb_domain_recv(0:mpi_size-1)
+    INTEGER :: nb_domain_send(0:mpi_size-1)
+    INTEGER :: tag_rank(0:mpi_size-1)
+    INTEGER :: nb_data_domain_recv(ndomain_glo)
+    INTEGER :: list_domain_recv(ndomain_glo)
+    INTEGER,ALLOCATABLE :: list_domain_send(:)
+    INTEGER             :: list_domain(ndomain)
+
+    INTEGER :: rank,i,j,pos
+    INTEGER :: size_,ind_glo,ind_loc, ind_src
+    INTEGER :: isend, irecv, ireq, nreq, nsend, nrecv
+    INTEGER, ALLOCATABLE :: mpi_req(:)
+    INTEGER, ALLOCATABLE :: status(:,:)
+    INTEGER, ALLOCATABLE :: rank_list(:)
+    INTEGER, ALLOCATABLE :: offset(:)
+    LOGICAL,PARAMETER :: debug = .FALSE.
+
+ 
+    IF (.NOT. using_mpi) RETURN
+    
+    DO ind_loc=1,ndomain
+      req=>request(ind_loc)
+      
+      nb_data_domain_recv(:) = 0
+      nb_domain_recv(:) = 0
+      tag_rank(:)=0
+      
+      DO i=1,req%size
+        ind_glo=req%src_domain(i)
+        nb_data_domain_recv(ind_glo)=nb_data_domain_recv(ind_glo)+1
+      ENDDO
+ 
+      DO ind_glo=1,ndomain_glo
+        IF ( nb_data_domain_recv(ind_glo) > 0 )  nb_domain_recv(domglo_rank(ind_glo))=nb_domain_recv(domglo_rank(ind_glo))+1
+      ENDDO
+
+      req%nrecv=sum(nb_domain_recv(:))
+      ALLOCATE(req%recv(req%nrecv))
+
+      irecv=0
+      DO ind_glo=1,ndomain_glo
+        IF (nb_data_domain_recv(ind_glo)>0) THEN
+          irecv=irecv+1
+          list_domain_recv(ind_glo)=irecv
+          req%recv(irecv)%rank=domglo_rank(ind_glo)
+          req%recv(irecv)%size=nb_data_domain_recv(ind_glo)
+          req%recv(irecv)%domain=domglo_loc_ind(ind_glo)
+          ALLOCATE(req%recv(irecv)%value(req%recv(irecv)%size))
+          ALLOCATE(req%recv(irecv)%sign(req%recv(irecv)%size))
+          ALLOCATE(req%recv(irecv)%buffer(req%recv(irecv)%size))
+        ENDIF
+      ENDDO
+      
+      req%recv(:)%size=0
+      irecv=0
+      DO i=1,req%size
+        irecv=list_domain_recv(req%src_domain(i))
+        req%recv(irecv)%size=req%recv(irecv)%size+1
+        size_=req%recv(irecv)%size
+        req%recv(irecv)%value(size_)=req%src_ind(i)
+        req%recv(irecv)%buffer(size_)=req%target_ind(i)
+        req%recv(irecv)%sign(size_)=req%target_sign(i)
+      ENDDO
+    ENDDO
+
+    nb_domain_recv(:) = 0    
+    DO ind_loc=1,ndomain
+      req=>request(ind_loc)
+      
+      DO irecv=1,req%nrecv
+        rank=req%recv(irecv)%rank
+        nb_domain_recv(rank)=nb_domain_recv(rank)+1
+      ENDDO
+    ENDDO
+    
+    CALL MPI_Alltoall(nb_domain_recv,1,MPI_INTEGER,nb_domain_send,1,MPI_INTEGER,comm_icosa,ierr)     
+    
+
+    ALLOCATE(list_domain_send(sum(nb_domain_send)))
+    
+    nreq=sum(nb_domain_recv(:))+sum(nb_domain_send(:))
+    ALLOCATE(mpi_req(nreq))
+    ALLOCATE(status(MPI_STATUS_SIZE,nreq))
+    
+
+    ireq=0
+    DO ind_loc=1,ndomain
+      req=>request(ind_loc)
+      DO irecv=1,req%nrecv
+        ireq=ireq+1
+        CALL MPI_ISEND(req%recv(irecv)%domain,1,MPI_INTEGER,req%recv(irecv)%rank,0,comm_icosa, mpi_req(ireq),ierr)
+        IF (debug) PRINT *,"Isend ",req%recv(irecv)%domain, "from ", mpi_rank, "to ",req%recv(irecv)%rank, "tag ",0
+      ENDDO
+    ENDDO
+
+    IF (debug) PRINT *,"------------"    
+    j=0
+    DO rank=0,mpi_size-1
+      DO i=1,nb_domain_send(rank)
+        j=j+1
+        ireq=ireq+1
+        CALL MPI_IRECV(list_domain_send(j),1,MPI_INTEGER,rank,0,comm_icosa, mpi_req(ireq),ierr)
+        IF (debug) PRINT *,"IRecv ",list_domain_send(j), "from ", rank, "to ",mpi_rank, "tag ",0
+      ENDDO
+    ENDDO
+    IF (debug) PRINT *,"------------"    
+    
+    CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+    
+    list_domain(:)=0
+    DO i=1,sum(nb_domain_send)
+      ind_loc=list_domain_send(i)
+      list_domain(ind_loc)=list_domain(ind_loc)+1
+    ENDDO
+    
+    DO ind_loc=1,ndomain
+      req=>request(ind_loc)
+      req%nsend=list_domain(ind_loc)
+      ALLOCATE(req%send(req%nsend))
+    ENDDO
+
+    IF (debug) PRINT *,"------------"    
+   
+   ireq=0 
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       ireq=ireq+1
+       CALL MPI_ISEND(mpi_rank,1,MPI_INTEGER,req%recv(irecv)%rank,req%recv(irecv)%domain,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"Isend ",mpi_rank, "from ", mpi_rank, "to ",req%recv(irecv)%rank,"tag ",req%recv(irecv)%domain
+     ENDDO
+    IF (debug) PRINT *,"------------"    
+     
+     DO isend=1,req%nsend
+       ireq=ireq+1
+       CALL MPI_IRECV(req%send(isend)%rank,1,MPI_INTEGER,MPI_ANY_SOURCE,ind_loc,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"IRecv ",req%send(isend)%rank, "from ", "xxx", "to ",mpi_rank, "tag ",ind_loc
+     ENDDO
+   ENDDO
+
+   IF (debug) PRINT *,"------------"    
+
+   CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+   CALL MPI_BARRIER(comm_icosa,ierr)
+
+   IF (debug) PRINT *,"------------"    
+
+   ireq=0 
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       ireq=ireq+1
+       CALL MPI_ISEND(ind_loc,1,MPI_INTEGER,req%recv(irecv)%rank,req%recv(irecv)%domain,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"Isend ",ind_loc, "from ", mpi_rank, "to ",req%recv(irecv)%rank,"tag ",req%recv(irecv)%domain
+     ENDDO
+
+     IF (debug) PRINT *,"------------"    
+     
+     DO isend=1,req%nsend
+       ireq=ireq+1
+       CALL MPI_IRECV(req%send(isend)%domain,1,MPI_INTEGER,req%send(isend)%rank,ind_loc,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"IRecv ",req%send(isend)%domain, "from ", req%send(isend)%rank, "to ",mpi_rank, "tag ",ind_loc
+     ENDDO
+   ENDDO
+   IF (debug) PRINT *,"------------"    
+   
+   CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+   CALL MPI_BARRIER(comm_icosa,ierr)
+   IF (debug) PRINT *,"------------"    
+
+   ireq=0
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       ireq=ireq+1
+       req%recv(irecv)%tag=tag_rank(req%recv(irecv)%rank)
+       tag_rank(req%recv(irecv)%rank)=tag_rank(req%recv(irecv)%rank)+1
+       CALL MPI_ISEND(req%recv(irecv)%tag,1,MPI_INTEGER,req%recv(irecv)%rank,req%recv(irecv)%domain,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"Isend ",req%recv(irecv)%tag, "from ", mpi_rank, "to ",req%recv(irecv)%rank,"tag ",req%recv(irecv)%domain
+     ENDDO
+   IF (debug) PRINT *,"------------"    
+     
+     DO isend=1,req%nsend
+       ireq=ireq+1
+       CALL MPI_IRECV(req%send(isend)%tag,1,MPI_INTEGER,req%send(isend)%rank,ind_loc,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"IRecv ",req%send(isend)%tag, "from ", req%send(isend)%rank, "to ",mpi_rank, "tag ",ind_loc
+     ENDDO
+   ENDDO
+   IF (debug) PRINT *,"------------"    
+   
+   CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+   CALL MPI_BARRIER(comm_icosa,ierr)
+
+
+   IF (debug) PRINT *,"------------"    
+
+   ireq=0 
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       ireq=ireq+1
+       CALL MPI_ISEND(req%recv(irecv)%size,1,MPI_INTEGER,req%recv(irecv)%rank,req%recv(irecv)%tag,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"Isend ",req%recv(irecv)%size, "from ", mpi_rank, "to ",req%recv(irecv)%rank,"tag ",req%recv(irecv)%domain
+     ENDDO
+     IF (debug) PRINT *,"------------"    
+     
+     DO isend=1,req%nsend
+       ireq=ireq+1
+       CALL MPI_IRECV(req%send(isend)%size,1,MPI_INTEGER,req%send(isend)%rank,req%send(isend)%tag,comm_icosa, mpi_req(ireq),ierr)
+       IF (debug) PRINT *,"IRecv ",req%send(isend)%size, "from ", req%send(isend)%rank, "to ",mpi_rank, "tag ",ind_loc
+     ENDDO
+   ENDDO
+
+   CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+
+   ireq=0 
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       ireq=ireq+1
+       CALL MPI_ISEND(req%recv(irecv)%value,req%recv(irecv)%size,MPI_INTEGER,&
+            req%recv(irecv)%rank,req%recv(irecv)%tag,comm_icosa, mpi_req(ireq),ierr)
+     ENDDO
+     
+     DO isend=1,req%nsend
+       ireq=ireq+1
+       ALLOCATE(req%send(isend)%value(req%send(isend)%size))
+       CALL MPI_IRECV(req%send(isend)%value,req%send(isend)%size,MPI_INTEGER,&
+            req%send(isend)%rank,req%send(isend)%tag,comm_icosa, mpi_req(ireq),ierr)
+     ENDDO
+   ENDDO
+
+   CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       req%recv(irecv)%value(:)=req%recv(irecv)%buffer(:)
+       req%recv(irecv)%sign(:) =req%recv(irecv)%sign(:)
+       DEALLOCATE(req%recv(irecv)%buffer)
+     ENDDO
+   ENDDO  
+   
+
+! domain is on the same mpi process => copie memory to memory
+   
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+   
+       IF (req%recv(irecv)%rank==mpi_rank) THEN
+           req_src=>request(req%recv(irecv)%domain)
+           DO isend=1,req_src%nsend
+             IF (req_src%send(isend)%rank==mpi_rank .AND. req_src%send(isend)%tag==req%recv(irecv)%tag) THEN
+               req%recv(irecv)%src_value => req_src%send(isend)%value
+               IF ( size(req%recv(irecv)%value) /= size(req_src%send(isend)%value)) THEN
+                 PRINT *,ind_loc, irecv, isend, size(req%recv(irecv)%value), size(req_src%send(isend)%value)
+                 STOP "size(req%recv(irecv)%value) /= size(req_src%send(isend)%value"
+               ENDIF
+             ENDIF
+           ENDDO
+       ENDIF
+     
+     ENDDO
+   ENDDO
+   
+! true number of mpi request
+
+   request(:)%nreq_mpi=0
+   request(:)%nreq_send=0
+   request(:)%nreq_recv=0
+   ALLOCATE(rank_list(sum(request(:)%nsend)))
+   ALLOCATE(offset(sum(request(:)%nsend)))
+   offset(:)=0
+   
+   nsend=0
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+
+     DO isend=1,req%nsend
+       IF (req%send(isend)%rank/=mpi_rank) THEN
+         pos=0
+         DO i=1,nsend
+           IF (req%send(isend)%rank==rank_list(i)) EXIT
+           pos=pos+1
+         ENDDO
+        
+         IF (pos==nsend) THEN
+           nsend=nsend+1
+           req%nreq_mpi=req%nreq_mpi+1
+           req%nreq_send=req%nreq_send+1
+           IF (mpi_threading_mode==MPI_THREAD_FUNNELED .OR. mpi_threading_mode==MPI_THREAD_SINGLE) THEN
+             rank_list(nsend)=req%send(isend)%rank
+           ELSE
+             rank_list(nsend)=-1
+           ENDIF
+         ENDIF
+         
+         pos=pos+1
+         req%send(isend)%ireq=pos
+         req%send(isend)%offset=offset(pos)
+         offset(pos)=offset(pos)+req%send(isend)%size
+       ENDIF
+     ENDDO
+   ENDDO
+
+   DEALLOCATE(rank_list)
+   DEALLOCATE(offset)
+     
+   ALLOCATE(rank_list(sum(request(:)%nrecv)))
+   ALLOCATE(offset(sum(request(:)%nrecv)))
+   offset(:)=0
+   
+   nrecv=0
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+
+     DO irecv=1,req%nrecv
+       IF (req%recv(irecv)%rank/=mpi_rank) THEN
+         pos=0
+         DO i=1,nrecv
+           IF (req%recv(irecv)%rank==rank_list(i)) EXIT
+           pos=pos+1
+         ENDDO
+        
+         IF (pos==nrecv) THEN
+           nrecv=nrecv+1
+           req%nreq_mpi=req%nreq_mpi+1
+           req%nreq_recv=req%nreq_recv+1
+           IF (mpi_threading_mode==MPI_THREAD_FUNNELED .OR. mpi_threading_mode==MPI_THREAD_SINGLE) THEN
+             rank_list(nrecv)=req%recv(irecv)%rank
+           ELSE
+             rank_list(nrecv)=-1
+           ENDIF
+         ENDIF
+        
+         pos=pos+1
+         req%recv(irecv)%ireq=nsend+pos
+         req%recv(irecv)%offset=offset(pos)
+         offset(pos)=offset(pos)+req%recv(irecv)%size
+       ENDIF
+     ENDDO
+   ENDDO 
+
+! get the offsets   
+
+   ireq=0 
+   DO ind_loc=1,ndomain
+     req=>request(ind_loc)
+     
+     DO irecv=1,req%nrecv
+       ireq=ireq+1
+       CALL MPI_ISEND(req%recv(irecv)%offset,1,MPI_INTEGER,&
+            req%recv(irecv)%rank,req%recv(irecv)%tag,comm_icosa, mpi_req(ireq),ierr)
+     ENDDO
+     
+     DO isend=1,req%nsend
+       ireq=ireq+1
+       CALL MPI_IRECV(req%send(isend)%offset,1,MPI_INTEGER,&
+            req%send(isend)%rank,req%send(isend)%tag,comm_icosa, mpi_req(ireq),ierr)
+     ENDDO
+   ENDDO
+
+   CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+      
+       
+  END SUBROUTINE Finalize_request 
+
+
+  SUBROUTINE init_message_seq(field, request, message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE mpi_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_request),POINTER :: request(:)
+    TYPE(t_message) :: message
+
+!$OMP MASTER    
+    message%request=>request
+!$OMP END MASTER    
+!$OMP BARRIER    
+
+  END SUBROUTINE init_message_seq
+
+  SUBROUTINE send_message_seq(field,message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE omp_para
+  USE trace
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_message) :: message
+
+    CALL transfert_request_seq(field,message%request)
+    
+  END SUBROUTINE send_message_seq
+  
+  SUBROUTINE test_message_seq(message)
+  IMPLICIT NONE
+    TYPE(t_message) :: message
+  END SUBROUTINE  test_message_seq
+  
+   
+  SUBROUTINE wait_message_seq(message)
+  IMPLICIT NONE
+    TYPE(t_message) :: message
+    
+  END SUBROUTINE wait_message_seq    
+
+  SUBROUTINE transfert_message_seq(field,message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE omp_para
+  USE trace
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_message) :: message
+
+   CALL send_message_seq(field,message)
+    
+  END SUBROUTINE transfert_message_seq    
+    
+
+
+    
+  SUBROUTINE init_message_mpi(field,request, message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE mpi_mod
+  IMPLICIT NONE
+  
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_request),POINTER :: request(:)
+    TYPE(t_message) :: message
+
+    TYPE(ARRAY),POINTER :: recv,send 
+    TYPE(t_request),POINTER :: req
+    INTEGER :: irecv,isend
+    INTEGER :: ireq,nreq, nreq_send
+    INTEGER :: ind
+    INTEGER :: dim3,dim4
+    INTEGER :: i,j
+    INTEGER,SAVE :: message_number=0
+!    TYPE(t_reorder),POINTER :: reorder(:)
+!    TYPE(t_reorder) :: reorder_swap
+
+!$OMP BARRIER
+!$OMP MASTER
+    message%number=message_number
+    message_number=message_number+1
+    IF (message_number==100) message_number=0
+
+  
+    message%request=>request
+    message%nreq=sum(message%request(:)%nreq_mpi)
+    message%nreq_send=sum(message%request(:)%nreq_send)
+    message%nreq_recv=sum(message%request(:)%nreq_recv)
+    nreq=message%nreq
+
+    ALLOCATE(message%mpi_req(nreq))
+    ALLOCATE(message%buffers(nreq))
+    ALLOCATE(message%status(MPI_STATUS_SIZE,nreq))
+    message%buffers(:)%size=0
+    message%pending=.FALSE.
+    message%completed=.FALSE.
+  
+    DO ind=1,ndomain
+      req=>request(ind)
+      DO isend=1,req%nsend
+        IF (req%send(isend)%rank/=mpi_rank) THEN
+          ireq=req%send(isend)%ireq 
+          message%buffers(ireq)%size=message%buffers(ireq)%size+req%send(isend)%size
+          message%buffers(ireq)%rank=req%send(isend)%rank
+        ENDIF
+      ENDDO
+      DO irecv=1,req%nrecv
+        IF (req%recv(irecv)%rank/=mpi_rank) THEN
+          ireq=req%recv(irecv)%ireq 
+          message%buffers(ireq)%size=message%buffers(ireq)%size+req%recv(irecv)%size
+          message%buffers(ireq)%rank=req%recv(irecv)%rank
+        ENDIF
+      ENDDO
+    ENDDO
+
+
+    IF (field(1)%data_type==type_real) THEN
+
+      IF (field(1)%ndim==2) THEN
+     
+        DO ireq=1,message%nreq
+          CALL allocate_mpi_buffer(message%buffers(ireq)%r,message%buffers(ireq)%size)
+        ENDDO
+      
+      ELSE  IF (field(1)%ndim==3) THEN
+      
+        dim3=size(field(1)%rval3d,2)
+        DO ireq=1,message%nreq
+          message%buffers(ireq)%size=message%buffers(ireq)%size*dim3
+          CALL allocate_mpi_buffer(message%buffers(ireq)%r,message%buffers(ireq)%size)
+        ENDDO
+      
+      ELSE  IF (field(1)%ndim==4) THEN
+        dim3=size(field(1)%rval4d,2)
+        dim4=size(field(1)%rval4d,3)
+        DO ireq=1,message%nreq
+          message%buffers(ireq)%size=message%buffers(ireq)%size*dim3*dim4
+          CALL allocate_mpi_buffer(message%buffers(ireq)%r,message%buffers(ireq)%size)
+        ENDDO
+      ENDIF      
+    ENDIF
+      
+         
+    
+! ! Reorder the request, so recv request are done in the same order than send request
+
+!    nreq_send=sum(request(:)%nsend)  
+!    message%nreq_send=nreq_send
+!    ALLOCATE(message%reorder(nreq_send))
+!    reorder=>message%reorder
+!    ireq=0
+!    DO ind=1,ndomain
+!      req=>request(ind)
+!      DO isend=1,req%nsend
+!        ireq=ireq+1
+!        reorder(ireq)%ind=ind
+!        reorder(ireq)%isend=isend
+!        reorder(ireq)%tag=req%send(isend)%tag
+!      ENDDO
+!    ENDDO
+
+! ! do a very very bad sort
+!    DO i=1,nreq_send-1
+!      DO j=i+1,nreq_send
+!        IF (reorder(i)%tag > reorder(j)%tag) THEN
+!          reorder_swap=reorder(i)
+!          reorder(i)=reorder(j)
+!          reorder(j)=reorder_swap
+!        ENDIF
+!      ENDDO
+!    ENDDO
+!    PRINT *,"reorder ",reorder(:)%tag
+    
+ 
+!$OMP END MASTER
+!$OMP BARRIER    
+
+  END SUBROUTINE init_message_mpi
+  
+  SUBROUTINE Finalize_message_mpi(field,message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE mpi_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_message) :: message
+
+    TYPE(t_request),POINTER :: req
+    INTEGER :: irecv,isend
+    INTEGER :: ireq,nreq
+    INTEGER :: ind
+
+!$OMP BARRIER
+!$OMP MASTER
+
+
+    IF (field(1)%data_type==type_real) THEN
+
+      IF (field(1)%ndim==2) THEN
+     
+        DO ireq=1,message%nreq
+          CALL free_mpi_buffer(message%buffers(ireq)%r)
+        ENDDO
+      
+      ELSE  IF (field(1)%ndim==3) THEN
+
+        DO ireq=1,message%nreq
+          CALL free_mpi_buffer(message%buffers(ireq)%r)
+        ENDDO
+      
+      ELSE  IF (field(1)%ndim==4) THEN
+
+        DO ireq=1,message%nreq
+          CALL free_mpi_buffer(message%buffers(ireq)%r)
+        ENDDO
+
+      ENDIF      
+    ENDIF
+    
+
+
+!$OMP END MASTER
+!$OMP BARRIER
+
+      
+  END SUBROUTINE Finalize_message_mpi
+
+
+  
+  SUBROUTINE barrier
+  USE mpi_mod
+  USE mpipara
+  IMPLICIT NONE
+    
+    CALL MPI_BARRIER(comm_icosa,ierr)
+    
+  END SUBROUTINE barrier  
+    
+  SUBROUTINE transfert_message_mpi(field,message)
+  USE field_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_message) :: message
+    
+    CALL send_message_mpi(field,message)
+    CALL wait_message_mpi(message)
+    
+  END SUBROUTINE transfert_message_mpi
+
+
+  SUBROUTINE send_message_mpi(field,message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE omp_para
+  USE trace
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_message) :: message
+    REAL(rstd),POINTER :: rval2d(:), src_rval2d(:) 
+    REAL(rstd),POINTER :: rval3d(:,:), src_rval3d(:,:) 
+    REAL(rstd),POINTER :: rval4d(:,:,:), src_rval4d(:,:,:) 
+    REAL(rstd),POINTER :: buffer_r(:) 
+    INTEGER,POINTER :: value(:) 
+    INTEGER,POINTER :: sgn(:) 
+    TYPE(ARRAY),POINTER :: recv,send 
+    TYPE(t_request),POINTER :: req
+    INTEGER, ALLOCATABLE :: mpi_req(:)
+    INTEGER, ALLOCATABLE :: status(:,:)
+    INTEGER :: irecv,isend
+    INTEGER :: ireq,nreq
+    INTEGER :: ind,i,n,l,m
+    INTEGER :: dim3,dim4,d3,d4
+    INTEGER,POINTER :: src_value(:)
+    INTEGER,POINTER :: sign(:)
+    INTEGER :: offset,msize,rank
+
+    CALL trace_start("transfert_mpi")
+
+!$OMP BARRIER
+
+
+!$OMP MASTER
+    message%field=>field
+
+    IF (message%nreq>0) THEN
+      message%completed=.FALSE.
+      message%pending=.TRUE.
+    ELSE
+      message%completed=.TRUE.
+      message%pending=.FALSE.
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+     
+    IF (field(1)%data_type==type_real) THEN
+      IF (field(1)%ndim==2) THEN
+
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          
+          rval2d=>field(ind)%rval2d
+        
+          req=>message%request(ind)
+          DO isend=1,req%nsend
+            send=>req%send(isend)
+            value=>send%value
+
+            
+            IF (send%rank/=mpi_rank) THEN
+              ireq=send%ireq
+
+              buffer_r=>message%buffers(ireq)%r
+              offset=send%offset
+                                            
+              DO n=1,send%size
+                buffer_r(offset+n)=rval2d(value(n))
+              ENDDO
+
+              IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) THEN
+                !$OMP CRITICAL            
+                CALL MPI_ISEND(buffer_r,send%size,MPI_REAL8,send%rank,send%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+                !$OMP END CRITICAL
+              ELSE IF (mpi_threading_mode==MPI_THREAD_MULTIPLE) THEN
+                CALL MPI_ISEND(buffer_r,send%size,MPI_REAL8,send%rank,send%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+              ENDIF
+             
+            ENDIF
+          ENDDO
+        ENDDO
+        
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          rval2d=>field(ind)%rval2d
+          req=>message%request(ind)        
+
+          DO irecv=1,req%nrecv
+            recv=>req%recv(irecv)
+
+            IF (recv%rank==mpi_rank) THEN
+
+              value=>recv%value
+              src_value => recv%src_value
+              src_rval2d=>field(recv%domain)%rval2d
+              sgn=>recv%sign
+
+              DO n=1,recv%size
+                rval2d(value(n))=src_rval2d(src_value(n))*sgn(n)
+              ENDDO
+                
+                    
+            ELSE
+            
+              ireq=recv%ireq
+              buffer_r=>message%buffers(ireq)%r
+              IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) THEN
+               !$OMP CRITICAL            
+                CALL MPI_IRECV(buffer_r,recv%size,MPI_REAL8,recv%rank,recv%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+               !$OMP END CRITICAL
+              ELSE IF (mpi_threading_mode==MPI_THREAD_MULTIPLE) THEN
+                 CALL MPI_IRECV(buffer_r,recv%size,MPI_REAL8,recv%rank,recv%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+              ENDIF
+            
+            ENDIF
+          ENDDO
+        
+        ENDDO
+        
+      
+      ELSE  IF (field(1)%ndim==3) THEN
+      
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+
+          dim3=size(field(ind)%rval3d,2)
+          rval3d=>field(ind)%rval3d
+          req=>message%request(ind)
+ 
+          DO isend=1,req%nsend
+            send=>req%send(isend)
+            value=>send%value
+
+            IF (send%rank/=mpi_rank) THEN
+              ireq=send%ireq
+              buffer_r=>message%buffers(ireq)%r
+              offset=send%offset*dim3
+
+              DO d3=1,dim3
+                DO n=1,send%size
+                  buffer_r(n+offset)=rval3d(value(n),d3)
+                ENDDO
+                offset=offset+send%size
+              ENDDO
+
+              IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) THEN
+                !$OMP CRITICAL   
+                CALL MPI_ISEND(buffer_r,send%size*dim3,MPI_REAL8,send%rank,send%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+                !$OMP END CRITICAL
+              ELSE IF (mpi_threading_mode==MPI_THREAD_MULTIPLE) THEN
+                CALL MPI_ISEND(buffer_r,send%size*dim3,MPI_REAL8,send%rank,send%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+              ENDIF
+            ENDIF
+          ENDDO
+        ENDDO
+         
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          dim3=size(field(ind)%rval3d,2)
+          rval3d=>field(ind)%rval3d
+          req=>message%request(ind)
+
+          DO irecv=1,req%nrecv
+            recv=>req%recv(irecv)
+
+            IF (recv%rank==mpi_rank) THEN
+              value=>recv%value
+              src_value => recv%src_value
+              src_rval3d=>field(recv%domain)%rval3d
+              sgn=>recv%sign
+
+              DO n=1,recv%size
+                rval3d(value(n),:)=src_rval3d(src_value(n),:)*sgn(n)
+              ENDDO
+
+            ELSE
+              ireq=recv%ireq
+              buffer_r=>message%buffers(ireq)%r
+ 
+              IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) THEN
+                !$OMP CRITICAL
+                CALL MPI_IRECV(buffer_r,recv%size*dim3,MPI_REAL8,recv%rank,recv%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+                !$OMP END CRITICAL
+              ELSE IF (mpi_threading_mode==MPI_THREAD_MULTIPLE) THEN
+                CALL MPI_IRECV(buffer_r,recv%size*dim3,MPI_REAL8,recv%rank,recv%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+              ENDIF
+            ENDIF
+          ENDDO
+        
+        ENDDO
+
+      ELSE  IF (field(1)%ndim==4) THEN
+    
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+
+          dim3=size(field(ind)%rval4d,2)
+          dim4=size(field(ind)%rval4d,3)
+          rval4d=>field(ind)%rval4d
+          req=>message%request(ind)
+
+          DO isend=1,req%nsend
+            send=>req%send(isend)
+            value=>send%value
+
+            IF (send%rank/=mpi_rank) THEN
+
+              ireq=send%ireq
+              buffer_r=>message%buffers(ireq)%r
+              offset=send%offset*dim3*dim4
+
+              DO d4=1,dim4
+                DO d3=1,dim3
+                  DO n=1,send%size
+                    buffer_r(n+offset)=rval4d(value(n),d3,d4)
+                  ENDDO
+                  offset=offset+send%size
+                ENDDO
+              ENDDO
+
+              IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) THEN
+                !$OMP CRITICAL
+                CALL MPI_ISEND(buffer_r,send%size*dim3*dim4,MPI_REAL8,send%rank,send%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+                !$OMP END CRITICAL
+              ELSE IF (mpi_threading_mode==MPI_THREAD_MULTIPLE) THEN
+                CALL MPI_ISEND(buffer_r,send%size*dim3*dim4,MPI_REAL8,send%rank,send%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+              ENDIF
+
+            ENDIF
+          ENDDO
+        ENDDO
+        
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          
+          dim3=size(field(ind)%rval4d,2)
+          dim4=size(field(ind)%rval4d,3)
+          rval4d=>field(ind)%rval4d
+          req=>message%request(ind)
+
+          DO irecv=1,req%nrecv
+            recv=>req%recv(irecv)
+            IF (recv%rank==mpi_rank) THEN
+              value=>recv%value
+              src_value => recv%src_value
+              src_rval4d=>field(recv%domain)%rval4d
+              sgn=>recv%sign
+
+              DO n=1,recv%size
+                rval4d(value(n),:,:)=src_rval4d(src_value(n),:,:)*sgn(n)
+              ENDDO
+                   
+            ELSE
+
+              ireq=recv%ireq
+              buffer_r=>message%buffers(ireq)%r
+              IF (mpi_threading_mode==MPI_THREAD_SERIALIZED) THEN
+                !$OMP CRITICAL           
+                CALL MPI_IRECV(buffer_r,recv%size*dim3*dim4,MPI_REAL8,recv%rank,recv%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr) 
+                !$OMP END CRITICAL
+              ELSE IF (mpi_threading_mode==MPI_THREAD_MULTIPLE) THEN
+                CALL MPI_IRECV(buffer_r,recv%size*dim3*dim4,MPI_REAL8,recv%rank,recv%tag+1000*message%number,comm_icosa, message%mpi_req(ireq),ierr) 
+              ENDIF
+    
+            ENDIF
+          ENDDO
+        ENDDO
+
+      ENDIF      
+
+      IF (mpi_threading_mode==MPI_THREAD_FUNNELED .OR. mpi_threading_mode==MPI_THREAD_SINGLE) THEN
+!$OMP BARRIER
+!$OMP MASTER        
+
+        DO ireq=1,message%nreq_send
+          buffer_r=>message%buffers(ireq)%r
+          msize=message%buffers(ireq)%size
+          rank=message%buffers(ireq)%rank
+          CALL MPI_ISEND(buffer_r,msize,MPI_REAL8,rank,1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+        ENDDO
+
+        DO ireq=message%nreq_send+1,message%nreq_send+message%nreq_recv
+          buffer_r=>message%buffers(ireq)%r
+          msize=message%buffers(ireq)%size
+          rank=message%buffers(ireq)%rank
+          CALL MPI_IRECV(buffer_r,msize,MPI_REAL8,rank,1000*message%number,comm_icosa, message%mpi_req(ireq),ierr)
+        ENDDO
+
+!$OMP END MASTER
+      ENDIF              
+    ENDIF
+    
+!$OMP BARRIER
+    CALL trace_end("transfert_mpi")
+    
+  END SUBROUTINE send_message_mpi
+  
+  SUBROUTINE test_message_mpi(message)
+  IMPLICIT NONE
+    TYPE(t_message) :: message
+    
+    INTEGER :: ierr
+
+!$OMP MASTER
+    IF (message%pending .AND. .NOT. message%completed) CALL MPI_TESTALL(message%nreq,message%mpi_req,message%completed,message%status,ierr)
+!$OMP END MASTER
+  END SUBROUTINE  test_message_mpi
+  
+   
+  SUBROUTINE wait_message_mpi(message)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  USE omp_para
+  USE trace
+  IMPLICIT NONE
+    TYPE(t_message) :: message
+
+    TYPE(t_field),POINTER :: field(:)
+    REAL(rstd),POINTER :: rval2d(:) 
+    REAL(rstd),POINTER :: rval3d(:,:) 
+    REAL(rstd),POINTER :: rval4d(:,:,:) 
+    REAL(rstd),POINTER :: buffer_r(:) 
+    INTEGER,POINTER :: value(:) 
+    INTEGER,POINTER :: sgn(:) 
+    TYPE(ARRAY),POINTER :: recv,send 
+    TYPE(t_request),POINTER :: req
+    INTEGER, ALLOCATABLE :: mpi_req(:)
+    INTEGER, ALLOCATABLE :: status(:,:)
+    INTEGER :: irecv,isend
+    INTEGER :: ireq,nreq
+    INTEGER :: ind,n,l,m,i
+    INTEGER :: dim3,dim4,d3,d4
+    INTEGER :: offset
+
+    IF (.NOT. message%pending) RETURN
+
+    CALL trace_start("transfert_mpi")
+
+    field=>message%field
+    nreq=message%nreq
+    
+    IF (field(1)%data_type==type_real) THEN
+      IF (field(1)%ndim==2) THEN
+
+!$OMP MASTER
+        IF (.NOT. message%completed) CALL MPI_WAITALL(nreq,message%mpi_req,message%status,ierr)
+!$OMP END MASTER
+!$OMP BARRIER
+        
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+          
+          rval2d=>field(ind)%rval2d
+          req=>message%request(ind)
+          DO irecv=1,req%nrecv
+            recv=>req%recv(irecv)
+            IF (recv%rank/=mpi_rank) THEN
+              ireq=recv%ireq
+              buffer_r=>message%buffers(ireq)%r
+              value=>recv%value
+              sgn=>recv%sign
+              offset=recv%offset
+              DO n=1,recv%size
+                rval2d(value(n))=buffer_r(n+offset)*sgn(n)  
+              ENDDO
+
+            ENDIF
+          ENDDO
+        
+        ENDDO
+      
+      
+      ELSE  IF (field(1)%ndim==3) THEN
+
+!$OMP MASTER
+        IF (.NOT. message%completed) CALL MPI_WAITALL(nreq,message%mpi_req,message%status,ierr)
+!$OMP END MASTER
+!$OMP BARRIER
+
+        
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+
+          rval3d=>field(ind)%rval3d
+          req=>message%request(ind)
+          DO irecv=1,req%nrecv
+            recv=>req%recv(irecv)
+            IF (recv%rank/=mpi_rank) THEN
+              ireq=recv%ireq
+              buffer_r=>message%buffers(ireq)%r
+              value=>recv%value
+              sgn=>recv%sign
+              
+              dim3=size(rval3d,2)
+              offset=recv%offset*dim3
+              DO d3=1,dim3
+                DO n=1,recv%size
+                  rval3d(value(n),d3)=buffer_r(n+offset)*sgn(n)  
+                ENDDO
+                offset=offset+recv%size
+              ENDDO  
+            ENDIF
+          ENDDO
+        
+        ENDDO
+
+      ELSE  IF (field(1)%ndim==4) THEN
+!$OMP MASTER
+        IF (.NOT. message%completed) CALL MPI_WAITALL(nreq,message%mpi_req,message%status,ierr)
+!$OMP END MASTER
+!$OMP BARRIER
+
+                
+        DO ind=1,ndomain
+          IF (.NOT. assigned_domain(ind)) CYCLE
+
+          rval4d=>field(ind)%rval4d
+          req=>message%request(ind)
+          DO irecv=1,req%nrecv
+            recv=>req%recv(irecv)
+            IF (recv%rank/=mpi_rank) THEN
+              ireq=recv%ireq
+              buffer_r=>message%buffers(ireq)%r
+              value=>recv%value
+              sgn=>recv%sign
+
+              dim3=size(rval4d,2)
+              dim4=size(rval4d,3)
+              offset=recv%offset*dim3*dim4
+              DO d4=1,dim4
+                DO d3=1,dim3
+                  DO n=1,recv%size
+                    rval4d(value(n),d3,d4)=buffer_r(n+offset)*sgn(n) 
+                  ENDDO
+                  offset=offset+recv%size
+                ENDDO
+              ENDDO
+            ENDIF
+          ENDDO
+        
+        ENDDO
+      
+      ENDIF      
+      
+    ENDIF
+
+!$OMP MASTER
+    message%pending=.FALSE.
+!$OMP END MASTER
+
+    CALL trace_end("transfert_mpi")
+!$OMP BARRIER
+    
+  END SUBROUTINE wait_message_mpi
+
+  SUBROUTINE transfert_request_mpi(field,request)
+  USE field_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_request),POINTER :: request(:)
+
+    TYPE(t_message),SAVE :: message
+   
+   
+    CALL init_message_mpi(field,request, message)
+    CALL transfert_message_mpi(field,message)
+    CALL finalize_message_mpi(field,message)
+   
+  END SUBROUTINE transfert_request_mpi
+ 
+   
+   
+  SUBROUTINE transfert_request_seq(field,request)
+  USE field_mod
+  USE domain_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field(:)
+    TYPE(t_request),POINTER :: request(:)
+    REAL(rstd),POINTER :: rval2d(:) 
+    REAL(rstd),POINTER :: rval3d(:,:) 
+    REAL(rstd),POINTER :: rval4d(:,:,:) 
+    INTEGER :: ind
+    TYPE(t_request),POINTER :: req
+    INTEGER :: n
+    REAL(rstd) :: var1,var2
+    
+    DO ind=1,ndomain
+      req=>request(ind)
+      rval2d=>field(ind)%rval2d
+      rval3d=>field(ind)%rval3d
+      rval4d=>field(ind)%rval4d
+      
+      IF (field(ind)%data_type==type_real) THEN
+        IF (field(ind)%ndim==2) THEN
+          DO n=1,req%size
+            rval2d(req%target_ind(n))=field(req%src_domain(n))%rval2d(req%src_ind(n))*req%target_sign(n)
+          ENDDO
+        ELSE IF (field(ind)%ndim==3) THEN
+          DO n=1,req%size
+            rval3d(req%target_ind(n),:)=field(req%src_domain(n))%rval3d(req%src_ind(n),:)*req%target_sign(n)
+          ENDDO
+        ELSE IF (field(ind)%ndim==4) THEN
+          DO n=1,req%size
+            rval4d(req%target_ind(n),:,:)=field(req%src_domain(n))%rval4d(req%src_ind(n),:,:)*req%target_sign(n)
+          ENDDO
+        ENDIF
+      ENDIF        
+
+    ENDDO
+    
+  END SUBROUTINE transfert_request_seq
+  
+  
+  SUBROUTINE gather_field(field_loc,field_glo)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field_loc(:)
+    TYPE(t_field),POINTER :: field_glo(:)
+    INTEGER, ALLOCATABLE :: mpi_req(:)
+    INTEGER, ALLOCATABLE :: status(:,:)
+    INTEGER :: ireq,nreq
+    INTEGER :: ind_glo,ind_loc    
+    TYPE t_field_tmp
+      REAL,POINTER :: rval2d(:)
+      REAL,POINTER :: rval3d(:,:)
+      REAL,POINTER :: rval4d(:,:,:)
+    END TYPE t_field_tmp
+      
+    TYPE(t_field_tmp),ALLOCATABLE :: field_tmp(:)
+    TYPE(t_field_tmp),ALLOCATABLE :: field_tmp2(:)
+
+
+  
+    IF (.NOT. using_mpi) THEN
+    
+      DO ind_loc=1,ndomain
+        IF (field_loc(ind_loc)%ndim==2) field_glo(ind_loc)%rval2d=field_loc(ind_loc)%rval2d
+        IF (field_loc(ind_loc)%ndim==3) field_glo(ind_loc)%rval3d=field_loc(ind_loc)%rval3d
+        IF (field_loc(ind_loc)%ndim==4) field_glo(ind_loc)%rval4d=field_loc(ind_loc)%rval4d
+      ENDDO
+    
+    ELSE
+          
+      nreq=ndomain
+      IF (mpi_rank==0) nreq=nreq+ndomain_glo 
+      ALLOCATE(mpi_req(nreq))
+      ALLOCATE(status(MPI_STATUS_SIZE,nreq))
+    
+    
+      ireq=0
+      IF (mpi_rank==0) THEN
+        ALLOCATE(field_tmp(ndomain_glo))
+        DO ind_glo=1,ndomain_glo
+          ireq=ireq+1
+
+          IF (field_glo(ind_glo)%ndim==2) THEN
+            ALLOCATE(field_tmp(ind_glo)%rval2d(size(field_glo(ind_glo)%rval2d,1)))
+            CALL MPI_IRECV(field_tmp(ind_glo)%rval2d(1),size(field_glo(ind_glo)%rval2d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+   
+          ELSE IF (field_glo(ind_glo)%ndim==3) THEN
+            ALLOCATE(field_tmp(ind_glo)%rval3d(size(field_glo(ind_glo)%rval3d,1),size(field_glo(ind_glo)%rval3d,2)))
+            CALL MPI_IRECV(field_tmp(ind_glo)%rval3d(1,1),size(field_glo(ind_glo)%rval3d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+
+          ELSE IF (field_glo(ind_glo)%ndim==4) THEN
+            ALLOCATE(field_tmp(ind_glo)%rval4d(size(field_glo(ind_glo)%rval4d,1),size(field_glo(ind_glo)%rval4d,2), &
+                                             size(field_glo(ind_glo)%rval4d,3)))
+            CALL MPI_IRECV(field_tmp(ind_glo)%rval4d(1,1,1),size(field_glo(ind_glo)%rval4d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+          ENDIF
+         
+        ENDDO
+      ENDIF
+
+      ALLOCATE(field_tmp2(ndomain))
+  
+      DO ind_loc=1,ndomain
+        ireq=ireq+1
+
+        IF (field_loc(ind_loc)%ndim==2) THEN
+          ALLOCATE(field_tmp2(ind_loc)%rval2d(size(field_loc(ind_loc)%rval2d,1)))
+          field_tmp2(ind_loc)%rval2d=field_loc(ind_loc)%rval2d
+          CALL MPI_ISEND(field_tmp2(ind_loc)%rval2d(1),size(field_loc(ind_loc)%rval2d) , MPI_REAL8 ,   &
+                         0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+        ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+          ALLOCATE(field_tmp2(ind_loc)%rval3d(size(field_loc(ind_loc)%rval3d,1),size(field_loc(ind_loc)%rval3d,2)))
+          field_tmp2(ind_loc)%rval3d=field_loc(ind_loc)%rval3d
+          CALL MPI_ISEND(field_tmp2(ind_loc)%rval3d(1,1),size(field_loc(ind_loc)%rval3d) , MPI_REAL8 ,   &
+                         0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+        ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            ALLOCATE(field_tmp2(ind_loc)%rval4d(size(field_loc(ind_loc)%rval4d,1),size(field_loc(ind_loc)%rval4d,2), &
+                                               size(field_loc(ind_loc)%rval4d,3)))
+          field_tmp2(ind_loc)%rval4d=field_loc(ind_loc)%rval4d
+          CALL MPI_ISEND(field_tmp2(ind_loc)%rval4d(1,1,1),size(field_loc(ind_loc)%rval4d) , MPI_REAL8 ,   &
+                         0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+        ENDIF
+      
+      ENDDO
+   
+      CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+
+        DO ind_loc=1,ndomain
+          IF (field_loc(ind_loc)%ndim==2) THEN
+            DEALLOCATE(field_tmp2(ind_loc)%rval2d)
+          ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+            DEALLOCATE(field_tmp2(ind_loc)%rval3d)
+          ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            DEALLOCATE(field_tmp2(ind_loc)%rval4d)
+          ENDIF
+        ENDDO
+
+      IF (mpi_rank==0) THEN
+    
+        DO ind_glo=1,ndomain_glo
+          IF (field_glo(ind_glo)%ndim==2) THEN
+            field_glo(ind_glo)%rval2d=field_tmp(ind_glo)%rval2d
+            DEALLOCATE(field_tmp(ind_glo)%rval2d)
+          ELSE IF (field_glo(ind_glo)%ndim==3) THEN
+            field_glo(ind_glo)%rval3d=field_tmp(ind_glo)%rval3d
+            DEALLOCATE(field_tmp(ind_glo)%rval3d)
+          ELSE IF (field_glo(ind_glo)%ndim==4) THEN
+            field_glo(ind_glo)%rval4d=field_tmp(ind_glo)%rval4d
+            DEALLOCATE(field_tmp(ind_glo)%rval4d)
+          ENDIF
+        ENDDO
+      
+      ENDIF
+
+    ENDIF
+        
+  END SUBROUTINE gather_field
+
+
+  SUBROUTINE scatter_field(field_glo,field_loc)
+  USE field_mod
+  USE domain_mod
+  USE mpi_mod
+  USE mpipara
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: field_glo(:)
+    TYPE(t_field),POINTER :: field_loc(:)
+    INTEGER, ALLOCATABLE :: mpi_req(:)
+    INTEGER, ALLOCATABLE :: status(:,:)
+    INTEGER :: ireq,nreq, root_request
+    INTEGER :: ind_glo,ind_loc    
+    INTEGER :: recv_size(ndomain)
+    LOGICAL :: index
+    INTEGER ::root_status(MPI_STATUS_SIZE)
+    TYPE t_field_tmp
+      REAL,POINTER :: rval2d(:)
+      REAL,POINTER :: rval3d(:,:)
+      REAL,POINTER :: rval4d(:,:,:)
+    END TYPE t_field_tmp
+      
+    TYPE(t_field_tmp),ALLOCATABLE :: field_tmp(:)
+     
+    IF (.NOT. using_mpi) THEN
+    
+      DO ind_loc=1,ndomain
+        IF (field_loc(ind_loc)%ndim==2) field_loc(ind_loc)%rval2d=field_glo(ind_loc)%rval2d
+        IF (field_loc(ind_loc)%ndim==3) field_loc(ind_loc)%rval3d=field_glo(ind_loc)%rval3d
+        IF (field_loc(ind_loc)%ndim==4) field_loc(ind_loc)%rval4d=field_glo(ind_loc)%rval4d
+      ENDDO
+      
+    ELSE IF (.FALSE.) THEN
+
+      CALL MPI_BARRIER(comm_icosa,ierr)          
+
+      IF (mpi_rank/=0) THEN
+        nreq=ndomain
+        ALLOCATE(mpi_req(nreq))
+        ALLOCATE(status(MPI_STATUS_SIZE,nreq))
+        ALLOCATE(field_tmp(ndomain))
+        ireq=0
+        DO ind_loc=1,ndomain
+          ireq=ireq+1
+          IF (field_loc(ind_loc)%ndim==2) THEN
+            ALLOCATE(field_tmp(ind_loc)%rval2d(size(field_loc(ind_loc)%rval2d,1)))
+            CALL MPI_IRECV(field_tmp(ind_loc)%rval2d,size(field_loc(ind_loc)%rval2d) , MPI_REAL8 ,   &
+                           0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+!            DEALLOCATE(rval2d)
+          ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+            ALLOCATE(field_tmp(ind_loc)%rval3d(size(field_loc(ind_loc)%rval3d,1),size(field_loc(ind_loc)%rval3d,2)))
+            CALL MPI_IRECV(field_tmp(ind_loc)%rval3d,size(field_loc(ind_loc)%rval3d) , MPI_REAL8 ,   &
+                           0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+!            DEALLOCATE(rval3d)
+          ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            ALLOCATE(field_tmp(ind_loc)%rval4d(size(field_loc(ind_loc)%rval4d,1),size(field_loc(ind_loc)%rval4d,2), &
+                                               size(field_loc(ind_loc)%rval4d,3)))
+            CALL MPI_IRECV(field_tmp(ind_loc)%rval4d,size(field_loc(ind_loc)%rval4d) , MPI_REAL8 ,   &
+                           0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+!            DEALLOCATE(rval4d)
+          ENDIF
+       ENDDO
+      
+       DO ind_loc=1,ndomain
+         CALL MPI_WAITANY(nreq,mpi_req,index,status,ierr)
+       ENDDO
+
+       DO ind_loc=1,ndomain
+          IF (field_loc(ind_loc)%ndim==2) THEN
+            field_loc(ind_loc)%rval2d=field_tmp(ind_loc)%rval2d
+            DEALLOCATE(field_tmp(ind_loc)%rval2d)
+          ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+            field_loc(ind_loc)%rval3d=field_tmp(ind_loc)%rval3d
+            DEALLOCATE(field_tmp(ind_loc)%rval3d)
+          ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            field_loc(ind_loc)%rval4d=field_tmp(ind_loc)%rval4d
+            DEALLOCATE(field_tmp(ind_loc)%rval4d)
+          ENDIF
+
+       ENDDO
+       
+     ELSE    
+    
+        DO ind_glo=1,ndomain_glo
+
+          IF (field_glo(ind_glo)%ndim==2) THEN
+           
+            IF (domglo_rank(ind_glo)/=0) THEN
+              CALL MPI_ISSEND(field_glo(ind_glo)%rval2d,size(field_glo(ind_glo)%rval2d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, root_request, ierr)
+              CALL MPI_WAIT(root_request,root_status,ierr)
+            ELSE
+              field_loc(domglo_loc_ind(ind_glo))%rval2d =  field_glo(ind_glo)%rval2d
+            ENDIF
+
+          ELSE IF (field_glo(ind_glo)%ndim==3) THEN
+           
+            IF (domglo_rank(ind_glo)/=0) THEN
+              CALL MPI_ISSEND(field_glo(ind_glo)%rval3d,size(field_glo(ind_glo)%rval3d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, root_request, ierr)
+              CALL MPI_WAIT(root_request,root_status,ierr)
+            ELSE
+              field_loc(domglo_loc_ind(ind_glo))%rval3d =  field_glo(ind_glo)%rval3d
+            ENDIF
+
+          ELSE IF (field_glo(ind_glo)%ndim==4) THEN
+           
+            IF (domglo_rank(ind_glo)/=0) THEN
+              CALL MPI_ISSEND(field_glo(ind_glo)%rval4d,size(field_glo(ind_glo)%rval4d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, root_request, ierr)
+              CALL MPI_WAIT(root_request,root_status,ierr)
+            ELSE
+              field_loc(domglo_loc_ind(ind_glo))%rval4d =  field_glo(ind_glo)%rval4d
+            ENDIF
+         
+          ENDIF
+                         
+   
+         
+        ENDDO
+      ENDIF
+    
+    
+    ELSE
+      CALL MPI_BARRIER(comm_icosa,ierr)          
+      nreq=ndomain
+      IF (mpi_rank==0) nreq=nreq+ndomain_glo 
+      ALLOCATE(mpi_req(nreq))
+      ALLOCATE(status(MPI_STATUS_SIZE,nreq))
+      ALLOCATE(field_tmp(ndomain))
+    
+    
+      IF (.FALSE.) THEN
+      
+        ireq=0
+        IF (mpi_rank==0) THEN
+          DO ind_glo=1,ndomain_glo
+            ireq=ireq+1
+
+            IF (field_glo(ind_glo)%ndim==2) THEN
+              CALL MPI_ISEND(size(field_glo(ind_glo)%rval2d),1 , MPI_INTEGER ,   &
+                           domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+     
+            ELSE IF (field_glo(ind_glo)%ndim==3) THEN
+              CALL MPI_ISEND(size(field_glo(ind_glo)%rval3d),1 , MPI_INTEGER ,   &
+                           domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+
+            ELSE IF (field_glo(ind_glo)%ndim==4) THEN
+              CALL MPI_ISEND(size(field_glo(ind_glo)%rval4d),1 , MPI_INTEGER ,   &
+                           domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+            ENDIF
+           
+          ENDDO
+        ENDIF
+    
+        DO ind_loc=1,ndomain
+          ireq=ireq+1
+
+          IF (field_loc(ind_loc)%ndim==2) THEN
+            CALL MPI_IRECV(recv_size(ind_loc),1 , MPI_INTEGER ,   &
+                           0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+          ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+            CALL MPI_IRECV(recv_size(ind_loc),1, MPI_INTEGER ,   &
+                           0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+          ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            CALL MPI_IRECV(recv_size(ind_loc),1 , MPI_INTEGER ,   &
+                           0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+          ENDIF
+        
+        ENDDO
+     
+        CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+
+        DO ind_loc=1,ndomain
+          IF (field_loc(ind_loc)%ndim==2) THEN
+            IF (recv_size(ind_loc)/=size(field_loc(ind_loc)%rval2d)) THEN 
+              PRINT *,"Pb in  scatter_field : recv_size not conform :",recv_size(ind_loc),size(field_loc(ind_loc)%rval2d)    
+            ENDIF
+          ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+            IF (recv_size(ind_loc)/=size(field_loc(ind_loc)%rval3d)) THEN 
+              PRINT *,"Pb in  scatter_field : recv_size not conform :",recv_size(ind_loc),size(field_loc(ind_loc)%rval3d)    
+            ENDIF
+          ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            IF (recv_size(ind_loc)/=size(field_loc(ind_loc)%rval4d)) THEN 
+              PRINT *,"Pb in  scatter_field : recv_size not conform :",recv_size(ind_loc),size(field_loc(ind_loc)%rval4d)    
+            ENDIF
+          ENDIF
+        ENDDO
+        PRINT *,"scatter_field : Every thing OK ?"       
+        CALL MPI_BARRIER(comm_icosa,ierr)
+        PRINT *,"YES scatter_field : Every thing is OK ?"       
+      ENDIF
+
+
+
+      ireq=0
+      IF (mpi_rank==0) THEN
+        DO ind_glo=1,ndomain_glo
+          ireq=ireq+1
+
+          IF (field_glo(ind_glo)%ndim==2) THEN
+            CALL MPI_ISEND(field_glo(ind_glo)%rval2d,size(field_glo(ind_glo)%rval2d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+   
+          ELSE IF (field_glo(ind_glo)%ndim==3) THEN
+            CALL MPI_ISEND(field_glo(ind_glo)%rval3d,size(field_glo(ind_glo)%rval3d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+
+          ELSE IF (field_glo(ind_glo)%ndim==4) THEN
+            CALL MPI_ISEND(field_glo(ind_glo)%rval4d,size(field_glo(ind_glo)%rval4d) , MPI_REAL8 ,   &
+                         domglo_rank(ind_glo),domglo_loc_ind(ind_glo), comm_icosa, mpi_req(ireq), ierr)
+          ENDIF
+         
+        ENDDO
+      ENDIF
+  
+      DO ind_loc=1,ndomain
+        ireq=ireq+1
+
+        IF (field_loc(ind_loc)%ndim==2) THEN
+          ALLOCATE(field_tmp(ind_loc)%rval2d(size(field_loc(ind_loc)%rval2d,1)))
+          CALL MPI_IRECV(field_tmp(ind_loc)%rval2d,size(field_loc(ind_loc)%rval2d) , MPI_REAL8 ,   &
+                         0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+        ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+          ALLOCATE(field_tmp(ind_loc)%rval3d(size(field_loc(ind_loc)%rval3d,1),size(field_loc(ind_loc)%rval3d,2)))
+          CALL MPI_IRECV(field_tmp(ind_loc)%rval3d,size(field_loc(ind_loc)%rval3d) , MPI_REAL8 ,   &
+                         0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+        ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+          ALLOCATE(field_tmp(ind_loc)%rval4d(size(field_loc(ind_loc)%rval4d,1),size(field_loc(ind_loc)%rval4d,2), &
+                                             size(field_loc(ind_loc)%rval4d,3)))
+          CALL MPI_IRECV(field_tmp(ind_loc)%rval4d,size(field_loc(ind_loc)%rval4d) , MPI_REAL8 ,   &
+                         0, ind_loc, comm_icosa, mpi_req(ireq), ierr)
+        ENDIF
+      
+      ENDDO
+   
+      CALL MPI_WAITALL(nreq,mpi_req,status,ierr)
+
+      DO ind_loc=1,ndomain
+          IF (field_loc(ind_loc)%ndim==2) THEN
+            field_loc(ind_loc)%rval2d=field_tmp(ind_loc)%rval2d
+            DEALLOCATE(field_tmp(ind_loc)%rval2d)
+          ELSE IF (field_loc(ind_loc)%ndim==3) THEN
+            field_loc(ind_loc)%rval3d=field_tmp(ind_loc)%rval3d
+            DEALLOCATE(field_tmp(ind_loc)%rval3d)
+          ELSE IF (field_loc(ind_loc)%ndim==4) THEN
+            field_loc(ind_loc)%rval4d=field_tmp(ind_loc)%rval4d
+            DEALLOCATE(field_tmp(ind_loc)%rval4d)
+          ENDIF
+
+     ENDDO
+      
+      CALL MPI_BARRIER(comm_icosa,ierr)
+
+    ENDIF
+        
+  END SUBROUTINE scatter_field
+
+
+   
+  SUBROUTINE trace_in
+  USE trace
+  IMPLICIT NONE
+  
+    CALL trace_start("transfert_buffer")
+  END SUBROUTINE trace_in              
+
+  SUBROUTINE trace_out
+  USE trace
+  IMPLICIT NONE
+  
+    CALL trace_end("transfert_buffer")
+  END SUBROUTINE trace_out              
+
+
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! Definition des Broadcast --> 4D   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+!! -- Les chaine de charactère -- !!
+
+  SUBROUTINE bcast_mpi_c(var1)
+  IMPLICIT NONE
+    CHARACTER(LEN=*),INTENT(INOUT) :: Var1
+   
+    CALL bcast_mpi_cgen(Var1,len(Var1))
+
+  END SUBROUTINE bcast_mpi_c
+
+!! -- Les entiers -- !!
+  
+  SUBROUTINE bcast_mpi_i(var)
+  USE mpipara
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var
+    
+    INTEGER               :: var_tmp(1)
+    
+    IF (is_mpi_master) var_tmp(1)=var
+    CALL bcast_mpi_igen(Var_tmp,1)
+    var=var_tmp(1)
+    
+  END SUBROUTINE bcast_mpi_i
+
+  SUBROUTINE bcast_mpi_i1(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:)
+
+    CALL bcast_mpi_igen(Var,size(Var))
+    
+  END SUBROUTINE bcast_mpi_i1
+
+  SUBROUTINE bcast_mpi_i2(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:)
+   
+    CALL bcast_mpi_igen(Var,size(Var))
+  
+  END SUBROUTINE bcast_mpi_i2
+
+  SUBROUTINE bcast_mpi_i3(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:,:)
+   
+    CALL bcast_mpi_igen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_i3
+
+  SUBROUTINE bcast_mpi_i4(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:,:,:)
+   
+    CALL bcast_mpi_igen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_i4
+
+
+!! -- Les reels -- !!
+
+  SUBROUTINE bcast_mpi_r(var)
+  USE mpipara
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var
+    REAL               :: var_tmp(1)
+    
+    IF (is_mpi_master) var_tmp(1)=var
+    CALL bcast_mpi_rgen(Var_tmp,1)
+    var=var_tmp(1)   
+
+  END SUBROUTINE bcast_mpi_r
+
+  SUBROUTINE bcast_mpi_r1(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:)
+   
+    CALL bcast_mpi_rgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_r1
+
+  SUBROUTINE bcast_mpi_r2(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:)
+   
+    CALL bcast_mpi_rgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_r2
+
+  SUBROUTINE bcast_mpi_r3(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:,:)
+   
+    CALL bcast_mpi_rgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_r3
+
+  SUBROUTINE bcast_mpi_r4(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:,:,:)
+   
+    CALL bcast_mpi_rgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_r4
+  
+!! -- Les booleans -- !!
+
+  SUBROUTINE bcast_mpi_l(var)
+  USE mpipara
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var
+    LOGICAL               :: var_tmp(1)
+    
+    IF (is_mpi_master) var_tmp(1)=var
+    CALL bcast_mpi_lgen(Var_tmp,1)
+    var=var_tmp(1)   
+
+  END SUBROUTINE bcast_mpi_l
+
+  SUBROUTINE bcast_mpi_l1(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:)
+   
+    CALL bcast_mpi_lgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_l1
+
+  SUBROUTINE bcast_mpi_l2(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:)
+   
+    CALL bcast_mpi_lgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_l2
+
+  SUBROUTINE bcast_mpi_l3(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:,:)
+   
+    CALL bcast_mpi_lgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_l3
+
+  SUBROUTINE bcast_mpi_l4(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:,:,:)
+   
+    CALL bcast_mpi_lgen(Var,size(Var))
+
+  END SUBROUTINE bcast_mpi_l4
+  
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! DEFINITION DES FONCTIONS DE TRANSFERT GENERIQUES !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+  SUBROUTINE bcast_mpi_cgen(var,nb)
+    USE mpi_mod
+    USE mpipara
+    IMPLICIT NONE
+    
+    CHARACTER(LEN=*),INTENT(INOUT) :: Var
+    INTEGER,INTENT(IN) :: nb
+
+    IF (.NOT. using_mpi) RETURN
+    
+    CALL MPI_BCAST(Var,nb,MPI_CHARACTER,mpi_master,comm_icosa,ierr)
+        
+  END SUBROUTINE bcast_mpi_cgen
+
+
+      
+  SUBROUTINE bcast_mpi_igen(var,nb)
+    USE mpi_mod
+    USE mpipara
+    IMPLICIT NONE
+    
+    INTEGER,DIMENSION(nb),INTENT(INOUT) :: Var
+    INTEGER,INTENT(IN) :: nb
+
+    IF (.NOT. using_mpi) RETURN
+
+    CALL MPI_BCAST(Var,nb,MPI_INTEGER,mpi_master,comm_icosa,ierr)
+        
+  END SUBROUTINE bcast_mpi_igen
+
+
+
+  
+  SUBROUTINE bcast_mpi_rgen(var,nb)
+    USE mpi_mod
+    USE mpipara
+    IMPLICIT NONE
+    
+    REAL,DIMENSION(nb),INTENT(INOUT) :: Var
+    INTEGER,INTENT(IN) :: nb
+
+    IF (.NOT. using_mpi) RETURN
+
+    CALL MPI_BCAST(Var,nb,MPI_REAL8,mpi_master,comm_icosa,ierr)
+    
+  END SUBROUTINE bcast_mpi_rgen
+  
+
+
+
+  SUBROUTINE bcast_mpi_lgen(var,nb)
+    USE mpi_mod
+    USE mpipara
+    IMPLICIT NONE
+    
+    LOGICAL,DIMENSION(nb),INTENT(INOUT) :: Var
+    INTEGER,INTENT(IN) :: nb
+
+    IF (.NOT. using_mpi) RETURN
+
+    CALL MPI_BCAST(Var,nb,MPI_LOGICAL,mpi_master,comm_icosa,ierr)
+
+  END SUBROUTINE bcast_mpi_lgen
+  
+   
+END MODULE transfert_mpi_mod
+      
+        
+        
+        
+      
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert_omp.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert_omp.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/transfert_omp.f90	(revision 329)
@@ -0,0 +1,743 @@
+MODULE transfert_omp_mod
+  PRIVATE
+  
+  INTEGER,PARAMETER :: grow_factor=1.5
+  INTEGER,PARAMETER :: size_min=1024
+  
+  CHARACTER(LEN=size_min),SAVE            :: buffer_c
+!  INTEGER,SAVE                            :: size_c=0
+  INTEGER,SAVE,ALLOCATABLE,DIMENSION(:)   :: buffer_i
+  INTEGER,SAVE                            :: size_i=0
+  REAL,SAVE,ALLOCATABLE,DIMENSION(:)      :: buffer_r
+  INTEGER,SAVE                            :: size_r=0
+  LOGICAL,SAVE,ALLOCATABLE,DIMENSION(:)   :: buffer_l
+  INTEGER,SAVE                            :: size_l=0
+
+
+  
+  
+  INTERFACE bcast_omp
+    MODULE PROCEDURE bcast_omp_c,                                                     &
+                     bcast_omp_i,bcast_omp_i1,bcast_omp_i2,bcast_omp_i3,bcast_omp_i4, &
+                     bcast_omp_r,bcast_omp_r1,bcast_omp_r2,bcast_omp_r3,bcast_omp_r4, &
+		     bcast_omp_l,bcast_omp_l1,bcast_omp_l2,bcast_omp_l3,bcast_omp_l4
+  END INTERFACE
+
+  INTERFACE reduce_sum_omp
+    MODULE PROCEDURE reduce_sum_omp_i,reduce_sum_omp_i1,reduce_sum_omp_i2,reduce_sum_omp_i3,reduce_sum_omp_i4, &
+                     reduce_sum_omp_r,reduce_sum_omp_r1,reduce_sum_omp_r2,reduce_sum_omp_r3,reduce_sum_omp_r4
+  END INTERFACE 
+
+  INTERFACE allreduce_sum_omp
+    MODULE PROCEDURE allreduce_sum_omp_i,allreduce_sum_omp_i1,allreduce_sum_omp_i2,allreduce_sum_omp_i3,allreduce_sum_omp_i4, &
+                     allreduce_sum_omp_r,allreduce_sum_omp_r1,allreduce_sum_omp_r2,allreduce_sum_omp_r3,allreduce_sum_omp_r4
+  END INTERFACE 
+
+  PUBLIC bcast_omp, reduce_sum_omp, allreduce_sum_omp
+  
+CONTAINS
+
+  SUBROUTINE check_buffer_i(buff_size)
+  IMPLICIT NONE
+  INTEGER :: buff_size
+
+!$OMP BARRIER
+!$OMP MASTER
+    IF (buff_size>size_i) THEN
+      IF (ALLOCATED(buffer_i)) DEALLOCATE(buffer_i)
+      size_i=MAX(size_min,INT(grow_factor*buff_size))
+      ALLOCATE(buffer_i(size_i))
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+  
+  END SUBROUTINE check_buffer_i
+  
+  SUBROUTINE check_buffer_r(buff_size)
+  IMPLICIT NONE
+  INTEGER :: buff_size
+
+!$OMP BARRIER
+!$OMP MASTER
+    IF (buff_size>size_r) THEN
+      IF (ALLOCATED(buffer_r)) DEALLOCATE(buffer_r)
+      size_r=MAX(size_min,INT(grow_factor*buff_size))
+      ALLOCATE(buffer_r(size_r))
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+  
+  END SUBROUTINE check_buffer_r
+  
+  SUBROUTINE check_buffer_l(buff_size)
+  IMPLICIT NONE
+  INTEGER :: buff_size
+
+!$OMP BARRIER
+!$OMP MASTER
+    IF (buff_size>size_l) THEN
+      IF (ALLOCATED(buffer_l)) DEALLOCATE(buffer_l)
+      size_l=MAX(size_min,INT(grow_factor*buff_size))
+      ALLOCATE(buffer_l(size_l))
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+  
+  END SUBROUTINE check_buffer_l
+    
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! Definition des Broadcast --> 4D   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+!! -- Les chaine de charactère -- !!
+
+  SUBROUTINE bcast_omp_c(var)
+  IMPLICIT NONE
+    CHARACTER(LEN=*),INTENT(INOUT) :: Var
+    INTEGER :: lenvar
+    lenvar=len(Var)
+    CALL bcast_omp_i(lenvar)
+    CALL bcast_omp_cgen(Var,lenvar,buffer_c)    
+  END SUBROUTINE bcast_omp_c
+
+!! -- Les entiers -- !!
+  
+  SUBROUTINE bcast_omp_i(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var
+    INTEGER :: Var_tmp(1)
+    
+    Var_tmp(1)=Var
+    CALL check_buffer_i(1)
+    CALL bcast_omp_igen(Var_tmp,1,buffer_i)
+    Var=Var_tmp(1)
+
+  END SUBROUTINE bcast_omp_i
+
+
+  SUBROUTINE bcast_omp_i1(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:)
+   
+    CALL check_buffer_i(size(Var))
+    CALL bcast_omp_igen(Var,size(Var),buffer_i)
+
+  END SUBROUTINE bcast_omp_i1
+
+
+  SUBROUTINE bcast_omp_i2(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:)
+   
+    CALL check_buffer_i(size(Var))
+    CALL bcast_omp_igen(Var,size(Var),buffer_i)
+
+  END SUBROUTINE bcast_omp_i2
+
+
+  SUBROUTINE bcast_omp_i3(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:,:)
+
+    CALL check_buffer_i(size(Var))
+    CALL bcast_omp_igen(Var,size(Var),buffer_i)
+
+  END SUBROUTINE bcast_omp_i3
+
+
+  SUBROUTINE bcast_omp_i4(var)
+  IMPLICIT NONE
+    INTEGER,INTENT(INOUT) :: Var(:,:,:,:)
+   
+    CALL check_buffer_i(size(Var))
+    CALL bcast_omp_igen(Var,size(Var),buffer_i)
+
+  END SUBROUTINE bcast_omp_i4
+
+
+!! -- Les reels -- !!
+
+  SUBROUTINE bcast_omp_r(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var
+    REAL :: Var_tmp(1)
+    
+    Var_tmp(1)=Var
+    CALL check_buffer_r(1)
+    CALL bcast_omp_rgen(Var_tmp,1,buffer_r)
+    Var=Var_tmp(1)
+
+  END SUBROUTINE bcast_omp_r
+
+
+  SUBROUTINE bcast_omp_r1(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:)
+   
+    CALL check_buffer_r(size(Var))
+    CALL bcast_omp_rgen(Var,size(Var),buffer_r)
+
+  END SUBROUTINE bcast_omp_r1
+
+
+  SUBROUTINE bcast_omp_r2(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:)
+   
+    CALL check_buffer_r(size(Var))
+    CALL bcast_omp_rgen(Var,size(Var),buffer_r)
+
+  END SUBROUTINE bcast_omp_r2
+
+
+  SUBROUTINE bcast_omp_r3(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:,:)
+
+    CALL check_buffer_r(size(Var))
+    CALL bcast_omp_rgen(Var,size(Var),buffer_r)
+
+  END SUBROUTINE bcast_omp_r3
+
+
+  SUBROUTINE bcast_omp_r4(var)
+  IMPLICIT NONE
+    REAL,INTENT(INOUT) :: Var(:,:,:,:)
+   
+    CALL check_buffer_r(size(Var))
+    CALL bcast_omp_rgen(Var,size(Var),buffer_r)
+
+  END SUBROUTINE bcast_omp_r4
+
+  
+!! -- Les booleans -- !!
+
+  SUBROUTINE bcast_omp_l(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var
+    LOGICAL :: Var_tmp(1)
+    
+    Var_tmp(1)=Var
+    CALL check_buffer_l(1)
+    CALL bcast_omp_lgen(Var_tmp,1,buffer_l)
+    Var=Var_tmp(1)
+
+  END SUBROUTINE bcast_omp_l
+
+
+  SUBROUTINE bcast_omp_l1(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:)
+   
+    CALL check_buffer_l(size(Var))
+    CALL bcast_omp_lgen(Var,size(Var),buffer_l)
+
+  END SUBROUTINE bcast_omp_l1
+
+
+  SUBROUTINE bcast_omp_l2(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:)
+   
+    CALL check_buffer_l(size(Var))
+    CALL bcast_omp_lgen(Var,size(Var),buffer_l)
+
+  END SUBROUTINE bcast_omp_l2
+
+
+  SUBROUTINE bcast_omp_l3(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:,:)
+
+    CALL check_buffer_l(size(Var))
+    CALL bcast_omp_lgen(Var,size(Var),buffer_l)
+
+  END SUBROUTINE bcast_omp_l3
+
+
+  SUBROUTINE bcast_omp_l4(var)
+  IMPLICIT NONE
+    LOGICAL,INTENT(INOUT) :: Var(:,:,:,:)
+   
+    CALL check_buffer_l(size(Var))
+    CALL bcast_omp_lgen(Var,size(Var),buffer_l)
+
+  END SUBROUTINE bcast_omp_l4
+  
+
+
+
+  SUBROUTINE reduce_sum_omp_i(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN)  :: VarIn
+    INTEGER,INTENT(OUT) :: VarOut
+    INTEGER             :: VarIn_tmp(1)
+    INTEGER             :: VarOut_tmp(1)
+    
+    VarIn_tmp(1)=VarIn
+    CALL Check_buffer_i(1)   
+    CALL reduce_sum_omp_igen(VarIn_tmp,Varout_tmp,1,buffer_i)
+    VarOut=VarOut_tmp(1)
+    
+  END SUBROUTINE reduce_sum_omp_i
+
+  SUBROUTINE reduce_sum_omp_i1(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN),DIMENSION(:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:) :: VarOut
+    
+    CALL Check_buffer_i(size(VarIn))   
+    CALL reduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+   
+  END SUBROUTINE reduce_sum_omp_i1
+  
+  
+  SUBROUTINE reduce_sum_omp_i2(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN),DIMENSION(:,:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:,:) :: VarOut
+
+    CALL Check_buffer_i(size(VarIn))   
+    CALL reduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+  
+  END SUBROUTINE reduce_sum_omp_i2
+
+
+  SUBROUTINE reduce_sum_omp_i3(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN),DIMENSION(:,:,:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:,:,:) :: VarOut
+    
+    CALL Check_buffer_i(size(VarIn))   
+    CALL reduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+  
+  END SUBROUTINE reduce_sum_omp_i3
+
+
+  SUBROUTINE reduce_sum_omp_i4(VarIn, VarOut)
+    IMPLICIT NONE
+
+    INTEGER,INTENT(IN),DIMENSION(:,:,:,:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:,:,:,:) :: VarOut
+  
+    CALL Check_buffer_i(size(VarIn))   
+    CALL reduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+  
+  END SUBROUTINE reduce_sum_omp_i4
+
+
+  SUBROUTINE reduce_sum_omp_r(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN)  :: VarIn
+    REAL,INTENT(OUT) :: VarOut
+    REAL             :: VarIn_tmp(1)
+    REAL             :: VarOut_tmp(1)
+    
+    VarIn_tmp(1)=VarIn
+    CALL Check_buffer_r(1)   
+    CALL reduce_sum_omp_rgen(VarIn_tmp,Varout_tmp,1,buffer_r)
+    VarOut=VarOut_tmp(1)
+  
+  END SUBROUTINE reduce_sum_omp_r
+
+  SUBROUTINE reduce_sum_omp_r1(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN),DIMENSION(:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:) :: VarOut
+    
+    CALL Check_buffer_r(size(VarIn))   
+    CALL reduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+   
+  END SUBROUTINE reduce_sum_omp_r1
+  
+  
+  SUBROUTINE reduce_sum_omp_r2(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN),DIMENSION(:,:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:,:) :: VarOut
+    
+    CALL Check_buffer_r(size(VarIn))   
+    CALL reduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+  
+  END SUBROUTINE reduce_sum_omp_r2
+
+
+  SUBROUTINE reduce_sum_omp_r3(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN),DIMENSION(:,:,:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:,:,:) :: VarOut
+    
+    CALL Check_buffer_r(size(VarIn))   
+    CALL reduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+  
+  END SUBROUTINE reduce_sum_omp_r3
+
+
+  SUBROUTINE reduce_sum_omp_r4(VarIn, VarOut)
+    IMPLICIT NONE
+
+    REAL,INTENT(IN),DIMENSION(:,:,:,:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:,:,:,:) :: VarOut
+  
+    CALL Check_buffer_r(size(VarIn))   
+    CALL reduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+  
+  END SUBROUTINE reduce_sum_omp_r4  
+  
+  
+  
+  
+    SUBROUTINE allreduce_sum_omp_i(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN)  :: VarIn
+    INTEGER,INTENT(OUT) :: VarOut
+    INTEGER             :: VarIn_tmp(1)
+    INTEGER             :: VarOut_tmp(1)
+    
+    VarIn_tmp(1)=VarIn
+    CALL Check_buffer_i(1)   
+    CALL allreduce_sum_omp_igen(VarIn_tmp,Varout_tmp,1,buffer_i)
+    VarOut=VarOut_tmp(1)
+    
+  END SUBROUTINE allreduce_sum_omp_i
+
+  SUBROUTINE allreduce_sum_omp_i1(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN),DIMENSION(:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:) :: VarOut
+    
+    CALL Check_buffer_i(size(VarIn))   
+    CALL allreduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+   
+  END SUBROUTINE allreduce_sum_omp_i1
+  
+  
+  SUBROUTINE allreduce_sum_omp_i2(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN),DIMENSION(:,:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:,:) :: VarOut
+
+    CALL Check_buffer_i(size(VarIn))   
+    CALL allreduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+  
+  END SUBROUTINE allreduce_sum_omp_i2
+
+
+  SUBROUTINE allreduce_sum_omp_i3(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    INTEGER,INTENT(IN),DIMENSION(:,:,:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:,:,:) :: VarOut
+    
+    CALL Check_buffer_i(size(VarIn))   
+    CALL allreduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+  
+  END SUBROUTINE allreduce_sum_omp_i3
+
+
+  SUBROUTINE allreduce_sum_omp_i4(VarIn, VarOut)
+    IMPLICIT NONE
+
+    INTEGER,INTENT(IN),DIMENSION(:,:,:,:)  :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(:,:,:,:) :: VarOut
+  
+    CALL Check_buffer_i(size(VarIn))   
+    CALL allreduce_sum_omp_igen(VarIn,Varout,Size(VarIn),buffer_i)
+  
+  END SUBROUTINE allreduce_sum_omp_i4
+
+
+  SUBROUTINE allreduce_sum_omp_r(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN)  :: VarIn
+    REAL,INTENT(OUT) :: VarOut
+    REAL             :: VarIn_tmp(1)
+    REAL             :: VarOut_tmp(1)
+    
+    VarIn_tmp(1)=VarIn
+    CALL Check_buffer_r(1)   
+    CALL allreduce_sum_omp_rgen(VarIn_tmp,Varout_tmp,1,buffer_r)
+    VarOut=VarOut_tmp(1)
+  
+  END SUBROUTINE allreduce_sum_omp_r
+
+  SUBROUTINE allreduce_sum_omp_r1(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN),DIMENSION(:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:) :: VarOut
+    
+    CALL Check_buffer_r(size(VarIn))   
+    CALL allreduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+   
+  END SUBROUTINE allreduce_sum_omp_r1
+  
+  
+  SUBROUTINE allreduce_sum_omp_r2(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN),DIMENSION(:,:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:,:) :: VarOut
+    
+    CALL Check_buffer_r(size(VarIn))   
+    CALL allreduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+  
+  END SUBROUTINE allreduce_sum_omp_r2
+
+
+  SUBROUTINE allreduce_sum_omp_r3(VarIn, VarOut)
+    IMPLICIT NONE
+  
+    REAL,INTENT(IN),DIMENSION(:,:,:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:,:,:) :: VarOut
+    
+    CALL Check_buffer_r(size(VarIn))   
+    CALL allreduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+  
+  END SUBROUTINE allreduce_sum_omp_r3
+
+
+  SUBROUTINE allreduce_sum_omp_r4(VarIn, VarOut)
+    IMPLICIT NONE
+
+    REAL,INTENT(IN),DIMENSION(:,:,:,:)  :: VarIn
+    REAL,INTENT(OUT),DIMENSION(:,:,:,:) :: VarOut
+  
+    CALL Check_buffer_r(size(VarIn))   
+    CALL allreduce_sum_omp_rgen(VarIn,Varout,Size(VarIn),buffer_r)
+  
+  END SUBROUTINE allreduce_sum_omp_r4  
+  
+  
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!    LES ROUTINES GENERIQUES    !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+  SUBROUTINE bcast_omp_cgen(Var,Nb,Buff)
+  IMPLICIT NONE
+    
+    CHARACTER(LEN=*),INTENT(INOUT) :: Var
+    CHARACTER(LEN=*),INTENT(INOUT) :: Buff
+    INTEGER,INTENT(IN) :: Nb
+    
+    INTEGER :: i
+  
+  !$OMP MASTER
+      Buff=Var
+  !$OMP END MASTER
+  !$OMP BARRIER
+
+    DO i=1,Nb
+      Var=Buff
+    ENDDO
+  !$OMP BARRIER      
+  
+  END SUBROUTINE bcast_omp_cgen
+
+
+      
+  SUBROUTINE bcast_omp_igen(Var,Nb,Buff)
+  IMPLICIT NONE
+    
+    INTEGER,DIMENSION(Nb),INTENT(INOUT) :: Var
+    INTEGER,DIMENSION(Nb),INTENT(INOUT) :: Buff
+    INTEGER,INTENT(IN) :: Nb
+
+    INTEGER :: i
+    
+  !$OMP MASTER
+    DO i=1,Nb
+      Buff(i)=Var(i)
+    ENDDO
+  !$OMP END MASTER
+  !$OMP BARRIER
+
+    DO i=1,Nb
+      Var(i)=Buff(i)
+    ENDDO
+  !$OMP BARRIER        
+
+  END SUBROUTINE bcast_omp_igen
+
+
+  SUBROUTINE bcast_omp_rgen(Var,Nb,Buff)
+  IMPLICIT NONE
+    
+    REAL,DIMENSION(Nb),INTENT(INOUT) :: Var
+    REAL,DIMENSION(Nb),INTENT(INOUT) :: Buff
+    INTEGER,INTENT(IN) :: Nb
+
+    INTEGER :: i
+    
+  !$OMP MASTER
+    DO i=1,Nb
+      Buff(i)=Var(i)
+    ENDDO
+  !$OMP END MASTER
+  !$OMP BARRIER
+
+    DO i=1,Nb
+      Var(i)=Buff(i)
+    ENDDO
+  !$OMP BARRIER        
+
+  END SUBROUTINE bcast_omp_rgen
+
+  SUBROUTINE bcast_omp_lgen(Var,Nb,Buff)
+  IMPLICIT NONE
+    
+    LOGICAL,DIMENSION(Nb),INTENT(INOUT) :: Var
+    LOGICAL,DIMENSION(Nb),INTENT(INOUT) :: Buff
+    INTEGER,INTENT(IN) :: Nb
+  
+    INTEGER :: i
+    
+  !$OMP MASTER
+    DO i=1,Nb
+      Buff(i)=Var(i)
+    ENDDO
+  !$OMP END MASTER
+  !$OMP BARRIER
+
+    DO i=1,Nb
+      Var(i)=Buff(i)
+    ENDDO
+  !$OMP BARRIER        
+
+  END SUBROUTINE bcast_omp_lgen
+  
+
+  SUBROUTINE reduce_sum_omp_igen(VarIn,VarOut,dimsize,Buff)
+  IMPLICIT NONE
+
+    INTEGER,INTENT(IN) :: dimsize
+    INTEGER,INTENT(IN),DIMENSION(dimsize) :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(dimsize) :: VarOut
+    INTEGER,INTENT(INOUT),DIMENSION(dimsize) :: Buff
+
+    INTEGER :: i
+
+  !$OMP MASTER
+    Buff(:)=0
+  !$OMP END MASTER
+  !$OMP BARRIER
+  
+  !$OMP CRITICAL     
+    DO i=1,dimsize
+      Buff(i)=Buff(i)+VarIn(i)
+    ENDDO
+  !$OMP END CRITICAL
+  !$OMP BARRIER  
+  
+  !$OMP MASTER
+    DO i=1,dimsize
+      VarOut(i)=Buff(i)
+    ENDDO
+  !$OMP END MASTER
+  !$OMP BARRIER
+  
+  END SUBROUTINE reduce_sum_omp_igen
+
+  SUBROUTINE reduce_sum_omp_rgen(VarIn,VarOut,dimsize,Buff)
+  IMPLICIT NONE
+
+    INTEGER,INTENT(IN) :: dimsize
+    REAL,INTENT(IN),DIMENSION(dimsize) :: VarIn
+    REAL,INTENT(OUT),DIMENSION(dimsize) :: VarOut
+    REAL,INTENT(INOUT),DIMENSION(dimsize) :: Buff
+
+    INTEGER :: i
+
+  !$OMP MASTER
+    Buff(:)=0
+  !$OMP END MASTER
+  !$OMP BARRIER
+  
+  !$OMP CRITICAL     
+    DO i=1,dimsize
+      Buff(i)=Buff(i)+VarIn(i)
+    ENDDO
+  !$OMP END CRITICAL
+  !$OMP BARRIER  
+  
+    DO i=1,dimsize
+      VarOut(i)=Buff(i)
+    ENDDO
+  !$OMP BARRIER
+  
+  END SUBROUTINE reduce_sum_omp_rgen
+
+
+
+  SUBROUTINE allreduce_sum_omp_igen(VarIn,VarOut,dimsize,Buff)
+  IMPLICIT NONE
+
+    INTEGER,INTENT(IN) :: dimsize
+    INTEGER,INTENT(IN),DIMENSION(dimsize) :: VarIn
+    INTEGER,INTENT(OUT),DIMENSION(dimsize) :: VarOut
+    INTEGER,INTENT(INOUT),DIMENSION(dimsize) :: Buff
+
+    INTEGER :: i
+
+  !$OMP MASTER
+    Buff(:)=0
+  !$OMP END MASTER
+  !$OMP BARRIER
+  
+  !$OMP CRITICAL     
+    DO i=1,dimsize
+      Buff(i)=Buff(i)+VarIn(i)
+    ENDDO
+  !$OMP END CRITICAL
+  !$OMP BARRIER  
+  
+    DO i=1,dimsize
+      VarOut(i)=Buff(i)
+    ENDDO
+  !$OMP BARRIER
+  
+  END SUBROUTINE allreduce_sum_omp_igen
+
+  SUBROUTINE allreduce_sum_omp_rgen(VarIn,VarOut,dimsize,Buff)
+  IMPLICIT NONE
+
+    INTEGER,INTENT(IN) :: dimsize
+    REAL,INTENT(IN),DIMENSION(dimsize) :: VarIn
+    REAL,INTENT(OUT),DIMENSION(dimsize) :: VarOut
+    REAL,INTENT(INOUT),DIMENSION(dimsize) :: Buff
+
+    INTEGER :: i
+
+  !$OMP MASTER
+    Buff(:)=0
+  !$OMP END MASTER
+  !$OMP BARRIER
+  
+  !$OMP CRITICAL     
+    DO i=1,dimsize
+      Buff(i)=Buff(i)+VarIn(i)
+    ENDDO
+  !$OMP END CRITICAL
+  !$OMP BARRIER  
+  
+    DO i=1,dimsize
+      VarOut(i)=Buff(i)
+    ENDDO
+
+  !$OMP BARRIER
+  
+  END SUBROUTINE allreduce_sum_omp_rgen
+    
+END MODULE transfert_omp_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vector.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vector.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vector.f90	(revision 329)
@@ -0,0 +1,55 @@
+MODULE vector
+  USE genmod
+
+CONTAINS
+
+  FUNCTION Norm(V)
+  IMPLICIT NONE
+    REAL(rstd)            :: Norm
+    REAL(rstd),INTENT(IN) :: V(3)
+    
+    Norm=sqrt(V(1)*V(1)+V(2)*V(2)+V(3)*V(3))
+  
+  END FUNCTION Norm
+  
+  FUNCTION dot_product(V1,V2)
+  IMPLICIT NONE
+    REAL(rstd)       :: dot_product
+    REAL(rstd),INTENT(IN) :: V1(3)
+    REAL(rstd),INTENT(IN) :: V2(3)
+    
+    dot_product=V1(1)*V2(1)+V1(2)*V2(2)+V1(3)*V2(3)
+    
+   END FUNCTION dot_product
+   
+   FUNCTION cross_product(V1,V2)
+   IMPLICIT NONE
+     REAL(rstd)     ::cross_product(3)
+     REAL(rstd),INTENT(IN) :: V1(3)
+     REAL(rstd),INTENT(IN) :: V2(3)
+    
+     cross_product(1)=V1(2)*V2(3)-V1(3)*V2(2)
+     cross_product(2)=V1(3)*V2(1)-V1(1)*V2(3)
+     cross_product(3)=V1(1)*V2(2)-V1(2)*V2(1)
+     
+    END FUNCTION cross_product
+
+
+   SUBROUTINE cross_product2(V1,V2,cross_product)
+   IMPLICIT NONE
+     REAL(rstd),INTENT(OUT):: cross_product(3)
+     REAL(rstd),INTENT(IN) :: V1(3)
+     REAL(rstd),INTENT(IN) :: V2(3)
+    
+     cross_product(1)=V1(2)*V2(3)-V1(3)*V2(2)
+     cross_product(2)=V1(3)*V2(1)-V1(1)*V2(3)
+     cross_product(3)=V1(1)*V2(2)-V1(2)*V2(1)
+     
+    END SUBROUTINE cross_product2
+
+    FUNCTION arc(lon,lat, lonc,latc)
+      REAL(rstd) :: lon,lat, lonc,latc, arc
+      arc=ACOS(sin(latc)*sin(lat)+cos(latc)*cos(lat)*cos(lon-lonc))
+    END FUNCTION arc
+
+END MODULE vector
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vertical_interp.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vertical_interp.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vertical_interp.f90	(revision 329)
@@ -0,0 +1,76 @@
+MODULE vertical_interp_mod
+  USE icosa
+  PRIVATE
+  
+  TYPE(t_field),SAVE, POINTER :: f_p(:)
+  
+
+  PUBLIC init_vertical_interp, vertical_interp, compute_vertical_interp
+
+CONTAINS
+
+  SUBROUTINE init_vertical_interp
+  USE icosa
+  IMPLICIT NONE
+    
+    CALL allocate_field(f_p,field_t,type_real,llm+1)
+    
+  END SUBROUTINE init_vertical_interp
+    
+  SUBROUTINE vertical_interp(f_ps,f_in,f_out,pval)
+  USE icosa
+  USE pression_mod
+  IMPLICIT NONE
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_in(:)
+    TYPE(t_field),POINTER :: f_out(:)
+    REAL(rstd),INTENT(IN) :: pval
+
+    REAL(rstd),POINTER :: in(:,:)
+    REAL(rstd),POINTER :: out(:)
+    REAL(rstd),POINTER :: p(:,:)
+    
+    INTEGER :: ind
+        
+    CALL pression(f_ps,f_p)
+ 
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      p=f_p(ind)
+      in=f_in(ind)
+      out=f_out(ind)
+      CALL compute_vertical_interp(p,in,out,pval)
+    ENDDO
+    
+  END SUBROUTINE  vertical_interp
+
+  SUBROUTINE compute_vertical_interp(p,in,out,pval)
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN) :: p(iim*jjm,llm+1)
+    REAL(rstd),INTENT(IN) :: in(iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: out(iim*jjm)
+    REAL(rstd) :: pval
+    REAL(rstd) :: coeff, pmid,pmidp1
+    INTEGER :: i,j,ij,l
+        
+    DO j=jj_begin-1,jj_end+1
+      DO i=ii_begin-1,ii_end+1
+        ij=(j-1)*iim+i
+        l=llm-1
+        DO WHILE(0.5*(p(ij,l)+p(ij,l+1))<pval .AND. l>1)
+          l=l-1
+        ENDDO
+        pmid=0.5*(p(ij,l)+p(ij,l+1))
+        pmidp1=0.5*(p(ij,l+1)+p(ij,l+2))
+
+        coeff=(pval-pmid)/(pmid-pmidp1)
+        
+        out(ij)=in(ij,l)+coeff*(in(ij,l)-in(ij,l+1))
+      ENDDO
+    ENDDO
+        
+  END SUBROUTINE compute_vertical_interp
+
+END MODULE vertical_interp_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vorticity.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vorticity.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/vorticity.f90	(revision 329)
@@ -0,0 +1,55 @@
+MODULE vorticity_mod
+
+CONTAINS
+
+  SUBROUTINE vorticity(f_ue,f_vort)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ue(:)
+    TYPE(t_field), POINTER :: f_vort(:)
+  
+    REAL(rstd), POINTER :: ue(:,:)
+    REAL(rstd), POINTER :: vort(:,:)
+    INTEGER :: ind
+
+    CALL transfert_request(f_ue,req_e1_vect)
+   
+    DO ind=1,ndomain
+      IF (.NOT. assigned_domain(ind)) CYCLE
+      CALL swap_dimensions(ind)
+      CALL swap_geometry(ind)
+      ue=f_ue(ind)
+      vort=f_vort(ind)
+      CALL compute_vorticity(ue, vort)
+    ENDDO
+  
+  END SUBROUTINE vorticity
+  
+  SUBROUTINE compute_vorticity(ue,vort)
+  USE icosa
+  USE disvert_mod
+  IMPLICIT NONE
+    REAL(rstd),INTENT(IN)  :: ue(3*iim*jjm,llm)
+    REAL(rstd),INTENT(OUT) :: vort(2*iim*jjm,llm)
+    INTEGER :: i,j,ij,l
+
+    DO l = 1,llm
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+        
+           vort(ij+z_up,l) = 1./Av(ij+z_up)*(  ne(ij,rup)        * ue(ij+u_rup,l)        * de(ij+u_rup)         &
+                                + ne(ij+t_rup,left) * ue(ij+t_rup+u_left,l) * de(ij+t_rup+u_left)               &
+                                - ne(ij,lup)        * ue(ij+u_lup,l)        * de(ij+u_lup) )                               
+
+           vort(ij+z_down,l) = 1./Av(ij+z_down)*(  ne(ij,ldown)         * ue(ij+u_ldown,l)         * de(ij+u_ldown)          &
+                                   + ne(ij+t_ldown,right) * ue(ij+t_ldown+u_right,l) * de(ij+t_ldown+u_right)                &
+                                   - ne(ij,rdown)         * ue(ij+u_rdown,l)          * de(ij+u_rdown) )
+
+        ENDDO
+      ENDDO
+    ENDDO
+    
+  END SUBROUTINE compute_vorticity
+
+END MODULE vorticity_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/wind.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/wind.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/wind.f90	(revision 329)
@@ -0,0 +1,399 @@
+MODULE wind_mod
+
+CONTAINS
+
+  SUBROUTINE un2ulonlat(f_u, f_ulon, f_ulat)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_u(:) ! IN  : normal velocity components on edges
+    TYPE(t_field), POINTER :: f_ulon(:), f_ulat(:) ! OUT : velocity reconstructed at hexagons
+    
+    REAL(rstd),POINTER :: u(:,:),  ulon(:,:), ulat(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       u=f_u(ind)
+       ulon=f_ulon(ind)
+       ulat=f_ulat(ind)
+       CALL compute_un2ulonlat(u,ulon, ulat)
+    END DO
+
+  END SUBROUTINE un2ulonlat
+
+  SUBROUTINE ulonlat2un(f_ulon, f_ulat,f_u)
+  USE icosa
+  IMPLICIT NONE
+    TYPE(t_field), POINTER :: f_ulon(:), f_ulat(:) ! IN : velocity reconstructed at hexagons
+    TYPE(t_field), POINTER :: f_u(:) ! OUT  : normal velocity components on edges
+    
+    REAL(rstd),POINTER :: u(:,:),  ulon(:,:), ulat(:,:)
+    INTEGER :: ind
+
+    DO ind=1,ndomain
+       IF (.NOT. assigned_domain(ind)) CYCLE
+       CALL swap_dimensions(ind)
+       CALL swap_geometry(ind)
+       u=f_u(ind)
+       ulon=f_ulon(ind)
+       ulat=f_ulat(ind)
+       CALL compute_ulonlat2un(ulon, ulat,u)
+    END DO
+
+  END SUBROUTINE ulonlat2un
+ 
+  SUBROUTINE compute_wind_centered(ue,ucenter)
+  USE icosa
+  
+  IMPLICIT NONE
+  REAL(rstd) :: ue(3*iim*jjm,llm)
+  REAL(rstd) :: ucenter(iim*jjm,3,llm)
+  INTEGER :: i,j,ij,l    
+ 
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          ucenter(ij,:,l)=1/Ai(ij)*                                                                                                &
+                        ( ne(ij,right)*ue(ij+u_right,l)*le(ij+u_right)*((xyz_v(ij+z_rdown,:)+xyz_v(ij+z_rup,:))/2-centroid(ij,:))  &
+                         + ne(ij,rup)*ue(ij+u_rup,l)*le(ij+u_rup)*((xyz_v(ij+z_rup,:)+xyz_v(ij+z_up,:))/2-centroid(ij,:))          &
+                         + ne(ij,lup)*ue(ij+u_lup,l)*le(ij+u_lup)*((xyz_v(ij+z_up,:)+xyz_v(ij+z_lup,:))/2-centroid(ij,:))          &
+                         + ne(ij,left)*ue(ij+u_left,l)*le(ij+u_left)*((xyz_v(ij+z_lup,:)+xyz_v(ij+z_ldown,:))/2-centroid(ij,:))    &
+                         + ne(ij,ldown)*ue(ij+u_ldown,l)*le(ij+u_ldown)*((xyz_v(ij+z_ldown,:)+xyz_v(ij+z_down,:))/2-centroid(ij,:))&
+                         + ne(ij,rdown)*ue(ij+u_rdown,l)*le(ij+u_rdown)*((xyz_v(ij+z_down,:)+xyz_v(ij+z_rdown,:))/2-centroid(ij,:)))
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+ END SUBROUTINE compute_wind_centered
+ 
+  
+ SUBROUTINE compute_wind_on_edge(ue,uedge)
+  USE icosa
+    
+  IMPLICIT NONE
+  REAL(rstd) :: ue(3*iim*jjm,llm)
+  REAL(rstd) :: uedge(3*iim*jjm,3,llm)
+
+  REAL(rstd) :: ut(3*iim*jjm,llm)
+  INTEGER :: i,j,ij,l     
+    
+    CALL compute_tangential_compound(ue,ut)
+  
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          uedge(ij+u_right,:,l)=ue(ij+u_right,l)*ep_e(ij+u_right,:)*ne(ij,right) + ut(ij+u_right,l)*et_e(ij+u_right,:)*ne(ij,right) 
+          uedge(ij+u_lup,:,l)=ue(ij+u_lup,l)*ep_e(ij+u_lup,:)*ne(ij,lup) + ut(ij+u_lup,l)*et_e(ij+u_lup,:)*ne(ij,lup)
+          uedge(ij+u_ldown,:,l)=ue(ij+u_ldown,l)*ep_e(ij+u_ldown,:)*ne(ij,ldown) + ut(ij+u_ldown,l)*et_e(ij+u_ldown,:)*ne(ij,ldown)
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+ END SUBROUTINE compute_wind_on_edge
+ 
+ 
+ 
+ SUBROUTINE compute_tangential_compound(ue,ut)
+  USE icosa  
+  IMPLICIT NONE
+  REAL(rstd) :: ue(3*iim*jjm,llm)
+  REAL(rstd) :: ut(3*iim*jjm,llm)
+  INTEGER :: i,j,l,ij
+    
+  DO l=1,llm
+    DO j=jj_begin,jj_end
+      DO i=ii_begin,ii_end
+        ij=(j-1)*iim+i
+   
+        ut(ij+u_right,l) = 1/de(ij+u_right) *                                            &  
+                         ( wee(ij+u_right,1,1)*ue(ij+u_rup,l)+                           &
+                           wee(ij+u_right,2,1)*ue(ij+u_lup,l)+                           &
+                           wee(ij+u_right,3,1)*ue(ij+u_left,l)+                          &
+                           wee(ij+u_right,4,1)*ue(ij+u_ldown,l)+                         &
+                           wee(ij+u_right,5,1)*ue(ij+u_rdown,l)+                         & 
+                           wee(ij+u_right,1,2)*ue(ij+t_right+u_ldown,l)+                 &
+                           wee(ij+u_right,2,2)*ue(ij+t_right+u_rdown,l)+                 &
+                           wee(ij+u_right,3,2)*ue(ij+t_right+u_right,l)+                 &
+                           wee(ij+u_right,4,2)*ue(ij+t_right+u_rup,l)+                   &
+                           wee(ij+u_right,5,2)*ue(ij+t_right+u_lup,l) )   
+     
+        ut(ij+u_lup,l) =  1/de(ij+u_lup) *                                           &  
+                         ( wee(ij+u_lup,1,1)*ue(ij+u_left,l)+                        &
+                           wee(ij+u_lup,2,1)*ue(ij+u_ldown,l)+                       &
+                           wee(ij+u_lup,3,1)*ue(ij+u_rdown,l)+                       &
+                           wee(ij+u_lup,4,1)*ue(ij+u_right,l)+                       &
+                           wee(ij+u_lup,5,1)*ue(ij+u_rup,l)+                         & 
+                           wee(ij+u_lup,1,2)*ue(ij+t_lup+u_right,l)+                 &
+                           wee(ij+u_lup,2,2)*ue(ij+t_lup+u_rup,l)+                   &
+                           wee(ij+u_lup,3,2)*ue(ij+t_lup+u_lup,l)+                   &
+                           wee(ij+u_lup,4,2)*ue(ij+t_lup+u_left,l)+                  &
+                           wee(ij+u_lup,5,2)*ue(ij+t_lup+u_ldown,l) )
+
+    
+        ut(ij+u_ldown,l) = 1/de(ij+u_ldown) *   &  
+                         ( wee(ij+u_ldown,1,1)*ue(ij+u_rdown,l)+                      &
+                           wee(ij+u_ldown,2,1)*ue(ij+u_right,l)+                      &
+                           wee(ij+u_ldown,3,1)*ue(ij+u_rup,l)+                        &
+                           wee(ij+u_ldown,4,1)*ue(ij+u_lup,l)+                        &
+                           wee(ij+u_ldown,5,1)*ue(ij+u_left,l)+                       & 
+                           wee(ij+u_ldown,1,2)*ue(ij+t_ldown+u_lup,l)+                &
+                           wee(ij+u_ldown,2,2)*ue(ij+t_ldown+u_left,l)+               &
+                           wee(ij+u_ldown,3,2)*ue(ij+t_ldown+u_ldown,l)+              &
+                           wee(ij+u_ldown,4,2)*ue(ij+t_ldown+u_rdown,l)+              &
+                           wee(ij+u_ldown,5,2)*ue(ij+t_ldown+u_right,l) )  
+        
+        ENDDO
+      ENDDO
+    ENDDO
+                        
+ END SUBROUTINE compute_tangential_compound
+ 
+ SUBROUTINE compute_wind_lonlat_compound(u, ulon, ulat)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: u(3*iim*jjm,3,llm)
+  REAL(rstd) :: ulon(3*iim*jjm,3,llm)
+  REAL(rstd) :: ulat(3*iim*jjm,3,llm)
+
+  INTEGER :: i,j,ij,l     
+    
+  
+    DO l=1,llm
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+          ulon(ij+u_right,:,l)=sum(u(ij+u_right,:,l)*elon_e(ij+u_right,:))*elon_e(ij+u_right,:) 
+          ulon(ij+u_lup,:,l)=sum(u(ij+u_lup,:,l)*elon_e(ij+u_lup,:))*elon_e(ij+u_lup,:)
+          ulon(ij+u_ldown,:,l)=sum(u(ij+u_ldown,:,l)*elon_e(ij+u_ldown,:))*elon_e(ij+u_ldown,:)
+          
+          ulat(ij+u_right,:,l)=sum(u(ij+u_right,:,l)*elat_e(ij+u_right,:))*elat_e(ij+u_right,:) 
+          ulat(ij+u_lup,:,l)=sum(u(ij+u_lup,:,l)*elat_e(ij+u_lup,:))*elat_e(ij+u_lup,:) 
+          ulat(ij+u_ldown,:,l)=sum(u(ij+u_ldown,:,l)*elat_e(ij+u_ldown,:))*elat_e(ij+u_ldown,:) 
+          
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+ END SUBROUTINE compute_wind_lonlat_compound
+ 
+  SUBROUTINE compute_wind_from_lonlat_compound(ulon, ulat, u)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: u(3*iim*jjm,3,llm)
+  REAL(rstd) :: ulon(3*iim*jjm,llm)
+  REAL(rstd) :: ulat(3*iim*jjm,llm)
+
+  INTEGER :: i,j,ij,l     
+  
+    DO l=1,llm
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+          u(ij+u_right,:,l)=ulon(ij+u_right,l)*elon_e(ij+u_right,:)+ ulat(ij+u_right,l)*elat_e(ij+u_right,:)
+          u(ij+u_lup,:,l)=ulon(ij+u_lup,l)*elon_e(ij+u_lup,:) + ulat(ij+u_lup,l)*elat_e(ij+u_lup,:)
+          u(ij+u_ldown,:,l)=ulon(ij+u_ldown,l)*elon_e(ij+u_ldown,:) + ulat(ij+u_ldown,l)*elat_e(ij+u_ldown,:)
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+  END SUBROUTINE compute_wind_from_lonlat_compound
+ 
+  SUBROUTINE compute_wind_centered_from_lonlat_compound(ulon, ulat, u)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: u(iim*jjm,3,llm)
+  REAL(rstd) :: ulon(iim*jjm,llm)
+  REAL(rstd) :: ulat(iim*jjm,llm)
+
+  INTEGER :: i,j,ij,l     
+  DO l=1,llm
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+          u(ij,:,l)=ulon(ij,l)*elon_i(ij,:)+ ulat(ij,l)*elat_i(ij,:)
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+  END SUBROUTINE compute_wind_centered_from_lonlat_compound
+ 
+  SUBROUTINE compute_wind2D_from_lonlat_compound(ulon, ulat, u)
+  USE icosa  
+  
+  IMPLICIT NONE
+  REAL(rstd) :: u(3*iim*jjm,3)
+  REAL(rstd) :: ulon(3*iim*jjm)
+  REAL(rstd) :: ulat(3*iim*jjm)
+  
+  INTEGER :: i,j,ij
+  
+  DO j=jj_begin-1,jj_end+1
+     DO i=ii_begin-1,ii_end+1
+        ij=(j-1)*iim+i
+        u(ij+u_right,:)=ulon(ij+u_right)*elon_e(ij+u_right,:)+ ulat(ij+u_right)*elat_e(ij+u_right,:)
+        u(ij+u_lup,:)=ulon(ij+u_lup)*elon_e(ij+u_lup,:) + ulat(ij+u_lup)*elat_e(ij+u_lup,:)
+        u(ij+u_ldown,:)=ulon(ij+u_ldown)*elon_e(ij+u_ldown,:) + ulat(ij+u_ldown)*elat_e(ij+u_ldown,:)
+     ENDDO
+  ENDDO
+    
+  END SUBROUTINE compute_wind2D_from_lonlat_compound
+ 
+  SUBROUTINE compute_wind_perp_from_lonlat_compound(ulon, ulat, up)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: up(3*iim*jjm,llm)
+  REAL(rstd) :: ulon(3*iim*jjm,llm)
+  REAL(rstd) :: ulat(3*iim*jjm,llm)
+  REAL(rstd) :: u(3*iim*jjm,3,llm)
+
+  INTEGER :: i,j,ij,l     
+  
+   CALL compute_wind_from_lonlat_compound(ulon, ulat, u)
+
+    DO l=1,llm
+      DO j=jj_begin-1,jj_end+1
+        DO i=ii_begin-1,ii_end+1
+          ij=(j-1)*iim+i
+          up(ij+u_right,l)=sum(u(ij+u_right,:,l)*ep_e(ij+u_right,:))
+          up(ij+u_lup,l)=sum(u(ij+u_lup,:,l)*ep_e(ij+u_lup,:))
+          up(ij+u_ldown,l)=sum(u(ij+u_ldown,:,l)*ep_e(ij+u_ldown,:))
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+  END SUBROUTINE compute_wind_perp_from_lonlat_compound
+   
+  SUBROUTINE compute_wind2D_perp_from_lonlat_compound(ulon, ulat, up)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: up(3*iim*jjm)
+  REAL(rstd) :: ulon(3*iim*jjm)
+  REAL(rstd) :: ulat(3*iim*jjm)
+  REAL(rstd) :: u(3*iim*jjm,3)
+
+  INTEGER :: i,j,ij 
+  
+  CALL compute_wind2D_from_lonlat_compound(ulon, ulat, u)
+  DO j=jj_begin-1,jj_end+1
+     DO i=ii_begin-1,ii_end+1
+        ij=(j-1)*iim+i
+        up(ij+u_right)=sum(u(ij+u_right,:)*ep_e(ij+u_right,:))
+        up(ij+u_lup)=sum(u(ij+u_lup,:)*ep_e(ij+u_lup,:))
+        up(ij+u_ldown)=sum(u(ij+u_ldown,:)*ep_e(ij+u_ldown,:))
+     ENDDO
+  ENDDO
+   
+  END SUBROUTINE compute_wind2D_perp_from_lonlat_compound
+   
+ SUBROUTINE compute_wind_centered_lonlat_compound(uc, ulon, ulat)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: uc(iim*jjm,3,llm)
+  REAL(rstd) :: ulon(iim*jjm,llm)
+  REAL(rstd) :: ulat(iim*jjm,llm)
+
+  INTEGER :: i,j,ij,l     
+    
+  
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          ulon(ij,l)=sum(uc(ij,:,l)*elon_i(ij,:))
+          ulat(ij,l)=sum(uc(ij,:,l)*elat_i(ij,:)) 
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+ END SUBROUTINE compute_wind_centered_lonlat_compound
+
+ SUBROUTINE compute_wind_centered_from_wind_lonlat_centered(ulon, ulat,uc)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd) :: ulon(iim*jjm,llm)
+  REAL(rstd) :: ulat(iim*jjm,llm)
+  REAL(rstd) :: uc(iim*jjm,3,llm)
+
+  INTEGER :: i,j,ij,l     
+    
+  
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          uc(ij,:,l)=ulon(ij,l)*elon_i(ij,:)+ulat(ij,l)*elat_i(ij,:)
+        ENDDO
+      ENDDO
+    ENDDO
+ 
+ END SUBROUTINE compute_wind_centered_from_wind_lonlat_centered
+
+
+
+ SUBROUTINE compute_wind_perp_from_wind_centered(uc,un)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd),INTENT(IN)   :: uc(iim*jjm,3,llm)
+  REAL(rstd),INTENT(OUT)  :: un(3*iim*jjm,llm)
+
+  INTEGER :: i,j,ij,l     
+    
+  
+    DO l=1,llm
+      DO j=jj_begin,jj_end
+        DO i=ii_begin,ii_end
+          ij=(j-1)*iim+i
+          un(ij+u_right,l) = sum(0.5*(uc(ij,:,l) + uc(ij+t_right,:,l))*ep_e(ij+u_right,:))
+          un(ij+u_lup,l) = sum(0.5*(uc(ij,:,l) + uc(ij+t_lup,:,l))*ep_e(ij+u_lup,:))
+          un(ij+u_ldown,l) = sum(0.5*(uc(ij,:,l) + uc(ij+t_ldown,:,l))*ep_e(ij+u_ldown,:))
+         ENDDO
+      ENDDO
+    ENDDO
+ 
+ END SUBROUTINE compute_wind_perp_from_wind_centered
+
+
+ SUBROUTINE compute_un2ulonlat(un, ulon, ulat)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd),INTENT(IN)  :: un(3*iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: ulon(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT) :: ulat(iim*jjm,llm)
+
+  REAL(rstd)             :: uc(iim*jjm,3,llm)
+    
+  CALL compute_wind_centered(un,uc)  
+  CALL compute_wind_centered_lonlat_compound(uc, ulon, ulat)
+ 
+ END SUBROUTINE compute_un2ulonlat
+
+ SUBROUTINE compute_ulonlat2un(ulon, ulat,un)
+  USE icosa  
+    
+  IMPLICIT NONE
+  REAL(rstd),INTENT(IN) :: ulon(iim*jjm,llm)
+  REAL(rstd),INTENT(IN) :: ulat(iim*jjm,llm)
+  REAL(rstd),INTENT(OUT)  :: un(3*iim*jjm,llm)
+
+  REAL(rstd)             :: uc(iim*jjm,3,llm)
+    
+    CALL compute_wind_centered_from_wind_lonlat_centered(ulon, ulat, uc)  
+    CALL compute_wind_perp_from_wind_centered(uc, un)
+ 
+ END SUBROUTINE compute_ulonlat2un
+
+
+END MODULE wind_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/write_etat0.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/write_etat0.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/write_etat0.f90	(revision 329)
@@ -0,0 +1,37 @@
+MODULE write_etat0_mod
+
+
+
+CONTAINS
+
+  SUBROUTINE write_etat0(it,f_ps,f_phis,f_theta_rhodz,f_u, f_q)
+  USE icosa
+  USE restart_mod
+  USE wind_mod
+  USE write_field
+  IMPLICIT NONE
+    INTEGER,INTENT(IN)    :: it
+    TYPE(t_field),POINTER :: f_ps(:)
+    TYPE(t_field),POINTER :: f_phis(:)
+    TYPE(t_field),POINTER :: f_theta_rhodz(:)
+    TYPE(t_field),POINTER :: f_u(:)
+    TYPE(t_field),POINTER :: f_q(:)
+  
+    TYPE(t_field),POINTER,SAVE :: f_ulon(:)
+    TYPE(t_field),POINTER,SAVE :: f_ulat(:)
+    
+    
+    CALL allocate_field(f_ulon,field_t,type_real,llm,name='ulon')
+    CALL allocate_field(f_ulat,field_t,type_real,llm,name='ulat')
+
+    CALL transfert_request(f_u,req_e1_vect)
+    CALL un2ulonlat(f_u, f_ulon, f_ulat)
+    
+    CALL write_restart(it,f_ps,f_phis,f_theta_rhodz,f_u, f_ulon, f_ulat, f_q)
+
+    CALL deallocate_field(f_ulon)
+    CALL deallocate_field(f_ulat)
+    
+  END SUBROUTINE write_etat0
+    
+END MODULE write_etat0_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/write_field.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/write_field.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/write_field.f90	(revision 329)
@@ -0,0 +1,1802 @@
+module write_field
+USE genmod
+implicit none
+  PRIVATE  
+  INTEGER,SAVE :: ncprec
+  
+  TYPE ncvar
+    INTEGER :: size
+    INTEGER,POINTER :: nc_id(:)
+    INTEGER :: displ
+  END TYPE ncvar
+
+  INTEGER, PARAMETER :: MaxWriteField = 1000
+  INTEGER, DIMENSION(MaxWriteField),SAVE :: FieldId
+  TYPE(ncvar), dimension(MaxWriteField),SAVE :: FieldVarId
+  INTEGER, DIMENSION(MaxWriteField),SAVE :: FieldIndex
+  CHARACTER(len=255), DIMENSION(MaxWriteField) ::  FieldName 
+   
+  INTEGER,SAVE :: NbField = 0
+  
+  PUBLIC init_writeField, writefield, close_files
+  
+  CONTAINS
+  
+    SUBROUTINE init_writeField
+    USE ioipsl
+    use netcdf_mod
+    IMPLICIT NONE
+      CHARACTER(LEN=255) :: netcdf_prec
+      
+      netcdf_prec='float'
+      CALL getin("netcdf_prec",netcdf_prec)
+      
+      SELECT CASE(TRIM(netcdf_prec))
+        CASE('float')
+          ncprec=NF90_FLOAT
+        CASE('double')
+          ncprec=NF90_DOUBLE
+        CASE default
+        PRINT*,'Bad selector for variable netcdf_prec : <', TRIM(netcdf_prec),"> options are <float>, <double>" 
+        STOP   
+      END SELECT
+    END SUBROUTINE init_writeField
+    
+    function GetFieldIndex(name)
+    implicit none
+      integer          :: GetFieldindex
+      character(len=*) :: name
+    
+      character(len=255) :: TrueName
+      integer            :: i
+       
+      
+      TrueName=TRIM(ADJUSTL(name))
+    
+      GetFieldIndex=-1
+      do i=1,NbField
+        if (TrueName==FieldName(i)) then
+          GetFieldIndex=i
+          exit
+        endif
+      enddo
+    end function GetFieldIndex
+    
+    SUBROUTINE Writefield(name_in,field,nind,once)
+    USE domain_mod
+    USE field_mod
+    USE transfert_mpi_mod
+    USE dimensions
+    USE mpipara
+    IMPLICIT NONE  
+     CHARACTER(LEN=*),INTENT(IN) :: name_in
+      TYPE(t_field),POINTER :: field(:)
+      INTEGER,OPTIONAL,INTENT(IN) :: nind
+      LOGICAL,OPTIONAL,INTENT(IN) :: once
+      LOGICAL                     :: once_
+      
+      TYPE(t_field),POINTER :: field_glo(:)
+
+!$OMP BARRIER
+!$OMP MASTER      
+      IF(PRESENT(once)) THEN
+         once_=once
+      ELSE
+         once_=.FALSE.
+      END IF
+
+      IF (field(1)%ndim==2) THEN
+        CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type)
+      ELSE IF (field(1)%ndim==3) THEN
+        CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,field(1)%dim3) 
+      ELSE IF (field(1)%ndim==4) THEN
+        CALL allocate_field_glo(field_glo,field(1)%field_type,field(1)%data_type,field(1)%dim3,field(1)%dim4)
+      ENDIF
+      
+      CALL gather_field(field,field_glo)
+      
+      IF (mpi_rank==0) THEN
+        IF (PRESENT(nind)) THEN
+         CALL writefield_gen(name_in,field_glo,domain_glo,nind,once=once_)
+        ELSE
+         CALL writefield_gen(name_in,field_glo,domain_glo,1,ndomain_glo,once=once_)
+        ENDIF
+      ENDIF
+      
+      CALL deallocate_field_glo(field_glo)
+!$OMP END MASTER
+!$OMP BARRIER
+      
+   END SUBROUTINE writefield
+   
+!   SUBROUTINE Writefield(name_in,field,nind)
+!   USE netcdf
+!   USE domain_mod
+!   use field_mod
+!   USE dimensions
+!   USE geometry
+!   IMPLICIT NONE
+!     CHARACTER(LEN=*),INTENT(IN) :: name_in
+!     TYPE(t_field),POINTER :: field(:)
+!     INTEGER,OPTIONAL,INTENT(IN) :: nind
+!     REAL(r8),ALLOCATABLE :: field_val2d(:)
+!     REAL(r8),ALLOCATABLE :: field_val3d(:,:)
+!     REAL(r8),ALLOCATABLE :: field_val4d(:,:,:)
+!     TYPE(t_domain),POINTER :: d
+!     INTEGER :: Index
+!     INTEGER :: ind,i,j,k,n,ncell,q
+!     INTEGER :: iie,jje,iin,jjn
+!     INTEGER :: status
+!     CHARACTER(len=255) :: name
+!     CHARACTER(len=255) :: str_ind
+!     INTEGER :: ind_b,ind_e
+!     INTEGER :: halo_size
+!     LOGICAL :: single
+!     
+!     
+!     name=TRIM(ADJUSTL(name_in))
+
+!     IF (PRESENT(nind)) THEN
+!       name=TRIM(name)//"_"//TRIM(int2str(nind))
+!       PRINT *,"NAME",nind,int2str(nind),name
+!       ind_b=nind
+!       ind_e=nind
+!       halo_size=1
+!       single=.TRUE.
+!     ELSE
+!       ind_b=1
+!       ind_e=ndomain
+!       halo_size=0
+!       single=.FALSE.
+!     ENDIF      
+
+!     Index=GetFieldIndex(name)
+!     if (Index==-1) then
+!       call create_header(name,field,nind)
+!	Index=GetFieldIndex(name)
+!     else
+!       FieldIndex(Index)=FieldIndex(Index)+1.
+!     endif
+!     
+!     IF (Field(ind_b)%field_type==field_T) THEN
+!       ncell=1
+!       DO ind=ind_b,ind_e
+!         d=>domain(ind)
+!         IF (Field(ind)%field_type/=field_T) THEN
+!           PRINT *,"Writefield, grille non geree"
+!           RETURN
+!         ENDIF
+
+!       n=0
+!       DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!         DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!           IF (d%own(i,j) .OR. single) n=n+1
+!         ENDDO
+!       ENDDO
+
+!       IF (field(ind)%ndim==2) THEN
+!         ALLOCATE(Field_val2d(n))
+!         n=0
+!         DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!           DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!             k=d%iim*(j-1)+i
+!             IF (d%own(i,j) .OR. single) THEN
+!               n=n+1
+!               Field_val2d(n)=field(ind)%rval2d(k)
+!             ENDIF
+!           ENDDO
+!         ENDDO
+!         status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val2d,  &
+!                             start=(/ ncell,FieldIndex(Index) /),count=(/n,1 /))
+!         DEALLOCATE(field_val2d)
+!       ELSE IF (field(ind)%ndim==3) THEN
+!         ALLOCATE(Field_val3d(n,size(field(ind)%rval3d,2)))
+!         n=0
+!         DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!           DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!             k=d%iim*(j-1)+i
+!             IF (d%own(i,j) .OR. single) THEN
+!               n=n+1
+!               Field_val3d(n,:)=field(ind)%rval3d(k,:)
+!             ENDIF
+!           ENDDO
+!         ENDDO
+!          status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,start=(/ ncell,1,FieldIndex(Index) /),   &
+!                              count=(/n,size(field(1)%rval3d,2),1 /))
+!         DEALLOCATE(field_val3d)
+!       ELSE IF (field(1)%ndim==4) THEN
+
+!         DO q=1,FieldVarId(index)%size
+!         
+!           ALLOCATE(Field_val3d(n,size(field(ind)%rval4d,2)))
+!           n=0
+!           DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!             DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!               k=d%iim*(j-1)+i
+!               IF (d%own(i,j) .OR. single) THEN
+!                 n=n+1
+!                 Field_val3d(n,:)=field(ind)%rval4d(k,:,q)
+!               ENDIF
+!             ENDDO
+!           ENDDO
+!           status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,start=(/ ncell,1,FieldIndex(Index) /),   &
+!                              count=(/n,size(field(1)%rval4d,2),1 /))
+!           DEALLOCATE(field_val3d)
+!         ENDDO         
+!       ENDIF
+!       
+!        PRINT *,NF90_STRERROR(status)
+!       ncell=ncell+n
+
+!    ENDDO
+!    
+!    ELSE IF (Field(ind_b)%field_type==field_Z) THEN
+!       ncell=1
+!       n=0
+!       DO ind=ind_b,ind_e
+!         d=>domain(ind)
+!         CALL swap_geometry(ind)
+!         CALL swap_dimensions(ind)
+! 
+!         n=0
+!         DO j=jj_begin+1,jj_end
+!           DO i=ii_begin,ii_end-1
+!             n=n+1
+!           ENDDO
+!         ENDDO
+
+!         DO j=jj_begin,jj_end-1
+!           DO i=ii_begin+1,ii_end
+!             n=n+1
+!           ENDDO
+!         ENDDO
+
+!       IF (field(ind)%ndim==2) THEN
+!         ALLOCATE(Field_val2d(n))
+
+!         n=0
+!         DO j=jj_begin+1,jj_end
+!           DO i=ii_begin,ii_end-1
+!             n=n+1
+!             k=iim*(j-1)+i
+!             Field_val2d(n)=field(ind)%rval2d(k+z_down)
+!           ENDDO
+!         ENDDO
+
+!         DO j=jj_begin,jj_end-1
+!           DO i=ii_begin+1,ii_end
+!             n=n+1
+!             k=iim*(j-1)+i
+!             Field_val2d(n)=field(ind)%rval2d(k+z_up)
+!           ENDDO
+!         ENDDO
+
+!         status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),                       &
+!                             Field_val2d,start=(/ ncell,FieldIndex(Index) /),count=(/n,1 /))
+!         DEALLOCATE(field_val2d)
+
+!       ELSE IF (field(ind)%ndim==3) THEN
+!         ALLOCATE(Field_val3d(n,size(field(ind)%rval3d,2)))
+!         n=0
+!         DO j=jj_begin+1,jj_end
+!           DO i=ii_begin,ii_end-1
+!             n=n+1
+!             k=iim*(j-1)+i
+!             Field_val3d(n,:)=field(ind)%rval3d(k+z_down,:)
+!           ENDDO
+!         ENDDO
+
+!         DO j=jj_begin,jj_end-1
+!           DO i=ii_begin+1,ii_end
+!             n=n+1
+!             k=iim*(j-1)+i
+!             Field_val3d(n,:)=field(ind)%rval3d(k+z_up,:)
+!           ENDDO
+!         ENDDO
+!          status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,start=(/ ncell,1,FieldIndex(Index) /),   &
+!                              count=(/n,size(field(1)%rval3d,2),1 /))
+!         DEALLOCATE(field_val3d)
+!       ELSE IF (field(1)%ndim==4) THEN
+
+!         DO q=1,FieldVarId(index)%size
+!           ALLOCATE(Field_val3d(n,size(field(ind)%rval4d,2)))
+!           n=0
+!           DO j=jj_begin+1,jj_end
+!             DO i=ii_begin,ii_end-1
+!               n=n+1
+!               k=iim*(j-1)+i
+!               Field_val3d(n,:)=field(ind)%rval4d(k+z_down,:,q)
+!             ENDDO
+!           ENDDO
+
+!           DO j=jj_begin,jj_end-1
+!             DO i=ii_begin+1,ii_end
+!               n=n+1
+!               k=iim*(j-1)+i
+!               Field_val3d(n,:)=field(ind)%rval4d(k+z_up,:,q)
+!             ENDDO
+!           ENDDO
+
+!           status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,start=(/ ncell,1,1,FieldIndex(Index) /),   &
+!                               count=(/n,size(field(1)%rval4d,2),1 /))
+!           DEALLOCATE(field_val3d)
+!         ENDDO
+!       ENDIF
+!       
+!        PRINT *,NF90_STRERROR(status)
+!       ncell=ncell+n
+
+!    ENDDO
+!    
+!    ENDIF
+!    status=NF90_SYNC(FieldId(Index))
+!     
+!   END SUBROUTINE Writefield
+
+
+    SUBROUTINE Writefield_gen(name_in, field, domain_type, ind_b_in, ind_e_in,once )
+    USE netcdf_mod
+    USE domain_mod
+    USE field_mod
+    IMPLICIT NONE
+      CHARACTER(LEN=*),INTENT(IN) :: name_in
+      TYPE(t_field), POINTER :: field(:)
+      TYPE(t_domain),INTENT(IN),TARGET :: domain_type(:)
+      INTEGER,OPTIONAL,INTENT(IN) :: ind_b_in
+      INTEGER,OPTIONAL,INTENT(IN) :: ind_e_in
+      REAL(r8),ALLOCATABLE :: field_val2d(:)
+      REAL(r8),ALLOCATABLE :: field_val3d(:,:)
+      REAL(r8),ALLOCATABLE :: field_val4d(:,:,:)
+      LOGICAL, INTENT(IN) :: once
+      TYPE(t_domain),POINTER :: d
+      INTEGER :: Index
+      INTEGER :: ind,i,j,k,n,ncell,q
+      INTEGER :: iie,jje,iin,jjn
+      INTEGER :: status
+      CHARACTER(len=255) :: name
+      CHARACTER(len=255) :: str_ind
+      INTEGER :: ind_b,ind_e
+      INTEGER :: halo_size
+      LOGICAL :: single
+      
+      name=TRIM(ADJUSTL(name_in))
+
+      IF (PRESENT(ind_b_in) .AND. .NOT. PRESENT(ind_e_in)) THEN
+        name=TRIM(name)//"_"//TRIM(int2str(ind_b))
+        ind_b=ind_b_in
+        ind_e=ind_b_in
+        halo_size=1
+        single=.TRUE.
+      ELSE IF (.NOT. PRESENT(ind_b_in) .AND. PRESENT(ind_e_in)) THEN
+        name=TRIM(name)//"_"//TRIM(int2str(ind_e))
+        ind_b=ind_e_in
+        ind_e=ind_e_in
+        halo_size=1
+        single=.TRUE.
+      ELSE IF ( PRESENT(ind_b_in) .AND. PRESENT(ind_e_in)) THEN
+        ind_b=ind_b_in
+        ind_e=ind_e_in
+        halo_size=0
+        single=.FALSE.
+      ELSE
+        halo_size=0
+        ind_b=1
+        ind_e=ndomain
+        single=.FALSE.
+      ENDIF      
+      
+      Index=GetFieldIndex(name)
+      if (Index==-1) then
+        call create_header_gen(name_in,field,domain_type,ind_b_in,ind_e_in,once)
+	Index=GetFieldIndex(name)
+      else
+        FieldIndex(Index)=FieldIndex(Index)+1.
+      endif
+      
+      IF (Field(ind_b)%field_type==field_T) THEN
+
+        ncell=0
+        DO ind=ind_b,ind_e
+          d=>domain_type(ind)
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+              IF (d%assign_domain(i,j)==ind .OR. single) ncell=ncell+1
+            ENDDO
+          ENDDO
+        ENDDO
+        
+        IF (field(1)%ndim==2) THEN
+          ALLOCATE(Field_val2d(ncell))
+          n=0
+          DO ind=ind_b,ind_e
+            d=>domain_type(ind)
+            DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+              DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+                k=d%iim*(j-1)+i
+                IF (d%assign_domain(i,j)==ind .OR. single) THEN
+                  n=n+1
+                  Field_val2d(n)=field(ind)%rval2d(k)
+                ENDIF
+              ENDDO
+            ENDDO
+          ENDDO
+
+          IF (once) THEN 
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val2d,  &
+                               start=(/ 1 /),count=(/ncell /))
+          ELSE
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val2d,  &
+                               start=(/ 1,FieldIndex(Index) /),count=(/ncell,1 /))
+          ENDIF
+          
+          DEALLOCATE(field_val2d)
+        ELSE IF (field(1)%ndim==3) THEN
+          ALLOCATE(Field_val3d(ncell,size(field(1)%rval3d,2)))
+          n=0
+          DO ind=ind_b,ind_e
+            d=>domain_type(ind)
+            DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+              DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+                k=d%iim*(j-1)+i
+                IF (d%assign_domain(i,j)==ind .OR. single) THEN
+                  n=n+1
+                  Field_val3d(n,:)=field(ind)%rval3d(k,:)
+                ENDIF
+              ENDDO
+            ENDDO
+          ENDDO
+
+          PRINT *, 'Writefield ', TRIM(name), MAXVAL(Field_val3d(:,1)), MINVAL(Field_val3d(:,1)) ! FIXME
+
+          IF (once) THEN 
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,start=(/ 1,1 /),   &
+                                 count=(/ncell,size(field(1)%rval3d,2) /))
+          ELSE
+             status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,start=(/ 1,1,FieldIndex(Index) /),   &
+                                 count=(/ncell,size(field(1)%rval3d,2),1 /))
+          ENDIF
+                                
+          DEALLOCATE(field_val3d)
+        ELSE IF (field(1)%ndim==4) THEN
+
+          DO q=1,FieldVarId(index)%size
+          
+            ALLOCATE(Field_val3d(ncell,size(field(1)%rval4d,2)))
+            n=0
+            DO ind=ind_b,ind_e
+              d=>domain_type(ind)
+              DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+                DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+                  k=d%iim*(j-1)+i
+                  IF (d%assign_domain(i,j)==ind .OR. single) THEN
+                    n=n+1
+                    Field_val3d(n,:)=field(ind)%rval4d(k,:,q)
+                  ENDIF
+                ENDDO
+              ENDDO
+            ENDDO
+            
+            IF (once) THEN 
+              status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,start=(/ 1,1 /),   &
+                                 count=(/ncell,size(field(1)%rval4d,2),1 /))
+            ELSE
+              status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,start=(/ 1,1,FieldIndex(Index) /),   &
+                                 count=(/ncell,size(field(1)%rval4d,2),1 /))
+            ENDIF
+            DEALLOCATE(field_val3d)
+          ENDDO         
+        ENDIF
+        
+     
+     ELSE IF (Field(ind_b)%field_type==field_Z) THEN
+
+        ncell=0
+        DO ind=ind_b,ind_e
+          d=>domain_type(ind)
+  
+          DO j=d%jj_begin+1,d%jj_end
+            DO i=d%ii_begin,d%ii_end-1
+              ncell=ncell+1
+            ENDDO
+          ENDDO
+
+          DO j=d%jj_begin,d%jj_end-1
+            DO i=d%ii_begin+1,d%ii_end
+              ncell=ncell+1
+            ENDDO
+          ENDDO
+        ENDDO
+
+        IF (field(1)%ndim==2) THEN
+          ALLOCATE(Field_val2d(ncell))
+
+          n=0
+          
+          DO ind=ind_b,ind_e
+            d=>domain_type(ind)
+            DO j=d%jj_begin+1,d%jj_end
+              DO i=d%ii_begin,d%ii_end-1
+                n=n+1
+                k=d%iim*(j-1)+i
+                Field_val2d(n)=field(ind)%rval2d(k+d%z_down)
+              ENDDO
+            ENDDO
+
+            DO j=d%jj_begin,d%jj_end-1
+              DO i=d%ii_begin+1,d%ii_end
+                n=n+1
+                k=d%iim*(j-1)+i
+                Field_val2d(n)=field(ind)%rval2d(k+d%z_up)
+              ENDDO
+            ENDDO
+          ENDDO
+          
+          IF (once) THEN 
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),                       &
+                                Field_val2d,start=(/ 1 /),count=(/ncell /))
+           ELSE
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),                       &
+                                Field_val2d,start=(/ 1,FieldIndex(Index) /),count=(/ncell,1 /))
+          ENDIF
+          DEALLOCATE(field_val2d)
+
+        ELSE IF (field(1)%ndim==3) THEN
+          ALLOCATE(Field_val3d(ncell,size(field(1)%rval3d,2)))
+          n=0
+          DO ind=ind_b,ind_e
+            d=>domain_type(ind)
+            DO j=d%jj_begin+1,d%jj_end
+              DO i=d%ii_begin,d%ii_end-1
+                n=n+1
+                k=d%iim*(j-1)+i
+                Field_val3d(n,:)=field(ind)%rval3d(k+d%z_down,:)
+              ENDDO
+            ENDDO
+
+            DO j=d%jj_begin,d%jj_end-1
+              DO i=d%ii_begin+1,d%ii_end
+                n=n+1
+                k=d%iim*(j-1)+i
+                Field_val3d(n,:)=field(ind)%rval3d(k+d%z_up,:)
+              ENDDO
+            ENDDO
+          ENDDO
+          
+          IF (once) THEN 
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,start=(/ 1,1 /),   &
+                                count=(/ncell,size(field(1)%rval3d,2) /))
+          ELSE
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,start=(/ 1,1,FieldIndex(Index) /),   &
+                                count=(/ncell,size(field(1)%rval3d,2),1 /))
+          ENDIF
+          DEALLOCATE(field_val3d)
+        
+        ELSE IF (field(1)%ndim==4) THEN
+
+          DO q=1,FieldVarId(index)%size
+            ALLOCATE(Field_val3d(ncell,size(field(1)%rval4d,2)))
+            n=0
+            DO ind=ind_b,ind_e
+              d=>domain_type(ind)
+              DO j=d%jj_begin+1,d%jj_end
+                DO i=d%ii_begin,d%ii_end-1
+                  n=n+1
+                  k=d%iim*(j-1)+i
+                  Field_val3d(n,:)=field(ind)%rval4d(k+d%z_down,:,q)
+                ENDDO
+              ENDDO
+
+              DO j=d%jj_begin,d%jj_end-1
+                DO i=d%ii_begin+1,d%ii_end
+                  n=n+1
+                  k=d%iim*(j-1)+i
+                  Field_val3d(n,:)=field(ind)%rval4d(k+d%z_up,:,q)
+                ENDDO
+              ENDDO
+            ENDDO
+
+            IF (once) THEN 
+              status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,start=(/ 1,1,1 /),   &
+                                  count=(/ncell,size(field(1)%rval4d,2) /))
+            ELSE
+              status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,start=(/ 1,1,1,FieldIndex(Index) /),   &
+                                  count=(/ncell,size(field(1)%rval4d,2),1 /))
+            ENDIF
+            DEALLOCATE(field_val3d)
+          ENDDO
+        ENDIF
+     
+     ENDIF
+     status=NF90_SYNC(FieldId(Index))
+      
+    END SUBROUTINE Writefield_gen
+
+      
+
+    SUBROUTINE Writefield_mpi(name_in,field,nind)
+    USE netcdf_mod
+    USE domain_mod
+    use field_mod
+    USE dimensions
+    USE geometry
+    IMPLICIT NONE
+      CHARACTER(LEN=*),INTENT(IN) :: name_in
+      TYPE(t_field),POINTER :: field(:)
+      INTEGER,OPTIONAL,INTENT(IN) :: nind
+      REAL(r8),ALLOCATABLE :: field_val2d(:)
+      REAL(r8),ALLOCATABLE :: field_val3d(:,:)
+      REAL(r8),ALLOCATABLE :: field_val4d(:,:,:)
+      TYPE(t_domain),POINTER :: d
+      INTEGER :: Index
+      INTEGER :: ind,i,j,l,k,n,ncell,q
+      INTEGER :: iie,jje,iin,jjn
+      INTEGER :: status
+      CHARACTER(len=255) :: name
+      CHARACTER(len=255) :: str_ind
+      INTEGER :: ind_b,ind_e
+      INTEGER :: halo_size
+      LOGICAL :: single
+      INTEGER :: displ
+      
+      
+      name=TRIM(ADJUSTL(name_in))
+
+      IF (PRESENT(nind)) THEN
+        name=TRIM(name)//"_"//TRIM(int2str(nind))
+        PRINT *,"NAME",nind,int2str(nind),name
+        ind_b=nind
+        ind_e=nind
+        halo_size=1
+        single=.TRUE.
+      ELSE
+        ind_b=1
+        ind_e=ndomain
+        halo_size=0
+        single=.FALSE.
+      ENDIF      
+
+      Index=GetFieldIndex(name)
+      if (Index==-1) then
+        call create_header_mpi(name,field,nind)
+	Index=GetFieldIndex(name)
+      else
+        FieldIndex(Index)=FieldIndex(Index)+1.
+      endif
+      
+      IF (Field(ind_b)%field_type==field_T) THEN
+        ncell=1
+        DO ind=ind_b,ind_e
+          d=>domain(ind)
+          IF (Field(ind)%field_type/=field_T) THEN
+            PRINT *,"Writefield, grille non geree"
+            RETURN
+          ENDIF
+
+        n=0
+        DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+          DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+            IF (d%own(i,j) .OR. single) n=n+1
+          ENDDO
+        ENDDO
+
+        displ=FieldVarId(index)%displ
+        
+        IF (field(ind)%ndim==2) THEN
+          ALLOCATE(Field_val2d(n))
+          n=0
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+              k=d%iim*(j-1)+i
+              IF (d%own(i,j) .OR. single) THEN
+                n=n+1
+                Field_val2d(n)=field(ind)%rval2d(k)
+              ENDIF
+            ENDDO
+          ENDDO
+          status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val2d,  &
+                              start=(/ displ+ncell,FieldIndex(Index) /),count=(/n,1 /))
+          DEALLOCATE(field_val2d)
+        ELSE IF (field(ind)%ndim==3) THEN
+          ALLOCATE(Field_val3d(n,size(field(ind)%rval3d,2)))
+          n=0
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+              k=d%iim*(j-1)+i
+              IF (d%own(i,j) .OR. single) THEN
+                n=n+1
+                Field_val3d(n,:)=field(ind)%rval3d(k,:)
+              ENDIF
+            ENDDO
+          ENDDO
+          status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,  &
+                                start=(/ displ+ncell,1,FieldIndex(Index) /), count=(/n,size(field(ind)%rval3d,2),1 /))
+          DEALLOCATE(field_val3d)
+
+        ELSE IF (field(1)%ndim==4) THEN
+
+          DO q=1,FieldVarId(index)%size
+          
+            ALLOCATE(Field_val3d(n,size(field(ind)%rval4d,2)))
+            n=0
+            DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+              DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+                k=d%iim*(j-1)+i
+                IF (d%own(i,j) .OR. single) THEN
+                  n=n+1
+                  Field_val3d(n,:)=field(ind)%rval4d(k,:,q)
+                ENDIF
+              ENDDO
+             ENDDO
+
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d(:,l), &
+                                start=(/ displ+ncell,l,FieldIndex(Index) /), count=(/n,size(field(ind)%rval4d,2),1 /))
+            DEALLOCATE(field_val3d)
+          ENDDO         
+        ENDIF
+        
+        ncell=ncell+n
+
+     ENDDO
+     
+     ELSE IF (Field(ind_b)%field_type==field_Z) THEN
+        ncell=1
+        n=0
+        DO ind=ind_b,ind_e
+          d=>domain(ind)
+          CALL swap_geometry(ind)
+          CALL swap_dimensions(ind)
+  
+          n=0
+          DO j=jj_begin+1,jj_end
+            DO i=ii_begin,ii_end-1
+              n=n+1
+            ENDDO
+          ENDDO
+
+          DO j=jj_begin,jj_end-1
+            DO i=ii_begin+1,ii_end
+              n=n+1
+            ENDDO
+          ENDDO
+
+        displ=FieldVarId(index)%displ
+
+        IF (field(ind)%ndim==2) THEN
+          ALLOCATE(Field_val2d(n))
+
+          n=0
+          DO j=jj_begin+1,jj_end
+            DO i=ii_begin,ii_end-1
+              n=n+1
+              k=iim*(j-1)+i
+              Field_val2d(n)=field(ind)%rval2d(k+z_down)
+            ENDDO
+          ENDDO
+
+          DO j=jj_begin,jj_end-1
+            DO i=ii_begin+1,ii_end
+              n=n+1
+              k=iim*(j-1)+i
+              Field_val2d(n)=field(ind)%rval2d(k+z_up)
+            ENDDO
+          ENDDO
+
+          status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),                       &
+                              Field_val2d,start=(/ displ+ncell,FieldIndex(Index) /),count=(/n,1 /))
+          DEALLOCATE(field_val2d)
+
+        ELSE IF (field(ind)%ndim==3) THEN
+          ALLOCATE(Field_val3d(n,size(field(ind)%rval3d,2)))
+          n=0
+          DO j=jj_begin+1,jj_end
+            DO i=ii_begin,ii_end-1
+              n=n+1
+              k=iim*(j-1)+i
+              Field_val3d(n,:)=field(ind)%rval3d(k+z_down,:)
+            ENDDO
+          ENDDO
+
+          DO j=jj_begin,jj_end-1
+            DO i=ii_begin+1,ii_end
+              n=n+1
+              k=iim*(j-1)+i
+              Field_val3d(n,:)=field(ind)%rval3d(k+z_up,:)
+            ENDDO
+          ENDDO
+
+           status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(1),Field_val3d,    &
+                               start=(/ displ+ncell,1,FieldIndex(Index) /), count=(/n,size(field(ind)%rval3d,2),1 /))
+          DEALLOCATE(field_val3d)
+
+        ELSE IF (field(1)%ndim==4) THEN
+
+          DO q=1,FieldVarId(index)%size
+            ALLOCATE(Field_val3d(n,size(field(ind)%rval4d,2)))
+            n=0
+            DO j=jj_begin+1,jj_end
+              DO i=ii_begin,ii_end-1
+                n=n+1
+                k=iim*(j-1)+i
+                Field_val3d(n,:)=field(ind)%rval4d(k+z_down,:,q)
+              ENDDO
+            ENDDO
+
+            DO j=jj_begin,jj_end-1
+              DO i=ii_begin+1,ii_end
+                n=n+1
+                k=iim*(j-1)+i
+                Field_val3d(n,:)=field(ind)%rval4d(k+z_up,:,q)
+              ENDDO
+            ENDDO
+
+            status=NF90_PUT_VAR(FieldId(Index),FieldVarId(index)%nc_id(q),Field_val3d,  &
+                                start=(/ displ+ncell,1,FieldIndex(Index) /), count=(/n,size(field(ind)%rval4d,2),1 /))
+            DEALLOCATE(field_val3d)
+          ENDDO
+        ENDIF
+        
+        ncell=ncell+n
+
+     ENDDO
+     
+     ENDIF
+     status=NF90_SYNC(FieldId(Index))
+      
+    END SUBROUTINE Writefield_mpi
+    
+    
+           
+!   SUBROUTINE Create_header(name,field,nind)
+!   USE netcdf
+!   USE field_mod
+!   USE domain_mod
+!   USE spherical_geom_mod
+!   USE dimensions
+!   USE geometry
+!   IMPLICIT NONE
+!     CHARACTER(LEN=*) :: name
+!     TYPE(t_field),POINTER :: field(:)
+!     INTEGER,OPTIONAL,INTENT(IN) :: nind
+!     INTEGER :: ncell
+!     INTEGER :: nvert
+!     REAL(rstd),ALLOCATABLE :: lon(:),lat(:),bounds_lon(:,:),bounds_lat(:,:)
+!     TYPE(t_domain),POINTER :: d
+!     INTEGER :: nvertId,ncid,lonId,latId,bounds_lonId,bounds_latId,timeId,ncellId
+!     INTEGER :: dim3id,dim4id
+!     INTEGER :: status
+!     INTEGER :: ind,i,j,k,n,q
+!     INTEGER :: iie,jje,iin,jjn
+!     INTEGER :: ind_b,ind_e
+!     INTEGER :: halo_size
+!     LOGICAL :: single 
+!     INTEGER :: nij
+!         
+!     NbField=NbField+1
+!     FieldName(NbField)=TRIM(ADJUSTL(name))
+!     FieldIndex(NbField)=1
+!     
+!     IF (PRESENT(nind)) THEN
+!       ind_b=nind
+!       ind_e=nind
+!       halo_size=1
+!       single=.TRUE.
+!     ELSE
+!       ind_b=1
+!       ind_e=ndomain
+!       halo_size=0
+!       single=.FALSE.
+!     ENDIF
+!     
+!     ncell=0
+!     
+!     IF (Field(ind_b)%field_type==field_T) THEN
+!       nvert=6
+!       
+!       DO ind=ind_b,ind_e
+!         d=>domain(ind)
+!       
+!         DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!           DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!             IF (single .OR. domain(ind)%own(i,j)) ncell=ncell+1
+!           ENDDO
+!         ENDDO
+
+!       END DO
+!     
+!       status = NF90_CREATE(TRIM(ADJUSTL(name))//'.nc', NF90_CLOBBER, ncid)
+!       FieldId(NbField)=ncid
+!       status = NF90_DEF_DIM(ncid,'cell',ncell,ncellId)
+!       status = NF90_DEF_DIM(ncid,'nvert',nvert,nvertid)
+
+!       IF (Field(ind_b)%ndim==2)  THEN
+!         FieldVarId(NbField)%size=1
+!         ALLOCATE(FieldVarId(NbField)%nc_id(1))
+!       ELSE IF (Field(ind_b)%ndim==3)  THEN
+!         FieldVarId(NbField)%size=1
+!         ALLOCATE(FieldVarId(NbField)%nc_id(1))
+!         status = NF90_DEF_DIM(ncid,'Z',size(field(ind_b)%rval3d,2),dim3id)
+!       ELSE IF (Field(1)%ndim==4) THEN
+!         FieldVarId(NbField)%size=size(field(ind_b)%rval4d,3)
+!         ALLOCATE(FieldVarId(NbField)%nc_id(FieldVarId(NbField)%size))
+!         status = NF90_DEF_DIM(ncid,'Z',size(field(ind_b)%rval4d,2),dim3id)
+!          status = NF90_DEF_DIM(ncid,'Q',size(field(ind_b)%rval4d,3),dim4id)
+!       ENDIF
+!     
+!       status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeId)
+!     
+!       status = NF90_DEF_VAR(ncid,'lon',NF90_DOUBLE,(/ ncellId /),lonId)
+!       status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+!       status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+!       status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon")
+!       status = NF90_DEF_VAR(ncid,'lat',NF90_DOUBLE,(/ ncellId /),latId)
+!       status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+!       status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+!       status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat")
+!       status = NF90_DEF_VAR(ncid,'bounds_lon',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_lonId)
+!       status = NF90_DEF_VAR(ncid,'bounds_lat',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_latId)
+
+!       IF (Field(ind_b)%ndim==2) THEN
+!         status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),NF90_DOUBLE,(/ ncellId,timeId /),FieldVarId(NbField)%nc_id(1))
+!         status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+!       ELSE IF (Field(ind_b)%ndim==3) THEN
+!         status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),NF90_DOUBLE,(/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(1))
+!         status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+!       ELSE IF (Field(ind_b)%ndim==4) THEN
+!         DO i=1,FieldVarId(NbField)%size
+!           status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name))//int2str(i),NF90_DOUBLE,(/ ncellId,dim3id,timeId /),  &
+!                                 FieldVarId(NbField)%nc_id(i))
+!           status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(i),"coordinates","lon lat")
+!         ENDDO        
+!       ENDIF 
+! 
+!     
+!       status = NF90_ENDDEF(ncid)      
+
+!       ncell=1
+!       DO ind=ind_b,ind_e
+!         d=>domain(ind)
+! 
+!         n=0
+!         DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!           DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!             IF (single .OR. d%own(i,j)) n=n+1
+!           ENDDO
+!         ENDDO
+!         
+!        ALLOCATE(lon(n),lat(n),bounds_lon(0:nvert-1,n),bounds_lat(0:nvert-1,n))
+!         
+!         n=0  
+!         DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+!           DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+!               IF (d%own(i,j) .OR. single) THEN
+!               n=n+1
+!               CALL xyz2lonlat(d%xyz(:,i,j),lon(n),lat(n))
+!               lon(n)=lon(n)*180/Pi
+!               lat(n)=lat(n)*180/Pi
+!               DO k=0,5
+!                 CALL xyz2lonlat(d%vertex(:,k,i,j),bounds_lon(k,n), bounds_lat(k,n))
+!                 bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+!                 bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+!               ENDDO
+!             ENDIF
+!           ENDDO
+!         ENDDO
+!         status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ ncell /),count=(/ n /))
+!         status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ ncell /),count=(/ n /))
+!         status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,ncell /),count=(/ nvert,n /))
+!         status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,ncell /),count=(/ nvert,n /))
+! 
+!         ncell=ncell+n
+!         DEALLOCATE(lon,lat,bounds_lon,bounds_lat)
+!     END DO 
+
+!   ELSE IF (Field(ind_b)%field_type==field_Z) THEN
+!       nvert=3
+!       DO ind=ind_b,ind_e
+!         d=>domain(ind)
+!       
+!         DO j=d%jj_begin+1,d%jj_end
+!           DO i=d%ii_begin,d%ii_end-1
+!             ncell=ncell+1
+!           ENDDO
+!         ENDDO
+
+!         DO j=d%jj_begin,d%jj_end-1
+!           DO i=d%ii_begin+1,d%ii_end
+!             ncell=ncell+1
+!           ENDDO
+!         ENDDO
+
+!       END DO
+!     
+!       status = NF90_CREATE(TRIM(ADJUSTL(name))//'.nc', NF90_CLOBBER, ncid)
+!       FieldId(NbField)=ncid
+!       status = NF90_DEF_DIM(ncid,'cell',ncell,ncellId)
+!       status = NF90_DEF_DIM(ncid,'nvert',nvert,nvertid)
+
+!       IF (Field(ind_b)%ndim==2)  THEN
+!         FieldVarId(NbField)%size=1
+!         ALLOCATE(FieldVarId(NbField)%nc_id(1))
+!       ELSE IF (Field(ind_b)%ndim==3)  THEN
+!         FieldVarId(NbField)%size=1
+!         ALLOCATE(FieldVarId(NbField)%nc_id(1))
+!         status = NF90_DEF_DIM(ncid,'Z',size(field(ind_b)%rval3d,2),dim3id)
+!       ELSE IF (Field(1)%ndim==4) THEN
+!         FieldVarId(NbField)%size=size(field(ind_b)%rval4d,3)
+!         ALLOCATE(FieldVarId(NbField)%nc_id(FieldVarId(NbField)%size))
+!         status = NF90_DEF_DIM(ncid,'Z',size(field(ind_b)%rval4d,2),dim3id)
+!       ENDIF
+
+
+!     
+!       status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeId)
+!     
+!       status = NF90_DEF_VAR(ncid,'lon',NF90_DOUBLE,(/ ncellId /),lonId)
+!       status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+!       status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+!       status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon")
+!       status = NF90_DEF_VAR(ncid,'lat',NF90_DOUBLE,(/ ncellId /),latId)
+!       status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+!       status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+!       status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat")
+!       status = NF90_DEF_VAR(ncid,'bounds_lon',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_lonId)
+!       status = NF90_DEF_VAR(ncid,'bounds_lat',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_latId)
+
+
+!       IF (Field(ind_b)%ndim==2) THEN
+!         status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),NF90_DOUBLE,(/ ncellId,timeId /),FieldVarId(NbField)%nc_id(1))
+!         status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+!       ELSE IF (Field(ind_b)%ndim==3) THEN
+!         status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),NF90_DOUBLE,(/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(1))
+!         status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+!       ELSE IF (Field(ind_b)%ndim==4) THEN
+!         DO q=1,FieldVarId(NbField)%size
+!           status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)//int2str(q)),NF90_DOUBLE,             &
+!                                 (/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(q))
+!           status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(q),"coordinates","lon lat")
+!         ENDDO        
+!       ENDIF 
+!       
+!       status = NF90_ENDDEF(ncid)      
+
+!       ncell=1
+!       DO ind=ind_b,ind_e
+!         d=>domain(ind)
+!         CALL swap_geometry(ind)
+!         CALL swap_dimensions(ind)
+! 
+!         n=0
+!         DO j=jj_begin+1,jj_end
+!           DO i=ii_begin,ii_end-1
+!             n=n+1
+!           ENDDO
+!         ENDDO
+
+!         DO j=jj_begin,jj_end-1
+!           DO i=ii_begin+1,ii_end
+!             n=n+1
+!           ENDDO
+!         ENDDO
+
+!        ALLOCATE(lon(n),lat(n),bounds_lon(0:nvert-1,n),bounds_lat(0:nvert-1,n))
+!         
+!         n=0  
+!      
+!         DO j=jj_begin+1,jj_end
+!           DO i=ii_begin,ii_end-1
+!             nij=(j-1)*iim+i
+!             n=n+1
+!             CALL xyz2lonlat(xyz_v(nij+z_down,:)/radius,lon(n),lat(n))
+!             lon(n)=lon(n)*180/Pi
+!!             IF (lon(n)<0) lon(n)=lon(n)+360
+!             lat(n)=lat(n)*180/Pi
+!             CALL xyz2lonlat(xyz_i(nij,:)/radius,bounds_lon(0,n), bounds_lat(0,n))
+!             CALL xyz2lonlat(xyz_i(nij+t_ldown,:)/radius,bounds_lon(1,n), bounds_lat(1,n))
+!             CALL xyz2lonlat(xyz_i(nij+t_rdown,:)/radius,bounds_lon(2,n), bounds_lat(2,n))
+
+!             DO k=0,2
+!               bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+!               bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+!                IF (bounds_lon(k,n)<0) bounds_lon(k,n)=bounds_lon(k,n)+360
+!             ENDDO
+!           ENDDO
+!         ENDDO
+
+!         DO j=jj_begin,jj_end-1
+!           DO i=ii_begin+1,ii_end
+!             nij=(j-1)*iim+i
+!             n=n+1
+!             CALL xyz2lonlat(xyz_v(nij+z_up,:)/radius,lon(n),lat(n))
+!             lon(n)=lon(n)*180/Pi
+!              IF (lon(n)<0) lon(n)=lon(n)+360
+!             lat(n)=lat(n)*180/Pi
+!             CALL xyz2lonlat(xyz_i(nij,:)/radius,bounds_lon(0,n), bounds_lat(0,n))
+!             CALL xyz2lonlat(xyz_i(nij+t_rup,:)/radius,bounds_lon(1,n), bounds_lat(1,n))
+!             CALL xyz2lonlat(xyz_i(nij+t_lup,:)/radius,bounds_lon(2,n), bounds_lat(2,n))
+
+!             DO k=0,2
+!               bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+!               bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+!                IF (bounds_lon(k,n)<0) bounds_lon(k,n)=bounds_lon(k,n)+360
+!             ENDDO
+!           ENDDO
+!         ENDDO
+!         
+!         
+!         status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ ncell /),count=(/ n /))
+!         status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ ncell /),count=(/ n /))
+!         status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,ncell /),count=(/ nvert,n /))
+!         status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,ncell /),count=(/ nvert,n /))
+! 
+!         ncell=ncell+n
+!         DEALLOCATE(lon,lat,bounds_lon,bounds_lat)
+!     END DO          
+!   ENDIF
+
+
+!     
+!      status = NF90_CLOSE(ncid)
+
+!   END SUBROUTINE Create_Header
+
+
+
+   
+    SUBROUTINE Create_header_gen(name_in,field,domain_type,ind_b_in,ind_e_in,once)
+    USE netcdf_mod
+    USE field_mod
+    USE domain_mod
+    USE metric
+    USE spherical_geom_mod
+    IMPLICIT NONE
+      CHARACTER(LEN=*),INTENT(IN) :: name_in
+      TYPE(t_field),POINTER :: field(:)
+      TYPE(t_domain),INTENT(IN),TARGET :: domain_type(:)
+      INTEGER,OPTIONAL,INTENT(IN) :: ind_b_in
+      INTEGER,OPTIONAL,INTENT(IN) :: ind_e_in
+      LOGICAL,INTENT(IN) :: once
+      
+      INTEGER :: ncell
+      INTEGER :: nvert
+      REAL(rstd),ALLOCATABLE :: lon(:),lat(:),bounds_lon(:,:),bounds_lat(:,:)
+      TYPE(t_domain),POINTER :: d
+      INTEGER :: nvertId,ncid,lonId,latId,bounds_lonId,bounds_latId,timeId,ncellId
+      INTEGER :: dim3id,dim4id
+      INTEGER :: status
+      INTEGER :: ind,i,j,k,n,q
+      INTEGER :: iie,jje,iin,jjn
+      INTEGER :: ind_b,ind_e
+      INTEGER :: halo_size
+      LOGICAL :: single 
+      INTEGER :: nij
+      CHARACTER(LEN=255) :: name
+      
+            
+      name=TRIM(ADJUSTL(name_in))
+
+      IF (PRESENT(ind_b_in) .AND. .NOT. PRESENT(ind_e_in)) THEN
+        name=TRIM(name)//"_"//TRIM(int2str(ind_b))
+        ind_b=ind_b_in
+        ind_e=ind_b_in
+        halo_size=1
+        single=.TRUE.
+      ELSE IF (.NOT. PRESENT(ind_b_in) .AND. PRESENT(ind_e_in)) THEN
+        name=TRIM(name)//"_"//TRIM(int2str(ind_e))
+        ind_b=ind_e_in
+        ind_e=ind_e_in
+        halo_size=1
+        single=.TRUE.
+      ELSE IF ( PRESENT(ind_b_in) .AND. PRESENT(ind_e_in)) THEN
+        ind_b=ind_b_in
+        ind_e=ind_e_in
+        halo_size=0
+        single=.FALSE.
+      ELSE
+        halo_size=0
+        ind_b=1
+        ind_e=ndomain
+        single=.FALSE.
+      ENDIF      
+                
+      NbField=NbField+1
+      FieldName(NbField)=TRIM(ADJUSTL(name))
+      FieldIndex(NbField)=1
+      
+      ncell=0
+      
+      IF (Field(ind_b)%field_type==field_T) THEN
+        nvert=6
+        
+        DO ind=ind_b,ind_e
+          d=>domain_type(ind)
+        
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+              IF (single .OR. d%assign_domain(i,j)==ind) ncell=ncell+1
+            ENDDO
+          ENDDO
+
+        END DO
+      
+        status = NF90_CREATE(TRIM(ADJUSTL(name))//'.nc', NF90_CLOBBER, ncid)
+        FieldId(NbField)=ncid
+        status = NF90_DEF_DIM(ncid,'cell_i',ncell,ncellId)
+        status = NF90_DEF_DIM(ncid,'nvert_i',nvert,nvertid)
+
+        IF (Field(ind_b)%ndim==2)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+        ELSE IF (Field(ind_b)%ndim==3)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval3d,2),dim3id)
+        ELSE IF (Field(1)%ndim==4) THEN
+          FieldVarId(NbField)%size=size(field(ind_b)%rval4d,3)
+          ALLOCATE(FieldVarId(NbField)%nc_id(FieldVarId(NbField)%size))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval4d,2),dim3id)
+!          status = NF90_DEF_DIM(ncid,'Q',size(field(ind_b)%rval4d,3),dim4id)
+        ENDIF
+      
+        status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeId)
+      
+        status = NF90_DEF_VAR(ncid,'lon_i',NF90_DOUBLE,(/ ncellId /),lonId)
+        status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+        status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+        status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon_i")
+        status = NF90_DEF_VAR(ncid,'lat_i',NF90_DOUBLE,(/ ncellId /),latId)
+        status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+        status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+        status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat_i")
+        status = NF90_DEF_VAR(ncid,'bounds_lon_i',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_lonId)
+        status = NF90_DEF_VAR(ncid,'bounds_lat_i',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_latId)
+
+        IF (Field(ind_b)%ndim==2) THEN
+          IF (once) THEN 
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId /),FieldVarId(NbField)%nc_id(1))
+          ELSE
+             status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,timeId /),FieldVarId(NbField)%nc_id(1))
+          ENDIF
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon_i lat_i")
+        ELSE IF (Field(ind_b)%ndim==3) THEN
+          IF (once) THEN 
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,dim3id /),FieldVarId(NbField)%nc_id(1))
+          ELSE
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(1))
+          ENDIF
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon_i lat_i")
+        ELSE IF (Field(ind_b)%ndim==4) THEN
+          DO i=1,FieldVarId(NbField)%size
+            IF (once) THEN 
+              status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name))//int2str(i),ncprec,(/ ncellId,dim3id /),  &
+                                    FieldVarId(NbField)%nc_id(i))
+            ELSE
+              status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name))//int2str(i),ncprec,(/ ncellId,dim3id,timeId /),  &
+                                   FieldVarId(NbField)%nc_id(i))
+            ENDIF
+            status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(i),"coordinates","lon_i lat_i")
+          ENDDO        
+        ENDIF 
+  
+      
+        status = NF90_ENDDEF(ncid)      
+         
+         ALLOCATE(lon(ncell),lat(ncell),bounds_lon(0:nvert-1,ncell),bounds_lat(0:nvert-1,ncell))
+          
+         n=0  
+         DO ind=ind_b,ind_e
+           d=>domain_type(ind)
+           DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+             DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+               IF (d%assign_domain(i,j)==ind .OR. single) THEN
+                 n=n+1
+                 CALL xyz2lonlat(d%xyz(:,i,j),lon(n),lat(n))
+                 lon(n)=lon(n)*180/Pi
+                 lat(n)=lat(n)*180/Pi
+                 DO k=0,5
+                   CALL xyz2lonlat(d%vertex(:,k,i,j),bounds_lon(k,n), bounds_lat(k,n))
+                   bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+                   bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+                 ENDDO
+               ENDIF
+             ENDDO
+           ENDDO
+         ENDDO
+         status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ 1 /),count=(/ ncell /))
+         status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ 1 /),count=(/ ncell /))
+         status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,1 /),count=(/ nvert,ncell /))
+         status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,1 /),count=(/ nvert,ncell /))
+  
+         DEALLOCATE(lon,lat,bounds_lon,bounds_lat)
+
+    ELSE IF (Field(ind_b)%field_type==field_Z) THEN
+        nvert=3
+        DO ind=ind_b,ind_e
+          d=>domain_type(ind)
+        
+          DO j=d%jj_begin+1,d%jj_end
+            DO i=d%ii_begin,d%ii_end-1
+              ncell=ncell+1
+            ENDDO
+          ENDDO
+
+          DO j=d%jj_begin,d%jj_end-1
+            DO i=d%ii_begin+1,d%ii_end
+              ncell=ncell+1
+            ENDDO
+          ENDDO
+
+        END DO
+      
+        status = NF90_CREATE(TRIM(ADJUSTL(name))//'.nc', NF90_CLOBBER, ncid)
+        FieldId(NbField)=ncid
+        status = NF90_DEF_DIM(ncid,'cell_v',ncell,ncellId)
+        status = NF90_DEF_DIM(ncid,'nvert_v',nvert,nvertid)
+
+        IF (Field(ind_b)%ndim==2)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+        ELSE IF (Field(ind_b)%ndim==3)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval3d,2),dim3id)
+        ELSE IF (Field(1)%ndim==4) THEN
+          FieldVarId(NbField)%size=size(field(ind_b)%rval4d,3)
+          ALLOCATE(FieldVarId(NbField)%nc_id(FieldVarId(NbField)%size))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval4d,2),dim3id)
+        ENDIF
+
+
+      
+        status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeId)
+      
+        status = NF90_DEF_VAR(ncid,'lon_v',NF90_DOUBLE,(/ ncellId /),lonId)
+        status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+        status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+        status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon_v")
+        status = NF90_DEF_VAR(ncid,'lat_v',NF90_DOUBLE,(/ ncellId /),latId)
+        status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+        status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+        status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat_v")
+        status = NF90_DEF_VAR(ncid,'bounds_lon_v',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_lonId)
+        status = NF90_DEF_VAR(ncid,'bounds_lat_v',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_latId)
+
+
+        IF (Field(ind_b)%ndim==2) THEN
+          IF (once) THEN 
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId /),FieldVarId(NbField)%nc_id(1))
+          ELSE
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,timeId /),FieldVarId(NbField)%nc_id(1))
+          ENDIF
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon_v lat_v")
+        ELSE IF (Field(ind_b)%ndim==3) THEN
+          IF (once) THEN 
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,dim3id /),FieldVarId(NbField)%nc_id(1))
+          ELSE
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(1))
+          ENDIF
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon_v lat_v")
+        ELSE IF (Field(ind_b)%ndim==4) THEN
+          DO q=1,FieldVarId(NbField)%size
+            IF (once) THEN 
+              status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)//int2str(q)),ncprec,             &
+                                    (/ ncellId,dim3id /),FieldVarId(NbField)%nc_id(q))
+            ELSE
+              status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)//int2str(q)),ncprec,             &
+                                    (/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(q))
+            ENDIF
+            status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(q),"coordinates","lon_v lat_v")
+          ENDDO        
+        ENDIF 
+        
+        status = NF90_ENDDEF(ncid)      
+
+         ALLOCATE(lon(ncell),lat(ncell),bounds_lon(0:nvert-1,ncell),bounds_lat(0:nvert-1,ncell))
+          
+         n=0  
+       
+         DO ind=ind_b,ind_e
+           d=>domain_type(ind)
+           DO j=d%jj_begin+1,d%jj_end
+             DO i=d%ii_begin,d%ii_end-1
+               nij=(j-1)*d%iim+i
+               n=n+1
+               CALL xyz2lonlat(d%vertex(:,vdown,i,j),lon(n),lat(n))
+               lon(n)=lon(n)*180/Pi
+               lat(n)=lat(n)*180/Pi
+
+               CALL xyz2lonlat(d%xyz(:,i,j),bounds_lon(0,n), bounds_lat(0,n))
+               CALL xyz2lonlat(d%xyz(:,i,j-1),bounds_lon(1,n), bounds_lat(1,n))
+               CALL xyz2lonlat(d%xyz(:,i+1,j-1),bounds_lon(2,n), bounds_lat(2,n))
+
+               DO k=0,2
+                 bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+                 bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+               ENDDO
+             ENDDO
+           ENDDO
+
+           DO j=d%jj_begin,d%jj_end-1
+             DO i=d%ii_begin+1,d%ii_end
+               nij=(j-1)*d%iim+i
+               n=n+1
+               CALL xyz2lonlat(d%vertex(:,vup,i,j),lon(n),lat(n))
+               lon(n)=lon(n)*180/Pi
+               lat(n)=lat(n)*180/Pi
+               CALL xyz2lonlat(d%xyz(:,i,j),bounds_lon(0,n), bounds_lat(0,n))
+               CALL xyz2lonlat(d%xyz(:,i,j+1),bounds_lon(1,n), bounds_lat(1,n))
+               CALL xyz2lonlat(d%xyz(:,i-1,j+1),bounds_lon(2,n), bounds_lat(2,n))
+
+               DO k=0,2
+                 bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+                 bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+               ENDDO
+             ENDDO
+           ENDDO
+         ENDDO 
+          
+         status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ 1 /),count=(/ ncell /))
+         status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ 1 /),count=(/ ncell /))
+         status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,1 /),count=(/ nvert,ncell /))
+         status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,1 /),count=(/ nvert,ncell /))
+  
+          DEALLOCATE(lon,lat,bounds_lon,bounds_lat)
+      ENDIF
+
+
+    END SUBROUTINE Create_Header_gen
+
+    SUBROUTINE Create_header_mpi(name,field,nind)
+    USE netcdf_mod
+    USE field_mod
+    USE domain_mod
+    USE spherical_geom_mod
+    USE dimensions
+    USE geometry
+    USE mpi_mod
+    USE mpipara
+    IMPLICIT NONE
+      CHARACTER(LEN=*) :: name
+      CHARACTER(LEN=LEN_TRIM(ADJUSTL(name))) :: name_adj
+      TYPE(t_field),POINTER :: field(:)
+      INTEGER,OPTIONAL,INTENT(IN) :: nind
+      INTEGER :: ncell
+      INTEGER :: nvert
+      REAL(rstd),ALLOCATABLE :: lon(:),lat(:),bounds_lon(:,:),bounds_lat(:,:)
+      TYPE(t_domain),POINTER :: d
+      INTEGER :: nvertId,ncid,lonId,latId,bounds_lonId,bounds_latId,timeId,ncellId
+      INTEGER :: dim3id,dim4id
+      INTEGER :: status
+      INTEGER :: ind,i,j,k,n,q
+      INTEGER :: iie,jje,iin,jjn
+      INTEGER :: ind_b,ind_e
+      INTEGER :: halo_size
+      LOGICAL :: single 
+      INTEGER :: nij
+      INTEGER :: ncell_glo(0:mpi_size-1)
+      INTEGER :: displ, ncell_tot
+      
+          
+      NbField=NbField+1
+      name_adj=TRIM(ADJUSTL(name))  ! work around ICE with pgf90
+      FieldName(NbField)=name_adj
+      FieldIndex(NbField)=1
+      
+      IF (PRESENT(nind)) THEN
+        ind_b=nind
+        ind_e=nind
+        halo_size=1
+        single=.TRUE.
+      ELSE
+        ind_b=1
+        ind_e=ndomain
+        halo_size=0
+        single=.FALSE.
+      ENDIF
+      
+      ncell=0
+      
+      IF (Field(ind_b)%field_type==field_T) THEN
+        nvert=6
+        
+        DO ind=ind_b,ind_e
+          d=>domain(ind)
+        
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+              IF (single .OR. domain(ind)%own(i,j)) ncell=ncell+1
+            ENDDO
+          ENDDO
+
+        END DO
+      
+        CALL MPI_ALLGATHER(ncell,1,MPI_INTEGER,ncell_glo,1,MPI_INTEGER,comm_icosa,ierr)
+
+        displ=0
+        DO i=1,mpi_rank
+          displ=displ+ncell_glo(i-1)
+        ENDDO
+        FieldVarId(NbField)%displ=displ
+        ncell_tot=sum(ncell_glo(:))
+        
+!        status = NF90_CREATE_PAR(TRIM(ADJUSTL(name))//'.nc', IOR(NF90_NETCDF4, NF90_MPIIO), comm_icosa, MPI_INFO_NULL, ncid)
+        FieldId(NbField)=ncid
+        status = NF90_DEF_DIM(ncid,'cell',ncell_tot,ncellId)
+        status = NF90_DEF_DIM(ncid,'nvert',nvert,nvertid)
+
+        IF (Field(ind_b)%ndim==2)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+        ELSE IF (Field(ind_b)%ndim==3)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval3d,2),dim3id)
+        ELSE IF (Field(1)%ndim==4) THEN
+          FieldVarId(NbField)%size=size(field(ind_b)%rval4d,3)
+          ALLOCATE(FieldVarId(NbField)%nc_id(FieldVarId(NbField)%size))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval4d,2),dim3id)
+!          status = NF90_DEF_DIM(ncid,'Q',size(field(ind_b)%rval4d,3),dim4id)
+        ENDIF
+      
+        status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeId)
+      
+        status = NF90_DEF_VAR(ncid,'lon',NF90_DOUBLE,(/ ncellId /),lonId)
+        status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+        status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+        status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon")
+        status = NF90_DEF_VAR(ncid,'lat',NF90_DOUBLE,(/ ncellId /),latId)
+        status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+        status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+        status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat")
+        status = NF90_DEF_VAR(ncid,'bounds_lon',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_lonId)
+        status = NF90_DEF_VAR(ncid,'bounds_lat',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_latId)
+
+        IF (Field(ind_b)%ndim==2) THEN
+          status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,timeId /),FieldVarId(NbField)%nc_id(1))
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+          status = NF90_DEF_VAR_CHUNKING(ncid, FieldVarId(NbField)%nc_id(1), NF90_CHUNKED, (/ncell_tot,1/))
+        ELSE IF (Field(ind_b)%ndim==3) THEN
+          status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(1))
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+          status = NF90_DEF_VAR_CHUNKING(ncid, FieldVarId(NbField)%nc_id(1), NF90_CHUNKED,   &
+                                         (/ncell_tot,size(field(ind_b)%rval3d,2),1/))
+        ELSE IF (Field(ind_b)%ndim==4) THEN
+          DO i=1,FieldVarId(NbField)%size
+            status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name))//int2str(i),ncprec,(/ ncellId,dim3id,timeId /),  &
+                                  FieldVarId(NbField)%nc_id(i))
+            status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(i),"coordinates","lon lat")
+            status = NF90_DEF_VAR_CHUNKING(ncid, FieldVarId(NbField)%nc_id(q), NF90_CHUNKED,   &
+                                           (/ncell_tot,size(field(ind_b)%rval4d,2),1/))
+          ENDDO        
+        ENDIF 
+  
+      
+        status = NF90_ENDDEF(ncid)      
+
+        ncell=1
+        DO ind=ind_b,ind_e
+          d=>domain(ind)
+  
+          n=0
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+              IF (single .OR. d%own(i,j)) n=n+1
+            ENDDO
+          ENDDO
+          
+         ALLOCATE(lon(n),lat(n),bounds_lon(0:nvert-1,n),bounds_lat(0:nvert-1,n))
+          
+          n=0  
+          DO j=d%jj_begin-halo_size,d%jj_end+halo_size
+            DO i=d%ii_begin-halo_size,d%ii_end+halo_size
+                IF (d%own(i,j) .OR. single) THEN
+                n=n+1
+                CALL xyz2lonlat(d%xyz(:,i,j),lon(n),lat(n))
+                lon(n)=lon(n)*180/Pi
+                lat(n)=lat(n)*180/Pi
+                DO k=0,5
+                  CALL xyz2lonlat(d%vertex(:,k,i,j),bounds_lon(k,n), bounds_lat(k,n))
+                  bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+                  bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+                ENDDO
+              ENDIF
+            ENDDO
+          ENDDO
+          status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ displ+ncell /),count=(/ n /))
+          status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ displ+ncell /),count=(/ n /))
+          status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,displ+ncell /),count=(/ nvert,n /))
+          status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,displ+ncell /),count=(/ nvert,n /))
+  
+          ncell=ncell+n
+          DEALLOCATE(lon,lat,bounds_lon,bounds_lat)
+      END DO 
+
+    ELSE IF (Field(ind_b)%field_type==field_Z) THEN
+        nvert=3
+        DO ind=ind_b,ind_e
+          d=>domain(ind)
+        
+          DO j=d%jj_begin+1,d%jj_end
+            DO i=d%ii_begin,d%ii_end-1
+              ncell=ncell+1
+            ENDDO
+          ENDDO
+
+          DO j=d%jj_begin,d%jj_end-1
+            DO i=d%ii_begin+1,d%ii_end
+              ncell=ncell+1
+            ENDDO
+          ENDDO
+
+        END DO
+        
+        CALL MPI_ALLGATHER(ncell,1,MPI_INTEGER,ncell_glo,1,MPI_INTEGER,comm_icosa,ierr)
+
+        displ=0
+        DO i=1,mpi_rank
+          displ=displ+ncell_glo(i-1)
+        ENDDO
+        FieldVarId(NbField)%displ=displ
+        ncell_tot=sum(ncell_glo(:))
+              
+!        status = NF90_CREATE_PAR(TRIM(ADJUSTL(name))//'.nc',IOR(NF90_NETCDF4, NF90_MPIIO), comm_icosa, MPI_INFO_NULL, ncid)
+!        status = NF90_CREATE(TRIM(ADJUSTL(name))//'.nc', NF90_CLOBBER, ncid)
+        FieldId(NbField)=ncid
+        status = NF90_DEF_DIM(ncid,'cell',ncell_tot,ncellId)
+        status = NF90_DEF_DIM(ncid,'nvert',nvert,nvertid)
+
+        IF (Field(ind_b)%ndim==2)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+        ELSE IF (Field(ind_b)%ndim==3)  THEN
+          FieldVarId(NbField)%size=1
+          ALLOCATE(FieldVarId(NbField)%nc_id(1))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval3d,2),dim3id)
+        ELSE IF (Field(1)%ndim==4) THEN
+          FieldVarId(NbField)%size=size(field(ind_b)%rval4d,3)
+          ALLOCATE(FieldVarId(NbField)%nc_id(FieldVarId(NbField)%size))
+          status = NF90_DEF_DIM(ncid,'lev',size(field(ind_b)%rval4d,2),dim3id)
+        ENDIF
+
+
+      
+        status = NF90_DEF_DIM(ncid,'time_counter',NF90_UNLIMITED,timeId)
+      
+        status = NF90_DEF_VAR(ncid,'lon',NF90_DOUBLE,(/ ncellId /),lonId)
+        status = NF90_PUT_ATT(ncid,lonId,"long_name","longitude")
+        status = NF90_PUT_ATT(ncid,lonId,"units","degrees_east")
+        status = NF90_PUT_ATT(ncid,lonId,"bounds","bounds_lon")
+        status = NF90_DEF_VAR(ncid,'lat',NF90_DOUBLE,(/ ncellId /),latId)
+        status = NF90_PUT_ATT(ncid,latId,"long_name","latitude")
+        status = NF90_PUT_ATT(ncid,latId,"units","degrees_north")
+        status = NF90_PUT_ATT(ncid,latId,"bounds","bounds_lat")
+        status = NF90_DEF_VAR(ncid,'bounds_lon',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_lonId)
+        status = NF90_DEF_VAR(ncid,'bounds_lat',NF90_DOUBLE,(/ nvertid,ncellId /),bounds_latId)
+
+
+        IF (Field(ind_b)%ndim==2) THEN
+          status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,timeId /),FieldVarId(NbField)%nc_id(1))
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+          status = NF90_DEF_VAR_CHUNKING(ncid, FieldVarId(NbField)%nc_id(1), NF90_CHUNKED, (/ncell_tot,1/))
+        ELSE IF (Field(ind_b)%ndim==3) THEN
+          status = NF90_DEF_VAR(ncid,TRIM(ADJUSTL(name)),ncprec,(/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(1))
+          status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(1),"coordinates","lon lat")
+          status = NF90_DEF_VAR_CHUNKING(ncid, FieldVarId(NbField)%nc_id(1), NF90_CHUNKED,   &
+                                         (/ncell_tot,size(field(ind_b)%rval3d,2),1/))
+        ELSE IF (Field(ind_b)%ndim==4) THEN
+          DO q=1,FieldVarId(NbField)%size
+            status = NF90_DEF_VAR(ncid,name_adj//int2str(q),ncprec,             &
+                                  (/ ncellId,dim3id,timeId /),FieldVarId(NbField)%nc_id(q))
+            status = NF90_PUT_ATT(ncid,FieldVarId(NbField)%nc_id(q),"coordinates","lon lat")
+           status = NF90_DEF_VAR_CHUNKING(ncid, FieldVarId(NbField)%nc_id(q), NF90_CHUNKED, &
+                                          (/ncell_tot,size(field(ind_b)%rval4d,2),1/))
+          ENDDO        
+        ENDIF 
+        
+        status = NF90_ENDDEF(ncid)      
+
+        ncell=1
+        DO ind=ind_b,ind_e
+          d=>domain(ind)
+          CALL swap_geometry(ind)
+          CALL swap_dimensions(ind)
+  
+          n=0
+          DO j=jj_begin+1,jj_end
+            DO i=ii_begin,ii_end-1
+              n=n+1
+            ENDDO
+          ENDDO
+
+          DO j=jj_begin,jj_end-1
+            DO i=ii_begin+1,ii_end
+              n=n+1
+            ENDDO
+          ENDDO
+
+         ALLOCATE(lon(n),lat(n),bounds_lon(0:nvert-1,n),bounds_lat(0:nvert-1,n))
+          
+          n=0  
+       
+          DO j=jj_begin+1,jj_end
+            DO i=ii_begin,ii_end-1
+              nij=(j-1)*iim+i
+              n=n+1
+              CALL xyz2lonlat(xyz_v(nij+z_down,:)/radius,lon(n),lat(n))
+              lon(n)=lon(n)*180/Pi
+              lat(n)=lat(n)*180/Pi
+              CALL xyz2lonlat(xyz_i(nij,:)/radius,bounds_lon(0,n), bounds_lat(0,n))
+              CALL xyz2lonlat(xyz_i(nij+t_ldown,:)/radius,bounds_lon(1,n), bounds_lat(1,n))
+              CALL xyz2lonlat(xyz_i(nij+t_rdown,:)/radius,bounds_lon(2,n), bounds_lat(2,n))
+
+              DO k=0,2
+                bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+                bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+              ENDDO
+            ENDDO
+          ENDDO
+
+          DO j=jj_begin,jj_end-1
+            DO i=ii_begin+1,ii_end
+              nij=(j-1)*iim+i
+              n=n+1
+              CALL xyz2lonlat(xyz_v(nij+z_up,:)/radius,lon(n),lat(n))
+              lon(n)=lon(n)*180/Pi
+              lat(n)=lat(n)*180/Pi
+              CALL xyz2lonlat(xyz_i(nij,:)/radius,bounds_lon(0,n), bounds_lat(0,n))
+              CALL xyz2lonlat(xyz_i(nij+t_rup,:)/radius,bounds_lon(1,n), bounds_lat(1,n))
+              CALL xyz2lonlat(xyz_i(nij+t_lup,:)/radius,bounds_lon(2,n), bounds_lat(2,n))
+
+              DO k=0,2
+                bounds_lat(k,n)=bounds_lat(k,n)*180/Pi
+                bounds_lon(k,n)=bounds_lon(k,n)*180/Pi
+              ENDDO
+            ENDDO
+          ENDDO
+          
+          
+          status=NF90_PUT_VAR(ncid,lonid,REAL(lon,r8),start=(/ displ+ncell /),count=(/ n /))
+          status=NF90_PUT_VAR(ncid,latid,REAL(lat,r8),start=(/ displ+ncell /),count=(/ n /))
+          status=NF90_PUT_VAR(ncid,bounds_lonId,REAL(bounds_lon,r8),start=(/ 1,displ+ncell /),count=(/ nvert,n /))
+          status=NF90_PUT_VAR(ncid,bounds_latId,REAL(bounds_lat,r8),start=(/ 1,displ+ncell /),count=(/ nvert,n /))
+  
+          ncell=ncell+n
+          DEALLOCATE(lon,lat,bounds_lon,bounds_lat)
+      END DO          
+    ENDIF
+
+
+   END SUBROUTINE Create_Header_mpi  
+   
+   SUBROUTINE Close_files
+   USE netcdf
+   IMPLICIT NONE
+     INTEGER :: i,k,status
+!$OMP MASTER     
+     DO i=1,NbField
+         status=NF90_CLOSE(FieldId(i))
+     ENDDO
+!$OMP END MASTER
+   END SUBROUTINE  Close_files
+     
+     
+  function int2str(int)
+    implicit none
+    integer, parameter :: MaxLen=10
+    integer,intent(in) :: int
+    character(len=MaxLen) :: int2str
+    logical :: flag
+    integer :: i
+    flag=.true.
+    
+    i=int
+    
+    int2str=''
+    do while (flag)
+      int2str=CHAR(MOD(i,10)+48)//int2str
+      i=i/10
+      if (i==0) flag=.false.
+    enddo
+  end function int2str
+
+end module write_field
+  
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/xios_mod.F90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/xios_mod.F90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/src/xios_mod.F90	(revision 329)
@@ -0,0 +1,466 @@
+MODULE xios_mod
+
+#ifdef CPP_USING_XIOS
+   USE xios
+#endif
+
+  PUBLIC
+  LOGICAL,SAVE :: using_xios
+
+  INTEGER,SAVE :: ncell_i
+!$OMP THREADPRIVATE(ncell_i)
+  INTEGER,SAVE :: ncell_v
+!$OMP THREADPRIVATE(ncell_v)
+
+  PRIVATE ncell_i,ncell_v
+  
+CONTAINS
+
+#ifdef CPP_USING_XIOS
+ 
+ SUBROUTINE xios_init
+   USE getin_mod
+   IMPLICIT NONE
+
+   using_xios=.TRUE.
+   
+ END SUBROUTINE xios_init  
+ 
+ SUBROUTINE xios_init_write_field
+ USE genmod
+ USE mpipara
+ USE xios
+ USE grid_param
+ USE domain_mod
+ USE dimensions
+ USE spherical_geom_mod
+ USE geometry
+ USE mpi_mod
+ USE time_mod
+ USE metric, ONLY : vup,vdown
+ IMPLICIT NONE
+  TYPE(xios_context) :: ctx_hdl
+  TYPE(xios_time)      :: dtime
+  REAL(rstd) :: lev_value(llm)
+  REAL(rstd) :: lev_valuep1(llm+1)
+  INTEGER :: ncell, ncell_tot, ncell_glo(0:mpi_size-1), displ
+  INTEGER :: ind, i,j,k,l
+  REAL(rstd),ALLOCATABLE    :: lon(:), lat(:), bounds_lon(:,:), bounds_lat(:,:)
+  TYPE(t_domain),POINTER :: d
+
+!$OMP BARRIER
+!$OMP MASTER
+   CALL xios_context_initialize("icosagcm",comm_icosa)
+   CALL xios_get_handle("icosagcm",ctx_hdl)
+   CALL xios_set_current_context(ctx_hdl)
+   lev_value(:) = (/ (l,l=1,llm) /)     
+   lev_valuep1(:) = (/ (l,l=1,llm+1) /)     
+   CALL xios_set_axis_attr("lev",size=llm ,value=lev_value) ;
+   CALL xios_set_axis_attr("levp1",size=llm+1 ,value=lev_value) ;
+   
+   ncell=0
+   DO ind=1,ndomain
+     d=>domain(ind)
+        
+     DO j=d%jj_begin,d%jj_end
+       DO i=d%ii_begin,d%ii_end
+         IF (domain(ind)%own(i,j)) ncell=ncell+1
+       ENDDO
+     ENDDO
+   ENDDO      
+   ncell_i=ncell
+   
+   CALL MPI_ALLGATHER(ncell,1,MPI_INTEGER,ncell_glo,1,MPI_INTEGER,comm_icosa,ierr)
+
+   displ=0
+   DO i=1,mpi_rank
+     displ=displ+ncell_glo(i-1)
+   ENDDO
+
+   ncell_tot=sum(ncell_glo(:))
+   
+   ALLOCATE(lon(ncell), lat(ncell), bounds_lon(0:5,ncell), bounds_lat(0:5,ncell)) 
+   
+   ncell=0
+   DO ind=1,ndomain
+     d=>domain(ind)
+        
+     DO j=d%jj_begin,d%jj_end
+       DO i=d%ii_begin,d%ii_end
+         IF (domain(ind)%own(i,j)) THEN 
+           ncell=ncell+1
+           CALL xyz2lonlat(d%xyz(:,i,j),lon(ncell),lat(ncell))
+           lon(ncell)=lon(ncell)*180/Pi
+           lat(ncell)=lat(ncell)*180/Pi
+           DO k=0,5
+             CALL xyz2lonlat(d%vertex(:,k,i,j),bounds_lon(k,ncell), bounds_lat(k,ncell))
+             bounds_lat(k,ncell)=bounds_lat(k,ncell)*180/Pi
+             bounds_lon(k,ncell)=bounds_lon(k,ncell)*180/Pi
+           ENDDO
+         ENDIF
+       ENDDO
+     ENDDO
+   ENDDO         
+
+  
+   CALL xios_set_domain_attr("i",ni_glo=ncell_tot, ibegin=displ+1, ni=ncell)
+   CALL xios_set_domain_attr("i", data_dim=1, type='unstructured' , nvertex=6)
+   CALL xios_set_domain_attr("i",lonvalue=lon, latvalue=lat, bounds_lon=bounds_lon, bounds_lat=bounds_lat)
+   
+   DEALLOCATE(lon, lat, bounds_lon, bounds_lat) 
+    
+   ncell=0
+   DO ind=1,ndomain
+     d=>domain(ind)
+        
+     DO j=d%jj_begin+1,d%jj_end
+       DO i=d%ii_begin,d%ii_end-1
+         ncell=ncell+1
+       ENDDO
+     ENDDO
+
+     DO j=d%jj_begin,d%jj_end-1
+       DO i=d%ii_begin+1,d%ii_end
+          ncell=ncell+1
+        ENDDO
+     ENDDO
+
+   ENDDO      
+   
+   ncell_v=ncell
+   
+   CALL MPI_ALLGATHER(ncell,1,MPI_INTEGER,ncell_glo,1,MPI_INTEGER,comm_icosa,ierr)
+
+   displ=0
+   DO i=1,mpi_rank
+     displ=displ+ncell_glo(i-1)
+   ENDDO
+
+   ncell_tot=sum(ncell_glo(:))
+   
+   ALLOCATE(lon(ncell), lat(ncell), bounds_lon(0:2,ncell), bounds_lat(0:2,ncell)) 
+   
+   ncell=0
+   DO ind=1,ndomain
+     d=>domain(ind)
+ 
+     DO j=d%jj_begin+1,d%jj_end
+       DO i=d%ii_begin,d%ii_end-1
+           ncell=ncell+1
+           CALL xyz2lonlat(d%vertex(:,vdown,i,j),lon(ncell),lat(ncell))
+           lon(ncell)=lon(ncell)*180/Pi
+           lat(ncell)=lat(ncell)*180/Pi
+
+           CALL xyz2lonlat(d%xyz(:,i,j),bounds_lon(0,ncell), bounds_lat(0,ncell))
+           CALL xyz2lonlat(d%xyz(:,i,j-1),bounds_lon(1,ncell), bounds_lat(1,ncell))
+           CALL xyz2lonlat(d%xyz(:,i+1,j-1),bounds_lon(2,ncell), bounds_lat(2,ncell))
+
+           DO k=0,2
+             bounds_lat(k,ncell)=bounds_lat(k,ncell)*180/Pi
+             bounds_lon(k,ncell)=bounds_lon(k,ncell)*180/Pi
+           ENDDO
+         ENDDO
+       ENDDO 
+ 
+       DO j=d%jj_begin,d%jj_end-1
+         DO i=d%ii_begin+1,d%ii_end
+           ncell=ncell+1
+           CALL xyz2lonlat(d%vertex(:,vup,i,j),lon(ncell),lat(ncell))
+           lon(ncell)=lon(ncell)*180/Pi
+           lat(ncell)=lat(ncell)*180/Pi
+           CALL xyz2lonlat(d%xyz(:,i,j),bounds_lon(0,ncell), bounds_lat(0,ncell))
+           CALL xyz2lonlat(d%xyz(:,i,j+1),bounds_lon(1,ncell), bounds_lat(1,ncell))
+           CALL xyz2lonlat(d%xyz(:,i-1,j+1),bounds_lon(2,ncell), bounds_lat(2,ncell))
+
+           DO k=0,2
+             bounds_lat(k,ncell)=bounds_lat(k,ncell)*180/Pi
+             bounds_lon(k,ncell)=bounds_lon(k,ncell)*180/Pi
+           ENDDO
+         ENDDO
+       ENDDO 
+        
+   ENDDO         
+
+  
+   CALL xios_set_domain_attr("v",ni_glo=ncell_tot, ibegin=displ+1, ni=ncell)
+   CALL xios_set_domain_attr("v", data_dim=1, type='unstructured' , nvertex=3)
+   CALL xios_set_domain_attr("v",lonvalue=lon, latvalue=lat, bounds_lon=bounds_lon, bounds_lat=bounds_lat)
+
+
+   dtime%second=dt
+   CALL xios_set_timestep(dtime) 
+   CALL xios_close_context_definition()
+!$OMP END MASTER
+!$OMP BARRIER
+   
+ END SUBROUTINE xios_init_write_field
+  
+  
+ SUBROUTINE xios_write_field(name,field)
+ USE field_mod
+ IMPLICIT NONE 
+   CHARACTER(LEN=*),INTENT(IN) :: name
+   TYPE(t_field), POINTER :: field(:)
+   CHARACTER(LEN=10) :: str_number
+   INTEGER :: iq
+
+!$OMP BARRIER
+!$OMP MASTER
+   
+   IF (Field(1)%field_type==field_T) THEN
+     IF (field(1)%ndim==2) THEN
+        CALL xios_write_field_scalar(name,field,1)
+      ELSE IF (field(1)%ndim==3) THEN
+        CALL xios_write_field_scalar(name,field,size(field(1)%rval3d,2))
+      ELSE IF (field(1)%ndim==4) THEN
+        DO iq=1,size(field(1)%rval4d,3)
+          WRITE(str_number,'(i10)') iq
+          CALL xios_write_field_scalar(name//TRIM(ADJUSTL(str_number)),field,size(field(1)%rval4d,2),iq)
+        ENDDO
+      ELSE
+        PRINT *, "xios_write_field : dimension > 4 are not supported for now"
+      ENDIF
+    ELSE IF (Field(1)%field_type==field_Z) THEN
+     IF (field(1)%ndim==2) THEN
+        CALL xios_write_field_vort(name,field,1)
+      ELSE IF (field(1)%ndim==3) THEN
+        CALL xios_write_field_vort(name,field,size(field(1)%rval3d,2))
+      ELSE IF (field(1)%ndim==4) THEN
+        DO iq=1,size(field(1)%rval4d,3)
+          WRITE(str_number,'(i10)') iq
+          CALL xios_write_field_vort(name//TRIM(ADJUSTL(str_number)),field,size(field(1)%rval4d,2),iq)
+        ENDDO
+      ELSE
+        PRINT *, "xios_write_field : dimension > 4 are not supported for now"
+      ENDIF
+    ENDIF
+!$OMP END MASTER
+!$OMP BARRIER
+      
+ END SUBROUTINE xios_write_field
+ 
+ SUBROUTINE xios_write_field_scalar(name,field,nlev,iq)
+ USE genmod
+ USE mpipara
+ USE xios
+ USE grid_param
+ USE domain_mod
+ USE dimensions
+ USE spherical_geom_mod
+ USE geometry
+ USE mpi_mod
+ IMPLICIT NONE 
+   CHARACTER(LEN=*),INTENT(IN) :: name
+   TYPE(t_field), POINTER :: field(:)
+   INTEGER,INTENT(IN) :: nlev
+   INTEGER,INTENT(IN),OPTIONAL :: iq
+   
+   REAL(rstd) :: field_tmp(ncell_i,nlev)
+   TYPE(t_domain),POINTER :: d
+   INTEGER :: n,i,j,ij,ind
+   
+   IF (field(1)%ndim==2) THEN
+     n=0
+     DO ind=1,ndomain
+       
+       d=>domain(ind)
+        
+       DO j=d%jj_begin,d%jj_end
+         DO i=d%ii_begin,d%ii_end
+           IF (d%own(i,j)) THEN
+             n=n+1
+             ij=d%iim*(j-1)+i
+             field_tmp(n,1)=field(ind)%rval2d(ij)
+           ENDIF
+         ENDDO
+       ENDDO
+     ENDDO
+   ELSE IF (field(1)%ndim==3) THEN
+     n=0
+     DO ind=1,ndomain
+       d=>domain(ind)
+        
+       DO j=d%jj_begin,d%jj_end
+         DO i=d%ii_begin,d%ii_end
+           IF (d%own(i,j)) THEN
+             n=n+1
+             ij=d%iim*(j-1)+i
+             field_tmp(n,:)=field(ind)%rval3d(ij,:)
+           ENDIF
+         ENDDO
+       ENDDO
+     ENDDO
+   ELSE IF (field(1)%ndim==4) THEN
+     n=0
+     DO ind=1,ndomain
+       d=>domain(ind)
+        
+       DO j=d%jj_begin,d%jj_end
+         DO i=d%ii_begin,d%ii_end
+           IF (d%own(i,j)) THEN
+             n=n+1
+             ij=d%iim*(j-1)+i
+             field_tmp(n,:)=field(ind)%rval4d(ij,:,iq)
+           ENDIF
+         ENDDO
+       ENDDO
+     ENDDO     
+   ENDIF
+   
+   CALL xios_send_field(name,field_tmp)
+ 
+ END SUBROUTINE xios_write_field_scalar  
+      
+ SUBROUTINE xios_write_field_vort(name,field,nlev,iq)
+ USE genmod
+ USE mpipara
+ USE xios
+ USE grid_param
+ USE domain_mod
+ USE dimensions
+ USE spherical_geom_mod
+ USE geometry
+ USE mpi_mod
+ IMPLICIT NONE 
+   CHARACTER(LEN=*),INTENT(IN) :: name
+   TYPE(t_field), POINTER :: field(:)
+   INTEGER,INTENT(IN) :: nlev
+   INTEGER,INTENT(IN),OPTIONAL :: iq
+   
+   REAL(rstd) :: field_tmp(ncell_v,nlev)
+   TYPE(t_domain),POINTER :: d
+   INTEGER :: n,i,j,ij,ind
+   
+   IF (field(1)%ndim==2) THEN
+     n=0
+     DO ind=1,ndomain
+       d=>domain(ind)
+       CALL swap_dimensions(ind)  
+       
+       DO j=d%jj_begin+1,d%jj_end
+         DO i=d%ii_begin,d%ii_end-1
+           n=n+1
+           ij=iim*(j-1)+i
+           Field_tmp(n,1)=field(ind)%rval2d(ij+z_down)
+         ENDDO
+       ENDDO
+
+       DO j=d%jj_begin,d%jj_end-1
+         DO i=d%ii_begin+1,d%ii_end
+           n=n+1
+           ij=iim*(j-1)+i
+           Field_tmp(n,1)=field(ind)%rval2d(ij+z_up)
+          ENDDO
+       ENDDO
+          
+     ENDDO
+
+   ELSE IF (field(1)%ndim==3) THEN
+     n=0
+     DO ind=1,ndomain
+       d=>domain(ind)
+       CALL swap_dimensions(ind)    
+             
+       DO j=d%jj_begin+1,d%jj_end
+         DO i=d%ii_begin,d%ii_end-1
+           n=n+1
+           ij=iim*(j-1)+i
+           Field_tmp(n,:)=field(ind)%rval3d(ij+z_down,:)
+         ENDDO
+       ENDDO
+
+       DO j=d%jj_begin,d%jj_end-1
+         DO i=d%ii_begin+1,d%ii_end
+           n=n+1
+           ij=iim*(j-1)+i
+           Field_tmp(n,:)=field(ind)%rval3d(ij+z_up,:)
+          ENDDO
+       ENDDO
+          
+     ENDDO
+
+   ELSE IF (field(1)%ndim==4) THEN
+     n=0
+     DO ind=1,ndomain
+       d=>domain(ind)
+       CALL swap_dimensions(ind) 
+               
+       DO j=d%jj_begin+1,d%jj_end
+         DO i=d%ii_begin,d%ii_end-1
+           n=n+1
+           ij=iim*(j-1)+i
+           Field_tmp(n,:)=field(ind)%rval4d(ij+z_down,:,iq)
+         ENDDO
+       ENDDO
+
+       DO j=d%jj_begin,d%jj_end-1
+         DO i=d%ii_begin+1,d%ii_end
+           n=n+1
+           ij=iim*(j-1)+i
+           Field_tmp(n,:)=field(ind)%rval4d(ij+z_up,:,iq)
+          ENDDO
+       ENDDO
+          
+     ENDDO
+
+   ENDIF
+   
+   CALL xios_send_field(name,field_tmp)
+ 
+ END SUBROUTINE xios_write_field_vort 
+  
+ SUBROUTINE xios_write_field_finalize
+ IMPLICIT NONE
+
+!$OMP BARRIER
+!$OMP MASTER 
+   CALL xios_context_finalize
+!$OMP END MASTER
+!$OMP BARRIER
+
+ END SUBROUTINE xios_write_field_finalize
+
+ SUBROUTINE xios_set_context
+ IMPLICIT NONE   
+  TYPE(xios_context) :: ctx_hdl
+
+!$OMP MASTER 
+   CALL xios_get_handle("icosagcm",ctx_hdl)
+   CALL xios_set_current_context(ctx_hdl)
+!$OMP END MASTER
+
+  END SUBROUTINE xios_set_context
+#else
+  
+  SUBROUTINE xios_init
+   IMPLICIT NONE
+         
+    using_xios=.FALSE.
+    
+  END SUBROUTINE xios_init
+  
+  SUBROUTINE xios_write_field(name,field)
+  USE field_mod
+  IMPLICIT NONE 
+   CHARACTER(LEN=*),INTENT(IN) :: name
+   TYPE(t_field), POINTER :: field(:)
+  END SUBROUTINE xios_write_field
+ 
+  SUBROUTINE xios_update_calendar(step)
+  IMPLICIT NONE
+   INTEGER, INTENT(IN):: step  
+  END SUBROUTINE xios_update_calendar
+
+  SUBROUTINE xios_write_field_finalize
+  END SUBROUTINE xios_write_field_finalize
+  
+  SUBROUTINE xios_init_write_field
+  END SUBROUTINE xios_init_write_field  
+  
+  SUBROUTINE xios_set_context
+  END SUBROUTINE xios_set_context
+  
+
+#endif  
+  
+END MODULE xios_mod
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/COPYRIGHT.txt
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/COPYRIGHT.txt	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/COPYRIGHT.txt	(revision 329)
@@ -0,0 +1,109 @@
+!------------------------------------------------------------------------------!
+!              Flexible Configuration Management Software License              !
+!                                                                              !
+!     Please read this Software Licence as you will be bound by its terms      !
+!                           if you use the Software                            !
+!------------------------------------------------------------------------------!
+
+The Licensor:
+-------------
+
+The Met Office of FitzRoy Road, Exeter EX1 3PB, United Kingdom
+--------------------------------------------------------------------------------
+
+1. Licence.
+-----------
+
+The Met Office grants you a non-exclusive, royalty free; world-wide,
+transferable Licence to use, modify, copy and distribute the Flexible
+Configuration Management software ("the software") accompanying this License
+providing:
+
+a. you undertake to provide to the Met Office a copy of any modifications made
+   by you on the same terms contained within this licence agreement;
+
+b. modified files carry prominent notices stating that you changed the files
+   and the date of change;
+
+c. distribution of original or modified files is made free of charge under the
+   terms of this Licence;
+
+d. the appropriate copyright notices, the above copyright notice and a
+   disclaimer of warranty is included with the distribution.
+
+2. Ownership.
+-------------
+
+The Flexible Configuration Management software is Crown copyright and is
+reproduced with the permission of Met Office under delegated authority from
+the Controller of HMSO. The software and documentation are provided to you to
+allow you to exercise your rights under this License, which is granted to you.
+
+3. Duration.
+------------
+
+This license will remain in effect until terminated.
+ 
+4. Termination.
+---------------
+
+You may terminate this license at any time by removing all copies of the
+software from your system.  This License will terminate immediately without
+notice from us if you fail to comply with any of the provisions of this
+License or in the event of your breaching the terms of this licence you are
+given notice that the license has been terminated.  Upon termination you will
+delete all copies of the software and any related documentation.
+
+5. Disclaimer of Warranty.
+--------------------------
+
+a. THE MET OFFICE DISCLAIMS ALL WARRANTIES, REPRESENTATIONS AND PROMISES,
+   INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF SATISFACTORY QUALITY
+   AND FIT FOR THE PURPOSE.  NEITHER DOES THE MET OFFICE MAKE ANY
+   REPRESENTATIONS AS TO COMPATABILITY WITH YOUR OPERATING SYSTEMS AND
+   PLATFORMS.
+
+b. In no event does the Met Office warrant that the software or related
+   documentation will satisfy your requirements, that the software and
+   documentation will be without errors or defects or that the operation of
+   the software will be uninterrupted.
+
+c. IN NO EVENT WILL THE MET OFFICE BE LIABLE FOR ANY OTHER DAMAGES, INCLUDING
+   BUT NOT LIMITED TO DAMAGES FOR LOSS OF PROFITS DATA OR USE OF THE SOFTWARE
+   OR FOR ANY INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF THE MET
+   OFFICE HAS BEEN SPECIFICALLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+6. General Provisions.
+----------------------
+
+a. You will not do anything, relating to this software that will bring the Met
+   Office into disrepute.
+
+b. You will not use the name of the Met Office or any other contributor to
+   endorse or promote any products derived from the software without the
+   written permission of the Met Office.
+
+7. Acknowledgements.
+--------------------
+
+The Fortran 9X Interface Generator found in file
+./src/lib/Ecmwf/Fortran90_stuff.pm is adapted from a script developed at ECMWF
+and is provided by kind permission of ECMWF under the same terms of this
+Licence.
+
+8. Entire Agreement.
+--------------------
+
+This License constitutes the entire agreement between us with respect to your
+rights or warranties for using the software and related documentation.  If any
+provision of this agreement is determined to be invalid or unenforceable the
+remaining provisions shall continue in full force.
+
+9. Governing Law.
+-----------------
+
+This Agreement is governed by and construed in accordance with the Laws of
+England.
+
+--------------------------------------------------------------------------------
+                                                 © British Crown copyright 2006.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/LICENSE.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/LICENSE.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/LICENSE.html	(revision 329)
@@ -0,0 +1,150 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Flexible Configuration Management Software License</title>
+  <meta name="copyright" content="&copy; British Crown Copyright">
+  <style type="text/css">
+  <!--
+  body {
+    font: normal normal 10pt Arial, sans-serif;
+  }
+
+  h1 {
+    text-align: center;
+    text-decoration: underline;
+    font: normal bold 14pt Arial, sans-serif;
+  }
+
+  h2 {
+    text-align: left;
+    text-decoration: none;
+    font: normal normal 14pt Arial, sans-serif;
+  }
+
+  h3 {
+    text-align: left;
+    text-decoration: none;
+    font: normal bold 10pt Arial, sans-serif;
+  }
+
+  .copyright {
+    text-align: right;
+    font: normal bold 11pt Arial, sans-serif;
+  }
+
+  ol li {
+    list-style: lower-alpha;
+  }
+  //-->
+  </style>
+</head>
+
+<body>
+  <h1>Flexible Configuration Management Software License</h1>
+
+  <h1>Please read this Software Licence as you will be bound by its terms if
+  you use the Software</h1>
+
+  <h2>The Licensor:</h2>
+
+  <h2>The Met Office of FitzRoy Road, Exeter EX1 3PB, United Kingdom</h2>
+
+  <h3>1. Licence.</h3>
+
+  <p>The Met Office grants you a non-exclusive, royalty free; world-wide,
+  transferable Licence to use, modify, copy and distribute the Flexible
+  Configuration Management software ("the software") accompanying this License
+  providing:</p>
+
+  <ol>
+    <li>you undertake to provide to the Met Office a copy of any modifications
+    made by you on the same terms contained within this licence agreement;</li>
+
+    <li>modified files carry prominent notices stating that you changed the
+    files and the date of change;</li>
+
+    <li>distribution of original or modified files is made free of charge under
+    the terms of this Licence;</li>
+
+    <li>the appropriate copyright notices, the above copyright notice and a
+    disclaimer of warranty is included with the distribution.</li>
+  </ol>
+
+  <h3>2. Ownership.</h3>
+
+  <p>The Flexible Configuration Management software is Crown copyright and is
+  reproduced with the permission of Met Office under delegated authority from
+  the Controller of HMSO. The software and documentation are provided to you to
+  allow you to exercise your rights under this License, which is granted to
+  you.</p>
+
+  <h3>3. Duration.</h3>
+
+  <p>This license will remain in effect until terminated.</p>
+
+  <h3>4. Termination.</h3>
+
+  <p>You may terminate this license at any time by removing all copies of the
+  software from your system. This License will terminate immediately without
+  notice from us if you fail to comply with any of the provisions of this
+  License or in the event of your breaching the terms of this licence you are
+  given notice that the license has been terminated. Upon termination you will
+  delete all copies of the software and any related documentation.</p>
+
+  <h3>5. Disclaimer of Warranty.</h3>
+
+  <ol>
+    <li>THE MET OFFICE DISCLAIMS ALL WARRANTIES, REPRESENTATIONS AND PROMISES,
+    INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF SATISFACTORY QUALITY
+    AND FIT FOR THE PURPOSE. NEITHER DOES THE MET OFFICE MAKE ANY
+    REPRESENTATIONS AS TO COMPATABILITY WITH YOUR OPERATING SYSTEMS AND
+    PLATFORMS.</li>
+
+    <li>In no event does the Met Office warrant that the software or related
+    documentation will satisfy your requirements, that the software and
+    documentation will be without errors or defects or that the operation of
+    the software will be uninterrupted.</li>
+
+    <li>IN NO EVENT WILL THE MET OFFICE BE LIABLE FOR ANY OTHER DAMAGES,
+    INCLUDING BUT NOT LIMITED TO DAMAGES FOR LOSS OF PROFITS DATA OR USE OF THE
+    SOFTWARE OR FOR ANY INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF
+    THE MET OFFICE HAS BEEN SPECIFICALLY ADVISED OF THE POSSIBILITY OF SUCH
+    DAMAGES.</li>
+  </ol>
+
+  <h3>6. General Provisions.</h3>
+
+  <ol>
+    <li>You will not do anything, relating to this software that will bring the
+    Met Office into disrepute.</li>
+
+    <li>You will not use the name of the Met Office or any other contributor to
+    endorse or promote any products derived from the software without the
+    written permission of the Met Office.</li>
+  </ol>
+
+  <h3>7. Acknowledgements.</h3>
+
+  <p>The Fortran 9X Interface Generator found in file
+  ./src/lib/Ecmwf/Fortran90_stuff.pm is adapted from a script developed at
+  ECMWF and is provided by kind permission of ECMWF under the same terms of
+  this Licence.</p>
+
+  <h3>8. Entire Agreement.</h3>
+
+  <p>This License constitutes the entire agreement between us with respect to
+  your rights or warranties for using the software and related documentation.
+  If any provision of this agreement is determined to be invalid or
+  unenforceable the remaining provisions shall continue in full force.</p>
+
+  <h3>9. Governing Law.</h3>
+
+  <p>This Agreement is governed by and construed in accordance with the Laws of
+  England.</p>
+
+  <div class="copyright">
+    <p>&copy; British Crown copyright 2006.</p>
+  </div>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/README
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/README	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/README	(revision 329)
@@ -0,0 +1,4 @@
+FCM release 1-1 created from revision 1841
+
+For further details please refer to the release notes
+which can be found in the directory doc/release_notes.
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm	(revision 329)
@@ -0,0 +1,748 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm
+#
+# SYNOPSIS
+#   fcm SUBCOMMAND [OPTIONS...] ARGS...
+#
+# DESCRIPTION
+#   The fcm command is the frontend of the FCM system. The first argument to the
+#   command must be a recognised subcommand. See "fcm help" for a full list of
+#   functionalities.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use warnings;
+use strict;
+
+# Standard modules:
+use File::Basename;
+use File::Spec;
+use Getopt::Long;
+use Cwd;
+
+# FCM component modules:
+use lib File::Spec->catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Config;
+use Fcm::Extract;
+use Fcm::Build;
+use Fcm::Util;
+
+BEGIN {
+  eval {
+    require Fcm::Cm;
+    import Fcm::Cm;
+
+    require Fcm::CmUrl;
+    import Fcm::CmUrl;
+  }
+}
+
+# Function declaration:
+sub cmp_ext_cfg;
+sub invoke_build_system;
+sub invoke_extract_system;
+sub invoke_cfg_printer;
+sub invoke_cm_system;
+sub invoke_www_browser;
+sub invoke_help;
+
+# ------------------------------------------------------------------------------
+
+my $prog      = basename $0;
+my $year      = (localtime)[5] + 1900;
+my $copyright = <<EOF;
+
+(C) Crown copyright $year Met Office. All rights reserved.
+EOF
+
+# List of sub-commands recognised by FCM
+my %subcommand = (
+  HLP => [qw/help ? h/],
+  BLD => [qw/build bld/],
+  EXT => [qw/extract ext/],
+  CFG => [qw/cfg/],
+  GUI => [qw/gui/],
+  CM  => [qw/
+    branch    br
+    conflicts cf
+    add
+    blame     praise annotate ann
+    cat
+    checkout  co
+    cleanup
+    commit    ci
+    copy      cp
+    delete    del    remove   rm
+    diff      di
+    export
+    import
+    info
+    list      ls
+    lock
+    log
+    merge
+    mkdir
+    mkpatch
+    move      mv     rename   ren
+    propdel   pdel   pd
+    propedit  pedit  pe
+    propget   pget   pg
+    proplist  plist  pl
+    propset   pset   ps
+    resolved
+    revert
+    status    stat   st
+    switch    sw
+    unlock
+    update    up
+  /],
+  CMP => [qw/cmp-ext-cfg/],
+  WWW => [qw/www trac/],
+);
+
+# Get configuration settings
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+# Determine the functionality of this invocation of the command
+my $function = @ARGV ? shift @ARGV : '';
+
+# Run command accordingly
+if (grep {$_ eq $function} @{ $subcommand{BLD} }) {
+  invoke_build_system;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{EXT} }) {
+  invoke_extract_system;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{CFG} }) {
+  invoke_cfg_printer;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{GUI} }) {
+  &run_command (['fcm_gui', @ARGV], METHOD => 'exec');
+
+} elsif (grep {$_ eq $function} @{ $subcommand{CM} }) {
+  invoke_cm_system;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{CMP} }) {
+  cmp_ext_cfg;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{WWW} }) {
+  invoke_www_browser;
+
+} elsif ($function =~ /^\s*$/ or grep {$_ eq $function} @{ $subcommand{HLP} }) {
+  invoke_help;
+
+} else {
+  w_report 'Unknown command: ', $function;
+  e_report 'Type "', $prog, ' help" for usage';
+}
+
+exit;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &cmp_ext_cfg ();
+#
+# DESCRIPTION
+#   Compare two similar extract configuration files.
+# ------------------------------------------------------------------------------
+
+sub cmp_ext_cfg {
+  # Check options
+  # ----------------------------------------------------------------------------
+  my ($wiki);
+
+  GetOptions ('wiki|w=s' => \$wiki);
+
+  # Check arguments
+  # ----------------------------------------------------------------------------
+  e_report $prog, ' ', $function,
+           ': 2 extract config files must be specified, abort.'
+    if @ARGV < 2;
+
+  # Invoke 2 new instances of the Fcm::Extract class
+  # ----------------------------------------------------------------------------
+  my (@cfg, $rc);
+  for my $i (0 .. 1) {
+    $cfg[$i] = Fcm::Extract->new (CFG_SRC => $ARGV[$i]);
+
+    # Read the extract configuration file
+    $rc = $cfg[$i]->decipher_cfg;
+    $rc = $cfg[$i]->expand_cfg if $rc;
+
+    last if not $rc;
+  }
+
+  # Throw error if command has failed
+  # ----------------------------------------------------------------------------
+  e_report $prog, ' ', $function, ': failed.' if not $rc;
+
+  # Get list of URLs
+  # ----------------------------------------------------------------------------
+  my @urls = ();
+  for my $i (0 .. 1) {
+    # List of branches in each extract configuration file
+    my @branches = $cfg[$i]->branches;
+
+    for my $branch (@branches) {
+      # Ignore declarations of local directories
+      next if $branch->type eq 'user';
+
+      # List of SRC declarations in each branch
+      my %dirs = $branch->dirs;
+
+      for my $dir (values %dirs) {
+        # Set up a new instance of Fcm::CmUrl object for each SRC declaration
+        my $cm_url = Fcm::CmUrl->new (
+          URL => $dir . ($branch->version ? '@' . $branch->version : ''),
+        );
+
+        $urls[$i]{$cm_url->branch_url}{$dir} = $cm_url;
+      }
+    }
+  }
+
+  # Compare
+  # ----------------------------------------------------------------------------
+  my %log;
+  for my $i (0 .. 1) {
+    # Compare the first file with the second one and then vice versa
+    my $j = ($i == 0) ? 1 : 0;
+
+    for my $branch (sort keys %{ $urls[$i] }) {
+      if (exists $urls[$j]{$branch}) {
+        # Same REPOS declarations in both files
+        for my $dir (sort keys %{ $urls[$i]{$branch} }) {
+          if (exists $urls[$j]{$branch}{$dir}) {
+            # Same SRC declarations in both files, only need to compare once
+            next if $i == 1;
+
+            my $this_url = $urls[$i]{$branch}{$dir};
+            my $that_url = $urls[$j]{$branch}{$dir};
+
+            # Check whether their last changed revisions are the same
+            my $this_rev = $this_url->svninfo (FLAG => 'Last Changed Rev');
+            my $that_rev = $that_url->svninfo (FLAG => 'Last Changed Rev');
+
+            next if $this_rev eq $that_rev;
+
+            # Last changed revisions differ, get list of changed revisions
+            # between them using the commit log
+            my $u   = ($this_rev > $that_rev) ? $this_url : $that_url;
+            my %revs = $u->svnlog (REV => [$this_rev, $that_rev]);
+
+            for my $rev (keys %revs) {
+              $log{$branch}{$rev} = $u unless exists $log{$branch}{$rev};
+            }
+
+          } else {
+            # Report SRC declaration in one file but not in another
+            print $urls[$i]{$branch}{$dir}->url_peg, ':', "\n";
+            print '  in    : ', $ARGV[$i], "\n";
+            print '  not in: ', $ARGV[$j], "\n\n";
+          }
+        }
+
+      } else {
+        # Report REPOS declaration in one file but not in another
+        print $branch, ':', "\n";
+        print '  in    : ', $ARGV[$i], "\n";
+        print '  not in: ', $ARGV[$j], "\n\n";
+      }
+    }
+  }
+
+  # Report modifications
+  # ----------------------------------------------------------------------------
+  print 'Revisions at which declared source directories are modified:', "\n"
+    if keys %log;
+
+  if ($wiki) {
+    # Output in wiki format
+    my $wiki_url  = Fcm::CmUrl->new (URL => &expand_url_keyword (URL => $wiki));
+    my $base_trac = &get_browser_url (URL => $wiki_url->project_url);
+    $base_trac    = $wiki_url if not $base_trac;
+
+    for my $branch (sort keys %log) {
+      # Name of the branch
+      my $branch_trac = &get_browser_url (URL => $branch);
+      $branch_trac =~ s#^$base_trac(?:/*|$)#source:#;
+
+      print '[', $branch_trac, ']:', "\n";
+
+      # Revision table
+      for my $rev (sort {$b <=> $a} keys %{ $log{$branch} }) {
+        print $log{$branch}{$rev}->display_svnlog ($rev, $base_trac), "\n";
+      }
+    }
+
+  } else {
+    for my $branch (sort keys %log) {
+      # Output in plain text format
+      print $branch, ':', "\n";
+      print join (' ', sort {$b <=> $a} keys %{ $log{$branch} }), "\n\n";
+    }
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_build_system ();
+#
+# DESCRIPTION
+#   Invoke the build system.
+# ------------------------------------------------------------------------------
+
+sub invoke_build_system {
+  my ($archive, $full, $ignore_lock, $jobs, $stage, @targets, $verbose);
+
+  GetOptions (
+    'archive|a'   => \$archive,     # switch on archive mode?
+    'full|f'      => \$full,        # full build?
+    'ignore-lock' => \$ignore_lock, # ignore lock file?
+    'jobs|j=i'    => \$jobs,        # number of parallel jobs in make
+    'stage|s=s'   => \$stage,       # build up to and including this stage
+    'targets|t=s' => \@targets,     # make targets
+    'verbose|v=i' => \$verbose,     # verbose level
+  );
+
+  # Verbose level
+  $config->verbose ($verbose) if defined $verbose;
+
+  # Invoke a new instance of the Fcm::Build class
+  my $bld = Fcm::Build->new (CFG_SRC  => @ARGV ? join (' ', @ARGV) : cwd ());
+
+  # Perform build
+  $bld->build (
+    ARCHIVE     => $archive,
+    FULL        => $full,
+    IGNORE_LOCK => $ignore_lock,
+    JOBS        => $jobs ? $jobs : 1,
+    STAGE       => $stage ? $stage : 5,
+    TARGETS     => (@targets ? [split (/:/, join (':', @targets))] : [qw/all/]),
+  );
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_extract_system ();
+#
+# DESCRIPTION
+#   Invoke the extract system.
+# ------------------------------------------------------------------------------
+
+sub invoke_extract_system {
+  my ($full, $ignore_lock, $verbose);
+
+  GetOptions (
+    'full|f'      => \$full,        # full extract?
+    'ignore-lock' => \$ignore_lock, # ignore lock file?
+    'verbose|v=i' => \$verbose,     # verbose level
+  );
+
+  $config->verbose ($verbose) if defined $verbose;
+
+  # Invoke a new instance of the Fcm::Extract class
+  my $ext = Fcm::Extract->new (CFG_SRC => @ARGV ? join (' ', @ARGV) : cwd ());
+
+  # Perform extract
+  $ext->extract (FULL => $full, IGNORE_LOCK => $ignore_lock);
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_cfg_printer ();
+#
+# DESCRIPTION
+#   Invoke the CFG file pretty printer.
+# ------------------------------------------------------------------------------
+
+sub invoke_cfg_printer {
+
+  use Fcm::CfgFile;
+
+  my $out_file;
+  GetOptions (
+    'output|o=s'  => \$out_file,  # output file for print
+  );
+
+  my $file = join (' ', @ARGV);
+  e_report $prog, ' ', $function, ': file not specified, abort.' if ! $file;
+
+  # Invoke a new Fcm::CfgFile instance
+  my $cfg = Fcm::CfgFile->new (SRC => $file);
+
+  # Read the cfg file
+  my $read = $cfg->read_cfg;
+  e_report if not $read;
+
+  # Pretty print CFG file
+  $cfg->print_cfg ($out_file);
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_cm_system ();
+#
+# DESCRIPTION
+#   Invoke a code management system command.
+# ------------------------------------------------------------------------------
+
+sub invoke_cm_system {
+
+  &cm_command ($function);
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_www_browser ();
+#
+# DESCRIPTION
+#   Invoke a web browser on the specified PATH.
+# ------------------------------------------------------------------------------
+
+sub invoke_www_browser {
+
+  # Options
+  my ($browser);
+  GetOptions (
+    'browser|b=s' => \$browser, # browser command
+  );
+
+  $browser = &cfg->setting (qw/MISC WEB_BROWSER/) unless $browser;
+
+  # Arguments
+  my ($arg) = @ARGV ? $ARGV[0] : (&is_wc () ? '.' : '');
+  e_report $prog, ' ', $function,
+           ': input URL not specified and . not a working copy, abort.'
+    if not $arg;
+
+  # Local PATH?
+  $arg = &expand_tilde ($arg);
+  $arg = &get_url_of_wc ($arg) if -e $arg;
+
+  # Expand URL and revision keywords
+  my $www_url = &expand_url_keyword (URL => $arg);
+  my $rev     = 'HEAD';
+
+  if ($www_url =~ m#^(\w+://\S+)@(\S+)$#) {
+    $www_url = $1;
+    $rev     = $2;
+  }
+
+  $rev = &expand_rev_keyword (URL => $www_url, REV => $rev, HEAD => 1)
+    unless uc ($rev) eq 'HEAD';
+
+  # Get web browser URL
+  $www_url = &get_browser_url (URL => $www_url);
+  die 'WWW URL not defined for "', $arg, '", abort' unless $www_url;
+
+  $www_url = $www_url . '?rev=' . $rev;
+
+  # Execute command
+  my @command = (split (/\s+/, $browser), $www_url);
+  &run_command (\@command, METHOD => 'exec', PRINT => 1);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_help ();
+#
+# DESCRIPTION
+#   Invoke help.
+# ------------------------------------------------------------------------------
+
+sub invoke_help {
+
+  my $cmd = @ARGV ? shift @ARGV : undef;
+
+  if ($cmd) {
+    if (grep {$_ eq $cmd} @{ $subcommand{BLD} }) {
+      print <<EOF;
+$prog $cmd: invoke the build system.
+usage: $prog $cmd [OPTIONS...] [CFGFILE]
+
+  The path to a CFG file may be provided. Otherwise, the build system
+  searches the default locations for a bld cfg file.
+
+  If no option is specified, the options "-s 5 -t all -j 1 -v 1" are assumed.
+
+  If the option for full build is specified, the sub-directories created by
+  previous builds will be removed, so that the current build can start cleanly.
+
+  The -s option can be used to limit the actions performed by the build system
+  up to a named stage. The stages are:
+    "1", "s" or "setup"                - stage 1, setup
+    "2", "pp" or "pre_process"         - stage 2, pre-process
+    "3", "gd" or "generate_dependency" - stage 3, generate dependency
+    "4", "gi" or "generate_interface"  - stage 4, generate Fortran 9X interface
+    "5", "m", "make"                   - stage 5, make
+
+  If a colon separated list of targets is specified using the -t option, the
+  default targets specified in the configuration file will not be used.
+
+  If archive mode is switched on, build sub-directories that are only used
+  in the build process will be archived to TAR files. The default is off.
+
+  If specified, the verbose level must be an integer greater than 0. Verbose
+  level 0 is the quiet mode. Increasing the verbose level will increase the
+  amount of diagnostic output.
+
+  When a build is invoked, it sets up a lock file in the build root directory.
+  The lock is normally removed at the end of the build. While the lock file is
+  in place, othe build commands invoked in the same root directory will fail.
+  If you need to bypass this check for whatever reason, you can invoke the
+  build system with the --ignore-lock option.
+
+Valid options:
+  -a [--archive]     : archive build sub-directories?
+  -f [--full]        : full build
+  --ignore-lock      : ignore lock files in build root directory
+  -j [--jobs] arg    : number of parallel jobs that "make" can handle
+  -s [--stage] arg   : perform build up to a named stage
+  -t [--targets] arg : build a colon (:) separated list of targets
+  -v [--verbose] arg : verbose level
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{EXT} }) {
+      print <<EOF;
+$prog $cmd: invoke the extract system.
+usage: $prog $cmd [OPTIONS...] [CFGFILE]
+
+  The path to a CFG file may be provided. Otherwise, the extract system
+  searches the default locations for an ext cfg file.
+
+  If no option is specified, the system will attempt an incremental extract
+  where appropriate.
+
+  If specified, the verbose level must be an integer greater than 0. Verbose
+  level 0 is the quiet mode. Increasing the verbose level will increase the
+  amount of diagnostic output.
+
+  When an extract is invoked, it sets up a lock file in the extract destination
+  root directory. The lock is normally removed at the end of the extract. While
+  the lock file is in place, othe extract commands invoked in the same
+  destination root directory will fail. If you need to bypass this check for
+  whatever reason, you can invoke the extract system with the --ignore-lock
+  option.
+
+Valid options:
+  -f [--full]        : perform a full/clean extract
+  --ignore-lock      : ignore lock files in build root directory
+  -v [--verbose] arg : verbose level
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{CFG} }) {
+      print <<EOF;
+$prog $cmd: invoke the CFG file pretty printer.
+usage: $prog $cmd [OPTIONS...] FILE
+
+  If no option is specified, the output will be sent to standard output.
+
+Valid options:
+  -o [--output] arg : send output to a file as specified by arg.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{GUI} }) {
+      print <<EOF;
+$prog $cmd: invoke the GUI wrapper for CM commands.
+usage: $prog $cmd DIR
+
+  The optional argument DIR modifies the initial working directory.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{CM} }) {
+      @ARGV = qw(--help);
+      cm_command ($cmd);
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{CMP} }) {
+      print <<EOF;
+$prog $cmd: compare two similar extract configuration files.
+usage: $prog $cmd [OPTIONS...] CFG1 CFG2
+
+  Compares the extract configurations of two similar extract configuration
+  files CFG1 and CFG2.
+
+Valid options:
+  -w [--wiki] arg : print revision tables in wiki format. The argument to this
+                    option must be the Subversion URL or FCM URL keyword of a
+                    FCM project associated with the intended Trac system.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{WWW} }) {
+      print <<EOF;
+$prog $cmd: invoke the web repository browser on a Subversion URL.
+usage: $prog $cmd [OPTIONS...] [PATH]
+
+  If PATH is specified, it must be a FCM URL keyword, a Subversion URL or the
+  PATH to a local working copy. If not specified, the current working directory
+  is assumed to be a working copy. If the --browser option is specified, the
+  specified web browser command is used to launch the repository browser.
+  Otherwise, it attempts to use the default browser from the configuration
+  setting.
+
+Valid options:
+  -b [--browser] arg : specify a command arg for the web browser.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{HLP} }) {
+      print <<EOF;
+help (?, h): Describe the usage of $prog or its subcommands.
+usage: $prog help [SUBCOMMAND...]
+$copyright
+EOF
+
+      &run_command ([qw/svn help/, $cmd, @ARGV], PRINT => 1);
+
+    } else {
+      warn $prog, ' help: "', $cmd, '" not recognised';
+      $cmd = undef;
+    }
+  }
+
+  if (not $cmd) {
+    # Get output from "svn help"
+    my @lines = &run_command (
+      [qw/svn help/], DEVNULL => 1, METHOD => 'qx', ERROR => 'ignore',
+    );
+
+    # Get release number, (and revision number from revision number file)
+    my $release  = &cfg->setting ('RELEASE');
+    my $rev_file = &cfg->setting ('REV_FILE');
+
+    if (-r $rev_file) {
+      open FILE, '<', $rev_file;
+      my $rev = readline 'FILE';
+      close FILE;
+
+      chomp $rev;
+      $release .= ' (r' . $rev . ')' if $rev;
+    }
+
+    # Print common help
+    print <<EOF;
+usage: $prog <subcommand> [options] [args]
+Flexible configuration management system, release $release.
+Type "$prog help <subcommand>" for help on a specific subcommand.
+
+Available subcommands:
+  help       (h, ?) - help
+  build      (bld)  - build system
+EOF
+
+    # The following are only available on platforms with "svn" installed
+    if (@lines) {
+      print <<EOF;
+  branch     (br)   - cm system: branch info & creation
+  cfg               - CFG file pretty printer
+  cmp-ext-cfg       - compare two similar extract configuration files
+  conflicts  (cf)   - cm system: resolve conflicts
+  extract    (ext)  - extract system
+  mkpatch           - create patches from specified revisions of a URL
+  trac       (www)  - cm system: browse a path using the web browser
+  <SVN COMMANDS>    - any Subversion sub-commands
+EOF
+    }
+
+    # Print FCM copyright notice
+    print $copyright;
+
+    # Print output from "svn help"
+    if (@lines) {
+      print "\n";
+      &print_command ([qw/svn help/]);
+      print @lines;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ans = &main::get_input (MESSAGE => $mesg, TYPE => $type, DEFAULT => $def);
+#
+# DESCRIPTION
+#   Get an input string from the user and return it as $ans. MESSAGE is the
+#   main message printed on screen to prompt the user for an input.  If TYPE is
+#   'YN', print message to prompt user to enter either 'y' or 'n'. If TYPE is
+#   'YNA', then 'a' is given as a third option. If DEFAULT is set, print message
+#   to inform user that the return value will be set to the $def (if nothing is
+#   entered).
+# ------------------------------------------------------------------------------
+
+sub get_input {
+  my %args = @_;
+  my $type  = exists $args{TYPE}    ? $args{TYPE}    : '';
+  my $mesg  = exists $args{MESSAGE} ? $args{MESSAGE} : '';
+  my $def   = exists $args{DEFAULT} ? $args{DEFAULT} : '';
+
+  my $ans;
+
+  while (1) {
+    # Print the prompt
+    print $mesg;
+    print "\n", 'Enter "y" or "n"' if uc ($type) eq 'YN';
+    print "\n", 'Enter "y", "n" or "a"' if uc ($type) eq 'YNA';
+    print ' (or just press <return> for "', $def, '")' if $def;
+    print ': ';
+
+    # Get answer from STDIN
+    $ans = <STDIN>;
+    chomp $ans;
+
+    # Set answer to default, if necessary
+    $ans = $def if ($def and not $ans);
+
+    if ($type =~ /^yna?$/i) {
+      # For YN and YNA type dialog boxes,
+      # check that the answer is in the correct form
+      my $pat = (uc ($type) eq 'YN' ? 'y|n' : 'y|n|a');
+      last if $ans =~ /^(?:$pat)/i;
+
+    } else {
+      last;
+    }
+  }
+
+  return $ans;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_gui
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_gui	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_gui	(revision 329)
@@ -0,0 +1,1321 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_gui
+#
+# SYNOPSIS
+#   fcm_gui [DIR]
+#
+# DESCRIPTION
+#   The fcm_gui command is a simple graphical user interface for some of the
+#   commands of the FCM system. The optional argument DIR modifies the initial
+#   working directory.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use warnings;
+use strict;
+
+# Standard modules
+use File::Basename;
+use File::Spec::Functions;
+use Cwd;
+use Tk;
+use Tk::ROText;
+
+# FCM component modules:
+use lib catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Config;
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+
+# Argument
+if (@ARGV) {
+  my $dir = shift @ARGV;
+  chdir $dir if -d $dir;
+}
+
+# Get configuration settings
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+# ------------------------------------------------------------------------------
+
+# FCM subcommands
+my @subcmds = qw/CHECKOUT BRANCH STATUS DIFF ADD DELETE MERGE CONFLICTS COMMIT
+                 UPDATE SWITCH/;
+
+# Subcommands allowed when CWD is not a WC
+my @nwc_subcmds = qw/CHECKOUT BRANCH/;
+
+# Subcommands allowed, when CWD is a WC
+my @wc_subcmds = qw/STATUS BRANCH DIFF ADD DELETE MERGE CONFLICTS COMMIT UPDATE
+                    SWITCH/;
+
+# Subcommands that apply to WC only
+my @wco_subcmds = qw/BRANCH STATUS DIFF ADD DELETE MERGE CONFLICTS COMMIT UPDATE
+                     SWITCH/;
+
+# Subcommands that apply to top level WC only
+my @wcto_subcmds = qw/BRANCH MERGE COMMIT UPDATE SWITCH/;
+
+# Selected subcommand
+my $selsubcmd = '';
+
+# Selected subcommand is running?
+my $cmdrunning = 0;
+
+# PID of running subcommand
+my $cmdpid = undef;
+
+# List of subcommand frames
+my %subcmd_f;
+
+# List of subcommand buttons
+my %subcmd_b;
+
+# List of subcommand button help strings
+my %subcmd_help = (
+  BRANCH    => 'list information about, create or delete a branch.',
+  CHECKOUT  => 'check out a working copy from a repository.',
+  STATUS    => 'print the status of working copy files and directories.',
+  DIFF      => 'display the differences in modified files.',
+  ADD       => 'put files and directories under version control.',
+  DELETE    => 'remove files and directories from version control.',
+  MERGE     => 'merge changes into your working copy.',
+  CONFLICTS => 'use "xxdiff" to resolve any conflicts within your working copy.',
+  COMMIT    => 'send changes from your working copy to the repository.',
+  UPDATE    => 'bring changes from the repository into your working copy.',
+  SWITCH    => 'update your working copy to a different URL.',
+);
+
+for (keys %subcmd_help) {
+  $subcmd_help{$_} = 'Select the "' . lc ($_) . '" sub-command - ' .
+                     $subcmd_help{$_};
+}
+
+# List of subcommand button bindings (key name and underline position)
+my %subcmd_bind = (
+  BRANCH    => {KEY => '<Alt-Key-b>', U => 0},
+  CHECKOUT  => {KEY => '<Alt-Key-o>', U => 5},
+  STATUS    => {KEY => '<Alt-Key-s>', U => 0},
+  DIFF      => {KEY => '<Alt-Key-d>', U => 0},
+  ADD       => {KEY => '<Alt-Key-a>', U => 0},
+  DELETE    => {KEY => '<Alt-Key-t>', U => 4},
+  MERGE     => {KEY => '<Alt-Key-m>', U => 0},
+  CONFLICTS => {KEY => '<Alt-Key-f>', U => 3},
+  COMMIT    => {KEY => '<Alt-Key-c>', U => 0},
+  UPDATE    => {KEY => '<Alt-Key-u>', U => 0},
+  SWITCH    => {KEY => '<Alt-Key-w>', U => 1},
+);
+
+# List of subcommand variables
+my %subcmdvar = (
+  CWD       => cwd (),
+  WCT       => '',
+  CWD_URL   => '',
+  WCT_URL   => '',
+
+  BRANCH    => {
+    OPT     => 'info',
+    URL     => '',
+    NAME    => '',
+    TYPE    => 'DEV::USER',
+    REVFLAG => 'NORMAL',
+    REV     => '',
+    TICKET  => '',
+    SRCTYPE => 'trunk',
+    S_CHD   => 0,
+    S_SIB   => 0,
+    S_OTH   => 0,
+    VERBOSE => 0,
+    OTHER   => '',
+  },
+
+  CHECKOUT  => {
+    URL     => '',
+    REV     => 'HEAD',
+    PATH    => '',
+    OTHER   => '',
+  },
+
+  STATUS    => {
+    USEWCT  => 0,
+    UPDATE  => 0,
+    VERBOSE => 0,
+    OTHER   => '',
+  },
+
+  DIFF      => {
+    USEWCT  => 0,
+    GRAPHIC => 1,
+    BRANCH  => 0,
+    URL     => '',
+    OTHER   => '',
+  },
+
+  ADD       => {
+    USEWCT  => 0,
+    CHECK   => 1,
+    OTHER   => '',
+  },
+
+  DELETE    => {
+    USEWCT  => 0,
+    CHECK   => 1,
+    OTHER   => '',
+  },
+
+  MERGE     => {
+    USEWCT  => 1,
+    SRC     => '',
+    MODE    => 'automatic',
+    DRYRUN  => 0,
+    VERBOSE => 0,
+    REV     => '',
+    OTHER   => '',
+  },
+
+  CONFLICTS => {
+    USEWCT  => 0,
+    OTHER   => '',
+  },
+
+  COMMIT    => {
+    USEWCT  => 1,
+    DRYRUN  => 0,
+    OTHER   => '',
+  },
+
+  UPDATE    => {
+    USEWCT  => 1,
+    OTHER   => '',
+  },
+
+  SWITCH    => {
+    USEWCT  => 1,
+    URL     => '',
+    OTHER   => '',
+  },
+);
+
+# List of action buttons
+my %action_b;
+
+# List of action button help strings
+my %action_help = (
+  QUIT  => 'Quit fcm gui',
+  HELP  => 'Print help to the output text box for the selected sub-command',
+  CLEAR => 'Clear the output text box',
+  RUN   => 'Run the selected sub-command',
+);
+
+# List of action button bindings
+my %action_bind = (
+  QUIT  => {KEY => '<Control-Key-q>', U => undef},
+  HELP  => {KEY => '<F1>'           , U => undef},
+  CLEAR => {KEY => '<Alt-Key-l>'    , U => 1},
+  RUN   => {KEY => '<Alt-Key-r>'    , U => 0},
+);
+
+# List of branch subcommand options
+my %branch_opt = (
+  INFO   => undef,
+  CREATE => undef,
+  DELETE => undef,
+  LIST   => undef,
+);
+
+# List of branch create types
+my %branch_type = (
+  'DEV::USER'   => undef,
+  'DEV::SHARE'  => undef,
+  'TEST::USER'  => undef,
+  'TEST::SHARE' => undef,
+  'PKG::USER'   => undef,
+  'PKG::SHARE'  => undef,
+  'PKG::CONFIG' => undef,
+  'PKG::REL'    => undef,
+);
+
+# List of branch create source type
+my %branch_srctype = (
+  TRUNK  => undef,
+  BRANCH => undef,
+);
+
+# List of branch create revision prefix option
+my %branch_revflag = (
+  NORMAL => undef,
+  NUMBER => undef,
+  NONE   => undef,
+);
+
+# List of branch info/delete options
+my %branch_info_opt = (
+  S_CHD   => 'Show children',
+  S_SIB   => 'Show siblings',
+  S_OTH   => 'Show other',
+  VERBOSE => 'Print extra information',
+);
+
+# Text in the status bar
+my $statustext = '';
+
+# ------------------------------------------------------------------------------
+
+my $mw = MainWindow->new ();
+
+my $mw_title = 'FCM GUI';
+$mw->title ($mw_title);
+
+# Frame containing subcommand selection buttons
+my $top_f = $mw->Frame ()->grid (
+  '-row'    => 0,
+  '-column' => 0,
+  '-sticky' => 'w',
+);
+
+# Frame containing subcommand options
+my $mid_f = $mw->Frame ()->grid (
+  '-row'    => 1,
+  '-column' => 0,
+  '-sticky' => 'ew',
+);
+
+# Frame containing action buttons
+my $bot_f = $mw->Frame ()->grid (
+  '-row'    => 2,
+  '-column' => 0,
+  '-sticky' => 'ew',
+);
+
+# Text box to display output
+my $out_t  = $mw->Scrolled ('ROText', '-scrollbars' => 'osow')->grid (
+  '-row'    => 3,
+  '-column' => 0,
+  '-sticky' => 'news',
+);
+
+# Text box - allow scroll with mouse wheel
+$out_t->bind (
+  '<4>' => sub {
+    $_[0]->yview ('scroll', -1, 'units') unless $Tk::strictMotif;
+  },
+);
+
+$out_t->bind (
+  '<5>' => sub {
+    $_[0]->yview ('scroll', +1, 'units') unless $Tk::strictMotif;
+  },
+);
+
+# Status bar
+$mw->Label (
+  '-textvariable' => \$statustext,
+  '-relief'       => 'groove',
+)->grid (
+  '-row'    => 4,
+  '-column' => 0,
+  '-sticky' => 'ews',
+);
+
+# Main window grid configure
+{
+  my ($cols, $rows) = $mw->gridSize ();
+  $mw->gridColumnconfigure ($_, '-weight' => 1) for (0 .. $cols - 1);
+  $mw->gridRowconfigure    ( 3, '-weight' => 1);
+}
+
+# Frame grid configure
+{
+  my ($cols, $rows) = $mid_f->gridSize ();
+  $bot_f->gridColumnconfigure (3, '-weight' => 1);
+}
+
+$mid_f->gridRowconfigure    (0, '-weight' => 1);
+$mid_f->gridColumnconfigure (0, '-weight' => 1);
+
+# ------------------------------------------------------------------------------
+
+# Buttons to select subcommands
+{
+  my $col = 0;
+  for my $name (@subcmds) {
+    $subcmd_b{$name} = $top_f->Button (
+      '-text'    => uc (substr ($name, 0, 1)) . lc (substr ($name, 1)),
+      '-command' => [\&button_clicked, $name],
+      '-width'   => 8,
+    )->grid (
+      '-row'    => 0,
+      '-column' => $col++,
+      '-sticky' => 'w',
+    );
+
+    $subcmd_b{$name}->bind ('<Enter>', sub {$statustext = $subcmd_help{$name}});
+    $subcmd_b{$name}->bind ('<Leave>', sub {$statustext = ''});
+
+    $subcmd_b{$name}->configure ('-underline' => $subcmd_bind{$name}{U})
+      if defined $subcmd_bind{$name}{U};
+
+    $mw->bind ($subcmd_bind{$name}{KEY}, sub {$subcmd_b{$name}->invoke});
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+# Frames to contain subcommands options
+{
+  my %row = ();
+
+  for my $name (@subcmds) {
+    $subcmd_f{$name} = $mid_f->Frame ();
+    $subcmd_f{$name}->gridColumnconfigure (1, '-weight' => 1);
+
+    $row{$name} = 0;
+
+    # Widgets common to all sub-commands
+    $subcmd_f{$name}->Label ('-text' => 'Current working directory: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Label ('-textvariable' => \($subcmdvar{CWD}))->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'w',
+    );
+  }
+
+  # Widgets common to all sub-commands that apply to working copies
+  for my $name (@wco_subcmds) {
+    my @labtxts = (
+      'Corresponding URL: ',
+      'Working copy top: ',
+      'Corresponding URL: ',
+    );
+    my @varrefs = \(
+      $subcmdvar{URL_CWD},
+      $subcmdvar{WCT},
+      $subcmdvar{URL_WCT},
+    );
+
+    for my $i (0 .. $#varrefs) {
+      $subcmd_f{$name}->Label ('-text' => $labtxts[$i])->grid (
+        '-row'    => $row{$name},
+        '-column' => 0,
+        '-sticky' => 'w',
+      );
+      $subcmd_f{$name}->Label ('-textvariable' => $varrefs[$i])->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+    }
+
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Apply sub-command to working copy top',
+      '-variable' => \($subcmdvar{$name}{USEWCT}),
+      '-state'    => (grep ({$_ eq $name} @wcto_subcmds) ? 'disabled' : 'normal'),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+  }
+
+  # Widget for the Branch sub-command
+  {
+    my $name = 'BRANCH';
+
+    # Radio buttons to select the sub-option of the branch sub-command
+    my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    my $col = 0;
+    for my $key (sort keys %branch_opt) {
+      my $opt = lc $key;
+
+      $branch_opt{$key} = $opt_f->Radiobutton (
+        '-text'     => $opt,
+        '-value'    => $opt,
+        '-variable' => \($subcmdvar{$name}{OPT}),
+        '-state'    => 'normal',
+      )->grid (
+        '-row'      => 0,
+        '-column'   => $col++,
+        '-sticky'   => 'w',
+      );
+    }
+
+    # Label and entry box for specifying URL
+    $subcmd_f{$name}->Label ('-text' => 'URL: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{URL}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and entry box for specifying create branch name
+    $subcmd_f{$name}->Label (
+      '-text' => 'Branch name (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{NAME}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and entry box for specifying create branch source revision
+    $subcmd_f{$name}->Label (
+      '-text' => 'Source revision (create/list only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{REV}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and radio buttons box for specifying create branch type
+    $subcmd_f{$name}->Label (
+      '-text' => 'Branch type (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (sort keys %branch_type) {
+        my $txt = lc $key;
+        my $opt = $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{TYPE}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Label and radio buttons box for specifying create source type
+    $subcmd_f{$name}->Label (
+      '-text' => 'Source type (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (sort keys %branch_srctype) {
+        my $txt = lc $key;
+        my $opt = lc $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{SRCTYPE}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Label and radio buttons box for specifying create prefix option
+    $subcmd_f{$name}->Label (
+      '-text' => 'Prefix option (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (sort keys %branch_revflag) {
+        my $txt = lc $key;
+        my $opt = $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{REVFLAG}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Label and entry box for specifying ticket number
+    $subcmd_f{$name}->Label (
+      '-text' => 'Related Trac ticket(s) (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{TICKET}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Check button for info/delete
+    # --show-children, --show-siblings, --show-other, --verbose
+    $subcmd_f{$name}->Label (
+      '-text' => 'Options for info/delete only: ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+
+      for my $key (sort keys %branch_info_opt) {
+        $opt_f->Checkbutton (
+          '-text'     => $branch_info_opt{$key},
+          '-variable' => \($subcmdvar{$name}{$key}),
+        )->grid (
+          '-row'    => 0,
+          '-column' => $col++,
+          '-sticky' => 'w',
+        );
+      }
+    }
+  }
+
+  # Widget for the Checkout sub-command
+  {
+    my $name = 'CHECKOUT';
+
+    # Label and entry boxes for specifying URL and revision
+    my @labtxts = (
+      'URL: ',
+      'Revision: ',
+      'Path: ',
+    );
+    my @varrefs = \(
+      $subcmdvar{$name}{URL},
+      $subcmdvar{$name}{REV},
+      $subcmdvar{$name}{PATH},
+    );
+
+    for my $i (0 .. $#varrefs) {
+      $subcmd_f{$name}->Label ('-text' => $labtxts[$i])->grid (
+        '-row'    => $row{$name},
+        '-column' => 0,
+        '-sticky' => 'w',
+      );
+      $subcmd_f{$name}->Entry (
+        '-textvariable' => $varrefs[$i],
+      )->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'ew',
+      );
+    }
+  }
+
+  # Widget for the Status sub-command
+  {
+    my $name = 'STATUS';
+
+    # Checkbuttons for various options
+    my @labtxts = (
+      'Display update information',
+      'Print extra information',
+    );
+    my @varrefs = \(
+      $subcmdvar{$name}{UPDATE},
+      $subcmdvar{$name}{VERBOSE},
+    );
+
+    for my $i (0 .. $#varrefs) {
+      $subcmd_f{$name}->Checkbutton (
+        '-text'     => $labtxts[$i],
+        '-variable' => $varrefs[$i],
+      )->grid (
+        '-row'        => $row{$name}++,
+        '-column'     => 0,
+        '-columnspan' => 2,
+        '-sticky'     => 'w',
+      );
+    }
+  }
+
+  # Widget for the Diff sub-command
+  {
+    my $name = 'DIFF';
+
+    # Checkbuttons for various options
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Use xxdiff to display differences',
+      '-variable' => \($subcmdvar{$name}{GRAPHIC}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    my $entry;
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Show differences relative to the base of the branch',
+      '-variable' => \($subcmdvar{$name}{BRANCH}),
+      '-command'  => sub {
+        $entry->configure (
+          '-state' => ($subcmdvar{$name}{BRANCH} ? 'normal' : 'disabled'),
+        );
+      },
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    $subcmd_f{$name}->Label ('-text' => 'Branch URL')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    $entry = $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{URL}),
+      '-state'        => ($subcmdvar{$name}{BRANCH} ? 'normal' : 'disabled'),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+
+  # Widget for the Add/Delete sub-command
+  for my $name (qw/ADD DELETE/) {
+
+    # Checkbuttons for various options
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Check for files or directories not under version control',
+      '-variable' => \($subcmdvar{$name}{CHECK}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+  }
+
+  # Widget for the Merge sub-command
+  {
+    my $name = 'MERGE';
+
+    # Label and radio buttons box for specifying merge mode
+    $subcmd_f{$name}->Label (
+      '-text' => 'Mode: ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (qw/automatic custom reverse/) {
+        my $txt = lc $key;
+        my $opt = $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{MODE}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Check buttons for dry-run
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Dry run',
+      '-variable' => \($subcmdvar{$name}{DRYRUN}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    # Check buttons for verbose mode
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Print extra information',
+      '-variable' => \($subcmdvar{$name}{VERBOSE}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    # Label and entry boxes for specifying merge source
+    $subcmd_f{$name}->Label (
+      '-text' => 'Source (automatic/custom only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{SRC}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and entry boxes for specifying merge revision (range)
+    $subcmd_f{$name}->Label (
+      '-text' => 'Revision (custom/reverse only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{REV}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+
+  # Widget for the Commit sub-command
+  {
+    my $name = 'COMMIT';
+
+    # Checkbuttons for various options
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Dry run',
+      '-variable' => \($subcmdvar{$name}{DRYRUN}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+  }
+
+  # Widget for the Switch sub-command
+  {
+    my $name = 'SWITCH';
+
+    # Label and entry boxes for specifying switch URL
+    $subcmd_f{$name}->Label ('-text' => 'URL: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{URL}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+
+  # Widgets common to all sub-commands
+  for my $name (@subcmds) {
+    $subcmd_f{$name}->Label ('-text' => 'Other options: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{OTHER}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+# Buttons to perform main actions
+{
+  my $col = 0;
+  for my $name (qw/QUIT HELP CLEAR RUN/) {
+    $action_b{$name} = $bot_f->Button (
+      '-text'    => uc (substr ($name, 0, 1)) . lc (substr ($name, 1)),
+      '-command' => [\&button_clicked, $name],
+      '-width'   => 8,
+    )->grid (
+      '-row'    => 0,
+      '-column' => $col++,
+      '-sticky' => ($name eq 'RUN' ? 'ew' : 'w'),
+    );
+
+    $action_b{$name}->bind ('<Enter>', sub {$statustext = $action_help{$name}});
+    $action_b{$name}->bind ('<Leave>', sub {$statustext = ''});
+
+    $action_b{$name}->configure ('-underline' => $action_bind{$name}{U})
+      if defined $action_bind{$name}{U};
+
+    $mw->bind ($action_bind{$name}{KEY}, sub {$action_b{$name}->invoke});
+  }
+}
+
+&change_cwd ($subcmdvar{CWD});
+
+# ------------------------------------------------------------------------------
+
+# Handle the situation when the user attempts to quit the window while a
+# sub-command is running
+
+$mw->protocol ('WM_DELETE_WINDOW', sub {
+  if (defined $cmdpid) {
+    my $ans = $mw->messageBox (
+      '-title'   => $mw_title,
+      '-message' => $selsubcmd . ' is still running. Really quit?',
+      '-type'    => 'YesNo',
+      '-default' => 'No',
+    );
+
+    if ($ans eq 'Yes') {
+      kill 9, $cmdpid; # Need to kill the sub-process before quitting
+
+    } else {
+      return; # Do not quit
+    }
+  }
+
+  exit;
+});
+
+MainLoop;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &change_cwd ($dir);
+#
+# DESCRIPTION
+#   Change current working directory to $dir
+# ------------------------------------------------------------------------------
+
+sub change_cwd {
+  my $dir = $_[0];
+  my @allowed_subcmds = (&is_wc ($dir) ? @wc_subcmds : @nwc_subcmds);
+
+  for my $subcmd (@subcmds) {
+    if (grep {$_ eq $subcmd} @allowed_subcmds) {
+      $subcmd_b{$subcmd}->configure ('-state' => 'normal');
+
+    } else {
+      $subcmd_b{$subcmd}->configure ('-state' => 'disabled');
+    }
+  }
+
+  &display_subcmd_frame ($allowed_subcmds[0])
+    if not grep {$_ eq $selsubcmd} @allowed_subcmds;
+
+  chdir $dir;
+  $subcmdvar{CWD} = $dir;
+
+  if (&is_wc ($dir)) {
+    $subcmdvar{WCT}     = &get_wct ($dir);
+    $subcmdvar{URL_CWD} = &get_url_of_wc ($dir);
+    $subcmdvar{URL_WCT} = &get_url_of_wc ($subcmdvar{WCT});
+
+    $branch_opt{INFO}  ->configure ('-state' => 'normal');
+    $branch_opt{DELETE}->configure ('-state' => 'normal');
+    $subcmdvar{BRANCH}{OPT} = 'info';
+
+  } else {
+    $branch_opt{INFO}  ->configure ('-state' => 'disabled');
+    $branch_opt{DELETE}->configure ('-state' => 'disabled');
+    $subcmdvar{BRANCH}{OPT} = 'create';
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &button_clicked ($name);
+#
+# DESCRIPTION
+#   Call back function to handle a click on a command button named $name.
+# ------------------------------------------------------------------------------
+
+sub button_clicked {
+  my $name = $_[0];
+
+  if (grep {$_ eq $name} keys %subcmd_b) {
+    &display_subcmd_frame ($name);
+
+  } elsif ($name eq 'CLEAR') {
+    $out_t->delete ('1.0', 'end');
+
+  } elsif ($name eq 'QUIT') {
+    exit;
+
+  } elsif ($name eq 'HELP') {
+    &invoke_cmd ('help ' . lc ($selsubcmd));
+
+  } elsif ($name eq 'RUN') {
+    &invoke_cmd (&setup_cmd ($selsubcmd));
+
+  } else {
+    $out_t->insert ('end', $name . ': function to be implemented' . "\n");
+    $out_t->yviewMoveto (1);
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &display_subcmd_frame ($name);
+#
+# DESCRIPTION
+#   Change selected subcommand to $name, and display the frame containing the
+#   widgets for configuring the options and arguments of that subcommand.
+# ------------------------------------------------------------------------------
+
+sub display_subcmd_frame {
+  my $name = $_[0];
+
+  if ($selsubcmd ne $name and not $cmdrunning) {
+    $subcmd_b{$name     }->configure ('-relief' => 'sunken');
+    $subcmd_b{$selsubcmd}->configure ('-relief' => 'raised') if $selsubcmd;
+
+    $subcmd_f{$name     }->grid ('-sticky' => 'new');
+    $subcmd_f{$selsubcmd}->gridForget if $selsubcmd;
+
+    $selsubcmd = $name;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $pos = &get_wm_pos ();
+#
+# DESCRIPTION
+#   Returns the position part of the geometry string of the main window.
+# ------------------------------------------------------------------------------
+
+sub get_wm_pos {
+  my $geometry = $mw->geometry ();
+  $geometry =~ /^=?(?:\d+x\d+)?([+-]\d+[+-]\d+)$/;
+  return $1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $command = &setup_cmd ($name);
+#
+# DESCRIPTION
+#   Setup the the system command for the sub-command $name.
+# ------------------------------------------------------------------------------
+
+sub setup_cmd {
+  my $name = $_[0];
+  my $cmd  = '';
+
+  if ($name eq 'BRANCH') {
+    $cmd .= lc ($name);
+    if ($subcmdvar{$name}{OPT} eq 'create') {
+      $cmd .= ' -c --svn-non-interactive';
+      $cmd .= ' -n '     . $subcmdvar{$name}{NAME} if $subcmdvar{$name}{NAME};
+      $cmd .= ' -t '     . $subcmdvar{$name}{TYPE};
+      $cmd .= ' --rev-flag ' . $subcmdvar{$name}{REVFLAG};
+      $cmd .= ' -r ' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+      $cmd .= ' -k ' . $subcmdvar{$name}{TICKET} if $subcmdvar{$name}{TICKET};
+      $cmd .= ' --branch-of-branch ' if $subcmdvar{$name}{SRCTYPE} eq 'branch';
+
+    } elsif ($subcmdvar{$name}{OPT} eq 'delete') {
+      $cmd .= ' -v' if $subcmdvar{$name}{VERBOSE};
+      $cmd .= ' -d --svn-non-interactive';
+
+    } elsif ($subcmdvar{$name}{OPT} eq 'list') {
+      $cmd .= ' -l';
+      $cmd .= ' -r ' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+
+    } else {
+      $cmd .= ' -i';
+      $cmd .= ' --show-children' if $subcmdvar{$name}{S_CHD};
+      $cmd .= ' --show-siblings' if $subcmdvar{$name}{S_SIB};
+      $cmd .= ' --show-other'    if $subcmdvar{$name}{S_OTH};
+      $cmd .= ' -v' if $subcmdvar{$name}{VERBOSE};
+    }
+    $cmd .= ' ' . $subcmdvar{$name}{URL}   if $subcmdvar{$name}{URL};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'CHECKOUT') {
+    $cmd .= lc ($name);
+    $cmd .= ' -r' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+    $cmd .= ' ' . $subcmdvar{$name}{URL};
+    $cmd .= ' ' . $subcmdvar{$name}{PATH} if $subcmdvar{$name}{PATH};
+
+  } elsif ($name eq 'STATUS') {
+    $cmd .= lc ($name);
+    $cmd .= ' -u' if $subcmdvar{$name}{UPDATE};
+    $cmd .= ' -v' if $subcmdvar{$name}{VERBOSE};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'DIFF') {
+    $cmd .= lc ($name);
+    $cmd .= ' -g' if $subcmdvar{$name}{GRAPHIC};
+
+    if ($subcmdvar{$name}{BRANCH}) {
+      $cmd .= ' -b';
+      $cmd .= ' ' . $subcmdvar{$name}{URL} if $subcmdvar{$name}{URL};
+    }
+
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'ADD' or $name eq 'DELETE') {
+    $cmd .= lc ($name);
+    $cmd .= ' -c' if $subcmdvar{$name}{CHECK};
+    $cmd .= ' --non-interactive'
+      if $name eq 'DELETE' and not $subcmdvar{$name}{CHECK};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'MERGE') {
+    $cmd .= lc ($name);
+
+    if ($subcmdvar{$name}{MODE} ne 'automatic') {
+      $cmd .= ' --' . $subcmdvar{$name}{MODE};
+      $cmd .= ' --revision ' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+    }
+
+    $cmd .= ' --dry-run' if $subcmdvar{$name}{DRYRUN};
+    $cmd .= ' -v'        if $subcmdvar{$name}{VERBOSE};
+    $cmd .= ' ' . $subcmdvar{$name}{SRC}   if $subcmdvar{$name}{SRC};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'CONFLICTS') {
+    $cmd .= lc ($name);
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'COMMIT') {
+    $cmd .= lc ($name);
+    $cmd .= ' --dry-run' if $subcmdvar{$name}{DRYRUN};
+    $cmd .= ' --svn-non-interactive';
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'SWITCH') {
+    $cmd .= lc ($name);
+    $cmd .= ' ' . $subcmdvar{$name}{URL}   if $subcmdvar{$name}{URL};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'UPDATE') {
+    $cmd .= lc ($name);
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  }
+
+  return $cmd;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_cmd ($cmd);
+#
+# DESCRIPTION
+#   Invoke the command $cmd.
+# ------------------------------------------------------------------------------
+
+sub invoke_cmd {
+  my $cmd      = $_[0];
+  return unless $cmd;
+
+  my $disp_cmd = 'fcm ' . $cmd;
+  $cmd         = (index ($cmd, 'help ') == 0)
+                 ? $disp_cmd
+                 : ('fcm_gui_internal ' . &get_wm_pos () . ' ' . $cmd);
+
+  # Change directory to working copy top if necessary
+  if ($subcmdvar{$selsubcmd}{USEWCT} and $subcmdvar{WCT} ne $subcmdvar{CWD}) {
+    chdir $subcmdvar{WCT};
+    $out_t->insert ('end', 'cd ' . $subcmdvar{WCT} . "\n");
+    $out_t->yviewMoveto (1);
+  }
+
+  # Report start of command
+  $out_t->insert ('end', timestamp_command ($disp_cmd, 'Start'));
+  $out_t->yviewMoveto (1);
+
+  # Open the command as a pipe
+  if ($cmdpid = open CMD, '-|', $cmd . ' 2>&1') {
+    # Disable all action buttons
+    $action_b{$_}->configure ('-state' => 'disabled') for (keys %action_b);
+    $cmdrunning = 1;
+
+    # Set up a file event to read output from the command
+    $mw->fileevent (\*CMD, readable => sub {
+      if (sysread CMD, my ($buf), 1024) {
+        # Insert text into the output text box as it becomes available
+        $out_t->insert ('end', $buf);
+        $out_t->yviewMoveto (1);
+
+      } else {
+        # Delete the file event and close the file when the command finishes
+        $mw->fileevent(\*CMD, readable => '');
+        close CMD;
+        $cmdpid = undef;
+
+        # Check return status
+        if ($?) {
+          $out_t->insert (
+            'end', '"' . $disp_cmd . '" failed (' . $? . ')' . "\n",
+          );
+          $out_t->yviewMoveto (1);
+        }
+
+        # Report end of command
+        $out_t->insert ('end', timestamp_command ($disp_cmd, 'End'));
+        $out_t->yviewMoveto (1);
+
+        # Change back to CWD if necessary
+        if ($subcmdvar{$selsubcmd}{USEWCT} and
+            $subcmdvar{WCT} ne $subcmdvar{CWD}) {
+          chdir $subcmdvar{CWD};
+          $out_t->insert ('end', 'cd ' . $subcmdvar{CWD} . "\n");
+          $out_t->yviewMoveto (1);
+        }
+
+        # Enable all action buttons again
+        $action_b{$_}->configure ('-state' => 'normal') for (keys %action_b);
+        $cmdrunning = 0;
+
+        # If the command is "checkout", change directory to working copy
+        if (lc ($selsubcmd) eq 'checkout') {
+          my $url = expand_url_keyword (URL => $subcmdvar{CHECKOUT}{URL});
+          my $dir = $subcmdvar{CHECKOUT}{PATH}
+                  ? $subcmdvar{CHECKOUT}{PATH}
+                  : basename $url;
+          $dir    = File::Spec->rel2abs ($dir);
+          &change_cwd ($dir);
+
+        # If the command is "switch", change URL
+        } elsif (lc ($selsubcmd) eq 'switch') {
+          $subcmdvar{URL_CWD} = &get_url_of_wc ($subcmdvar{CWD}, 1);
+          $subcmdvar{URL_WCT} = &get_url_of_wc ($subcmdvar{WCT}, 1);
+        }
+      }
+      1;
+    });
+
+  } else {
+    $mw->messageBox (
+      '-title'   => 'Error',
+      '-message' => 'Error running "' . $cmd . '"',
+      '-icon'    => 'error',
+    );
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_gui_internal
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_gui_internal	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_gui_internal	(revision 329)
@@ -0,0 +1,272 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_gui_internal
+#
+# SYNOPSIS
+#   fcm_gui_internal POS FUNCTION
+#
+# DESCRIPTION
+#   The fcm_gui_internal command is part of a simple graphical user interface
+#   for some of the commands of the FCM system. The argument POS is a geometry
+#   string used by the &Main::get_input method to determine the location of the
+#   pop up window. The argument FUNCTION must be a keyword recognised by the
+#   &Fcm::Cm::cm_command function.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use warnings;
+use strict;
+
+# Standard modules
+use Tk;
+use File::Basename;
+use File::Spec::Functions;
+
+# FCM component modules:
+use lib catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Cm;
+use Fcm::Config;
+
+# ------------------------------------------------------------------------------
+
+# Get configuration settings
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+my $pos      = shift @ARGV;
+my $function = shift @ARGV;
+cm_command $function;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ans = &main::get_input (
+#     TITLE   => $title,
+#     MESSAGE => $mesg,
+#     TYPE    => $type,
+#     DEFAULT => $def,
+#   );
+#
+# DESCRIPTION
+#   Get an input string from the user and return it as $ans. If TYPE is 'YN', a
+#   'YesNo' type message box will be displayed to prompt the user to click
+#   either the 'yes' or 'no' button. If TYPE is 'YNA', then an 'all' button is
+#   provided as a third option. Otherwise, a dialog box with an entry box for
+#   the user to type in a string will be displayed. TITLE is the title of the
+#   dialog box, and MESSAGE is the main message of the dialog box. If DEFAULT is
+#   set, $ans is set to the default value when the dialog box is invoked.
+# ------------------------------------------------------------------------------
+
+sub get_input {
+  my %args  = @_;
+  my $title = exists $args{TITLE}   ? $args{TITLE}   : '';
+  my $mesg  = exists $args{MESSAGE} ? $args{MESSAGE} : '';
+  my $type  = exists $args{TYPE}    ? $args{TYPE}    : '';
+  my $def   = exists $args{DEFAULT} ? $args{DEFAULT} : '';
+  my $ans   = '';
+
+  # Create a main window
+  my $mw = MainWindow->new;
+  $mw->title ($title);
+
+  # Define the default which applies if the dialog box is just closed or
+  # the user selects 'cancel'
+  $ans = $def ? $def : '';
+
+  if ($type =~ /^yn/i) {
+    # Create a yes-no(-all) dialog box
+
+    # If TYPE is YNA then add a third button: 'all'
+    my $buttons;
+    if ($type =~ /a$/i) {
+      $buttons = 3;
+
+    } else {
+      $buttons = 2;
+    }
+
+    # Message of the dialog box
+    $mw->Label ('-text' => $mesg)->grid (
+      '-row'        => 0,
+      '-column'     => 0,
+      '-columnspan' => $buttons,
+      '-padx'       => 10,
+      '-pady'       => 10,
+    );
+
+    # The "yes" button
+    my $y_b = $mw->Button (
+      '-text'      => 'Yes',
+      '-underline' => 0,
+      '-command'   => sub {$ans = 'y'; $mw->destroy},
+    )->grid (
+      '-row'    => 1,
+      '-column' => 0,
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    # The "no" button
+    my $n_b = $mw->Button (
+      '-text'      => 'No',
+      '-underline' => 0,
+      '-command'   => sub {$ans = 'n'; $mw->destroy},
+    )->grid (
+      '-row'    => 1,
+      '-column' => 1,
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    # The "all" button
+    my $a_b;
+    if ($buttons == 3) {
+      $a_b = $mw->Button (
+        '-text'      => 'All',
+        '-underline' => 0,
+        '-command'   => sub {$ans = 'a'; $mw->destroy},
+      )->grid (
+        '-row'    => 1,
+        '-column' => 2,
+        '-padx'   => 5,
+        '-pady'   => 5,
+      );
+    }
+
+    # Keyboard binding
+    if ($buttons == 3) {
+      $mw->bind ('<Key>' => sub {
+	if ($Tk::event->K eq 'Y' or $Tk::event->K eq 'y') {
+	  $y_b->invoke;
+
+	} elsif ($Tk::event->K eq 'N' or $Tk::event->K eq 'n') {
+	  $n_b->invoke;
+
+	} elsif ($Tk::event->K eq 'A' or $Tk::event->K eq 'a') {
+	  $a_b->invoke;
+	}
+      });
+
+    } else {
+      $mw->bind ('<Key>' => sub {
+	if ($Tk::event->K eq 'Y' or $Tk::event->K eq 'y') {
+	  $y_b->invoke;
+
+	} elsif ($Tk::event->K eq 'N' or $Tk::event->K eq 'n') {
+	  $n_b->invoke;
+	}
+      });
+    }
+
+    # Handle the situation when the user attempts to quit the window
+    $mw->protocol ('WM_DELETE_WINDOW', sub {
+      $ans = $def if $def;
+      $mw->destroy;
+    });
+
+  } else {
+    # Create a dialog box to obtain an input string
+
+    # Message of the dialog box
+    $mw->Label ('-text' => $mesg)->grid (
+      '-row'    => 0,
+      '-column' => 0,
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    # Entry box for the user to type in the input string
+    my $entry   = $ans;
+    my $input_e = $mw->Entry (
+      '-textvariable'    => \$entry,
+      '-width'           => 40,
+    )->grid (
+      '-row'    => 0,
+      '-column' => 1,
+      '-sticky' => 'ew',
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    my $b_f = $mw->Frame->grid (
+      '-row'        => 1,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'e',
+    );
+
+    # An OK button to accept the input string
+    my $ok_b = $b_f->Button (
+      '-text' => 'OK',
+      '-command' => sub {$ans = $entry; $mw->destroy},
+    )->grid (
+      '-row'        => 0,
+      '-column'     => 0,
+      '-padx'       => 5,
+      '-pady'       => 5,
+    );
+
+    # A Cancel button to reject the input string
+    my $cancel_b = $b_f->Button (
+      '-text' => 'Cancel',
+      '-command' => sub {$ans = undef; $mw->destroy},
+    )->grid (
+      '-row'        => 0,
+      '-column'     => 1,
+      '-padx'       => 5,
+      '-pady'       => 5,
+    );
+
+    # Keyboard binding
+    $mw->bind ('<Key>' => sub {
+      if ($Tk::event->K eq 'Return' or $Tk::event->K eq 'KP_Enter') {
+        $ok_b->invoke;
+
+      } elsif ($Tk::event->K eq 'Escape') {
+        $cancel_b->invoke;
+      }
+    });
+
+    # Allow the entry box to expand
+    $mw->gridColumnconfigure (1, '-weight' => 1);
+
+    # Set initial focus on the entry box
+    $input_e->focus;
+    $input_e->icursor ('end');
+  }
+
+  $mw->geometry ($pos);
+
+  # Switch on "always on top" property for $mw
+  $mw->property (
+    qw/set _NET_WM_STATE ATOM/,
+    32,
+    ['_NET_WM_STATE_STAYS_ON_TOP'],
+    ($mw->toplevel->wrapper)[0],
+  );
+
+  MainLoop;
+
+  return $ans;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_internal
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_internal	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_internal	(revision 329)
@@ -0,0 +1,581 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_internal
+#
+# SYNOPSIS
+#   fcm_internal SUBCOMMAND ARGS
+#
+# DESCRIPTION
+#   The fcm_internal command is a frontend for some of the internal commands of
+#   the FCM build system. The subcommand can be "compile", "load" or "archive"
+#   for invoking the compiler, loader and library archiver respectively. If
+#   "compile" is specified, it can be suffixed with ":TYPE" to specify the
+#   nature of the source file. If TYPE is not specified, it is set to F by
+#   default (for Fortran source). For compile and load, the other arguments are
+#   the 1) name of the container package of the source file, 2) the path to the
+#   source file and 3) the target name after compiling or loading the source
+#   file. For compile, the 4th argument is a flag to indicate whether
+#   pre-processing is required for compiling the source file. For load, the 4th
+#   and the rest of the arguments is a list of object files that cannot be
+#   archived into the temporary load library and must be linked into the target
+#   through the linker command. (E.g. Fortran BLOCKDATA program units must be
+#   linked this way.) If archive is specified, the first argument should be the
+#   name of the library archive target and the rest should be the object files
+#   to be included in the archive. This command is invoked via the build system
+#   and should never be called directly by the user.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use warnings;
+use strict;
+
+# FCM component modules
+use Fcm::Timer;
+
+# Function declarations
+sub catfile;
+sub basename;
+sub dirname;
+
+# ------------------------------------------------------------------------------
+
+# Module level variables
+my %unusual_tool_name = ();
+
+# ------------------------------------------------------------------------------
+
+MAIN: {
+  # Name of program
+  my $this = basename $0;
+
+  # Arguments
+  my $subcommand = shift @ARGV;
+  my ($function, $type) = split /:/, $subcommand; 
+  my ($srcpackage, $src, $target, $requirepp, @objects, @blockdata);
+  
+  if ($subcommand eq 'archive') {
+    ($target, @objects) = @ARGV;
+
+  } elsif ($subcommand eq 'load') {
+    ($srcpackage, $src, $target, @blockdata) = @ARGV;
+
+  } else {
+    ($srcpackage, $src, $target, $requirepp) = @ARGV;
+  }
+
+  # Set up hash reference for all the required information
+  my %info = (
+    SRCPACKAGE => $srcpackage,
+    SRC        => $src,
+    TYPE       => $type,
+    TARGET     => $target,
+    REQUIREPP  => $requirepp,
+    OBJECTS    => \@objects,
+    BLOCKDATA  => \@blockdata,
+  );
+
+  # Get list of unusual tools
+  my $i = 0;
+  while (my $label = &get_env ('FCM_UNUSUAL_TOOL_LABEL' . $i)) {
+    my $value = &get_env ('FCM_UNUSUAL_TOOL_VALUE' . $i);
+    $unusual_tool_name{$label} = $value;
+    $i++;
+  }
+
+  # Invoke the action
+  my $rc = 0;
+  if ($function eq 'compile') {
+    $rc = &compile (\%info);
+
+  } elsif ($function eq 'load') {
+    $rc = &load (\%info);
+
+  } elsif ($function eq 'archive') {
+    $rc = &archive (\%info);
+
+  } else {
+    print STDERR $this, ': incorrect usage, abort';
+    $rc = 1;
+  }
+
+  # Throw error if action failed
+  if ($rc) {
+    print STDERR $this, ' ', $function, ' failed (', $rc, ')', "\n";
+    exit 1;
+
+  } else {
+    exit;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &compile (\%info);
+#
+# DESCRIPTION
+#   This method invokes the correct compiler with the correct options to
+#   compile the source file into the required target. The argument $info is a
+#   hash reference set up in MAIN. The following environment variables are
+#   used, where * is the source file type (F for Fortran, and C for C/C++):
+# 
+#   *C          - compiler command
+#   *C_OUTPUT   - *C option to specify the name of the output file
+#   *C_DEFINE   - *C option to declare a pre-processor def
+#   *C_INCLUDE  - *C option to declare an include directory
+#   *C_COMPILE  - *C option to ask the compiler to perform compile only
+#   *CFLAGS     - *C user options
+#   *PPKEYS     - list of pre-processor defs (may have sub-package suffix)
+#   FCM_VERBOSE - verbose level
+#   FCM_OBJDIR  - destination directory of object file
+#   FCM_TMPDIR  - temporary destination directory of object file
+# ------------------------------------------------------------------------------
+
+sub compile {
+  my $info = shift;
+
+  # Verbose mode
+  my $verbose = &get_env ('FCM_VERBOSE');
+  $verbose    = 1 unless defined ($verbose);
+
+  my @command = ();
+
+  # Only support C and Fortran source files at the moment
+  my $type = $info->{TYPE};
+  $type    = ($info->{SRC} =~ /\.c(\w+)?$/i) ? 'C' : 'F' if not $type;
+
+  # Compiler
+  push @command, &get_env ($type . 'C', 1);
+
+  # Compile output target (typical -o option)
+  push @command, &get_env ($type . 'C_OUTPUT', 1), $info->{TARGET};
+
+  # Pre-processor definition macros
+  if ($info->{REQUIREPP}) {
+    my @ppkeys = split /\s+/, &select_flags ($info, $type . 'PPKEYS');
+    my $defopt = &get_env ($type . 'C_DEFINE', 1);
+
+    push @command, (map {$defopt . $_} @ppkeys);
+  }
+
+  # Include search path
+  my $incopt  = &get_env ($type . 'C_INCLUDE', 1);
+  my @incpath = split /:/, &get_env ('FCM_INCPATH');
+  push @command, (map {$incopt . $_} @incpath);
+
+  # Other compiler flags
+  my $flags = &select_flags ($info, $type . 'FLAGS');
+  push @command, $flags if $flags;
+
+  my $compile_only = &get_env ($type . 'C_COMPILE');
+  if ($flags !~ /(?:^|\s)$compile_only\b/) {
+    push @command, &get_env ($type . 'C_COMPILE');
+  }
+
+  # Name of source file
+  push @command, $info->{SRC};
+
+  # Execute command
+  my $objdir = &get_env ('FCM_OBJDIR', 1);
+  my $tmpdir = &get_env ('FCM_TMPDIR', 1);
+  chdir $tmpdir;
+
+  my $command = join ' ', @command;
+  if ($verbose > 1) {
+    print 'cd ', $tmpdir, "\n";
+    print &timestamp_command ($command, 'Start');
+
+  } elsif ($verbose) {
+    print $command, "\n";
+  }
+
+  my $rc = system $command;
+
+  print &timestamp_command ($command, 'End  ') if $verbose > 1;
+
+  # Move temporary output to correct location on success
+  # Otherwise, remove temporary output
+  if ($rc) { # error
+    unlink $info->{TARGET};
+
+  } else {   # success
+    print 'mv ', $info->{TARGET}, ' ', $objdir, "\n" if $verbose > 1;
+    rename $info->{TARGET}, &catfile ($objdir, $info->{TARGET});
+  }
+
+  # Move any Fortran module definition files to the INC directory
+  my @modfiles = <*.mod *.MOD>;
+  for my $file (@modfiles) {
+    rename $file, &catfile ($incpath[0], $file);
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &load (\%info);
+#
+# DESCRIPTION
+#   This method invokes the correct loader with the correct options to link
+#   the main program object into an executable. The argument $info is a hash
+#   reference set up in MAIN. The following environment variables are used:
+# 
+#   LD           - linker command
+#   LD_OUTPUT    - LD option to specify the name of the output file
+#   LD_LIBSEARCH - LD option to declare a directory in the library search path
+#   LD_LIBLINK   - LD option to declare an object library
+#   LDFLAGS      - LD user options
+#   FCM_VERBOSE  - verbose level
+#   FCM_LIBDIR   - destination directory of object libraries
+#   FCM_OBJDIR   - destination directory of object files
+#   FCM_BINDIR   - destination directory of executable file
+#   FCM_TMPDIR   - temporary destination directory of executable file
+# ------------------------------------------------------------------------------
+
+sub load {
+  my $info = shift;
+
+  my $rc = 0;
+
+  # Verbose mode
+  my $verbose = &get_env ('FCM_VERBOSE');
+  $verbose    = 1 unless defined ($verbose);
+
+  # Create temporary object library
+  (my $name   = $info->{TARGET}) =~ s/\.\S+$//;
+  my $libname = '__fcm__' . $name;
+  my $lib     = 'lib' . $libname . '.a';
+  my $libfile = catfile (&get_env ('FCM_LIBDIR', 1), $lib);
+  $rc = &archive ({TARGET => $lib});
+
+  unless ($rc) {
+    my @command = ();
+
+    # Linker
+    push @command, &select_flags ($info, 'LD');
+
+    # Linker output target (typical -o option)
+    push @command, &get_env ('LD_OUTPUT', 1), $info->{TARGET};
+
+    # Name of main object file
+    my $mainobj = (basename ($info->{SRC}) eq $info->{SRC})
+                  ? catfile (&get_env ('FCM_OBJDIR'), $info->{SRC})
+                  : $info->{SRC};
+    push @command, $mainobj;
+
+    # Link with Fortran BLOCKDATA objects if necessary
+    if (@{ $info->{BLOCKDATA} }) {
+      my @blockdata = @{ $info->{BLOCKDATA} };
+      my @objpath   = split /:/, &get_env ('FCM_OBJPATH');
+
+      # Search each BLOCKDATA object file from the object search path
+      for my $file (@blockdata) {
+        for my $dir (@objpath) {
+          my $full = catfile ($dir, $file);
+
+          if (-r $full) {
+            $file = $full;
+            last;
+          }
+        }
+
+        push @command, $file;
+      }
+    }
+
+    # Library search path
+    my $libopt  = &get_env ('LD_LIBSEARCH', 1);
+    my @libpath = split /:/, &get_env ('FCM_LIBPATH');
+    push @command, (map {$libopt . $_} @libpath);
+
+    # Link with temporary object library if it exists
+    push @command, &get_env ('LD_LIBLINK', 1) . $libname if -f $libfile;
+
+    # Other linker flags
+    my $flags = &select_flags ($info, 'LDFLAGS');
+    push @command, $flags;
+
+    # Execute command
+    my $tmpdir = &get_env ('FCM_TMPDIR', 1);
+    my $bindir = &get_env ('FCM_BINDIR', 1);
+    chdir $tmpdir;
+
+    my $command = join ' ', @command;
+    if ($verbose > 1) {
+      print 'cd ', $tmpdir, "\n";
+      print &timestamp_command ($command, 'Start');
+
+    } elsif ($verbose) {
+      print $command, "\n";
+    }
+
+    $rc = system $command;
+
+    print &timestamp_command ($command, 'End  ') if $verbose > 1;
+
+    # Move temporary output to correct location on success
+    # Otherwise, remove temporary output
+    if ($rc) { # error
+      unlink $info->{TARGET};
+
+    } else {   # success
+      print 'mv ', $info->{TARGET}, ' ', $bindir, "\n" if $verbose > 1;
+      rename $info->{TARGET}, &catfile ($bindir, $info->{TARGET});
+    }
+  }
+
+  # Remove the temporary object library
+  unlink $libfile if -f $libfile;
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &archive (\%info);
+#
+# DESCRIPTION
+#   This method invokes the library archiver to create an object library. The
+#   argument $info is a hash reference set up in MAIN. The following
+#   environment variables are used:
+# 
+#   AR           - archiver command
+#   ARFLAGS      - AR options to update/create an object library
+#   FCM_VERBOSE  - verbose level
+#   FCM_LIBDIR   - destination directory of object libraries
+#   FCM_OBJPATH  - search path of object files
+#   FCM_OBJDIR   - destination directory of object files
+#   FCM_TMPDIR   - temporary destination directory of executable file
+# ------------------------------------------------------------------------------
+
+sub archive {
+  my $info = shift;
+
+  my $rc = 0;
+
+  # Verbose mode
+  my $verbose = &get_env ('FCM_VERBOSE');
+  $verbose    = 1 unless defined ($verbose);
+
+  # Set up the archive command
+  my $lib     = &basename ($info->{TARGET});
+  my $tmplib  = &catfile (&get_env ('FCM_TMPDIR', 1), $lib);
+  my @ar_cmd  = ();
+  push @ar_cmd, (&get_env ('AR', 1), &get_env ('ARFLAGS', 1));
+  push @ar_cmd, $tmplib;
+
+  # Get object directories and their files
+  my %objdir;
+  if (exists $info->{OBJECTS}) {
+    # List of objects set in the argument, sort into directory/file list
+    for my $name (@{ $info->{OBJECTS} }) {
+      my $dir = (&dirname ($name) eq '.')
+                ? &get_env ('FCM_OBJDIR', 1) : &dirname ($name);
+      $objdir{$dir}{&basename ($name)} = 1;
+    }
+
+  } else {
+    # Objects not listed in argument, search object path for all files
+    my @objpath  = split /:/, &get_env ('FCM_OBJPATH', 1);
+    my %objbase  = ();
+
+    # Get registered objects into a hash (keys = objects, values = 1)
+    my %objects = map {($_, 1)} split (/\s+/, &get_env ('OBJECTS'));
+
+    # Seach object path for all files
+    for my $dir (@objpath) {
+      next unless -d $dir;
+
+      chdir $dir;
+
+      # Use all files from each directory in the object search path
+      for ((glob ('*'))) {
+        next unless exists $objects{$_}; # consider registered objects only
+        $objdir{$dir}{$_} = 1 unless exists $objbase{$_};
+        $objbase{$_} = 1;
+      }
+    }
+  }
+
+  for my $dir (keys %objdir) {
+    next unless -d $dir;
+
+    # Go to each object directory and executes the library archive command 
+    chdir $dir;
+    my $command = join ' ', (@ar_cmd, sort keys %{ $objdir{$dir} });
+
+    if ($verbose > 1) {
+      print 'cd ', $dir, "\n";
+      print &timestamp_command ($command, 'Start');
+
+    } else {
+      print $command, "\n" if exists $info->{OBJECTS};
+    }
+
+    $rc = system $command;
+
+    print &timestamp_command ($command, 'End  ')
+      if $verbose > 1;
+    last if $rc;
+  }
+
+  # Move temporary output to correct location on success
+  # Otherwise, remove temporary output
+  if ($rc) { # error
+    unlink $tmplib;
+
+  } else {   # success
+    my $libdir = &get_env ('FCM_LIBDIR', 1);
+
+    print 'mv ', $tmplib, ' ', $libdir, "\n" if $verbose > 1;
+    rename $tmplib, &catfile ($libdir, $lib);
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flags = &select_flags (\%info, $set);
+#
+# DESCRIPTION
+#   This function selects the correct compiler/linker flags for the current
+#   sub-package from the environment variable prefix $set. The argument $info
+#   is a hash reference set up in MAIN.
+# ------------------------------------------------------------------------------
+
+sub select_flags {
+  my ($info, $set) = @_;
+
+  (my $srcroot = &basename ($info->{SRC})) =~ s/\.\S+$//;
+  my @names    = ($set);
+  push @names, split (/__/, $info->{SRCPACKAGE} . '__' . $srcroot);
+
+  my $string   = '';
+  while (@names) {
+    my $name = join '__', @names;
+    my $var  = &get_env ($name);
+
+    if (defined $var) {
+      $string = $var;
+      last;
+
+    } else {
+      pop @names;
+    }
+  }
+
+  return $string;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $variable = &get_env ($name);
+#   $variable = &get_env ($name, $compulsory);
+#
+# DESCRIPTION
+#   This internal method gets a variable from $ENV{$name}. If $compulsory is
+#   set to true, it throws an error if the variable is a not set or is an empty
+#   string. Otherwise, it returns C<undef> if the variable is not set.
+# ------------------------------------------------------------------------------
+
+sub get_env {
+  (my $name, my $compulsory) = @_;
+  my $string;
+
+  if ($name =~ /^\w+$/) {
+    # $name contains only word characters, variable is exported normally
+    die 'The environment variable "', $name, '" must be set, abort'
+      if $compulsory and not exists $ENV{$name};
+
+    $string = exists $ENV{$name} ? $ENV{$name} : undef;
+
+  } else {
+    # $name contains unusual characters
+    die 'The environment variable "', $name, '" must be set, abort'
+      if $compulsory and not exists $unusual_tool_name{$name};
+
+    $string = exists $unusual_tool_name{$name}
+              ? $unusual_tool_name{$name} : undef;
+  }
+
+  return $string;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = &catfile (@paths);
+#
+# DESCRIPTION
+#   This is a local implementation of what is in the File::Spec module.
+# ------------------------------------------------------------------------------
+
+sub catfile {
+  my @names = split (m!/!, join ('/', @_));
+  my $path  = shift @names;
+
+  for my $name (@names) {
+    $path .= '/' . $name if $name;
+  }
+
+  return $path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $basename = &basename ($path);
+#
+# DESCRIPTION
+#   This is a local implementation of what is in the File::Basename module.
+# ------------------------------------------------------------------------------
+
+sub basename {
+  my $name = $_[0];
+
+  $name =~ s{/*$}{}; # remove trailing slashes
+
+  if ($name =~ m#.*/([^/]+)$#) {
+    return $1;
+
+  } else {
+    return $name;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dirname = &dirname ($path);
+#
+# DESCRIPTION
+#   This is a local implementation of what is in the File::Basename module.
+# ------------------------------------------------------------------------------
+
+sub dirname {
+  my $name = $_[0];
+
+  if ($name =~ m#^/+$#) {
+    return '/'; # dirname of root is root
+
+  } else {
+    $name =~ s{/*$}{}; # remove trailing slashes
+
+    if ($name =~ m#^(.*)/[^/]+$#) {
+      my $dir = $1;
+      $dir =~ s{/*$}{}; # remove trailing slashes
+      return $dir;
+
+    } else {
+      return '.';
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_setup_konqueror
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_setup_konqueror	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_setup_konqueror	(revision 329)
@@ -0,0 +1,44 @@
+#!/usr/bin/ksh
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_setup_konqueror
+#
+# SYNOPSIS
+#   fcm_setup_konqueror
+#
+# DESCRIPTION
+#   Set up Konqueror to use "fcm gui".
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Check number of arguments
+script=$(basename $0)
+usage="$script: no argument required"
+if (( $# != 0 )); then
+  echo "$usage, abort..." >&2
+  exit 1
+fi
+
+filename=fcm_gui.desktop
+
+file=$(dirname $0)
+file=${file%/bin}/etc/$filename
+
+if [[ ! -f $file ]]; then
+  echo "$script: $file not found, abort..." >&2
+  exit 1
+fi
+
+dir=$HOME/.kde/share/applnk/.hidden
+mkdir -p $dir
+cd $dir
+rm -f $filename             # Always remove.
+ln -s $file .
+
+echo "$script: finished"
+
+#EOF
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_update_version_dir.pl
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_update_version_dir.pl	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_update_version_dir.pl	(revision 329)
@@ -0,0 +1,302 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_update_version_dir.pl
+#
+# SYNOPSIS
+#   fcm_update_version_dir.pl [OPTIONS] [CFGFILE]
+#
+# DESCRIPTION
+#   See $usage for detail.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use Getopt::Long;
+use Cwd;
+use File::Basename;
+use File::Path;
+use File::Spec;
+
+# FCM component modules:
+use lib File::Spec->catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Config;
+use Fcm::Util;
+
+# Usage
+# ------------------------------------------------------------------------------
+my $this  = basename $0;
+my $usage = <<EOF;
+NAME
+  $this
+
+SYNOPSIS
+  $this [OPTIONS] [CFGFILE]
+
+DESCRIPTION
+  Update the version directories for a list of relative paths in the source
+  repository URL.
+
+OPTIONS
+  -d [--dest] arg: Specify a destination for the extraction. If not specified,
+                   the command extracts to the current working directory.
+  -h [--help]    : Print help and exit.
+  -f [--full]    : Specify the full mode. If not specified, the command runs
+                   in incremental mode.
+  -u [--url]  arg: Specify the source repository URL. No default.
+
+ARGUMENTS
+  A configuration file may be given to this command, or it will attempt to
+  read from the standard input. Each line in the configuration must contain
+  a relative path that resides under the given source repository URL. (Empty
+  lines and lines beginning with a "#" are ignored.) Optionally, each
+  relative path may be followed by a list of space separated "conditions".
+  Each condition is a conditional operator (>, >=, <, <=, == or !=) followed
+  by a revision number or the keyword HEAD. The command uses the revision
+  log to determine the revisions at which the relative path has been updated
+  in the source repository URL. If these revisions also satisfy the
+  "conditions" set by the user, they will be considered in the extraction.
+  In full mode, everything is re-extracted. In incremental mode, the version
+  directories are only updated if they do not already exist.
+
+COPYRIGHT
+  This program is part of the FCM system.
+  (C) Crown copyright Met Office. All rights reserved.
+  For further details please refer to the file COPYRIGHT.txt
+  which you should have received as part of this distribution.
+EOF
+
+# Options
+# ------------------------------------------------------------------------------
+my ($dest, $full, $help, $url);
+GetOptions (
+  'dest|d=s' => \$dest,
+  'full|f'   => \$full,
+  'help'     => \$help,
+  'url|u=s'  => \$url,
+);
+
+if ($help) {
+  print $usage;
+  exit;
+}
+
+$dest = cwd () unless $dest;
+
+die 'An URL must be specified with the --url option, abort' unless $url;
+
+# Arguments
+# ------------------------------------------------------------------------------
+if (@ARGV) {
+  die 'Cannot read: ', $ARGV[0], ', abort' unless -f $ARGV[0] and -r $ARGV[0];
+}
+
+# Get configuration settings
+# ------------------------------------------------------------------------------
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+# Expand URL keyword
+$url = &expand_url_keyword (URL => $url);
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+
+MAIN: {
+  my $date = localtime;
+  print $this, ': started on ', $date, "\n";
+
+  my %dirs;
+
+  # Read input (file) for a list directories and update conditions
+  while (<>) {
+    chomp;
+
+    # Ignore empty and comment lines
+    next if /^\s*(?:#|$)/;
+
+    # Each line must contain a relative path, and optionally a list of
+    # space delimited conditions
+    my @words = split /\s+/;
+    my $dir   = shift @words;
+
+    # Check that the conditions are valid
+    my @conditions;
+    for my $word (@words) {
+      if ($word =~ /^([<>]=?|[!=]=)(.+)$/i) {
+        # Condition must be a conditional operator followed by a revision
+        my ($operator, $rev) = ($1, $2);
+        $rev = &expand_rev_keyword (REV => $rev, URL => $url, HEAD => 1);
+        push @conditions, $operator . $rev;
+
+      } else {
+        print STDERR 'Warning: ignore unknown syntax for update condition: ',
+                     $word, "\n";
+      }
+    }
+
+    # Add directory and its conditions to a hash
+    if ($dir =~ s#/\*$##) { # Directory finishes with wildcard
+
+      # Run "svn ls" in recursive mode
+      my $dirurl  = join ('/', ($url, $dir));
+      my @files   = &run_command ([qw/svn ls -R/, $dirurl], METHOD => 'qx');
+
+      # Find directories containing regular files
+      while (my $file = shift @files) {
+	# Skip directories
+	next if $file =~ m#/$#;
+
+	# Get "dirname" of regular file and add to hash
+	my $subdir = join ('/', ($dir, dirname ($file)));
+	$dirs{$subdir} = \@conditions;
+      }
+
+    } else {
+      $dirs{$dir} = \@conditions;
+    }
+
+  }
+
+  # Update each directory, if required
+  for my $dir (sort keys %dirs) {
+    # Use "svn log" to determine the revisions that need to be updated
+    my %allversions;
+    {
+      my $command = 'svn log -q ' . join ('/', ($url, $dir));
+      my @log     = &run_command (
+        [qw/svn log -q/, join ('/', ($url, $dir))], METHOD => 'qx',
+      );
+      @log        = grep /^r\d+/, @log;
+
+      # Assign a sequential "version" number to each sub-directory
+      my $version = scalar @log;
+      for (@log) {
+        m/^r(\d+)/;
+        $allversions{$1} = 'v' . $version--;
+      }
+    }
+    my %versions = %allversions;
+
+    # Extract only revisions matching the conditions
+    if (@{ $dirs{$dir} }) {
+      my @conditions = @{ $dirs{$dir} };
+
+      for my $condition (@conditions) {
+        for my $rev (keys %versions) {
+          delete $versions{$rev} unless eval ($rev . $condition);
+        }
+      }
+    }
+
+    # Destination directory
+    my $dirpath = File::Spec->catfile ($dest, $dir);
+
+    if (-d $dirpath) {
+      if ($full or not keys %versions) {
+        # Remove destination directory top, in full mode
+        # or if there are no matching revisions
+        &run_command ([qw/rm -rf/, $dirpath], PRINT => 1);
+
+      } else {
+        # Delete excluded revisions if they exist, in incremental mode
+        if (opendir DIR, $dirpath) {
+          while (my $rev = readdir 'DIR') {
+            next unless $rev =~ /^\d+$/;
+
+            if (not grep {$_ eq $rev} keys %versions) {
+              my @command = (qw/rm -rf/, File::Spec->catfile ($dirpath, $rev));
+              &run_command (\@command, PRINT => 1);
+
+              # Remove "version" symlink
+              my $verlink = File::Spec->catfile ($dirpath, $allversions{$rev});
+              unlink $verlink if -l $verlink;
+            }
+          }
+          closedir DIR;
+        }
+      }
+    }
+
+    # Create container directory of destination if it does not already exist
+    if (keys %versions and not -d $dirpath) {
+      print '-> mkdir -p ', $dirpath, "\n";
+      my $rc = mkpath $dirpath;
+      die 'mkdir -p ', $dirpath, ' failed' unless $rc;
+    }
+
+    # Update each version directory that needs updating
+    for my $rev (keys %versions) {
+      my $revpath = File::Spec->catfile ($dest, $dir, $rev);
+
+      # Create version directory if it does not exist
+      if (not -e $revpath) {
+        # Use "svn export" to create the version directory
+        my @command = (
+          qw/svn export -q -r/,
+          $rev,
+          join ('/', ($url, $dir)),
+          $revpath,
+        );
+
+        &run_command (\@command, PRINT => 1);
+
+        # Run GenScr_GenRule on any component directories
+        # This can be removed once old versions of the SCSUI are no longer used
+	if ($dir =~ m#(?:^|/)components/#) {
+          my @command = (
+            "GenScr_GenRule",
+            File::Spec->catfile ($revpath, join ('.', (basename ($dir), "rule")))
+          );
+
+          &run_command (\@command, PRINT => 1);
+	}
+      }
+
+      # Create "version" symlink if necessary
+      my $verlink = File::Spec->catfile ($dest, $dir, $versions{$rev});
+      symlink $rev, $verlink unless -l $verlink;
+    }
+
+    # Symbolic link to the "latest" version directory
+    my $headlink = File::Spec->catfile ($dest, $dir, 'latest');
+    my $headrev  = 0;
+    for my $rev (keys %versions) {
+      $headrev = $rev if $rev > $headrev;
+    }
+
+    if (-l $headlink) {
+      # Remove old symbolic link if there is no revision to update or if it
+      # does not point to the correct version directory
+      my $org = readlink $headlink;
+      unlink $headlink if (! $headrev or $org ne $headrev);
+    }
+
+    # (Re-)create the "latest" symbolic link, if necessary
+    symlink $headrev, $headlink if ($headrev and not -l $headlink);
+  }
+
+  $date = localtime;
+  print $this, ': finished normally on ', $date, "\n";
+}
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_xxdiff_wrapper
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_xxdiff_wrapper	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/bin/fcm_xxdiff_wrapper	(revision 329)
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_xxdiff_wrapper
+#
+# SYNOPSIS
+#   fcm_xxdiff_wrapper ARGS
+#
+# DESCRIPTION
+#   Wrapper script which allows "xxdiff" to be invoked by the "svn diff"
+#   command. It is used in combination with the "--diff-cmd" option to
+#   "svn diff". The arguments supplied by "svn diff" are as follows:
+#   -u -L OLD_FILE_DESC -L NEW_FILE_DESC OLD_FILE_NAME NEW_FILE_NAME
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use warnings;
+use strict;
+
+# ------------------------------------------------------------------------------
+
+if ($ARGV[0] ne "-u" or $ARGV[1] ne "-L" or $ARGV[3] ne "-L") {
+  die "Unexpected argument";
+}
+
+# Check existence of files
+die $ARGV[5], ': not found, abort' if not -f $ARGV[5];
+die $ARGV[6], ': not found, abort' if not -f $ARGV[6];
+
+if ($ARGV[5] =~ m#.svn/empty-file$#) {
+  print "Skipping new file\n";
+
+} elsif ($ARGV[6] =~ m#.svn/empty-file$#) {
+  print "Skipping deleted file\n";
+
+} elsif (-B $ARGV[6]) {
+  print "Skipping binary file\n";
+
+} else {
+  print "Comparing '$ARGV[2]' with '$ARGV[4]'\n";
+  exec "xxdiff --title1 '$ARGV[2]' --title2 '$ARGV[4]' $ARGV[5] $ARGV[6]";
+}
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/build.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/build.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/build.html	(revision 329)
@@ -0,0 +1,812 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Build System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design: Build System">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Build System
+  </address>
+
+  <h1>Build System</h1>
+  
+  <p>In this chapter, we shall discuss in detail the design of the build
+  system. For information of how to use the build system, please see: <a
+  href="../user_guide/build.html">FCM System User Guide &gt; The Build
+  System</a>.</p>
+
+  <p>The build system analyses the directory tree containing a set of source
+  code, processes the configuration, and invokes <em>make</em> to compile/build
+  the source code into the project executables. The system is written in a set
+  of Perl modules. It is designed to work with GNU <em>make</em>. It creates
+  the <em>Makefile</em> and many other dependent files automcatically. The
+  build system uses a similar interface to the extract system. Its
+  configuration file can be produced through the extract system. It also
+  shares the same command line interface and many other utilities with the
+  code management system and the extract system.</p>
+
+  <h2><a name="io">Input and Output</a></h2>
+
+  <p>The build system has the following input:</p>
+
+  <ul class="pad">
+    <li>a directory tree populated with a set of Fortran and C source files,
+    and scripts written in Perl, Python, TCL, PVWave or a Unix shell.</li>
+
+    <li>the location of the root directory of the build.</li>
+
+    <li>the tools/commands (and their options) to be used for the build.</li>
+
+    <li>the locations of previous builds, if the current build is to base on
+    them.</li>
+
+    <li>other build options.</li>
+  </ul>
+
+  <p>Output from the build system includes:</p>
+
+  <ul class="pad">
+    <li>the targets of the build and their dependencies.</li>
+
+    <li>other files used by the system to build the targets.</li>
+  </ul>
+
+  <h2><a name="component">Components</a></h2>
+
+  <p>The build system uses the following commands, modules and tools:</p>
+
+  <table class="pad" summary="build system components" border="1">
+    <tr>
+      <th>Name</th>
+
+      <th>Category</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>fcm</th>
+
+      <td>Perl executable</td>
+
+      <td>Top level command line interface of the FCM system.</td>
+    </tr>
+
+    <tr>
+      <th>fcm_internal</th>
+
+      <td>Perl executable</td>
+
+      <td>Command wrapper for the compiler and linker.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Build</th>
+
+      <td>Perl module</td>
+
+      <td>Main class that controls the running of the build system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::BuildTask</th>
+
+      <td>Perl module</td>
+
+      <td>A class that performs various "tasks" (such as pre-process and
+      generate interface) for the build system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::CfgFile</th>
+
+      <td>Perl module</td>
+
+      <td>A class for reading from and writing to configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Compiler</th>
+
+      <td>Perl module</td>
+
+      <td>A class for wrapping the compiler and linker commands.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Config</th>
+
+      <td>Perl module</td>
+
+      <td>A class that contains the configuration settings shared by all
+      FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::SrcFile</th>
+
+      <td>Perl module</td>
+
+      <td>A class that controls the actions on a source file.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::SrcPackage</th>
+
+      <td>Perl module</td>
+
+      <td>A class that deals with the actions on a source directory
+      sub-package.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Util</th>
+
+      <td>Perl module</td>
+
+      <td>A collection of utilities shared by all FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>Ecmwf::Fortran90_stuff</th>
+
+      <td>Perl module</td>
+
+      <td>A utility originally developed by the ECMWF for generating interface
+      blocks for Fortran 9X source files. Modified for adoptation by the FCM
+      system.</td>
+    </tr>
+
+    <tr>
+      <th>make</th>
+
+      <td>Unix utility</td>
+
+      <td>The <em>make</em> build utility. FCM is designed to work with the
+      GNU version of <em>make</em>.</td>
+    </tr>
+
+    <tr>
+      <th>ksh</th>
+
+      <td>Unix shell</td>
+
+      <td>The following shell commands are used: "cp", "rm", "mv", "cd" and
+      "touch".</td>
+    </tr>
+
+    <tr>
+      <th>f90aib</th>
+
+      <td>Fortran utility</td>
+
+      <td>Formerly used by the GEN system as the generator for Fortran 9X
+      interface blocks. It is a freeware developed by Michel Olagnon at the
+      French Research Institute for Exploitation of the Sea. Its use is still
+      supported by FCM, but the ECMWF interface generator is now
+      preferred.</td>
+    </tr>
+  </table>
+
+  <h2><a name="command">The Build Command</a></h2>
+
+  <p>There are several options that can be supplied to the build command.
+  These options are implemented as follows:</p>
+
+  <ul>
+    <li><strong>Archive mode</strong>: the build system generates many files,
+    which are placed in various sub-directories according to their categories.
+    Most of these files are not used in the runtime environment. To prevent a
+    clutter up of disk space, it may be desirable to archive these
+    sub-directories. The system implements this by using the "tar" command to
+    archive each sub-directory. For an incremental build in the same
+    directory, the archived "tar" files are extracted back into the
+    sub-directories so that they can be re-used. It is worth noting that the
+    archive mode should not be used if a build is going to be re-used as a
+    pre-compiled build, as it will not be possible to extract the "tar" archives
+    back to their original forms. The default is not to archive
+    sub-directories.</li>
+
+    <li><strong>Full mode</strong>: on an incremental build, the system removes
+    all sub-directories created by the previous build, so that a new build can
+    be performed. The default is to perform an incremental build.</li>
+
+    <li><strong>Parallel jobs</strong>: this is implemented via the option in
+    GNU <em>make</em>. The generated <em>Makefile</em> is written with
+    parallel <em>make</em> in mind. The default is to perform a serial
+    build.</li>
+
+    <li><strong>Stage</strong>: this is implemented by running the build
+    system up to and including a named or a numbered stage. The default is to
+    go through all the stages.</li>
+
+    <li><strong>Targets</strong>: if targets are specified in the build
+    command, overrides the default targets supplied to the <em>make</em>
+    command. The default is to build the "all" target.</li>
+
+    <li><strong>Verbose</strong>: the verbose setting is a variable in the
+    Fcm::Config module. If the option is specified in the build command, it
+    sets this variable to the value supplied to the option. At various places
+    in the build process, it may be useful to print out diagnostic
+    information. This variable contols whether the information will get
+    printed.</li>
+  </ul>
+
+  <h2><a name="fcm-cfg">The Central/User Configuration File</a></h2>
+
+  <p>When we invoke the FCM command, it creates a new instance of Fcm::Config,
+  which reads, processes and stores information from the central and user
+  configuration file. The default settings in Fcm::Config is overwritten by
+  the information provided by the central configuration file. If a user
+  configuration file is found, its settings will take overall precedence.
+  These settings are stored in the Fcm::Config instance, which are parsed to
+  all other modules used by the build system. By convention, the reference to
+  the Fcm::Config instance can normally be fetched by the "config" method for
+  all OO "Fcm::" modules.</p>
+
+  <h2><a name="bld-cfg">The Build Configuration File</a></h2>
+
+  <p>When we invoke the build command, it creates a new instance of Fcm::Build,
+  which automatically creates a new instance of Fcm::CfgFile. If an argument
+  is specified in the build command, it is used as the build configuration
+  file if it is a regular file. Otherwise, it is used to search for the build
+  configuration file. If no argument is specified, the current working directory
+  is searched. Fcm::CfgFile will attempt to locate a file called "bld.cfg"
+  under this directory. If such a file is not found, it will attempt to locate
+  it under "cfg/bld.cfg".</p>
+  
+  <p>Once a file is located, Fcm::CfgFile will attempt to parse it. This is
+  done by reading and processing each line of the configuration file into
+  separate label, value and comment fields. Each line is then pushed into an
+  array that can be fetched using the "lines" method of the Fcm::CfgFile
+  instance. Internally, each line is recorded as a reference to a hash table
+  with the following keys:</p>
+
+  <ul class="pad">
+    <li>LABEL: the label of a declaration.</li>
+
+    <li>VALUE: the value of a declaration.</li>
+
+    <li>COMMENT: the comment following a declaration or the comment in a
+    comment line.</li>
+
+    <li>NUMBER: the line number of the current line in the source file.</li>
+
+    <li>SRC: the name of the source file.</li>
+  </ul>
+  
+  <p>The information given by each line is "deciphered" by Fcm::Build. The
+  information is processed in the following ways:</p>
+
+  <ul class="pad">
+    <li>The configuration file type "CFG::TYPE" and version "CFG::VERSION"
+    declarations are stored as properties of the Fcm::CfgFile instance.
+    Fcm::Build uses the information to ensure that it is reading a build
+    configuration file.</li>
+
+    <li>Build target(s) declarations "TARGET" are delimited by space
+    characters. Each target is pushed into the array reference "TARGET".</li>
+
+    <li>The location of the build root directory "DIR::ROOT" and its
+    sub-directories are stored in the "DIR" hash reference in the Fcm::Build
+    instance.  The keys of the hash table are the internal names of the
+    sub-directories, and the values are the locations of the
+    sub-directories.</li>
+
+    <li>The source directories "SRC::&lt;pcks&gt;" are stored in the "SRCDIR"
+    hash reference under the Fcm::Build instance. The keys of the hash table
+    are the names of the sub-packages. (If package names are delimited by the
+    double colons "::", they are turned into the double underscores "__" at
+    this stage.) The values of the "SRCDIR" hash reference are new instances
+    of Fcm::SrcPackage. When initialised, Each Fcm::SrcPackage creates a list
+    of source files in its source directory. For each source file in the list,
+    a new instance of Fcm::SrcFile is created, and pushed into the the
+    "SRCFILE" array reference under the Fcm::SrcPackage instance. When
+    initialised, each Fcm::SrcFile instance will attempt to determine the type
+    associated with the source file. This information can be fetched using the
+    "type" method of the Fcm::SrcFile instance.</li>
+
+    <li>Pre-processor switches "PP[::&lt;pcks&gt;]" declarations are stored in
+    the "PP" hash reference under the Fcm::Build instance. The keys of this hash
+    table are the names of the sub-packages, prefix with PP and a pair of
+    underscores, i.e. "PP__&lt;pcks&gt;". The declaration to switch on/off
+    pre-processing globally is stored using the key "PP". The values in the
+    hash table is either true (1) or false (0).</li>
+
+    <li>A tool declaration "TOOL::&lt;name&gt;[::&lt;pcks&gt;]" is stored as
+    a setting in Fcm::Config as ("TOOL", &lt;name&gt;[__&lt;pcks&gt;]. The
+    value of the declaration can then be fetched using the "setting" method of
+    the Fcm::Config instance.</li>
+
+    <li>An exclude dependency declaration "EXCL_DEP[::&lt;pcks&gt;]" is stored
+    as a setting in Fcm::Config as ("EXCL_DEP", &lt;value&gt;, &lt;pcks&gt;,
+    where &lt;value&gt; is the value of the declaration. For an exclude
+    dependency declaration that applies globally, &lt;pcks&gt; is set to a
+    null string "".) The value of an exclude dependency setting is always set
+    to 1.</li>
+
+    <li>Input file extension declaration "INFILE_EXT::&lt;ext&gt;" is stored
+    as a setting in Fcm::Config as ("INFILE_EXT", &lt;ext&gt;). The value of
+    the setting can then be fetched using the "setting" method of the
+    Fcm::Config instance.</li>
+
+    <li>Output file extension declaration "OUTFILE_EXT::&lt;type&gt;" is
+    stored as a in Fcm::Config as ("OUTFILE_EXT", &lt;type&gt;). The value of
+    the setting can then be fetched using the "setting" method of the
+    Fcm::Config instance.</li>
+
+    <li>For each "USE" declaration to use a pre-compiled build, a new instance of
+    Fcm::Build is created. The instance Fcm::Build for the previous build
+    creates a new instance of Fcm::CfgFile for its configuration file. The
+    configuration of the previous build is read and processed as described
+    above. The current instance of Fcm::Build will then attempt to inherit the
+    settings of the previous build where appropriate. The Fcm::Build instance
+    for the pre-compiled build is pushed into the "USE" array reference under
+    the current Fcm::Build.</li>
+
+    <li>The inherit flags for targets "INHERIT::TARGET", source directories
+    "INHERIT::SRC[::&lt;pcks&gt;]" and pre-processor switches
+    "INHERIT::PP[::&lt;pcks&gt;]" are stored in the "INHERIT" hash reference
+    under the Fcm::Build instance. For declarations that apply globally, the
+    keys to the hash table are "TARGET", "SRCDIR" or "PP". If the declarations
+    apply to &lt;pcks&gt;, the keys are "SRCDIR__&lt;pcks&gt;" or
+    "PP__&lt;pcks&gt;". (The inherit target flag always applies globally.)</li>
+  </ul>
+
+  <p>Unless the search source flag "SEARCH_SRC" is switched off (0) in the build
+  configuration, Fcm::Build will attempt to search the source sub-directory
+  "src/" of the build root recursively for source directory sub-packages. The
+  source directories obtained in the search are treated as if they are
+  declared using "SRC::&lt;pcks&gt;" in the build configuration file.</p>
+
+  <h2><a name="flags">Compiler Flags</a></h2>
+
+  <p>As discussed in the user guide, if you declare the Fortran compiler flags
+  without specifying a sub-package, the declaration applies globally.
+  Otherwise, it only applies to the Fortran source files within the
+  sub-package. This is implemented via a simple "tool selection" mechanism. You
+  may have noticed that all TOOL declarations (and TOOL settings in
+  Fcm::Config) are turned into an environemnt variable declaration in the
+  generated <em>Makefile</em>. For example, if we have a
+  "FFLAGS__bar__egg__ham__foo" declaration, it will be declared as an
+  environment variable in the generated <em>Makefile</em>. Suppose we have a
+  source file "foo.f90" under the sub-package "bar::egg::ham". When we invoke
+  the compiler wrapper (i.e. "fcm_internal" and "Fcm::Compile") to compile the
+  source file, the system will first attempt to select from the FFLAGS
+  environment variable that matches the sub-package of the source file, which
+  is "FFLAGS__bar__egg__ham__foo" in this case. If the environment variable
+  does not exist, it will attempt to go one sub-package up, i.e.
+  "FFLAGS__bar__egg__ham", and so on until it reaches the global "FFLAGS"
+  declaration, (which should always exists).</p>
+
+  <p>For changes in compiler flags declaration, the build system should
+  trigger re-compilation of required targets only. This is implemented using a
+  "flags" file system. These "flags" files are dummy files created in the
+  "flags/" sub-directory of the build root. They are updated by the "touch"
+  command.  The following dependencies are followed:</p>
+
+  <ul>
+    <li>Source files are dependent on its own "flags" file. E.g. the file
+    Ops_Switch in sub-package ":ops::code::OpsMod_Control" is dependent
+    on "FFLAGS__ops__code__OpsMod_Control__Ops_Switch.flags".</li>
+
+    <li>The "flags" file of a source file is dependent on the "flags" file
+    of its container sub-package. E.g. the above flags file is dependent
+    on "FFLAGS__ops__code__OpsMod_Control.flags".</li>
+
+    <li>The "flags" file of a sub-package is dependent on the "flags"
+    file of its container sub-package. E.g. the above is dependent on
+    "FFLAGS__ops__code.flags", which is dependent on
+    "FFLAGS__ops.flags".</li>
+
+    <li>The "flags" file of a top-level package is dependent on the
+    "flags" file of the global flags. E.g. "FFLAGS__ops.flags" is
+    dependent on "FFLAGS.flags".</li>
+
+    <li>The "flags" file of the global "flags" file is dependent on the
+    "flags" file of the compiler command. E.g. "FFLAGS.flags" is
+    dependent on "FC.flags".</li>
+  </ul>
+  
+  <p>The system records changes in declared tools using a cache file, (called
+  ".bld_tool", located at the ".cache/" sub-directory of the built root). It
+  is basically a list of "TOOL::" declarations for the latest build.  When an
+  incremental build is invoked, the list is compared against the current set.
+  If there are changes (modification, addition and deletion) in any
+  declarations, the timestamp of the corresponding "flags" files will be
+  updated. Files depending on the updated "flags" file will then be considered
+  out of date by <em>make</em>, triggering a re-build of those files.</p>
+
+  <h2><a name="interface">Fortran 9X Interface Block Generator</a></h2>
+
+  <p>The build system generates an interface block file for each Fortran 9X
+  source file. If the original source file has been pre-processed, the system
+  uses the pre-processed source file. Otherwise, the system uses the original
+  source file. For each source file containing standalone subroutines and
+  functions, the system will generate an interface file containing the
+  interfaces for the subroutines and functions. The interface files for other
+  Fortran 9X source files are empty.</p>
+
+  <p>Fcm::Build controls the creation of interface files by searching for a
+  list of Fcm::SrcFile instances containing Fortran 9X source files, by
+  calling the "is_type ('FORTRAN9X')" method of each Fcm::SrcFile instance.
+  For each of Fortran 9X source file, a Fcm::BuildTask is created to "build"
+  the interface file. The build task is dependent on the interface
+  generator. The interface files will be re-generated if we change the
+  interface generator. The generated interface is held in an array initially.
+  If an old file exists, it is read into an array so that it can be compared
+  with the current one. The current interface is written to the interface file
+  if it is not the same as the old one, or if an old one does not already
+  exist.</p>
+
+  <p>FCM supports the use of <em>f90aib</em> and the ECMWF interface
+  generator. The latter is the default.</p>
+
+  <h2><a name="dependency">Depdendency Scanner</a></h2>
+
+  <p>For each source directory sub-package, the build system scans its source
+  files for dependency information. The dependency scanner uses a pre-defined
+  set of patterns and rules in Fcm::Config to determine whether a line in a
+  source file contains a dependency. Only source files of supported types are
+  scanned. The dependency information of a sub-package is stored in the memory
+  as well as a cache file. The latter can be re-used by subsequent incremental
+  builds. In an incremntal build, only those source files newer than the cache
+  file is re-scanned for dependency. The cache file is read/written using
+  temporary instances of Fcm::CfgFile.</p>
+
+  <p>The control of the source file selection process is handled by the
+  Fcm::SrcPackage instances, while the actual dependency scans are performed
+  via the scan_dependency method of the Fcm::SrcFile instances.</p>
+
+  <p>A dependency has a type. For example, it can be a Fortran module or an
+  include file. The type of a dependency determines how it will be used by the
+  source file during the <em>make</em> stage, and so it affects how the
+  <em>make</em> rule will be written for the source file. In memory, the
+  dependency information is stored in a hash table, which can be retrieved as
+  a property of the Fcm::SrcFile instance. The keys of the hash table are the
+  dependency items, and the values are their types.</p>
+
+  <p>A dependency is not added to the hash table if it matches with an exclude
+  dependency declaration for the current sub-package.</p>
+
+  <p>While the dependency scanner is scanning through each line of a Fortran
+  source file, the system also attempt to determine its internal name. This is
+  normally the name of the first compilable program unit defined in the
+  Fortran source file. The internal name is converted into lowercase (bearing
+  in mind that Fortran is case insensitive), and will be used to name the
+  compiled object file of the source file.</p>
+
+  <p>The package configuration file is a system to bypass the automatic
+  dependency scanner. It can also be used to add extra dependencies to a
+  source file in the package. The configuration file is a special file in a
+  source package. The lines in the file is read using a temporary instance of
+  Fcm::CfgFile created by Fcm::SrcPackage. All declarations in a package
+  configuration file apply to named source files. The declarations set the
+  properties of the Fcm::SrcFile instance associated with the source file. It
+  can be used to add dependencies to a source file, and to tell the system to
+  bypass automatic dependency scanning of the source file. Other modifications
+  such as the internal name (object file name) of a source file, or the target
+  name of the executable can also be set using the package configuration file
+  in the package containing the source file.</p>
+
+  <h2><a name="rule">Make Rule Generator</a></h2>
+
+  <p>The dependency information is used to create the <em>Makefile</em>
+  fragments for the source directory sub-packages. A <em>Makefile</em> fragment
+  is updated if it is older than its corresponding dependency cache file.</p>
+
+  <p>The following is a list of file types and their <em>make</em> rule
+  targets:</p>
+
+  <table class="pad" summary="list of file types and thier make rules"
+  border="1">
+    <tr>
+      <th colspan="2">File type</th>
+
+      <th>Targets</th>
+    </tr>
+
+    <tr>
+      <th rowspan="5">SOURCE</th>
+
+      <th>all</th>
+
+      <td>
+        <ul>
+          <li>compile: object file</li>
+
+          <li>touch: flags file for compiler flags</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>FPP and C</th>
+
+      <td>
+        <p>If the original source has not been pre-processed:</p>
+
+        <ul>
+          <li>touch: flags file for pre-processor definition macros</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>PROGRAM</th>
+
+      <td>
+        <ul>
+          <li>load: executable binary file</li>
+
+          <li>touch: flags file for loader (linker) flags</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>all except PROGRAM</th>
+
+      <td>
+        <ul>
+          <li>touch: "done" file to denote the resolution of all external
+          objects.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>all FORTRAN except PROGRAM and MODULE</th>
+
+      <td>
+        <ul>
+          <li>interface: "interface" file to denote that all dependent module
+          information files are up to date.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th colspan="2">INCLUDE</th>
+
+      <td>
+        <ul>
+          <li>cp: "include" file to "inc/" sub-directory</li>
+
+          <li>touch: "idone" file to denote the resolution of all external
+          objects.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th colspan="2">EXE and SCRIPT</th>
+
+      <td>
+        <ul>
+          <li>cp: executable file to "bin/" sub-directory</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th colspan="2">LIB</th>
+
+      <td>
+        <ul>
+          <li>ar: archive object library file</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <p>The resulting <em>Makefile</em> is made up of a top level
+  <em>Makefile</em> and a list of include ".mk" files, (one for each
+  sub-package). The toplevel <em>Makefile</em> consists of useful environment
+  variables, including the search path of each sub-directory, the build tools,
+  the verbose mode and the VPATH directives for different file types. It has
+  two top level build targets, "all" and "clean". The "all" target is the
+  default target, and the "clean" target is for removing the previous build
+  from the current build root. It also has a list of targets for building the
+  top level and the container sub-package "flags" files. At the end of the
+  file is a list of "include" statements to include the ".mk" files.</p>
+
+  <p>A the top of each of ".mk" files are local variables for locating the
+  source directories of the sub-package. Below that are the rules for building
+  source files in the sub-package.</p>
+
+  <h2><a name="pp">Pre-processing</a></h2>
+
+  <p>As discussed in the user guide, the PP switch can be used to switch on
+  pre-processing. The PP switch can be specified globally or for individual
+  sub-packages. (However, it does not go down to the level of individual
+  source files.) The "inheritance" relationship is similar to that of the
+  compiler flags.</p>
+
+  <p>Currently, only Fortran source files with uppercase file extensions and C
+  source files are considered to be source files requiring pre-processing. If
+  a sub-package source directory contains such files and has its PP switch set
+  to ON, the system will attempt to pre-process these files.</p>
+
+  <p>The system allows header files to be located anywhere in the source tree.
+  Therefore, a dependency scan is performed on all files requiring
+  pre-processing as well as all header files to obtain a list of "#include"
+  header file dependencies. For each header file or source file requiring
+  pre-processing, a new instance of Fcm::BuildTask is created to represent a
+  "target". Similar to the logic in <em>make</em>, a "target" is only up to
+  date if all its dependencies are up to date. The Fcm::BuildTask instance
+  uses this logic to pre-process its files. Dependent header files are updated
+  by copying them to the "inc/" sub-directory of the build root. The "inc/"
+  sub-directory is automatically placed in the search path of the
+  pre-processor command, usually by the "-I" option. Pre-processing is
+  performed by a method of the Fcm::SrcFile instance. The method builds the
+  command by selecting the correct set of pre-processor definition macros and
+  pre-processor flags, using an inheritance relationship similar to that used
+  by the compiler flags. Unlike <em>make</em>, however, Fcm::BuildTask only
+  updates the target if both the timestamp and the content are out of date.
+  Therefore, if the target already exists, the pre-processing command is only
+  invoked if the timestamp of the target is out of date. The output from the
+  pre-processor will then be compared with the content in the target. The
+  target is only updated if the content has changed.</p>
+
+  <p>Once a source file is pre-processed, subsequent build system operations
+  such as Fortran 9X interface block generation and dependency scan (for
+  creating the <em>Makefile</em>) will be based on the pre-processed source,
+  and not the original source file. If a source file requires pre-processing
+  and is not pre-processed at the pre-processing stage, it will be left to the
+  compiler to perform the task.</p>
+
+  <h2><a name="file-type">File Type Register</a></h2>
+
+  <p>The build system file type register is a simple interface for modifying
+  the default settings in the Fcm::Config module. There are two registers, one
+  for output file type and one for input file type.</p>
+
+  <p>The output file register is the simpler of the two. It is implemented as
+  a hash table, with the keys being the names of the file types as known by the
+  system internally, and the values being the suffices that will be added to
+  those output files. Therefore, the output file register allows us to modify
+  the suffix added to an output file of a particular type.</p>
+
+  <p>The input file register allows us to modify the type flags of a file
+  named with a particular extension. The type flags are keywords used by the
+  build system to determine what type of input files it is dealing with. It is
+  implemented as a list of uppercase keywords delimited by a pair of colons.
+  The order of the keywords in the string is insignificant. Internally, the
+  build system determines the action on a file by looking at whether it
+  belongs to a type that is tied with that particular action. For example, a
+  file that has the keyword "SOURCE" in its type flag will be treated as a
+  compilable source file, and so it will be written to the <em>Makefile</em>
+  with a rule to compile it.</p>
+
+  <h2><a name="makefile">The <em>Makefile</em></a></h2>
+
+  <p>The following items are automatically written to the <em>Makefile</em>:</p>
+
+  <ul>
+    <li>The root directory and sub-directories of the current build, as
+    environment variables FCM_ROOTDIR, etc.</li>
+
+    <li>The search path of the different types of output file, using a set of
+    "vpath" directives.</li>
+
+    <li>TOOL declarations in the build configuration file are exported as
+    environment variables.</li>
+
+    <li>The diagnostic verbose mode information.</li>
+
+    <li>The default build targets.</li>
+
+    <li>The rules for building the targets for all the source files.</li>
+  </ul>
+
+  <h2><a name="wrapper">The Compiler/Linker Wrapper</a></h2>
+
+  <p>Compile and link are handled by the <em>fcm_internal</em> wrapper script.
+  The wrapper script uses the environment variables exported by the
+  <em>Makefile</em> to generate the correct compiler (or linker) command for the
+  current source (or object) file. Depending on the diagnistic verbose level,
+  it also prints out various amount of diagnostic output.</p>
+
+  <p>For compilation, the wrapper does the following:</p>
+
+  <ol>
+    <li>Select the correct compiler for the current source file.</li>
+
+    <li>Specify the output file name for the current source file.</li>
+
+    <li>If pre-processing is left to the compiler, specify the definition
+    macros, if any, for the pre-processor.</li>
+
+    <li>Specify the "include" path, in case the source file has dependencies
+    on include files.</li>
+
+    <li>Specify the "compile only" option, if it is not already set.</li>
+
+    <li>Add any other user defined flags to the compiler command.</li>
+
+    <li>Run the command, sending the output to a temporary directory.</li>
+
+    <li>If the compile succeeded, move the output from the temporary directory
+    to the output object directory.</li>
+
+    <li>Otherwise, delete the output from the temporary directory.</li>
+
+    <li>If there are Fortran module definition files (*.mod, *.MOD, etc), move
+    them to the "inc/" sub-directory.</li>
+  </ol>
+
+  <p>For linking, the wrapper does the following:</p>
+
+  <ol>
+    <li>Create a temporary object archive library with all the object files
+    currently residing in the output object sub-directory.</li>
+
+    <li>Select the correct linker for the current main program object
+    file.</li>
+
+    <li>Specify the output file name for the main program.</li>
+
+    <li>Specify the main program object file.</li>
+
+    <li>Specify the link library search path and the temporary link
+    library.</li>
+
+    <li>Add any other user defined flags to the linker command.</li>
+
+    <li>Run the command, sending the output to a temporary directory.</li>
+
+    <li>If the link succeeded, move the output from the temporary directory to
+    the "bin/" sub-directory of the build root.</li>
+
+    <li>Otherwise, delete the output from the temporary directory.</li>
+
+    <li>Remove the temporary object archive library.</li>
+  </ol>
+
+  <h2><a name="inheritance">Inheriting from a Pre-compiled Build</a></h2>
+
+  <p>A build can inherit configurations, source files and other items from a
+  previous build. At the Perl source code level, this is implemented via hash
+  tables and search paths. At the <em>Makefile</em> level, this is implemented
+  using the "vpath" directives. The following is a summary:</p>
+
+  <ul>
+    <li>Build targets are stored in a list. Targets that are specified in the
+    configuration file in the previous build are pushed into the list first.
+    A target that is specified in the current configuration file is pushed
+    into the list if it has not already been specified.</li>
+
+    <li>Each source directory has a unique sub-package identifier and a path
+    location. If a source directory in the previous build has the same
+    sub-package identifier, its location as specified in the previous build
+    will be placed in the search path of the source directory. The directory
+    specified in the current build is searched for files before the directory
+    specified in the previous build.</li>
+
+    <li>Tool settings such as compiler flags are set via the configuration
+    hash table. Settings declared in the previous build overrides those of the
+    default, and settings declared in the current build overrides those
+    declared in the previous build.</li>
+
+    <li>Ditto for exclude dependency, input file extension and output file
+    extension declarations.</li>
+
+    <li>Build items such as object files, executable files and other dummy
+    files are inherited via search path (and/or "vpath"). For example, the
+    system searches the "obj/" sub-directory of the current build for object
+    files before looking at that of the previous build. The system does not
+    re-build an item that exists in the previous build and is up to date.</li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/code_management.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/code_management.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/code_management.html	(revision 329)
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Code Management System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content=
+  "FCM Detailed Design: Code Management System">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Code Management System
+  </address>
+
+  <h1>Code Management System</h1>
+
+  <p>The code management commands provided by FCM are generally wrappers around
+  the underlying Subversion commands intended to add functionality or make the
+  system easier to use. Most of the wrappers are very simple and you can find
+  all the information you need from the <a href=
+  "../user_guide/command_ref.html">command reference section</a> of the FCM
+  User Guide and from the source code (which all resides within the Perl
+  package <a href=
+  "http://www-nwp/~fcm/FCM/src/lib/Fcm/Cm.pm"><em>Fcm::Cm</em></a>.
+  This section describes the few areas which merit further discussion.</p>
+
+  <h2><a name="prompts">Interactive Prompts</a></h2>
+
+  <p>Several of the commands prompt for further information interactively. This
+  is done using the function "&amp;main::get_input". This allows a different
+  version of the function to be used depending on the calling program. When
+  called by the main <tt>fcm</tt> script this function simply prompts for
+  information on the command line. However, when called from
+  <tt>fcm_gui_internal</tt> (which runs commands within the GUI) this function
+  uses a dialog box generated using Perl-Tk.</p>
+
+  <p>This design ensures that the main <tt>fcm</tt> command has no dependency
+  on the Perl <em>Tk</em> module.</p>
+
+  <h2><a name="merge">Merging</a></h2>
+
+  <p><em>Explain the logic used in determining the base path and
+  revision.</em></p>
+
+  <h2><a name="gui">GUI</a></h2>
+
+  <p><em>Anything needed here?</em></p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/extract.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/extract.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/extract.html	(revision 329)
@@ -0,0 +1,388 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Extract System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design: Extract System">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Extract System
+  </address>
+
+  <h1>Extract System</h1>
+  
+  <p>In this chapter, we shall discuss in detail the design of the extract
+  system. For information of how to use the extract system, please see: <a
+  href="../user_guide/extract.html">FCM System User Guide &gt; The Extract
+  System</a>.</p>
+
+  <p>The extract system extracts source directories from different branches of
+  Subversion repositories, combining them with source directories from the
+  local file system to give a source directory tree suitable for feeding into
+  the build system. The system is written in a set of Perl modules. The extract
+  system uses a similar interface to the build system. It shares the same
+  command line interface and many other utilities with the code management
+  system and the build system.</p>
+
+  <h2><a name="io">Input and Output</a></h2>
+
+  <p>The extract system should provide the following outputs:</p>
+
+  <ul class="pad">
+    <li>a directory tree with the extracted source code suitable for feeding
+    into the build system.</li>
+
+    <li>a configuration file for the build system.</li>
+
+    <li>an expanded version of the current configuration file, so that the
+    current extraction can be re-used.</li>
+  </ul>
+
+  <p>The following inputs are required by the extract system:</p>
+
+  <ul class="pad">
+    <li>the location of the destination.</li>
+
+    <li>the location of the source, e.g a repository URL or a local file
+    system path.</li>
+
+    <li>the revision of the source, if applicable.</li>
+
+    <li>extra configuration settings to be exported to the build system.</li>
+
+    <li>the location of previous extractions, if the current extract is to be
+    based on them.</li>
+  </ul>
+
+  <h2><a name="component">Components</a></h2>
+
+  <p>The extract system uses the following commands, modules and tools:</p>
+
+  <table class="pad" summary="build system components" border="1">
+    <tr>
+      <th>Name</th>
+
+      <th>Category</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>fcm</th>
+
+      <td>Perl executable</td>
+
+      <td>Top level command line interface of the FCM system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::CfgFile</th>
+
+      <td>Perl module</td>
+
+      <td>A class for reading from and writing to configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Config</th>
+
+      <td>Perl module</td>
+
+      <td>A class that contains the configuration settings shared by all
+      FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Extract</th>
+
+      <td>Perl module</td>
+
+      <td>Main class that controls the running of the extract system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::ReposBranch</th>
+
+      <td>Perl module</td>
+
+      <td>A class that stores and processes information of a repository
+      branch.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::SrcDirLayer</th>
+
+      <td>Perl module</td>
+
+      <td>A class that stores and processes information of a "layer" in the
+      extraction sequence of a source directory.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Util</th>
+
+      <td>Perl module</td>
+
+      <td>A collection of utilities shared by all FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>svn</th>
+
+      <td>Subversion client</td>
+
+      <td>The following sub-commands are used: "info", "list", "export" and
+      "cat".</td>
+    </tr>
+
+    <tr>
+      <th>ksh</th>
+
+      <td>Unix shell</td>
+
+      <td>The following shell commands are used: "cp", "rm" and "mkdir".</td>
+    </tr>
+
+    <tr>
+      <th>rdist</th>
+
+      <td>Unix utility</td>
+
+      <td>A remote distribution tool for mirror the extracted source
+      directory to a remote host.</td>
+    </tr>
+
+    <tr>
+      <th>rsync</th>
+
+      <td>Unix utility</td>
+
+      <td>A remote synchronisation tool for mirror the extracted source
+      directory to a remote host.</td>
+    </tr>
+
+    <tr>
+      <th>remsh</th>
+
+      <td>Unix command</td>
+
+      <td>A command to invoke a shell on a remote host.</td>
+    </tr>
+  </table>
+
+  <h2><a name="task">Task</a></h2>
+  
+  <p>To do its job, the extract system executes the following tasks in
+  order:</p>
+
+  <ul class="pad">
+    <li>parse/decipher the extract configuration file.</li>
+
+    <li>establish the extraction sequence when dealing with extraction of
+    multiple branches of the same package.</li>
+
+    <li>extract or copy individual files from the source to the
+    destination.</li>
+
+    <li>generate of an expanded extraction configuration file to allow another
+    extraction to be based on the current one.</li>
+
+    <li>generate of a build configuration file.</li>
+
+    <li>mirror extracted source code and configuration files to a remote build
+    machine.</li>
+  </ul>
+
+  <h3><a name="task_cfg">The extract configuration</a></h3>
+
+  <p>When we invoke the FCM command, it creates a new instance of Fcm::Config,
+  which reads, processes and stores information from the central and user
+  configuration file. Configuration settings in Fcm::Config are then
+  accessible by all other modules used by the extract system.</p> 
+
+  <p>When we invoke the extract command, it creates a new instance of
+  Fcm::Extract, which automatically creates a new instance of the
+  Fcm::CfgFile. If an argument is specified in the command line, the argument
+  is used as the "basis". Otherwise, the current working directory is taken as
+  the basis. If the basis is a directory, Fcm::CfgFile will attempt to locate
+  a file called "ext.cfg" under this directory. If such a file is not found,
+  it will attempt to locate it under "cfg/ext.cfg". If the basis is a regular
+  file, the file itself is used.</p>
+  
+  <p>Once a file is located, Fcm::CfgFile will attempt to parse it. This is
+  done by reading and processing each line of the configuration file into
+  separate label, value and comment fields. If an INC declaration is
+  encountered, a new instance of Fcm::CfgFile is created to read the included
+  file as specified. The included lines are then added to the current array.
+  Each line is then pushed into an array that can be fetched as a property of
+  Fcm::CfgFile. Internally, each line is recorded as a reference to a hash
+  table with the following keys:</p>
+
+  <ul class="pad">
+    <li>LABEL: the label of a declaration.</li>
+
+    <li>VALUE: the value of a declaration.</li>
+
+    <li>COMMENT: the comment following a declaration or the comment in a
+    comment line.</li>
+
+    <li>NUMBER: the line number of the current line in the source file.</li>
+
+    <li>SRC: the name of the source file.</li>
+  </ul>
+  
+  <p>The information given by each line is "deciphered" by Fcm::Extract. The
+  information is processed in the following ways:</p>
+
+  <ul class="pad">
+    <li>The configuration file type and version declarations are stored as
+    properties of the Fcm::CfgFile instance. Fcm::Extract uses the
+    information to ensure that it is reading an extract configuration
+    file.</li>
+
+    <li>The destination directory declarations are stored in a hash table,
+    which is a property of the Fcm::Extract instance.</li>
+
+    <li>The remote destionation machine, logname and directory declarations
+    are stored in a hash table, which is another property of the Fcm::Extract
+    instance.</li>
+
+    <li>Build configuration declarations are stored in a hash table, which is
+    yet another property of the Fcm::Extract instance.</li>
+
+    <li>For each declaration of a repository branch, a new instance of
+    Fcm::ReposBranch is created, if it does not already exist. (A
+    Fcm::ReposBranch instance is identified by a "tag" property, which is the
+    combination of its package name and its branch name.) The REPOS, VERSION,
+    SRC and EXPSRC declarations set the "repos", "version", "dir" and "expdir"
+    properties of the Fcm::ReposBranch instance.</li>
+
+    <li>The override mode flag is stored as a property of the Fcm::Extract
+    instance.</li>
+
+    <li>For each declaration to USE a previous extract, a new instance of
+    Fcm::Extract is created, with its "extracted" property set to true. The
+    instance Fcm::Extract for the previous extraction creates a new instance of
+    Fcm::CfgFile for its configuration file. The configuration of the previous
+    extract is read and processed similarly to what was described above. The
+    current instance of Fcm::Extract will then attempt to inherit the settings
+    of the previous extraction where appropriate. The instances of the
+    previous extractions are stored in an array, which can be fetched as a
+    property of the current Fcm::Extract instance.</li>
+
+    <li>The INC declaration is ignored, as it is already processed by
+    Fcm::CfgFile.</li>
+
+    <li>The MIRROR declaration changes the setting (TOOL, MIRROR) in the
+    Fcm::Config instance.</li>
+  </ul>
+
+  <p>If a full extraction is required, Fcm::Extract will attempt to remove any
+  sub-directories created by previous extractions in the same location.
+  Destination directories are (re-)created as they are required.</p>
+
+  <p>For each repository branch, if the REPOS declaration is a file system
+  path, the VERSION declaration will be set automatically to the word "USER".
+  If the REPOS declaration matches a FCM URL keyword pattern, it is expanded
+  to the full URL. If REPOS is not in the local file system and the VERSION
+  declaration is not a number, the system will attempt to convert the keyword
+  back to a number. If the keyword is "HEAD", the system will use <tt>"svn
+  info"</tt> to determine the revision number. Otherwise, it will attempt to
+  match the keyword with a pre-defined FCM revision keyword. If there are any
+  expanded source directory (EXPSRC) declarations, the system will use
+  <tt>"svn ls -R"</tt> to search recursively for all normal source directories
+  containing regular files. These directories are then added to the "dir"
+  property of the Fcm::ReposBranch instance.</p>
+
+  <h3><a name="task_seq">The extraction sequence</a></h3>
+
+  <p>In the next step, the extract system converts the information given in
+  the list of repository branches into a list of source directory sub-package.
+  Each source directory sub-package will have a destination and a "stack" of
+  extraction sequence. The sequence is basically a list for locating the
+  source directories in the repository branches. The order of the sequence is
+  based on the order in which a repository branch is declared. The logic has
+  already been discussed in the user guide.</p>
+
+  <p>The sequence is implemented by a list of Fcm::SrcDirLayer instances. For
+  each Fcm::SrcDirLayer instance in an extraction sequence of a source
+  directory, the system will attempt to find out its "last commit" revision,
+  using the <tt>"svn info"</tt> command on the particular revision on the
+  given URL. This information is normally cached in a file called ".config" in
+  the cache sub-directory of the extraction destination root. For an
+  incremental extraction, the system will consult the cache to obtain the list
+  of "last commit" revisions for the source directories, instead of having to
+  go through a large number of <tt>"svn info"</tt> commands again. The cache
+  file is read/written using a temporary instance of Fcm::CfgFile. The label
+  in each line consists of the package name of the sub-package, its URL and a
+  revision number. The corresponding value is the "last commit" revision at
+  the given revision number.</p>
+
+  <h3><a name="task_ext">The extraction</a></h3>
+
+  <p>With the extraction sequence in place for each source directory, the
+  extraction itself can now take place. There are two steps in this
+  process.</p>
+
+  <p>For each "layer" in the extraction sequence of each source directory, if
+  the "layer" contains a repository URL, the system extracts from that URL the
+  source directory and place the resulting source files in a cache. From the
+  cache sub-directory of the destination root, the cache for each source
+  directory is placed under a relative path that reflects the sub-package name
+  of the source directory. Underneath this path is a list of directories
+  with names reflecting the name of the branch and the "last commit"
+  revision, (separated by double underscore "__"). These are where the cache of
+  the source files for the "layers" of the source directory are placed.</p>
+
+  <p>It is also worth noting that source files from the local file system are
+  not cached. They will be taken directly from their locations.</p>
+
+  <p>Once we have the cached "layers" (or branches) of the source directories,
+  the system will select the source files from the correct cache before
+  updating the destinations. The logic of which has already been discussed in
+  the user guide.</p>
+
+  <p>At the end of this stage, we should have a directory tree in the
+  destination source sub-directory, with the relative paths to the extracted
+  files reflecting the sub-package names of those files.</p>
+
+  <h3><a name="task_gen">The extract/build configuration generator</a></h3>
+
+  <p>If extraction completes without any error, the system will attempt to
+  write an expanded extract configuration file, where all revision keywords
+  are expanded into numbers, and all source directory packages are declared.
+  Subsequent dependent extractions will be able to re-use this configuration
+  without having to invoke the Subversion client for repository and revision
+  information.</p>
+
+  <p>The system will also attempt to produce a build configuration file for
+  feeding to the build system. The following "conversions" are performed:</p>
+
+  <ul>
+    <li>The destination root becomes the build root.</li>
+
+    <li>The destination directories are all are declared as the source
+    directories.</li>
+
+    <li>All BLD declarations are unchanged, except that the BLD prefixes are
+    removed from the label.</li>
+
+    <li>All USE extract configuration statements are converted to USE build
+    configuration statements.</li>
+  </ul>
+
+  <h3><a name="task_mir">The mirror interface</a></h3>
+
+  <p>The system uses "rdist" or "rsync" to mirror the extracted source code
+  and the generated configuration files to a remote machine.</p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/index.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/index.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/index.html	(revision 329)
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+  <img src="logo.png" alt="Met Office logo" align="right">
+  <br clear="right">
+
+  <h1>FCM Detailed Design</h1>
+
+  <!-- Content -->
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown Copyright 2005-6</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+
+  <h2 align="center">Contents</h2>
+
+  <ol>
+    <li><a href="introduction.html">Introduction</a></li>
+
+    <li>
+      <a href="code_management.html">Code Management System</a>
+    </li>
+
+    <li>
+      <a href="extract.html">Extract System</a>
+    </li>
+
+    <li>
+      <a href="build.html">Build System</a>
+    </li>
+
+  </ol>
+
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/introduction.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/introduction.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/introduction.html	(revision 329)
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Introduction</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design: Introduction">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Introduction
+  </address>
+
+  <h1>Introduction</h1>
+
+  <p>This document contains the Detailed Design for the <em>Flexible
+  Configuration Management</em> system which is known as <em>FCM</em>.</p>
+
+  <p>A lot of information about the design of FCM can be found within:</p>
+
+  <ul class="pad">
+    <li>The <a href="../user_guide">FCM User Guide</a>. This contains all the
+    information which a user needs to know about FCM, including relevant
+    aspects of the design.</li>
+
+    <li>The FCM source code which is, we hope, well commented.</li>
+  </ul>
+
+  <p>Everything else which you might need to know about the design should be
+  described in the following sections. It includes higher level design
+  information not suited for inclusion in the source code but too detailed to
+  be included in the User Guide. It is intended for those who need to maintain
+  or develop the FCM system or simply for those who wish to obtain a deeper
+  understanding of how the system works. This document consists of the following
+  sections:</p>
+
+  <ul class="pad">
+    <li><a href="code_management.html">Code Management System</a></li>
+
+    <li><a href="extract.html">Extract System</a></li>
+
+    <li><a href="build.html">Build System</a></li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/maintain.js
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/maintain.js	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/maintain.js	(revision 329)
@@ -0,0 +1,11 @@
+// Display info about maintenance team
+
+// FCM contact URL
+var url     = 'http://www.metoffice.gov.uk/research/nwp/external/fcm/'
+var contact = '<a href="' + url + '">the FCM team</a>'
+
+// Output string 
+var out     = '<p></p><hr><address>Maintained by ' + contact + '.</address>'
+
+// Write to document
+document.write (out)
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/style.css
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/style.css	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/design/style.css	(revision 329)
@@ -0,0 +1,146 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+body {
+  background-color: #ffffcc;
+  color: black;
+  font-family: Arial, Helvetica, sans-serif;
+  font-size: 12pt;
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+table.head {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+
+table.foot {
+  background-color: #ccccff;
+  padding: 5px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+ol li {
+  margin: 5px;
+}
+
+ul.contents {
+  margin-bottom: 5px;
+  list-style-type: none;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+em {
+  font-style: italic;
+}
+
+strong {
+  font-weight: bold;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+div.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+p.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+div.yell td {
+  background-color: #ffffcc;
+}
+
+.pad th, .pad td, .pad li {
+  padding: 5px;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/etc/maintain.js
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/etc/maintain.js	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/etc/maintain.js	(revision 329)
@@ -0,0 +1,11 @@
+// Display info about maintenance team
+
+// FCM contact URL
+var url     = 'http://www.metoffice.gov.uk/research/nwp/external/fcm/'
+var contact = '<a href="' + url + '">the FCM team</a>'
+
+// Output string 
+var out     = '<p></p><hr><address>Maintained by ' + contact + '.</address>'
+
+// Write to document
+document.write (out)
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/etc/style.css
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/etc/style.css	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/etc/style.css	(revision 329)
@@ -0,0 +1,146 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+body {
+  background-color: #ffffcc;
+  color: black;
+  font-family: Arial, Helvetica, sans-serif;
+  font-size: 12pt;
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+table.head {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+
+table.foot {
+  background-color: #ccccff;
+  padding: 5px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+ol li {
+  margin: 5px;
+}
+
+ul.contents {
+  margin-bottom: 5px;
+  list-style-type: none;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+em {
+  font-style: italic;
+}
+
+strong {
+  font-weight: bold;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+div.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+p.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+div.yell td {
+  background-color: #ffffcc;
+}
+
+.pad th, .pad td, .pad li {
+  padding: 5px;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/1-1.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/1-1.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/1-1.html	(revision 329)
@@ -0,0 +1,488 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM 1.1 Release Notes</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Release Notes">
+  <meta name="keywords" content="FCM, release">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <h1>FCM 1.1 Release Notes<br>
+  06 November 2006</h1>
+
+  <p>These are the release notes for FCM release 1.1. You can use this release
+  of FCM freely under the terms of the <a href="../../LICENSE.html">FCM
+  LICENSE</a>, which you should receive with this distribution. Release 1.1 is
+  the first external release of FCM. (Release 1.0, 30 November 2005, was an
+  internal Met Office release which marked the start of the main migration of
+  systems into FCM.)</p>
+
+  <p>FCM is maintained by the FCM team at the Met Office. Please feedback any
+  bug reports or feature requests to us by <a href=
+  "mailto:fcm-team@metoffice.gov.uk">e-mail</a>.</p>
+
+  <h2>Contents</h2>
+
+  <ul>
+    <li><a href="#new">What's New?</a></li>
+
+    <li><a href="#fix">Minor Enhancements &amp; Bug Fixes</a></li>
+
+    <li><a href="#req">System Requirements</a></li>
+
+    <li><a href="#ins">Installation</a></li>
+  </ul>
+
+  <h2><a name="new" id="new">What's New?</a></h2>
+
+  <p>Build system:</p>
+
+  <ul>
+    <li>Support building of Fortran <span class="mono">BLOCKDATA</span> program
+    units.</li>
+
+    <li>Option to generate Fortran interface files in lower case names after
+    their program units.</li>
+
+    <li>Allow renaming of main program targets using the build configuration
+    file.</li>
+
+    <li>The <span class="mono">fcm_env.ksh</span> file now provides an
+    environment variable for the <span class="mono">etc/</span> sub-directory
+    of the build which can be used if you are "building" data files.</li>
+
+    <li>The build root directory is now locked while a build is running. This
+    prevents multiple instances of build running in the same directory.
+    However, you can bypass the lock if you specify the new <span class=
+    "mono">--ignore-lock</span> option with <span class="mono">fcm
+    build</span>.</li>
+  </ul>
+
+  <p>Extract system:</p>
+
+  <ul>
+    <li>The destination root directory is now locked while an extract is
+    running. This prevents multiple instances of extract running in the same
+    directory. However, you can bypass the lock if you specify the new
+    <span class="mono">--ignore-lock</span> option with <span class="mono">fcm
+    extract</span>.</li>
+  </ul>
+
+  <p>Code management commands:</p>
+
+  <ul>
+    <li><span class="mono">fcm merge</span> now supports custom and reverse
+    modes.</li>
+
+    <li><span class="mono">fcm merge</span> now allows automatic merges in
+    sub-trees if it is safe.</li>
+
+    <li><span class="mono">fcm merge</span> now handles automatic merges from
+    sibling branches that are created at different revisions of the
+    parent.</li>
+
+    <li><span class="mono">fcm branch, fcm diff --branch</span> and
+    <span class="mono">fcm merge</span> can now handle creation, diff and
+    automatic merge of a branch of a branch.</li>
+
+    <li><span class="mono">fcm switch</span> is improved to allow safer
+    switches of your working copy to point to different branches in your
+    project.</li>
+
+    <li><span class="mono">fcm commit</span> now displays your location in the
+    branch, and extra warning when you are committing to the trunk of a
+    project.</li>
+
+    <li>New <span class="mono">fcm mkpatch</span> command.</li>
+  </ul>
+
+  <p>General:</p>
+
+  <ul>
+    <li>Error handling is improved.</li>
+
+    <li>The User Guide is now complete, with a much improved tutorial.</li>
+
+    <li>New document: Fortran coding standard for FCM.</li>
+  </ul>
+
+  <h2><a name="fix" id="fix">Minor Enhancements &amp; Bug Fixes</a></h2>
+
+  <p>Build system:</p>
+
+  <ul>
+    <li>Ignore empty Fortran source files, so that alternate sections can be
+    handled correctly.</li>
+
+    <li>Handle recursive header file dependency correctly in pre-processing
+    stage.</li>
+
+    <li>Identify changes in pre-processed source file, the pre-processor
+    options and "keys" correctly in incremental builds.</li>
+
+    <li>Improve speed of pre-processing in incremental builds by not performing
+    any unnecessary null-action pre-processing.</li>
+
+    <li>Load archiver no longer includes main program objects.</li>
+
+    <li>It is now possible for a sub-package to exclude particular types of
+    dependencies.</li>
+  </ul>
+
+  <p>Extract system:</p>
+
+  <ul>
+    <li>Sub-directories are now extracted with the non-recursive mode of
+    <span class="mono">svn export</span>.</li>
+
+    <li>Peg revisions should now be handled correctly in <span class=
+    "mono">INC</span> extract declarations.</li>
+
+    <li>The command should now fail if a declared source directory does not
+    exist or if the update of an extract destination fails.</li>
+  </ul>
+
+  <p>Code management commands:</p>
+
+  <ul>
+    <li><span class="mono">fcm branch --info</span> and <span class="mono">fcm
+    diff</span> can now take a <span class="mono">PATH</span> as an
+    argument.</li>
+
+    <li>The <span class="mono">--ticket</span> option of <span class="mono">fcm
+    branch --create</span> can now accept multiple tickets.</li>
+
+    <li><span class="mono">fcm branch --info</span> and <span class="mono">fcm
+    diff --branch</span> should now work correctly in a sub-tree of a
+    branch.</li>
+
+    <li><span class="mono">fcm branch --create</span> no longer offers to
+    checkout the branch.</li>
+
+    <li><span class="mono">fcm commit</span> no longer fails when adding a new
+    symbolic link.</li>
+
+    <li>The <span class="mono">--password</span> option is now supported by the
+    <span class="mono">fcm branch --create, fcm branch --delete, fcm
+    commit</span> and <span class="mono">fcm delete</span> commands.</li>
+
+    <li>Empty arguments to code management commands are now parsed
+    correctly.</li>
+
+    <li>The <span class="mono">fcm diff --graphical</span> option no longer
+    fails with binary files.</li>
+
+    <li>FCM will always set the environment variable <span class=
+    "mono">LANG=en_GB</span> before running Subversion commands. This prevents
+    failure of FCM when it attempts to parse output from Subversion commands
+    when a different <span class="mono">LANG</span> setting is used.</li>
+  </ul>
+
+  <p>General:</p>
+
+  <ul>
+    <li>Various other very minor enhancements and bug fixes.</li>
+  </ul>
+
+  <h2><a name="req" id="req">System Requirements</a></h2>
+
+  <h3><a name="req_perl" id="req_perl">Perl</a></h3>
+
+  <p>The core part of FCM is a set of Perl scripts and modules. For the build
+  system to work, you need the following modules installed:</p>
+
+  <ul>
+    <li class="mono">Carp</li>
+
+    <li class="mono">Cwd</li>
+
+    <li class="mono">File::Basename</li>
+
+    <li class="mono">File::Compare</li>
+
+    <li class="mono">File::Find</li>
+
+    <li class="mono">File::Path</li>
+
+    <li class="mono">File::Spec::Functions</li>
+
+    <li class="mono">File::Spec</li>
+
+    <li class="mono">FindBin</li>
+
+    <li class="mono">Getopt::Long</li>
+
+    <li class="mono">POSIX</li>
+  </ul>
+
+  <p>The code management commands and extract system need the following
+  additional modules installed:</p>
+
+  <ul>
+    <li class="mono">File::Temp</li>
+
+    <li class="mono">Getopt::Long</li>
+
+    <li class="mono">HTTP::Date</li>
+
+    <li class="mono">XML::DOM</li>
+  </ul>
+
+  <p>To use the simple GUI for some of the code management commands, you also
+  need the following modules:</p>
+
+  <ul>
+    <li class="mono">Tk::ROText</li>
+
+    <li class="mono">Tk</li>
+  </ul>
+
+  <p>At the Met Office we are currently using the complete FCM system with Perl
+  5.8.x. In addition the build system is being used with Perl 5.6.x.</p>
+
+  <h3><a name="req_svn" id="req_svn">Subversion</a></h3>
+
+  <p>To use the code management commands (and relevant parts of the extract
+  system) you need to have <a href=
+  "http://subversion.tigris.org/">Subversion</a> installed.</p>
+
+  <ul>
+    <li>FCM makes extensive use of peg revisions in both the code management
+    and extract systems. This requires Subversion 1.2.0.</li>
+
+    <li>At the Met Office we are currently using Subversion 1.3.2 (although
+    1.2.3 was used until very recently).</li>
+  </ul>
+
+  <p>Note that the extract system can mirror extracted code to a remote
+  platform for building. Therefore it is only necessary to have Subversion
+  installed on the platform where you do your code development. If you use
+  other platforms purely for building and running then you do not need to have
+  Subversion installed on these platforms.</p>
+
+  <h3><a name="req_trac" id="req_trac">Trac</a></h3>
+
+  <p>The use of <a href="http://projects.edgewall.com/trac/">Trac</a> is
+  entirely optional (although highly recommended if you are using Subversion).
+  At the Met Office we are currently using version 0.9.6.</p>
+
+  <h3><a name="req_other" id="req_other">Other Requirements</a></h3>
+
+  <p>The <tt>fcm diff --graphical</tt> and <tt>fcm conflicts</tt> commands
+  require <a href="http://furius.ca/xxdiff/">xxdiff</a>. At the Met Office we
+  are currently using version 3.1.</p>
+
+  <p>The build system requires <a href=
+  "http://www.gnu.org/software/make/make.html">GNU make</a>. At the Met Office
+  we are currently using version 3.79.x and 3.80.</p>
+
+  <p>Optionally, the build system can use <a href=
+  "http://www.ifremer.fr/ditigo/molagnon/fortran90">f90aib</a> to generate
+  interface files. However, there is also a built in Perl based interface file
+  generator which is quicker and better in most cases so you are unlikely to
+  need f90aib unless you hit a problem with some particular code.</p>
+
+  <p>FCM is intended to run on a Unix/Linux system. It is currently used at the
+  Met Office on Linux (Red Hat 9 and Red Hat Enterprise 2.1 and 4.4) and HP-UX
+  11.00.</p>
+
+  <h2><a name="ins" id="ins">Installation</a></h2>
+
+  <p>FCM is distributed in the form of a compressed tar file. Un-pack the tar
+  file into an appropriate location on your system. Then add the <tt>bin</tt>
+  directory into your PATH. Once you have done this you should now have full
+  access to the FCM system, assuming that you have met the requirements
+  described in the previous section.</p>
+
+  <p>If you wish to define keywords for your systems you will need to create a
+  file <tt>etc/fcm.cfg</tt>. An example file, <tt>fcm.cfg.eg</tt>, is provided
+  which is a copy of the file currently used at the Met Office. For further
+  details please refer to the section <a href=
+  "../user_guide/system_admin.html#fcm-keywords">FCM keywords</a> in the System
+  Admin chapter of the User Guide.</p>
+
+  <p>The <tt>doc</tt> directory contains all the system documentation.</p>
+
+  <ul>
+    <li><tt>doc/release_notes</tt> contains these release notes. It also
+    contains the release notes for all previous versions which may be useful if
+    you have skipped any versions.</li>
+
+    <li><tt>doc/user_guide</tt> contains the FCM User Guide in both <a href=
+    "../user_guide/index.html">HTML</a> and <a href=
+    "../user_guide/fcm-user-guide.pdf">PDF</a> form.</li>
+
+    <li><tt>doc/design</tt> contains the <a href="../design/index.html">FCM
+    Detailed Design</a> document (currently in draft form).</li>
+
+    <li><tt>doc/standards</tt> contains the FCM <a href=
+    "../standards/perl_standard.html">Perl</a> and <a href=
+    "../standards/fortran_standard.html">Fortran</a> coding standards. The Perl
+    standard describes the standards followed by the FCM code. The Fortran
+    standard contains some <a href=
+    "../standards/fortran_standard.html#fcm">specific advice</a> on the best
+    way of writing Fortran code for use with FCM as well as more general advice
+    on good practise.</li>
+  </ul>
+
+  <p>The <tt>tutorial</tt> directory contains the files necessary to set up a
+  tutorial repository. This will allow you to follow the <a href=
+  "../user_guide/getting_started.html#tutorial">tutorial section</a> in the
+  User Guide.</p>
+
+  <ul>
+    <li>The file <tt>tutorial/repos/tutorial.dump</tt> should be loaded into an
+    empty repository using the <tt>svnadmin load</tt> command.</li>
+
+    <li>The hook scripts in <tt>tutorial/hook</tt> should then be installed in
+    this repository in order to prevent any commits to the trunk. Note that the
+    configuration file <tt>svnperms.conf</tt> assumes that the tutorial
+    repository is called <tt>tutorial_svn</tt>. Please edit this file if you
+    use a different name.</li>
+
+    <li>The repository should be configured to allow users write access. You
+    may find it easiest to simply allow anonymous access.</li>
+
+    <li>A Trac system should be configured associated with the Tutorial
+    repository. You then need to allow users write access. You may find it
+    easiest to set up a number of guest accounts for this purpose.</li>
+  </ul>
+
+  <p>The <tt>templates</tt> directory contains various example scripts which
+  you may find useful. Note that these scripts are all specific to the Met
+  Office and may contain hard coded paths and email addresses. They are
+  provided in the hope that you may find them useful as templates for setting
+  up similar scripts of your own. However, they should only be used after
+  careful review to adapt them to your environment. The contents are as
+  follows:</p>
+
+  <table summary="list of template scripts" border="1" width="100%">
+    <tr>
+      <th>Script</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-commit</th>
+
+      <td>
+        This script restricts write-access to the repository by checking the
+        following:
+
+        <ul>
+          <li>It executes the Subversion utility <tt>svnperms.py</tt> if it
+          exists. This utility checks whether the author of the current
+          transaction has enough permission to write to particular paths in the
+          repository.</li>
+
+          <li>It checks the disk space required by the current transaction. It
+          fails the commit if it requires more than 5Mb of disk space.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-commit</th>
+
+      <td>A simple post-commit hook script which runs the script
+      <tt>post-commit-background</tt> in the background.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-commit-background</th>
+
+      <td>
+        This script runs in the background after each commit
+
+        <ul>
+          <li>It updates a <tt>&lt;repos&gt;.latest</tt> file with the latest
+          revision number.</li>
+
+          <li>It creates a dump of the new revision.</li>
+
+          <li>It calls the script <tt>background_updates.pl</tt> if it
+          exists.</li>
+        </ul>This script is installed as standard in all our repositories.
+      </td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/background_updates.pl</th>
+
+      <td>An example of how you may want to set up a
+      <tt>background_updates.pl</tt> script to perform post-commit tasks for a
+      specific repository. This script uses a lock file to prevent multiple
+      commits in quick succession from causing problems.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-revprop-change</th>
+
+      <td>A simple pre-revprop-change hook script which runs the script
+      <tt>pre-revprop-change.pl</tt>.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-revprop-change.pl</th>
+
+      <td>If a user attempts to modify the log message of a changeset and
+      he/she is not the original author of the changeset, this script will
+      e-mail the original author. You can also set up a watch facility to
+      monitor changes of log messages that affect particular paths in the
+      repository. For further details please refer to the section <a href=
+      "../user_guide/system_admin.html#svn_watch">Watching changes in log
+      messages</a> in the System Admin chapter of the User Guide.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-revprop-change</th>
+
+      <td>A simple post-revprop-change hook script which runs the script
+      <tt>post-revprop-change.py</tt>.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-revprop-change.py</th>
+
+      <td>This hook script updates the Trac SQLite database following a
+      successful change in the log message.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/cron_template.ksh</th>
+
+      <td>An example of how you might set up a cron job to make use of the
+      <tt>&lt;repos&gt;.latest</tt> file.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/daily_cron</th>
+
+      <td>The cron job which we run each night. It verifies and backs up each
+      of our repositories, housekeeps the revision dumps created by
+      <tt>post-commit-background</tt> and backs up each of our Trac systems. It
+      also handles the distribution of FCM to various platforms at the Met
+      Office.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/fcm_add_trac.pl</th>
+
+      <td>This script sets up a new Trac system and applies some configuration
+      options which we use by default at the Met Office.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/recover_svn.pl</th>
+
+      <td>This script allows us to recover all of our Subversion repositories
+      by using the nightly backups and the repository dumps.</td>
+    </tr>
+  </table>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/maintain.js
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/maintain.js	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/maintain.js	(revision 329)
@@ -0,0 +1,11 @@
+// Display info about maintenance team
+
+// FCM contact URL
+var url     = 'http://www.metoffice.gov.uk/research/nwp/external/fcm/'
+var contact = '<a href="' + url + '">the FCM team</a>'
+
+// Output string 
+var out     = '<p></p><hr><address>Maintained by ' + contact + '.</address>'
+
+// Write to document
+document.write (out)
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/style.css
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/style.css	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/release_notes/style.css	(revision 329)
@@ -0,0 +1,146 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+body {
+  background-color: #ffffcc;
+  color: black;
+  font-family: Arial, Helvetica, sans-serif;
+  font-size: 12pt;
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+table.head {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+
+table.foot {
+  background-color: #ccccff;
+  padding: 5px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+ol li {
+  margin: 5px;
+}
+
+ul.contents {
+  margin-bottom: 5px;
+  list-style-type: none;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+em {
+  font-style: italic;
+}
+
+strong {
+  font-weight: bold;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+div.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+p.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+div.yell td {
+  background-color: #ffffcc;
+}
+
+.pad th, .pad td, .pad li {
+  padding: 5px;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/fortran_standard.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/fortran_standard.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/fortran_standard.html	(revision 329)
@@ -0,0 +1,1157 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Fortran coding standard for FCM</title>
+  <meta name="author" content="FCM team">
+  <meta name="descriptions" content="Fortran coding standard for FCM">
+  <meta name="keywords" content="Fortran, coding standard, FCM">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="StyleSheet" type="text/css" href="style.css">
+  <style type="text/css">
+  <!--
+  li, th, td {
+    padding: 3px;
+  }
+  td {
+    vertical-align: top;
+  }
+  mono {
+    font-family: monospace;
+  }
+  -->
+  </style>
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85"
+  height="85"></p>
+
+  <h1>Fortran coding standard for FCM</h1>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown copyright 2006. All rights reserved.</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+
+  <h2>Contents</h2>
+
+  <p>Main contents:</p>
+
+  <ol>
+    <li><a href="#intro">Introduction</a></li>
+
+    <li>
+      <a href="#fcm">Programming Fortran for the FCM build system</a>
+
+      <ul>
+        <li><a href="#fcm-general">General</a></li>
+
+        <li><a href="#fcm-cpp">Use of C pre-processor</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="#fortran">Programming Fortran in general</a>
+
+      <ul>
+        <li><a href="#fortran-layout">Layout and formatting</a></li>
+
+        <li><a href="#fortran-style">Style</a></li>
+
+        <li><a href="#fortran-feature">Fortran features</a></li>
+      </ul>
+    </li>
+
+    <li><a href="#template">Program templates</a></li>
+  </ol>
+
+  <h2><a name="intro"></a>1. Introduction</h2>
+
+  <p>Fortran is the standard programming language at the Met Office for
+  developing scientific and research applications, in particular, for programs
+  running on the supercomputers. This document describes some guidelines that
+  should be followed by developers when writing Fortran code, especially for
+  code in systems hosted by FCM.</p>
+
+  <h2><a name="fcm"></a>2. Programming Fortran for the FCM build system</h2>
+
+  <h3><a name="fcm-general"></a>2.1 General</h3>
+
+  <p>To get the most out of the FCM build system, you should follow these
+  guidelines when you develop your code:</p>
+
+  <ol>
+    <li>Each source file should contain one and no more than one top level
+    program unit, (such as a PROGRAM, a standalone SUBROUTINE/FUNCTION or a
+    MODULE). All top level standalone program units in a source tree should be
+    uniquely named. ("Top level" means a standalone program unit that is
+    compilable independently, i.e. this rule does not restrict the naming and
+    placements of sub-programs in a CONTAINS section.) FCM may fail to set up
+    the dependency tree of your source correctly if you do not follow this rule.
+
+      <p>A clash of program unit names happens most often when you have multiple
+      versions of the same program unit in the same source tree. You should
+      design your code to avoid this situation. If it is not possible to do so,
+      you may have to use a pre-processor to ensure that there is only one copy
+      of each program unit in the source tree. Another situation where clashes
+      of program unit names may occur is when you are developing code that is
+      shared between several projects. In this case, you may want to agree with
+      the other projects a naming convention to define a unique namespace for
+      program units in each project. (E.g. some projects at the Met Office have
+      adopted a naming convention such that all shared program units in a
+      project are named with a unique prefix.)</p>
+    </li>
+
+    <li>All code should be written using the free source form. (At Fortran 95,
+    the free source form can have a maximum of 132 characters per line, and up
+    to 39 continuations in a Fortran statement.) The fixed source form is
+    obsolete, and is not supported by the interface file generators used by
+    FCM.</li>
+
+    <li>An interface should be provided when calling a SUBROUTINE or a FUNCTION.
+    Not only is this considered good practice, it also allows FCM to determine
+    the dependency relationship of your source files. An interface can be
+    provided in these ways:
+
+      <table summary="interface - internal procedures" width="100%" border="1">
+        <tr>
+          <th colspan="2">Internal sub-program</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">Place sub-programs in the CONTAINS section of a
+          standalone program unit. There are two advantages for this approach.
+          Firstly, the sub-programs will get an automatic interface when the
+          container program unit is compiled. Secondly, it should be easier for
+          the compiler to provide optimisation when the sub-programs are
+          internal to the caller.  The disadvantage of this approach is that the
+          sub-programs are local to the caller, and so they cannot be called by
+          other program units.  Therefore, this approach is only suitable for
+          small sub-programs local to a particular program unit.
+        
+            <p>Note: One way to share a sub-program unit between several top
+            level program units is to make use of the Fortran INCLUDE statement.
+            You can write the sub-program unit in a separate file and place it
+            in the CONTAINS section of different program units using INCLUDE
+            statements.  The disadvantage of this approach is that when the
+            program is compiled, a copy of the sub-program unit will be embedded
+            within each of the top level program units. This may lead to an
+            increase in size of the executable, and so this approach is still
+            only suitable for small sub-programs local to a small number of
+            program units.</p>
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "sub_prog.inc":
+
+            <pre>
+SUBROUTINE sub_prog (some, arg)
+! Some declarations ...
+! Some executable statements ...
+END SUBROUTINE sub_prog
+</pre>
+          </td>
+
+          <td>In the file "bar.f90":
+
+            <pre>
+SUBROUTINE bar (more, arg)
+! Some declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arg)
+! More executable statements ...
+CONTAINS
+  INCLUDE 'sub_prog.inc'
+END SUBROUTINE bar
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <table summary="interface - module procedures" width="100%" border="1">
+        <tr>
+          <th colspan="2">Module procedures</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">Place sub-programs in the CONTAINS section of a
+          MODULE. Again, the sub-programs will have automatic interfaces when
+          the MODULE is compiled.  If you give the sub-programs the PUBLIC
+          attribute (which is the default), you will be able to call them from
+          anywhere using the current MODULE. You will also gain all the
+          advantages offered by a MODULE. (E.g. a MODULE will allow you to
+          design your code in a more object-oriented manner.) However, MODULE
+          dependency can have an impact on the efficiency of incremental
+          compilations. For example, if you modify items that are local to the
+          MODULE, it is very difficult for the build system to detect that your
+          change does not affect program units using the MODULE, so the build
+          system will end up compiling the MODULE and all the program units that
+          use it.
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "my_mod.f90":
+
+            <pre>
+MODULE my_mod
+! Some module declarations
+CONTAINS
+  SUBROUTINE sub_prog (some, arg)
+  ! Some declarations ...
+  ! Some executable statements ...
+  END SUBROUTINE sub_prog
+END MODULE my_mod
+</pre>
+          </td>
+
+          <td>In the file "foo.f90":
+
+            <pre>
+SUBROUTINE foo (some, arg)
+USE my_mod, ONLY: sub_prog
+! Some declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arg)
+! More executable statements ...
+END SUBROUTINE foo
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <table summary="interface - interface files" width="100%" border="1">
+        <tr>
+          <th colspan="2">Interface files</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">For each source file containing a standalone
+          SUBROUTINE or FUNCTION, FCM generates a file containing the interface
+          of the SUBROUTINE or FUNCTION. By default, the generated file is named
+          after the original source file, but with the file extension replaced
+          by "*.interface". In the specification section of the caller routine,
+          you will then be able to declare the interface using a Fortran INCLUDE
+          statement to include the interface file. This type of INCLUDE
+          statement is detected automatically by FCM, which will use it to set
+          up the dependency tree.
+        
+            <p>The advantage of using an interface file is that the caller is
+            now dependent on the interface file, rather than the SUBROUTINE or
+            FUNCTION itself. If you change the SUBROUTINE or FUNCTION without
+            modifying its interface, the build system will not re-compile the
+            caller in incremental build, (but it will be intelligent enough to
+            re-link the executable with the updated object).</p>
+
+            <p>Note: By default, an interface file is named after the original
+            source file. Bearing this in mind, it is worth noting that file
+            names in a Unix/Linux system are case-sensitive, and so the
+            interface file name declared by your INCLUDE statement is also case
+            sensitive. If you use an incorrect case in the INCLUDE statement,
+            the dependency tree will be set up incorrectly and the compilation
+            will fail. Another problem is that if you do not name your file
+            after the program unit, the dependency tree will be wrong. To avoid
+            this problem, it is recommended that all source files are named in
+            lower case after the program units they contain. (Alternatively, you
+            can use the TOOL::INTERFACE option in the FCM build configuration
+            file to allow you to alter the default behaviour so that the
+            interface file is named after the "program" unit in lowercase. We
+            may alter FCM in the future so that this will become the default. In
+            the mean time, it is highly recommended that you use this option and
+            design your new code accordingly.)</p>
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "sub_prog.f90":
+
+            <pre>
+SUBROUTINE sub_prog (some, arg)
+! Some declarations ...
+! Some executable statements ...
+END SUBROUTINE sub_prog
+</pre>
+          </td>
+
+          <td>In the file "egg.f90":
+
+            <pre>
+SUBROUTINE egg (some, arg)
+! Some declarations ...
+INCLUDE 'sub_prog.interface'
+! More declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arg)
+! More executable statements ...
+END SUBROUTINE egg
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <table summary="interface - interfaces in a module" width="100%" border="1">
+        <tr>
+          <th colspan="2">Interfaces in a module</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">There is also a half-way house approach between the
+          second and the third options. You can have a dedicated MODULE where a
+          large number of INCLUDE interface file statements are placed. Other
+          program units get their interfaces by importing from this MODULE. A
+          major disadvantage of this approach is that the sub-programs with
+          their interfaces declared within this MODULE will not be able to call
+          any other sub-programs declared within the same MODULE, as it will run
+          into a cyclic dependency problem. Another disadvantage is that if an
+          interface changes, the MODULE and all program units depending on the
+          MODULE will have to be re-compiled, even though the change may be
+          unrelated to some or all of these program units. For these reasons,
+          this approach is only good if you have a bundle of sub-programs that
+          have relatively stable interfaces and are very much independent of one
+          another.
+
+            <p>Note: a similar approach can be useful when you have a library of
+            legacy or external code. In this situation, you will simply declare
+            the interfaces for all the library sub-programs in the MODULE. Any
+            programs that call sub-programs within the library can then import
+            their interfaces by using the MODULE.</p>
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "my_i_mod.f90":
+
+            <pre>
+MODULE my_i_mod
+! Some declarations
+INCLUDE 'sub_prog.interface'
+! More declarations
+END MODULE my_i_mod
+</pre>
+          </td>
+
+          <td>In the file "ham.f90":
+
+            <pre>
+SUBROUTINE ham (some, arguments)
+USE my_i_mod, ONLY: sub_prog
+! Some declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arguments)
+! More executable statements ...
+END SUBROUTINE ham
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <p>FCM also supports the use of a <tt>"! DEPENDS ON"</tt> directive for
+      users to specify a dependency from within a source file. This feature is
+      documented in the <a href=
+      "../user_guide/build.html#advanced_dependency">Further dependency
+      features</a> sub-section of the <a href="../user_guide/">FCM user
+      guide</a>. However, it is worth noting that this method is only included
+      in FCM to support legacy code. It is not a feature recommended for new
+      code, and its use should be gradually phased out from existing code.</p>
+    </li>
+
+    <li>Arguments and local variables should be declared in different
+    statements. It makes your declaration clearer, and it is friendlier to the
+    interface file generator.
+
+      <table summary="declaration example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+SUBROUTINE foo (a, b, c)
+
+INTEGER :: a, b, c, i, j, k
+
+! ...
+
+END SUBROUTINE foo
+</pre>
+          </td>
+
+          <td>
+            <pre>
+SUBROUTINE foo (a, b, c)
+
+INTEGER :: a, b, c
+
+INTEGER :: i, j, k
+
+! ...
+
+END SUBROUTINE foo
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Use the ONLY clause in a USE &lt;module&gt; statement to declare all
+    imported symbols (i.e. parameters, variables, functions, subroutines, etc).
+    This makes it easier to locate the source of each symbol, and avoids
+    unintentional access to other PUBLIC symbols within the MODULE. It is also
+    friendlier to the compiler and the interface file generator, as they will
+    not have to import modules and symbols that are unnecessary.</li>
+
+    <li>In its default settings, FCM recognises the following file extensions
+    as Fortran free format source files:
+
+      <ul>
+        <li>*.f90, *.f95: regular Fortran free format source files</li>
+
+        <li>*.F90, *.F95: Fortran free format source files that require
+        pre-processing</li>
+
+        <li>*.inc: INCLUDE files that can be added to a regular Fortran free
+        format source file with a Fortran INCLUDE statement</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="fcm-cpp"></a>2.2 Use of C pre-processor with Fortran</h3>
+
+  <p>We do not recommend the use of C pre-processor with Fortran. However, it is
+  acknowledged that there are some situations when it is necessary to
+  pre-process Fortran code. FCM supports pre-processing in two ways.
+  Pre-processing can be left to the compiler or it can be done in a separate
+  early stage of the build process. A separate pre-process stage can be useful
+  if pre-processing changes any of the following in a program unit:</p>
+
+  <ul>
+    <li>its name</li>
+
+    <li>its calling interface</li>
+
+    <li>its dependencies</li>
+  </ul>
+
+  <p>However, using a separate pre-process stage is not the best way of working,
+  as it adds an overhead to the build process. If your code requires
+  pre-processing, you should try to design it to avoid changes in the above.</p>
+
+  <p>In practice, the only reasonable use of C pre-processor with Fortran is for
+  code selection. For example, pre-processing is useful for isolating machine
+  specific libraries or instructions, where it may be appropriate to use inline
+  alternatives for small sections of code. Another example is when multiple
+  versions of the same procedure exist in the source tree and you need to use
+  the pre-processor to select the correct version for your build.</p>
+
+  <p>Avoid using the C pre-processor for code inclusion, as you should be able
+  to do the same via the Fortran INCLUDE statement. You should also avoid
+  embedding pre-processor macros within the continuations of a Fortran
+  statement, as it can make your code very confusing.</p>
+
+  <h2><a name="fortran"></a>3. Programming Fortran in general</h2>
+
+  <p>The guidelines in this section are recommended practices for programming
+  Fortran in general. These are guidelines you should try to adhere to when you
+  are developing new code. If you are modifying existing code, you should adhere
+  to its existing standard and style where possible. If you want to change its
+  standard and style, you should seek prior agreements with the owner and the
+  usual developers of the code. Where possible, you should try to maintain the
+  same layout and style within a source file, and preferably, within all the
+  source code in a particular project.</p>
+
+  <p>When reading these guidelines, it is assumed that you already have a good
+  understanding of modern Fortran terminology. It is understood that these
+  guidelines may not cover every aspect of your work. In such cases, you will
+  be a winner if you use a bit of common sense, and always bearing in mind that
+  some other people may have to maintain the code in the future.</p>
+
+  <p>Always test your code before releasing it. Do not ignore compiler warnings,
+  as they may point you to potential problems.</p>
+
+  <h3><a name="fortran-layout"></a>3.1 Layout and formatting</h3>
+
+  <p>The following is a list of recommended practices for layout and formatting
+  when you write code in Fortran.</p>
+
+  <ul>
+    <li>Indent blocks by 2 characters. Where possible, comments should be
+    indented with the code within a block.</li>
+
+    <li>Use space and blank lines where appropriate to format your code to
+    improve readability. (Use genuine spaces but avoid using tabs, as the "tab"
+    character is not in the Fortran character set.) In the following example,
+    the code on the right hand side is preferred:
+
+      <table summary="space example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+DO i=1,n
+  a(i)%c=10*i/n
+  b(i)%d=20+i
+ENDDO
+IF(this==that)THEN
+  distance=0
+  time=0
+ENDIF
+</pre>
+          </td>
+
+          <td>
+            <pre>
+DO i = 1, n
+  a(i) % c = 10 * i / n
+  b(i) % d = 20 + i
+END DO
+
+IF (this == that) THEN
+  distance = 0
+  time     = 0
+END IF
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Try to confine your line width to 80 characters, so that your code can
+    be printed easily on A4 paper.</li>
+
+    <li>Line up your statements, where appropriate, to improve readability. For
+    example:
+
+      <table summary="line up example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+REAL, INTENT (OUT) :: my_out (:)
+REAL, INTENT (INOUT) :: my_inout (:)
+REAL, INTENT (IN) :: my_in  (:)
+
+! ...
+
+CHARACTER (LEN = 256) :: my_char
+
+my_char = 'This is a very very' // &amp;
+  ' very very very long' // &amp;
+  ' character assignment'.
+</pre>
+          </td>
+
+          <td>
+            <pre>
+REAL, INTENT (  OUT) :: my_out   (:)
+REAL, INTENT (INOUT) :: my_inout (:)
+REAL, INTENT (IN   ) :: my_in    (:)
+
+! ...
+
+CHARACTER (LEN = 256) :: my_char
+
+my_char = 'This is a very very'  // &amp;
+          ' very very very long' // &amp;
+          ' character assignment'.
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Short and simple Fortran statements are easier to read and understand
+    than long and complex ones. Where possible, avoid using continuation lines
+    in a statement.</li>
+
+    <li>Avoid putting multiple statements on the same line. It is not good for
+    readability.</li>
+  </ul>
+
+  <h3><a name="fortran-style"></a>3.2 Style</h3>
+
+  <p>The following is a list of recommended styles when you write code in
+  Fortran.</p>
+
+  <ul>
+    <li>New code should be written using Fortran 95 syntax. Avoid unportable
+    vendor/compiler extensions. Avoid Fortran 2003 features for the moment, as
+    they will not become widely available in the near future. (Having said that,
+    there is no harm in designing your code with the future in mind. For
+    example, if there is a feature that is not in Fortran 95 and you know that
+    it is in Fortran 2003, you may want to write your Fortran 95 code to make it
+    easier for the future upgrade.)</li>
+
+    <li>Write your program in UK English, unless you have a very good reason for
+    not doing so. Write your comments in simple UK English and name your program
+    units and variables based on sensible UK English words, bearing in mind that
+    your code may be read by people who are not proficient English
+    speakers.</li>
+
+    <li>When naming your variables and program units, always bear in mind that
+    Fortran is a case-insensitive language. (E.g. EditOrExit is the same as
+    EditorExit.)</li>
+
+    <li>Use only characters in the Fortran character set. In particular, accent
+    characters and tabs are not allowed in code, although they are usually OK
+    in comments. If your editor inserts tabs automatically, you should
+    configure it to switch off the functionality when you are editing Fortran
+    source files.</li>
+
+    <li>Although Fortran has no reserved keywords, you should avoid naming your
+    program units and variables with names that match an intrinsic FUNCTION or
+    SUBROUTINE. Similarly, you should avoid naming your program units and
+    variables with names that match a "keyword" in a Fortran statement.</li>
+
+    <li>Be generous with comments. State the reason for doing something,
+    instead of repeating the Fortran logic in words.</li>
+
+    <li>To improve readability, write your program in mainly lower case
+    characters. Writing a program in mainly lower case also means that you will
+    not have to use the Shift/Caps Lock keys often. There is a lot of debate on
+    using upper/lower cases in a case insensitive language such as Fortran.
+    There is no right or wrong, but people have adopted the different approaches
+    over time, each has its own merit. If you are starting a new project, you
+    should choose a suitable option and stick to it. Otherwise, you should stick
+    with the style in the existing code. Some options are listed here:
+
+      <ul>
+        <li>The ALL CAPS Fortran keywords approach, like most of the examples in
+        this document, where all Fortran keywords and intrinsic procedures are
+        written in ALL CAPS. This approach has the advantage that Fortran
+        keywords stand out, but it does increase how often the Shift/Caps Lock
+        key is used. Programmers who are used to some other programming
+        languages may also find it difficult to read a program with a lot of
+        upper case characters.</li>
+
+        <li>The Title Case Fortran keywords approach, where all Fortran keywords
+        are written with an initial capital case letter.</li>
+
+        <li>The sentence case approach, where only the initial character in a
+        Fortran statements is written in capital case letter, like a normal
+        sentence.</li>
+
+        <li>The all lower case approach, where all Fortran keywords are written
+        in lower case letters.</li>
+
+        <li>Some people have also proposed a variable naming convention where
+        local variables start with an initial lower case letter, private
+        module level variables with an initial capital case letter and public
+        module variables written in all caps. However, this approach has been
+        seen by many as too restrictive, and so its use has not been widely
+        spread.</li>
+      </ul>
+    </li>
+
+    <li>Use the new and clearer syntax for LOGICAL comparisons, i.e.:
+
+      <ul>
+        <li>== instead of .EQ.</li>
+
+        <li>/= instead of .NE.</li>
+
+        <li>&gt; instead of .GT.</li>
+
+        <li>&lt; instead of .LT.</li>
+
+        <li>&gt;= instead of .GE.</li>
+
+        <li>&lt;= instead of .LE.</li>
+      </ul>
+    </li>
+
+    <li>Where appropriate, simplify your LOGICAL assignments, for example:
+
+      <table summary="logic assignment example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+IF (my_var == some_value) THEN
+  something      = .TRUE.
+  something_else = .FALSE.
+
+ELSE
+  something      = .FALSE.
+  something_else = .TRUE.
+END IF
+
+IF (something .EQV. .TRUE.) THEN
+  CALL do_something ()
+  ! ...
+END IF
+</pre>
+          </td>
+
+          <td>
+            <pre>
+something      = (my_var == some_value)
+something_else = (my_var /= some_value)
+
+IF (something) THEN
+  CALL do_something ()
+  ! ...
+END IF
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Positive logic is usually easier to understand. When you have an
+    IF-ELSE-END IF construct, you should use positive logic in the IF test,
+    provided that the positive and the negative blocks are about the same size.
+    (However, it may be more appropriate to use negative logic if the negative
+    block is significantly bigger than the positive block.) For example:
+
+      <table summary="positive logic example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+IF (my_var != some_value) THEN
+  CALL do_this ()
+
+ELSE
+  CALL do_that ()
+END IF
+</pre>
+          </td>
+
+          <td>
+            <pre>
+IF (my_var == some_value) THEN
+  CALL do_that ()
+
+ELSE
+  CALL do_this ()
+END IF
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>To improve readability, you should always use the optional space to
+    separate the following Fortran keywords:
+
+      <table summary="space in Fortran keywords" width="100%">
+        <tr class="mono">
+          <td width="25%">else if</td>
+
+          <td width="25%">end do</td>
+
+          <td width="25%">end forall</td>
+
+          <td width="25%">end function</td>
+        </tr>
+
+        <tr class="mono">
+          <td width="25%">end if</td>
+
+          <td width="25%">end interface</td>
+
+          <td width="25%">end module</td>
+
+          <td width="25%">end program</td>
+        </tr>
+
+        <tr class="mono">
+          <td width="25%">end select</td>
+
+          <td width="25%">end subroutine</td>
+
+          <td width="25%">end type</td>
+
+          <td width="25%">end where</td>
+        </tr>
+
+        <tr class="mono">
+          <td width="25%">select case</td>
+
+          <td width="25%">-</td>
+
+          <td width="25%">-</td>
+
+          <td width="25%">-</td>
+        </tr>
+      </table>
+    </li>
+
+    <li>If you have a large or complex code block embedding other code blocks,
+    you may consider naming some or all of them to improve readability.</li>
+
+    <li>If you have a large or complex interface block or if you have one or
+    more sub-program units in the CONTAINS section, you can improve readability
+    by using the full version of the END statement (i.e. END SUBROUTINE
+    &lt;name&gt; or END FUNCTION &lt;name&gt; instead of just END) at the end of
+    each sub-program unit. For readability in general, the full version of the
+    END statement is recommended over the simple END.</li>
+
+    <li>Where possible, consider using CYCLE, EXIT or a WHERE-construct to
+    simplify complicated DO-loops.</li>
+
+    <li>When writing a REAL literal with an integer value, put a 0 after the
+    decimal point (i.e. 1.0 as opposed to 1.) to improve readability.</li>
+
+    <li>Where reasonable and sensible to do so, you should try to match the
+    names of dummy and actual arguments to a SUBROUTINE/FUNCTION.</li>
+
+    <li>In an array assignment, it is recommended that you use array notations
+    to improve readability. E.g.:
+
+      <table summary="array notation example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+INTEGER :: array1(10, 20), array2(10, 20)
+INTEGER :: scalar
+
+array1 = 1
+array2 = array1 * scalar
+</pre>
+          </td>
+
+          <td>
+            <pre>
+INTEGER :: array1(10, 20), array2(10, 20)
+INTEGER :: scalar
+
+array1(:, :) = 1
+array2(:, :) = array1(:, :) * scalar
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Where appropriate, use parentheses to improve readability. E.g.:
+
+      <table summary="parentheses example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+a = b * i + c / n
+</pre>
+          </td>
+
+          <td>
+            <pre>
+a = (b * i) + (c / n)
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+  </ul>
+
+  <h3><a name="fortran-feature"></a>3.3 Fortran features</h3>
+
+  <p>The following is a list of Fortran features that you should use or
+  avoid.</p>
+
+  <ul>
+    <li>Use IMPLICIT NONE in all program units. It means that you have declare
+    all your variables explicitly. This helps to reduce bugs in your program
+    that will otherwise be difficult to track.</li>
+
+    <li>Design your derived data types carefully and use them to group related
+    variables. Appropriate use of derived data types will allow you to design
+    modules and procedures with simpler and cleaner interfaces.</li>
+
+    <li>Where possible, module variables and procedures should be declared
+    PRIVATE. This avoids unnecessary export of symbols, promotes data hiding and
+    may also help the compiler to optimise the code.</li>
+
+    <li>When you are passing an array argument to a SUBROUTINE/FUNCTION, and the
+    SUBROUTINE/FUNCTION does not change the SIZE/DIMENSION of the array, you
+    should pass it as an assumed shape array. Memory management of such an array
+    is automatically handled by the SUBROUTINE/FUNCTION, and you do not have to
+    worry about having to ALLOCATE or DEALLOCATE your array. It also helps the
+    compiler to optimise the code.</li>
+
+    <li>Use an array POINTER when you are passing an array argument to a
+    SUBROUTINE, and the SUBROUTINE has to alter the SIZE/DIMENSION of the array.
+    You should also use an array POINTER when you need a dynamic array in a
+    component of a derived data type. (Note: Fortran 2003 allows passing
+    ALLOCATABLE arrays as arguments as well as using ALLOCATABLE arrays as
+    components of a derived data type. Therefore, the need for using an array
+    POINTER should be reduced once Fortran 2003 becomes more widely
+    accepted.)</li>
+
+    <li>Where possible, an ALLOCATE statement for an ALLOCATABLE array (or a
+    POINTER used as a dynamic array) should be coupled with a DEALLOCATE within
+    the same scope. If an ALLOCATABLE array is a PUBLIC MODULE variable, it is
+    highly desirable if its memory allocation and deallocation are only
+    performed in procedures within the MODULE in which it is declared. You may
+    consider writing specific SUBROUTINEs within the MODULE to handle these
+    memory managements.</li>
+
+    <li>To avoid memory fragmentation, it is desirable to DEALLOCATE in reverse
+    order of ALLOCATE.
+
+      <table summary="ALLOCATE example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+ALLOCATE (a(n))
+ALLOCATE (b(n))
+ALLOCATE (c(n))
+! ... do something ...
+DEALLOCATE (a)
+DEALLOCATE (b)
+DEALLOCATE (c)
+</pre>
+          </td>
+
+          <td>
+            <pre>
+ALLOCATE (a(n))
+ALLOCATE (b(n))
+ALLOCATE (c(n))
+! ... do something ...
+DEALLOCATE (c)
+DEALLOCATE (b)
+DEALLOCATE (a)
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Always define a POINTER before using it. You can define a POINTER in its
+    declaration by pointing it to the intrinsic function NULL (). Alternatively,
+    you can make sure that your POINTER is defined or nullified early on in the
+    program unit. Similarly, NULLIFY a POINTER when it is no longer in use,
+    either by using the NULLIFY statement or by pointing your POINTER to NULL
+    ().</li>
+
+    <li>Avoid the DIMENSION attribute or statement. Declare the DIMENSION with
+    the declared variables. E.g.:
+
+      <table summary="dimension attribute example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+INTEGER, DIMENSION(10) :: array1
+INTEGER                :: array2
+DIMENSION              :: array2(20)
+</pre>
+          </td>
+
+          <td>
+            <pre>
+INTEGER :: array1(10), array2(20)
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Avoid COMMON blocks and BLOCK DATA program units. Use PUBLIC MODULE
+    variables.</li>
+
+    <li>Avoid the EQUIVALENCE statament. Use a POINTER or a derived data type,
+    and the TRANSFER intrinsic function to convert between types.</li>
+
+    <li>Avoid the PAUSE statement, as your program will hang in a batch
+    environment. If you need to halt your program for interactive use, consider
+    using a READ* statement instead.</li>
+
+    <li>Avoid the ENTRY statement. Use a MODULE or internal SUBROUTINE.</li>
+
+    <li>Avoid the GOTO statement. The only commonly acceptable usage of GOTO is
+    for error trapping. In such case, the jump should be to a commented 9999
+    CONTINUE statement near the end of the program unit. Typically, you will
+    only find error handlers beyond the 9999 CONTINUE statement.</li>
+
+    <li>Avoid assigned GOTO, arithmetic IF, etc. Use the appropriate modern
+    constructs such as IF, WHERE, SELECT CASE, etc..</li>
+
+    <li>Avoid numbered statement labels. DO ... <em>label</em> CONTINUE
+    constructs should be replaced by DO ... END DO constructs. FORMAT statements
+    should be replaced by format strings. (Tip: a format string can be a
+    CHARACTER variable.)</li>
+
+    <li>A FUNCTION should be PURE, i.e. it should have no side effects (e.g.
+    altering an argument or module variable, or performing I/O). If you need to
+    perform a task with side effects, you should use a SUBROUTINE instead.</li>
+
+    <li>Avoid using a statement FUNCTION. Use an internal FUNCTION instead.</li>
+
+    <li>Avoid RECURSIVE procedures if possible. RECURSIVE procedures are usually
+    difficult to understand, and are always difficult to optimise in a
+    supercomputer environment.</li>
+
+    <li>Avoid using the specific names of intrinsic procedures. Use the generic
+    names of intrinsic procedures where possible.</li>
+  </ul>
+
+  <h2><a name="template"></a>4. Program templates</h2>
+
+  <p>The following is a basic template for a SUBROUTINE:</p>
+  <pre>
+SUBROUTINE &lt;subroutine_name&gt; (&lt;arguments&gt;, ...)
+
+! Description:
+!   &lt;Explain the usage of the subroutine and what it does.&gt;
+!
+! (c) Crown copyright Met Office. All rights reserved.
+! For further details please refer to the file COPYRIGHT.txt
+! which you should have received as part of this distribution.
+! ------------------------------------------------------------------------------
+
+! Modules
+&lt;module declarations, each with a list of imported symbols&gt;
+
+IMPLICIT NONE
+
+! Arguments:
+&lt;arguments with INTENT (  OUT)&gt;
+&lt;arguments with INTENT (INOUT)&gt;
+&lt;arguments with INTENT (IN   )&gt;
+
+! Local declarations:
+&lt;parameters, derived data types, variables, etc&gt;
+
+! INTERFACE blocks
+&lt;INCLUDE interface blocks for external procedures&gt;
+&lt;interface blocks for procedure and operator overloading&gt;
+
+!-------------------------------------------------------------------------------
+
+&lt;... subroutine executable statements&gt;
+
+!-------------------------------------------------------------------------------
+
+CONTAINS
+
+  &lt;sub-programs&gt;
+
+END SUBROUTINE &lt;subroutine_name&gt;
+</pre>
+
+  <p>Note:</p>
+
+  <ul>
+    <li>The basic templates for other types of program units are similar to
+    that of a SUBROUTINE, with the following exceptions:
+
+      <ul>
+        <li>A PROGRAM does not have arguments, so the "arguments" list in the
+        header and the "Arguments" section in the declaration section should be
+        removed. All declarations are local to a PROGRAM, so the "Local
+        Declarations" section should be replaced by a simple "Declarations"
+        section.</li>
+
+        <li>A FUNCTION should have no INTENT (OUT) and INTENT (INOUT) arguments.
+        You will also need to declare the type returned by the FUNCTION. This
+        can be in the FUNCTION header, declared separately or declared using a
+        RESULT clause. For the latters, make your declaration at the beginning
+        of the "Local declarations" section.</li>
+
+        <li>A MODULE does not have arguments, so the "arguments" list in the
+        header and the "Arguments" section in the declaration section should be
+        removed. Where appropriate, the "Local Declarations" section should be
+        replaced by a "PUBLIC declarations" section and a "PRIVATE declarations"
+        section.</li>
+      </ul>
+    </li>
+
+    <li>When you are distributing your code, you should include a COPYRIGHT.txt
+    file at a top level directory in your source tree. The file should contain
+    the detailed copyright information:
+
+      <ul>
+        <li>the copyright year, ranging from the year the code is first
+        distributed to the year the code is last distributed</li>
+
+        <li>the copyright statement</li>
+
+        <li>the owner of the code and his/her address</li>
+      </ul>
+
+      <p>For example:</p>
+      <pre>
+!------------------------------------------------------------------------------!
+!                                                                              !
+! (C) Crown copyright 2005-6 Met Office. All rights reserved.                  !
+!                                                                              !
+! Use, duplication or disclosure of this code is subject to the restrictions   !
+! as set forth in the contract. If no contract has been raised with this copy  !
+! of the code, the use, duplication or disclosure of it is strictly            !
+! prohibited. Permission to do so must first be obtained in writing from the   !
+! Head of Numerical Modelling at the following address:                        !
+!                                                                              !
+! Met Office, FitzRoy Road, Exeter, Devon, EX1 3PB, United Kingdom             !
+!                                                                              !
+!------------------------------------------------------------------------------!
+</pre>
+    </li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/maintain.js
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/maintain.js	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/maintain.js	(revision 329)
@@ -0,0 +1,11 @@
+// Display info about maintenance team
+
+// FCM contact URL
+var url     = 'http://www.metoffice.gov.uk/research/nwp/external/fcm/'
+var contact = '<a href="' + url + '">the FCM team</a>'
+
+// Output string 
+var out     = '<p></p><hr><address>Maintained by ' + contact + '.</address>'
+
+// Write to document
+document.write (out)
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/perl_standard.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/perl_standard.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/perl_standard.html	(revision 329)
@@ -0,0 +1,384 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Perl coding standard for FCM</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="Perl coding standard for FCM">
+  <meta name="keywords" content="Perl, coding standard, FCM">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="StyleSheet" type="text/css" href="style.css">
+  <style type="text/css">
+  <!--
+  li, th, td {
+    padding: 3px;
+  }
+  td {
+    vertical-align: top;
+  }
+  th.r {
+    text-align: right;
+    background-color: transparent;
+    padding-right: 5px;
+  }
+  th.l {
+    text-align: left;
+    background-color: transparent;
+  }
+  -->
+  </style>
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85"
+  height="85"></p>
+
+  <h1>Perl coding standard for FCM</h1>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown copyright 2005-6. All rights reserved.</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+
+  <h2>Contents</h2>
+
+  <ul>
+    <li>Main contents:
+
+      <ol>
+        <li><a href="#1">Introduction</a></li>
+
+        <li><a href="#2">Online Perl style guides</a></li>
+
+        <li><a href="#3">Coding standard</a></li>
+      </ol>
+    </li>
+  </ul><a name="1"></a>
+
+  <h2>1. Introduction</h2>
+
+  <p>Perl (Practical Extraction and Report Language) is gaining a lot of
+  popularity at the Met Office for developing applications that are
+  traditionally programmed using shell script. For example, it is currently our
+  choice of language for developing the in-house components of the FCM
+  system.</p>
+ 
+  <p>Perl is a very powerful general purpose scripting tool that is free and
+  portable across a huge variety of platforms including many non-Unix systems.
+  Replacing a shell script with an equivalent Perl program often results in a
+  massive reduction in runtime - using cleaner syntax and algorithm.</p>
+
+  <p>Perl is a language with a rich set of "grammar". To most people, the first
+  impression of a piece of code written in Perl is that it is very ugly. Its
+  lines are full of punctuation junks that nobody can hope to understand. This
+  is often caused by poorly written programs coupled with little and often
+  inadequte documentations. To improve readability and to reduce the overheads
+  of maintenance, it is important for Perl programmers to write their code in a
+  nice and consistent way.</p>
+
+  <p>The aim of this document is to propose ideas on how the Perl programming
+  language should be used with FCM.</p>
+
+  <a name="2"></a><h2>2. Online Perl style guides</h2>
+
+  <p>There are many Perl style guides available online. Some are listed
+  below:</p>
+
+  <ul>
+    <li>the manpages <code>perlstyle</code> and <code>perlmodstyle</code></li>
+
+    <li><a href=
+    "http://www.kulnet.kuleuven.ac.be/perlcourse/perlingo.html">Perlingo</a></li>
+
+    <li><a href="http://ali.as/devel/code.html">Perl Style Guide for Large Scale
+    Object Oriented Development</a></li>
+
+    <li><a href="http://perltidy.sourceforge.net/">Perltidy</a></li>
+
+    <li><a href=
+    "http://perl.apache.org/docs/2.0/devel/core/coding_style.pdf">mod_perl
+    Coding Style Guide</a> (PDF)</li>
+  </ul>
+
+  <p>It is worth noting that the ideas in some of the Perl style guides may
+  conflict with each other - as they are targeted to different people. However,
+  there is a common theme to most of the best practices. The following is a
+  summary:</p>
+
+  <ul>
+    <li>A source file, whether it is a top-level script or a module, should
+    contain a header block with information of the source file,
+    some general description of the code as well as standard pragmas or
+    options for running the Perl interpreter.</li>
+
+    <li>Each function should be preceded by a comment block or a block of
+    POD to specify a synopsis for the defined function.</li>
+
+    <li>Avoid using names of built-in functions to name your new functions.</li>
+
+    <li>If the parameter list of a function is becoming too long, e.g. more
+    than 3 arguments, you may want to implement the argument list with a hash,
+    so that all the arguments are named.</li>
+
+    <li>Indent to an appropriate number of spaces/tabs for code blocks.</li>
+
+    <li>Open curly brackets should be on the same line as the keyword.</li>
+
+    <li>Close curly brackets should line up with the keywords that started
+    the block.</li>
+
+    <li>Insert a blank line between chunks of code that do different
+    things.</li>
+
+    <li>Use space between tokens and operators to improve readability.
+    Use space after commas. No space before commas and semi-colons.</li>
+
+    <li>Line up corresponding items vertically.</li>
+
+    <li>Use parentheses only if necessary.</li>
+
+    <li>Restrict line length to e.g. 80 characters.</li>
+
+    <li>Be consistent with style.</li>
+
+    <li>Use the "strict" and "warnings" pragmas.</li>
+
+    <li>options and arguments should be processed as "soon" as possible,
+    preferably at the beginning of a source file or a function.</li>
+
+    <li>Use the "__END__" directive at the end of a Perl script.</li>
+
+    <li>-more later-</li>
+  </ul>
+
+  <a name="3"></a><h2>3. Coding standard</h2>
+
+  <p>The main question is: what should we include in our coding standard?
+  Although we would like to recommend using the best practices described in
+  the last section, we would not want to impose any restriction, as Perl is a
+  language designed to do things in many different ways. The only thing we
+  would like to impose is a header block in each source file, and a header
+  comment block for each function in a source file.</p>
+
+  <p>For a Perl executable, the header block of the source file should contain
+  the following:</p>
+  
+  <ul>
+    <li>the first line should be <tt>"#!/usr/bin/perl"</tt></li>
+
+    <li>the name of the executable</li>
+    
+    <li>a synopsis and/or a description or what the executable does</li>
+
+    <li>an explanation of the options and arguments (either in separate
+    sections or described within the "description" section)</li>
+
+    <li>copyright and owner information</li>
+
+    <li>no history or revision information, (as we would prefer using the
+    Subversion log message to record such information)</li>
+
+    <li>use "strict" and use "warnings" statements</li>
+
+    <li>use the "__END__" directive at the end of a Perl script.</li>
+  </ul>
+
+  <table summary="executable header block example" border="1" width="100%">
+    <tr>
+      <th>Executable header block example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   example.pl
+#
+# SYNOPSIS
+#   example.pl [options] args
+#
+# DESCRIPTION
+#   This is a header example, and so on and so forth.
+#
+# OPTIONS
+#   -b [--bar] - this option does what "bar" does.
+#   -f [--foo] - this option does what "foo" does.
+#
+# ARGUMENTS
+#   args       - description of each argument.
+#
+# SEE ALSO
+#   list of relevant commands, modules and documents
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use Getopt::Long;
+
+# ------------------------------------------------------------------------------
+
+# Process options
+my ($foo, $bar);
+GetOptions (
+  'foo|f' =&gt; \$foo,
+  'bar|b' =&gt; \$bar,
+);
+
+# Process arguments
+my $arg = shift @ARGV;
+
+# Do something...
+print 'This is an example: ', $arg, "\n";
+print 'FOO', "\n" if $foo;
+print 'BAR', "\n" if $bar;
+
+__END__
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>For a Perl module, the header block of the source file should contain
+  the following:</p>
+  
+  <ul>
+    <li>the first line should be <tt>"#!/usr/bin/perl"</tt></li>
+
+    <li>the name of the module</li>
+    
+    <li>a synopsis and/or a description or what the module does</li>
+
+    <li>copyright and owner information</li>
+
+    <li>no history or revision information</li>
+
+    <li>use "strict" and use "warnings" statements</li>
+
+    <li>a list of exports (do not export if you are writing an OO module)</li>
+
+    <li>use the "__END__" directive at the end of a Perl script, and remember
+    to put 1 before the end of the module, so that it will return true.</li>
+  </ul>
+
+  <table summary="module header block example" border="1" width="100%">
+    <tr>
+      <th>Module header block example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Metoffice::Example
+#
+# DESCRIPTION
+#   This is a header example, and so on and so forth.
+#
+# SEE ALSO
+#   list of relevant commands, modules and documents
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Metoffice::Example;
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Exports
+our (@ISA, @EXPORT, @EXPORT_OK);
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(
+  foo
+  bar
+);
+
+# ------------------------------------------------------------------------------
+# ... some more Perl ...
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The header of a function (or "method" for OO code) should have the
+  following:</p>
+
+  <ul>
+    <li>a synopsis of the function's calling interfaces.</li>
+
+    <li>a description of what the function does and what it returns, and if
+    appropriate, what each argument represents</li>
+  </ul>
+
+  <table summary="function header block example" border="1" width="100%">
+    <tr>
+      <th>Function header block example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+# ... Something before the function ...
+#
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $result = &amp;print_hello;
+#   $result = &amp;print_hello ($arg);
+#
+# DESCRIPTION
+#   Print the word "hello" to standard output. If no argument is specified,
+#   the word "world" will be printed after the word "hello". Otherwise, the
+#   word specified by the argument $arg will follow "hello". The function
+#   returns true on success.
+#
+# ARGUMENTS
+#   $arg - optional, describe $arg if it has not been done in the above section
+# ------------------------------------------------------------------------------
+
+sub print_hello {
+  my ($arg) = @_;
+  $arg = defined ($arg) ? $arg : 'world';
+  my $result = print 'hello ', $arg, "\n";
+  return $result;
+}
+
+# ------------------------------------------------------------------------------
+#
+# ... Something after the function ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/style.css
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/style.css	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/standards/style.css	(revision 329)
@@ -0,0 +1,146 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+body {
+  background-color: #ffffcc;
+  color: black;
+  font-family: Arial, Helvetica, sans-serif;
+  font-size: 12pt;
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+table.head {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+
+table.foot {
+  background-color: #ccccff;
+  padding: 5px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+ol li {
+  margin: 5px;
+}
+
+ul.contents {
+  margin-bottom: 5px;
+  list-style-type: none;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+em {
+  font-style: italic;
+}
+
+strong {
+  font-weight: bold;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+div.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+p.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+div.yell td {
+  background-color: #ffffcc;
+}
+
+.pad th, .pad td, .pad li {
+  padding: 5px;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_bld_cfg.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_bld_cfg.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_bld_cfg.html	(revision 329)
@@ -0,0 +1,1533 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM build
+  configuration file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM build configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM build configuration file</h1>
+
+  <p>The following is a list of supported declarations for the configuration
+  file used by the FCM build system. Unless otherwise stated, the fields in
+  all declaration labels are not case sensitive. Build declarations can be
+  made either in a build configuration file or in an extract configuration
+  file. In the latter case, the prefix "BLD::" must be added at the beginning
+  of each label to inform the extract system that the declaration is a build
+  system declaration. (In a build configuration file, the prefix "BLD::" is
+  optional.)</p>
+
+  <table class="pad" summary="Declarations in build configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::TYPE</th>
+
+      <th>Description</th>
+
+      <td>The configuration file type, the value should always be "bld" for a
+      build configuration file. This declaration is compulsory for all
+      build configuration files. (This declaration is automatic when the
+      extract system creates a build configuration file.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::type  bld
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::VERSION</th>
+
+      <th>Description</th>
+
+      <td>The file format version, currently "1.0" - a version is included so
+      that we shall be able to read the configuration file correctly should we
+      decide to change its format in the future. (This declaration is automatic
+      when the extract system creates a build configuration file.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::version  1.0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TARGET</th>
+
+      <th>Description</th>
+
+      <td>Specify the targets for the build. Multiple targets can be declared in
+      one or more declarations. These targets become the dependencies of the
+      default "all" target in the <em>Makefile</em>.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+target  VarScr_AnalysePF VarScr_CovAccStats
+target  VarScr_CovPFstats
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">DIR::ROOT</th>
+
+      <th>Description</th>
+
+      <td>The root directory of the build. It must be declared for each build.
+      (This declaration is automatic when the extract system creates a build
+      configuration file. The value is normally the root path of the
+      extraction destination.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::root  $HOME/my_build
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SRC::&lt;pcks&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a source directory in the sub-package &lt;pcks&gt;.
+      The name of the sub-package &lt;pcks&gt; must be unique. Package names
+      are delimited by double colons "::" or double underscores "__". (This
+      declaration is automatic when the extract system creates the build
+      configuration file. The list of declared source directories will be the
+      list of extracted source directories.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+src::var::code::VarMod_PF  $HOME/my_build/src/var/code/VarMod_PF
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SEARCH_SRC</th>
+
+      <th>Description</th>
+
+      <td>This declares a flag to determine whether the build system should
+      search the source sub-directory of the build root for a list of source
+      directories. The automatic search is useful if the build system is
+      invoked standalone and the source sub-directory contains the full source
+      tree of the build. The default is to search (1). Set the flag to 0 to
+      switch off the behaviour. (When the extract system creates a build
+      configuration file, it declares all source directories. Searching of the
+      source sub-directory should not be required, and so this flag is
+      automatically set to 0.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+search_src  0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXE_DEP[::&lt;target&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares an extra dependency for either all main program targets
+      or only &lt;target&gt; if it is specified. If &lt;target&gt; is specified,
+      it must be the name of a main program target. The value of the declaration
+      is a space delimited list. Each item in the list can either be a valid
+      name of a sub-package or the name of a valid object target. If a
+      sub-package name is used, the <em>make</em> rule for the main program will
+      be set to depend on all (non-program) object files within the
+      sub-package.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Only foo.exe to depend on the package foo::bar and egg.o
+exe_dep::foo.exe  foo::bar egg.o
+
+# All executables to depend on the package foo::bar and egg.o
+exe_dep  foo::bar egg.o
+
+# Only foo.exe to depend on all objects
+exe_dep::foo.exe
+
+# All executables to depend on all objects
+exe_dep
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">BLOCKDATA[::&lt;target&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares a BLOCKDATA dependency for either all main program targets
+      or only &lt;target&gt; if it is specified. If &lt;target&gt; is specified,
+      it must be the name of a main program target. The value of the declaration
+      is a space delimited list. Each item in the list must be the name of a
+      valid object target containing a Fortran BLOCKDATA program unit.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Only foo.exe to depend on blkdata.o
+blockdata::foo.exe  blkdata.o
+
+# All executables to depend on fbd.o
+blockdata  fbd.o
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXE_NAME::&lt;name&gt;</th>
+
+      <th>Description</th>
+
+      <td>This renames the executable target of a main program source file
+      &lt;name&gt; to the specified value.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Rename the executable target name of foo.f90 from "foo.exe" to "bar"
+exe_name::foo  bar
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">LIB[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a library archive target. If &lt;pcks&gt; is
+      specified in the label, the declaration applies to the library archive
+      target for that sub-package only. If set, the name of the library archive
+      target will be named "lib&lt;value&gt;.a", where &lt;value&gt; is the
+      value of the declaration. If not specified, the default is to name the
+      global library "libfcm_default.a". For a library archive of a sub-package,
+      the default is to name its library after the name of the sub-package.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Rename the top level library "libfoo.a"
+lib  foo
+
+# Rename the library for the sub-package "egg::ham"
+# from "libegg__ham.a" to "libegg-ham.a"
+lib::egg::ham  egg-ham
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">PP[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares whether a pre-processing stage is required. To switch on
+      pre-processing, set the value to 1. If &lt;pcks&gt; is specified
+      in the label, the flag applies to the files within that sub-package
+      only. Otherwise, the flag affects source directories in all packages.
+      The pre-processing stage is useful if the pre-processor changes the
+      dependency and/or the argument list of the source files. The default
+      behaviour is skip the pre-processing stage for all source
+      directories.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+pp::gen 1  # switch on pre-processing for sub-packages in "gen"
+pp      1  # switch on pre-processing globally
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TOOL::&lt;label&gt;[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declaration is used to specify a build "tool" such as the
+      Fortran compiler or its flags. The &lt;label&gt; determines the "tool"
+      you are declaring. If a sub-package &lt;pcks&gt; is specified, the
+      declaration applies only to the files and directories under the
+      sub-package.  Otherwise, the declaration applies globally. A list of
+      &lt;label&gt; fields is available <a href="#tools-list">later in this
+      section</a>.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+tool::fc      sxmpif90
+tool::fflags  -Chopt -Pstack
+
+tool::cc      sxmpic++
+tool::cflags  -O nomsg -pvctl nomsg
+
+tool::ar      sxar
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXCL_DEP[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>
+        This declaration is used to specify whether a particular dependency
+        should be ignored during the automatic dependency scan. If a sub-package
+        &lt;pcks&gt; is specified, the declaration applies only to the files and
+        directories under the sub-package. Otherwise, the declaration applies
+        globally. It is worth noting that the build system is not yet clever
+        enough to recognise changes in this declaration in incremental builds.
+        Therefore, users should manually trigger a full build if these
+        statements are modified. The value of this declaration must contain one
+        or two fields (separated by the double colon "::"). The first field
+        denotes the dependency type, and the second field is the dependency
+        target. If the second field is specified, it will only exclude the
+        dependency to the specified target. Otherwise, it will exclude all
+        dependency to the specified type. The following dependency types are
+        supported:
+
+        <a name="dependency-types"></a>
+
+        <table summary="dependency types" border="1">
+          <tr>
+            <th>Dependency type</th>
+
+            <th>Description</th>
+          </tr>
+
+          <tr>
+            <th>USE</th>
+
+            <td>The dependency target is a Fortran module.</td>
+          </tr>
+
+          <tr>
+            <th>INTERFACE</th>
+
+            <td>The dependency target is a Fortran 9X interface block file.</td>
+          </tr>
+
+          <tr>
+            <th>INC</th>
+
+            <td>The dependency target is a Fortran INCLUDE file.</td>
+          </tr>
+
+          <tr>
+            <th>H</th>
+
+            <td>The dependency target is a pre-processor #include header
+            file.</td>
+          </tr>
+
+          <tr>
+            <th>OBJ</th>
+
+            <td>The dependency target is a compiled binary object file.</td>
+          </tr>
+
+          <tr>
+            <th>EXE</th>
+
+            <td>The dependency target is an executable binary or script.</td>
+          </tr>
+        </table>
+
+        <p>N.B. The following dependency targets are in the default list of
+        excluded dependencies:</p>
+
+        <ul>
+          <li>
+            Intrinsic Fortran modules:
+
+            <ul>
+              <li>USE::ISO_C_BINDING</li>
+
+              <li>USE::IEEE_EXCEPTIONS</li>
+
+              <li>USE::IEEE_ARITHMETIC</li>
+
+              <li>USE::IEEE_FEATURES</li>
+            </ul>
+          </li>
+
+          <li>
+            Intrinsic Fortran subroutines:
+
+            <ul>
+              <li>OBJ::CPU_TIME</li>
+
+              <li>OBJ::GET_COMMAND</li>
+
+              <li>OBJ::GET_COMMAND_ARGUMENT</li>
+
+              <li>OBJ::GET_ENVIRONMENT_VARIABLE</li>
+
+              <li>OBJ::MOVE_ALLOC</li>
+
+              <li>OBJ::MVBITS</li>
+
+              <li>OBJ::RANDOM_NUMBER</li>
+
+              <li>OBJ::RANDOM_SEED</li>
+
+              <li>OBJ::SYSTEM_CLOCK</li>
+            </ul>
+          </li>
+
+          <li>
+            Dummy declarations:
+
+            <ul>
+              <li>OBJ::NONE</li>
+
+              <li>EXE::NONE</li>
+            </ul>
+          </li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+excl_dep  USE::YourFortranMod
+excl_dep  INTERFACE::HerFortran.interface
+excl_dep  INC::HisFortranInc.inc
+excl_dep  H::TheirHeader.h
+excl_dep  OBJ
+excl_dep  EXE
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INFILE_EXT::&lt;ext&gt;</th>
+
+      <th>Description</th>
+
+      <td>
+        This declaration is used to re-register particular file name
+        extensions &lt;ext&gt; to associate with different file types. The
+        value of the declaration is a list of type flags delimited by the
+        double colon "::". Each type flag is used internally to describe the
+        nature of the file. For example, a Fortran free source form containing
+        a main program is registered as
+        <tt>"FORTRAN::FORTRAN9X::SOURCE::PROGRAM"</tt>. The following is a
+        list of type flags that are currently in-use (or <span class="gray">*
+        reserved</span>) by the build system:
+
+        <a name="infile-ext-types"></a>
+
+        <table summary="input file extension type flags" border="1">
+          <tr>
+            <th>Flag</th>
+
+            <th>Description</th>
+          </tr>
+
+          <tr>
+            <td class="mono">SOURCE</td>
+
+            <td>a source file containing program code of a supported language
+            (currently Fortran, FPP, C and CPP).</td>
+          </tr>
+
+          <tr>
+            <td class="mono">INCLUDE</td>
+
+            <td>an include file containing program code of a supported language
+            (currently Fortran, FPP, C and CPP).</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FORTRAN</td>
+
+            <td>a file containing Fortran code.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FORTRAN9X</td>
+
+            <td>a file containing the Fortran free source form. This word must be
+            used in conjunction with the word "FORTRAN".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FPP</td>
+
+            <td>a file containing Fortran code requiring pre-processing.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FPP9X</td>
+
+            <td>a file containing Fortran free source form requiring
+            pre-processing. This word must be used in conjunction with the word
+            "FPP".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">C</td>
+
+            <td>a file containing C code.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">CPP</td>
+
+            <td>a file containing CPP include header.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">INTERFACE</td>
+
+            <td>a file containing a Fortran 9X interface block.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">PROGRAM</td>
+
+            <td>a file containing a main program.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">MODULE</td>
+
+            <td>a file containing a Fortran 9X module.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">BINARY</td>
+
+            <td>a binary file.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">EXE</td>
+
+            <td>an executable file. This word must be used in conjunction with
+            the word "BINARY".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">LIB</td>
+
+            <td>an archive library. This word must be used in conjunction with
+            the word "BINARY".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">SCRIPT</td>
+
+            <td>a file containing source code of a scripting language.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">PVWAVE</td>
+
+            <td>a file containing executable PVWAVE scripts. This word must be
+            used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">SQL</td>
+
+            <td>a file containing SQL scripts. This word must be used in
+            conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">GENLIST</td>
+
+            <td>a GEN List file.</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">OBJ</td>
+
+            <td>(* reserved) an object file. This word must be used in
+            conjunction with the word "BINARY".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">SHELL</td>
+
+            <td>(* reserved) a file containing executable shell scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">PERL</td>
+
+            <td>(* reserved) a file containing executable Perl scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">PYTHON</td>
+
+            <td>(* reserved) a file containing executable Python scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">TCL</td>
+
+            <td>(* reserved) a file containing executable TCL scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+infile_ext::h90  CPP::INCLUDE
+infile_ext::inc  FORTRAN::FORTRAN9X::INCLUDE
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">OUTFILE_EXT::&lt;type&gt;</th>
+
+      <th>Description</th>
+
+      <td>
+        This declaration is used to re-register the output file extension
+        for a particular &lt;type&gt; of output files. The value must be a
+        valid file extension. The following is a list of output file types
+        in-use by the build system:
+
+        <a name="outfile-ext-types"></a>
+
+        <table summary="output file extension types" border="1">
+          <tr>
+            <th>Type</th>
+
+            <th>Description</th>
+
+            <th>Default</th>
+          </tr>
+
+          <tr>
+            <td class="mono">MK</td>
+
+            <td>dependency files, <em>Makefile</em> fragments</td>
+
+            <td class="mono">.mk</td>
+          </tr>
+
+          <tr>
+            <td class="mono">OBJ</td>
+
+            <td>compiled object files</td>
+
+            <td class="mono">.o</td>
+          </tr>
+
+          <tr>
+            <td class="mono">MOD</td>
+
+            <td>compiled Fortran module information files</td>
+
+            <td class="mono">.mod</td>
+          </tr>
+
+          <tr>
+            <td class="mono">EXE</td>
+
+            <td>binary executables</td>
+
+            <td class="mono">.exe</td>
+          </tr>
+
+          <tr>
+            <td class="mono">DONE</td>
+
+            <td>"done" files for compiled source</td>
+
+            <td class="mono">.done</td>
+          </tr>
+
+          <tr>
+            <td class="mono">IDONE</td>
+
+            <td>"done" files for included source</td>
+
+            <td class="mono">.idone</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FLAGS</td>
+
+            <td>"flags" files, compiler flags config</td>
+
+            <td class="mono">.flags</td>
+          </tr>
+
+          <tr>
+            <td class="mono">INTERFACE</td>
+
+            <td>interface files for F9X standalone subroutines/functions</td>
+
+            <td class="mono">.interface</td>
+          </tr>
+
+          <tr>
+            <td class="mono">LIB</td>
+
+            <td>archive object library</td>
+
+            <td class="mono">.a</td>
+          </tr>
+
+          <tr>
+            <td class="mono">TAR</td>
+
+            <td>TAR archive</td>
+
+            <td class="mono">.tar</td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Output F9X interface files will now have ".foo" extension
+outfile_ext::interface  .foo
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INC</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a file containing build configuration. The
+      lines in the declared file will be included inline to the current build
+      configuration file.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inc  ~frva/var_stable_22.0/cfg/bld.cfg
+# ... and then your changes ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">USE</th>
+
+      <th>Description</th>
+
+      <td>This declares a pre-compiled build, which the current build is
+      dependent on. The value must be must be either the configuration file or
+      the root directory of a successful build. Output of the pre-compiled
+      build, the build tools, the exclude dependency declarations, the file
+      type registers declarations are automatically inherited from the
+      pre-compiled build. Source directories, build targets and pre-processing
+      stage declarations may be inherited depending on the INHERIT
+      declarations. (If you have a USE declaration in an extraction, the
+      resulting build configuration file will contain an automatic USE
+      declaration, which expects a pre-compiled build at the destination of
+      the extraction.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Use VAR build 22.0
+USE  ~frva/var_22.0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INHERIT::&lt;name&gt;[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares whether build targets (&lt;name&gt; = "target"),
+      source directories (&lt;name&gt; = "src") and pre-processing stage
+      declarations (&lt;name&gt; = "pp") are inherited from pre-compiled builds
+      declared by the USE statement. By default, source directories and
+      pre-processing stage declarations are inherited from pre-compiled
+      builds, while build targets are not. Use the value 1 to switch on
+      inheritance, or 0 to switch off. For source directories and
+      pre-processing stage declarations, the name of a sub-package
+      &lt;pcks&gt; can be specified. If a sub-package pcks is specified, the
+      declaration applies only to the files and directories under the
+      sub-package. Otherwise, the declaration applies globally.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inherit::target   1
+inherit::src      0
+inherit::pp::gen  0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">%&lt;name&gt;</th>
+
+      <th>Description</th>
+
+      <td>%&lt;name&gt; declares an internal variable &lt;name&gt; that
+      can later be re-used.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+%my_variable  foo
+src::bar      %my_variable
+src::egg      %my_variable
+src::ham      %my_variable
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <p><a name="tools-list"></a>The following is a list of &lt;label&gt; fields
+  that can be used with a TOOL::&lt;label&gt;[::&lt;pcks&gt;]
+  declaration:</p>
+
+  <table class="pad" summary="list of tools" width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th>Description</th>
+
+      <th>Default</th>
+    </tr>
+
+    <tr>
+      <th>FC</th>
+
+      <td>The Fortran compiler.</td>
+
+      <td class="mono">"f90"</td>
+    </tr>
+
+    <tr>
+      <th>FFLAGS</th>
+
+      <td>Options used by the Fortran compiler.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>FC_COMPILE</th>
+
+      <td>The option used by the Fortran compiler to suppress the
+      linking stage.</td>
+
+      <td class="mono">"-c"</td>
+    </tr>
+
+    <tr>
+      <th>FC_INCLUDE</th>
+
+      <td>The option used by the Fortran compiler to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>FC_DEFINE</th>
+
+      <td>The option used by the Fortran compiler to define a
+      pre-processor definition macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>FC_OUTPUT</th>
+
+      <td>The option used by the Fortran compiler to specify the output
+      file name.</td>
+
+      <td class="mono">"-o"</td>
+    </tr>
+
+    <tr>
+      <th>CC</th>
+
+      <td>The C compiler.</td>
+
+      <td class="mono">"cc"</td>
+    </tr>
+
+    <tr>
+      <th>CFLAGS</th>
+
+      <td>Options used by the C compiler.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>CC_COMPILE</th>
+
+      <td>The option used by the C compiler to suppress the
+      linking stage.</td>
+
+      <td class="mono">"-c"</td>
+    </tr>
+
+    <tr>
+      <th>CC_INCLUDE</th>
+
+      <td>The option used by the C compiler to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>CC_DEFINE</th>
+
+      <td>The option used by the C compiler to define a
+      pre-processor definition macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>CC_OUTPUT</th>
+
+      <td>The option used by the C compiler to specify the output
+      file name.</td>
+
+      <td class="mono">"-o"</td>
+    </tr>
+
+    <tr>
+      <th>LD</th>
+
+      <td>Name of the linker or loader for linking object files into an
+      executable.</td>
+
+      <td class="mono">"ld"</td>
+    </tr>
+
+    <tr>
+      <th>LDFLAGS</th>
+
+      <td>The flags used by the linker or loader.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>LD_OUTPUT</th>
+
+      <td>The option used by the linker or loader for the output file name
+      (other than the default "a.out").</td>
+
+      <td class="mono">"-o"</td>
+    </tr>
+
+    <tr>
+      <th>LD_LIBSEARCH</th>
+
+      <td>The option used by the linker or loader for specifying the
+      search path for link libraries.</td>
+
+      <td class="mono">"-L"</td>
+    </tr>
+
+    <tr>
+      <th>LD_LIBLINK</th>
+
+      <td>The option used by the linker or loader command for linking
+      with a library.</td>
+
+      <td class="mono">"-l"</td>
+    </tr>
+
+    <tr>
+      <th>AR</th>
+
+      <td>The archive command.</td>
+
+      <td class="mono">"ar"</td>
+    </tr>
+
+    <tr>
+      <th>ARFLAGS</th>
+
+      <td>The options used for the archive command to create a
+      library.</td>
+
+      <td class="mono">"rs"</td>
+    </tr>
+
+    <tr>
+      <th>FPP</th>
+
+      <td>The Fortran pre-processor command.</td>
+
+      <td class="mono">"cpp"</td>
+    </tr>
+
+    <tr>
+      <th>FPPKEYS</th>
+
+      <td>The Fortran pre-processor will pre-define each word in this
+      setting as a macro.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>FPPFLAGS</th>
+
+      <td>The options used by the Fortran pre-processor.</td>
+
+      <td class="mono">"-P -traditional"</td>
+    </tr>
+
+    <tr>
+      <th>FPP_DEFINE</th>
+
+      <td>The option used by the Fortran pre-processor to define a
+      macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>FPP_INCLUDE</th>
+
+      <td>The option used by the Fortran pre-processor to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>CPP</th>
+
+      <td>The C pre-processor command.</td>
+
+      <td class="mono">"cpp"</td>
+    </tr>
+
+    <tr>
+      <th>CPPKEYS</th>
+
+      <td>The C pre-processor will pre-define each word in this
+      setting as a macro.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>CPPFLAGS</th>
+
+      <td>The options used by the C pre-processor.</td>
+
+      <td class="mono">"-C"</td>
+    </tr>
+
+    <tr>
+      <th>CPP_DEFINE</th>
+
+      <td>The option used by the C pre-processor to define a
+      macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>CPP_INCLUDE</th>
+
+      <td>The option used by the C pre-processor to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>MAKE</th>
+
+      <td>The "make" command.</td>
+
+      <td class="mono">"make"</td>
+    </tr>
+
+    <tr>
+      <th>MAKEFLAGS</th>
+
+      <td>The options used by the "make" command</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>MAKE_SILENT</th>
+
+      <td>The option used by the "make" command to specify silent
+      operation.</td>
+
+      <td class="mono">"-s"</td>
+    </tr>
+
+    <tr>
+      <th>MAKE_JOB</th>
+
+      <td>The option used by the "make" command to specify the number
+      jobs to run simultaneously.</td>
+
+      <td class="mono">"-j"</td>
+    </tr>
+
+    <tr>
+      <th>GENINTERFACE</th>
+
+      <td>The command/method for generating interface for Fortran 9X
+      standalone subroutines/functions. Supported values are "ECMWF",
+      "f90aib" and "none". (The keyword "none" is used to switch off
+      interface generation.)</td>
+
+      <td class="mono">"ECMWF"</td>
+    </tr>
+
+    <tr>
+      <th>INTERFACE</th>
+
+      <td>Generate Fortran 9X interface files with root names according to
+      either the root name of the source "file" or the name of the "program"
+      unit.</td>
+
+      <td class="mono">"file"</td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th>Description</th>
+
+      <th>Default</th>
+    </tr>
+  </table>
+
+  <p class="gray">The following declarations are for reference only. They
+  should not be used in normal operations of the FCM build system:</p>
+
+  <table class="pad" summary="Unused declarations in build configuration file"
+  width="100%" border="1">
+    <tr class="gray">
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::BIN</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "bin" directory, container of executable files created by the build.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::bin  $HOME/my_build/bin
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::BLD</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      build directory, container of the <em>Makefile</em> and its fragments
+      created by the build system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::bld  $HOME/my_build/bld
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::CACHE</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      cache directory, container of internal cache files used by the build
+      system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::cache $HOME/my_build/.cache
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      configuration directory, container of the build configuration file. Not
+      created by the build system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::cfg $HOME/my_build/cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::DONE</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "done" file directory, container of dummy "done" files created by the
+      build process. A "done" file is used to indicate that all the external
+      objects of an object files are compiled and ready to be used by the link
+      process.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::done $HOME/my_build/done
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::ETC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      miscellaneous file directory, container of "data" files. "Data" files
+      are files in the source sub-package without a registered type. It is
+      possible for the user to tell the build system to copy all "data" files
+      in a sub-package to this directory by "building" a dummy sub-package
+      data file target.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::etc $HOME/my_build/etc
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::FLAGS</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "flags" file directory, container of dummy "flags" files created by the
+      build process. A "flags" file is used to indicate to <em>make</em> that
+      the compiler flags for a source file or a container package has
+      changed.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::flags $HOME/my_build/flags
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::INC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      include directory, container of "include" files such as pre-processor
+      header files, Fortran INCLUDE files, Fortran 9X interface files, and
+      Fortran compiled module information files.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::inc $HOME/my_build/inc
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::LIB</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      library directory, container of object library achive files created by
+      the build.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::lib $HOME/my_build/lib
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::OBJ</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      object directory, container of compiled object files created by the
+      build process.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::obj $HOME/my_build/obj
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::PPSRC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      pre-processed source directory, container of pre-processed source files
+      created by the build process.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::ppsrc $HOME/my_build/ppsrc
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::SRC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      source directory, container of the source tree. Not created by the build
+      system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::src $HOME/my_build/src
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::TMP</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      temporary directory, container of temporary files used by the wrapper to
+      the compiler and linker.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::tmp $HOME/my_build/tmp
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_ext_cfg.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_ext_cfg.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_ext_cfg.html	(revision 329)
@@ -0,0 +1,643 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM extract configuration
+  file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM extract configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM extract configuration file</h1>
+
+  <p>The following is a list of supported declarations for the configuration
+  file used by the FCM extract system. Unless otherwise stated, the fields in
+  all declaration labels are not case sensitive.</p>
+
+  <table class="pad" summary="Declarations in extract configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::TYPE</th>
+
+      <th>Description</th>
+
+      <td>The configuration file type, the value should always be "ext" for an
+      extract configuration file. This declaration is compulsory for all
+      extract configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::type  ext
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::VERSION</th>
+
+      <th>Description</th>
+
+      <td>The file format version, currently "1.0" - a version is included so
+      that we shall be able to read the configuration file correctly should we
+      decide to change its format in the future.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::version  1.0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">DEST::ROOTDIR</th>
+
+      <th>Description</th>
+
+      <td>The "root" path of the destination of this extraction. This
+      declaration is compulsory for all extract configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::rootdir  $HOME/project/my_project
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">RDEST::MACHINE</th>
+
+      <th>Description</th>
+
+      <td>The destination machine for this extraction. If set, the extraction
+      will be mirrored to a location on this machine.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::machine  tx01
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">RDEST::LOGNAME</th>
+
+      <th>Description</th>
+
+      <td>The login name of the user on the remote destination machine. If not
+      specified, the current login name of the user on the local platform is
+      assumed.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::logname  frva
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">RDEST::ROOTDIR</th>
+
+      <th>Description</th>
+
+      <td>The "root" path of the remote destination of this extraction. This
+      declaration is compulsory if this extraction requires mirroring to a
+      remote machine.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::rootdir  /home/nwp/da/frva/project/my_project
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">REPOS::&lt;pck&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a URL or a local file system path for the container
+      "repository" of a branch named &lt;branch&gt; in a package named
+      &lt;pck&gt;. The package name &lt;pck&gt; must be the name of a
+      top-level package (i.e. it must not contain the double colon "::"
+      delimiter). The name &lt;branch&gt; is used internally within the
+      extract system, and so is independent of the branch name of the code
+      management system. However, it is usually desirable to use the same name
+      of the actual branch in the code management system. For declaration of a
+      local file system path, the convention is to name the branch "user".
+      Please note that both &lt;pck&gt; and &lt;branch&gt; fields are case
+      sensitive. The declared URL must be a valid Subversion URL or a valid
+      FCM repository keyword.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+repos::var::trunk        fcm:var_tr
+repos::var::r4790_foobar fcm:var_br/frsn/r4790_foobar
+repos::var::user         $HOME/var
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">VERSION::&lt;pck&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>The revision to be used for the URL of &lt;branch&gt; in the package
+      &lt;pck&gt;. If not specified, the revision defaults to "HEAD". Please
+      note that if the delcared "repository" is in the local file system, this
+      declaration must not be used. The value of the declaration can be a FCM
+      revision keyword or any revision argument acceptable by Subversion. You
+      can use a valid revision number, a date between a pair of curly brackets
+      (e.g. {"2005-05-01 12:00"}) or the keyword "HEAD". However, please do
+      not use the keywords "BASE", "COMMITTED" or "PREV" as these are reserved
+      for working copy only. Again, please note that both &lt;pck&gt; and
+      &lt;branch&gt; fields are case sensitive. </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Declare the revision with the FCM revision keyword "vn22.0"
+version::var::trunk        vn22.0
+# Declare the revision with a {date}
+version::var::r4790_foobar {2006-01-01}
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SRC::&lt;pcks&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a source directory for the sub-package &lt;pcks&gt;
+      of &lt;branch&gt;. If the repository is declared as a URL, the source
+      directory must be quoted as a relative path to the URL. If the
+      repository is declared as a path in the local file system, the source
+      directory can be declared as either a relative path to the "repository"
+      or a full path. If the source directory is a relative path and
+      &lt;pcks&gt; is a top-level package, the full name of the sub-package
+      will be determined automatically using the directory names of the
+      relative path as the name of the sub-packages. If the source directory
+      is a full path, the full sub-package name must be specified. The name of
+      the sub-package determines the destination path of the source directory
+      in the extraction.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+src::var::trunk                   code/VarMod_PF
+src::var::code::VarMod_PF::user   $HOME/var/code/VarMod_PF 
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXPSRC::&lt;pcks&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares an expandable source directory for the sub-package
+      &lt;pcks&gt; of &lt;branch&gt;. This declaration is essentially the
+      same as the SRC declaration, except that the system will attempt to
+      search recursively for sub-directories within the declared source
+      directory.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+expsrc::var::trunk code
+expsrc::var::user  code
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">BLD::&lt;fields&gt;</th>
+
+      <th>Description</th>
+
+      <td>Declare a build configuration file declaration. The label
+      &lt;fields&gt; is the label of the declaration. On a successful
+      extraction, &lt;fields&gt; will be added to the build configuration
+      file. Please note that some of the &lt;fields&gt; may be case
+      sensitive.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+bld::name     var_stable_22.0
+bld::target   VarScr_AnalysePF
+bld::tool::fc sxmpif90
+bld::tool::cc sxmpic++
+# ... and so on ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">USE</th>
+
+      <th>Description</th>
+
+      <td>The declares the location of a previous successful extraction, which
+      the current extraction will base on. If the previous extraction is also
+      a build, the subsequent invocation of the build system on the current
+      extraction will automatically trigger an inherited incremental build
+      based on that build.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+use  ~frva/var_stable_22.0
+# ... and then the settings for your current extraction ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INC</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a file containing extract configuration.
+      The lines in the declared file will be included inline to the current
+      extract configuration file.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inc  ~frva/var_stable_22.0/cfg/ext.cfg
+# ... and then your changes ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">OVERRIDE</th>
+
+      <th>Description</th>
+
+      <td>If a file is modified by two different branches, this flag can be
+      used to specify either to allow the later branch to override (1) the
+      earlier one or to fail (0) the extraction. If not specified, the default
+      is to fail (0).</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+override  1
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">MIRROR</th>
+
+      <th>Description</th>
+
+      <td>The extract system can mirror the extracted source to a remote
+      machine. Currently, it does this using either the <em>rdist</em> or the
+      <em>rsync</em> command. The default is <em>rsync</em>. This declaration
+      can be used to switch to using <em>rdist</em>.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+mirror  rdist
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">%&lt;name&gt;</th>
+
+      <th>Description</th>
+
+      <td>%&lt;name&gt; declares an internal variable &lt;name&gt; that
+      can later be re-used.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+%my_variable      foo
+src::bar::trunk   %my_variable
+src::egg::trunk   %my_variable
+src::ham::trunk   %my_variable
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <p class="gray">The following declarations are for reference only. They
+  should not be used in normal operations of the FCM extract system:</p>
+
+  <table class="pad" summary="Unused declarations in extract configuration file"
+  width="100%" border="1">
+    <tr class="gray">
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::SRCDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "source" path of the desintation of this extraction. Source directories
+      will be extracted to this directory. The default is to extract source
+      directories to the "src/" sub-directory under the root path of the
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::srcdir  $HOME/project/my_project/src
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::CFGDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "configuration" path of the destination of this extraction.
+      Configuration files such as the expanded extraction configuration file
+      and the build configuration file will be written in this location. The
+      default is to send the configuration files to the "cfg/" sub-directory
+      under the root path of the destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::cfgdir  $HOME/project/my_project/cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::CACHEDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      cache directory used by this extraction. Source directories and other
+      configuration files will normally be extracted and written to the cache
+      directory before being copied to the destination. This ensures fast
+      subsequent incremental extractions. It also reduces the load on the
+      repository server. The default is use the ".cache/" sub-directory under
+      the root path of the destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::cachedir  $HOME/project/my_project/.cache
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::BLD_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      destination path of the build configuration file. By default, this file
+      will be named "bld.cfg" and will be placed under the configuration
+      directory, i.e. "cfg/bld.cfg" under the root path of the
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::bld_cfg  $HOME/project/my_project/cfg/bld.cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::EXT_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      destination path of the output expanded extract configuration file. By
+      default, this file will be named "ext.cfg" and will be placed under the
+      configuration directory, i.e. "cfg/ext.cfg" under the root path of the
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::ext_cfg  $HOME/project/my_project/cfg/ext.cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::SRCDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "source" path of the remote desintation of this extraction. Source
+      directories will be mirrored to this directory. The default is to mirror
+      source directories to the "src/" sub-directory under the root path of the
+      remote destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::srcdir  /home/nwp/da/frva/project/my_project/src
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::CFGDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "configuration" path of the remote destination of this extraction.
+      Configuration files such as the expanded extraction configuration file
+      and the build configuration file are mirrored in this location. The
+      default is to send the configuration files to the "cfg/" sub-directory
+      under the root path of the remote destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::cfgdir  /home/nwp/da/frva/project/my_project/cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::BLD_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      remote destination path of the build configuration file. By default, this
+      file will be named "bld.cfg" and will be placed under the configuration
+      directory, i.e. "cfg/bld.cfg" under the root path of the remote
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::bld_cfg  /home/nwp/da/frva/project/my_project/cfg/bld.cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::EXT_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      remote destination path of the output expanded extract configuration file.
+      By default, this file will be named "ext.cfg" and will be placed under the
+      configuration directory, i.e. "cfg/ext.cfg" under the root path of the
+      remote destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::ext_cfg  /home/nwp/da/frva/project/my_project/cfg/ext.cfg
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_fcm_cfg.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_fcm_cfg.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_fcm_cfg.html	(revision 329)
@@ -0,0 +1,171 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM central/user
+  configuration file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM central/user configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM central/user configuration file</h1>
+
+  <p>Please note that setting labels in both the central and the user
+  configuration files are case insensitive.</p>
+
+  <table class="pad" summary="Declarations in FCM configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::REPOS::&lt;pck&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a URL keyword for the package &lt;pck&gt;. The value
+      of the declaration must be a valid Subversion URL. Once declared, the
+      URL keyword &lt;pck&gt; will be associated with the specified URL. In
+      subsequent invocations of the "fcm" command, the string
+      "fcm:&lt;pck&gt;" will be replaced by the URL.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Associate "var" with "svn://server/VAR_svn/var"
+set::repos::var  svn://server/VAR_svn/var
+
+# "fcm:var" is now the same as "svn://server/VAR_svn/var"
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::REVISION::&lt;pck&gt;::&lt;keyword&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares &lt;keyword&gt; to be the revision number for the
+      package &lt;pck&gt;. The &lt;keyword&gt; string can contain any
+      characters except spaces. It must not contain only digits (as digits are
+      treated as revision numbers). It must not be the Subversion revision
+      keywords "HEAD", "BASE", "COMMITTED" and "PREV". It cannot begin and end
+      with a pair of curly brackets (as this will be parsed as a revision
+      date). The package &lt;pck&gt; must be associated with a URL using the
+      SET::REPOS::&lt;pck&gt; declaration described above before this
+      declaration can make sense. Once defined, &lt;keyword&gt; can be used
+      anywhere in place the defined revision number.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+set::revision::var::v22.0  8410
+
+# E.g. "fcm list -r v22.0 fcm:var" is now the same as
+#      "fcm list -r 8410 fcm:var".
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::TRAC::&lt;pck&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a Trac browser URL that corresponds to the Subversion
+      URL declared using SET::REPOS::&lt;pck&gt;.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+set::trac::var  http://server/Trac/VAR/browser/VAR
+
+# E.g. "fcm trac fcm:var" will launch the web browser to view above.
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::MISC::WEB_BROWSER</th>
+
+      <th>Description</th>
+
+      <td>This declares a default web browser that can be used by some FCM
+      commands to browse files and documents online. The default is
+      "firefox".</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Use Netscape instead of Firefox
+set::misc::web_browser  netscape
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INC</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a file containing user configuration. The
+      lines in the declared file will be included inline.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inc  ~fred/etc/fcm.cfg
+# ... and then your changes ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <p>N.B. almost all settings in the Fcm::Config module can be modified using
+  the central/user configuration file. However, most users should only ever
+  need to use the above.</p>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_pck_cfg.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_pck_cfg.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_pck_cfg.html	(revision 329)
@@ -0,0 +1,183 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM build package
+  configuration file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM build package configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM build package configuration file</h1>
+
+  <p>The following is a list of supported declarations for package
+  configuration files. The package configuration is used by the build system.
+  It must be stored in a file called <tt>@PACKAGE.cfg</tt> in a source
+  directory. The labels in all declarations in a package configuration file
+  contain two fields delimited by the double colon "::". The first field is the
+  name of the label, which is case insensitive. The second field is the name
+  of a file, which the declaration is associated with.</p>
+
+  <table class="pad" summary="Declarations in build package configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TYPE::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares the type of <em>file</em>. The value of this
+      declaration is a list of type flags delimited by the double colon "::".
+      Each type flag is used internally to describe the nature of the file.
+      Supported flags are the same as those used in the INFILE_EXT
+      declarations in the build configuration file. For a list of these flags,
+      please see the <a href="annex_bld_cfg.html#infile-ext-types">Input file
+      extension type flags table</a> of the <a href="annex_bld_cfg.html">FCM
+      System User Guide &gt; Annex: Declarations in FCM build configuration
+      file</a> document.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Declare a Fortran 9X program source file
+type::MyFortranProg.f90  FORTRAN::FORTRAN9X::SOURCE::PROGRAM
+
+# Declare a target to build a shared object library
+type::libbooks.a         BINARY::LIB
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SCAN::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares a flag to determine whether <em>file</em> needs to be
+      scanned for dependency. Set the value to 1 to switch on, and 0 to switch
+      off. If <em>file</em> is declared a shared library, this flag is
+      automatically set to 0. For all other files, this flag is automatically
+      set to 1.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+scan::MyFortranProg.f90  0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TARGET::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares the executable name of <em>file</em> if it is a C or
+      Fortran program. If not set, the default executable name of a program is
+      the root name (i.e. base name without the file extension) of
+      <em>file</em> suffixed with the file extension ".exe".</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+target::MyFortranProg.f90  hello_world
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INTNAME::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares the internal name of <em>file</em> if it contains a
+      Fortran subroutine, function or module. The internal name determines the
+      name of the compiled object file of <em>file</em>. If not set, the
+      default depends on whether the <em>file</em> will be scanned for
+      dependencies. If so, the name of the first program unit will be used as
+      the internal name. Otherwise, the root name of <em>file</em> will be
+      used.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+intname::YourFortranMod.f90  hello_mod
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">DEP::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares a dependency target for <em>file</em>. The value of this
+      declaration must contain two fields separated by the double colon "::".
+      The first field denotes the dependency type, and the second field is the
+      dependency target. Supported dependency types are the same as those used
+      in the EXCL_DEP declarations in the build configuration file. For a list
+      of these flags, please see the <a
+      href="annex_bld_cfg.html#dependency-types">dependency types table</a> of
+      the <a href="annex_bld_cfg.html">FCM System User Guide &gt; Annex:
+      Declarations in FCM build configuration file</a> document.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+dep::MyFortranProg.f90  USE::YourFortranMod
+dep::MyFortranProg.f90  INTERFACE::HerFortran.interface
+dep::MyFortranProg.f90  INC::HisFortranInc.inc
+dep::MyFortranProg.f90  H::TheirHeader.h
+dep::MyFortranProg.f90  OBJ::ItsObject.o
+
+dep::libbooks.a         OBJ::MyObject.o
+dep::libbooks.a         OBJ::YourObject.o
+dep::libbooks.a         OBJ::HisObject.o
+dep::libbooks.a         OBJ::HerObject.o
+dep::libbooks.a         OBJ::TheirObject.o
+dep::libbooks.a         OBJ::ItsObject.o
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_quick_ref.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_quick_ref.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/annex_quick_ref.html	(revision 329)
@@ -0,0 +1,302 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Quick reference</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <script type="text/javascript">
+  <!--
+    document.write ('<address>')
+    document.write ('<a href="index.html">FCM System User Guide</a>')
+    document.write (' &gt; ')
+    document.write ('Annex: Quick reference')
+    document.write ('<\/address>')
+  //-->
+  </script>
+
+  <h1>Annex:<br>
+  Quick reference</h1>
+
+  <a name="help"></a><h2>Getting help</h2>
+
+  <table summary="help" width="100%" border="0">
+    <tr>
+      <td>fcm help</td>
+
+      <td width="70%">get list of subcommands</td>
+    </tr>
+
+    <tr>
+      <td>fcm help SUBCOMMAND</td>
+
+      <td width="70%">get help on SUBCOMMAND</td>
+    </tr>
+  </table>
+
+  <a name="maintaining-wc"></a><h2>Maintaining the working copy</h2>
+
+  <table summary="maintaining-wc" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm&nbsp;checkout&nbsp;[OPTIONS]&nbsp;URL&nbsp;[DEST]</td>
+
+      <td width="70%">Checkout URL (and create a working copy at DEST)</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N</td>
+
+      <td width="70%">Checkout revision N of URL</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm info</td>
+
+      <td width="70%">Print working copy information</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm status [OPTIONS]</td>
+
+      <td width="70%">Print status of working copy</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-u</td>
+
+      <td width="70%">Show update information</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-v</td>
+
+      <td width="70%">Show verbose information</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm update</td>
+
+      <td width="70%">Update working copy with repository changes</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm switch URL</td>
+
+      <td width="70%">Switch your working copy to point to a branch specified by
+      URL</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm commit</td>
+
+      <td width="70%">Commit local changes back into the repository</td>
+    </tr>
+  </table>
+
+  <a name="preparing-changes"></a><h2>Preparing changes</h2>
+
+  <table summary="preparing-changes" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm diff [OPTIONS]</td>
+
+      <td width="70%">Display working copy changes in unified diff format</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-b</td>
+
+      <td width="70%">Show differences relative to the base of the branch</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-g</td>
+
+      <td width="70%">Display working copy changes with xxdiff</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N</td>
+
+      <td width="70%">Display working copy changes against revision N</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm revert [OPTIONS] PATH</td>
+
+      <td width="70%">Restore the file PATH to the pristine copy</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td>-R</td>
+
+      <td width="70%">Descend PATH recursively, restoring any modified files to
+      the pristine copy</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm mkdir [PATH]</td>
+
+      <td width="70%">Add a directory PATH under revision control</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm add [OPTIONS] [PATH]</td>
+
+      <td width="70%">Add PATH under revision control</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-c</td>
+
+      <td width="70%">Check for items not under revision control and add
+      them</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm delete [OPTIONS] [PATH]</td>
+
+      <td width="70%">Remove PATH from revision control</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-c</td>
+
+      <td width="70%">Check for missing items and remove them</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm copy SRC DST</td>
+
+      <td width="70%">Duplicate SRC to DST, remembering history</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm move SRC DST</td>
+
+      <td width="70%">Move or rename SRC to DST, remembering history</td>
+    </tr>
+  </table>
+
+  <a name="browse"></a><h2>Browsing</h2>
+
+  <table summary="browse" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm&nbsp;log&nbsp;[OPTIONS]&nbsp;[TARGET]</td>
+
+      <td width="70%">Show the log message of a TARGET that can either be
+      working copy or URL</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N[:M]</td>
+
+      <td width="70%">Show the log message of a range of reivsions</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm list [OPTIONS] [TARGET]</td>
+
+      <td width="70%">List directory entries in TARGET</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N</td>
+
+      <td width="70%">List directory entries of revision N</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-v</td>
+
+      <td width="70%">List directory entries in verbose mode</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-R</td>
+
+      <td width="70%">List directory entries recursively down the
+      directories</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm trac [TARGET]</td>
+
+      <td width="70%">Open a WWW browser to browse TARGET with Trac</td>
+    </tr>
+  </table>
+
+  <a name="branch"></a><h2>Branching</h2>
+
+  <table summary="browse" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm branch [OPTIONS] [URL]</td>
+
+      <td width="70%">Show branch information of URL or local working
+      copy</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-d</td>
+
+      <td width="70%">Show branch information and delete the branch</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-c -n NAME</td>
+
+      <td width="70%">Create a branch</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm merge [SOURCE]</td>
+
+      <td width="70%">Merge changes from SOURCE to your working copy</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm conflicts</td>
+
+      <td width="70%">Use xxdiff to resolve conflicts in your working copy</td>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/build.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/build.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/build.html	(revision 329)
@@ -0,0 +1,1975 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: The Build System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - The Build System">
+  <meta name="keywords" content="FCM, user guide, extract, build">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; The Build System
+  </address>
+
+  <h1>The Build System</h1>
+
+  <p>The build system analyses the directory tree containing a set of source
+  code, processes the configuration, and invokes <em>make</em> to compile/build
+  the source code into the project executables. In this chapter, we shall use
+  many examples to explain how to use the build system. At the end of this
+  chapter, you should be able to use the build system, either by defining the
+  build configuration file directly or by using the extract system to generate
+  a suitable build configuration file.</p>
+
+  <h2><a name="command">The Build Command</a></h2>
+
+  <p>To invoke the build system, simply issue the command:</p>
+  <pre>
+fcm build
+</pre>
+
+  <p>By default, the build system searches for a build configuration file
+  "bld.cfg" in "$PWD" and then "$PWD/cfg". If a build configuration file is
+  not found in these directories, the command fails with an error. If a build
+  configuration file is found, the system will use the configuration specified
+  in the file to perform the build. If you use the extract system to extract
+  your source tree, a build configuration should be written for you
+  automatically at the "cfg/" sub-directory of the destination root
+  directory.</p>
+
+  <p>If the root directory of the build does not exist, the system performs a
+  new full build at this directory. If a previous build already exists at this
+  directory, the system performs an incremental build. If a full (fresh) build
+  is required for whatever reason, you can invoke the build system using the
+  "-f" option, (i.e. the command becomes "fcm build -f").</p>
+
+  <p>The build system uses GNU <em>make</em> to perform the majority of the
+  build. GNU <em>make</em> has a "-j &lt;jobs&gt;" option to specify the
+  number of &lt;jobs&gt; to run simultaneously. Invoking the build system with
+  the same option triggers this option when the build system invokes the
+  <em>make</em> command. The argument to the option &lt;jobs&gt; must be an
+  integer. The default is 1. For example, the command "fcm build -j 4"
+  will allow <em>make</em> to perform 4 jobs simultaneously.</p>
+
+  <p>For further information on the build command, please see <a href=
+  "command_ref.html#fcm_bld">FCM Command Reference &gt; fcm build</a>.</p>
+
+  <h2><a name="basic">Basic Features</a></h2>
+
+  <p>The build configuration file is the user interface of the build system. It
+  is a line based text file. You can create your own build configuration file
+  or you can use the extract system to create one for you.  For a complete set
+  of build configuration file declarations, please refer to the <a
+  href="annex_bld_cfg.html">Annex: Declarations in FCM build configuration
+  file</a>.</p>
+
+  <h3><a name="basic_build">Basic build configuration</a></h3>
+
+  <p>Suppose we have a directory at "$HOME/example". Its sub-directory
+  at "$HOME/example/src" contains a source tree to be built. You may
+  want to have a build configuration file "$HOME/example/cfg/bld.cfg",
+  which may contain:</p>
+
+  <table class="pad" summary="build_example1" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 1 - basic build configuration</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type     bld                           # line 1
+cfg::version  1.0                           # line 2
+
+dir::root     $HOME/example                 # line 4
+
+target        foo.exe bar.exe               # line 6
+
+tool::fc      ifc                           # line 8
+tool::fflags  -O3                           # line 9
+tool::cc      gcc                           # line 10
+tool::cflags  -O3                           # line 11
+tool::ld      ifc                           # line 12
+tool::ldflags -O3 -L$(HOME)/lib -legg -lham # line 13
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 1: the label CFG::TYPE declares the type of the configuration
+    file. The value "bld" tells the system that it is a build configuration
+    file.</li>
+
+    <li>line 2: the label CFG::VERSION declares the version of the build
+    configuration file. The current default is "1.0". Although it is not
+    currently used, if we have to change the format of the configuration file
+    at a later stage, we shall be able to use this number to determine whether
+    we are reading a file with an older format or one with a newer
+    format.</li>
+
+    <li>line 4: the label DIR::ROOT declares the root directory of the current
+    build.</li>
+
+    <li>line 6: the label TARGET declares a list of "default" targets. The
+    default targets of the current build will be "foo.exe" and "bar.exe".</li>
+
+    <li>line 8: the label TOOL::FC declares the Fortran compiler command.</li>
+
+    <li>line 9: the label TOOL::FFLAGS declares the options to be used when
+    invoking the Fortran compiler command.</li>
+
+    <li>line 10: the label TOOL::CC declares the C compiler command.</li>
+
+    <li>line 11: the label TOOL::CFLAGS declares the options to be used when
+    invoking the C compiler command.</li>
+
+    <li>line 12: the label TOOL::LD declares the linker command.</li>
+
+    <li>line 13: the label TOOL::LDFLAGS declares the options to be used when
+    invoking the linker command.</li>
+  </ul>
+
+  <p>When we invoke the build system, it reads the above configuration file.  It
+  will go through various internal processes, such as dependency generations, to
+  obtain the required information to prepare the <em>Makefile</em> of the build.
+  (All of which will be described in later sections.) The <em>Makefile</em> of
+  the build will be placed at "$HOME/example/bld". The system will then invoke
+  <em>make</em> to build the targets specified in line 6, i.e. "foo.exe" and
+  "bar.exe" using the build tools specified between line 8 to line 13. On a
+  successful build, the target executables will be sent to "$HOME/example/bin/".
+  The build system also creates a shell script called "fcm_env.ksh" in
+  "$HOME/example/". If you source the shell script, it will export your PATH
+  environment variable to search the "$HOME/example/bin/" directory for
+  executables.</p>
+
+  <p>N.B. You may have noticed that the "-c" (compile to object file only)
+  option is missing from the compiler flags declarations. This is because the
+  option is inserted automatically by the build system, unless it is already
+  declared.</p>
+
+  <table class="pad" summary=
+  "note - declaration of source directories for build" border="1" width="100%">
+    <tr>
+      <th>Note - declaration of source directories for build</th>
+    </tr>
+
+    <tr>
+      <td>
+        Source directories do not have to reside in the source sub-directory
+        of the build root directory. They can be anywhere, but you will have to
+        declare them individually, using the label SRC::&lt;pcks&gt;, where
+        &lt;pcks&gt; is the sub-package name in which the source directory
+        belongs. E.g.
+
+        <pre>
+# Declare a source directory in the sub-package "foo::bar"
+src::foo::bar  $HOME/foo/bar
+</pre>
+
+        <p>By default, the build system searches the "src/"
+        sub-directory of the build root directory for sub-package source
+        directories. If all source directories are already declared
+        explicitly, you can switch off the automatic directory search by
+        setting the SEARCH_SRC flag to 0. E.g.</p>
+
+        <pre>
+search_src  0
+</pre>
+
+        <p>As mentioned in the previous chapter, the name of a sub-package
+        &lt;pcks&gt; provides a unique namespace for a file container. The
+        name of a sub-package is a list of words delimited by the double
+        colons "::", which is turned into the double underscores "__" by
+        the build system internally. Please avoid using "::" and "__" for
+        naming your files and directories.</p>
+        
+        <p>In the build system, the sub-package name also provides an
+        "inheritance" relationship for sub-packages. For instance, we may
+        have a sub-package called "foo::bar::egg", which belongs to the
+        sub-package "foo::bar", which belongs to the package "foo".</p>
+        
+        <ul>
+          <li>If we declare a global build tool, it applies to all
+          packages.</li>
+          
+          <li>If we declare a build tool for "foo", it applies also to the
+          sub-package "foo::bar" and "foo::bar::egg".</li>
+          
+          <li>If we declare a build tool for "foo::bar", it applies also to
+          "foo::bar::egg", but not to other sub-packages in "foo".</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="basic_extract">Build configuration via the extract
+  system</a></h3>
+
+  <p>As mentioned earlier, you can obtain a build configuration file through
+  the extract system. The following example is what you may have in your
+  extract configuration in order to obtain a similar configuration as example
+  1:</p>
+
+  <table class="pad" summary="build_example2" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 2 - created by the extract system</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext                           # line 1
+cfg::version       1.0                           # line 2
+
+dest::rootdir      $HOME/example                 # line 4
+
+bld::target        foo.exe bar.exe               # line 6
+
+bld::tool::fc      ifc                           # line 8
+bld::tool::fflags  -O3                           # line 9
+bld::tool::cc      gcc                           # line 10
+bld::tool::cflags  -O3                           # line 11
+bld::tool::ld      ifc                           # line 12
+bld::tool::ldflags -O3 -L$(HOME)/lib -legg -lham # line 13
+
+# ... and other declarations for repositories and source directories ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>It is easy to note the similarities and differences between example 1 and
+  example 2. Example 2 is an extract configuration file. It extracts to a
+  destination root directory that will become the root directory of the build.
+  Line 6 to line 13 are the same declarations, except that they are now
+  prefixed with "BLD::". In an extract configuration file, any lines prefixed
+  with "BLD::" means that they are build configuration setting. These lines
+  are "ignored" by the extract system but are parsed down to the output build
+  configuration file, with the "BLD::" prefix removed. (Note: the "BLD::" prefix
+  is optional for declarations in a build configuration file.)</p>
+
+  <p>N.B. If you use the extract system to mirror an extraction to a remote
+  machine, the extract system will assume that the root directory of the
+  remote destination is the root directory of the build, and that the build
+  will be carried out in the remote machine.</p>
+
+  <h3><a name="basic_exename">Naming of executables</a></h3>
+
+  <p>If a source file called "foo.f90" contains a main program, the default
+  behaviour of the system is to name its executable "foo.exe". The root name of
+  the executable is the same as the original file name, but its file extension
+  is replaced with ".exe". The output extension can be altered by re-registering
+  the extension for output EXE files. How this can be done will be discussed
+  later in the sub-section <a href="#advanced_file-type">File Type</a>.</p>
+  
+  <p>If you need to alter the full name of the executable, you can use the
+  "EXE_NAME::" declaration. For example, the declaration:</p>
+
+  <pre>
+bld::exe_name::foo  bar
+</pre>
+
+  <p>will rename the executable of "foo.f90" from "foo.exe" to "bar".</p>
+
+  <p>Note: the declaration label is "bld::exe_name::foo" (not
+  "bld::exe_name::foo.exe") and the executable will be named "bar" (not
+  "bar.exe").</p>
+  
+  <p>Another way to alter the full name of the executable is to use the package
+  configuration file, which will be discussed later in the sub-section <a
+  href="#other_pckcfg">Using a package configuration file</a>.</p>
+
+  <h3><a name="basic_flags">Setting the compiler flags</a></h3>
+
+  <p>As discussed in the first example, the compiler commands and their flags
+  can be set via the "TOOL::" declarations. A simple "TOOL::FFLAGS"
+  declaration, for example, alters the compiler options for compiling all
+  Fortran source files in the build. If you need to alter the compiler options
+  only for the source files in a particular sub-package, it is possible to do so
+  by adding the sub-package name to the declaration label. For example, the
+  declaration label "TOOL::FFLAGS::ops::code::OpsMod_Control" will ensure that
+  the declaration only applies to the code in the sub-package
+  "ops::code::OpsMod_Control". You can even make declarations down to the
+  individual source file level. For example, the declaration label
+  "TOOL::FFLAGS::ops::code::OpsMod_Control::Ops_Switch" will ensure that the
+  declaration applies only for the file "Ops_Switch.f90".</p>
+  
+  <p>N.B. Although the prefix "TOOL::" and the tool names are
+  case-insensitive, sub-package names are case sensitive in the declarations.
+  Internally, tool names are turned into uppercase, and the sub-package
+  delimiters are changed from the double colons "::" to the double underscores
+  "__". When the system generates the <em>Makefile</em> for the build, each
+  "TOOL" declaration will be exported as an environment variable. For example,
+  the declaration "tool::fflags::ops::code::OpsMod_Control" will be exported
+  as "FFLAGS__ops__code__OpsMod_Control".</p>
+
+  <p>N.B. Although you can declare different compiler flags, linker commands and
+  linker flags for different sub-packages, you cannot declare different
+  compilers for different sub-packages.</p>
+
+  <!--table class="pad" summary="note - TOOL declarations" border="1"
+  width="100%">
+    <tr>
+      <th>Note - TOOL declarations</th>
+    </tr>
+
+    <tr>
+      <td>The system does not stop you from making TOOL declarations that are
+      not supported, but it will only use the ones that are supported. For
+      example, you can define a compiler command for a sub-package, but it
+      will be ignored.</td>
+    </tr>
+  </table-->
+
+  <p>The following is an example setting in an extract configuration file
+  based on example 2:</p>
+
+  <table class="pad" summary="build_example3" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 3 - compiler flags for different
+      sub-packages</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type              ext
+cfg::version           1.0
+
+dest::rootdir          $HOME/example
+
+bld::target            foo.exe bar.exe
+
+bld::tool::fc          ifc
+bld::tool::fflags      -O3    # line 9
+bld::tool::cc          gcc
+bld::tool::cflags      -O3
+bld::tool::ld          ifc
+bld::tool::ldflags     -L$(HOME)/lib -legg -lham
+
+bld::tool::fflags::ops -O1 -C # line 15
+bld::tool::fflags::gen -O2    # line 16
+
+# ... and other declarations for repositories and source directories ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>In the example above, line 15 alters the Fortran compiler flags for "ops",
+  so that all source files in "ops" will be compiled with optimisation level
+  1 and will have runtime error checking switched on. Line 16, alters the
+  Fortran compiler flags for "gen", so that all source files in "gen" will be
+  compiled with optimisation level 2. All other Fortran source files will use
+  the global setting declared at line 9, so they they will all be compiled
+  with optimisation level 3.</p>
+
+  <table class="pad" summary=
+  "note - changing compiler flags in incremental builds" border="1"
+  width="100%">
+    <tr>
+      <th>Note - changing compiler flags in incremental builds</th>
+    </tr>
+
+    <tr>
+      <td>
+        Suppose you have performed a successful build using the configuration
+        in example 3, and you have decided to change some of the compiler
+        flags, you can do so by altering the appropriate flags in the build
+        configuration file.  When you trigger an incremental build, the system
+        will detect changes in compiler flags automatically, and update only
+        the required targets. The following hierarchy is followed:
+
+        <ul>
+          <li>If the compiler flags for a particular source file change, only
+          that source file and any targets depending on that source file are
+          re-built.</li>
+
+          <li>If the compiler flags for a particular sub-package change, only
+          source files within that sub-package and any targets depending on
+          those source files are re-built.</li>
+
+          <li>If the global compiler flags change, all source files are
+          re-built.</li>
+
+          <li>If the compiler command changes, all source files are
+          re-built.</li>
+        </ul>
+
+        <!--p>The build system implements the above hierarchy using a "flags"
+        file system, which are dummy files created in the "flags/"
+        sub-directory of the build root. They are updated by the "touch"
+        command. The following dependencies are followed:</p>
+
+        <ul>
+          <li>Source files are dependent on its own "flags" file. E.g. the file
+          Ops_Switch in sub-package ":ops::code::OpsMod_Control" is dependent
+          on "FFLAGS__ops__code__OpsMod_Control__Ops_Switch.flags".</li>
+
+          <li>The "flags" file of a source file is dependent on the "flags" file
+          of its container sub-package. E.g. the above flags file is dependent
+          on "FFLAGS__ops__code__OpsMod_Control.flags".</li>
+
+          <li>The "flags" file of a sub-package is dependent on the "flags"
+          file of its container sub-package. E.g. the above is dependent on
+          "FFLAGS__ops__code.flags", which is dependent on
+          "FFLAGS__ops.flags".</li>
+
+          <li>The "flags" file of a top-level package is dependent on the
+          "flags" file of the global flags. E.g. "FFLAGS__ops.flags" is
+          dependent on "FFLAGS.flags".</li>
+
+          <li>The "flags" file of the global "flags" file is dependent on the
+          "flags" file of the compiler command. E.g. "FFLAGS.flags" is
+          dependent on "FC.flags".</li>
+        </ul>
+        
+        <p>The system records changes in declared tools using a cache file,
+        (called ".bld_tool", located at the ".cache/" sub-directory of the
+        built root). It is basically a list of "TOOL::" declarations for the
+        latest build.  When an incremental build is invoked, the list is
+        compared against the current set. If there are changes (modification,
+        addition and deletion) in any declarations, the timestamp of the
+        corresponding "flags" files will be updated. Files depending on the
+        updated "flags" file will then be considered out of date by
+        <em>make</em>, triggering a re-build of those files.</p-->
+      </td>
+    </tr>
+  </table>
+
+  <p>N.B. For a full list of build tools declarations, please see <a
+  href="annex_bld_cfg.html#tools-list">Annex: Declarations in FCM build
+  configuration file &gt; list of tools</a>.</p>
+
+  <h3><a name="basic_interface">Automatic Fortran 9X interface block</a></h3>
+
+  <p>For each Fortran 9X source file containing standalone subroutines and/or
+  functions, the system generates an interface file and sends it to the "inc/"
+  sub-directory of the build root. An interface file contains the interface
+  blocks for the subroutines and functions in the original source file. In an
+  incremental build, if you have modified a Fortran 9X source file, its
+  interface file will only be re-generated if the content of the interface has
+  changed.</p>
+  
+  <p>Consider a source file "foo.f90" containing a subroutine called "foo". In a
+  normal operation, the system writes the interface file to "foo.interface" in
+  the "inc/" sub-directory of the build root. By default, the root name of the
+  interface file is the same as that of the source file, and is case sensitive.
+  You can change this behaviour using a "TOOL::INTERFACE" declaration. E.g.:</p>
+
+  <pre>
+bld::tool::interface  program # The default is "file"
+</pre>
+
+  <p>In such case, the root name of the interface file will be named in lower
+  case after the first program unit in the file.</p>
+  
+  <p>The default extension for an interface file is ".interface". This can be
+  modified through the input and output file type register, which will be
+  discussed in a later section on <a href="#advanced_file-type">File
+  Type</a>.</p>
+  
+  <p>In most cases, we modify procedures without altering their calling
+  interfaces. Consider another source file "bar.f90" containing a subroutine
+  "bar". If "bar" calls "foo", it is good practice for "bar" to have an explicit
+  interface for "foo". This can be achieved if the subroutine "bar" has the
+  following within its declaration section:</p>
+
+  <pre>
+INCLUDE 'foo.interface'
+</pre>
+
+  <p>The source file "bar.f90" is now dependent on the interface file
+  "foo.interface". This can make incremental build very efficient, as changes
+  in the "foo.f90" file will not normally trigger the re-compilation of
+  "bar.f90", provided that the interface of the subroutine "foo" remains
+  unchanged. (However, the system is clever enough to know that it needs to
+  re-link any executables that are dependent on the object file for the
+  subroutine "bar".)</p>
+
+  <p>The default interface block generator is a piece of "plugged-in" Perl
+  code originally developed by the ECMWF. It has been modified at the Met
+  Office to work with FCM. Currently, the system can also work with the
+  interface generator <em>f90aib</em>, which is a freeware obtained from <a
+  href="http://www.ifremer.fr/ditigo/molagnon/fortran90/contenu.html">Fortran
+  90 texts and programs, assembled by Michel Olagnon</a> at the French
+  Research Institute for Exploitation of the Sea. To do so, you need to make a
+  declaration in the build configuration file using the label
+  "TOOL::GENINTERFACE". As for any other TOOL declarations, you can attach a
+  sub-package name to the label. The change will then apply only to source
+  files within that sub-package. If "TOOL::GENINTERFACE" is declared to have
+  the value "NONE", interface generation will be switched off. The following
+  are some examples:</p>
+
+  <table class="pad" summary="build_example4" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 4 - Fortran 9X interface block
+      generator</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+# This is an EXTRACT configuration file ...
+
+# ... some other declarations ...
+
+bld::tool::geninterface       f90aib # line 5
+bld::tool::geninterface::foo  ECMWF  # line 6
+bld::tool::geninterface::bar  none   # line 7
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>In line 5, the global interface generator is now set to <em>f90aib</em>.
+  In line 6, the interface generator for the package "foo" is set to the ECMWF
+  one. In line 7, by setting the interface generator for the package "bar" to
+  the "none" keyword, no interface file will be generated for source files
+  under the package "bar".</p>
+
+  <p>Switching off the interface block generator can be useful in many
+  circumstances. For example, if the interface block is already provided
+  manually within the source tree, or if the interface block is never used by
+  other program units, it is worth switching off the interface generator for
+  the source file to speed up the build process.</p>
+
+  <h3><a name="basic_dependency">Automatic dependency</a></h3>
+
+  <p>The build system has a built-in dependency scanner, which works out the
+  dependency relationship between source files, so that they can be built in
+  the correct order. The system scans all source files of known types for all
+  supported dependency patterns. Dependencies of source files in a sub-package
+  are written in a cache, which can be retrieved for incremental builds. (In
+  an incremental build, only changed source files need to be re-scanned for
+  dependency information. Dependency information for other files are retrieved
+  from the cache.) The dependency information is parsed to the <em>make</em>
+  rule generator, which writes the <em>Makefile</em> fragment for building the
+  source files in the sub-package. In an incremental build, a
+  <em>Makefile</em> fragment for a sub-package is only re-generated if a
+  source file in the sub-package has changed.</p>
+
+  <p>The <em>make</em> rule generator generates different <em>make</em> rules
+  for different dependency types. The following dependency patterns are
+  automatically detected by the current system:</p>
+
+  <ul>
+    <li>The [USE &lt;module&gt;] statement in a Fortran source file is the first
+    pattern. The statement has two implications: 1) The current file compiles
+    only if the module has been successfully compiled, and needs to be
+    re-compiled if the module has changed. 2) The executable depending on the
+    current file can only resolve all its externals by linking with the object
+    file of the compiled module. The executable needs to be re-linked if the
+    module and its dependencies has changed.</li>
+
+    <li>The [INCLUDE '&lt;name&gt;.interface'] statement in a Fortran source
+    file is the second pattern. (The default extension for an interface file is
+    ".interface". This can be modified through the input and output file type
+    register, which will be discussed in a later section on <a href=
+    "#advanced_file-type">File Type</a>.) It has two implications: 1) The
+    current file compiles only if the included interface file is in the INCLUDE
+    search path, and needs to be re-compiled if the interface file changes. 2)
+    The executable depending on the current file can only resolve all its
+    externals by linking with the object file of the source file that generates
+    the interface file. The executable needs to be re-linked if the source file
+    (and its dependencies) associated with the interface file has changed. It is
+    worth noting that for this dependency to work, the root &lt;name&gt; of the
+    interface file should match with that of the source file associated with the
+    interface file. (Please note that you can use pre-processor [#include
+    "&lt;name&gt;.interface] instead of Fortran INCLUDE, but it will not work
+    if you switch on the <a href="#advanced_pp">pre-processing</a> stage, which
+    will be discussed in a later section.)</li>
+
+    <li>The [INCLUDE '&lt;file&gt;'] statement (excluding the INCLUDE
+    interface file statement) in a Fortran source file is the third pattern.
+    It has two implications: 1) The current file compiles only if the included
+    file is in the INCLUDE search path, and needs to be re-compiled if the
+    include file changes. 2) The executable needs to be linked with any
+    objects the include file is dependent on. It needs to be re-linked if
+    these objects have changed.</li>
+
+    <li>The [#include '&lt;file&gt;'] statement in a Fortran/C source or header
+    file is the fourth pattern. It has similar implications as the Fortran
+    INCLUDE statement. However, they have to be handled differently because
+    "#include" statements are processed by the pre-processor, which may be
+    performed in a separate stage of the FCM build process. This will be
+    further discussed in a later sub-section on <a
+    href="#advanced_pp">Pre-processing</a>.</li>
+  </ul>
+
+  <p>If you want your code to be built automatically by the FCM build system,
+  you should also design your code to conform to the following rules:</p>
+
+  <ol>
+    <li>Single compilable program unit, (i.e. program, subroutine, function or
+    module), per file.</li>
+
+    <li>Unique name for each compilable program unit.</li>
+
+    <li>Always supply an interface for subroutines and functions, i.e.:
+      <ul>
+        <li>Put them in modules.</li>
+
+        <li>Put them in the CONTAINS section within the main program unit.</li>
+
+        <li>Use interface files.</li>
+      </ul>
+    </li>
+
+    <li>If interface files are used, it is good practise to name each source
+    file after the program unit it contains. It will make life a lot simpler
+    when using the <a href="#basic_interface">Automatic Fortran 9X interface
+    block</a> feature, which has already been discussed in the previous
+    section.
+      <ul>
+        <li>The problem is that, by default, the root name of the interface file
+	    is the same as that of the source file rather than the program unit.
+	    If they differ then the build system will create a dependency on the
+	    wrong object file (since the object files are named according to the
+	    program unit).</li>
+	<li>This problem can be avoided by changing the behaviour of the interface
+	    file generator to use the name of the program unit instead (using a
+	    "TOOL::INTERFACE" declaration).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <table class="pad" summary=
+  "note - setting build targets" border="1" width="100%">
+    <tr>
+      <th>Note - setting build targets</th>
+    </tr>
+
+    <tr>
+      <td>
+        The <em>Makefile</em> (and its include fragments) generated by the
+        build system contains a list of targets that can be built. The build
+        system allows you to build (or perform the actions of) any targets that
+        are present in the generated <em>Makefile</em>. There are two ways to
+        specify the targets to be built. Firstly, you can use the TARGET
+        declarations in your build configuration file to specify the default
+        targets to be built.  These targets will be set as dependencies of the
+        "all" target in the generated <em>Makefile</em>, which is the default
+        target to be built when <em>make</em> is invoked by FCM. Alternatively,
+        you can use the "-t" option when you invoke the "fcm build" command. The
+        option takes an argument, which should be a colon ":" separated list of
+        targets to be built. When the "-t" option is set, FCM invokes
+        <em>make</em> to build these targets instead. (E.g. if we invoke the
+        build system with the command "fcm build -t foo.exe:bar.exe", it will
+        invoke <em>make</em> to build "foo.exe" and "bar.exe".)
+
+        <p>If you do not specify any explicit targets, the system will search
+        your source tree for main programs:</p>
+        
+        <ul>
+          <li>If there are main programs in your source tree, they will be set
+          as the default targets automatically.</li>
+
+          <li>Otherwise, the default is to build the top level library archive
+          containing objects compiled from the source files in the current
+          source tree. (For more information on building library archives,
+          please see the section on <a href="#advanced_library">Creating
+          library archives</a>.)</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="advanced">Advanced Features</a></h2>
+
+  <h3><a name="advanced_dependency">Further dependency features</a></h3>
+
+  <p>Apart from the usual dependency patterns described in the previous
+  sub-section, the automatic dependency scanner also recognises two special
+  directives when they are inserted into a source file:</p>
+
+  <ul>
+    <li>The directive [DEPENDS ON: &lt;object&gt;] in a comment line of a
+    Fortran/C source file: It states that the current file is dependent on the
+    declared external object. The executable depending on the current file
+    needs to link with this external object in order to resolve all its
+    external references. It needs to be re-linked if the declared external
+    object (and its dependencies) has changed.</li>
+
+    <li>The directive [CALLS: &lt;executable&gt;] in a comment line of a
+    script: It states that the current script is dependent on the declared
+    executable file, which can be another script or a binary executable. The
+    current script can only function correctly if the declared executable is
+    found in the search path. This directive is useful to ensure that all
+    dependent executables are built or copied to the correct path.</li>
+  </ul>
+
+  <p>There are situations when you need to bypass the automatic dependency
+  scanner. In such case, you may need to use a package configuration file. For
+  further information, please refer to the sub-section on <a href=
+  "#advanced_pckcfg">Using a package configuration file</a>.</p>
+
+  <p>Another way to specify external dependency is to use the EXE_DEP
+  declaration to declare extra dependencies. The declaration normally applies to
+  all main programs, but if the the form EXE_DEP::&lt;target&gt; is used, it
+  will only apply to &lt;target&gt;, (which must be the name of a main program
+  target). If the declaration is made without a value, the main programs will be
+  set to depend on all object files. Otherwise, the value can be supplied as a
+  space delimited list of items. Each item can be either the name of a
+  sub-package or an object target. For the former, the main programs will be set
+  to depend on all object files within the sub-package. For the latter, the main
+  programs will be set to depend on the object target. The following are some
+  examples:</p>
+
+  <table class="pad" summary="build_example5" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 5 - extra executable dependency</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext
+cfg::version       1.0
+
+bld::exe_dep::foo.exe  foo::bar egg.o # line 4
+bld::exe_dep                          # line 5
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line declares the dependency on the sub-package "foo::bar"
+    and the object target "egg.o" for building the main program target
+    "foo.exe". The target "foo.exe" will now depends on all object files in the
+    "foo::bar" sub-package as well as the object target "egg.o".</li>
+
+    <li>line 5: this line declares that all other main program targets will
+    depend on all (non-program) object files in the build.</li>
+  </ul>
+
+  <table class="pad" summary="note - naming of object files" border="1"
+  width="100%">
+    <tr>
+      <th>Note - naming of object files</th>
+    </tr>
+
+    <tr>
+      <td>By default, object files are named with the suffix ".o". For a
+      Fortran source file, the build system uses the lower case name of the
+      first program unit within the file to name its object file. For example,
+      if the first program unit in the Fortran source file "foo.f90" is
+      "PROGRAM Bar", the object file will be "bar.o". For a C source file, the
+      build system uses the lower case root name of the source file to name
+      its object file. For example, a C source file called "egg.c" will have
+      its object file named "egg.o".
+      
+        <p>The reason for using lower case to name the object files is because
+        Fortran is a case insensitive language. Its symbols can either be in
+        lower or upper case. E.g. the SUBROUTINE "Foo" is the same as the
+        SUBROUTINE "foo". It can be rather confusing if the subroutines are
+        stored in different files. When they are compiled and archived into a
+        library, there will be a clash of namespace, as the Fortran compiler
+        thinks they are the same. However, this type of error does not normally
+        get reported. If "Foo" and "foo" are very different code, the user may
+        end up using the wrong subroutine, which may lead to a very long
+        debugging session. By naming all object files in lower case, this type
+        of situation can be avoided. If there is a clash in names due to the use
+        of upper/lower cases, it will be reported as warnings by <em>make</em>,
+        (as "duplicated targets" for building "foo.o").</p>
+      </td>
+    </tr>
+  </table>
+  
+  <p>It is realised that there are situations when an automatically detected
+  dependency should not be written into the <em>Makefile</em>. For example,
+  the dependency may be a standard module provided by the Fortran compiler,
+  and does not need to be built in the usual way. In such case, we need to
+  have a way to exclude this module during an automatic dependency scan.</p>
+
+  <p>The EXCL_DEP declaration can be used to do just that. The following
+  extract configuration contains some examples of the basic usage of the
+  EXCL_DEP declaration:</p>
+
+  <table class="pad" summary="build_example6" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 6 - exclude dependency</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext
+cfg::version       1.0
+
+bld::excl_dep  USE::YourFortranMod             # line 4
+bld::excl_dep  INTERFACE::HerFortran.interface # line 5
+bld::excl_dep  INC::HisFortranInc.inc          # line 6
+bld::excl_dep  H::TheirHeader.h                # line 7
+bld::excl_dep  OBJ::ItsObject.o                # line 8
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line declares that the Fortran module "YourFortranMod"
+    should be excluded. The value of each EXCL_DEP declaration has two parts.
+    The first part is a label that is used to define the type of dependency to
+    be excluded. For a full list of these labels, please see the <a
+    href="annex_bld_cfg.html#dependency-types">dependency types table</a> in
+    the <a href="annex_bld_cfg.html">Annex:
+    Declarations in FCM build configuration file</a>. The label "USE"
+    denotes a Fortran module. The second part of the label is the dependency
+    itself. For instance, if a Fortran source file contains the line: "USE
+    YourFortranMod", the dependency scanner will ignore it.</li>
+
+    <li>line 5: this line declares that the include statement for the Fortran
+    9X interface file "HerFortran.interface" should be excluded. The label
+    "INTERFACE" denotes a Fortran INCLUDE statement for a Fortran 9X interface
+    block file. For example, if a Fortran source file contains the line:
+    "INCLUDE 'HerFortran.interface'", the dependency scanner will
+    ignore it.</li>
+
+    <li>line 6: this line declares that the include statement for
+    "HisFortranInc.inc" should be excluded. The label "INC" denotes a Fortran
+    INCLUDE statement other than an INCLUDE statement for an interface block
+    file. For example, if a Fortran source file contains the line:
+    "INCLUDE 'HisFortranInc.inc'", the dependency scanner will ignore
+    it.</li>
+
+    <li>line 7: this line declares that the header include statement
+    "TheirHeader.h" should be excluded. The label "H" denotes a pre-processing
+    #include statement. For example, if a source file contains the line:
+    "#include 'TheirHeader.h'", the dependency scanner will ignore
+    it.</li>
+
+    <li>line 8: this line declares that the external dependency for
+    "ItsObject.o" should be excluded. The label "OBJ" denotes a compiled
+    binary object. These dependencies are normally inserted into the source
+    files as special comments. For example, if a source file contains the line:
+    "! depends on: ItsObject.o", the dependency scanner will ignore
+    it.</li>
+  </ul>
+
+  <p>An EXCL_DEP declaration normally applies to all files in the build.
+  However, you can suffix it with the name of a sub-package, i.e.
+  EXCL_DEP::&lt;pcks&gt;. In such case, the declaration will only apply while
+  scanning for dependencies in the source files in the sub-package named
+  &lt;pcks&gt;.</p>
+
+  <p>You can also exclude all dependency scan of a particular type. To do so,
+  simply declare the type in the value. For example, if you do not want the
+  build system to scan for the [CALLS: &lt;executable&gt;] directive in the
+  comment lines of your scripts, you can make the following declaration:</p>
+
+  <pre>
+bld::excl_dep  EXE
+</pre>
+
+  <p>N.B. Currently, the build system is unable to detect changes in EXCL_DEP
+  declarations. Therefore, you will need to invoke the build system in full
+  build mode if you have changed these settings.</p>
+
+  <h3><a name="advanced_blockdata">Linking a Fortran executable with a BLOCKDATA
+  program unit</a></h3>
+
+  <p>If it is required to link Fortran executables with BLOCKDATA program units,
+  you must declare the executable targets and the objects containing the
+  BLOCKDATA program units using the BLOCKDATA::&lt;target&gt; declarations. For
+  example, if "foo.exe" is an executable target depending on the objects of the
+  BLOCKDATA program units "blkdata.o" and "fbk.o", you will make the following
+  declarations:</p>
+
+  <pre>
+bld::blockdata::foo.exe  blkdata fbk
+</pre>
+
+  <p>If all your executables are dependent on "blkdata.o" and "fbk.o", you will
+  make the following declarations:</p>
+
+  <pre>
+bld::blockdata  blkdata fbk
+</pre>
+
+  <h3><a name="advanced_library">Creating library archives</a></h3>
+
+  <p>If you are interested in building library archives, the build system allows
+  you to do it in a relatively simple way. For each sub-package in the source
+  tree, there is a target to build a library containing all the objects compiled
+  from the source files (that are not main programs) within the sub-package. If
+  the sub-package contains children sub-packages, the object files of the
+  children will also be included recursively. By default, the library archive is
+  named after the sub-package, in the format "lib&lt;pcks&gt;.a". (For example,
+  the library archive for the package "foo::bar::egg" will be named
+  "libfoo__bar__egg.a" by default.) If you do not like the default name for the
+  sub-package library, you can use the LIB::&lt;pcks&gt; declaration to rename
+  it, as long as the new name does not clash with other targets. For example, to
+  rename "libfoo__bar__egg.a" to "libham.a", you will make the following
+  declaration in your extract configuration file:</p>
+
+  <pre>
+bld::lib::foo::bar::egg  ham
+</pre>
+
+  <p>In addition to sub-package libraries, you can also build a global library
+  archive for the whole source tree. By default, the library is named
+  "libfcm_default.a", but you can rename it using the LIB declaration as above.
+  For example, to rename the library to "libmy-lib.a", you will make the
+  following declaration in your extract configuration file:</p>
+
+  <pre>
+bld::lib  my-lib
+</pre>
+
+  <p>When a library archive is created successfully, the build system will
+  automatically generate the relevant exclude dependency configurations in the
+  "etc/" sub-directory of the build root. You will be able to include these
+  configurations in subsequent builds that utilise the library. The root names
+  of the configuration files match those of the library archives that you can
+  create in the current build, but the extension "*.a" is replaced with "*.cfg".
+  For example, the exclude dependency configuration for "libmy-lib.a"
+  is "libmy-lib.cfg".</p>
+
+  <h3><a name="advanced_pp">Pre-processing</a></h3>
+
+  <p>As most modern compilers can handle pre-processing, the build system
+  leaves pre-processing to the compiler by default. However, it is recognised
+  that there are code written with pre-processor directives that can alter the
+  argument list of procedures and/or their dependencies. If a source file
+  requires pre-processing in such a way, we have to pre-process before running
+  the interface block generator and the dependency scanner. The PP declaration
+  can be used to switch on this pre-processing stage. The pre-processing stage
+  can be switched on globally or for individual sub-packages only. The
+  following is an example, using an extract configuration file:</p>
+
+  <table class="pad" summary="build_example7" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 7 - pre-processing switch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext
+cfg::version       1.0
+
+bld::pp::gen       1                     # line 4
+bld::pp::var::foo  1                     # line 5
+
+bld::tool::cppkeys GOOD WEATHER FORECAST # line 7
+bld::tool::fppkeys FOO BAR EGG HAM       # line 8
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4 to 5: these switches on the pre-processing stage for all
+    sub-packages under "gen" and "var::foo".</li>
+
+    <li>line 7: this declares a list of pre-defined macros "GOOD", "WEATHER"
+    and "FORECAST" for pre-processing all C files.</li>
+
+    <li>line 8: this declares a list of pre-defined macros "FOO", "BAR",
+    "EGG" and "HAM" for pre-processing all Fortran files that require
+    processing.</li>
+  </ul>
+
+  <p>Source files requiring pre-processing may contain "#include" statements to
+  include header files. For including a local file, its name should be embedded
+  within a pair of quotes, i.e. 'file.h' or "file.h". If the header file is
+  embedded within a pair of "&lt;file.h&gt;" angle brackets, the system will
+  assume that the file can be found in a standard location.</p>
+
+  <p>The build system allows header files to be placed anywhere within the
+  declared source tree. The system uses the dependency scanner, as described
+  in the previous sub-section to scan for any header file dependencies. All
+  source files requiring pre-processing and all header files are scanned. Header
+  files that are required are copied to the "inc/" subdirectory of the build
+  root, which is automatically added to the pre-processor search path via the
+  "-I&lt;dir&gt;" option. The build system uses an internal logic similar to
+  <em>make</em> to perform pre-processing. Header files are only copied to the
+  "inc/" sub-directory if they are used in "#include" statements.</p>
+  
+  <p>Unlike <em>make</em>, which only uses the timestamp to determine whether an
+  item is out of date, the internal logic of the build system does this by
+  inspecting the content of the file as well. In an incremental build, the
+  pre-processed file is only updated if its content has changed. This avoids
+  unnecessary updates (and hence unnecessary re-compilation) in an incremental
+  build if the changed section of the code does not affect the output file.</p>
+
+  <p>Pre-processed code generated during the pre-processing stage are sent to
+  the "ppsrc/" sub-directory of the build root. It will have a relative path
+  that reflects the name of the declared sub-package. The pre-processed source
+  file will have the same root name as the original source file. For C files,
+  the same extension ".c" will be used. For Fortran files, the case of the
+  extension will normally be dropped, e.g. from ".F90" to ".f90".</p>
+  
+  <p>Following pre-processing, the system will use the pre-processed source
+  file as if it is the original source file. The interface generator will
+  generate the interface file using the pre-processed file, the dependency
+  scanner will scan the pre-processed file for dependencies, and the compiler
+  will compile the pre-processed source.</p>
+
+  <p>The TOOL::CPPKEYS and TOOL::FPPKEYS declarations are used to pre-define
+  macros in the C and Fortran pre-processor respectively. This is implemented
+  by the build system using the pre-processor "-D" option on each word in the
+  list. The use of these declarations are not confined to the pre-process
+  stage. If any source files requiring pre-processing are left to the compiler,
+  the declarations will be used to set up the commands for compiling these
+  source files.</p>
+
+  <p>The TOOL::CPPKEYS and TOOL::FPPKEYS declarations normally applies
+  globally, but like any other TOOL declarations, they can be suffixed with
+  sub-package names. In such cases, the declarations will apply only to the
+  specified sub-packages.</p>
+
+  <table class="pad" summary="note - changing pre-processor flags" border="1"
+  width="100%">
+    <tr>
+      <th>Note - changing pre-processor flags</th>
+    </tr>
+
+    <tr>
+      <td>
+        As for compiler flags, the build system detects changes in
+        pre-processor flags (TOOL::CPPFLAGS and TOOL::FPPFLAGS) and macro
+        definitions (TOOL::CPPKEYS and TOOL::FPPKEYS). If the pre-processor
+        flags or the macro definitions have changed in an incremental build,
+        the system will re-do all the necessary pre-processing. The following
+        hierarchy is followed:
+
+        <ul>
+          <li>If the pre-processor flags or macro definitions for a particular
+          source file change, only that source file will be pre-processed
+          again.</li>
+
+          <li>If the pre-processor flags or macro definitions for a particular
+          sub-package change, only source files within that sub-package will
+          be pre-processed again.</li>
+
+          <li>If the global pre-processor flags or macro definitions change,
+          all source files will be pre-processed again.</li>
+
+          <li>If the pre-processor command changes, all source files are
+          pre-processed again.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="advanced_file-type">File type</a></h3>
+
+  <p>The build system only knows what to do with an input source file if it
+  knows what type of file it is. The type of a source file is normally
+  determined automatically using one of the following three methods (in
+  order):</p>
+
+  <ol>
+    <li>If the file is named with an extension, its extension will be matched
+    against a set of registered file extensions. If a match is found, the file
+    type will be set according to the register.</li>
+
+    <li>If a file does not have an extension or does not match with a
+    registered extension, its name is compared with a set of pre-defined
+    patterns. If a match is found, the file type will be set according to the
+    file type associated with the pattern.</li>
+
+    <li>If the above two methods failed and if the file is a text file, the
+    system will attempt to read the first line of the file. If the first line
+    begins with a "#!" pattern, the line will be compared with a set of
+    pre-defined patterns. If a match is found, the file type will be set
+    according to the file type associated with the pattern.</li>
+  </ol>
+
+  <p>In addition to the above, if a file is a Fortran or C source file, the
+  system will attempt to open the source file to determine whether it contains
+  a main program, module (Fortran only) or just standalone procedures. All
+  these information will be used later by the build system to process the
+  source file.</p>
+
+  <p>The build system registers a file type with a set of type flags
+  delimited by the double colons "::". For example, a Fortran 9X source file is
+  registered as "FORTRAN::FORTRAN9X::SOURCE". (Please note that the
+  order of the type flags in the list is insignificant. For example,
+  "FORTRAN::SOURCE" is the same as "SOURCE::FORTRAN".) For a list of all the
+  type flags used by the build system, please see the <a
+  href="annex_bld_cfg.html#infile-ext-types">input file extension type
+  flags table</a> in the <a href="annex_bld_cfg.html">
+  Annex: Declarations in FCM build configuration file</a>.</p>
+  
+  <p>The following is a list of default input file extensions and their
+  associated types:</p>
+
+  <table class="pad" summary="list of known file extensions" border="1">
+    <tr>
+      <th>Extensions</th>
+
+      <th>Type flags</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td class="mono">.f .for .ftn .f77</td>
+
+      <td class="mono">FORTRAN::SOURCE</td>
+
+      <td>Fortran 77 source file (assumed to be fixed format)</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.f90 .f95</td>
+
+      <td class="mono">FORTRAN::FORTRAN9X::SOURCE</td>
+
+      <td>Fortran 9X source file (assumed to be free format)</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.F .FOR .FTN .F77</td>
+
+      <td class="mono">FPP::SOURCE</td>
+
+      <td>Fortran 77 source file (assumed to be fixed format) that requires
+      pre-processing</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.F90 .F95</td>
+
+      <td class="mono">FPP::FPP9X::SOURCE</td>
+
+      <td>Fortran 9X source file (assumed to be free format) that requires
+      pre-processing</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.c</td>
+
+      <td class="mono">C::SOURCE</td>
+
+      <td>C source file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.h .h90</td>
+
+      <td class="mono">CPP::INCLUDE</td>
+
+      <td>Pre-processor "#include" header file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.o .obj</td>
+
+      <td class="mono">BINARY::OBJ</td>
+
+      <td>Compiled binary object</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.exe</td>
+
+      <td class="mono">BINARY::EXE</td>
+
+      <td>Binary executable</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.a</td>
+
+      <td class="mono">BINARY::LIB</td>
+
+      <td>Binary object library archive</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.sh .ksh .bash .csh</td>
+
+      <td class="mono">SHELL::SCRIPT</td>
+
+      <td>Unix shell script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.pl .pm</td>
+
+      <td class="mono">PERL::SCRIPT</td>
+
+      <td>Perl script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.py</td>
+
+      <td class="mono">PYTHON::SCRIPT</td>
+
+      <td>Python script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.tcl</td>
+
+      <td class="mono">TCL::SCRIPT</td>
+
+      <td>Tcl/Tk script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.pro</td>
+
+      <td class="mono">PVWAVE::SCRIPT</td>
+
+      <td>PVWave program</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.cfg</td>
+
+      <td class="mono">CFGFILE</td>
+
+      <td>FCM configuration file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.inc</td>
+
+      <td class="mono">FORTRAN::FORTRAN9X::INCLUDE</td>
+
+      <td>Fortran INCLUDE file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.interface</td>
+
+      <td class="mono">FORTRAN::FORTRAN9X::INCLUDE::INTERFACE</td>
+
+      <td>Fortran 9X INCLUDE interface block file</td>
+    </tr>
+  </table>
+
+  <p>N.B. The extension must be unique. For example, the system does not
+  support the use of ".inc" files for both "#include" and Fortran
+  "INCLUDE".</p>
+
+  <p>The following is a list of supported file name patterns and their
+  associated types:</p>
+
+  <table class="pad" summary="list of known file name patterns" border="1">
+    <tr>
+      <th>Patterns</th>
+
+      <th>Type flags</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td class="mono">*Scr_* *Comp_* *IF_* *Suite_* *Interface_*</td>
+
+      <td class="mono">SHELL::SCRIPT</td>
+
+      <td>Unix shell script, GEN-based project naming conventions</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*List_*</td>
+
+      <td class="mono">SHELL::SCRIPT::GENLIST</td>
+
+      <td>Unix shell script, GEN "list" file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*Sql_*</td>
+
+      <td class="mono">SCRIPT::SQL</td>
+
+      <td>SQL script, GEN-based project naming conventions</td>
+    </tr>
+  </table>
+
+  <p>The following is a list of supported "#!" line patterns and their
+  associated types:</p>
+
+  <table class="pad" summary="list of known file name patterns" border="1">
+    <tr>
+      <th>Patterns</th>
+
+      <th>Type flags</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td class="mono">*sh* *ksh* *bash* *csh*</td>
+
+      <td class="mono">SHELL::SCRIPT</td>
+
+      <td>Unix shell script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*perl*</td>
+
+      <td class="mono">PERL::SCRIPT</td>
+
+      <td>Perl script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*python*</td>
+
+      <td class="mono">PYTHON::SCRIPT</td>
+
+      <td>Python script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*tclsh* *wish*</td>
+
+      <td class="mono">TCL::SCRIPT</td>
+
+      <td>Tcl/Tk script</td>
+    </tr>
+  </table>
+
+  <p>The build system allows you to add or modify the register for input file
+  extensions and their associated type using the INFILE_EXT::&lt;ext&gt;
+  declaration, where &lt;ext&gt; is a file name extension without the leading
+  dot. For example, in an extract configuration file, you may have:</p>
+
+  <table class="pad" summary="build_example8" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 8 - add/modify input file extension
+      types</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type             ext
+cfg::version          1.0
+
+bld::infile_ext::foo  CPP::INCLUDE                # line 4
+bld::infile_ext::bar  FORTRAN::FORTRAN9X::INCLUDE # line 5
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line registers the extension ".foo" to be of type
+    "CPP::INCLUDE". This means that any input files with ".foo"
+    extension will be treated as if they are pre-processor header files.</li>
+
+    <li>line 5: this line registers the extension ".bar" to be of type
+    "FORTRAN::FORTRAN9X::INCLUDE". This means that any input file
+    with ".bar" extension will be treated as if they are Fortran 9X INCLUDE
+    files.</li>
+  </ul>
+
+  <p>The INFILE_EXT declarations deal with extensions of input files. There is
+  also a OUTFILE_EXT::&lt;type&gt; declaration that deals with extensions of
+  output files. The declaration is opposite that of INFILE_EXT. The file
+  &lt;type&gt; is now declared with the label, and the extension is declared
+  as the value. It is worth noting that OUTFILE_EXT declarations use very
+  different syntax for &lt;type&gt;, and the declared extension must include
+  the leading dot. For a list of output types used by the build system,
+  please see the <a href="annex_bld_cfg.html#outfile-ext-types">output file
+  extension types table</a> in the <a href="annex_bld_cfg.html">
+  Annex: Declarations in FCM build configuration file</a>.
+  An example is given below:</p>
+
+  <table class="pad" summary="build_example9" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 9 - modify output file extensions</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type                   ext
+cfg::version                1.0
+
+bld::outfile_ext::mk        .rule  # line 4
+bld::outfile_ext::mod       .MOD   # line 5
+bld::outfile_ext::interface .intfb # line 6
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line modifies the extension of output <em>Makefile</em>
+    fragments, output of the dependency scanner, from the default ".mk" to
+    ".rule".</li>
+
+    <li>line 5: this line modifies the extension of compiled Fortran 9X module
+    information files from the default ".mod" to ".MOD".</li>
+
+    <li>line 6: this line modifies the extension of INCLUDE Fortran 9X
+    interface block files from the default ".interface" to ".intfb".</li>
+  </ul>
+
+  <p>N.B. If you have made changes to the file type registers, whether it is
+  for input files or output files, it is always worth re-building your code in
+  full-build mode to avoid unexpected behaviour.</p>
+
+  <h3><a name="advanced_incremental">Incremental build based on a pre-compiled
+  build</a></h3>
+
+  <p>As you can perform incremental extractions against pre-extracted source
+  code, you can perform incremental builds against pre-compiled builds. The
+  very same USE statement can be used to declare a build, which the current
+  build will depend on. The only difference is that the declared location must
+  contain a valid build configuration file. In fact, if you use the extract
+  system to obtain your build configuration file, any USE declarations in the
+  extract configuration file will also be USE declarations in the output
+  build configuration file.</p>
+
+  <p>By declaring a USE statement, the current build automatically inherits
+  settings from the pre-compiled build. The following points are worth
+  noting:</p>
+
+  <ul>
+    <li>
+      Build targets are not normally inherited. However, you can switch on
+      inheritance of build targets using an INHERIT::TARGET declaration, such
+      as:
+      <pre>
+inherit::target  1
+</pre>
+    </li>
+
+    <li> The build root directory and its sub-directories of the pre-compiled
+    build are placed into the search paths. For example, if we have a
+    pre-compiled build at "/path/to/pre/compiled", and it is used by an
+    incremental build at "/path/to/incremental", the search path of executable
+    files will become "/path/to/incremental/bin:/path/to/pre/compiled/bin", so
+    that the "bin/" sub-directory of the incremental build is searched before
+    the "bin/" sub-directory of the pre-compiled build. If two or more USE
+    statements are declared, the USE statement declared last will have higher
+    priority. For example, if the current build is "C", and it USEs build "A"
+    before build "B", the search path will be "C:B:A".</li>
+
+    <li>
+      Sub-package source directories are inherited by default. If a source
+      directory is declared in the current build that has the same sub-package
+      name as a source directory of the pre-compiled build, any source files in
+      the source directory of the current build will override those in the
+      source directory of the pre-compiled build. Any source files missing
+      from the source directory of the current build will be taken from the
+      source directory of the pre-compiled build.
+
+      <p>For example, if build "B" USEs build "A", and both of them have a
+      sub-package called "basic::element". In build "A", the sub-package
+      contains the source files "earth.f90", "wind.f90" and "water.f90". In
+      build "B", the sub-package contains "earth.f90" and "fire.f90". When the
+      system searches for source files, it will look for source files in "B"
+      before "A". Therefore, the source file "earth.f90" in "B" will override
+      that of "A", and the files used for the build will be "earth.f90" and
+      "fire.f90" from "B" and "wind.f90" and "water.f90" from "A".</p>
+      
+      <p>You can switch off inheritance of source directories using an
+      INHERIT::SRC declaration.  This declaration can be suffixed with the
+      name of a sub-package. In such case, the declaration applies only to the
+      inheritance of the sub-package. Otherwise, it applies to all source
+      directories. For example:</p>
+
+      <pre>
+# Switch off inheritance of source directories in the "gen" sub-package
+inherit::src::gen  0
+</pre>
+    </li>
+
+    <li>All build tools are automatically inherited. If the same tool is
+    declared in the current incremental build, it overrides the declaration in
+    the pre-compiled build.</li>
+
+    <li>"PP", "EXCL_DEP", "INFILE_EXT" and "OUTFILE_EXT" declarations are
+    inherited using a similar mechanism as build tool declarations.</li>
+  </ul>
+
+  <p>As an example, suppose we have already performed an extract and build based
+  on the configuration in example 2, we can set up an extract configuration
+  file as follows:</p>
+
+  <table class="pad" summary="build_example10" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 10 - "USE" a pre-compiled
+      build</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type            ext
+cfg::version         1.0
+
+use                  $HOME/example               # line 4
+
+dest::rootdir        $HOME/example9              # line 6
+
+bld::inherit::target 1                           # line 8 
+bld::target          ham.exe egg.exe             # line 9
+
+bld::tool::fflags    -O2 -w                      # line 11
+bld::tool::cflags    -O2                         # line 12
+
+# ... and other declarations for repositories and source directories ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line declares a previous extraction at
+    "$HOME/example" which the current extraction will be based on. The
+    same line will be written to the output build configuration file at
+    "$HOME/example9/cfg/bld.cfg". The subsequent build will then be
+    based on the build at "$HOME/example".</li>
+
+    <li>line 6: this declares the destination root directory of the current
+    extraction, which will become the root directory of the current build.
+    Search paths of the build sub-directories will be set automatically. For
+    example, the search path for executable files created by the current build
+    will be "$HOME/example9/bin:$HOME/example/bin".</li>
+
+    <li>line 8: this line switches on inheritance of build targets. The build
+    targets in example 1, i.e. "foo.exe" and "bar.exe" will be built as part
+    of the current build.</li>
+
+    <li>line 9: this declares two new build targets "ham.exe" and "egg.exe" to
+    be added to the inherited ones. The default build targets of the current
+    build will now be "foo.exe", "bar.exe", "ham.exe" and "egg.exe".</li>
+
+    <li>line 11-12: these lines modify options used by the Fortran and the C
+    compilers, overriding those inherited from example 1.</li>
+  </ul>
+
+  <h3><a name="advanced_pckcfg">Using a package configuration file</a></h3>
+
+  <p>It is recognised that the build system needs to be able to work with code
+  that is not designed to work with the automatic dependency scanner. There are
+  various techniques which can be used to achieve this, some of which are
+  already described. However, it should be noted that these techniques are
+  simply designed to allow code to be successfully built. They will not
+  necessarily result in a good environment for developing such code, since for
+  example, dependencies need to be manually maintained by the developer.</p>
+
+  <p>The final technique is the package configuration file. The package
+  configuration file is a special source file to inform the build system about
+  any additional information of the source files in the package. It must be a
+  file called "@PACKAGE.cfg" in a source directory. For a full list of available
+  declarations in the package configuration file, please refer to the <a
+  href="annex_pck_cfg.html">Annex: Declarations in FCM build package
+  configuration file</a>.</p>
+
+  <p>The following is an example of how a package configuration file can be
+  used to provide additional information to the build system for a source
+  file:</p>
+
+  <table class="pad" summary="package_example1" border="1" width="100%">
+    <tr>
+      <th>Package configuration example 1 - dependency information for a
+      source file</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+type::MyFortranProg.f90    FORTRAN::FORTRAN9X::SOURCE::PROGRAM # line 1
+scan::MyFortranProg.f90    0                                   # line 2
+intname::MyFortranProg.f90 myprog                              # line 3
+target::MyFortranProg.f90  hello_world                         # line 4
+
+dep::MyFortranProg.f90     USE::YourFortranMod                 # line 6
+dep::MyFortranProg.f90     INTERFACE::HerFortran.interface     # line 7
+dep::MyFortranProg.f90     INC::HisFortranInc.inc              # line 8
+dep::MyFortranProg.f90     H::TheirHeader.h                    # line 9
+dep::MyFortranProg.f90     OBJ::ItsObject.o                    # line 10
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 1: this declares a source file "MyFortranProg.f90" in the package
+    of type "FORTRAN::FORTRAN9X::SOURCE::PROGRAM", i.e. a Fortran 9X source
+    file containing a main program. The list of type flags used in the value
+    is the same list of type flags used in the INFILE_EXT declaration of a
+    build configuration file. For a list of  these flags, please see the <a
+    href="annex_bld_cfg.html#infile-ext-types">Input file extension type flags
+    table</a> in the <a href="annex_bld_cfg.html">
+    Annex: Declarations in FCM build configuration file</a>.</li>
+
+    <li>line 2: this declaration switches off (0) automatic dependency scan for
+    this source file. If this switch is not declared, it is automatically set
+    to on (1) for a source file. If the switch is on, the dependency scanner
+    will scan the source file for further dependencies. Otherwise, dependency
+    information for this source file will only be read from this configuration
+    file.</li>
+
+    <li>line 3: this declares the internal name of the source file to be
+    "myprog". If this is not set and the dependency scanner is switched on,
+    the internal name of the source file will be taken from the first program
+    unit of the source file. The resulting object file will be named after
+    the internal name, plus the ".o" extension. If internal name is not set
+    and cannot be determined automatically, the default is to use the root
+    name of the source file to name the object file.</li>
+
+    <li>line 4: this declares the executable target name of a main program.
+    This declaration is only used when the source file contains a main
+    program. If the target name is not set, the name of the executable will be
+    named after the root name of the source file plus the ".exe" extension. In
+    the above example, the executable will be named "hello_world".</li>
+
+    <li>line 6-10: these lines declare the dependencies of the source file.
+    The syntax of the values are exactly the same as those used in the
+    EXCL_DEP declarations in the build configuration file. For a list of these
+    flags, please see the <a
+    href="annex_bld_cfg.html#dependency-types">dependency types table</a> in
+    the <a href="annex_bld_cfg.html">Annex:
+    Declarations in FCM build configuration file</a>. In the example,
+    the source file is dependent on a Fortran module called "YourFortranMod",
+    a Fortran INCLUDE interface block file called "HerFortran.interface", a
+    Fortran INCLUDE file called "HistFortran.inc, a pre-processor header file
+    called "TheirHeader.h", and an object file called "ItsObject.o".</li>
+  </ul>
+
+  <h3><a name="advanced_data">Building data files</a></h3>
+
+  <p>While the usual targets to be built are the executables associated with
+  source files containing main programs, libraries or scripts, the build system
+  also allows you to build "data" files. All files with no registered type are
+  considered to be "data" files.  For each sub-package, there is an automatic
+  target for copying all "data" files to the "etc/" sub-directory of the build
+  root. The name of the target has the form "&lt;pcks&gt;.etc", where
+  &lt;pcks&gt; is the name of the sub-package (with package names delimited by
+  the double underscore "__"). For example, the target name for sub-package
+  "foo::bar" is "foo__bar.etc". This target is particularly useful for copying,
+  say, all namelists in a sub-package to the "etc/" sub-directory of the build
+  root.</p>
+
+  <p>At the end of a successful build, if the "etc/" sub-directory is not empty,
+  the "fcm_env.ksh" script will export the environment variable FCM_ETCDIR to
+  point to the "etc/" sub-directory. You should be able to use this environment
+  variable to locate your data files.</p>
+
+  <h2><a name="verbose">Diagnostic verbose level</a></h2>
+
+  <p>The amount of diagnostic messages generated by the build system is
+  normally set to a level suitable for normal everyday operation. This is the
+  default diagnostic verbose level 1. If you want a minimum amount of
+  diagnostic messages, you should set the verbose level to 0. If you want more
+  diagnostic messages, you can set the verbose level to 2 or 3. You can modify
+  the verbose level in two ways. The first way is to set the environment
+  variable FCM_VERBOSE to the desired verbose level. The second way is to
+  invoke the build system with the "-v &lt;level&gt;" option. (If set, the
+  command line option overrides the environment variable.)</p>
+
+  <p>The following is a list of diagnostic output at each verbose level:</p>
+
+  <table class="pad" summary="List of diagnostic verbose output" border="1">
+    <tr>
+      <th>Verbose level</th>
+
+      <th>Possible output</th>
+    </tr>
+
+    <tr>
+      <th>0</th>
+
+      <td>
+        <ul>
+          <li>Report the time taken at the end of each stage of the build
+          process.</li>
+
+          <li>Run the <em>make</em> command in silent mode.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>1</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 0.</li>
+
+          <li>Report the name of the build configuration file.</li>
+
+          <li>Report date/time at the beginning of each stage of the build
+          process.</li>
+
+          <li>Report removed directories.</li>
+
+          <li>Report number of pre-processed files.</li>
+
+          <li>Report number of generated F9X interface files.</li>
+
+          <li>Report number of sub-packages that have source files scanned
+          for dependencies.</li>
+
+          <li>Report number of generated/updated sub-package <em>make</em>
+          rule fragment files.</li>
+
+          <li>Report name of updated <em>Makefile</em>.</li>
+
+          <li>Print compiler/linker commands.</li>
+
+          <li>Report total time.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>2</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 1.</li>
+
+          <li>For incremental build in archive mode, report the commands used
+          to extract the archives.</li>
+
+          <li>Report creation and removal of directories.</li>
+
+          <li>Report pre-processor commands.</li>
+
+          <li>Report number of files scanned for dependency in each
+          sub-package.</li>
+
+          <li>Report names of generated/updated sub-package <em>make</em> rule
+          fragment files.</li>
+
+          <li>Print compiler/linker commands with timestamps.</li>
+
+          <li>Print usage of the runtime environment set up script.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>3</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 2.</li>
+
+          <li>Report update of dummy files.</li>
+
+          <li>Report all shell commands.</li>
+
+          <li>Report pre-processor commands with timestamps.</li>
+
+          <li>If F9X interface is generated by <em>f90aib</em>, print commands
+          with timestamps.</li>
+
+          <li>If F9X interface is generated by ECMWF code, report start
+          date/time and time taken to generate each interface file.</li>
+
+          <li>Report start date/time and time taken of dependency scan for each
+          source file.</li>
+
+          <li>Run <em>make</em> on normal mode (as opposed to silent mode).</li>
+
+          <li>Report start date/time and time taken of <em>make</em>
+          commands.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="overview">Overview of the build process</a></h2>
+
+  <p>The FCM build process can be summarised in five stages. Here is a summary
+  of what is done in each stage:</p>
+
+  <ol>
+    <li><strong>Setup</strong>: in this first stage, the build system reads
+    and processes the configuration file. The source sub-directory is searched
+    recursively for source directories. For full builds, it ensures that the
+    sub-directories created by the build system are removed. For inherited
+    (i.e. pre-compiled) builds, it sets up the search paths for the
+    sub-directories, inherits the targets, source directories, etc. For
+    incremental builds, the system also works out whether the current list of
+    build tools have changed.</li>
+
+    <li><strong>Pre-process</strong>: if any files in any source directories
+    require pre-processing, they will be pre-processed at this stage. The
+    resulting pre-processed source files will be sent to the "ppsrc/"
+    sub-directory of the build root.</li>
+
+    <li><strong>Generate dependency</strong>: the system scans source files of
+    registered types for dependency information. For an incremental build, the
+    information is only updated if a source file is changed. The system then
+    uses the information to write a <em>Makefile</em> for the main build. The
+    <em>Makefile</em> and any of its included fragments are generated in the
+    "bld/" sub-directory of the build root.</li>
+
+    <li><strong>Generate interface</strong>: if there are Fortran 9X source
+    files with standalone subroutines and functions, the build system
+    generates interface blocks for them. The result of which will be written
+    to the interface files in the "inc/" sub-directory of the build root.</li>
+
+    <li>
+      <strong>Make</strong>: the system invokes <em>make</em> on the
+      <em>Makefile</em> generated in the previous stage to perform the main
+      build. Following a build, the "root" directory of the build may contain
+      the following sub-directories (empty ones are removed automatically at the
+      end of the build process):
+
+      <table summary="list of build sub-directories" border="1" width="100%">
+        <tr>
+          <th>Sub-directory</th>
+
+          <th>Contents</th>
+
+          <th>Note</th>
+        </tr>
+
+        <tr>
+          <th>.cache/</th>
+
+          <td>&lt;cache files&gt;</td>
+
+          <td>used internally by FCM</td>
+        </tr>
+
+        <tr>
+          <th>bin/</th>
+
+          <td>&lt;executable binaries and scripts&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>bld/</th>
+
+          <td>Makefile and &lt;Makefile include files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>cfg/</th>
+
+          <td>bld.cfg</td>
+
+          <td>this directory is not changed by the build system</td>
+        </tr>
+
+        <tr>
+          <th>done/</th>
+
+          <td>&lt;dummy "done" files&gt;</td>
+
+          <td>used internally by the Makefile generated by FCM</td>
+        </tr>
+
+        <tr>
+          <th>etc/</th>
+
+          <td>&lt;miscellaneous data files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>flags/</th>
+
+          <td>&lt;dummy "flags" files&gt;</td>
+
+          <td>used internally by the Makefile generated by FCM</td>
+        </tr>
+
+        <tr>
+          <th>inc/</th>
+
+          <td>&lt;include files&gt;</td>
+
+          <td>such as *.h, *.inc, *.interface and *.mod files</td>
+        </tr>
+
+        <tr>
+          <th>lib/</th>
+
+          <td>&lt;object library archives&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>obj/</th>
+
+          <td>&lt;compiled object files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>ppsrc/</th>
+
+          <td>&lt;source directories with pre-processed files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+
+        <tr>
+          <th>src/</th>
+
+          <td>&lt;source directories&gt;</td>
+
+          <td>this directory is not changed by the build system</td>
+        </tr>
+        <tr>
+          <th>tmp/</th>
+
+          <td>&lt;temporary objects and binaries&gt;</td>
+
+          <td>files generated by the compiler/linker may be left here</td>
+        </tr>
+      </table>
+    </li>
+  </ol>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/code_management.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/code_management.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/code_management.html	(revision 329)
@@ -0,0 +1,1214 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Code Management</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Code Management">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Code Management System
+  </address>
+
+  <h1>Code Management System</h1>
+
+  <h2><a name="svn">Using Subversion</a></h2>
+
+  <p>One of the key strengths of Subversion
+  is its documentation. <a href="http://svnbook.red-bean.com/en/1.2">Version
+  Control with Subversion</a> (which we'll just refer to as the "Subversion
+  book" from now on) is an excellent book which explains in detail how to use
+  Subversion and also provides a good introduction to all the basic concepts of
+  version control. Rather than trying to write our own explanations (and not
+  doing as good a job) we will simply refer you to the Subversion book, where
+  appropriate, for the relevant information.</p>
+
+  <p>In general, the approach taken in this section is to make sure that you
+  first understand how to perform a particular action using the Subversion
+  tools and then describe how this differs using FCM.</p>
+
+  <h3><a name="svn_concepts">Basic Concepts</a></h3>
+
+  <p>In order to use FCM you need to have a basic understanding of version
+  control. If you're not already familiar with Subversion or CVS then please
+  read the chapter <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.basic.html">Basic Concepts</a> from
+  the Subversion book. In particular, make sure that you understand:</p>
+
+  <ul>
+    <li>The <em>Copy-Modify-Merge</em> approach to file sharing.</li>
+
+    <li>Global Revision Numbers.</li>
+  </ul>
+
+  <p>Note that this chapter states that <em>"working copies do not always
+  correspond to any single revision in the repository"</em>. However, the FCM
+  working practises do not encourage this and the wrapper scripts provided by
+  FCM should ensure that your working copy (a local copy of the repository's
+  files and directories where you can prepare changes) always corresponds to
+  exactly one revision.</p>
+
+  <p>CVS users should already be familiar with all the basic concepts. This is
+  not surprising since Subversion was designed as a replacement for CVS and it
+  uses the same development model. However, there are some important
+  differences which may confuse those more familiar with CVS. Fortunately,
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.forcvs.html">Appendix A</a> of
+  the Subversion book is specifically written for those moving from CVS to
+  Subversion and you should read this if you are a CVS user.</p>
+
+  <h3><a name="svn_basic">Basic Command Line Usage</a></h3>
+
+  <p>Before we discuss the FCM system you need to have a good understanding of
+  how to perform most of the normal day-to-day tasks using Subversion.
+  Therefore, unless you are already familiar with Subversion, please read the
+  chapter <a href="http://svnbook.red-bean.com/en/1.2/svn.tour.html">Guided
+  Tour</a> from the Subversion book.</p>
+
+  <p>So, now you have an understanding of how to do basic tasks using
+  Subversion (you did read the <em>Guided Tour</em> didn't you?), how is using
+  FCM different? Well, the key thing to remember is that, instead of using the
+  command <tt>svn</tt> you need to use the command <tt>fcm</tt>. The advantages
+  of this are as follows:</p>
+
+  <ul>
+    <li><tt>fcm</tt> implements all of the commands that <tt>svn</tt> does
+    (including all the command abbreviations).</li>
+
+    <li>In some cases <tt>fcm</tt> does very little and basically passes on the
+    command to <tt>svn</tt>.</li>
+
+    <li>In other cases <tt>fcm</tt> has a lot of additional functionality
+    compared with the equivalent <tt>svn</tt> command.</li>
+
+    <li><tt>fcm</tt> also implements several commands not provided by
+    <tt>svn</tt>.</li>
+
+    <li><tt>fcm</tt> provides support for repository keywords and revision
+    keywords.</li>
+
+    <li>Most of the additional features and commands are discussed later in
+    this section or in the following sections.</li>
+  </ul>
+
+  <p>Full details of all the <tt>fcm</tt> commands available are provided in
+  the <a href="command_ref.html">FCM Command Reference</a> section.</p>
+
+  <h4><a name="svn_basic_keywords">Repository &amp; Revision Keywords</a></h4>
+
+  <p>Repository keywords can be used to specify URLs in <tt>fcm</tt> commands.
+  The syntax is <tt>fcm:&lt;keyword&gt;</tt>. Keywords can be defined globally
+  (see the file <a href=
+  "http://www-nwp/~fcm/FCM/src/etc/fcm.cfg"><tt>../etc/fcm.cfg</tt></a>
+  where-ever the <tt>fcm</tt> command has been installed) or individually in a
+  user configuration file (<tt>$HOME/.fcm</tt>). See the <a href=
+  "command_ref.html#fcm_config">FCM Command Reference</a> for further details
+  about configuration files.</p>
+
+  <p>For example, if you define a keyword in your configuration file as
+  follows:</p>
+  <pre>
+set::repos::fcm_tr      svn://fcm1/FCM_svn/trunk
+</pre>
+
+  <p>then the following commands are equivalent:<br>
+  <tt>fcm ls svn://fcm1/FCM_svn/trunk</tt><br>
+  <tt>fcm ls fcm:fcm_tr</tt></p>
+
+  <p>Using repository keywords has two advantages.</p>
+
+  <ul>
+    <li>They are shorter and easier to remember.</li>
+
+    <li>If the repository needs to be moved then only the keyword definitions
+    need to be updated (although any working copies you have will still need to
+    be <em>relocated</em> by issuing a <a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.switch.html"><tt>fcm
+    switch --relocate</tt></a> command).</li>
+  </ul>
+
+  <p>In a similar way, revision keywords can be used to specify revision
+  numbers in <tt>fcm</tt> commands. The keyword can be used anywhere a revision
+  number can be used. Each keyword is associated with a repository keyword and
+  can only be used when referring to that repository.</p>
+
+  <p>For example, if you define a keyword in your configuration file as
+  follows:</p>
+  <pre>
+set::revision::fcm::vn1.0  112
+</pre>
+
+  <p>then the following commands are equivalent:<br>
+  <tt>fcm log -r 112 svn://fcm1/FCM_svn/trunk</tt><br>
+  <tt>fcm log -r vn1.0 fcm:fcm_tr</tt></p>
+
+  <h4><a name="svn_basic_diff">Examining Changes</a></h4>
+
+  <p>Code differences can be displayed graphically using <em>xxdiff</em> by
+  using the <tt>--graphical</tt> (or <tt>-g</tt>) option to <tt>fcm diff</tt>.
+  This option can be used in combination with any other options which are
+  accepted by <tt>svn diff</tt>.</p>
+
+  <p>An example display from xxdiff is shown below.</p>
+
+  <p class="image"><img src="xxdiff1.png" alt="xxdiff 2-way display"></p>
+
+  <p align="center"><em>xxdiff</em> 2-way display</p>
+
+  <p>Points to note:</p>
+
+  <ul>
+    <li>By default <em>xxdiff</em> is configured to show horizontal
+    differences. This means that the parts of the line which have changed are
+    highlighted (e.g. the text "useful" is highlighted in the example
+    above).</li>
+
+    <li>The number shown to the right of each file name shows the current line
+    number. The number on the far right is the number of differences found (2
+    in the example above).</li>
+
+    <li>You may find the following keyboard shortcuts useful.
+
+      <ul>
+        <li><em>N</em> - move to the next difference</li>
+
+        <li><em>P</em> - move to the previous difference</li>
+
+        <li><em>Ctrl-Q</em> - exit</li>
+      </ul>
+    </li>
+  </ul>
+
+  <h4><a name="svn_basic_conflicts">Resolving Conflicts</a></h4>
+
+  <p>Your working copy may contain files <em>in conflict</em> as a result of an
+  update or a merge (covered later). Conflicts arise from the situation where
+  two changes being applied to a file <em>overlap</em>. For conflicts in text
+  files, the command <tt>fcm conflicts</tt> can be used to help resolve them.
+  (A discussion on binary files is given in the section
+  <a href="working_practices.html#binary">Working with Binary Files</a> later in
+  this document.) The <tt>fcm conflicts</tt> command calls <em>xxdiff</em> which
+  then displays a 3-way diff for each of the files in conflict.</p>
+
+  <p class="image"><img src="xxdiff2.png" alt="xxdiff 3-way display"></p>
+
+  <p align="center"><em>xxdiff</em> 3-way display</p>
+
+  <p>Points to note:</p>
+
+  <ul>
+    <li>The file in the middle is the common ancestor from the merge. The file
+    on the left is your original file and the file on the right is the file
+    containing the changes which you are merging in.</li>
+
+    <li><em>xxdiff</em> is configured to automatically select regions that
+    would end up being selected by an automatic merge (e.g. there are only
+    changes in one of the files). Any difference "hunks" which cannot be
+    resolved automatically are left "unselected".</li>
+
+    <li>Before you can save a merged version you need to go through each
+    unselected difference hunk and decide which text you wish to use.
+
+      <ul>
+        <li>Selecting a diff hunk can be carried out by clicking on it with the
+        left mouse button (or refer to the keyboard shortcuts shown under the
+        <em>Region</em> menu). The colours update to display which side is
+        selected for output. You can select individual lines with the middle
+        mouse button.</li>
+
+        <li>If you want to select more than one side, you have to invoke the
+        <em>Region-&gt;Split/swap/join</em> command (keyboard shortcut:
+        <em>S</em>). This will split the current diff hunk so you can select
+        the pieces you want from both sides. Further invocations of this
+        command will cause swapping of the regions, looping through all the
+        different ordering possibilities, and finally joining the regions again
+        (preserving selections where it is possible).</li>
+      </ul>
+    </li>
+
+    <li>The number on the far right is the number of unselected difference
+    hunks (1 in the example above). Once this number is 0 then you are ready to
+    save the merged file.</li>
+
+    <li>If you want to see how the merged file will look with the current
+    selections then select <em>Windows-&gt;Toggle Merged View</em> (keyboard
+    shortcut: <em>Alt+Y</em>). An extra window then appears showing the merged
+    output that updates interactively as you make selections.</li>
+
+    <li>You may find the following keyboard shortcuts useful.
+
+      <ul>
+        <li><em>B</em> - move to the next unselected hunk</li>
+
+        <li><em>O</em> - move to the previous unselected hunk</li>
+      </ul>
+    </li>
+
+    <li>There are several different ways to exit the 3-way diff (available from
+    the <em>file</em> menu):
+
+      <ul>
+        <li>Exit with MERGE (keyboard shortcut: <em>M</em>) - This saves the
+        merge result. If there are any unselected difference hunks remaining
+        then you will be warned and given the option of saving the file with
+        conflict markers.</li>
+
+        <li>Exit with ACCEPT (keyboard shortcut: <em>A</em>) - This saves the
+        file you are merging in (i.e. the middle one) as the merge result
+        (i.e. you have <em>accepted</em> all the changes).</li>
+
+        <li>Exit with REJECT (keyboard shortcut: <em>R</em>) - This saves the
+        original working copy file (i.e. the left one) as the merge result
+        (i.e. you have <em>rejected</em> all the changes).</li>
+      </ul>
+      
+      <p>If you just want to exit without making any decisions you can also just
+      close the window.</p>
+    </li>
+
+    <li>For further details please read the <a href=
+    "http://furius.ca/xxdiff/doc/xxdiff-doc.html"><em>xxdiff</em> users
+    manual</a> (available from the <em>Help</em> menu). In particular, read the
+    section <a href=
+    "http://furius.ca/xxdiff/doc/xxdiff-doc.html#merging-files-and-resolving-conflicts">
+    <em>Merging files and resolving conflicts</em></a>.</li>
+  </ul>
+
+  <p>If you have resolved all the conflicts in a file then you will be prompted
+  on whether to run <tt>svn resolved</tt> on the file to signal that the file
+  is no longer in conflict.</p>
+
+  <table class="pad" summary="fcm conflicts example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm conflicts</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm conflicts
+Conflicts in file: Gen_setup_local1.proc
+You have chosen to ACCEPT all the changes
+Would you like to run "svn resolved"?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Resolved conflicted state of 'Gen_setup_local1.proc'
+Conflicts in file: Gen_setup_remote2.proc
+Merge conflicts were not all resolved
+Conflicts in file: Gen_setup_remote3.proc
+All merge conflicts resolved
+Would you like to run "svn resolved"?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Resolved conflicted state of 'Gen_setup_remote3.proc'
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>It is important to realise that there are some types of merge that
+  <em>xxdiff</em> will not be able to help you with.</p>
+
+  <ul>
+    <li>It you have 2 versions of a file, both with substantial changes to the
+    same piece of code, then the <em>xxdiff</em> display will be extremely
+    colourful and not very helpful.</li>
+
+    <li>In these cases it is often easier to start with one version of the file
+    and manually re-apply the changes from the other version. It might not be
+    obvious how to do this and you may need to speak to the author of the other
+    change to agree how this can be done. Fortunately this situation should be
+    very rare.</li>
+
+    <li>For a more detailed discussion please refer to <a href=
+    "http://software.ericsink.com/scm/scm_file_merge.html">Chapter 3: File
+    Merge</a> in the online book called <a href=
+    "http://software.ericsink.com/scm/source_control.html">Source Control
+    HOWTO</a>.</li>
+  </ul>
+
+  <h4><a name="svn_basic_check">Adding and Removing Files</a></h4>
+
+  <p>If your working copy contains files which are not under version control
+  then you can use the command <tt>fcm add --check</tt> to add them. This will
+  go through each of the files and prompt to see if you wish to put that file
+  under version control using <tt>svn add</tt>. For each file you can enter "y"
+  for yes, "n" for no or "a" to assume yes for all following files.</p>
+
+  <table class="pad" summary="fcm add --check example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm add --check</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm add -c
+?      xxdiff1.png
+?      xxdiff2.png
+?      xxdiff3.png
+?      xxdiff4.png
+Add file 'xxdiff1.png'?
+Enter "y", "n" or "a" (or just press &lt;return&gt; for "n"): y
+A         xxdiff1.png
+Add file 'xxdiff2.png'?
+Enter "y", "n" or "a" (or just press &lt;return&gt; for "n"): n
+Add file 'xxdiff3.png'?
+Enter "y", "n" or "a" (or just press &lt;return&gt; for "n"): a
+A         xxdiff3.png
+A         xxdiff4.png
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Similarly, if your working copy contains files which are missing (i.e. you
+  have deleted them without using <tt>svn delete</tt>) then you can use the
+  command <tt>fcm delete --check</tt> to delete them. This will go through each
+  of the files and prompt to see if you wish to remove that file from version
+  control using <tt>svn delete</tt>.</p>
+
+  <p>As noted in the <a href=
+  "http://subversion.tigris.org/faq.html#wc-change-detection">Subversion
+  FAQ</a>, it can be dangerous using these commands. If you have moved or
+  copied a file then simply adding them would cause the history to be lost.
+  Therefore take care to only use these commands on files which really are new
+  or deleted.</p>
+
+  <h4><a name="svn_basic_commit">Committing Changes</a></h4>
+
+  <p>The command <tt>fcm commit</tt> should be used for committing changes back
+  to the repository. It differs from the <tt>svn commit</tt> command in a
+  number of important ways:</p>
+
+  <ul>
+    <li>Your working copy <em>must</em> be up to date. <tt>fcm commit</tt> will
+    abort if it finds that any files are out of date with respect to the
+    repository. This ensures that your working copy reflects how the repository
+    will be after you have committed your changes.
+
+      <ul>
+        <li>This helps to ensure that any tests you have done prior to
+        committing are valid.</li>
+
+        <li><tt>fcm commit</tt> is not suitable if you need to commit changes
+        from a working copy containing mixed revisions. However, you are very
+        unlikely to need to do this.</li>
+
+        <li>Actually there is a small chance that your working copy might not
+        be up to date when you commit if someone else is committing some
+        changes at the same time. However, this should very seldom happen and,
+        even if it does, the commit would fail if any of the files being
+        changed became out of date (i.e. it is not possible to lose any
+        changes).</li>
+      </ul>
+    </li>
+
+    <li>If it discovers a file named <tt>#commit_message#</tt> in the top level
+    of your working copy it uses this to provide a template commit message
+    (which you can then edit).
+
+      <ul>
+        <li>If you have performed a merge then a message describing the merge
+        will have been added to this file. It is important that you leave this
+        included in the commit message and do not change its format, as it is
+        used by the <tt>fcm branch</tt> command.</li>
+
+        <li>You can, if you wish, add entries to this file as you go along to
+        record what changes you have prepared in your working copy. You can
+        also use the command <tt>fcm commit --dry-run</tt> to allow you to edit
+        the commit message without committing any changes.</li>
+
+        <li><tt>#commit_message#</tt> is ignored by Subversion (so you won't
+        see it show up as an unversioned files when you run <tt>fcm
+        status</tt>).</li>
+      </ul>
+    </li>
+
+    <li>It always operates from the top of your working copy. If you issue the
+    <tt>fcm commit</tt> command from a sub-directory of your working copy then
+    it will automatically work out the top directory and work from there.
+
+      <ul>
+        <li>This ensures that any template commit message gets picked up and
+        that you do not, for example, accidently commit a partial set of
+        changes from a merge.</li>
+      </ul>
+    </li>
+
+    <li>It always commits <em>all</em> the changes in your working copy (it
+    does not accept a list of files to commit).
+
+      <ul>
+        <li>Once again, this avoids any danger of accidently committing a
+        partial set of changes.</li>
+
+        <li>You should only work on one change within a working copy. If you
+        need to prepare another, unrelated change then use a separate working
+        copy.</li>
+      </ul>
+    </li>
+
+    <li>It runs <tt>svn update</tt> after the commit to ensure that your
+    working copy is at the latest revision and to avoid any confusion caused by
+    your working copy containing mixed revisions.</li>
+  </ul>
+
+  <table class="pad" summary="fcm commit example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm commit</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm commit
+Starting editor to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+An example commit.
+--This line, and those below, will be ignored--
+[Project: GEN]
+[Branch : branches/test/frsn/r123_foo_bar]
+[Sub-dir: &lt;top&gt;]
+
+M      src/code/GenMod_Control/GenMod_Control.f90
+M      src/code/GenMod_Control/Gen_SetupControl.f90
+------------------------------------------------------------------------
+Would you like to commit this change?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Sending        src/code/GenMod_Control/GenMod_Control.f90
+Sending        src/code/GenMod_Control/Gen_SetupControl.f90
+Transmitting file data ..
+Committed revision 170.
+Performing update to make sure your working copy is at this new revision ...
+At revision 170.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="svn_branching">Branching &amp; Merging</a></h3>
+
+  <p>Branching is a fundamental concept common to most version control systems.
+  For a good introduction please read the chapter <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.branchmerge.html">Branching &amp;
+  Merging</a> from the Subversion book. Even if you are already familiar with
+  branching using other version control systems you should still read this
+  chapter to see how branching is implemented in Subversion.</p>
+
+  <p>Having read this chapter from the Subversion book you should understand:</p>
+
+  <ul>
+    <li>Why each project directory has sub-directories called <em>trunk</em>,
+    <em>branches</em> and <em>tags</em>. This structure is assumed by
+    <tt>fcm</tt> (Subversion recommends it but doesn't insist on it).</li>
+
+    <li>That when you make a branch you are taking a copy of the entire project
+    file tree. Fortunately, the design of the Subversion repository means that
+    these copies are "cheap" - they are quick to create and take very little
+    space.</li>
+
+    <li>That Subversion doesn't (currently) track merge information for you -
+    this has to be done manually.</li>
+
+    <li>That each revision of your repository can also be thought of as a
+    <em>changeset</em>.</li>
+
+    <li>That once a change is committed to a repository it cannot be removed
+    (only reversed). Therefore you must take care not to committ a sensitive
+    document or a large data file unintentionally.</li>
+  </ul>
+
+  <p>FCM provides various commands which make working with branches easier (as
+  described in the following sections).</p>
+
+  <h4><a name="svn_branching_create">Creating Branches</a></h4>
+
+  <p>The command <tt>fcm branch --create</tt> should be used for creating new
+  branches. It provides a number of features:</p>
+
+  <ul>
+    <li>It applies a standard naming convention for branches. The branch name
+    is automatically constructed for you depending on the option(s) supplied to
+    the command. The full detail of these options are described in the <a href=
+    "command_ref.html#fcm_svn_br">FCM Command Reference &gt; fcm branch</a>
+    section.</li>
+
+    <li>By default, it assumes that you are branching from the last changed
+    revision of the <em>trunk</em>.
+
+      <ul>
+        <li>You can use the <tt>--branch-of-branch</tt> option if you need to
+        create a branch of a branch. A branch of a branch can be useful in many
+        situations. For example, consider a shared branch used by several
+        members of your team to develop, say, a new science scheme, and you have
+        come up with some different ideas of implementing the scheme. You may
+        want to create a branch of the shared branch to develop your idea before
+        merging it back to the shared branch. Note that you can only merge a
+        branch of a branch with it's parent or with another branch created from
+        the same parent. You can't, for example, merge it with the trunk.</li>
+
+        <li>You can use the <tt>--revision &lt;rev&gt;</tt> option if you need
+        to create a branch from an earlier revision of the source.</li>
+      </ul>
+    </li>
+
+    <li>Each branch always contains a full copy of the trunk (or its parent
+    branch) - you cannot create a branch from a sub-tree.
+
+      <ul>
+        <li>There would be no reason to only include a sub-tree in a
+        branch.</li>
+      </ul>
+    </li>
+
+    <li>It applies a standard commit message which defines how the branch has
+    been created. If a Trac ticket is specified using the <tt>--ticket
+    &lt;number&gt;</tt> option, it is added to the commit log message. If you need to
+    add anything to the commit log message, please do so <strong>above</strong>
+    the line that says "--This line will be ignored and those below will be
+    inserted automatically--".</li>
+  </ul>
+  
+  <p>The following is a list of the different types of branches available:</p>
+
+  <table class="pad" summary="list of available branch types" border="1">
+    <tr>
+      <th>Type</th>
+
+      <th>Branch Name</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td rowspan="2">Development<br>
+      Branches</td>
+
+      <td class="mono">branches/dev/&lt;Userid&gt;/&lt;Branch_Name&gt;</td>
+
+      <td>These are for changes which are intended to be merged back to the
+      trunk once they are complete. Most branches will belong to this type.
+      e.g. branches/dev/frdm/vn6.1_ImprovedDeepConvection,
+      branches/dev/frdm/r2134_NewBranchNamingConvention.</td>
+    </tr>
+
+    <tr>
+      <td class="mono">branches/dev/Share/&lt;Branch_Name&gt;</td>
+
+      <td>Shared development branches not owned by one specific user.</td>
+    </tr>
+
+    <tr>
+      <td rowspan="2">Test<br>
+      Branches</td>
+
+      <td class="mono">branches/test/&lt;Userid&gt;/&lt;Branch_Name&gt;</td>
+
+      <td>These are for changes which are <em>not</em> intended for the trunk.
+      e.g. Proof of concept work, temporary code written for dealing with a
+      one-off problem, etc.</td>
+    </tr>
+
+    <tr>
+      <td class="mono">branches/test/Share/&lt;Branch_Name&gt;</td>
+
+      <td>Shared test branches.</td>
+    </tr>
+
+    <tr>
+      <td rowspan="2">Packages</td>
+
+      <td class="mono">branches/pkg/&lt;Userid&gt;/&lt;Branch_Name&gt;</td>
+
+      <td>These are branches which combine together a number of different
+      development branches. Sometimes this will simply be for testing purposes
+      (i.e. for testing a branch in combination with other branches). Other
+      times it may be the package which eventually gets merged to the trunk
+      (rather than the development branches). e.g.
+      branches/pkg/frdm/vn6.1_TestImprovedDeepConvection</td>
+    </tr>
+
+    <tr>
+      <td class="mono">branches/pkg/Share/&lt;Branch_Name&gt;</td>
+
+      <td>Shared packages. e.g.
+      branches/pkg/Share/vn6.1_NewConvectionScheme.</td>
+    </tr>
+
+    <tr>
+      <td>Configurations</td>
+
+      <td class="mono">branches/pkg/Config/&lt;Branch_Name&gt;</td>
+
+      <td>These are major packages which combine together a number of different
+      packages and development branches. e.g.
+      branches/pkg/Config/vn6.1_HadGEM1a.</td>
+    </tr>
+
+    <tr>
+      <td>Releases</td>
+
+      <td class="mono">branches/pkg/Rel/&lt;Branch_Name&gt;</td>
+
+      <td>These may be bug-fix branches for system releases, if required. They
+      can also be branches on which stable releases are prepared if you don't
+      do this on the trunk (although you lose the ability to branch from stable
+      releases if you work this way). e.g.
+      branches/pkg/Rel/vn6.1_BugFixes.</td>
+    </tr>
+  </table>
+
+  <table class="pad" summary="fcm branch --create example output" border="1"
+  width="100%">
+    <tr>
+      <th>Example output from <tt>fcm branch --create</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm br -c -n my_test_branch -k 23 fcm:test
+Starting nedit to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+Create an example branch to demonstrate branch creation for the user guide.
+Created /OPS/branches/dev/frsn/r118_my_test_branch from /OPS/trunk@118.
+Relates to ticket #23.
+--This line, and those below, will be ignored--
+
+A    svn://fcm1/repos/OPS/branches/dev/frsn/r118_my_test_branch
+------------------------------------------------------------------------
+Would you like to go ahead and create this branch?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Creating branch svn://fcm1/repos/OPS/branches/dev/frsn/r118_my_test_branch ...
+
+Committed revision 169.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4><a name="svn_branching_list">Listing Branches Created by You or Other
+  Users</a></h4>
+
+  <p>The command <tt>fcm branch --list</tt> can be used to list the branches
+  you have created at the HEAD of a repository. If you specify the <tt>--user
+  &lt;userid&gt;</tt> option, the branches created by &lt;userid&gt; are listed
+  instead. You can specify multiple users with multiple <tt>--user
+  &lt;userid&gt;</tt> options, or with a colon (:) separated list to a single
+  <tt>--user &lt;userid:list&gt;</tt> option. The command returns 0 (success)
+  if one or more branches is found for the specified users, or 1 (failure) if
+  no branch is found.</p>
+
+  <table class="pad" summary="fcm branch --list example output" border="1"
+  width="100%">
+    <tr>
+      <th>Example output from <tt>fcm branch --list</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm branch --list fcm:gen
+1 branch found for frsn in svn://fcm1/GEN_svn/GEN
+svn://fcm1/GEN_svn/GEN/branches/dev/frsn/r1191_clean_up/
+(SHELL PROMPT)$ echo $?
+0
+(SHELL PROMPT)$ fcm branch --list --user frbj --user frsn fcm:gen
+2 branches found for frbj, frsn in svn://fcm1/GEN_svn/GEN
+svn://fcm1/GEN_svn/GEN/branches/dev/frbj/r1177_gen_ui_for_scs/
+svn://fcm1/GEN_svn/GEN/branches/dev/frsn/r1191_clean_up/
+(SHELL PROMPT)$ echo $?
+0
+(SHELL PROMPT)$ fcm branch --list --user frva fcm:gen
+0 branch found for frva in svn://fcm1/GEN_svn/GEN
+(SHELL PROMPT)$ echo $?
+1
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4><a name="svn_branching_info">Getting Information About Branches</a></h4>
+
+  <p>The command <tt>fcm branch --info</tt> can be used to get various
+  information about a branch. In particular, it summarises information about
+  merges to and from the branch and its parent.</p>
+
+  <table class="pad" summary="fcm branch --info example output" border="1"
+  width="100%">
+    <tr>
+      <th>Example output from <tt>fcm branch --info</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm branch --info
+URL: svn://fcm1/FCM_svn/FCM/branches/dev/frsn/r1346_merge
+Repository Root: svn://fcm1/FCM_svn
+Revision: 1385
+Last Changed Author: frsn
+Last Changed Rev: 1385
+Last Changed Date: 2006-04-20 11:08:45 +0100 (Thu, 20 Apr 2006)
+--------------------------------------------------------------------------------
+Branch Create Author: frsn
+Branch Create Rev: 1354
+Branch Create Date: 2006-04-04 14:27:47 +0100 (Tue, 04 Apr 2006)
+Branch Parent: svn://fcm1/FCM_svn/FCM/trunk@1346
+Last Merge From Parent, Revision: 1444
+Last Merge From Parent, Delta: /FCM/trunk@1439 cf. /FCM/trunk@1395
+Merges Avail From Parent: 1445
+Merges Avail Into Parent: 1453 1452 1449 1446 1444 1443 1441 1434 1397 1396 ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>If you need information on the current children of the branch, use the
+  <tt>--show-children</tt> option of the <tt>fcm branch --info</tt> command. If
+  you need information on recent merges to and from the branch and its siblings,
+  use the <tt>--show-siblings</tt> option of the <tt>fcm branch --info</tt>
+  command.</p>
+
+  <p>To find out what changes have been made on a branch relative to its parent
+  you can use the command <tt>fcm diff --branch</tt>.</p>
+
+  <ul>
+    <li>You can combine this with the <tt>--graphical</tt> switch to see the
+    differences displayed in <em>xxdiff</em>.</li>
+
+    <li>The base of the difference is adjusted to account for any merges from
+    the branch to its parent or vice-versa.</li>
+  </ul>
+
+  <h4><a name="svn_branching_switch">Switching your working copy to point to
+  another branch</a></h4>
+
+  <p>The command <tt>fcm switch</tt> can be used to switch your working copy to
+  point to another branch. For example, if you have a working copy at
+  <tt>$HOME/work</tt>, currently pointing to the trunk or a branch of a project
+  at <tt>svn://fcm1/FCM_svn/FCM/trunk</tt>, you can switch the working copy to
+  point to another branch of same project:</p>
+
+  <table class="pad" summary="fcm switch" border="1" width="100%">
+    <tr>
+      <th>Example output from <tt>fcm switch</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(Shell prompt)$ cd $HOME/work
+(Shell prompt)$ fcm sw dev/frsn/r959_blockdata
+-&gt; svn switch --revision HEAD svn://fcm1/FCM_svn/FCM/branches/dev/frsn/r959_blockdata
+U    doc/user_guide/getting_started.html
+U    doc/user_guide/code_management.html
+U    doc/user_guide/command_ref.html
+U    src/lib/Fcm/SrcFile.pm
+U    src/lib/Fcm/Util.pm
+U    src/lib/Fcm/Build.pm
+U    src/lib/Fcm/Cm.pm
+U    src/lib/Fcm/SrcPackage.pm
+U    src/bin/fcm_internal
+U    src/bin/fcm_gui
+Updated to revision 1009.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Unlike <tt>svn switch</tt>, <tt>fcm switch</tt> does extra checking to
+  ensure that your whole working copy is switched to the new branch at the
+  correct level of sub-directory. In addition, you can specify only the "branch"
+  part of the URL, such as "trunk", "branches/dev/fred/r1234_bob" or even
+  "dev/fred/r1234_bob" and the command will work out the full URL for you.</p>
+
+  <h4><a name="svn_branching_delete">Deleting Branches</a></h4>
+
+  <p>The command <tt>fcm branch --delete</tt> can be used to delete branches
+  which are no longer required. Before being asked to confirm that you want to
+  delete the branch, you will first see the same output as from <tt>fcm branch
+  --info</tt>. This allows you to check, for example, whether your branch is
+  being used anywhere else or whether the latest changes on your branch have
+  been merged to the trunk. You will be prompted to edit your commit log
+  message. If you need to add anything to the commit log message, please do so
+  <strong>above</strong> the line that says "--This line will be ignored and
+  those below will be inserted automatically--".</p>
+
+  <h4><a name="svn_branching_merge">Merging</a></h4>
+
+  <p>As mentioned earlier, Subversion doesn't track merge information
+  (although, in the longer term, there are plans to add this feature). However,
+  <tt>fcm</tt> <em>does</em> track a limited amount of merge information. It
+  does this by making a number of assumptions:</p>
+
+  <ul>
+    <li>That all merges are performed using FCM and are identified using a
+    standard template in the commit log message.</li>
+
+    <li>That you only ever merge all the changes available on the source branch
+    up to a chosen point (i.e. you can't only include a subset of the
+    changes made to the branch).</li>
+
+    <li>That the source and target are both branches (or the trunk) in the
+    same FCM project.</li>
+
+    <li>That the source and target are directly related, i.e. they must either
+    have a parent/child relationship or they are siblings from the same parent
+    branch.</li>
+  </ul>
+
+  <p>Note that the term "source branch" and "target branch" referred to above
+  can also mean the trunk.</p>
+
+  <p>To perform a merge, use the command <tt>fcm merge &lt;source&gt;</tt>. This
+  includes a number of important features:</p>
+
+  <ul>
+    <li>If it finds any local modifications in your working copy then it checks
+    whether you wish to continue (in most cases you won't want to mix a merge
+    with other changes).</li>
+
+    <li>It determines the base revision and path of the <em>common
+    ancestor</em> to be used for the merge, taking into account any merges from
+    the <em>source</em> to the <em>target</em> or vice-versa.</li>
+
+    <li>Before doing the merge, (unless you specify the
+    <tt>--non-interactive</tt> option), it reports what changes will result from
+    performing the merge and checks that you wish to continue.</li>
+
+    <li>It adds details of the merge, using a standard template, into the commit
+    message file (<tt>#commit_message#</tt>). If you need to add any extra
+    comment, you should do so <strong>above</strong> the line that says "--This
+    line will be ignored and those below will be inserted automatically--".
+
+      <ul>
+        <li>If you decide to revert the merge, you should remove the template
+        line manually from the commit message file, making sure that you do not
+        alter the standard template by accident.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <table class="pad" summary="fcm merge example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm merge</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm merge trunk # merge changes from the trunk into the branch
+Available Merges From /FCM/trunk: 1383 1375
+Please enter the revision you wish to merge from
+  (or just press <return> for "1383"):
+About to merge in changes from /FCM/trunk@1383 compared with /FCM/trunk@1371
+This merge will result in the following changes:
+--------------------------------------------------------------------------------
+A    doc/standards/fortran_standard.html
+U    src/lib/Fcm/ReposBranch.pm
+--------------------------------------------------------------------------------
+Would you like to go ahead with the merge?
+Enter "y" or "n" (or just press <return> for "n"): y
+Performing merge ...
+A    doc/standards/fortran_standard.html
+U    src/lib/Fcm/ReposBranch.pm
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="svn_gui">Using the GUI</a></h3>
+
+  <p>So far, all the tools described have been command line tools. Many people
+  will be happy with these but, for those who prefer it, there is also a simple
+  Graphical User Interface (GUI).</p>
+
+  <h4><a name="svn_gui_start">Starting the GUI</a></h4>
+
+  <p>To run the GUI simply issue the command <tt>fcm gui</tt> from the
+  directory you want as your working directory. You can also start the GUI from
+  within Konqueror (see <a href="#svn_gui_konqueror">Accessing the GUI from
+  Konqueror</a>).</p>
+
+  <p>The GUI consists of several sections:</p>
+
+  <ul>
+    <li>The top section contains a row of buttons to allow you to select which
+    command you want to run.</li>
+
+    <li>Beneath this is shown the current working directory and the top level
+    directory of your working copy (these may be the same).</li>
+
+    <li>Beneath this come various buttons and entry boxes to allow you to
+    configure the command you have selected. These vary according to the
+    command.</li>
+
+    <li>Beneath this comes a further row of buttons
+
+      <ul>
+        <li><em>Quit</em> - this exits the GUI.</li>
+
+        <li><em>Help</em> - this displays the help message for the selected
+        command.</li>
+
+        <li><em>Clear</em> - this empties the text window.</li>
+
+        <li><em>Run</em> - this allows you to run your command.</li>
+      </ul>
+    </li>
+
+    <li>Beneath this comes a scrolling text window where the output from the
+    commands is displayed.</li>
+
+    <li>The bottom section displays help information when you position the
+    cursor over various parts of the GUI.</li>
+  </ul>
+
+  <p class="image"><img src="gui1.png" alt=
+  "Example GUI screen with the Status commands selected"></p>
+
+  <p align="center">Example GUI screen with the <em>Status</em> commands
+  selected</p>
+
+  <p>If you run a more complicated command, like <tt>fcm branch</tt>, which
+  prompts for input then extra entry windows will pop up.</p>
+
+  <p class="image"><img src="gui2.png" alt="Example GUI pop-up window"></p>
+
+  <p align="center">Example GUI pop-up window</p>
+
+  <h4><a name="svn_gui_commands">GUI Commands</a></h4>
+
+  <p>The commands available from the GUI should be self explanatory. A few
+  points to note:</p>
+
+  <ul>
+    <li>If the current directory is not a working copy, you will only be able to
+    Checkout a working copy or create a branch from the GUI.</li>
+
+    <li>The <em>Checkout</em> command is only available if you start the GUI in
+    a directory which is not already a working copy. After successfully running
+    a checkout the GUI automatically sets the working directory to the top of
+    this new working copy.</li>
+
+    <li>With some commands (Status, Diff, Add, Delete, Conflicts) you can
+    choose whether to run from the top level of your working copy or from your
+    working directory. With the remaining commands this would not make sense
+    and they can only be run from the top level.</li>
+
+    <li>You can only issue commands from the GUI if they do not need to prompt
+    you for authentication (i.e. the Subversion command can be run with the
+    <em>--non-interactive</em> option).  
+
+      <ul>
+        <li>If authentication is required then the command issued by the GUI
+        will fail. For the "branch --create", "branch --delete" and "commit"
+        commands, which support the "--password" option, you should specify your
+        password in "Other options" and click "Run" again. For other commands,
+        you should run the command in interactive mode on the command line. Use
+        the command displayed in the GUI text window but remove the
+        <em>--non-interactive</em> option.</li>
+
+        <li>Most repositories will be configured so that you only need
+        authentication for writing (not reading). Therefore, the first command
+        requiring authentication will probably be creating a branch or commiting
+        to the trunk.</li>
+
+        <li>You should only need to do this the first time you ever issue such
+        a command on a each repository (unless the repository is moved to a new
+        location) since the Subversion client caches this information for future
+        comamnds .</li>
+      </ul>
+    </li>
+  </ul>
+
+  <h4><a name="svn_gui_konqueror">Accessing the GUI from Konqueror</a></h4>
+
+  <p>To enable access from Konqueror run the script
+  <tt>fcm_setup_konqueror</tt>. You can then use the Konqueror file manager to
+  select the directory which you want as your working directory. To run the GUI
+  click the right mouse button and select <em>Open With =&gt; FCM GUI</em>.</p>
+
+  <ul>
+    <li>Make sure that your current selection is the directory and not a file
+    within that directory.</li>
+  </ul>
+
+  <p class="image"><img src="konqueror.png" alt=
+  "Running the GUI from within Konqueror"></p>
+
+  <p align="center">Running the GUI from within Konqueror</p>
+
+  <h3><a name="svn_problems">Known Problems with Subversion</a></h3>
+
+  <p>There are some limitations with Subversion v1.3 which you should be aware
+  of:</p>
+
+  <ul>
+    <li>The <em>svn rename</em> command is not a true rename/move operation,
+    but is implemented as a copy and delete. As a result, if you rename an item
+    in a branch, and later attempt to merge it back to the trunk, the operation
+    may not be handled correctly by <em>svn merge</em> (see <a href=
+    "http://subversion.tigris.org/issues/show_bug.cgi?id=1864">subversion issue
+    1864</a> for further details). Support for a "true move" will hopefully be
+    available in Subversion in the near future. Until this is implemented, you
+    should avoid renaming of files or directories unless you can ensure that
+    no-one is working in parallel on the affected areas of the project.</li>
+  </ul>
+
+  <h2><a name="trac">Using Trac</a></h2>
+
+  <p><em>Trac</em> has a simple and intuitive web interface which is relatively
+  easy to pick up. It also includes a <a href=
+  "http://trac.edgewall.org/wiki/TracGuide">User and Administration Guide</a>
+  which is full of helpful information (and is referred to extensively in this
+  section).</p>
+
+  <p>Trac contains a menu bar at the top of each page (which we will refer to
+  as the <em>Trac menu</em>). This provides access to all the main
+  features.</p>
+
+  <h3><a name="trac_login">Logging In</a></h3>
+
+  <p>Although different projects may choose their own rules, we expect that
+  most systems will have Trac configured so that all the information is
+  viewable by anyone. However, in order to make any changes you will need to
+  login. This ensures that any changes are identified with the appropriate
+  userid.</p>
+
+  <p>In the rest of this section it is assumed that you have logged in to Trac
+  and are therefore able to make changes.</p>
+
+  <p>If you haven't yet got a Trac userid (which should be the same as the
+  userid you use for committing changes to Subversion) then please contact your
+  system manager.</p>
+
+  <h3><a name="trac_wiki">Using the Wiki Pages</a></h3>
+
+  <p>A wiki enables documents to be written in a simple markup language using a
+  web browser. See the Trac Guide for information on the <a href=
+  "http://trac.edgewall.org/wiki/TracWiki">Trac Wiki Engine</a>. Make sure that
+  you read the information provided on:</p>
+
+  <ul>
+    <li><a href="http://trac.edgewall.org/wiki/WikiFormatting">Wiki
+    Formatting</a> which explains how to format your wiki pages.</li>
+
+    <li><a href="http://trac.edgewall.org/wiki/WikiPageNames">Wiki Page
+    Names</a> which explains how <em>CamelCase</em> is used to create <a href=
+    "http://trac.edgewall.org/wiki/WikiNewPage">New Wiki Pages</a>.</li>
+
+    <li><a href="http://trac.edgewall.org/wiki/TracLinks">Trac Links</a> which
+    allow hyperlinking between Trac entities (tickets, reports, changesets,
+    Wiki pages, milestones and source files). This is a fundamental feature of
+    Trac which makes it easy, for example, to link a bug report (ticket) to the
+    changeset which fixed the bug (and vice-versa).</li>
+  </ul>
+
+  <p>Whenever you are viewing a wiki page in Trac you should see several
+  buttons at the bottom of the page:</p>
+
+  <ul>
+    <li><em>Edit This Page</em> - Clicking this will bring up a page where you
+    can edit the page contents. Before saving your changes you can preview how
+    the modified page will appear. You can also leave a comment explaining what
+    changes you made.</li>
+
+    <li><em>Attach File</em> - Allows you to attach files to a page, e.g. an
+    image.</li>
+
+    <li>If you have admin rights then you will also see
+
+      <ul>
+        <li><em>Delete This Version</em> - Delete the particular version of the
+        page you are viewing.</li>
+
+        <li><em>Delete Page</em> - Delete the page and all its history.</li>
+      </ul>Use with care - these operations are irreversible!
+    </li>
+  </ul>
+
+  <p>At the top of each wiki page at the right hand side you can select
+  <em>Page History</em>. This shows you the full history of each page with
+  details of when each change was made, who made the change and what the
+  changes were.</p>
+
+  <h3><a name="trac_browser">Using the Repository Browser</a></h3>
+
+  <p>The <a href="http://trac.edgewall.org/wiki/TracBrowser">Trac Browser</a>
+  is used to view the contents of your repository. To get to it just select
+  <em>Browse Source</em> from the Trac menu. You can view directories and files
+  at any version, see their revision histories and view <a href=
+  "http://trac.edgewall.org/wiki/TracChangeset">changesets</a>. Any wiki
+  formatting in log messages is recognised and interpreted so you can easily
+  link a changeset to a Trac ticket by using <a href=
+  "http://trac.edgewall.org/wiki/TracLinks">Trac Links</a>.</p>
+
+  <h3><a name="trac_tickets">Using the Issue Tracker</a></h3>
+
+  <p>The Trac issue database provides a way of tracking issues within a project
+  (e.g. bug reports, feature requests, software support issues, project tasks).
+  Within Trac an issue is often referred to as a <em>Ticket</em>.</p>
+
+  <p>Please refer to the Trac Guide for the following information:</p>
+
+  <ul>
+    <li>
+      <a href="http://trac.edgewall.org/wiki/TracTickets">The Trac Ticket
+      System</a> - Creating and modifying tickets.
+
+      <ul>
+        <li>Only Trac accounts with admin rights can modify ticket
+        descriptions.</li>
+      </ul>
+    </li>
+
+    <li><a href="http://trac.edgewall.org/wiki/TracQuery">Trac Ticket
+    Queries</a> - List tickets matching your chosen criterion.</li>
+  </ul>
+
+  <h3><a name="trac_roadmap">Using the Roadmap</a></h3>
+
+  <p>Each ticket can be assigned to a milestone. The Trac Roadmap can then be
+  used to provide a view on the ticket system. This can useful to see what
+  changes went into a particular system release or what changes are outstanding
+  before a milestone can be reached.</p>
+
+  <p>Please refer to the Trac Guide for further information on the <a href=
+  "http://trac.edgewall.org/wiki/TracRoadmap">Trac Roadmap</a>.</p>
+
+  <ul>
+    <li>Only Trac accounts with admin rights can add, modify and remove
+    milestones using the web interface.</li>
+  </ul>
+
+  <h3><a name="trac_timeline">Using the Timeline</a></h3>
+
+  <p>The <a href="http://trac.edgewall.org/wiki/TracTimeline">Trac Timeline</a>
+  allows you to list all the acitivity on a project over any given period. It
+  can list:</p>
+
+  <ul>
+    <li>Creation and changes to wiki pages.</li>
+
+    <li>Creation, closure and changes to tickets.</li>
+
+    <li>Commits to the Subversion repository.</li>
+
+    <li>Milestones reached.</li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/command_ref.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/command_ref.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/command_ref.html	(revision 329)
@@ -0,0 +1,1242 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: FCM Command Reference</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - FCM Command Reference">
+  <meta name="keywords" content="FCM, user guide, command reference">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; FCM Command Reference
+  </address>
+
+  <h1>FCM Command Reference</h1>
+
+  <h2><a name="fcm_config">fcm Configuration File</a></h2>
+
+  <p>The FCM system uses simple line based text files to store configuration
+  settings. All configuration files used by FCM are based on the same
+  principles:</p>
+
+  <ul>
+    <li>All configurations are stored in plain text files.</li>
+
+    <li>A line in a file may contain a configuration setting or a comment.</li>
+
+    <li>Blank lines are ignored.</li>
+
+    <li>A line that begins with a <tt>#</tt> is a <em>comment</em> line.</li>
+
+    <li>Each configuration line has a <em>label</em>, a <em>value</em> and
+    optionally a trailing <em>comment</em>. For example:
+      <pre>
+my::label  this is the value  # some comment
+</pre>
+    </li>
+
+    <li>A <em>label</em> in a configuration line may contain any non-space
+    character. A space character marks the end of the <em>label</em>.</li>
+
+    <li>Words or fields in the <em>label</em> are normally delimited by the
+    double colon (<tt>::</tt>).</li>
+
+    <li>The first non-space character after the <em>label</em> is the beginning
+    of the <em>value</em>. The <em>value</em> may contain space characters. The
+    newline character or the character sequence <tt>" # "</tt> marks the end of
+    the <em>value</em>.</li>
+
+    <li>The first non-space character after the character sequence <tt>" #
+    "</tt> at the end of the <em>value</em> is the <em>comment</em>. The
+    <em>comment</em> is normally ignored by the parser of the configuration
+    file.</li>
+
+    <li>If the last character of the <em>value</em> is a backslash "\", the
+    next non-comment line will be the continuation of the current line. Please
+    note that trailing spaces before the continuation mark are preserved, and
+    leading spaces are removed from the beginning of a continuation. If you
+    want to have leading spaces in a continued line, start the line with a
+    backslash "\" before the leading spaces. It is also worth bearing in mind
+    that the backslash "\" character is only significant if it appears at the
+    end of a value or the beginning of a continuation line. It is not a special
+    character if it appears elsewhere. For example:
+      <pre>
+foo bar\
+    egg\
+    ham
+# will become:
+foo bareggham
+
+foo bar \
+    egg \
+    ham
+# will become:
+foo bar egg ham
+
+foo bar\
+    \ egg\
+    \ ham
+# will become:
+foo bar egg ham
+
+foo bar\
+    \ egg\ham
+# will become:
+foo bar egg\ham
+</pre>
+    </li>
+  </ul>
+
+  <p>The FCM central and user configuration files can be used to add or modify
+  some of the default settings of FCM. When the <em>fcm</em> command is
+  invoked, it normally attempts to search for a central configuration file at
+  <tt>$BINDIR/../etc/fcm.cfg</tt> and then <tt>$BINDIR/fcm.cfg</tt>, where
+  <tt>$BINDIR</tt> is the container directory of the <em>fcm</em> command. If a
+  central configuration file can be located, the settings in the file will
+  replace the pre-defined ones. After searching/reading the central
+  configuration file, the system will attempt to search for a user
+  configuration file located at <tt>$HOME/.fcm</tt> of the current user. If
+  such a file can be found, its settings will replace the pre-defined ones as
+  well as those defined in the central configuration file.</p>
+
+  <p>For information on the valid entries in the central and user configuration
+  files, please refer to the <a href="annex_fcm_cfg.html">Annex: Declarations
+  in FCM central/user configuration file</a>.</p>
+
+  <h2><a name="fcm_bld">fcm build</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm build [OPTIONS...] [CFGFILE]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm build</tt> invokes the FCM build system.</p>
+
+  <p>The path to a valid build configuration file <tt>CFGFILE</tt> may be
+  provided as either a URL or a pathname. Otherwise, the build system
+  searches the default locations for a build configuration file.</p>
+
+  <p>If no option is specified, the system uses the "<tt>-s 5 -t all -j 1 -v
+  1</tt>" by default.</p>
+
+  <ul>
+    <li>The "<tt>-a [--archive]</tt>" option can be specified to switch on the
+    archive mode. In archive mode, sub-directories produced by the build will
+    be archived in <em>tar</em> format at the end of a successful build. This
+    option should not be used if the current build is intended to be re-used as
+    a pre-compiled build.</li>
+
+    <li>If the "<tt>-f [--full]</tt>" option is specified, the build system
+    will attempt to perform a full/clean build by removing any previous build
+    files. Otherwise, the build system will attempt to perform an incremental
+    build where appropriate.</li>
+
+    <li>When the build system is invoked, it sets a lock file in the build root
+    directory to prevent other extracts/builds taking place in the same
+    location. The lock file is normally removed when the build system exits.
+    (However, a lock file may be left behind if the user interrupts the command,
+    e.g. by typing <tt>Ctrl-C</tt>.) You can bypass the check for lock files by
+    using the "<tt>--ignore-lock</tt>" option.</li>
+
+    <li>The "<tt>-j [--jobs] arg</tt>" option can be used to specify the number
+    of parallel jobs that can be handled by the <em>make</em> command. The
+    argument <tt>arg</tt> must be a natural integer to represent the number of
+    jobs. If not specified, the default is to perform serial <em>make</em>
+    (i.e. 1 job).</li>
+
+    <li>The "<tt>-s [--stage] arg</tt>" option can be used to limit the actions
+    performed by the build system, up to a named stage determined by the
+    argument <tt>arg</tt>. If not specified, the default is 5. The stages are:
+
+      <ul>
+        <li>"1", "s" or "setup": stage 1, read configuration and set up the
+        build</li>
+
+        <li>"2", "pp" or "pre_process": stage 2, perform pre-processing for
+        source files that require pre-processing</li>
+
+        <li>"3", "gd" or "generate_dependency": stage 3, scan source files for
+        dependency information and generate <em>make</em> rules for them</li>
+
+        <li>"4", "gi" or "generate_interface": stage 4, generate interface
+        files for Fortran 9X source files</li>
+
+        <li>"5", "m", "make": stage 5, invoke the <em>make</em> command to
+        build the project</li>
+      </ul>
+    </li>
+
+    <li>The "<tt>-t [--targets] arg</tt>" can be used to specify the targets to
+    be built. The argument <tt>arg</tt> must be a colon-separated list of valid
+    targets. If not specified, the default target to be built is the "all"
+    target.</li>
+
+    <li>The "<tt>-v [--verbose] arg</tt>" option can be specified to alter the
+    level of diagnostic output. The argument <tt>arg</tt> to this option must
+    be an integer greater than or equal to 0. The verbose level increases with
+    this number. If not specified, the default verbose level is 1.</li>
+  </ul>
+
+  <p>For further details, please refer to the chapter on <a href=
+  "build.html">The Build System</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>bld</p>
+
+  <h2><a name="fcm_ext">fcm extract</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm extract [OPTIONS...] [CFGFILE]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm extract</tt> invokes the FCM extract system.</p>
+
+  <p>The path to a valid extract configuration file <tt>CFGFILE</tt> may be
+  provided as either a URL or a pathname. Otherwise, the extract system
+  searches the default locations for an extract configuration file.</p>
+
+  <ul>
+    <li>If the "<tt>-f [--full]</tt>" option is specified, the extract system
+    will attempt to perform a full/clean extraction by removing any previous
+    extracted files. Otherwise, the extract system will attempt to perform an
+    incremental extraction where appropriate.</li>
+
+    <li>When the extract system is invoked, it sets a lock file in the extract
+    destination root directory to prevent other extracts/builds taking place in
+    the same location. The lock file is normally removed when the extract system
+    exits.  (However, a lock file may be left behind if the user interrupts the
+    command, e.g. by typing <tt>Ctrl-C</tt>.) You can bypass the check for lock
+    files by using the "<tt>--ignore-lock</tt>" option.</li>
+
+    <li>The "<tt>-v [--verbose] arg</tt>" option can be specified to alter the
+    level of diagnostic output. The argument <tt>arg</tt> to this option must
+    be an integer greater than or equal to 0. The verbose level increases with
+    this number. If not specified, the default verbose level is 1.</li>
+  </ul>
+
+  <p>For further details, please refer to the chapter on <a href=
+  "extract.html">The Extract System</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>ext</p>
+
+  <h2><a name="fcm_cmp-ext-cfg">fcm cmp-ext-cfg</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm cmp-ext-cfg [--wiki (-w) arg] CFG1 CFG2</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm cmp-ext-cfg</tt> compares the extract configurations of two similar
+  extract configuration files CFG1 and CFG2. It reports repository branches and
+  source directories that are declared in one file but not another. If a source
+  directory is declared in both files, it compares their versions. If they
+  differ, it uses <tt>svn log</tt> to obtain a list of revision numbers at which
+  changes are made to the source directory. It then reports, for each declared
+  repository branch, the revisions at which changes occur in their declared
+  source directories.</p>
+
+  <p>The list of revisions for each declared repository branch is normally
+  printed out as a simple list in plain text. You can use the <tt>--wiki</tt>
+  option to change that into an tabular output suitable for inserting into a Trac
+  wiki page. The <tt>--wiki</tt> option must be specified with an argument, which
+  must be the Subversion URL or FCM URL keyword of a FCM project associated with
+  the intended Trac system. The URL allows the command to work out the correct
+  wiki syntax to use.</p>
+
+  <h2><a name="fcm_gui">fcm gui</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm gui [DIR]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm gui</tt> starts up the FCM GUI. If DIR is specified then this is
+  used as the working directory.</p>
+
+  <p>For further details, please refer to the section <a href=
+  "code_management.html#svn_gui">Using the GUI</a>.</p>
+
+  <h2><a name="fcm_svn">fcm Subversion Subcommands</a></h2>
+
+  <p>This section describes all of the Subversion related commands supported by
+  <tt>fcm</tt>.</p>
+
+  <ul>
+    <li>In some cases <tt>fcm</tt> simply passes the command directly on to
+    <tt>svn</tt> (after expanding any repository keywords). These commands are
+    listed in the <a href="#fcm_svn_other">Other Subversion Commands</a>
+    section.</li>
+
+    <li>Where <tt>fcm</tt> adds functionality these commands are discussed
+    individually.</li>
+
+    <li>In all cases, all the command abbreviations supported by <tt>svn</tt>
+    work with <tt>fcm</tt>.</li>
+  </ul>
+
+  <h3><a name="fcm_svn_add">fcm add</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm add --check (-c)</p>
+ 
+  <p>fcm add &lt;any valid <em>svn add</em> options&gt;</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm add</tt> supports all of the switches and arguments supported by
+  <tt>svn add</tt> (refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.add.html">Subversion
+  book</a> for details).</p>
+
+  <p>In addition, <tt>fcm add</tt> supports a <tt>--check</tt> switch (no
+  other switches or arguments). When this is specified then <tt>fcm</tt>
+  checks for any files which are not currently under version control (i.e. those
+  marked with a "?" by <tt>svn status</tt>) and prompts to see if you wish to
+  schedule them for addition at the next commit (using <tt>svn add</tt>).</p>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_check">Adding and Removing
+  Files</a>.</p>
+
+  <h3><a name="fcm_svn_br">fcm branch</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm branch [--info (-i)] [--verbose (-v)] [--show-children]
+  [--show-siblings] [--show-other] [--show-all (-a)] [TARGET]</p>
+
+  <p>fcm branch --delete (-d) [--verbose (-v)] [--show-children]
+  [--show-siblings] [--show-other] [--show-all (-a)] [--svn-non-interactive]
+  [--non-interactive] [--password arg] [TARGET]</p>
+
+  <p>fcm branch --create (-c) --name (-n) arg [--type (-t) arg] [--rev-flag arg]
+  [--ticket (-k) arg] [--branch-of-branch] [--svn-non-interactive]
+  [--non-interactive] [--password arg] [--revision arg] [TARGET]</p>
+
+  <p>fcm branch --list (-l) [--user (-u) arg] [--revision arg] [TARGET]</p>
+
+  <h4>Description</h4>
+
+  <p>If TARGET is specified, it must either be a URL or a path to a local
+  working copy. Otherwise, the current working directory must be a working copy.
+  For <tt>--info</tt> and <tt>--delete</tt>, the specified URL or that of the
+  working copy must be a valid branch (including the trunk) in a standard FCM
+  project. For <tt>--create</tt> and <tt>--list</tt>, it must be a valid URL of
+  a standard FCM project.</p>
+
+  <p><tt>fcm branch --info</tt> displays information about a branch.</p>
+
+  <ul>
+    <li>This is the default if no options are specified (e.g. if you just
+    issue the command <tt>fcm br</tt>).</li>
+
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>It reports the basic information of the branch URL, as returned
+        by "svn info".</li>
+
+        <li>If <tt>--verbose</tt> is set, it also prints the log message of
+        the last change revision.</li>
+
+        <li>If the URL is not the trunk:
+        
+          <ul>
+            <li>It reports the branch creation information, including the
+            revision, author and date. It also reports the parent URL@REV of the
+            branch.  If <tt>--verbose</tt> is set, it prints the log message of
+            the branch creation revision.</li>
+
+            <li>If the branch does not exist at the HEAD, it reports the
+            revision at which it is deleted.</li>
+
+            <li>It reports the last merges into and from the parent branch. If
+            <tt>--verbose</tt> is set, it also prints the log message of
+            these merges.</li>
+
+            <li>It reports the revisions available for merging into and from the
+            parent branch. If <tt>--verbose</tt> is set, it also prints the log
+            message of these revisions.</li>
+          </ul>
+        </li>
+
+        <li>If <tt>--show-children</tt> is specified, it lists the current
+        children of the branch and their create revisions. Where appropriate, it
+        reports the revision of each child, which is last merged from/into the
+        current branch. It also reports the available merges from/into each
+        child into the current branch.</li>
+
+        <li>If <tt>--show-siblings</tt> is specified, it reports recent merges
+        from/into sibling branches. It also reports the available merges
+        from/into sibling branches where recent merges are detected. If
+        <tt>--verbose</tt> is set, it also prints the log message of these
+        merges.</li>
+
+        <li>If <tt>--show-other</tt> is specified, it reports all custom and
+        reverse merges into the current branch.</li>
+
+        <li>You can turn on <tt>--show-children</tt>, <tt>--show-siblings</tt>
+        and <tt>--show-other</tt> simultaneously by specifying
+        <tt>--show-all</tt>.</li>
+      </ul>
+    </li>
+
+    <li>For further details refer to the section <a href=
+    "code_management.html#svn_branching_info">Getting Information About
+    Branches</a>.</li>
+  </ul>
+
+  <p><tt>fcm branch --delete</tt> deletes a branch.</p>
+
+  <ul>
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>Firstly, it provides exactly the same output as <tt>fcm branch
+        --info</tt>.</li>
+
+        <li>If you do not specify the --non-interactive option, it starts an
+        editor (using a similar convention as <a href= "#fcm_svn_ci">commit</a>)
+        to allow you to add further comment to the commit log message. A
+        standard commit log template is provided for you below the line that
+        says "--This line will be ignored and those below will be inserted
+        automatically--". If you need to add any extra message to the log,
+        please do so <strong>above</strong> this line. When you exit the editor,
+        the command will report the commit log before prompting for confirmation
+        that you wish to proceed with deleting the branch (it aborts if
+        not).</li>
+      </ul>
+    </li>
+
+    <li>If you specify the --non-interactive option, the command will not prompt
+    you for anything. (The --svn-non-interactive option is set automatically
+    when you specify --non-interactive.)</li>
+
+    <li>Subversion may prompt you for authentication if it is the first time
+    you access the repository. The command fails if the authentication
+    fails. If you specify the --svn-non-interfactive option, Subversion will not
+    prompt you for authentication. In such case, the command will simply
+    fail if authentication is required. You can use the --password option to
+    specify a password. Please note that the --svn-non-interactive option is
+    always specified if you are running "branch --delete" from the FCM GUI.
+    If authentication is required, you should specify your password using
+    the --password option in "Other options".</li>
+
+    <li>For further details refer to the section <a href=
+    "code_management.html#svn_branching_delete">Deleting Branches</a>.</li>
+  </ul>
+
+  <p><tt>fcm branch --create</tt> creates a new branch.</p>
+
+  <ul>
+    <li>You have to choose a name for your branch. This must be specified
+    as the argument of the --name (-n) option. The name of the branch must
+    contain only word characters, i.e. [A-Za-z0-9_].</li>
+
+    <li>You can specify the type of branch you are creating using the
+    --type (-t) option. The argument to the option must be one of the
+    following:
+
+      <ul>
+        <li>DEV::USER - a development branch for the current user (e.g.
+        branches/dev/&lt;user_id&gt;/&lt;branch_name&gt;)</li>
+
+        <li>DEV::SHARE - a shared development branch (e.g.
+        branches/dev/Share/&lt;branch_name&gt;)</li>
+
+        <li>DEV - same as DEV::USER</li>
+
+        <li>TEST::USER - a test branch for the current user (e.g.
+        branches/test/&lt;user_id&gt;/&lt;branch_name&gt;)</li>
+
+        <li>TEST::SHARE - a shared test branch (e.g.
+        branches/test/Share/&lt;branch_name&gt;)</li>
+
+        <li>TEST - same as TEST::USER</li>
+
+        <li>PKG::USER - a package branch for the current user (e.g.
+        branches/pkg/&lt;user_id&gt;/&lt;branch_name&gt;)</li>
+
+        <li>PKG::SHARE - a shared package branch (e.g.
+        branches/pkg/Share/&lt;branch_name&gt;)</li>
+
+        <li>PKG::CONFIG - a configuration branch (e.g.
+        branches/pkg/Config/&lt;branch_name&gt;)</li>
+
+        <li>PKG::REL - a release branch (e.g.
+        branches/pkg/Rel/&lt;branch_name&gt;)</li>
+
+        <li>PKG - same as PKG::USER</li>
+
+        <li>CONFIG - same as PKG::CONFIG</li>
+
+        <li>REL - same as PKG::REL</li>
+
+        <li>SHARE - same as DEV::SHARE</li>
+
+        <li>USER - same as DEV::USER</li>
+      </ul>
+
+      <p>If the --type option is not specified, it defaults to
+      DEV::USER.</p>
+    </li>
+
+    <li>Your branch name will normally be prefixed by the revision number
+    from which it is branched. (E.g. if the branch name is "my_branch" and
+    you are branching from revision 123 of the trunk, the final name will
+    be "r123_my_branch".) If this revision number is associated with a
+    revision keyword, the keyword will be used in place of the revision
+    number. (E.g. if revision 123 is associated with the keyword vn6.1,
+    "r123_my_branch" will become "vn6.1_my_branch".) You can alter this
+    behaviour using the argument to the --rev-flag option. If NORMAL is
+    specified, it uses the default behaviour. If NUMBER is specified, it
+    will always use the revision number as the prefix, regardless of
+    whether the revision number is defined as a keyword or not. If NONE is
+    specified, it will not add a prefix to your branch name.</li>
+
+    <li>The command will normally create your branch from the last changed
+    revision of the trunk of the specified project.
+      
+      <ul>
+        <li>You can use the --revision option to specify an earlier revision of
+        the source.</li>
+
+        <li>If the source URL is a valid URL of a branch in a standard FCM
+        project, you can use the <tt>--branch-of-branch</tt> option to create
+        a branch of the source branch.</li>
+      </ul>
+    </li>
+
+    <li>The --ticket option can be used to specify one or more Trac ticket
+    numbers, which the branch relates to. Multiple ticket numbers can be set
+    by specifying this option multiple times, or by using a comma-separated
+    list of ticket numbers as the argument to the option. If set, the line
+    "Relates to ticket #&lt;number&gt;[, #&lt;number&gt;...]" will be added
+    to the template commit log.</li>
+
+    <li>If you specify the --non-interactive option, the command will not prompt
+    you for anything. (The --svn-non-interactive option is set automatically
+    when you specify --non-interactive.)</li>
+
+    <li>Subversion may prompt you for authentication if it is the first time
+    you access the repository. The command fails if the authentication
+    fails. If you specify the --svn-non-interfactive option, Subversion will not
+    prompt you for authentication. In such case, the command will simply
+    fail if authentication is required. You can use the --password option to
+    specify a password. Please note that the --svn-non-interactive option is
+    always specified if you are running "branch --create" from the FCM GUI.
+    If authentication is required, you should specify your password using
+    the --password option in "Other options".</li>
+
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>It determines the last changed revision of the trunk/source branch
+        at the HEAD (or the specified) revision.</li>
+
+        <li>It constructs the branch name from the option you have
+        specified and reports it.</li>
+
+        <li>It checks that the chosen branch name does not currently exist.
+        If so, the command aborts with an error.</li>
+
+        <li>If you do not specify the --non-interactive option, it starts an
+        editor (using a similar convention as <a href= "#fcm_svn_ci">commit</a>)
+        to allow you to add further comment to the commit log message. A
+        standard commit log template is provided for you below the line that
+        says "--This line will be ignored and those below will be inserted
+        automatically--". If you need to add any extra message to the log,
+        please do so <strong>above</strong> this line. When you exit the editor,
+        the command will report the commit log before prompting for confirmation
+        that you wish to proceed (it aborts if not).</li>
+
+        <li>It uses <tt>svn mkdir</tt> to create any sub-directories
+        required for the copy to succeed.</li>
+
+        <li>It uses <tt>svn copy</tt> to create the branch.</li>
+      </ul>
+    </li>
+
+    <li>For further details refer to the section <a href=
+    "code_management.html#svn_branching_create">Creating Branches</a>.</li>
+  </ul>
+
+  <p><tt>fcm branch --list</tt> lists the branches created by you (and/or other
+  users) at the HEAD revision of a standard FCM project.</p>
+
+  <ul>
+    <li>By default, it lists the branches created by you at the HEAD revision.
+    To display the branches at a different revision, you can use the
+    <tt>--revision arg</tt> option.</li>
+
+    <li>You can specify a list of users with the <tt>--user arg</tt>
+    option, where "arg" is a colon separated list of users. (Alternatively,
+    you can specify this option multiple times.) When this option is set,
+    the command lists the branches created by the specified list of users
+    instead.</li>
+
+    <li>The command returns 0 (success) if one or more branches is found
+    for the specified users, or 1 (failure) if no branch is found.</li>
+  </ul>
+
+  <h4>Alternate Names</h4>
+
+  <p>br</p>
+
+  <h3><a name="fcm_svn_ci">fcm commit</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm commit [--dry-run] [--svn-non-interactive] [--password arg] [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm commit</tt> sends changes from your working copy in the current
+  working directory (or from PATH if it is specified) to the repository.</p>
+
+  <ul>
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>It checks that the current working directory (or PATH if it is
+        specified) is a working copy. (If not, it aborts with an error).</li>
+
+        <li>It always commits from the top level of the working copy.</li>
+
+        <li>It checks that there are no files in conflict, missing or out of
+        date (it aborts if there are).</li>
+
+        <li>It checks that any files which have been added have the
+        <em>svn:executable</em> property set correctly (in case a script was
+        added before the execute bit was set correctly).</li>
+
+        <li>It reads in any existing commit message and strips out any previous
+        status info (it starts with an empty file if there is none).
+
+          <ul>
+            <li>The commit message is stored in the file
+            <tt>#commit_message#</tt> in the top level of your working
+            copy.</li>
+          </ul>
+        </li>
+
+        <li>If you have run the <a href="fcm_svn_merge">merge</a> command
+        before the commit, you will get a standard commit log template below
+        the line that says "--This line will be ignored and those below will be
+        inserted automatically--". If you need to add any extra message to the
+        log, please do so <strong>above</strong> this line.</li>
+
+        <li>It adds the following line to the commit message:<br>
+        <tt>--This line, and those below, will be ignored--</tt><br>
+        This line, and anything below it, is automatically ignored by <tt>svn
+        commit</tt>.</li>
+
+        <li>It adds current status information to the commit message showing
+        the list of modifications.</li>
+
+        <li>It starts an editor to allow you to edit the commit message.
+
+          <ul>
+            <li>If defined, the environment variable SVN_EDITOR specifies the
+            editor.</li>
+
+            <li>Otherwise the environment variable VISUAL specifies the
+            editor.</li>
+
+            <li>Otherwise the environment variable EDITOR specifies the
+            editor.</li>
+
+            <li>Otherwise the editor <em>nedit</em> is used.</li>
+          </ul>
+        </li>
+
+        <li>It reports the commit message and then asks if you want to proceed
+        (it aborts if not).</li>
+
+        <li>It calls <tt>svn commit</tt> to send the changes to the
+        repository.</li>
+
+        <li>It calls <tt>svn update</tt> to bring your working copy up to the
+        new revision.</li>
+      </ul>
+    </li>
+
+    <li>Subversion may prompt you for authentication if it is the first time you
+    access the repository. The command fails if the authentication fails. If you
+    specify the --non-interfactive option, Subversion will not prompt you for
+    authentication. In such case, the command will simply fail if authentication
+    is required. You can use the --password option to specify a password. Please
+    note that the --svn-non-interactive option is always specified if you are
+    running "commit" from the FCM GUI. If authentication is required, you should
+    specify your password using the --password option in "Other options".</li>
+
+    <li>The <tt>--dry-run</tt> switch prevents the command from committing any
+    changes. This can be used to allow you to add notes to your commit message
+    whilst you are still preparing your change.</li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_commit">Committing Changes</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>ci</p>
+
+  <h3><a name="fcm_svn_cf">fcm conflicts</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm conflicts [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm conflicts</tt> helps you to resolve any text files in your working
+  copy which have conflicts by using the graphical merge tool <em>xxdiff</em>.
+  If PATH is set, it must be a working copy, and the command will operate in
+  it. If PATH is not set, the command will operate in your current working
+  directory.</p>
+
+  <li>This command performs the following actions:
+
+    <ul>
+      <li>For each text file reported as being in conflict (i.e. marked with a
+      "C" by <tt>svn status</tt>) it calls <tt>xxdiff</tt>.</li>
+
+      <li>If <tt>xxdiff</tt> reports all conflicts resolved then if asks if
+      you wish to run <tt>svn resolved</tt> on that file.</li>
+    </ul>
+  </li>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_conflicts">Resolving Conflicts</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>cf</p>
+
+  <h3><a name="fcm_svn_rm">fcm delete</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm delete --check (-c)</p>
+
+  <p>fcm delete &lt;any valid <em>svn delete</em> options&gt;</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm delete</tt> supports all of the switches, arguments and alternate
+  names supported by <tt>svn delete</tt> (refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.delete.html">Subversion
+  book</a> for details).</p>
+
+  <ul>
+    <li>In addition, <tt>fcm delete</tt> supports a <tt>--check</tt> switch (no
+    other switches or arguments). When this is specified then <tt>fcm</tt>
+    checks for any files which are missing (i.e. marked with a "!" by <tt>svn
+    status</tt>) and prompts to see if you wish to schedule them for deletion
+    at the next commit (using <tt>svn delete</tt>).
+
+    <li>Subversion may prompt you for authentication if it is the first time
+    you access the repository. The command fails if the authentication fails.
+    If you specify the --non-interactive option, Subversion will not prompt
+    you for authentication. In such case, the command will simply fail if
+    authentication is required. Please note that the --non-interactive option
+    is automatically specified if you are running "delete" from the FCM GUI and
+    you have not checked the box "Check for files and directories...". If
+    authentication is required, you should run "delete" in interactive mode on
+    a command line.</li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_check">Adding and Removing Files</a>.</p>
+
+  <h3><a name="fcm_svn_diff">fcm diff</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm diff --branch (-b) [--graphical (-g)] [TARGET]</p>
+
+  <p>fcm diff [--graphical (-g)] &lt;any valid <em>svn diff</em> options&gt;</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm diff</tt> supports all of the switches, arguments and alternate
+  names supported by <tt>svn diff</tt> (refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.diff.html">Subversion
+  book</a> for details). In addition, <tt>fcm diff</tt> supports the following
+  switches:</p>
+
+  <ul>
+    <li>The <tt>--graphical</tt> switch uses <em>xxdiff</em> to display the
+    differences. This switch can be used in combination with any other
+    valid switch (including <tt>--branch</tt>).</li>
+
+    <li>The <tt>--branch</tt> switch shows differences relative to the parent.
+    This command performs the following actions:
+
+      <ul>
+        <li>If TARGET is specified, it must either be a URL or a path to a
+        local working copy. Otherwise, the current working directory must be a
+        working copy. The specified URL or that of the working copy must be a
+        valid branch in a standard FCM project.</li>
+
+        <li>It determines the base of the branch relative to its parent. This is
+        adjusted to account for any merges from the branch to its parent or
+        vice-versa.</li>
+
+        <li>It reports what path and revision it is comparing against.</li>
+
+        <li>It calls <tt>svn diff</tt> to report the differences between the
+        base and the specified branch (or working copy).</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_diff">Examining Changes</a>.</p>
+
+  <h3><a name="fcm_svn_merge">fcm merge</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm merge [--dry-run] [--non-interactive] [--verbose (-v)] SOURCE</p>
+
+  <p>fcm merge --custom --revision N[:M] [--dry-run] [--non-interactive]
+  [--verbose (-v)] SOURCE</p>
+
+  <p>fcm merge --custom [--dry-run] [--non-interactive] [--verbose (-v)]
+  URL1[@REV1] URL2[@REV2]</p>
+
+  <p>fcm merge --reverse --revision [M:]N [--dry-run] [--non-interactive]
+  [--verbose (-v)]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm merge</tt> allows you to merge changes from a source into your
+  working copy.</p>
+
+  <p>Before it begins, the command does the following:</p>
+
+  <ul>
+    <li>If a SOURCE/URL is specified, it can be a full URL or a partial URL
+    starting at the branches, trunk or tags level.
+
+      <ul>
+        <li>If a partial URL is given, and the path name does not begin with
+        "trunk", "tags" or "branches" then "branches/" is automatically
+        added to the beginning of your path.</li>
+      </ul>
+    </li>
+
+    <li>It determines the TARGET URL by examining your working copy.</li>
+
+    <li>If the current directory is not the top of your working copy, it
+    changes the current directory to the top of your working copy.</li>
+
+    <li>If your working copy is not pointing to a branch of a project
+    managed by FCM, the command aborts with an error.</li>
+
+    <li>If you do not specify the --non-interactive option, it checks for any
+    local modifications in your working copy. If it finds any it reports them
+    and asks you to confirm that you wish to continue (it aborts if not).</li>
+  </ul>
+
+  <p>If neither --custom nor --reverse is specified, the command defaults to the
+  automatic mode. Automatic merges are used to merge changes between two
+  directly related branches, (i.e. the branches must either be created from the
+  same parent or have a parent/child relationship). These merges are tracked by
+  FCM and can be used by subsequent FCM commands. The merge delta is calculated
+  by doing the following:</p>
+
+  <ul>
+    <li>It checks that the SOURCE and TARGET are directly related.</li>
+
+    <li>It determines the base revision and path of the <em>common
+    ancestor</em> of the SOURCE and TARGET.</li>
+
+    <li>The base revision and path are adjusted to account for any merges
+    from the SOURCE to the TARGET or vice-versa.</li>
+
+    <li>It reports the revisions from SOURCE available for merging into
+    TARGET. If the --verbose option is set, it prints the log for these
+    revisions. It aborts if no revision is available for merging.</li>
+
+    <li>If there are 2 or more revisions available for merging and you do not
+    specify the --non-interactive target, it asks you which revision of the
+    SOURCE you wish to merge from. The default is the last changed revision of
+    the SOURCE. The merge delta is between the base and the specified revision
+    of the SOURCE.</li>
+
+    <li>If your working copy is a sub-tree of the TARGET, it ensures that the
+    SOURCE contains only changes in the same sub-tree. Otherwise, the merge is
+    unsafe, and the command will abort with an error.
+
+     <p>N.B.: The command looks for changes in the SOURCE by going through the
+     list of changed files since the the SOURCE was last merged into the TARGET.
+     (If there is no previous merge from SOURCE to TARGET, the common ancestor
+     is used.) It is worth noting that there are situations when the command
+     will regard your merge as "unsafe" (and so will fail incorrectly) even if
+     the changes in the SOURCE outside of the current sub-tree will result in a
+     null merge. This can happen if the changes are the results of a previous
+     merge from the TARGET to the SOURCE or if these changes have been
+     reversed. In such case, you will have to perform your merge in a working
+     copy of a full tree.</p>
+    </li>
+  </ul>
+
+  <p>The --custom mode is useful if you need to merge changes selectively from
+  another branch. The custom mode can be used in two forms:
+  
+  <ul>
+    <li>In the first form, you must specify a SOURCE as well as a revision
+    (range) using the --revision option. If you specify a single revision N, the
+    merge delta is between revision N - 1 and revision N of the SOURCE.
+    Otherwise, the merge delta is between revision N and revision M, where N
+    &lt; M.</li>
+  
+    <li>In the second form, you must specify two URLs. The merge delta is simply
+    between the two URLs. (For each URL, if you do not specify a peg revision,
+    the command will peg the URL with its last changed revision.)</li>
+  </ul>
+  
+  <p>N.B. Unlike automatic merges, custom merges are not tracked or used by
+  subsequent FCM <tt>diff</tt> or <tt>merge</tt> commands, (although <tt>branch
+  --info</tt> can be set to report them). Custom merges are always allowed, even
+  if your working copy is pointing to a sub-tree of a branch. However, there is no
+  checking mechanism to ensure the safety of your sub-tree custom merge so you
+  should only do this if you are confident it is what you want.
+  Therefore, it is recommended that you use automatic merges where possible, and
+  use custom merges only if you know what you are doing.</p>
+
+  <p>The --reverse mode is useful if you need to reverse a changeset (or a range
+  of changesets) in the current branch of the working copy. In this mode, you
+  must specify a revision (range) using the --revision option. If you specify a
+  single revision N, the merge delta is between revision N and revision N - 1 of
+  the current branch. Otherwise, the merge delta is between revision M and
+  revision N, where M &gt; N.</p>
+
+  <p>N.B. Like custom merges, reverse merges are not tracked or used by
+  subsequent FCM <tt>diff</tt> or <tt>merge</tt> commands, (although <tt>branch
+  --info</tt> can be set to report them). Likewise, reverse merges in sub-trees
+  are always allowed, although there is no checking mechanism to ensure the safety of
+  your sub-tree reverse merge.</p>
+
+  <p>Once the merge delta is determined, the command performs the following:</p>
+
+  <ul>
+    <li>If you set the --dry-run option or if you are running in the interactive
+    mode, it reports what changes will result from performing this merge by
+    calling <tt>svn merge --dry-run</tt>.
+
+      <ul>
+        <li>It prints the actual <tt>svn merge --dry-run</tt> command if the
+        --verbose option is specified.</li>
+
+        <li>If you specify the --dry-run option, it exits after reporting what
+        changes will result from performing the merge.</li>
+      </ul>
+    </li>
+
+    <li>If you are running in the interactive mode, it asks if you want to go
+    ahead with the merge (it aborts if not).</li>
+
+    <li>It performs the merge by calling <tt>svn merge</tt> to apply the delta
+    between the base and the SOURCE on your working copy.
+
+      <ul>
+        <li>It prints the actual <tt>svn merge</tt> command if the --verbose
+        option is specified.</li>
+      </ul>
+    </li>
+
+    <li>It adds a standard template into the commit message to provide
+    details of the merge. The template is written below the line that says
+    "--This line will be ignored and those below will be inserted
+    automatically--". The <a href="fcm_svn_commit">fcm commit</a> command
+    will detect the existence of the template, so that you will not be able
+    to alter it by accident.
+
+      <ul>
+        <li>The commit message is stored in the file
+        <tt>#commit_message#</tt> in the top level of your working copy. It
+        is created by the merge command if it does not already exist.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_branching_merge">Merging</a>.</p>
+
+  <h3><a name="fcm_svn_mkpatch">fcm mkpatch</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm mkpatch [OPTIONS] URL [OUTDIR]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm mkpatch</tt> creates patches from the specified revisions of the
+  specified URL, which must be a branch URL of a valid FCM project. If the URL
+  is a sub-directory of a branch, it will use the root of the branch.</p>
+  
+  <p>If OUTDIR is specified, the output is sent to OUTDIR.  Otherwise, the
+  output will be sent to a default location in the current directory
+  (<tt>$PWD/fcm-mkpatch-out/</tt>). The output directory will contain the patch
+  for each revision as well as a script for importing the patch.</p>
+
+  <p>If a revision is specified using the <tt>--revision</tt> option, it will
+  attempt to create a patch based on the changes at that revision. If a revision
+  is not specified, it will attempt to create a patch based on the changes at
+  the HEAD revision. If a revision range is specified, it will attempt to create
+  a patch for each revision in that range (including the change in the lower
+  range) where changes have taken place in the URL. No output will be written if
+  there is no change in the given revision (range).</p>
+
+  <p>The <tt>--exclude</tt> option can be used to exclude a path in the URL. The
+  specified path must be a relative path of the URL. Glob patterns such as
+  <tt>*</tt> and <tt>?</tt> are acceptable. Changes in an excluded path will not
+  be considered in the patch. A changeset containing changes only in the
+  excluded path will not be considered at all.</p>
+
+  <p>The <tt>--organisation</tt> option can be used to specify the name of your
+  organisation. The command will attempt to parse the commit log message for
+  each revision in the patch. It will remove all merge templates, replace links
+  to Trac tickets with a simple string, and add information about the original
+  changeset. If you specify the name of your organisation, it will replace Trac
+  ticket links such as <tt>"ticket:123"</tt> to <tt>"Original $organisation
+  ticket 123"</tt>, and report the orginal changeset with a message such as
+  <tt>"Original $organisation changeset 1000"</tt>. Otherwise, it will report
+  without the organisation name, e.g. <tt>"Original ticket 123"</tt> and
+  <tt>"Original changeset 1000"</tt>.</p>
+
+  <p>Within the output directory are the "patches" and the log message file for
+  each revision. It also contains a generated script <tt>fcm-import-patch</tt>
+  for importing the patches. The user of the script can invoke the script with
+  either a URL or a working copy argument, and the script will attempt to import
+  the patches into the given URL or working copy.</p>
+
+  <p>It is worth noting that changes in Subversion properties, including changes
+  in executable permissions, are not handled by the import script.</p>
+
+  <h3><a name="fcm_svn_switch">fcm switch</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm switch [OPTIONS] URL [PATH]</p>
+
+  <p>fcm switch --relocate [OPTIONS] FROM TO [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm switch</tt> supports the arguments and alternate names supported by
+  <tt>svn switch</tt>. If <tt>--relocate</tt> is specified, it supports all
+  options supported by <tt>svn switch</tt>. Otherwise, it supports
+  <tt>--non-interactive</tt>, <tt>-r [--revision]</tt> and <tt>-q [--quiet]</tt>
+  only. (Please refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.branchmerge.switchwc.html">Subversion
+  book</a> for details).</p>
+
+  <p>If <tt>--relocate</tt> is specified, FCM will pass the options and
+  arguments directly to the corresponding Subversion command. Otherwise, FCM
+  will ensure that your working copy switches safely through the following
+  actions:</p>
+
+  <ul>
+    <li>If PATH (or the current working directory if PATH is not specified)
+    is not at the top of a working copy, the command will automatically
+    search for the top of the working copy, and the switch command will
+    always apply recursively from that level.</li>
+
+    <li>You can specify only the "branch" part of the URL, such as "trunk",
+    "branches/dev/fred/r1234_bob" or even "dev/fred/r1234_bob" and the
+    command will work out the full URL for you.</li>
+
+    <li>If you do not specify the --non-interactive option, it checks for any
+    local modifications in your working copy. If it finds any it reports them
+    and asks you to confirm that you wish to continue (it aborts if not).</li>
+
+    <li>If you have some template messages in the <tt>#commit_message#</tt> file
+    in the top level of your working copy, (e.g. after you have performed a
+    merge), the command will report an error. You should remove the template
+    message manually from the <tt>#commit_message#</tt> file before re-running
+    <tt>switch</tt>.</li>
+
+    <li>The command will analyse the current working copy URL and the
+    specified URL to ensure that they are in the same project. If your
+    working copy is a sub-tree of a project, the command will assume that
+    you want the same sub-tree in the new URL.</li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_branching_switch">Switching your working copy to
+  point to another branch</a>.</p>
+
+  <h3><a name="fcm_svn_trac">fcm trac</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm trac [--browser (-b) ARG] [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm trac</tt> invokes the web-browser to launch the corresponding
+  URL of the web-based repository browser (currently Trac browser) to view
+  the Subversion repository specified by PATH.</p>
+
+  <ul>
+    <li>If the --browser or -b option is specified, ARG must be a valid command
+    to a web browser. If this option is not specified, the default is to use
+    "firefox", or whatever setting you have declared in the user configuration
+    file (<tt>$HOME/.fcm</tt>) using the label "SET::MISC::WEB_BROWSER". For
+    example:
+
+      <pre>
+set::misc::web_browser  mozilla
+</pre>
+    </li>
+
+    <li>If PATH is specified, it must be a path to a local working copying, a
+    Subversion URL or a FCM URL keyword. If PATH is not specified, it is set to
+    ".", the current working directory. If PATH is a directory in the local
+    file system, the command will determine whether it is a working copy. If
+    so, its associated Subversion URL will be used. The command fails if the
+    directory is not a working copy. If PATH is a Subversion URL or a FCM URL
+    keyword, the URL can be "pegged" with a revision number using the "@"
+    symbol. For example, to view the trunk of the FCM repository at revision
+    400, you can use "fcm:fcm_tr@400". The URL declared by or associated with
+    PATH must also be associated with a Trac browser URL, which is declared
+    using the "SET::TRAC::&lt;pck&gt;" label in the FCM central/user
+    configuration file. The command fails if an associated Trac browser URL is
+    not found.</li>
+  </ul>
+
+  <h4>Alternate Names</h4>
+
+  <p>www</p>
+
+  <h3><a name="fcm_svn_other">Other Subversion Commands</a></h3>
+
+  <p>Other <tt>svn</tt> commands are supported by <tt>fcm</tt> without
+  any change in functionality, with the following minor enhancements:</p>
+
+  <ul>
+    <li>Where appropriate, FCM performs repository and revision keywords
+    expansion.</li>
+
+    <li>The <tt>fcm checkout</tt> command fails if you attempt to checkout into
+    an existing working copy.</li>
+
+    <li>FCM prints the corresponding <tt>svn</tt> command, except for
+    <tt>cat</tt> and any commands with the <tt>--xml</tt> option specified.</li>
+  </ul>
+  
+  <p>The following is a list of the commands:</p>
+
+  <ul>
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.blame.html">svn
+    blame</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.cat.html">svn
+    cat</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.checkout.html">svn
+    checkout</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.cleanup.html">svn
+    cleanup</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.copy.html">svn
+    copy</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.export.html">svn
+    export</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.import.html">svn
+    import</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.info.html">svn
+    info</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.list.html">svn
+    list</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.log.html">svn
+    log</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.lock.html">svn
+    lock</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.mkdir.html">svn
+    mkdir</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.move.html">svn
+    move</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propdel.html">svn
+    propdel</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propedit.html">svn
+    propedit</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propget.html">svn
+    propget</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.proplist.html">svn
+    proplist</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propset.html">svn
+    propset</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.resolved.html">svn
+    resolved</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.revert.html">svn
+    revert</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.status.html">svn
+    status</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.unlock.html">svn
+    unlock</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.update.html">svn
+    update</a></li>
+  </ul>
+
+  <p>Please refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.html">Subversion book</a> for
+  details of these commands.</p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/extract.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/extract.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/extract.html	(revision 329)
@@ -0,0 +1,1118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: The Extract System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - The Extract System">
+  <meta name="keywords" content="FCM, user guide, extract, build">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; The Extract System
+  </address>
+
+  <h1>The Extract System</h1>
+
+  <p>The extract system provides an interface between the revision control
+  system (currently Subversion) and the build system. Where appropriate, it
+  extracts code from the repository and other user-defined locations to a
+  directory tree suitable for feeding into the build system. In this chapter,
+  we shall use many examples to explain how to use the extract system. At the
+  end of this chapter, you will be able to extract code from the local file system
+  as well as from different branches of different repository URLs. You will
+  also learn how to mirror code to a remote machine. Finally, you will be given
+  an introduction on how to specify configurations for the build system via the
+  extract configuration file. (For further information on the build system,
+  please see the next chapter <a href="build.html">The Build System</a>.) The
+  last section of the chapter tells you what you can do in the case when
+  Subversion is not available.</p>
+
+  <h2><a name="command">The Extract Command</a></h2>
+
+  <p>To invoke the extract system, simply issue the command:</p>
+  <pre>
+fcm extract
+</pre>
+
+  <p>By default, the extract system searches for an extract configuration file
+  "ext.cfg" in "$PWD" and then "$PWD/cfg". If an extract configuration file is
+  not found in these directories, the command fails with an error. If an
+  extract configuration file is found, the system will use the configuration
+  specified in the file to perform the current extraction.</p>
+
+  <p>If the destination of the extraction does not exist, the system performs a
+  new full extraction to the destination. If a previous extraction already
+  exists at the destination, the system performs an incremental extraction,
+  updating any modifications if necessary. If a full (fresh) extraction is
+  required for whatever reason, you can invoke the extract system using the
+  "-f" option, (i.e. the command becomes "fcm extract -f"). For further
+  information on the extract command, please see <a href=
+  "command_ref.html#fcm_ext">FCM Command Reference &gt; fcm extract</a>.</p>
+
+  <h2><a name="simple">Simple Usage</a></h2>
+
+  <p>The extract configuration file is the main user interface of the extract
+  system. It is a line based text file. For a complete set of extract
+  configuration file declarations, please refer to the <a href=
+  "annex_ext_cfg.html">Annex: Declarations in FCM extract configuration
+  file</a>.</p>
+
+  <h3><a name="simple_local">Extract from a local path</a></h3>
+
+  <p>A simple example of a basic extract configuration file is given below:</p>
+
+  <table class="pad" summary="extract_example1" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 1 - extract from a local path</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type         ext       # line 1
+cfg::version      1.0       # line 2
+                            # line 3
+dest::rootdir     $PWD      # line 4
+                            # line 5
+repos::var::user  $HOME/var # line 6
+                            # line 7
+expsrc::var::user code      # line 8
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The above demonstrates how to use the extract system to extract code from
+  a local user directory. Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 1: the label "CFG::TYPE" declares the type of the configuration
+    file. The value "ext" tells the system that it is an extract configuration
+    file.</li>
+
+    <li>line 2: the label "CFG::VERSION" declares the version of the extract
+    configuration file. The current default is "1.0". Although it is not
+    currently used, if we have to change the format of the configuration file
+    at a later stage, we shall be able to use this number to determine whether
+    we are reading a file with an older format or one with a newer format.</li>
+
+    <li>line 3: a blank line or a line beginning with a "#" is a comment, and
+    is ignored by the interpreter.</li>
+
+    <li>line 4: the label "DEST::ROOTDIR" declares the destination root
+    directory of this extraction. The value "$PWD" expands to the current
+    working directory.</li>
+
+    <li>line 5: comment line, ignored.</li>
+
+    <li>line 6: the label "REPOS::&lt;pck&gt;::&lt;branch&gt;" declares the top
+    level URL or path of a repository. The package name of the repository is
+    given by &lt;pck&gt;. In our example, we choose "var" as the name of the
+    package. (You can choose any name you like, however, it is usually sensible
+    to use a package name that matches the name of the project or system you are
+    working with.) The branch name in the repository is given by &lt;branch&gt;.
+    (Again, you can choose any name you like, however, it is usually sensible to
+    use a name such as "trunk", "user" or something that matches your branch
+    name.) In our example, the word "user" is normally used to denote a local
+    user directory. Hence the statement declares that the repository path for
+    the "var" package in the "user" branch can be found at "$HOME/var".</li>
+
+    <li>line 7: comment line, ignored.</li>
+
+    <li>line 8: the label "EXPSRC::&lt;pck&gt;::&lt;branch&gt;" declares an
+    "expandable" source directory for the package &lt;pck&gt; in the branch
+    &lt;branch&gt;. In our example, the package name is "var", and the branch
+    name is "user". These match the package and the branch names of the
+    repository declaration in line 6. It means that the source directory
+    declaration is associated with the path "$HOME/var". The value of the
+    declaration "code" is therefore a sub-directory under "$HOME/var". By
+    declaring a source directory using an "expsrc" label, the system
+    automatically searches for all sub-directories (recursively) under the
+    declared source directory.</li>
+  </ul>
+
+  <p>Invoking the extract system using the above configuration file will
+  "extract" all sub-directories under "$HOME/var/code" to "$PWD/src/var/code".
+  Note: the extract system ignores all hidden files, (i.e. directories and
+  files beginning with a "."). It will write a build configuration file to
+  "$PWD/cfg/bld.cfg". The configuration used for this extraction will be
+  written to the configuration file at "$PWD/cfg/ext.cfg".</p>
+
+  <table class="pad" summary="note - incremental extraction" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - incremental extraction</th>
+    </tr>
+
+    <tr>
+      <td>Suppose you have already performed an extraction using the above
+      configuration file. At a later time, you have made some changes to some
+      of the files in the source directory. Re-running the extract system on
+      the same configuration will trigger an incremental extraction. In an
+      incremental extraction, the system will update only those files that are
+      modified. In exact words, the system checks the modification time of each
+      file in the source and destination. If a source file is newer than its
+      corresponding destination file, it checks whether the content differs.
+      The destination is only updated if its content differs from the
+      source.</td>
+    </tr>
+  </table>
+
+  <h3><a name="simple_url">Extract from a Subversion URL</a></h3>
+
+  <p>The next example demonstrates how to extract from a Subversion repository
+  URL:</p>
+
+  <table class="pad" summary="extract_example2" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 2 - extract from a Subversion URL</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext                    # line 1
+cfg::version        1.0                    # line 2
+                                           # line 3
+dest::rootdir       $PWD                   # line 4
+                                           # line 5
+repos::var::trunk   svn://server/var/trunk # line 6
+version::var::trunk 1234                   # line 7
+                                           # line 8
+expsrc::var::trunk  code                   # line 9
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <ul>
+    <li>line 1 to 5: same as example 1.</li>
+
+    <li>line 6: the line declares the repository location of the "trunk" branch
+    of the "var" package to be the Subversion URL
+    "svn://server/var/trunk".</li>
+
+    <li>line 7: the label "VERSION::&lt;pck&gt;::&lt;branch&gt;" declares the
+    revision of the repository associated with the package &lt;pck&gt; in the
+    branch &lt;branch&gt;. The current line tells the extract system to use
+    revision 1234 of "svn://server/var/trunk". If the revision is not declared,
+    the default revision "HEAD" will be assumed.</li>
+
+    <li>line 8: comment line, ignored.</li>
+
+    <li>line 9: the line declares an expandable source directory in the
+    repository "svn://server/var/trunk".</li>
+  </ul>
+
+  <p>Invoking the extract system using the above configuration file will
+  extract all sub-directories under "svn://server/var/trunk/code" to
+  "$PWD/src/var/code". It will write a build configuration file to
+  "$PWD/cfg/bld.cfg". The configuration used for this extraction will be
+  written to the configuration file at "$PWD/cfg/ext.cfg".</p>
+
+  <table class="pad" summary=
+  "note - declaration of source directories for extraction" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - declaration of source directories for extraction</th>
+    </tr>
+
+    <tr>
+      <td>
+        <strong>EXPSRC or SRC?</strong>
+
+        <p>So far, we have only declared source directories using the "EXPSRC"
+        statement, which stands for "expandable source directory". A source
+        directory declared using this statement will trigger the system to
+        search recursively for any sub-directories under the declared one. Any
+        sub-directories containing regular source files will be included in the
+        extraction. Empty directories, hidden directories and directories
+        containing only hidden files are ignored.</p>
+
+        <p>If you do not want the system to search for sub-directories
+        underneath your declared source directory, you can declare your source
+        directory using the "SRC" statement. The "SRC" statement is essentially
+        the same as "EXPSRC" except that it does not trigger the automatic
+        recursive search for source directories. In fact, the system implements
+        the "EXPSRC" statement by expanding it into a list of "SRC"
+        statements.</p>
+
+        <p><strong>Package and sub-package</strong></p>
+
+        <p>The second field of a repository, revision or source directory
+        declaration label is the name of the container package. It is a name
+        selected by the user to identify the system or project he/she is
+        working on. (Therefore, it is often sensible to choose an identifier
+        that matches the name of the project or system.) The package name
+        provides a unique namespace for a file container. Source directories
+        are automatically arranged into sub-packages, using the names of the
+        sub-directories as the names of the sub-packages. For example, the
+        declaration at line 9 in example 2 will put the source directory in the
+        "var::code" sub-package automatically.</p>
+
+        <p>The double colon "::" and the double underscore "__" (internal only)
+        are delimiters for package names in the extract system. Please avoid
+        using "::" and "__" for naming your files and directories.</p>
+
+        <p>You can declare a sub-package name explicitly in your source
+        directory statement. For example, the following two lines are
+        equivalent:</p>
+        <pre>
+src::var::trunk                        code/VarMod_Surface
+src::var::code::VarMod_Surface::trunk  code/VarMod_Surface
+</pre>
+
+        <p>Explicit sub-package declaration should not be used normally, as it
+        requires a lot more typing (although there are some situations where it
+        can be useful).</p>
+      </td>
+    </tr>
+  </table>
+
+  <table class="pad" summary="note - the expanded extract configuration file"
+  border="1" width="100%">
+    <tr>
+      <th>Note - the expanded extract configuration file</th>
+    </tr>
+
+    <tr>
+      <td>
+        At the end of a successful extraction, the configuration used by the
+        current extraction is written in "cfg/ext.cfg" under the extract
+        destination root. This file is an "expanded" version of the original,
+        with changes in the following declarations:
+
+        <ul>
+          <li>All revision keywords are converted into revision numbers.</li>
+
+          <li>If a revision is not defined for a repository, it is set to the
+          corresponding revision number of the HEAD revision.</li>
+
+          <li>All URL keywords are converted into the full URLs.</li>
+
+          <li>All EXPSRC declarations are expanded into SRC declarations.</li>
+
+          <li>All other variables are expanded.</li>
+        </ul>
+
+        <p>With this file, it should be possible for later extraction to
+        re-create the current configuration even if the contents of the
+        repository have changed. (This applies only to code stored in the
+        repository.)</p>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="simple_mirror">Mirror code to a remote machine</a></h3>
+
+  <p>The next example demonstrates how to extract from a repository and mirror
+  the code to a remote machine. It is essentially the same as example 2,
+  except that it has three new lines to describe how the system can mirror the
+  extracted code to a remote machine.</p>
+
+  <table class="pad" summary="extract_example3" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 3 - mirror code to remote machine</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext
+cfg::version        1.0
+
+dest::rootdir       $PWD
+
+rdest::machine      tx01                           # line 6
+rdest::logname      frva                           # line 7
+rdest::rootdir      /scratch/frva/extract/example3 # line 8
+
+repos::var::trunk   svn://server/var/trunk
+version::var::trunk 1234
+
+expsrc::var::trunk  code
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 6: "RDEST::MACHINE" declares the target machine to which the code
+    will be mirrored. The example mirrors the code to the machine named
+    "tx01".</li>
+
+    <li>line 7: "RDEST::LOGNAME" declares the remote user name of the target
+    machine, to which the user has remote login access. If this is not
+    declared, the system uses the login name of the current user on the local
+    machine.</li>
+
+    <li>line 8: "RDEST::ROOTDIR" declares the root directory of the extraction
+    on the remote target machine. This is where the mirror version of the
+    extraction will be sent.</li>
+  </ul>
+
+  <p>Invoking the extract system on the above configuration will trigger an
+  extraction similar to that given in example 2, but it will also attempt to
+  mirror the contents at "$PWD/src/var/code" to
+  "/scratch/frva/extract/example3/src" on the remote machine. It will also
+  mirror the expanded extract configuration file "$PWD/cfg/ext.cfg" to
+  "/scratch/frva/extract/example3/cfg/ext.cfg" and "$PWD/cfg/bld.cfg" to
+  "/scratch/frva/extract/example3/cfg/bld.cfg". It is also worth noting that
+  the content of the build configuration file will be slightly different, since
+  it will include directory names appropriate for the remote system.</p>
+
+  <table class="pad" summary="note - mirroring command" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - mirroring command</th>
+    </tr>
+
+    <tr>
+      <td>
+        The extract system currently supports "rdist" and "rsync" as its
+        mirroring tool. The default is "rsync". To use "rdist" instead of
+        "rsync", add the following line to your "$HOME/.fcm" file:
+        <pre>
+set::tool::mirror  rdist
+</pre>
+
+        <p>N.B. If you are going to mirror code to another machine, you need to
+        ensure that your account on the remote machine is set up correctly to
+        accept commands from the local machine. In our current settings of both
+        "rdist" and "rsync", all you need to do is set up your "$HOME/.rhosts"
+        file on the remote machine. For example, if you are "fred" working on
+        the local machine "eld001", you will need to have the following entry
+        in your "$HOME/.rhosts" on the remote machine:</p>
+        <pre>
+eld001  fred
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="advanced">Advanced Usage</a></h2>
+
+  <h3><a name="advanced_multi">Extract from multiple repositories</a></h3>
+
+  <p>So far, we have only extracted from a single location. The extract system
+  is not much use if that is the only thing it can do. In fact, the extract
+  system supports extraction of multiple source directories from multiple
+  branches in multiple repositories. The following configuration file is an
+  example of how to extract from multiple repositories:</p>
+
+  <table class="pad" summary="extract_example4" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 4 - extract from multiple
+      repositories</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext
+cfg::version        1.0
+
+dest::rootdir       $PWD
+
+repos::var::trunk   fcm:var_tr              # line 6
+repos::ops::trunk   fcm:ops_tr              # line 7
+repos::gen::trunk   fcm:gen_tr              # line 8
+
+version::gen::trunk 2468                    # line 10
+
+expsrc::var::trunk  code                    # line 12
+expsrc::var::trunk  scripts                 # line 13
+expsrc::ops::trunk  code                    # line 14
+src::gen::trunk     code/GenMod_Constants   # line 15
+src::gen::trunk     code/GenMod_Control     # line 16
+src::gen::trunk     code/GenMod_FortranIO   # line 17
+src::gen::trunk     code/GenMod_GetEnv      # line 18
+src::gen::trunk     code/GenMod_ModelIO     # line 19
+src::gen::trunk     code/GenMod_ObsInfo     # line 20
+src::gen::trunk     code/GenMod_Platform    # line 21
+src::gen::trunk     code/GenMod_Reporting   # line 22
+src::gen::trunk     code/GenMod_Trace       # line 23
+src::gen::trunk     code/GenMod_UMConstants # line 24
+src::gen::trunk     code/GenMod_Utilities   # line 25
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 6 to 8: these lines declare the repositories for the "trunk"
+    branches of the "var", "ops" and "gen" packages respectively. It is worth
+    noting that the values of the declarations are no longer Subversion URLs
+    but are FCM URL keywords. These keywords are normally declared in the
+    central configuration file of the FCM system, and will be expanded into the
+    corresponding Subversion URLs by the FCM system. For further information on
+    URL keywords, please see <a href=
+    "code_management.html#svn_basic_keywords">Code Management System &gt; Using
+    Subversion &gt; Basic Command Line Usage &gt; Repository &amp; Revision
+    Keywords</a>.</li>
+
+    <li>line 10: this line declares the revision number for the "trunk" branch
+    of the "gen" package, i.e. for the "fcm:gen_tr" repository. It is worth
+    noting that the revision numbers for the "var" and "ops" packages have not
+    been declared. By default, their revision numbers will be set to
+    "HEAD".</li>
+
+    <li>line 12 to 14: these line declares the source directories for the
+    "trunk" branches of the "var" and "ops" packages. For the "var" package, we
+    are extracting everything from the "code" and the "scripts" sub-directory.
+    For the "ops" package, we are extracting everything from the "code"
+    directory.</li>
+
+    <li>line 15 to 25: these line declares the source directories for the
+    "trunk" branch of the "gen" package. The source directories declared will
+    not be searched for sub-directories underneath the declared
+    directories.</li>
+  </ul>
+
+  <p>We shall end up with a directory tree such as:</p>
+  <pre>
+$PWD
+   |
+   |--- cfg
+   |      |
+   |      |--- bld.cfg
+   |      |--- ext.cfg
+   |
+   |--- src
+          |
+          |--- gen
+          |      |
+          |      |--- code
+          |              |
+          |              |--- GenMod_Constants
+          |              |--- GenMod_Control
+          |              |--- GenMod_FortranIO
+          |              |--- GenMod_GetEnv
+          |              |--- GenMod_ModelIO
+          |              |--- GenMod_ObsInfo
+          |              |--- GenMod_Platform
+          |              |--- GenMod_Reporting
+          |              |--- GenMod_Trace
+          |              |--- GenMod_UMConstants
+          |              |--- GenMod_Utilities
+          |
+          |--- ops
+          |      |
+          |      |--- code
+          |              |
+          |              |--- ...
+          |
+          |--- var
+                 |
+                 |--- code
+                 |       |
+                 |       |--- ...
+                 |
+                 |--- scripts
+                         |
+                         |--- ...
+</pre>
+
+  <table class="pad" summary="note - revision number" border="1" width="100%">
+    <tr>
+      <th>Note - revision number</th>
+    </tr>
+
+    <tr>
+      <td>
+        As seen in the above example, if a revision number is not specified for
+        a repository URL, it defaults to the "HEAD" revision. The revision
+        number can also be declared in other ways:
+
+        <ul>
+          <li>Any revision arguments acceptable by Subversion are allowed. You
+          can use a valid revision number, a date between a pair of curly
+          brackets (e.g. {"2005-05-01 12:00"}) or the keyword "HEAD". However,
+          please do not use the keywords "BASE", "COMMITTED" or "PREV" as these
+          are reserved for working copy only.</li>
+
+          <li>FCM revision keywords are allowed. These must be defined for the
+          corresponding repository URLs in either the central or the user FCM
+          configuration file. For further information on revision keywords,
+          please see <a href="code_management.html#svn_basic_keywords">Code
+          Management &gt; Using Subversion &gt; Basic Command Line Usage &gt;
+          Repository &amp; Revision Keywords</a>.</li>
+
+          <li>Do not use the keyword "USER", as it is used internally by the
+          extract system.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="advanced_branches">Extract from multiple branches</a></h3>
+
+  <p>We have so far dealt with extraction from a single branch in any package.
+  The extract system can be used to "combine" changes from different branches
+  of a package. An example is given below:</p>
+
+  <table class="pad" summary="extract_example5" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 5 - extract from multiple branches</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type               ext
+cfg::version            1.0
+ 
+dest::rootdir           $PWD
+ 
+repos::var::trunk       fcm:var_tr
+repos::ops::trunk       fcm:ops_tr
+repos::gen::trunk       fcm:gen_tr
+ 
+version::gen::trunk     2468
+ 
+expsrc::var::trunk      code
+expsrc::var::trunk      scripts
+expsrc::ops::trunk      code
+src::gen::trunk         code/GenMod_Constants
+src::gen::trunk         code/GenMod_Control
+src::gen::trunk         code/GenMod_FortranIO
+src::gen::trunk         code/GenMod_GetEnv
+src::gen::trunk         code/GenMod_ModelIO
+src::gen::trunk         code/GenMod_ObsInfo
+src::gen::trunk         code/GenMod_Platform
+src::gen::trunk         code/GenMod_Reporting
+src::gen::trunk         code/GenMod_Trace
+src::gen::trunk         code/GenMod_UMConstants
+src::gen::trunk         code/GenMod_Utilities
+
+repos::var::new_stuff   fcm:var_br/frva/r1234_new_stuff   # line 27
+repos::var::bug_fix     fcm:var_br/frva/r1516_bug_fix     # line 28
+repos::ops::good_stuff  fcm:ops_br/opsrc/r3188_good_stuff # line 29
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The configuration file in example 5 is similar to that of example 4 except
+  for the last three lines. Here is an explanation of what they do:</p>
+
+  <ul>
+    <li>line 27: this line declares a repository URL for the "new_stuff" branch
+    of the "var" package. From the URL of the branch, we know that the branch
+    was created by the user "frva" based on the trunk at revision at 1234. The
+    description of the branch is "new_stuff". The following points are worth
+    noting:
+
+      <ul>
+        <li>By declaring a new branch with the same package name to a
+        previously declared branch, it is assumed that both branches reside in
+        the same Subversion repository.</li>
+
+        <li>It is only by convention that the branch name "new_stuff" declared
+        using the "REPOS::var::new_stuff" label should correspond to the branch
+        description of the URL. It is not a requirement by the extract system.
+        It is perfectly valid to use "REPOS::var::ham_egg" as the label of line
+        27. In such case, the extract system will use "ham_egg" instead of
+        "new_stuff" as the internal label of the URL.</li>
+
+        <li>No revision is declared for this URL, so the default "HEAD"
+        revision is used.</li>
+
+        <li>No source directory is declared for this URL. By default, if no
+        source directory is declared for a branch repository, it will attempt
+        to use the same set of source directories as the first declared branch
+        of the package. In this case, the source directories declared for the
+        "trunk" branch of the "var" package will be used.</li>
+      </ul>
+    </li>
+
+    <li>line 28: this line declares another branch called "bug_fix" for the
+    "var" package. No source directory is declared for this URL either, so it
+    will use the same set of source directories declared for the "trunk"
+    branch.</li>
+
+    <li>line 29: this line declares a branch called "good_stuff" for the "ops"
+    package. It will use the same set of source directories declared for the
+    "ops" package "trunk" branch.</li>
+  </ul>
+
+  <p>When we invoke the extract system, it will attempt to extract from the
+  first declared branch of a package, if the last commit revision of the source
+  directory is the same in all the branches. However, if the last commit
+  revision of the source directory differs for different branches, the system
+  will attempt to obtain an extract priority list for each source directory,
+  using the following logic:</p>
+
+  <ol>
+    <li>The system looks for source directory packages from the first declared
+    branch to the last declared branch.</li>
+
+    <li>The branch in which a source directory package is first declared is
+    the "base" branch of the source directory package.</li>
+
+    <li>The commit revision of a source directory package in a subsequently
+    declared repository branch is compared with that of the base branch. If
+    the commit revision is the same as that of the base branch, the source
+    directory of this branch is discarded. Otherwise, it is placed at the end
+    of the extract priority list.</li>
+  </ol>
+
+  <p>For the "var" package in the above example, let us assume that we have
+  three source directory packages X, Y and Z under "code", and their commit
+  revisions under "trunk" are 100. Let's say we have committed some changes to
+  X and Z in the "new_stuff" branch at revision 102, and other changes to Y
+  and Z in the "bug_fix" branch at revision 104, the extract priority lists
+  for X, Y and Z will look like:</p>
+
+  <ul>
+    <li>X: trunk (100, base), new_stuff (102), bug_fix (100, discarded)</li>
+
+    <li>Y: trunk (100, base), new_stuff (100, discarded), bug_fix (104)</li>
+
+    <li>Z: trunk (100, base), new_stuff (102), bug_fix (104)</li>
+  </ul>
+
+  <p>Once we have an extract priority list for a source directory, we can
+  begin the extraction of source files in the source directory. The source
+  directory of the base branch is extracted first, followed by that in the
+  subsequent branches. If a source file in a subsequent branch has the same
+  content as the that in the base branch, it is discarded. Otherwise, the
+  following logic determines the branch to use:</p>
+
+  <ol>
+    <li>If a source file is modified in only one subsequent branch, the source
+    file in that branch is extracted.</li>
+
+    <li>If a source file is modified in two or more subsequent branches, but
+    their modifications are the same, then the source file in the first
+    modification is used.</li>
+
+    <li>If a source file is modified in two or more subsequent branches and
+    their modifications differ, then the behaviour depends on the override
+    mode setting. If override mode is false, the extraction fails. Otherwise,
+    the file in the latest declared branch takes precedence. The default
+    override mode is false, which is the safe behaviour - conflicting changes
+    should be resolved manually. However, this behaviour may not be the most
+    efficient way for development. Therefore, an override mode is provided,
+    which should be used with care. To switch on the override mode, make the
+    following declaration in the extract configuration file:
+      <pre>
+override  1
+</pre>
+    </li>
+  </ol>
+  
+  <p>Once the system has established which source files to use, it determines
+  whether the destination is out of date or not. The destination is out of
+  date if the source file does not exist or if its content differs from the
+  version of the source file we are using. The system only updates the
+  destination if it is considered to be out of date.</p>
+
+  <p>The extract system can also combine changes from branches in the Subversion
+  repository and the local file system. The limitation is that there can only
+  be one branch from the local file system. (By convention, the branch is named
+  "user".)</p>
+
+  <p>It is also worth bearing in mind that the "user" branch always takes
+  precedence over branches residing in Subversion repositories. Hence, source
+  directories from a "user" branch are always placed at the end of the extract
+  priority list.</p>
+
+  <p>Extracting from a mixture of Subversion repository and local file system
+  is demonstrated in the next example.</p>
+
+  <table class="pad" summary="extract_example6" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 6 - extract from multiple branches +
+      user paths</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type               ext
+cfg::version            1.0
+ 
+dest::rootdir           $PWD
+  
+repos::var::trunk       fcm:var_tr
+repos::ops::trunk       fcm:ops_tr
+repos::gen::trunk       fcm:gen_tr
+ 
+version::gen::trunk     2468
+ 
+expsrc::var::trunk      code
+expsrc::var::trunk      scripts
+expsrc::ops::trunk      code
+src::gen::trunk         code/GenMod_Constants
+src::gen::trunk         code/GenMod_Control
+src::gen::trunk         code/GenMod_FortranIO
+src::gen::trunk         code/GenMod_GetEnv
+src::gen::trunk         code/GenMod_ModelIO
+src::gen::trunk         code/GenMod_ObsInfo
+src::gen::trunk         code/GenMod_Platform
+src::gen::trunk         code/GenMod_Reporting
+src::gen::trunk         code/GenMod_Trace
+src::gen::trunk         code/GenMod_UMConstants
+src::gen::trunk         code/GenMod_Utilities
+
+repos::var::new_stuff   fcm:var_br/frva/r1234_new_stuff
+repos::var::bug_fix     fcm:var_br/frva/r1516_bug_fix
+repos::ops::good_stuff  fcm:ops_br/opsrc/r3188_good_stuff
+
+repos::var::user        $HOME/var/src                     # line 31
+repos::gen::user        $HOME/gen/src                     # line 32
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Example 6 is similar to example 5 except that it is also extracting from
+  local directories. Here is an explanation of the lines:</p>
+
+  <ul>
+    <li>line 31 to 32: these line declare the "repositories" for the "user"
+    branches of the "var" and "gen" packages respectively. Both are local paths
+    at the local file system. There are no declarations for source directories
+    for the "user" branches, so they use the same set of source directories of
+    the first declared branches, the "trunk" branches in both cases.</li>
+  </ul>
+
+  <table class="pad" summary="note - the inc statement" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - the INC declaration</th>
+    </tr>
+
+    <tr>
+      <td>
+        You have probably realised that the above examples have many repeated
+        lines. To avoid having repeated lines in multiple extract configuration
+        files, you can use INC declarations to "include" other extract
+        configuration files. For example, if the configuration file of example 5
+        is stored in the file "$HOME/var/example5/ext.cfg", line 1 to 29 of
+        example 6 can be replaced with an INC declaration. Example 6 can then be
+        written as:
+        <pre>
+inc                     $HOME/var/example5/ext.cfg
+
+repos::var::user        $HOME/var/src
+repos::gen::user        $HOME/gen/src
+</pre>
+
+        <p>Note: the INC declaration supports the special "environment variable"
+        $HERE. If this variable is already set in the environment, it acts as a
+        normal environment variable. However, if it is not set, it will be
+        expanded into the container directory of the current extract
+        configuration file. This feature is particularly useful if you are
+        including a hierarchy of extract configurations from files in the same
+        container directory in a repository.</p>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="advanced_incremental">Incremental extract based on a previous
+  extraction</a></h3>
+
+  <p>All the examples above dealt with standalone extraction, that is, the
+  current extraction is independent of any other extraction. If a previous
+  extraction exists in another location, the extract system can "USE" this
+  previous extraction in your current extraction. This works like a normal
+  incremental extraction, except that your extraction will only contain the
+  changes you have specified (compared with the USEd extraction) instead of the
+  full source directory tree. This type of incremental extraction is useful in
+  several ways. For instance:</p>
+
+  <ul>
+    <li>The extraction is fast, because you only have to extract and mirror
+    files that you have changed.</li>
+
+    <li>The subsequent build will also be fast, since it will use incremental
+    build.</li>
+
+    <li>You do not need write access to the original extraction. A system
+    administrator can set up a stable version in a central account, which
+    developers can then reuse.</li>
+
+    <li>You want an incremental extraction, but you need to leave the original
+    extraction unmodified.</li>
+  </ul>
+
+  <p>The following example is based on example 4 and 6. The assumption is that
+  an extraction has already been performed at the directory "~frva/var/vn22.0"
+  based on the configuration file in example 4.</p>
+
+  <table class="pad" summary="extract_example7" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 7 - incremental extract based on a
+      previous extraction</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type               ext
+cfg::version            1.0
+ 
+dest::rootdir           $PWD
+
+use                     ~frva/var/vn22.0                  # line 6
+
+repos::var::new_stuff   fcm:var_br/frva/r1234_new_stuff   # line 8
+repos::var::bug_fix     fcm:var_br/frva/r1516_bug_fix     # line 9
+repos::ops::good_stuff  fcm:ops_br/opsrc/r3188_good_stuff # line 10
+
+repos::var::user        $HOME/var/src                     # line 12
+repos::gen::user        $HOME/gen/src                     # line 13
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <ul>
+    <li>line 6: this line replaces line 1 to 25 of example 6. It declares that
+    the current extraction should be based on the previous extraction located
+    at "~frva/var/vn22.0".</li>
+  </ul>
+
+  <p>Running the extract system using the above configuration will trigger an
+  incremental extraction, as if you are running an incremental extraction
+  having modified the configuration file in example 4 to that of example 6. The
+  only difference is that the original extraction using the example 4
+  configuration will be left untouched at "~frva/var/vn22.0", and the new
+  extraction will contain only the changes in the branches declared from line 8
+  to 13.</p>
+
+  <p>If you are setting up an extraction to be reused, you do not have to
+  perform a build. If you don't you will still gain the benefit of incremental
+  file extraction, but you will be performing a full build of the code.</p>
+
+  <h3><a name="advanced_build">Extract - Build Configuration</a></h3>
+
+  <p>Configuration settings for feeding into the build system can be declared
+  through the extract configuration file using the "BLD::" prefix. Any line in
+  an extract configuration containing a label with such a prefix will be
+  considered a build system variable. At the end of a successful extraction,
+  the system strips out the "BLD::" prefix before writing these variables to
+  the build configuration file. Some example entries are given between line 17
+  and 22 in the following configuration file:</p>
+
+  <table class="pad" summary="extract_example8" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 8 - setting build configuration</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext
+cfg::version        1.0
+
+dest::rootdir       $PWD
+
+repos::var::trunk   fcm:var_tr
+repos::ops::trunk   fcm:ops_tr
+repos::gen::trunk   fcm:gen_tr
+
+version::gen::trunk 2468
+
+expsrc::var::trunk  code
+expsrc::var::trunk  scripts
+expsrc::ops::trunk  code
+src::gen::trunk     code/GenMod_Constants
+src::gen::trunk     code/GenMod_Control
+src::gen::trunk     code/GenMod_FortranIO
+src::gen::trunk     code/GenMod_GetEnv
+src::gen::trunk     code/GenMod_ModelIO
+src::gen::trunk     code/GenMod_ObsInfo
+src::gen::trunk     code/GenMod_Platform
+src::gen::trunk     code/GenMod_Reporting
+src::gen::trunk     code/GenMod_Trace
+src::gen::trunk     code/GenMod_UMConstants
+src::gen::trunk     code/GenMod_Utilities
+
+bld::target         VarProg_AnalysePF.exe   # line 27
+
+bld::tool::fc       sxmpif90                # line 29
+bld::tool::cc       sxmpic++                # line 30
+bld::tool::ld       sxmpif90                # line 31
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The above example is essentially the same as example 4, apart from the
+  additional build configuration. The following is a simple explanation of what
+  the lines represent: (For detail of the build system, please see the next
+  chapter on <a href="build.html">The Build System</a>.)</p>
+
+  <ul>
+    <li>Line 27: the line declares a default target of the build.</li>
+
+    <li>Line 29-31: the lines declare the Fortran compiler, the C compiler and
+    the linker respectively.</li>
+  </ul>
+
+  <table class="pad" summary="note - user variable" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - user variable</th>
+    </tr>
+
+    <tr>
+      <td>When you start using the extract system to define compiler flags for
+      the build system, you may end up having to make a lot of long and
+      repetitive declarations. In such case, you may want to define variables to
+      replace the repetitive parts of the declarations. In the extract system,
+      you can define a local variable by making a declaration with a label that
+      begins with a percent sign "%". For example:
+
+        <pre>
+# Declare a variable %fred
+%fred                     -Cdebug -eC -Wf,-init heap=nan stack=nan
+
+bld::tool::fflags         %fred
+# bld::tool::fflags       -Cdebug -eC -Wf,-init heap=nan stack=nan
+
+bld::tool::fflags::foo    %fred -f0
+# bld::tool::fflags::foo  -Cdebug -eC -Wf,-init heap=nan stack=nan -f0
+
+bld::tool::fflags::bar    -w %fred
+# bld::tool::fflags::bar  -w -Cdebug -eC -Wf,-init heap=nan stack=nan
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="verbose">Diagnostic verbose level</a></h2>
+
+  <p>The amount of diagnostic messages generated by the extract system is
+  normally set to a level suitable for normal everyday operation. This is the
+  default diagnostic verbose level 1. If you want a minimum amount of
+  diagnostic messages, you should set the verbose level to 0. If you want more
+  diagnostic messages, you can set the verbose level to 2 or 3. You can modify
+  the verbose level in two ways. The first way is to set the environment
+  variable FCM_VERBOSE to the desired verbose level. The second way is to
+  invoke the extract system with the "-v &lt;level&gt;" option. (If set, the
+  command line option overrides the environment variable.)</p>
+
+  <p>The following is a list of diagnostic output at each verbose level:</p>
+
+  <table class="pad" summary="List of diagnostic verbose output" border="1">
+    <tr>
+      <th>Verbose level</th>
+
+      <th>Possible output</th>
+    </tr>
+
+    <tr>
+      <th>0</th>
+
+      <td>
+        <ul>
+          <li>Report the time taken to extract the code.</li>
+
+          <li>Report the time taken to mirror the code.</li>
+
+          <li>If "rdist" is used to mirror the code, run the command with the
+          "-q" option.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>1</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 0.</li>
+
+          <li>Report the name of the extract configuration file.</li>
+
+          <li>Report date/time at the beginning of the extract step.</li>
+
+          <li>Report the number of directories created, number of ignored
+          sub-directories, number of files updated and number of removed
+          files.</li>
+
+          <li>In override mode, report any files that are modified in two or
+          more branches.</li>
+
+          <li>Report date/time at the beginning of the mirror step.</li>
+
+          <li>Report total time.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>2</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 1.</li>
+
+          <li>If the revision specified for a repository branch is not current
+          (i.e. the specified revision number is less than the revision number
+          of the last commit revision), print an information statement to
+          inform the user of the last commit revision of the branch.</li>
+
+          <li>Report details of created directories, ignored sub-directories,
+          removed files and updated files.</li>
+
+          <li>Report any files that have the same modifications in two or more
+          branches.</li>
+
+          <li>If "rdist" is used to mirror the code, run the command without the
+          "-q" option.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>3</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 2.</li>
+
+          <li>Report all shell commands invoked by the extract system with
+          timestamp.</li>
+
+          <li>If "rdist" is used to mirror the code, print the "distfile"
+          supplied to the command.</li>
+
+          <li>If "rsync" is used to mirror the code, invoke the command with
+          the "-v" option.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="nosvn">When Subversion Is Not Available</a></h2>
+
+  <p>The extract system can still be used if Subversion is not available.
+  Clearly, you can only use local repositories. However, you can still do
+  incremental extraction, mirror an extraction to another machine, or combine
+  code from multiple local repositories.</p>
+
+  <p>If you are using Subversion but your server is down then clearly there is
+  little you can do. However, if you already have an extraction then you can
+  re-run <tt>fcm extract</tt> as long as the extract configuration file only
+  refers to fixed revisions. If this is not the case then you can always use the
+  expanded extract configuration file which can be found in "cfg/ext.cfg" under
+  the extract destination root. This means that you can continue to makes changes
+  to local code and do incremental extractions even whilst your Subversion server
+  is down.</p>
+
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/further_info.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/further_info.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/further_info.html	(revision 329)
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Further Information</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Further Information">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Further Information
+  </address>
+
+  <h1>Further Information</h1>
+
+  <ul>
+    <li>Project documents
+
+      <ul>
+        <li>
+          <a href="../../../FCM_Admin/doc/project/HighLevelDesign.html">High Level Design</a>
+
+          <ul>
+            <li>Gives the original reasons behind the choice of tools used in
+            the FCM system (e.g. Subversion &amp; Trac).</li>
+
+            <li>Some of the issues discussed are no longer relevant.</li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="../design">FCM Detailed Design</a>
+
+          <ul>
+            <li>Information about the internal workings of the FCM system.</li>
+
+            <li>Intended mainly for people maintaining or developing the FCM
+            system.</li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="../../../FCM_Admin/doc/project/scmUsecaseSolutions.html">Use-Case
+          Solution</a>
+
+          <ul>
+            <li>Discusses how FCM meets its requirements.</li>
+
+            <li>Some of the working practices discussed may not match current
+            advice. This User Guide takes precedence where there are any
+            differences.</li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>Subversion
+
+      <ul>
+        <li><a href="http://subversion.tigris.org/">Subversion Home
+        Page</a></li>
+
+        <li><a href="http://svnbook.red-bean.com/en/1.2/">Subversion
+        Book</a></li>
+
+        <li><a href="http://subversion.tigris.org/faq.html">Subversion
+        FAQ</a></li>
+      </ul>
+    </li>
+
+    <li>Other links
+
+      <ul>
+        <li><a href="http://projects.edgewall.com/trac/">Trac Home
+        Page</a></li>
+
+        <li><a href="http://furius.ca/xxdiff/">xxdiff Home Page</a></li>
+
+        <li><a href="http://subversion.tigris.org/hacking.html">Hacker's
+        Guide to Subversion</a>: Contains some useful guidelines on log
+        message, filing issues, etc.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/getting_started.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/getting_started.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/getting_started.html	(revision 329)
@@ -0,0 +1,1656 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Getting Started</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Getting Started">
+  <meta name="keywords" content="FCM, user guide, getting started, tutorial">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Getting Started
+  </address>
+
+  <h1>Getting Started</h1>
+
+  <p><em>Getting Started</em> is a "hands-on" approach to help you set up your
+  FCM session, and familiarise yourself with some of the system's basic
+  concepts and working practices. It is designed to complement other sections
+  of the User Guide.</p>
+
+  <p>You may also find it useful to refer to the <a href=
+  "annex_quick_ref.html">Annex: Quick reference</a>.</p>
+
+  <h2><a name="setup">How to set yourself up to run FCM</a></h2>
+
+  <p>It is easy to set yourself up to run FCM. Simply follow the steps
+  below:</p>
+
+  <p><strong>Setting up your PATH</strong></p>
+
+  <p>The full FCM system is already available for you to use on the Met Office
+  Linux desktop systems. On other Met Office systems (currently NEC &amp;
+  HP-UX) only the build component is functional.</p>
+
+  <p>On Linux &amp; HP-UX systems FCM is automatically available in the
+  standard PATH. It is also automatically added to your PATH when you run UI
+  jobs on the NEC computers. However, if you intend to run FCM from the command
+  line on the NEC then you will need to add the following to your
+  <tt>$HOME/.profile</tt> script on that platform:</p>
+  <pre>
+. ~fcm/FCM/bin/env.sh  # Add FCM environment
+</pre>
+
+  <p><strong>Setting up the FCM GUI to work with Konqueror</strong></p>
+
+  <p>If you like to use a graphical user interface for some common code
+  management commands, you can set it up for launching from your desktop
+  Konqueror file manager by typing:</p>
+  <pre>
+(SHELL PROMPT)$ fcm_setup_konqueror
+</pre>
+
+  <p>See the section on <a href=
+  "code_management.html#svn_gui_konqueror">Accessing the GUI from Konqueror</a>
+  for further information.</p>
+
+  <p>Note that the first time you issue a command which requires authentication
+  you may need to supply a password or run it from the command line. See the
+  section on <a href="code_management.html#svn_gui_commands">GUI Commands</a>
+  for further information.</p>
+
+  <p><strong>Configure your editor for Subversion</strong></p>
+
+  <p>When you attempt to create a branch or commit changes to the repository,
+  you will normally be prompted to edit your commit log message using a text
+  editor. The system chooses its editor by searching for a non-empty string
+  through a hierarchy of environment variables in this order: SVN_EDITOR,
+  VISUAL, and EDITOR. If none of these environment variables are set, the
+  default is to use <em>nedit</em>. If you set your editor with an environment
+  variable, it is worth bearing in mind that it must be able to run in the
+  foreground. For example, you can add one of the followings in your
+  <tt>$HOME/.kshrc</tt> (Korn) or <tt>$HOME/.bashrc</tt> (Bash):</p>
+  <pre>
+# GVim
+export SVN_EDITOR='gvim -f'
+
+# Emacs
+export SVN_EDITOR=emacs
+
+# NEdit client "nc"
+export SVN_EDITOR='nc -wait'
+</pre>
+
+  <p><strong>Register your user name</strong></p>
+
+  <p>At the Met Office, most projects managed by FCM grant write accesses to
+  their Subversion repositories and Trac ticket create/modify privileges to
+  authorised users only. If you are developing code for a project for the first
+  time, please contact the system manager of the project, who will arrange with
+  the FCM team to put your user name in the register.</p>
+
+  <p><strong>Configure your email address in Trac</strong></p>
+
+  <p>Trac can be configured to automatically email the owner and reporter of any
+  ticket whenever there are changes to that ticket (and we would expect most
+  systems to be configured in this way). You should check that the settings for
+  your name and e-mail address are correct. To do this you need to go to the
+  Settings page once you are logged into Trac. (Click on &lt;Settings&gt; just
+  above the menu bar). Check that your settings are entered correctly. Note: at
+  the Met Office, these settings are set up and maintained automatically, and so
+  you should report any errors to the FCM team.</p>
+
+  <p><strong>Configure your web browser</strong></p>
+
+  <p>FCM assumes that you are using Firefox as your default web browser. If you
+  use another web browser such as Mozilla, you should configure it in your
+  <tt>$HOME/.fcm</tt> file. See the section on <a href=
+  "command_ref.html#fcm_svn_trac">fcm trac</a> for further information.</p>
+
+  <h2><a name="tutorial">Tutorial</a></h2>
+
+  <h3><a name="tutorial_intro">Introduction</a></h3>
+
+  <p>This tutorial leads you through the basics of using FCM to make changes to
+  your source code, and demonstrates the recommended practices for working with
+  it. A tutorial Subversion repository, with its own Trac system, is available
+  for you to practice for working with the FCM system. You will work through
+  the following activities:</p>
+
+  <ul>
+    <li><a href="#tutorial_create-ticket">Create a new ticket</a></li>
+
+    <li><a href="#tutorial_launch-gui">Launch the GUI</a></li>
+
+    <li><a href="#tutorial_create-branch">Create a branch</a></li>
+
+    <li><a href="#tutorial_checkout">Checkout a working copy</a></li>
+
+    <li><a href="#tutorial_change">Make changes to files in your working
+    copy</a></li>
+
+    <li><a href="#tutorial_commit">Commit your changes to the
+    repository</a></li>
+
+    <li><a href="#tutorial_extract">Test your changes</a></li>
+
+    <li><a href="#tutorial_merge">Merge changes from the trunk and resolve
+    conflicts</a></li>
+
+    <li><a href="#tutorial_review-ticket">Review changes</a></li>
+
+    <li><a href="#tutorial_merge-back">Commit to the trunk</a></li>
+
+    <li><a href="#tutorial_extra-extract">Extra activities on the extract and
+    build systems</a></li>
+
+    <li><a href="#tutorial_delete-branch">Delete your branch</a></li>
+
+    <li><a href="#tutorial_delete-final-comments">Final comments</a></li>
+  </ul>
+
+  <p>We recommend that you create a work area in your filespace, for example,
+  <tt>$HOME/tutorial/work</tt> for your working copy, and
+  <tt>$HOME/tutorial/build</tt> for your build.</p>
+
+  <p>If you have not already done so, you should set up your desktop environment
+  as described above in the <a href="#setup">How to set yourself up to run
+  FCM</a> section.</p>
+
+  <p>It is also worth knowing that the <a href=
+  "http://svnbook.red-bean.com/en/1.2/">Subversion Book</a> is a great source
+  of reference of Subversion features. In particular, the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.basic.html">Basic Concepts</a> and
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.tour.html">Guided Tour</a>
+  chapters are well worth reading.</p>
+
+  <h3><a name="tutorial_create-ticket">Create a new ticket</a></h3>
+
+  <p><em>Trac is an integrated web-based issue tracker and wiki system. You
+  will use it to manage and keep track of changes in your project. The issue
+  tracker is called the ticket system. When you want to report a problem or
+  submit a change request, you will create a new ticket. In a typical
+  situation, you and/or your colleagues will make changes to your system in
+  order to resolve the problem or change request, and you will monitor these
+  changes via the ticket.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>launch a Trac system,</li>
+
+    <li>create a new Trac ticket,</li>
+
+    <li>search for a Trac ticket, and</li>
+
+    <li>accept a Trac ticket.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li><a href="overview.html">System Overview</a></li>
+
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_basic">Basic Command Line Usage</a></li>
+
+    <li>Code Management System &gt; <a href="code_management.html#trac">Using
+    Trac</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_trac">fcm
+    trac</a></li>
+  </ul>
+
+  <h4>Launch a Trac system</h4>
+
+  <p>To launch the Trac system for the tutorial: type and <span class=
+  "mono">&lt;Enter&gt;</span> the following command:</p>
+  <pre>
+(SHELL PROMPT)$ fcm trac fcm:tutorial
+</pre>
+
+  <p>This is probably the first time you have used the <tt>fcm</tt> command.
+  The command has the general syntax:</p>
+  <pre>
+fcm &lt;sub-command&gt; [&lt;options...&gt;] &lt;arguments&gt;
+</pre>
+
+  <p>For example, if you type <tt>fcm help</tt>, it will display a listing of
+  what sub-commands are available, and if you type <tt>fcm help
+  &lt;sub-command&gt;</tt>, it will display help for that particular
+  sub-command.</p>
+
+  <p>The <tt>trac</tt> sub-command launches the corresponding Trac system
+  browser for a Subversion URL specified in your argument. In this case, we are
+  asking it to display the Trac system browser for the tutorial. The argument
+  <tt>fcm:tutorial</tt> is a FCM URL keyword and will be expanded by FCM into a
+  real Subversion URL (e.g. <tt>svn://fcm1/tutorial_svn/tutorial</tt>). You are
+  encouraged to use FCM URL keywords throughout the tutorial, as it will save
+  you a lot of typing.</p>
+
+  <p>Note: Although we use the Trac system as a browser for a Subversion
+  repository, they do not interact in any other ways. Having access to a Trac
+  system does not guarantee the same privilege to a Subversion repository. In
+  particular, you should note the differences between the URLs of a Subversion
+  repository path and its equivalence in a Trac browser.</p>
+
+  <p>There are other ways to launch the Trac system for a project. If you know
+  its URL, you can launch the Trac system by entering it in the address box of
+  your favourite browser. If you often access a Trac system for a particular
+  project, you should bookmark it in your favourite browser.</p>
+
+  <h4>Create a new Trac ticket</h4>
+
+  <p>Click on <span class="mono">&lt;Login&gt;</span> just above the menu bar,
+  enter your Unix/Linux user ID as your user name and leave the password empty.
+  Then click on <span class="mono">&lt;OK&gt;</span> to proceed.</p>
+
+  <p>Once you have logged in, the <span class="mono">&lt;New Ticket&gt;</span>
+  link will become available on the menu bar. Click on it to display a new
+  ticket form, where you can enter details about your problem or change
+  request. In the tutorial, it does not matter what you enter, but you should
+  feel free to play around with wiki formatting when entering the "Full
+  description". (Click on <span class="mono">&lt;WikiFormatting&gt;</span> to
+  see how you can use it.) For example:</p>
+
+  <ul>
+    <li>Short summary:
+      <pre>
+Tutorial to change repository files and resolve conflicts with the trunk
+</pre>
+    </li>
+
+    <li>Full description:
+      <pre>
+In this tutorial, I shall:
+ 1. try out the FCM GUI and its functions
+ 2. play with WikiFormatting in Trac tickets     
+ 3. create a branch and checkout a working copy
+ 4. make changes to files in it
+ 5. commit my changes and assign the ticket for review
+ 6. record the review and assign the ticket back to the author
+ 7. merge in the trunk, and resolve any conflicts 
+ 8. merge my changes back to the trunk
+ 9. close the ticket
+ 10. delete my branch
+</pre>
+    </li>
+
+    <li>Feel free to select an option you desire for each of the other ticket
+    properties: Type, Component, Priority, Version, Milestone and
+    Severity.</li>
+  </ul>
+
+  <p>At the bottom of the page, click the <span class=
+  "mono">&lt;Preview&gt;</span> button to see what the description would look
+  like. When you are happy, click the <span class="mono">&lt;Submit
+  changes&gt;</span> button. Trac will create the new ticket and return it in a
+  state where you can append to it.</p>
+
+  <h4>Search for a Trac ticket</h4>
+
+  <p>You should remember the number of your new ticket, as you will have to
+  revisit it later.</p>
+
+  <p>In real work, it is often not practical to have to remember the numbers of
+  all the tickets you have created. Trac provides a powerful custom query for
+  searching a ticket. You can search for the ticket you have just created by
+  clicking the <span class="mono">&lt;View Tickets&gt;</span> link. Feel free
+  to play with the custom query tool. Add or remove filters and try grouping
+  your results by different categories.</p>
+
+  <p>In addition, you can search your ticket using the keyword <span class=
+  "mono">&lt;Search&gt;</span> utility at the top right hand corner of each
+  Trac page. (If you enter <tt>#&lt;number&gt;</tt> in the search box, it will
+  take you directly to that ticket.) In the tutorial, however, it may be
+  easiest if you simply leave the tutorial Trac system open, so that you do not
+  have to login again when you come back to your ticket.</p>
+
+  <h4>Accept Trac ticket</h4>
+
+  <p>The status of the ticket is <em>new</em>. When you start working on a
+  problem reported in a ticket or when you are reviewing changes for a
+  colleague, it is often good practice to "accept" the ticket to indicate that
+  you are working on it. For the purpose of the tutorial, however, it is
+  entirely optional whether you accept the ticket or not, since you know you
+  will be doing all the work any way.</p>
+
+  <p>To accept a ticket, click on <span class="mono">&lt;accept
+  ticket&gt;</span> in the <em>Action</em> box at the bottom of the page, and
+  then click on <span class="mono">&lt;Submit changes&gt;</span>.</p>
+
+  <h3><a name="tutorial_launch-gui">Launch the GUI</a></h3>
+
+  <p><em>The FCM GUI is a simple graphical user interface for some of the
+  common code management commands. The examples in this tutorial are all based
+  on the GUI. However, you can skip this section and use only the command line
+  if that is what you prefer. An appropriate command line usage will be given
+  following each GUI example.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>launch the GUI from the command line, and</li>
+
+    <li>launch the GUI from Konqueror.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_gui">Using the GUI</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_gui">fcm
+    gui</a></li>
+  </ul>
+
+  <h4>Launch the GUI from the command line</h4>
+
+  <p>You can launch the GUI from the command line. Change directory to your
+  work area and then type <tt>fcm gui</tt>.</p>
+
+  <h4>Launch the GUI from Konqueror</h4>
+
+  <p>Alternatively, open Konqueror and navigate to your work area. Right-click
+  in the file-manager window to bring up a menu. Select <em>Open with</em> &gt;
+  <em>FCM GUI</em>.</p>
+
+  <h3><a name="tutorial_create-branch">Create a branch</a></h3>
+
+  <p><em>You create a branch by making a copy of your project at a particular
+  revision. Most often, this will be a particular revision of the trunk, i.e.
+  the main branch/development line in your project.  A branch resides in the
+  repository. It allows you to work in parallel with your colleagues without
+  affecting one another, while keeping your changes under version
+  control.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>create a branch in a Subversion repository, and</li>
+
+    <li>update a ticket with a link to a branch.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_create">Creating Branches</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#branching">Branching &amp; Merging</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_br">fcm
+    branch</a></li>
+  </ul>
+
+  <h4>Create a branch in a Subversion repository</h4>
+
+  <p>In the FCM GUI, click on <span class="mono">&lt;Branch&gt;</span> on the
+  top menu bar of the GUI. Check the <span class="mono">&lt;create&gt;</span>
+  radio button and configure your branch details as follow:</p>
+
+  <ul>
+    <li>Enter <tt>fcm:tutorial</tt> for the URL of the tutorial
+    repository.</li>
+
+    <li>Enter the short branch name. This must contain only alpha-numeric
+    characters and/or underscores, e.g. <tt>tutorial</tt>.</li>
+
+    <li>Enter <tt>1</tt> for the source revision. The trunk was last changed at
+    revision 2. To facilitate the generation of conflicts when you merge with
+    it, you will branch from revision 1 of the trunk.</li>
+
+    <li>Set the branch type. In this case click on <span class=
+    "mono">&lt;test::user&gt;</span>. This will ensure the branch you create is
+    a user test branch.</li>
+
+    <li>Leave the source type as <span class="mono">&lt;trunk&gt;</span> and
+    the prefix option as <span class="mono">&lt;normal&gt;</span>.</li>
+
+    <li>Enter the related Trac ticket number for the ticket you created
+    earlier.</li>
+
+    <li>As this is probably the first time you access the tutorial repository,
+    you should also enter <tt>--password ""</tt> (i.e. <tt>--password</tt>
+    followed by a pair of quotes) in the "Other Options" entry box.</li>
+  </ul>
+
+  <p>Click on <span class="mono">&lt;Run&gt;</span> when you are ready.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm branch --create</tt> (or
+  simply <tt>fcm br -c</tt>) command. E.g.:</p>
+  <pre>
+(SHELL PROMPT)$ fcm br -c -n tutorial -r 1 --type test -k 2 fcm:tutorial
+</pre>
+
+  <p class="image"><img src="create_branch.png" border="0" alt=
+  "create my branch"></p>
+
+  <p>You will be prompted to edit the message log file. A standard template is
+  automatically supplied for the commit. However, if you want to add extra
+  comment for the branch, please do so <strong>above</strong> the line that
+  says "<tt>--This line will be ignored and those below will be inserted
+  automatically--</tt>". When you are ready, save your change and exit the
+  editor. Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to
+  go ahead and create the branch.</p>
+
+  <p>Note: If you are on the command line, the Subversion command will prompt
+  you for a password the first time you access a repository. The password will
+  normally be cached by the client, and you will not have to specify a password
+  on subsequent access. If you are using the GUI, please refer to the section on
+  <a href="code_management.html#svn_gui_commands">GUI Commands</a> in the next
+  chapter for further information.</p>
+
+  <p>When creating branches for the first time, you will notice that FCM will
+  create and commit any missing sub-directories it needs to set up your branch
+  inside the repository, before creating your branch and commiting it.</p>
+
+  <p>Take a note of the revision number the branch was created at, and its
+  branch name. (The revision number is the number following the last output
+  that says "Committed revision". In the example above, the branch created at
+  <tt>[5]</tt> is called <tt>branches/test/frsn/r1_tutorial</tt>, which is a
+  branch of the <tt>tutorial</tt> project in the
+  <tt>svn://fcm1/tutorial_svn</tt> repository.)</p>
+
+  <h4>Update your ticket with a link to your branch</h4>
+
+  <p>If you wish, you can update your ticket with details of the branch. Note
+  that this step is entirely optional. It is useful for developments which will
+  take a long time to complete. For short lived branches, this step is probably
+  unnecessary.</p>
+
+  <p>In the ticket you have created, refer to the revision number in the
+  <em>Add/Change</em> box, for example:</p>
+  <pre>
+Created the branch [source:tutorial/branches/test/frsn/r1_tutorial@5] at [5].
+</pre>
+
+  <p>Note:</p>
+
+  <ul>
+    <li><tt>[source:tutorial/branches/test/frsn/r1_tutorial@5]</tt> is a Trac
+    wiki link. In this syntax, you do not have to put in the root URL, (e.g.
+    <tt>svn://fcm1/tutorial_svn/</tt>), but you should specify your branch
+    using the project name (<tt>tutorial</tt>), the branch name
+    (<tt>branches/test/frsn/r1_tutorial</tt>), and a revision number. Trac will
+    translate this into a link to that branch.</li>
+
+    <li>Trac will translate the syntax <tt>[&lt;number&gt;]</tt> into a link to
+    the numbered changeset.</li>
+  </ul>
+
+  <p>Click on &lt;Preview&gt; and check that the links work correctly, and on
+  <span class="mono">&lt;Submit changes&gt;</span> when you are ready.</p>
+
+  <h3><a name="tutorial_checkout">Checkout a working copy</a></h3>
+
+  <p><em>A Subversion working copy is an ordinary directory tree on your local
+  system, containing a collection of files. It is your private working area in
+  which you can make changes before publishing them back to the repository. You
+  create a working copy by using the checkout command on some subtree of the
+  repository.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>checkout a Subversion working copy.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_concepts">Basic Concepts</a></li>
+
+    <li>FCM Command Reference &gt; <a href=
+    "command_ref.html#fcm_svn_other">Other Subversion Commands</a></li>
+  </ul>
+
+  <h4>Checkout a Subversion working copy</h4>
+
+  <p>Click on <span class="mono">&lt;Checkout&gt;</span> in the GUI, and enter
+  the URL of your branch, e.g. <tt>fcm:tutorial_br/test/frsn/r1_tutorial</tt>.
+  Note:</p>
+
+  <ul>
+    <li>In the example, we have replaced the leading part of the Subversion URL
+    <tt>svn://fcm1/tutorial_svn/tutorial/branches</tt> with the FCM repository
+    keyword <tt>fcm:tutorial_br</tt>. This is mainly to save you from having to
+    type in the full URL. However, you may find it easier to copy-and-paste the
+    full Subversion URL from the output generated when you created the
+    branch.</li>
+
+    <li>If you do not specify a local directory PATH in the <tt>checkout</tt>
+    command, it will create a working copy in your current working directory,
+    using the basename of the URL you are checking out. For example, when you
+    checkout the branch you have just created, the command should create the
+    working copy in <tt>$PWD/r1_tutorial</tt>. Make a note of the location of
+    your working copy, in case you forget where you have put it.</li>
+
+    <li>If you do not specify a revision to checkout, it will checkout the
+    HEAD, i.e. the latest, revision.</li>
+  </ul>
+
+  <p>Click on <span class="mono">&lt;Run&gt;</span> - a working copy pointing
+  to your branch will be created. The GUI will automatically change directory
+  to the top of your new working copy.</p>
+
+  <table class="pad" summary="branch checkout example" border="1" width="100%">
+    <tr>
+      <th>Example output, checking out the branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+=&gt; svn co --revision HEAD svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial
+A    r1_tutorial/cfg
+A    r1_tutorial/cfg/ext.cfg
+A    r1_tutorial/doc
+A    r1_tutorial/doc/hello.html
+A    r1_tutorial/src
+A    r1_tutorial/src/subroutine
+A    r1_tutorial/src/subroutine/hello_c.c
+A    r1_tutorial/src/subroutine/hello_sub.f90
+A    r1_tutorial/src/module
+A    r1_tutorial/src/module/hello_constants.f90
+A    r1_tutorial/src/program
+A    r1_tutorial/src/program/hello.f90
+Checked out revision 5.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm checkout</tt> (or simply
+  <tt>fcm co</tt>) command. E.g.:</p>
+  <pre>
+(SHELL PROMPT)$ fcm co fcm:tutorial_br/test/frsn/r1_tutorial
+</pre>
+
+  <h3><a name="tutorial_change">Make changes to files in your working
+  copy</a></h3>
+
+  <p><em>Subversion provides various useful commands to help you monitor your
+  working copy. The most useful ones are "diff", "revert" and "status". You
+  will also find "add", "copy", "delete" and "move" useful when you are
+  rearranging your files and directories.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>make and revert changes,</li>
+
+    <li>add and remove files,</li>
+
+    <li>inspect the status of a working copy, and</li>
+
+    <li>display changes in a working copy.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_basic">Basic Command Line Usage</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_add">fcm
+    add</a>, <a href="command_ref.html#fcm_svn_diff">fcm diff</a>, <a href=
+    "command_ref.html#fcm_svn_delete">fcm delete</a>, <a href=
+    "command_ref.html#fcm_svn_other">Other Subversion Commands</a></li>
+  </ul>
+
+  <h4>Make and revert changes</h4>
+
+  <p>For the later part of the tutorial to work, you must make the following
+  modification:</p>
+
+  <ul>
+    <li>Change to the "<tt>src/module/</tt>" sub-directory in your working
+    copy.</li>
+
+    <li>Edit <b>hello_constants.f90</b>, using your favourite editor, and
+    change: <em>"Hello World!"</em> to <em>"Hello Earthlings!"</em>. Save your
+    change and exit the editor.</li>
+  </ul>
+
+  <p>Try the following so that you know how to restore a changed file:</p>
+
+  <ul>
+    <li>Change to the "<tt>src/subroutine/</tt>" directory of your working
+    copy.</li>
+
+    <li>Make a change in file <b>hello_c.c</b>, using your favourite
+    editor.</li>
+
+    <li>In the GUI, click on <span class="mono">&lt;Status&gt;</span> and then
+    on <span class="mono">&lt;Run&gt;</span> to see that you have
+    <u>M</u>odified this file. (Alternatively, you can type "<tt>fcm
+    status</tt>" on the command line.)</li>
+
+    <li>Run the <em>revert</em> command to get the file back unmodified:
+      <pre>
+(SHELL PROMPT)$ fcm revert hello_c.c
+</pre>
+    </li>
+  </ul>
+
+  <h4>Add and remove files</h4>
+
+  <p>You may also want to try the following FCM commands in your <tt>doc/</tt>
+  sub-directory. You can safely make changes here since they will not interfere
+  with your code changes.</p>
+
+  <ul>
+    <li>change to the "doc/" directory of your working copy.</li>
+
+    <li>Echo some text into a new file and then run the <em>add</em> command,
+    which lets the repository know you're adding a new file at the next commit.
+    For example:
+      <pre>
+(SHELL PROMPT)$ echo 'Some text' &gt;new_file.txt
+(SHELL PROMPT)$ fcm add new_file.txt
+</pre>
+    </li>
+
+    <li>Make a copy of <em>hello.html</em> and remove the original, using the
+    <em>copy</em> and <em>delete</em> commands. For example:
+      <pre>
+(SHELL PROMPT)$ fcm copy hello.html add.html
+(SHELL PROMPT)$ fcm delete hello.html
+</pre>
+    </li>
+
+    <li>You can use a simple <em>move</em> sub-command for the above
+    <em>copy</em> and <em>delete</em>.</li>
+  </ul>
+
+  <h4>Inspect the status of a working copy</h4>
+
+  <p>In the GUI, click on <span class="mono">&lt;Status&gt;</span> and then on
+  <span class="mono">&lt;Run&gt;</span> to see what has changed:</p>
+
+  <table class="pad" summary="status example 1" border="1" width="100%">
+    <tr>
+      <th>Example output, status in a working copy</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+=&gt; svn status
+D      doc/hello.html
+A      doc/new_file.txt
+A  +   doc/add.html
+M      src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm status</tt> (or simply
+  <tt>fcm st</tt>) command.</p>
+
+  <p>This confirms the actions you have taken. You have <u>D</u>eleted a file,
+  <u>A</u>dded a new file, <u>A</u>dded a file with history (<tt>+</tt>) and
+  <u>M</u>odified another. It also confirms the action of the <em>revert</em>
+  command.</p>
+
+  <h4>Display changes in a working copy</h4>
+
+  <p>You can view the changes you have made to your working copy. In the GUI,
+  click on <span class="mono">&lt;Diff&gt;</span> and then on <span class=
+  "mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm diff --graphical</tt>
+  (or simply <tt>fcm di -g</tt>) command.</p>
+
+  <p>A listing of the files you have changed will be displayed, and a graphical
+  diff tool will open up for each modified file.</p>
+
+  <h3><a name="tutorial_commit">Commit your changes to the repository</a></h3>
+
+  <p><em>The change in your working copy remains local until you commit it to
+  the repository where it becomes permanent. If you are planning to make a
+  large number of changes, you are encouraged to commit regularly to your
+  branch at appropriate intervals.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>commit your changes, and</li>
+
+    <li>inspect your changes using Trac.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_basic">Basic Command Line Usage</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_ci">fcm
+    commit</a></li>
+  </ul>
+
+  <h4>Commit changes</h4>
+
+  <p>In the GUI, click on <span class="mono">&lt;Commit&gt;</span> and then on
+  <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm commit</tt> (or simply
+  <tt>fcm ci</tt>) command.</p>
+
+  <p>A text editor will appear to allow you to edit the commit message. You
+  must add a commit message to describe your change <strong>above</strong> the
+  line that says "<tt>--This line, and those below, will be ignored--</tt>". (A
+  suggestion is given as the highlighted text in the example below.) Your
+  commit will fail if you do not enter a commit message.</p>
+
+  <p>Save your change and exit the editor. Answer <span class=
+  "mono">&lt;Yes&gt;</span> when you are prompted to confirm the commit. For
+  example:</p>
+
+  <table class="pad" summary="status example 1" border="1" width="100%">
+    <tr>
+      <th>Example output, commit my changes to the repository</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Starting nedit to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+<font color="purple">In my tutorial branch, for #2:
+  1. Moved hello.html to add.html, and created a new document '''new_file.txt'''
+  2. Changed greeting in hello_constants.f90 to ''Hello Earthlings!''</font>
+--This line, and those below, will be ignored--
+[Project: tutorial]
+[Branch : branches/test/frsn/r1_tutorial]
+[Sub-dir: &lt;top&gt;]
+
+D      doc/hello.html
+A      doc/new_file.txt
+A  +   doc/add.html
+M      src/module/hello_constants.f90
+------------------------------------------------------------------------
+Adding         doc/add.html
+Deleting       doc/hello.html
+Adding         doc/new_file.txt
+Sending        src/module/hello_constants.f90
+Transmitting file data ..
+Committed revision 6.
+Performing update to make sure your working copy is at this new revision ...
+At revision 6.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4>Inspect changes using Trac</h4>
+
+  <p>Click on <span class="mono">&lt;Timeline&gt;</span> in Trac. Drill down to
+  your changeset and see how it appears. (Alternatively, if you enter
+  "<tt>[&lt;number&gt;]</tt>" into the search box at the top right, it will
+  take you directly to the numbered changeset.) For example:</p>
+
+  <p class="image"><img src="changeset.png" border="0" alt=
+  "commit my changes"></p>
+
+  <p>Note:</p>
+
+  <ul>
+    <li>Wiki Formatting, used in the commit message, has customised the
+    changeset message.</li>
+
+    <li>All your changes are listed.</li>
+  </ul>
+
+  <h3><a name="tutorial_extract">Test your changes</a></h3>
+
+  <p><em>You should test the changes in your branch before asking a colleague
+  to review them. FCM features a build system that allows you to build your
+  code easily. As your changes may be located in a repository branch and/or a
+  working copy, you should work with the extract system to extract the correct
+  code to build. The extract system allows you to extract code from the
+  repository, combining changes in different branches and your working copy,
+  before generating a configuration file and a suitable source tree for feeding
+  into the build system.</em></p>
+
+  <p><em>In this sub-section of the tutorial, you will be shown how to extract
+  and build the code from your branch. (There are some <a href=
+  "#tutorial_extra-extract">extra activities on the extract and build
+  systems</a> in a later sub-section of the tutorial should you want to explore
+  the extract and build systems in more depth.) In the example here, the
+  extract and build systems will be shown to you in their simplest form. In
+  real life, the managers of the systems you are developing code for will
+  provide you with more information on how to extract and build their
+  systems.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>set up a simple extract configuration file, and</li>
+
+    <li>perform simple extracts and builds.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li><a href="extract.html">The Extract System</a></li>
+
+    <li><a href="build.html">The Build System</a></li>
+  </ul>
+
+  <p>You should extract and build your code in a different directory to your
+  working copy. For example, you may want to create a sub-directory
+  <tt>tutorial/build/</tt> in <tt>$HOME</tt> and change to it:</p>
+  <pre>
+(SHELL PROMPT)$ mkdir -p $HOME/tutorial/build
+(SHELL PROMPT)$ cd $HOME/tutorial/build
+</pre>
+
+  <h4>Set up an extract configuration file</h4>
+
+  <p>To set up an extract configuration file from scratch, launch your
+  favourite editor and add the following lines:</p>
+
+  <table class="pad" summary="extract config example, branch" border="1" width=
+  "100%">
+    <tr>
+      <th>Example extract configuration, extract from a branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+# Extract configuration, format version 1.0
+cfg::type              ext
+cfg::version           1.0
+
+# Extract destination root directory
+dest::rootdir          $HOME/tutorial/build
+
+# Location of the source in the "r1_tutorial" branch
+repos::tutorial::base  fcm:tutorial_br/test/$LOGNAME/r1_tutorial
+
+# Extract all sub-directories under the above URL
+expsrc::tutorial::base src
+
+# Fortran compiler, C compiler and linker commands respectively
+# You may need to redefine these for different platforms
+bld::tool::fc          ifc
+bld::tool::cc          gcc
+bld::tool::ld          ifc
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Note:</p>
+
+  <ul>
+    <li>The "<tt>dest::rootdir</tt>" declaration is set to
+    <tt>$HOME/tutorial/build</tt>. If you decide to extract to a different
+    directory, you should modify its value.</li>
+
+    <li>Similarly, the "<tt>repos::tutorial::base</tt>" declaration is set to
+    <tt>fcm:tutorial_br/test/$LOGNAME/r1_tutorial</tt>. If you have named your
+    branch differently, you should modify its value.</li>
+  </ul>
+
+  <p>Save the file as "<tt>ext.cfg</tt>" and exit your editor.</p>
+
+  <h4>Perform an extract and a build</h4>
+
+  <p>Issue the command "<tt>fcm extract</tt>" and you should get an output
+  similar to the following:</p>
+
+  <table class="pad" summary="extract example, branch" border="1" width="100%">
+    <tr>
+      <th>Example output, extract from a branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm extract
+Extraction started on Thu Oct 27 13:54:06 2005.
+Config file (ext): /net/home/h01/frsn/tutorial/build/ext.cfg
+-&gt;Extract: start
+Number of directories created    : 4
+Number of updated files          : 4
+-&gt;Extract: 1 second
+-&gt;TOTAL  : 1 second
+Extraction finished on Thu Oct 27 13:54:07 2005.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>If nothing goes wrong, you should end up with the sub-direcories
+  "<tt>src/</tt>" and "<tt>cfg/</tt>" in your working directory. The
+  "<tt>src/</tt>" contains a source tree to be built, and "<tt>cfg/</tt>" should
+  contain two configuration files: "<tt>ext.cfg</tt>" and "<tt>bld.cfg</tt>".
+  The former is an expanded version of your extract configuration file and the
+  latter is a build configuration file. You can now build your code by running
+  the "<tt>fcm build</tt>" command:</p>
+
+  <table class="pad" summary="build example, branch" border="1" width="100%">
+    <tr>
+      <th>Example output, build</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm build 2&gt;err
+Build command started on Fri Oct 14 09:15:38 2005.
+-&gt;gt;Setup              : start
+Config file (bld): /net/home/h01/frsn/tutorial/build/cfg/bld.cfg
+-&gt;Setup              : 0 second
+-&gt;Pre-process        : start
+-&gt;Pre-process        : 0 second
+-&gt;Scan dependency    : start
+Scanned files in 3 package(s) for dependency
+Updated make rules for 3 package(s).
+Updated Makefile: /net/home/h01/frsn/tutorial/build/bld/Makefile
+-&gt;Scan dependency    : 1 second
+-&gt;Generate interface : start
+Number of generated interfaces: 1
+-&gt;Generate interface : 0 second
+-&gt;Make               : start
+ifc -o hello_constants.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/module/hello_constants.f90
+ifc -o hello.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/program/hello.f90
+ifc -o hello_sub.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/subroutine/hello_sub.f90
+gcc -o hello_c.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/subroutine/hello_c.c
+ifc -o hello.exe /home/h01/frsn/tutorial/build/obj/hello.o
+  -L/home/h01/frsn/tutorial/build/lib -l__fcm__hello
+-&gt;Make               : 3 seconds
+-&gt;TOTAL              : 4 second
+Build command finished on Fri Oct 14 09:15:42 2005.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The executable you have built is "<tt>hello.exe</tt>", which is located in
+  the "<tt>bin/</tt>" sub-directory. You can test your executable by running
+  it. You should an output similar to the following:</p>
+
+  <table class="pad" summary="build example run, working copy" border="1"
+  width="100%">
+    <tr>
+      <th>Example output, running the build</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ bin/hello.exe 
+Hello: Hello Earthlings!
+Hello_Sub: Hello Earthlings!
+Hello_Sub: maximum integer: 2147483647
+Hello_C: Hello World!
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="tutorial_merge">Merge changes from the trunk and resolve
+  conflicts</a></h3>
+
+  <p><em>Your branch is normally isolated from other development lines in your
+  project. However, at some point during your development, you may need to merge
+  your changes with those of your colleagues. In some cases, it is desirable to
+  merge changes regularly from the trunk to keep your branch up to date with the
+  latest development. The automatic merge provided by FCM allows you to do this
+  easily.</em></p>
+
+  <p><em>A merge results in a conflict if changes being applied to a file
+  overlap. FCM uses a graphical merge tool to help you resolve conflicts in text
+  files.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>merge changes from the trunk into your working copy, and</li>
+
+    <li>resolve conflicts in your working copy.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Basic Command Line Usage &gt; <a href=
+    "code_management.html#svn_basic_conflicts">Resolving Conflicts</a></li>
+
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_branching">Branching &amp; Merging</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#branching">Branching &amp; Merging</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_cf">fcm
+    conflicts</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_merge">fcm
+    merge</a></li>
+  </ul>
+
+  <h4>Merge changes from the trunk into a working copy</h4>
+
+  <p>Change directory back to your working copy.</p>
+
+  <p>In the GUI, click on <span class="mono">&lt;Merge&gt;</span>. Enter
+  "<tt>trunk</tt>" into the Source entry box and click on <span class=
+  "mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm merge</tt> command.
+  E.g.</p>
+  <pre>
+(SHELL PROMPT)$ fcm merge trunk
+</pre>
+
+  <p>If there is more than one revision of the source that you can merge with,
+  you will be prompted for the revision number you wish to merge from. You will
+  not be prompted in this case, because there is only one revision of the
+  source that you can merge with.</p>
+
+  <p>Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to go
+  ahead with the merge.</p>
+
+  <table class="pad" summary="merge from trunk example" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output, merging changes from the trunk</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Available Merges From /tutorial/trunk: 2
+About to merge in changes from tutorial/trunk@2 compared with tutorial/trunk@1
+This merge will result in the following changes:
+------------------------------------------------------------------------
+U    src/subroutine/hello_c.c
+C    src/module/hello_constants.f90
+------------------------------------------------------------------------
+Performing merge ...
+U    src/subroutine/hello_c.c
+C    src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4>Resolve conflicts in a working copy</h4>
+
+  <p>The "C" status indicates that the file you changed is now in conflict. If
+  you run <tt>status</tt>, you will see extra files created by the merge, which
+  enable you to resolve the conflict using the 3-way difference tool
+  <em>xxdiff</em>:</p>
+
+  <table class="pad" summary="conflict status example" border="1" width="100%">
+    <tr>
+      <th>Example output, status in conflict</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+=&gt; svn status
+M      src/subroutine/hello_c.c
+?      src/module/hello_constants.f90.merge-left.r1
+?      src/module/hello_constants.f90.merge-right.r2
+?      src/module/hello_constants.f90.working
+C      src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>You will now have to resolve the conflicts.</p>
+
+  <p>In the GUI, click on <span class="mono">&lt;Conflicts&gt;</span> and then
+  on <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm conflicts</tt> (or
+  simply <tt>fcm cf</tt>) command.</p>
+
+  <p><em>xxdiff</em> comes into play:</p>
+
+  <p class="image"><img src="xxdiff_tutorial.png" border="0" alt=
+  "3-way diff"></p>
+
+  <p>See the sub-section on <a href=
+  "code_management.html#svn_basic_conflicts">resolving conflicts</a>, or the
+  <em>xxdiff User's Manual (click on <span class=
+  "mono">&lt;Help&gt;</span>)</em> to guide you through this process. (If you
+  do not want to learn how to use <em>xxdiff</em> now, you can just select
+  <em>Exit with ACCEPT</em> from the <em>File</em> menu. This saves the file
+  you are merging in as the result of the merge, i.e. you have
+  <em>accepted</em> all the changes).</p>
+
+  <p>On resolving the conflict, you will be asked to run "<tt>svn
+  resolved</tt>". Answer <span class="mono">&lt;Yes&gt;</span>.</p>
+
+  <p>If you now run <tt>status</tt>, you will notice that these extra conflict
+  files have disappeared.</p>
+
+  <table class="pad" summary="resolve conflicts example" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output, resolving conflicts</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Conflicts in file: src/module/hello_constants.f90
+All merge conflicts resolved
+Resolved conflicted state of 'hello_constants.f90'
+=&gt; svn status
+M      src/subroutine/hello_c.c
+M      src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>It is important to remember that the <tt>merge</tt> command only applies
+  changes to your working copy. Therefore, you must now commit the change in
+  order for it to become permanent in the repository. Similar to other changes,
+  it is a good practice to use <tt>diff</tt> to inspect the changes before
+  committing.</p>
+
+  <p>When you run <tt>commit</tt>, you will be prompted to edit the commit log
+  as usual. However, you may notice that a standard template is already
+  provided for you by the <tt>merge</tt> command. In most cases, the standard
+  message should be sufficient. However, if you want to add extra comment to
+  the commit, please do so <strong>above</strong> the line that says
+  "<tt>--This line will be ignored and those below will be inserted
+  automatically--</tt>". This is useful, for example, if there were significant
+  issues addressed in the merge.</p>
+
+  <h3><a name="tutorial_review-ticket">Review changes</a></h3>
+
+  <p><em>For the purpose of this tutorial, we assume that your changes are
+  complete, have been tested and committed to the repository, and are now ready
+  for review. You should assign the ticket to the reviewer and inform him/her
+  where to find the changes you wish him/her to review. The reviewer will
+  record any issues in the ticket, perhaps linking to other documents as
+  required. Once completed, he/she will record the outcome in the ticket and
+  assign it back to the you.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>re-assign a ticket, and</li>
+
+    <li>display changes in a branch.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_info">Getting Information About
+    Branches</a></li>
+
+    <li>Code Management System &gt; <a href="code_management.html#trac">Using
+    Trac</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#tickets">Using Tickets</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_diff">fcm
+    diff</a></li>
+  </ul>
+
+  <h4>Re-assign a ticket to a reviewer</h4>
+
+  <p>Back in your ticket, add an appropriate comment showing where to find your
+  changes, in the <em>Add/Change</em> box. Include the location of the branch,
+  and its latest revision number in the comment. For example:</p>
+
+  <table summary="review ticket example" border="1">
+    <tr>
+      <td>
+        <pre>
+The [log:tutorial/branches/test/frsn/r1_tutorial@5:7] branch proposes changes
+to the greeting message in hello_constants.f90. It also contains some new
+documents.
+
+Fred, could you review the change, please?
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Note: the syntax <tt>[log:tutorial/branches/test/frsn/r1_tutorial@5:7]</tt>
+  will be translated by Trac into a link to the revision log browser to display
+  the log between revision 5 and 7 of the
+  <tt>branches/test/frsn/r1_tutorial</tt> branch in the <tt>tutorial</tt>
+  project. Click on &lt;Preview&gt; and check that the
+  link works correctly.</p>
+
+  <p>To re-assign a ticket to your reviewer, click on the <span class=
+  "mono">&lt;reassign to&gt;</span> button in the <em>Action</em> box section
+  and enter the reviewer's User ID.</p>
+
+  <p>When you are ready, click on <span class="mono">&lt;Submit
+  changes&gt;</span>. In real life, if the reviewer is a registered user of the
+  Trac system, he/she should be sent an e-mail of the review request
+  automatically. Otherwise, you may need to inform the reviewer of the request
+  by other means.</p>
+
+  <h4>Display changes in a branch</h4>
+
+  <p>For the purpose of this tutorial, you will act as the reviewer of the
+  changes you have made. To review the changes in a branch, you can look at all
+  the changes relative to its base.</p>
+
+  <p>In the GUI, click on <span class="mono">&lt;Diff&gt;</span>. Enter the URL
+  of the branch (e.g. <tt>fcm:tutorial_br/test/frsn/r1_tutorial</tt>), check
+  the box <span class="mono">&lt;Show differences relative to the base of the
+  branch&gt;</span>, and click on <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm diff --branch</tt> (or
+  simply <tt>fcm di -b</tt>) command. E.g.</p>
+  <pre>
+fcm di -b -g fcm:tutorial_br/test/frsn/r1_tutorial
+</pre>
+
+  <p>You should be presented with the differences between the branch and the
+  trunk (since the last merge).</p>
+
+  <h4>Reassign the ticket back to the author</h4>
+
+  <p>Following the review, you should record its outcome and re-assign the
+  ticket back to the author. Enter the comment "<tt>No issues were found during
+  the review</tt>". Click on the <span class="mono">&lt;reassign to&gt;</span>
+  button in the <em>Action</em> box section, and enter your guest account name.
+  Click on <span class="mono">&lt;Submit changes&gt;</span> when you are
+  ready.</p>
+
+  <p>In real life, the original author will be notified by an automatic
+  e-mail.</p>
+
+  <h3><a name="tutorial_merge-back">Commit to the trunk</a></h3>
+
+  <p><em>Your changes in the branch have been tested and reviewed. It is now
+  time to merge and commit it to the trunk. Once you have committed your
+  change, you will close your ticket to complete the work cycle.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>use the <tt>switch</tt> command,</li>
+
+    <li><tt>merge</tt> and <tt>commit</tt> your changes into the trunk,
+    and</li>
+
+    <li>close a ticket</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_branching">Branching &amp; Merging</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#branching">Branching &amp; Merging</a></li>
+
+    <li>FCM Command Reference &gt; <a href=
+    "command_ref.html#fcm_svn_switch">fcm switch</a></li>
+  </ul>
+
+  <h4>Switch a working copy to point to the trunk</h4>
+
+  <p>In the GUI, click on <span class="mono">&lt;Switch&gt;</span>. Enter
+  "<tt>trunk</tt>" as the URL and then click on <span class=
+  "mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm switch</tt> (or simply
+  <tt>fcm sw</tt>) command. E.g.:</p>
+  <pre>
+(SHELL PROMPT)$ fcm sw trunk
+</pre>
+
+  <p>To check that your working copy is pointing to the trunk, you should
+  inspect the "corresponding URL" of your working copy while you are in the
+  GUI.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm info</tt> command.</p>
+
+  <h4>Merge and commit your changes into the trunk</h4>
+
+  <p>In the GUI, click on <span class="mono">&lt;Merge&gt;</span>. Enter the
+  name of your branch in the Source entry box, (e.g.
+  "<tt>branches/test/frsn/r1_tutorial</tt>"). Click on <span class=
+  "mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm merge</tt> command.
+  E.g.</p>
+  <pre>
+(SHELL PROMPT)$ fcm merge branches/test/frsn/r1_tutorial
+</pre>
+
+  <table class="pad" summary="merge back to trunk example" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output, merging changes back to the trunk</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Available Merges From /tutorial/branches/test/frsn/r1_tutorial: 7 6
+About to merge in changes from /tutorial/branches/test/frsn/r1_tutorial@7
+  compared with /tutorial/trunk@2
+This merge will result in the following changes:
+------------------------------------------------------------------------
+D    doc/hello.html
+A    doc/new_file.txt
+U    src/module/hello_constants.f90
+A    add.html
+------------------------------------------------------------------------
+Performing merge ...
+D    doc/hello.html
+A    doc/new_file.txt
+U    src/module/hello_constants.f90
+A    add.html
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Since there is more than one revision available for merging, you will be
+  prompted for the revision number you wish to merge from. The default is the
+  last changed revision of your branch. which is the revision you want to merge
+  with, so you should just proceed with the default.</p>
+
+  <p>Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to go
+  ahead with the merge.</p>
+
+  <p>Since we merged in the latest changes from the trunk into the branch,
+  there should be no conflicts from this merge.</p>
+
+  <p>Once again, please remember that the merge command only changes your
+  working copy. You need to commit the change before it becomes permanent in
+  the repository. Before you commit to the trunk, however, it is often sensible
+  to have a last look at what you are going to change using the <tt>diff</tt>
+  command.</p>
+
+  <p>Note: We have set up the repository to prevent any commits to the trunk to
+  preserve the tutorial for other users, so your commit to the trunk will fail.
+  However, you should try doing it any way to complete the exercise.</p>
+
+  <p>In the GUI, click on <span class="mono">&lt;Commit&gt;</span> and then on
+  <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm commit</tt> (or simply
+  <tt>fcm ci</tt>) command.</p>
+
+  <p>A text editor will appear to allow you to edit the commit message. You
+  must add a commit message to describe your change <strong>above</strong> the
+  line that says "<tt>--This line will be ignored and those below will be
+  inserted automatically--</tt>". Since you are going to commit changes to the
+  trunk, you should provide a useful message, including a link to your ticket.
+  For example:</p>
+
+  <table summary="" border="1">
+    <tr>
+      <td>
+        <pre>
+For #2: complete the tutorial:
+  1. Changed greeting in hello_constants.f90 to "Hello Earthlings!"
+  2. Moved hello.html to add.html, and created a new document ''new_file.txt''
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>When you are ready, save your change and exit the editor.</p>
+
+  <p>As we have said before, the command will fail when you try to proceed with
+  the commit.</p>
+
+  <h4>Close your ticket</h4>
+
+  <p>As you have completed your work, you should now update and close your
+  ticket. In real life, you will typically include a closing comment with an
+  appropriate Trac wiki link to the changeset in the trunk that fixes the
+  ticket.</p>
+
+  <p>Since you cannot commit to the trunk in the tutorial, you can include a
+  Trac link to the latest changeset in your branch. For example, you can put
+  "<tt>Fixed at changeset [7].</tt>" in the comment. To mark the ticket as
+  "fixed", move down to the <em>Action</em> box section, click on <span class=
+  "mono">&lt;resolve as&gt;</span> and choose <em>fixed</em>. Use <span class=
+  "mono">&lt;Preview&gt;</span> to ensure that your links work correctly. When
+  you are happy, click on <span class="mono">&lt;Submit changes&gt;</span>.</p>
+
+  <h3><a name="tutorial_extra-extract">Extra activities on the extract and
+  build systems</a></h3>
+
+  <p><em>The extract and build systems are very flexible. If you have time, you
+  may want to explore their uses in more depth.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>extract from a working copy,</li>
+
+    <li>change a compiler flag, and</li>
+
+    <li>extract from a particular branch and/or revision from the
+    repository.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li><a href="extract.html">The Extract System</a></li>
+
+    <li><a href="build.html">The Build System</a></li>
+  </ul>
+
+  <h4>Extract from a working copy</h4>
+
+  <p>Modify the source files in your working copy and commit the changes back
+  to your branch in the repository. Re-run <tt>"fcm extract"</tt> and <tt>"fcm
+  build"</tt> and see the results of the changes. [The file(s) you have changed
+  should be updated by "extract", and "build" should only re-build the
+  necessary code.]</p>
+
+  <p>In fact, you can test changes in your working copy directly using a
+  similar "extract" and "build" mechanism. In such case, you need to modify the
+  REPOS declaration. For example:</p>
+  <pre>
+repos::tutorial::base  $HOME/fcm/work/r1_tutorial
+</pre>
+
+  <h4>Change a compiler flag</h4>
+
+  <p>Modify the compiler flags, and re-run <tt>"fcm extract"</tt> and <tt>"fcm
+  build"</tt> and see the results of the changes. To modify the compiler flags,
+  edit your extract configuration file, and add the declarations for changing
+  compiler flags. For example:</p>
+  <pre>
+# Declare extra options for Fortran compiler
+bld::tool::fflags  -i8 -O3
+</pre>
+
+  <p>For further information on how to set your compiler flags, please refer to
+  the sub-section on <a href="build.html#basic_flags">Setting the compiler
+  flags</a>.</p>
+
+  <h4>Extract from a particular branch and/or revision</h4>
+
+  <p>Try extracting from an earlier revision of your branch. Suppose the HEAD
+  of your branch is revision 7, and the branch was created at an earlier
+  revision. You can extract your branch at, say, revision 5 by adding a
+  declaration in your extract configuration file:</p>
+  <pre>
+version::tutorial::base  5
+</pre>
+
+  <p>You can also try extracting from the trunk. In such case, you will need to
+  modify the REPOS declaration in your extract configuration file. For
+  example:</p>
+  <pre>
+repos::tutorial::base  fcm:tutorial_tr/src
+
+# Extract with and without the following line and note the difference!
+version::tutorial::base  1
+</pre>
+
+  <h3><a name="tutorial_delete-branch">Delete your branch</a></h3>
+
+  <p><em>You should remove your branch when it is no longer required. When you
+  remove it, it becomes invisible from the HEAD revision, but will continue to
+  exist in the repository, should you want to refer to it in the
+  future.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>list branches owned by you, and</li>
+
+    <li>delete a branch.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_list">Listing Branches Created by You
+    or Other Users</a></li>
+
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_delete">Deleting Branches</a></li>
+  </ul>
+
+  <h4>List branches owned by you</h4>
+
+  <p>If you forget what your branch is called and/or what other branches you
+  have created, you can get a listing of all the branches you have created in a
+  project. To do this in the GUI, click on <span class=
+  "mono">&lt;Branch&gt;</span>, and then on the <span class=
+  "mono">&lt;list&gt;</span> radio button. Click on <span class=
+  "mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm branch --list</tt> (or
+  simply <tt>fcm br -l</tt>) command.</p>
+
+  <h4>Delete a branch</h4>
+
+  <p>Switch your working copy to point back to your branch. In the GUI, click
+  on <span class="mono">&lt;Switch&gt;</span>. Enter the name of your branch as
+  the URL and click on <span class="mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm switch
+  &lt;URL&gt;</tt> (or simply <tt>fcm sw &lt;URL&gt;</tt>) command.</p>
+
+  <p>You can continue your work in the branch if you wish, but once you have
+  finished all the work, you should delete it. To do so in the GUI, click on
+  <span class="mono">&lt;Branch&gt;</span> in the GUI. Check the <span class=
+  "mono">&lt;delete&gt;</span> radio button, and click <span class=
+  "mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <p><em>Command line alternative</em>: use the <tt>fcm branch --delete</tt> (or
+  simply <tt>fcm br -d</tt>) command.</p>
+
+  <table class="pad" summary="branch delete example" border="1" width="100%">
+    <tr>
+      <th>Example output, deleting a branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+URL: svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial
+Repository Root: svn://fcm1/tutorial_svn
+Repository UUID: cb858ce8-0f05-0410-9e64-efa98b760b62
+Revision: 7
+Node Kind: directory
+Last Changed Author:
+Last Changed Rev: 7
+Last Changed Date: 2005-11-09 09:11:57 +0000 (Wed, 09 Nov 2005)
+--------------------------------------------------------------------------------
+Branch Create Rev: 5
+Branch Create Date: 2005-11-09 08:34:22 +0000 (Wed, 09 Nov 2005)
+Branch Parent: svn://fcm1/tutorial_svn/tutorial/trunk@1
+--------------------------------------------------------------------------------
+Last Merge From Trunk: /tutorial/branches/test/frsn/r1_tutorial@7
+                       /tutorial/trunk@2
+Avail Merges Into Trunk: 7 6
+Starting nedit to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+Deleted tutorial/branches/test/frsn/r1_tutorial.
+--This line, and those below, will be ignored--
+D    svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial
+------------------------------------------------------------------------
+Deleting branch
+  svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial ...
+
+Committed revision 8.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>You will be prompted to edit the commit message file. A standard template
+  is automatically supplied for the commit. However, if you want to add extra
+  comment for the branch, please do so <strong>above</strong> the line that
+  says "<tt>--This line will be ignored and those below will be inserted
+  automatically--</tt>". Save your change and exit the editor.</p>
+
+  <p>Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to go
+  ahead and delete this branch.</p>
+
+  <p>Your working copy is now pointing to a branch that no longer exists at the
+  HEAD revision of the repository. If you want to try the tutorial again, you
+  may want to create another branch, and switch your working copy to point to
+  the new branch. Otherwise, you can remove your working copy by issuing a
+  careful <tt>rm -rf</tt> command.</p>
+
+  <h3><a name="tutorial_delete-final-comments">Final comments</a></h3>
+
+  <p>We have guided you through the basics of the complete change process,
+  using recommended ways of working. Most of the basic and important commands
+  have been covered by the tutorial. (The only exception is <tt>update</tt>,
+  which you may have to use regularly. For information on the command, please
+  refer to the section on <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.tour.cycle.html#svn.tour.cycle.update">
+  Update Your Working Copy</a> in the <a href=
+  "http://svnbook.red-bean.com/en/1.2/">Subversion book</a>.) You should now be
+  in a position to continue with your development work with FCM. However, if at
+  any time you are unsure about any aspect of using FCM, please consult the
+  relevant section of the <a href="index.html">FCM User Guide</a>.</p>
+
+  <p>Feel free to use the tutorial, at any time, for testing out any aspect of
+  the system. You may wish to do this rather than use your own repository and
+  ticket system, to avoid cluttering them with unwanted junk.</p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/index.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/index.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/index.html	(revision 329)
@@ -0,0 +1,465 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM User Guide">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85" height=
+  "85"></p>
+
+  <h1>FCM System<br>
+  User Guide</h1>
+
+  <p align="center">Release: 1.1</p>
+
+  <p align="center">Last updated: 03 November 2006</p>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown copyright 2005-6. All rights reserved.</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+  
+  <script type="text/javascript">
+  <!--
+  var out = 'For printing, please use the '
+  out    += '<a href="fcm-user-guide.pdf">PDF<\/a> version of the document.'
+  document.write ('<p align="center">')
+  document.write (out)
+  document.write ('<\/p>')
+  //-->
+  </script>
+
+  <h2 align="center">Contents</h2>
+
+  <ol>
+    <li><a href="introduction.html">Introduction</a></li>
+
+    <li><a href="overview.html">System Overview</a></li>
+
+    <li>
+      <a href="getting_started.html">Getting Started</a>
+
+      <ul>
+        <li><a href="getting_started.html#setup">How to set yourself up to run
+        FCM</a></li>
+
+        <li><a href="getting_started.html#tutorial">Tutorial</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="code_management.html">Code Management System</a>
+
+      <ul>
+        <li>
+          <a href="code_management.html#svn">Using Subversion</a>
+
+          <ul>
+            <li><a href="code_management.html#svn_concepts">Basic
+            Concepts</a></li>
+
+            <li>
+              <a href="code_management.html#svn_basic">Basic Command Line
+              Usage</a>
+
+              <ul>
+                <li><a href=
+                "code_management.html#svn_basic_keywords">Repository &amp;
+                Revision Keywords</a></li>
+
+                <li><a href="code_management.html#svn_basic_diff">Examining
+                Changes</a></li>
+
+                <li><a href=
+                "code_management.html#svn_basic_conflicts">Resolving
+                Conflicts</a></li>
+
+                <li><a href="code_management.html#svn_basic_check">Adding and
+                Removing Files</a></li>
+
+                <li><a href="code_management.html#svn_basic_commit">Committing
+                Changes</a></li>
+              </ul>
+            </li>
+
+            <li>
+              <a href="code_management.html#svn_branching">Branching &amp;
+              Merging</a>
+
+              <ul>
+                <li><a href=
+                "code_management.html#svn_branching_create">Creating
+                Branches</a></li>
+
+                <li><a href="code_management.html#svn_branching_list">Listing
+                Branches Created by You or Other Users</a></li>
+
+                <li><a href="code_management.html#svn_branching_info">Getting
+                Information About Branches</a></li>
+
+                <li><a href=
+                "code_management.html#svn_branching_switch">Switching your
+                working copy to point to another branch</a></li>
+
+                <li><a href=
+                "code_management.html#svn_branching_delete">Deleting
+                Branches</a></li>
+
+                <li><a href=
+                "code_management.html#svn_branching_merge">Merging</a></li>
+              </ul>
+            </li>
+
+            <li>
+              <a href="code_management.html#svn_gui">Using the GUI</a>
+
+              <ul>
+                <li><a href="code_management.html#svn_gui_start">Starting the
+                GUI</a></li>
+
+                <li><a href="code_management.html#svn_gui_commands">GUI
+                Commands</a></li>
+
+                <li><a href="code_management.html#svn_gui_konqueror">Accessing
+                the GUI from Konqueror</a></li>
+              </ul>
+            </li>
+
+            <li><a href="code_management.html#svn_problems">Known Problems with
+            Subversion</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="code_management.html#trac">Using Trac</a>
+
+          <ul>
+            <li><a href="code_management.html#trac_login">Logging In</a></li>
+
+            <li><a href="code_management.html#trac_wiki">Using the Wiki
+            Pages</a></li>
+
+            <li><a href="code_management.html#trac_browser">Using the
+            Repository Browser</a></li>
+
+            <li><a href="code_management.html#trac_tickets">Using the Issue
+            Tracker</a></li>
+
+            <li><a href="code_management.html#trac_roadmap">Using the
+            Roadmap</a></li>
+
+            <li><a href="code_management.html#trac_timeline">Using the
+            Timeline</a></li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="working_practices.html">Code Management Working Practices</a>
+
+      <ul>
+        <li><a href="working_practices.html#changes">Making Changes</a></li>
+
+        <li><a href="working_practices.html#wc">Working Copies</a></li>
+
+        <li>
+          <a href="working_practices.html#branching">Branching &amp;
+          Merging</a>
+
+          <ul>
+            <li><a href="working_practices.html#branching_when">When to
+            Branch</a></li>
+
+            <li><a href="working_practices.html#branching_where">Where to
+            Branch From</a></li>
+
+            <li><a href="working_practices.html#branching_update">Merging From
+            the Trunk</a></li>
+
+            <li><a href="working_practices.html#branching_commit">Merging Back
+            to the Trunk</a></li>
+
+            <li><a href="working_practices.html#branching_delete">When to
+            Delete Branches</a></li>
+          </ul>
+        </li>
+
+        <li><a href="working_practices.html#binary">Working with Binary Files</a>
+
+          <ul>
+            <li><a href="working_practices.html#binary_conflicts">Resolving
+            Conflicts in Binary Files</a></li>
+
+            <li><a href="working_practices.html#binary_locking">Using
+            Locking</a></li>
+          </ul>
+        </li>
+
+        <li><a href="working_practices.html#messages">Commit Log
+        Messages</a></li>
+
+        <li>
+          <a href="working_practices.html#tickets">Trac Tickets</a>
+
+          <ul>
+            <li><a href="working_practices.html#tickets_create">Creating
+            Tickets</a></li>
+
+            <li><a href="working_practices.html#tickets_use">Using
+            Tickets</a></li>
+          </ul>
+        </li>
+
+        <li><a href="working_practices.html#packages">Creating
+        Packages</a></li>
+
+        <li><a href="working_practices.html#releases">Preparing System
+        Releases</a></li>
+
+        <li><a href="working_practices.html#rapid">Rapid vs Staged Development
+        Practises</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="extract.html">The Extract System</a>
+
+      <ul>
+        <li><a href="extract.html#command">The Extract Command</a></li>
+
+        <li>
+          <a href="extract.html#simple">Simple Usage</a>
+
+          <ul>
+            <li><a href="extract.html#simple_local">Extract from a local
+            path</a></li>
+
+            <li><a href="extract.html#simple_url">Extract from a Subversion
+            URL</a></li>
+
+            <li><a href="extract.html#simple_mirror">Mirror code to a remote
+            machine</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="extract.html#advanced">Advanced Usage</a>
+
+          <ul>
+            <li><a href="extract.html#advanced_multi">Extract from multiple
+            repositories</a></li>
+
+            <li><a href="extract.html#advanced_branches">Extract from multiple
+            branches</a></li>
+
+            <li><a href="extract.html#advanced_incremental">Incremental extract
+            based on a previous extraction</a></li>
+
+            <li><a href="extract.html#advanced_build">Extract - Build
+            Configuration</a></li>
+          </ul>
+        </li>
+
+        <li><a href="extract.html#verbose">Diagnostic verbose level</a></li>
+
+        <li><a href="extract.html#nosvn">When Subversion Is Not
+        Available</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="build.html">The Build System</a>
+
+      <ul>
+        <li><a href="build.html#command">The Build Command</a></li>
+
+        <li>
+          <a href="build.html#basic">Basic Features</a>
+
+          <ul>
+            <li><a href="build.html#basic_build">Basic build
+            configuration</a></li>
+
+            <li><a href="build.html#basic_extract">Build configuration via the
+            extract system</a></li>
+
+            <li><a href="build.html#basic_exename">Naming of executables</a></li>
+
+            <li><a href="build.html#basic_flags">Setting the compiler
+            flags</a></li>
+
+            <li><a href="build.html#basic_interface">Automatic Fortran 9X
+            interface block</a></li>
+
+            <li><a href="build.html#basic_dependency">Automatic
+            dependency</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="build.html#advanced">Advanced Features</a>
+
+          <ul>
+            <li><a href="build.html#advanced_dependency">Further dependency
+            features</a></li>
+
+            <li><a href="build.html#advanced_blockdata">Linking a Fortran
+            executable with a BLOCKDATA program unit</a></li>
+
+            <li><a href="build.html#advanced_library">Creating library
+            archives</a></li>
+
+            <li><a href="build.html#advanced_pp">Pre-processing</a></li>
+
+            <li><a href="build.html#advanced_file-type">File type</a></li>
+
+            <li><a href="build.html#advanced_incremental">Incremental build
+            based on a pre-compiled build</a></li>
+
+            <li><a href="build.html#advanced_pckcfg">Using a package
+            configuration file</a></li>
+
+            <li><a href="build.html#advanced_data">Building data files</a></li>
+          </ul>
+        </li>
+
+        <li><a href="build.html#verbose">Diagnostic verbose level</a></li>
+
+        <li><a href="build.html#overview">Overview of the build
+        process</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="system_admin.html">System Administration</a>
+
+      <ul>
+        <li>
+          <a href="system_admin.html#svn">Subversion</a>
+
+          <ul>
+            <li><a href="system_admin.html#svn_design">Repository
+            design</a></li>
+
+            <li><a href="system_admin.html#svn_create">Creating a
+            repository</a></li>
+
+            <li><a href="system_admin.html#svn_access">Access control</a></li>
+
+            <li><a href="system_admin.html#svn_hosting">Repository
+	    hosting</a></li>
+
+            <li><a href="system_admin.html#svn_watch">Watching changes in log
+            messages</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="system_admin.html#trac">Trac</a>
+
+          <ul>
+            <li><a href="system_admin.html#trac_config">Trac
+            configuration</a></li>
+
+            <li><a href="system_admin.html#trac_hosting">Trac hosting</a></li>
+          </ul>
+        </li>
+
+        <li><a href="system_admin.html#fcm-keywords">FCM keywords</a></li>
+
+        <li><a href="system_admin.html#ext-bld-cfg">Extract and build
+        configuration</a></li>
+
+        <li><a href="system_admin.html#alternate_versions">Maintaining
+        alternate versions of namelists and data files</a></li>
+
+        <li><a href="system_admin.html#work-practise">Defining working
+        practises and policies</a></li>
+
+      </ul>
+    </li>
+
+    <li>
+      <a href="command_ref.html">FCM Command Reference</a>
+
+      <ul>
+        <li><a href="command_ref.html#fcm_config">fcm Configuration
+        File</a></li>
+
+        <li><a href="command_ref.html#fcm_bld">fcm build</a></li>
+
+        <li><a href="command_ref.html#fcm_ext">fcm extract</a></li>
+
+        <li><a href="command_ref.html#fcm_cmp-ext-cfg">fcm cmp-ext-cfg</a></li>
+
+        <li><a href="command_ref.html#fcm_gui">fcm gui</a></li>
+
+        <li>
+          <a href="command_ref.html#fcm_svn">fcm Subversion Subcommands</a>
+
+          <ul>
+            <li><a href="command_ref.html#fcm_svn_add">fcm add</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_br">fcm branch</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_ci">fcm commit</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_cf">fcm conflicts</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_rm">fcm delete</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_diff">fcm diff</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_merge">fcm merge</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_mkpatch">fcm mkpatch</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_switch">fcm switch</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_trac">fcm trac</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_other">Other Subversion
+            Commands</a></li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li><a href="further_info.html">Further Information</a></li>
+  </ol>
+
+  <p>Annex:</p>
+
+  <ul>
+    <li><a href="annex_quick_ref.html">Quick reference</a></li>
+
+    <li><a href="annex_fcm_cfg.html">Declarations in FCM central/user
+    configuration file</a></li>
+
+    <li><a href="annex_ext_cfg.html">Declarations in FCM extract configuration
+    file</a></li>
+
+    <li><a href="annex_bld_cfg.html">Declarations in FCM build configuration
+    file</a></li>
+
+    <li><a href="annex_pck_cfg.html">Declarations in FCM build package
+    configuration file</a></li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/introduction.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/introduction.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/introduction.html	(revision 329)
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Introduction</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Introduction">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Introduction
+  </address>
+
+  <h1>Introduction</h1>
+
+  <p>This is the User Guide for the <em>Flexible Configuration Management</em>
+  system which is known as <em>FCM</em>. It is designed to tell you everything
+  you need to know if you want to develop code which has been configured within
+  FCM. In addition it also provides the extra information you will need if you
+  are system manager of a project within FCM.</p>
+
+  <p>Note: some hyperlinks in this document lead to pages that are internal to
+  the Met Office, and so will generally not work when this document is viewed
+  externally. Please accept our apologies if this causes you any
+  inconvenience.</p>
+
+  <p>This guide consists of the following sections:</p>
+
+  <ul>
+    <li><a href="overview.html">System Overview</a>: A brief description of the
+    main features of FCM.</li>
+
+    <li><a href="getting_started.html">Getting Started</a>: How to start using
+    FCM. It includes a tutorial for you to work through and
+    familiarise yourself with some FCM activities.</li>
+
+    <li><a href="code_management.html">Code Management System</a>: How to use
+    the code management system to manage code changes.</li>
+
+    <li><a href="working_practices.html">Code Management Working Practices</a>:
+    Recommended ways of working with the code management system.</li>
+
+    <li><a href="extract.html">The Extract System</a>: How to extract code from
+    the repository ready for building.</li>
+
+    <li><a href="build.html">The Build System</a>: How to compile code using
+    the build system.</li>
+
+    <li><a href="system_admin.html">System Administration</a>: How to configure
+    and maintain a new system within FCM.</li>
+
+    <li><a href="command_ref.html">FCM Command Reference</a>: Detailed
+    information about each of the <em>fcm</em> commands.</li>
+
+    <li><a href="further_info.html">Further Information</a>: Where to find
+    further information about FCM and about configuration management in
+    general.</li>
+
+    <li>Annex: <a href="annex_quick_ref.html">Quick reference</a>: A quick
+    reference to many useful FCM code management system commands.</li>
+
+    <li>Annex: Detailed definitions of what declarations are allowed in the
+    following configuration files:
+
+      <ul>
+        <li><a href="annex_fcm_cfg.html">central/user</a></li>
+
+        <li><a href="annex_ext_cfg.html">extract</a></li>
+
+        <li><a href="annex_bld_cfg.html">build</a></li>
+
+        <li><a href="annex_pck_cfg.html">build package</a></li>
+      </ul>
+    </li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/maintain.js
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/maintain.js	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/maintain.js	(revision 329)
@@ -0,0 +1,11 @@
+// Display info about maintenance team
+
+// FCM contact URL
+var url     = 'http://www.metoffice.gov.uk/research/nwp/external/fcm/'
+var contact = '<a href="' + url + '">the FCM team</a>'
+
+// Output string 
+var out     = '<p></p><hr><address>Maintained by ' + contact + '.</address>'
+
+// Write to document
+document.write (out)
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/overview.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/overview.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/overview.html	(revision 329)
@@ -0,0 +1,192 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: System Overview</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - System Overview">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; System Overview
+  </address>
+
+  <h1>System Overview</h1>
+
+  <p>The FCM system is designed to simplify the task of managing and building
+  source code. It consists of three main components.</p>
+
+  <ul>
+    <li>Code Management (CM) System
+
+      <ul>
+        <li>This system provides facilities for making changes to source code in
+        a controlled and straightforward manner.</li>
+
+	<li>Version control is provided by the open source tool
+        <a href="http://subversion.tigris.org/"><em>Subversion</em></a>. The
+        source code and its history are stored in a central database which is
+        called the repository. Support for parallel working is provided through
+        the use of branches.</li>
+
+	<li>The open source web-based tool <a href="http://trac.edgewall.org/">
+        <em>Trac</em></a> allows changes to be examined and documented. It
+        provides an integrated issue tracker, wiki and repository browser.</li>
+      </ul>
+    </li>
+
+    <li>Build System
+
+      <ul>
+        <li>This system allows source code to be compiled with a minimal amount
+        of configuration. Compilation time can be minimised through the use of
+        pre-compiled code and by using the parallel make facilities provided by
+        the open source tool <a href="http://www.gnu.org/software/make/"><em>GNU
+        Make</em></a>.</li>
+
+        <li>It provides a number of powerful features aimed primarily at building
+        Fortran 9x code.</li>
+      </ul>
+    </li>
+
+    <li>Extract System
+
+      <ul>
+        <li>This system provides the interface between the CM and build systems.
+        Code is extracted and presented in a suitable form for the build system.
+	Code can be mirrored to a different build platform if necessary.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>The diagram below illustrates how these components fit together.</p>
+
+  <p class="image"><img src="fcm_overview.png" alt="FCM system overview"></p>
+
+  <p>The following sections discuss these components in more detail.</p>
+
+  <h2>Code Management System</h2>
+
+  <p>The CM system is built using a number of open source tools, in particular
+  <em>Subversion</em> and <em>Trac</em>.</p>
+
+  <p><em>Subversion</em> is a modern version control tool with a large and
+  rapidly expanding user base. For a summary of its main features please refer
+  to chapter 1 of the book
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.intro.html">Version Control
+  with Subversion</a>.</p>
+
+  <p>Subversion is a generalised tool which can be used in lots of different
+  ways. This makes some day-to-day tasks more complex than they need be. FCM
+  defines a simplified process and appropriate naming conventions. It then adds
+  a layer on top of Subversion to provide a natural interface which is
+  specifically tailored to this process. Where appropriate it simply makes use of
+  the command line tools provided by Subversion. However, in other cases it
+  provides significant additional functionality, for example:</p>
+
+  <ul>
+    <li>By making some assumptions about the repository layout (i.e. by
+    imposing a standard working practise) FCM simplifies the task of
+    creating branches and enforces a standard branch naming convention.</li>
+
+    <li>Having defined working practises and standard log messages allows FCM to
+    greatly simplify the process of merging changes between branches.</li>
+
+    <li>FCM makes use of <a href="http://furius.ca/xxdiff/"><em>xxdiff</em></a>
+    (a graphical merge tool) to simplify the process of resolving any conflicts
+    which result from a merge.</li>
+
+    <li>Code changes can be examined in graphical form using <em>xxdiff</em>.
+    FCM also allows you to easily examine the changes made on a branch.</li>
+
+    <li>FCM allows you to check where any particular branch has been used and
+    which version is being used.</li>
+  </ul>
+
+  <p>FCM also provides a simple GUI which allows easy access to most of the
+  common commands which you will need.</p>
+
+  <p><em>Trac</em> is the other main component of the CM system. It is a
+  powerful web based tool which helps you to manage your software project. It
+  includes the following features:</p>
+
+  <ul>
+    <li>A flexible issue tracker which can be used to keep track of bugs, feature
+    requests, etc. Each issue (known as a "ticket" within Trac) can be given a
+    priority and assigned to a particular person. Changes made to your Subversion
+    repository can easily be traced to the relevant ticket. Where appropriate,
+    tickets can be used to record information about who has reviewed each change.
+    </li>
+
+    <li>A roadmap feature which helps you to plan and manage project releases.
+    Each ticket can be associated with a particular milestone. Trac can then
+    easily show you what features or fixes went into a particular release or
+    what work remains before a particular milestone is reached.</li>
+
+    <li>A "wiki" which can be used for project documentation.</li>
+
+    <li>A browser for viewing your Subversion repository which allows you to
+    browse the project tree / files and examine revision logs and changesets.
+    </li>
+
+    <li>A timeline view which summarises all the activity on a project (changes
+    to the tickets, wiki pages or the Subversion repository).</li>
+  </ul>
+
+  <h2>Build System</h2>
+
+  <p>The build system provides the following features:</p>
+
+  <ul>
+    <li>Automatic generation of Makefile's at build time based on a simple
+    configuration file.</li>
+
+    <li>Full dependency analysis at build time.</li>
+
+    <li>Automatic generation of Fortran 9x interface files at build time.</li>
+
+    <li>Support for non-standard source code. You can override automatic
+    dependency and compile rules in order to deal with code which does not
+    conform to the necessary coding standards.</li>
+
+    <li>Flexible control over compiler flags. Changes to compiler flags trigger
+    the appropriate re-compilation.</li>
+
+    <li>Support for Pre-processor directives. Changes to Pre-processor flags
+    trigger the appropriate re-compilation.</li>
+
+    <li>Support for pre-compiled object code to speed compilation time.</li>
+
+    <li><em>GNU make</em> is used to perform the build. Build times on
+    multi-processor systems can be reduced using <em>parallel make</em>.</li>
+  </ul>
+
+  <h2>Extract System</h2>
+
+  <p>The extract system provides the following features:</p>
+
+  <ul>
+    <li>Extraction of code to a directory tree suitable for feeding into the
+    build system. Code can be combined from multiple repositories and branches.
+    Local user code can also be included.</li>
+
+    <li>Either a complete set of source code may be extracted or just a set of
+    changes relative to pre-compiled code.</li>
+
+    <li>A simple configuration file defines what code is required (and what
+    compile options are required). Typically, standard versions of these
+    configuration files are maintained within the repository. Users can then
+    define changes relative to these standard versions.</li>
+
+    <li>If necessary, code can be transferred to a different platform ready for
+    building.</li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/style.css
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/style.css	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/style.css	(revision 329)
@@ -0,0 +1,128 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+@media screen {
+  body {
+    background-color: #ffffcc;
+    color: black;
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: 12pt;
+  }
+}
+@media print {
+  body {
+    color: black;
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: 12pt;
+  }
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+li {
+  padding: 5px;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+.yell td {
+  background-color: transparent;
+}
+
+.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
+
+.pad th, .pad td {
+  padding: 5px;
+}
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/style.html2ps.css
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/style.html2ps.css	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/style.html2ps.css	(revision 329)
@@ -0,0 +1,29 @@
+/* Configuration file for html2ps on the FCM user guide */
+
+h1 {
+  color: navy;
+  text-align: center;
+}
+
+h2 {
+  color: navy;
+}
+
+h3 {
+  color: #40668c;
+}
+
+h4 {
+  font-size: 12pt;
+}
+
+a:link {
+  color: blue;
+}
+
+@page {
+  margin-left: 2cm;
+  margin-right: 2cm;
+  margin-top: 2cm;
+  margin-bottom: 2cm;
+}
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/system_admin.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/system_admin.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/system_admin.html	(revision 329)
@@ -0,0 +1,558 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: System Administration</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - System Administration">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; System Administration
+  </address>
+
+  <h1>System Administration</h1>
+
+  <p>This chapter provides an administration guide for managers of projects or
+  systems which are using FCM.</p>
+
+  <p>Note that, where this section refers to the "FCM team" this applies only to
+  Met Office users. External users will either need to refer to the equivalent
+  team within their organisation or will need to perfom these tasks themselves.
+  </p>
+
+  <h2><a name="svn">Subversion</a></h2>
+
+  <h3><a name="svn_design">Repository design</a></h3>
+
+  <p>The FCM system assumes that each project directory has sub-directories called
+  <em>trunk</em>, <em>branches</em> and <em>tags</em> (Subversion recommends it but
+  doesn't insist on it). We recommend that each project within a Subversion
+  repository is in a sub-directory of the repository root.</p>
+      <pre>
+&lt;root&gt;
+    |
+    |-- &lt;project 1&gt;
+    |       |
+    |       |-- trunk
+    |       |-- branches
+    |       |-- tags
+    |
+    |-- &lt;project 2&gt;
+    |       |
+    |       |-- trunk
+    |       |-- branches
+    |       |-- tags
+    |
+    |-- ...
+</pre>
+  <p>In theory you could also have the project as the root directory or several levels
+  below the root directory. However, this is not tested and could cause problems with
+  some <tt>fcm</tt> commands so is best avoided.</p>
+
+  <p>You will need to decide whether to use a single project tree for your system or
+  whether to use multiple projects.</p>
+
+  <p>Advantages of a single project tree:</p>
+
+  <ul>
+    <li>Changes to any part of the system can always be committed as a single logical
+    changeset. If you split your system into multiple projects then you may have
+    occasions when a logical change involves more than one project and hence requires
+    multiple commits (and branches).</li>
+  </ul>
+
+  <p>Disadvantages of a single project tree:</p>
+
+  <ul>
+    <li>If you have a large system then your working copies may become very large
+    and unwieldy. Basic commands such as <tt>checkout</tt> and <tt>status</tt>
+    can become frustratingly slow if your working copy is too large.</li>
+        
+    <li>Depending on how you work, you may end up doing lots more merges of files
+    that are unrelated to your work.</li>
+  </ul>
+
+  <p>One common approach is to split the admin type files (things that only the
+  system manager should need to touch) into a separate project from the core
+  system files (which all the developers need access to). If you include any
+  large data files under version control you may also want to use a separate
+  project for them to avoid making your working copies very large when editing
+  code.</p>
+  
+  <p>Note that there is often no obvious right or wrong answer so you just have
+  to make a decision and see how it works out. You can always re-arrange your
+  repository in the future (although be aware that this will break any changes
+  being prepared on branches at the time).</p>
+
+  <p>You also need to decide whether your system requires its own repository (or
+  multiple repositories) or whether it can share with another system.</p>
+  
+  <ul>
+    <li>The main disadvantage of having separate repositories for each system is
+    the maintenance overhead (although this is almost all automated by the FCM
+    team so is not a big deal).</li>
+        
+    <li>We normally configure a single Trac system per repository. If the
+    repository contains multiple systems then it makes it difficult to use the
+    Trac milestones to handle system releases. However, Trac now supports
+    restricting itself to a sub-directory within a repository so, again, this is
+    not a big deal.</li>
+        
+    <li>If you share a repository with other systems then your revision numbers
+    can increase even when there are no changes to your system. This doesn't
+    matter but some people don't like it.</li>
+  </ul>
+  
+  <p>For simplicity, in most cases you will probably want your own repository for
+  your system.</p>
+
+  <p>You will not normally want to have multiple repositories for a system. One
+  exception may be if you are storing large data files where you might not want
+  to keep all the old versions for ever. Removing old versions can't be done
+  without changing all the revision numbers which would mess up all your code
+  history and Trac tickets. Storing the large data files in a separate
+  repository reduces the impact if you do decide to remove old versions in the
+  future. One disadvantage of this approach is that, for the moment at least,
+  Trac only handles one repository so you will need a separate Trac system for
+  the data files.</p>
+
+  <p>For further details please see the section
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.reposadmin.projects.html#svn.reposadmin.projects.chooselayout">
+  Choosing a Repository Layout</a> from the Subversion book.</p>
+
+  <h3><a name="svn_create">Creating a repository</a></h3>
+
+  <p>Normally the FCM team will help you to set up your initial repository.
+  However, it is quite simple if you need to do it yourself. First you need to
+  issue the command <tt>svnadmin create /path/to/repos</tt>. This creates an
+  empty repository which is now ready to accept an initial import. To do so,
+  you should create a directory tree in a suitable location, and issue the
+  <tt>svn import</tt> command. At the top level of your directory tree should be
+  the project directories. Each project should then contain three directories
+  "trunk", "branches" and "tags". The directories "branches" and "tags" should be
+  empty.  The directory "trunk" should contain your source files in a directory
+  structure you have chosen.  For example, if your directory tree is located
+  at "$HOME/foo", you will do the following to import it to a new repository:</p>
+
+  <table class="pad" summary="creating a repository and importing a project tree" border="1" width="100%">
+    <tr>
+      <th>Creating a repository and importing a project tree</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ svnadmin create FOO_svn
+(SHELL PROMPT)$ svn import $HOME/foo file://$PWD/FOO_svn -m 'Initial import'
+Adding         FOO
+Adding         FOO/trunk
+Adding         FOO/trunk/doc
+Adding         FOO/trunk/doc/hello.html
+Adding         FOO/trunk/doc/world.html
+Adding         FOO/trunk/src
+Adding         FOO/trunk/src/bar
+Adding         FOO/trunk/src/bar/egg.f90
+Adding         FOO/trunk/src/bar/ham.f90
+Adding         FOO/branches
+Adding         FOO/tags
+
+Committed revision 1.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Note that the <tt>svnadmin</tt> command takes a PATH as an argument, as
+  opposed to a URL for the <tt>svn</tt> command.</p>
+
+  <p>For further details please see the section
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.reposadmin.projects.html#svn.reposadmin.projects.import">
+  Creating the Layout, and Importing Initial Data</a> from the Subversion book.</p>  
+
+  <h3><a name="svn_access">Access control</a></h3>
+
+  <p>You will not normally want to allow anonymous write access to your repository
+  since this means that changes do not get identified with a userid. Therefore
+  system managers need to provide the FCM team with a list of users who should
+  have write access to their repositories. You may also want to arrange passwords
+  for these users although this is only necessary if you need to prevent
+  malicious access. Further restrictions such as preventing anonymous read access
+  or restricting write access to the trunk to a limited set of users can be
+  arranged if necessary.</p>
+
+  <h3><a name="svn_hosting">Repository hosting</a></h3>
+
+  <p>The FCM team will organise the hosting of your repository. A number of
+  facilities will be set up for you as standard.</p>
+  
+  <ul>
+    <li>Your repository will be set up on a central FCM server and access will be
+    provided via <em>svnserve</em> (which we use in preference to <em>Apache</em>
+    for performance reasons). The FCM team will advise you of the URL.</li>
+        
+    <li>Each night a full backup of your repository will be taken. An integrity
+    check will also be performed using the <tt>svnadmin verify</tt> command.</li>
+        
+    <li>Standard hook scripts will be set up to handle the following post-commit
+    tasks:
+
+      <ul>
+        <li>Each time a changeset is successfully committed an incremental dump
+        of the new revision is taken. This would allow the repository to be
+        recovered should the live repository become corrupted for whatever
+        reason.</li>
+            
+        <li>A file is updated which records the latest revision of your
+        repository. This can be used by system managers to regularly check for
+        new commits in a cron job and perform any required actions (updating
+        files on a remote platform for instance). The FCM team can advise you
+        of the location of this file and show you some example scripts which
+        make use of it.</li>
+      </ul>
+    </li>
+
+    <li>Standard hook scripts will be set up to handle the following tasks for
+    changes in revision properties (pre-revprop-change/post-revprop-change):
+
+      <ul>
+        <li>If a user attempts to modify the log message of a changeset and
+        he/she is not the original author of the changeset, the
+        pre-revprop-change hook script will e-mail the original author. You can
+        also set up a watch facility to monitor changes of log messages that
+        affect particular paths in the repository. (See the <a href=
+        "#svn_watch">next sub-section</a> for details.)</li>
+
+        <li>The post-revprop-change hook script updates the Trac SQLite database
+        following a successful change in the log message.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>Additional hook scripts can be put in place if you have a requirement. The
+  use of hook scripts is discussed in the section <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.reposadmin.create.html#svn.reposadmin.create.hooks">
+  Repository Creation and Configuration</a> from the Subversion book.</p>
+
+  <p>Note that if you want to use a Subversion repository for your own individual
+  use there is no need to get the FCM team to host it. You can simply create your
+  repository and then use a <tt>file://</tt> URL to access it.</p>
+
+  <h3><a name="svn_watch">Watching changes in log messages</a></h3>
+
+  <p>You can set up a watch facility to monitor changes in revision log messages
+  in your repository. An obvious use of this facility is for system managers to
+  monitor changes of log messages affecting the trunks of their projects. To set
+  up the facility, you will need to add a <tt>watch.cfg</tt> file to the root of
+  your repository. (To avoid checking out the whole repository, including every
+  branch, make sure that you checkout the root of your repository
+  non-recursively, i.e. <tt>fcm checkout -N URL</tt>.) The <tt>watch.cfg</tt>
+  file is an INI-type file, with the basic format:</p>
+
+  <pre>
+[repos_base]
+
+path/in/repos = list,of,watchers
+</pre>
+
+  <p>For example, if your repository is <tt>svn://fcm1/FCM_svn/</tt>, and you
+  want set up particular users to monitor changes of the log messages affecting
+  several areas within the repository, you may have something like this:</p>
+
+  <pre>
+[FCM_svn]
+
+FCM/trunk/src            = fred,bob
+FCM/trunk/doc            = fred,bob,alice
+FCM/branches/dev/*/*/src = fred
+</pre>
+
+  <p>Later on, if "dave" attempts to modify the log message of a changeset that
+  affects the path <tt>FCM/trunk/src</tt>, "fred" and "bob" will both be
+  notified by e-mail.</p>
+    
+  <h2><a name="trac">Trac</a></h2>
+
+  <h3><a name="trac_config">Trac configuration</a></h3>
+
+  <p>Normally the FCM team will set up your Trac system for you (using a script
+  which helps automate the configuration). This section describes some things you
+  may wish to be configured. This can be done when the Trac system is set up or
+  later if you are unsure what you will require at first.</p>
+
+  <h4><a name="trac_access">Access control</a></h4>
+
+  <p>You will not normally want to allow anonymous users to make changes to your
+  Trac system since this means that changes may not get identified with a userid.
+  The FCM team will set up your Trac system with accounts for all users who have
+  write access to your Subversion repository. You may also want to arrange
+  passwords for these users although this is only necessary if you need to prevent
+  malicious access. Further restrictions such as preventing anonymous read access
+  can be arranged if necessary.</p>
+
+  <p>An additional admin account will be set up for the system manager which will
+  be given TRAC_ADMIN privileges. This allows this account to do additional
+  things which normal users cannot do such as:</p>
+
+  <ul>
+    <li>Delete wiki pages (particular versions or the entire page).</li>
+        
+    <li>Add or modify milestones.</li>
+        
+    <li>Modify ticket descriptions and delete ticket attachments.</li>
+        
+    <li>Make wiki pages read-only.</li>
+  </ul>
+  
+  <p>We recommend that the system manager uses a normal account most of the time
+  and only uses their admin account when they require the additional privileges.
+  </p>
+
+  <p>For further details please see the section
+  <a href="http://projects.edgewall.com/trac/wiki/TracPermissions">
+  Trac Permissions</a> from the Trac documentation.</p>  
+
+  <h4><a name="trac_email">Email notification</a></h4>
+
+  <p>By default, each Trac system is configured such that the owner and reporter
+  and anyone on the "CC" list are notified whenever a change is made to a
+  ticket. If system mangers wish to be notified of all ticket changes then this
+  can also be configured. Alternatively, email notifications can be disabled if
+  they are not wanted.</p>
+
+  <h4><a name="trac_milestones">Milestones</a></h4>
+
+  <p>Milestones are useful for identifying when tickets need to be resolved.
+  Typically, milestones may be particular system releases or time periods. The
+  FCM team can configure milestones for you when they set up your Trac system.
+  However, this is not strictly necessary since milestones can be set up via the
+  web interface using the admin account (go to the <em>Roadmap</em> page).</p>
+
+  <h4><a name="trac_misc">Other configurable items</a></h4>
+
+  <p>There are lots of other things that can be configured in your Trac system
+  such as:</p>
+  
+  <ul>
+    <li>Components</li>
+        
+    <li>Versions</li>
+        
+    <li>Custom fields</li>
+        
+    <li>System icon</li>
+        
+    <li>Stylesheets</li>
+  </ul>
+
+  <p>For further details please see the sections
+  <a href="http://projects.edgewall.com/trac/wiki/TracIni">
+  The Trac Configuration File</a> and
+  <a href="http://projects.edgewall.com/trac/wiki/TracTickets">
+  The Trac Ticket System</a> from the Trac documentation.</p>  
+  
+  <h3><a name="trac_hosting">Trac hosting</a></h3>
+
+  <p>The FCM team will organise the hosting of your Trac system. It will be set
+  up on the same server that hosts your Subversion repository and access will be
+  provided via a web server. The FCM team will advise you of the URL. Each night
+  a backup of your Trac system will be taken in case the live system should
+  become corrupted for whatever reason.</p>
+  
+  <h2><a name="fcm-keywords">FCM keywords</a></h2>
+
+  <p>When you set up a repository for a new project, you will normally want the
+  FCM team to set up a set of URL keywords for it in the FCM central
+  configuration file. The name of the project should be a short string containing
+  only word characters. If your project is called "PROJ", the recommended set of
+  keywords are:</p>
+
+  <ul>
+    <li>fcm:proj - for the top level URL of the PROJ repository.</li>
+
+    <li>fcm:proj_tr - for the "trunk" sub-directory of PROJ repository.</li>
+
+    <li>fcm:proj_br - for the "branches" sub-directory of PROJ repository.</li>
+
+    <li>fcm:proj_tg - for the "tags" sub-directory of PROJ repository.</li>
+  </ul>
+
+  <p>If your project has an associated Trac browser, you should also declare the
+  Trac browser URL (that corresponds to the Subversion URL) in the central
+  configuration file. This allows FCM to associate the URL to the Trac browser
+  with a Subversion URL.</p>
+
+  <p>For more information on how to set up the keywords, please refer to <a
+  href="code_management.html#svn_basic_keywords">Repository &amp; Revision
+  Keywords</a> and the <a href="annex_fcm_cfg.html">Annex: Declarations in FCM
+  central/user configuration file</a>.</p>
+
+  <h2><a name="ext-bld-cfg">Extract and build configuration</a></h2>
+
+  <p>The extract and build systems are very flexibile and can be used in lots of
+  different ways. It is therefore difficult to give specific advice explaining
+  how to configure them. However, based on experience with a number of systems,
+  the following general advice can be offered.</p>
+
+  <ul>
+    <li>Standard extract configuration files should be defined and stored within
+    the repository. Users then include these files into their configurations,
+    before applying their local changes.</li>
+    <li>The files should be designed to include one another in a hierarchy. For
+    example, you may have one core file which defines all the repository and
+    source locations plus a series of platform/compiler specific files which
+    include the core file. More complex setups are also possible if you need to
+    cater for other options such as different optimisation levels, 32/64 bit,
+    etc.</li>
+    <li>When including other configuration files, always make use of the special
+    <tt>$HERE</tt> variable
+    (rather than, for instance, referring to a fixed repository location). When
+    your configuration file is parsed, this special variable is normally
+    expanded into the container directory of the current configuration file. This
+    means that the include statements should work correctly whether you are
+    referring to configuration files in the repository trunk, in a branch or in
+    a local working copy.</li>
+    <li>Make good use of user variables (e.g. <tt>%fred</tt>) to simplify
+    repetitive declarations and make your configuration files easier to
+    maintain.</li>
+    <li>Use continuation lines to split long lines and make them easier to read
+    (see the <a href="command_ref.html#fcm_config">FCM Command Reference</a>
+    section for further details about configuration files).</li>
+  </ul>
+
+  <p>Probably the best advice is to look at what has already been set up for
+  other systems. The FCM team can advise on the best systems to examine.</p>
+
+  <p>When you create a stable build you should keep an extract configuration file
+  that can reproduce the build. One easy way to do this is to create your build
+  using the standard configuration files and the latest versions of the code. You
+  can then save the expanded extract configuration file which is created when you
+  run the extraction. To help document your stable build you can use the command
+  <tt>fcm cmp-ext-cfg</tt> to show what has changed.</p>
+
+  <h2><a name="alternate_versions">Maintaining alternate versions of namelists
+  and data files</a></h2>
+
+  <p>Sometimes it is useful to be able to access particular revisions of some
+  directories from a FCM repository without having to go via Subversion. Typical
+  examples are namelist or data files used as inputs to a program. The script
+  <tt>fcm_update_version_dir.pl</tt> is designed to help with this. It can be
+  used to maintain a set of extracted version directories from a FCM repository.
+  The script has the following options and arguments:</p>
+
+  <ul>
+    <li>-f [--full]: specify the full mode, in which the versioned directories
+    of each specified item will be removed before being re-extracted.</li>
+
+    <li>-d [--dest] &lt;arg&gt;: specify a destination &lt;arg&gt; for the
+    extraction. If not specified, the current working directory will be used as
+    the base path.</li>
+
+    <li>-u [--url] &lt;arg&gt;: specify the source repository URL. This option
+    is compulsory.</li>
+  </ul>
+
+  <p>If an argument is specified, it must be the location of a configuration
+  file. Otherwise, the command reads its configuration from the standard input.
+  The configuration file is a line-based text file. Blank lines and lines
+  beginning with a "#" are ignored.</p>
+
+  <p>Each configuration line must contain the relative path of a sub-directory
+  under the specified source repository URL. If the path ends in "<tt>*</tt>"
+  then the path is expanded recursively and any sub-directories containing
+  regular files are added to the list of relative paths to extract.</p>
+
+  <p>Optionally, each relative path may be followed by a list of space separated
+  "conditions". Each condition is a conditional operator (&gt;, &gt;=, &lt;,
+  &lt;=, == or !=) followed by a revision number or the keyword HEAD.</p>
+
+  <p>The command uses the revision log to determine the revisions at which the
+  relative path has been updated in the source repository URL. If these
+  revisions also satisfy the "conditions" set by the user, they will be
+  considered in the extraction. In full mode, everything is re-extracted. In
+  incremental mode, the version directories are only updated if they do not
+  already exist.</p>
+
+  <p>Example:</p>
+
+  <table class="pad" summary="fcm_update_version_dir.pl example" border="1"
+  width="100%">
+    <tr>
+      <th>fcm_update_version_dir.pl example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm_update_version_dir.pl -u fcm:ver_tr &lt;&lt;EOF
+namelists/VerNL_AreaDefinition   &gt;1000 !=1234
+namelists/VerNL_GRIBToPPCode     &gt;=600 &lt;3000
+namelists/VerNL_StationList      
+elements/*                       &gt;1000
+EOF
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>N.B.</p>
+
+  <ol>
+    <li>Each time a sub-directory is revised, the script assigns a sequential
+    "v" number for the item. Each "v" number for a sub-directory, therefore, is
+    associated with a revision number. For each extracted revision directory,
+    there is a corresponding "v" number symbolic link pointing to it.</li>
+
+    <li>The system also creates a symbolic link "latest" to point to the latest
+    extracted revision directory.</li>
+  </ol>
+
+  <h2><a name="work-practise">Defining working practises and policies</a></h2>
+
+  <p>Some options on working practises and policies are defined in the chapter
+  on <a href="working_practices.html">Code Management Working Practices</a>.
+  Individual projects should document the approach they have adopted. In
+  addition, each project may also need to define its own working practices and
+  policies to suit its local need. For example each project may need to
+  specify:</p>
+
+  <ul>
+    <li>Whether changes are allowed directly on the trunk or whether branches
+    have to be used in all cases.</li>
+
+    <li>Whether all users are allowed to make changes to the trunk.</li>
+
+    <li>Whether Trac tickets have to be raised for all changes to the trunk.</li>
+        
+    <li>Whether Trac tickets should be raised for all support queries or whether
+    a Trac ticket should only be raised once there is an agreed "issue".</li>
+
+    <li>Whether branches should normally be made from the latest code or from a
+    stable release.</li>
+
+    <li>Whether a user is allowed to resolve conflicts directly when merging a
+    branch into the trunk or whether he/she should merge the trunk into the
+    branch and resolve the conflicts in the branch first.</li>
+
+    <li>Whether all code changes to the trunk need to be reviewed.</li>
+
+    <li>What testing is required before changes can be merged to the trunk.</li>
+
+    <li>Whether history entries are maintained in source files or whether
+    individual source files changes need to be described in the Subversion log
+    message.</li>
+
+    <li>Branch deletion policy.</li>
+
+    <li>Whether any files in the project require locking before being changed.
+    </li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/working_practices.html
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/working_practices.html	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/doc/user_guide/working_practices.html	(revision 329)
@@ -0,0 +1,825 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Working Practices</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Working Practices">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Code Management
+    Working Practices
+  </address>
+
+  <h1>Code Management Working Practices</h1>
+
+  <p>The previous chapter described how to use the various parts of the FCM
+  code management system. They also described aspects of working practises
+  which are enforced by the system. This section discusses other recommended
+  working practises.  They are optional in the sense that you don't have to
+  follow them to use FCM.  It is a matter for individual projects to decide
+  which working practises to adopt (although we expect most projects/systems
+  at the Met Office to adopt similar practises).</p>
+
+  <h2><a name="changes">Making Changes</a></h2>
+
+  <p>This sub-section gives an overview of the recommended approach for
+  preparing changes. Particular topics are discussed in more detail
+  in later sub-sections where appropriate.</p>
+
+  <p>The recommended process for making a change is as follows:</p>
+
+  <ol>
+    <li>Before work starts on any coding you should make sure that
+	there is a Trac ticket open which explains the purpose of the change.
+	<ul>
+	  <li>Make sure that you set the ticket milestone to indicate
+	      which release of the system you are aiming to include
+	      your change in.
+	  <li>Accept the ticket to indicate that you are working on the change.
+	  <li>For further advice on using tickets see
+	      <a href="#tickets">Trac Tickets</a> later in this section.
+	</ul>
+    <li>Create a branch
+	<ul>
+	  <li>For very simple changes you may be happy to prepare your changes
+	      directly on the trunk. For further details see
+	      <a href="#branching_when">When to Branch</a> later in this section.
+	  <li>Create your branch either from the latest version or from a stable
+	      release (see <a href="#branching_where">Where to Branch From</a>
+	      later in this section).
+	</ul>
+    <li>Prepare your code changes on the branch
+	<ul>
+	  <li>Commit interim versions to your branch on a regular basis as you
+	      develop your change. This makes it much easier to keep track of
+	      what you're changing and to revert changes if necessary.
+	  <li>You may wish to merge in changes from the trunk. For further details see
+	      <a href="#branching_update">Merging From the Trunk</a> later in this section.
+	      <ul>
+		<li>Make sure that you always commit any local changes to your branch
+		    before doing a merge. Otherwise it becomes impossible to distinguish
+		    your changes from those you have merged in. It is also impossible to
+		    revert the merge without losing your local changes.
+		<li>Likewise, always commit the merge to your branch (after resolving any
+		    conflicts) before making any further changes.
+	      </ul>
+	  <li>Don't include unrelated changes. If you want to make some changes which
+	      aren't really associated with your other changes then use a separate ticket and
+	      branch for these changes.
+	</ul>
+    <li>Once your changes are ready for review, update the Trac ticket to record
+	which version of the branch is to be reviewed and assign the ticket to your reviewer.
+    <li>If the reviewer is happy with the change then he/she should update the ticket
+	to record that the change is approved and assign the ticket back to you.
+	<ul>
+	  <li>The reviewer can use the command
+	      <tt>fcm&nbsp;diff&nbsp;--branch &lt;branch_name&gt;</tt> to examine all of the
+	      changes on the branch.
+	  <li>If changes are necessary then these should be prepared and then the
+	      ticket updated to refer to the new version under review.
+	</ul>
+    <li>Once the change is approved it can be merged back to the trunk
+	<ul>
+	  <li>If you have been merging the latest changes from the trunk onto your
+	      branch then the merge should be automatic. If not you may have
+	      conflicts to resolve.
+	  <li>Make sure that each merge is a separate commit to the trunk.
+	      i.e. Don't combine changes from several branches in one commit.
+	      This makes it easier to reverse changes if necessary. It also
+	      makes the changeset easier to understand.
+	  <li>Make sure that you use a good log message to describe your change.
+	      For further details see <a href="#messages">Commit Log Messages</a>
+	      later in this section.	      
+	  <li>Once the changes are commited, update the ticket to refer to the
+	      changeset. Then the ticket can be closed.
+	</ul>
+    <li>Once you are finished with the branch it should be deleted.
+  </ol>
+
+  <h2><a name="wc">Working Copies</a></h2>
+
+  Some points to consider regarding working copies:
+
+  <ol>
+    <li>In general we recommend that you keep your working copies in your home directory.
+	This ensures that any local changes which you accidently delete can be recovered
+	via the snapshot facility (on Met Office Exeter and Reading based systems).
+    <li>If the size of your project is small then you will probably find it easiest to
+	work with a complete copy of the project (either the trunk or your branch).
+	This means that you always have immediate access to all the files and that you
+	are always able to perform merges using your normal working copy.
+    <li>If you have a large project then you may prefer to work on a sub-tree of your
+	project.
+	<ul>
+	  <li><em>Pros:</em>
+	      <ul>
+		<li>Subversion operations on your working copy are faster.
+		<li>Your working copies use up less disk space. Remember that
+		    you may be working on several changes at once on separate branches
+		    so you may wish to have several working copies.
+	      </ul>
+	  <li><em>Cons:</em>
+	      <ul>
+		<li>You cannot always perform merge operations in sub-trees (if
+		    the changes which need to be merged include files outside of
+		    your sub-tree). To handle this we suggest that if you need to
+		    perform a merge using a complete copy of your project you
+		    check it out in your $LOCALDATA area (local disk space which
+		    is not backed up) to be used purely for doing the merge.
+		<li>You may find that your change involves more files than you originally
+		    thought and that some of the files to be changed lie outside of your
+		    working copy. You then have to make sure that you have committed any
+		    changes before checking out a larger working copy.
+	      </ul>
+	</ul>
+
+  </ol>
+  
+  <h2><a name="branching">Branching &amp; Merging</a></h2>
+
+  <h3><a name="branching_when">When to Branch</a></h3>
+
+  <p>If you are making a reasonably large change which will take more than a
+  hour or two to prepare then there are clear advantages to doing this work on a
+  branch.</p>
+
+  <ul>
+    <li>You can commit intermediate versions to the branch.</li>
+
+    <li>If you need to merge in changes from the trunk then you have a record
+    of your files prior to the merge.</li>
+
+    <li>The version of the code which gets reviewed is recorded. If subsequent
+    changes are required then only those changes will need reviewing.</li>
+  </ul>
+
+  <p>However, if you are only making a small change (maybe only one line)
+  should you create a branch for this? There are two possible approaches:</p>
+
+  <ol>
+    <li>The <em>Always Branch</em> system
+
+      <ul>
+        <li>ALL coding changes are prepared on branches.</li>
+
+        <li><em>Pros:</em> Same process is followed in all cases.</li>
+
+        <li><em>Cons:</em> The extra work required to create the branch and
+        merge it back to the trunk may seem unnecessary for a very small
+        change.</li>
+      </ul>
+    </li>
+
+    <li>The <em>Branch When Needed</em> system
+
+      <ul>
+        <li>Small changes can be committed directly to the trunk (after testing
+        and code review).</li>
+
+        <li><em>Pros:</em> Avoids the overhead of using branches.</li>
+
+        <li><em>Cons:</em> Danger of underestimating the size of a change. What
+        you thought was a small change may turn out to be larger than you
+        thought (although you can always move it onto a branch if this
+        happens).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <p>This is a matter for project policy although, in general, we would
+  recommend the <em>Branch When Needed</em> approach.</p>
+
+  <h3><a name="branching_where">Where to Branch From</a></h3>
+
+  <p>When you create a new branch you have two choices for which revision to
+  create the branch from:</p>
+
+  <ol>
+    <li>The latest version of the trunk.
+
+      <ul>
+        <li>This is the preferred choice where possible. It minimised the
+        chances of conflicts when you need to incorporate your changes back
+        onto the trunk.</li>
+      </ul>
+    </li>
+
+    <li>An older version of the trunk. There are a number of reasons why you
+    may need to do this. For example:
+
+      <ul>
+        <li>You are using a stable version to act as your "control" data.</li>
+
+        <li>You need to know that your baseline is well tested (e.g. scientific
+        changes).</li>
+
+        <li>Your change may need to be merged with other changes relative to a
+        stable version for testing purposes or for use in a package (see
+        <a href="#packages">Creating Packages</a> later in this section).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="branching_update">Merging From the Trunk</a></h3>
+
+  <p>Once you've created your branch you need to decide whether you now work in
+  isolation or whether you periodically merge in the latest changes from the
+  trunk.</p>
+
+  <ul>
+    <li>Regularly merging from the trunk minimises the work involved when you
+    are ready to merge back to the trunk. You deal with any merge issues as you
+    go along rather than all at the end (by which time your branch and the
+    trunk could have diverged significantly).</li>
+
+    <li>One downside of merging from the trunk is that the baseline for your
+    changes is a moving target. This may not be what you want if you have some
+    "control" results that you have generated.</li>
+
+    <li>Another downside of merging from the trunk is that it may introduce
+    bugs. Although any code on the trunk should have been tested and reviewed
+    it is unlikely to be as well tested as code from a stable release.</li>
+
+    <li>Unless you originally created your branch from the latest version of
+    the trunk it is unlikely that you are going to want to merge in changes
+    from the trunk. The exception to this is once your change is complete when
+    it may make sense to merge all the changes on the trunk into your branch as
+    a final step. This is discussed in
+    <a href="#branching_commit">Merging Back to the Trunk</a> below.</li>
+  </ul>
+
+  <p>So, there are basically three methods of working:</p>
+
+  <ol>
+    <li>Branch from a stable version and prepare all your changes in isolation.
+
+      <ul>
+        <li>Necessary if you need to make your change relative to a well tested
+        release.</li>
+      </ul>
+    </li>
+
+    <li>Branch from the latest code but then prepare all your changes in
+    isolation.
+
+      <ul>
+        <li>Necessary if you need a stable baseline for your "control"
+        data.</li>
+      </ul>
+    </li>
+
+    <li>Branch from the latest code and then update your branch from the trunk
+    on a regular basis.
+
+      <ul>
+        <li>This is considered "best practise" for parallel working and should
+        be used where possible.</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="branching_commit">Merging Back to the Trunk</a></h3>
+
+  <p>Before merging your change back to the trunk you will need to test your
+  change and get it reviewed. There are two options for what code to test and
+  review:</p>
+
+  <ol>
+    <li>Test and review your changes in isolation. Then merge to the trunk and
+    deal with any conflicts at this stage. This may be the best method if:
+
+      <ul>
+        <li>Your changes have already been tested against a stable baseline and
+        re-testing after merging would be impracticable.</li>
+
+        <li>Your branch needs to be available for others to merge in its
+        changes in isolation.</li>
+      </ul>
+    </li>
+
+    <li>Merge in the latest code from the trunk before your final test and
+    review. This has the advantage that you are testing and reviewing the
+    actual code which will be committed to the trunk. However, it is possible
+    that other changes could get committed to the trunk whilst you are
+    completing your testing and review. There are several ways of dealing with
+    this:
+
+      <ul>
+        <li>Use locking to prevent it happening. The danger with this is that
+        you may prevent others from being able to get their change tested and
+        reviewed, hence inhibiting parallel devlopment.</li>
+
+        <li>Insist that the change is re-tested and reviewed. The problem with
+        this is that there is no guarantee that the same thing won't happen
+        again.</li>
+
+        <li>Merge in the new changes but don't insist on further testing or
+        review.
+
+          <ul>
+            <li>In most cases any changes won't clash so there is little to
+            worry about.</li>
+
+            <li>Where there are clashes then, in most cases, they will be
+            trivial with little danger of any side-effects.</li>
+
+            <li>Where the clashes are significant then, in most cases, this
+            will be very obvious whilst you are resolving the conflicts. In
+            this case you should repeat the testing and get the updates
+            reviewed.</li>
+          </ul>This is the recommended approach since it doesn't inhibit
+          parallel development and yet the chances of a bad change being
+          committed to the trunk are still very small.
+        </li>
+      </ul>
+
+      You should also consider what can be done to minimise the time taken
+      for testing and review.
+      <ul>
+	<li>Try to keep your changes small by breaking them down where possible.
+	    Smaller changes are easier and quicker to review. This also
+	    helps to minimise merge problems by getting changes back onto the
+	    trunk earlier.
+	<li>Automate your testing as far as possible to speed up the process.
+      </ul>
+    </li>
+  </ol>
+
+  <p>Most projects will require the developer who prepared the change to merge
+  it back to the trunk once it is complete. However, larger projects may wish
+  to consider restricting this to a number of experienced / trusted
+  developers.</p>
+
+  <ul>
+    <li>This makes it easier to control and prioritise the merges.</li>
+
+    <li>It applies an extra level of quality control.</li>
+
+    <li>It minimises the risk of mistakes being merged back on to the trunk by
+    less experienced developers</li>
+
+    <li>Scientific developers can concentrate on the scientific work.</li>
+
+    <li>One issue is that the person doing the merge to the trunk may need help
+    from the original developer to prepare a suitable log message.</li>
+  </ul>
+
+  <h3><a name="branching_delete">When to Delete Branches</a></h3>
+
+  <p>Once you are finished with your branch it is best to delete it to avoid
+  cluttering up the directory tree (remember that the branch and all its
+  history will still be available). There are two obvious approaches to
+  deleting branches.</p>
+
+  <ol>
+    <li>Delete the branch as soon as it has been merged back to the trunk
+    (prior to closing any associated Trac ticket).
+
+      <ul>
+        <li>This is the tidiest approach which minimises the chances of old
+        branches being left around.</li>
+      </ul>
+    </li>
+
+    <li>Delete the branch once a stable version of the system has been released
+    which incorporates your change.
+
+      <ul>
+        <li>If a bug is found in your change during integration testing then
+        you can prepare the fix on the original branch (without having to do
+        any additional work to restore the branch).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h2><a name="binary">Working with Binary Files</a></h2>
+
+  <p>The <tt>fcm conflicts</tt> command and <tt>xxdiff</tt> can only help you
+  resolve conflicts in text files. If you have binary files in your repository
+  you need to consider whether conflicts in these files would cause a problem.</p>
+
+  <h3><a name="binary_conflicts">Resolving Conflicts in Binary Files</a></h3>
+
+  <p>Conflicts in some types of binary files can be resolved manually. When you
+  are satisfied that the conflicts are resolved, issue the <tt>fcm resolved</tt>
+  command on the file to remove the conflict status. (You will be prevented from
+  committing if you have a conflicting file in your working copy.)</p>
+
+  <p>If you have a conflicting MS Office 2003 document, you may be able to take
+  advantage of the "Compare and Merge Documents" facility under the "Tools" menu
+  in a MS Office application. Consider a working copy, which you have just
+  updated from revision 100 to revision 101, and someone else has committed some
+  changes to a file <tt>doument.doc</tt> you are editing, you will get:</p>
+
+  <table class="pad" summary="Conflicts in a binary file" border="1"
+  width="100%">
+    <tr>
+      <th>Conflicts in a binary file</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm conflicts
+Conflicts in file: document.doc
+document.doc: ignoring binary file, please resolve conflicts manually.
+(SHELL PROMPT)$ fcm status
+=&gt; svn st
+?      document.doc.r100
+?      document.doc.r101
+C      document.doc
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Open <tt>document.doc.r101</tt> with MS Word. In <em>Tools &gt; Compare
+  and Merge Documents...</em>, open <tt>document.doc</tt>. You will be in Track
+  Changes mode automatically. Go through the document to accept, reject or merge
+  any changes. Save the document and exit MS Word when you are ready. Finally,
+  issue the <tt>fcm resolved</tt> command to remove the conflict status:</p>
+
+  <table class="pad" summary="Resolved conflicts in a binary file" border="1"
+  width="100%">
+    <tr>
+      <th>Resolved conflicts in a binary file</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm resolved document.doc
+=&gt; svn resolved document.doc
+Resolved conflicted state of 'document.doc'
+(SHELL PROMPT)$ fcm status
+=&gt; svn st
+M      document.doc
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Another type of conflict that you may be able to resolve manually is where
+  the binary file is generated from another file which can be merged. For
+  instance, some people who use LaTeX also store a PDF version of the document in
+  the repository. In such cases it is easy to resolve the conflict by
+  re-generating the PDF file from the merged LaTeX file and then issuing the
+  <tt>fcm resolved</tt> command to remove the conflict status. Note that, in this
+  particular case, a better approach might be to automate the generation of the
+  PDF file outside of the repository.</p>
+
+  <h3><a name="binary_locking">Using Locking</a></h3>
+
+  <p>For files with binary formats, such as artwork or sound, it is often
+  impossible to merge conflicting changes. In these situations, it is necessary
+  for users to take strict turns when changing the file in order to prevent time
+  wasted on changes that are ultimately discarded.</p>
+
+  <p>Subversion supports <em>locking</em> to allow you to prevent other users
+  from modifying a file while you are preparing changes. For details please refer
+  to the chapter
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.advanced.locking.html">
+  Locking</a> from the Subversion book. Note that:</p>
+
+  <ul>
+    <li>FCM does not add any functionality to the locking commands provided by
+    Subversion.</li>
+
+    <li>If you need to lock a file you must do this in a working copy of the
+    trunk. There is nothing to stop you preparing the changes in a branch (maybe
+    you want to prepare the change in combination with a number of other changes
+    which do not require locking). However, you must always remember to lock the
+    file in the trunk first to prevent other users from preparing changes to the
+    file in parallel.</li> 
+
+    <li>Locking isn't the only way of preventing conflicts with binary files. If
+    you only have a small project team and a small number of binary files you may
+    find it easier to use other methods of communication such as emails or
+    just talking to each other. Alternatively, you may have a working practise
+    that particular files are only modified by particular users.</li>
+  </ul>
+  
+  <h2><a name="messages">Commit Log Messages</a></h2>
+
+  <p>Certain guidelines should be adhered to when writing log messages for code
+  changes when committing to the trunk:</p>
+
+  <ul>
+    <li>Try to start off the log message with one line indicating the general
+    nature of the change. This helps developers to tell whether a change is
+    important to them when viewing the Trac timeline view.</li>
+
+    <li>If you want to use bullets in your message then make them compatible
+    with <a href="http://trac.edgewall.org/wiki/WikiFormatting">Wiki
+    Formatting</a>. For example:
+
+      <table class="pad" summary="Example bullets using wiki formatting"
+      border="1" width="100%">
+        <tr>
+          <td>
+            <pre>
+No bullet
+ * First level bullet (single space at beginning)
+   * Second level bullet (three spaces at beginning)
+ 1. Numbered item instead of a bullet
+</pre>
+          </td>
+        </tr>
+      </table>This will ensure that the log message is displayed with proper
+      bullets in the Trac changeset view. You can also include other types of
+      wiki formatting but please be aware that the message still needs to be
+      readable when simply viewed as text (e.g. via <tt>fcm&nbsp;log</tt>).
+    </li>
+
+    <li>If your changes close a Trac ticket, make sure that your log message
+    refers to this using <a href="http://trac.edgewall.org/wiki/TracLinks">Trac
+    Links</a>, e.g. <tt>Closes issue #26.</tt></li>
+
+    <li>Don't leave blank lines at the end of your log message since they get
+    included in the message and, therefore, get included in the ouptut from
+    <tt>fcm log</tt>.</li>
+
+    <li>Take care to avoid making mistakes in your log messages since
+    correcting them involves additional work. However, if you realise that that
+    you've made a mistake don't leave it - get it corrected.
+
+      <ul>
+        <li>A log message can be corrected using the <em>propedit</em>
+        command,<br>
+        e.g. <tt>fcm propedit svn:log --revprop -r REV</tt><br>
+        Take care since this is an <em>unversioned</em> property so you run the
+        risk of losing information if you aren't careful with your edits.</li>
+
+        <li>By default, FCM repositories are configured such that all users can
+        update log messages. If you are not the original author of the changeset
+        then the original author will be sent an e-mail informing them of the
+        change. Other users can also be informed of log message changes if they
+        wish (see the section <a href="system_admin.html#svn_watch">Watching
+        changes in log messages</a> for details).</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>There are two possible approaches to recording the changes to individual
+  files:</p>
+
+  <ol>
+    <li>Maintain history entries in file headers.
+
+      <ul>
+        <li>
+          <em>Pros:</em>
+
+          <ul>
+            <li>You don't need access to the Subversion repository in order to
+            be able to view a files change history (e.g. external
+            collaborators).</li>
+          </ul>
+        </li>
+
+        <li>
+          <em>Cons:</em>
+
+          <ul>
+            <li>History entries will produce clashes whenever files are changed
+            in parallel (although these conflicts are trivial to resolve).</li>
+
+            <li>Source files which are changed regularly can become cluttered
+            with very long history entries.</li>
+
+            <li>It is not possible to include history entries in some types of
+            file.</li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>Record which files have changed in the commit log message.
+
+      <ul>
+        <li>The log message should name every modified file and explain why it
+        was changed. For example:
+
+          <table class="pad" summary="Example log message" border="1" width=
+          "100%">
+            <tr>
+              <td>
+                <pre>
+ * working_practices.html:
+   Added guidelines for writing log messages.
+</pre>
+              </td>
+            </tr>
+          </table>
+
+	  Make sure that the log message includes some sort of description for
+	  every change. The value of the log becomes much less if developers cannot
+	  rely on its completeness. Even if you've only changed comments, note this
+	  in the message.</li>
+
+        <li>If you make exactly the same change in several files, list all the
+        changed files in one entry. For example:
+
+          <table class="pad" summary="Example log message" border="1" width=
+          "100%">
+            <tr>
+              <td>
+                <pre>
+ * code_management.html, system_admin.html, index.html:
+   Ran pages through tidy to fix HTML errors.
+</pre>
+              </td>
+            </tr>
+          </table>
+        </li>
+
+        <li>It shouldn't normally be necessary to include the full path in the
+	    file name - just make sure it is clear which of the changed files
+	    you are referring to. You can get a full list of the files changed using
+	    <tt>fcm&nbsp;log&nbsp;-v</tt>.
+        </li>
+      </ul>
+    </li>
+  </ol>
+
+  <p>When you're committing to your own branch then you can be much more
+  relaxed about log messages. Use whatever level of detail you find helpful.
+  However, if you follow similar guidelines then this will help when it comes
+  to preparing the log message when your change is merged back to the
+  trunk.</p>
+
+  <h2><a name="tickets">Trac Tickets</a></h2>
+
+  <h3><a name="tickets_create">Creating Tickets</a></h3>
+
+  <p>There are two different approaches to using the issue tracker within
+  Trac:</p>
+
+  <ol>
+    <li>All problems should be reported using Trac tickets.
+
+      <ul>
+        <li><em>Pros:</em> The issue tracker contains a full record of all the
+        problems reported and enhancements requested.</li>
+
+        <li>
+          <em>Cons:</em> The issue tracker gets cluttered up with lots of
+          inappropriate tickets.
+
+          <ul>
+            <li>Duplicate tickets.</li>
+
+            <li>Issues already discussed in the documentation.</li>
+
+            <li>Problems which turn out to be unrelated to the system.</li>
+
+            <li>Problems which are poorly described.</li>
+
+            <li>Things which would be better solved by a quick
+            conversation.</li>
+          </ul>This makes it much harder to search the issues and can slow down
+          the response to simple issues.
+        </li>
+      </ul>
+    </li>
+
+    <li>A Trac ticket shouldn't be created until the issue has been agreed.
+
+      <ul>
+        <li>Problems and issues should first be discussed with the project team
+        / system maintainers. Depending on the project, this could be via
+        email, on the newsgroups or through a quick chat over coffee.</li>
+
+        <li>Nothing is lost this way. Issues which are appropriate for the
+        issue tracker still get filed. It just happens slightly later, after
+        initial discussion has helped to clarify the best description for the
+        issue.</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="tickets_use">Using Tickets</a></h3>
+
+  <p>This sub-section provides advice on the best way of using tickets:</p>
+
+  <ol>
+    <li>In general, mature systems will require that there is a Trac ticket related
+	to every changeset made to the trunk. However this doesn't mean that there
+	should be a separate ticket for each change.
+	<ul>
+	  <li>If a change is made to the trunk and then a bug is subsequently found then,
+	      if this happens before the next release of the system, the subsequent
+	      change can be recorded on the same ticket.
+	  <li>There can often be changes which don't really affect the system itself since
+	      they are just system administration details. One way of dealing with this
+	      is to open a ticket for each release in which to record all such miscellaneous
+	      changes. It will probably be acceptable to review these changes after they have
+	      been committed, prior to the system release.
+	</ul>
+    <li>Whenever you refer to source files/directories in tickets, make sure that you refer
+	to particular versions of the files. This ensures that the links will work
+	in the future, even if those files are no longer in the latest version.
+	For example:<br>
+	<tt>Changes now ready for review:  source:/OPS/branches/dev/frdm/r123_MyBranch@234</tt>
+    <li>For some types of information, simply appending to the ticket may not be the
+	best way of working. For example, design notes or test results may be best recorded
+	elsewhere, preferably in a wiki page. If using wiki pages we recommend using a naming
+	convention to identify the wiki page with the associated ticket, for example:<br>
+	<tt>Please refer to [wiki:ticket/123/Design design notes]</tt><br>
+	<tt>See separate [wiki:ticket/123/TestResults test results]</tt><br>
+	Note that the square brackets have to be used since a page name containing numbers is
+	not recognised automatically.
+  </ol>
+
+  
+  <h2><a name="packages">Creating Packages</a></h2>
+
+  <p>Sometimes you may need to combine the changes from several different branches.
+  For example:
+  <ul>
+    <li>Your branch is just part of a larger change which needs to be tested in its
+	entirety before committing to the trunk.</li>
+    <li>You have some diagnostic code stored on a branch which you want to combine
+	with another branch for testing purposes.</li>
+  </ul>
+  We refer to this as creating a <em>package</em>.</p>
+
+  <p>To create a package you simply create a new branch as normal. The <em>type</em> should
+  be a <em>package</em> or possibly a <em>configuration</em> branch to help you distinguish
+  it from your other branches. You then simply merge in all of the branches that you want to
+  combine using <tt>fcm merge</tt>.</p>
+  
+  <ul>
+    <li>The chance of conflicts will be reduced if the branches you are combining have been
+	created from the same point on the trunk. Your package branch should also be created
+	from the same point on the trunk.
+	<ul>
+	  <li><em>Currently, <tt>fcm merge</tt> will not work unless this is true.</em></li>
+	</ul></li>
+    <li>If further changes are made on a branch you are using in a package then you can
+	incorporate these changes into your package using <tt>fcm merge</tt>. Note, however,
+	that if you have a branch which is being used in a package then you should avoid merging
+	changes from the trunk into your branch. If you do then it will be very difficult to
+	get updates to your branch merged into the package.</li>
+  </ul>
+
+  <p>The <tt>fcm branch --info</tt> command is very useful for maintaining packages. It tells
+  you all of the branches which have been merged into your package and whether there are any
+  more recent changes on those branches.</p>
+
+  <h2><a name="releases">Preparing System Releases</a></h2>
+
+  There are two ways of preparing system releases:
+  <ol>
+    <li>A system release is simply a particular version of the trunk. In order to do this it
+	will be necessary to restrict changes on the trunk whilst the release is being prepared.
+	<ul>
+	  <li>Users can continue to develop changes not intended for inclusion
+	      in this release on branches.
+	  <li>This may be a problem if preparing the release takes too long.
+	</ul>
+    <li>Create a release branch where the release is finalised.
+	<ul>
+	  <li>You then lose the ability to be able to branch from the release.
+	  <li>It may be harder to identify what changes have been made between releases
+	      (since you can't simply look at all the changesets made between two versions
+	      of the trunk).
+	</ul>
+  </ol>
+
+  <h2><a name="rapid">Rapid vs Staged Development Practises</a></h2>
+
+  <p>Most of this section on working practises has focussed on projects/systems
+  which are quite mature. Such systems are likely to have regular releases and
+  will, for example, insist that all changes to the trunk are reviewed and
+  tested.</p>
+
+  <p>If your system is still undergoing rapid development and has not yet
+  reached any sort of formal release then you will probably want to adopt a
+  much more relaxed set of working practises. For example:</p>
+
+  <ul>
+    <li>Changes don't need to be reviewed.</li>
+
+    <li>More changes will be committed to the trunk. Only very large changes
+    will be prepared on branches.</li>
+
+    <li>No requirement to have a Trac ticket associated with each change.</li>
+  </ul>
+
+  <p>We have tried to avoid building too many assumptions about working
+  practises into the FCM system. This gives projects the flexibility to decide
+  which working practises are appropriate for their system. Hopefully this
+  means that FCM can be used for large or small systems and for rapidly
+  evolving or very stable systems.</p>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/etc/fcm.cfg.eg
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/etc/fcm.cfg.eg	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/etc/fcm.cfg.eg	(revision 329)
@@ -0,0 +1,403 @@
+# ------------------------------------------------------------------------------
+# FCM central configuration file
+# ------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
+# Standard repository locations
+# ------------------------------------------------------------------------------
+
+# AMV repository
+set::repos::amv              svn://fcm7/AMV_svn/AMV
+set::repos::amv_tr           svn://fcm7/AMV_svn/AMV/trunk
+set::repos::amv_br           svn://fcm7/AMV_svn/AMV/branches
+set::repos::amv_tg           svn://fcm7/AMV_svn/AMV/tags
+
+set::trac::amv               http://fcm7/projects/AMV/browser/AMV
+
+# ANCIL repository
+set::repos::ancil            svn://fcm8/ANCIL_svn/ANCIL
+set::repos::ancil_tr         svn://fcm8/ANCIL_svn/ANCIL/trunk
+set::repos::ancil_br         svn://fcm8/ANCIL_svn/ANCIL/branches
+set::repos::ancil_tg         svn://fcm8/ANCIL_svn/ANCIL/tags
+
+set::trac::ancil             http://fcm8/projects/ANCIL/browser/ANCIL
+
+# ATSR repository
+set::repos::atsr             svn://fcm7/ATSR_svn/ATSR
+set::repos::atsr_tr          svn://fcm7/ATSR_svn/ATSR/trunk
+set::repos::atsr_br          svn://fcm7/ATSR_svn/ATSR/branches
+set::repos::atsr_tg          svn://fcm7/ATSR_svn/ATSR/tags
+
+set::trac::atsr              http://fcm7/projects/ATSR/browser/ATSR
+
+# CICE repository
+set::repos::cice             svn://fcm3/CICE_svn/CICE
+set::repos::cice_tr          svn://fcm3/CICE_svn/CICE/trunk
+set::repos::cice_br          svn://fcm3/CICE_svn/CICE/branches
+set::repos::cice_tg          svn://fcm3/CICE_svn/CICE/tags
+
+set::trac::cice              http://fcm3/projects/CICE/browser/CICE
+
+# CVC repository
+set::repos::cvc_admin        svn://fcm6/CVC_svn/Admin
+set::repos::cvc_admin_tr     svn://fcm6/CVC_svn/Admin/trunk
+set::repos::cvc_admin_br     svn://fcm6/CVC_svn/Admin/branches
+set::repos::cvc_admin_tg     svn://fcm6/CVC_svn/Admin/tags
+set::repos::bullseye         svn://fcm6/CVC_svn/Bullseye
+set::repos::bullseye_tr      svn://fcm6/CVC_svn/Bullseye/trunk
+set::repos::bullseye_br      svn://fcm6/CVC_svn/Bullseye/branches
+set::repos::bullseye_tg      svn://fcm6/CVC_svn/Bullseye/tags
+set::repos::cat              svn://fcm6/CVC_svn/CAT
+set::repos::cat_tr           svn://fcm6/CVC_svn/CAT/trunk
+set::repos::cat_br           svn://fcm6/CVC_svn/CAT/branches
+set::repos::cat_tg           svn://fcm6/CVC_svn/CAT/tags
+set::repos::deicing          svn://fcm6/CVC_svn/Deicing
+set::repos::deicing_tr       svn://fcm6/CVC_svn/Deicing/trunk
+set::repos::deicing_br       svn://fcm6/CVC_svn/Deicing/branches
+set::repos::deicing_tg       svn://fcm6/CVC_svn/Deicing/tags
+set::repos::ensemble         svn://fcm6/CVC_svn/Ensemble
+set::repos::ensemble_tr      svn://fcm6/CVC_svn/Ensemble/trunk
+set::repos::ensemble_br      svn://fcm6/CVC_svn/Ensemble/branches
+set::repos::ensemble_tg      svn://fcm6/CVC_svn/Ensemble/tags
+set::repos::gales            svn://fcm6/CVC_svn/Gales
+set::repos::gales_tr         svn://fcm6/CVC_svn/Gales/trunk
+set::repos::gales_br         svn://fcm6/CVC_svn/Gales/branches
+set::repos::gales_tg         svn://fcm6/CVC_svn/Gales/tags
+set::repos::ifv              svn://fcm6/CVC_svn/IFV
+set::repos::ifv_tr           svn://fcm6/CVC_svn/IFV/trunk
+set::repos::ifv_br           svn://fcm6/CVC_svn/IFV/branches
+set::repos::ifv_tg           svn://fcm6/CVC_svn/IFV/tags
+set::repos::openroad         svn://fcm6/CVC_svn/OpenRoad
+set::repos::openroad_tr      svn://fcm6/CVC_svn/OpenRoad/trunk
+set::repos::openroad_br      svn://fcm6/CVC_svn/OpenRoad/branches
+set::repos::openroad_tg      svn://fcm6/CVC_svn/OpenRoad/tags
+set::repos::powertable       svn://fcm6/CVC_svn/PowerTable
+set::repos::powertable_tr    svn://fcm6/CVC_svn/PowerTable/trunk
+set::repos::powertable_br    svn://fcm6/CVC_svn/PowerTable/branches
+set::repos::powertable_tg    svn://fcm6/CVC_svn/PowerTable/tags
+set::repos::qnh              svn://fcm6/CVC_svn/QNH
+set::repos::qnh_tr           svn://fcm6/CVC_svn/QNH/trunk
+set::repos::qnh_br           svn://fcm6/CVC_svn/QNH/branches
+set::repos::qnh_tg           svn://fcm6/CVC_svn/QNH/tags
+
+set::trac::cvc_admin         http://fcm6/projects/CVC/browser/Admin
+set::trac::bullseye          http://fcm6/projects/CVC/browser/Bullseye
+set::trac::cat               http://fcm6/projects/CVC/browser/CAT
+set::trac::deicing           http://fcm6/projects/CVC/browser/Deicing
+set::trac::ensemble          http://fcm6/projects/CVC/browser/Ensemble
+set::trac::gales             http://fcm6/projects/CVC/browser/Gales
+set::trac::ifv               http://fcm6/projects/CVC/browser/IFV
+set::trac::openroad          http://fcm6/projects/CVC/browser/OpenRoad
+set::trac::powertable        http://fcm6/projects/CVC/browser/PowerTable
+set::trac::qnh               http://fcm6/projects/CVC/browser/QNH
+
+# DA repository
+set::repos::da               svn://fcm5/DA_svn/DA
+set::repos::da_tr            svn://fcm5/DA_svn/DA/trunk
+set::repos::da_br            svn://fcm5/DA_svn/DA/branches
+set::repos::da_tg            svn://fcm5/DA_svn/DA/tags
+
+set::trac::da                http://fcm5/projects/DA/browser/DA
+
+# ENS repository
+set::repos::ens              svn://fcm9/ENS_svn/ENS
+set::repos::ens_tr           svn://fcm9/ENS_svn/ENS/trunk
+set::repos::ens_br           svn://fcm9/ENS_svn/ENS/branches
+set::repos::ens_tg           svn://fcm9/ENS_svn/ENS/tags
+
+set::trac::ens               http://fcm9/projects/ENS/browser/ENS
+
+# FCM repository
+set::repos::fcm              svn://fcm1/FCM_svn/FCM
+set::repos::fcm_tr           svn://fcm1/FCM_svn/FCM/trunk
+set::repos::fcm_br           svn://fcm1/FCM_svn/FCM/branches
+set::repos::fcm_tg           svn://fcm1/FCM_svn/FCM/tags
+set::repos::fcm_admin        svn://fcm1/FCM_svn/Admin
+set::repos::fcm_admin_tr     svn://fcm1/FCM_svn/Admin/trunk
+set::repos::fcm_admin_br     svn://fcm1/FCM_svn/Admin/branches
+set::repos::fcm_admin_tg     svn://fcm1/FCM_svn/Admin/tags
+
+set::trac::fcm               http://fcm1/projects/FCM/browser/FCM
+set::trac::fcm_admin         http://fcm1/projects/FCM/browser/Admin
+
+# FLUME repository
+set::repos::flmtestharness    svn://fcm2/FLUME_svn/FlmTestHarness
+set::repos::flmtestharness_tr svn://fcm2/FLUME_svn/FlmTestHarness/trunk
+set::repos::flmtestharness_br svn://fcm2/FLUME_svn/FlmTestHarness/branches
+set::repos::flmtestharness_tg svn://fcm2/FLUME_svn/FlmTestHarness/tags
+
+set::trac::flmtestharness     http://fcm2/projects/FLUME/browser/FlmTestHarness
+
+# GEN repository
+set::repos::gen              svn://fcm1/GEN_svn/GEN
+set::repos::gen_tr           svn://fcm1/GEN_svn/GEN/trunk
+set::repos::gen_br           svn://fcm1/GEN_svn/GEN/branches
+set::repos::gen_tg           svn://fcm1/GEN_svn/GEN/tags
+
+set::trac::gen               http://fcm1/projects/GEN/browser/GEN
+
+# NEMO repository
+set::repos::nemosys          svn://fcm3/NEMO_svn/NEMOSYS
+set::repos::nemosys_tr       svn://fcm3/NEMO_svn/NEMOSYS/trunk
+set::repos::nemosys_br       svn://fcm3/NEMO_svn/NEMOSYS/branches
+set::repos::nemosys_tg       svn://fcm3/NEMO_svn/NEMOSYS/tags
+
+set::trac::nemosys           http://fcm3/projects/NEMO/browser/NEMOSYS
+
+# NWPWEB repository
+set::repos::www_nwp          svn://fcm1/NWPWEB_svn/www_nwp
+set::repos::www_nwp_tr       svn://fcm1/NWPWEB_svn/www_nwp/trunk
+set::repos::www_nwp_br       svn://fcm1/NWPWEB_svn/www_nwp/branches
+set::repos::www_nwp_tg       svn://fcm1/NWPWEB_svn/www_nwp/tags
+
+set::trac::www_nwp           http://fcm1/projects/NWPWEB_svn/browser/www_nwp
+
+# obsmon repository
+set::repos::obsmon_dc        svn://fcm4/obsmon_svn/DC
+set::repos::obsmon_dc_tr     svn://fcm4/obsmon_svn/DC/trunk
+set::repos::obsmon_dc_br     svn://fcm4/obsmon_svn/DC/branches
+set::repos::obsmon_dc_tg     svn://fcm4/obsmon_svn/DC/tags
+set::repos::obsmon_rtm       svn://fcm4/obsmon_svn/RTM
+set::repos::obsmon_rtm_tr    svn://fcm4/obsmon_svn/RTM/trunk
+set::repos::obsmon_rtm_br    svn://fcm4/obsmon_svn/RTM/branches
+set::repos::obsmon_rtm_tg    svn://fcm4/obsmon_svn/RTM/tags
+
+set::trac::obsmon_dc         http://fcm4/projects/obsmon/browser/DC
+set::trac::obsmon_rtm        http://fcm4/projects/obsmon/browser/RTM
+
+# OCN repository
+set::repos::polcoms          svn://fcm3/OCN_svn/POLCOMS
+set::repos::polcoms_tr       svn://fcm3/OCN_svn/POLCOMS/trunk
+set::repos::polcoms_br       svn://fcm3/OCN_svn/POLCOMS/branches
+set::repos::polcoms_tg       svn://fcm3/OCN_svn/POLCOMS/tags
+
+set::trac::polcoms           http://fcm3/projects/OCN/browser/POLCOMS
+
+# OPFC repository
+set::repos::opfc             svn://fcm9/OPFC_svn/OPFC
+set::repos::opfc_tr          svn://fcm9/OPFC_svn/OPFC/trunk
+set::repos::opfc_br          svn://fcm9/OPFC_svn/OPFC/branches
+set::repos::opfc_tg          svn://fcm9/OPFC_svn/OPFC/tags
+
+set::trac::opfc              http://fcm9/projects/OPFC/browser/OPFC
+
+# OPS repository
+set::repos::ops              svn://fcm4/OPS_svn/OPS
+set::repos::ops_tr           svn://fcm4/OPS_svn/OPS/trunk
+set::repos::ops_br           svn://fcm4/OPS_svn/OPS/branches
+set::repos::ops_tg           svn://fcm4/OPS_svn/OPS/tags
+set::repos::ops_admin        svn://fcm4/OPS_svn/Admin
+set::repos::ops_admin_tr     svn://fcm4/OPS_svn/Admin/trunk
+set::repos::ops_admin_br     svn://fcm4/OPS_svn/Admin/branches
+set::repos::ops_admin_tg     svn://fcm4/OPS_svn/Admin/tags
+set::repos::ops_data         svn://fcm4/OPS_svn/Data
+set::repos::ops_data_tr      svn://fcm4/OPS_svn/Data/trunk
+set::repos::ops_data_br      svn://fcm4/OPS_svn/Data/branches
+set::repos::ops_data_tg      svn://fcm4/OPS_svn/Data/tags
+
+set::trac::ops               http://fcm4/projects/OPS/browser/OPS
+set::trac::ops_admin         http://fcm4/projects/OPS/browser/Admin
+set::trac::ops_data          http://fcm4/projects/OPS/browser/Data
+
+# OSTIA repository
+set::repos::ostia            svn://fcm3/OSTIA_svn/OSTIA
+set::repos::ostia_tr         svn://fcm3/OSTIA_svn/OSTIA/trunk
+set::repos::ostia_br         svn://fcm3/OSTIA_svn/OSTIA/branches
+set::repos::ostia_tg         svn://fcm3/OSTIA_svn/OSTIA/tags
+
+set::trac::ostia             http://fcm3/projects/OSTIA/browser/OSTIA
+
+# PF repository
+set::repos::pf               svn://fcm5/PF_svn/PF
+set::repos::pf_tr            svn://fcm5/PF_svn/PF/trunk
+set::repos::pf_br            svn://fcm5/PF_svn/PF/branches
+set::repos::pf_tg            svn://fcm5/PF_svn/PF/tags
+
+set::trac::pf                http://fcm5/projects/PF/browser/PF
+
+# PostProc repository
+set::repos::pp               svn://fcm9/PostProc_svn/PostProc
+set::repos::pp_tr            svn://fcm9/PostProc_svn/PostProc/trunk
+set::repos::pp_br            svn://fcm9/PostProc_svn/PostProc/branches
+set::repos::pp_tg            svn://fcm9/PostProc_svn/PostProc/tags
+set::repos::ppancil          svn://fcm9/PostProc_svn/PostProcAncil
+set::repos::ppancil_tr       svn://fcm9/PostProc_svn/PostProcAncil/trunk
+set::repos::ppancil_br       svn://fcm9/PostProc_svn/PostProcAncil/branches
+set::repos::ppancil_tg       svn://fcm9/PostProc_svn/PostProcAncil/tags
+
+set::trac::pp                http://fcm9/projects/PostProc/browser/PostProc
+set::trac::ppancil           http://fcm9/projects/PostProc/browser/PostProcAncil
+
+# PRISM repository
+set::repos::oasis4           svn://fcm2/PRISM_svn/oasis4
+set::repos::oasis4_tr        svn://fcm2/PRISM_svn/oasis4/trunk
+set::repos::oasis4_br        svn://fcm2/PRISM_svn/oasis4/branches
+set::repos::oasis4_tg        svn://fcm2/PRISM_svn/oasis4/tags
+
+set::trac::oasis4            http://fcm2/projects/PRISM/browser/oasis4
+
+# radarnet repository
+set::repos::radarnet4        svn://fcm9/radarnet_svn/radarnet4
+set::repos::radarnet4_tr     svn://fcm9/radarnet_svn/radarnet4/trunk
+set::repos::radarnet4_br     svn://fcm9/radarnet_svn/radarnet4/branches
+set::repos::radarnet4_tg     svn://fcm9/radarnet_svn/radarnet4/tags
+
+set::trac::radarnet4         http://fcm7/projects/radarnet/browser/radarnet4
+
+# ROPP repository
+set::repos::ropp_doc         svn://fcm7/ROPP_svn/ropp_doc
+set::repos::ropp_doc_tr      svn://fcm7/ROPP_svn/ropp_doc/trunk
+set::repos::ropp_doc_br      svn://fcm7/ROPP_svn/ropp_doc/branches
+set::repos::ropp_doc_tg      svn://fcm7/ROPP_svn/ropp_doc/tags
+set::repos::ropp_src         svn://fcm7/ROPP_svn/ropp_src
+set::repos::ropp_src_tr      svn://fcm7/ROPP_svn/ropp_src/trunk
+set::repos::ropp_src_br      svn://fcm7/ROPP_svn/ropp_src/branches
+set::repos::ropp_src_tg      svn://fcm7/ROPP_svn/ropp_src/tags
+set::repos::ropp_test        svn://fcm7/ROPP_svn/ropp_test
+set::repos::ropp_test_tr     svn://fcm7/ROPP_svn/ropp_test/trunk
+set::repos::ropp_test_br     svn://fcm7/ROPP_svn/ropp_test/branches
+set::repos::ropp_test_tg     svn://fcm7/ROPP_svn/ropp_test/tags
+set::repos::ropp_web         svn://fcm7/ROPP_svn/ropp_web
+set::repos::ropp_web_tr      svn://fcm7/ROPP_svn/ropp_web/trunk
+set::repos::ropp_web_br      svn://fcm7/ROPP_svn/ropp_web/branches
+set::repos::ropp_web_tg      svn://fcm7/ROPP_svn/ropp_web/tags
+
+set::trac::ropp_doc          http://fcm7/projects/ROPP/browser/ropp_doc
+set::trac::ropp_src          http://fcm7/projects/ROPP/browser/ropp_src
+set::trac::ropp_test         http://fcm7/projects/ROPP/browser/ropp_test
+set::trac::ropp_web          http://fcm7/projects/ROPP/browser/ropp_web
+
+# RTTOV repository
+set::repos::rttov            svn://fcm7/RTTOV_svn
+set::repos::rttov_tr         svn://fcm7/RTTOV_svn/trunk
+set::repos::rttov_br         svn://fcm7/RTTOV_svn/branches
+set::repos::rttov_tg         svn://fcm7/RTTOV_svn/tags
+
+set::trac::rttov             http://fcm7/projects/RTTOV/browser/RTTOV
+
+# SBV repository
+set::repos::sbv              svn://fcm6/SBV_svn/SBV
+set::repos::sbv_tr           svn://fcm6/SBV_svn/SBV/trunk
+set::repos::sbv_br           svn://fcm6/SBV_svn/SBV/branches
+set::repos::sbv_tg           svn://fcm6/SBV_svn/SBV/tags
+set::repos::sbv_admin        svn://fcm6/SBV_svn/Admin
+set::repos::sbv_admin_tr     svn://fcm6/SBV_svn/Admin/trunk
+set::repos::sbv_admin_br     svn://fcm6/SBV_svn/Admin/branches
+set::repos::sbv_admin_tg     svn://fcm6/SBV_svn/Admin/tags
+
+set::trac::sbv               http://fcm6/projects/SBV/browser/SBV
+set::trac::sbv_admin         http://fcm6/projects/SBV/browser/Admin
+
+# SCS repository
+set::repos::scs              svn://fcm1/SCS_svn/SCS
+set::repos::scs_tr           svn://fcm1/SCS_svn/SCS/trunk
+set::repos::scs_br           svn://fcm1/SCS_svn/SCS/branches
+set::repos::scs_tg           svn://fcm1/SCS_svn/SCS/tags
+set::repos::tik              svn://fcm1/SCS_svn/TIK
+set::repos::tik_tr           svn://fcm1/SCS_svn/TIK/trunk
+set::repos::tik_br           svn://fcm1/SCS_svn/TIK/branches
+set::repos::tik_tg           svn://fcm1/SCS_svn/TIK/tags
+set::repos::tt               svn://fcm1/SCS_svn/TT
+set::repos::tt_tr            svn://fcm1/SCS_svn/TT/trunk
+set::repos::tt_br            svn://fcm1/SCS_svn/TT/branches
+set::repos::tt_tg            svn://fcm1/SCS_svn/TT/tags
+
+set::trac::scs               http://fcm1/projects/SCS/browser/SCS
+set::trac::tik               http://fcm1/projects/SCS/browser/TIK
+set::trac::tt                http://fcm1/projects/SCS/browser/TT
+
+# SPS repository
+set::repos::sps              svn://fcm7/SPS_svn/SPS
+set::repos::sps_tr           svn://fcm7/SPS_svn/SPS/trunk
+set::repos::sps_br           svn://fcm7/SPS_svn/SPS/branches
+set::repos::sps_tg           svn://fcm7/SPS_svn/SPS/tags
+set::repos::sps_archive      svn://fcm7/VER_svn/Archive
+set::repos::sps_archive_tr   svn://fcm7/SPS_svn/Archive/trunk
+set::repos::sps_archive_br   svn://fcm7/SPS_svn/Archive/branches
+set::repos::sps_archive_tg   svn://fcm7/SPS_svn/Archive/tags
+
+set::trac::sps               http://fcm7/projects/SPS/browser/SPS
+set::trac::sps_archive       http://fcm7/projects/SPS/browser/Archive
+
+# SURF repository
+set::repos::surf             svn://fcm8/SURF_svn/SURF
+set::repos::surf_tr          svn://fcm8/SURF_svn/SURF/trunk
+set::repos::surf_br          svn://fcm8/SURF_svn/SURF/branches
+set::repos::surf_tg          svn://fcm8/SURF_svn/SURF/tags
+
+set::trac::surf              http://fcm8/projects/SURF/browser/SURF
+
+# test repository
+set::repos::test             svn://fcm1/test_svn/OPS
+set::repos::test_tr          svn://fcm1/test_svn/OPS/trunk
+set::repos::test_br          svn://fcm1/test_svn/OPS/branches
+set::repos::test_tg          svn://fcm1/test_svn/OPS/tags
+
+set::trac::test              http://fcm1/projects/test/browser/OPS
+
+# tutorial repository
+set::repos::tutorial         svn://fcm1/tutorial_svn/tutorial
+set::repos::tutorial_tr      svn://fcm1/tutorial_svn/tutorial/trunk
+set::repos::tutorial_br      svn://fcm1/tutorial_svn/tutorial/branches
+set::repos::tutorial_tg      svn://fcm1/tutorial_svn/tutorial/tags
+
+set::trac::tutorial          http://fcm1/projects/tutorial/browser/tutorial
+
+# UM repository
+set::repos::um               svn://fcm2/UM_svn/UM
+set::repos::um_tr            svn://fcm2/UM_svn/UM/trunk
+set::repos::um_br            svn://fcm2/UM_svn/UM/branches
+set::repos::um_tg            svn://fcm2/UM_svn/UM/tags
+set::repos::um_admin         svn://fcm2/UM_svn/Admin
+set::repos::um_admin_tr      svn://fcm2/UM_svn/Admin/trunk
+set::repos::um_admin_br      svn://fcm2/UM_svn/Admin/branches
+set::repos::um_admin_tg      svn://fcm2/UM_svn/Admin/tags
+
+set::trac::um                http://fcm2/projects/UM/browser/UM
+set::trac::um_admin          http://fcm2/projects/UM/browser/Admin
+
+# UM repository
+set::repos::um_tutorial      svn://fcm2/UM_TUTORIAL_svn/UM
+set::repos::um_tutorial_tr   svn://fcm2/UM_TUTORIAL_svn/UM/trunk
+set::repos::um_tutorial_br   svn://fcm2/UM_TUTORIAL_svn/UM/branches
+set::repos::um_tutorial_tg   svn://fcm2/UM_TUTORIAL_svn/UM/tags
+
+set::trac::um_tutorial       http://fcm2/projects/UM_TUTORIAL/browser/UM
+
+# VAR repository
+set::repos::var              svn://fcm5/VAR_svn/VAR
+set::repos::var_tr           svn://fcm5/VAR_svn/VAR/trunk
+set::repos::var_br           svn://fcm5/VAR_svn/VAR/branches
+set::repos::var_tg           svn://fcm5/VAR_svn/VAR/tags
+set::repos::var_admin        svn://fcm5/VAR_svn/Admin
+set::repos::var_admin_tr     svn://fcm5/VAR_svn/Admin/trunk
+set::repos::var_admin_br     svn://fcm5/VAR_svn/Admin/branches
+set::repos::var_admin_tg     svn://fcm5/VAR_svn/Admin/tags
+set::repos::var_data         svn://fcm5/VAR_svn/Data
+set::repos::var_data_tr      svn://fcm5/VAR_svn/Data/trunk
+set::repos::var_data_br      svn://fcm5/VAR_svn/Data/branches
+set::repos::var_data_tg      svn://fcm5/VAR_svn/Data/tags
+
+set::trac::var               http://fcm5/projects/VAR/browser/VAR
+set::trac::var_admin         http://fcm5/projects/VAR/browser/Admin
+set::trac::var_data          http://fcm5/projects/VAR/browser/Data
+
+# VER repository
+set::repos::ver              svn://fcm6/VER_svn/VER
+set::repos::ver_tr           svn://fcm6/VER_svn/VER/trunk
+set::repos::ver_br           svn://fcm6/VER_svn/VER/branches
+set::repos::ver_tg           svn://fcm6/VER_svn/VER/tags
+set::repos::ver_admin        svn://fcm6/VER_svn/Admin
+set::repos::ver_admin_tr     svn://fcm6/VER_svn/Admin/trunk
+set::repos::ver_admin_br     svn://fcm6/VER_svn/Admin/branches
+set::repos::ver_admin_tg     svn://fcm6/VER_svn/Admin/tags
+set::repos::ver_archive      svn://fcm6/VER_svn/Archive
+set::repos::ver_archive_tr   svn://fcm6/VER_svn/Archive/trunk
+set::repos::ver_archive_br   svn://fcm6/VER_svn/Archive/branches
+set::repos::ver_archive_tg   svn://fcm6/VER_svn/Archive/tags
+
+set::trac::ver               http://fcm6/projects/VER/browser/VER
+set::trac::ver_admin         http://fcm6/projects/VER/browser/Admin
+set::trac::ver_archive       http://fcm6/projects/VER/browser/Archive
+
+# EOF
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/etc/fcm_gui.desktop
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/etc/fcm_gui.desktop	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/etc/fcm_gui.desktop	(revision 329)
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Comment=
+Exec=fcm gui %f
+Hidden=false
+Icon=wizard
+MimeType=inode/directory
+Name=FCM GUI
+Path=
+Terminal=0
+TerminalOptions=
+Type=Application
+X-KDE-SubstituteUID=false
+X-KDE-Username=
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Ecmwf/Fortran90_stuff.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Ecmwf/Fortran90_stuff.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Ecmwf/Fortran90_stuff.pm	(revision 329)
@@ -0,0 +1,2710 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Ecmwf::Fortran90_stuff
+#
+# DESCRIPTION
+#   This is a module for analysing Fortran 9X code. It is used by the FCM
+#   system to generate interface blocks for Fortran 9X free source files.
+#
+# ABOUT THIS MODULE:
+#   The original version of this module was developed by the European Centre
+#   for Medium-Range Weather Forecasts (ECMWF). This version has been modified
+#   by UK Met Office to become part of the FCM system.
+# ------------------------------------------------------------------------------
+
+package Ecmwf::Fortran90_stuff;
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+require Exporter;
+
+our @ISA      = qw(Exporter);
+our @EXPORT   = qw(study setup_parse pre_tidy remove_macro expcont 
+                   process_include_files tidy tidy_decl getvars 
+		   find_unused_vars remove_unused_vars doctor_viol
+		   fix_doctor_viol various cont_lines f90_indent
+		   writefile readfile create_interface_block
+		   add_interface_blocks change_var_names insert_hook
+		   remake_arg_decl remove_some_comments parse_prog_unit
+		   get_calls_inc);
+
+# ------------------------------------------------------------------------------
+
+# Module variables
+
+my $fname = '';
+
+# ------------------------------------------------------------------------------
+# SYNPOSIS
+#   $file = &Ecmwf::Fortran90_stuff::fname ();
+#   &Ecmwf::Fortran90_stuff::fname ($file);
+#
+# DESCRIPTION
+#   This function returns the value in the module variable $fname, which is the
+#   name of the input Fortran source file from FCM. If an argument exists, the
+#   value of $fname is set to the value of the argument.
+#
+# ------------------------------------------------------------------------------
+
+sub fname {
+  $fname = $_[0] if @_;
+  return $fname;
+}
+
+#==========================================================================
+sub study{
+# Study statements and put attributes into array $statements
+# Attributes assigned:
+# $href->{content}       - What statement it is
+# $href->{decl}       - true if declaration,
+#                       5 means statement function
+#                       4 means USE statement,
+#                       2 means type decleration
+#                       3 means FORMAT statement
+#                       1 means the rest
+# $href->{in_contain} - true while in internal procedure(s)
+# $href->{exec}       - true if executable statement
+#                     - 2 means first executable statement in program unit
+#                     - 3 means last executable statement in program unit
+#                     - 23 means first and last executable statement in program unit
+# $href->{prog_unit}  - program unit number (numbered from 0)
+# $href->{number}     - statement number (numbered from 0)
+ 
+# Further attributes will be assigned later (action attributes)
+
+  my($statements,$prog_info) = @_;
+
+  our ($name,$nest_par);
+  my ($unit_name,@args,$prog_unit,$href,@punit,$current_punit);
+  my ($content,$decl,$exec);
+  my($type_def)=0;
+  my($unit_count)=-1;
+  @punit=();
+  $current_punit='';
+  my $number=-1;
+  my $in_contain=0;
+  my $in_interface=0;
+  my $contain_host='';
+  my $current_unit_name='';
+  our($study_called);
+#  if(! $study_called) {
+#    $$prog_info{has_interface_block}=0;
+#  }
+# Initial "parsing" loop
+
+  foreach $href (@$statements) {
+    $href->{in_contain}=$in_contain;
+    $href->{contain_host}=$contain_host if($in_contain);
+    $number++;
+    $_=$href->{statement};
+    $content='unknown';
+    my $content2='';
+    $decl=0;
+    $exec=0;
+
+    if($type_def) {
+ #     $href->{content}='typedef';
+    }
+    
+# Comment
+CRACK:    {
+      if(/^\s*(?:!|$)/) {
+	$content='comment';
+	last CRACK;
+      }
+
+      $_ = uc unless /^#/;
+      s/^\s*//;
+      s/\!.*\n/\n/g; # Remove trailing comments in all lines
+#      print "AA $_";
+ 
+# Program name statement 
+      if($content eq 'unknown' and ! $in_interface) {
+	$prog_unit=&parse_prog_unit(\$unit_name,\@args);
+	if($prog_unit) {
+          $current_unit_name=$unit_name;
+	  $content=uc($prog_unit);
+	  push(@punit,$prog_unit);
+	  $current_punit=$prog_unit;
+	  $unit_count++;
+	  if(! $study_called) {
+	    $$prog_info{'unit_name'}[$unit_count]=uc($unit_name);
+	    $$prog_info{'unit_name'}[$unit_count]=uc($unit_name);
+#	  $$prog_info{'tokens'}[$unit_count]=[];
+	    if($prog_unit eq 'module') {
+	      $$prog_info{'is_module'}=1;
+	      $$prog_info{'module_name'}=$unit_name;
+	    }
+	  }
+	  last CRACK;
+	}
+      }
+      if($content eq 'unknown') {
+	$decl=0;
+	$exec=1;
+# Executable constructs
+	&study_exec(\$content,$prog_info,\$study_called);
+	if($content eq 'IF') {
+	  s/^IF\s*$nest_par\s*//;
+	  &study_exec(\$content2,$prog_info,\$study_called);
+	}
+      }
+      
+
+      if($content eq 'unknown') {
+# Specification statemnts
+	$exec=0;
+	$decl=1;
+	if(/^USE\b/) {
+	  $content='USE';
+	  $decl=4;
+	}
+	elsif(/^INTEGER\b/) {
+	  $content='INTEGER';
+	  $decl=2;
+	}
+	elsif(/^REAL\b/) {
+	  $content='REAL';
+	  $decl=2;
+	}
+	elsif(/^LOGICAL\b/) {
+	  $content='LOGICAL';
+	  $decl=2;
+	}
+	elsif(/^CHARACTER\b/) {
+	  $content='CHARACTER';
+	  $decl=2;
+	}
+	elsif(/^DOUBLE\s*PRECISION\b/) {
+	  $content='DOUBLE PRECISION';
+	  $decl=2;
+	}
+	elsif(/^COMPLEX\b/) {
+	  $content='COMPLEX';
+	  $decl=2;
+	}
+	elsif(/^TYPE *\(/) {
+	  $content='type_decl';
+	  $decl=2;
+	}
+	elsif(/^ALLOCATABLE\b/) {
+	  $content='ALLOCATABLE';
+	}
+	elsif(/^COMMON\b/) {
+	  $content='COMMON';
+	}
+	elsif(/^DATA\b/) {
+	  $content='DATA';
+	}
+	elsif(/^DIMENSION\b/) {
+	  $content='DIMENSION';
+	}
+	elsif(/^EQUIVALENCE\b/) {
+	  $content='EQUIVALENCE';
+	}
+	elsif(/^EXTERNAL\b/) {
+	  $content='EXTERNAL';
+	}
+	elsif(/^\d+\s+FORMAT\b/) {
+	  $content='FORMAT';
+	  $decl=3;
+	}
+	elsif(/^IMPLICIT\b\s+NONE\b/) {
+	  $content='IMPLICIT NONE';
+	}
+	elsif(/^IMPLICIT\b/) {
+	  $content='IMPLICIT';
+	}
+	elsif(/^INTENT\b/) {
+	  $content='INTENT';
+	}
+	elsif(/^INTRINSIC\b/) {
+	  $content='INTRINSIC';
+	}
+	elsif(/^NAMELIST\b/) {
+	  $content='NAMELIST';
+	}
+	elsif(/^OPTIONAL\b/) {
+	  $content='OPTIONAL';
+	}
+	elsif(/^PARAMETER\b/) {
+	  $content='PARAMETER';
+          $decl = 2;
+	}
+	elsif(/^POINTER\b/) {
+	  $content='POINTER';
+	}
+	elsif(/^PUBLIC\b/) {
+	  $content='PUBLIC';
+	}
+	elsif(/^PRIVATE\b/) {
+	  $content='PRIVATE';
+	}
+	elsif(/^SAVE\b/) {
+	  $content='SAVE';
+	}
+	elsif(/^TARGET\b/) {
+	  $content='TARGET';
+	}
+	elsif(/^SEQUENCE\b/) {
+	  $content='SEQUENCE';
+	}
+	elsif(/^INTERFACE\b/) {
+	  $content='INTERFACE';
+	  if(! $study_called) {
+	    $$prog_info{has_interface_block}=1;
+	    $in_interface=1;
+	  }
+	}
+	elsif(/^END ?INTERFACE\b/) {
+	  $content='END INTERFACE';
+	    $in_interface=0;
+	}
+	elsif(/^TYPE *[^\( ]/i) {
+	  $content='type_def';
+	  $type_def=1;
+	}
+	elsif(/^END\s*TYPE\b/){
+	  $content='type_def';
+	  $type_def=0;
+	}
+        elsif( $in_interface ) {
+          if(/^MODULE PROCEDURE\b/) {
+            $content='MODULE PROCEDURE';
+          }
+        }
+      }
+# Other constructs
+      if($content eq 'unknown') {
+	$decl=0;
+	$exec=0;
+	
+	if(/^CONTAINS\b/) {
+	  $content='CONTAINS';
+	  $in_contain=1;
+          $contain_host=uc($current_unit_name);
+	  if(! $study_called) {
+	    $$prog_info{has_contain}=1;
+	    $$prog_info{containing}=1;
+	  }
+	}
+	elsif(/^(?:INCLUDE|#include)\b/) {
+	  $content='include';
+	  if(! $study_called) {
+	    $$prog_info{has_include}=1;
+	  }
+	}
+	elsif(/^\#/) {
+	  $content='cpp';
+	}
+	elsif(/^\@/) {
+	  $content='compiler_directive';
+	}
+	
+	else{
+	  if(/^END\b/ and ! $in_interface) {
+	    $prog_unit=pop(@punit);
+	    $content='END '.uc($prog_unit);
+	    if($in_contain) {
+	      unless(@punit) {
+		$unit_count=0;
+		$href->{in_contain}=0;
+		$in_contain=0;
+	      }
+	    }
+	  }
+	} 
+      }
+    }
+    
+    if($in_interface and $content ne 'INTERFACE') {
+      $content='in_interface';
+      $exec=0;
+      $decl=1;
+    }
+
+#    print "BB $unit_count $content $_";
+    if($content  eq 'unknown') {
+      print STDERR $fname, ': failed to crack statement starting at line ',
+                   $href->{first_line}, ', - syntax error?', "\n";
+      print STDERR ' ', $_, "\n";
+#      print STDERR "study_called $study_called in_interface $in_interface \n";
+#      print STDERR Dumper($statements);
+      #die "Failed in study";
+    }
+#    unless($content eq 'comment') {
+#      my @tmpvar=/\b$name\b/g;
+#      my $i=0;
+#      foreach my $tmp (@tmpvar){ 
+#	$href->{'tokens'}[$i]=$tmp;
+#	$i++;
+#	if(! $study_called and $unit_count > -1) {
+#	  $$prog_info{'token_hash'}[$unit_count]{$tmp}++;
+#	}
+#      }
+#    }
+               
+    $href->{content}=$content;
+    $href->{content2}=$content2 if($content2);
+    $href->{decl}=$decl;
+    $href->{exec}=$exec;
+#    $href->{type_decl}=$type_decl;
+    $href->{prog_unit}=$unit_count;
+    $href->{number}=$number;
+    unless($content eq 'comment') {
+      $href->{multi_line} = 1 if(tr/\n// > 1);
+    }
+  }
+
+
+# Find first executable statement in each program unit
+# Also repair statement functions wrongly assigned as executable
+  my $prev_unit_count=-2;
+  my $stat_func_suspicion=0;
+  my @lastexec=();
+
+  foreach $href (@$statements) {
+    $exec=$href->{exec};
+    $unit_count=$href->{prog_unit};
+    if($exec) {
+      if($unit_count > $prev_unit_count) {
+	$content=$href->{content};
+	if($content eq 'array_assign') {
+	  $stat_func_suspicion=1;
+	  $_=$href->{statement};
+	  if(/^\s*$name\s*\(\s*:/){
+	    $stat_func_suspicion=0;
+#	    print " A $_";
+	   } 
+	  elsif(/^\s*$name\s*\(\s*$name\s*:/){
+	    $stat_func_suspicion=0;
+#	    print " B $_";
+	  } 
+	  elsif(/^\s*$name\s*\(\s*\d+/){
+	    $stat_func_suspicion=0;
+#	    print " C $_";
+	  }
+	  else {
+	    $href->{exec}=0;
+	    $href->{decl}=5;
+	    $href->{content}='statmf';
+#	    print " D $_";
+	    next;
+	  }
+	}
+	$href->{exec}=2;
+	$prev_unit_count=$unit_count;
+	$content=$href->{content};
+      }
+      $lastexec[$unit_count]=$href->{number}  unless ($unit_count < 0);  
+# No prog_unit assigned, include file?
+    }
+  }
+
+# Assign last executable statement
+  if(@lastexec) {
+    foreach my $last (@lastexec) {
+      if(defined ($last)) {
+	if($$statements[$last]->{exec} == 1) {
+	  $$statements[$last]->{exec}=3;
+	}
+	else{
+	  $$statements[$last]->{exec}=23;
+	}      
+      }
+    }
+  }
+# Consistency checks
+  my $fail=0;
+  my $prev_exec=0;
+  $prev_unit_count=-1;
+  foreach $href (@$statements) {
+    $content=$href->{content};
+    next if($content eq 'comment');
+    $unit_count=$href->{prog_unit};
+    $exec=$href->{exec};
+    $decl=$href->{decl};
+    if($unit_count == $prev_unit_count) {
+      if($decl and $prev_exec) {
+	unless ($content eq 'FORMAT' | $content eq 'DATA' ) {
+          die $fname, ': declaration after executable statement', "\n",
+              $href->{first_line}, ' ', $href->{statement}, "\n";
+	}
+      }
+    }
+    $prev_unit_count=$unit_count;
+    $prev_exec=$exec;
+  }
+
+  $study_called=1;
+}
+
+#==========================================================================
+sub study_exec{
+  my($content,$prog_info,$study_called) = @_;
+  our ($name,$nest_par);
+  if(/^(\w+\s*:\s*)*IF\s*$nest_par\s*THEN/) {
+    $$content='IF_construct';
+  }
+  elsif(/^ELSE\s*IF\s*\(/) {
+    $$content='ELSEIF';
+  }
+  elsif(/^ELSE\b\s*($name)*/) {
+    $$content='ELSE';
+  }
+  elsif(/^END\s*IF\b\s*($name)*/) {
+    $$content='ENDIF';
+  }
+  elsif(/^(?:\d+\s+)?($name\s*:\s*)*DO(\s+WHILE)?\b/) {
+    $$content='DO';
+  }
+  elsif(/^(?:\d+\s+)?END\s*DO\b/) {
+    $$content='ENDDO';
+  }
+  elsif(/^(?:\d+\s+)?ALLOCATE\b/) {
+    $$content='ALLOCATE';
+  }
+  elsif(/^ASSIGN\b/) {
+    $$content='ASIGN';
+  }
+  elsif(/^(?:\d+\s+)?BACKSPACE\b/) {
+    $$content='BACKSPACE';
+  }
+  elsif(/^(?:\d+\s+)?CALL\b/) {
+    $$content='CALL';
+    if(!$$study_called) {
+      $$prog_info{no_calls}++;
+    }
+  }
+  elsif(/^(?:\d+\s+)?CLOSE\b/) {
+    $$content='CLOSE';
+  }
+  elsif(/^(?:\d+\s+)?CONTINUE\b/) {
+    $$content='CONTINUE';
+  }
+  elsif(/^(?:\d+\s+)?CYCLE\b/) {
+    $$content='CYCLE';
+  }
+  elsif(/^(?:\d+\s+)?DEALLOCATE\b/) {
+    $$content='DEALLOCATE';
+  }
+  elsif(/^ENDFILE\b/) {
+    $$content='ENDFILE';
+  }
+  elsif(/^(?:\d+\s+)?EXIT\b/) {
+    $$content='EXIT';
+  }
+  elsif(/^(?:\d+\s+)?GO\s*TO\b/) {
+    $$content='GOTO';
+  }
+  elsif(/^(?:\d+\s+)?IF\s*\(/) {
+    $$content='IF';
+  }
+  elsif(/^(?:\d+\s+)?INQUIRE\b/) {
+    $$content='INQUIRE';
+  }
+  elsif(/^(?:\d+\s+)?NULLIFY\b/) {
+    $$content='NULLIFY';
+  }
+  elsif(/^(?:\d+\s+)?OPEN\b/) {
+    $$content='OPEN';
+  }
+  elsif(/^(?:\d+\s+)?PAUSE\b/) {
+    $$content='PAUSE';
+  }
+  elsif(/^(?:\d+\s+)?PRINT\b/) {
+    $$content='PRINT';
+  }
+  elsif(/^(?:\d+\s+)?(?:READ|BUFFER\s*IN)\b/) {
+    $$content='READ';
+  }
+  elsif(/^(?:\d+\s+)?RETURN\b/) {
+    $$content='RETURN';
+  }
+  elsif(/^(?:\d+\s+)?REWIND\b/) {
+    $$content='REWIND';
+  }
+  elsif(/^(?:\d+\s+)?STOP\b/) {
+    $$content='STOP';
+  }
+  elsif(/^(?:\d+\s+)?(?:WRITE|BUFFER\s*OUT)\s*\(/) {
+    $$content='WRITE';
+  }
+  elsif(/^(?:\d+\s+)?($name\s*:\s*)*SELECT\s*CASE\b/) {
+    $$content='SELECT CASE';
+  }
+  elsif(/^(?:\d+\s+)?CASE\b/) {
+    $$content='CASE';
+  }
+  elsif(/^(?:\d+\s+)?END\s*SELECT\b/) {
+    $$content='END SELECT';
+  }
+  elsif(/^(?:\d+\s+)?WHERE\s*$nest_par\s*$name.*=/) {
+    $$content='WHERE';
+  }
+  elsif(/^(?:\d+\s+)?WHERE\s*\(/) {
+    $$content='WHERE_construct';
+  }
+  elsif(/^ELSE\s*WHERE\b/) {
+    $$content='ELSEWHERE';
+  }
+  elsif(/^END\s*WHERE\b/) {
+    $$content='ENDWHERE';
+  }
+  elsif(/^(?:\d+\s+)?FORALL\s*\(/) {
+    $$content='FORALL';
+  }
+  elsif(/^END\s*FORALL\b/) {
+    $$content='ENDFORALL';
+  }
+  elsif(/^(?:\d+\s+)?$name(?:\s*%\s*$name)*\s*=/o) {
+    $$content='scal_assign';
+  }
+  elsif(/^(?:\d+\s+)?$name(?:\s*$nest_par)*(?:\s*%\s*$name(?:\s*$nest_par)?)*\s*=/o) {
+    $$content='array_assign';
+  }
+}
+#===================================================================================
+sub pre_tidy {
+
+# Initial tidying to make the rest work
+
+  my($lines)=@_;
+  foreach (@$lines) {
+
+# Substitute tab with four blanks
+    s/\t/    /g;
+    s/^ *INTEGER /INTEGER_M /i;
+    s/^ *REAL /REAL_B /i;
+  }
+}
+#==========================================================================
+sub remove_macro {
+
+# Remove INTEGER_M, _ONE_ etc. macros and replace by expanded statement
+
+  my($lines)=@_;
+
+  my($im)=1; # Until I start checking include files
+  my($ia)=0;
+  my($ib)=0;
+  my($rb)=1; # Until I start checking include files
+  my($is)=0;
+  my($rh)=0;
+  my($rm)=0;
+  my(@pars,$string);
+  for (@$lines) {
+    next if(/^ *$/ | /^ *!/);
+# The following two substitutions should be restored at end of processing
+    s/(\'[^!]*)!+(.*\')/$1\£$2/;   # Protect against mischief 
+    s/(["][^!]*)!+(.*["])/$1\£$2/;      # Protect against mischief
+    $im=$im+/JPIM\b/i unless($im);
+    $rb=$rb+/JPRB\b/i unless($rb);
+    $rm=$rm+/JPRM\b/i unless($rm);
+    $im=$im+s/\bINTEGER_M\b/INTEGER(KIND=JPIM)/o;
+    $ia=$ia+s/\bINTEGER_A\b/INTEGER(KIND=JPIA)/o;
+    $ib=$ib+s/\bINTEGER_B\b/INTEGER(KIND=JPIB)/o;
+    $is=$is+s/\bINTEGER_S\b/INTEGER(KIND=JPIS)/o;
+    $rb=$rb+s/\bREAL_B\b/REAL(KIND=JPRB)/o;
+    $rh=$rh+s/\bREAL_H\b/REAL(KIND=JPRH)/o;
+    $rm=$rm+s/\bREAL_M\b/REAL(KIND=JPRM)/o;
+    $rb=$rb+s/\b_ZERO_\b/0.0_JPRB/og;
+    $rb=$rb+s/\b_ONE_\b/1.0_JPRB/og;
+    $rb=$rb+s/\b_TWO_\b/2.0_JPRB/og;
+    $rb=$rb+s/\b_HALF_\b/0.5_JPRB/og;
+  }
+  @pars=();
+  push(@pars,"JPIM") if $im;
+  push(@pars,"JPRB") if $rb;
+  push(@pars,"JPRM") if $rm;
+  push(@pars,"JPIA") if $ia;
+  push(@pars,"JPIB") if $ib;
+  push(@pars,"JPIS") if $is;
+  ($string=join('     ,',@pars))=~s/ *$//;
+  for (@$lines) {
+    next unless (/^\#/);
+    if(@pars) {
+      s/^#include +"tsmbkind.h"/USE PARKIND1  ,ONLY : $string/ ;
+    }
+    else {
+      s/^#include +"tsmbkind.h"//;
+    }
+#    if($rh) {
+      s/^#include +"hugekind.h"/USE PARKIND2  ,ONLY : JPRH/ ;
+#    }
+#    else {
+#      s/^#include +"hugekind.h"// ;
+#    }
+  }
+}
+
+#==========================================================================
+sub readfile  {
+# Read file 
+  my($fname)=@_;
+  my(@lines);
+  if(!open(INFIL,$fname)) {
+    print STDERR "Can't open $fname for reading\n";
+    die("Can't open $fname for reading\n");
+  }
+  @lines=<INFIL>;
+  close INFIL;
+  (@lines);
+}
+
+#==========================================================================
+sub writefile  {
+# Write file
+  my($fname,$lines)=@_;
+  if(!open(OUTFIL,">".$fname)) {
+    print STDERR "Can't open $fname for writing\n";
+    exit;
+  }
+  print OUTFIL @$lines;
+  close OUTFIL;
+}
+
+#==========================================================================
+sub expcont {
+#
+# Expand continuation lines into statements for free-format Fortran while
+# maintaining line-breaking and all comments
+# Put statements onto array of references to anonymous hashes as key 'statement'
+# Also put into the hash the linenumber of first line of statement as key 'first_line'
+  my ($lines, $statements) = @_;
+  my ($statm, $first_line);
+
+  my $prev        = 0;
+  my $line_number = 0;
+
+  for (@$lines) {
+    $line_number++;
+
+    s/^([^'"]*)(?:\s*!.*)$/$1/; # Remove trailing comments
+
+    s/^(\s*)&(.*)$/$1$2/s;
+
+    if (!/^\s*!.*$/ && /^.+?&(?:\s*!.*)*\s*$/) {
+      s/(.+?)&(.+)/$1\n/s;
+
+      $statm     .= $_;
+      $first_line = $line_number unless $prev;
+      $prev       = 1;
+      next;
+
+    } elsif ($prev && /^\s*(?:!|$)/) { # ignore blank/comment lines
+      next;
+
+    } else {
+      s/!.*?$//;
+
+      $statm     .= $_;
+      push @$statements, {
+        'statement'  => $statm,
+        'first_line' => $prev ? $first_line : $line_number,
+      };
+
+      $statm = "";
+      $prev  = 0;
+    }
+  }
+}
+#==========================================================================
+
+sub cont_lines {
+#
+# Put back continuation character in correct place and execute delayed actions
+#
+  my($statements,$lines,$line_hash) = @_;
+  my(@temp,$i,$iup,$href);
+
+
+# Put back continuation characters and split statements into lines as they were
+  @$lines=();
+  @$line_hash=();
+  foreach $href (@$statements) {
+    $_=$href->{statement};
+    if (/\n.*\n/){                      # This is a multi-line statement
+      @temp=split /\n/;                 # Split statement into lines (removes EOL)
+      $iup=scalar(@temp);               # Number of lines in statement
+      for ($i=0;$i < $iup;$i++) {       # Loop through lines
+	$_=$temp[$i];
+	if($i == 0 ){                   # First line
+	  if(/^([^!]+)(!.*)$/) {        # Line has trailing comment
+	    s/^([^!]+)(!.*)$/$1&$2\n/;  # Put back & at end of line before comment
+	  }
+	  else {                        # No trailing comment
+	    s/^([^!]+)$/$1&\n/;         # Put back & and EOL at end of line
+	  }	    
+	}
+	elsif ($i == ($iup-1)) {        # Last line
+	  s/^( *)(.*)$/$1& $2 \n/;      # Put back & at beginning of line
+	}
+	else {                          # Other lines
+	  if (/^ *!/) {                 # Line is comment line
+	    $_=$_."\n";                 # Restore EOL for comments
+	  }
+	  else {
+	    if(/^( *)([^!]*)(!.*)$/) {  # Line has trailing comment
+	      s/^( *)([^!]*)(!.*)*$/$1& $2&$3\n/;  # & at beginning and end of line
+	    }
+	    else {                      # No trailing comment
+	      s/^( *)([^!]*)$/$1& $2&\n/; # & at beggining and end of line
+	    }	 
+	  }  
+	}
+	if($i == 0        && exists $href->{pre_insert}) {
+	  my @templines=split('\n',$href->{pre_insert});
+	  foreach my $tline (@templines) {
+	    my $rec={};
+	    $rec->{'content'}='unknown';
+	    $rec->{'line'}=$tline."\n";
+	    push(@$lines,$rec->{'line'});
+	    push(@$line_hash,$rec);
+	  }
+	}
+	unless(exists $href->{remove}) {
+	  my $rec={};
+	  $rec->{'line'}=$_;
+	  if($i == 0) {
+	    $rec->{'content'}=$href->{content};
+	  }
+	  else {
+	    $rec->{'content'}='cont_line';
+	  }
+	  push(@$lines,$rec->{'line'});
+	  push(@$line_hash,$rec);
+	}
+	if($i == ($iup-1) && exists $href->{post_insert}) {
+	  my @templines=split('\n',$href->{post_insert});
+	  foreach my $tline (@templines) {
+	    my $rec={};
+	    $rec->{'content'}='unknown';
+	    $rec->{'line'}=$tline."\n";
+	    push(@$lines,$rec->{'line'});
+	    push(@$line_hash,$rec);
+	  }
+	}
+      }
+    }
+    else {  # Not multiline statement
+      if(exists $href->{pre_insert}) {
+	my @templines=split('\n',$href->{pre_insert});
+	foreach my $tline (@templines) {
+	  my $rec={};
+	  $rec->{'content'}='unknown';
+	  $rec->{'line'}=$tline."\n";
+	  push(@$lines,$rec->{'line'});
+	  push(@$line_hash,$rec);
+	}
+      }
+      unless(exists $href->{remove}) {
+	my $rec={};
+	$rec->{'line'}=$_;
+	$rec->{'content'}=$href->{content};
+	push(@$lines,$rec->{'line'});
+	push(@$line_hash,$rec);
+#	print $rec;
+      }
+      if(exists $href->{post_insert}) {
+	my @templines=split('\n',$href->{post_insert});
+	foreach my $tline (@templines) {
+	  my $rec={};
+	  $rec->{'content'}='unknown';
+	  $rec->{'line'}=$tline."\n";
+	  push(@$lines,$rec->{'line'});
+	  push(@$line_hash,$rec);
+	}
+      }
+    }
+  }
+}
+#==========================================================================
+sub getvars {
+# Return list of locally declared variables with type and scope information
+# 
+  my($statements,$prog_info,$vars,$use_vars) = @_;
+  my ($test,$type,@vars1,$func,$prog_unit,$dum,$tmp_name,@pu_args);
+  my ($preserve,$rank,$href);
+  our($nest_par,$name);
+
+  %$vars=();
+  $func="";
+  $prog_unit=0;
+  %$use_vars=();
+  foreach $href (@$statements) {
+    next if($href->{content} eq 'comment');           # Skip comments
+    next if($href->{exec});                        # Don't look in executable statements
+    next if($$prog_info{is_module} and ! $href->{in_contain}); # Unless inside CONTAIN skip module 
+    $prog_unit=$href->{prog_unit};
+    if($href->{content} eq 'FUNCTION') {
+      $_=$href->{statement};
+      my $dum=&parse_prog_unit(\$func,\@pu_args);          # Get name of FUNCTION
+#      print "GETVARS FUNCTION $func \n";
+      $func=uc($func);
+    }
+    if($href->{decl} == 2 or $href->{content} eq 'EXTERNAL'){  # Real parse starts
+      $_=$href->{statement};
+      $_=uc($_);                                   # Upcase to avoid /.../i
+      s/^ *//;                                     # remove leading blanks
+      if($href->{decl} == 2) {
+	$type=lc(substr($href->{content},0,1));
+      }
+      else {
+	$type='e';
+      }
+      s/\!.*\n/\n/g;                               # Remove trailing comments in all lines
+      $preserve=$_;
+      s/(.+)::(.+)/$2/s;                           #REAL(KIND=JPRB) :: zsig(:) -> zsig(:),
+      s/^EXTERNAL (.+)$/$1/;
+      s/\s+//g;                                    # Remove all white-space
+      if($href->{content} eq 'CHARACTER') {
+	s/($name)\*\d+/$1/g;
+	s/($name)\*$nest_par/$1/g;
+	s/($name)$nest_par\*\w+/$1/g;
+      }
+      s#=\(/.+/\)##;      # ZVAL(1:2)=(/1.0,2.0/) -> ZVAL(1:2)
+#?      s/=[^,\n]+//g;
+      s/$nest_par//g;     # ISEC3(SIZE(NSEC3)),ISEC4(SIZE(NSEC4)) -> ISEC3,ISEC4
+      s/=\w+//g;          # ZVAL=1.0 -> ZVAL
+      s@/.*/@@;           # What?
+      @vars1=split(',',$_);
+      for(@vars1) {
+	next unless /^$name$/;          # A bit of security
+	if($preserve =~ /\b$_\b *\(/ | $preserve =~ /DIMENSION/) {
+	  $rank=1;        # Variable is array
+	}
+	else {
+	  $rank=0;        # Variable is scalar
+	}
+	if($_ eq $func) {
+	  $$vars{$_}{type_spec}="f";
+	} 
+	else {
+	  if($href->{content} eq 'FUNCTION') {
+	    $$vars{$_}{type_spec}='f';
+	  }
+	  else {
+	    $$vars{$_}{type_spec}=$type;
+	  }
+	}
+	$$vars{$_}{scope}=$prog_unit;
+	$$vars{$_}{rank}=$rank;
+	$$vars{$_}{usage}='local';
+      }
+    }
+# Perhaps the variable is really a statement function?
+    if($href->{decl} == 5) {
+      $_=$href->{statement};
+      s/\s+//g;                                    # Remove all white-space
+      /^($name)\((.+)\)=/i;
+      my $tvar=uc($1);
+      my @stmf_args=split(',',$2);
+      if (exists($$vars{$tvar})) {
+	$$vars{$tvar}{type_spec}='s';
+#	print "STATMF OK $tvar \n ";
+      }
+      for (@stmf_args) {
+	if (exists($$vars{$_})) {
+	  $$vars{$_}{type_spec}='s';
+#	  print "STATMF ARG OK $_ \n ";
+	}
+      }
+    }
+  }
+# Perhaps instead the variable is a declaration of an external function?
+  my @extract=();                  # Extract part of statements for efficiency
+  foreach $href (@$statements) {
+    if($href->{exec}) {                 # Function call must be in executable stat.
+      next if($href->{content} eq 'CALL'); # A call can't contain an undeclared function
+      push(@extract,$href->{statement});
+    }
+  }
+  
+  foreach my $var (keys (%$vars)) {
+    next if($$vars{$var}{rank} > 0);   # Can't be a function if rank > 0
+    next if($$vars{$var}{type_spec} eq 's' | $$vars{$var}{type_spec} eq 'f');
+    my $dec_unit=$$vars{$var}{scope};
+    my $regex1=qr/\b$var\b\s*\(/i;      # As var's rank=0 this could be function call
+    for(@extract) {
+      if(/${regex1}/) {
+	s/\!.*\n/\n/g;                       # Remove trailing comments in all lines
+	s/\s+//g;                            # Remove all white-space
+	if(/${regex1}/) {
+	  if($$vars{$var}{type_spec} eq 'c') {   # Avoid CLVAR(1:3) etc.
+	    next if(/${regex1}\s*(\d+|$name)*\s*:\s*(\d+|$name)*\s*\)/);
+	  }
+#	  print "TYPE changed to function $var $_ \n";
+	  $$vars{$var}{type_spec}='f';
+	  last;
+	}
+      }
+    }
+  }
+# ---------------------------------------------------------------------
+# Assign  "usage" in Doctor sense to variable (default usage is 'local')
+# 
+  foreach $href (@$statements) {
+# Is the varaible a dummy argument
+    if($href->{content} eq 'FUNCTION' or $href->{content} eq 'SUBROUTINE') {
+      $_=$href->{statement};
+      @pu_args=();
+      my $dum=&parse_prog_unit(\$func,\@pu_args);   # Get arguments
+      for(@pu_args) {
+	if( exists $$vars{$_} ) {
+	  if($$vars{$_}{scope} == $href->{prog_unit}) {
+	    $$vars{$_}{usage}='arg';
+	  }
+
+	} else {
+          print STDERR "Argument $_ has not got a corresponding declaration " .
+                       "statement\n";
+          print STDERR "Bailing out at this point\n";
+          die "Bailing out";
+	}
+      }
+    }
+# Does the variable appear in a NAMELIST
+# We want to distinguish this for more lenient Doctor check
+    if($href->{content} eq 'NAMELIST') {
+      $_=$href->{statement};
+      s/\!.*\n/\n/g;     # Remove trailing comments in all lines
+      s/\s+//g;          # Remove all white-space
+      m:NAMELIST/\w+/(.+):;
+      my @namvars=split(',',uc($1));
+      for (@namvars) {
+	if( exists $$vars{$_} ) {
+	  if($$vars{$_}{scope} == $href->{prog_unit}) {
+	    $$vars{$_}{usage}='namvar';
+	  }
+	}
+      }
+    }
+    if(exists $href->{inc_statm}) { # We also have to look in include files
+      my $incs=$href->{inc_statm};
+      foreach my $hrefi (@$incs) {
+	if($hrefi->{content} eq 'NAMELIST') {
+	  $_=$hrefi->{statement};
+	  s/\!.*\n/\n/g;     # Remove trailing comments in all lines
+	  s/\s+//g;          # Remove all white-space
+	m:NAMELIST/\w+/(.+):;
+	  my @namvars=split(',',uc($1));
+	  for (@namvars) {
+	    if( exists $$vars{$_} ) {
+	      if($$vars{$_}{scope} == $href->{prog_unit}) {
+		$$vars{$_}{usage}='namvar';
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+# -----------------------------------------------------------------------------
+# Find use variables
+  my %use_count=();
+  foreach $href (@$statements) {
+    if($href->{content} eq 'USE') {
+      $prog_unit=$href->{prog_unit};
+      $_=$href->{statement};
+      s/\!.*\n/\n/g;                               # Remove trailing comments in all lines
+      s/\s+//g;                                    # Remove all white-space
+      $_=uc($_);                                   # Upcase to avoid /.../i
+      if(/^USE($name),ONLY:(.+)$/){
+	my $modname=$1;
+	if( exists $use_count{$modname}) {
+	  if($prog_unit == $use_count{$modname}) {
+	    print STDERR "-> $href->{statement}";
+            print STDERR "USE $modname appears more than once in program unit $prog_unit \n\n";
+
+	  }
+	}
+	$use_count{$modname} = $prog_unit;
+	my @usevars = split /,/ ,$2;
+	my %usevars=();
+	foreach my $usevar (@usevars) {
+	  $usevars{$usevar}++;
+	  $$use_vars{$usevar}{module}=$modname;
+	  $$use_vars{$usevar}{scope}=$prog_unit;
+	  $$use_vars{$usevar}{count}++;
+	}
+	foreach my $usevar (keys (%usevars)) {
+	  if($usevars{$usevar} >1) {
+	    print STDERR "DUPLICATE USE ONLY VARIABLE ",
+	    "$modname $usevar $prog_unit \n";
+	    $_=$href->{statement};
+	    s/\b$usevar\b//i;
+	    s/,\s*,/,/;
+	    s/,\s*\n$/\n/;
+	    s/\n *\n/\n/;
+	    s/^(.+:\s*),/$1/;
+	    $href->{statement}=$_;
+	  }
+	}
+      }
+      else {
+#	print "WARNING:USE without ONLY \n";
+      }
+    }
+  }
+}
+#==========================================================================
+sub find_unused_vars {
+# Find declared variables not used
+  my($statements,$vars,$unused_vars,$use_vars,$unused_use_vars) = @_;
+  my ($var,@tokens,$href);
+  @tokens=();
+# Find all tokens in file
+  foreach $href (@$statements) {
+    next if($href->{content} eq 'comment');
+    if(exists $href->{inc_statm}) {  # Look also in include files
+      my $incs=$href->{inc_statm};
+      foreach my $hrefi (@$incs) {
+	die "FUV $href->{content} $href->{statement}" unless exists $hrefi->{statement};
+	$_=$hrefi->{statement};
+	if(/\b[a-zA-Z]\w*\b/) {
+	  push(@tokens,/\b[a-zA-Z]\w*\b/g);
+	}
+      }
+    }
+    else {
+      $_=$href->{statement};
+      push(@tokens,/\b[a-zA-Z]\w*\b/g);
+    }
+  }
+  @tokens= map {uc} @tokens; # Upcase array of tokens, the variables are upper-case
+
+# Find out how many times the variable appears in array tokens
+  foreach $var (keys (%$vars)) {
+    $$vars{$var}{uses}=0;
+  }
+  foreach $var (keys (%$use_vars)) {
+    $$use_vars{$var}{uses}=0;
+  }
+  for (@tokens) {
+    if(exists($$vars{$_})){
+      $$vars{$_}{uses}++; 
+    }
+    if(exists($$use_vars{$_})){
+      $$use_vars{$_}{uses}++; 
+    }
+  }
+# If it appears only one time (which must be in a declaration) it is unused
+  @$unused_vars=();
+  foreach $var (keys (%$vars)) {
+    push(@$unused_vars,$var) if($$vars{$var}{uses} < 2);
+  }
+  @$unused_use_vars=();
+  foreach $var (keys (%$use_vars)) {
+    push(@$unused_use_vars,$var) if($$use_vars{$var}{uses} < 2);
+  }
+}
+#==========================================================================
+sub remove_unused_vars {
+# Does what it says on the tin
+  my($statements,$unused_vars,$unused_use_vars) = @_;
+  my ($var,$href);
+  our $nest_par;
+  for (@$unused_vars) {
+    $var=$_;
+    foreach $href (@$statements) {
+      $_=$href->{statement};
+      next unless(($href->{decl}) | ($href->{content} eq 'comment'));
+      if($href->{content} eq 'comment') {
+	next unless(/^ *!\$OMP/);
+      }
+      if(/\b$var\b/i) {
+#	print $_;
+	
+	if(/\b$var\b *\(/i) {
+#	  print "ZYZ $var $_";
+	  s/\b$var\b *$nest_par *(=\s*\(\/.*\/\))*//si;
+#	  print "ZZZ $var $_";
+	}
+	s/\b$var\b\s*=\s*\d+(\.\d*)*//i;
+	s/\b$var\b *(\* *\d+)*//i if($href->{content} eq 'CHARACTER') ;
+	s/\b$var\b//i; 
+#	print $_;
+        s/^.+:: *\n$//;
+        s/^.+:: *\!.*\n$//;
+#	print $_;
+        s/,\s*,/,/;
+#	print $_;
+	s/, *\n$/\n/;
+#	print $_;
+        s/(::\s*),(.+)$/$1$2/s;
+        s/\n *\n/\n/;
+        s/\n *!.*\n/\n/;
+	s/, *\n$/\n/;
+# Remove "empty" lines
+        s/^.+::\s*$//;
+        s/^.+::\s*=.*$//;
+        s/^.+::\s*!.*$//;
+#	print $_;
+        s/^CHARACTER *\*\d+ *\n$//i if($href->{content} eq 'CHARACTER') ;
+	$href->{statement}=$_;
+      }
+    }
+  }
+  for (@$unused_use_vars) {
+    $var=$_;
+    foreach $href (@$statements) {
+      next unless($href->{decl} == 4);
+      $_=$href->{statement};
+      next if(/PARKIND/); #I am sure this could be done betterh
+
+      if(/\b$var\b/i) {
+	s/\b$var\b//i;
+        s/,\s*,/,/;
+        s/,\s*\n$/\n/;
+        s/\n *\n/\n/;
+	s/^(.+:\s*),/$1/;
+	s/^.+:\s*$//;
+	$href->{statement}=$_;
+      }
+    }
+  }
+}
+#==========================================================================
+sub tidy_decl {
+# Tidy up declarions
+  my($statements) = @_;
+  my($href,$content);
+
+  foreach $href (@$statements) {
+    next unless($href->{decl} == 2);
+    $_=$href->{statement};
+    $content=$href->{content};
+    
+    if($content eq 'CHARACTER') {
+      s/CHARACTER *\* *(\w+)/CHARACTER \(LEN = $1\)/i; 
+      s/CHARACTER *\* *\(\*\)/CHARACTER \(LEN = \*\)/i;
+      s/CHARACTER *\* *\( *(\w+) *\)/CHARACTER \(LEN = $1)/i;
+    }
+    if($content eq 'INTEGER') {
+      if(/^ *INTEGER[^\(]/i) {
+	s/INTEGER\b/INTEGER(KIND=JPIM)/;
+      }
+    }
+    unless (/::/) {
+      s/^( *LOGICAL )/$1:: /i;
+      s/^( *INTEGER\(KIND=JPI\w\) )/$1:: /;
+      s/^( *REAL\(KIND=JPR\w\) )/$1:: /;
+      if(/^ *CHARACTER/i) {
+	if( s/^( *CHARACTER *\( *LEN *= *\w+ *\))/$1 :: /i) {
+	  $href->{statement}=$_;
+	  next;
+	}
+	if(s/^( *CHARACTER *\( *LEN *= *\* *\))/$1 :: /i) {
+	  $href->{statement}=$_;
+	  next;
+	}
+	s/^( *CHARACTER )/$1:: /i;
+      }
+    }
+    $href->{statement}=$_;
+  }
+}
+#==========================================================================
+
+sub doctor_viol {
+# Find Doctor violations
+
+  my($vars,$fix_doc) = @_;
+  my ($var,$type,$zz,$prog_unit,$usage);
+  %$fix_doc=();
+
+  foreach $var (keys (%$vars)) {
+    $type=$$vars{$var}{type_spec};
+    $prog_unit=$$vars{$var}{scope};
+    $usage=$$vars{$var}{usage};
+#    print "DOC $var $type $prog_unit $usage \n";
+    if($zz=&doc_char($type,$usage,$var)) {
+#      print "DOCTOR VIOL - ",$var," $type $zz $prog_unit\n";
+      $$fix_doc{$var}=$zz.'_'.$var.','.$prog_unit
+    }
+  }  
+}
+#==========================================================================
+
+sub fix_doctor_viol {
+# Fix Doctor violations
+  my($statements,$fix_doc) = @_;
+  my($doc_viol,$repl,$prog_unit,$cur_prog_unit,@allowed,$href,$content);
+  my($tmp_name,@pu_args);
+
+  @allowed=('NRGRI'); # Hack
+
+  VIOL:foreach $doc_viol (keys (%$fix_doc)) {
+    # Let's allow some violations
+    for (@allowed){ 
+      next VIOL if($doc_viol eq $_);
+    }
+
+    ($repl,$prog_unit)=split(',',$$fix_doc{$doc_viol});
+
+    print "FIX $repl $prog_unit \n";
+    foreach $href (@$statements) {
+      $content=$href->{content};
+      $_=$href->{statement};
+      if($href->{content} eq 'comment') {
+	next unless(/^ *!\$OMP/);
+      }
+      $cur_prog_unit=$href->{prog_unit};
+      if($prog_unit == $cur_prog_unit) {  # Could be fine in other program units
+	if(/\b$doc_viol\b/i) {
+	  s/%$doc_viol\b/_X_$doc_viol/ig; # Protect type-components
+	  s/\b$doc_viol\b/$repl/ig;
+	  s/_X_$doc_viol\b/%$doc_viol/ig; # Restore type-components
+	}
+      }
+      $href->{statement}=$_;
+    }
+  }
+  
+}
+#==========================================================================
+sub various{
+# 
+  my($statements,$prog_info,$vars) = @_;
+  my($punit,@args,$tmp_name,$cont,$statm);
+  my($href,$exec);
+  our $nest_par;
+#------------------------------------------------------------------
+# Remove unneccesary RETURN statement
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    if($cont eq 'RETURN') {
+      if($href->{exec} == 3) {   # $href->{exec} == 3 means last executable statement
+	$href->{remove} = 1;     # Post remove line for later
+      }
+    }
+  }
+
+
+# Make sure all CALL MPL_... has a CDSTRING argument
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    if($href->{content} eq 'CALL' ) {
+      $_=$href->{statement};
+      if(/^\s*CALL\s+MPL_/i) {
+	next if(/^\s*CALL\s+MPL_ABORT/i);
+	next if(/^\s*CALL\s+MPL_WRITE/i);
+	next if(/^\s*CALL\s+MPL_READ/i);
+	next if(/^\s*CALL\s+MPL_OPEN/i);
+	next if(/^\s*CALL\s+MPL_CLOSE/i);
+	next if(/^\s*CALL\s+MPL_INIT/i);
+	next if(/^\s*CALL\s+MPL_GROUPS_CREATE/i);
+	next if(/^\s*CALL\s+MPL_BUFFER_METHOD/i);
+	next if(/^\s*CALL\s+MPL_IOINIT/i);
+	next if(/^\s*CALL\s+MPL_CART_COORD/i);
+#	print "CDSTRING=$$prog_info{'unit_name'}[$href->{prog_unit}]: \n";
+	unless(/CDSTRING\s*=/i) {
+	  s/\)(\s)$/,CDSTRING=\'$$prog_info{'unit_name'}[$href->{prog_unit}]:\'\)$1/;
+	  $href->{statement}=$_;
+	}
+      }
+    }
+  }
+	
+
+
+#------------------------------------------------------------------
+# Add Standard Modification Line
+
+  my $start=0;
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    if($cont eq 'comment') {
+      $_=$href->{statement};
+      if($start) {                        # Found header - look for end of mod lines
+	if(/^ *$/ || /^! *------------------------/) {
+	  $href->{pre_insert} = "!        M.Hamrud      01-Oct-2003 CY28 Cleaning\n";
+	  last;
+	}
+	next;
+      }
+      $start=1 if(/^! +Modifications/i) ;  # This how the header should look
+      next;
+    }
+    last if($href->{exec});                # We have failed - bail out
+  }
+
+# Change subroutine and call multi-line statements so that the comma
+# beetwen variables comes at the end of the line
+  my @lines=();
+  foreach $href (@$statements) {
+    if(exists $href->{multi_line}) {
+      $cont=$href->{content};
+      if($cont eq 'SUBROUTINE' | $cont eq 'CALL' ) {
+	$statm=$href->{statement};
+	@lines=split "\n", $statm;
+	@lines = reverse @lines;
+	my $append_comma=0;
+	for (@lines) {
+#	  print "A $append_comma $_ \n";
+	  next if(/^ *!/);
+	  if($append_comma) {
+	    if(/\S *!.*$/) {
+	      s/(\S)( *!.*)$/$1,$2/;
+	    }
+	    else {
+	      s/(\S) *$/$1,/;
+	    }
+	  }
+	  $append_comma=s/^ *,//;
+#	  print "B $append_comma $_ \n";
+	}
+	@lines = reverse @lines;
+	$statm=join  "\n",@lines;
+	$statm=$statm."\n";
+	$href->{statement}=$statm;
+      }
+    }
+  }
+  our $name;
+  foreach $href (@$statements) {
+    if($href->{content} eq 'USE') {
+      $_=$href->{statement};
+      unless(/^\s*USE\s+$name\s*,\s*ONLY\s*:/i){
+	print $_;
+	print "WARNING:USE without ONLY \n";
+      }
+    }
+  }    
+}
+#==========================================================================
+sub insert_hook{
+# 
+  my($statements,$prog_info,$vars) = @_;
+  my($punit,@args,$tmp_name,$cont,$statm);
+  my($href,$exec);
+  our $nest_par;
+#------------------------------------------------------------------
+# Add HOOK function
+  my $unit_name='';
+  my $last_use=0;
+  my $hook_status=0;
+  my $in_contain=0;
+  my $prev_prog=0;
+  my ($decl,$remember);
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    next if($cont eq 'comment');
+
+    $decl=$href->{decl};
+    $exec=$href->{exec};
+    $in_contain=$href->{in_contain};
+    if(! $in_contain and $href->{prog_unit} > $prev_prog) {
+      $hook_status=0;
+      $prev_prog=$href->{prog_unit};
+      print "resetting hook status \n";
+    }
+
+    if($cont eq 'FUNCTION' or $cont eq 'SUBROUTINE' or 
+       $cont eq 'PROGRAM'){ # Need name of routine
+      $_=$href->{statement};
+      &parse_prog_unit(\$unit_name,\@args);
+      $unit_name=uc($unit_name);
+# If in module pre-pend module name
+      $unit_name=$$prog_info{module_name}.':'.$unit_name if($$prog_info{is_module}); 
+      $remember=0;
+    }
+
+    if($hook_status == 0) {   # $hook_status == 0 means we have not done anything yet
+      if($cont eq 'USE') {    # Add USE YOMHOOK as second use statement
+	$href->{post_insert}="USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK\n";
+	$hook_status=1;
+      }
+      elsif($cont eq 'IMPLICIT NONE') { # No previous USE, add USE YOMHOOK before IMPLICIT NONE
+	$href->{pre_insert} ="USE PARKIND1  ,ONLY : JPRB\n".
+	  "USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK\n";
+	$hook_status=1;
+      } 
+    }
+    $remember=$href->{number} if($decl == 2); 
+
+#   Use statement added ($hook_status == 1), now insert HOOK switch on statement
+#   before first executable statement in program unit ($exec == 2)
+    if($hook_status == 1 && $exec == 2) {
+      if($remember) {
+	$$statements[$remember]->{post_insert}="REAL(KIND=JPRB) :: ZHOOK_HANDLE\n";
+	$href->{pre_insert}="IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',0,ZHOOK_HANDLE)\n";
+      }
+      else {
+	$href->{pre_insert}="REAL(KIND=JPRB) :: ZHOOK_HANDLE\n".
+	    "IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',0,ZHOOK_HANDLE)\n";
+      }   
+      if($cont eq 'IF') {
+	if($href->{content2} eq 'RETURN') {
+	  $_=$href->{statement};
+	  s/(\s*IF\s*$nest_par).*\n/$1/i;
+	  s/\)$/ .AND. LHOOK\)/;
+	  $href->{pre_insert}=$href->{pre_insert}."$_ CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+	}
+      }
+      $hook_status=2;
+    }
+#   Hook switched on($hook_status == 2), switch off after last executable statement
+#   ($exec == 3)
+    elsif($hook_status == 2) {
+      if($exec == 3 or $exec == 23) {
+	$href->{post_insert}="IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+	$hook_status=3;
+      }
+      elsif($cont eq 'RETURN') {
+	$href->{pre_insert}="IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+      }
+      elsif($cont eq 'IF') {
+	if($href->{content2} eq 'RETURN') {
+	  $_=$href->{statement};
+	  s/(\s*IF\s*$nest_par).*\n/$1/i;
+	  s/\)$/ .AND. LHOOK\)/;
+	  $href->{pre_insert}="$_ CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+	}
+      }	
+    }
+    $hook_status=1 if($in_contain && $hook_status==3); # Reset hook status in CONTAIN region
+  }
+  die "Adding HOOK function failed " if($hook_status == 2);
+}
+#==========================================================================
+
+sub doc_char{
+# Returns suggested prefix in case of DOCTOR violation (otherwise null string)
+  my($type,$usage,$var) = @_;
+  my $prefix="";
+# INTEGER variables
+  if( $type eq "i") {
+    if($usage eq "arg") {
+      $prefix="K" unless($var=~/^K/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="I" unless($var=~/^[IJ]/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="N" unless($var=~/^[MN]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="I" unless($var=~/^[MNIJ]/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+# REAL variables
+  elsif( $type eq "r") {
+    if($usage eq "arg") {
+      $prefix="P" unless($var=~/^P/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="Z" unless($var=~/^Z|^PP/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="R" if ($var=~/^[ZPIJKLMNCY]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="Z" if ($var=~/^[PIJKLMNCY]/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+#LOGICAL variables
+  elsif( $type eq "l") {
+    if($usage eq "arg") {
+      $prefix="LD" unless($var=~/^LD/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="LL" unless($var=~/^LL/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="L" unless($var=~/^L[^LD]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="LL" unless($var=~/^L/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+#CHARACTER variables
+  elsif( $type eq "c") {
+    if($usage eq "arg") {
+      $prefix="CD" unless($var=~/^CD/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="CL" unless($var=~/^CL/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="C" unless($var=~/^C[^LD]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="CL" unless($var=~/^C/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+# USER DEFINED TYPES
+  elsif( $type eq 't') {
+    if($usage eq "arg") {
+      $prefix="YD" unless($var=~/^YD/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="YL" unless($var=~/^YL/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="Y" unless($var=~/^Y[^LD]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="YL" unless($var=~/^Y/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+# FUNCTION/EXTERNAL declarations
+  elsif( $type eq 'f' || $type eq 'e' || $type eq 's') {
+# Everything is OK
+  }
+  else {
+    die "Unknown type $type"
+  }
+  ($prefix);
+}
+#==========================================================================
+     
+sub parse_prog_unit {
+# Find out program type,program name and arguments for program statement
+  my($unit_name,$args)=@_;
+  my($type)='';
+  $$unit_name='';
+  @$args=();
+  our($name,$type_spec);
+  if(/^\s*MODULE\s+($name)\s*$/io) {
+    $type='module';
+    $$unit_name=$1;
+  }
+  elsif(/^\s*PROGRAM\s+($name)\s*$/io) {
+    $type='program';
+    $$unit_name=$1;
+  }
+  elsif(/^\s*BLOCK\s*DATA\s+($name)\s*$/io) {
+    $type='blockdata';
+    $$unit_name=$1;
+  }
+  elsif(/^\s*(?:RECURSIVE)?\s*(SUBROUTINE)\s+($name)\b/io or
+	/^\s*(?:RECURSIVE)?\s*(?:$type_spec)?\s*(FUNCTION)\s+($name)\b/io) {
+    $type=lc($1);
+    $$unit_name=$2;
+#    print "FOUND PPU  $type $$unit_name \n ";
+    if(/^[^\(]+\([^\)]+\)/) {
+      my $tstatm=$_;
+      $tstatm=~ s/\!.*\n/\n/g;
+      $tstatm=~s/\s//g;
+      $tstatm=~s/\)result\((\w+\))$/,$1/i if $type eq 'function';
+      $tstatm=~s/.+\((.+)\)/$1/;
+      @$args=split(',',uc($tstatm));
+
+      push @$args, uc ($$unit_name)
+        if $type eq 'function' and not grep {$_ eq uc ($$unit_name)} @$args;
+    }
+  }
+  return $type;
+}
+
+#==========================================================================
+
+sub setup_parse {
+# Set up some "global" variables that helps with parsing statements
+  our $nest_par;
+  $nest_par = qr/\((?:(?>[^()]+)|(??{$nest_par}))*\)/; #Camel p214
+  our $name='[a-zA-Z]\w*';
+  our $digit_string='\d+';
+  our $type_name=$name;
+  our $specification_expr='(?:'.$name.'|'.$digit_string.')'; # Simplification
+  our $type_param_value='(?:\*|'.$specification_expr.')';
+  our $char_selector='LEN *= *'.$type_param_value; # Simplification
+  our $kind_selector='\( *KIND *= *'.$name.' *\)';    # Simplification
+  our $type_spec='INTEGER *(?:'.$kind_selector.')?|REAL *(?:'.$kind_selector.
+    ')?|DOUBLE PRECISION|COMPLEX *(?:'.$kind_selector.')?|CHARACTER *'.
+    $char_selector.'|LOGICAL *(?:'.$kind_selector.')?|TYPE\s*\(\s*'.$type_name.
+    '\s*\)';
+}
+
+#==========================================================================
+
+sub f90_indent {
+# Indent free-format F90 program to our standards
+  my($line_hash,$lines)=@_;
+  my($delta)='  '; 
+  my($cur_indent)='';
+  @$lines=();
+  foreach my $href (@$line_hash) {
+    $_=$href->{line};
+    if($href->{content} eq 'comment') {
+      push(@$lines,$_);
+      next;
+    }
+    s/^ *//; # Remove current indentation
+    my($post_chg)=0;
+    my($pre_chg)=0;
+    my($cont_line)='';
+    exit if (! exists $href->{content});
+    if($href->{content} eq 'DO') {
+      $post_chg=1 unless /^DO\s+\d/;
+    }
+    elsif($href->{content} eq 'ENDDO') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'IF_construct') {
+      $post_chg=1;
+    }
+    elsif($href->{content} eq 'ELSEIF') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ELSE') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDIF') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDIF') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'WHERE_construct') {
+      $post_chg=1;
+    }
+    elsif($href->{content} eq 'ELSEWHERE') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDWHERE') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDIF') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'SELECT CASE') {
+      $post_chg=1;
+    }
+    elsif($href->{content} eq 'CASE') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'END SELECT') {
+      $pre_chg=1;
+    }
+    $cont_line=' ' if($href->{content} eq 'cont_line');
+    if( $pre_chg ) {
+      unless($cur_indent=~s/^$delta//o) {
+	print STDERR $_;
+	die  "f90_indent: something wrong, indent negative\n";;
+      }
+    }
+#    print "$cur_indent$cont_line$_";
+    
+    $_=$cur_indent.$cont_line.$_;
+    push(@$lines,$_);
+    $cur_indent.=$delta if( $post_chg );
+  }
+
+  if(! ($cur_indent eq '')) {
+    die "f90_indent: something wrong, indent=XX${cur_indent}XX\n";
+  }
+}
+
+#==========================================================================
+
+sub tidy {
+# Straigthforward tidiyng of statements
+  my($statements) = @_;
+  my($href,$content);
+  foreach $href (@$statements) {
+    $_=$href->{statement};
+    $content=$href->{content};
+# Substitute tab with four blanks
+    s/\t/    /g;
+    if($content eq 'comment') {
+# Substitute empty comment line with empty line
+      s/^[!] *\n$/\n/;
+      $href->{statement}=$_;
+      next;
+    }
+    if($href->{exec}) {
+      if($content eq 'ENDDO') {
+	s/\bEND DO\b/ENDDO/i;
+	$href->{statement}=$_;
+	next;
+      }
+      if($content eq 'ENDIF') {
+	s/\bEND IF\b/ENDIF/i;
+	$href->{statement}=$_;
+	next;
+      }
+      if($content eq 'ENDWHERE') {
+	s/\bEND WHERE\b/ENDWHERE/i;
+	$href->{statement}=$_;
+	next;
+      }
+
+      s/\bELSE IF\b/ELSEIF/i  if($content eq 'ELSEIF');
+
+      if(/\./) {
+	s/ *\.EQ\. */ == /gi;
+	s/ *\.NE\. */ \/= /gi;
+	s/ *\.LT\. */ < /gi;
+	s/ *\.LE\. */ <= /gi;
+	s/ *\.GT\. */ > /gi;
+	s/ *\.GE\. */ >= /gi;
+      }
+
+#
+      s/\bA?MAX[01]\b/MAX/gi;
+      s/\bA?MIN[01]\b/MIN/gi;
+      s/\bAMOD\b/MOD/gi;
+      s/\bALOG\b/LOG/gi;
+      s/\bALOG10\b/LOG10/gi;
+#      s/\bI(SIGN *\()/$1/gi; # Goes wrong in larcinad etc.
+      s/\bFLOAT\b/REAL/g;
+      s/\bfloat\b/real/g;
+    }
+    
+    $href->{statement}=$_;
+  }
+}
+
+#==========================================================================
+
+sub process_include_files {
+# Read include files and put reference to the anonomys array
+# holding the array of "statement" hashes in $href->{inc_statm}
+  my($statements,$prog_info,$inc_statements) = @_;
+  my ($content,$fname,$href);
+  return unless ($$prog_info{has_include});
+  my @lines=();
+  foreach $href (@$statements) {
+    $content=$href->{content};
+    if($content eq 'include'){
+      $_=$href->{statement};
+      /["](\S+)["]/;
+      $fname=$1;
+      &get_inc_lines($fname,\@lines);
+# Macro-removal
+      &remove_macro(\@lines);
+# Expand lines into statements and put refernce to this
+# array of hashes into $href->{inc_statm}
+      my @inc_statms=();
+      my $dum={};
+      &expcont(\@lines,\@inc_statms);
+      $href->{inc_statm}=[@inc_statms];
+      my $incs=$href->{inc_statm};
+# Study the read in file and add more attributes
+      &study($incs);
+#      print Dumper($incs,$dum);
+      
+    }
+  }
+}
+#==========================================================================
+sub get_inc_lines{
+# Recurcivly get lines from include files, flatten into array of lines
+  my ($fname,$lines) = @_;
+  my ($VPATH,@vpath,@tmp_lines);
+
+  $VPATH=$ENV{VPATH} or die "VPATH not defined ";
+# IFS VPATH /tmp/27/ifs/function:/tmp/27/ifs/common:/tmp/27/ifs/interface:/tmp/27/ifs/namelist:/tmp/27/ifsaux/include:/tmp/27/trans/interface:/tmp/27/obsort/interface:/tmp/27/ifs/ald_inc/function:/tmp/27/ifs/ald_inc/interface:/tmp/27/ifs/ald_inc/namelist
+  @vpath=split(":",$VPATH);
+# Look for include file in VPATH
+  foreach my $path (@vpath) {
+    my $ffname=$path.'/'.$fname;
+    if( -f $ffname) {
+# Read lines from include file
+      @tmp_lines = &readfile($ffname);
+#      print "$ffname \n";
+      for (@tmp_lines) {
+	if(/^\#include\b/){
+	  /["](\S+)["]/;
+	  my $fname2=$1;
+	  &get_inc_lines($fname2,$lines);
+	}
+	else {
+	  push(@$lines,$_);
+	}
+      }
+      last;
+    }
+  }
+  die "Include file $fname not found in VPATH=$VPATH " unless(@$lines);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &create_interface_block (\@statements, \@interface_block);
+#
+# DESCRIPTION
+#   This function analyses the Fortran statements in \@statements and returns
+#   an interface block in \@interface_block.
+# ------------------------------------------------------------------------------
+
+sub create_interface_block {
+  # Create a "minimal" interface block for subroutines
+  my  ($statements, $interface_block) = @_;
+  my  (%pu_args, %tokens);
+  our ($name, $nest_par);
+
+  @$interface_block = ();
+
+  my @tokens_in_lines = (); # List of tokens in each line
+
+  # Gather information needed to create interface block for routine
+  for my $href (@$statements) {
+    last if $href->{exec}; # exit loop at beginning of executable statements
+
+    # Get arguments of subroutine or function
+    if ($href->{content} eq 'SUBROUTINE' or $href->{content} eq 'FUNCTION') {
+      my $func;
+      my @pu_args;
+      $_ = $href->{statement};
+      &parse_prog_unit (\$func, \@pu_args);
+      $pu_args{uc ($_)} = 1 for @pu_args;
+      next;
+    }
+
+    # Get tokens from lines where arguments are present
+    # Inspect only type declaration statements
+    next unless $href->{decl} == 2;
+
+    my $statement = uc $href->{statement};
+    $statement =~ s/!.*$//; # Remove trailing comment
+
+    my @line_tokens = ();
+    if ($statement =~ s/^(.*?):://) {
+      # New style declaration statement contains "::"
+
+      # Tokens in specification part
+      my $spec = $1;
+      my @tokens = ($spec =~ /\b$name\b/g);
+      shift @tokens; # Remove leading token
+
+      for (@tokens) {
+        push @line_tokens, $_
+          unless /^(?:KIND|LEN|ALLOCATABLE|POINTER|TARGET|DIMENSION|OPTIONAL|
+                  SAVE|INTENT|IN|OUT|INOUT|PARAMETER)$/x;
+      }
+
+      # Tokens in declaration part
+      push @line_tokens, ($statement =~ /\b$name\b/g);
+
+    } else {
+      # Old style declaration statement does not contain "::"
+      @line_tokens = ($statement =~ /\b$name\b/g);
+      shift @line_tokens; # Remove leading token
+    }
+
+    push @tokens_in_lines, \@line_tokens;
+
+    # Check whether each token matches an argument
+    for my $token (@line_tokens) {
+      if (exists $pu_args{$token}) {
+        $tokens{$_} = 1 for @line_tokens;
+        last;
+      }
+    }
+  }
+
+  # Parse statements one more time to ensure all required tokens are included
+  for (@tokens_in_lines) {
+    my @line_tokens = @{ $_ };
+
+    # Check whether line contains an essential token
+    for my $token (@line_tokens) {
+      if (exists $tokens{$token}) {
+        $tokens{$_} = 1 for @line_tokens;
+        last;
+      }
+    }
+  }
+
+  # Create the interface block
+  for my $href (@$statements) {
+    my %myhref  = %$href;
+    my $content = $myhref{content};
+
+    # Ignore comment, executable statements and items in CONTAINS block
+    next if $content eq 'comment';
+    next if $myhref{exec};
+    next if $myhref{in_contain};
+
+    # Delete existing pre- and post -inserts
+    delete $myhref{pre_insert}  if exists $myhref{pre_insert};
+    delete $myhref{post_insert} if exists $myhref{post_insert};
+
+    # Put SUBROUTINE/FUNCTION statement into interface block
+    if ($content =~ /^(?:SUBROUTINE|FUNCTION)$/) {
+      $myhref{pre_insert} = 'INTERFACE' . "\n"; # Insert INTERFACE statement
+      push @$interface_block, \%myhref;
+    }
+
+    # Add USE statement in interface block, if necessary
+    if($myhref{decl} == 4) {
+      $_ = uc $myhref{statement};
+      tr/ \n//d;
+
+      if(/^USE$name,ONLY:(.+)$/) {
+        # USE statement with ONLY, check token to see if it is necessary
+	my @line_tokens = /\b$name\b/g;
+
+	for (@line_tokens) {
+	  if (exists $tokens{$_}) {
+	    push @$interface_block, \%myhref;
+	    last;
+	  }
+	}
+
+      } else {
+        # Always add USE statement without ONLY
+	push @$interface_block, \%myhref;
+      }  
+    }
+
+    if ($myhref{decl} == 1 or $myhref{decl} == 2) {
+      $_ = uc ($myhref{statement});
+      s/\s*!.*$//;
+
+      if ($content eq 'INTEGER' or $content eq 'PARAMETER') {
+        # INTEGER and PARAMETER may be used for dimensioning
+	my @line_tokens = /\b$name\b/g;
+
+	for (@line_tokens) {
+	  if (exists $tokens{$_}) {
+	    push @$interface_block, \%myhref;
+	    last;
+	  }
+	}
+      } else {
+        # Add line only if an argument is present
+	s/$nest_par//g;
+	my @line_tokens = /\b$name\b/g;
+
+	for (@line_tokens) {
+	  if (exists $pu_args{$_}) {
+	    push @$interface_block, \%myhref;
+	    last;
+	  }
+	}
+      }
+    }
+
+    # Add END statement to interface block
+    if ($content =~ /^END\s+(?:SUBROUTINE|FUNCTION)/) {
+      $myhref{post_insert} = 'END INTERFACE' . "\n";
+      push @$interface_block, \%myhref;
+    }
+  }
+
+  # Beautify the interface block
+  for my $href (@$interface_block) {
+    $_ = $href->{statement};
+
+    s/\!.*\n/\n/g; # Remove trailing comments
+    s/ +/ /g;      # Only one space
+    s/\n *\n/\n/g; # Remove empty lines
+    s/\n *\n/\n/g; # Remove empty lines again
+    s/ +\n/\n/g;   # No trailing spaces
+
+    $href->{statement} = $_;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+
+sub change_var_names{
+  my($statements) = @_;
+  foreach my $href (@$statements) {
+    $_=$href->{statement};
+    s/\bVAZX\b/YVAZX/ig;
+    s/\bPVAZX\b/YDVAZX/ig;
+    s/\bVAZG\b/YVAZG/ig;
+    s/\bPVAZG\b/YDVAZG/ig;
+    s/\bSCALP_DV\b/YSCALP/ig;
+    s/\bRSCALP_DV\b/YRSCALP/ig;
+    s/\bSCALPSQRT_DV\b/YSCALPSQRT/ig;
+    s/\bRSCALPSQRT_DV\b/YRSCALPSQRT/ig;
+    s/\bPYBAR\b/YDYBAR/ig;
+    s/\bPSBAR\b/YDSBAR/ig;
+    s/\bVCGLPC\b/YVCGLPC/ig;
+    s/\bVCGLEV\b/YVCGLEV/ig;
+    s/\bSKFROT\b/YSKFROT/ig;
+    s/\bSKFMAT\b/YSKFMAT/ig;
+    s/\bSTATE_VECTOR_4D\b/YSTATE_VECTOR_4D/ig;
+    s/\bVAZX0\b/YVAZX0/ig;
+    s/\bVAZG0\b/YVAZG0/ig;
+    s/\bRSPFORCE\b/YSPFORCE/ig;
+    $href->{statement}=$_;
+  }
+}
+# =========================================================================
+sub remake_arg_decl{
+  my($statements,$prog_info) = @_;
+  my($href,$content,@pu_args,$func,%tokens);
+  my($left,$right,%arghash,$dim);
+  our($nest_par,$name);
+
+  my $dims='';
+# Crack existing dummy declarations, build hash arghash
+  foreach $href (@$statements) {
+    last if($href->{prog_unit} >0);
+    if($href->{content} eq 'SUBROUTINE') {   # Get arguments of subroutine
+      $_=$href->{statement};
+      my $dum=&parse_prog_unit(\$func,\@pu_args);
+#      print Dumper(\@pu_args);
+      for(@pu_args) {
+	$_=uc($_);
+	$arghash{$_}{other}='';
+	$arghash{$_}{dimuse}=0;
+	$arghash{$_}{intent}='';
+	$arghash{$_}{used}=0;
+	$arghash{$_}{set}=0;
+	$arghash{$_}{reallyset}=0;
+	$arghash{$_}{type}='';
+	$arghash{$_}{comment}='';
+	$arghash{$_}{inif}=0;
+      }
+      next;
+    }
+    if($href->{decl} == 2) {
+      $_=$href->{statement};
+      my $comment='';
+      $comment=$1 if(/.*(\!.*)$/);
+      s/\!.*\n/\n/g;                        # Remove trailing comments in all lines
+      $_=uc($_);
+      s/\s//g;
+      if(/^(.+)::(.+)$/){
+	$left=$1;
+	$right=$2;
+	$_=$right;
+	s/$nest_par//g;
+	s/($name)\*\w+/$1/g;
+#	print "XX  $_ \n";
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/) {
+#	    print "ARG $arg $left $_ \n";
+	    $arghash{$arg}{linedec}=$href->{number};
+	    $arghash{$arg}{comment}=$comment;
+	    my @locdec =split ',',$left;
+	    my $i=0;
+	    foreach my $locdec (@locdec) {
+	      if($i == 0) {
+		$arghash{$arg}{type}=$locdec;
+	      }
+	      elsif($locdec=~/\bINTENT/) {
+		$arghash{$arg}{intent}=','.$locdec;
+	      }
+	      else {
+		$arghash{$arg}{other}=$arghash{$arg}{other}.','.$locdec;
+	      }
+	      $i++;
+	    }
+	    if($right=~/\b$arg\b(\*\w+)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b($nest_par\*$nest_par)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b($nest_par\*\w+)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b(\*$nest_par)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b($nest_par)/) {
+	      $dim=$1;
+	    }
+	    else {
+	      $dim='';
+	    }
+	    $arghash{$arg}{dim}=$dim;
+	    $dims=$dims.$dim
+	      }
+	}
+	foreach my $arg (@pu_args) {  # Is arg. used for dimensioning other args?
+	  if($dims=~/\b$arg\b/i) {
+	    $arghash{$arg}{dimuse}=1;
+	  }
+	}  
+      }
+    }
+  }
+  my $insert_line=0;
+  foreach $href (@$statements) {
+    last if($href->{prog_unit} >0);
+    if($href->{decl} == 2 or $href->{content} eq 'PARAMETER') {                 
+      $_=uc($href->{statement});
+      next unless /\bPARAMETER\b/;
+      my @tmpvar=/\b$name\b/g;
+      foreach my $token (@tmpvar) {
+	if($dims=~/\b$token\b/) {
+	  $insert_line=$href->{number};
+	}
+      }
+    }
+  }
+      
+# Gather info to decide INTENT status
+  my $inif=0;
+  my @inif_stack=();
+  my $cur_inif=0;
+  foreach $href (@$statements) {
+    last if($href->{prog_unit} >0);
+    if($href->{exec}) {
+      if($href->{content} eq 'ENDIF') {
+	$inif--;
+	$cur_inif=pop @inif_stack;
+	next;
+      }
+      elsif($href->{content} eq 'ELSEIF' or $href->{content} eq 'ELSE') {
+	$cur_inif=pop @inif_stack;
+	$cur_inif=$href->{number};
+	push @inif_stack,$cur_inif;
+      }
+      my ($left,$right);
+      $_=$href->{statement};
+      s/\!.*\n/\n/g;                        # Remove trailing comments in all lines
+      my %setnow=();
+      foreach my $arg (@pu_args) {
+	$setnow{$arg}=0;
+	$setnow{$arg}=1 if($arghash{$arg}{reallyset});
+	unless ($setnow{$arg}) {
+	  foreach my $xx (@inif_stack) {
+	    $setnow{$arg}=1 if($xx == $arghash{$arg}{inif});
+	  }
+	}
+      }
+      
+      if($href->{content} eq 'scal_assign' or $href->{content} eq 'array_assign') {
+	s/\s//g;
+	($left,$right)=/^(.+)=(.+)$/;
+	$_=$right;
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+	$_=$left;
+	if(/($nest_par)/) {
+	  $_=$1;
+	  foreach my $arg (@pu_args) {
+	    if(/\b$arg\b/i) {
+	      $arghash{$arg}{used}=1 unless $setnow{$arg};
+	    }
+	  }
+	}
+	$_=$left;
+	foreach my $arg (@pu_args) {
+	  if(/^$arg\b/i) {
+	    $arghash{$arg}{set}=1;
+	    $arghash{$arg}{inif}=$cur_inif;
+	    $arghash{$arg}{reallyset}=1 unless($inif);
+	  }
+	}
+      }
+      elsif($href->{content} eq 'IF' ) {
+	if($href->{content2} eq 'scal_assign' or $href->{content2} eq 'array_assign' or 
+	   $href->{content2} eq 'CALL') {
+	  s/\n//g;
+	  ($left,$right)=/^\s*(IF\b\s*$nest_par)(.+)/i;
+	  $_=$left;
+	  foreach my $arg (@pu_args) {
+	    if(/\b$arg\b/i) {
+	      $arghash{$arg}{used}=1 unless $setnow{$arg};
+	    }
+	  }
+	  $_=$right;
+	  if($href->{content2} eq 'CALL') {
+	    my $statement=$right;
+	    my $inifx=1;
+	    &propag_arg(\$statement,\%arghash,\$inifx,\%setnow);
+	  }
+	  else {
+	    s/\s//g;
+	    ($left,$right)=/^(.+)=(.+)$/;
+	    $_=$right;
+	    foreach my $arg (@pu_args) {
+	      if(/\b$arg\b/i) {
+		$arghash{$arg}{used}=1 unless $setnow{$arg};
+	      }
+	    }
+	    $_=$left;
+	    if(/($nest_par)/) {
+	      $_=$1;
+	      foreach my $arg (@pu_args) {
+		if(/\b$arg\b/i) {
+		  $arghash{$arg}{used}=1 unless $setnow{$arg};
+		}
+	      }
+	    }
+	    $_=$left;
+	    foreach my $arg (@pu_args) {
+	      if(/^$arg\b/i) {
+		$arghash{$arg}{inif}=$cur_inif;
+		$arghash{$arg}{set}=1;
+	      }
+	    }
+	  }
+	}
+	else {
+	  foreach my $arg (@pu_args) {
+	    if(/\b$arg\b/i) {
+	      $arghash{$arg}{used}=1 unless $setnow{$arg};
+	    }
+	  }
+	}
+      }
+      elsif($href->{content} eq 'WHERE' ) {
+	s/\s//g;
+	($left,$right)=/^(WHERE$nest_par)(.+)/i;
+	$_=$left;
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+	$_=$right;
+	($left,$right)=/^(.+)=(.+)$/;
+	$_=$right;
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+	$_=$left;
+	foreach my $arg (@pu_args) {
+	  if(/^$arg\b/i) {
+	    $arghash{$arg}{inif}=$cur_inif;
+	    $arghash{$arg}{set}=1;
+	  }
+	}
+      }
+      elsif($href->{content} eq 'CALL') {
+	my $statement=$_;
+	&propag_arg(\$statement,\%arghash,\$inif);
+      }
+      else{
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+      }
+      if($href->{content} eq 'IF_construct') {
+	$inif++;
+	$cur_inif=$href->{number};
+	push @inif_stack,$cur_inif;
+      }
+    }	  
+  }
+
+# Create INTENT statemant based on gathered info
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      if($arghash{$arg}{nointent}) {
+	unless($arghash{$arg}{intent}) {
+	  $arghash{$arg}{intent}=' ';
+	  $arghash{$arg}{comment}='! UNDETERMINED INTENT';
+	}
+      }
+      else{
+	my $intent='';
+	$intent='IN' if($arghash{$arg}{used} or $arghash{$arg}{dimuse});
+	$intent=$intent.'OUT' if($arghash{$arg}{set});
+	if($intent) {
+	  if($arghash{$arg}{intent} and $intent eq 'OUT') {
+	    $intent='INOUT' if $arghash{$arg}{intent}=~/INOUT/i;
+	  }
+	  $arghash{$arg}{intent}=',INTENT('.$intent.')';
+	}
+	else {
+	  $arghash{$arg}{intent}=' ';
+	  $arghash{$arg}{comment}='! Argument NOT used';
+	}
+      }
+    }
+  }
+
+# Remove existing argument declarations
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      $_=$$statements[$arghash{$arg}{linedec}]->{statement};
+      #   print "BEFORE $arg $_";
+      if(/.*::\s*\b$arg\b\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*$nest_par\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*\*\s*\w+\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*\*\s*$nest_par\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*$nest_par\s*\*\s*\w+\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*$nest_par\s*\*\s*$nest_par\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      else{
+	/^(.*::)(.*)$/s;
+	my $left=$1;
+	$_=$2;
+	s/\b$arg\b\s*$nest_par//i;
+	s/\b$arg\b\s*\*\s*\w+//i;
+	s/\b$arg\b\s*\*\s*$nest_par//i;
+	s/\b$arg\b//i;
+	s/,\s*,/,/;
+	s/,(\s*)$/$1/;
+	s/\n\s*\n/\n/g;
+	$_=$left.$_;
+	s/::\s*,/::/;
+      }
+ #   print "AFTER $arg $_\n";
+      $$statements[$arghash{$arg}{linedec}]->{statement}=$_; 
+    }
+  }
+
+ # Write out
+
+  my $newdecl='';
+  my $linedec;
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      if($arghash{$arg}{other} and ! $arghash{$arg}{dim}) {
+	$arghash{$arg}{other}=~s/\s//g;
+	if($arghash{$arg}{other}=~/^,DIMENSION($nest_par)$/i) {
+	  $arghash{$arg}{other}='';
+	  $arghash{$arg}{dim}=$1;
+	}
+      }
+      if($arghash{$arg}{dimuse}) { # Put declerations of args first
+	$linedec=sprintf "%-18s%s%-14s%s%s%s%s %s",
+	$arghash{$arg}{type},$arghash{$arg}{other},$arghash{$arg}{intent},
+	    ' :: ',$arg,$arghash{$arg}{dim},$arghash{$arg}{comment},"\n";
+	$newdecl=$newdecl.$linedec;
+      }
+    }
+  }
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      unless($arghash{$arg}{dimuse}) {
+	$linedec=sprintf "%-18s%s%-14s%s%s%s %s%s",
+	$arghash{$arg}{type},$arghash{$arg}{other},$arghash{$arg}{intent},
+	    ' :: ',$arg,$arghash{$arg}{dim},$arghash{$arg}{comment},"\n";
+	$newdecl=$newdecl.$linedec;
+      }
+    }
+  }
+#  print "INSERT_LINE $insert_line \n";
+  if($insert_line) {
+    $$statements[$insert_line]->{post_insert}=$newdecl;
+  }
+  else{
+    foreach $href (@$statements) {
+      if($href->{decl} == 2) {                 
+	$href->{pre_insert}=$newdecl;
+	last;
+      }
+    }
+  }
+
+#  print $newdecl;
+#  print Dumper(\%arghash);
+}
+
+sub propag_arg{
+  my ($statement,$arghash,$inif,$setnow) = @_;
+  our ($name,$nest_par);
+  my (%argpos);
+  $_=$$statement;
+  s/^\s*CALL\s+($name)//i;
+  my $called=lc($1);
+  s/\s//g;
+  s/^\((.*)\)$/$1/s;
+  my @inpars=/$nest_par/g;
+  s/$nest_par//g;
+  s/($name)%$name/$1/g;
+  $_=uc($_);
+#  print "PROPAG $called $_ ££ @inpars \n";
+  my @call_args=split ',' , $_;
+  my $i=0;
+  my $interesting=0;
+  %argpos=();
+  foreach my $call (@call_args) {
+    
+#    print "CALL $called $call \n" ;
+    if($call=~/(.+)=(.+)/) {
+      $call=$2; #This just by-passes the problem
+    }
+    if(exists $$arghash{$call}) {
+      if(exists $argpos{$call}) {
+	push @{$argpos{$call}},$i;
+      }
+      else {
+	my @i=($i);
+	$argpos{$call}=[@i];
+      }
+      $interesting=1;
+    }
+    $i++;
+  }
+  if($interesting) {
+    my $fname='/tmp/intblocks/'.$called.'.intfb.h';
+    if( -f $fname ) {
+      my @dumargs=();
+      my $unit_name;
+      print "FILE $fname FOUND \n";
+      my @lines = &readfile($fname);
+      my @loc_statements=(); 
+      &expcont(\@lines,\@loc_statements);
+      foreach my $href (@loc_statements) {
+	$_=$href->{statement};
+	if(/^\s*SUBROUTINE/i) {
+	  my $dum=&parse_prog_unit(\$unit_name,\@dumargs);
+	  next;
+	}
+	if(/::/) {
+	  s/\s//g;
+	  foreach my $arg (keys (%argpos)) {
+	    my $set_before=$$setnow{$arg};
+	    foreach my $i (@{$argpos{$arg}}){
+	      if(/::$dumargs[$i]/) {
+		if(/INTENT\(IN\)/i) {
+		  $$arghash{$arg}{used}=1 unless $set_before;
+		}
+		elsif(/INTENT\(OUT\)/i) {
+		  $$arghash{$arg}{set}=1;
+		  $$setnow{$arg}=1 unless($$inif);
+		}
+		elsif(/INTENT\(INOUT\)/i) {
+		  $$arghash{$arg}{set}=1;
+		  $$arghash{$arg}{used}=1 unless $set_before;;
+		  $$arghash{$arg}{reallyset}=1 unless($$inif);
+		}
+		elsif(/\! UNDETERMINED INTENT/) {
+		  $$arghash{$arg}{nointent}=1;
+		}
+	      }
+	    }
+	  }
+	}
+      }
+    }
+    else {
+      foreach my $arg (keys (%argpos)) {
+	$$arghash{$arg}{nointent}=1;
+      }
+    }
+  }
+  for (@inpars) {
+    foreach my $arg (keys (%$arghash)) {
+      if(exists $$arghash{$arg}) {
+	if(/\b$arg\b/i) {
+	  $$arghash{$arg}{used}=1 unless $$setnow{$arg};
+	}
+      }
+    }
+  }
+}
+  
+sub add_interface_blocks {
+# Add interface block for called routines
+  use File::Find;
+  my($statements,$prog_info) = @_;
+  my($href,$call);
+  our($name,$nest_par);
+  our(@call_names,@call_names_found,%call_names);
+
+  return unless ($$prog_info{no_calls}); # Skip if there are no calls
+  @call_names=();
+  %call_names=();
+
+  my $last_decl=0;
+  my $in_intfblk=0;
+  my %already_in=();
+  ST:foreach $href (@$statements) {
+    last if($href->{prog_unit} > 0);  # Only consider first program unit (no contains)
+    if($href->{content} eq 'INTERFACE') {
+      $in_intfblk=1;
+      next;
+    }
+    if($href->{content} eq 'END INTERFACE') {
+      $in_intfblk=0;
+      next;
+    }
+    if($in_intfblk) {
+      $_=$href->{statement};
+      s/\#include\s*\"(\w+)\.h\"\s*$/$1/;
+      $_=lc($_);
+      $already_in{$_}++;
+      next;
+    }
+    
+# Find last declaration
+    if($href->{decl}) {
+      next if($href->{content} eq 'FORMAT');
+      next if($href->{content} eq 'DATA');
+      $last_decl = $href->{number} ;
+    }
+# Find calls
+    next unless($href->{exec});
+    if($href->{content} eq 'CALL' or 
+       (exists  $href->{content2} and$ href->{content2} eq 'CALL') ) {
+      $_=$href->{statement};
+      /\s*\bCALL\b\s*($name)/i;
+      my $call=lc($1);
+      next if($already_in{$call}); # Exclude already existing interface block
+      next if($call eq 'packmsg'); # A couple of special exceptions
+      next if($call eq 'unpkmsg');
+      $call_names{$call}++;
+    }
+  }
+  
+
+# Check that routine exists in IFS
+  @call_names_found=();
+  find(\&calls_wanted,'/tmp/27/ifs/');
+#  find(\&calls_wanted,'/home/mats/work/cy28/ifs/');
+#  find(\&calls_wanted,'/tmp/27/trans/');
+  @call_names_found=sort(@call_names_found);
+#  print "P2 @call_names_found \n";
+  @call_names=@call_names_found;
+
+# Contruct include block
+  my $block='';
+  for (@call_names) {
+    $block=$block.'#include "'.$_.'.intfb.h"'."\n";
+  }
+#  print $block;
+
+  my $clean=0;
+  if(@call_names) {
+    if($$prog_info{has_interface_block}) {
+      foreach $href (@$statements) {
+# Add interface block to routine that already has INTERFACE statement
+	if($href->{content} eq 'END INTERFACE'){
+	  if($href->{post_insert}) {
+	    $href->{post_insert}=$href->{post_insert}."\n".$block;
+	  }
+	  else {
+	    $href->{post_insert}="\n".$block;
+	  }	    
+	  last;
+	}
+      }
+    }
+# Add interface block to routine that does not have previous INTERFACE statement
+    else {
+      $href=@$statements[$last_decl];
+      if($href->{post_insert}) {
+	$href->{post_insert}=$href->{post_insert}."\n".$block;
+      }
+      else {
+	$href->{post_insert}="\n".$block;
+      }	    
+    }
+# Remove from EXTERNAL statement where interface block has been added
+    foreach $href (@$statements) {
+      if($href->{content} eq 'EXTERNAL') {
+	$_=$href->{statement};
+	foreach my $ext (@call_names) {
+	  s/\b$ext\b//i;
+	}
+	s/,\s*,/,/g;
+	s/^(\s*EXTERNAL\s*),/$1/i;
+	s/^(\s*EXTERNAL.*),\s*$/$1/i;
+	s/^\s*EXTERNAL\s*,*\s*$//i;
+	$href->{statement}=$_;	
+      }
+    }
+  }
+}
+#======================================================================================
+sub calls_wanted {
+  # Used by Find as called from add_interface_blocks
+  our(%call_names,@call_names_found);
+  return unless (/^(\w+)\.F90$/);
+  my $call=$1;
+  if($call_names{$call}) {
+    push(@call_names_found,$call);
+  }    
+}
+sub remove_some_comments{
+  my($statements) = @_;
+  my $prev_empty=0;
+  foreach my $href (@$statements) {
+    if($href->{content} eq 'comment'){
+      $_=$href->{statement};
+      if(/^\s*$/) {
+	if($prev_empty) {
+	  s/\s*//;
+	  $href->{statement}=$_;
+	}
+	else {
+	  $prev_empty=1;
+	} 
+	next;
+      }
+      $prev_empty=0;
+      s/^\s*![\s\*]*\bLOCAL\s+(INTEGER|REAL|LOGICAL|CHARACTER)\s+(SCALARS|ARRAYS).*\n$//i;
+      s/^\s*![\s\*]*\bDUMMY\s+(INTEGER|REAL|LOGICAL|CHARACTER)\s+(SCALARS|ARRAYS).*\n$//i;
+      s/^\s*![\s\*]*\bLOCAL\s+(INTEGER|REAL|LOGICAL|CHARACTER).*\n$//i;
+      s/^\s*![\s\*]*\bDUMMY\b\s*$//i;
+      s/^\s*![\s\*]*\bLOCAL\b\s*$//i;
+      s/^\s*![\s\*]*\bLOCAL\b:\s*$//i;
+      s/^\s*![\s\*]*\bLOCAL ARRAYS\b[\s\*]*$//i;
+      s/^\s*![\s\*]*\bLOCAL SCALARS\b\s*$//i;
+      s/^\s*![\s\*]*\s*\d\.\d+\s*\bLOCAL ARRAYS\b\s*$//i;
+      s/^\s*![\s\*]*\s*=== LOCAL ARRAYS ===\s*$//i;
+      $href->{statement}=$_;
+    }
+    else {
+      $prev_empty=0;
+    }
+  }
+}      
+sub get_calls_inc {
+  my($statements,$calls,$intfb) = @_;
+  foreach my $href (@$statements) {
+    if($href->{content} eq 'CALL') {
+      $_=$href->{statement};
+      /^\s*CALL\s+([A-Z]\w*)/i;
+      $$calls{lc($1)}++;
+    }
+    elsif($href->{content} eq 'IF') {
+      if($href->{content2} eq 'CALL') {
+	$_=$href->{statement};
+	/\bCALL\s+([A-Z]\w*)/i;
+	$$calls{lc($1)}++;
+      }
+    }
+    elsif($href->{content} eq 'include') {
+      $_=$href->{statement};
+      $$intfb{$1}=1 if(/["](\S+)\.intfb\.h["]/);
+      $$intfb{$1}=2 if(/["](\S+)\.h["]/); # For old-style interface blocks
+    }
+  }
+}
+
+1;
+      
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Build.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Build.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Build.pm	(revision 329)
@@ -0,0 +1,2302 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Build
+#
+# DESCRIPTION
+#   The main purpose of this class is to process the build configuration,
+#   generate the required files for the build and invoke make to create the
+#   build.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Build;
+
+# Standard pragma
+use strict;
+use warnings;
+
+# Standard modules
+use Carp;
+use Cwd;
+use File::Basename;
+use File::Path;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::CfgFile;
+use Fcm::SrcPackage;
+use Fcm::BuildTask;
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld = Fcm::Build->new (
+#     CONFIG  => $config,
+#     CFG_SRC => $cfg_src,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Build class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   CFG_SRC    - source path to the build configuration file
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $cfg    = exists $args{CFG_SRC} ? $args{CFG_SRC} : undef;
+  my $config = exists $args{CONFIG}  ? $args{CONFIG}  : &main::cfg;
+
+  my $self  = {
+    CONFIG   => $config,            # configuration settings
+    CFG      => Fcm::CfgFile->new ( # bld cfg
+      TYPE   => 'bld',              # config file type
+      SRC    => $cfg,               # source path of the bld cfg
+      CONFIG => $config,            # configuration settings
+    ),
+    NAME     => '',                 # name of this build
+    DIR      => {                   # directory tree of this build
+      ROOT    => '',                # root directory of this build
+    },
+    PATH     => {},                 # search paths of this build
+    SEARCH   => 1,                  # search for source directories in src/?
+    SRCDIR   => {},                 # source directories of this build
+    PP       => {},                 # pre-process flags
+    PACKAGE  => {},                 # source directory packages of this build
+    TARGET   => [],                 # targets of this build
+    USE      => [],                 # list of inherited builds
+    INHERIT  => {                   # inheritance flags
+      SRCDIR => 1,                  # inherit source directories?
+      PP     => 1,                  # inherit pre-process flags?
+      TARGET => 0,                  # inherit targets?
+    },
+    LIB      => {'' => ''},         # name of libraries
+    LOCK     => undef,              # lock file
+  };
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->DESTROY;
+#
+# DESCRIPTION
+#   This method is called automatically when a Fcm::Build object is
+#   destroyed.
+# ------------------------------------------------------------------------------
+
+sub DESTROY {
+  my $self = shift;
+
+  # Remove the lock if it is set
+  unlink $self->{LOCK} if $self->{LOCK} and -e $self->{LOCK};
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $bld->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = $bld->cfg;
+#
+# DESCRIPTION
+#   This method returns a reference to a Fcm::CfgFile instance for the build
+#   configuration file.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  my $self = shift;
+
+  return $self->{CFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %allpcks = $bld->allpcks ();
+#
+# DESCRIPTION
+#   This method returns a hash table with keys representing all the packages
+#   declared in the current build. The value of each element in the hash is a
+#   reference to a list of children of the current package.
+# ------------------------------------------------------------------------------
+
+sub allpcks {
+  my $self        = shift;
+  my %allpcks = ();
+
+  for my $pckname (keys %{ $self->{PACKAGE} }) {
+    $allpcks{$pckname} = [];
+  }
+
+  for my $pckname (keys %{ $self->{PACKAGE} }) {
+    my @names = split /__/, $pckname;
+
+    my $cur = $pckname;
+    while ($cur) {
+      pop @names;
+      my $depend = @names ? join '__', @names : '';
+      $allpcks{$depend} = [] unless exists $allpcks{$depend};
+
+      push @{ $allpcks{$depend} }, $cur
+        unless grep {$_ eq $cur} @{ $allpcks{$depend} };
+
+      $cur = $depend;
+    }
+  }
+
+  return %allpcks;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $bld->build (
+#     [ARCHIVE     => $archive,]
+#     [FULL        => $full,]
+#     [IGNORE_LOCK => $ignore_lock,]
+#     [JOBS        => $jobs,]
+#     [STAGE       => $stage,]
+#     [TARGETS     => \@targets,]
+#   );
+#
+# DESCRIPTION
+#   This method performs a build based on the current configuration. The
+#   method returns 1 on success.
+#
+# ARGUMENTS
+#   ARCHIVE      - If set to "true", invoke the "archive" mode. Most build files
+#                  and directories created by this build will be archived using
+#                  the "tar" command. If not set, the default is not to invoke
+#                  the "archive" mode.
+#   FULL         - If set to "true", invoke the build in "full" mode. Build files
+#                  and directories created by previous builds in the same
+#                  location will be removed before the current build is
+#                  performed. If not set, the default is to perform the build
+#                  in "incremental" mode.
+#   IGNORE_LOCK  - If set to "true", it ignores any lock files that may exist in
+#                  the build root directory. 
+#   JOBS         - Specify number of jobs that can be handled by "make". If set,
+#                  the value must be a natural integer. If not set, the default
+#                  value is 1 (i.e. run "make" in serial mode).
+#   STAGE        - If set, it should be an integer number or a recognised
+#                  keyword or abbreviation. If set, the build is performed up
+#                  to the named stage. If not set, the default is to perform
+#                  all stages of the build. Allowed values are:
+#                  1, setup or s
+#                  2, pre_process or pp
+#                  3, generate_dependency or gd
+#                  4, generate_interface or gi
+#                  5, all, a, make or m
+#   TARGETS      - Specify targets to be built. If set, these targets will be
+#                  built instead of the ones specified in the build
+#                  configuration file.
+# ------------------------------------------------------------------------------
+
+sub build {
+  my $self = shift;
+  my %args = @_;
+
+  # Process arguments
+  my $archive     = exists $args{ARCHIVE}     ? $args{ARCHIVE}     : 0;
+  my $full        = exists $args{FULL}        ? $args{FULL}        : 0;
+  my $ignore_lock = exists $args{IGNORE_LOCK} ? $args{IGNORE_LOCK} : 0;
+  my $jobs        = exists $args{JOBS}        ? $args{JOBS}        : 1;
+  my $stage       = exists $args{STAGE}       ? $args{STAGE}       : 5;
+  my $targets     = exists $args{TARGETS}     ? $args{TARGETS}     : [qw/all/];
+
+  # Resolve named stages
+  $stage = 5 unless $stage;
+  if ($stage !~ /^\d$/) {
+    my %stagenames = (
+      'S(?:ETUP)?'                      => 1,
+      'P(?:RE)?_?P(?:ROCESS)?'          => 2,
+      'G(?:ENERATE)?_?D(?:ENPENDENCY)?' => 3,
+      'G(?:ENERATE)?_?I(?:NTERFACE)?'   => 4,
+      '(?:A(?:LL)|M(?:AKE)?)'           => 5,
+    );
+
+    for my $name (keys %stagenames) {
+      if ($stage =~ /$name/i) {
+        $stage = $stagenames{$name};
+        last;
+      }
+    }
+
+    if ($stage !~ /^\d$/) {
+      w_report 'Warning: invalid build stage: ', $stage, ', default to "5"';
+      $stage = 5;
+    }
+  }
+
+  # Get verbose mode
+  my $verbose = $self->config->verbose;
+
+  # Stage 1: setup
+  my $date = localtime;
+  print 'Build command started on ', $date, '.', "\n" if $verbose;
+  my $otime = time;
+
+  print '->Setup              : start', "\n" if $verbose;
+  my $stime = time;
+
+  # Read configurations
+  my $rc = $self->decipher_cfg;
+
+  # Check directories are set
+  $rc = $self->check_dir if $rc;
+
+  # Check for lock files
+  $rc = $self->check_lock if $rc and not $ignore_lock;
+
+  # Set a lock file
+  $rc = $self->_set_lock if $rc;
+
+  # Create build root directory if necessary
+  $rc = $self->_create_build_dir if $rc;
+
+  # Set up inheritance and update cache information if necessary
+  $rc = $self->_update_bld_info (FULL => $full) if $rc;
+
+  my $ftime = time;
+  my $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+  print '->Setup              : ', $ftime - $stime, ' ', $s_str, "\n";
+
+  # Stage 2: Pre-process
+  if ($rc and $stage >= 2) {
+    print '->Pre-process        : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_pre_process;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Pre-process        : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  # Stage 3: Scan dependency and write make rules
+  if ($rc and $stage >= 3) {
+    print '->Scan dependency    : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_scan_dependency;
+    $rc = $self->_write_makefile if $rc;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Scan dependency    : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  # Stage 4: Generate Fortran 9x interface block
+  if ($rc and $stage >= 4) {
+    print '->Generate interface : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_generate_f9x_interface;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Generate interface : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  # Stage 5: Make the build
+  if ($rc and $stage >= 5) {
+    print '->Make               : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_invoke_make (
+      TARGETS => $targets,
+      JOBS    => $jobs,
+      ARCHIVE => $archive,
+    );
+
+    # Remove empty build directories
+    $rc = $self->_remove_empty_dirs () if $rc;
+
+    # Create TAR archives if necessary
+    $rc = $self->_tar_build_dirs () if $rc and $archive;
+
+    # Create run time environment script if necessary
+    $rc = $self->_create_runenv_script () if $rc;
+
+    # Create exclude dependency configurations for libraries
+    $rc = $self->_create_lib_excl_dep () if $rc;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Make               : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  if ($verbose) {
+    $s_str = $ftime - $otime > 1 ? 'seconds' : 'second';
+    print '->TOTAL              : ', $ftime - $otime, ' ', $s_str, "\n";
+  }
+
+  $date = localtime;
+  if ($rc) {
+    print 'Build command finished on ', $date, '.', "\n" if $verbose;
+
+  } else {
+    e_report 'Build command failed on ', $date, '.';
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld->decipher_cfg ();
+#
+# DESCRIPTION
+#   This method deciphers the build configuration file and assigns the
+#   configurations to the variables of the current build.
+# ------------------------------------------------------------------------------
+
+sub decipher_cfg {
+  my $self = shift;
+
+  my $read = $self->cfg->read_cfg;
+
+  # Check config file type
+  if ($read) {
+    if ($self->cfg->type ne 'bld') {
+      w_report 'Error: ', $self->cfg->src, ': not a build config file.';
+      return;
+    }
+
+  } else {
+    return;
+  }
+
+  my %cfg_label = %{ $self->config->setting ('CFG_LABEL') };
+
+  # Get lines from cfg file
+  my @cfg_lines  = $self->cfg->lines;
+
+  LINE: for my $line (@cfg_lines) {
+    # Label and value of each line
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next LINE unless $label; # ignore blank or comment line
+
+    # Strip out BLD prefix from all labels
+    my $prefix = $cfg_label{BDECLARE} . '::';
+    $label = substr ($label, length ($prefix))
+      if index (uc ($label), $prefix) == 0;
+
+    next LINE unless $label; # ignore blank or comment line
+
+    # Configuration file type/version, ignore
+    next LINE if uc $label eq $cfg_label{CFGFILE}{TYPE};
+    next LINE if uc $label eq $cfg_label{CFGFILE}{VERSION};
+
+    # User variable, ignore
+    next LINE if index (uc ($label), '%') == 0;
+
+    # Build name
+    if (uc $label eq $cfg_label{NAME}) {
+      $self->{NAME} = $value;
+      next LINE;
+    }
+
+    # Build directory tree
+    $prefix = $cfg_label{DIR} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr uc ($label), length ($prefix);
+      $self->{DIR}{$name} = expand_tilde $value;
+      next LINE;
+    }
+
+    # Source directory
+    $prefix = $cfg_label{SRCDIR} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr $label, length ($prefix);
+      $name    =~ s/::/__/g;
+      $self->{SRCDIR}{$name} = expand_tilde $value;
+      next LINE;
+    }
+
+    # Automatic source directory search?
+    if (uc $label eq $cfg_label{SEARCH_SRC}) {
+      $self->{SEARCH} = $value;
+      next LINE;
+    }
+
+    # Pre-process flag, directory/file requires pre-processing before all tasks
+    $prefix = $cfg_label{PP};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      my $name = uc shift @flds;
+      $name    = join '__', ($name, @flds) if @flds;
+      $self->{PP}{$name} = $value;
+      next LINE;
+    }
+
+    # Specify name of top level or package library
+    $prefix = $cfg_label{LIB};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      shift @flds;
+      my $name = @flds ? join ('__', @flds) : '';
+      $self->{LIB}{$name} = $value;
+
+      next LINE;
+    }
+
+    # Specify extra executable dependencies and BLOCKDATA dependency
+    for my $name (qw/EXE_DEP BLOCKDATA/) {
+      $prefix = $cfg_label{$name};
+
+      if (index (uc ($label), $prefix) == 0) {
+        my @flds = split /::/, $label;
+        shift @flds;
+        my $target = @flds ? $flds[0] : '';
+        my @deps   = split /\s+/, $value;
+
+        # If $value is a null string, set executable to depend on all objects
+        if (not @deps) {
+          if ($name eq 'BLOCKDATA') {
+
+            # Label not recognised
+            w_report 'Warning: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+                     ': "', $label, '" declaration must have a value';
+            next LINE;
+
+          } else {
+            push @deps, '';
+          }
+        }
+
+        for my $dep (@deps) {
+          $dep =~ s/::/__/g;
+
+          $self->config->assign_setting (
+            LABELS => [$name, $target, $dep],
+            VALUE  => 1,
+          );
+        }
+
+        next LINE;
+      }
+    }
+
+    # Build target
+    if (uc $label eq $cfg_label{TARGET}) {
+      push @{ $self->{TARGET} }, split (/\s+/, $value);
+      next LINE;
+    }
+
+    # Rename a main program target
+    $prefix = $cfg_label{EXE_NAME};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      shift @flds;
+      my $name = shift @flds;
+
+      if ($name and $value) {
+        $self->config->assign_setting (
+          LABELS => ['EXE_NAME', $name],
+          VALUE  => $value,
+        );
+
+        next LINE;
+      }
+    }
+
+    # Build tool
+    $prefix = $cfg_label{TOOL} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr $label, length ($prefix);
+      my @flds = split /::/, $name;
+
+      $name = uc (shift @flds);
+      $name = join '__', ($name, @flds) if @flds;
+
+      $self->config->assign_setting (
+        LABELS => ['TOOL', $name],
+        VALUE  => $value,
+      );
+      next LINE;
+    }
+
+    # File name extension and type
+    for my $name (qw/INFILE_EXT OUTFILE_EXT/) {
+      $prefix = $cfg_label{$name};
+      if (index (uc ($label), $prefix) == 0) {
+        my $key = (split /::/, $label)[1];
+        $key    = uc $key if $name eq 'OUTFILE_EXT';
+
+        my $val = ($name eq 'INFILE_EXT') ? uc $value : $value;
+
+        $self->config->assign_setting (
+          LABELS => [$name, $key],
+          VALUE  => $val,
+        );
+        next LINE;
+      }
+    }
+
+    # Dependency scan exclusion
+    $prefix = $cfg_label{EXCL_DEP};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      shift @flds;
+
+      my $pk = @flds ? join ('__', @flds) : '';
+      $self->config->assign_setting (
+        LABELS => ['EXCL_DEP', uc ($value), $pk],
+        VALUE  => 1,
+      );
+      next LINE;
+    }
+
+    # Use (inherit from) another build
+    if (uc $label eq $cfg_label{USE}) {
+      my $use = Fcm::Build->new (
+        CONFIG  => $self->config,
+        CFG_SRC => expand_tilde ($value),
+      );
+      $use->decipher_cfg;
+      $use->check_dir;
+      push @{ $self->{USE} }, $use;
+      next LINE;
+    }
+
+    # Inheritance flag
+    $prefix = $cfg_label{INHERIT} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr $label, length ($prefix);
+      my @flds = split /::/, $name;
+
+      $name = uc (shift @flds);
+
+      for my $flag (qw/SRCDIR PP LIB TARGET/) {
+        if ($name eq $cfg_label{$flag}) {
+          $name = @flds ? join ('__', ($flag, @flds)) : $flag;
+          $self->{INHERIT}{$name} = $value;
+          next LINE;
+        }
+      }
+    }
+
+    # Label not recognised
+    w_report 'ERROR: ', $line->{SRC}, ': LINE ', $line->{NUMBER}, ': label "',
+             $label, '" not recognised';
+    return;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld->check_dir ();
+#
+# DESCRIPTION
+#   This method checks whether the build directories are set correctly.
+# ------------------------------------------------------------------------------
+
+sub check_dir {
+  my $self = shift;
+
+  # Make sure build root directory is set
+  if (not $self->{DIR}{ROOT}) {
+    w_report 'Error: build root directory not set.';
+    return;
+  }
+
+  # Set value of build sub-directories if necessary
+  for my $name (keys %{ $self->config->setting ('DIR') }) {
+    next if $self->{DIR}{$name};
+
+    $self->{DIR}{$name} = catfile (
+      $self->{DIR}{ROOT},
+      $self->config->setting ('DIR', $name),
+    );
+  }
+
+  # Search src/ sub-directory if necessary
+  if ($self->{SEARCH} and -d $self->{DIR}{SRC}) {
+    my %dir = find_srcdir ($self->{DIR}{SRC});
+    for my $name (keys %dir) {
+      $self->{SRCDIR}{$name} = $dir{$name} unless $self->{SRCDIR}{$name};
+    }
+  }
+
+  # Expand source directory paths if necessary
+  for my $name (keys %{ $self->{SRCDIR} }) {
+    if ($self->{SRCDIR}{$name} =~ /^\w/) {
+      my $src_search  = catfile $self->{DIR}{SRC} , $self->{SRCDIR}{$name};
+      my $root_search = catfile $self->{DIR}{ROOT}, $self->{SRCDIR}{$name};
+
+      if ($self->{DIR}{SRC} and -d $src_search) {
+        $self->{SRCDIR}{$name} = $src_search;
+
+      } elsif (-d $root_search) {
+        $self->{SRCDIR}{$name} = $root_search;
+
+      } else {
+        w_report 'Warning: cannot locate declared source directory: ',
+                 $self->{SRCDIR}{$name};
+        next;
+      }
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld->check_lock ();
+#
+# DESCRIPTION
+#   This method checks whether a lock is set in the current build.
+# ------------------------------------------------------------------------------
+
+sub check_lock {
+  my $self = shift;
+
+  my $rootdir  = $self->{DIR}{ROOT};
+  my $lock_ext = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_EXT/));
+  my $lock_bld = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_BLD/));
+
+  # Always throw error if extract lock exists
+  if (-e $lock_ext) {
+    w_report 'ERROR: extract lock file exists: ', $lock_ext, ',';
+    w_report '       an extract may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Always throw error if build lock exists
+  if (-e $lock_bld) {
+    w_report 'ERROR: build lock file exists: ', $lock_bld, ',';
+    w_report '       a build may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Check locks in inherited build
+  for my $use (@{ $self->{USE} }) {
+    return unless $use->check_lock;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_set_lock ();
+#
+# DESCRIPTION
+#   This method sets a lock is set in the current build.
+# ------------------------------------------------------------------------------
+
+sub _set_lock {
+  my $self = shift;
+
+  $self->{LOCK} = catfile (
+    $self->{DIR}{ROOT}, $self->config->setting (qw/MISC LOCK_BLD/),
+  );
+
+  &touch_file ($self->{LOCK});
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_bld_info (FULL => $full);
+#
+# DESCRIPTION
+#   This internal method updates the inheritance relationship for source
+#   directories, tools, and targets. If FULL is set, remove all sub-directories
+#   created by previous builds.
+# ------------------------------------------------------------------------------
+
+sub _update_bld_info {
+  my $self = shift;
+  my %args = @_;
+
+  my $full = exists $args{FULL} ? $args{FULL} : 0;
+
+  my $tar      = $self->config->setting (qw/OUTFILE_EXT TAR/);
+  my @tar_dirs = split /,/, $self->config->setting (qw/TAR_DIRS/);
+  my $verbose  = $self->config->verbose;
+
+  if ($full) {
+    # Remove sub-directories/archives created from previous builds
+    for my $name (qw/BIN BLD CACHE DONE ETC FLAGS INC LIB PPSRC OBJ TMP/) {
+      &run_command ([qw/rm -rf/, $self->{DIR}{$name}], PRINT => $verbose)
+        if -d $self->{DIR}{$name};
+
+      &run_command ([qw/rm -f/, $self->{DIR}{$name} . $tar], PRINT => $verbose)
+        if -f $self->{DIR}{$name} . $tar;
+    }
+
+  } else {
+    # Extract archives if necessary
+    for my $name (@tar_dirs) {
+      my $tar_file = $self->{DIR}{$name} . $tar;
+
+      if (-f $tar_file) {
+        &run_command ([qw/tar -x -f/, $tar_file], PRINT => $verbose > 1);
+        &run_command ([qw/rm -f/, $tar_file], PRINT => $verbose > 1);
+      }
+    }
+  }
+
+  # Set up search paths
+  for my $name (keys %{ $self->{DIR} }) {
+    $self->{PATH}{$name} = [$self->_get_inherited_paths ($name)];
+
+    $self->config->assign_setting (
+      LABELS => ['PATH', $name],
+      VALUE  => $self->{PATH}{$name},
+    )
+  }
+
+  # Set up PP switches
+  $self->{PP} = {$self->_get_inherited_items ('PP')};
+
+  # Set up build targets
+  $self->{TARGET} = [$self->_get_inherited_items ('TARGET')];
+
+  # Check whether build tools have changed
+  return unless $self->_update_tool_info;
+
+  # Set up source directory packages for this build
+  my %srcdir = $self->_get_inherited_items ('SRCDIR');
+  for my $name (keys %srcdir) {
+    my $package = Fcm::SrcPackage->new (
+      CONFIG     => $self->config,
+      NAME       => $name,
+      CURRENT    => exists $self->{SRCDIR}{$name},
+      REQUIREPP  => $self->_require_pp ($name),
+      SEARCHPATH => [$self->_get_inherited_srcdirs ($name)],
+    );
+
+    $package->update_file_info ();
+
+    $self->{PACKAGE}{$name} = $package;
+  }
+
+  # Check whether pre-processor options have changed
+  return unless $self->_update_pp_info;
+
+  # Set up runtime dependency scan patterns
+  my %dep_pattern = %{ $self->config->setting ('DEP_PATTERN') };
+  for my $key (keys %dep_pattern) {
+    my $pattern = $dep_pattern{$key};
+
+    while ($pattern =~ /##([\w:]+)##/g) {
+      my $match = $1;
+      my $val   = $self->config->setting (split (/::/, $match));
+
+      last unless defined $val;
+      $val =~ s/\./\\./;
+
+      $pattern =~ s/##$match##/$val/;
+    }
+
+    $self->config->assign_setting (
+      LABELS => ['DEP_PATTERN', $key],
+      VALUE  => $pattern,
+    ) unless $pattern eq $dep_pattern{$key};
+  }
+
+  # Set up top level library name
+  {
+    $self->{LIB} = {$self->_get_inherited_items ('LIB')};
+
+    my $lib = $self->{LIB}{''};
+    $lib    = ($self->{NAME} ? $self->{NAME} : 'fcm_default') unless $lib;
+    $self->{LIB}{''} = $lib;
+  }
+
+  # Detect changes in EXE_DEP declarations
+  {
+    # Look for an extra executable dependency cache file
+    my $cachebase = $self->config->setting (qw/CACHE EXE_DEP/);
+    my $incache   = find_file_in_path $cachebase, $self->{PATH}{CACHE};
+
+    my $uptodate = 0;
+    my @inlines  = ();
+
+    # Read cache if it exists
+    if ($incache and -r $incache) {
+      my $incfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $incache);
+      $incfg->read_cfg;
+
+      @inlines  = $incfg->lines;
+      $uptodate = 1;
+    }
+
+    # Prepare output lines
+    my $outcfg = Fcm::CfgFile->new (CONFIG => $self->config);
+    $outcfg->add_line (COMMENT => 'EXE_DEP cache');
+
+    # List of extra executable dependencies
+    my %exe_dep   = %{ $self->config->setting ('EXE_DEP') };
+    for my $target (sort keys %exe_dep) {
+      $outcfg->add_line (
+        LABEL => ($target ? 'OBJECTS__' . $target : 'OBJECTS'),
+        VALUE => join (' ', sort keys %{ $exe_dep{$target} }),
+      );
+    }
+
+    # List of BLOCKDATA dependencies
+    my %blockdata = %{ $self->config->setting ('BLOCKDATA') };
+    for my $target (sort keys %blockdata) {
+      $outcfg->add_line (
+        LABEL => ($target ? 'BLOCKDATA__' . $target : 'BLOCKDATA'),
+        VALUE => join (' ', sort keys %{ $blockdata{$target} }),
+      );
+    }
+
+    # List of EXE_NAME
+    my %exe_name = %{ $self->config->setting ('EXE_NAME') };
+    for my $target (sort keys %exe_name) {
+      $outcfg->add_line (
+        LABEL => 'EXE_NAME__' . $target,
+        VALUE => $exe_name{$target},
+      );
+    }
+
+    # Compare cache with current output
+    my @outlines = $outcfg->lines ();
+
+    $uptodate = 0 if @inlines != @outlines;
+
+    if ($uptodate) {
+      for my $i (0 .. $#outlines) {
+        next unless $inlines[$i]->{LABEL} and $outlines[$i]->{LABEL};
+
+        if ($inlines[$i]->{LABEL} ne $outlines[$i]->{LABEL} or
+            $inlines[$i]->{VALUE} ne $outlines[$i]->{VALUE}) {
+          $uptodate = 0;
+          last;
+        }
+      }
+    }
+
+    # Update cache if it is out of date
+    $outcfg->print_cfg (catfile ($self->{DIR}{CACHE}, $cachebase))
+      unless $uptodate;
+    $self->config->assign_setting (
+      LABELS => [qw/REGEN_MAKERULE/],
+      VALUE  => ! $uptodate,
+    );
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_pp_info ();
+#
+# DESCRIPTION
+#   This internal method compares the current set of pre-processor options
+#   with that of the previous build using a "cache" file. If some
+#   pre-processor options have changed, the method updates the cache file and
+#   remove the "make" rules for the appropriate source packages.
+# ------------------------------------------------------------------------------
+
+sub _update_pp_info {
+  my $self = shift;
+
+  # Look for a PP option cache file
+  my $cachebase = $self->config->setting (qw/CACHE PPOPTION/);
+  my $incache   = find_file_in_path $cachebase, $self->{PATH}{CACHE};
+
+  my @chgpp = ();
+  my %newpp = %{ $self->{PP} };
+
+  # Read config if exists, otherwise marked all current tools as "changed"
+  if ($incache and -r $incache) {
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $incache);
+    $cfg->read_cfg;
+
+    my @lines   = $cfg->lines;
+    my %oldpp = ();
+
+    for my $line (@lines) {
+      next unless $line->{LABEL};
+
+      $oldpp{$line->{LABEL}} = $line->{VALUE};
+    }
+
+    # Compare new and old, mark as "changed" if changed or does not exist in old
+    @chgpp = (grep {
+      exists $oldpp{$_} ? $oldpp{$_} ne $newpp{$_} : 1;
+    } keys %newpp);
+
+    # Compare old and new, mark as "changed" if not exist in new
+    push @chgpp, (grep {not exists $newpp{$_}} keys %oldpp);
+
+  } else {
+    @chgpp = keys %newpp;
+  }
+
+  if (@chgpp) {
+    for my $name (@chgpp) {
+      for my $package (values %{ $self->{PACKAGE} }) {
+        next if $package->newpp;
+
+        if (('PP__' . $package->name) =~ /^$name(?:__|$)/) {
+          $package->current (1);
+          $package->newpp   (1);
+        }
+      }
+    }
+
+    # Update the build tool cache file if necessary
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+    for my $name (keys %newpp) {
+      $cfg->add_line (LABEL => $name, VALUE => $newpp{$name});
+    }
+    $cfg->add_line unless $cfg->lines;
+
+    $cfg->print_cfg (catfile ($self->{DIR}{CACHE}, $cachebase));
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_tool_info ();
+#
+# DESCRIPTION
+#   This internal method compares the current set of build tools with that of
+#   the previous build using a "cache" file. If some build tools have changed,
+#   the method updates the cache file and (the time stamps of) dummy "flags"
+#   files to denote changes in build tools from the previous build.
+# ------------------------------------------------------------------------------
+
+sub _update_tool_info {
+  my $self = shift;
+
+  # Look for a build tool cache file
+  my $cachebase = $self->config->setting (qw/CACHE BLDTOOL/);
+  my $incache   = find_file_in_path $cachebase, $self->{PATH}{CACHE};
+
+  my @chgtool = ();
+  my %newtool = %{ $self->config->setting ('TOOL') };
+
+  # Read config if exists, otherwise marked all current tools as "changed"
+  if ($incache and -r $incache) {
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $incache);
+    $cfg->read_cfg;
+
+    my @lines   = $cfg->lines;
+    my %oldtool = ();
+
+    for my $line (@lines) {
+      next unless $line->{LABEL};
+
+      $oldtool{$line->{LABEL}} = $line->{VALUE};
+    }
+
+    # Compare new and old, mark as "changed" if changed or does not exist in old
+    @chgtool = (grep {
+      exists $oldtool{$_} ? $oldtool{$_} ne $newtool{$_} : 1;
+    } keys %newtool);
+
+    # Compare old and new, mark as "changed" if not exist in new
+    push @chgtool, (grep {not exists $newtool{$_}} keys %oldtool);
+
+  } else {
+    @chgtool = keys %newtool;
+  }
+
+  # Changes of special tool names
+  for my $name (qw/CPP CC FPP FC LD/) {
+    next if grep {$_ eq $name} @chgtool;
+
+    push @chgtool, $name if grep /^$name\_\w+/, @chgtool;
+  }
+
+  if (@chgtool) {
+    # Update the time stamps of dummy files for changed tools
+    $self->_create_build_dir ('FLAGS');
+
+    my $ext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+    for my $name (@chgtool) {
+      my $file = catfile $self->{DIR}{FLAGS}, $name . $ext;
+
+      # Create/touch the file
+      touch_file $file or croak 'Unable to update: ', $file, ', abort';
+
+      print 'Updated: ', $file, "\n" if $self->config->verbose > 2;
+    }
+
+    # Update the build tool cache file if necessary
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+    for my $name (keys %newtool) {
+      $cfg->add_line (LABEL => $name, VALUE => $newtool{$name});
+    }
+
+    $cfg->print_cfg (catfile ($self->{PATH}{CACHE}->[0], $cachebase));
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_pre_process ();
+#
+# DESCRIPTION
+#   This internal method obtains a list of source files that require
+#   pre-processing in the source packages of this build, and attempts to
+#   pre-process them. The method returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub _pre_process {
+  my $self = shift;
+
+  # Go through source packages/files to see if PP is required
+  my @srcfiles = ();
+  for my $package (values %{ $self->{PACKAGE} }) {
+    next unless $package->requirepp;
+
+    $package->scan_dependency (HEADER_ONLY => 1);
+
+    push @srcfiles, grep ({$_->is_type_or (qw/FPP C/)} $package->srcfile);
+  }
+
+  return 1 unless @srcfiles;
+
+  my %task     = ();
+  my $flagsext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  my $pdoneext = $self->config->setting (qw/OUTFILE_EXT PDONE/);
+
+  # Set up tasks for each source file
+  for my $srcfile (@srcfiles) {
+    my $command  = $srcfile->is_type ('FPP') ? 'FPP' : 'CPP';
+    my @pck_list = $srcfile->get_package_list;
+    my @pknames  = split '__', pop (@pck_list);
+
+    # Set up a PP build task for each source file
+    my $target    = $srcfile->base . $pdoneext;
+    my $ppkeyname = join ('__', ($command . 'KEYS' , @pknames)) . $flagsext;
+    my $flagsname = join ('__', ($command . 'FLAGS', @pknames)) . $flagsext;
+
+    # Issue warning for duplicated tasks
+    if (exists $task{$target}) {
+      w_report 'Warning: ', $target, ': unable to create task for: ',
+               $srcfile->src, ': task already exists for: ',
+               $task{$target}->srcfile->src;
+      next;
+    }
+
+    $task{$target} = Fcm::BuildTask->new (
+      CONFIG     => $self->config,
+      TARGET     => $target,
+      TARGETPATH => $self->{PATH}{DONE},
+      SRCFILE    => $srcfile,
+      DEPENDENCY => [$ppkeyname, $flagsname, ($srcfile->dep ('H'))],
+      ACTIONTYPE => 'PP',
+    );
+
+    # Set up update ppkeys/flags build tasks for each source file/package
+    for my $i (0 .. $#pknames) {
+      my $name  = join '__', @pknames [0 .. $i];     # package name
+      my $dname = join '__', @pknames [0 .. $i - 1]; # dependent package name
+
+      for my $flag (qw/KEYS FLAGS/) {
+        my $fullflag = $command . $flag;
+        my $target   = join '__', ($fullflag, $name);
+        my $depend   = $dname ? join '__', ($fullflag, $dname) : $fullflag;
+
+        $target .= $flagsext;
+        $depend .= $flagsext;
+
+        next if exists $task{$target};
+
+        $task{$target} = Fcm::BuildTask->new (
+          CONFIG     => $self->config,
+          TARGET     => $target,
+          TARGETPATH => $self->{PATH}{FLAGS},
+          DEPENDENCY => [$depend],
+          ACTIONTYPE => 'UPDATE',
+        );
+      }
+    }
+  }
+
+  # Set up update global ppkeys/flags build tasks
+  for my $command (qw/CPP FPP/) {
+    for my $flag ('', qw/KEYS FLAGS/) {
+      my $target = $command . $flag . $flagsext;
+
+      $task{$target} = Fcm::BuildTask->new (
+        CONFIG     => $self->config,
+        TARGET     => $target,
+        TARGETPATH => $self->{PATH}{FLAGS},
+        ACTIONTYPE => 'UPDATE',
+      );
+    }
+  }
+
+  # Set up build tasks to copy all header files
+  for my $package (values %{ $self->{PACKAGE} }) {
+    my @files = grep {$_->is_type (qw/CPP INCLUDE/)} $package->srcfile;
+
+    # Author's note: may also want to issue warning for duplicated tasks
+
+    for my $file (@files) {
+      $task{$file->base} = Fcm::BuildTask->new (
+        CONFIG     => $self->config,
+        TARGET     => $file->base,
+        TARGETPATH => $self->{PATH}{INC},
+        SRCFILE    => $file,
+        DEPENDENCY => [$file->dep ('H')],
+        ACTIONTYPE => 'COPY',
+      );
+    }
+  }
+
+  # Build all PP tasks
+  my $count = 0;
+
+  for my $task (values %task) {
+    next unless $task->actiontype eq 'PP';
+
+    my $rc = $task->action (TASKLIST => \%task);
+    $count++ if $rc;
+  }
+
+  print 'Number of pre-processed files: ', $count, "\n"
+    if $self->config->verbose and $count;
+
+  # Change path and file type of pre-processed source files
+  for my $task (values %task) {
+    next unless $task->actiontype eq 'PP';
+
+    # Remove header dependencies from source file
+    my %dep = $task->srcfile->dep ();
+    for my $key (keys %dep) {
+      delete $dep{$key} if $dep{$key} eq 'H';
+    }
+    $task->srcfile->dep (\%dep);
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_generate_f9x_interface ();
+#
+# DESCRIPTION
+#   This internal method obtains a list of Fortran 9X source files in the
+#   source packages of this build, and attempts to generate an interface block
+#   file for each of the Fortran 9X source files. The method returns 1 on
+#   success.
+# ------------------------------------------------------------------------------
+
+sub _generate_f9x_interface {
+  my $self = shift;
+
+  # Go through source packages/files for Fortran 9x source files with
+  # standalone subroutines or functions
+  my @srcfiles = ();
+  for my $package (values %{ $self->{PACKAGE} }) {
+    next unless $package->current;
+
+    push @srcfiles, grep {
+      $_->is_type_or (qw/FORTRAN9X FPP9X/) and
+      uc ($_->select_tool ('GENINTERFACE')) ne 'NONE' and
+      not $_->is_type_or (qw/PROGRAM MODULE INCLUDE/)
+    } $package->srcfile;
+  }
+
+  my $flagsext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  my $pdoneext = $self->config->setting (qw/OUTFILE_EXT PDONE/);
+
+  # Set up build task to generate interface files for all selected Fortran 9x
+  # sources
+  my %task         = ();
+  for my $srcfile (@srcfiles) {
+    my $target  = $srcfile->interfacebase . $pdoneext;
+    my @pknames = split '__', ($srcfile->get_package_list)[-1];
+    my $flag    = join ('__', ('GENINTERFACE', @pknames)) . $flagsext;
+
+    $task{$target} = Fcm::BuildTask->new (
+      CONFIG     => $self->config,
+      TARGET     => $target,
+      TARGETPATH => $self->{PATH}{DONE},
+      SRCFILE    => $srcfile,
+      DEPENDENCY => [$flag],
+      ACTIONTYPE => 'GENINTERFACE',
+    );
+
+    # Set up build tasks for each source file/package flags file for interface
+    # generator tool
+    for my $i (0 .. $#pknames) {
+      my $name   = join '__', @pknames [0 .. $i];     # package name
+      my $dname  = join '__', @pknames [0 .. $i - 1]; # dependent package name
+
+      my $target = join '__', ('GENINTERFACE', $name);
+      my $depend = $dname ? join '__', ('GENINTERFACE', $dname) : 'GENINTERFACE';
+
+      $target .= $flagsext;
+      $depend .= $flagsext;
+
+      next if exists $task{$target};
+
+      $task{$target} = Fcm::BuildTask->new (
+        CONFIG     => $self->config,
+        TARGET     => $target,
+        TARGETPATH => $self->{PATH}{FLAGS},
+        DEPENDENCY => [$depend],
+        ACTIONTYPE => 'UPDATE',
+      );
+    }
+  }
+
+  # Set up build task to update the flags file for interface generator tool
+  {
+    my $target     = 'GENINTERFACE' . $flagsext;
+    $task{$target} = Fcm::BuildTask->new (
+      CONFIG     => $self->config,
+      TARGET     => $target,
+      TARGETPATH => $self->{PATH}{FLAGS},
+      ACTIONTYPE => 'UPDATE',
+    );
+  }
+
+  my $count = 0;
+
+  # Performs task
+  for my $task (values %task) {
+    next unless $task->actiontype eq 'GENINTERFACE';
+
+    my $rc = $task->action (TASKLIST => \%task);
+    $count++ if $rc;
+  }
+
+  print 'Number of generated interfaces: ', $count, "\n"
+    if $self->config->verbose and $count;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_scan_dependency ();
+#
+# DESCRIPTION
+#   This internal method goes through each source package to obtain dependency
+#   information from their source files. It returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub _scan_dependency {
+  my $self = shift;
+
+  # Go through source packages/files
+  my $count = 0;
+
+  for my $package (values %{ $self->{PACKAGE} }) {
+    my $rc = $package->scan_dependency;
+    $count++ if $rc;
+  }
+
+  print 'Scanned files in ', $count, ' package(s) for dependency', "\n"
+    if $self->config->verbose and $count;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_set_targets ();
+#
+# DESCRIPTION
+#   This internal method determines the default targets to be built.
+# ------------------------------------------------------------------------------
+
+sub _set_targets {
+  my $self = shift;
+
+  # Targets of the build
+  if (not @{ $self->{TARGET} }) {
+    # Build targets not specified by user, default to building all main programs
+    my @programs = ();
+
+    # Get all main programs from all packages
+    for my $package (values %{ $self->{PACKAGE} }) {
+      my @srcfiles = grep {$_->is_type ('PROGRAM')} $package->srcfile;
+
+      for (@srcfiles) {
+        push @programs, $_->target;
+      }
+    }
+
+    @programs = sort (@programs);
+
+    @{ $self->{TARGET} } = @programs ? @programs : ($self->{LIB}{''});
+  }
+
+  return @{ $self->{TARGET} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_makefile ();
+#
+# DESCRIPTION
+#   This internal method writes the "Makefile" for this build.
+# ------------------------------------------------------------------------------
+
+sub _write_makefile {
+  my $self = shift;
+
+  # Handle the sub-packages
+  # ----------------------------------------------------------------------------
+  # Get list of all packages
+  my %allpcks = $self->allpcks;
+
+  # Register non-word package names
+  my $unusual = 0;
+  for my $name (sort keys %allpcks) {
+    if ($name !~ /^\w*$/) {
+      $self->config->assign_setting (
+        LABELS => ['FCM_PCK_OBJECTS', $name],
+        VALUE  => 'FCM_PCK_OBJECTS' . $unusual++,
+      );
+    }
+  }
+
+  # Update make rule for each current source package, if necessary
+  my $count = 0;
+  for my $package (values %{ $self->{PACKAGE} }) {
+    my $regen_mk = $unusual ? 1 : $self->config->setting ('REGEN_MAKERULE');
+
+    next unless $regen_mk or $package->current;
+
+    if ($regen_mk or not $package->makerule_uptodate) {
+      $package->write_makerule ();
+      $count++;
+    }
+  }
+
+  print 'Updated make rules for ', $count, ' package(s).', "\n"
+    if $self->config->verbose and $count;
+
+  # Makefile header
+  # ----------------------------------------------------------------------------
+  my $makefile = '# Automatic Makefile' . "\n\n";
+
+  # Name of the build
+  $makefile .= 'FCM_BUILD_NAME = ' . $self->{NAME} . "\n" if $self->{NAME};
+  
+  # Location of FCM config file
+  $makefile .= 'FCM_BLD_CFG = ' . $self->cfg->src . "\n";
+
+  # Targets of the build
+  $makefile .= 'FCM_BLD_TARGETS = ' . join (' ', ($self->_set_targets)) . "\n\n";
+
+  # Perl library
+  # ----------------------------------------------------------------------------
+  {
+    my $libdir  = dirname (dirname ($INC{'Fcm/Build.pm'}));
+    my @libpath = split /:/, ($ENV{PERL5LIB} ? $ENV{PERL5LIB} : '');
+
+    if (not grep (m/$libdir/, @libpath)) {
+      $makefile .= 'export PERL5LIB := ' . $libdir;
+      $makefile .= ':$(PERL5LIB)' if exists $ENV{PERL5LIB};
+      $makefile .= "\n\n";
+    }
+  }
+
+  # Build directories
+  # ----------------------------------------------------------------------------
+  # Build root directory
+  my $rootdir = $self->{DIR}{ROOT};
+  $makefile  .= 'export FCM_ROOTDIR = ' . $rootdir . "\n";
+
+  # Build root directory path
+  {
+    my @path = @{ $self->{PATH}{ROOT} };
+    shift @path;
+    $makefile   .= 'export FCM_ROOTPATH = $(FCM_ROOTDIR)';
+    $makefile   .= ':' . join (':', @path) if @path;
+    $makefile   .= "\n";
+  }
+
+  $makefile .= "\n";
+
+  # Build sub-directories
+  for my $name (sort keys %{ $self->{DIR} }) {
+    next if $name eq 'ROOT';
+
+    my $dir = $self->{DIR}{$name};
+    $dir    =~ s/^$rootdir/\$(FCM_ROOTDIR)/;
+
+    $makefile .= 'export FCM_' . $name . 'DIR = ' . $dir . "\n";
+  }
+
+  $makefile .= "\n";
+
+  # Build sub-directory paths
+  for my $name (sort keys %{ $self->{PATH} }) {
+    next if $name eq 'ROOT';
+
+    my @path = @{ $self->{PATH}{$name} };
+    shift @path;
+
+    $makefile   .= 'export FCM_' . $name . 'PATH = $(FCM_' . $name . 'DIR)';
+    $makefile   .= ':' . join (':', @path) if @path;
+    $makefile   .= "\n";
+  }
+
+  $makefile .= "\n";
+
+  # Build tools
+  # ----------------------------------------------------------------------------
+  # List of build tools
+  my $tool          = $self->config->setting ('TOOL');
+
+  # List of tools local to FCM, (will not be exported)
+  my %localtool     = map {($_, 1)} split (    # map into a hash table
+    /,/, $self->config->setting ('LOCALTOOL'), # split comma separated list
+  );
+
+  # Export required tools
+  my $unusual_count = 0;
+  for my $name (sort keys %$tool) {
+    # Ignore local tools
+    my $topname = (split (/__/, $name))[0];
+    next if exists $localtool{$topname};
+
+    if ($name =~ /^\w+$/) {
+      # Tools with normal name, just export it as an environment variable
+      $makefile .= 'export ' . $name . ' = ' . $tool->{$name} . "\n";
+
+    } else {
+      # Tools with unusual characters, export using a label/value pair
+      $makefile .= 'export FCM_UNUSUAL_TOOL_LABEL' . $unusual_count . ' = ' .
+                   $name . "\n";
+      $makefile .= 'export FCM_UNUSUAL_TOOL_VALUE' . $unusual_count . ' = ' .
+                   $tool->{$name} . "\n";
+      $unusual_count++;
+    }
+  }
+
+  $makefile .= "\n";
+
+  # Verbose mode
+  # ----------------------------------------------------------------------------
+  $makefile .= 'export FCM_VERBOSE ?= ' . $self->config->verbose . "\n\n";
+
+  # VPATH
+  # ----------------------------------------------------------------------------
+  # $name is internal name of build sub-directories
+  # $type is the type of files
+  for my $name (sort keys %{ $self->config->setting ('VPATH') }) {
+    my @types = split /,/, $self->config->setting ('VPATH', $name);
+
+    for my $type (sort @types) {
+      # If $type is EMPTY, it is a file with no file name extension
+      if (uc ($type) eq 'EMPTY') {
+        $makefile .= 'vpath % $(FCM_' . $name . 'PATH)' . "\n";
+
+      } elsif ($type =~ s/^(in|out)://i) {
+        if (uc ($1) eq 'IN') {
+          # If $type begins with IN:<type>, it is a list of file extensions that
+          # can be found under the INFILE_EXT hash in the configuration setting,
+          # with <type> matching a keyword in the values of the hash.
+          my %infile_ext = %{ $self->config->setting ('INFILE_EXT') };
+
+          for my $ext (sort keys %infile_ext) {
+            $makefile .= 'vpath %.' . $ext . ' $(FCM_' . $name . 'PATH)' . "\n"
+              if grep {$_ eq $type} split /::/, $infile_ext{$ext};
+          }
+
+        } else {
+          # If $type begins with OUT:<type>, it is the value of a hash element
+          # in the OUTFILE_EXT hash in the configuration setting, with <type>
+          # matching the key.
+          my $ext    = $self->config->setting ('OUTFILE_EXT', $type);
+          $makefile .= 'vpath %' . $ext . ' $(FCM_' . $name . 'PATH)' . "\n";
+        }
+
+      } else {
+        # Otherwise, $type is a VPATH pattern recognised by "make".
+        $makefile .= 'vpath ' . $type . ' $(FCM_' . $name . 'PATH)' . "\n";
+      }
+    }
+  }
+
+  # VPATH for dummy files
+  $makefile .= 'vpath %.dummy $(FCM_DONEDIR)' . "\n";
+  $makefile .= "\n";
+
+  # Default targets
+  # ----------------------------------------------------------------------------
+  $makefile .= '.PHONY : all clean' . "\n\n";
+  $makefile .= 'all : $(FCM_BLD_TARGETS)' . "\n\n";
+  $makefile .= 'clean : ' . "\n";
+  $makefile .= "\t" . 'rm -rf';
+  for my $dir (qw/BIN LIB OBJ DONE/) {
+    $makefile .= ' $(FCM_' . $dir . 'DIR)' if exists $self->{DIR}{$dir};
+  }
+  $makefile .= "\n";
+  $makefile .= "\t" . 'rm -f lib__*' .
+               $self->config->setting (qw/OUTFILE_EXT LIB/) .
+               ' *' . $self->config->setting (qw/OUTFILE_EXT OBJ/) . "\n";
+  $makefile .= "\n";
+
+  # Targets for copy dummy
+  $makefile .= $self->config->setting (qw/MISC CPDUMMY/) . ' :' . "\n";
+  $makefile .= "\t" . 'touch $@' . "\n\n";
+
+  # Targets for all (non-main-program) objects and libraries
+  # ----------------------------------------------------------------------------
+  for my $key (reverse sort keys %allpcks) {
+    # Objects variable
+    my $var;
+    if ($self->config->setting ('FCM_PCK_OBJECTS', $key)) {
+      # Package name contains unusual characters, use predefined variable
+      $var = $self->config->setting ('FCM_PCK_OBJECTS', $key);
+
+    } else {
+      # Normal package name, prefix the package name with "OBJECTS__"
+      # Top level package, simply set to "OBJECTS"
+      $var = $key ? join ('__', ('OBJECTS', $key)) : 'OBJECTS';
+    }
+
+    # Export top level OBJECTS variable
+    # but keep sub-package OBJECTS variables local to the Makefile
+    $makefile .= ($var eq 'OBJECTS' ? 'export ' : '') . $var . ' =';
+
+    # Add objects from children
+    if (@{ $allpcks{$key} }) {
+      # List of sub-packages of current package
+      my @deps   = map {
+        if ($self->config->setting ('FCM_PCK_OBJECTS', $_)) {
+          # Package name contains unusual characters, use predefined variable
+          '$(' . $self->config->setting ('FCM_PCK_OBJECTS', $_) . ')';
+
+        } else {
+          # Normal package name, prefix the package name with "OBJECTS__"
+          '$(OBJECTS__' . $_ . ')';
+        }
+      } @{ $allpcks{$key} };
+
+      $makefile .= ' ' . join (' ', @deps);
+    }
+
+    # Add its own objects
+    if (exists $self->{PACKAGE}{$key}) {
+      # List of source files in the current package
+      my @files = $self->{PACKAGE}{$key}->srcfile;
+
+      for my $file (@files) {
+        # Consider compilable source files only
+        next unless $file->is_type ('SOURCE');
+
+        # Ignore main programs and Fortran BLOCKDATA program units
+        next if $file->is_type_or (qw/PROGRAM BLOCKDATA/);
+
+        # Add to object list
+        $makefile .= ' ' . $file->intname .
+                     $self->config->setting (qw/OUTFILE_EXT OBJ/);
+      }
+    }
+
+    $makefile .= "\n\n";
+
+    # Library target
+    my $lib = exists ($self->{LIB}{$key}) ? $self->{LIB}{$key} : $key;
+    $lib    = 'lib' . $lib . $self->config->setting (qw/OUTFILE_EXT LIB/);
+
+    $makefile .= $lib . ' : $(' . $var . ')' . "\n";
+    $makefile .= "\t" . 'fcm_internal archive $@ $^' . "\n\n";
+  }
+
+  # Targets for top level and package flags files and dummy dependencies
+  my %flags_tool = (
+    FFLAGS  => 'FC',
+    CFLAGS  => 'CC',
+  );
+
+  my $ext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  for my $name (qw/FFLAGS CFLAGS LD LDFLAGS FPPKEYS CPPKEYS/) {
+    # Flags files for tool command
+    if (exists $flags_tool{$name}) {
+      $makefile .= $flags_tool{$name} . $ext . ' :' . "\n";
+      $makefile .= "\t" . 'touch ' . catfile ('$(FCM_FLAGSDIR)', '$@') . "\n\n";
+    }
+
+    # Top level flags files
+    $makefile .= $name . $ext . ' :';
+    $makefile .= ' ' . $flags_tool{$name} . $ext if exists $flags_tool{$name};
+    $makefile .= "\n\t" . 'touch ' . catfile ('$(FCM_FLAGSDIR)', '$@') . "\n\n";
+
+    # Package level flags files
+    for my $key (sort keys %allpcks) {
+      next unless @{ $allpcks{$key} }; # ignore packages without children
+
+      my $depend  = $key ? join '__', ($name, $key) : $name;
+      my @targets = sort map {$name . '__' . $_ . $ext} @{ $allpcks{$key} };
+
+      $makefile .= join (' ', @targets) . ' : ' . $depend . $ext . "\n";
+      $makefile .= "\t" . 'touch ' . catfile ('$(FCM_FLAGSDIR)', '$@') .
+                   "\n\n";
+    }
+  }
+
+  # Include source package make rules
+  # ----------------------------------------------------------------------------
+  for my $package (sort {$a->name cmp $b->name} values %{ $self->{PACKAGE} }) {
+    my $mkbase = $package->name . $self->config->setting (qw/OUTFILE_EXT MK/);
+    my $mkfile = find_file_in_path ($mkbase, $self->{PATH}{BLD});
+
+    if ($mkfile) {
+      if (index ($mkfile, $self->{DIR}{BLD}) == 0) {
+        $mkfile = catfile '$(FCM_BLDDIR)',
+                  substr ($mkfile, length ($self->{DIR}{BLD}) + 1);
+
+      } elsif (index ($mkfile, $self->{DIR}{ROOT}) == 0) {
+        $mkfile = catfile '$(FCM_ROOTDIR)',
+                  substr ($mkfile, length ($self->{DIR}{ROOT}) + 1);
+      }
+
+      $makefile .= 'include ' . $mkfile . "\n";
+
+    } else {
+      my $pck = join ('::', split (/__/, $package->name));
+      w_report 'Warning: no make rule file for source package: ', $pck;
+    }
+  }
+
+  $makefile .= "\n" . '# EOF' . "\n";
+
+  # Print Makefile
+  # ----------------------------------------------------------------------------
+  my $dir = $self->{DIR}{BLD};
+  my $out = catfile $dir, $self->config->setting (qw/MISC MAKEFILE/);
+
+  if (not -d $dir) {
+    print 'Make directory: ', $dir, "\n" if $self->config->verbose > 1;
+    mkpath $dir or croak 'Cannot create directory "', $dir, '", abort';
+  }
+
+  open OUT, '>', $out or croak 'Cannot open "', $out, '" (', $!, '), abort';
+  print OUT $makefile;
+  close OUT or croak 'Cannot close "', $out, '" (', $!, '), abort';
+
+  print 'Updated Makefile: ', $out, "\n" if $self->config->verbose;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_invoke_make (
+#     TARGETS => \@targets,
+#     JOBS    => $jobs,
+#     ARCHIVE => $archive,
+#   );
+#
+# DESCRIPTION
+#   This internal method invokes the "make" command to make the build.
+#
+# ARGUMENTS
+#   TARGETS - Specify targets to be built. If set, these targets will be built
+#             instead of the ones specified in the build configuration file.
+#   JOBS    - Specify number of jobs that can be handled by "make". If set,
+#             the value must be a natural integer. If not set, the default
+#             value is 1 (i.e. run "make" in serial mode).
+#   ARCHIVE - If set to "true", invoke the "archive" mode. Most build files and
+#             directories created by this build will be archived using the
+#             "tar" command. If not set, the default is not to invoke the
+#             "archive" mode.
+# ------------------------------------------------------------------------------
+
+sub _invoke_make {
+  my $self = shift;
+  my %args = @_;
+
+  # Build the make command from the specified targets
+  my @targets  = exists $args{TARGETS} ? @{ $args{TARGETS} } : qw/all/;
+  my $jobs     = exists $args{JOBS}    ? $args{JOBS}         : 1;
+  my $archive  = exists $args{ARCHIVE} ? $args{ARCHIVE}      : 0;
+  my $verbose  = $self->config->verbose;
+
+  # Create the required build directories
+  for my $dir (qw/BIN DONE ETC INC FLAGS LIB OBJ TMP/) {
+    $self->_create_build_dir ($dir);
+  }  
+
+  my @commands = ();
+  my @make_cmd = ($self->config->setting (qw/TOOL MAKE/));
+  push @make_cmd, split (/\s+/, $self->config->setting (qw/TOOL MAKEFLAGS/));
+  push @make_cmd, $self->config->setting (qw/TOOL MAKE_SILENT/)
+    unless $verbose > 2;
+
+  if ($jobs > 1) { # multi-process "make"
+    my $make_job = $self->config->setting (qw/TOOL MAKE_JOB/);
+
+    # Setup the "make" commands for each target
+    while (my $target = shift @targets) {
+      if ($target eq 'clean') { # Do not run "clean" in parallel
+        push @commands, [@make_cmd, $target];
+
+      } else {
+        push @commands, [@make_cmd, $make_job, $jobs, $target];
+      }
+    }
+
+  } else { # single process "make"
+
+    # Setup the "make" command
+    push @commands, [@make_cmd, @targets];
+
+  }
+  
+  # Run the make command
+  my $rc  = 0;
+  my $cwd = cwd;
+  print 'cd ', $self->{DIR}{BLD}, "\n" if $verbose > 2;
+  chdir $self->{DIR}{BLD};
+  while (my $cmd = shift @commands) {
+    $| = 1; # flush STDOUT before running "make"
+    print timestamp_command (&get_command_string ($cmd)) if $verbose > 2;
+    $| = 0;
+    &run_command ($cmd, ERROR => 'warn', RC => \$rc);
+    print timestamp_command (&get_command_string ($cmd), 'End') if $verbose > 2;
+    last if $rc;
+  }
+  print 'cd ', $cwd, "\n" if $verbose > 2;
+  chdir $cwd;
+
+  return $rc ? undef : 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $self->_remove_empty_dirs ();
+#
+# DESCRIPTION
+#   This internal method removes empty build directories.
+# ------------------------------------------------------------------------------
+
+sub _remove_empty_dirs {
+  my $self = shift;
+
+  for my $name (qw/BIN CACHE DONE ETC FLAGS INC LIB PPSRC OBJ TMP/) {
+    opendir DIR, $self->{DIR}{$name};
+    my @files = readdir DIR;
+    @files    = grep !/^\.\.?$/, @files;
+    closedir DIR;
+
+    if (not @files) {
+      print 'Remove directory: ', $self->{DIR}{$name}, "\n"
+        if $self->config->verbose > 1;
+      rmdir $self->{DIR}{$name};
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $self->_tar_build_dirs ();
+#
+# DESCRIPTION
+#   This internal method creates TAR archives for selected build directories.
+# ------------------------------------------------------------------------------
+
+sub _tar_build_dirs {
+  my $self = shift;
+
+  # Create TAR archives if necessary
+  my $cwd = cwd;
+
+  my $tar      = $self->config->setting (qw/OUTFILE_EXT TAR/);
+  my @tar_dirs = split /,/, $self->config->setting (qw/TAR_DIRS/);
+  my $verbose  = $self->config->verbose;
+
+  for my $name (@tar_dirs) {
+    my $dir = $self->{DIR}{$name};
+
+    if (-d $dir) {
+      my $base = basename ($dir);
+      print 'cd ', dirname ($dir), "\n" if $verbose > 2;
+      chdir dirname ($dir);
+
+      my $rc = &run_command (
+        [qw/tar -c -f/, $base . $tar, $base],
+        PRINT => $verbose > 1, ERROR => 'warn',
+      );
+
+      &run_command ([qw/rm -rf/, $base], PRINT => $verbose > 1) if not $rc;
+    }
+  }
+
+  print 'cd ', $cwd, "\n" if $verbose > 2;
+  chdir $cwd;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $self->_create_runenv_script ();
+#
+# DESCRIPTION
+#   This internal method creates the runtime environment script if necessary.
+# ------------------------------------------------------------------------------
+
+sub _create_runenv_script {
+  my $self = shift;
+
+  # More diagnostic on how to use the build
+  my @bin_dirs = grep {-d} @{ $self->{PATH}{BIN} };
+  my $etc_dir  = -d $self->{DIR}{ETC} ? $self->{DIR}{ETC} : undef;
+
+  if (@bin_dirs or $etc_dir) {
+    # Create a runtime environment script if necessary
+    my $run_env_sh_base = $self->config->setting (qw/MISC RUN_ENV_SH/);
+    my $run_env_sh      = catfile $self->{DIR}{ROOT}, $run_env_sh_base;
+
+    open FILE, '>', $run_env_sh
+      or croak $run_env_sh, ': cannot open (', $!, '), abort';
+    print FILE '#!/usr/bin/ksh', "\n";
+    print FILE 'export PATH=', join (':', @bin_dirs), ':$PATH', "\n"
+      if @bin_dirs;
+    print FILE 'export FCM_ETCDIR=', $self->{DIR}{ETC}, "\n" if $etc_dir;
+    close FILE or croak $run_env_sh, ': cannot close (', $!, '), abort';
+
+    # Create symbolic link in bin/ sub-directory for backward compatibility
+    if (-d $self->{DIR}{BIN}) {
+      my $file = catfile ($self->{DIR}{BIN}, $run_env_sh_base);
+      
+      # Remove old link if necessary
+      unlink $file if -l $file and readlink ($file) ne $run_env_sh;
+
+      # Create the new link
+      symlink $run_env_sh, $file if not -l $file;
+    }
+
+    # Information on the location/usage of the runtime environment script
+    if ($self->config->verbose > 1 and $run_env_sh) {
+      print '# ', '-' x 78, "\n";
+      print '# To use this build, source the following shell script:', "\n";
+      print '. ', $run_env_sh, "\n";
+      print '# ', '-' x 78, "\n";
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_create_lib_excl_dep ();
+#
+# DESCRIPTION
+#   This internal method creates a set of exclude dependency configurations for
+#   libraries of this build.
+# ------------------------------------------------------------------------------
+
+sub _create_lib_excl_dep {
+  my $self = shift;
+
+  if (-d $self->{DIR}{LIB}) {
+    $self->_create_build_dir ('ETC');
+    
+    my %allpcks  = $self->allpcks;
+    my $cfgext   = $self->config->setting (qw/OUTFILE_EXT CFG/);
+    my %cfglabel = %{ $self->config->setting ('CFG_LABEL') };
+
+    for my $key (reverse sort keys %allpcks) {
+      my $outcfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+      # Include configurations from sub-packages
+      for my $subpck (@{ $allpcks{$key} }) {
+        my $base = 'lib' . $subpck . $cfgext;
+        ($base = $self->{LIB}{$subpck}) =~ s/\.\w+$/$cfgext/
+          if exists ($self->{LIB}{$subpck});
+        my $file = catfile ('$HERE', $base);
+
+        $outcfg->add_line (LABEL => $cfglabel{INC}, VALUE => $file)
+          if -r catfile ($self->{DIR}{ETC}, $base);;
+      }
+
+      # Exclude dependency for source files in current package
+      if (exists $self->{PACKAGE}{$key}) {
+        my @srcfiles = $self->{PACKAGE}{$key}->srcfile;
+
+        for my $srcfile (@srcfiles) {
+          if ($srcfile->is_type ('INCLUDE')) {
+            if ($srcfile->is_type ('CPP')) {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'H::' . $srcfile->base,
+              );
+
+            } elsif ($srcfile->is_type ('INTERFACE')) {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'INTERFACE::' . $srcfile->base,
+              );
+
+            } else {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'INC::' . $srcfile->base,
+              );
+            }
+
+          } elsif ($srcfile->is_type ('SOURCE')) {
+            next if $srcfile->is_type_or (qw/PROGRAM BLOCKDATA/);
+
+            if ($srcfile->is_type ('FORTRAN')) {
+              if ($srcfile->is_type (qw/FORTRAN MODULE/)) {
+                $outcfg->add_line (
+                  LABEL => $cfglabel{EXCL_DEP},
+                  VALUE => 'USE::' . $srcfile->root,
+                );
+
+              } else {
+                $outcfg->add_line (
+                  LABEL => $cfglabel{EXCL_DEP},
+                  VALUE => 'INTERFACE::' . $srcfile->interfacebase,
+                );
+
+                $outcfg->add_line (
+                  LABEL => $cfglabel{EXCL_DEP},
+                  VALUE => 'OBJ::' . $srcfile->root,
+                );
+              }
+
+            } else {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'OBJ::' . $srcfile->root,
+              );
+            }
+          }
+        }
+      }
+
+      # Name of configuration file, follows the name of library
+      my $outbase ='lib' . $key . $cfgext;
+      ($outbase = $self->{LIB}{$key}) =~ s/\.\w+$/$cfgext/
+        if exists ($self->{LIB}{$key});
+      my $outfile = catfile ($self->{DIR}{ETC}, $outbase);
+
+      # Write to configuration file
+      $outcfg->print_cfg ($outfile);
+    }
+
+    # Information on the location/usage of the exclude dependency configurations
+    if ($self->config->verbose > 1) {
+      my $etcdir = $self->{DIR}{ETC};
+      print '# ', '-' x 78, "\n";
+      print <<EOF;
+# To use a library archive of this build in another FCM build, you need to
+# include in the new build configuration the corresponding configuration file
+# that has the relevant exclude dependency information. These configurations
+# files can be found in $etcdir.
+EOF
+      print '# ', '-' x 78, "\n";
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_create_build_dir ();
+#   $self->_create_build_dir ($label);
+#
+# DESCRIPTION
+#   This internal method creates a build directory. If $label is specified,
+#   the method will attempt to create a named sub-directory according to
+#   $label. Otherwise, the method attempts to create the build root
+#   directory. Returns the name of the directory if it is created successfully
+#   or if it already exists.
+# ------------------------------------------------------------------------------
+
+sub _create_build_dir {
+  my $self  = shift;
+  my $label = $_[0] ? uc $_[0] : 'ROOT';
+
+  my $dir = undef;
+
+  # Make sure the variable is set
+  if ($self->{DIR}{$label}) {
+    $dir = $self->{DIR}{$label};
+
+    # Expand relative path if necessary
+    $dir = catfile $self->{DIR}{ROOT}, $dir if $dir =~ /^\w/;
+
+  } else {
+    if ($label eq 'ROOT') {
+      w_report 'Error: build root directory not set.';
+      return;
+
+    } elsif ($self->config->setting ('DIR', $label)) {
+      $dir = catfile $self->{DIR}{ROOT}, $self->config->setting ('DIR', $label);
+
+    } else {
+      carp 'Directory label "', $label, '" not recognised';
+      return undef;
+    }
+  }
+
+  # Set up the bld directory, if required
+  if (not -d $dir) {
+    print 'Make directory: ', $dir, "\n" if $self->config->verbose > 1;
+    mkpath $dir or croak 'Cannot create directory "', $dir, '"';
+  }
+
+  $self->{DIR}{$label} = $dir unless $self->{DIR}{$label};
+
+  return $dir;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_inherited_paths ($name);
+#
+# DESCRIPTION
+#   This recursive internal method returns a list containing the search path
+#   for a build directory named by the internal label $name. (Please note that
+#   a build directory will only be placed into the search path if the
+#   directory exists.)
+# ------------------------------------------------------------------------------
+
+sub _get_inherited_paths {
+  my $self = shift;
+  my $name = shift;
+
+  return () unless $name and exists $self->{DIR}{$name};
+
+  my @path = ();
+
+  # Recursively inherit the search path for a this type of build directory
+  for my $use (@{ $self->{USE} }) {
+    my @cur_path = $use->_get_inherited_paths ($name);
+    unshift @path, @cur_path;
+  }
+
+  # Place the path of the current build in the front
+  unshift @path, $self->{DIR}{$name};
+
+  return @path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_inherited_srcdirs ($name);
+#
+# DESCRIPTION
+#   This recursive internal method returns a list containing the search path
+#   for a source directory named by the internal package label $name. (Please
+#   note that a source directory will only be placed into the search path if
+#   the directory exists.)
+# ------------------------------------------------------------------------------
+
+sub _get_inherited_srcdirs {
+  my $self = shift;
+  my $name = shift;
+
+  return () unless $name;
+
+  my @path = ();
+
+  # Recursively inherit the search path for this source directory
+  my $key = 'SRCDIR__' . $name;
+  if ($self->_inherit_ok ($key)) {
+    for my $use (@{ $self->{USE} }) {
+      my @cur_path = $use->_get_inherited_srcdirs ($name);
+      unshift @path, @cur_path;
+    }
+  }
+
+  # Place the path of the current source in the front
+  unshift @path, $self->{SRCDIR}{$name}
+    if exists $self->{SRCDIR}{$name} and -d $self->{SRCDIR}{$name};
+
+  return @path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_inherited_items ($type);
+#
+# DESCRIPTION
+#   This recursive internal method returns a list containing an inherited
+#   build item of the type $type. (Depending of $type, the returned list can
+#   be an array or a hash.)
+# ------------------------------------------------------------------------------
+
+sub _get_inherited_items {
+  my $self = shift;
+  my $type = shift;
+
+  return () if not exists $self->{$type};
+
+  if (ref $self->{$type} eq 'ARRAY') {
+
+    my @items = ();
+
+    # Recursively inherit from used builds
+    if ($self->{INHERIT}{$type}) {
+      for my $use (@{ $self->{USE} }) {
+        my @cur_items = $use->_get_inherited_items ($type);
+
+        for my $item (@cur_items) {
+          my $type_item = $type . '__' . $item;
+
+          # Check inheritance option of current item
+          next unless $self->_inherit_ok ($type_item);
+
+          # The statement ensures that there is no duplication
+          push @items, $item unless grep {$_ eq $item} @items;
+        }
+      }
+    }
+
+    # Items in current build
+    if (@{ $self->{$type} }) {
+      for my $item (@{ $self->{$type} }) {
+        # The statement ensures that there is no duplication
+        push @items, $item unless grep {$_ eq $item} @items;
+      }
+    }
+
+    return @items;
+
+  } elsif (ref $self->{$type} eq 'HASH') {
+
+    my %items = ();
+
+    # Recursively inherit from used builds
+    if ($self->{INHERIT}{$type}) {
+      for my $use (@{ $self->{USE} }) {
+        my %cur_items = $use->_get_inherited_items ($type);
+
+        for my $name (keys %cur_items) {
+          my $type_name = $type . '__' . $name;
+
+          # Check inheritance option of current item
+          next unless $self->_inherit_ok ($type_name);
+
+          # "Closer" ancestors overrides more "distant" ones
+          $items{$name} = $cur_items{$name};
+        }
+      }
+    }
+
+    # Items in current build
+    if (%{ $self->{$type} }) {
+      for my $name (keys %{ $self->{$type} }) {
+        # Settings in current build override inherited settings
+        $items{$name} = $self->{$type}{$name};
+      }
+    }
+
+    return %items;
+
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_require_pp ($name);
+#
+# DESCRIPTION
+#   This internal method returns true if source package $name requires
+#   pre-processing.
+# ------------------------------------------------------------------------------
+
+sub _require_pp {
+  my $self = shift;
+  my $name = $_[0];
+
+  my $rc    = 0;
+  my @names = 'PP';
+  push @names, (split /__/, $name);
+
+  # Check whether pre-process flag exists, going up the source package hierarchy
+  do {
+    my $cur_name = join '__', @names;
+    if (exists $self->{PP}{$cur_name}) {
+      $rc = $self->{PP}{$cur_name};
+      return $rc;
+    }
+  } while pop @names;
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_inherit_ok ($name);
+#
+# DESCRIPTION
+#   This internal method returns true if it is OK to inherit an item specified
+#   by $name, (where $name is a double underscore "__" delimited positional
+#   list of source package names).
+# ------------------------------------------------------------------------------
+
+sub _inherit_ok {
+  my $self  = shift;
+  my $name  = $_[0];
+
+  my $rc    = 1;
+  my @names = split /__/, $name;
+
+  # Check whether INHERIT flag exists, going up the source package hierarchy
+  do {
+    my $cur_name = join '__', @names;
+    if (exists $self->{INHERIT}{$cur_name}) {
+      $rc = $self->{INHERIT}{$cur_name};
+      return $rc;
+    }
+  } while pop @names;
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/BuildTask.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/BuildTask.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/BuildTask.pm	(revision 329)
@@ -0,0 +1,406 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::BuildTask
+#
+# DESCRIPTION
+#   This class hosts information of a build task in the FCM build system.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::BuildTask;
+
+# Standard pragma
+use strict;
+use warnings;
+
+# Standard modules
+use Carp;
+use File::Compare;
+use File::Basename;
+use File::Path;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $task = Fcm::BuildTask->new (
+#     CONFIG     => $config,
+#     TARGET     => $target,
+#     TARGETPATH => \@targetpath,
+#     SRCFILE    => $srcfile,
+#     DEPENDENCY => \@dependency,
+#     TASKTYPE   => $tasktype,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::BuildTask class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   TARGET     - target name for this task
+#   TARGETPATH - search path for the target
+#   SRCFILE    - reference to input Fcm::SrcFile instance
+#   DEPENDENCY - list of dependencies for this target
+#   TASKTYPE   - type of task to build the target
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self  = {
+    CONFIG      => exists $args{CONFIG}     ? $args{CONFIG}     : &main::cfg,
+    TARGET      => exists $args{TARGET}     ? $args{TARGET}     : undef,
+    TARGETPATH  => exists $args{TARGETPATH} ? $args{TARGETPATH} : [],
+    SRCFILE     => exists $args{SRCFILE}    ? $args{SRCFILE}    : undef,
+    DEPENDENCY  => exists $args{DEPENDENCY} ? $args{DEPENDENCY} : [],
+    ACTIONTYPE  => exists $args{ACTIONTYPE} ? $args{ACTIONTYPE} : undef,
+
+    OUTPUT      => undef,
+    OUTPUTMTIME => undef,
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $task->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile = $task->srcfile;
+#   $task->srcfile ($srcfile);
+#
+# DESCRIPTION
+#   This method returns the reference to the input Fcm::SrcFile instance
+#   associated with this task. If an argument is specified, the reference is
+#   modified to the value given by the argument.
+# ------------------------------------------------------------------------------
+
+sub srcfile {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRCFILE} = $_[0];
+  }
+
+  return $self->{SRCFILE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $actiontype = $task->actiontype;
+#   $task->actiontype ($actiontype);
+#
+# DESCRIPTION
+#   This method returns the action type of this task. If an argument is
+#   specified, the action type of this task is set to the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub actiontype {
+  my $self = shift;
+
+  if (@_) {
+    $self->{ACTIONTYPE} = $_[0];
+  }
+
+  return $self->{ACTIONTYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $output = $task->output;
+#   $task->output ($output);
+#
+# DESCRIPTION
+#   This method returns the name of the output file after the task has been
+#   performed successfully. If an argument is specified, it sets the output
+#   file (and its last modified time) to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub output {
+  my $self = shift;
+
+  if (@_) {
+    $self->{OUTPUT}      = $_[0];
+    $self->{OUTPUTMTIME} = (stat $self->{OUTPUT}) [9];
+  }
+
+  return $self->{OUTPUT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $time = $task->outputmtime;
+#
+# DESCRIPTION
+#   This method returns the modified time of the output file.
+# ------------------------------------------------------------------------------
+
+sub outputmtime {
+  my $self = shift;
+
+  return $self->{OUTPUTMTIME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $task->action (TASKLIST => \%tasklist);
+#
+# DESCRIPTION
+#   This method performs the task action and sets the output accordingly. The
+#   argument TASKLIST must be a reference to a hash containing the other tasks
+#   of the build, which this task may depend on. The keys of the hash must the
+#   name of the target names of the tasks, and the values of the hash must be
+#   the references to the corresponding Fcm::BuildTask instances. The method
+#   returns true if the task has been performed to create a new version of the
+#   target.
+# ------------------------------------------------------------------------------
+
+sub action {
+  my $self     = shift;
+  my %args     = @_;
+  my $tasklist = exists $args{TASKLIST} ? $args{TASKLIST} : {};
+
+  return unless $self->actiontype;
+
+  my $uptodate     = 1;
+  my $dep_uptodate = 1;
+
+  # Check if dependencies are up to date
+  # ----------------------------------------------------------------------------
+  for my $depend (@{ $self->{DEPENDENCY} }) {
+    if (exists $tasklist->{$depend}) {
+      if (not $tasklist->{$depend}->output) {
+        # Dependency task output is not set, performs its task action
+        if ($tasklist->{$depend}->action (TASKLIST => $tasklist)) {
+          $uptodate     = 0;
+          $dep_uptodate = 0;
+        }
+      }
+
+    } elsif ($self->config->verbose > 1) {
+      w_report 'Warning: Task for "', $depend,
+               '" does not exist, may be required by ', $self->{TARGET};
+    }
+  }
+
+  # Check if the target exists in the search path
+  # ----------------------------------------------------------------------------
+  if (@{ $self->{TARGETPATH} }) {
+    my $output = find_file_in_path ($self->{TARGET}, $self->{TARGETPATH});
+    $self->output ($output) if $output;
+  }
+
+  # Target is out of date if it does not exist
+  if ($uptodate) {
+    $uptodate = 0 if not $self->output;
+  }
+
+  # Check if current target is older than its dependencies
+  # ----------------------------------------------------------------------------
+  if ($uptodate) {
+    for my $depend (@{ $self->{DEPENDENCY} }) {
+      next unless exists $tasklist->{$depend};
+
+      if ($tasklist->{$depend}->outputmtime > $self->outputmtime) {
+        $uptodate     = 0;
+        $dep_uptodate = 0;
+      }
+    }
+
+    if ($uptodate and ref $self->srcfile) {
+      $uptodate = 0 if $self->srcfile->mtime > $self->outputmtime;
+    }
+  }
+
+  if ($uptodate) {
+    # Current target and its dependencies are up to date
+    # --------------------------------------------------------------------------
+    if ($self->actiontype eq 'PP') {
+      # "done" file up to date, set name of pre-processed source file
+      # ------------------------------------------------------------------------
+      my $base     = $self->srcfile->root . lc ($self->srcfile->ext);
+      my @pck_list = $self->srcfile->get_package_list;
+      pop @pck_list;
+      my @pknames  = split '__', pop (@pck_list);
+      my @path     = map {
+        catfile ($_, @pknames);
+      } @{ $self->config->setting (qw/PATH PPSRC/) };
+      my $oldfile = find_file_in_path ($base, \@path);
+      $self->srcfile->ppsrc ($oldfile);
+    }
+
+  } else {
+    # Perform action is not up to date
+    # --------------------------------------------------------------------------
+    # (For GENINTERFACE and PP, perform action if "done" file not up to date)
+    my $new_output = @{ $self->{TARGETPATH} }
+                     ? catfile ($self->{TARGETPATH}[0], $self->{TARGET})
+                     : $self->{TARGET};
+
+    # Create destination container directory if necessary
+    my $destdir = dirname $new_output;
+
+    if (not -d $destdir) {
+      print 'Make directory: ', $destdir, "\n" if $self->config->verbose > 2;
+      mkpath $destdir;
+    }
+
+    # List of actions
+    if ($self->actiontype eq 'UPDATE') {
+      # Action is UPDATE: Update file
+      # ------------------------------------------------------------------------
+      print 'Update: ', $new_output, "\n" if $self->config->verbose > 2;
+      touch_file $new_output
+        or croak 'Unable to update "', $new_output, '", abort';
+      $self->output ($new_output);
+
+    } elsif ($self->actiontype eq 'COPY') {
+      # Action is COPY: copy file to destination if necessary
+      # ------------------------------------------------------------------------
+      my $copy_required = ($dep_uptodate and $self->output and -r $self->output)
+                          ? compare ($self->output, $self->srcfile->src)
+                          : 1;
+
+      if ($copy_required) {
+        # Set up copy command
+        &run_command (
+          ['cp', $self->srcfile->src, $destdir],
+          TIME => $self->config->verbose > 2,
+        );
+
+        $self->output ($new_output);
+
+      } else {
+        $uptodate = 1;
+      }
+
+    } elsif ($self->actiontype eq 'PP' or $self->actiontype eq 'GENINTERFACE') {
+      # Action is PP or GENINTERFACE: process file
+      # ------------------------------------------------------------------------
+      my ($newlines, $base, @path);
+
+      if ($self->actiontype eq 'PP') {
+        # Invoke the pre-processor on the source file
+        # ----------------------------------------------------------------------
+        # Get lines in the pre-processed source
+        $newlines = $self->srcfile->pre_process;
+        $base     = $self->srcfile->root . lc ($self->srcfile->ext);
+
+        # Get search path for the existing pre-processed file
+        my @pck_list = $self->srcfile->get_package_list;
+        pop @pck_list;
+        my @pknames  = split '__', pop (@pck_list);
+        @path        = map {
+          catfile ($_, @pknames);
+        } @{ $self->config->setting (qw/PATH PPSRC/) };
+
+      } else { # if ($self->actiontype eq 'GENINTERFACE')
+        # Invoke the interface generator
+        # ----------------------------------------------------------------------
+        # Get new interface lines
+        $newlines = $self->srcfile->gen_interface;
+
+        # Get search path for the existing interface file
+        $base     = $self->srcfile->interfacebase;
+        @path     = @{ $self->config->setting (qw/PATH INC/) },
+      }
+
+
+      # If pre-processed or interface file exists,
+      # compare its content with new lines to see if it has been updated
+      my $update_required = 1;
+      my $oldfile = find_file_in_path ($base, \@path);
+
+      if ($oldfile and -r $oldfile) {
+        # Read old file
+        open FILE, '<', $oldfile;
+        my @oldlines = readline 'FILE';
+        close FILE;
+
+        # Compare old contents and new contents
+        if (@oldlines eq @$newlines) {
+          $update_required = grep {
+            $oldlines[$_] ne $newlines->[$_];
+          } (0 .. $#oldlines);
+        }
+      }
+
+      if ($update_required) {
+        # Update the pre-processed source or interface file
+        # ----------------------------------------------------------------------
+        # Determine container directory of the  pre-processed or interface file
+        my $newfile = @path ? catfile ($path[0], $base) : $base;
+
+        # Create the container directory if necessary
+        if (not -d $path[0]) {
+          print 'Make directory: ', $path[0], "\n"
+            if $self->config->verbose > 1;
+          mkpath $path[0];
+        }
+
+        # Update the pre-processor or interface file
+        open FILE, '>', $newfile
+          or croak 'Cannot write to "', $newfile, '" (', $!, '), abort';
+        print FILE @$newlines;
+        close FILE
+          or croak 'Cannot write to "', $newfile, '" (', $!, '), abort';
+        print 'Generated: ', $newfile, "\n" if $self->config->verbose > 1;
+
+        # Set the name of the pre-processed file
+        $self->srcfile->ppsrc ($newfile) if $self->actiontype eq 'PP';
+
+        # Set the "current" flag of the container source package to "true"
+        $self->srcfile->srcpackage->current (1);
+
+      } else {
+        # Content in pre-processed source or interface file is up to date
+        # ----------------------------------------------------------------------
+        $uptodate = 1;
+
+        # Set the name of the pre-processed file
+        $self->srcfile->ppsrc ($oldfile) if $self->actiontype eq 'PP';
+      }
+
+      # Update the "done" file
+      print 'Update: ', $new_output, "\n" if $self->config->verbose > 2;
+      touch_file $new_output
+        or croak 'Unable to update "', $new_output, '", abort';
+      $self->output ($new_output);
+
+    } else {
+      carp 'Action type "', $self->actiontype, "' not supported";
+    }
+  }
+
+  return not $uptodate;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CfgFile.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CfgFile.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CfgFile.pm	(revision 329)
@@ -0,0 +1,861 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CfgFile
+#
+# DESCRIPTION
+#   This class is used for reading and writing FCM config files. A FCM config
+#   file is a line-based text file that provides information on how to perform
+#   a particular task using the FCM system.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CfgFile;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Basename;
+use File::Path;
+use File::Spec;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::Util;
+
+# Local module variables
+my $expand_type   = 'bld|ext'; # config file type that needs variable expansions
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = Fcm::CfgFile->new (CONFIG=> $config, SRC => $src, TYPE => $type);
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CfgFile class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   SRC    - configuration file source
+#   TYPE   - type of expected configuration file
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG     => exists $args{CONFIG} ? $args{CONFIG} : &main::cfg,
+    SRC        => exists $args{SRC}    ? $args{SRC}    : undef,
+    TYPE       => exists $args{TYPE}   ? $args{TYPE}   : undef,
+
+    # Version of the configuration file
+    VERSION    => undef,
+
+    # List of references to hash tables for each line in the file
+    LINES      => [],
+
+    # Actual source of configuration file
+    ACTUAL_SRC => undef,
+    PEGREV     => undef,
+  };
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $cfgfile->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $src = $cfgfile->src ();
+#   $cfgfile->src ($src);
+#
+# DESCRIPTION
+#   This method returns the specified source of the configuration file. If an
+#   argument is specified, the source of the configuration file is modified to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub src {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRC} = shift;
+  }
+
+  return $self->{SRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $src = $cfgfile->actual_src ();
+#
+# DESCRIPTION
+#   This method returns the actual source of the configuration file. If an
+#   argument is specified, the source of the configuration file is modified to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub actual_src {
+  my $self = shift;
+
+  return $self->{ACTUAL_SRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cfgfile->pegrev ();
+#
+# DESCRIPTION
+#   This method returns the peg revision of the configuration file.
+# ------------------------------------------------------------------------------
+
+sub pegrev {
+  my $self = shift;
+
+  return $self->{PEGREV};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $cfgfile->type ();
+#   $cfgfile->type ($type);
+#
+# DESCRIPTION
+#   This method returns the configuration file type. If an argument is
+#   specified, the type is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $cfgfile->version ();
+#
+# DESCRIPTION
+#   This method returns the version of the configuration file.
+# ------------------------------------------------------------------------------
+
+sub version {
+  my $self = shift;
+
+  return $self->{VERSION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @lines = $cfgfile->lines ();
+#
+# DESCRIPTION
+#   This method returns an array containing all "lines" in the configuration
+#   file. Each "line" is a reference to a hash table with the following keys:
+#
+#   SRC     - the source of the configuration file
+#   NUMBER  - the line number in the source
+#   LABEL   - the label of the of the configuration line
+#   VALUE   - the value of the configuration line
+#   COMMENT - comment in the configuration line
+# ------------------------------------------------------------------------------
+
+sub lines {
+  my $self = shift;
+
+  return @{ $self->{LINES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $line = $cfgfile->line ($line_number);
+#
+# DESCRIPTION
+#   This method return a "line" at $line_number in the configuration file. A
+#   "line" is a reference to a hash table with the following keys:
+#
+#   SRC     - the source of the configuration file
+#   NUMBER  - the line number in the source
+#   LABEL   - the label of the of the configuration line
+#   VALUE   - the value of the configuration line
+#   COMMENT - comment in the configuration line
+# ------------------------------------------------------------------------------
+
+sub line {
+  my $self     = shift;
+  my $line_num = shift;
+
+  if (exists $self->{LINES}[$line_num]) {
+    return $self->{LINES}[$line_num]; # returns a ref to a label:value pair hash
+
+  } else {
+    return undef;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile->add_line (
+#     LABEL   => $label,
+#     VALUE   => $value,
+#     COMMENT => $comment,
+#     SRC     => $src,
+#     NUMBER  => $line_number
+#   );
+#
+# DESCRIPTION
+#   This method adds a "line" to the configuration file. LABEL is the
+#   configuration line label. VALUE is the configuration line value. COMMENT
+#   is the comment in the line. VALUE should only be specified if LABEL is
+#   specified. COMMENT can be specified without LABEL. In such case, the whole
+#   line is a comment line. A blank line is inserted if no argument is
+#   specified. SRC can be specified to indicate the name of the source file
+#   from which this line is obtained. If not specified, the source file of the
+#   current configuration file is used. NUMBER can be specified to indicate
+#   the line number of the source file from which this line is obtained.
+# ------------------------------------------------------------------------------
+
+sub add_line {
+  my $self = shift;
+  my %args = @_;
+
+  my $line = {
+    SRC     => exists $args{SRC    } ? $args{SRC    } : $self->actual_src,
+    NUMBER  => exists $args{NUMBER } ? $args{NUMBER } : 0,
+    LABEL   => exists $args{LABEL  } ? $args{LABEL  } : '',
+    VALUE   => exists $args{VALUE  } ? $args{VALUE  } : '',
+    COMMENT => exists $args{COMMENT} ? $args{COMMENT} : '',
+  };
+
+  push @{ $self->{LINES} }, $line;
+
+  return $line;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile->add_comment_block ($line1, [$line2, ...]);
+#
+# DESCRIPTION
+#   This method adds a comment block to the configuration file. Each argument
+#   represents a line in the comment block.
+# ------------------------------------------------------------------------------
+
+sub add_comment_block {
+  my $self = shift;
+
+  $self->add_line (COMMENT => '-' x 78,);
+
+  while (my $line = shift @_) {
+    $self->add_line (COMMENT => $line,)
+  }
+
+  $self->add_line (COMMENT => '-' x 78,);
+  $self->add_line;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile->add_header ();
+#
+# DESCRIPTION
+#   This method adds a header to the configuration file, with its type and
+#   type version. It returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub add_header {
+  my $self = shift;
+
+  return undef unless $self->{TYPE};
+
+  $self->{VERSION} = $self->config->setting ('CFG_VERSION', uc ($self->{TYPE}))
+    if not $self->{VERSION};
+
+  $self->add_comment_block ('File header');
+
+  $self->add_line (
+    LABEL => $self->config->setting (qw/CFG_LABEL CFGFILE TYPE/),
+    VALUE => $self->{TYPE},
+  );
+
+  $self->add_line (
+    LABEL => $self->config->setting (qw/CFG_LABEL CFGFILE VERSION/),
+    VALUE => $self->{VERSION},
+  );
+
+  $self->add_line;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $exist = $cfg->label_exists ($label);
+#   @lines = $cfg->label_exists ($label);
+#
+# DESCRIPTION
+#   This method returns the (number of) "lines" with their LABEL matching the
+#   argument $label.
+# ------------------------------------------------------------------------------
+
+sub label_exists {
+  my $self  = shift;
+  my $label = shift;
+
+  return grep {$_->{LABEL} eq $label} @{ $self->{LINES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $mtime = $cfgfile->mtime ();
+#
+# DESCRIPTION
+#   This method returns the modified time of the configuration file source.
+# ------------------------------------------------------------------------------
+
+sub mtime {
+  my $self  = shift;
+  my $mtime = undef;
+
+  if (-f $self->{SRC}) {
+    $mtime = (stat $self->{SRC})[9];
+  }
+
+  return $mtime;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $read = $cfgfile->read_cfg ();
+#
+# DESCRIPTION
+#   This method reads the current configuration file. It returns the number of
+#   lines read from the config file, or "undef" if it fails. The result is
+#   placed in the LINES array of the current instance, and can be accessed via
+#   the "lines" method.
+# ------------------------------------------------------------------------------
+
+sub read_cfg {
+  my $self = shift;
+
+  my @lines = $self->_get_cfg_lines;
+
+  # List of CFG labels
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+
+  # List of CFG types that need INC declarations expansion
+  my %exp_inc    = ();
+  for (split (/,/, $self->config->setting ('CFG_EXP_INC'))) {
+    $exp_inc{uc ($_)} = 1;
+  }
+
+  # List of CFG labels that are reserved keywords
+  my %cfg_keywords = ();
+  for (split (/,/, $self->config->setting ('CFG_KEYWORD'))) {
+    $cfg_keywords{$cfg_labels{$_}} = 1;
+  }
+
+  # Loop each line, to separate lines into label : value pairs
+  my $cont = undef;
+  my $here = undef;
+  for my $line_num (1 .. @lines) {
+    my $line = $lines[$line_num - 1];
+    chomp $line;
+
+    my $label   = '';
+    my $value   = '';
+    my $comment = '';
+
+    # If this line is a continuation, set $start to point to the line that
+    # starts this continuation. Otherwise, set $start to undef
+    my $start   = defined ($cont) ? $self->line ($cont) : undef;
+
+    if ($line =~ /^(\s*#.*)$/) { # comment line
+      $comment = $1;
+
+    } elsif ($line =~ /\S/) {    # non-blank line
+      if (defined $cont) {
+        # Previous line has a continuation mark
+        $value = $line;
+
+        # Separate value and comment
+        if ($value =~ s/((?:\s+|^)#\s+.*)$//) {
+          $comment = $1;
+        }
+
+        # Remove leading spaces
+        $value =~ s/^\s*\\?//;
+
+        # Expand environment variables
+        $value = $self->_expand_variable ($value, 1) if $value;
+
+        # Expand internal variables
+        $value = $self->_expand_variable ($value) if $value;
+
+        # Get "line" that begins the current continuation
+        ($start->{VALUE} .= $value) =~ s/\\$//;
+
+      } else {
+        # Previous line does not have a continuation mark
+        if ($line =~ /^\s*(\S+)(?:\s+(.*))?$/) {
+          # Check line contains a valid label:value pair
+          $label = $1;
+          $value = defined ($2) ? $2 : '';
+
+          # Separate value and comment
+          if ($value =~ s/((?:\s+|^)#\s+.*)$//) {
+            $comment = $1;
+          }
+
+          # Remove trailing spaces
+          $value =~ s/\s+$//;
+
+          # Value begins with $HERE?
+          $here  = ($value =~ /\$\{?HERE\}?(?:[^A-Z_]|$)/);
+
+          # Expand environment variables
+          $value = $self->_expand_variable ($value, 1) if $value;
+
+          # Expand internal variables
+          $value = $self->_expand_variable ($value) if $value;
+        }
+      }
+
+      # Determine whether current line ends with a continuation mark
+      if ($value =~ s/\\$//) {
+        $cont = scalar ($self->lines) unless $cont;
+
+      } else {
+        $cont = undef;
+      }
+    }
+
+    if (exists $exp_inc{uc ($self->type)} and
+        uc ($start ? $start->{LABEL} : $label) eq $cfg_labels{INC} and
+        not defined $cont) {
+      # Current configuration file requires expansion of INC declarations
+      # The start/current line is an INC declaration
+      # The current line is not a continuation or is the end of the continuation
+
+      # Get lines from an "include" configuration file
+      my $src = ($start ? $start->{VALUE} : $value);
+      $src   .= '@' . $self->pegrev if $here and $self->pegrev;
+
+      if ($src) {
+        # Invoke a new instance to read the source
+        my $cfg = Fcm::CfgFile->new (
+          SRC    => expand_tilde ($src),
+          TYPE   => $self->type,
+          CONFIG => $self->config,
+        );
+
+        $cfg->read_cfg;
+
+        # Add lines to the "LINES" array in the current configuration file
+        $comment = 'INC ' . $src . ' ';
+        $self->add_line (
+          COMMENT => $comment . '# Start',
+          NUMBER  => ($start ? $start->{NUMBER} : $line_num),
+        );
+        $self->add_line (%{ $_ }) for (($cfg->lines));
+        $self->add_line (COMMENT => $comment . '# End');
+
+      } else {
+        $self->add_line (NUMBER  => $line_num);
+        w_report 'Warning: ', $self->actual_src, ': line ', $line_num,
+                 ': empty INC declaration.' if $self->config->verbose > 2;
+      }
+
+    } else {
+      # Push label:value pair into "LINES" array
+      $self->add_line (
+        LABEL   => $label,
+        VALUE   => ($label ? $value : ''),
+        COMMENT => $comment,
+        NUMBER  => $line_num,
+      );
+    }
+
+    next if defined $cont; # current line not a continuation
+
+    my $slabel = ($start ? $start->{LABEL} : $label);
+    my $svalue = ($start ? $start->{VALUE} : $value);
+    next unless $slabel;
+
+    # Check config file type and version
+    if (uc ($slabel) eq $cfg_labels{CFGFILE}{TYPE}) {
+      $self->type ($svalue);
+
+    } elsif (uc ($slabel) eq $cfg_labels{CFGFILE}{VERSION}) {
+      $self->version ($svalue);
+    }
+
+    # Set internal variable
+    $slabel =~ s/^\%//; # Remove leading "%" from label
+
+    $self->config->assign_variable (
+      LABEL => $slabel,
+      VALUE => $svalue,
+    ) unless exists $cfg_keywords{$slabel};
+  }
+
+  return $self->lines;
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $cfgfile->print_cfg ($file);
+#
+# DESCRIPTION
+#   This method prints the content of current configuration file. If no
+#   argument is specified, it prints output to the standard output. If $file
+#   is specified, and is a writable file name, the output is sent to the file.
+#   If the file already exists, its content is compared to the current output.
+#   Nothing will be written if the content is unchanged. Otherwise, for typed
+#   configuration files, the existing file is renamed using a prefix that
+#   contains its last modified time. The method returns 1 if there is no
+#   error.
+# ------------------------------------------------------------------------------
+
+sub print_cfg {
+  my $self = shift;
+  my $file = shift;
+
+  # Count maximum number of characters in the labels, (for pretty printing)
+  my $max_label_len = 0;
+  for my $line (@{ $self->{LINES} }) {
+    next unless $line->{LABEL};
+    my $label_len  = length $line->{LABEL};
+    $max_label_len = $label_len if $label_len > $max_label_len;
+  }
+
+  # Output string
+  my $out = '';
+
+  # Append each line of the config file to the output string
+  for my $line (@{ $self->{LINES} }) {
+    my $label   = $line->{LABEL};
+    my $value   = $line->{VALUE};
+    my $comment = $line->{COMMENT};
+
+    if ($label) {
+      # Line up label/value for pretty printing
+      $label   = $label . ' ' x ($max_label_len - length ($label));
+      $comment =~ s/^\s+/ / if $comment;
+
+      $out .= $label;
+      $out .= ' ' . $value if defined $value;
+
+    } else {
+      # Make sure comments begin with a "#"
+      $comment = '# ' . $comment if $comment and $comment !~ /^\s*($|#)/;
+      $comment =~ s/^\s*//;
+    }
+
+    $out .= $comment if $comment;
+    $out .= "\n";
+  }
+
+  if ($out) {
+
+    my $old_select = select;
+
+    # Open file if necessary
+    if ($file) {
+      # Make sure the host directory exists and is writable
+      my $dirname = dirname $file;
+      if (not -d $dirname) {
+        print 'Make directory: ', $dirname, "\n" if $self->config->verbose;
+        mkpath $dirname;
+      }
+      croak 'Cannot write to config file directory: "', $dirname, '", abort'
+        unless -d $dirname and -w $dirname;
+
+      # If config file already exists, make sure it is writable
+      if (-f $file) {
+        if (-r $file) {
+          # Read old config file to see if content has changed
+          open IN, '<', $file;
+          my $in_lines = '';
+          while (my $line = <IN>) {
+            $in_lines .= $line;
+          }
+          close IN;
+
+          # Return if content is up-to-date
+          if ($in_lines eq $out) {
+            print 'No change in ', lc ($self->{TYPE}), ' cfg: ', $file,
+                  "\n" if $self->config->verbose > 1 and $self->{TYPE};
+            return;
+          }
+        }
+
+        if (-w $file) {
+          if ($self->{TYPE}) {
+            # Existing config file writable, rename it using its time stamp
+            my $mtime = (stat $file)[9];
+            my ($sec, $min, $hour, $mday, $mon, $year) = (gmtime $mtime)[0 .. 5];
+            my $timestamp = sprintf '%4d%2.2d%2.2d_%2.2d%2.2d%2.2d_',
+                            $year + 1900, $mon + 1, $mday, $hour, $min, $sec;
+            my $oldfile   = catfile $dirname, $timestamp . basename ($file);
+            rename $file, $oldfile;
+            print 'Renamed existing ', lc ($self->{TYPE}), ' cfg: ',
+                  $oldfile, "\n" if $self->config->verbose > 1;
+          }
+        } else {
+          # Existing config file not writable, throw an error
+          croak 'Config file "', $file, '" not writable, abort';
+        }
+      }
+
+      # Open file and select file handle
+      open OUT, '>', $file
+        or croak 'Cannot write to config file "', $file, '" (', $!, '), abort';
+      select OUT;
+    }
+
+    # Print output
+    print $out;
+
+    # Close file if necessary
+    if ($file) {
+      select $old_select;
+      close OUT;
+
+      if ($self->{TYPE} and $self->config->verbose > 1) {
+        print 'Generated ', lc ($self->{TYPE}), ' cfg: ', $file, "\n";
+      } elsif ($self->config->verbose > 2) {
+        print 'Generated cfg: ', $file, "\n";
+      }
+    }
+
+  } else {
+
+    # Warn if nothing to print
+    my $warning = 'Empty configuration';
+    $warning   .= ' - nothing written to file: "' . $file . '"' if $file;
+    carp $warning if $self->{TYPE};
+
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @lines = $self->_get_cfg_lines ();
+#
+# DESCRIPTION
+#   This internal method reads from a configuration file residing in a
+#   Subversion repository or in the normal file system.
+# ------------------------------------------------------------------------------
+
+sub _get_cfg_lines {
+  my $self  = shift;
+  my @lines = ();
+
+  my $verbose = $self->config->verbose;
+
+  # Expand URL keywords if necessary
+  {
+    my $src = expand_url_keyword (URL => $self->src, CFG => $self->config);
+    $self->src ($src) if $src ne $self->src;
+  }
+
+  if (&is_url ($self->src)) {
+    # Config file resides in a SVN repository
+    # --------------------------------------------------------------------------
+    # Set URL source and version
+    my $src = $self->src;
+    my $rev = 'HEAD';
+
+    # Extract version from source if it exists
+    if ($src =~ s/@(.+)$//) {
+      $rev = $1;
+    }
+
+    # Expand revision keyword, if required
+    $rev = expand_rev_keyword (REV => $rev, URL => $src, HEAD => 1);
+
+    # Check whether URL is a config file
+    my $rc;
+    my @cmd = (qw/svn cat/, $src . '@' . $rev);
+    @lines = &run_command (
+      \@cmd, METHOD => 'qx', DEVNULL => 1, RC => \$rc, ERROR => 'ignore',
+    );
+
+    # Error in "svn cat" command
+    if ($rc) {
+      # See whether specified config file is a known type
+      my %cfgname = %{ $self->config->setting ('CFG_NAME') };
+      my $key     = uc $self->type;
+      my $file    = exists $cfgname{$key} ? $cfgname{$key} : '';
+
+      # If config file is a known type, specified URL may be a directory
+      if ($file) {
+        # Check whether a config file with a default name exists in the URL
+        my $sep  = $self->config->setting (qw/MISC DIR_SEPARATOR/);
+        my $path = $src . $sep . $file;
+        my @cmd  = (qw/svn cat/, $path . '@' . $rev);
+
+        @lines = &run_command (
+          \@cmd, METHOD => 'qx', DEVNULL => 1, RC => \$rc, ERROR => 'ignore',
+        );
+
+        # Check whether a config file with a default name exists under the "cfg"
+        # sub-directory of the URL
+        if ($rc) {
+          my $cfgdir = $self->config->setting (qw/DIR CFG/);
+          $path   = $src . $sep . $cfgdir . $sep . $file;
+          my @cmd = (qw/svn cat/, $path . '@' . $rev);
+
+          @lines  = &run_command (
+            \@cmd, METHOD => 'qx', DEVNULL => 1, RC => \$rc, ERROR => 'ignore',
+          );
+        }
+
+        $src = $path unless $rc;
+      }
+    }
+
+    if ($rc) {
+      # Error in "svn cat"
+      croak 'Unable to locate config file from "', $self->src, '", abort';
+
+    } else {
+      # Print diagnostic, if necessary
+      if ($verbose and $self->type and $self->type =~ /$expand_type/) {
+        print '# Config file (', $self->type, '): ', $src;
+        print '@', $rev if $rev;
+        print "\n";
+      }
+    }
+
+    # Record the actual source location
+    $self->{PEGREV    } = $rev;
+    $self->{ACTUAL_SRC} = $src;
+
+  } else {
+    # Config file resides in the normal file system
+    # --------------------------------------------------------------------------
+    my $src = $self->src;
+
+    if (-d $src) { # Source is a directory
+      croak 'Config file "', $src, '" is a directory, abort' if not $self->type;
+
+      # Get name of the config file by looking at the type
+      my %cfgname = %{ $self->config->setting ('CFG_NAME') };
+      my $key     = uc $self->type;
+      my $file    = exists $cfgname{$key} ? $cfgname{$key} : '';
+
+      if ($file) {
+        my $cfgdir = $self->config->setting (qw/DIR CFG/);
+
+        # Check whether a config file with a default name exists in the
+        # specified path, then check whether a config file with a default name
+        # exists under the "cfg" sub-directory of the specified path
+        if (-f catfile $self->src, $file) {
+          $src = catfile $self->src, $file;
+
+        } elsif (-f catfile ($self->src, $cfgdir, $file)) {
+          $src = catfile $self->src, $cfgdir, $file;
+
+        } else {
+          croak 'Unable to locate config file from "', $self->src, '", abort';
+        }
+
+      } else {
+        croak 'Unknown config file type "', $self->type, '", abort';
+      }
+    }
+
+    if (-r $src) {
+      open FILE, '<', $src;
+      print '# Config file (', $self->type, '): ', $src, "\n"
+        if $verbose and $self->type and $self->type =~ /$expand_type/;
+
+      @lines = readline 'FILE';
+      close FILE;
+
+    } else {
+      croak 'Unable to read config file "', $src, '", abort';
+    }
+
+    # Record the actual source location
+    $self->{ACTUAL_SRC} = $src;
+  }
+
+  return @lines;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $self->_expand_variable ($string[, $env]);
+#
+# DESCRIPTION
+#   This internal method expands variables in $string. If $env is specified
+#   and is true, it expands environment variables. Otherwise, it expands
+#   local variables.
+# ------------------------------------------------------------------------------
+
+sub _expand_variable {
+  my ($self, $string, $env) = @_;
+
+  # Pattern for environment/local variable
+  my $pattern = $env ? '\$\{?([A-Z][A-Z0-9_]+)\}?' : '%\{?([\w:]+)\}?';
+
+  while ($string and $string =~ /$pattern/) {
+    my $var_label = $1; # variable label
+
+    # Get variable value from environment or local configuration
+    my $variable = $env
+                   ? (exists $ENV{$var_label} ? $ENV{$var_label} : undef)
+                   : $self->config->variable ($var_label);
+
+    $variable = dirname ($self->actual_src)
+      if $env and $var_label eq 'HERE' and not defined $variable;
+
+    # Substitute match with value of variable
+    if (defined $variable) {
+      $string =~ s/$pattern/$variable/;
+
+    } else {
+      w_report 'Warning: ', $self->actual_src, ': variable "',
+               ($env ? '$' : '%'), $var_label, '" not expanded.';
+      last;
+    }
+  }
+
+  return $string;
+}
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Cm.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Cm.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Cm.pm	(revision 329)
@@ -0,0 +1,2150 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Cm
+#
+# DESCRIPTION
+#   This module contains the FCM code management functionalities and wrappers
+#   to Subversion commands.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Cm;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+our (@ISA, @EXPORT, @EXPORT_OK);
+use Getopt::Long;
+use File::Basename;
+use File::Path;
+use File::Spec;
+use File::Temp qw/tempfile/;
+use Cwd;
+
+# FCM component modules
+use Fcm::CmBranch;
+use Fcm::CmUrl;
+use Fcm::Util;
+
+sub cm_command;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(
+  cm_command
+);
+
+# Function declaration:
+sub cm_add;
+sub cm_branch;
+sub cm_commit;
+sub cm_conflicts;
+sub cm_delete;
+sub cm_diff;
+sub cm_merge;
+sub cm_mkpatch;
+sub cm_svn;
+sub cm_switch;
+sub _construct_branch_url;
+
+# ------------------------------------------------------------------------------
+
+my @subcommand_url = qw/
+  branch    br
+  blame     praise annotate ann
+  cat
+  checkout  co
+  copy      cp
+  delete    del    remove   rm
+  diff      di
+  export
+  import
+  info
+  list      ls
+  lock
+  log
+  merge
+  mkdir
+  mkpatch
+  move      mv     rename   ren
+  propdel   pdel   pd
+  propedit  pedit  pe
+  propget   pget   pg
+  proplist  plist  pl
+  propset   pset   ps
+  switch    sw
+  unlock
+/; # List of subcommands that accept URL inputs
+
+my @subcommand_rev = qw/
+  blame     praise annotate ann
+  branch    br
+  cat
+  checkout  co
+  copy      cp
+  diff      di
+  export
+  info
+  list      ls
+  log
+  merge
+  mkpatch
+  move      mv     rename   ren
+  propdel   pdel   pd
+  propedit  pedit  pe
+  propget   pget   pg
+  proplist  plist  pl
+  propset   pset   ps
+  update    up
+/; # List of subcommands that accept revision inputs
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &cm_command ($function);
+#
+# DESCRIPTION
+#   This is the generic FCM code management wrapper. It calls the correct FCM
+#   code management function or a wrapper to a Subversion command based on the
+#   value of the argument $function.
+# ------------------------------------------------------------------------------
+
+sub cm_command {
+
+  my ($function) = shift @_;
+
+  # Expand URL keywords if necessary
+  if (grep {$_ eq $function} @subcommand_url) {
+    for my $arg (@ARGV) {
+      my $var = expand_url_keyword (URL => $arg);
+      $arg = $var if $arg ne $var;
+    }
+  }
+
+  # Expand revision keywords (for -r or --revision options) if necessary
+  if (grep {$_ eq $function} @subcommand_rev) {
+    my @new_argv = ();
+
+    while (defined (my $arg = shift @ARGV)) {
+      if ($arg eq '--revision') {
+        # Long --revision option, must be followed by a space before the
+        # revision argument
+        push @new_argv, $arg;
+
+      } elsif ($arg =~ s/^-r//) {
+        # Short -r option, may be followed by the revision argument with or
+        # without a space in between
+        push @new_argv, '--revision';
+        unshift @ARGV, $arg if $arg;
+
+      } else {
+        # Other option or argument
+        push @new_argv, $arg;
+        next;
+      }
+
+      # First revision number/keyword
+      my $rev1 = '';
+
+      # Get the next argument from the list
+      $arg = shift @ARGV;
+
+      if (index ($arg, '{') == 0) {
+        # A revision date argument may contain a space. Therefore, it may need
+        # the next argument(s) from the list
+        while (index ($arg, '}') == -1) {
+          my $shift = shift @ARGV;
+          last unless $shift;
+          $arg     .= ' ' . $shift;
+        }
+
+        $arg  =~ s/^(\{.+?\})//;
+        $rev1 = $1;
+
+      } else {
+        # Other revision argument
+        $arg  =~ s/^(\S+?)(?::|$)//;
+        $rev1 = $1;
+      }
+
+      # The rest of $arg is the second revision number/keyword
+      my $rev2 = $arg;
+      $rev2 =~ s/^:*//;
+
+      # A revision date argument may contain a space. Therefore, it may need
+      # the next argument(s) from the list
+      if (index ($rev2, '{') == 0) {
+        while (index ($rev2, '}') == -1) {
+          my $shift = shift @ARGV;
+          last unless $shift;
+          $rev2    .= ' ' . $shift;
+        }
+      }
+
+      # Expand revision keyword if necessary
+      if ($rev1 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i or
+          $rev2 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i) {
+        # Find out the associated URLs by inspecting the argument list
+        my $url1 = '';
+        my $url2 = '';
+
+        for (@new_argv, @ARGV) {
+          my $arg = Fcm::CmUrl->new (URL => $_);
+          next unless $arg->is_url;
+
+          if ($url1) {
+            $url2 = $arg->url_peg;
+            last;
+
+          } else {
+            $url1 = $arg->url_peg;
+          }
+        }
+
+        # Argument list does not contain a URL, try "svn info" on WC
+        $url1 = &get_url_of_wc () if not $url1;
+        $url2 = $url1 if not $url2;
+
+        # Expand 1st revision keyword if necessary
+        $rev1 = expand_rev_keyword (REV => $rev1, URL => $url1)
+          if $rev1 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i;
+
+        # Expand 2nd revision keyword if necessary
+        $rev2 = expand_rev_keyword (REV => $rev2, URL => $url2)
+          if $rev2 and $rev2 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i;
+      }
+
+      # Append revision argument to argument list
+      push @new_argv, ($rev2 ? $rev1 . ':' . $rev2 : $rev1);
+    }
+
+    @ARGV = @new_argv;
+  }
+
+  # Expand revision keywords (for peg revision TARGET@REVSION) if necessary
+  for (@ARGV) {
+    if (m#^(\w+://\S+)@(\S+)$#) {
+      my $url = $1;
+      my $rev = $2;
+
+      my $new_rev = expand_rev_keyword (URL => $url, REV => $rev, HEAD => 1);
+
+      $_ = $url . '@' . $new_rev if $new_rev ne $rev;
+    }
+  }
+
+  # List of special sub-commands recognised by FCM
+  my %subcommand = (
+    ADD       => [qw/add/],
+    BRANCH    => [qw/branch br/],
+    COMMIT    => [qw/commit ci/],
+    CONFLICTS => [qw/conflicts cf/],
+    CHECKOUT  => [qw/checkout co/],
+    DELETE    => [qw/delete del remove rm/],
+    DIFF      => [qw/diff di/],
+    MERGE     => [qw/merge/],
+    MKPATCH   => [qw/mkpatch/],
+    SWITCH    => [qw/switch sw/],
+  );
+
+  if (grep {$_ eq $function} @{ $subcommand{ADD} }) {
+    cm_add;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{BRANCH} }) {
+    cm_branch;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{CHECKOUT} }) {
+    # Check whether the last argument is a PATH.
+    # If so, check whether it is a working copy.
+    # Otherwise, check whether the current directory is a working copy.
+    # If current working direcory (or PATH) is a working copy, fail the command.
+    if (@ARGV) {
+      my $arg  = Fcm::CmUrl->new (URL => $ARGV [-1]);
+      my $path = $arg->is_url ? cwd () : $ARGV [-1];
+
+      e_report $path, ': already a working copy, abort checkout.'
+        if &is_wc ($path);
+    }
+
+    # Invoke checkout
+    cm_svn ('checkout');
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{COMMIT} }) {
+    cm_commit;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{CONFLICTS} }) {
+    cm_conflicts;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{DELETE} }) {
+    cm_delete;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{DIFF} }) {
+    cm_diff;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{MERGE} }) {
+    cm_merge;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{MKPATCH} }) {
+    cm_mkpatch;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{SWITCH} }) {
+    cm_switch;
+
+  } else {
+    cm_svn ($function);
+  }
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_add ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn add". It adds an extra functionality to check
+#   for any files or directories reported by "svn status" as not under version
+#   control, and to prompt the user whether these files or directories should
+#   be added.
+# ------------------------------------------------------------------------------
+
+sub cm_add {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+usage: fcm add [options] [args]
+
+Valid options:
+  -c [--check]  : Check for any files or directories reported by svn status as
+                  not under version control and add them.
+  <SVN options> : Standard options to svn add as described below ...
+
+EOF
+
+    &run_command ([qw/svn add --help/], PRINT => 1, METHOD => 'exec');
+  }
+
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--check -c)) {
+    # The --check option is specified, add any new files
+    # Execute "svn status", print lines starting with a "?"
+    my $pat    = '^\?.{4}\s*';
+    my @status = grep /$pat.*/, &run_command ([qw/svn status/], METHOD => 'qx');
+    print @status if @status;
+
+    # Get list of "?" files
+    my @files  = map {chomp; s/$pat//; $_} @status;
+    my $reply  = '';
+
+    # Execute "add" command depending on user reply
+    for my $file (@files) {
+      # Get a user reply, unless previous reply is "a" for "all"
+      $reply = &main::get_input (
+        TITLE   => 'fcm add',
+        MESSAGE => "Add file '$file'?",
+        TYPE    => 'yna',
+        DEFAULT => 'n',
+      ) unless $reply eq "a";
+
+      # Add current $file if reply is "y" for "yes" or "a" for "all"
+      &run_command ([qw/svn add/, $file]) if $reply =~ /^[ya]$/;
+    }
+
+  } else {
+    # The --check option is not specified, just call "svn add"
+    cm_svn ("add");
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_branch ();
+#
+# DESCRIPTION
+#   This is a FCM command to check information, create or delete a branch in
+#   a Subversion repository.
+# ------------------------------------------------------------------------------
+
+sub cm_branch {
+  my $usage = <<EOF;
+branch: Create, delete or display information of a branch
+usage: 1. fcm branch [--info] [OPTIONS] [TARGET]
+       2. fcm branch --delete [OPTIONS] [TARGET]
+       3. fcm branch --create [OPTIONS] [SOURCE]
+       4. fcm branch --list   [OPTIONS] [SOURCE]
+
+  1. Display information about a branch. This is the default option if --create,
+     --delete and --list are not specified.
+
+  2. Delete a branch.
+
+  3. Create a new branch from SOURCE. The --name option must be used to specify
+     a short name for the new branch.
+
+  4. List all the branches owned by the current user in SOURCE. If the --user
+     option is specified with a list of users, list all the branches owned by
+     these users instead of the current user.
+
+  TARGET (and SOURCE) can be an URL or a Subversion working copy. Otherwise,
+  the current working directory must be a working copy. For --info and
+  --delete, the specified URL (or the URL of the working copy) must be a URL
+  under a valid branch in a standard FCM project. For --create and --list, it
+  must be a URL under a standard FCM project.
+
+Valid options with --info and --delete:
+  -v [--verbose]        : Print extra information.
+  -a [--show-all]       : Set --show-children, --show-other and --show-siblings.
+  --show-children       : Report children of the current branch.
+  --show-other          : Report custom/ reverse merges into the current branch.
+  --show-siblings       : Report merges with siblings of the current branch.
+
+Valid options with --delete and --create:
+  --non-interactive     : Do no interactive prompting. This option implies
+                          --svn-non-interactive.
+  --password arg        : Specify a password for write access to the repository.
+  --svn-non-interactive : Do no interactive prompting at commit time. This
+                          option is implied by --non-interactive.
+
+Valid options with --create and --list:
+  -r [--revision] arg   : Specify the operative revision of the SOURCE for
+                          creating the branch.
+
+Valid options with --create:
+  --branch-of-branch    : If this option is specified and the SOURCE is a
+                          branch, it will create a new branch from the SOURCE
+                          branch. Otherwise, the branch is created from the
+                          trunk.
+  -k [--ticket] arg     : Specify one (or more) Trac ticket. If specified, the
+                          command will add to the commit log the line "Relates
+                          to ticket #<ticket>". Multiple tickets can be set by
+                          specifying this option multiple times, or by
+                          specifying the tickets in a comma-separated list.
+  -n [--name] arg       : Specify a short name for the branch, which should
+                          contain only word characters, i.e. [A-Za-z0-9_].
+  --rev-flag arg        : Specify a flag for determining the prefix of the
+                          branch name. The flag can be the the string "NORMAL",
+                          "NUMBER" or "NONE".  "NORMAL" is the default
+                          behaviour, in which the branch name will be prefixed
+                          with a Subversion revision number if the revision is
+                          not associated with a registered FCM revision
+                          keyword. If the revision is registered with a FCM
+                          revision keyword, the keyword will be used in place
+                          of the number. If "NUMBER" is specified, the branch
+                          name will always be prefixed with a Subversion
+                          revision number. If "NONE" is specified, the branch
+                          name will not be prefixed by a revision number or
+                          keyword.
+  -t [--type] arg       : Specify the type of the branch to be created. It must
+                          be one of the following:
+                            DEV::USER   - a development branch for the user
+                            DEV::SHARE  - a shared development branch
+                            DEV         - same as DEV::USER
+                            TEST::USER  - a test branch for the user
+                            TEST::SHARE - a shared test branch
+                            TEST        - same as TEST::USER
+                            PKG::USER   - a package branch for the user
+                            PKG::SHARE  - a shared package branch
+                            PKG::CONFIG - a configuration branch
+                            PKG::REL    - a release branch
+                            PKG         - same as PKG::USER
+                            CONFIG      - same as PKG::CONFIG
+                            REL         - same as PKG::REL
+                            SHARE       - same as DEV::SHARE
+                            USER        - same as DEV::USER
+                          If not specified, the default is to create a
+                          development branch for the current user, i.e.
+                          DEV::USER.
+
+Valid options with --list:
+  -u [--user] arg       : Specify a colon-separated list of users. List branches
+                          owned by these users instead of the current user.
+EOF
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print $usage;
+    return 1;
+  }
+
+  # Process command line options
+  # ----------------------------------------------------------------------------
+  my (
+    $info,
+    $delete,
+    $create,
+    $list,
+    $branch_of_branch,
+    $name,
+    $non_interactive,
+    $password,
+    $rev,
+    $rev_flag,
+    $show_all,
+    $show_children,
+    $show_other,
+    $show_siblings,
+    $svn_non_interactive,
+    @tickets,
+    $type,
+    @userlist,
+    $verbose,
+  );
+  GetOptions (
+    'info|i'              => \$info,
+    'delete|d'            => \$delete,
+    'create|c'            => \$create,
+    'list|l'              => \$list,
+    'branch-of-branch'    => \$branch_of_branch,
+    'name|n=s'            => \$name,
+    'non-interactive'     => \$non_interactive,
+    'password=s'          => \$password,
+    'revision|r=s'        => \$rev,
+    'rev-flag=s'          => \$rev_flag,
+    'show-all|a'          => \$show_all,
+    'show-children'       => \$show_children,
+    'show-other'          => \$show_other,
+    'show-siblings'       => \$show_siblings,
+    'svn-non-interactive' => \$svn_non_interactive,
+    'ticket|k=s'          => \@tickets,
+    'type|t=s'            => \$type,
+    'user|u=s'            => \@userlist,
+    'verbose|v'           => \$verbose,
+  );
+
+  my $num_options = 0;
+  $num_options++ if defined $info;
+  $num_options++ if defined $delete;
+  $num_options++ if defined $create;
+  $num_options++ if defined $list;
+
+  # Report invalid usage
+  # ----------------------------------------------------------------------------
+  e_report $usage if $num_options > 1;
+
+  # Get URL of repository or branch
+  # ----------------------------------------------------------------------------
+  my $url;
+  if ($ARGV[0]) {
+    $url = Fcm::CmUrl->new (URL => $ARGV[0]);
+
+    if (not $url->is_url) {
+      # An argument is specified and is not a URL
+      # Assume that it is a path with a working copy
+      if (&is_wc ($ARGV[0])) {
+        $url = Fcm::CmUrl->new (URL => &get_url_of_wc ($ARGV[0]));
+
+      } else {
+        e_report $ARGV[0], ': is not a working copy, abort.';
+      }
+    }
+
+  } else {
+    # An argument is not specified
+    # Assume that the current directory is a working copy
+    if (&is_wc ()) {
+      $url = Fcm::CmUrl->new (URL => &get_url_of_wc ());
+
+    } else {
+      e_report 'The current directory is not a working copy, please specify a ',
+               'URL or a path to a working copy, abort.';
+    }
+  }
+
+  # Ensure $url->url_peg is a URL of a standard FCM project
+  e_report $url->url_peg, ': not a URL of a standard FCM project, abort.'
+    if not $url->project_url;
+
+  if ($create) {
+    # The --create option is specified, create a branch
+    # --------------------------------------------------------------------------
+
+    # Check branch type flags
+    if ($type) {
+      $type = uc ($type);
+
+      if ($type =~ /^(USER|SHARE)$/) {
+        $type = 'DEV::' . $1;
+
+      } elsif ($type =~ /^(CONFIG|REL)$/) {
+        $type = 'PKG::' . $1;
+
+      } elsif ($type =~ /^(DEV|TEST|PKG)$/) {
+        $type = $1 . '::USER';
+
+      } elsif ($type !~ /^(?:DEV|TEST|PKG)::(?:USER|SHARE)$/ and
+               $type !~ /^PKG::(?:CONFIG|REL)/) {
+        e_report $type, ': is not a valid type flag, abort.';
+      }
+
+    } else {
+      $type = 'DEV::USER';
+    }
+
+    # Check branch name
+    e_report 'The option --name must be used to specify a branch name, abort.'
+      if not $name;
+
+    e_report $name, ': invalid characters in name, abort.' if $name !~ /^\w+$/;
+
+    # Check revision flag is valid
+    if ($rev_flag) {
+      $rev_flag = uc ($rev_flag);
+
+      e_report $rev_flag, ': invalid argument to the --rev-flag option, abort.'
+        if $rev_flag !~ /^(?:NORMAL|NUMBER|NONE)$/;
+
+    } else {
+      $rev_flag = 'NORMAL';
+    }
+
+    # Handle multiple tickets
+    @tickets = split (/,/, join (',', @tickets));
+    s/^#// for (@tickets);
+    @tickets = sort {$a <=> $b} @tickets;
+
+    # Determine whether to create a branch of a branch
+    $url->branch ('trunk') unless $branch_of_branch;
+
+    # Create the branch
+    my $branch = Fcm::CmBranch->new;
+    $branch->create (
+      SRC                 => $url,
+      TYPE                => $type,
+      NAME                => $name,
+      PASSWORD            => $password,
+      REV_FLAG            => $rev_flag,
+      TICKET              => \@tickets,
+      REV                 => $rev,
+      NON_INTERACTIVE     => $non_interactive,
+      SVN_NON_INTERACTIVE => $svn_non_interactive,
+    );
+
+  } elsif ($list) {
+    # The option --list is specified
+    # List branches owned by current or specified users
+    # --------------------------------------------------------------------------
+    # Get URL of the project "branches/" sub-directory
+    $url->subdir ('');
+    $url->branch ('');
+    my @list = map {$_, 1} $url->branch_list ($rev);
+
+    if (@userlist) {
+      # Sort list of users
+      @userlist = sort (split /:/, join (':', @userlist));
+
+    } else {
+      # No user specified, add currrent user to list
+      push @userlist, $ENV{LOGNAME} unless @userlist;
+    }
+
+    # Filter branches matching user list
+    my @branches;
+    for my $branch (@list) {
+      next unless $branch =~ m#/([^/]+)/[^/]+/*$#;
+
+      my $user = $1;
+
+      push @branches, $branch if grep {$user eq $_} @userlist;
+    }
+
+    # Output, number of branches found
+    print scalar (@branches), ' ',
+          (scalar (@branches) > 1 ? 'branches' : 'branch'), ' found for ',
+          join (', ', @userlist), ' in ', $url->project_url_peg,
+          ($rev ? (' at r', $rev) : ()), "\n";
+
+    if (@branches) {
+      # Output the URL of each branch
+      @branches = map {$_ . "\n"} sort @branches;
+      print @branches;
+
+    } else {
+      # No branch found, exit with an error code
+      exit 1;
+    }
+
+  } else {
+    # The option --info or --delete is specified
+    # Report branch information (and/or delete a branch)
+    # --------------------------------------------------------------------------
+    # Set verbose level
+    &main::cfg->verbose ($verbose ? 1 : 0);
+
+    # Set up the branch, report any error
+    my $branch = Fcm::CmBranch->new (URL => $url->url_peg);
+    e_report $branch->url_peg, ': not a branch, abort.' unless $branch->branch;
+
+    e_report $branch->url_peg, ': does not exist, abort.'
+      unless $branch->url_exists;
+
+    # Remove the sub-directory part of the URL
+    $branch->subdir ('');
+
+    # Report branch info
+    $branch->display_info (
+      SHOW_CHILDREN => ($show_all || $show_children),
+      SHOW_OTHER    => ($show_all || $show_other   ),
+      SHOW_SIBLINGS => ($show_all || $show_siblings),
+    );
+
+    # Delete branch if --delete is specified
+    $branch->del (
+      PASSWORD            => $password,
+      NON_INTERACTIVE     => $non_interactive,
+      SVN_NON_INTERACTIVE => $svn_non_interactive,
+    ) if $delete;
+  }
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_commit ();
+#
+# DESCRIPTION
+#   This is a FCM wrapper to the "svn commit" command.
+# ------------------------------------------------------------------------------
+
+sub cm_commit {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+commit (ci): Send changes from your working copy to the repository.
+usage: fcm commit [PATH]
+
+  Invoke your favourite editor to prompt you for a commit log message. Send
+  changes from your working copy to the repository. Update your working copy
+  following the commit.
+
+Valid options:
+  --dry-run             : Allows you to add to the commit message without
+                          committing.
+  --svn-non-interactive : Do no interactive prompting at commit time.
+  --password arg        : Specify a password ARG.
+EOF
+    return 1;
+  }
+
+  my ($dry_run, $svn_non_interactive, $password);
+  GetOptions (
+    'dry-run'             => \$dry_run,
+    'svn-non-interactive' => \$svn_non_interactive,
+    'password'            => \$password,
+  );
+
+  # The remaining argument is the path to a working copy
+  my ($path) = @ARGV;
+
+  if ($path) {
+    # Check that specified path exists
+    e_report $path, ': does not exist, abort.' if not -e $path;
+
+  } else {
+    # No argument specified, use current working directory
+    $path = cwd ();
+  }
+
+  # Make sure we are in a working copy
+  e_report $path, ': not a working copy, abort.' if not &is_wc ($path);
+
+  # Make sure we are at the top level of the working copy
+  # (otherwise we might miss any template commit message)
+  my $dir = &get_wct ($path);
+
+  if ($dir ne cwd ()) {
+    chdir $dir or die 'Cannot change directory to: ', $dir;
+    print 'Committing changes from ', $dir, ' ...', "\n";
+  }
+
+  # Get update status of working copy
+  # Check working copy files are not in conflict, missing, or out of date
+  my @status = &run_command ([qw/svn status --show-updates/], METHOD => 'qx');
+  unless (defined $dry_run) {
+    my (@conflict, @missing, @outdate);
+
+    for (@status) {
+      if (/^C/) {
+        push @conflict, $_;
+        next;
+      }
+
+      if (/^!/) {
+        push @missing, $_;
+        next;
+      }
+
+      if (/^.{7}\*/) {
+        push @outdate, $_;
+        next;
+      }
+
+      # Check that all files which have been added have the svn:executable
+      # property set correctly (in case the developer adds a script before they
+      # remember to set the execute bit)
+      next unless /^A.{7} *\d+ +(.*)/;
+      my $file = $1;
+
+      next unless -f $file;
+      my @command = (-x $file)
+                    ? (qw/svn propset -q svn:executable */, $file)
+                    : (qw/svn propdel -q svn:executable/  , $file);
+      &run_command (\@command);
+    }
+
+    # Abort commit if files are in conflict, missing, or out of date
+    if (@conflict or @missing or @outdate) {
+      w_report 'File(s) in conflict:', "\n", @conflict if @conflict;
+      w_report 'File(s) missing:'    , "\n", @missing  if @missing;
+      w_report 'File(s) out of date:', "\n", @outdate  if @outdate;
+      e_report 'Abort commit.';
+    }
+  }
+
+  # Read in any existing message
+  my $ci_mesg = Fcm::CmCommitMessage->new ();
+  $ci_mesg->read_file;
+
+  # Execute "svn status" for a list of changed items
+  @status = grep !/^\?/, &run_command ([qw/svn status/], METHOD => 'qx');
+
+  # Abort if there is no change in the working copy
+  if (not @status) {
+    print 'No change in working copy, abort.', "\n";
+    return;
+  }
+
+  # Get associated URL of current working copy
+  my $url = Fcm::CmUrl->new (URL => &get_url_of_wc ());
+
+  # Include URL, or project, branch and sub-directory info in @status
+  unshift @status, "\n";
+
+  if ($url->project and $url->branch) {
+    unshift @status, (
+      '[Project: ' . $url->project                           . ']' . "\n",
+      '[Branch : ' . $url->branch                            . ']' . "\n",
+      '[Sub-dir: ' . ($url->subdir ? $url->subdir : '<top>') . ']' . "\n",
+    );
+
+  } else {
+    unshift @status, '[URL: ' . $url->url . ']' . "\n";
+  }
+
+  # Use a temporary file to store the final commit log message
+  $ci_mesg->ignore_mesg (@status);
+  my $logfile = $ci_mesg->edit_file (TEMP => 1);
+
+  # Check with the user to see if he/she wants to go ahead
+  my $reply = 'n';
+  if (not defined $dry_run) {
+    # Add extra warning for trunk commit
+    my $mesg = $url->is_trunk
+      ? "\n" .
+        '*** WARNING: YOU ARE COMMITTING TO THE TRUNK.' . "\n" .
+        '*** Please ensure that your change conforms to your project\'s ' .
+        'working practices.' . "\n\n"
+      : '';
+    $mesg   .= 'Would you like to commit this change?';
+
+    # Prompt the user
+    $reply = &main::get_input (
+      TITLE   => 'fcm commit',
+      MESSAGE => $mesg,
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+  }
+
+  if ($reply eq 'y') {
+    # Commit the change if user replies "y" for "yes"
+    my @command = (
+      qw/svn commit -F/, $logfile,
+      ($svn_non_interactive  ? '--non-interactive'       : ()),
+      (defined $password     ? ('--password', $password) : ()),
+    );
+    my $rc;
+    &run_command (\@command, RC => \$rc, ERROR => 'warn');
+
+    if ($rc) {
+      # Commit failed
+      # Write temporary commit log content to commit log message file
+      $ci_mesg->write_file;
+
+      # Fail the command
+      e_report;
+    }
+
+    # Remove commit message file
+    unlink $ci_mesg->file;
+
+    # Update the working copy
+    print 'Performing update to make sure your working copy is at this new ',
+          'revision ...', "\n";
+    &run_command ([qw/svn update/]);
+
+  } else {
+    # Abort commit if dry run or user replies "n" for "no"
+    w_report 'Commit aborted by user.' unless $dry_run;
+
+    # Write temporary commit log content to commit log message file
+    $ci_mesg->write_file;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_conflicts ();
+#
+# DESCRIPTION
+#   This is a FCM command for resolving conflicts within working copy using a
+#   graphical merge tool.
+# ------------------------------------------------------------------------------
+
+sub cm_conflicts {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+conflicts: Use graphical tool to resolve any conflicts within your working copy.
+usage: fcm conflicts [PATH]
+
+  Invoke the xxdiff graphical merge tool to help you resolve conflicts in your
+  working copy. It prompts you to run "svn resolved" each time you have
+  resolved the conflicts in a file.
+EOF
+    return 1;
+  }
+
+  # Path to the working copy
+  my $path = $ARGV[0];
+  $path    = cwd () if not $path;
+
+  # Check for any files with conflicts
+  my @status = grep /^C.{4} *(.*)/, &run_command (
+    [qw/svn st/, ($path eq cwd () ? () : $path)], METHOD => 'qx',
+  );
+  my @files  = map {m/^C.{4} *(.*)/; $1} @status;
+
+  # Save current working directory
+  my $topdir = cwd ();
+
+  for my $file (@files) {
+    # Print name of file in conflicts
+    print "Conflicts in file: $file\n";
+
+    # Determine directory and base name of file in conflicts
+    my $base = basename $file;
+    my $dir  = dirname $file;
+
+    # Change to container directory of file in conflicts
+    chdir File::Spec->catfile ($topdir, $dir) or die "Directory change to $dir failed";
+
+    # Use "svn info" to determine conflict marker files
+    my @info = &run_command ([qw/svn info/, $base], METHOD => 'qx');
+
+    # Ignore if $base is a binary file
+    if (-B $base) {
+      w_report $base,
+               ': ignoring binary file, please resolve conflicts manually.';
+      next;
+    }
+
+    # Get conflicts markers files
+    my ($older, $mine, $yours);
+
+    for (@info) {
+      $older = $1 if (/^Conflict Previous Base File: (.*)/);
+      $mine  = $1 if (/^Conflict Previous Working File: (.*)/);
+      $yours = $1 if (/^Conflict Current Base File: (.*)/);
+    }
+
+    if ((stat $base)[9] > (stat $mine)[9]) {
+      # If $base is newer, it may contain saved changes
+      my $reply = &main::get_input (
+        TITLE   => 'fcm conflicts',
+        MESSAGE => 'Existing changes in ' . $base . ' will be overwritten.' .
+                   "\n" . 'Do you wish to continue?',
+        TYPE    => 'yn',
+        DEFAULT => 'n',
+      );
+
+      next if $reply ne 'y';
+    }
+
+    # Launch "xxdiff" to allow user to perform graphical merging
+    my $xxdiffrc;
+    my @command  = (qw/xxdiff -m -M/, $base, qw/-O -X/, $mine, $older, $yours);
+    my ($decision) = &run_command (
+      \@command, METHOD => 'qx', RC => \$xxdiffrc, ERROR => 'ignore',
+    );
+    die &get_command_string (\@command), ' failed' if $xxdiffrc and ! $decision;
+    chomp $decision;
+
+    # Perform different actions depending on the user's decision
+    if ($decision eq "NODECISION") {
+      print "No decision taken\n";
+
+    } elsif ($decision eq "MERGED" and $xxdiffrc != 0) {
+      print "Merge conflicts were not all resolved\n";
+
+    } else {
+      # User has MERGED, ACCEPTED or REJECTED all changes
+      if ($decision eq "MERGED") {
+        print "All merge conflicts resolved\n";
+
+      } else {
+        print "You have chosen to $decision all the changes\n";
+      }
+
+      # Prompt user to run "svn resolved" on the file
+      my $reply = &main::get_input (
+        TITLE   => 'fcm conflicts',
+        MESSAGE => 'Would you like to run "svn resolved"?',
+        TYPE    => 'yn',
+        DEFAULT => 'n',
+      );
+
+      # If reply is "yes"...
+      &run_command ([qw/svn resolved/, $base]) if $reply eq 'y';
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_delete ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn delete". It adds an extra functionality to check
+#   for any files or directories reported by "svn status" as missing, and to
+#   prompt the user whether these files or directories should be deleted.
+# ------------------------------------------------------------------------------
+
+sub cm_delete {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+usage: fcm delete [options] [args]
+
+Valid options:
+  -c [--check]  : Check for any files or directories reported by svn status as
+                  missing and delete them.
+  <SVN options> : Standard options to svn delete as described below ...
+
+EOF
+
+    &run_command ([qw/svn delete --help/], PRINT => 1, METHOD => 'exec');
+  }
+
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--check -c)) {
+    # The --check option is specified, delete any missing files
+    # Execute "svn status", print lines starting with a "!"
+    my $pat    = '^!.{4}\s*';
+    my @status = grep /$pat.*/, &run_command ([qw/svn status/], METHOD => 'qx');
+    print @status if @status;
+
+    # Get list of "!" files
+    my @files  = map {chomp; s/$pat//; $_} @status;
+    my $reply  = '';
+
+    # Execute "delete" command depending on user reply
+    for my $file (@files) {
+      # Get a user reply, unless previous reply is "a" for "all"
+      $reply = &main::get_input (
+        TITLE   => 'fcm delete',
+        MESSAGE => "Delete file '$file'?",
+        TYPE    => 'yna',
+        DEFAULT => 'n',
+      ) unless $reply eq "a";
+
+      # Delete current $file if reply is "y" for "yes" or "a" for "all"
+      &run_command ([qw/svn delete/, $file]) if $reply =~ /^[ya]$/;
+    }
+
+  } else {
+    # The --check option is not specified, just call "svn delete"
+    cm_svn ("delete");
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_diff ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn diff". It adds two extra functionalities. The
+#   first one allows the command to show differences relative to the base of
+#   the branch. The second one allows differences to be displayed via a
+#   graphical tool.
+# ------------------------------------------------------------------------------
+
+sub cm_diff {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+usage: fcm diff [options] [args]
+
+Valid options:
+  -g [--graphical]    : Use xxdiff to display the differences.
+  -b [--branch] [URL] : Show differences relative to the base of the branch.
+  <SVN options>       : Standard options to svn diff as described below ...
+
+EOF
+
+    &run_command ([qw/svn diff --help/], PRINT => 1, METHOD => 'exec');
+  }
+
+  # Check for the --branch options
+  # ----------------------------------------------------------------------------
+  my $branch = grep {$_ eq '-b' or $_ eq '--branch'} @ARGV;
+
+  if (not $branch) {
+    # The --branch option not specified, just call "svn diff"
+    # Convert the --graphical to qw/--diff-cmd fcm_xxdiff_wrapper/
+    @ARGV = map {
+      ($_ eq '-g' or $_ eq '--graphical')
+      ? (qw/--diff-cmd fcm_xxdiff_wrapper/)
+      : $_
+    } @ARGV;
+
+    # Execute the command
+    cm_svn ('diff');
+  }
+
+  # The --branch option is specified
+  # ----------------------------------------------------------------------------
+
+  # Determine whether the --graphical option is specified,
+  # if so set the appropriate command
+  # ----------------------------------------------------------------------------
+  my $graphical;
+  GetOptions ('b|branch' => \$branch, 'g|graphical' => \$graphical);
+
+  my @diff_cmd = $graphical ? (qw/--diff-cmd fcm_xxdiff_wrapper/) : ();
+
+  # The remaining argument should either be a URL or a PATH
+  my ($url_arg, $path);
+
+  if (@ARGV) {
+    my $arg = Fcm::CmUrl->new (URL => $ARGV[0]);
+
+    if ($arg->is_url) {
+      $url_arg = $ARGV[0];
+
+    } else {
+      $path = $ARGV[0];
+    }
+  }
+
+  # Get repository and branch information
+  # ----------------------------------------------------------------------------
+  my $url;
+  if (defined $url_arg) {
+    # If a URL is specified, get repository and branch information from it
+    $url = Fcm::CmBranch->new (URL => $url_arg);
+
+  } else {
+    # Get repository and branch information from the specified path or the
+    # current directory if it is a working copy
+    $path = cwd () if not $path;
+    $url  = Fcm::CmBranch->new (URL => &get_url_of_wc ($path));
+  }
+
+  # Check that URL is a standard FCM branch
+  e_report $url->url_peg, ': not a standard FCM branch, abort.'
+    unless $url->is_branch;
+
+  # Save and remove sub-directory part of the URL
+  my $subdir = $url->subdir ();
+  $url->subdir ('');
+
+  # Check that $url exists
+  e_report $url->url_peg, ': not a valid URL, abort.' unless $url->url_exists;
+
+  # Compare current branch with its parent
+  # ----------------------------------------------------------------------------
+  my $parent = Fcm::CmBranch->new (URL => $url->parent->url);
+  $parent->pegrev ($url->pegrev) if $url->pegrev;
+
+  e_report $parent->url, ': branch parent no longer exists',
+           ($parent->pegrev ? ' at ' . $parent->pegrev : ''), ', abort.'
+    unless $parent->url_exists;
+
+  my $base = $parent->base_of_merge_from ($url);
+
+  # Execute the "diff" command
+  # ----------------------------------------------------------------------------
+  $url->subdir ($subdir);
+  $base->subdir ($subdir);
+  print 'Comparing against ', $base->path_peg, "\n";
+  my @command = (
+    qw/svn diff/, @diff_cmd,
+    '--old', $base->url_peg,
+    '--new', ($url_arg ? $url->url_peg : $path),
+  );
+  &run_command (\@command);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_merge ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn merge".
+# ------------------------------------------------------------------------------
+
+sub cm_merge {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+merge: Merge changes from a source into your working copy.
+usage: 1. fcm merge SOURCE
+       2. fcm merge --custom  --revision N[:M] SOURCE
+          fcm merge --custom  URL[\@REV1] URL[\@REV2]
+       3. fcm merge --reverse --revision [M:]N
+
+  1. If neither --custom nor --reverse is specified, the command merges changes
+     automatically from SOURCE into your working copy. SOURCE must be a valid
+     URL[\@REV] of a branch in a standard FCM project. The base of the merge
+     will be calculated automatically based on the common ancestor and latest
+     merge information between the SOURCE and the branch of the working copy.
+
+  2. If --custom is specified, the command can be used in two forms.
+  
+     In the first form, it performs a custom merge from the specified
+     changeset(s) of SOURCE into your working copy. SOURCE must be a valid
+     URL[\@REV] of a branch in a standard FCM project. If a single revision is
+     specified, the merge delta is (N - 1):N of SOURCE. Otherwise, the merge
+     delta, is N:M of SOURCE, where N < M.
+     
+     In the second form, it performs a custom merge using the delta between the
+     two specified branch URLs. For each URL, if a peg revision is not
+     specified, the command will peg the URL with its last changed revision.
+
+  3. If --reverse is specified, the command performs a reverse merge of the
+     changeset(s) specified by the --revision option. If a single revision is
+     specified, the merge delta is N:(N - 1). Otherwise, the merge delta is
+     M:N, where M > N. Note that you do not have to specify a SOURCE for a
+     reverse merge, because the SOURCE should always be the branch your working
+     copy is pointing to.
+  
+  The command provide a commit log message template following the merge.
+
+Valid options:
+  --dry-run          : Try operation but make no changes.
+  --non-interactive  : Do no interactive prompting.
+  -r [--revision] arg: Specify a (range of) revision number(s).
+  --verbose          : Print extra information.
+EOF
+    return 1;
+  }
+
+  # Options
+  # ----------------------------------------------------------------------------
+  my ($custom, $dry_run, $non_interactive, $reverse, $rev, $verbose);
+  GetOptions (
+    'custom'          => \$custom,
+    'dry-run'         => \$dry_run,
+    'non-interactive' => \$non_interactive,
+    'reverse'         => \$reverse,
+    'revision|r=s'    => \$rev,
+    'verbose|v'       => \$verbose,
+  );
+
+  # Find out the URL of the working copy
+  # ----------------------------------------------------------------------------
+  my ($target, $wct);
+  if (&is_wc ()) {
+    $wct = &get_wct ();
+
+    if ($wct ne cwd ()) {
+      print 'Change directory to top of working copy: ', $wct, "\n";
+      chdir $wct or die 'Cannot change directory to: ', $wct;
+    }
+
+    $target = Fcm::CmBranch->new (URL => &get_url_of_wc ($wct));
+
+  } else {
+    e_report 'The current directory is not a working copy, abort.';
+  }
+
+  e_report 'Your working copy URL does not exist at the HEAD revision, abort.'
+    unless $target->url_exists;
+
+  # The target must be at the top of a branch
+  # $subdir will be used later to determine whether the merge is allowed or not
+  my $subdir = $target->subdir;
+  $target->subdir ('') if $subdir;
+
+  # Check for any local modifications
+  # ----------------------------------------------------------------------------
+  return
+    if ! ($dry_run or $non_interactive) and &_abort_modified_wc ('fcm merge');
+
+  # Determine the SOURCE URL
+  # ----------------------------------------------------------------------------
+  my $source;
+
+  if ($reverse) {
+    # Reverse merge, the SOURCE is the the working copy URL
+    $source = Fcm::CmBranch->new (URL => $target->url);
+
+  } else {
+    # Automatic/custom merge, argument 1 is the SOURCE of the merge
+    my $source_url = shift (@ARGV);
+    e_report 'Error: argument 1 must be the URL/name of a source branch in ',
+             'automatic/custom mode, abort.'
+      if not $source_url;
+
+    $source = &_construct_branch_url ($source_url, $target);
+  }
+
+  # Parse the revision option
+  # ----------------------------------------------------------------------------
+  my @revs;
+  if ($reverse or $custom) {
+    if ($reverse and not $rev) {
+      e_report 'Error: a revision (range) must be specified with ',
+               '--revision in reverse mode, abort.'
+    }
+
+    @revs = split (/:/, $rev) if $rev;
+  }
+
+  # Determine the merge delta and the commit log message
+  # ----------------------------------------------------------------------------
+  my (@delta, $mesg);
+  my $separator = '-' x 80 . "\n";
+
+  if ($reverse) {
+    # Reverse merge
+    # --------------------------------------------------------------------------
+    if (@revs == 1) {
+      $revs[1] = ($revs[0] - 1);
+
+    } else {
+      @revs = sort {$b <=> $a} @revs;
+    }
+
+    $source->pegrev ($source->svninfo (FLAG => 'Last Changed Rev'))
+      unless $source->pegrev;
+    $source->subdir ($subdir);
+
+    # "Delta" of the "svn merge" command
+    @delta = ('-r' . $revs[0] . ':' . $revs[1], $source->url_peg);
+
+    # Template message
+    $mesg = 'Reversed r' . $revs[0] .
+            (($revs[1] < $revs[0] - 1) ? ':' . $revs[1] : '') . ' of ' .
+            $source->path . "\n";
+
+  } elsif ($custom) {
+    # Custom merge
+    # --------------------------------------------------------------------------
+    if (@revs) {
+      # Revision specified
+      # ------------------------------------------------------------------------
+      # Only one revision N specified, use (N - 1):N as the delta
+      unshift @revs, ($revs[0] - 1) if @revs == 1;
+
+      $source->pegrev ($source->svninfo (FLAG => 'Last Changed Rev'))
+        unless $source->pegrev;
+      $source->subdir ($subdir);
+      $target->subdir ($subdir);
+
+      # "Delta" of the "svn merge" command
+      @delta = ('-r' . $revs[0] . ':' . $revs[1], $source->url_peg);
+
+      # Template message
+      $mesg = 'Custom merge into ' . $target->path . ': r' . $revs[1] .
+              ' cf. r' . $revs[0] . ' of ' . $source->path_peg . "\n";
+
+    } else {
+      # Revision not specified
+      # ------------------------------------------------------------------------
+      # Get second source URL
+      my $source2_url = shift (@ARGV);
+      e_report 'Error: argument 2 must be the URL/name of a source branch in ',
+               'custom mode when --revision is not specified, abort.'
+        if not $source2_url;
+
+      my $source2 = &_construct_branch_url ($source2_url, $target);
+
+      $source->pegrev  ($source->svninfo  (FLAG => 'Last Changed Rev'))
+        unless $source->pegrev;
+      $source2->pegrev ($source2->svninfo (FLAG => 'Last Changed Rev'))
+        unless $source2->pegrev;
+      $source->subdir  ($subdir);
+      $source2->subdir ($subdir);
+      $target->subdir  ($subdir);
+
+      # "Delta" of the "svn merge" command
+      @delta = ($source->url_peg, $source2->url_peg);
+
+      # Template message
+      $mesg = 'Custom merge into ' . $target->path . ': ' . $source->path_peg .
+              ' cf. ' . $source2->path_peg . "\n";
+    }
+
+  } else {
+    # Automatic merge
+    # --------------------------------------------------------------------------
+
+    # Only allow the merge if the source and target are "directly related"
+    # --------------------------------------------------------------------------
+    my $anc = $target->ancestor ($source);
+    e_report 'Error: source and target are not directly related' unless
+      ($anc->url eq $target->url and $anc->url_peg eq $source->parent->url_peg)
+      or
+      ($anc->url eq $source->url and $anc->url_peg eq $target->parent->url_peg)
+      or
+      ($anc->url eq $source->parent->url and $anc->url eq $target->parent->url);
+
+    # Check for available merges from the source
+    # --------------------------------------------------------------------------
+    my @revs = $target->avail_merge_from ($source, 1);
+
+    if (@revs) {
+      print 'Available Merge', (@revs > 1 ? 's' : ''), ' From ',
+            $source->path_peg, ':';
+
+      if ($verbose) {
+        # Verbose mode, print log messages of available merges
+        print "\n";
+
+        for (@revs) {
+          print $separator, $source->display_svnlog ($_);
+        }
+
+        print $separator;
+
+      } else {
+        # Normal mode, list revisions of available merges
+        print ' ', join (' ', @revs), "\n";
+      }
+
+    } else {
+      w_report 'No merge available from ', $source->path_peg, ', abort.';
+      return;
+    }
+
+    # If more than one merge available, prompt user to enter a revision number
+    # to merge from, default to $revs [0]
+    # --------------------------------------------------------------------------
+    my $reply = ($non_interactive or @revs == 1) ? $revs[0] : &main::get_input (
+      TITLE   => 'fcm merge',
+      MESSAGE => 'Please enter the revision you wish to merge from',
+      DEFAULT => $revs [0],
+    );
+
+    if (not defined ($reply)) {
+      w_report 'Merge aborted by user.';
+      return;
+    }
+
+    # Expand revision keyword if necessary
+    if ($reply) {
+      $reply = expand_rev_keyword (REV => $reply, URL => $target->project_url);
+    }
+
+    # Check that the reply is a number in the available merges list
+    e_report $reply, ': not a revision in the list of available merges.'
+      unless (grep {$_ == $reply} @revs);
+
+    $source->pegrev ($1) if ($reply =~ /^(\d+)/);
+
+    # If the working copy top is pointing to a sub-directory of a branch,
+    # we need to check whether the merge will result in losing changes made in
+    # other sub-directories of the source.
+    if ($subdir and not $target->allow_subdir_merge_from ($source, $subdir)) {
+      e_report 'SOURCE contains changes outside the current sub-directory.', "\n",
+               'Please use a full tree for the merge, abort.';
+    }
+
+    # Calculate the base of the merge
+    my $base = $target->base_of_merge_from ($source);
+
+    # $source and $base must take into account the sub-directory
+    my $s = Fcm::CmBranch->new (URL => $source->url_peg);
+    my $b = Fcm::CmBranch->new (URL => $base->url_peg);
+
+    $s->subdir ($subdir) if $subdir;
+    $b->subdir ($subdir) if $subdir;
+
+    # Diagnostic
+    print 'About to merge in changes from ', $s->path_peg, ' compared with ',
+          $b->path_peg, "\n";
+
+    # Delta of the "svn merge" command
+    @delta = ($b->url_peg, $s->url_peg);
+
+    # Template message
+    $mesg = 'Merged into ' . $target->path . ': ' . $source->path_peg .
+            ' cf. ' . $base->path_peg . "\n";
+  }
+
+  # Run "svn merge" in "--dry-run" mode to see the result
+  # ----------------------------------------------------------------------------
+  my @out   = &run_command (
+    [qw/svn merge --dry-run/, @delta],
+    METHOD => 'qx', PRINT => ($dry_run and $verbose),
+  );
+
+  # Abort merge if it will result in no change
+  if (not @out) {
+    print 'This merge will not result in any change, abort.', "\n";
+    return;
+  }
+
+  # Report result of "svn merge --dry-run"
+  if (not $non_interactive) {
+    print 'This merge will result in the following change',
+          (@out > 1 ? 's' : ''), ':', "\n";
+    print $separator, @out, $separator;
+  }
+
+  return if $dry_run;
+
+  # Prompt the user to see if (s)he would like to go ahead
+  # ----------------------------------------------------------------------------
+  my $reply = $non_interactive ? 'y' : &main::get_input (
+    TITLE   => 'fcm merge',
+    MESSAGE => 'Would you like to go ahead with the merge?',
+    TYPE    => 'yn',
+    DEFAULT => 'n',
+  );
+
+  # Go ahead with merge only if user replies "y"
+  if ($reply eq "y") {
+    print "Performing merge ...\n";
+    &run_command ([qw/svn merge/, @delta], PRINT => $verbose);
+
+  } else {
+    w_report 'Merge aborted by user.';
+    return;
+  }
+
+  # Prepare the commit log
+  # ----------------------------------------------------------------------------
+  # Read in any existing message
+  my $ci_mesg = Fcm::CmCommitMessage->new;
+  $ci_mesg->read_file;
+  $ci_mesg->auto_mesg ($mesg, ($ci_mesg->auto_mesg));
+  $ci_mesg->write_file;
+
+  if ($verbose) {
+    print <<EOF;
+${separator}The following line has been added to your commit message file:
+$mesg
+EOF
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_mkpatch ();
+#
+# DESCRIPTION
+#   This is a FCM command to create a patching script from particular revisions
+#   of a URL.
+# ------------------------------------------------------------------------------
+
+sub cm_mkpatch {
+  my $usage = <<EOF;
+mkpatch: Create patches from specified revisions of a URL
+usage: fcm mkpatch [OPTIONS] URL [OUTDIR]
+
+  URL must be the URL of a branch in a FCM project. If the URL is a
+  sub-directory of a branch, it will use the root of the branch.
+
+  Create patches from specified revisions of the specified URL. If OUTDIR is
+  specified, the output is sent to OUTDIR. Otherwise, the output will be sent
+  to a default location in the current directory (\$PWD/fcm-mkpatch-out). The
+  output directory will contain the patch for each revision as well as a script
+  for importing the patch.
+
+  If a revision is specified with the --revision option, it will attempt to
+  create a patch based on the changes at that revision. If a revision is not
+  specified, it will attempt to create a patch based on the changes at the HEAD
+  revision. If a revision range is specified, it will attempt to create a patch
+  for each revision in that range (including the change in the lower range)
+  where changes have taken place in the URL. No output will be written if there
+  is no change in the given revision (range).
+
+  The --exclude option can be used to exclude a path in the URL. The specified
+  path must be a relative path of the URL. Glob patterns such as * and ? are
+  acceptable. Changes in an excluded path will not be considered in the patch.
+  A changeset containing changes only in the excluded path will not be
+  considered at all.
+
+  The --organisation option can be used to specify the name of your
+  organisation. The command will attempt to parse the commit log message for
+  each revision in the patch. It will remove all merge templates, replace links
+  to Trac tickets with a simple string, and add information about the original
+  changeset. If you specify the name of your organisation, it will replace Trac
+  ticket links such as "ticket:123" to "Original \$organisation ticket 123",
+  and report the orginal changeset with a message such as "Original
+  \$organisation changeset 1000". Otherwise, it will report without the
+  organisation name, e.g. "Original ticket 123" and "Original  changeset 1000".
+
+Valid options:
+  --exclude       arg : Exclude a path in the URL. Multiple paths can be
+                        specified by using a colon-separated list of paths, or
+                        by specifying this option multiple times.
+  --organisation  arg : Specify the name of your organisation.
+  -r [--revision] arg : Specify a revision number or a revision number range.
+EOF
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print $usage;
+    return 1;
+  }
+
+  # Process command line options and arguments
+  # ----------------------------------------------------------------------------
+  my (@exclude, $organisation, $revision);
+  GetOptions (
+    'exclude=s'      => \@exclude,
+    'organisation=s' => \$organisation,
+    'r|revision=s'   => \$revision,
+  );
+
+  # Excluded paths, convert glob into regular patterns
+  @exclude = split (/:/, join (':', @exclude));
+  for (@exclude) {
+    s#\*#[^/]*#; # match any number of non-slash character
+    s#\?#[^/]#;  # match a non-slash character
+    s#/*$##;     # remove trailing slash
+  }
+
+  # Organisation prefix
+  $organisation = $organisation ? $organisation : 'original';
+
+  # Make sure revision option is set correctly
+  my @revs = $revision ? split (/:/, $revision) : ();
+  @revs    = @revs [0, 1] if @revs > 2;
+
+  # Arguments
+  my ($u, $outdir) = @ARGV;
+
+  if (not $u) {
+    print $usage;
+    return 1;
+  }
+
+  my $url = Fcm::CmUrl->new (URL => $u);
+  e_report $u, ': URL is not a URL, abort.' if not $url->is_url;
+  e_report $u, ': URL does not exist, abort.' if not $url->url_exists;
+  e_report $u, ': URL is not a valid branch in a FCM project, abort.'
+    if not $url->branch;
+
+  $url->subdir ('');
+
+  if (@revs) {
+    # If HEAD revision is given, convert it into a number
+    # --------------------------------------------------------------------------
+    for my $rev (@revs) {
+      $rev = $url->svninfo (FLAG => 'Revision') if uc ($rev) eq 'HEAD';
+    }
+
+  } else {
+    # If no revision is given, use the HEAD
+    # --------------------------------------------------------------------------
+    $revs[0] = $url->svninfo (FLAG => 'Revision');
+  }
+
+  $revs[1] = $revs[0] if @revs == 1;
+
+  # Check that output directory is set
+  # ----------------------------------------------------------------------------
+  $outdir = File::Spec->catfile (cwd (), 'fcm-mkpatch-out') if not $outdir;
+
+  if (-e $outdir) {
+    # Ask user to confirm removal of old output directory if it exists
+    my $reply = &main::get_input (
+      TITLE   => 'fcm mkpatch',
+      MESSAGE => 'Output location ' . $outdir . ' exists. OK to overwrite?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    if ($reply ne 'y') {
+      w_report 'fcm mkpatch: command aborted by user.';
+      return 1;
+    }
+
+    rmtree $outdir or die $outdir, ': cannot remove';
+  }
+
+  # (Re-)create output directory
+  mkpath $outdir or die $outdir, ': cannot create';
+  print 'Output directory: ', $outdir, "\n";
+
+  # Get and process log of URL
+  # ----------------------------------------------------------------------------
+  my @script     = (); # output script, from the log
+  my %log        = $url->svnlog (REV => \@revs);
+  my $url_path   = $url->path;
+  my $file_count = 0;
+
+  for my $rev (sort {$a <=> $b} keys %log) {
+    # Look at the changed paths for each revision
+    my @paths;
+
+    # Skip excluded paths if necessary
+    PATH: for my $path (sort keys %{ $log{$rev}{paths} }) {
+      for my $exclude (@exclude) {
+        (my $file = $path) =~ s#^$url_path/*##;
+
+        next PATH if $file =~ m#^$exclude(?:/*|$)#;
+      }
+
+      push @paths, $path;
+    }
+
+    next unless @paths;
+
+    # Parse commit log message
+    my @msg = split /\n/, $log{$rev}{msg};
+    for (@msg) {
+      # Re-instate line break
+      $_ .= "\n";
+
+      # Remove line if it matches a merge template
+      $_ = '' if /^Reversed r\d+(?::\d+)? of \S+$/;
+      $_ = '' if /^Custom merge into \S+:.+$/;
+      $_ = '' if /^Merged into \S+: \S+ cf\. \S+$/;
+
+      # Modify Trac ticket link
+      s/(?:#|ticket:)(\d+)/[$organisation ticket $1]/g;
+
+      # Modify Trac changeset link
+      s/(?:r|changeset:)(\d+)/[$organisation changeset $1]/g;
+      s/\[(\d+)\]/[$organisation changeset $1]/g;
+    }
+
+    push @msg, '[' . $organisation . ' changeset ' . $rev . ']' . "\n";
+
+    # Write commit log message in a file
+    my $f_revlog = File::Spec->catfile ($outdir, $rev . '-log');
+    open FILE, '>', $f_revlog or die $f_revlog, ': cannot open (', $!, ')';
+    print FILE @msg;
+    close FILE or die $f_revlog, ': cannot close (', $!, ')';
+
+    # Create a directory for this revision in the output directory
+    my $outdir_rev = File::Spec->catfile ($outdir, $rev);
+    mkpath $outdir_rev or die $outdir_rev, ': cannot create';
+
+    # Handle modified/copy/new path, export the path, + script to copy/add it
+    for my $path (@paths) {
+      next unless $log{$rev}{paths}{$path}{action} =~ /^[AMR]$/;
+
+      (my $file = $path) =~ s#^$url_path/*##;
+
+      # Download the file using "svn export"
+      my $patch    = File::Spec->catfile ($outdir_rev, $file_count++);
+      my $url_file = $url->url . '/' . $file . '@' . $rev;
+      &run_command ([qw/svn export -q -r/, $rev, $url_file, $patch]);
+
+      (my $patch_path = $patch) =~ s#^$outdir/*##;
+
+      # Script to copy the file, if required
+      my $is_newfile = 0;
+      if ($log{$rev}{paths}{$path}{action} eq 'A') {
+        if (exists $log{$rev}{paths}{$path}{'copyfrom-path'}) {
+          # History exists for this file
+          my $copyfrom_path = $log{$rev}{paths}{$path}{'copyfrom-path'};
+          my $copyfrom_rev  = $log{$rev}{paths}{$path}{'copyfrom-rev'};
+
+          # Check whether file is copied from a file under the specified URL
+          # It is likely to be a new file if it is copied from outside of the
+          # specified URL.
+          $is_newfile = not ($copyfrom_path =~ s#^$url_path/*##);
+
+          if ($is_newfile) {
+            # File copied from outside of the specified URL
+            # If it is copied from a branch, follow its history, stop on copy
+            my $cp_url = Fcm::CmUrl->new (
+              URL => $url->root . $copyfrom_path . '@' . $copyfrom_rev,
+            );
+
+            # Log of the copied file
+            my %cp_log = $cp_url->svnlog (STOP_ON_COPY => 1);
+
+            # "First" revision of the copied file
+            my $cp_rev = (sort {$a <=> $b} keys %cp_log) [0];
+            my %attrib = %{ $cp_log{$cp_rev}{paths}{$cp_url->path} };
+
+            # Check whether the "first" revision is copied from elsewhere.
+            if (exists $attrib{'copyfrom-path'}) {
+              # Check whether source exists in the current branch
+              my $cp_cp_url = Fcm::CmUrl->new (
+                URL => $url->root . $attrib{'copyfrom-path'} . '@' .
+                       $attrib{'copyfrom-rev'},
+              );
+
+              $cp_cp_url->branch ($url->branch);
+
+              # If source exists in current branch, set up copy from the source
+              if ($cp_cp_url->url_exists ($rev - 1)) {
+                $is_newfile     = 0;
+                (my $cp_cp_path = $cp_cp_url->path) =~ s#^$url_path/*##;
+
+                push @script, 'svn copy ' . $cp_cp_path .  ' ' . $file;
+              }
+            }
+
+          } else {
+            # File copied from a location under the specified URL
+            # Script to copy file
+            push @script, 'svn copy ' . $copyfrom_path .  ' ' . $file;
+          }
+
+        } else {
+          # History does not exist, must be a new file
+          $is_newfile = 1;
+        }
+      }
+
+      # Copy the "patch" into the file
+      push @script, 'cp -r ${fcm_patch_dir}/' . $patch_path . ' ' . $file;
+
+      # Script to add the file, if required
+      push @script, 'svn add ' . $file
+        if $log{$rev}{paths}{$path}{action} eq 'A' and $is_newfile;
+    }
+
+    # Handle deleted path, script to delete it
+    for my $path (@paths) {
+      next unless $log{$rev}{paths}{$path}{action} eq 'D';
+
+      (my $file = $path) =~ s#^$url_path/*##;
+
+      push @script, 'svn delete ' . $file;
+    }
+
+    # Script to commit the change
+    push @script, 'svn commit -F ${fcm_patch_dir}/' . $rev . '-log';
+    push @script, '';
+  }
+
+  # Write the script if necessary. Otherwise remove output directory
+  # ----------------------------------------------------------------------------
+  if (@script) {
+    # Add line break to each line in @script
+    @script = map {($_ ? $_ . ' || exit 1' . "\n" : "\n")} @script;
+
+    # Write script to output
+    my $out = File::Spec->catfile ($outdir, 'fcm-import-patch');
+    open FILE, '>', $out or die $out, ': cannot open (', $!, ')';
+
+    # Script header
+    print FILE <<EOF;
+#!/bin/sh
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm-import-patch
+#
+# SYNOPSIS
+#   fcm-import-patch TARGET
+#
+# DESCRIPTION
+#   This script is generated automatically by the "fcm mkpatch" command,
+#   together with the revision "patches" it creates. The script imports the
+#   patches into TARGET, which must either be a URL or a working copy of a
+#   valid project tree that can accept the import of the patches.
+#
+#   Patch created from $organisation URL: $u
+# ------------------------------------------------------------------------------
+
+this=`basename \$0`
+
+# Check argument
+target=\$1
+
+# First argument must be a URL or working copy
+if [[ -z \$target ]]; then
+  echo "\$this: the first argument must be a URL or a working copy, abort." >&2
+  exit 1
+fi
+
+if [[ \$target == svn://*  || \$target == svn+ssh://* || \\
+      \$target == http://* || \$target == https://*   || \\
+      \$target == file://* ]]; then
+  # A URL, checkout a working copy in a temporary location
+  fcm_tmp_dir=`mktemp -d \$TMPDIR/\$0.XXXXXX`
+  fcm_working_copy=\$fcm_tmp_dir
+  svn checkout -q \$target \$fcm_working_copy || exit 1
+
+else
+  # A working copy, check that it does not have local changes
+  status=`svn status \$target`
+
+  if [[ -n \$status ]]; then
+    echo "\$target: working copy contains changes, abort." >&2
+    exit 1
+  fi
+
+  fcm_working_copy=\$target
+fi
+
+# Location of the patches, base on the location of this script
+cd `dirname \$0` || exit 1
+fcm_patch_dir=\$PWD
+
+# Change directory to the working copy
+cd \$fcm_working_copy || exit 1
+
+# Commands to apply patches
+EOF
+
+    # Script content
+    print FILE @script;
+
+    # Script footer
+    print FILE <<EOF;
+# Remove temporary working copy, if necessary
+if [[ -d \$fcm_tmp_dir && -w \$fcm_tmp_dir ]]; then
+  rm -rf \$fcm_tmp_dir
+fi
+
+echo "\$this: finished normally."
+#EOF
+EOF
+
+    close FILE or die $out, ': cannot close (', $!, ')';
+
+    # Add executable permission
+    chmod 0755, $out;
+
+    # Diagnostic
+    print $outdir, ': patch generated.', "\n";
+
+  } else {
+    # Remove output directory
+    rmtree $outdir or die $outdir, ': cannot remove';
+
+    # Diagnostic
+    w_report 'No patch is required, abort.';
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_svn ();
+#
+# DESCRIPTION
+#   This is a generic wrapper for all "other" Subversion commands.
+# ------------------------------------------------------------------------------
+
+sub cm_svn {
+  &run_command (
+    ['svn', @_, @ARGV],
+    PRINT => ($_[0] ne 'cat' and not grep {$_ eq '--xml'} @ARGV),
+    METHOD => 'exec',
+  );
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_switch ();
+#
+# DESCRIPTION
+#   This is a wrapper for the Subversion "switch" command.
+# ------------------------------------------------------------------------------
+
+sub cm_switch {
+  if (grep {$_ eq '-h' or $_ eq '--help'} @ARGV or not @ARGV) {
+    # Print usage message if requested
+    print <<EOF;
+usage: 1. switch URL [PATH]
+       2. switch --relocate FROM TO [PATH...]
+
+Note: if --relocate is not specified, "fcm switch" will only support the
+      options --non-interactive, -r [--revision] and -q [--quiet].
+
+EOF
+
+    &run_command ([qw/svn switch --help/], PRINT => 1, METHOD => 'exec');
+
+  } elsif (grep {$_ eq '--relocate'} @ARGV) {
+    # If "--relocate" is specified, call the command "as is"
+    cm_svn ('switch');
+  }
+
+  # "--help" and "--relocate" not specified, implement custom switch command
+
+  # Get command line options
+  my ($non_interactive, $rev, $quiet);
+  GetOptions (
+    'non-interactive' => \$non_interactive,
+    'revision|r=s'    => \$rev,
+    'quiet|q'         => \$quiet,
+  );
+
+  # The remaining arguments
+  $rev = 'HEAD' if not $rev;
+
+  # The remaining arguments
+  my ($newurl_arg, $path) = @ARGV;
+
+  # Make sure we are in a working copy
+  if ($path) {
+    e_report $path, ': does not exist, abort.' if not -e $path;
+
+  } else {
+    $path = cwd ();
+  }
+
+  e_report $path, ': not a working copy, abort.' if not &is_wc ($path);
+
+  # Make sure we are at the top level of the working copy
+  my $dir = &get_wct ($path);
+
+  # Check for merge template in the commit log file in the working copy
+  my $ci_mesg = Fcm::CmCommitMessage->new (DIR => $dir);
+  $ci_mesg->read_file;
+  e_report (
+    (($path eq $dir) ? $ci_mesg->base : $ci_mesg->file),
+    ': merge template exists, please remove it before running switch, abort.',
+  ) if $ci_mesg->auto_mesg;
+
+  # Check for any local modifications
+  return if ! $non_interactive and &_abort_modified_wc ('fcm switch', $dir);
+
+  # Get current URL information associated with the working copy
+  my $oldurl = Fcm::CmBranch->new (URL => &get_url_of_wc ($dir));
+
+  # Analyse new URL
+  my $newurl = &_construct_branch_url ($newurl_arg, $oldurl);
+
+  # Construct the switch command
+  my @command = (
+    qw/svn switch/,
+    ($non_interactive ? '--non-interactive' : ()),
+    ($rev             ? ('-r', $rev)        : ()),
+    ($quiet           ? '--quiet'           : ()),
+    $newurl->url,
+    ($dir eq cwd () ? () : $dir),
+  );
+
+  # Execute the command
+  &run_command (\@command, METHOD => 'exec', PRINT => 1);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $source = &_construct_branch_url ($src_url, $target);
+#
+# DESCRIPTION
+#   The function takes a string $src_url, which is normally the SOURCE URL
+#   argument for "merge" and "switch", and a target, which is an instance of a
+#   Fcm::CmBranch object with a valid URL of a standard FCM branch. It returns
+#   an instance of a Fcm::CmBranch object that represents a valid URL for
+#   $src_url.
+# ------------------------------------------------------------------------------
+
+sub _construct_branch_url {
+  my ($src_url, $target) = @_;
+
+  my $source = Fcm::CmBranch->new (URL => $src_url);
+
+  if (not $source->is_url) {
+    # Not a full URL, construct full URL based on current URL
+    $source->url_peg ($target->url_peg);
+
+    my $path    = '';
+    my $project = $target->project;
+
+    # Construct the branch URL
+    if ($src_url =~ m#^/*$project/(?:trunk|branches|tags)$#) {
+      # Argument contains the full path under the repository root
+      $path = $src_url;
+
+    } elsif ($src_url =~ m#^/*trunk/*(?:@\d+)?$# or
+             $src_url =~ m#^/*(?:trunk|branches|tags)/+#) {
+      # Argument contains the full branch name
+      $src_url =~ s#^/*##;
+      $path    = $target->project_path . '/' . $src_url;
+
+    } else {
+      # Argument contains the shorter branch name
+      $src_url =~ s#^/*##;
+      $path    = $target->project_path . '/branches/' . $src_url;
+    }
+
+    $source->path_peg ($path);
+  }
+
+  # Replace source sub-directory with the target sub-directory
+  $source->subdir ($target->subdir);
+
+  # Ensure that the branch name exists
+  e_report $src_url, ': not a valid URL, abort.'
+    if not $source->url_exists;
+
+  # Ensure that the branch name is valid
+  e_report $src_url, ': not a standard branch in a FCM project, abort.'
+    if not $source->branch;
+
+  # Ensure that the source and target URLs are in the same project
+  e_report 'Source and target URLs are in different projects, abort.'
+    if $source->project_url ne $target->project_url;
+
+  return $source;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &_abort_modified_wc ($title, [$wc]);
+#
+# DESCRIPTION
+#   The function checks for any local modifications in a working copy and
+#   prompts the user whether he/she wants to continue with the command. $title
+#   is the title of the current command. If $wc is specified, it must be the
+#   path to a working copy. Otherwise, the current working directory is used.
+# ------------------------------------------------------------------------------
+
+sub _abort_modified_wc {
+  my ($title, $wc) = @_;
+
+  my @status = &run_command ([qw/svn status/, ($wc ? $wc : ())], METHOD => 'qx');
+
+  if (@status) {
+    print 'You have local modifications:', "\n", @status;
+    my $reply = &main::get_input (
+      TITLE   => $title,
+      MESSAGE => 'Are you sure you want to continue?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    # Abort if user gives any reply other than "y"
+    if ($reply ne 'y') {
+      w_report $title, ': command aborted by user.';
+      return 1;
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmBranch.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmBranch.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmBranch.pm	(revision 329)
@@ -0,0 +1,1199 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CmBranch
+#
+# DESCRIPTION
+#   This class contains methods for manipulating a branch. It is a sub-class of
+#   Fcm::CmUrl, and inherits all methods from that class.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CmBranch;
+@ISA = qw(Fcm::CmUrl);
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+
+# FCM component modules
+use Fcm::CmCommitMessage;
+use Fcm::CmUrl;
+use Fcm::Util qw/run_command e_report w_report get_rev_keyword svn_date/;
+
+my @properties = (
+  'CREATE_REV',  # revision at which the branch is created
+  'DELETE_REV',  # revision at which the branch is deleted
+  'PARENT',      # reference to parent branch Fcm::CmBranch
+  'ANCESTOR',    # list of common ancestors with other branches
+                 # key = URL, value = ancestor Fcm::CmBranch
+  'LAST_MERGE',  # list of last merges from branches
+                 # key = URL@REV, value = [TARGET, UPPER, LOWER]
+  'AVAIL_MERGE', # list of available revisions for merging
+                 # key = URL@REV, value = [REV ...]
+  'CHILDREN',    # list of children of this branch
+  'SIBLINGS',    # list of siblings of this branch
+);
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch = Fcm::CmBranch->new (
+#     CONFIG  => $config,
+#     URL     => $url,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CmBranch class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   URL    - URL of a branch
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = Fcm::CmUrl->new (%args);
+
+  $self->{$_} = undef for (@properties);
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_branch->url_peg;
+#   $cm_branch->url_peg ($url);
+#
+# DESCRIPTION
+#   This method returns/sets the current URL.
+# ------------------------------------------------------------------------------
+
+sub url_peg {
+  my $self = shift;
+
+  if (@_) {
+    if (! $self->{URL} or $_[0] ne $self->{URL}) {
+      # Re-set URL and other essential variables in the SUPER-class
+      $self->SUPER::url_peg (@_);
+
+      # Re-set essential variables
+      $self->{$_} = undef for (@properties);
+    }
+  }
+
+  return $self->{URL};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cm_branch->create_rev;
+#
+# DESCRIPTION
+#   This method returns the revision at which the branch was created.
+# ------------------------------------------------------------------------------
+
+sub create_rev {
+  my $self = shift;
+
+  if (not $self->{CREATE_REV}) {
+    return unless $self->url_exists ($self->pegrev);
+
+    # Use "svn log" to find out the first revision of the branch
+    my %log = $self->svnlog (STOP_ON_COPY => 1);
+
+    # Look at log in ascending order
+    my $rev   = (sort {$a <=> $b} keys %log) [0];
+    my $paths = $log{$rev}{paths};
+
+    # Get revision when URL is first added to the repository
+    if (exists $paths->{$self->branch_path}) {
+      $self->{CREATE_REV} = $rev if $paths->{$self->branch_path}{action} eq 'A';
+    }
+  }
+
+  return $self->{CREATE_REV};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $parent = $cm_branch->parent;
+#
+# DESCRIPTION
+#   This method returns the parent (a Fcm::CmBranch object) of the current
+#   branch.
+# ------------------------------------------------------------------------------
+
+sub parent {
+  my $self = shift;
+
+  if (not $self->{PARENT}) {
+    # Use the log to find out the parent revision
+    my %log = $self->svnlog (REV => $self->create_rev);
+
+    if (exists $log{paths}{$self->branch_path}) {
+      my $path = $log{paths}{$self->branch_path};
+
+      if ($path->{action} eq 'A') {
+        if (exists $path->{'copyfrom-path'}) {
+          # Current branch is copied from somewhere, set the source as the parent
+          my $url = $self->root .  $path->{'copyfrom-path'};
+          my $rev = $path->{'copyfrom-rev'};
+          $self->{PARENT} = Fcm::CmBranch->new (URL => $url . '@' . $rev);
+
+        } else {
+          # Current branch is not copied from somewhere
+          $self->{PARENT} = $self;
+        }
+      }
+    }
+  }
+
+  return $self->{PARENT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cm_branch->delete_rev;
+#
+# DESCRIPTION
+#   This method returns the revision at which the branch was deleted.
+# ------------------------------------------------------------------------------
+
+sub delete_rev {
+  my $self = shift;
+
+  if (not $self->{DELETE_REV}) {
+    return if $self->url_exists ('HEAD');
+
+    # Container of the current URL
+    (my $dir_url = $self->branch_url) =~ s#/+[^/]+/*$##;
+
+    # Use "svn log" on the container between a revision where the branch exists
+    # and the HEAD
+    my $dir = Fcm::CmUrl->new (URL => $dir_url);
+    my %log = $dir->svnlog (
+      REV => ['HEAD', ($self->pegrev ? $self->pegrev : $self->create_rev)],
+    );
+
+    # Go through the log to see when branch no longer exists
+    for my $rev (sort {$a <=> $b} keys %log) {
+      next unless exists $log{$rev}{paths}{$self->branch_path} and
+                  $log{$rev}{paths}{$self->branch_path}{action} eq 'D';
+
+      $self->{DELETE_REV} = $rev;
+      last;
+    }
+  }
+
+  return $self->{DELETE_REV};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_branch->is_child_of ($branch);
+#
+# DESCRIPTION
+#   This method returns true if the current branch is a child of $branch.
+# ------------------------------------------------------------------------------
+
+sub is_child_of {
+  my ($self, $branch) = @_;
+
+  # The trunk cannot be a child branch
+  return if $self->is_trunk;
+
+  # If $branch is a branch, use name of $self to see when it is created
+  if ($branch->is_branch and $self->url =~ m#/r(\d+)_[^/]+/*$#) {
+    my $rev = $1;
+
+    # $self can only be a child if it is copied from a revision > the create
+    # revision of $branch
+    return if $rev < $branch->create_rev;
+  }
+
+  return if $self->parent->url ne $branch->url;
+
+  # If $branch is a branch, ensure that it is created before $self
+  return if $branch->is_branch and $self->create_rev <= $branch->create_rev;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_branch->is_sibling_of ($branch);
+#
+# DESCRIPTION
+#   This method returns true if the current branch is a sibling of $branch.
+# ------------------------------------------------------------------------------
+
+sub is_sibling_of {
+  my ($self, $branch) = @_;
+
+  # The trunk cannot be a sibling branch
+  return if $branch->is_trunk;
+
+  return if $self->parent->url ne $branch->parent->url;
+
+  # If the parent is a branch, ensure they are actually the same branch
+  return if $branch->parent->is_branch and
+            $self->parent->create_rev != $branch->parent->create_rev;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_relatives ($relation);
+#
+# DESCRIPTION
+#   This method sets the $self->{$relation} variable by inspecting the list of
+#   branches at the current revision of the current branch. $relation can be
+#   either "CHILDREN" or "SIBLINGS".
+# ------------------------------------------------------------------------------
+
+sub _get_relatives {
+  my ($self, $relation) = @_;
+
+  my @branch_list = $self->branch_list;
+
+  $self->{$relation} = [];
+
+  # If we are searching for CHILDREN, get list of SIBLINGS, and vice versa
+  my $other = ($relation eq 'CHILDREN' ? 'SIBLINGS' : 'CHILDREN');
+  my %other_list;
+  if ($self->{$other}) {
+    %other_list = map {$_->url, 1} @{ $self->{$other} };
+  }
+
+  for my $u (@branch_list) {
+    # Ignore URL of current branch and its parent
+    next if $u eq $self->url;
+    next if $self->is_branch and $u eq $self->parent->url;
+
+    # Ignore if URL is a branch detected to be another type of relative
+    next if exists $other_list{$u};
+
+    # Construct new Fcm::CmBranch object from branch URL
+    my $url = $u . ($self->pegrev ? '@' . $self->pegrev : '');
+    my $branch = Fcm::CmBranch->new (URL => $url);
+
+    # Test whether $branch is a relative we are looking for
+    if ($relation eq 'CHILDREN') {
+      push @{ $self->{$relation} }, $branch if $branch->is_child_of ($self);
+
+    } else {
+      push @{ $self->{$relation} }, $branch if $branch->is_sibling_of ($self);
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @children = $cm_branch->children;
+#
+# DESCRIPTION
+#   This method returns a list of children (Fcm::CmBranch objects) of the
+#   current branch that exists in the current revision.
+# ------------------------------------------------------------------------------
+
+sub children {
+  my $self = shift;
+
+  $self->_get_relatives ('CHILDREN') if not $self->{CHILDREN};
+
+  return @{ $self->{CHILDREN} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @siblings = $cm_branch->siblings;
+#
+# DESCRIPTION
+#   This method returns a list of siblings (Fcm::CmBranch objects) of the
+#   current branch that exists in the current revision.
+# ------------------------------------------------------------------------------
+
+sub siblings {
+  my $self = shift;
+
+  $self->_get_relatives ('SIBLINGS') if not $self->{SIBLINGS};
+
+  return @{ $self->{SIBLINGS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ancestor = $cm_branch->ancestor ($branch);
+#
+# DESCRIPTION
+#   This method returns the common ancestor (a Fcm::CmBranch object) of a
+#   specified $branch and the current branch. The argument $branch must be a
+#   Fcm::CmBranch object. Both the current branch and $branch are assumed to be
+#   in the same project.
+# ------------------------------------------------------------------------------
+
+sub ancestor {
+  my ($self, $branch) = @_;
+
+  if (not exists $self->{ANCESTOR}{$branch->url_peg}) {
+    if ($self->url_peg eq $branch->url_peg) {
+      $self->{ANCESTOR}{$branch->url_peg} = $self;
+
+    } else {
+      # Get family tree of current branch, from trunk to current branch
+      my @this_family = ($self);
+      while (not $this_family [0]->is_trunk) {
+        unshift @this_family, $this_family [0]->parent;
+      }
+
+      # Get family tree of $branch, from trunk to $branch
+      my @that_family = ($branch);
+      while (not $that_family [0]->is_trunk) {
+        unshift @that_family, $that_family [0]->parent;
+      }
+
+      # Find common ancestor from list of parents
+      my $ancestor = undef;
+
+      while (not $ancestor) {
+        # $this and $that should both start as some revisions on the trunk.
+        # Walk down a generation each time it loops around.
+        my $this = shift @this_family;
+        my $that = shift @that_family;
+
+        if ($this->url eq $that->url) {
+          if ($this->is_trunk or $this->create_rev eq $that->create_rev) {
+            # $this and $that are the same branch
+            if (@this_family and @that_family) {
+              # More generations in both branches, try comparing the next
+              # generations.
+              next;
+
+            } else {
+              # End of lineage in one of the branches, ancestor is at the lower
+              # revision of the current URL.
+              if ($this->pegrev and $that->pegrev) {
+                $ancestor = $this->pegrev < $that->pegrev ? $this : $that;
+
+              } else {
+                $ancestor = $this->pegrev ? $this : $that;
+              }
+            }
+
+          } else {
+            # Despite the same URL, $this and $that are different branches as
+            # they are created at different revisions. The ancestor must be the
+            # parent with the lower revision. (This should not occur at the
+            # start.)
+            $ancestor = $this->parent->pegrev < $that->parent->pegrev
+                        ? $this->parent : $that->parent;
+          }
+
+        } else {
+          # Different URLs, ancestor must be the parent with the lower revision.
+          # (This should not occur at the start.)
+          $ancestor = $this->parent->pegrev < $that->parent->pegrev
+                      ? $this->parent : $that->parent;
+        }
+      }
+
+      $self->{ANCESTOR}{$branch->url_peg} = $ancestor;
+    }
+  }
+
+  return $self->{ANCESTOR}{$branch->url_peg};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   ($target, $upper, $lower) = $cm_branch->last_merge_from (
+#     $branch, $stop_on_copy,
+#   );
+#
+# DESCRIPTION
+#   This method returns a 3-element list with information of the last merge
+#   into the current branch from a specified $branch. The first element in the
+#   list $target (a Fcm::CmBranch object) is the target at which the merge was
+#   performed. (This can be the current branch or a parent branch up to the
+#   common ancestor with the specified $branch.) The second and third elements,
+#   $upper and $lower, (both Fcm::CmBranch objects), are the upper and lower
+#   ends of the source delta. If there is no merge from $branch into the
+#   current branch from their common ancestor to the current revision, this
+#   method will return an empty list. If $stop_on_copy is specified, it ignores
+#   merges from parents of $branch, and merges into parents of the current
+#   branch.
+# ------------------------------------------------------------------------------
+
+sub last_merge_from {
+  my ($self, $branch, $stop_on_copy) = @_;
+
+  if (not exists $self->{LAST_MERGE}{$branch->url_peg}) {
+    # Get "log" of current branch down to the common ancestor
+    my %log = $self->svnlog (
+      REV => [
+       ($self->pegrev ? $self->pegrev : 'HEAD'),
+       $self->ancestor ($branch)->pegrev,
+      ],
+
+      STOP_ON_COPY => $stop_on_copy,
+    );
+
+    my $cr = $self;
+
+    # Go down the revision log, checking for merge template messages
+    REV: for my $rev (sort {$b <=> $a} keys %log) {
+      # Loop each line of the log message at each revision
+      my @msg = split /\n/, $log{$rev}{msg};
+
+      # Also consider merges into parents of current branch
+      $cr = $cr->parent if ($cr->is_branch and $rev < $cr->create_rev);
+
+      for (@msg) {
+        # Ignore unless log message matches a merge template
+        next unless /Merged into \S+: (\S+) cf\. (\S+)/;
+
+        # Upper $1 and lower $2 ends of the source delta
+        my $u_path = $1;
+        my $l_path = $2;
+
+        # Add the root directory to the paths if necessary
+        $u_path = '/' . $u_path if substr ($u_path, 0, 1) ne '/';
+        $l_path = '/' . $l_path if substr ($l_path, 0, 1) ne '/';
+
+        # Only consider merges with specified branch (and its parent)
+        (my $path = $u_path) =~ s/@(\d+)$//;
+        my $u_rev = $1;
+
+        my $br = $branch;
+        $br    = $br->parent while (
+          $br->is_branch and $u_rev < $br->create_rev and not $stop_on_copy
+        );
+
+        next unless $br->branch_path eq $path;
+
+        # If $br is a parent of branch, ignore those merges with the parent
+        # above the branch point of the current branch
+        next if $br->pegrev and $br->pegrev < $u_rev;
+
+        # Set the return values
+        $self->{LAST_MERGE}{$branch->url_peg} = [
+          Fcm::CmBranch->new (URL => $cr->url . '@' . $rev), # target
+          Fcm::CmBranch->new (URL => $self->root . $u_path), # delta upper
+          Fcm::CmBranch->new (URL => $self->root . $l_path), # delta lower
+        ];
+
+        last REV;
+      }
+    }
+  }
+
+  return (exists $self->{LAST_MERGE}{$branch->url_peg}
+          ? @{ $self->{LAST_MERGE}{$branch->url_peg} } : ());
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @revs = $cm_branch->avail_merge_from ($branch[, $stop_on_copy]);
+#
+# DESCRIPTION
+#   This method returns a list of revisions of a specified $branch, which are
+#   available for merging into the current branch. If $stop_on_copy is
+#   specified, it will not list available merges from the parents of $branch.
+# ------------------------------------------------------------------------------
+
+sub avail_merge_from {
+  my ($self, $branch, $stop_on_copy) = @_;
+
+  if (not exists $self->{AVAIL_MERGE}{$branch->url_peg}) {
+    # Find out the revision of the upper delta at the last merge from $branch
+    # If no merge is found, use revision of common ancestor with $branch
+    my @last_merge = $self->last_merge_from ($branch);
+    my $rev        = $self->ancestor ($branch)->pegrev;
+    $rev           = $last_merge [1]->pegrev
+      if @last_merge and $last_merge [1]->pegrev > $rev;
+
+    # Get the "log" of the $branch down to $rev
+    my %log = $branch->svnlog (
+      REV          => [($branch->pegrev ? $branch->pegrev : 'HEAD'), $rev],
+      STOP_ON_COPY => $stop_on_copy,
+    );
+
+    # No need to include $rev itself, as it has already been merged
+    delete $log{$rev};
+
+    # No need to include the branch create revision
+    delete $log{$branch->create_rev}
+      if $branch->is_branch and exists $log{$branch->create_rev};
+
+    if (keys %log) {
+      # Check whether there is a latest merge from $self into $branch, if so,
+      # all revisions of $branch below that merge should become unavailable
+      my @last_merge_into = $branch->last_merge_from ($self);
+
+      if (@last_merge_into) {
+        for my $rev (keys %log) {
+          delete $log{$rev} if $rev < $last_merge_into [0]->pegrev;
+        }
+      }
+    }
+
+    # Available merges include all revisions above the branch creation revision
+    # or the revision of the last merge
+    $self->{AVAIL_MERGE}{$branch->url_peg} = [sort {$b <=> $a} keys %log];
+  }
+
+  return @{ $self->{AVAIL_MERGE}{$branch->url_peg} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $lower = $cm_branch->base_of_merge_from ($branch);
+#
+# DESCRIPTION
+#   This method returns the lower delta (a Fcm::CmBranch object) for the next
+#   merge from $branch.
+# ------------------------------------------------------------------------------
+
+sub base_of_merge_from {
+  my ($self, $branch) = @_;
+
+  # Base is the ancestor if there is no merge between $self and $branch
+  my $return = $self->ancestor ($branch);
+
+  # Get configuration for the last merge from $branch to $self
+  my @merge_from = $self->last_merge_from ($branch);
+
+  # Use the upper delta of the last merge from $branch, as all revisions below
+  # that have already been merged into the $self
+  $return = $merge_from [1]
+    if @merge_from and $merge_from [1]->pegrev > $return->pegrev;
+
+  # Get configuration for the last merge from $self to $branch
+  my @merge_into = $branch->last_merge_from ($self);
+
+  # Use the upper delta of the last merge from $self, as the current revision
+  # of $branch already contains changes of $self up to the peg revision of the
+  # upper delta
+  $return = $merge_into [1]
+    if @merge_into and $merge_into [0]->pegrev > $return->pegrev;
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_branch->allow_subdir_merge_from ($branch, $subdir);
+#
+# DESCRIPTION
+#   This method returns true if a merge from the sub-directory $subdir in
+#   $branch  is allowed - i.e. it does not result in losing changes made in
+#   $branch outside of $subdir.
+# ------------------------------------------------------------------------------
+
+sub allow_subdir_merge_from {
+  my ($self, $branch, $subdir) = @_;
+
+  # Get revision at last merge from $branch or ancestor
+  my @merge_from = $self->last_merge_from ($branch);
+  my $last       = @merge_from ? $merge_from [1] : $self->ancestor ($branch);
+  my $rev        = $last->pegrev;
+
+  if ($branch->pegrev > $rev) {
+    # Inspect log from revision at last merge/ancestor to current revision
+    my %log = $branch->svnlog (REV => [$branch->pegrev, $rev + 1]);
+    my $br  = $branch;
+
+    # Check whether there are changes outside of $subdir
+    for my $rev (sort {$b <=> $a} keys %log) {
+      $br = $br->parent if $br->is_branch and $rev < $br->create_rev;
+
+      for my $path (keys %{ $log{$rev}{paths} }) {
+        next if $path eq $br->branch_path; # Ignore branch creation
+
+        my $p_subdir = substr ($path, length ($br->branch_path) + 1);
+
+        return if $p_subdir !~ m#^$subdir(?:/|$)#;
+      }
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch->create (
+#     SRC                  => $src,
+#     TYPE                 => $type,
+#     NAME                 => $name,
+#     [PASSWORD            => $password,]
+#     [REV_FLAG            => $rev_flag,]
+#     [TICKET              => \@tickets,]
+#     [REV                 => $rev,]
+#     [NON_INTERACTIVE     => 1,]
+#     [SVN_NON_INTERACTIVE => 1,]
+#   );
+#
+# DESCRIPTION
+#   This method creates a branch in a Subversion repository.
+#
+# OPTIONS
+#   SRC                 - reference to a Fcm::CmUrl object.
+#   TYPE                - Specify the branch type. See help in "fcm branch" for
+#                         further information.
+#   NAME                - specify the name of the branch.
+#   NON_INTERACTIVE     - Do no interactive prompting, set SVN_NON_INTERACTIVE
+#                         to true automatically.
+#   PASSWORD            - specify the password for commit access.
+#   REV                 - specify the operative revision of the source.
+#   REV_FLAG            - A flag to specify the behaviour of the prefix to the
+#                         branch name. See help in "fcm branch" for further
+#                         information.
+#   SVN_NON_INTERACTIVE - Do no interactive prompting when running svn commit,
+#                         etc. This option is implied by NON_INTERACTIVE.
+#   TICKET              - Specify one or more related tickets for the branch.
+# ------------------------------------------------------------------------------
+
+sub create {
+  my $self = shift;
+  my %args = @_;
+
+  # Options
+  # ----------------------------------------------------------------------------
+  # Compulsory options
+  my $src  = $args{SRC};
+  my $type = $args{TYPE};
+  my $name = $args{NAME};
+
+  # Other options
+  my $rev_flag        = $args{REV_FLAG}        ? $args{REV_FLAG}    : 'NORMAL';
+  my @tickets         = exists $args{TICKET}   ? @{ $args{TICKET} } : ();
+  my $password        = exists $args{PASSWORD} ? $args{PASSWORD}    : undef;
+  my $orev            = exists $args{REV}      ? $args{REV}         : 'HEAD';
+
+  my $non_interactive     = exists $args{NON_INTERACTIVE}
+                            ? $args{NON_INTERACTIVE} : 0;
+  my $svn_non_interactive = exists $args{SVN_NON_INTERACTIVE}
+                            ? $args{SVN_NON_INTERACTIVE} : 0;
+  $svn_non_interactive    = $non_interactive ? 1 : $svn_non_interactive;
+
+  # Analyse the source URL
+  # ----------------------------------------------------------------------------
+  # Create branch from the trunk by default
+  $src->branch ('trunk') if not $src->branch;
+
+  # Remove "sub-directory" part from source URL
+  $src->subdir ('')      if $src->subdir;
+
+  # Remove "peg revision" part because it does not work with "svn copy"
+  $src->pegrev ('')      if $src->pegrev;
+
+  # Find out the URL and the last changed revision of the specified URL at the
+  # specified operative revision
+  my $url = $src->svninfo (FLAG => 'URL', REV => $orev);
+  e_report $src->url, ': cannot determine the operative URL at revision ',
+           $orev, ', abort.' if not $url;
+
+  $src->url ($url) if $url ne $src->url;
+
+  my $rev = $src->svninfo (FLAG => 'Last Changed Rev', REV => $orev);
+  e_report $src->url, ': cannot determine the last changed rev at revision',
+           $orev, ', abort.' if not $rev;
+
+  # Warn user if last changed revision is not the specified revision
+  w_report 'Warning: branch will be created from revision ', $rev,
+           ', i.e. the last changed rev.'
+    unless $orev and $orev eq $rev;
+
+  # Determine the sub-directory names of the branch
+  # ----------------------------------------------------------------------------
+  my @branch_dirs = ('branches');
+
+  # Split branch type flags into a hash table
+  my %type_flags = ();
+  $type_flags{$_} = 1 for ((split /::/, $type));
+
+  # Branch sub-directory 1, development, test or package
+  for my $flag (qw/DEV TEST PKG/) {
+    if (exists $type_flags{$flag}) {
+      push @branch_dirs, lc ($flag);
+      last;
+    }
+  }
+
+  # Branch sub-directory 2, user, share, configuration or release
+  if (exists $type_flags{USER}) {
+    my $userid = getlogin;
+    $userid    = $ENV{LOGNAME} unless $userid;
+    $userid    = $ENV{USER}    unless $userid;
+    die 'Unable to determine your user ID, abort' unless $userid;
+
+    push @branch_dirs, $userid;
+
+  } else {
+    for my $flag (qw/SHARE CONFIG REL/) {
+      if (exists $type_flags{$flag}) {
+        push @branch_dirs, uc (substr $flag, 0, 1) . lc (substr $flag, 1);
+        last;
+      }
+    }
+  }
+
+  # Branch sub-directory 3, branch name
+  # Prefix branch name with revision number/keyword if necessary
+  my $prefix = '';
+  if ($rev_flag ne 'NONE') {
+    $prefix = $rev;
+
+    # Attempt to replace revision number with a revision keyword if necessary
+    $prefix = &get_rev_keyword (
+      REV => $rev,
+      URL => $src->url_peg,
+    ) if $rev_flag eq 'NORMAL';
+
+    # $prefix is still a revision number, add "r" in front of it
+    $prefix = 'r' . $prefix if $prefix eq $rev;
+
+    # Add an underscore before the branch name
+    $prefix.= '_';
+  }
+
+  # Branch name
+  push @branch_dirs, $prefix . $name;
+
+  # Check whether the branch already exists, fail if so
+  # ----------------------------------------------------------------------------
+  # Construct the URL of the branch
+  $self->project_url ($src->project_url);
+  $self->branch  (join ('/', @branch_dirs));
+
+  # Check that branch does not already exists
+  e_report $self->url, ': branch already exists, abort.' if $self->url_exists;
+
+  # Message for the commit log
+  # ----------------------------------------------------------------------------
+  my @message = ('Created ' . $self->branch_path .  ' from ' .
+                 $src->branch_path . '@' . $rev . '.' . "\n");
+
+  # Add related Trac ticket links to commit log if set
+  if (@tickets) {
+    my $ticket_mesg = 'Relates to ticket' . (@tickets > 1 ? 's' : '');
+
+    while (my $ticket = shift @tickets) {
+      $ticket_mesg .= ' #' . $ticket;
+      $ticket_mesg .= (@tickets > 1 ? ',' : ' and') if @tickets >= 1;
+    }
+
+    push @message, $ticket_mesg . ".\n";
+  }
+
+  # Create a temporary file for the commit log message
+  my $ci_mesg = Fcm::CmCommitMessage->new;
+  $ci_mesg->auto_mesg (@message);
+  $ci_mesg->ignore_mesg ('A' . ' ' x 4 . $self->url . "\n");
+  my $logfile = $ci_mesg->edit_file (TEMP => 1, BATCH => $non_interactive);
+
+  # Check with the user to see if he/she wants to go ahead
+  # ----------------------------------------------------------------------------
+  if (not $non_interactive) {
+    my $reply = &main::get_input (
+      TITLE   => 'fcm branch',
+      MESSAGE => 'Would you like to go ahead and create this branch?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    return unless $reply eq 'y';
+  }
+
+  # Ensure existence of container sub-directories of the branch
+  # ----------------------------------------------------------------------------
+  for my $i (0 .. $#branch_dirs - 1) {
+    my $subdir     = join ('/', @branch_dirs[0 .. $i]);
+    my $subdir_url = Fcm::CmUrl->new (URL => $src->project_url . '/' . $subdir);
+
+    # Check whether each sub-directory of the branch already exists,
+    # if sub-directory does not exist, create it
+    next if $subdir_url->url_exists;
+
+    print 'Creating sub-directory: ', $subdir, "\n";
+
+    my @command = (
+      qw/svn mkdir/,
+      '-m', 'Created ' . $subdir . ' directory.',
+      ($svn_non_interactive  ? '--non-interactive'       : ()),
+      (defined $password     ? ('--password', $password) : ()),
+
+      $subdir_url->url,
+    );
+    &run_command (\@command);
+  }
+
+  # Create the branch
+  # ----------------------------------------------------------------------------
+  {
+    print 'Creating branch ', $self->url, ' ...', "\n";
+    my @command = (
+      qw/svn copy/,
+      '-r', $rev,
+      '-F', $logfile,
+      ($svn_non_interactive  ? '--non-interactive'       : ()),
+      (defined $password     ? ('--password', $password) : ()),
+
+      $src->url, $self->url,
+    );
+    &run_command (\@command);
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch->delete (
+#     [NON_INTERACTIVE     => 1,]
+#     [PASSWORD            => $password,]
+#     [SVN_NON_INTERACTIVE => 1,]
+#   );
+#
+# DESCRIPTION
+#   This method deletes the current branch from the Subversion repository.
+#
+# OPTIONS
+#   NON_INTERACTIVE     - Do no interactive prompting, set SVN_NON_INTERACTIVE
+#                         to true automatically.
+#   PASSWORD            - specify the password for commit access.
+#   SVN_NON_INTERACTIVE - Do no interactive prompting when running svn commit,
+#                         etc. This option is implied by NON_INTERACTIVE.
+# ------------------------------------------------------------------------------
+
+sub del {
+  my $self = shift;
+  my %args = @_;
+
+  # Options
+  # ----------------------------------------------------------------------------
+  my $password            = exists $args{PASSWORD} ? $args{PASSWORD} : undef;
+  my $non_interactive     = exists $args{NON_INTERACTIVE}
+                            ? $args{NON_INTERACTIVE} : 0;
+  my $svn_non_interactive = exists $args{SVN_NON_INTERACTIVE}
+                            ? $args{SVN_NON_INTERACTIVE} : 0;
+  $svn_non_interactive    = $non_interactive ? 1 : $svn_non_interactive;
+
+  # Ensure URL is a branch
+  # ----------------------------------------------------------------------------
+  e_report $self->url_peg, ': not a branch, abort.' if not $self->is_branch;
+
+  # Message for the commit log
+  # ----------------------------------------------------------------------------
+  my @message = ('Deleted ' . $self->branch_path . '.' . "\n");
+
+  # Create a temporary file for the commit log message
+  my $ci_mesg = Fcm::CmCommitMessage->new ();
+  $ci_mesg->auto_mesg (@message);
+  $ci_mesg->ignore_mesg ('D' . ' ' x 4 . $self->url . "\n");
+  my $logfile = $ci_mesg->edit_file (TEMP => 1, BATCH => $non_interactive);
+
+  # Check with the user to see if he/she wants to go ahead
+  # ----------------------------------------------------------------------------
+  if (not $non_interactive) {
+    my $reply = &main::get_input (
+      TITLE   => 'fcm branch',
+      MESSAGE => 'Would you like to go ahead and delete this branch?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    return unless $reply eq 'y';
+  }
+
+  # Delete branch if answer is "y" for "yes"
+  # ----------------------------------------------------------------------------
+  print 'Deleting branch ', $self->url, ' ...', "\n";
+  my @command = (
+    qw/svn delete/,
+    '-F', $logfile,
+    (defined $password    ? ('--password', $password) : ()),
+    ($svn_non_interactive ? '--non-interactive'       : ()),
+
+    $self->url,
+  );
+  &run_command (\@command);
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch->display_info (
+#     [SHOW_CHILDREN => 1],
+#     [SHOW_OTHER    => 1]
+#     [SHOW_SIBLINGS => 1]
+#   );
+#
+# DESCRIPTION
+#   This method displays information of the current branch. If SHOW_CHILDREN is
+#   set, it shows information of all current children branches of the current
+#   branch. If SHOW_SIBLINGS is set, it shows information of siblings that have
+#   been merged recently with the current branch. If SHOW_OTHER is set, it shows
+#   information of custom/reverse merges.
+# ------------------------------------------------------------------------------
+
+sub display_info {
+  my $self = shift;
+  my %args = @_;
+
+  # Arguments
+  # ----------------------------------------------------------------------------
+  my $show_children = exists $args{SHOW_CHILDREN} ? $args{SHOW_CHILDREN} : 0;
+  my $show_other    = exists $args{SHOW_OTHER   } ? $args{SHOW_OTHER}    : 0;
+  my $show_siblings = exists $args{SHOW_SIBLINGS} ? $args{SHOW_SIBLINGS} : 0;
+
+  # Useful variables
+  # ----------------------------------------------------------------------------
+  my $separator  = '-' x 80 . "\n";
+  my $separator2 = '  ' . '-' x 78 . "\n";
+
+  # Print "info" as returned by "svn info"
+  # ----------------------------------------------------------------------------
+  for my $key ('URL', 'Repository Root', 'Revision', 'Last Changed Author',
+               'Last Changed Rev', 'Last Changed Date') {
+    print $key, ': ', $self->svninfo (FLAG => $key), "\n"
+      if $self->svninfo (FLAG => $key);
+  }
+
+  if ($self->config->verbose) {
+    # Verbose mode, print log message at last changed revision
+    my %log = $self->svnlog (REV => $self->svninfo (FLAG => 'Last Changed Rev'));
+    my @log = split /\n/, $log{msg};
+    print 'Last Changed Log:', "\n\n", map ({'  ' . $_ . "\n"} @log), "\n";
+  }
+
+  if ($self->is_branch) {
+    # Print create information
+    # --------------------------------------------------------------------------
+    my %log = $self->svnlog (REV => $self->create_rev);
+
+    print $separator;
+    print 'Branch Create Author: ', $log{author}, "\n" if $log{author};
+    print 'Branch Create Rev: ', $self->create_rev, "\n";
+    print 'Branch Create Date: ', &svn_date ($log{date}), "\n";
+
+    if ($self->config->verbose) {
+      # Verbose mode, print log message at last create revision
+      my @log = split /\n/, $log{msg};
+      print 'Branch Create Log:', "\n\n", map ({'  ' . $_ . "\n"} @log), "\n";
+    }
+
+    # Print delete information if branch no longer exists
+    # --------------------------------------------------------------------------
+    print 'Branch Delete Rev: ', $self->delete_rev, "\n" if $self->delete_rev;
+
+    # Report merges into/from the parent
+    # --------------------------------------------------------------------------
+    # Print the URL@REV of the parent branch
+    print $separator, 'Branch Parent: ', $self->parent->url_peg, "\n";
+
+    # Set up a new object for the parent at the current revision
+    # --------------------------------------------------------------------------
+    my $p_url  = $self->parent->url;
+    $p_url    .= '@' . $self->pegrev if $self->pegrev;
+    my $parent = Fcm::CmBranch->new (URL => $p_url);
+
+    if (not $parent->url_exists) {
+      print 'Branch parent deleted.', "\n";
+      return;
+    }
+
+    # Report merges into/from the parent
+    # --------------------------------------------------------------------------
+    print $self->_report_merges ($parent, 'Parent');
+  }
+
+  # Report merges with siblings
+  # ----------------------------------------------------------------------------
+  if ($show_siblings) {
+    # Report number of sibling branches found
+    print $separator, 'Seaching for siblings ... ';
+    my @siblings = $self->siblings;
+    print scalar (@siblings), ' ', (@siblings> 1 ? 'siblings' : 'sibling'),
+          ' found.', "\n";
+
+    # Report branch name and merge information only if there are recent merges
+    my $out = '';
+    for my $sibling (@siblings) {
+      my $string = $self->_report_merges ($sibling, 'Sibling');
+
+      $out .= $separator2 . '  ' . $sibling->url . "\n" . $string if $string;
+    }
+
+    if (@siblings) {
+      if ($out) {
+        print 'Merges with existing siblings:', "\n", $out;
+
+      } else {
+        print 'No merges with existing siblings.', "\n";
+      }
+    }
+  }
+
+  # Report children
+  # ----------------------------------------------------------------------------
+  if ($show_children) {
+    # Report number of child branches found
+    print $separator, 'Seaching for children ... ';
+    my @children = $self->children;
+    print scalar (@children), ' ', (@children > 1 ? 'children' : 'child'),
+          ' found.', "\n";
+
+    # Report children if they exist
+    print 'Current children:', "\n" if @children;
+
+    for my $child (@children) {
+      print $separator2, '  ', $child->url, "\n";
+      print '  Child Create Rev: ', $child->create_rev, "\n";
+      print $self->_report_merges ($child, 'Child');
+    }
+  }
+
+  # Report custom/reverse merges into the branch
+  # ----------------------------------------------------------------------------
+  if ($show_other) {
+    my %log = $self->svnlog (STOP_ON_COPY => 1);
+    my @out;
+
+    # Go down the revision log, checking for merge template messages
+    REV: for my $rev (sort {$b <=> $a} keys %log) {
+      # Loop each line of the log message at each revision
+      my @msg = split /\n/, $log{$rev}{msg};
+
+      for (@msg) {
+        # Ignore unless log message matches a merge template
+        if (/^Reversed r\d+(:\d+)? of \S+$/ or
+            s/^(Custom merge) into \S+(:.+)$/$1$2/) {
+          push @out, ('r' . $rev . ': ' . $_) . "\n";
+        }
+      }
+    }
+
+    print $separator, 'Other merges:', "\n", @out if @out;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $self->_report_merges ($branch, $relation);
+#
+# DESCRIPTION
+#   This method returns a string for displaying merge information with a
+#   branch, the $relation of which can be a Parent, a Sibling or a Child.
+# ------------------------------------------------------------------------------
+
+sub _report_merges {
+  my ($self, $branch, $relation) = @_;
+
+  my $indent    = ($relation eq 'Parent') ? '' : '  ';
+  my $separator = ($relation eq 'Parent') ? ('-' x 80) : ('  ' . '-' x 78);
+  $separator   .= "\n";
+
+  my $return = '';
+
+  # Report last merges into/from the $branch
+  # ----------------------------------------------------------------------------
+  my %merge  = (
+    'Last Merge From ' . $relation . ':'
+    => [$self->last_merge_from ($branch, 1)],
+    'Last Merge Into ' . $relation . ':'
+    => [$branch->last_merge_from ($self, 1)],
+  );
+
+  if ($self->config->verbose) {
+    # Verbose mode, print the log of the merge
+    for my $key (keys %merge) {
+      next if not @{ $merge{$key} };
+
+      # From: target (0) is self, upper delta (1) is $branch
+      # Into: target (0) is $branch, upper delta (1) is self
+      my $t = ($key =~ /From/) ? $self : $branch;
+
+      $return .= $indent . $key . "\n";
+      $return .= $separator . $t->display_svnlog ($merge{$key}[0]->pegrev);
+    }
+
+  } else {
+    # Normal mode, print in simplified form (rREV Parent@REV)
+    for my $key (keys %merge) {
+      next if not @{ $merge{$key} };
+
+      # From: target (0) is self, upper delta (1) is $branch
+      # Into: target (0) is $branch, upper delta (1) is self
+      $return .= $indent . $key . ' r' . $merge{$key}[0]->pegrev . ' ' .
+                 $merge{$key}[1]->path_peg . ' cf. ' .
+                 $merge{$key}[2]->path_peg . "\n";
+    }
+  }
+
+  if ($relation eq 'Sibling') {
+    # For sibling, do not report further if there is no recent merge
+    my @values = values %merge;
+
+    return $return unless (@{ $values[0] } or @{ $values[1] });
+  }
+
+  # Report available merges into/from the $branch
+  # ----------------------------------------------------------------------------
+  my %avail = (
+    'Merges Avail From ' . $relation . ':'
+    => ($self->delete_rev ? [] : [$self->avail_merge_from ($branch, 1)]),
+    'Merges Avail Into ' . $relation . ':'
+    => [$branch->avail_merge_from ($self, 1)],
+  );
+
+  if ($self->config->verbose) {
+    # Verbose mode, print the log of each revision
+    for my $key (keys %avail) {
+      next unless @{ $avail{$key} };
+
+      $return .= $indent . $key . "\n";
+
+      my $s = ($key =~ /From/) ? $branch: $self;
+
+      for my $rev (@{ $avail{$key} }) {
+        $return .= $separator . $s->display_svnlog ($rev);
+      }
+    }
+
+  } else {
+    # Normal mode, print only the revisions
+    for my $key (keys %avail) {
+      next unless @{ $avail{$key} };
+
+      $return .= $indent . $key . ' ' . join (' ', @{ $avail{$key} }) . "\n";
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmCommitMessage.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmCommitMessage.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmCommitMessage.pm	(revision 329)
@@ -0,0 +1,395 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CmCommitMessage
+#
+# DESCRIPTION
+#   This class contains methods to read, write and edit the commit message file
+#   in a working copy.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CmCommitMessage;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use Cwd;
+use File::Spec;
+use File::Temp qw/tempfile/;
+
+# FCM component modules
+use Fcm::Util qw/e_report run_command/;
+
+# Commit log delimiter messages
+my $ignore_line = '--This line, and those below, will be ignored--';
+my $auto_line   = '--This line will be ignored and those below will be ' .
+                  'inserted automatically--';
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ci_mesg = Fcm::CmCommitMessage->new (
+#     CONFIG  => $config,
+#     DIR     => $dir,
+#     BASE    => $base,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CmCommitMessageFile class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   DIR    - directory containing the commit message file
+#   BASE   - base name of the commit message file
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG => (exists $args{CONFIG} ? $args{CONFIG} : &main::cfg),
+    DIR    => (exists $args{DIR}    ? $args{DIR}    : cwd),
+    BASE   => (exists $args{BASE}   ? $args{BASE}   : '#commit_message#'),
+    USER_M => [],
+    AUTO_M => [],
+    IGNORE => [],
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $ci_mesg->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $ci_mesg->dir;
+#   $ci_mesg->dir ($dir);
+#
+# DESCRIPTION
+#   This method returns the directory container of the commit message file. If
+#   an argument is specified, the directory is reset using the value of the
+#   argument. (It does nothing is the directory does not already exist.)
+# ------------------------------------------------------------------------------
+
+sub dir {
+  my $self = shift;
+
+  if (@_) {
+    my $dir = shift;
+    $self->{DIR} = $dir if -d $dir;
+  }
+
+  return $self->{DIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $base = $ci_mesg->base;
+#   $ci_mesg->base ($base);
+#
+# DESCRIPTION
+#   This method returns the base name of the commit message file. If an
+#   argument is specified, the file is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub base {
+  my $self = shift;
+
+  if (@_) {
+    $self->{BASE} = shift;
+  }
+
+  return $self->{BASE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $ci_mesg->file;
+#   $ci_mesg->file ($file);
+#
+# DESCRIPTION
+#   This method returns the full name of the commit message file. If an
+#   argument is specified, the file is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub file {
+  my $self = shift;
+
+  if (@_) {
+    my $file      = shift;
+    $self->{DIR}  = dirname  ($file);
+    $self->{BASE} = basename ($file);
+  }
+
+  return File::Spec->catfile ($self->{DIR}, $self->{BASE});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @mesg = $ci_mesg->user_mesg;
+#   $ci_mesg->user_mesg (@mesg);
+#
+# DESCRIPTION
+#   This method returns the user defined commit message. If an argument is
+#   specified, the message is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub user_mesg {
+  my $self = shift;
+
+  if (@_) {
+    @{ $self->{USER_M} } = @_;
+  }
+
+  return @{ $self->{USER_M} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @mesg = $ci_mesg->auto_mesg;
+#   $ci_mesg->auto_mesg (@mesg);
+#
+# DESCRIPTION
+#   This method returns the automatically inserted commit message. If an
+#   argument is specified, the message is reset using the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub auto_mesg {
+  my $self = shift;
+
+  if (@_) {
+    @{ $self->{AUTO_M} } = @_;
+  }
+
+  return @{ $self->{AUTO_M} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @mesg = $ci_mesg->ignore_mesg;
+#   $ci_mesg->ignore_mesg (@mesg);
+#
+# DESCRIPTION
+#   This method returns the ignored part of a commit message. If an argument is
+#   specified, the message is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub ignore_mesg {
+  my $self = shift;
+
+  if (@_) {
+    @{ $self->{IGNORE} } = @_;
+  }
+
+  return @{ $self->{IGNORE} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   ($user, $auto) = $ci_mesg->read_file ();
+#
+# DESCRIPTION
+#   This function reads from the commit log message file. It resets the user
+#   and the automatic messages after reading the file. It returns the message
+#   back in two array references.
+# ------------------------------------------------------------------------------
+
+sub read_file {
+  my $self = shift;
+
+  my @user = ();
+  my @auto = ();
+  my $file = $self->file;
+
+  if (-r $file) {
+    open FILE, '<', $file or croak 'Cannot open ', $file, '(', $!, '), abort';
+
+    my $in_auto = 0;
+    while (<FILE>) {
+      last if index ($_, $ignore_line) == 0; # ignore after the ignore delimiter
+
+      if (index ($_, $auto_line) == 0) {
+        # Beginning of the automatically inserted message delimiter
+        $in_auto = 1;
+        next;
+      }
+
+      if ($in_auto) {
+        push @auto, $_;
+
+      } else {
+        push @user, $_;
+      }
+    }
+
+    close FILE;
+
+    $self->user_mesg (@user);
+    $self->auto_mesg (@auto);
+  }
+
+  return (\@user, \@auto);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ci_mesg->write_file ();
+#
+# DESCRIPTION
+#   This function writes to the commit log message file based on the content of
+#   the user defined message, and the automatically inserted message.
+# ------------------------------------------------------------------------------
+
+sub write_file {
+  my $self = shift;
+  my %args = @_;
+
+  my @user = $self->user_mesg;
+  my @auto = $self->auto_mesg;
+  my $file = $self->file;
+
+  open FILE, '>', $file or die 'Cannot open ', $file, '(', $!, '), abort';
+  print FILE @user;
+  print FILE $auto_line, "\n", @auto if @auto;
+  close FILE or croak 'Cannot close ', $file, '(', $!, '), abort';
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $ci_mesg->edit_file ([TEMP => 1,] [BATCH => 1,]);
+#
+# DESCRIPTION
+#   This function normally triggers an editor for editing the commit message.
+#   If TEMP is set, it edits a temporary file. Otherwise, it edits the current
+#   commit message file. It resets the user defined message on success. Returns
+#   the name of the commit log file. Do not start the editor if BATCH is set.
+# ------------------------------------------------------------------------------
+
+sub edit_file {
+  my $self  = shift;
+  my %args  = @_;
+  my $temp  = exists $args{TEMP}  ? $args{TEMP}  : 0;
+  my $batch = exists $args{BATCH} ? $args{BATCH} : 0;
+
+  my @user   = $self->user_mesg;
+  my @auto   = $self->auto_mesg;
+  my @ignore = $self->ignore_mesg;
+  my $file   = $self->file;
+
+  if ($temp) {
+    my $fh;
+    ($fh, $file) = tempfile (SUFFIX => ".fcm", UNLINK => 1);
+    close $fh;
+  }
+
+  # Add original or code driven message and status information to the file
+  my $select = select;
+  open FILE, '>', $file or croak 'Cannot open ', $file, ' (', $!, '), abort';
+  select FILE;
+
+  print @user;
+  print (@auto || @user ? '' : "\n");
+  print $auto_line, "\n", @auto, "\n" if @auto;
+  print $ignore_line, "\n\n";
+  print @ignore if @ignore;
+
+  close FILE or die 'Cannot close ', $file, ' (', $!, '), abort';
+  select $select;
+
+  if (not $batch) {
+    # Select editor
+    my $editor = 'nedit';
+    
+    if ($ENV{'SVN_EDITOR'}) {
+      $editor = $ENV{'SVN_EDITOR'};
+
+    } elsif ($ENV{'VISUAL'}) {
+      $editor = $ENV{'VISUAL'};
+
+    } elsif ($ENV{'EDITOR'}) {
+      $editor = $ENV{'EDITOR'};
+    }
+
+    # Execute command to start the editor
+    print 'Starting ', $editor, ' to edit commit message ...', "\n";
+    &run_command ([split (/\s+/, $editor), $file]);
+  }
+
+  # Read the edited file, and extract user log message from it
+  open FILE, '<', $file or croak 'Cannot open ', $file, ' (', $!, '), abort';
+  my (@log);
+  my $in_auto    = 0;
+  my $in_ignored = 0;
+
+  while (<FILE>) {
+    if (index ($_, $auto_line) == 0) {
+      $in_auto = 1;
+
+    } elsif (index ($_, $ignore_line) == 0) {
+      $in_ignored = 1;
+      last;
+
+    } else {
+      next if $in_auto;
+      push @log, $_;
+    }
+  }
+
+  close FILE;
+
+  # Ensure auto and ignored lines are not altered
+  e_report 'Error: the line "', $auto_line, '" has been altered, abort.'
+    if @auto and not $in_auto;
+
+  e_report 'Error: the line "', $ignore_line, '" has been altered, abort.'
+    if not $in_ignored;
+
+  # Check for empty commit log
+  e_report 'Error: log message unchanged or not specified, abort.'
+    if join (' ', (@log, @auto)) =~ /^\s*$/;
+
+  # Echo the commit message to standard output
+  my $separator = '-' x 80 . "\n";
+  print 'Commit message is as follows:', "\n";
+  print $separator, @log, @auto, $ignore_line, "\n", @ignore, $separator;
+
+  open FILE, '>', $file or croak 'Cannot open ', $file, ' (', $!, '), abort';
+  print FILE @log, @auto;
+  close FILE or croak 'Cannot close ', $file, ' (', $!, '), abort';
+
+  # Reset the array for the user specified log message
+  $self->user_mesg (@log);
+
+  return $file;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmUrl.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmUrl.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/CmUrl.pm	(revision 329)
@@ -0,0 +1,1110 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CmUrl
+#
+# DESCRIPTION
+#   This class contains methods for manipulating a Subversion URL in a standard
+#   FCM project.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CmUrl;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use HTTP::Date;
+use XML::DOM;
+
+# FCM component modules
+use Fcm::Util qw/run_command svn_date get_browser_url/;
+
+# Revision pattern
+my $rev_pattern = '\d+|HEAD|BASE|COMMITTED|PREV|\{.+\}';
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_url = Fcm::CmUrl->new (
+#     CONFIG  => $config,
+#     URL     => $url,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CmUrl class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   URL    - URL of a branch
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG      => (exists $args{CONFIG} ? $args{CONFIG} : &main::cfg),
+    URL         => (exists $args{URL}    ? $args{URL}    : ''),
+    ANALYSED    => undef,
+    PROJECT     => undef,
+    BRANCH      => undef,
+    SUBDIR      => undef,
+    PEGREV      => undef,
+    LIST        => undef,
+    RLIST       => undef,
+    LOG         => undef,
+    LOG_RANGE   => undef,
+    INFO        => undef,
+    BRANCH_LIST => undef, # list of branches in current project
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $cm_url->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->url_peg;
+#   $cm_url->url_peg ($url);
+#
+# DESCRIPTION
+#   This method returns/sets the current URL@PEG.
+# ------------------------------------------------------------------------------
+
+sub url_peg {
+  my $self = shift;
+
+  if (@_) {
+    if (! $self->{URL} or $_[0] ne $self->{URL}) {
+      # Re-set URL
+      $self->{URL} = shift;
+
+      # Re-set essential variables
+      $self->{$_}  = undef for (qw/ANALYSED RLIST LIST INFO LOG LOG_RANGE/);
+    }
+  }
+
+  return $self->{URL};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_url ();
+#
+# DESCRIPTION
+#   Returns true if current url is a valid Subversion URL.
+# ------------------------------------------------------------------------------
+
+sub is_url {
+  my $self = shift;
+
+  # This should handle URL beginning with svn://, http:// and svn+ssh://
+  return ($self->url_peg =~ m#^[\+\w]+://#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->url_exists ([$rev]);
+#
+# DESCRIPTION
+#   Returns true if current url exists (at operative revision $rev) in a
+#   Subversion repository.
+# ------------------------------------------------------------------------------
+
+sub url_exists {
+  my ($self, $rev) = @_;
+
+  my $exists = $self->svnlist (REV => $rev);
+
+  return defined ($exists);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $cm_url->svninfo ([FLAG => $flag], [REV => $rev]);
+#
+# DESCRIPTION
+#   Returns the value of $flag, where $flag is a field returned by "svn info".
+#   (If $flag is not set, default to "URL".) Otherwise returns an empty string.
+#   If REV is specified, it will be used as the operative revision.
+# ------------------------------------------------------------------------------
+
+sub svninfo {
+  my $self = shift;
+  my %args = @_;
+
+  my $flag = exists $args{FLAG} ? $args{FLAG} : 'URL';
+  my $rev  = exists $args{REV}  ? $args{REV}  : undef;
+
+  $rev = ($self->pegrev ? $self->pegrev : 'HEAD') if not $rev;
+
+  return if not $self->is_url;
+
+  # Get "info" for the specified revision if necessary
+  if (not exists $self->{INFO}{$rev}) {
+    # Invoke "svn info" command
+    my @info = &run_command (
+      [qw/svn info -r/, $rev, $self->url_peg],
+      PRINT   => $self->config->verbose > 2,
+      METHOD  => 'qx',
+      DEVNULL => 1,
+      ERROR   => 'ignore',
+    );
+
+    # Store selected information
+    for (@info) {
+      chomp;
+
+      if (/^(.+?):\s*(.+)$/) {
+        $self->{INFO}{$rev}{$1} = $2;
+      }
+    }
+  }
+
+  my $return = exists $self->{INFO}{$rev}{$flag}
+               ? $self->{INFO}{$rev}{$flag} : undef;
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %logs = $cm_url->svnlog (
+#     [REV          => $rev,]
+#     [REV          => \@revs,] # reference to a 2-element array
+#     [STOP_ON_COPY => 1,]
+#   );
+#
+# DESCRIPTION
+#   Returns the logs for the current URL. If REV is a range of revisions or not
+#   specified, return a hash where the keys are revision numbers and the values
+#   are the entries (which are hash references). If a single REV is specified,
+#   return the entry (a hash reference) at the specified REV. Each entry in the
+#   returned list is a hash reference, with the following structure:
+#
+#   $entry = {
+#     author => $author,              # the commit author
+#     date   => $date,                # the commit date (in seconds since epoch)
+#     msg    => $msg,                 # the log message
+#     paths  => {                     # list of changed paths
+#       $path1  => {                  # a changed path
+#         copyfrom-path => $frompath, # copy-from-path
+#         copyfrom-rev  => $fromrev,  # copy-from-revision
+#         action        => $action,   # action status code
+#       },
+#       ...     => { ... },           # ... more changed paths ...
+#     },
+#   }
+# ------------------------------------------------------------------------------
+
+sub svnlog {
+  my $self = shift;
+  my %args = @_;
+
+  my $stop_on_copy  = exists $args{STOP_ON_COPY} ? $args{STOP_ON_COPY} : 0;
+  my $rev_arg       = exists $args{REV}          ? $args{REV}          : 0;
+
+  my @revs;
+
+  # Get revision options
+  # ----------------------------------------------------------------------------
+  if ($rev_arg) {
+    if (ref ($rev_arg)) {
+      # Revsion option is an array, a range of revisions specified?
+      ($revs [0], $revs [1]) = @$rev_arg;
+
+    } else {
+      # A single revision specified
+      $revs [0] = $rev_arg;
+    }
+
+    # Expand 'HEAD' revision
+    for my $rev (@revs) {
+      next unless uc ($rev) eq 'HEAD';
+      $rev = $self->svninfo (FLAG => 'Revision', REV => 'HEAD');
+    }
+
+  } else {
+    # No revision option specified, get log for all revisions
+    $revs [0] = $self->svninfo (FLAG => 'Revision');
+    $revs [1] = 1;
+  }
+
+  $revs [1] = $revs [0] if not $revs [1];
+  @revs     = sort {$b <=> $a} @revs;
+
+  # Check whether a "svn log" run is necessary
+  # ----------------------------------------------------------------------------
+  my $need_update = ! ($revs [0] == $revs [1] and exists $self->{LOG}{$revs [0]});
+  my @ranges      = @revs;
+  if ($need_update and $self->{LOG_RANGE}) {
+    my %log_range = %{ $self->{LOG_RANGE} };
+
+    if ($stop_on_copy) {
+      $ranges [1] = $log_range{UPPER} if $ranges [1] >= $log_range{LOWER_SOC};
+
+    } else {
+      $ranges [1] = $log_range{UPPER} if $ranges [1] >= $log_range{LOWER};
+    }
+  }
+
+  $need_update = 0 if $ranges [0] < $ranges [1];
+
+  if ($need_update) {
+    # Invoke "svn log" command for all revisions of the current branch
+    # --------------------------------------------------------------------------
+    my @command = (
+      qw/svn log --xml -v/, ($stop_on_copy ? '--stop-on-copy' : ()),
+      '-r' . join (':', @ranges),
+      $self->url,
+    );
+
+    my $rc;
+    my @xml = &run_command (
+      \@command,
+      PRINT   => $self->config->verbose > 2,
+      METHOD  => 'qx',
+      DEVNULL => 1,
+      ERROR   => 'ignore',
+      RC      => \$rc,
+    );
+
+    # Parse the XML
+    # --------------------------------------------------------------------------
+    if (not $rc) {
+      my $parser = XML::DOM::Parser->new;
+      my $doc    = $parser->parse (join ('', @xml));
+
+      my $entry_list = $doc->getElementsByTagName ('logentry');
+
+      # Record the author, date, message and path change for each revision
+      for my $i (0 .. $entry_list->getLength - 1) {
+        # Select current entry from node list
+        my $entry = $entry_list->item ($i);
+        my %this = ();
+
+        # Revision is an attribute of the entry node
+        my $rev   = $entry->getAttributeNode ('revision')->getValue;
+
+        # Author, date and log message are children elements of the entry node
+        for my $key (qw/author date msg/) {
+          # Get data of each node, also convert date to seconds since epoch
+          my $node    = $entry->getElementsByTagName ($key)->item (0);
+          my $data    = ($node and $node->getFirstChild)
+                        ? $node->getFirstChild->getData : '';
+          $this{$key} = ($key eq 'date' ? str2time ($data) : $data);
+        }
+
+        # Path nodes are grand children elements of the entry node
+        my $paths = $entry->getElementsByTagName ('path');
+
+        for my $p (0 .. $paths->getLength - 1) {
+          # Select current path node from node list
+          my $node = $paths->item ($p);
+
+          # Get data from the path node
+          my $path = $node->getFirstChild->getData;
+          $this{paths}{$path} = {};
+
+          # Action, copyfrom-path and copyfrom-rev are attributes of path nodes
+          for my $key (qw/action copyfrom-path copyfrom-rev/) {
+            next unless $node->getAttributeNode ($key); # ensure attribute exists
+
+            $this{paths}{$path}{$key} = $node->getAttributeNode ($key)->getValue;
+          }
+        }
+
+        $self->{LOG}{$rev} = \%this;
+      }
+    }
+
+    # Update the range cache
+    # --------------------------------------------------------------------------
+    # Upper end of the range
+    $self->{LOG_RANGE}{UPPER} = $ranges [0]
+      if ! $self->{LOG_RANGE}{UPPER} or $ranges [0] > $self->{LOG_RANGE}{UPPER};
+
+    # Lower end of the range, need to take into account the stop-on-copy option
+    if ($stop_on_copy) {
+      # Lower end of the range with stop-on-copy option
+      $self->{LOG_RANGE}{LOWER_SOC} = $ranges [1]
+        if ! $self->{LOG_RANGE}{LOWER_SOC} or
+           $ranges [1] < $self->{LOG_RANGE}{LOWER_SOC};
+
+      my $low = (sort {$a <=> $b} keys %{ $self->{LOG} }) [0];
+      $self->{LOG_RANGE}{LOWER} = $low
+        if ! $self->{LOG_RANGE}{LOWER} or $low < $self->{LOG_RANGE}{LOWER};
+
+    } else {
+      # Lower end of the range without the stop-on-copy option
+      $self->{LOG_RANGE}{LOWER} = $ranges [1]
+        if ! $self->{LOG_RANGE}{LOWER} or
+           $ranges [1] < $self->{LOG_RANGE}{LOWER};
+
+      $self->{LOG_RANGE}{LOWER_SOC} = $ranges [1]
+        if ! $self->{LOG_RANGE}{LOWER_SOC} or
+           $ranges [1] < $self->{LOG_RANGE}{LOWER_SOC};
+    }
+  }
+
+  my %return = ();
+
+  if (! $rev_arg or ref ($rev_arg)) {
+    # REV is an array, return log entries if they are within range
+    for my $rev (sort {$b <=> $a} keys %{ $self->{LOG} }) {
+      next if $rev > $revs [0] or $revs [1] > $rev;
+
+      $return{$rev} = $self->{LOG}{$rev};
+
+      if ($stop_on_copy) {
+        last if exists $self->{LOG}{$rev}{paths}{$self->branch_path} and
+           $self->{LOG}{$rev}{paths}{$self->branch_path}{action} eq 'A';
+      }
+    }
+
+  } else {
+    # REV is a scalar, return log of the specified revision if it exists
+    %return = %{ $self->{LOG}{$revs [0]} } if exists $self->{LOG}{$revs [0]};
+  }
+
+  return %return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $cm_branch->display_svnlog ($rev, [$wiki]);
+#
+# DESCRIPTION
+#   This method returns a string for displaying the log of the current branch
+#   at a $rev. If $wiki is set, returns a string for displaying in a Trac wiki
+#   table.  The value of $wiki should be the Subversion URL of a FCM project
+#   associated with the intended Trac system.
+# ------------------------------------------------------------------------------
+
+sub display_svnlog {
+  my ($self, $rev, $wiki) = @_;
+  my $return = '';
+
+  my %log  = $self->svnlog (REV => $rev);
+
+  if ($wiki) {
+    # Output in Trac wiki format
+    $return .= '|| ' . &svn_date ($log{date}) . ' || ' . $log{author} . ' || ';
+
+    my $trac_url = &get_browser_url (URL => $self->url);
+
+    if ($trac_url =~ m#^$wiki(?:/*|$)#) {
+      $return .= '[' . $rev . '] ||';
+
+    } else {
+      my $rev_url = $trac_url;
+      $rev_url    =~ s#/browser/.*$##;
+      $rev_url   .= '/changeset/' . $rev;
+      $return    .= '[' . $rev_url . '] ||';
+    }
+
+  } else {
+    # Output in plain text format
+    my @msg  = split /\n/, $log{msg};
+    my $line = (@msg > 1 ? ' lines' : ' line');
+
+    $return .= join (
+      ' | ',
+      ('r' . $rev, $log{author}, &svn_date ($log{date}), scalar (@msg) . $line),
+    );
+    $return .= "\n\n";
+    $return .= $log{msg};
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @list = $cm_url->svnlist ([REV => $rev], [RECURSIVE => 1]);
+#
+# DESCRIPTION
+#   The method returns a list of paths as returned by "svn list". If RECURSIVE
+#   is set, "svn list" is invoked with the "-R" option.
+# ------------------------------------------------------------------------------
+
+sub svnlist {
+  my $self = shift;
+  my %args = @_;
+
+  my $recursive = exists $args{RECURSIVE} ? $args{RECURSIVE} : 0;
+  my $rev       = exists $args{REV}       ? $args{REV}       : undef;
+  my $key       = $recursive ? 'RLIST' : 'LIST';
+
+  # Find out last changed revision of the current URL
+  $rev = $self->svninfo (FLAG => 'Last Changed Rev', REV => $rev);
+  return () if not $rev;
+
+  # Get directory listing for the current URL at the last changed revision
+  if (not exists $self->{$key}{$rev}) {
+    my $rc;
+
+    my @list = map {chomp; $_} &run_command (
+      [qw/svn list -r/, $rev, ($recursive ? '-R' : ()), $self->url_peg],
+      METHOD => 'qx', ERROR => 'ignore', DEVNULL => 1, RC => \$rc,
+    );
+
+    $self->{$key}{$rev} = $rc ? undef : \@list;
+  }
+
+  return (defined ($self->{$key}{$rev}) ? @{ $self->{$key}{$rev} } : undef);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @list = $cm_url->branch_list ($rev);
+#
+# DESCRIPTION
+#   The method returns a list of branches in the current project, assuming the
+#   FCM naming convention. If $rev if specified, it returns the list of
+#   branches at $rev.
+# ------------------------------------------------------------------------------
+
+sub branch_list {
+  my ($self, $rev) = @_;
+
+  # Current URL must be a valid FCM project
+  return if not $self->project;
+
+  # Find out last changed revision of the current URL
+  $rev = $self->svninfo (FLAG => 'Revision', REV => $rev);
+  return () if not $rev;
+
+  if (not exists $self->{BRANCH_LIST}{$rev}) {
+    # Get URL of the project "branches/" sub-directory
+    my $url = Fcm::CmUrl->new (URL => $self->project_url . '/branches');
+
+    # List three levels underneath "branches/"
+    # First level, i.e. dev, test, pkg, etc
+    my @list1 = map {$url->url . '/' . $_} $url->svnlist (REV => $rev);
+    @list1    = grep m#/$#, @list1;
+
+    # Second level, i.e. user name, Shared, Rel or Config
+    my @list2;
+    for (@list1) {
+      my $u    = Fcm::CmUrl->new (URL => $_);
+      my @list = $u->svnlist (REV => $rev);
+
+      push @list2, map {$u->url . $_} @list;
+    }
+
+    # Third level, branch name
+    for (@list2) {
+      my $u    = Fcm::CmUrl->new (URL => $_);
+      my @list = map {s#/*$##; $_} $u->svnlist (REV => $rev);
+
+      push @{ $self->{BRANCH_LIST}{$rev} }, map {$u->url . $_} @list;
+    }
+  }
+
+  return @{ $self->{BRANCH_LIST}{$rev} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_analyse_url ();
+#
+# DESCRIPTION
+#   The method analyses the current URL, breaking it up into the project
+#   (substring of URL up to the slash before "trunk", "branches" or "tags"),
+#   branch name ("trunk", "branches/<type>/<id>/<name>" or "tags/<name>") and
+#   the sub-directory below the top of the project sub-tree. It re-sets the
+#   corresponding interal variables.
+# ------------------------------------------------------------------------------
+
+sub _analyse_url {
+  my $self = shift;
+  my ($url, $project, $branch, $subdir, $pegrev);
+
+  # Check that URL is set
+  $url    = $self->url_peg;
+  return if not $url;
+  return if not $self->is_url;
+
+  # Extract from URL the peg revision
+  $pegrev = $1 if $url =~ s/@($rev_pattern)$//i;
+
+  if ($url =~ m#^(.*?)/+(trunk|branches|tags)(?:/+(.*))?/*$#) {
+    # URL is under the "trunk", a branch or a tag
+    $project                 = $1;
+    my ($branch_id, $remain) = ($2, $3);
+
+    $remain = '' if not defined $remain;
+
+    if ($branch_id eq 'trunk') {
+      # URL under the "trunk"
+      $branch = 'trunk';
+
+    } else {
+      # URL under a branch or a tag
+      $branch = $branch_id;
+
+      # Assume "3 sub-directories", FCM branch naming convention
+      for (1 .. 3) {
+        if ($remain =~ s#^([^/]+)(?:/+|$)##) {
+          $branch .=  '/' . $1;
+
+        } else {
+          $branch = undef;
+          last;
+        }
+      }
+    }
+
+    $subdir = $remain ? $remain : '' if $branch;
+
+  } else {
+    # URL is at some level above the "trunk", a branch or a tag
+    # Use "svn ls" to determine whether it is a project URL
+    my @list = $self->svnlist (REV => ($pegrev ? $pegrev : 'HEAD'));
+    my %lines = map {chomp $_; ($_, 1)} @list;
+
+    # A project URL should have the "trunk", "branches" and "tags" directories
+    ($project = $url) =~ s#/*$##
+      if $lines{'trunk/'} and $lines{'branches/'} and $lines{'tags/'};
+  }
+
+  $self->{PROJECT}  = $project;
+  $self->{BRANCH}   = $branch;
+  $self->{SUBDIR}   = $subdir;
+  $self->{PEGREV}   = $pegrev;
+  $self->{ANALYSED} = 1;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->root ();
+#
+# DESCRIPTION
+#   The method returns the repository root of the current URL.
+# ------------------------------------------------------------------------------
+
+sub root {
+  my $self = shift;
+
+  return $self->svninfo (FLAG => 'Repository Root');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->project_url_peg ();
+#   $cm_url->project_url_peg ($url);
+#
+# DESCRIPTION
+#   The method returns the URL@PEG of the "project" part of the current URL. If
+#   an argument is specified, the URL of the "project" part and the peg
+#   revision of the current URL are re-set.
+# ------------------------------------------------------------------------------
+
+sub project_url_peg {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->project_url_peg or $url ne $self->project_url_peg) {
+      my $pegrev = ($url =~ s/@($rev_pattern)$//i) ? $1 : '';
+
+      $url .= '/' . $self->branch if $self->branch;
+      $url .= '/' . $self->subdir if $self->subdir;
+      $url .= '@' . $pegrev       if $pegrev;
+
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{PROJECT} . ($self->pegrev ? '@' . $self->pegrev : '');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->project_url ();
+#   $cm_url->project_url ($url);
+#
+# DESCRIPTION
+#   The method returns the URL of the "project" part of the current URL. If an
+#   argument is specified, the URL of the "project" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub project_url {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+    $url =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL is necessary
+    if (! $self->project_url or $url ne $self->project_url) {
+      $url .= '/' . $self->branch if $self->branch;
+      $url .= '/' . $self->subdir if $self->subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{PROJECT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->project_path ();
+#   $cm_url->project_path ($path);
+#
+# DESCRIPTION
+#   The method returns the path of the "project" part of the current URL. If an
+#   argument is specified, the path of the "project" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub project_path {
+  my $self = shift;
+
+  # Repository root
+  my $root = $self->root;
+  $root    = substr (
+    $self->project_url,
+    0,
+    length ($self->project_url) - length ($self->project) - 1
+  ) if not $root;
+
+  if (@_) {
+    my $path = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->project_path or $path ne $self->project_path) {
+      $path .= '/' . $self->branch if $self->branch;
+      $path .= '/' . $self->subdir if $self->subdir;
+
+      $self->path ($path);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return substr ($self->{PROJECT}, length ($root));
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $name = $cm_url->project ();
+#   $cm_url->project ($name);
+#
+# DESCRIPTION
+#   The method returns the basename of the "project" part of the current URL.
+#   If an argument is specified, the basename of the "project" part of the
+#   current URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub project {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->project or $name ne $self->project) {
+      my $url = '';
+      if ($self->project) {
+        $url =  $self->project;
+        $url =~ s#/[^/]+$##;
+
+      } else {
+        $url =  $self->root;
+      }
+
+      $url .=  '/' . $name;
+      $url .=  '/' . $self->branch if $self->branch;
+      $url .=  '/' . $self->subdir if $self->subdir;
+      $url .=  '@' . $self->pegrev if $self->pegrev;
+
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  my $name = $self->{PROJECT};
+  $name =~ s#^.*/([^/]+)$#$1# if $name;
+
+  return $name;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->branch_url_peg ();
+#   $cm_url->branch_url_peg ($url);
+#
+# DESCRIPTION
+#   The method returns the URL@PEG of the "branch" part of the current URL. If
+#   an argument is specified, the URL@PEG of the "branch" part of the current
+#   URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub branch_url_peg {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->branch_url_peg or $url ne $self->branch_url_peg) {
+      my $pegrev = ($url =~ s/@($rev_pattern)$//i) ? $1 : '';
+
+      $url .= '/' . $self->subdir if $self->subdir;
+      $url .= '@' . $pegrev       if $pegrev;
+
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->project_url . '/' . $self->branch .
+         ($self->pegrev ? '@' . $self->pegrev : '');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->branch_url ();
+#   $cm_url->branch_url ($url);
+#
+# DESCRIPTION
+#   The method returns the URL of the "branch" part of the current URL. If an
+#   argument is specified, the URL of the "branch" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub branch_url {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+    $url =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL is necessary
+    if (! $self->branch_url or $url ne $self->branch_url) {
+      $url .= '/' . $self->subdir if $self->subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->project_url . '/' . $self->branch;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->branch_path ();
+#   $cm_url->branch_path ($path);
+#
+# DESCRIPTION
+#   The method returns the path of the "branch" part of the current URL. If an
+#   argument is specified, the path of the "branch" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub branch_path {
+  my $self = shift;
+
+  if (@_) {
+    my $path = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->branch_path or $path ne $self->branch_path) {
+      $path .= '/' . $self->subdir if $self->subdir;
+
+      $self->path ($path);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->project_path . '/' . $self->branch;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch = $cm_url->branch ();
+#   $cm_url->branch ($branch);
+#
+# DESCRIPTION
+#   The method returns the "branch" part of the current URL. If an argument is
+#   specified, the "branch" part of the current URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub branch {
+  my $self = shift;
+
+  if (@_) {
+    my $branch = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->branch or $branch ne $self->branch) {
+      my $url = $self->project_url;
+      $url   .= '/' . $branch;
+      $url   .= '/' . $self->subdir if $self->subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{BRANCH};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_trunk ();
+#
+# DESCRIPTION
+#   The method returns true if the the current URL is (a sub-tree of) the trunk.
+# ------------------------------------------------------------------------------
+
+sub is_trunk {
+  my $self = shift;
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return ($self->branch and $self->branch eq 'trunk');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_branch ();
+#
+# DESCRIPTION
+#   The method returns true if the the current URL is (a sub-tree of) a branch.
+# ------------------------------------------------------------------------------
+
+sub is_branch {
+  my $self = shift;
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return ($self->branch and $self->branch =~ m#^branches/#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_tag ();
+#
+# DESCRIPTION
+#   The method returns true if the the current URL is (a sub-tree of) a tag.
+# ------------------------------------------------------------------------------
+
+sub is_tag {
+  my $self = shift;
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return ($self->branch and $self->branch =~ m#^tags/#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $subdir = $cm_url->subdir ();
+#   $cm_url->subdir ($subdir);
+#
+# DESCRIPTION
+#   The method returns the "subdir" part of the current URL. If an argument is
+#   specified, the "subdir" part of the current URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub subdir {
+  my $self = shift;
+
+  if (@_) {
+    my $subdir = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->subdir or $subdir ne $self->subdir) {
+      my $url = $self->project_url;
+      $url   .= '/' . $self->branch if $self->branch;
+      $url   .= '/' . $subdir if $subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{SUBDIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->url ();
+#   $cm_url->url ($url);
+#
+# DESCRIPTION
+#   The method returns the URL without the "peg revision" part. If an argument
+#   is specified, the URL is re-set without modifying the "peg revision" part.
+# ------------------------------------------------------------------------------
+
+sub url {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+    $url    =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL if necessary
+    if (! $self->url or $url ne $self->url) {
+      $self->url_peg ($url . ($self->pegrev ? '@' . $self->pegrev : ''));
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  (my $url = $self->url_peg) =~ s/@($rev_pattern)$//i;
+
+  return $url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->path ();
+#   $cm_url->path ($path);
+#
+# DESCRIPTION
+#   The method returns the "path" part of the URL (i.e. URL without the
+#   "root" part). If an argument is specified, the "path" part of the URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub path {
+  my $self = shift;
+
+  # Repository root
+  my $root = $self->root;
+  $root    = substr (
+    $self->project_url,
+    0,
+    length ($self->project_url) - length ($self->project) - 1
+  ) if not $root;
+
+  if (@_) {
+    my $path = shift;
+    $path    =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL is necessary
+    if (! $self->path or $path ne $self->path) {
+      my $url = ($root . (substr ($path, 0, 1) eq '/' ? '' : '/') . $path);
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return substr ($self->url, length ($root));
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->path_peg ();
+#   $cm_url->path_peg ($path);
+#
+# DESCRIPTION
+#   The method returns the PATH@PEG part of the URL (i.e. URL without the
+#   "root" part). If an argument is specified, the PATH@PEG part of the URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub path_peg {
+  my $self = shift;
+
+  # Repository root
+  my $root = $self->root;
+  $root    = substr (
+    $self->project_url,
+    0,
+    length ($self->project_url) - length ($self->project) - 1
+  ) if not $root;
+
+  if (@_) {
+    my $path = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->path_peg or $path ne $self->path_peg) {
+      my $url = ($root . (substr ($path, 0, 1) eq '/' ? '' : '/') . $path);
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return substr ($self->url_peg, length ($root));
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cm_url->pegrev ();
+#   $cm_url->pegrev ($rev);
+#
+# DESCRIPTION
+#   The method returns the "peg revision" part of the current URL. If an
+#   argument is specified, the "peg revision" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub pegrev {
+  my $self = shift;
+
+  if (@_) {
+    my $pegrev = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->pegrev or $pegrev ne $self->pegrev) {
+      $self->url_peg ($self->url . ($pegrev ? '@' . $pegrev : ''));
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{PEGREV};
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Config.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Config.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Config.pm	(revision 329)
@@ -0,0 +1,694 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Config
+#
+# DESCRIPTION
+#   This is a class for reading and processing central and user configuration
+#   settings for FCM.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Config;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use File::Basename;
+use File::Spec::Functions;
+use FindBin;
+use POSIX qw/setlocale LC_ALL/;
+
+# FCM component modules
+use Fcm::CfgFile;
+
+# Other declarations:
+sub _get_hash_value;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = Fcm::Config->new (VERBOSE => $verbose);
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Config class.
+#
+# ARGUMENTS
+#   VERBOSE - Set the verbose level of diagnostic output
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  # Ensure that all subsequent Subversion output is in UK English
+  if (setlocale (LC_ALL, 'en_GB')) {
+    $ENV{LANG} = 'en_GB';
+  }
+
+  # Location of the central/user configuration file
+  my $cntl_config = catfile (dirname ($FindBin::Bin), 'etc', 'fcm.cfg');
+  $cntl_config    = catfile $FindBin::Bin, 'fcm.cfg' unless -r $cntl_config;
+  my $user_config = exists $ENV{HOME} ? catfile $ENV{HOME}, '.fcm' : '';
+
+  # Verbose mode
+  my $verbose     = exists $ENV{FCM_VERBOSE} ? $ENV{FCM_VERBOSE} : 1;
+
+  my $self = {
+    CNTL_CONFIG => -r $cntl_config ? $cntl_config : '',
+    USER_CONFIG => -r $user_config ? $user_config : '',
+    VERBOSE     => exists $args{VERBOSE} ? $args{VERBOSE} : $verbose,
+    VARIABLE    => {},
+
+    # Primary settings
+    SETTING => {
+      # Release identifier/version
+      RELEASE  => '1.1',
+
+      # Location of file with the last changed revision of the FCM trunk
+      REV_FILE => catfile (dirname ($FindBin::Bin), 'etc', 'fcm_rev'),
+
+      # Default names of known FCM configuration files
+      CFG_NAME => {
+        BLD        => 'bld.cfg',      # bld cfg
+        EXT        => 'ext.cfg',      # ext cfg
+        SRCPACKAGE => '@PACKAGE.cfg', # source package cfg
+      },
+
+      # Latest version of known FCM configuration files
+      CFG_VERSION => {
+        BLD        => '1.0', # bld cfg
+        EXT        => '1.0', # ext cfg
+        SRCPACKAGE => '1.0', # source package cfg
+      },
+
+      # Labels for all types of FCM configuration files
+      CFG_LABEL => {
+        CFGFILE => {
+          TYPE    => 'CFG::TYPE',       # config file type
+          VERSION => 'CFG::VERSION',    # version of config file syntax
+        },
+
+        # Labels for central/user internal config setting
+        SETTING    => 'SET',
+
+        # Labels for ext and bld cfg
+        USE        => 'USE',            # use (inherit from) another ext/bld
+        SRCDIR     => 'SRC',            # prefix, source directory
+
+        # Labels for bld and pck cfg
+        TARGET     => 'TARGET',         # BLD: targets of current build
+                                        # PCK: target name of source file
+
+        # Labels for bld cfg
+        NAME        => 'NAME',          # build name
+        DIR         => 'DIR',           # prefix, build directory
+        PP          => 'PP',            # prefix, pre-process?
+        LIB         => 'LIB',           # declare name of a library
+        SEARCH_SRC  => 'SEARCH_SRC',    # search src/ sub-directory?
+        EXE_NAME    => 'EXE_NAME',      # rename a main program target
+        TOOL        => 'TOOL',          # prefix, build tool
+        INHERIT     => 'INHERIT',       # prefix, inheritance flag
+        EXCL_DEP    => 'EXCL_DEP',      # exclude these automatic dependencies
+        INFILE_EXT  => 'INFILE_EXT',    # input file name extension and type
+        OUTFILE_EXT => 'OUTFILE_EXT',   # output file type and name extension
+        EXE_DEP     => 'EXE_DEP',       # extra executable dependencies
+        BLOCKDATA   => 'BLOCKDATA',     # BLOCKDATA dependencies
+
+        # Labels for ext cfg
+        DEST       => {                 # local extract destinations
+          ROOTDIR  => 'DEST::ROOTDIR',  # top directory for this extract
+          SRCDIR   => 'DEST::SRCDIR',   # extracted source directory
+          CFGDIR   => 'DEST::CFGDIR',   # generated configuration directory
+          CACHEDIR => 'DEST::CACHEDIR', # cache directory for fast extract
+          BLD_CFG  => 'DEST::BLD_CFG',  # generated bld cfg file
+          EXT_CFG  => 'DEST::EXT_CFG',  # generated ext cfg file
+        },
+        RDEST      => {                 # remote extract destionations
+          MACHINE  => 'RDEST::MACHINE', # name of remote machine
+          LOGNAME  => 'RDEST::LOGNAME', # user logname on remote machine
+          ROOTDIR  => 'RDEST::ROOTDIR', # top directory for this extract
+          SRCDIR   => 'RDEST::SRCDIR',  # extracted source directory
+          CFGDIR   => 'RDEST::CFGDIR',  # generated configuration directory
+          BLD_CFG  => 'RDEST::BLD_CFG', # generated bld cfg file
+          EXT_CFG  => 'RDEST::EXT_CFG', # generated ext cfg file
+        },
+        INC        => 'INC',            # "include" settings in another cfg file
+        BDECLARE   => 'BLD',            # declare entries for build system
+        OVERRIDE   => 'OVERRIDE',       # set conflict override option
+        REPOS      => 'REPOS',          # set repos loc for a project branch
+        VERSION    => 'VERSION',        # set version for a project branch
+        EXPSRCDIR  => 'EXPSRC',         # prefix, expandable source directory
+        MIRROR     => 'MIRROR',         # mirror tool
+
+        # Labels for pck cfg
+        TYPE       => 'TYPE',           # type of source file/build task
+        SCAN       => 'SCAN',           # scan source file for dependency
+        INTNAME    => 'INTNAME',        # internal name of source file
+        DEP        => 'DEP',            # source file/build task dependencies
+      },
+
+      # Keywords in known FCM configuration files
+      CFG_KEYWORD => 'USE,INC,TARGET,EXCL_DEP',
+
+      # Types of "inc" statements expandable CFG files
+      CFG_EXP_INC => 'BLD,EXT,FCM',
+
+      # Standard sub-directories for extract/build
+      DIR => {
+        BIN    => 'bin',    # executable
+        BLD    => 'bld',    # build
+        CACHE  => '.cache', # cache
+        CFG    => 'cfg',    # configuration
+        DONE   => 'done',   # "done"
+        ETC    => 'etc',    # miscellaneous items
+        FLAGS  => 'flags',  # "flags"
+        INC    => 'inc',    # include
+        LIB    => 'lib',    # library
+        OBJ    => 'obj',    # object
+        PPSRC  => 'ppsrc',  # pre-processed source
+        SRC    => 'src',    # source
+        TMP    => 'tmp',    # temporary directory
+      },
+
+      # Build commands and options (i.e. tools)
+      TOOL => {
+        SHELL        => '/usr/bin/ksh',    # Default shell
+
+        CPP          => 'cpp',             # C pre-processor
+        CPPFLAGS     => '-C',              # CPP flags
+        CPP_INCLUDE  => '-I',              # CPP flag, specify "include" path
+        CPP_DEFINE   => '-D',              # CPP flag, define macro
+
+        CC           => 'cc',              # C compiler
+        CFLAGS       => '',                # CC flags
+        CC_COMPILE   => '-c',              # CC flag, compile only
+        CC_OUTPUT    => '-o',              # CC flag, specify output file name
+        CC_INCLUDE   => '-I',              # CC flag, specify "include" path
+        CC_DEFINE    => '-D',              # CC flag, define macro
+
+        FPP          => 'cpp',             # Fortran pre-processor
+        FPPFLAGS     => '-P -traditional', # FPP flags
+        FPP_INCLUDE  => '-I',              # FPP flag, specify "include" path
+        FPP_DEFINE   => '-D',              # FPP flag, define macro
+
+        FC           => 'f90',             # Fortran compiler
+        FFLAGS       => '',                # FC flags
+        FC_COMPILE   => '-c',              # FC flag, compile only
+        FC_OUTPUT    => '-o',              # FC flag, specify output file name
+        FC_INCLUDE   => '-I',              # FC flag, specify "include" path
+        FC_DEFINE    => '-D',              # FC flag, define macro
+
+        LD           => 'ld',              # linker
+        LDFLAGS      => '',                # LD flags
+        LD_OUTPUT    => '-o',              # LD flag, specify output file name
+        LD_LIBSEARCH => '-L',              # LD flag, specify "library" path
+        LD_LIBLINK   => '-l',              # LD flag, specify link library
+
+        AR           => 'ar',              # library archiver
+        ARFLAGS      => 'rs',              # AR flags
+
+        MAKE         => 'make',            # make command
+        MAKEFLAGS    => '',                # make flags
+        MAKE_SILENT  => '-s',              # make flag, silent diagnostic
+        MAKE_JOB     => '-j',              # make flag, number of jobs
+
+        INTERFACE    => 'file',            # name interface after file/program
+        GENINTERFACE => 'ECMWF',           # Fortran 9x interface generator
+
+        MIRROR       => 'rsync',           # extract mirroring tool
+        REMOTE_SHELL => 'remsh',           # command to invoke the remote shell
+      },
+
+      # List of tools that are local to FCM, (will not be exported to a Makefile)
+      LOCALTOOL => 'CPP,CPPFLAGS,CPP_INCLUDE,CPP_DEFINE,FPP,FPPFLAGS,' .
+                   'FPP_INCLUDE,FPP_DEFINE,MAKE,MAKEFLAGS,MAKE_SILENT,' .
+                   'MAKE_JOB,INTERFACE,GENINTERFACE,MIRROR,REMOTE_SHELL',
+
+      # Cache file names/extensions
+      CACHE => {
+        EXTCONFIG   => '.config',       # ext cache, commit version info
+        PCKFILE     => '.pck_file',     # bld cache, source package list
+        PCKPPDEPEND => '.pck_ppdepend', # bld cache, source package PP dependency
+        PCKDEPEND   => '.pck_depend',   # bld cache, source package dependency
+        BLDTOOL     => '.bld_tool',     # bld cache, build tool list
+        PPOPTION    => '.bld_pp',       # bld cache, PP option
+        EXE_DEP     => '.exe_dep',      # bld cache, executable extra dependency
+      },
+
+      # Input file name extension and type
+      # (may overlap with output and vpath, see below)
+      INFILE_EXT => {
+        # General extensions
+        'f'    => 'FORTRAN::SOURCE',
+        'for'  => 'FORTRAN::SOURCE',
+        'ftn'  => 'FORTRAN::SOURCE',
+        'f77'  => 'FORTRAN::SOURCE',
+        'f90'  => 'FORTRAN::FORTRAN9X::SOURCE',
+        'f95'  => 'FORTRAN::FORTRAN9X::SOURCE',
+        'F'    => 'FPP::SOURCE',
+        'FOR'  => 'FPP::SOURCE',
+        'FTN'  => 'FPP::SOURCE',
+        'F77'  => 'FPP::SOURCE',
+        'F90'  => 'FPP::FPP9X::SOURCE',
+        'F95'  => 'FPP::FPP9X::SOURCE',
+        'c'    => 'C::SOURCE',
+        'cpp'  => 'C::C++::SOURCE',
+        'h'    => 'CPP::INCLUDE',
+        'o'    => 'BINARY::OBJ',
+        'obj'  => 'BINARY::OBJ',
+        'exe'  => 'BINARY::EXE',
+        'a'    => 'BINARY::LIB',
+        'sh'   => 'SHELL::SCRIPT',
+        'ksh'  => 'SHELL::SCRIPT',
+        'bash' => 'SHELL::SCRIPT',
+        'csh'  => 'SHELL::SCRIPT',
+        'pl'   => 'PERL::SCRIPT',
+        'pm'   => 'PERL::SCRIPT',
+        'py'   => 'PYTHON::SCRIPT',
+        'tcl'  => 'TCL::SCRIPT',
+        'pro'  => 'PVWAVE::SCRIPT',
+
+        # Local extensions
+        'cfg'       => 'CFGFILE',
+        'h90'       => 'CPP::INCLUDE',
+        'inc'       => 'FORTRAN::FORTRAN9X::INCLUDE',
+        'interface' => 'FORTRAN::FORTRAN9X::INCLUDE::INTERFACE',
+      },
+
+      # Input file name pattern and type
+      INFILE_PAT => {
+        '\w+Scr_\w+'              => 'SHELL::SCRIPT',
+        '\w+Comp_\w+'             => 'SHELL::SCRIPT::GENTASK',
+        '\w+(?:IF|Interface)_\w+' => 'SHELL::SCRIPT::GENIF',
+        '\w+Suite_\w+'            => 'SHELL::SCRIPT::GENSUITE',
+        '\w+List_\w+'             => 'SHELL::SCRIPT::GENLIST',
+        '\w+Sql_\w+'              => 'SCRIPT::SQL',
+      },
+
+      # Input text file pattern and type
+      INFILE_TXT => {
+        '(?:[ck]|ba)?sh'  => 'SHELL::SCRIPT',
+        'perl'            => 'PERL::SCRIPT',
+        'python'          => 'PYTHON::SCRIPT',
+        'tcl(?:sh)?|wish' => 'TCL::SCRIPT',
+      },
+
+      # Output file type and extension
+      # (may overlap with input (above) and vpath (below))
+      OUTFILE_EXT => {
+        CFG       => '.cfg',       # FCM configuration file
+        DONE      => '.done',      # "done" files for compiled source
+        ETC       => '.etc',       # "etc" dummy file
+        EXE       => '.exe',       # binary executables
+        FLAGS     => '.flags',     # "flags" files, compiler flags config
+        IDONE     => '.idone',     # "done" files for included source
+        INTERFACE => '.interface', # interface for F90 subroutines/functions
+        LIB       => '.a',         # archive object library
+        MK        => '.mk',        # dependency files, Makefile fragments
+        MOD       => '.mod',       # compiled Fortran module information files
+        OBJ       => '.o',         # compiled object files
+        PDONE     => '.pdone',     # "done" files for pre-processed files
+        TAR       => '.tar',       # TAR archive
+      },
+
+      # VPATH, each value must be a comma separate list
+      # EMPTY      translates to %
+      # IN:<FLAG>  translates to any key in {INFILE_EXT} if the value contains
+      #            the word in <FLAG>
+      # OUT:<FLAG> translates to {OUTFILE_EXT}{<FLAG>}
+      VPATH   => {
+        BIN   => 'EMPTY,OUT:EXE,IN:SCRIPT',
+        BLD   => 'OUT:MK',
+        DONE  => 'OUT:DONE,OUT:IDONE,OUT:ETC',
+        FLAGS => 'OUT:FLAGS',
+        INC   => 'IN:INCLUDE',
+        LIB   => 'OUT:LIB',
+        OBJ   => 'OUT:OBJ',
+      },
+
+      # Dependency scan types for pre-processing
+      PP_DEP_TYPE => {
+        FPP => 'H',
+        CPP => 'H',
+        C   => 'H',
+      },
+
+      # Dependency scan types
+      DEP_TYPE => {
+        FORTRAN => 'USE::INTERFACE::INC::OBJ',
+        FPP     => 'USE::INTERFACE::INC::H::OBJ',
+        CPP     => 'H::OBJ',
+        C       => 'H::OBJ',
+        SCRIPT  => 'EXE',
+      },
+
+      # Dependency pattern for each type
+      DEP_PATTERN => {
+        H         => q/^#\s*include\s*['"](\S+)['"]/,
+        USE       => q/^\s*use\s+(\w+)/,
+        INTERFACE => q/^#?\s*include\s+['"](\S+##OUTFILE_EXT::INTERFACE##)['"]/,
+        INC       => q/^\s*include\s+['"](\S+)['"]/,
+        OBJ       => q#^\s*(?:/\*|!)\s*depends\s*on\s*:\s*(\S+)#,
+        EXE       => q/^\s*(?:#|;)\s*(?:calls|list|if|interface)\s*:\s*(\S+)/,
+      },
+
+      # Types that always need to be built
+      ALWAYS_BUILD_TYPE => 'PVWAVE,GENLIST,SQL',
+
+      # Excluded dependency
+      EXCL_DEP => {
+        # Fortran intrinsic modules
+        'USE::ISO_C_BINDING'            => {'' => 1},
+        'USE::IEEE_EXCEPTIONS'          => {'' => 1},
+        'USE::IEEE_ARITHMETIC'          => {'' => 1},
+        'USE::IEEE_FEATURES'            => {'' => 1},
+
+        # Fortran intrinsic subroutines
+        'OBJ::CPU_TIME'                 => {'' => 1},
+        'OBJ::GET_COMMAND'              => {'' => 1},
+        'OBJ::GET_COMMAND_ARGUMENT'     => {'' => 1},
+        'OBJ::GET_ENVIRONMENT_VARIABLE' => {'' => 1},
+        'OBJ::MOVE_ALLOC'               => {'' => 1},
+        'OBJ::MVBITS'                   => {'' => 1},
+        'OBJ::RANDOM_NUMBER'            => {'' => 1},
+        'OBJ::RANDOM_SEED'              => {'' => 1},
+        'OBJ::SYSTEM_CLOCK'             => {'' => 1},
+
+        # Dummy statements
+        'OBJ::NONE'                     => {'' => 1},
+        'EXE::NONE'                     => {'' => 1},
+      },
+
+      # Extra executable dependencies
+      EXE_DEP => {},
+
+      # Fortran BLOCKDATA dependencies
+      BLOCKDATA => {},
+
+      # Rename main program targets
+      EXE_NAME => {},
+
+      # Build sub-directories that can be archived by "tar"
+      TAR_DIRS => 'BLD,CACHE,DONE,FLAGS,INC,PPSRC,OBJ',
+
+      # Misc
+      MISC => {
+        CPDUMMY       => '$(FCM_DONEDIR)/FCM_CP.dummy',
+                                         # build system "copy" dummy target
+        DIR_SEPARATOR => '/',            # repository directory separator
+        EXPURL_PREFIX => 'fcm:',         # expandable URL keyword prefix
+        LOCK_BLD      => 'fcm.bld.lock', # build lock file
+        LOCK_EXT      => 'fcm.ext.lock', # extract lock file
+        MAKEFILE      => 'Makefile',     # name of Makefile
+        RUN_ENV_SH    => 'fcm_env.ksh',  # bld runtime environment shell script
+        WEB_BROWSER   => 'firefox',      # web browser
+      },
+
+      # Repository URL, revision, and Trac URL keywords
+      REPOS    => {},
+      REVISION => {},
+      TRAC     => {},
+    },
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $config->central_config ();
+#   $config->central_config ($file);
+#
+# DESCRIPTION
+#   This method returns the path name of the central configuration file. If an
+#   argument $file is specified, the path name of the central configuration
+#   file is set to its value.
+# ------------------------------------------------------------------------------
+
+sub central_config {
+  my $self = shift;
+
+  if (@_) {
+    $self->{CNTL_CONFIG} = $_[0];
+  }
+
+  return $self->{CNTL_CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $config->user_config ();
+#   $config->user_config ($file);
+#
+# DESCRIPTION
+#   This method returns the path name of the user configuration file. If an
+#   argument $file is specified, the path name of the user configuration file
+#   is set to its value.
+# ------------------------------------------------------------------------------
+
+sub user_config {
+  my $self = shift;
+
+  if (@_) {
+    $self->{USER_CONFIG} = $_[0];
+  }
+
+  return $self->{USER_CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $mode = $config->verbose ();
+#   $config->verbose ($mode);
+#
+# DESCRIPTION
+#   This method returns the diagnostic verbose level. If an argument $mode is
+#   specified, the diagnostic verbose level is set to its value.
+# ------------------------------------------------------------------------------
+
+sub verbose {
+  my $self = shift;
+
+  if (@_) {
+    $self->{VERBOSE} = $_[0];
+  }
+
+  return $self->{VERBOSE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $setting = $config->setting (arg, [...]);
+#
+# DESCRIPTION
+#   This method returns an item under the SETTING hash table. The depth within
+#   the hash table is given by the list of arguments, which should match with
+#   the keys in the multi-dimension SETTING hash table.
+# ------------------------------------------------------------------------------
+
+sub setting {
+  my $self = shift;
+
+  if (@_) {
+    my $label   = shift;
+    my $setting = $self->{SETTING};
+    return _get_hash_value ($setting->{$label}, @_) if exists $setting->{$label};
+  }
+
+  return undef;
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->assign_setting (
+#     LABELS => \@labels, # setting labels
+#     VALUE  => $value,   # setting value
+#   );
+#
+# DESCRIPTION
+#   This method assigns a VALUE to a SETTING specified by the names in LABEL.
+# ------------------------------------------------------------------------------
+
+sub assign_setting {
+  my $self = shift;
+  my %args = @_;
+
+  my @labels = exists $args{LABELS} ? @{ $args{LABELS} } : ();
+  my $value  = exists $args{VALUE}  ? $args{VALUE}       : undef;
+
+  my $setting = $self->{SETTING};
+  while (defined (my $label = shift @labels)) {
+    if (exists $setting->{$label}) {
+      if (ref $setting->{$label}) {
+        $setting = $setting->{$label};
+
+      } else {
+        $setting->{$label} = $value;
+        last;
+      }
+
+    } else {
+      if (@labels) {
+        $setting->{$label} = {};
+        $setting           = $setting->{$label};
+
+      } else {
+        $setting->{$label} = $value;
+      }
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $variable = $config->variable ([arg]);
+#
+# DESCRIPTION
+#   If arg is set, this method returns the value of a variable named arg. If
+#   arg is not set, this method returns the VARIABLE hash.
+# ------------------------------------------------------------------------------
+
+sub variable {
+  my $self     = shift;
+
+  my $variable = $self->{VARIABLE};
+
+  if (@_) {
+    my $label   = shift;
+    return exists $variable->{$label} ? $variable->{$label} : undef;
+
+  } else {
+    return %{ $variable };
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->assign_variable (
+#     LABEL => $label, # variable label
+#     VALUE => $value, # variable value
+#   );
+#
+# DESCRIPTION
+#   This method assigns a VALUE to a VARIABLE named by LABEL.
+# ------------------------------------------------------------------------------
+
+sub assign_variable {
+  my $self = shift;
+  my %args = @_;
+
+  my $label = exists $args{LABEL} ? $args{LABEL} : undef;
+  my $value = exists $args{VALUE} ? $args{VALUE} : undef;
+
+  if ($label) {
+    $self->{VARIABLE}{$label} = $value;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->get_config ();
+#
+# DESCRIPTION
+#   This method reads the configuration settings from the central and the user
+#   configuration files.
+# ------------------------------------------------------------------------------
+
+sub get_config {
+  my $self = shift;
+
+  $self->_read_config_file ($self->{CNTL_CONFIG}) if $self->{CNTL_CONFIG};  
+  $self->_read_config_file ($self->{USER_CONFIG}) if $self->{USER_CONFIG};
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->_read_config_file ();
+#
+# DESCRIPTION
+#   This internal method reads a configuration file and assign values to the
+#   attributes of the current instance.
+# ------------------------------------------------------------------------------
+
+sub _read_config_file {
+  my $self        = shift;
+  my $config_file = $_[0];
+
+  return undef unless -r $config_file;
+
+  my $cfgfile = Fcm::CfgFile->new (SRC => $config_file, TYPE => 'FCM');
+  $cfgfile->read_cfg ();
+  my @lines = $cfgfile->lines ();
+
+  LINE: for my $line (@lines) {
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next unless $label;
+
+    # "Environment variables" start with $
+    if ($label =~ s/^\$([A-Za-z_]\w*)$/$1/) {
+      $ENV{$label} = $value;
+      next LINE;
+    }
+
+    # "Settings variables" start with "set::"
+    my @tags = map {uc $_} split (/::/, $label);
+    if ($tags[0] eq uc $self->{SETTING}{CFG_LABEL}{SETTING}) {
+      shift @tags;
+      $self->assign_setting (LABELS => \@tags, VALUE => $value);
+      next LINE;
+    }
+
+    # Not a standard setting variable, put in internal variable list
+    $label =~ s/^\%//;
+    $self->assign_variable (LABEL => $label, VALUE => $value);
+  }
+
+  1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ref = _get_hash_value (arg1, arg2, ...);
+#
+# DESCRIPTION
+#   This internal method recursively gets a value from a multi-dimensional
+#   hash.
+# ------------------------------------------------------------------------------
+
+sub _get_hash_value {
+  my $value = shift;
+
+  while (defined (my $arg = shift)) {
+    if (exists $value->{$arg}) {
+      $value = $value->{$arg};
+
+    } else {
+      return undef;
+    }
+  }
+
+  return $value;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Extract.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Extract.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Extract.pm	(revision 329)
@@ -0,0 +1,1754 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Extract
+#
+# DESCRIPTION
+#   This class contains methods for carrying out the various tasks that are
+#   required to extract code from the FCM Subversion repository for feeding
+#   into the prototype build system. At the end of the extract, it writes a
+#   build configuration file for feeding into the build system.  If the code
+#   is to be built on a remote machine, it is mirrored to the remote machine
+#   using a "rdist" or "rsync" interface.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Extract;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use File::Spec::Functions;
+use File::Basename;
+use File::Path;
+use File::Compare;
+
+# FCM component modules
+use Fcm::CfgFile;
+use Fcm::ReposBranch;
+use Fcm::SrcDirLayer;
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext = Fcm::Extract->new (
+#     CONFIG    => $config,
+#     CFG_SRC   => $cfg_src,
+#     EXTRACTED => $extracted,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Extract class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   CFG_SRC    - source path to the extract configuration file
+#   EXTRACTED  - is it a pre-extracted object?
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $cfg       = exists $args{CFG_SRC}   ? $args{CFG_SRC}   : undef;
+  my $extracted = exists $args{EXTRACTED} ? $args{EXTRACTED} : undef;
+  my $config    = exists $args{CONFIG}    ? $args{CONFIG}    : &main::cfg;
+
+  my $self = {
+    CONFIG     => $config,            # configuration settings
+    CFG        => Fcm::CfgFile->new ( # ext cfg for this extract
+      SRC      => $cfg,               # source path of the config file
+      TYPE     => 'ext',              # config file type
+      CONFIG   => $config,            # configuration settings
+    ),
+    DEST       => {                   # destination info for this extract
+      ROOTDIR  => undef,              # destination root directory
+      CACHEDIR => undef,              # extract cache directory
+      CFGDIR   => undef,              # destination configuration directory
+      SRCDIR   => undef,              # destination source directory
+      BLD_CFG  => undef,              # bld cfg for the build system
+      EXT_CFG  => undef,              # ext cfg for subsequent extract
+    },
+    RDEST      => {                   # remote destination information
+      MACHINE  => undef,              # destination machine
+      LOGNAME  => undef,              # remote login name
+      ROOTDIR  => undef,              # destination root directory
+      CFGDIR   => undef,              # destination configuration directory
+      SRCDIR   => undef,              # destination source directory
+      BLD_CFG  => undef,              # bld cfg for the build system
+      EXT_CFG  => undef,              # ext cfg for subsequent extract
+    },
+    BDECLARE   => [],                 # list of declared bld cfg entries
+    OVERRIDE   => 0,                  # override conflicting patches?
+    EXTRACTED  => $extracted,         # is the current object pre-extracted?
+    USE        => [],                 # list of re-used extracts
+    BRANCHES   => [],                 # list of repository branch info
+    SRCDIRS    => {},                 # list of source directory extract info
+    LOCK       => undef,              # lock file
+  };
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->DESTROY;
+#
+# DESCRIPTION
+#   This method is called automatically when a Fcm::Extract object is
+#   destroyed.
+# ------------------------------------------------------------------------------
+
+sub DESTROY {
+  my $self = shift;
+
+  # Remove the lock if it is set
+  unlink $self->{LOCK} if $self->{LOCK} and -e $self->{LOCK};
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $ext->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = $ext->cfg;
+#   $ext->cfg ($cfgfile);
+#
+# DESCRIPTION
+#   This method returns a reference to a Fcm::CfgFile instance for the extract
+#   configuration file.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  my $self = shift;
+
+  return $self->{CFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dest = $ext->dest ([$name]);
+#
+# DESCRIPTION
+#   This method returns a hash containing the extract destination information
+#   (local) if no argument is specified. If $name is specified, it returns the
+#   named hash element if it exists.
+# ------------------------------------------------------------------------------
+
+sub dest {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+    $name    = uc $name;
+
+    if (exists $self->{DEST}{$name}) {
+      return $self->{DEST}{$name};
+    }
+  }
+
+  return %{ $self->{DEST} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rdest = $ext->rdest ([$name]);
+#
+# DESCRIPTION
+#   This method returns a hash containing the extract destination information
+#   (remote) if no argument is specified. If $name is specified, it returns the
+#   named hash element if it exists.
+# ------------------------------------------------------------------------------
+
+sub rdest {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+    $name    = uc $name;
+
+    if (exists $self->{RDEST}{$name}) {
+      return $self->{RDEST}{$name};
+    }
+  }
+
+  return %{ $self->{RDEST} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @bdeclare = $ext->bdeclare ();
+#
+# DESCRIPTION
+#   This method returns a list containing the build configuration file entries.
+# ------------------------------------------------------------------------------
+
+sub bdeclare {
+  my $self = shift;
+
+  return @{ $self->{BDECLARE} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @branches = $ext->branches ([$index]);
+#
+# DESCRIPTION
+#   This method returns a list of references to Fcm::ReposBranch instances. If
+#   $index is specified, it returns the numbered item in the list.
+# ------------------------------------------------------------------------------
+
+sub branches {
+  my $self = shift;
+
+  if (@_) {
+    my $index = $_[0];
+    return exists $self->{BRANCHES}[$index] ? $self->{BRANCHES}[$index] : undef;
+  }
+
+  return @{ $self->{BRANCHES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %srcdirs = $ext->srcdirs ([$name]);
+#
+# DESCRIPTION
+#   This method returns a hash of source directories to be processed by this
+#   extract. If $name is specified, a named element of the hash is returned
+#   instead.
+# ------------------------------------------------------------------------------
+
+sub srcdirs {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+    $name    = uc $name;
+
+    return exists $self->{SRCDIRS}{$name} ? $self->{SRCDIRS}{$name} : undef;
+  }
+
+  return %{ $self->{SRCDIRS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $ext->extract ([FULL => 1], [IGNORE_LOCK => 1]);
+#
+# DESCRIPTION
+#   This is the main class method. It performs an extract using the current
+#   configuration. If FULL is set to true, it runs in full mode. Otherwise, it
+#   runs in incremental mode. If IGNORE_LOCK is set to true, it ignores any lock
+#   files that may exist in the extract destination root directory.
+# ------------------------------------------------------------------------------
+
+sub extract {
+  my $self = shift;
+  my %args = @_;
+
+  my $full        = exists $args{FULL}        ? $args{FULL}        : 0;
+  my $ignore_lock = exists $args{IGNORE_LOCK} ? $args{IGNORE_LOCK} : 0;
+
+  my $verbose = $self->config->verbose;
+
+  my $date = localtime;
+  print 'Extract started on ', $date, '.', "\n" if $verbose;
+  my $otime = time;
+
+  my $rc;
+  $rc = $self->decipher_cfg;
+
+  print '->Extract: start', "\n" if $verbose;
+  my $stime = time;
+
+  $rc = $self->check_dest               if $rc;
+  $rc = $self->check_lock               if $rc and not $ignore_lock;
+  $rc = $self->_set_lock                if $rc;
+  $rc = $self->expand_cfg               if $rc;
+  $rc = $self->_create_dest_dir ($full) if $rc;
+  $rc = $self->create_dir_stack         if $rc;
+  $rc = $self->_extract_src             if $rc;
+
+  $rc = $self->_sort_bdeclare if $rc;
+  $rc = $self->_write_ext_cfg if $rc;
+  $rc = $self->_write_bld_cfg if $rc;
+
+  my $ftime = time;
+  my $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+  print '->Extract: ', $ftime - $stime, ' ', $s_str, "\n";
+
+  if ($rc and $self->{RDEST}{MACHINE}) {
+    print '->Mirror : start', "\n" if $verbose;
+    $stime = time;
+    $rc = $self->_mirror_extract;
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Mirror : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  if ($verbose) {
+    $s_str = $ftime - $otime > 1 ? 'seconds' : 'second';
+    print '->TOTAL  : ', $ftime - $otime, ' ', $s_str, "\n";
+  }
+
+  $date = localtime;
+  if ($rc) {
+    print 'Extract command finished on ', $date, '.', "\n" if $verbose;
+
+  } else {
+    e_report 'Extract command failed on ', $date, '.';
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->decipher_cfg ();
+#
+# DESCRIPTION
+#   This method deciphers the extract configuration file.
+# ------------------------------------------------------------------------------
+
+sub decipher_cfg {
+  my $self = shift;
+
+  return unless $self->cfg->src;
+
+  # Read config file
+  my $read = $self->cfg->read_cfg;
+
+  # Check config file type
+  if ($read) {
+    if ($self->cfg->type ne 'ext') {
+      w_report 'Error: ', $self->cfg->src, ': not an extract config file';
+      return;
+    }
+
+  } else {
+    return;
+  }
+
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+
+  # Extract information from each line of the config file
+  my @lines    = $self->cfg->lines;
+  LINE: for my $line (@lines) {
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next LINE unless $label;
+
+    # Configuration file type/version, ignore
+    for my $my_label (keys %{ $cfg_labels{CFGFILE} }) {
+      next LINE if uc ($label) eq uc ($cfg_labels{CFGFILE}{$my_label});
+    }
+
+    # Include another file, processed already, ignore this line
+    next LINE if uc ($label) eq $cfg_labels{INC};
+
+    # User variable, ignore
+    next LINE if index (uc ($label), '%') == 0;
+
+    # Local destination directories, config file, etc
+    for my $my_label (keys %{ $cfg_labels{DEST} }) {
+      if (uc ($label) eq uc ($cfg_labels{DEST}{$my_label})) {
+        $self->{DEST}{$my_label} = &expand_tilde ($value);
+        next LINE;
+      }
+    }
+
+    # Remote machine, logname, destination directories, config file, etc
+    for my $my_label (keys %{ $cfg_labels{RDEST} }) {
+      if (uc ($label) eq uc ($cfg_labels{RDEST}{$my_label})) {
+        $self->{RDEST}{$my_label} = $value;
+        next LINE;
+      }
+    }
+
+    # "USE" statements
+    if (uc ($label) eq uc ($cfg_labels{USE})) {
+      my $exists = grep {$_->cfg->src eq $value} @{ $self->{USE} };
+
+      # Initialise new Fcm::Extract object if not already exists
+      unless ($exists) {
+        my $extract = Fcm::Extract->new (
+          CONFIG    => $self->config,
+          CFG_SRC   => expand_tilde ($value),
+          EXTRACTED => 1,
+        );
+
+        $extract->decipher_cfg;
+        $extract->check_dest;
+        $extract->expand_cfg ();
+        push @{ $self->{USE} }, $extract;
+      }
+      next LINE;
+    }
+
+    # "Override" setting
+    if (uc ($label) eq uc ($cfg_labels{OVERRIDE})) {
+      $self->{OVERRIDE} = $value;
+      next LINE;
+    }
+
+    # "Mirror" command
+    if (uc ($label) eq uc ($cfg_labels{MIRROR})) {
+      $self->config->assign_setting (
+        LABELS => [qw/TOOL MIRROR/],
+        VALUE  => $value,
+      );
+      next LINE;
+    }
+
+    # Declared bld cfg entries
+    {
+      my $prefix = $cfg_labels{BDECLARE} . '::';
+
+      if (index (uc ($label), $prefix) == 0) {
+        my $name = substr $label, length ($prefix);
+
+        if ($name) {
+          push @{ $self->{BDECLARE} }, {LABEL => $name, VALUE => $value,};
+          next LINE;
+        }
+      }
+    }
+
+    # Repository, version and source directories
+    for my $my_label (qw/REPOS VERSION SRCDIR EXPSRCDIR/) {
+      my $prefix  = $cfg_labels{$my_label} . '::';
+
+      if (index (uc ($label), $prefix) == 0) {
+        my $name    = substr $label, length ($prefix);
+
+        # Detemine package and tag
+        my @names   = split /::/, $name;
+        my $tag     = pop @names;
+        my $pckroot = $names[0];
+        my $pck     = join '::', @names;
+
+        # Check that $tag and $pckroot are defined
+        last if not $tag;
+        last if not $pckroot;
+
+        # Check whether branch already exists
+        my @branches = grep {
+          $_->package eq $pckroot and $_->tag eq $tag
+        } @{ $self->{BRANCHES} };
+
+        my $branch   = undef;
+
+        if (@branches) { # If so, set $branch to point to existing branch
+          $branch = shift @branches;
+
+        } else {         # If not, create new branch
+          $branch = Fcm::ReposBranch->new (
+            CONFIG  => $self->config,
+            PACKAGE => $pckroot,
+            TAG     => $tag,
+          );
+
+          push @{ $self->{BRANCHES} }, $branch;
+        }
+
+        # Check package name for source directory declarations
+        if ($my_label eq 'SRCDIR' or $my_label eq 'EXPSRCDIR') {
+          if ($pck eq $pckroot and $value !~ m#^/#) {
+            # Sub-package name not set and source directory quoted as a relative
+            # path, determine package name from path name
+            my @subpck = File::Spec->splitdir ($value);
+            $pck       = join '::', ($pckroot, @subpck);
+          }
+        }
+
+        # Assign the value accordingly
+        if ($my_label eq 'REPOS') {          # Repository location
+          $branch->repos ($value);
+
+        } elsif ($my_label eq 'VERSION') {   # Version used
+          $branch->version ($value);
+
+        } elsif ($my_label eq 'SRCDIR') {    # Source directory used
+          $branch->dir ($pck, $value);
+
+        } elsif ($my_label eq 'EXPSRCDIR') { # Expandable source directory
+          $branch->expdir ($pck, $value);
+        }
+
+        next LINE;
+      }
+    }
+
+    # Label not recognised
+    w_report 'ERROR: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+             ': label "', $label, '" not recognised';
+    return;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->check_dest ();
+#
+# DESCRIPTION
+#   This method checks that the extract destionations are set correctly.
+# ------------------------------------------------------------------------------
+
+sub check_dest {
+  my $self = shift;
+
+  my %subdir  = %{ $self->config->setting ('DIR') };
+  my %cfgname = %{ $self->config->setting ('CFG_NAME') };
+
+  # Default destination settings
+  my $dest = $self->{DEST};
+  if ($dest->{ROOTDIR}) {
+    unless ($dest->{SRCDIR}) {   # Location of extracted source
+      $dest->{SRCDIR} = catfile $dest->{ROOTDIR}, $subdir{SRC};
+    }
+    unless ($dest->{CFGDIR}) {   # Location of configuration files
+      $dest->{CFGDIR} = catfile $dest->{ROOTDIR}, $subdir{CFG};
+    }
+    unless ($dest->{CACHEDIR}) { # Location of cache
+      $dest->{CACHEDIR} = catfile $dest->{ROOTDIR}, $subdir{CACHE};
+    }
+    unless ($dest->{BLD_CFG}) {  # Location of (output) bld cfg
+      $dest->{BLD_CFG} = catfile $dest->{CFGDIR}, $cfgname{BLD};
+    }
+    unless ($dest->{EXT_CFG}) {  # Location of (output) ext cfg
+      $dest->{EXT_CFG} = catfile $dest->{CFGDIR}, $cfgname{EXT};
+    }
+  } else {
+    w_report 'Error: ', $self->cfg->src,
+             ': destination root directory not set.';
+    return;
+  }
+
+  # Default remote destination settings
+  if ($self->{RDEST}{MACHINE}) {
+
+    # Use local logname as remote logname if it is not set
+    $self->{RDEST}{LOGNAME} = getlogin      unless $self->{RDEST}{LOGNAME};
+    $self->{RDEST}{LOGNAME} = $ENV{LOGNAME} unless $self->{RDEST}{LOGNAME};
+    $self->{RDEST}{LOGNAME} = $ENV{USER}    unless $self->{RDEST}{LOGNAME};
+
+    unless ($self->{RDEST}{LOGNAME}) {
+      w_report 'Error: ', $self->cfg->src,
+               ': cannot determine your remote logname.';
+      return;
+    }
+
+    # Make sure remote destination root directory is set
+    unless ($self->{RDEST}{ROOTDIR}) {
+      w_report 'Error: ', $self->cfg->src,
+               ': remote destination root directory not set.';
+      return;
+    }
+
+    # Make sure remote destination source directory is set
+    $self->{RDEST}{SRCDIR} = catfile $self->{RDEST}{ROOTDIR}, $subdir{SRC}
+      unless $self->{RDEST}{SRCDIR};
+
+    # Make sure remote destination configuration directory is set
+    $self->{RDEST}{CFGDIR} = catfile $self->{RDEST}{ROOTDIR}, $subdir{CFG}
+      unless $self->{RDEST}{CFGDIR};
+
+    # Make sure remote bld cfg is set
+    $self->{RDEST}{BLD_CFG} = catfile $self->{RDEST}{CFGDIR}, $cfgname{BLD}
+      unless $self->{RDEST}{BLD_CFG};
+
+    # Make sure remote ext cfg is set
+    $self->{RDEST}{EXT_CFG} = catfile $self->{RDEST}{CFGDIR}, $cfgname{EXT}
+      unless $self->{RDEST}{EXT_CFG};
+
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->check_lock ();
+#
+# DESCRIPTION
+#   This method checks whether a lock is set in the current extract.
+# ------------------------------------------------------------------------------
+
+sub check_lock {
+  my $self = shift;
+
+  my $rootdir  = $self->{DEST}{ROOTDIR};
+  my $lock_ext = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_EXT/));
+  my $lock_bld = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_BLD/));
+
+  # Always throw error if extract lock exists
+  if (-e $lock_ext) {
+    w_report 'ERROR: extract lock file exists: ', $lock_ext, ',';
+    w_report '       an extract may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Throw error if current object is not a "used" pre-extracted object and
+  # a build lock exists
+  if ((not $self->{EXTRACTED}) and -e $lock_bld) {
+    w_report 'ERROR: build lock file exists: ', $lock_bld, ',';
+    w_report '       a build may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Check locks in inherited extract
+  for my $use (@{ $self->{USE} }) {
+    return unless $use->check_lock;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_set_lock ();
+#
+# DESCRIPTION
+#   This method sets a lock is set in the current extract.
+# ------------------------------------------------------------------------------
+
+sub _set_lock {
+  my $self = shift;
+
+  $self->{LOCK} = catfile (
+    $self->{DEST}{ROOTDIR}, $self->config->setting (qw/MISC LOCK_EXT/),
+  );
+
+  &touch_file ($self->{LOCK});
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->expand_cfg ();
+#
+# DESCRIPTION
+#   This method expands the settings of the extract configuration.
+# ------------------------------------------------------------------------------
+
+sub expand_cfg {
+  my $self = shift;
+
+  # Establish a set of source directories from the "base repository"
+  my %base_branches = ();
+
+  # Inherit "base" set of source directories from re-used extracts
+  my @uses = @{ $self->{USE} };
+
+  for my $use (@uses) {
+    my @branches = $use->branches;
+
+    for my $branch (@branches) {
+      my $package              = $branch->package;
+      $base_branches{$package} = $branch unless exists $base_branches{$package};
+    }
+  }
+
+  for my $branch (@{ $self->{BRANCHES} }) {
+    # Expand URL keywords if necessary
+    if ($branch->repos) {
+      my $repos = expand_url_keyword (
+        URL => $branch->repos,
+        CFG => $self->config,
+      );
+      $branch->repos ($repos) if $repos ne $branch->repos;
+    }
+
+    # Check that repository type and version are set
+    if ($branch->repos and &is_url ($branch->repos)) {
+      $branch->type    ('svn')  unless $branch->type;
+      $branch->version ('head') unless $branch->version;
+
+    } else {
+      $branch->type    ('user') unless $branch->type;
+      $branch->version ('user') unless $branch->version;
+    }
+
+    $branch->expand_version_tag; # Work out revision number a version tag
+    $branch->expand_path;        # Expand relative path to full path
+    $branch->expand_all;         # Search sub-directories
+
+    my $package = $branch->package;
+
+    if (exists $base_branches{$package}) {
+      # A base branch for this package exists
+
+      # If current branch has no source directory, use the set provided by the
+      # base branch
+      my %dirs = $branch->dirs;
+      $branch->add_base_dirs ($base_branches{$package}) unless keys %dirs;
+
+    } else {
+      # This package does not yet have a base branch, set this branch as base
+      $base_branches{$package} = $branch;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_create_dest_dir ($full);
+#
+# DESCRIPTION
+#   This internal method (re-)creates all the destination directories if
+#   necessary. If $full is set to true, it removes existing directories/files
+#   in the destination directories.
+# ------------------------------------------------------------------------------
+
+sub _create_dest_dir {
+  my ($self, $full) = @_;
+
+  my $verbose = $self->config->verbose;
+
+  # Remove previous extract if "FULL" flag is set
+  if ($full) {
+    for my $my_label (qw/SRCDIR CACHEDIR/) {
+      my $dirname = $self->{DEST}{$my_label};
+
+      # If directory exists and writable by the user, remove it
+      if (-d $dirname and -w $dirname) {
+        print 'Remove directory: ', $dirname, "\n" if $verbose;
+        my $removed = rmtree $dirname;
+        w_report 'Warning: cannot remove old extract at: ', $dirname, '.'
+          if not $removed;
+      }
+    }
+  }
+
+  # Create extract destinations if necessary
+  for my $my_label (qw/ROOTDIR CACHEDIR CFGDIR SRCDIR/) {
+    my $dirname = $self->{DEST}{$my_label};
+
+    # Create directory if it does not already exist
+    if (not -d $dirname) {
+      print 'Make directory: ', $dirname, "\n" if $verbose > 1;
+      mkpath $dirname;
+    }
+
+    unless (-d $dirname and -w $dirname) {
+      w_report 'Error: cannot write to extract destination: ', $dirname, '.';
+      return;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->create_dir_stack (
+#     USE => $use, # Is this a pre-extracted configuration?
+#   );
+#
+# DESCRIPTION
+#   This method creates a hash of source directories to be processed. If the
+#   flag USE is set to true, the source directories are assumed processed and
+#   extracted.
+# ------------------------------------------------------------------------------
+
+sub create_dir_stack {
+  my $self = shift;
+  my %args = @_;
+  my $extracted = exists $args{USE} ? $args{USE} : undef;
+
+  # Inherit from USE ext cfg
+  if (@{ $self->{USE} } > 0) {
+    for my $use (@{ $self->{USE} }) {
+      $use->create_dir_stack (USE => 1);
+      my %use_srcdirs = $use->srcdirs;
+
+      while (my ($key, $value) = each %use_srcdirs) {
+        $self->{SRCDIRS}{$key} = $value;
+
+        # Re-set destination to current destination
+        my @path = split (/::/, $key);
+        $self->{SRCDIRS}{$key}{DEST} = catfile ($self->{DEST}{SRCDIR}, @path);
+      }
+    }
+  }
+
+  # Build stack from current ext cfg
+  for my $branch (@{ $self->{BRANCHES} }) {
+    my %branch_dirs = $branch->dirs;
+
+    for my $dir (keys %branch_dirs) {
+      # Check whether source directory is already in the list
+      if (not exists $self->{SRCDIRS}{$dir}) { # if not, create it
+        $self->{SRCDIRS}{$dir} = {
+          DEST  => catfile ($self->{DEST}{SRCDIR}, split (/::/, $dir)),
+          STACK => [],
+          FILES => {},
+        };
+      }
+
+      my $stack = $self->{SRCDIRS}{$dir}{STACK}; # copy reference
+
+      # Create a new layer in the input stack
+      my $layer = Fcm::SrcDirLayer->new (
+        CONFIG    => $self->config,
+        NAME      => $dir,
+        PACKAGE   => $branch->package,
+        TAG       => $branch->tag,
+        LOCATION  => $branch->dir ($dir),
+        REPOSROOT => $branch->repos,
+        VERSION   => $branch->version,
+        TYPE      => $branch->type,
+        EXTRACTED => $extracted ? $self->{SRCDIRS}{$dir}{DEST} : undef,
+      );
+
+      # Check whether layer is already in the stack
+      my $exist = grep {
+        $_->location eq $layer->location and $_->version  eq $layer->version;
+      } @{ $stack };
+
+      if (not $exist) {
+        # If not already exist, put layer into stack
+
+        # Note: user stack always comes last
+        if (! $layer->user and exists $stack->[-1] and $stack->[-1]->user) {
+          my $lastlayer = pop @{ $stack };
+          push @{ $stack }, $layer;
+          $layer = $lastlayer;
+        }
+
+        push @{ $stack }, $layer;
+
+      } elsif ($layer->user) {
+
+        # User layer already exists, overwrite it
+        $stack->[-1] = $layer;
+
+      }
+    }
+  }
+
+  # Read content of "commit cache" file if it exists
+  my $cachedir = $self->{DEST}{CACHEDIR};
+  my $cfgbase  = $self->config->setting (qw/CACHE EXTCONFIG/);
+  my $cfgfile  = catfile $cachedir, $cfgbase;
+  my %config_lines = ();
+  if (-r $cfgfile) {
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $cfgfile,);
+    $cfg->read_cfg;
+    my @lines = $cfg->lines;
+
+    for my $line (@lines) {
+      $config_lines{$line->{LABEL}} = $line->{VALUE};
+    }
+  }
+
+  my %new_config_lines;
+
+  # Compare each layer to base layer, discard unnecessary layers
+  for my $srcdir (keys %{ $self->{SRCDIRS} }) {
+    my @stack = ();
+
+    while (my $layer = shift @{ $self->{SRCDIRS}{$srcdir}{STACK} }) {
+      if ($layer->user) {
+        # User directory, check that the declared location exists
+        if (not -d $layer->location) {
+          w_report 'Error: declared source directory ', $layer->location,
+                   ' does not exists ';
+          return;
+        }
+
+        # Always override repository code
+        push @stack, $layer;
+
+      } else {
+        unless ($layer->extracted and $layer->commit) {
+
+          my $key = join '::', ($srcdir, $layer->location, $layer->version);
+
+          # See if commit version information is cached
+          if (keys %config_lines) {
+            if (exists $config_lines{$key}) {
+              $layer->commit ($config_lines{$key});
+            }
+          }
+
+          # Check source directory for commit version, if necessary
+          $layer->get_commit unless $layer->commit;
+          if (not $layer->commit) {
+            w_report 'Error: cannot determine the last changed revision of ',
+                     $layer->location;
+            return;
+          }
+
+          # Set cache directory for layer
+          my $tag_ver = $layer->tag . '__' . $layer->commit;
+          $layer->cachedir (catfile $cachedir, split (/::/, $srcdir), $tag_ver);
+
+          # New line in cache config file
+          $new_config_lines{$key} = $layer->commit;
+        }
+
+        # Push this layer in the stack:
+        # 1. it has a different version compared to the top layer
+        # 2. it is the top layer (base line code)
+        if (@stack > 0) {
+          push @stack, $layer if $layer->commit != $stack[0]->commit;
+
+        } else {
+          push @stack, $layer;
+        }
+
+      }
+    }
+
+    $self->{SRCDIRS}{$srcdir}{STACK} = \@stack;
+
+  }
+
+  # Write "commit cache" file
+  if (not $extracted) {
+    mkpath $cachedir if not -d $cachedir;
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config,);
+
+    while ((my $label, my $value) = each %new_config_lines) {
+      $cfg->add_line (LABEL => $label, VALUE => $value,);
+    }
+
+    $cfg->print_cfg ($cfgfile);
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_extract_src ();
+#
+# DESCRIPTION
+#   This internal method performs the extract of the source directories and
+#   files if necessary.
+# ------------------------------------------------------------------------------
+
+sub _extract_src {
+  my $self = shift;
+
+  my $verbose = $self->config->verbose;
+  my %v_count = (
+    CREATED_DIRS    => 0,
+    IGNORED_SUBDIRS => 0,
+    UPDATED_FILES   => 0,
+    REMOVED_FILES   => 0,
+  );
+
+  my $cachedir = $self->{DEST}{CACHEDIR};
+
+  # Go through the "stack" of each source directory
+  # Extract the source directories/files if required
+
+  for my $srcdir (values %{ $self->{SRCDIRS} }) {
+
+    # Check if destionation exists and is not a directory
+    if (-f $srcdir->{DEST}) {
+      w_report $srcdir->{DEST},
+               ': destination exists and is not a directory, abort.';
+      return;
+    }
+
+    my %base_files   = (); # list of files in the base layer
+    my %used_files   = (); # keys = file basenames, values = layer reference
+    $srcdir->{FILES} = \%used_files;
+    my @destpath     = (); # search path for source directory destinations
+ 
+    for my $layer (@{ $srcdir->{STACK} }) {
+      # Update the cache for each layer of the stack if necessary
+      $layer->update_cache unless $layer->extracted or -d $layer->localdir;
+
+      # Search path for extract destinations of this source directory
+      unshift @destpath, $layer->extracted
+        if $layer->extracted and not grep {$_ eq $layer->extracted} @destpath;
+ 
+      # Get list of files in the cache or local directory
+      for my $file (($layer->get_files)) {
+        if (exists $base_files{$file}) {
+          # File exists in the base, compare current version with base version,
+          # discard if not changed
+          my $base_file = catfile $base_files{$file}->localdir, $file;
+          my $used_file = catfile $used_files{$file}->localdir, $file;
+          my $this_file = catfile $layer->localdir, $file;
+
+          if (compare ($base_file, $this_file)) { # Differs
+            if ($base_files{$file} eq $used_files{$file}) {
+              # Base and used are the same layer, use current layer
+              $used_files{$file} = $layer;
+
+            } elsif (compare ($used_file, $this_file) == 0) {
+              # Changes in used and this are the same, no update required
+
+              # Print a message at verbose mode 2 or above
+              if ($verbose > 1) {
+                print &_print_override_mesg (
+                  FILE   => $file,
+                  LAYER0 => $base_files{$file},
+                  LAYER1 => $used_files{$file},
+                  LAYER2 => $layer,
+                );
+                print '  Same modifications, use the source in URL 1.', "\n";
+              }
+
+            } elsif ($self->{OVERRIDE}) {
+              # Base and used are different, and used is not the same as this
+              # Override mode, use current layer
+
+              # Print override mode message
+              if ($verbose) {
+                print &_print_override_mesg (
+                  FILE   => $file,
+                  LAYER0 => $base_files{$file},
+                  LAYER1 => $used_files{$file},
+                  LAYER2 => $layer,
+                );
+                print '  ', $file, ' in URL 2 overrides that in URL 1.', "\n";
+              }
+
+              $used_files{$file} = $layer;
+
+            } else {
+              # Base and used are different, and used is not the same as this
+              # Non-override mode, fail the extract
+              w_report &_print_override_mesg (
+                FILE   => $file,
+                LAYER0 => $base_files{$file},
+                LAYER1 => $used_files{$file},
+                LAYER2 => $layer,
+              );
+              w_report '  Override mode is false, file in URL 1 cannot ',
+                       'override file in URL 2, abort.';
+              return;
+            }
+          }
+ 
+        } else {
+          # The first time the file is found
+          $base_files{$file} = $layer;
+          $used_files{$file} = $layer;
+        }
+      }
+    }
+
+    # Add current destination to the beginning of the destination search path
+    unshift @destpath, $srcdir->{DEST} if -d $srcdir->{DEST};
+
+    for my $file (keys %used_files) {
+      # Ignore sub-directories
+      if (-d catfile $used_files{$file}->localdir, $file) {
+        # Print diagnostic
+        if ($verbose > 1) {
+          print 'Ignore subdirectory: ', $file, "\n";
+          print '                Src: ', $used_files{$file}->location;
+          print '@', $used_files{$file}->version unless $used_files{$file}->user;
+          print "\n";
+        }
+        $v_count{IGNORED_SUBDIRS}++;
+        next;
+      }
+
+      # Determine whether file has changed, compared with the destination
+      my $diff = 1;
+      for my $dir (@destpath) {
+        my $old = catfile ($dir, $file);
+
+        if (-f $old) {
+          my $new = catfile ($used_files{$file}->localdir, $file);
+          $diff   = compare $old, $new;
+          last;
+        }
+      }
+
+      if ($diff) { # copy if differs
+        # Create extract destination, if required
+        if (not -d $srcdir->{DEST}) {
+          print 'Create directory: ', $srcdir->{DEST}, "\n" if $verbose > 1;
+          my $mkdirs = mkpath $srcdir->{DEST};
+
+          if (! -d $srcdir->{DEST} or ! -w $srcdir->{DEST}) {
+            w_report $srcdir->{DEST}, ': not a writable directory, abort.';
+            return;
+          }
+
+          $v_count{CREATED_DIRS} += $mkdirs;
+        }
+
+        # Set up the copy command
+        my @cmd = (
+          'cp',
+          catfile ($used_files{$file}->localdir, $file),
+          $srcdir->{DEST},
+        );
+
+        my $dest_file = catfile ($srcdir->{DEST}, $file);
+
+        # Print diagnostic
+        if ($verbose > 1) {
+          print 'Update: ', $dest_file, "\n";
+          print '   Src: ', $used_files{$file}->location;
+          print '@', $used_files{$file}->version unless $used_files{$file}->user;
+          print "\n";
+        }
+
+        # Remove old file if it exists
+        unlink $dest_file if -f $dest_file;
+
+        # Execute the copy command
+        &run_command (\@cmd, TIME => $self->config->verbose > 2);
+
+        $v_count{UPDATED_FILES}++;
+      }
+
+    }
+
+    # Check that the destination directory does not contain any removed files
+    opendir DIR, $srcdir->{DEST};
+    my @dest_files = readdir DIR;
+    closedir DIR;
+
+    while (my $file = shift @dest_files) {
+      next if $file =~ /^\.\.?/;                   # ignore hidden files
+      next if -d catfile ($srcdir->{DEST}, $file); # ignore sub-directories
+
+      # Check if the file exists in any of the versions
+      my $exists = 0;
+      for my $layer (@{ $srcdir->{STACK} }) {
+        if (-f catfile ($layer->localdir, $file)) {
+          $exists = 1;
+          last;
+        }
+      }
+
+      # File exists in destination but not in any versions...
+      if (not $exists) {
+        my @cmd = (
+          qw/rm -f/,
+          catfile ($srcdir->{DEST}, $file),
+        );
+
+        # Print diagnostic
+        print 'Remove: ', catfile ($srcdir->{DEST}, $file), "\n"
+          if $verbose > 1;
+
+        # Execute the command
+        &run_command (\@cmd, TIME => $self->config->verbose > 2);
+
+        $v_count{REMOVED_FILES}++;
+      }
+    }
+  }
+
+  if ($verbose) {
+    my %v_label = (
+      CREATED_DIRS    => 'Number of directories created    : ',
+      IGNORED_SUBDIRS => 'Number of ignored sub-directories: ',
+      UPDATED_FILES   => 'Number of updated files          : ',
+      REMOVED_FILES   => 'Number of removed files          : ',
+    );
+    for my $key (qw/CREATED_DIRS IGNORED_SUBDIRS UPDATED_FILES REMOVED_FILES/) {
+      print $v_label{$key}, $v_count{$key}, "\n" if $v_count{$key};
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = _print_override_mesg (
+#     FILE => $file,
+#     LAYER0 => $layer0,
+#     LAYER1 => $layer1,
+#     LAYER2 => $layer2,
+#   );
+#
+# DESCRIPTION
+#   This internal method returns a string containing an override mode message.
+#
+# ARGUMENTS
+#   FILE   - name of the source file
+#   LAYER0 - base location
+#   LAYER1 - source location overridden by LOC2
+#   LAYER2 - source location overriding LOC1
+# ------------------------------------------------------------------------------
+
+sub _print_override_mesg {
+  my %args = @_;
+
+  my $string = $args{FILE};
+  $string .= ': modified in both URL 1 and URL 2, relative to BASE:';
+  $string .= "\n";
+  $string .= '  BASE : ' . $args{LAYER0}->location;
+  $string .= '@' . $args{LAYER0}->version unless $args{LAYER0}->user;
+  $string .= "\n";
+  $string .= '  URL 1: ' . $args{LAYER1}->location;
+  $string .= '@' . $args{LAYER1}->version unless $args{LAYER1}->user;
+  $string .= "\n";
+  $string .= '  URL 2: ' . $args{LAYER2}->location;
+  $string .= '@' . $args{LAYER2}->version unless $args{LAYER2}->user;
+  $string .= "\n";
+
+  return $string;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_sort_bdeclare ();
+#
+# DESCRIPTION
+#   This internal method sorts the declared build configuration entries,
+#   filtering out repeated entries.
+# ------------------------------------------------------------------------------
+
+sub _sort_bdeclare {
+  my $self = shift;
+
+  # Get list of build configuration labels that can be declared multiple times
+  my %cfg_labels   = %{ $self->config->setting ('CFG_LABEL') };
+  my @cfg_keywords = split /,/, $self->config->setting ('CFG_KEYWORD');
+  @cfg_keywords    = map {$cfg_labels{$_}} @cfg_keywords;
+
+  # Filter out repeated declarations
+  my @bdeclares = ();
+  for my $bdeclare (reverse @{ $self->{BDECLARE} }) {
+    my $label = $bdeclare->{LABEL};
+
+    # Do not filter any declarations that can be declared multiple times
+    my $unshift_ok = grep {
+      uc ($label) eq $_ or index (uc ($label), $_ . '::') == 0;
+    } @cfg_keywords;
+    # @bdeclare contains nothing, last entry
+    $unshift_ok    = 1 unless $unshift_ok or @bdeclares;
+    # Check if a later entry already exists
+    $unshift_ok    = 1
+      unless $unshift_ok or grep {$_->{LABEL} eq $label} @bdeclares;
+
+    # Reconstruct array from bottom up
+    unshift @bdeclares, $bdeclare if $unshift_ok;
+  }
+
+  $self->{BDECLARE} = \@bdeclares;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_ext_cfg ();
+#
+# DESCRIPTION
+#   This internal method writes the expanded extract configuration file.
+# ------------------------------------------------------------------------------
+
+sub _write_ext_cfg {
+  my $self = shift;
+
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+  my %subdir     = %{ $self->config->setting ('DIR') };
+  my %cfgname    = %{ $self->config->setting ('CFG_NAME') };
+
+  # Create new config file object and assign lines to it
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, TYPE => 'ext',);
+
+  # Set up config file header
+  $cfg->add_header ();
+
+  # Re-use pre-extracted expanded ext cfg
+  if (@{ $self->{USE} }) {
+    $cfg->add_comment_block ('Other ext cfg');
+
+    for my $reuse (@{ $self->{USE} }) {
+      my $rootdir = $reuse->dest ('ROOTDIR');
+      my $ext_cfg = $reuse->cfg->src;
+
+      # Default location of build config file
+      my $def_ext_cfg = catfile $rootdir, $subdir{CFG}, $cfgname{EXT};
+
+      $cfg->add_line (
+        LABEL => $cfg_labels{USE},
+        VALUE => $ext_cfg eq $def_ext_cfg ? $rootdir : $ext_cfg,
+      );
+    }
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  # Destination directories, config file, etc
+  my $dest = $self->{DEST};
+
+  $cfg->add_comment_block ('Destination');
+
+  $cfg->add_line (
+    LABEL => $cfg_labels{DEST}{ROOTDIR},
+    VALUE => $dest->{ROOTDIR},
+  );
+
+  for my $label (qw/CFG SRC CACHE/) {
+    my $dir = $label . 'DIR';
+
+    if ($dest->{$dir} ne catfile $dest->{ROOTDIR}, $subdir{$label}) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{DEST}{$dir},
+        VALUE => $dest->{$dir},
+      );
+    }
+  }
+
+  for my $name (qw/BLD EXT/) {
+    my $label = $name . '_CFG';
+
+    if ($dest->{$label} ne catfile $dest->{CFGDIR}, $cfgname{$name}) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{DEST}{$label},
+        VALUE => $dest->{$label},
+      );
+    }
+  }
+
+  # Blank line
+  $cfg->add_line;
+
+  # Remote destination directories, config file, etc
+  if ($self->{RDEST}{MACHINE}) {
+    my $rdest = $self->{RDEST};
+
+    $cfg->add_comment_block ('Remote destination');
+
+    for my $label (qw/MACHINE LOGNAME ROOTDIR/) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{RDEST}{$label},
+        VALUE => $rdest->{$label},
+      );
+    }
+
+    for my $label (qw/CFG SRC/) {
+      my $dir = $label . 'DIR';
+      if ($rdest->{$dir} ne catfile $rdest->{ROOTDIR}, $subdir{$label}) {
+        $cfg->add_line (
+          LABEL => $cfg_labels{RDEST}{$dir},
+          VALUE => $rdest->{$dir},
+        );
+      }
+    }
+
+    for my $name (qw/BLD EXT/) {
+      my $label = $name . '_CFG';
+
+      if ($rdest->{$label} ne catfile $rdest->{CFGDIR}, $cfgname{$name}) {
+        $cfg->add_line (
+          LABEL => $cfg_labels{RDEST}{$label},
+          VALUE => $rdest->{$label},
+        );
+      }
+    }
+
+    $cfg->add_line (
+      LABEL => $cfg_labels{MIRROR},
+      VALUE => $self->config->setting (qw/TOOL MIRROR/),
+    );
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  if ($self->{OVERRIDE}) {
+    $cfg->add_line (
+      LABEL => $cfg_labels{OVERRIDE},
+      VALUE => $self->{OVERRIDE} ? 1 : 0,
+    );
+    $cfg->add_line;
+  }
+
+  # Source directories
+  $cfg->add_comment_block ('Source directories');
+
+  # Set up lines in the ext cfg
+  my @lines = ();
+  for my $my_label (keys %{ $self->{SRCDIRS} }) {
+    for my $layer (@{ $self->{SRCDIRS}{$my_label}{STACK} }) {
+      next if $layer->extracted;
+
+      my $tag = $layer->package . '::' . $layer->tag;
+
+      # Repository
+      my $exists = grep {
+        $_->{LABEL} eq $cfg_labels{REPOS} . '::' . $tag;
+      } @lines;
+      push @lines, {
+        LABEL   => $cfg_labels{REPOS} . '::' . $tag,
+        VALUE   => $layer->reposroot,
+      } if not $exists;
+
+      # Version
+      $exists = grep {
+        $_->{LABEL} eq $cfg_labels{VERSION} . '::' . $tag;
+      } @lines;
+      push @lines, {
+        LABEL   => $cfg_labels{VERSION} . '::' . $tag,
+        VALUE   => $layer->version,
+      } unless $layer->user or $exists;
+
+      # Source directory
+      my ($pcks, $path);
+
+      if ($layer->reposroot) {
+        # Repository root declaration exists, print relative path
+        if ($layer->location eq $layer->reposroot) {
+          $path  = '';
+
+        } else {
+          $path  = substr ($layer->location, length ($layer->reposroot) + 1);
+        }
+        my @pcks = split /::/, $my_label;
+        shift @pcks;
+
+        if (join ('::', @pcks) eq join ('::', File::Spec->splitdir ($path))) {
+          # Print top package name if relative path matches sub-package name
+          $pcks = $layer->package;
+
+        } else {
+          # Print full sub-package name otherwise
+          $pcks = $my_label;
+        }
+
+      } else {
+        # No repository root declaration
+        # Print full path and full sub-package name
+        $path = $layer->location;
+        $pcks = $my_label;
+      }
+
+      my $length = $layer->reposroot ? length ($layer->reposroot) + 1 : 0;
+      push @lines, {
+        LABEL   => join ('::', ($cfg_labels{SRCDIR}, $pcks, $layer->tag)),
+        VALUE   => $path,
+      };
+    }
+  }
+
+  # Sort lines for specifying repository, version and source directories
+  @lines = sort {
+    my $rep_label = $cfg_labels{REPOS};
+    my $ver_label = $cfg_labels{VERSION};
+
+    if ($a->{LABEL} =~ /^$rep_label/) {
+
+      # Repository labels
+      if ($b->{LABEL} =~ /^$rep_label/) {
+        $a->{LABEL} cmp $b->{LABEL} or $a->{VALUE} cmp $b->{VALUE};
+      } else {
+        -1;
+      }
+
+    } elsif ($a->{LABEL} =~ /^$ver_label/) {
+
+      # Version labels
+      if ($b->{LABEL} =~ /^$rep_label/) {
+        1;
+      } elsif ($b->{LABEL} =~ /^$ver_label/) {
+        $a->{LABEL} cmp $b->{LABEL} or $a->{VALUE} cmp $b->{VALUE};
+      } else {
+        -1;
+      }
+    } else {
+
+      # Source directories labels
+      if ($b->{LABEL} =~ /^(?:$rep_label|$ver_label)/) {
+        1;
+      } else {
+        $a->{LABEL} cmp $b->{LABEL} or $a->{VALUE} cmp $b->{VALUE};
+      }
+
+    }
+  } @lines;
+
+  # Add lines for specifying repository, version and source directories
+  while (my $line = shift @lines) {
+    $cfg->add_line (
+      LABEL => $line->{LABEL},
+      VALUE => $line->{VALUE},
+    );
+  }
+
+  # Add declared bld cfg entries
+  if (@{ $self->{BDECLARE} }) {
+    # Blank line
+    $cfg->add_line;
+
+    $cfg->add_comment_block ('Declared bld cfg entries');
+    for my $bdeclare (@{ $self->{BDECLARE} }) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{BDECLARE} . '::' . $bdeclare->{LABEL},
+        VALUE => $bdeclare->{VALUE},
+      );
+    }
+  }
+
+  # Print lines to config file
+  $cfg->print_cfg ($self->{DEST}{EXT_CFG});
+
+  return 1;
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_bld_cfg ();
+#
+# DESCRIPTION
+#   This internal method writes the build configuration file.
+# ------------------------------------------------------------------------------
+
+sub _write_bld_cfg {
+  my $self = shift;
+
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+  my %subdir     = %{ $self->config->setting ('DIR') };
+  my %cfgname    = %{ $self->config->setting ('CFG_NAME') };
+
+  # Create new config file object and assign lines to it
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, TYPE => 'bld');
+
+  # Set up config file header
+  $cfg->add_header ();
+
+  # Pre-compile source
+  if (@{ $self->{USE} }) {
+    $cfg->add_comment_block ('Pre-compile source');
+
+    for my $reuse (@{ $self->{USE} }) {
+      my $rootdir;
+      my $bld_cfg;
+
+      if ($self->{RDEST}{MACHINE}) {
+        $rootdir = $reuse->rdest ('ROOTDIR');
+        $bld_cfg = $reuse->rdest ('BLD_CFG');
+      } else {
+        $rootdir = $reuse->dest ('ROOTDIR');
+        $bld_cfg = $reuse->dest ('BLD_CFG');
+      }
+
+      # Default location of build config file
+      my $def_bld_cfg = catfile $rootdir, $subdir{CFG}, $cfgname{BLD};
+
+      $cfg->add_line (
+        LABEL => $cfg_labels{USE},
+        VALUE => $bld_cfg eq $def_bld_cfg ? $rootdir : $bld_cfg,
+      );
+    }
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  # Add declared bld cfg entries
+  if (@{ $self->{BDECLARE} }) {
+    $cfg->add_comment_block ('Declared build options...');
+
+    my @bdeclares = sort {$a->{LABEL} cmp $b->{LABEL}} @{ $self->{BDECLARE} };
+    for my $bdeclare (@bdeclares) {
+      $cfg->add_line (
+        LABEL => $bdeclare->{LABEL},
+        VALUE => $bdeclare->{VALUE},
+      );
+    }
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  # Add source directories to config file
+  $cfg->add_comment_block ('Project directory tree');
+
+  my $dest = $self->{RDEST}{MACHINE} ? $self->{RDEST} : $self->{DEST};
+  $cfg->add_line (
+    LABEL => $cfg_labels{DIR} . '::ROOT',
+    VALUE => $dest->{ROOTDIR},
+  );
+  for my $label (qw/SRC CFG/) {
+    my $dir = $label . 'DIR';
+    if ($dest->{$dir} ne catfile $dest->{ROOTDIR}, $subdir{$label}) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{DIR} . '::' . $label,
+        VALUE => $dest->{$dir},
+      );
+    }
+  }
+
+  # Blank line
+  $cfg->add_line;
+
+  # Add source directories to config file
+  $cfg->add_comment_block ('Source directories');
+
+  $cfg->add_line (LABEL => $cfg_labels{SEARCH_SRC}, VALUE => '0',);
+  $cfg->add_line;
+
+  for my $srcdir (sort keys %{ $self->{SRCDIRS} }) {
+
+    if (-d $self->{SRCDIRS}{$srcdir}{DEST}) {
+      # Check whether pre-extracted source exists
+      my $pre_extracted = grep {
+        $_->extracted;
+      } @{ $self->{SRCDIRS}{$srcdir}{STACK} };
+
+      # Source directory
+      my $dest = undef;
+      if ($self->{RDEST}{MACHINE}) {
+        my $base = substr $self->{SRCDIRS}{$srcdir}{DEST},
+                          length ($self->{DEST}{SRCDIR}) + 1;
+        $dest    = catfile $self->{RDEST}{SRCDIR}, $base;
+      } else {
+        $dest = $self->{SRCDIRS}{$srcdir}{DEST}
+      }
+
+      # Source directory label
+      my $label = join '::', ($cfg_labels{SRCDIR}, $srcdir);
+
+      $cfg->add_line (LABEL => $label, VALUE => $dest,)
+    }
+
+  }
+
+  # Print lines to config file
+  $cfg->print_cfg ($self->{DEST}{BLD_CFG});
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_mirror_extract ();
+#
+# DESCRIPTION
+#   This internal method mirrors the current extract to a remote machine.
+# ------------------------------------------------------------------------------
+
+sub _mirror_extract {
+  my $self = shift;
+
+  # Needs mirroring only if remote machine is set
+  return unless $self->{RDEST}{MACHINE};
+
+  my $verbose = $self->config->verbose;
+
+  my $mirror = $self->config->setting (qw/TOOL MIRROR/);
+
+  if ($mirror eq 'rdist') {
+    # Use "rdist" to mirror extract
+
+    # Variable for "remote_logname@remote_machine"
+    my $rhost = $self->{RDEST}{LOGNAME} . '@' . $self->{RDEST}{MACHINE};
+
+    # Print distfile content to temporary file
+    my @distfile = ();
+    for my $my_label (qw/BLD_CFG EXT_CFG SRCDIR/) {
+      push @distfile, '( ' . $self->{DEST}{$my_label} . ' ) -> ' . $rhost . "\n";
+      push @distfile, '  install ' . $self->{RDEST}{$my_label} . ';' . "\n";
+    }
+
+    # Set up mirroring command (use "rdist" at the moment)
+    my $command = 'rdist -R';
+    $command   .= ' -q' unless $verbose > 1;
+    $command   .= ' -f - 1>/dev/null';
+
+    # Diagnostic
+    my $croak = 'Cannot execute "' . $command . '"';
+    if ($verbose > 2) {
+      print timestamp_command ($command, 'Start');
+      print '  ', $_ for (@distfile);
+    }
+
+    # Execute the mirroring command
+    open COMMAND, '|-', $command or croak $croak, ' (', $!, '), abort';
+    for my $line (@distfile) {
+      print COMMAND $line;
+    }
+    close COMMAND or croak $croak, ' (', $?, '), abort';
+
+    # Diagnostic
+    print timestamp_command ($command, 'End  ') if $verbose > 2;
+
+  } elsif ($mirror eq 'rsync') {
+    # Use "rsync" to mirror extract
+
+    my $rsh = $self->config->setting (qw/TOOL REMOTE_SHELL/);
+
+    # Variable for "remote_logname@remote_machine"
+    my $rhost = $self->{RDEST}{LOGNAME} . '@' . $self->{RDEST}{MACHINE};
+
+    for my $my_label (qw/BLD_CFG EXT_CFG SRCDIR/) {
+      my $rdir = dirname $self->{RDEST}{$my_label}; # remote container directory
+
+      {
+        # Create remote container directory with remote shell command
+        my @command = (
+          $rsh, $self->{RDEST}{MACHINE}, '-n', '-l', $self->{RDEST}{LOGNAME},
+          qw/mkdir -p/, $rdir,
+        );
+
+        # Execute command
+        &run_command (\@command, TIME => $verbose > 2);
+      }
+
+      {
+        # Build the rsync command
+        my @command = qw/rsync -a --exclude='.*' --delete-excluded/;
+        push @command, '-v' if $verbose > 2;
+        push @command, $self->{DEST}{$my_label};
+        push @command, $rhost . ':' . $rdir;
+
+        # Execute command
+        &run_command (\@command, TIME => $verbose > 2);
+      }
+    }
+
+  } else {
+    w_report $mirror, ': unknown mirroring tool, abort.';
+    return;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/ReposBranch.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/ReposBranch.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/ReposBranch.pm	(revision 329)
@@ -0,0 +1,516 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::ReposBranch
+#
+# DESCRIPTION
+#   This class contains methods for gathering information for a repository
+#   branch. It currently supports Subversion repository and local user
+#   directory.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::ReposBranch;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use File::Spec::Functions;
+use File::Basename;
+use File::Find;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch = Fcm::ReposBranch->new (
+#     CONFIG  => $config,
+#     PACKAGE => $package,
+#     TAG     => $tag,
+#     REPOS   => $repos,
+#     VERSION => $version,
+#     TYPE    => $type,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::ReposBranch class.
+#
+# ARGUMENTS
+#   CONFIG  - reference to a Fcm::Config instance
+#   PACKAGE - package name of which this repository belongs
+#   TAG     - "tag" name of this branch of the repository
+#   REPOS   - repository branch root URL/path
+#   VERSION - this version of the branch is used by the extract
+#   TYPE    - repository type
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG  => (exists $args{CONFIG}  ? $args{CONFIG}  : &main::cfg),
+    PACKAGE => (exists $args{PACKAGE} ? $args{PACKAGE} : undef),
+    TAG     => (exists $args{TAG}     ? $args{TAG}     : undef),
+    REPOS   => (exists $args{REPOS}   ? $args{REPOS}   : undef),
+    VERSION => (exists $args{VERSION} ? $args{VERSION} : undef),
+    TYPE    => (exists $args{TYPE}    ? $args{TYPE}    : undef),
+
+    # Use this list of directories in this branch
+    DIRS    => {},
+
+    # Expand this list of directories in this branch
+    EXPDIRS => {},
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $branch->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package = $branch->package;
+#   $branch->package ($package);
+#
+# DESCRIPTION
+#   This method returns the package name of this repository branch. If an
+#   argument is specified, the name is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub package {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PACKAGE} = shift;
+  }
+
+  return $self->{PACKAGE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $tag = $branch->tag;
+#   $branch->tag ($tag);
+#
+# DESCRIPTION
+#   This method returns the tag name of this repository branch. If an
+#   argument is specified, the name is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub tag {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TAG} = shift;
+  }
+
+  return $self->{TAG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $repos = $branch->repos;
+#   $branch->repos ($repos);
+#
+# DESCRIPTION
+#   This method returns the URL/path name of this repository branch. If an
+#   argument is specified, the URL/path is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub repos {
+  my $self = shift;
+
+  if (@_) {
+    $self->{REPOS} = shift;
+  }
+
+  return $self->{REPOS};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version= $branch->version;
+#   $branch->version ($version);
+#
+# DESCRIPTION
+#   This method returns the revision number of this repository branch. If an
+#   argument is specified, the revision is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub version {
+  my $self = shift;
+
+  if (@_) {
+    $self->{VERSION} = shift;
+  }
+
+  return $self->{VERSION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $branch->type;
+#   $branch->type ($type);
+#
+# DESCRIPTION
+#   This method returns the repository type ("svn" or "user"). If an
+#   argument is specified, the type is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $branch->dir ($name);
+#   $branch->dir ($name, $dir);
+#
+# DESCRIPTION
+#   This method returns the path to the source directory with sub-package name
+#   $name. If $dir is specified, the path is set to its value.
+# ------------------------------------------------------------------------------
+
+sub dir {
+  my $self = shift;
+  my $name = shift;
+
+  if (@_) {
+    $self->{DIRS}{$name} = $_[0];
+  }
+
+  if (exists $self->{DIRS}{$name}) {
+    return $self->{DIRS}{$name};
+
+  } else {
+    return undef;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %dirs = $branch->dirs;
+#
+# DESCRIPTION
+#   This method returns a hash containing the source directories of this
+#   repository. The keys of the hash are the sub-package names, and the values
+#   of the hash are the URL/path to the source directories.
+# ------------------------------------------------------------------------------
+
+sub dirs {
+  my $self = shift;
+
+  return %{ $self->{DIRS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $branch->expdir ($name);
+#   $branch->expdir ($name, $dir);
+#
+# DESCRIPTION
+#   This method returns the path to the expandable source directory with
+#   sub-package name $name. If $dir is specified, the path is set to its
+#   value.
+# ------------------------------------------------------------------------------
+
+sub expdir {
+  my $self = shift;
+  my $name = shift;
+
+  if (@_) {
+    $self->{EXPDIRS}{$name} = $_[0];
+  }
+
+  if (exists $self->{EXPDIRS}{$name}) {
+    return $self->{EXPDIRS}{$name};
+
+  } else {
+    return undef;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %dirs = $branch->expdirs;
+#
+# DESCRIPTION
+#   This method returns a hash containing the expandable source directories of
+#   this repository. The keys of the hash are the sub-package names, and the
+#   values of the hash are the URL/path to the expandable source directories.
+# ------------------------------------------------------------------------------
+
+sub expdirs {
+  my $self = shift;
+
+  return %{ $self->{EXPDIRS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->expand_version_tag;
+#
+# DESCRIPTION
+#   This method expands the VERSION of the current repository branch to a
+#   revision number.
+# ------------------------------------------------------------------------------
+
+sub expand_version_tag {
+  my $self = shift;
+
+  if ($self->type eq 'svn') {
+    # Expand revision keyword
+    my $rev = expand_rev_keyword (
+      REV  => $self->version,
+      URL  => $self->repos,
+      HEAD => 1,
+    );
+
+    # Find out whether the specified revision is current or not
+    if (uc ($self->version) ne 'HEAD' and $self->config->verbose > 1) {
+      # Get last commit revision
+      my $lc_rev = expand_rev_keyword (
+        REV => 'HEAD',
+        URL => $self->repos,
+      );
+
+      # Print information if used rev is less than the last commit rev
+      print 'Info: using rev ', $rev, ' of ', $self->repos,
+            ', last commit rev is ', $lc_rev, ".\n"
+        if $rev < $lc_rev;
+    }
+
+    $self->version ($rev) if $rev ne $self->version;
+
+  } elsif ($self->type eq 'user') {
+    return;
+
+  } else {
+    e_report $self->repos, ': repository type "', $self->type,
+             '" not supported.';
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->expand_path;
+#
+# DESCRIPTION
+#   This method expands the relative path names of sub-directories to full
+#   path names. It returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub expand_path {
+  my $self = shift;
+
+  my $separator = $self->{CONFIG}->setting (qw/MISC DIR_SEPARATOR/);
+
+  if ($self->type eq 'svn') {
+    # SVN repository
+    # Do nothing unless there is a declared repository for this branch
+    return unless $self->{REPOS};
+
+    # Remove trailing /
+    $self->{REPOS} =~ s/$separator+$//;
+
+    # Consider all declared (expandable) sub-directories
+    for my $name (qw/DIRS EXPDIRS/) {
+      for my $dir (keys %{ $self->{$name} }) {
+        # Do nothing if declared sub-directory is quoted as a full URL
+        next if &is_url ($self->{$name}{$dir});
+
+        # Expand sub-directory to full URL
+        $self->{$name}{$dir} = $self->{REPOS} . (
+          $self->{$name}{$dir} ? ($separator . $self->{$name}{$dir}) : ''
+        );
+      }
+    }
+    # Note: "catfile" cannot be used in the above statement because it has
+    #       the tendency of removing a slash from double slashes.
+
+  } elsif ($self->type eq 'user') {
+    # Local user directories
+
+    # Expand leading ~ for all declared (expandable) sub-directories
+    for my $name (qw/DIRS EXPDIRS/) {
+      for my $dir (keys %{ $self->{$name} }) {
+        $self->{$name}{$dir} = expand_tilde $self->{$name}{$dir};
+      }
+    }
+
+    # A top directory for the source is declared
+    if ($self->{REPOS}) {
+      # Expand leading ~ for the top directory
+      $self->{REPOS} = expand_tilde $self->{REPOS};
+
+      # Get the root directory of the file system
+      my $rootdir = File::Spec->rootdir ();
+
+      # Expand top directory to absolute path, if necessary
+      $self->{REPOS} = File::Spec->rel2abs ($self->{REPOS})
+        if $self->{REPOS} !~ m/^$rootdir/;
+
+      # Remove trailing /
+      $self->{REPOS} =~ s/$separator+$//;
+
+      # Consider all declared (expandable) sub-directories
+      for my $name (qw/DIRS EXPDIRS/) {
+        for my $dir (keys %{ $self->{$name} }) {
+          # Do nothing if declared sub-directory is quoted as a full path
+          next if $self->{$name}{$dir} =~ m#^$rootdir#;
+
+          # Expand sub-directory to full path
+          $self->{$name}{$dir} = $self->{$name}{$dir}
+                               ? catfile ($self->{REPOS}, $self->{$name}{$dir})
+                               : $self->{REPOS};
+        }
+      }
+    }
+
+  } else {
+    e_report $self->repos, ': repository type "', $self->type,
+             '" not supported.';
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->expand_all;
+#
+# DESCRIPTION
+#   This method searches the expandable source directories recursively for
+#   source directories containing regular files. These sub-directories are
+#   then added to the source directory list. The method returns total number
+#   of sub-directories to be extracted from the current repository.
+# ------------------------------------------------------------------------------
+
+sub expand_all {
+  my $self = shift;
+
+  my %dirs = ();
+
+  # Directory separator for SVN repository
+  my $separator = $self->{CONFIG}->setting (qw/MISC DIR_SEPARATOR/);
+
+  if ($self->type eq 'user') {
+    for my $rootname (keys %{ $self->{EXPDIRS} }) {
+      my %subdirs = find_srcdir $self->{EXPDIRS}{$rootname}, $rootname, '::';
+
+      for my $key (keys %subdirs) {
+        $dirs{$key} = $subdirs{$key};
+      }
+    }
+
+  } elsif  ($self->type eq 'svn') {
+    for my $rootname (keys %{ $self->{EXPDIRS} }) {
+      # Execute the "svn ls -R" command
+      my @lines   = &run_command (
+        [qw/svn ls -R/, $self->{EXPDIRS}{$rootname} . '@' . $self->{VERSION}],
+        METHOD => 'qx', TIME => $self->config->verbose > 2,
+      );
+
+      # Get list of sub-directories containing source files
+      for my $line (@lines) {
+        chomp $line;
+        next if $line =~ /$separator$/;
+
+        my $dir = dirname $line;
+
+        my @pck = split /::/, $rootname;
+        push @pck, (File::Spec->splitdir ($dir)) unless $dir eq '.';
+        my $pck = join '::', @pck;
+
+        my $val = $self->{EXPDIRS}{$rootname};
+        $val   .= $separator . $dir unless $dir eq '.';
+
+        $dirs{$pck} = $val;
+      }
+    }
+
+  } else {
+    e_report $self->repos, ': repository type "', $self->type,
+             '" not supported.';
+  }
+
+  for my $key (keys %dirs) {
+    $self->{DIRS}{$key} = $dirs{$key};
+  }
+
+  return scalar keys %dirs;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->add_base_dirs ($base);
+#
+# DESCRIPTION
+#   Add a list of source directories to the current branch based on the set
+#   provided by $base, which must be a reference to a Fcm::ReposBranch
+#   instance. It returns the total number of used sub-directories in the
+#   current repositories.
+# ------------------------------------------------------------------------------
+
+sub add_base_dirs {
+  my $self = shift;
+  my $base = shift;
+
+  my %base_dirs = $base->dirs;
+
+  for my $key (keys %base_dirs) {
+    # Remove repository root from base directories
+    if ($base_dirs{$key} eq $base->repos) {
+      $base_dirs{$key} = '';
+
+    } else {
+      $base_dirs{$key} = substr $base_dirs{$key}, length ($base->repos) + 1;
+    }
+
+    # Append base directories to current repository root
+    $self->dir ($key, $base_dirs{$key}); 
+  }
+
+  # Expand relative path names of sub-directories
+  $self->expand_path;
+
+  return scalar keys %{ $self->{DIRS} };
+  
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcDirLayer.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcDirLayer.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcDirLayer.pm	(revision 329)
@@ -0,0 +1,481 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::SrcDirLayer
+#
+# DESCRIPTION
+#   This class contains methods to manipulate the extract of a source
+#   directory from a branch of a (Subversion) repository.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::SrcDirLayer;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use File::Spec::Functions;
+use File::Basename;
+use File::Path;
+use File::Compare;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $layer = Fcm::SrcDirLayer->new (
+#     CONFIG    => $config,
+#     NAME      => $dir,
+#     PACKAGE   => $package,
+#     TAG       => $tag,
+#     LOCATION  => $loc,
+#     REPOSROOT => $repos,
+#     VERSION   => $ver,
+#     TYPE      => $type,
+#     COMMIT    => $com,
+#     EXTRACTED => $ext,
+#     CACHEDIR  => $cac,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::SrcDirLayer class.
+#
+# ARGUMENTS
+#   CONFIG    - reference to a Fcm::Config instance
+#   NAME      - sub-package name of the source directory
+#   PACKAGE   - top level package name of which the current repository belongs
+#   TAG       - package/revision tag of the current repository branch
+#   LOCATION  - location of the source directory in the branch
+#   REPOSROOT - repository root URL
+#   VERSION   - revision of the repository branch
+#   TYPE      - type of the repository branch ("svn" or "user")
+#   COMMIT    - revision at which the source directory was changed
+#   EXTRACTED - is this branch already extracted?
+#   CACHEDIR  - cache directory for this directory branch
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG    => (exists $args{CONFIG}    ? $args{CONFIG}    : &main::cfg),
+    NAME      => (exists $args{NAME}      ? $args{NAME}      : undef),
+    PACKAGE   => (exists $args{PACKAGE}   ? $args{PACKAGE}   : undef),
+    TAG       => (exists $args{TAG}       ? $args{TAG}       : undef),
+    LOCATION  => (exists $args{LOCATION}  ? $args{LOCATION}  : undef),
+    REPOSROOT => (exists $args{REPOSROOT} ? $args{REPOSROOT} : undef),
+    VERSION   => (exists $args{VERSION}   ? $args{VERSION}   : undef),
+    TYPE      => (exists $args{TYPE}      ? $args{TYPE}      : undef),
+    COMMIT    => (exists $args{COMMIT}    ? $args{COMMIT}    : undef),
+    EXTRACTED => (exists $args{EXTRACTED} ? $args{EXTRACTED} : undef),
+    CACHEDIR  => (exists $args{CACHEDIR}  ? $args{CACHEDIR}  : undef),
+
+    # List of source files in this directory branch
+    FILES     => [],
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $layer->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $name = $layer->name;
+#   $layer->name ($name);
+#
+# DESCRIPTION
+#   This method returns the sub-package name of the current source directory.
+#   If an argument is specified, the sub-package name is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub name {
+  my $self = shift;
+
+  if (@_) {
+    $self->{NAME} = shift;
+  }
+
+  return $self->{NAME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package = $layer->package;
+#   $layer->package ($package);
+#
+# DESCRIPTION
+#   This method returns the top level package name in which the current source
+#   directory belongs. If an argument is specified, the package name is set to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub package {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PACKAGE} = shift;
+  }
+
+  return $self->{PACKAGE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $tag = $layer->tag;
+#   $layer->tag ($tag);
+#
+# DESCRIPTION
+#   This method returns the branch/revision tag of the current repository
+#   branch. If an argument is specified, the tag is set to the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub tag {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TAG} = shift;
+  }
+
+  return $self->{TAG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $location = $layer->location;
+#   $layer->location ($location);
+#
+# DESCRIPTION
+#   This method returns the URL/location of the source directory in the
+#   branch. If an argument is specified, the location is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub location {
+  my $self = shift;
+
+  if (@_) {
+    $self->{LOCATION} = shift;
+  }
+
+  return $self->{LOCATION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $reposroot = $layer->reposroot;
+#   $layer->reposroot ($reposroot);
+#
+# DESCRIPTION
+#   This method returns the URL/location of the repository root of this
+#   branch. If an argument is specified, the location is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub reposroot {
+  my $self = shift;
+
+  if (@_) {
+    $self->{REPOSROOT} = shift;
+  }
+
+  return $self->{REPOSROOT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $layer->version;
+#   $layer->version ($version);
+#
+# DESCRIPTION
+#   This method returns the revision number of this branch. If an argument is
+#   specified, the revision number is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub version {
+  my $self = shift;
+
+  if (@_) {
+    $self->{VERSION} = shift;
+  }
+
+  return $self->{VERSION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $layer->type;
+#   $layer->type ($type);
+#
+# DESCRIPTION
+#   This method returns the repository type ("svn" or "user"). If an argument is
+#   specified, the type is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $layer->commit;
+#   $layer->commit ($version);
+#
+# DESCRIPTION
+#   This method returns the last modified revision of the source directory in
+#   the branch. If an argument is specified, this revision is set to the value
+#   of the argument.
+# ------------------------------------------------------------------------------
+
+sub commit {
+  my $self = shift;
+
+  if (@_) {
+    $self->{COMMIT} = shift;
+  }
+
+  return $self->{COMMIT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $extracted = $layer->extracted;
+#   $layer->extracted ($extracted);
+#
+# DESCRIPTION
+#   This method returns the "extracted flag" of the source directory branch
+#   If an argument is specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub extracted {
+  my $self = shift;
+
+  if (@_) {
+    $self->{EXTRACTED} = shift;
+  }
+
+  return $self->{EXTRACTED};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $layer->cachedir;
+#   $layer->cachedir ($dir);
+#
+# DESCRIPTION
+#   This method returns the cache directory of the source directory branch
+#   If an argument is specified, the cache directory is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub cachedir {
+  my $self = shift;
+
+  if (@_) {
+    my $dir = shift;
+    $self->{CACHEDIR} = $dir;
+  }
+
+  return $self->{CACHEDIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $layer->localdir;
+#
+# DESCRIPTION
+#   This method returns the user or cache directory for the current revision
+#   of the repository branch.
+# ------------------------------------------------------------------------------
+
+sub localdir {
+  my $self = shift;
+
+  return $self->user ? $self->{LOCATION} : $self->{CACHEDIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @files = $layer->files;
+#
+# DESCRIPTION
+#   This method returns a list of regular files in this directory branch.
+#   This method should only be called after a successful operation of the
+#   get_files method that will be described below.
+# ------------------------------------------------------------------------------
+
+sub files {
+  my $self = shift;
+
+  return @{ $self->{FILES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $user = $layer->user;
+#
+# DESCRIPTION
+#   This method returns the string "user" if the current source directory
+#   branch is a local directory. Otherwise, it returns "undef".
+# ------------------------------------------------------------------------------
+
+sub user {
+  my $self = shift;
+
+  return $self->{TYPE} eq 'user' ? 'user' : undef;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $layer->get_commit;
+#
+# DESCRIPTION
+#   If the current repository type is "svn", this method attempts to obtain
+#   the revision in which the branch is last committed. On a successful
+#   operation, it returns this revision number. Otherwise, it returns
+#   "undef".
+# ------------------------------------------------------------------------------
+
+sub get_commit {
+  my $self = shift;
+
+  if ($self->type eq 'svn') {
+    # Execute the "svn info" command
+    my @lines   = &run_command (
+      [qw/svn info/, $self->{LOCATION} . '@' . $self->{VERSION}],
+      METHOD => 'qx', TIME => $self->config->verbose > 2,
+    );
+
+    my $rev;
+    for (@lines) {
+      if (/^Last\s+Changed\s+Rev\s*:\s*(\d+)/i) {
+        $rev = $1;
+        last;
+      }
+    }
+
+    # Commit version of this source directory
+    $self->{COMMIT} = $rev;
+
+    return $self->{COMMIT};
+
+  } elsif ($self->type eq 'user') {
+    return;
+
+  } else {
+    e_report 'Repository type "', $self->type, '" not supported.';
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $layer->update_cache;
+#
+# DESCRIPTION
+#   If the current repository type is "svn", this method attempts to extract
+#   the current version source directory from the current branch from the
+#   repository, sending the output to the cache directory. It returns true on
+#   a successful operation, or false if the repository is not of type "svn".
+# ------------------------------------------------------------------------------
+
+sub update_cache {
+  my $self = shift;
+
+  return unless $self->{CACHEDIR};
+
+  # Create cache extract destination, if necessary
+  my $dirname = dirname $self->{CACHEDIR};
+  mkpath $dirname if not -d $dirname;
+
+  e_report $dirname, ': cannot write to cache, abort.'
+    unless -d $dirname and -w $dirname;
+  
+  if ($self->type eq 'svn') {
+    # Set up the extract command, "svn export --force -q -N"
+    my @command = (
+      qw/svn export --force -q -N/,
+      $self->{LOCATION} . '@' . $self->{VERSION},
+      $self->{CACHEDIR},
+    );
+
+    &run_command (\@command, TIME => $self->config->verbose > 2);
+
+  } elsif ($self->type eq 'user') {
+    return;
+
+  } else {
+    e_report 'Repository type "', $self->type, '" not supported.';
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @files = $layer->get_files;
+#
+# DESCRIPTION
+#   This method returns a list of files in the cache or local user directory
+#   of the current version of the source directory in the current branch.
+# ------------------------------------------------------------------------------
+
+sub get_files {
+  my $self = shift;
+
+  # Get a list of files in the cache (or local user) directory
+  my @files = ();
+
+  opendir (DIR, $self->localdir)
+    or die $self->localdir, ': cannot read directory';
+
+  while (my $file = readdir DIR) {
+    next if $file =~ /^\.\.?/;                   # ignore . and .. and hidden
+    next if $file =~ /~$/;                       # ignore emacs swap files
+    next if -d catfile ($self->localdir, $file); # ignore sub-directories
+    push @files, $file;
+  }
+  closedir DIR;
+
+  # Return the (base name) of the list of files
+  $self->{FILES} = \@files;
+  return @files;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcFile.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcFile.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcFile.pm	(revision 329)
@@ -0,0 +1,1479 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::SrcFile
+#
+# DESCRIPTION
+#   This class contains methods to manipulate the build process of a source
+#   file of supported type.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::SrcFile;
+
+# Standard pragma
+
+use strict;
+use warnings;
+
+# Standard modules
+use Cwd;
+use Carp;
+use File::Basename;
+use File::Spec;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# Other modules
+use Ecmwf::Fortran90_stuff ();
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile = Fcm::SrcFile->new (
+#     CONFIG     => $config,
+#     SRCPACKAGE => $srcpackage,
+#     SRC        => $src,
+#     PPSRC      => $ppsrc,
+#     TYPE       => $type,
+#     SCAN       => $scan,
+#     TARGET     => $target,
+#     PCKCFG     => $pckcfg,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Extract class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   SRCPACKAGE - reference to the container Fcm::SrcPackage instance
+#   SRC        - source path of this file
+#   PPSRC      - pre-processed source path of this file
+#   TYPE       - type flag of this source file
+#   SCAN       - scan source file for dependency?
+#   TARGET     - name of executable or library target
+#   PCKCFG     - this source file is modified by a package cfg?
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG     => exists $args{CONFIG}     ? $args{CONFIG}     : &main::cfg,
+    SRCPACKAGE => exists $args{SRCPACKAGE} ? $args{SRCPACKAGE} : undef,
+    SRC        => exists $args{SRC}        ? $args{SRC}        : undef,
+    PPSRC      => exists $args{PPSRC}      ? $args{PPSRC}      : undef,
+    TYPE       => exists $args{TYPE}       ? $args{TYPE}       : undef,
+    SCAN       => exists $args{SCAN}       ? $args{SCAN}       : 1,
+    TARGET     => exists $args{TARGET}     ? $args{TARGET}     : undef,
+    PCKCFG     => exists $args{PCKCFG}     ? $args{PCKCFG}     : undef,
+
+    INTNAME    => undef,
+    DEP        => {}, 
+  };
+  bless $self, $class;
+
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $srcfile->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcpackage = $srcfile->srcpackage;
+#   $srcfile->srcpackage ($srcpackage);
+#
+# DESCRIPTION
+#   This method returns the reference to the container Fcm::SrcPackage of this
+#   source file. If an argument is specified, the reference is set to the
+#   value of the argument.
+# ------------------------------------------------------------------------------
+
+sub srcpackage {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRCPACKAGE} = shift;
+  }
+
+  return $self->{SRCPACKAGE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $src = $srcfile->src;
+#   $srcfile->src ($src);
+#
+# DESCRIPTION
+#   This method returns the reference to the location of this source file. If
+#   an argument is specified, the location is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub src {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRC} = shift;
+  }
+
+  return $self->{SRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppsrc = $srcfile->ppsrc;
+#   $srcfile->ppsrc ($ppsrc);
+#
+# DESCRIPTION
+#   This method returns the reference to the location of the pre-processed
+#   file of this source file. If an argument is specified, the location is set
+#   to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub ppsrc {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PPSRC} = shift;
+  }
+
+  return $self->{PPSRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $time = $srcfile->mtime;
+#
+# DESCRIPTION
+#   This method returns the last modified time of the source file. If a
+#   pre-processed version of the source file exists, it returns the last
+#   modified time of the pre-processed source file instead.
+# ------------------------------------------------------------------------------
+
+sub mtime {
+  my $self = shift;
+
+  return $self->{PPSRC} ? (stat $self->{PPSRC})[9] : (stat $self->{SRC})[9];
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $base = $srcfile->base;
+#
+# DESCRIPTION
+#   This method returns the base name of the source file.
+# ------------------------------------------------------------------------------
+
+sub base {
+  my $self = shift;
+
+  return basename ($self->{SRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppbase = $srcfile->ppbase;
+#
+# DESCRIPTION
+#   This method returns the base name of the pre-processed source file.
+# ------------------------------------------------------------------------------
+
+sub ppbase {
+  my $self = shift;
+
+  return basename ($self->{PPSRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $interfacebase = $srcfile->interfacebase;
+#
+# DESCRIPTION
+#   This method returns the base name of the F9X interface file.
+# ------------------------------------------------------------------------------
+
+sub interfacebase {
+  my $self = shift;
+
+  my $flag = lc ($self->select_tool ('INTERFACE'));
+  my $ext  = $self->config->setting (qw/OUTFILE_EXT INTERFACE/);
+
+  return ($flag eq 'program' ? $self->intname : $self->root) . $ext;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $root = $srcfile->root;
+#
+# DESCRIPTION
+#   This method returns the root name (i.e. base name without file extension)
+#   of the source file.
+# ------------------------------------------------------------------------------
+
+sub root {
+  my $self = shift;
+
+  (my $root = $self->base) =~ s/\.\w+$//;
+
+  return $root;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext = $srcfile->ext;
+#
+# DESCRIPTION
+#   This method returns the file extension of the source file.
+# ------------------------------------------------------------------------------
+
+sub ext {
+  my $self = shift;
+
+  return substr $self->base, length ($self->root);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppext = $srcfile->ppext;
+#
+# DESCRIPTION
+#   This method returns the file extension of the pre-processed source file.
+# ------------------------------------------------------------------------------
+
+sub ppext {
+  my $self = shift;
+
+  return substr $self->ppbase, length ($self->root);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $srcfile->dir;
+#
+# DESCRIPTION
+#   This method returns the dir name of the source file.
+# ------------------------------------------------------------------------------
+
+sub dir {
+  my $self = shift;
+
+  return dirname ($self->{SRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppdir = $srcfile->ppdir;
+#
+# DESCRIPTION
+#   This method returns the dir name of the pre-processed source file.
+# ------------------------------------------------------------------------------
+
+sub ppdir {
+  my $self = shift;
+
+  return dirname ($self->{PPSRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $srcfile->type;
+#   $srcfile->type ($type);
+#
+# DESCRIPTION
+#   This method returns the type flag of the source file. If an argument is
+#   specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $srcfile->is_type ($type1[, $type2, ...]);
+#
+# DESCRIPTION
+#   This method returns true if current file is a known type matching all the
+#   arguments.
+# ------------------------------------------------------------------------------
+
+sub is_type {
+  my $self    = shift;
+  my @intypes = @_;
+  my $rc      = 0;
+
+  if ($self->{TYPE}) {
+    my @types = split /::/, $self->{TYPE};
+
+    for my $intype (@intypes) {
+      $rc = grep {uc $_ eq uc $intype} @types;
+      last unless $rc;
+    }
+
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $srcfile->is_type_or ($type1[, $type2, ...]);
+#
+# DESCRIPTION
+#   This method returns true if current file is a known type matching any of
+#   the arguments.
+# ------------------------------------------------------------------------------
+
+sub is_type_or {
+  my $self    = shift;
+  my @intypes = @_;
+  my $rc      = 0;
+
+  if ($self->{TYPE}) {
+    my @types = split /::/, $self->{TYPE};
+
+    for my $intype (@intypes) {
+      $rc = grep {uc $_ eq uc $intype} @types;
+      last if $rc;
+    }
+
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $srcfile->scan ();
+#   $srcfile->scan ($flag);
+#
+# DESCRIPTION
+#   This method returns the "scan" flag that determines whether the source
+#   file needs to be scanned for dependency. If an argument is specified, the
+#   flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub scan {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SCAN} = $_[0];
+  }
+
+  return $self->{SCAN};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $target = $srcfile->target ();
+#   $srcfile->target ($target);
+#
+# DESCRIPTION
+#   This method returns the name of the build target of the source file. (This
+#   affects only the executable names of main programs and file names of
+#   binary object libraries.) If an argument is specified, the target is set to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub target {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TARGET} = $_[0];
+  }
+
+  my $return;
+
+  if ($self->config->setting ('EXE_NAME', $self->root)) {
+    $return = $self->config->setting ('EXE_NAME', $self->root);
+
+  } elsif ($self->{TARGET}) {
+    $return = $self->{TARGET};
+
+  } else {
+    $return = $self->root . $self->config->setting (qw/OUTFILE_EXT EXE/);
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $pckcfg = $srcfile->pckcfg ();
+#   $srcfile->pckcfg ($pckcfg);
+#
+# DESCRIPTION
+#   This method returns the name of the flag to indicate whether this source
+#   file is modified by a package level configuration file. If an argument is
+#   specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub pckcfg {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PCKCFG} = $_[0];
+  }
+
+  return $self->{PCKCFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $progname = $srcfile->progname();
+#   $srcfile->progname ($progname);
+#
+# DESCRIPTION
+#   This method returns the name of the first program unit in a Fortran source
+#   file. If an argument is specified, the name is set to the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub progname {
+  my $self = shift;
+
+  if (@_) {
+    $self->{INTNAME} = $_[0];
+  }
+
+  return $self->{INTNAME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $intname = $srcfile->intname ();
+#
+# DESCRIPTION
+#   This method returns the internal name of the source file.
+# ------------------------------------------------------------------------------
+
+sub intname {
+  my $self = shift;
+
+  return $self->{INTNAME} ? $self->{INTNAME} : lc ($self->root);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %dep   = $srcfile->dep;
+#   @files = $srcfile->dep ($type);
+#   $srcfile->dep (\%dep);
+#
+# DESCRIPTION
+#   This method returns the dependencies of this source file. If no argument
+#   is set, the method returns the dependency hash of this source file. The
+#   keys of the hash are the names of the files this source files depends on
+#   and the values of the hash are the dependency types of the corresponding
+#   files. If an argument is specified and the argument is a normal string,
+#   the method returns the keys of the dependency hash, which have their
+#   corresponding values equal to $type. If an argument is specified and the
+#   argument is a reference to a hash, the reference to the dependency hash of
+#   the current source file is re-set to point to the reference of this new
+#   hash.
+# ------------------------------------------------------------------------------
+
+sub dep {
+  my $self = shift;
+
+  if (@_) {
+    if (ref $_[0] eq 'HASH') {
+      $self->{DEP} = $_[0];
+
+    } else {
+      my $type = $_[0];
+      return grep {
+        $self->{DEP}{$_} eq $type;
+      } keys %{ $self->{DEP} };
+    }
+  }
+
+  return %{ $self->{DEP} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile->add_dep ($target, $type);
+#
+# DESCRIPTION
+#   This method adds (or modifies) a dependency to the dependency hash of the
+#   source file. The argument $type is the type of the dependency and the
+#   argument $target is the dependency target.
+# ------------------------------------------------------------------------------
+
+sub add_dep {
+  my $self = shift;
+  my ($target, $type) = @_;
+
+  $self->{DEP}{$target} = $type;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @pklist = $self->get_package_list ();
+#
+# DESCRIPTION
+#   This method returns a list of package names associated with this source
+#   file. The list begins with the top level container package to the
+#   sub-package name of the current source file.
+# ------------------------------------------------------------------------------
+
+sub get_package_list {
+  my $self = shift;
+
+  my @pknames = ();
+
+  my @packages = split /__/, $self->srcpackage->name;
+  push @packages, $self->root;
+
+  for my $i (0 .. $#packages) {
+    push @pknames, join ('__', (@packages[0 .. $i]));
+  }
+
+  return @pknames;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile->determine_type;
+#
+# DESCRIPTION
+#   This method determines whether the source file is a type known to the
+#   build system. If so, it sets the "type" flag.
+# ------------------------------------------------------------------------------
+
+sub determine_type {
+  my $self = shift;
+
+  if (not $self->{TYPE}) {
+    # Determine file type by comparing its extension with supported ones
+    my %known_ext = %{ $self->config->setting ('INFILE_EXT') };
+    my $ext       = $self->ext ? substr ($self->ext, 1) : 0;
+    $self->{TYPE} = $known_ext{$ext} if $ext and exists $known_ext{$ext};
+  }
+
+  if (not $self->{TYPE}) {
+    # Determine file type by comparing its name with known patterns
+    my %known_pat = %{ $self->config->setting ('INFILE_PAT') };
+    for my $pat (keys %known_pat) {
+      if ($self->base =~ /$pat/) {
+        $self->{TYPE} = $known_pat{$pat};
+        last;
+      }
+    }
+  }
+
+  if (-s $self->{SRC} and -T $self->{SRC} and not $self->{TYPE}) {
+    # Determine file type by inspecting its first line (text file only)
+    if (open SRC, '<', $self->{SRC}) {
+      my $line = <SRC>;
+      close SRC;
+
+      my %known_txt = %{ $self->config->setting ('INFILE_TXT') };
+      for my $txt (keys %known_txt) {
+        if ($line =~ /^#!.*$txt/) {
+          $self->{TYPE} = $known_txt{$txt};
+          last;
+        }
+      }
+    }
+  }
+
+  if ($self->is_type_or (qw/FORTRAN FPP/)) {
+    # Determine whether source file is a main Fortran program or module
+    if (open SRC, '<', $self->{SRC}) {
+      while (my $line = <SRC>) {
+        if ($line =~ /^\s*(PROGRAM|MODULE)\b/i) {
+          $self->{TYPE} = $self->{TYPE} . '::' . uc ($1);
+          last;
+
+        } elsif ($line =~ /^\s*BLOCK\s*DATA\b/i) {
+          $self->{TYPE} = $self->{TYPE} . '::' . 'BLOCKDATA';
+          last;
+        }
+      }
+      close SRC;
+    }
+
+  } elsif ($self->is_type (qw/C/)) {
+    # Determine whether source file is a main C program
+    if (open SRC, '<', $self->{SRC}) {
+      while (my $line = <SRC>) {
+        next unless $line =~ /int\s*main\s*\(/i;
+        $self->{TYPE} = $self->{TYPE} . '::PROGRAM';
+        last;
+      }
+      close SRC;
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @pp_src = @{ $srcfile->pre_process () };
+#
+# DESCRIPTION
+#   This method invokes the pre-processor on the source file. It returns a
+#   reference to an array containing the lines of the pre-processed source if
+#   the pre-processor command succeeded.
+# ------------------------------------------------------------------------------
+
+sub pre_process {
+  my $self = shift;
+
+  # Support only Fortran and C source files
+  return unless $self->is_type_or (qw/FPP C/);
+
+  # List of include directories
+  my @inc = @{ $self->config->setting (qw/PATH INC/) };
+
+  # Build the pre-processor command according to file type
+  my $name    = $self->is_type ('FPP') ? 'FPP' : 'CPP';
+  my %tool    = %{ $self->config->setting ('TOOL') };
+
+  # The pre-processor command and its options
+  my @command = ($tool{$name});
+  my @ppflags = split /\s+/, $self->select_tool ($name . 'FLAGS');
+
+  # List of defined macros, add "-D" in front of each macro
+  my @ppkeys  = split /\s+/, $self->select_tool ($name . 'KEYS');
+  @ppkeys     = map {($tool{$name . '_DEFINE' }, $_)} @ppkeys;
+
+  # Add "-I" in front of each include directories
+  @inc        = map {($tool{$name . '_INCLUDE'}, $_)} @inc;
+
+  push @command, (@ppflags, @ppkeys, @inc, $self->base);
+
+  my $verbose = $self->config->verbose;
+  my $cwd     = cwd;
+
+  # Change to container directory of source file
+  print 'cd ', $self->dir, "\n" if $verbose > 1;
+  chdir $self->dir;
+
+  # Execute the command, getting the output lines
+  my @outlines = &run_command (
+    \@command, METHOD => 'qx', PRINT => $verbose > 1, TIME => $verbose > 2,
+  );
+
+  # Change back to original directory
+  print 'cd ', $cwd, "\n" if $self->config->verbose > 1;
+  chdir $cwd;
+
+  return \@outlines;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @interface_block = @{ $srcfile->gen_interface () };
+#
+# DESCRIPTION
+#   This method invokes the Fortran 9x interface block generator to generate
+#   an interface block for the current source file. It returns a reference to
+#   an array containing the lines of the interface block.
+# ------------------------------------------------------------------------------
+
+sub gen_interface {
+  my $self = shift;
+
+  my $generator = $self->select_tool ('GENINTERFACE');
+
+  my $src      = $self->{PPSRC} ? $self->{PPSRC} : $self->{SRC};
+  my @outlines = ();
+
+  if ($generator eq 'f90aib') {
+    # Use F90AIB
+
+    # Open pipeline to interface file generator and read its output
+    my $devnull = File::Spec->devnull;
+    my $command = $generator;
+    $command   .= " <'" . $src . "'" . " 2>'" . $devnull . "'";
+    my $croak   = $command . ' failed';
+
+    print timestamp_command ($command, 'Start') if $self->config->verbose > 2;
+    open COMMAND, '-|', $command or croak $croak, ' (', $!, '), abort';
+    @outlines = readline 'COMMAND';
+    close COMMAND or croak $croak, ' (', $?, '), abort';
+    print timestamp_command ($command, 'End  ') if $self->config->verbose > 2;
+
+  } elsif ($generator eq 'ECMWF') {
+    # Use ECMWF interface generator
+  
+    # Read source file into an array
+    open FILE, '<', $src or croak 'Cannot open "', $src, '" (', $!, '), abort';
+    my @src_lines = <FILE>;
+    close FILE;
+  
+    # Process standalone subroutines and functions only
+    if (not grep /^\s*(?:program|module)\b/i, @src_lines) {
+      print timestamp_command ('Analyse: ' . $self->src, 'Start')
+        if $self->config->verbose > 2;
+
+      my @statements = ();
+      my %prog_info  = ();
+  
+      # Set name of source file
+      &Ecmwf::Fortran90_stuff::fname ($src);
+  
+      # Parse lines in source
+      &Ecmwf::Fortran90_stuff::setup_parse ();
+
+      # Expand continuation lines in source
+      &Ecmwf::Fortran90_stuff::expcont (\@src_lines, \@statements);
+  
+      # Analyse statements in source
+      $Ecmwf::Fortran90_stuff::study_called = 0;
+      &Ecmwf::Fortran90_stuff::study (\@statements, \%prog_info);
+  
+      # Source code is not a module
+      if (not $prog_info{is_module}) {
+        my @interface_block = ();
+        my @line_hash       = ();
+  
+        # Create an interface block for the program unit
+        &Ecmwf::Fortran90_stuff::create_interface_block (
+          \@statements,
+          \@interface_block,
+        );
+
+        # Put continuation lines back
+        &Ecmwf::Fortran90_stuff::cont_lines (
+          \@interface_block,
+          \@outlines,
+          \@line_hash,
+        );
+      }
+
+      print timestamp_command ('Analyse: ' . $self->src, 'End')
+        if $self->config->verbose > 2;
+    }
+
+  } elsif (uc ($generator) eq 'NONE') {
+    print $self->root, ': interface generation is switched off', "\n"
+      if $self->config->verbose > 2;
+
+  } else {
+    e_report 'Error: Unknown Fortran 9x interface generator: ', $generator, '.';
+  }
+
+  return \@outlines;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $tool = $self->select_tool ($name);
+#
+# DESCRIPTION
+#   This method selects the correct "tool" for the current source file by
+#   following the name of its container package. The argument $name must be
+#   the generic name of the "tool" to be selected. The method returns the
+#   value of the selected tool.
+# ------------------------------------------------------------------------------
+
+sub select_tool {
+  my $self  = shift;
+  my $name  = shift;
+
+  return undef unless $name;
+
+  my @pknames = $self->get_package_list ();
+
+  my %tool    = %{ $self->config->setting ('TOOL') };
+
+  for my $pkname (reverse @pknames) {
+    my $cur_name = join '__', ($name, $pkname);
+    return $tool{$cur_name} if exists $tool{$cur_name};
+  }
+
+  return exists $tool{$name} ? $tool{$name} : '';
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $srcfile->scan_dependency ();
+#   $rc = $srcfile->scan_dependency (HEADER_ONLY => 1);
+#
+# DESCRIPTION
+#   This method scans the source file for dependencies. If no argument is
+#   specified, the method scans the pre-processed source file if it exists.
+#   Otherwise, the original source file is scanned. If HEADER_ONLY is
+#   specified, only pre-processing header dependencies are scanned from the
+#   source file. (The HEADER_ONLY flag should only be specified if "ppsrc" is
+#   not already specified.) This method returns the number of 1 on success.
+# ------------------------------------------------------------------------------
+
+sub scan_dependency {
+  my $self = shift;
+  my %args = @_;
+
+  my $header_only = exists $args{HEADER_ONLY} ? $args{HEADER_ONLY} : 0;
+
+  return 0 unless $self->{SCAN};
+  return 0 unless $self->{TYPE};
+
+  my $src = $self->{PPSRC} ? $self->{PPSRC} : $self->{SRC};
+  return 0 unless $src;
+
+  # Determine what dependencies are supported by this known type
+  my %types = $header_only
+              ? %{ $self->config->setting ('PP_DEP_TYPE') }
+              : %{ $self->config->setting ('DEP_TYPE') };
+
+  # List of excluded dependencies
+  my %excl_dep = %{ $self->config->setting ('EXCL_DEP') };
+
+  # Package list
+  my @pknames = $self->get_package_list ();
+
+  my @depends = ();
+  for my $key (keys %types) {
+    # Check if current file is a type of file requiring dependency scan
+    next unless $self->is_type ($key);
+    
+    # Get list of dependency type for this file
+    DEPEND: for my $depend ((split /::/, $types{$key})) {
+      # Ignore a dependency type if the dependency is in the exclude list
+      if (exists $excl_dep{$depend}) {
+        # Global exclude
+        next DEPEND if exists $excl_dep{$depend}{''};
+
+        # Sub-package exclude
+        for my $pkname (@pknames) {
+          next DEPEND if exists $excl_dep{$depend}{$pkname};
+        }
+      }
+
+      # Add to dependency list for current file
+      push @depends, $depend;
+    }
+  }
+
+  # Scan dependencies, if necessary ...
+  if (@depends) {
+    # Print diagnostic
+    print timestamp_command ('scan dependency in file: ' . $src, 'Start')
+      if $self->config->verbose > 2;
+
+    open FILE, '<', $src or croak 'Cannot open "', $src, '" (', $!, ')';
+    my @lines = readline 'FILE';
+    close FILE;
+
+    # List of dependency patterns
+    my %dep_pattern = %{ $self->config->setting ('DEP_PATTERN') };
+
+    LINE: for my $line (@lines) {
+      # Ignore empty lines
+      next LINE if $line =~ /^\s*$/;
+
+      # Fortran source, also determine internal name
+      if (! $header_only and ! $self->{INTNAME}) {
+        if ($self->is_type ('SOURCE') and $self->is_type_or (qw/FPP FORTRAN/)) {
+          my $pfx_pttn = '(?:(?:RECURSIVE|ELEMENTAL|PURE)\s+)?';
+          my $spc_pttn = '(?:(?:CHARACTER|COMPLEX|DOUBLE\s*PRECISION|INTEGER|' .
+                         'LOGICAL|REAL|TYPE)(?:\s*\(.+\)|\s*\*\d+\s*)??\s+)?';
+
+          if ($line =~ /^\s*PROGRAM\s+(\w+)/i) {
+            # Matches the beginning of a named main program
+            $self->{INTNAME} = lc $1;
+            next LINE;
+
+          } elsif ($line =~ /^\s*MODULE\s+(\w+)/i) {
+            my $keyword = $1;
+
+            if (uc ($keyword) ne 'PROCEDURE') {
+              # Matches the beginning of a module
+              $self->{INTNAME} = lc $keyword;
+              next LINE;
+            }
+
+          } elsif ($line =~ /^\s*BLOCK\s*DATA\s+(\w+)/i) {
+            # Matches the beginning of a named block data program unit
+            $self->{INTNAME} = lc $1;
+            next LINE;
+
+          } elsif ($line =~ /^\s*$pfx_pttn SUBROUTINE\s+(\w+)/ix) {
+            # Matches the beginning of a subroutine
+            $self->{INTNAME} = lc $1;
+            next LINE;
+
+          } elsif ($line =~ /^\s*$pfx_pttn $spc_pttn FUNCTION\s+(\w+)/ix) {
+            # Matches the beginning of a function
+            $self->{INTNAME} = lc $1;
+            next LINE;
+          }
+        }
+      }
+
+      # Scan known dependencies
+      for my $depend (@depends) {
+        # Check if a pattern exists for the current dependency
+        next unless exists $dep_pattern{$depend};
+
+        # Attempt to match the pattern
+        my $pattern = $dep_pattern{$depend};
+
+        if ($line =~ /$pattern/i) {
+          my $match = $1;
+
+          # $match may contain multiple items delimited by space
+          NAME: for my $name (split /\s+/, $match) {
+            # Skip dependency if it is in the exclusion list
+            my $key = uc ($depend . '::' . $name);
+
+            if (exists $excl_dep{$key}) {
+              # Exclude this dependency, in the global list
+              next NAME if exists $excl_dep{$key}{''};
+
+              # Exclude this dependency, current sub-package
+              for my $pkname (@pknames) {
+                next NAME if exists $excl_dep{$key}{$pkname};
+              }
+            }
+
+            # Add this dependency to the list
+            $self->add_dep ($name, $depend);
+          }
+
+          next LINE;
+        }
+      }
+    }
+
+    # Diagnostic messages
+    if ($self->config->verbose > 2) {
+      my $base = $self->ppsrc ? $self->ppbase : $self->base;
+
+      print $self->srcpackage->name, ': ', $base;
+      print ': scanned ', scalar (@lines), ' lines for ';
+      print 'header ' if $header_only;
+      print 'dependencies: ', scalar (keys %{ $self->{DEP} }), "\n";
+      print timestamp_command ('scan dependency in file: ' . $src, 'End');
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->write_makerule ();
+#
+# DESCRIPTION
+#   This method returns a string containing the "Make" rules for building the
+#   source file.
+# ------------------------------------------------------------------------------
+
+sub write_makerule {
+  my $self = shift;
+
+  my $mk   = '';
+
+  {
+    if ($self->is_type (qw/SOURCE/)) {
+      if ($self->is_type_or (qw/FORTRAN FPP/) and not $self->progname) {
+        last;
+      }
+
+      $mk .= $self->_write_makerule_compile ();
+      $mk .= $self->_write_makerule_touch ('FLAGS');
+
+      if ($self->is_type_or (qw/FPP C/) and not $self->ppsrc) {
+        $mk .= $self->_write_makerule_touch ('PPKEYS');
+      }
+
+      if ($self->is_type ('PROGRAM')) {
+        $mk .= $self->_write_makerule_load ();
+        $mk .= $self->_write_makerule_touch ('LD');
+        $mk .= $self->_write_makerule_touch ('LDFLAGS');
+
+      } else {
+        $mk .= $self->_write_makerule_touch ('DONE');
+      }
+      
+      if ($self->is_type_or (qw/FORTRAN FPP/) and
+          uc ($self->select_tool ('GENINTERFACE')) ne 'NONE' and
+          not $self->is_type_or (qw/PROGRAM MODULE/)) {
+        $mk .= $self->_write_makerule_interface ();
+      }
+
+    } elsif ($self->is_type ('INCLUDE')) {
+      $mk .= $self->_write_makerule_cp ('INC');
+      $mk .= $self->_write_makerule_touch ('IDONE');
+
+    } elsif ($self->is_type_or (qw/EXE SCRIPT/)) {
+      $mk .= $self->_write_makerule_cp ('EXE');
+
+    } elsif ($self->is_type ('LIB')) {
+      $mk .= $self->_write_makerule_ar;
+    }
+  }
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_write_makerule_compile ();
+#
+# DESCRIPTION
+#   This internal method returns a string containing the "Make" rules to
+#   compile the current source file.
+# ------------------------------------------------------------------------------
+
+sub _write_makerule_compile {
+  my $self = shift;
+
+  # Create a target to build an object file from the source file
+  my $base = $self->intname;
+  my $mk   = $base . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+  $mk     .= ' : ' . $self->_makerule_srcfile;
+
+  my $nl   = " \\\n" . ' ' x 10;
+
+  my $type = $self->is_type ('C') ? 'C' : 'F';
+
+  # Depends on the compiler flags dummy file
+  my $flag = $type . 'FLAGS';
+  $mk     .= $nl . join ('__', ($flag, $self->srcpackage->name, $self->root));
+  $mk     .= $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+
+  # Depends on the pre-processor keys dummy file
+  if ($self->is_type_or (qw/C FPP/) and not $self->ppsrc) {
+    my $pp = $type . 'PPKEYS';
+    $mk   .= $nl . join ('__', ($pp, $self->srcpackage->name, $self->root));
+    $mk   .= $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  }
+
+  # Source file dependencies
+  for my $name (sort keys %{ $self->{DEP} }) {
+    # A Fortran 9X module, lower case object file name
+    if ($self->{DEP}{$name} eq 'USE') {
+      (my $root = $name) =~ s/\.\w+$//;
+      $mk .= $nl . lc ($root) . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+
+    # An include file
+    } elsif ($self->{DEP}{$name} =~ /^(?:INC|H|INTERFACE)$/) {
+      $mk .= $nl . $name;
+    }
+  }
+
+  # Action: invoke the compile wrapper
+  $mk .= "\n";
+  $mk .= "\t" . 'fcm_internal compile:' . $type . ' ';
+  $mk .= $self->srcpackage->name . ' $< $@';
+  $mk .= ' 1' if ($self->is_type_or (qw/C FPP/) and not $self->ppsrc);
+  $mk .= "\n";
+  $mk .= "\n";
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_write_makerule_load;
+#
+# DESCRIPTION
+#   This internal method returns a string containing the "Make" rules to
+#   invoke the loader (linker) on the object file of the current source file.
+# ------------------------------------------------------------------------------
+
+sub _write_makerule_load {
+  my $self = shift;
+
+  # Create a target to build an executable from the object file
+  my $target = $self->target;
+  my $mk     = $target . ' : ';
+  my $base   = $self->intname;
+  $mk       .= $base . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+
+  my $nl   = " \\\n" . ' ' x 10;
+
+  # Depends on the loader flags
+  for my $flag (qw/LD LDFLAGS/) {
+    $mk   .= $nl . join ('__', ($flag, $self->srcpackage->name, $self->root));
+    $mk   .= $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  }
+
+  # Depends on BLOCKDATA program units, for Fortran programs
+  my %blockdata      = %{ $self->config->setting ('BLOCKDATA') };
+  my @blockdata_objs = ();
+
+  if ($self->is_type_or (qw/FPP FORTRAN/) and keys %blockdata) {
+    # List of BLOCKDATA object files
+    if (exists $blockdata{$target}) {
+      @blockdata_objs = keys (%{ $blockdata{$target} });
+
+    } elsif (exists $blockdata{''}) {
+      @blockdata_objs = keys (%{ $blockdata{''} });
+    }
+
+    for my $name (@blockdata_objs) {
+      (my $root = $name) =~ s/\.\w+$//;
+      $name = $root . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+      $mk  .= $nl . $root . $self->config->setting (qw/OUTFILE_EXT DONE/);
+    }
+  }
+
+  # Extra executable dependencies
+  my %exe_dep = %{ $self->config->setting ('EXE_DEP') };
+  if (keys %exe_dep) {
+    my @deps;
+    if (exists $exe_dep{$target}) {
+      @deps = keys (%{ $exe_dep{$target} });
+
+    } elsif (exists $exe_dep{''}) {
+      @deps = keys (%{ $exe_dep{''} });
+    }
+
+    my $pattern = '\\' . $self->config->setting (qw/OUTFILE_EXT OBJ/) . '$';
+
+    for my $name (@deps) {
+      if ($name =~ /$pattern/) {
+        # Extra dependency is an object
+        (my $root = $name) =~ s/\.\w+$//;
+        $mk .= $nl . $root . $self->config->setting (qw/OUTFILE_EXT DONE/);
+
+      } else {
+        # Extra dependency is a sub-package
+        my $var;
+        if ($self->config->setting ('FCM_PCK_OBJECTS', $name)) {
+          # sub-package name contains unusual characters
+          $var = $self->config->setting ('FCM_PCK_OBJECTS', $name);
+
+        } else {
+          # sub-package name contains normal characters
+          $var = $name ? join ('__', ('OBJECTS', $name)) : 'OBJECTS';
+        }
+
+        $mk   .= $nl . '$(' . $var . ')';
+      }
+    }
+  }
+
+  # Source file dependencies
+  for my $name (sort keys %{ $self->{DEP} }) {
+    (my $root = $name) =~ s/\.\w+$//;
+
+    # Lowercase name for object dependency
+    $root   = lc ($root) unless $self->{DEP}{$name} =~ /^(?:INC|H)$/;
+
+    # Select "done" file extension
+    if ($self->{DEP}{$name} =~ /^(?:INC|H)$/) {
+      $mk .= $nl . $name . $self->config->setting (qw/OUTFILE_EXT IDONE/);
+
+    } else {
+      $mk .= $nl . $root . $self->config->setting (qw/OUTFILE_EXT DONE/);
+    }
+  }
+
+  # Action: invoke the load wrapper
+  $mk .= "\n";
+  $mk .= "\t" . 'fcm_internal load ' . $self->srcpackage->name . ' $< $@';
+  $mk .= ' ' . join (' ', @blockdata_objs) if @blockdata_objs;
+  $mk .= "\n\n";
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_write_makerule_interface;
+#
+# DESCRIPTION
+#   This internal method returns a string containing the "Make" rules to
+#   update the Fortran 9X interface block target of the current source file.
+# ------------------------------------------------------------------------------
+
+sub _write_makerule_interface {
+  my $self = shift;
+
+  # Create a target to build all targets that are dependencies of the interface
+  # block file of the current source file
+  my $mk = $self->interfacebase;
+  $mk   .= ' :';
+
+  my $nl   = " \\\n" . ' ' x 10;
+
+  # Source file dependencies
+  for my $name (sort keys %{ $self->{DEP} }) {
+    # Depends on Fortran 9X modules
+    $mk .= $nl . lc ($name) . $self->config->setting (qw/OUTFILE_EXT OBJ/)
+      if $self->{DEP}{$name} eq 'USE';
+  }
+
+  $mk .= "\n\n";
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_write_makerule_touch ($type);
+#
+# DESCRIPTION
+#   This internal method returns a string containing the "Make" rules for
+#   updating a dummy file. The argument $type must be set to ensure correct
+#   behaviour. Recognised values for $type are "IDONE", "DONE", "FLAGS",
+#   "LDFLAGS" and "PPKEYS".
+# ------------------------------------------------------------------------------
+
+sub _write_makerule_touch {
+  my $self = shift;
+  my $type = $_[0];
+
+  my $mk;
+  my $target;
+  my $dest;
+  my $flag;
+
+  # Create a target to update the dummy "done" file for the source file
+  if ($type eq 'DONE') {
+    my $base = $self->intname;
+    $target  = $base . $self->config->setting (qw/OUTFILE_EXT DONE/);
+
+  # Create a target to update the dummy "idone" file for the source file
+  } elsif ($type eq 'IDONE') {
+    $target = $self->base . $self->config->setting (qw/OUTFILE_EXT IDONE/);
+
+  # Create a target to update the dummy "flags" file for the source file
+  } else { # if $type =~ /^(?:(?:LD)?FLAGS|PPKEYS)$/
+    my $prefix = $self->is_type ('C') ? 'C' : 'F';
+    $flag      = (index ($type, 'LD') == 0) ? $type : $prefix . $type;
+    $target    = join '__', ($flag, $self->srcpackage->name, $self->root);
+    $target   .= $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  }
+
+  my $nl   = " \\\n" . ' ' x 10;
+
+  # The "done" or "idone" file depends on the "done" and "idone" files of the
+  # source file dependencies. The "done" file is also dependent on the object
+  # file of the source file, whereas the "idone" file is dependent on the source
+  # file itself.
+  if ($type =~ /^I?DONE$/) {
+    my $base = $self->intname;
+    my $dep0 = $type eq 'IDONE'
+               ? $self->base
+               : $base . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+    $dest    = '$(FCM_DONEDIR)';
+    $mk      = $target . ' : ' . $dep0;
+
+    for my $name (sort keys %{ $self->{DEP} }) {
+      (my $root = $name) =~ s/\.\w+$//;
+
+      # Lowercase name for object dependency
+      $root   = lc ($root) unless $self->{DEP}{$name} =~ /^(?:INC|H)$/;
+
+      # Select "done" file extension
+      if ($self->{DEP}{$name} =~ /^(?:INC|H)$/) {
+        $mk .= $nl . $name . $self->config->setting (qw/OUTFILE_EXT IDONE/);
+
+      } else {
+        $mk .= $nl . $root . $self->config->setting (qw/OUTFILE_EXT DONE/);
+      }
+    }
+
+  # The "flags" file for the source file depends on the "flags" file for the
+  # container source package of the source file.
+  } else { # if $type =~ /^(?:(?:LD)?FLAGS|PPKEYS)$/
+    $dest = '$(FCM_FLAGSDIR)';
+    $mk  .= $target . ' : ' . $flag . '__' . $self->srcpackage->name;
+    $mk  .= $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  }
+
+  # Action: invoke the "touch" command
+  $mk .= "\n";
+  $mk .= "\t" . 'touch ' . catfile ($dest, '$@') . "\n";
+  $mk .= "\n";
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_write_makerule_cp ($type);
+#
+# DESCRIPTION
+#   This internal method returns a string containing the "Make" rules for
+#   copying the source file to its destination. The argument $type must be set
+#   to ensure correct behaviour. Recognised values for $type are "INC" and
+#   "EXE".
+# ------------------------------------------------------------------------------
+
+sub _write_makerule_cp {
+  my $self = shift;
+  my $type = $_[0];
+
+  # Create a target to copy the source file to a pre-defined destination
+  my $mk  = $self->base . ' : ' . $self->_makerule_srcfile;
+  my $dest;
+
+  my $nl  = " \\\n" . ' ' x 10;
+
+  # An "include" file goes to the "inc" sub-directory of the build.
+  if ($type eq 'INC') {
+    $dest = '$(FCM_INCDIR)';
+
+    for my $name (sort keys %{ $self->{DEP} }) {
+      # A Fortran 9X module, lower case object file name
+      if ($self->{DEP}{$name} eq 'USE') {
+        (my $root = $name) =~ s/\.\w+$//;
+        $mk .= $nl . lc ($root) . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+
+      # An include file
+      } elsif ($self->{DEP}{$name} =~ /^(?:INC|H|INTERFACE)$/) {
+        $mk .= $nl . $name;
+      }
+    }
+
+  # An executable file goes to the "bin" sub-directory of the build.
+  } else { # if $type eq 'EXE'
+    $dest = '$(FCM_BINDIR)';
+
+    # Depends on dummy copy file, if file is an "always build type"
+    $mk .= $nl . $self->config->setting (qw/MISC CPDUMMY/)
+      if $self->is_type_or (
+        split (/,/, $self->config->setting ('ALWAYS_BUILD_TYPE'))
+      );
+
+    # Depends on other executable files
+    for my $name (sort keys %{ $self->{DEP} }) {
+      $mk .= $nl . $name if $self->{DEP}{$name} eq 'EXE';
+    }
+  }
+
+  # Action: copy file, and chmod to grant write permission to the user
+  $mk .= "\n";
+  $mk .= "\t" . 'cp $< ' . $dest . "\n";
+  $mk .= "\t" . 'chmod u+w ' . catfile ($dest, '$@') . "\n";
+  $mk .= "\n";
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_write_makerule_ar ();
+#
+# DESCRIPTION
+#   This internal method returns a string containing the "Make" rules for
+#   building an object library.
+# ------------------------------------------------------------------------------
+
+sub _write_makerule_ar {
+  my $self = shift;
+
+  # Create a target to build a binary object library
+  my $target = $self->target;
+  my $mk = $target . ' :';
+
+  my $nl = " \\\n" . ' ' x 10;
+
+  # Depends on its member object files
+  for my $name (sort keys %{ $self->{DEP} }) {
+    next unless $self->{DEP}{$name} eq 'OBJ';
+
+    if ($name =~ /^\$\(\w+\)$/) {
+      # Dependency is a Makefile variable
+      $mk .= $nl . $name;
+
+    } else {
+      # Dependency is an object
+      (my $root = $name) =~ s/\.\w+$//;
+      $mk .= $nl . lc ($root) . $self->config->setting (qw/OUTFILE_EXT OBJ/);
+    }
+  }
+
+  # Action: invoke the archiver
+  $mk .= "\n";
+  $mk .= "\t" . 'fcm_internal archive $@ $^' . "\n";
+  $mk .= "\n";
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_makerule_srcfile ();
+#
+# DESCRIPTION
+#   This internal method returns a string containing the location of the
+#   source file relative to a package source path. This string will be
+#   suitable for use in a "Make" rule file for FCM.
+# ------------------------------------------------------------------------------
+
+sub _makerule_srcfile {
+  my $self = shift;
+
+  my $return;
+  my @searchpath;
+  my $label;
+  my $dir;
+  my $base;
+
+  if ($self->ppsrc) {
+    $return     = $self->ppsrc;
+    @searchpath = $self->srcpackage->ppsearchpath;
+    $label      = 'PPSRCDIR';
+    $dir        = $self->ppdir;
+    $base       = $self->ppbase;
+
+  } else {
+    $return     = $self->src;
+    @searchpath = $self->srcpackage->searchpath;
+    $label      = 'SRCDIR';
+    $dir        = $self->dir;
+    $base       = $self->base;
+  }
+
+  $return = catfile $dir, $base;
+
+  # Use variable for directory name
+  # if container package name contains word characters only
+  if ($self->srcpackage->name =~ /^\w+$/) {
+    for my $i (0 .. $#searchpath) {
+      if ($dir eq $searchpath[$i]) {
+        my $returndir = '$(' . $label . $i . '__' . $self->srcpackage->name .
+                        ')';
+        $return = catfile $returndir, $base;
+        last;
+      }
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcPackage.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcPackage.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/SrcPackage.pm	(revision 329)
@@ -0,0 +1,877 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::SrcPackage
+#
+# DESCRIPTION
+#   This is a class to process a source directory package. It uses the
+#   supplied inheritance hierarchy to obtain a list of source files of this
+#   package.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::SrcPackage;
+
+# Standard pragma
+use strict;
+use warnings;
+
+# Standard modules
+use Carp;
+use File::Spec::Functions;
+use File::Basename;
+use File::Path;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::SrcFile;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package = Fcm::SrcPackage->new (
+#     CONFIG     => $config,
+#     NAME       => $name,
+#     CURRENT    => $current,
+#     REQUIREPP  => $requirepp,
+#     NEWPP      => $newpp,
+#     SEARCHPATH => \@path,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::SrcPackage class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   NAME       - name of the source directory package
+#   CURRENT    - package declared in current build?
+#   REQUIREPP  - require pre-processing?
+#   NEWPP      - pre-process option has changed?
+#   SEARCHPATH - search path of files in the source package
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self  = {
+    CONFIG     => exists $args{CONFIG}     ? $args{CONFIG}     : &main::cfg,
+    NAME       => exists $args{NAME}       ? $args{NAME}       : undef,
+    CURRENT    => exists $args{CURRENT}    ? $args{CURRENT}    : undef,
+    REQUIREPP  => exists $args{REQUIREPP}  ? $args{REQUIREPP}  : undef,
+    NEWPP      => exists $args{NEWPP}      ? $args{NEWPP}      : undef,
+    SEARCHPATH => exists $args{SEARCHPATH} ? $args{SEARCHPATH} : [],
+
+    # Reference to Fcm::CfgFile, source package configuration file
+    CFG       => undef,
+
+    # References to Fcm::SrcFile, list of source files
+    SRCFILE   => [],
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $package->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $name = $package->name;
+#   $package->name ($name);
+#
+# DESCRIPTION
+#   This method returns the name of this package. If an argument is specified,
+#   the name is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub name {
+  my $self = shift;
+
+  if (@_) {
+    $self->{NAME} = shift;
+  }
+
+  return $self->{NAME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $package->current;
+#   $package->current ($flag);
+#
+# DESCRIPTION
+#   This method returns the "current" flag of the source package. If an
+#   argument is specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub current {
+  my $self = shift;
+
+  if (@_) {
+    $self->{CURRENT} = shift;
+  }
+
+  return $self->{CURRENT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $package->requirepp;
+#   $package->requirepp ($flag);
+#
+# DESCRIPTION
+#   This method returns the "require PP" flag of the source package. If an
+#   argument is specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub requirepp {
+  my $self = shift;
+
+  if (@_) {
+    $self->{REQUIREPP} = shift;
+  }
+
+  return $self->{REQUIREPP};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $package->newpp;
+#   $package->newpp ($flag);
+#
+# DESCRIPTION
+#   This method returns the flag to denote whether pre-processor option for
+#   this source package has changed. If an argument is specified, the flag is
+#   set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub newpp {
+  my $self = shift;
+
+  if (@_) {
+    $self->{NEWPP} = shift;
+  }
+
+  return $self->{NEWPP};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = $package->cfg;
+#   $package->cfg ($cfgfile);
+#
+# DESCRIPTION
+#   This method returns a reference to a Fcm::CfgFile instance for the source
+#   package configuration file. If an argument is specified, the reference is
+#   set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  my $self = shift;
+
+  if (@_) {
+    $self->{CFG} = $_[0];
+  }
+
+  return $self->{CFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @path = $package->searchpath;
+#   $package->searchpath (@path);
+#
+# DESCRIPTION
+#   This method returns the source file search path associated with this
+#   source package in the current build. If arguments are specified, the
+#   search path is replaced by the array in the argument list.
+# ------------------------------------------------------------------------------
+
+sub searchpath {
+  my $self = shift;
+
+  @{ $self->{SEARCHPATH} } = @_ if @_; 
+
+  return @{ $self->{SEARCHPATH} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @path = $package->ppsearchpath;
+#
+# DESCRIPTION
+#   This method returns the pre-processed source file search path associated
+#   with this source package in the current build.
+# ------------------------------------------------------------------------------
+
+sub ppsearchpath {
+  my $self = shift;
+
+  my @path = ();
+  my @name = split /__/, $self->name;
+
+  for my $ppsrcdir (@{ $self->config->setting (qw/PATH PPSRC/) }) {
+    push @path, catfile ($ppsrcdir, @name);
+  }
+
+  return @path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @srcfile = $package->srcfile;
+#
+# DESCRIPTION
+#   This method returns a list of references to Fcm::SrcFile instances
+#   associated with this package.
+# ------------------------------------------------------------------------------
+
+sub srcfile {
+  my $self = shift;
+
+  return @{ $self->{SRCFILE} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package->update_file_info ();
+#
+# DESCRIPTION
+#   This method updates the source file information of this package. Please
+#   note that information is only updated if the cache file for this package
+#   does not exist. For a package declared in the current build, the
+#   information is also updated if the cache file is out of date.
+# ------------------------------------------------------------------------------
+
+sub update_file_info {
+  my $self      = shift;
+
+  # Check if the cache file exists and up to date
+  my @cachepath = @{ $self->config->setting (qw/PATH CACHE/) };
+  my $cachefile = find_file_in_path ($self->_cache_basename, \@cachepath);
+
+  my $uptodate  = $cachefile ? 1 : 0;
+  if ($uptodate and $self->{CURRENT}) {
+    # Is cache file up to date compared with directory?
+    $uptodate = (stat $cachefile) [9] > (stat $self->{SEARCHPATH}[0]) [9];
+
+    # Is cache file up to date compared with each file?
+    if ($uptodate) {
+      my $dir = $self->{SEARCHPATH}[0];
+
+      if (opendir DIR, $dir) {
+        my @files = map {catfile $dir, $_} grep {!/^\.\.?/} readdir 'DIR';
+        closedir DIR;
+        $uptodate = (grep {(stat $cachefile) [9] > (stat) [9]} @files) ? 1 : 0;
+      }
+    }
+  }
+
+  # Read package source file information if it appears to be up to date
+  $uptodate = $self->_read_file_list_cache ($cachefile) if ($uptodate);
+
+  # Update package source file information if necessary
+  if (not $uptodate) {
+    # Get list of files by searching through the search path
+    my @files = ();
+    for my $dir (@{ $self->{SEARCHPATH} }) {
+      opendir DIR, $dir;
+      while (my $base = readdir 'DIR') {
+        next if $base =~ /^\./;
+
+        my $file = catfile $dir, $base;
+        next if -d $file;
+
+        push @files, $file unless grep {basename ($_) eq $base} @files;
+      }
+      closedir DIR;
+    }
+
+    # Declare new instances of source file objects
+    my @srcfile = ();
+    for my $file (@files) {
+      if (basename ($file) eq $self->config->setting (qw/CFG_NAME SRCPACKAGE/)) {
+        $self->{CFG} = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $file);
+
+      } else {
+        my $srcfile = Fcm::SrcFile->new (
+          CONFIG     => $self->config,
+          SRC        => $file,
+          SRCPACKAGE => $self,
+        );
+
+        # Determine source file types
+        $srcfile->determine_type;
+
+        # Record files of known types
+        push @srcfile, $srcfile;
+      }
+    }
+
+    # Set each SRCFILE to reference the source file instances
+    $self->{SRCFILE} = \@srcfile;
+
+    # Decipher configuration file if necessary
+    $self->_decipher_cfg if $self->cfg;
+
+    # Write to a new cache file
+    $self->_update_file_list_cache ();
+
+    # Source package info updated. Make sure the "current" flag is set to true
+    $self->current (1);
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $up_to_date = $self->_read_file_list_cache ($file);
+#
+# DESCRIPTION
+#   This internal method reads the cache $file of this package and assigns the
+#   information to the SRCFILE list. It returns true if the cache appears to
+#   be up to date.
+# ------------------------------------------------------------------------------
+
+sub _read_file_list_cache {
+  my $self = shift;
+  my $file = shift;
+
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $file);
+
+  # Read from config file
+  $cfg->read_cfg;
+  my @lines = $cfg->lines;
+
+  my %filetype = ();
+  my $uptodate = 1;
+  for my $line (@lines) {
+    next unless $line->{LABEL};
+
+    # On package declared in the current build, check that file is not deleted
+    if (not -f $line->{LABEL}) {
+      $uptodate = 0;
+      last;
+    }
+
+    $filetype{$line->{LABEL}} = $line->{VALUE};
+  }
+
+  # Assign to SRCFILE list if cache file is up to date
+  if ($uptodate) {
+    my @srcfiles = ();
+
+    for my $file (sort keys %filetype) {
+      if ($filetype{$file} eq 'SRCPACKAGECFG') {
+        $self->{CFG} = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $file);
+
+      } else {
+        my $srcfile = Fcm::SrcFile->new (
+          CONFIG     => $self->config,
+          SRC        => $file,
+          TYPE       => $filetype{$file},
+          SRCPACKAGE => $self,
+        );
+
+        push @srcfiles, $srcfile;
+      }
+    }
+
+    $self->{SRCFILE} = [@srcfiles];
+
+    $self->_decipher_cfg if $self->cfg;
+  }
+
+  return $uptodate;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_file_list_cache (\@cachepath);
+#
+# DESCRIPTION
+#   This internal method updates the cache file of this package by writing
+#   current SRCFILE information to it. The argument @cachepath must be the
+#   search path of the build cache directory.
+# ------------------------------------------------------------------------------
+
+sub _update_file_list_cache {
+  my $self      = shift;
+  my @cachepath = @{ $self->config->setting (qw/PATH CACHE/) };
+
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+  if ($self->{CFG}) {
+    $cfg->add_line (LABEL => $self->cfg->src, VALUE => 'SRCPACKAGECFG')
+  }
+
+  for my $file (@{ $self->{SRCFILE} }) {
+    $cfg->add_line (LABEL => $file->src, VALUE => $file->type);
+  }
+
+  my $cachefile = catfile $cachepath[0], $self->_cache_basename;
+  $cfg->print_cfg ($cachefile);
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $basename = $self->_cache_basename ($type);
+#
+# DESCRIPTION
+#   This internal method returns the basename of a cache file for this
+#   package. If no argument is specified, it returns the package file list
+#   cache name. Otherwise, it returns the package file dependency cache name.
+# ------------------------------------------------------------------------------
+
+sub _cache_basename {
+  my $self = shift;
+  my $type = $_[0] ? $_[0] : 'PCKFILE';
+
+  return $self->{NAME} . $self->config->setting ('CACHE', $type);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_decipher_cfg ();
+#
+# DESCRIPTION
+#   This internal method deciphers the CFG file associated with this source
+#   package.
+# ------------------------------------------------------------------------------
+
+sub _decipher_cfg {
+  my $self = shift;
+
+  $self->cfg->read_cfg;
+  my @lines = $self->cfg->lines;
+
+  my %cfg_label = %{ $self->config->setting ('CFG_LABEL') };
+
+  LINE: for my $line (@lines) {
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next unless $label;
+    next if uc $label eq $cfg_label{CFGFILE}{TYPE};
+    next if uc $label eq $cfg_label{CFGFILE}{VERSION};
+
+    my ($prefix, $name) = split /::/, $label;
+
+    # Get name of file from the package cfg
+    my $srcfile;
+    if ($name) {
+      ($srcfile) = grep {$_->base eq $name} @{ $self->{SRCFILE} };
+
+      # Create new instance of Fcm::SrcFile if not already in package
+      if (not $srcfile) {
+        my $src    = find_file_in_path ($name, $self->{SEARCHPATH});
+        my $target = $name unless $src;
+
+        $srcfile   = Fcm::SrcFile->new (
+          CONFIG     => $self->config,
+          SRCPACKAGE => $self,
+          SRC        => $src ? $src : $name,
+          TARGET     => $target,
+          PCKCFG     => 1,
+        );
+        push @{ $self->{SRCFILE} }, $srcfile;
+
+      } else {
+        $srcfile->pckcfg (1);
+      }
+
+    } else {
+      w_report 'Warning: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+               ': label "', $label, '" not recognised.';
+      next LINE;
+    }
+
+    $prefix = uc $prefix;
+    if ($prefix eq $cfg_label{TYPE}) {
+      # Type label of source file
+      $srcfile->type (uc $value);
+      $srcfile->scan (0) if $srcfile->is_type (qw/BINARY LIB/);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{SCAN}) {
+      # Scan original file for dependency?
+      $srcfile->scan ($value);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{TARGET}) {
+      # Name of build target for this source file
+      $srcfile->target ($value);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{INTNAME}) {
+      # Program unit name of this source file
+      $srcfile->progname ($value);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{DEP}) {
+      # Dependency of this source file
+      my ($type, $target) = split /::/, $value;
+      $srcfile->add_dep ($target, uc $type);
+      next LINE;
+
+    } else {
+      w_report 'Warning: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+               ': label "', $label, '" not recognised.';
+      next LINE;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package->scan_dependency ();
+#   $package->scan_dependency (HEADER_ONLY => 1);
+#
+# DESCRIPTION
+#   This method scans the dependency in each source file in this source
+#   package and updates the package dependency cache. If HEADER_ONLY is
+#   specified, it performs dependency scan for pre-processor headers only if
+#   this source package requires pre-processing.
+# ------------------------------------------------------------------------------
+
+sub scan_dependency {
+  my $self = shift;
+  my %args = @_;
+
+  # Search for include header dependencies only
+  my $header_only = exists $args{HEADER_ONLY} ? $args{HEADER_ONLY} : 0;
+
+  # Get list of source files
+  # If header dependencies only, only consider FPP, C and CPP files
+  my @srcfiles = $header_only
+                 ? grep {$_->is_type_or (qw/FPP C CPP/)} $self->srcfile
+                 : grep {$_->type} $self->srcfile;
+  return unless @srcfiles;
+
+  # Location of the cache
+  my @cachepath = @{ $self->config->setting (qw/PATH CACHE/) };
+  my $cachebase = $header_only
+                  ? $self->_cache_basename ('PCKPPDEPEND')
+                  : $self->_cache_basename ('PCKDEPEND');
+  my $cachefile = find_file_in_path ($cachebase, \@cachepath);
+
+  # Obtain old dependency information from cache file if it exists
+  my %dep     = ();
+  my %intname = ();
+
+  if ($cachefile) {
+    # Read the cache
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $cachefile);
+    $cfg->read_cfg;
+    my @lines = $cfg->lines;
+
+    # Get list of source file base names
+    my %srcfilebase;
+    for (@srcfiles) {
+      my $base = $_->ppsrc ? $_->ppbase : $_->base;
+      $srcfilebase{$base} = 1;
+    }
+
+    for my $line (@lines) {
+      next unless $line->{LABEL};
+
+      # Label is either INTNAME or a dependency type name
+      # For INTNAME, value is the program unit name
+      # Otherwise, value is file::dependency
+      my $type = $line->{LABEL};
+      (my $file, my $depend) = split /::/, $line->{VALUE};
+
+      # Make sure $file exists in the list of source file base names
+      next unless exists $srcfilebase{$file};
+
+      if ($type eq 'INTNAME') {
+        $intname{$file} = $depend;
+
+      } else {
+        $dep{$file}{$depend} = $type;
+      }
+    }
+  }
+
+  # If a source file is newer than the cache file, re-scan dependency for that
+  # source file.
+  my $uptodate        = $cachefile ? 1 : 0;
+  my $cachefile_mtime = $cachefile ? (stat $cachefile) [9] : undef;
+  my $count           = 0;
+
+  for my $srcfile (@srcfiles) {
+    # Check modified time of source file
+    my $srcfile_mtime = $srcfile->mtime;
+
+    # If a package config file exists and it affects the source file,
+    # compare its timestamp with that of the source file
+    if ($srcfile->pckcfg) {
+      $srcfile_mtime = $self->cfg->mtime if not defined $srcfile_mtime;
+      $srcfile_mtime = ($self->cfg->mtime > $srcfile_mtime) ? $self->cfg->mtime
+                                                            : $srcfile_mtime;
+    }
+
+    # For files requiring PP, must re-scan if PP option has changed
+    my $rescan = ($self->newpp and $srcfile->is_type_or (qw/FPP C/)) ? 1 : 0;
+
+    if ($cachefile_mtime and $cachefile_mtime > $srcfile_mtime and ! $rescan) {
+      # No need to re-scan dependency, read dependency from cache
+      my $base = ($srcfile->ppsrc ? $srcfile->ppbase : $srcfile->base);
+
+      $srcfile->progname ($intname{$base}) if $intname{$base};
+      $srcfile->dep ($dep{$base})          if $dep{$base};
+
+    } else {
+      # Rescan dependency
+      $srcfile->progname (undef);
+      my $rc = $srcfile->scan_dependency (HEADER_ONLY => $header_only);
+      my %dp = $srcfile->dep;
+
+      # Get list of dependencies for updating the cache
+      my $base = ($srcfile->ppsrc ? $srcfile->ppbase : $srcfile->base);
+
+      $intname{$base} = $srcfile->progname;
+      $dep    {$base} = \%dp;
+
+      $uptodate = 0;
+      $count++ if $rc;
+    }
+  }
+
+  # Output diagnostic, if necessary
+  if ($self->config->verbose > 1 and $count) {
+    my $out =  $self->name . ': scanned ' . $count . ' file(s) for';
+    $out   .= ' header' if $header_only;
+    $out   .= ' dependency' . "\n";
+    print $out;
+  }
+
+  # Check whether package config file is newer than the dependency cache
+  if ($uptodate and $self->cfg) {
+    $uptodate = $cachefile_mtime > $self->cfg->mtime ? 1 : 0;
+  }
+
+  if (not $uptodate) {
+    # Update dependency cache file
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+    # Program unit name of source files
+    for my $file (keys %intname) {
+      next unless $intname{$file};
+
+      $cfg->add_line (
+        LABEL => 'INTNAME',
+        VALUE => $file . '::' . $intname{$file},
+      );
+    }
+
+    # Dependencies of source files
+    for my $file (keys %dep) {
+      for my $depend (keys %{ $dep{$file} }) {
+        $cfg->add_line (
+          LABEL => $dep{$file}{$depend},
+          VALUE => $file . '::' . $depend,
+        );
+      }
+    }
+
+    # Create an empty config file if no dependency in this source package
+    $cfg->add_line unless $cfg->lines;
+
+    # Write to config file
+    my $outfile = catfile $cachepath[0], $cachebase;
+    $cfg->print_cfg ($outfile);
+  }
+
+  return not $uptodate;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $package->makerule_uptodate ();
+#
+# DESCRIPTION
+#   This method returns true if the make rule file for this source package
+#   is up to date.
+# ------------------------------------------------------------------------------
+
+sub makerule_uptodate {
+  my $self = shift;
+
+  my $return = 0;
+
+  if (not $self->newpp) {
+    # Check whether a Make rule file already exists
+    my $mkbase = $self->name . $self->config->setting (qw/OUTFILE_EXT MK/);
+    my $mkfile = find_file_in_path (
+      $mkbase,
+      $self->config->setting (qw/PATH BLD/),
+    );
+
+    # Check location of source package file type cache
+    my $pckfile = find_file_in_path (
+      $self->_cache_basename ('PCKFILE'),
+      $self->config->setting (qw/PATH CACHE/),
+    );
+
+    # Check location of source package dependency cache
+    my $pckdepend = find_file_in_path (
+      $self->_cache_basename ('PCKDEPEND'),
+      $self->config->setting (qw/PATH CACHE/),
+    );
+
+    # If make rule file exists, determine whether it is out of date
+    if ($pckdepend) {
+      if ($mkfile) {
+        my $pckfile_mt   = (stat $pckfile)  [9];
+        my $pckdepend_mt = (stat $pckdepend)[9];
+        my $mkfile_mt    = (stat $mkfile)   [9];
+
+        $return = 1 if $mkfile_mt >= $pckdepend_mt and $mkfile_mt >= $pckfile_mt;
+      }
+
+    } else {
+      $return = 1; # No cache file, no need to have a make rule
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package->write_makerule ();
+#
+# DESCRIPTION
+#   This method writes to the I<Make> rule file of the current source package.
+# ------------------------------------------------------------------------------
+
+sub write_makerule {
+  my $self = shift;
+
+  # Package Make rule header
+  my $mk = '# Automatic Make rule for ' . $self->name . "\n\n";
+
+  # Set up variable for directory name
+  # if package name contains only word characters
+  my @searchpath   = ();
+  my @ppsearchpath = ();
+  if ($self->name =~ /^\w+$/) {
+    # Package search path
+    @searchpath = $self->searchpath;
+    for my $i (0 .. $#searchpath) {
+      $mk .= 'SRCDIR' . $i . '__' . $self->name . ' = ' . $searchpath[$i];
+      $mk .= "\n";
+    }
+    $mk .= "\n" if @searchpath;
+
+    # Package PP search path
+    @ppsearchpath = $self->ppsearchpath;
+    for my $i (0 .. $#ppsearchpath) {
+      next unless -d $ppsearchpath[$i];
+      $mk .= 'PPSRCDIR' . $i . '__' . $self->name . ' = ' . $ppsearchpath[$i];
+      $mk .= "\n";
+    }
+    $mk .= "\n" if @ppsearchpath;
+  }
+
+  my $mk_out;
+
+  # Make rules for copying data files, if necessary
+  {
+    # Get a list of files with no associated type
+    my @files = grep {not $_->type} @{ $self->{SRCFILE} };
+
+    if (@files) {
+      my $target = $self->name . $self->config->setting (qw/OUTFILE_EXT ETC/);
+      $mk_out .= $target . ' :';
+
+      # Depends on all un-typed source files
+      my $nl = " \\\n" . ' ' x 10;
+      for my $file (@files) {
+        my $dir = $file->dir;
+
+        # Use variable for directory name
+        # if package name contains only word characters
+        if ($self->name =~ /^\w+$/) {
+          for my $i (0 .. $#searchpath) {
+            if ($dir eq $searchpath[$i]) {
+              $dir = '$(SRCDIR' . $i . '__' . $self->name . ')';
+              last;
+            }
+          }
+        }
+
+        $mk_out .= $nl . catfile ($dir, $file->base);
+      }
+
+      # Depends on dummy copy file, so there will be no dependency inheritance
+      $mk_out .= $nl . $self->config->setting (qw/MISC CPDUMMY/);
+
+      # Actions for target
+      $mk_out .= "\n";
+      $mk_out .= "\t" . 'cp $^ $(FCM_ETCDIR)' . "\n";
+      $mk_out .= "\t" . 'touch ' . catfile ('$(FCM_DONEDIR)', '$@') . "\n";
+
+      $mk_out .= "\n";
+    }
+  }
+
+  # Make rules for source files
+  my @srcfiles = grep {$_->type} @{ $self->{SRCFILE} };
+  for my $srcfile (@srcfiles) {
+    $mk_out .= $srcfile->write_makerule;
+  }
+
+  # Write make rule file only if necessary
+  if ($mk_out) {
+    $mk .= $mk_out;
+
+    # Write to output file
+    my $mkbase = $self->name . $self->config->setting (qw/OUTFILE_EXT MK/);
+    my $blddir = ${ $self->config->setting (qw/PATH BLD/) }[0];
+    my $mkfile = catfile $blddir, $mkbase;
+
+    if (not -d $blddir) {
+      print 'Make directory: ', $blddir, "\n" if $self->config->verbose > 1;
+      mkpath $blddir or croak $blddir, ': cannot create directory, abort';
+    }
+
+    open OUT, '>', $mkfile
+      or croak 'Cannot open "', $mkfile, '" (', $!, '), abort';
+    print OUT $mk;
+    close OUT or croak 'Cannot close "', $mkfile, '" (', $!, '), abort';
+
+    print 'Generated: ', $mkfile, "\n" if $self->config->verbose > 1;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Timer.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Timer.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Timer.pm	(revision 329)
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Timer
+#
+# DESCRIPTION
+#   This is a package of timer utility used by the FCM command.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Timer;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Exports
+our (@ISA, @EXPORT, @EXPORT_OK);
+
+sub timestamp_command;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(timestamp_command);
+
+# ------------------------------------------------------------------------------
+
+# Module level variables
+my %cmd_start_time = (); # Command start time, (key = command, value = time)
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &Fcm::Timer::timestamp_command ($command[, $status]);
+#
+# DESCRIPTION
+#   This function returns a string adding to $command a prefix according the
+#   value of $status. If $status is not specified or does not match the word
+#   "end", the status is assumed to be "start". At "start", the prefix will
+#   contain the current timestamp. If $status is the word "end", the prefix
+#   will contain the total time taken since this function was called with the
+#   same $command at the "start" status.
+# ------------------------------------------------------------------------------
+
+sub timestamp_command {
+  (my $command, my $status) = @_;
+
+  my $prefix;
+  if ($status and $status =~ /end/i) {
+    # Status is "end", insert time taken
+    my $lapse = time () - $cmd_start_time{$command};
+    $prefix = sprintf "# Time taken: %12d s=> ", $lapse;
+
+  } else {
+    # Status is "start", insert time stamp
+    $cmd_start_time{$command} = time;
+
+    (my $sec, my $min, my $hour, my $mday, my $mon, my $year) = localtime;
+    $prefix = sprintf "# Start: %04d-%02d-%02d %02d:%02d:%02d=> ",
+              $year + 1900, $mon + 1, $mday, $hour, $min, $sec;
+  }
+
+  return $prefix . $command . "\n";
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Util.pm
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Util.pm	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/lib/Fcm/Util.pm	(revision 329)
@@ -0,0 +1,802 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Util
+#
+# DESCRIPTION
+#   This is a package of misc utilities used by the FCM command.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Util;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Exports
+our (@ISA, @EXPORT, @EXPORT_OK);
+
+sub expand_rev_keyword;
+sub expand_tilde;
+sub expand_url_keyword;
+sub e_report;
+sub find_srcdir;
+sub find_file_in_path;
+sub get_browser_url;
+sub get_command_string;
+sub get_rev_of_wc;
+sub get_rev_keyword;
+sub get_url_of_wc;
+sub get_wct;
+sub is_url;
+sub is_wc;
+sub print_command;
+sub run_command;
+sub svn_date;
+sub touch_file;
+sub w_report;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(
+  expand_rev_keyword
+  expand_tilde
+  expand_url_keyword
+  e_report
+  find_srcdir
+  find_file_in_path
+  get_browser_url
+  get_command_string
+  get_rev_of_wc
+  get_rev_keyword
+  get_url_of_wc
+  get_wct
+  is_url
+  is_wc
+  print_command
+  run_command
+  svn_date
+  touch_file
+  w_report
+);
+
+# Standard modules
+use Carp;
+use Cwd;
+use File::Basename;
+use File::Find;
+use File::Path;
+use File::Spec;
+use POSIX qw/strftime/;
+
+# FCM component modules
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+
+# Module level variables
+my %svn_info       = (); # "svn info" log, (key1 = path,
+                         # key2 = URL, Revision, Last Changed Rev)
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %srcdir = &Fcm::Util::find_srcdir ($topdir, $toppck, $join);
+#
+# DESCRIPTION
+#   Search $topdir for sub-directories containing regular files. Returns a hash
+#   with each key/value pair assigned to a unique name of the source directory
+#   and the location of the source directory. If $toppck is set the name of
+#   each source directory will be prefixed with this package name, and the
+#   search may include the $topdir in the result. If $join is set, the name of
+#   the sub-package will use $join as the delimiter of packages. Otherwise, the
+#   default double underscore '__' will be used.  Please note that all
+#   directories beginning with a ".", i.e. hidden directories, are ignored.
+# ------------------------------------------------------------------------------
+
+sub find_srcdir {
+  (my $topdir, my $toppck, my $join) = @_;
+  $join = defined ($join) ? $join : '__';
+
+  my @dirs = ();
+
+  # Locate all source directories containing regular files
+  if (-d $topdir) {
+    find (
+      sub {
+        my $dir = $File::Find::name;
+        return 0 if $dir eq $topdir and not $toppck;
+
+        if (-d $dir) {
+          # Ignore sub-directories with names beginning with .
+          if ($dir ne $topdir) {
+            my $subdir = substr ($dir, length ($topdir) + 1);
+            return 0 if grep {m/^\./} File::Spec->splitdir ($subdir);
+          }
+
+          # Read contents of directory
+          opendir DIR, $dir;
+          my @files = readdir 'DIR';
+          closedir DIR;
+
+          # Check if the directory contains one or more source file
+          my $contain_src;
+          for my $file (@files) {
+            next if $file =~ /^\./; # ignore hidden file
+
+            if (-f File::Spec->catfile ($dir, $file)) {
+              $contain_src = 1;
+              last;
+            }
+          }
+
+          push @dirs, $dir if $contain_src;
+          return 1;
+
+        } else {
+          return 0;
+        }
+      },
+
+      $topdir,
+    );
+  }
+
+  # String length of src directory name
+  my $topdir_len = length $topdir;
+
+  # Assign new source directories to current build
+  my @pck    = $toppck ? split (/$join/, $toppck) : ();
+  my %srcdir = ();
+  for my $dir (@dirs) {
+    my $name = ($dir eq $topdir) ? '' : substr $dir, $topdir_len + 1;
+    my @path = File::Spec->splitdir ($name);
+    my $key  = join $join, (@pck, @path);
+
+    $srcdir{$key} = $dir;
+  }
+
+  return %srcdir;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %srcdir = &Fcm::Util::find_file_in_path ($file, \@path);
+#
+# DESCRIPTION
+#   Search $file in @path. Returns the full path of the $file if it is found
+#   in @path. Returns "undef" if $file is not found in @path.
+# ------------------------------------------------------------------------------
+
+sub find_file_in_path {
+  my ($file, $path) = @_;
+
+  for my $dir (@$path) {
+    my $full_file = File::Spec->catfile ($dir, $file);
+    return $full_file if -e $full_file;
+  }
+
+  return undef;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $expanded_path = &Fcm::Util::expand_tilde ($path);
+#
+# DESCRIPTION
+#   Returns an expanded path if $path is a path that begins with a tilde (~).
+# ------------------------------------------------------------------------------
+
+sub expand_tilde {
+  my $file = $_[0];
+
+  $file =~ s#^~([^/]*)#$1 ? (getpwnam $1)[7] : ($ENV{HOME} || $ENV{LOGDIR})#ex;
+
+  return $file;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &Fcm::Util::touch_file ($file);
+#
+# DESCRIPTION
+#   Touch $file if it exists. Create $file if it does not exist. Return 1 for
+#   success or 0 otherwise.
+# ------------------------------------------------------------------------------
+
+sub touch_file {
+  my $file = $_[0];
+  my $rc   = 1;
+
+  if (-e $file) {
+    my $now = time;
+    $rc = utime $now, $now, $file;
+
+  } else {
+    mkpath dirname ($file) unless -d dirname ($file);
+
+    $rc = open FILE, '>', $file;
+    $rc = close FILE if $rc;
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $new_url = &Fcm::Util::expand_url_keyword (URL => $url[, CFG => $cfg]);
+#
+# DESCRIPTION
+#   Expand URL if its begins with a pre-defined pattern followed by a keyword
+#   that can be found in the setting of CFG. If URL is a genuine URL, the
+#   function also attempts to expand any . or .. in the path. If CFG is not
+#   set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub expand_url_keyword {
+  my %args = @_;
+  my $url  = $args{URL};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  # URL keyword prefix and pattern
+  my $prefix  = $cfg->setting (qw/MISC EXPURL_PREFIX/);
+  my $pattern = '^' . $prefix . '(\w+)';
+
+  # URL matches pattern?
+  if ($url =~ /$pattern/) {
+    my $keyword = $1;
+
+    # Determine whether keyword is registered. If so, expand keyword
+    my $keyval = $cfg->setting ('REPOS', uc ($keyword));
+    $url =~ s/$pattern/$keyval/ if $keyval;
+  }
+
+  # Expand . and ..
+  if (&is_url ($url)) {
+    while ($url =~ s#/\.(?:/|$)#/#g) {next}
+    while ($url =~ s#/[^/]+/\.\.(?:/|$)#/#g) {next}
+  }
+
+  return $url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $new_rev = &Fcm::Util::expand_rev_keyword (
+#     REV  => $rev,
+#     URL  => $url,
+#    [HEAD => $flag,]
+#    [CFG  => $cfg,]
+#  );
+#
+# DESCRIPTION
+#   Expand REV if URL is a known URL in CFG setting and REV matches a revision
+#   keyword of this URL, or if REV is "HEAD". SVN revision numbers, date and
+#   other keywords are ignored. HEAD should only be specified if REV has the
+#   value "HEAD". If HEAD is specified and is true, the return value of the
+#   function will be the operative revision number of the HEAD revision.
+#   Otherwise, the last commit revision will be returned. If CFG is not set,
+#   it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub expand_rev_keyword {
+  my %args = @_;
+  my $rev  = $args{REV};
+  my $url  = $args{URL};
+  my $head = exists $args{HEAD} ? $args{HEAD} : undef;
+  my $cfg  = exists $args{CFG } ? $args{CFG } : &main::cfg;
+
+  if (uc ($rev) eq 'HEAD') {
+    # Expand HEAD revision
+    &_invoke_svn_info (PATH => $url, CFG => $cfg) unless exists $svn_info{$url};
+    my $expanded_rev = $head
+                     ? $svn_info{$url}{Revision}
+                     : $svn_info{$url}{'Last Changed Rev'};
+
+    &w_report ($url, ': cannot determine HEAD revision.')
+      if $cfg->verbose > 1 and not $expanded_rev;
+
+    $rev = $expanded_rev if $expanded_rev;
+
+  } elsif ($rev !~ /^(?:\d+|BASE|COMMITTED|PREV|\{.+\})$/i) {
+    # Expand revision keyword, if required
+
+    # Get configuration settings
+    my %keywords  = %{ $cfg->setting (qw/REVISION/) };
+    my $separator = $cfg->setting (qw/MISC DIR_SEPARATOR/);
+
+    my $name      = '';
+
+    # Find out whether URL matches a registered repository
+    for my $keyword (keys %keywords) {
+      my $repos = $cfg->setting ('REPOS', uc ($keyword));
+      next unless $repos;
+
+      if ($url =~ m#^$repos(?:$separator|$)#) {
+        $name = $keyword;
+        last;
+      }
+    }
+
+    # If revision keyword exists for the registered repository, expand it
+    if ($name and exists $keywords{$name}{uc ($rev)}) {
+      $rev = $keywords{$name}{uc ($rev)};
+
+    } else {
+      &e_report (
+        $rev, ': revision keyword not found for ', $url,
+        ' in FCM configuration file, abort.',
+      );
+    }
+  }
+
+  return $rev;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $keyword = Fcm::Util::get_rev_keyword (
+#     REV => $rev,
+#     URL => $url,
+#    [CFG => $cfg,]
+#  );
+#
+# DESCRIPTION
+#   Returns a revision keyword if URL is a known URL in CFG setting and REV is
+#   a revision number that matches a revision keyword of this URL. Otherwise,
+#   it returns REV unchanged. If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub get_rev_keyword {
+  my %args = @_;
+  my $rev  = $args{REV};
+  my $url  = $args{URL};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  if ($rev =~ /^\d+$/) {
+    # Get revision keyword, if REV is a revision number
+
+    # Get configuration settings
+    my %keywords  = %{ $cfg->setting (qw/REVISION/) };
+    my $separator = $cfg->setting (qw/MISC DIR_SEPARATOR/);
+
+    my $name      = '';
+
+    # Find out whether URL matches a registered repository
+    for my $keyword (keys %keywords) {
+      my $repos = $cfg->setting ('REPOS', uc ($keyword));
+      next unless $repos;
+
+      if ($url =~ m#^$repos(?:$separator|$)#) {
+        $name = $keyword;
+        last;
+      }
+    }
+
+    # If revision keyword for REV exists for the registered repository, get it
+    if ($name and exists $keywords{$name} and ref $keywords{$name} eq 'HASH') {
+      for my $key (keys %{ $keywords{$name} }) {
+        if ($rev eq $keywords{$name}{$key}) {
+          $rev = $key;
+          last;
+        }
+      }
+    }
+  }
+
+  return $rev;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $browser_url = Fcm::Util::get_browser_url (
+#     URL => $url,
+#    [CFG => $cfg,]
+#  );
+#
+# DESCRIPTION
+#   Returns a web address for browsing URL from Trac if URL is a known URL in
+#   CFG setting, and that it is a matching web address. Otherwise, it returns
+#   "undef". If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub get_browser_url {
+  my %args        = @_;
+  my $url         = $args{URL};
+  my $cfg         = exists $args{CFG} ? $args{CFG} : &main::cfg;
+  my $browser_url = undef;
+
+  # Get configuration settings
+  my %keywords  = %{ $cfg->setting (qw/TRAC/) };
+  my $separator = $cfg->setting (qw/MISC DIR_SEPARATOR/);
+
+  my $name  = '';
+  my $trail = '';
+
+  # Find out whether URL matches a registered repository
+  for my $keyword (keys %keywords) {
+    my $repos = $cfg->setting ('REPOS', uc ($keyword));
+    next unless $repos;
+
+    if ($url =~ m#^$repos(?:$separator(.*$)|$)#) {
+      $name  = $keyword;
+      $trail = $1 if $1;
+      last;
+    }
+  }
+
+  # If TRAC web address exists for the registered repository, get it
+  if ($name and exists $keywords{$name}) {
+    $browser_url  = $keywords{$name};
+    $browser_url .= $separator . $trail if $trail;
+  }
+
+  return $browser_url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = &is_wc ([$path]);
+#
+# DESCRIPTION
+#   Returns true if current working directory (or $path) is a Subversion
+#   working copy.
+# ------------------------------------------------------------------------------
+
+sub is_wc {
+  my $path = @_ ? $_[0] : cwd ();
+
+  if (-d $path) {
+    return (-e File::Spec->catfile ($path, qw/.svn format/)) ? 1 : 0;
+
+  } elsif (-f $path) {
+    return (-e File::Spec->catfile (dirname ($path), qw/.svn format/)) ? 1 : 0;
+
+  } else {
+    return 0;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = &is_url ($url);
+#
+# DESCRIPTION
+#   Returns true if $url is a URL.
+# ------------------------------------------------------------------------------
+
+sub is_url {
+  # This should handle URL beginning with svn://, http:// and svn+ssh://
+  return ($_[0] =~ m#^[\+\w]+://#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &get_wct ([$dir]);
+#
+# DESCRIPTION
+#   If current working directory (or $dir) is a Subversion working copy,
+#   returns the top directory of this working copy; otherwise returns an empty
+#   string.
+# ------------------------------------------------------------------------------
+
+sub get_wct {
+  my $dir = @_ ? $_[0] : cwd ();
+
+  return '' if not &is_wc ($dir);
+
+  my $updir = dirname $dir;
+  while (&is_wc ($updir)) {
+    $dir   = $updir;
+    $updir = dirname $dir;
+    last if $updir eq $dir;
+  }
+
+  return $dir;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &get_url_of_wc ([$path[, $refresh]]);
+#
+# DESCRIPTION
+#   If current working directory (or $path) is a Subversion working copy,
+#   returns the URL of the associated Subversion repository; otherwise returns
+#   an empty string. If $refresh is specified, do not use the cached
+#   information.
+# ------------------------------------------------------------------------------
+
+sub get_url_of_wc {
+  my $path    = @_ ? $_[0] : cwd ();
+  my $refresh = exists $_[1] ? $_[1] : 0;
+  my $url  = '';
+
+  if (&is_wc ($path)) {
+    delete $svn_info{$path} if $refresh;
+    &_invoke_svn_info (PATH => $path) unless exists $svn_info{$path};
+    $url = $svn_info{$path}{URL};
+  }
+
+  return $url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &_invoke_svn_info (PATH => $path, [CFG => $cfg]);
+#
+# DESCRIPTION
+#   The function is internal to this module. It invokes "svn info" on $path to
+#   gather information on URL, Revision and Last Changed Rev. The information
+#   is stored in a hash table at the module level, so that the information can
+#   be re-used. If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub _invoke_svn_info {
+  my %args = @_;
+  my $path = $args{PATH};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  return if exists $svn_info{$path};
+
+  # Invoke "svn info" command
+  my @info = &run_command (
+    [qw/svn info/, $path],
+    PRINT => $cfg->verbose > 2, METHOD => 'qx', DEVNULL => 1, ERROR => 'ignore',
+  );
+  for (@info) {
+    chomp;
+
+    if (/^(URL|Revision|Last Changed Rev):\s*(.+)$/) {
+      $svn_info{$path}{$1} = $2;
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &get_command_string ($cmd);
+#   $string = &get_command_string (\@cmd);
+#
+# DESCRIPTION
+#   The function returns a string by converting the list in @cmd or the scalar
+#   $cmd to a form, where it can be executed as a shell command.
+# ------------------------------------------------------------------------------
+
+sub get_command_string {
+  my $cmd    = $_[0];
+  my $return = '';
+
+  if (ref ($cmd) and ref ($cmd) eq 'ARRAY') {
+    # $cmd is a reference to an array
+
+    # Print each argument
+    for my $i (0 .. @{ $cmd } - 1) {
+      my $arg = $cmd->[$i];
+
+      $arg =~ s/./*/g if $i > 0 and $cmd->[$i - 1] eq '--password';
+
+      if ($arg =~ /[\s'"*?]/) {
+        # Argument contains a space, quote it
+        if (index ($arg, "'") >= 0) {
+          # Argument contains an apostrophe, quote it with double quotes
+          $return .= ($i > 0 ? ' ' : '') . '"' . $arg . '"';
+
+        } else {
+          # Otherwise, quote argument with apostrophes
+          $return .= ($i > 0 ? ' ' : '') . "'" . $arg . "'";
+        }
+
+      } else {
+        # Argument does not contain a space, just print it
+        $return .= ($i > 0 ? ' ' : '') . ($arg eq '' ? "''" : $arg);
+      }
+    }
+
+  } else {
+    # $cmd is a scalar, just print it "as is"
+    $return = $cmd;
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &print_command ($cmd);
+#   &print_command (\@cmd);
+#
+# DESCRIPTION
+#   The function prints the list in @cmd or the scalar $cmd, as it would be
+#   executed by the shell.
+# ------------------------------------------------------------------------------
+
+sub print_command {
+  my $cmd = $_[0];
+
+  print '=> ', &get_command_string ($cmd) , "\n";
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @return = &run_command (\@cmd, <OPTIONS>);
+#   @return = &run_command ($cmd , <OPTIONS>);
+#
+# DESCRIPTION
+#   This function executes the command in the list @cmd or in the scalar $cmd.
+#   The remaining are optional arguments in a hash table. Valid options are
+#   listed below. If the command is run using "qx", the function returns the
+#   standard output from the command. If the command is run using "system", the
+#   function returns true on success. By default, the function dies on failure.
+#
+# OPTIONS
+#   METHOD  => $method - this can be "system", "exec" or "qx". This determines
+#                        how the command will be executed. If not set, the
+#                        default is to run the command with "system".
+#   PRINT   => 1       - if set, print the command before executing it.
+#   ERROR   => $flag   - this should only be set if METHOD is set to "system"
+#                        or "qx". The $flag can be "die" (default), "warn" or
+#                        "ignore". If set to "die", the function dies on error.
+#                        If set to "warn", the function issues a warning on
+#                        error, and the function returns false. If set to
+#                        "ignore", the function returns false on error.
+#   RC      => 1       - if set, must be a reference to a scalar, which will be
+#                        set to the return code of the command.
+#   DEVNULL => 1       - if set, re-direct STDERR to /dev/null before running
+#                        the command.
+#   TIME    => 1       - if set, print the command with a timestamp before
+#                        executing it, and print the time taken when it
+#                        completes. This option supersedes the PRINT option.
+# ------------------------------------------------------------------------------
+
+sub run_command {
+  my $cmd     = shift;
+  my %options = @_;
+  my $method  = exists $options{METHOD}  ? $options{METHOD}  : 'system';
+  my $print   = exists $options{PRINT}   ? $options{PRINT}   : undef;
+  my $error   = exists $options{ERROR}   ? $options{ERROR}   : 'die';
+  my $rc      = exists $options{RC}      ? $options{RC}      : undef;
+  my $devnull = exists $options{DEVNULL} ? $options{DEVNULL} : undef;
+  my $time    = exists $options{TIME}    ? $options{TIME}    : undef;
+  my @return  = ();
+
+  # Check that the $error flag is set correctly
+  $error = 'die' unless $error =~ /^(?:die|warn|ignore)$/i;
+
+  # Print the command before execution, if necessary
+  if ($time) {
+    print &timestamp_command (&get_command_string ($cmd));
+
+  } elsif ($print) {
+    &print_command ($cmd);
+  }
+
+  # Re-direct to /dev/null if necessary
+  if ($devnull) {
+    $devnull = File::Spec->devnull;
+
+    # Save current STDERR
+    no warnings;
+    open OLDERR, ">&STDERR" or croak 'Cannot dup STDERR (', $!, '), abort';
+    use warnings;
+
+    # Redirect STDERR to /dev/null
+    open STDERR, '>', $devnull
+      or croak 'Cannot redirect STDERR (', $!, '), abort';
+
+    # Make sure the channels are unbuffered
+    my $select = select;
+    select STDERR; $| = 1;
+    select $select;
+  }
+
+  if (ref ($cmd) and ref ($cmd) eq 'ARRAY') {
+    # $cmd is an array
+    my @command = @{ $cmd };
+
+    if ($method eq 'qx') {
+      @return = qx(@command);
+
+    } elsif ($method eq 'exec') {
+      exec (@command);
+
+    } else {
+      system (@command);
+      @return = $? ? () : (1);
+    }
+
+  } else {
+    # $cmd is an scalar
+    if ($method eq 'qx') {
+      @return = qx($cmd);
+
+    } elsif ($method eq 'exec') {
+      exec ($cmd);
+
+    } else {
+      system ($cmd);
+      @return = $? ? () : (1);
+    }
+  }
+
+  # Put STDERR back to normal, if redirected previously
+  if ($devnull) {
+    close STDERR;
+
+    open STDERR, ">&OLDERR" or croak 'Cannot dup STDERR (', $!, '), abort';
+  }
+
+  # Print the time taken for command after execution, if necessary
+  print &timestamp_command (&get_command_string ($cmd), 'end') if $time;
+
+  if ($?) {
+    # The command has failed
+    if ($error eq 'die') {
+      # Throw fatal error if ERROR is set to "die"
+      croak &get_command_string ($cmd), ' failed (', $?, ')';
+
+    } elsif ($error eq 'warn') {
+      # Issue warning if ERROR is set to "warn"
+      carp  &get_command_string ($cmd), ' failed (', $?, ')';
+    }
+  }
+
+  # Set the return code if necessary
+  $$rc = $? if $rc;
+
+  return @return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &e_report (@message);
+#
+# DESCRIPTION
+#   The function prints @message to STDERR and aborts with a error.
+# ------------------------------------------------------------------------------
+
+sub e_report {
+  print STDERR @_, "\n" if @_;
+
+  exit 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &w_report (@message);
+#
+# DESCRIPTION
+#   The function prints @message to STDERR and returns.
+# ------------------------------------------------------------------------------
+
+sub w_report {
+  print STDERR @_, "\n" if @_;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $date = &svn_date ($time);
+#
+# DESCRIPTION
+#   The function returns a date, formatted as by Subversion. The argument $time
+#   is the number of seconds since epoch.
+# ------------------------------------------------------------------------------
+
+sub svn_date {
+  my $time = shift;
+
+  return strftime ('%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)', localtime ($time));
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/background_updates.pl
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/background_updates.pl	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/background_updates.pl	(revision 329)
@@ -0,0 +1,188 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   background_updates.pl
+#
+# SYNOPSIS
+#   background_updates.pl <repos> <logdir>
+#
+# DESCRIPTION
+#   Performs any background tasks required after each commit to the FCM
+#   respository. A lock file is used to prevent mulitple instances of this
+#   program from running.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use File::Basename;
+use File::Spec::Functions;
+use File::Path;
+
+# ------------------------------------------------------------------------------
+
+# Usage
+my $this = basename $0;
+
+# ------------------------------------------------------------------------------
+
+# Arguments
+my ($repos, $logdir) = @ARGV;
+die $this, ': incorrect usage' unless $repos and $logdir;
+
+# ------------------------------------------------------------------------------
+
+# Lock file
+my $lockfile = catfile ($logdir, $repos . '.lock');
+my $locked   = undef;
+
+# Do nothing if lock file exists
+if (-e $lockfile) {
+  print "$this: Found lock file ($lockfile). Exiting.\n";
+  exit;
+}
+
+# Create lock file
+open FILE, '>', $lockfile
+  or die $this, ': unable to create lock file ', $lockfile;
+close FILE;
+$locked = 1;
+
+# ------------------------------------------------------------------------------
+
+my $wc_main      = '/home/h03/fcm/FCM/work/FCM';   # Location of main working copy
+my $wc_admin     = '/home/h03/fcm/FCM/work/Admin'; # Location of admin working copy
+
+my $install_hook = '/home/h03/fcm/FCM/work/Admin/src/utils/install_hook.pl';
+my $hooksrc_top  = '/home/h03/fcm/FCM/work/Admin/src/hook';
+my $hookdest_top = '/data/local/fcm/svn/live';
+
+my $ug_to_pdf    = '/home/h03/fcm/FCM/work/Admin/src/utils/user_guide_to_pdf';
+my $ug_index     = '/home/h03/fcm/FCM/work/FCM/doc/user_guide/index.html';
+
+my @remotes      = (   # list of remote machines
+  # 1st remote machine
+  {
+    MACHINE => 'tx01',               # machine name
+    LOGNAME => 'fcm',                # logname
+    WC      => '~/FCM/work',         # working copy location
+    OPTIONS => [qw#-a -v
+		--exclude='.*'
+		--exclude='FCM/doc'
+		--delete-excluded#], # options to "rsync"
+  },
+
+  # 2nd remote machine, etc
+  #{
+  #  MACHINE => '',     # machine name
+  #  LOGNAME => '',     # logname
+  #  WC      => '',     # working copy location
+  #  OPTIONS => [],     # options to "rsync"
+  #},
+);
+
+$ENV{RSYNC_RSH} = 'rsh'; # Remote shell for "rsync"
+
+while (1) {
+  # Perform "svn update" on working copy of the "trunk" of the main project
+  print "$this: Updating main working copy ...\n";
+  my @update_main = qx(svn update $wc_main);
+  die $this, ': unable to update working copy of FCM/trunk' if $?;
+
+  # Perform "svn update" on working copy of the "trunk" of the Admin project
+  print "$this: Updating admin working copy ...\n";
+  my @update_admin = qx(svn update $wc_admin);
+  die $this, ': unable to update working copy of Admin/trunk' if $?;
+
+  # Remove last line from each output, which should be info of the revision
+  pop @update_main;
+  pop @update_admin;
+
+  # No updates, exit loop
+  if (not @update_main and not @update_admin) {
+    print "$this: No updates detected. Exiting.\n";
+    last;
+  }
+
+  # Set FCM release number, if necessary
+  if (@update_main) {
+    # Get last changed revision
+    my @info = qx(svn info $wc_main);
+    my $rev;
+
+    for (@info) {
+      next unless /^Last Changed Rev: (\d+)$/;
+
+      $rev = $1;
+      last;
+    }
+
+    # Update src/etc/fcm_rev
+    print "$this: updating the FCM release number file ...\n";
+    my $fcm_rev = catfile ($wc_main, 'src/etc/fcm_rev');
+    open FILE, '>', $fcm_rev or die $fcm_rev, ': cannot open';
+    print FILE $rev, "\n";
+    close FILE or die $fcm_rev, ': cannot close';
+  }
+
+  # Re-create user guide PDF if necessary
+  if (grep m#doc/user_guide#, @update_main) {
+    print "$this: Re-creating user guide PDF ...\n";
+    my @command = ($ug_to_pdf, $ug_index);
+    system @command;
+    die $this, ': unable to execute ', join (' ', @command) if $?;
+  }
+
+  # Re-install hook scripts if necessary
+  if (grep m#src/hook#, @update_admin) {
+    print "$this: Re-install hook scripts ...\n";
+    my @command = ($install_hook, $hooksrc_top, $hookdest_top);
+    system @command;
+    die $this, ': unable to execute ', join (' ', @command) if $?;
+  }
+
+  if (@update_main) {
+    # Update remote platforms, if necessary
+    my $rsh = 'rsh';
+    for my $remote (@remotes) {
+      next unless $remote->{MACHINE} and $remote->{WC};
+      print "$this: Updating working copy on $remote->{MACHINE} ...\n";
+
+      # Create the top level directory for the remote working copy (if necessary)
+      {
+        my @command = ($rsh, $remote->{MACHINE});
+        push @command, ('-l', $remote->{LOGNAME}) if $remote->{LOGNAME};
+        push @command, (qw/mkdir -p/, $remote->{WC});
+        system @command;
+        die $this, ': unable to execute ', join (' ', @command) if $?;
+      }
+
+      # Sync the working copy to the remote platform
+      {
+        my @command = ('rsync');
+        push @command, @{ $remote->{OPTIONS} } if @{ $remote->{OPTIONS} };
+        my $rwcpath = $remote->{LOGNAME};
+        $rwcpath   .= '@' . $remote->{MACHINE} . ':' . $remote->{WC};
+        push @command, ($wc_main, $rwcpath);
+        system join (' ', @command);
+        die $this, ': unable to execute ', join (' ', @command) if $?;
+      }
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+END {
+  # Remove lock file on exit
+  unlink $lockfile if $locked;
+}
+
+# ------------------------------------------------------------------------------
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-commit
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-commit	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-commit	(revision 329)
@@ -0,0 +1,68 @@
+#!/bin/ksh
+
+# POST-COMMIT HOOK
+#
+# The post-commit hook is invoked after a commit.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-commit' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the number of the revision just committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the commit has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# newly-committed tree.
+#
+# On a Unix system, the normal procedure is to have 'post-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-commit.bat' or 'post-commit.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS=$1
+REV=$2
+
+CMD=${REPOS}/hooks/post-commit-background
+ERR=''
+
+if [[ -x $CMD ]]; then
+  $CMD $REPOS $REV >/dev/null 2>&1 &
+  RC=$?
+
+  if ((RC != 0)); then
+    ERR="$CMD failed ($RC)"
+  fi
+
+else
+  ERR="$CMD does not exist"
+fi
+
+if [[ -n $ERR ]]; then
+  /bin/mail -s "$ERR" my.name@somewhere.org <<EOF
+$(date): $ERR
+EOF
+fi
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-commit-background
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-commit-background	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-commit-background	(revision 329)
@@ -0,0 +1,90 @@
+#!/bin/ksh
+# ------------------------------------------------------------------------------
+# NAME
+#   post-commit-background
+#
+# SYNOPSIS
+#   post-commit-background REPOS REV
+#
+# DESCRIPTION
+#   This script performs the Subversion post-commit tasks in the background. The
+#   first argument must be the path to the current Subversion repository, and
+#   the second argument must be the revision of the current commit. Errors in
+#   the script are automatically e-mailed to the FCM user account.
+#
+#   The script does the following:
+#    1. updates the "latest" file in the log directory with the latest revision
+#       number of the repository.
+#    2. creates an incremental revision dump of the current revision.
+#    3. runs "background_updates.pl" if it exists in the hook script directory.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+REPOS=$1
+REV=$2
+
+REPOS_NAME=${REPOS##*/}
+LOG_DIR=~fcm/svn/post-commit
+LOG_FILE=$LOG_DIR/${REPOS_NAME}.log
+DUMP_DIR=~fcm/svn/dumps/$REPOS_NAME
+DUMP_FILE=$DUMP_DIR/$REV
+ERR=''
+
+{
+  # Update the "latest" file with the latest revision number
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating ${REPOS_NAME}.latest ..."
+  echo $REV > $LOG_DIR/${REPOS_NAME}.latest
+
+  if (($? != 0)); then
+    ERR="${ERR}Update of ${REPOS_NAME}.latest: failed. "
+  fi
+
+  # Dump the current revision
+  # ----------------------------------------------------------------------------
+  if [[ ! -d $DUMP_DIR ]]; then
+    mkdir -p $DUMP_DIR
+  fi
+
+  svnadmin dump -r $REV --incremental --deltas $REPOS 1>$DUMP_FILE
+
+  if (($? != 0)); then
+    ERR="${ERR}$REPOS_NAME@$REV: svnadmin dump: failed. "
+  fi
+
+  # Warn us of large changesets (>1Mb)
+  dump_size=$(stat -c %s $DUMP_FILE)
+
+  if (($dump_size > 1048576)); then
+    ERR="${ERR}Dump size exceeds 1Mb. "
+    echo "WARNING: large changeset dump, size = ${dump_size}byte">&2 
+  fi
+
+  # Perform background update, if necessary
+  # ----------------------------------------------------------------------------
+  if [[ -e ${REPOS}/hooks/background_updates.pl ]]; then
+    echo "$(date): Running background tasks and exiting ..."
+    ${REPOS}/hooks/background_updates.pl $REPOS_NAME $LOG_DIR
+
+    if (($? != 0)); then
+      ERR="${ERR}background_updates.pl: failed. "
+    fi
+
+  else
+    echo "$(date): No background tasks required - exiting"
+  fi
+
+} 1>$LOG_FILE 2>&1
+
+# If there are errors, e-mail the log message to FCM
+# ------------------------------------------------------------------------------
+if [[ -n $ERR ]]; then
+  ERR=${ERR% *}
+  /bin/mail -s "$REPOS@$REV: $ERR" my.name@somewhere.org <<EOF
+$(<$LOG_FILE)
+EOF
+fi
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-revprop-change
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-revprop-change	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-revprop-change	(revision 329)
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# POST-REVPROP-CHANGE HOOK
+#
+# The post-revprop-change hook is invoked after a revision property
+# has been added, modified or deleted.  Subversion runs this hook by
+# invoking a program (script, executable, binary, etc.) named
+# 'post-revprop-change' (for which this file is a template), with the
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the revision that was tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property that was changed)
+#   [5] ACTION       (the property was 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the old property value is passed via STDIN.
+#
+# Because the propchange has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# new property value.
+#
+# On a Unix system, the normal procedure is to have 'post-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-revprop-change.bat' or 'post-revprop-change.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+REPOS_NAME=${REPOS##*/}
+LOG_DIR=~fcm/svn/revprop-change
+LOG_FILE=$LOG_DIR/${REPOS_NAME}.post.log
+CMD=${REPOS}/hooks/post-revprop-change.py
+
+$CMD "$@" <&0 1>$LOG_FILE 2>&1
+RC=$?
+
+if ((RC != 0)); then
+  /bin/mail -s "$CMD failed" my.name@somewhere.org <<EOF
+$(<$LOG_FILE)
+EOF
+fi
+
+exit $RC
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-revprop-change.py
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-revprop-change.py	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/post-revprop-change.py	(revision 329)
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# ------------------------------------------------------------------------------
+# NAME
+#   post-revprop-change.py
+#
+# SYNOPSIS
+#   post-revprop-change.py REPOS REV USER PROPNAME ACTION <&0
+#
+# DESCRIPTION
+#   This script updates the Trac SQLite database with the new revision log
+#   following a change in svn:log. The old property value is passed via STDIN.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard modules
+import commands
+import os.path
+import sqlite
+import sys
+
+def main ():
+  '''Main program'''
+
+  # Get command line arguments
+  (repos, rev, user, propname, action) = sys.argv [1:6]
+
+  # Handle only log message change
+  if not (propname == 'svn:log' and action == 'M'):
+    return
+
+  # Get new message with "svnlook"
+  message = commands.getoutput ('svnlook log -r ' + rev + ' ' + repos)
+  if not message:
+    return
+
+  # Name of the project
+  project = os.path.basename (repos)
+  project = project.replace ('_svn', '')
+
+  # Path to project Trac system
+  trac    = os.path.join (os.path.expanduser ('~fcm'), 'trac', 'live', project)
+  trac_db = os.path.join (trac, 'db', 'trac.db')
+
+  # Update Trac database
+  db      = sqlite.connect (trac_db)
+  cursor  = db.cursor ()
+  cursor.execute (
+    "UPDATE revision SET message = %s WHERE rev == %s", message, rev
+  )
+
+  try:
+    db.commit ()
+
+  except:
+    raise 'Failed to update log of revision ' + rev + ' in ' + trac_db + '.'
+
+  else:
+    print 'Updated log of revision ' + rev + ' in ' + trac_db + '.'
+
+  return
+
+# ------------------------------------------------------------------------------
+
+if __name__ == '__main__' :
+  main ()
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-commit
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-commit	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-commit	(revision 329)
@@ -0,0 +1,76 @@
+#!/bin/ksh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+TXN="$2"
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+script=$REPOS/hooks/svnperms.py
+if [[ -x $script ]]; then
+  $script -r "$REPOS" -t "$TXN" -f ${REPOS}/hooks/svnperms.conf || exit 1
+fi
+
+# Check that the size of the transaction does not exceed 5Mb
+size=$(du -b -s $REPOS/db/transactions/$TXN.txn | cut -f 1)
+if (($size > 5242880)); then
+  echo \
+"Your changeset requires a disk space ($size bytes) exceeding our 5Mb limit.
+Please contact the FCM team if you need to bypass this restriction." >&2
+  exit 1
+fi
+
+# All checks passed, so allow the commit.
+exit 0
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-revprop-change
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-revprop-change	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-revprop-change	(revision 329)
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# PRE-REVPROP-CHANGE HOOK
+#
+# The pre-revprop-change hook is invoked before a revision property
+# is added, modified or deleted.  Subversion runs this hook by invoking
+# a program (script, executable, binary, etc.) named 'pre-revprop-change'
+# (for which this file is a template), with the following ordered
+# arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REVISION     (the revision being tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property being set on the revision)
+#   [5] ACTION       (the property is being 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the new property value is passed via STDIN.
+#
+# If the hook program exits with success, the propchange happens; but
+# if it exits with failure (non-zero), the propchange doesn't happen.
+# The hook program can use the 'svnlook' utility to examine the 
+# existing value of the revision property.
+#
+# WARNING: unlike other hooks, this hook MUST exist for revision
+# properties to be changed.  If the hook does not exist, Subversion 
+# will behave as if the hook were present, but failed.  The reason
+# for this is that revision properties are UNVERSIONED, meaning that
+# a successful propchange is destructive;  the old value is gone
+# forever.  We recommend the hook back up the old value somewhere.
+#
+# On a Unix system, the normal procedure is to have 'pre-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-revprop-change.bat' or 'pre-revprop-change.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+REPOS_NAME=${REPOS##*/}
+LOG_DIR=~fcm/svn/revprop-change
+LOG_FILE=$LOG_DIR/${REPOS_NAME}.pre.log
+CMD=${REPOS}/hooks/pre-revprop-change.pl
+
+$CMD "$@" <&0 1>$LOG_FILE 2>&1
+RC=$?
+
+if ((RC != 0)); then
+  /bin/mail -s "$CMD failed" my.name@somewhere.org <<EOF
+$(<$LOG_FILE)
+EOF
+fi
+
+exit $RC
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-revprop-change.pl
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-revprop-change.pl	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/hook/pre-revprop-change.pl	(revision 329)
@@ -0,0 +1,222 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   pre-revprop-change.pl
+#
+# SYNOPSIS
+#   pre-revprop-change.pl REPOS REV USER PROPNAME ACTION <&0
+#
+# DESCRIPTION
+#   This script e-mails authors and watchers when a user attempts to modify the
+#   svn:log of a particular revision. The new property value is passed via
+#   STDIN. Watchers are set in the "watch.cfg" file, which should be located in
+#   the root within the Subversion repository. The watch.cfg file is a standard
+#   INI-type configuration file with the basic format:
+#
+#     [repos_base]
+#     path/in/repos = list,of,watchers
+#
+#   E.g.:
+#
+#     [FCM_svn]
+#
+#     FCM/trunk/src            = fcm,frsn
+#     FCM/trunk/doc            = fcm,frsn,frdm,frbj
+#     FCM/branches/dev/*/*/src = fcm,frsn
+#     FCM/branches/dev/*/*/doc = fcm,frsn,frdm,frbj
+#
+# COPYRIGHT
+#   This program is part of the FCM system.
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+use File::Temp qw/tempfile/;
+use Mail::Mailer;
+use Config::IniFiles;
+
+# Arguments
+# ------------------------------------------------------------------------------
+my ($repos, $rev, $user, $propname, $action) = @ARGV;
+
+# Basename of repository
+my $base = basename $repos;
+
+# Top level variables
+# ------------------------------------------------------------------------------
+# The watch configuration file, at the root of the current repository
+my $watch_config = 'watch.cfg';
+
+# Determine whether change is permitted
+# ------------------------------------------------------------------------------
+# Switch off for most revision properties
+my $return = 1;
+
+# Switch on only for "svn:log"
+$return = 0 if $propname eq 'svn:log' and $action eq 'M';
+
+if ($return == 0) {
+  # Diagnostic
+  print $repos, ': ', $propname, ' at revision ', $rev,
+        ' is being modified by ', $user, '.', "\n";
+
+  my %mail_to = ();
+
+  # Mail original author, if he/she is not the current user
+  # ----------------------------------------------------------------------------
+  # Find out who is the author of the changeset at $rev
+  my @command = (qw/svnlook author -r/, $rev, $repos);
+  my $author  = qx(@command);
+  chomp $author;
+
+  # Add author to mail list, if necessary
+  $mail_to{$author} = 1 if $author ne $user;
+
+  # Mail watchers, if changeset involves files being watched
+  # ----------------------------------------------------------------------------
+  # Find out what files were involved in the changeset
+  @command    = (qw/svnlook changed -r/, $rev, $repos);
+  my @changed = qx(@command);
+
+  # Get list of watchers for current repository
+  my %watch = &get_watchers ();
+
+  for my $file (@changed) {
+    # Remove trailing line break and leading status
+    chomp $file;
+    $file = substr ($file, 4);
+
+    # Find out who are watching this file
+    my @watchers = &who_watch ($file, \%watch);
+
+    # If necessary, add watchers to list, unless he/she is the current user
+    for my $watcher (@watchers) {
+      $mail_to{$watcher} = 1 if $user ne $watcher;
+    }
+  }
+
+  # Send mail if necessary
+  # ----------------------------------------------------------------------------
+  if (keys %mail_to) {
+    # Old value of revision property
+    my @command = (qw/svnlook pg -r/, $rev, '--revprop', $repos, $propname);
+    my $oldval  = qx(@command);
+
+    # Addresses as a comma-separated list
+    my $address = join (',', sort keys %mail_to);
+
+    # Invoke a new Mail::Mailer object
+    my $mailer  = Mail::Mailer->new ();
+    $mailer->open ({
+      From    => 'my.name@somewhere.org',
+      To      => $address,
+      Subject => $base . '@' . $rev . ': ' . $propname . ' modified by ' . $user,
+    }) or die 'Cannot e-mail ', $address, ' (', $!, ')';
+
+    # Write the mail
+    # Old value
+    print $mailer <<EOF;
+Old value:
+----------
+$oldval
+
+New value:
+----------
+EOF
+
+    # New value from STDIN
+    print $mailer $_ while (<STDIN>);
+
+    # Send the mail
+    $mailer->close;
+
+    print 'Mail notification has been sent to ', $address, '.', "\n";
+
+  } else {
+    print 'No mail notification is required for this change.', "\n";
+  }
+}
+
+exit $return;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %watch = &get_watchers ();
+#
+# DESCRIPTION
+#   From the list of watch configuration files, get a list of watched files and
+#   their watchers for the current repository. Returns the results in a hash
+#   containing the watched paths (keys) and their corresponding list of
+#   watchers (values, array references).
+# ------------------------------------------------------------------------------
+
+sub get_watchers {
+  my %watch;
+
+  # Get contents in watch file
+  my @command = (qw/svnlook cat/, $repos, $watch_config);
+  my @output  = qx(@command);
+
+  if (@output) {
+    # Write result to temporary file
+    my ($fh, $temp_file) = tempfile (UNLINK => 1);
+    print $fh @output;
+    close $fh;
+
+    # Parse the configuration
+    my $cfg = Config::IniFiles->new ('-file' => $temp_file);
+
+    # Check if current repository name exists in the configuration file
+    if ($cfg and $cfg->SectionExists ($base)) {
+      # The name of the parameter is a sub-path in the repository
+      # The value of the parameter is a comma-delimited list of the watchers
+      my $separator = '/';
+      for my $parameter ($cfg->Parameters ($base)) {
+        # Parameter may contain wildcards * and ?
+        $parameter =~ s#\*#[^$separator]*#g;
+        $parameter =~ s#\?#[^$separator]#g;
+
+        $watch{$parameter} = [split (/,/, $cfg->val ($base, $parameter))];
+      }
+    }
+  }
+
+  return %watch;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   my @watchers = &who_watch ($file, \%watch);
+#
+# DESCRIPTION
+#   Using the %watch hash, determine who are the watchers watching $file.
+#   Returns the list of watchers.
+# ------------------------------------------------------------------------------
+
+sub who_watch {
+  my $file  = $_[0];
+  my %watch = %{ $_[1] };
+
+  my %watchers;
+  my $separator = '/';
+
+  for my $watched (keys %watch) {
+    # Test if $file or its parent path is being watched
+    next unless $file =~ m#^$watched(?:$separator+|$)#;
+
+    # Add watchers to the return list
+    $watchers{$_} = 1 for (@{ $watch{$watched} });
+  }
+
+  return keys %watchers;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/cron_template.ksh
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/cron_template.ksh	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/cron_template.ksh	(revision 329)
@@ -0,0 +1,50 @@
+#!/usr/bin/ksh
+# ------------------------------------------------------------------------------
+# (C) Crown copyright Met Office. All rights reserved.
+# For further details please refer to the file COPYRIGHT.txt
+# which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+lockfile='lock'
+
+if [[ -f $lockfile ]]; then
+  exit
+fi
+
+touch $lockfile
+
+headrevfile='latest'
+lastrevfile='lastrev'
+
+# Current HEAD revision
+if [[ ! -r $headrevfile ]]; then
+  echo "HEAD revision file $headrevfile cannot be read, abort" >&2
+  rm -f $lockfile
+  exit 1
+fi
+headrev=$(<$headrevfile)
+headrev=$(echo $headrev)
+
+# Revision at which this script is last run
+if [[ -r $lastrevfile ]]; then
+  lastrev=$(<$lastrevfile)
+  lastrev=$(echo $lastrev)
+else
+  lastrev=0
+fi
+
+# Exit if HEAD revision is the same as the last run revision
+if (($lastrev == $headrev)); then
+  rm -f $lockfile
+  exit 0
+fi
+
+# ------------------------------------------------------------------------------
+# Do something...
+# ------------------------------------------------------------------------------
+
+# Update last run revision file
+echo $headrev >$lastrevfile
+rm -f $lockfile
+
+# EOF
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/daily_cron
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/daily_cron	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/daily_cron	(revision 329)
@@ -0,0 +1,277 @@
+#!/bin/ksh
+
+out=~fcm/FCM/daily_cron.out
+svn_live=/data/local/fcm/svn/live
+svn_backup=~fcm/svn/backups
+svn_tmp=/var/tmp/fcm/svn/backups
+svn_dump=~fcm/svn/dumps
+trac_live=~fcm/trac/live
+trac_backup=~fcm/trac/backups
+trac_tmp=/var/tmp/fcm/trac/backups
+err=''
+
+export RSYNC_RSH=rsh # remote shell for "rsync"
+
+{
+
+  # Verify and backup Subversion repository database
+  # ----------------------------------------------------------------------------
+  cd $svn_live
+  tmpfile=/tmp/${USER}.$$
+  now=$(date +%s)
+  for dir in *; do
+    if [[ ! -d $dir ]]; then continue; fi
+
+    # Verify
+    # --------------------------------------------------------------------------
+    echo "$(date): Verifying $dir ..."
+    sed '/^\* Verified revision [0-9][0-9]*\./d'<<EOF
+$(svnadmin verify $dir 2>&1; echo $? > $tmpfile)
+EOF
+    RC=$(cat $tmpfile)
+
+    if ((RC != 0)); then
+      err="${err}Error in $dir repository integrity. "
+      continue
+    fi
+
+    # Backup
+    # --------------------------------------------------------------------------
+    # Create the temporary backup location if it does not exists
+    if [[ ! -d $svn_tmp ]]; then
+      mkdir -p $svn_tmp
+
+      if (($? != 0)); then
+        err="${err}Error creating $svn_tmp. "
+        break
+      fi
+    fi
+
+    # Hotcopy to temporary location
+    tmp_backup_dir=$svn_tmp/$dir
+    echo "$(date): Hotcopying $dir SVN repository to $tmp_backup_dir ..."
+    svnadmin hotcopy $dir $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error hotcopying $dir SVN repository to $tmp_backup_dir. "
+      continue
+    fi
+
+    # Create the backup location if it does not exists
+    if [[ ! -d $svn_backup ]]; then
+      mkdir -p $svn_backup
+
+      if (($? != 0)); then
+        err="${err}Error creating $svn_backup. "
+        break
+      fi
+    fi
+
+    # Tar and gzip the backup
+    new_backup=$svn_backup/$dir.$(date +%Y%m%d).tgz
+    echo "$(date): Creating tar archive in $new_backup ..."
+    tar -C $svn_tmp -c -z -f $new_backup $(basename $tmp_backup_dir)
+
+    if (($? != 0)); then
+      err="${err}Error creating tar archive in $new_backup. "
+      continue
+    fi
+
+    # Remove the temporary hotcopy
+    rm -rf $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error removing $tmp_backup_dir. "
+    fi
+
+    # Remove the old backup, if necessary
+    backup=$svn_backup/$dir.tgz
+
+    if [[ -f $backup ]]; then
+      rm -f $backup
+
+      if (($? != 0)); then
+        err="${err}Error removing old copy of $backup. "
+        continue
+      fi
+    fi
+
+    # Move today's backup to the final location
+    echo "$(date): Renaming $new_backup to $backup ..."
+    mv $new_backup $backup
+
+    if (($? != 0)); then
+      err="${err}Error renaming $new_backup to $backup. "
+    fi
+
+    # Housekeep the revision dumps
+    # --------------------------------------------------------------------------
+    if [[ -d $svn_dump/$dir ]]; then
+      # Keep dumps created in the last 3 days
+      echo "$(date): Housekeeping dumps in $svn_dump/$dir ..."
+
+      cd $svn_dump/$dir
+      for rev in *; do
+        # Check that $rev is a regular file
+        if [[ ! -f $rev ]]; then
+          continue
+        fi
+
+        # 3 days = 24 * 60 * 60 * 3 = 259200 seconds
+        if (($now - $(stat -c %Y $rev) > 259200)); then
+          echo "$(date): Removing $svn_dump/$dir/$rev ..."
+          rm -f $rev
+          if (($? != 0)); then
+            err="${err}Error removing dump $svn_dump/$dir/$rev. "
+          fi
+        fi
+      done
+
+      cd $OLDPWD
+    fi
+  done
+
+  # Backing up Trac systems
+  # ----------------------------------------------------------------------------
+  cd $trac_live
+  for dir in *; do
+    if [[ ! -d $dir ]]; then continue; fi
+
+    # Backup
+    # --------------------------------------------------------------------------
+    # Create the temporary backup location if it does not exists
+    if [[ ! -d $trac_tmp ]]; then
+      mkdir -p $trac_tmp
+
+      if (($? != 0)); then
+        err="${err}Error creating $trac_tmp. "
+        break
+      fi
+    fi
+
+    # Hotcopy to temporary location
+    tmp_backup_dir=$trac_tmp/$dir
+    echo "$(date): Hotcopying $dir Trac system to $tmp_backup_dir ..."
+    trac-admin $dir hotcopy $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error hotcopying $dir Trac system to $tmp_backup_dir. "
+      continue
+    fi
+
+    # Create the backup location if it does not exists
+    if [[ ! -d $trac_backup ]]; then
+      mkdir -p $trac_backup
+
+      if (($? != 0)); then
+        err="${err}Error creating $trac_backup. "
+        break
+      fi
+    fi
+
+    # Tar and gzip the backup
+    new_backup=$trac_backup/$dir.$(date +%Y%m%d).tgz
+    echo "$(date): Creating tar archive in $new_backup ..."
+    tar -C $trac_tmp -c -z -f $new_backup $(basename $tmp_backup_dir)
+
+    if (($? != 0)); then
+      err="${err}Error creating tar archive in $new_backup. "
+      continue
+    fi
+
+    # Remove the temporary hotcopy
+    rm -rf $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error removing $tmp_backup_dir. "
+    fi
+
+    # Rename backups on success
+    # --------------------------------------------------------------------------
+    # Shift backup "1" to backup "2", and then backup "0" to backup "1"
+    for i in 1 0; do
+      old_file=$trac_backup/$dir.$i.tgz
+      new_file=$trac_backup/$dir.$((i + 1)).tgz
+
+      # Check if move is necessary
+      if [[ ! -f $old_file ]]; then
+        continue
+      fi
+
+      if [[ -f $new_file ]]; then
+        echo "$(date): Removing $new_file ..."
+        rm -f $new_file
+
+        if (($? != 0)); then
+          err="${err}Error removing $new_file. "
+          break
+        fi
+      fi
+
+      echo "$(date): Renaming $old_file to $new_file ..."
+      mv $old_file $new_file
+      if (($? != 0)); then
+        err="${err}Error renaming $old_file. "
+        break
+      fi
+    done
+
+    # Move today's backup to "0", if possible
+    backup=$trac_backup/$dir.0.tgz
+    if [[ ! -f $backup ]]; then
+      echo "$(date): Renaming $new_backup to $backup ..."
+      mv $new_backup $backup
+      if (($? != 0)); then
+        err="${err}Error renaming $new_backup to $backup. "
+      fi
+    fi
+  done
+
+  # Update the Trac password file and databases with latest login information
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating password files and Trac databases ..."
+  $(dirname $0)/fcm_manage_login.py
+  if (($? != 0)); then
+    err="${err} Error updating Trac password file and databases. "
+  fi
+
+  # Sync the working copy to the NEC
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating NEC ..."
+  rsync -a -v --exclude='.*' --exclude='FCM/doc' --delete-excluded \
+    ~/FCM/work/FCM fcm@tx01:~/FCM/work
+  if (($? != 0)); then
+    err="${err}Error updating NEC. "
+  fi
+
+  # Update "synch" path from "synch" machine
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating synch machine ..."
+  for subdir in bin lib etc; do
+    rsync -a -v --exclude='.*' ~/FCM/work/FCM/src/$subdir/* \
+      fcm@hc0100:/opt/ukmo/utils/supported/portable/$subdir/
+
+    if (($? != 0)); then
+      err="${err}Error updating $subdir/ on synch machine. "
+    fi
+  done
+
+  # Final report
+  # ----------------------------------------------------------------------------
+  if [[ -n $err ]]; then
+    subject="$(basename $0) finished with errors: $err"
+
+  else
+    subject="$(basename $0) finished normally."
+  fi
+
+  echo "$(date): $subject"
+} 1>$out 2>&1
+
+# Report completion via e-mail
+# ------------------------------------------------------------------------------
+mail -s "$subject" my.name@somewhere.org <<EOF
+$(<$out)
+EOF
+
+# EOF
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/fcm_add_trac.pl
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/fcm_add_trac.pl	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/fcm_add_trac.pl	(revision 329)
@@ -0,0 +1,343 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_add_trac.pl
+#
+# SYNOPSIS
+#   fcm_add_trac.pl [OPTIONS] <system>
+#   fcm_add_trac.pl -h
+#
+# DESCRIPTION
+#   See $usage for further information.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use Config::IniFiles;
+
+# In-house modules
+use lib File::Spec->catfile (
+  dirname (
+    (grep {-x File::Spec->catfile ($_, 'fcm')} split (/:/, $ENV{PATH})) [0]
+  ),
+  'lib',
+);
+use Fcm::Util;
+
+# ------------------------------------------------------------------------------
+
+# Program information
+my $this      = basename ($0);
+my $year      = (localtime)[5] + 1900;
+my $copyright = <<EOF;
+
+(C) Crown copyright $year Met Office. All rights reserved.
+EOF
+my $usage     = <<EOF;
+NAME
+  $this: add a new Trac browser for a FCM project
+
+SYNOPSIS
+  $this [OPTIONS] <project> # normal usage
+  $this -h                  # print help and exit
+
+DESCRIPTION
+  This script adds a new Trac browser for a project managed by FCM. The name of
+  the project is specified in the first argument.
+  
+  With the except of --authorised and --help, all options to the script take at
+  least one argument. If an option can take more than one argument, the
+  arguments should be specified in a comma-separated list.
+
+OPTIONS
+  -a, --authorised      - specify an "authorised" permission. Only those users
+                          granted this permission will have "_CREATE" and
+                          "_MODIFY" access. The default is to grant all
+                          authenticated users "_CREATE" and "_MODIFY" access.
+
+  -c, --component       - specify one or more components.
+
+  -d, --description     - specify a description of the project.
+
+  -e, --smtp-always-cc  - specify one or more e-mail addresses, where e-mails
+                          will be sent to on ticket changes.
+
+  -h, --help            - prints the usage string and exits.
+
+  -m, --milestone       - specify one or more milestones.
+
+  -s, --svn-repos       - specify the Subversion repository location.
+
+  -u, --admin-user      - specify one or more admin users.
+
+  -v, --version         - specify one or more versions.
+$copyright
+EOF
+
+# ------------------------------------------------------------------------------
+
+# Options
+my ($authorised, $help, $description, $svn_repos);
+my (@admin_users, @components, @emails, @milestones, @versions);
+
+GetOptions (
+  'a|authorised'       => \$authorised,
+  'c|component=s'      => \@components,
+  'd|description=s'    => \$description,
+  'e|smtp-always-cc=s' => \@emails,
+  'h|help'             => \$help,
+  'm|milestone=s'      => \@milestones,
+  's|svn-repos=s'      => \$svn_repos,
+  'u|admin-user=s'     => \@admin_users,
+  'v|version=s'        => \@versions,
+);
+
+@admin_users = split (/,/, join (',', @admin_users));
+@components  = split (/,/, join (',', @components));
+@emails      = split (/,/, join (',', @emails));
+@milestones  = split (/,/, join (',', @milestones));
+@versions    = split (/,/, join (',', @versions));
+
+if ($help) {
+  print $usage;
+  exit;
+}
+
+# Arguments
+my $project = $ARGV[0];
+die $this, ': the first argument must be the name of a project' if not $project;
+
+# ------------------------------------------------------------------------------
+
+# Useful variables
+my $svn_root  = '/data/local/fcm/svn/live';
+my $trac_root = File::Spec->catfile ((getpwnam ('fcm'))[7], 'trac', 'live');
+
+# ------------------------------------------------------------------------------
+
+MAIN: {
+  # Check for the existence of Trac for the current project
+  # ----------------------------------------------------------------------------
+  my $trac_project = File::Spec->catfile ($trac_root, $project);
+  die $this, ': Trac for "', $project, '" already exists in ', $trac_project
+    if -d $trac_project;
+
+  # Check for the existence of SVN for the current project
+  # ----------------------------------------------------------------------------
+  my $svn_project = $svn_repos
+                    ? $svn_repos
+                    : File::Spec->catfile ($svn_root, $project . '_svn');
+  die $this, ': SVN for "', $project, '" does not exist in ', $svn_project
+    if not -d $svn_project;
+
+  # Set up "trac-admin" command for this project
+  # ----------------------------------------------------------------------------
+  my @admin_cmd = ('trac-admin', $trac_project);
+
+  # Create project's Trac
+  my $trac_templates = '/usr/share/trac/templates';
+
+  my @command = (
+    @admin_cmd,
+    'initenv',
+    $project,
+    'sqlite:db/trac.db',
+    $svn_project,
+    $trac_templates,
+  );
+
+  &run_command (\@command, PRINT => 1);
+
+  # Ensure the new Trac has the correct group and permissions
+  &run_command ([qw/chgrp -R apache/, $trac_project], PRINT => 1);
+  &run_command ([qw/chmod -R g+w/, $trac_project], PRINT => 1);
+
+  # Components
+  # ----------------------------------------------------------------------------
+  my @cur_cmd = (@admin_cmd, 'component');
+
+  # Remove example components
+  for my $component (qw/component1 component2/) {
+    &run_command ([@cur_cmd, 'remove', $component], PRINT => 1);
+  }
+
+  # Add specified components
+  for my $component (@components) {
+    &run_command ([@cur_cmd, 'add', $component, ''], PRINT => 1);
+  }
+
+  # List components
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Versions
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'version');
+
+  # Remove example versions
+  for my $version (qw/1.0 2.0/) {
+    &run_command ([@cur_cmd, 'remove', $version], PRINT => 1);
+  }
+
+  # Add specified versions
+  for my $version (@versions) {
+    &run_command ([@cur_cmd, 'add', $version], PRINT => 1);
+  }
+
+  # List versions
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Milestones
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'milestone');
+
+  # Remove example milestones
+  for my $milestone (qw/milestone1 milestone2 milestone3 milestone4/) {
+    &run_command ([@cur_cmd, 'remove', $milestone], PRINT => 1);
+  }
+
+  # Add specified milestones
+  for my $milestone (@milestones) {
+    &run_command ([@cur_cmd, 'add', $milestone], PRINT => 1);
+  }
+
+  # List milestones
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Priority
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'priority');
+
+  # Change default priorities
+  my %priorities = (
+    blocker  => 'highest',
+    critical => 'high',
+    major    => 'normal',
+    minor    => 'low',
+    trivial  => 'lowest',
+  );
+  while (my ($old, $new) = each %priorities) {
+    &run_command ([@cur_cmd, 'change', $old, $new], PRINT => 1);
+  }
+
+  # List priorities
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Severity
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'severity');
+
+  # Add serverities
+  for my $severity (qw/blocker critical major normal minor trivial/) {
+    &run_command ([@cur_cmd, 'add', $severity], PRINT => 1);
+  }
+
+  # List serverities
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Permission
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'permission');
+
+  # Add permissions to admin users
+  for my $user (@admin_users) {
+    &run_command ([@cur_cmd, 'add', $user, 'admin'], PRINT => 1);
+  }
+  &run_command ([@cur_cmd, qw/add admin TRAC_ADMIN/], PRINT => 1);
+
+  # Remove wiki/ticket create/modify permissions from anonymous users
+  for my $per (qw/TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY/) {
+    &run_command ([@cur_cmd, qw/remove anonymous/, $per], PRINT => 1);
+  }
+
+  # Add wiki/ticket create/modify permissions to authenticated/authorised users
+  for my $per (qw/TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY/) {
+    &run_command (
+      [@cur_cmd, 'add', ($authorised ? 'authorised' : 'authenticated'), $per],
+      PRINT => 1,
+    );
+  }
+
+  # List permissions
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Misc modifications to "trac.ini"
+  # ----------------------------------------------------------------------------
+  my $trac_ini = File::Spec->catfile ($trac_project, 'conf', 'trac.ini');
+
+  # Read and parse "trac.ini"
+  my $parser = Config::IniFiles->new ('-file' => $trac_ini);
+
+  # Footer to be displayed in the each page
+  my $footer         = 'This system is managed by the<br />' .
+                       '<a href="http://fcm1/projects/FCM">' .
+                       'Flexible Configuration Management System</a>';
+
+  # Descriptive name for the current project
+  my $descr          = $description ? $description : $project;
+
+  # Default component
+  my $def_component  = @components ? $components [0] : '';
+
+  # List of e-mail addresses to always cc
+  my $smtp_always_cc = @emails ? join (',', @emails) : '';
+
+  # List of "default" config, in [section, option, value]
+  my @config = (
+    ['notification', 'always_notify_owner'   , 'true'],
+    ['notification', 'always_notify_reporter', 'true'],
+    ['notification', 'smtp_enabled'          , 'true'],
+    ['notification', 'smtp_server'           , 'localhost.metoffice.com'],
+    ['notification', 'smtp_always_cc'        , $smtp_always_cc],
+    ['project'     , 'url'                   , ''],
+    ['project'     , 'footer'                , $footer],
+    ['project'     , 'descr'                 , $descr],
+    ['timeline'    , 'ticket_show_details'   , 'true'],
+    ['ticket'      , 'default_component'     , $def_component],
+    ['ticket'      , 'default_priority'      , 'normal'],
+    ['ticket'      , 'default_severity'      , 'normal'],
+    ['timeline'    , 'changeset_show_files'  , '3'],
+    ['components'  , 'trac.ticket.report.*'  , 'disabled'],
+  );
+
+  for (@config) {
+    my ($section, $option, $value) = @{ $_ };
+
+    # Add new section, if necessary
+    $parser->AddSection ($section) if not $parser->SectionExists ($section);
+
+    if (defined ($parser->val ($section, $option))) {
+      # Modify existing option
+      $parser->setval ($section, $option, $value);
+
+    } else {
+      # Add new option
+      $parser->newval ($section, $option, $value);
+    }
+  }
+
+  # Rename original "trac.ini" to "trac.ini.orig"
+  rename $trac_ini, $trac_ini . '.orig';
+
+  # Output modifications to "trac.ini"
+  $parser->WriteConfig ($trac_ini);
+}
+
+# Finally...
+# ------------------------------------------------------------------------------
+print $this, ': finished', "\n";
+exit;
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/recover_svn.pl
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/recover_svn.pl	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/templates/utils/recover_svn.pl	(revision 329)
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   recover_svn.pl
+#
+# SYNOPSIS
+#   recover_svn.pl [<list of projects>]
+#
+# DESCRIPTION
+#   This command is used to recover live repositories from backups and dumps,
+#   using the following logic:
+#     1. If one or more <projects> are not specified, check the backup directory
+#        for list of projects and available backups.
+#     2. For each available project (or the specified <projects>), check if its
+#        live repository exists. If so, performs an integrity check.
+#     3. If the live repository does not exist or if the integrity check fails,
+#        recover by copying the backup into the live location.
+#     4. Determine the youngest revision of the live repository.
+#     5. Search the dump directory to see if there are dumps for newer
+#        reversions. If so, load them back to the live repository.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use strict;
+use warnings;
+
+# Standard modules:
+use File::Basename;
+use File::Spec;
+use File::Path;
+
+# ------------------------------------------------------------------------------
+
+# Top level locations of live repositories, backups, dumps and hook scripts
+my $logname  = 'fcm';
+my $svn_live = File::Spec->catfile (
+  File::Spec->rootdir (), qw/data local/, $logname, qw/svn live/,
+);
+my $svn_back = File::Spec->catfile ((getpwnam $logname) [7], qw/svn backups/);
+my $svn_dump = File::Spec->catfile ((getpwnam $logname) [7], qw/svn dumps/);
+my $hook_dir = File::Spec->catfile (
+  (getpwnam $logname) [7], qw/FCM work Admin src hook/,
+);
+
+# Arguments
+my %projects = map {$_, 1} @ARGV;
+
+# Search the backup directory to see what are available
+opendir DIR, $svn_back
+  or die $svn_back, ': cannot read directory (', $!, '), abort';
+my %backups = ();
+while (my $file = readdir 'DIR') {
+  next if $file =~ /^\./;
+  next if $file !~ /\.tgz$/;
+  next unless -f File::Spec->catfile ($svn_back, $file);
+
+  (my $project = $file) =~ s/\.tgz$//;
+
+  # If project arguments specified, skip projects that are not in the list
+  next if %projects and not exists $projects{$project};
+
+  # Store project name and its backup location
+  $backups{$project} = File::Spec->catfile ($svn_back, $file);
+}
+closedir DIR;
+
+# Create the live directory if it does not exist
+mkpath $svn_live or die $svn_live, ': cannot create, abort' if not -d $svn_live;
+
+# Exit if no backups found (for list of specified projects)
+if (not keys %backups) {
+  print 'No backup',
+        (keys %projects ? join (' ', (' for', sort keys %projects)) : ''),
+        ' found in ', $svn_back, "\n";
+  exit;
+}
+
+# Search the live directory to see what are available
+for my $project (sort keys %backups) {
+  my $live_dir = File::Spec->catfile ($svn_live, $project);
+
+  # Recovery required if $live_dir does not exist
+  my $recovery = not -d $live_dir;
+
+  # Perform an integrity check if $live_dir exist
+  $recovery = system ('svnadmin', 'verify', $live_dir) unless $recovery;
+
+  if (not $recovery) {
+    print $project, ': live repository appears to be fine.', "\n";
+    next;
+  }
+
+  # Recover to a temporary location first
+  my $temp_dir = $live_dir . '.tmp';
+
+  if (-d $temp_dir) {
+    # Remove $temp_dir if it exists
+    print 'Removing ', $temp_dir, ' ...', "\n";
+    rmtree $temp_dir;
+  }
+
+  # Un-tar the backup
+  print 'Extracting from the backup archive ', $backups{$project}, "\n";
+  ! system (
+    qw/tar -x -z -C/, dirname ($backups{$project}), '-f', $backups{$project},
+  ) or die 'Cannot extract from the backup archive', $backups{$project};
+
+  (my $backup_dir = $backups{$project}) =~ s/\.tgz$//;
+
+  # Recover from backup
+  print 'Copying ', $backup_dir, ' to ', $temp_dir, ' ...', "\n";
+  my @command = ('svnadmin', 'hotcopy', $backup_dir, $temp_dir);
+  system (@command);
+  die join (' ', @command), ' failed (', $?, '), abort' if $?;
+
+  rmtree $backup_dir;
+
+  # Determine the youngest revision of the repository
+  @command     = ('svnlook', 'youngest', $temp_dir);
+  my $youngest = qx(@command)
+    or die $temp_dir, ': cannot determine youngest revision (', $?, ')';
+
+  # Search dump directory to see if there are any later dumps available
+  my $dump_dir = File::Spec->catfile ($svn_dump, $project);
+  
+  if (opendir DIR, $dump_dir) {
+    my @revs = grep {m/^\d+$/ and $_ > $youngest} readdir DIR;
+    closedir DIR;
+
+    # If newer dumps available, load each one back to the repository
+    for my $rev (sort {$a <=> $b} @revs) {
+      print 'Loading dump for revision ', $rev, ' to ', $temp_dir, ' ...', "\n";
+      my $command = 'svnadmin load ' . $temp_dir .
+                    ' <' . File::Spec->catfile ($dump_dir, $rev);
+      system ($command);
+      die $command, ' failed (', $?, '), abort' if $?;
+    }
+
+  } else {
+      warn $project, ': dump directory not available for project';
+  }
+
+  # Move temporary directory to live
+  if (-d $live_dir) {
+    # Remove $live_dir if it exists
+    print 'Removing ', $live_dir, ' ...', "\n";
+    rmtree $live_dir;
+
+    die $live_dir, ': cannot remove' if -d $live_dir;
+  }
+
+  print 'Moving ', $temp_dir, ' to ', $live_dir, ' ...', "\n";
+  rename $temp_dir, $live_dir or die $temp_dir, ': cannot move to: ', $live_dir;
+}
+
+# Reinstate the hook scripts
+my @command = (
+  File::Spec->catfile (dirname ($0), 'install_hook.pl'),
+  $hook_dir,
+  $svn_live,
+);
+
+exec @command or die 'Cannot exec install_hook.pl (', $!, ')';
+
+__END__
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/pre-commit
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/pre-commit	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/pre-commit	(revision 329)
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+
+REPOS="$1"
+TXN="$2"
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+${REPOS}/hooks/svnperms.py -r "$REPOS" -t "$TXN" -f ${REPOS}/hooks/svnperms.conf || exit 1
+
+# All checks passed, so allow the commit.
+exit 0
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/svnperms.conf
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/svnperms.conf	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/svnperms.conf	(revision 329)
@@ -0,0 +1,5 @@
+## Configuration file for svnperms.py. ##
+
+[tutorial_svn]
+tutorial/trunk/.* = *()
+tutorial/branches/[^/]+/.* = *(add,remove,update)
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/svnperms.py
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/svnperms.py	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/FCM/tutorial/hook/svnperms.py	(revision 329)
@@ -0,0 +1,311 @@
+#!/usr/bin/env python
+
+# $HeadURL: https://svn.collab.net/repos/svn/trunk/tools/hook-scripts/svnperms.py $
+# $LastChangedDate: 2005-03-17 04:39:51 -0600 (Thu, 17 Mar 2005) $
+# $LastChangedBy: maxb $
+# $LastChangedRevision: 13456 $
+
+import commands
+import sys, os
+import getopt
+import re
+
+__author__ = "Gustavo Niemeyer <niemeyer@conectiva.com>"
+
+class Error(Exception): pass
+
+SECTION = re.compile(r'\[([^]]+)\]')
+OPTION = re.compile(r'(\S+)\s*=\s*(.*)$')
+
+class Config:
+    def __init__(self, filename):
+        # Options are stored in __sections_list like this:
+        # [(sectname, [(optname, optval), ...]), ...]
+        self._sections_list = []
+        self._sections_dict = {}
+        self._read(filename)
+
+    def _read(self, filename):
+        # Use the same logic as in ConfigParser.__read()
+        file = open(filename)
+        cursectdict = None
+        optname = None
+        lineno = 0
+        for line in file.xreadlines():
+            lineno = lineno + 1
+            if line.isspace() or line[0] == '#':
+                continue
+            if line[0].isspace() and cursectdict is not None and optname:
+                value = line.strip()
+                cursectdict[optname] = "%s %s" % (cursectdict[optname], value)
+                cursectlist[-1][1] = "%s %s" % (cursectlist[-1][1], value)
+            else:
+                m = SECTION.match(line)
+                if m:
+                    sectname = m.group(1)
+                    cursectdict = self._sections_dict.setdefault(sectname, {})
+                    cursectlist = []
+                    self._sections_list.append((sectname, cursectlist))
+                    optname = None
+                elif cursectdict is None:
+                    raise Error, "%s:%d: no section header" % \
+                                 (filename, lineno)
+                else:
+                    m = OPTION.match(line)
+                    if m:
+                        optname, optval = m.groups()
+                        optval = optval.strip()
+                        cursectdict[optname] = optval
+                        cursectlist.append([optname, optval])
+                    else:
+                        raise Error, "%s:%d: parsing error" % \
+                                     (filename, lineno)
+
+    def sections(self):
+        return self._sections_dict.keys()
+
+    def options(self, section):
+        return self._sections_dict.get(section, {}).keys()
+
+    def get(self, section, option, default=None):
+        return self._sections_dict.get(option, default)
+
+    def walk(self, section, option=None):
+        ret = []
+        for sectname, options in self._sections_list:
+            if sectname == section:
+                for optname, value in options:
+                    if not option or optname == option:
+                        ret.append((optname, value))
+        return ret
+
+
+class Permission:
+    def __init__(self):
+        self._group = {}
+        self._permlist = []
+    
+    def parse_groups(self, groupsiter):
+        for option, value in groupsiter:
+            self._group[option] = value.split()
+            
+    def parse_perms(self, permsiter):
+        for option, value in permsiter:
+            # Paths never start with /, so remove it if provided
+            if option[0] == "/":
+                option = option[1:]
+            pattern = re.compile("^%s$" % option)
+            for entry in value.split():
+                openpar, closepar = entry.find("("), entry.find(")")
+                groupsusers = entry[:openpar].split(",")
+                perms = entry[openpar+1:closepar].split(",")
+                users = []
+                for groupuser in groupsusers:
+                    if groupuser[0] == "@":
+                        try:
+                            users.extend(self._group[groupuser[1:]])
+                        except KeyError:
+                            raise Error, "group '%s' not found" % \
+                                         groupuser[1:]
+                    else:
+                        users.append(groupuser)
+                self._permlist.append((pattern, users, perms))
+
+    def get(self, user, path):
+        ret = []
+        for pattern, users, perms in self._permlist:
+            if pattern.match(path) and (user in users or "*" in users):
+                ret = perms
+        return ret
+
+class SVNLook:
+    def __init__(self, repospath, txn=None, rev=None):
+        self.repospath = repospath
+        self.txn = txn
+        self.rev = rev
+
+    def _execcmd(self, *cmd, **kwargs):
+        cmdstr = " ".join(cmd)
+        status, output = commands.getstatusoutput(cmdstr)
+        if status != 0:
+            sys.stderr.write(cmdstr)
+            sys.stderr.write("\n")
+            sys.stderr.write(output)
+            raise Error, "command failed: %s\n%s" % (cmdstr, output)
+        return status, output
+
+    def _execsvnlook(self, cmd, *args, **kwargs):
+        execcmd_args = ["svnlook", cmd, self.repospath]
+        self._add_txnrev(execcmd_args, kwargs)
+        execcmd_args += args
+        execcmd_kwargs = {}
+        keywords = ["show", "noerror"]
+        for key in keywords:
+            if kwargs.has_key(key):
+                execcmd_kwargs[key] = kwargs[key]
+        return self._execcmd(*execcmd_args, **execcmd_kwargs)
+
+    def _add_txnrev(self, cmd_args, received_kwargs):
+        if received_kwargs.has_key("txn"):
+            txn = received_kwargs.get("txn")
+            if txn is not None:
+                cmd_args += ["-t", txn]
+        elif self.txn is not None:
+            cmd_args += ["-t", self.txn]
+        if received_kwargs.has_key("rev"):
+            rev = received_kwargs.get("rev")
+            if rev is not None:
+                cmd_args += ["-r", rev]
+        elif self.rev is not None:
+            cmd_args += ["-r", self.rev]
+
+    def changed(self, **kwargs):
+        status, output = self._execsvnlook("changed", **kwargs)
+        if status != 0:
+            return None
+        changes = []
+        for line in output.splitlines():
+            line = line.rstrip()
+            if not line: continue
+            entry = [None, None, None]
+            changedata, changeprop, path = None, None, None
+            if line[0] != "_":
+                changedata = line[0]
+            if line[1] != " ":
+                changeprop = line[1]
+            path = line[4:]
+            changes.append((changedata, changeprop, path))
+        return changes
+
+    def author(self, **kwargs):
+        status, output = self._execsvnlook("author", **kwargs)
+        if status != 0:
+            return None
+        return output.strip()
+
+
+def check_perms(filename, section, repos, txn=None, rev=None, author=None):
+    svnlook = SVNLook(repos, txn=txn, rev=rev)
+    if author is None:
+        author = svnlook.author()
+    changes = svnlook.changed()
+    try:
+        config = Config(filename)
+    except IOError:
+        raise Error, "can't read config file "+filename
+    if not section in config.sections():
+        raise Error, "section '%s' not found in config file" % section
+    perm = Permission()
+    perm.parse_groups(config.walk("groups"))
+    perm.parse_groups(config.walk(section+" groups"))
+    perm.parse_perms(config.walk(section))
+    permerrors = []
+    for changedata, changeprop, path in changes:
+        pathperms = perm.get(author, path)
+        if changedata == "A" and "add" not in pathperms:
+            permerrors.append("you can't add "+path)
+        elif changedata == "U" and "update" not in pathperms:
+            permerrors.append("you can't update "+path)
+        elif changedata == "D" and "remove" not in pathperms:
+            permerrors.append("you can't remove "+path)
+        elif changeprop == "U" and "update" not in pathperms:
+            permerrors.append("you can't update properties of "+path)
+        #else:
+        #    print "cdata=%s cprop=%s path=%s perms=%s" % \
+        #          (str(changedata), str(changeprop), path, str(pathperms))
+    if permerrors:
+        permerrors.insert(0, "you don't have enough permissions for "
+                             "this transaction:")
+        raise Error, "\n".join(permerrors)
+
+
+# Command:
+
+USAGE = """\
+Usage: svnperms.py OPTIONS
+
+Options:
+    -r PATH    Use repository at PATH to check transactions
+    -t TXN     Query transaction TXN for commit information
+    -f PATH    Use PATH as configuration file (default is repository
+               path + /conf/svnperms.conf)
+    -s NAME    Use section NAME as permission section (default is
+               repository name, extracted from repository path)
+    -R REV     Query revision REV for commit information (for tests)
+    -A AUTHOR  Check commit as if AUTHOR had commited it (for tests)
+    -h         Show this message
+"""
+
+class MissingArgumentsException(Exception):
+    "Thrown when required arguments are missing."
+    pass
+
+def parse_options():
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "f:s:r:t:R:A:h", ["help"])
+    except getopt.GetoptError, e:
+        raise Error, e.msg
+    class Options: pass
+    obj = Options()
+    obj.filename = None
+    obj.section = None
+    obj.repository = None
+    obj.transaction = None
+    obj.revision = None
+    obj.author = None
+    for opt, val in opts:
+        if opt == "-f":
+            obj.filename = val
+        elif opt == "-s":
+            obj.section = val
+        elif opt == "-r":
+            obj.repository = val
+        elif opt == "-t":
+            obj.transaction = val
+        elif opt == "-R":
+            obj.revision = val
+        elif opt == "-A":
+            obj.author = val
+        elif opt in ["-h", "--help"]:
+            sys.stdout.write(USAGE)
+            sys.exit(0)
+    missingopts = []
+    if not obj.repository:
+        missingopts.append("repository")
+    if not (obj.transaction or obj.revision):
+        missingopts.append("either transaction or a revision")
+    if missingopts:
+        raise MissingArgumentsException, \
+              "missing required option(s): " + ", ".join(missingopts)
+    obj.repository = os.path.abspath(obj.repository)
+    if obj.filename is None:
+        obj.filename = os.path.join(obj.repository, "conf", "svnperms.conf")
+    if obj.section is None:
+        obj.section = os.path.basename(obj.repository)
+    if not (os.path.isdir(obj.repository) and
+            os.path.isdir(os.path.join(obj.repository, "db")) and
+            os.path.isdir(os.path.join(obj.repository, "hooks")) and
+            os.path.isfile(os.path.join(obj.repository, "format"))):
+        raise Error, "path '%s' doesn't look like a repository" % \
+                     obj.repository
+        
+    return obj
+
+def main():
+    try:
+        opts = parse_options()
+        check_perms(opts.filename, opts.section,
+                    opts.repository, opts.transaction, opts.revision,
+                    opts.author)
+    except MissingArgumentsException, e:
+        sys.stderr.write("%s\n" % str(e))
+        sys.stderr.write(USAGE)
+        sys.exit(1)
+    except Error, e:
+        sys.stderr.write("error: %s\n" % str(e))
+        sys.exit(1)
+
+if __name__ == "__main__":
+    main()
+
+# vim:et:ts=4:sw=4
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/calendar.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/calendar.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/calendar.f90	(revision 329)
@@ -0,0 +1,1044 @@
+MODULE calendar
+!-
+!$Id: calendar.f90 693 2009-07-29 15:49:31Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+!- This is the calendar which going to be used to do all
+!- calculations on time. Three types of calendars are possible :
+!-
+!-  - gregorian :
+!-      The normal calendar. The time origin for the
+!-      julian day in this case is 24 Nov -4713
+!-      (other names : 'standard','proleptic_gregorian')
+!-  - noleap :
+!-      A 365 day year without leap years.
+!-      The origin for the julian days is in this case 1 Jan 0
+!-      (other names : '365_day','365d')
+!-  - all_leap :
+!-      A 366 day year with leap years.
+!-      The origin for the julian days is in this case ????
+!-      (other names : '366_day','366d'
+!-  - julian :
+!-      same as gregorian, but with all leap century years
+!-  - xxxd :
+!-      Year of xxx days with month of equal length.
+!-      The origin for the julian days is then also 1 Jan 0
+!-
+!- As one can see it is difficult to go from one calendar to the other.
+!- All operations involving julian days will be wrong.
+!- This calendar will lock as soon as possible
+!- the length of the year and forbid any further modification.
+!-
+!- For the non leap-year calendar the method is still brute force.
+!- We need to find an Integer series which takes care of the length
+!- of the various month. (Jan)
+!-
+!-   one_day  : one day in seconds
+!-   one_year : one year in days
+!---------------------------------------------------------------------
+  USE stringop,ONLY  : strlowercase
+  USE errioipsl,ONLY : ipslerr
+!-
+  PRIVATE
+  PUBLIC :: ymds2ju,ju2ymds,tlen2itau,isittime,ioconf_calendar, &
+ &          ioget_calendar,ioget_mon_len,ioget_year_len,itau2date, &
+ &          ioget_timestamp,ioconf_startdate,itau2ymds, &
+ &          time_diff,time_add,lock_calendar
+!-
+  INTERFACE ioget_calendar
+    MODULE PROCEDURE &
+ &    ioget_calendar_real1,ioget_calendar_real2,ioget_calendar_str
+  END INTERFACE
+!-
+  INTERFACE ioconf_startdate
+     MODULE PROCEDURE &
+ &    ioconf_startdate_simple,ioconf_startdate_internal, &
+ &    ioconf_startdate_ymds
+  END INTERFACE
+!-
+  REAL,PARAMETER :: one_day = 86400.0
+  LOGICAL,SAVE :: lock_startdate = .FALSE.
+!-
+  CHARACTER(LEN=30),SAVE :: time_stamp='XXXXXXXXXXXXXXXX'
+!-
+!- Description of calendar
+!-
+  CHARACTER(LEN=20),SAVE :: calendar_used="gregorian"
+  LOGICAL,SAVE :: lock_one_year = .FALSE.
+  REAL,SAVE :: one_year = 365.2425
+  INTEGER,SAVE :: mon_len(12)=(/31,28,31,30,31,30,31,31,30,31,30,31/)
+!-
+  CHARACTER(LEN=3),PARAMETER :: &
+ &  cal(12) = (/'JAN','FEB','MAR','APR','MAY','JUN', &
+ &              'JUL','AUG','SEP','OCT','NOV','DEC'/)
+!-
+  REAL,SAVE :: start_day,start_sec
+!-
+CONTAINS
+!-
+!===
+!-
+SUBROUTINE lock_calendar (new_status,old_status)
+!!--------------------------------------------------------------------
+!! The "lock_calendar" routine
+!! allows to lock or unlock the calendar,
+!! and to know the current status of the calendar.
+!! Be careful !
+!!
+!! SUBROUTINE lock_calendar (new_status,old_status)
+!!
+!! Optional INPUT argument
+!!
+!! (L) new_status : new status of the calendar
+!!
+!! Optional OUTPUT argument
+!!
+!! (L) old_status : current status of the calendar
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  LOGICAL,OPTIONAL,INTENT(IN)  :: new_status
+  LOGICAL,OPTIONAL,INTENT(OUT) :: old_status
+!---------------------------------------------------------------------
+  IF (PRESENT(old_status)) THEN
+    old_status = lock_one_year
+  ENDIF
+  IF (PRESENT(new_status)) THEN
+    lock_one_year = new_status
+  ENDIF
+!---------------------------
+END SUBROUTINE lock_calendar
+!-
+!===
+!-
+SUBROUTINE ymds2ju (year,month,day,sec,julian)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year,month,day
+  REAL,INTENT(IN)    :: sec
+!-
+  REAL,INTENT(OUT) :: julian
+!-
+  INTEGER :: julian_day
+  REAL    :: julian_sec
+!---------------------------------------------------------------------
+  CALL ymds2ju_internal (year,month,day,sec,julian_day,julian_sec)
+!-
+  julian = julian_day+julian_sec/one_day
+!---------------------
+END SUBROUTINE ymds2ju
+!-
+!===
+!-
+SUBROUTINE ymds2ju_internal (year,month,day,sec,julian_day,julian_sec)
+!---------------------------------------------------------------------
+!- Converts year, month, day and seconds into a julian day
+!-
+!- In 1968 in a letter to the editor of Communications of the ACM
+!- (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel
+!- and Thomas C. Van Flandern presented such an algorithm.
+!-
+!- See also : http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm
+!-
+!- In the case of the Gregorian calendar we have chosen to use
+!- the Lilian day numbers. This is the day counter which starts
+!- on the 15th October 1582.
+!- This is the day at which Pope Gregory XIII introduced the
+!- Gregorian calendar.
+!- Compared to the true Julian calendar, which starts some
+!- 7980 years ago, the Lilian days are smaler and are dealt with
+!- easily on 32 bit machines. With the true Julian days you can only
+!- the fraction of the day in the real part to a precision of
+!- a 1/4 of a day with 32 bits.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year,month,day
+  REAL,INTENT(IN)    :: sec
+!-
+  INTEGER,INTENT(OUT) :: julian_day
+  REAL,INTENT(OUT)    :: julian_sec
+!-
+  INTEGER :: jd,m,y,d,ml
+!---------------------------------------------------------------------
+  lock_one_year = .TRUE.
+!-
+  m = month
+  y = year
+  d = day
+!-
+!- We deduce the calendar from the length of the year as it
+!- is faster than an INDEX on the calendar variable.
+!-
+  IF ( (one_year > 365.0).AND.(one_year < 366.0) ) THEN
+!-- "Gregorian"
+    jd = (1461*(y+4800+INT((m-14)/12)))/4 &
+ &      +(367*(m-2-12*(INT((m-14)/12))))/12 &
+ &      -(3*((y+4900+INT((m-14)/12))/100))/4 &
+ &      +d-32075
+    jd = jd-2299160
+  ELSE IF (    (ABS(one_year-365.0) <= EPSILON(one_year))  &
+ &         .OR.(ABS(one_year-366.0) <= EPSILON(one_year)) ) THEN
+!-- "No leap" or "All leap"
+    ml = SUM(mon_len(1:m-1))
+    jd = y*NINT(one_year)+ml+(d-1)
+  ELSE
+!-- Calendar with regular month
+    ml = NINT(one_year/12.)
+    jd = y*NINT(one_year)+(m-1)*ml+(d-1)
+  ENDIF
+!-
+  julian_day = jd
+  julian_sec = sec
+!------------------------------
+END SUBROUTINE ymds2ju_internal
+!-
+!===
+!-
+SUBROUTINE ju2ymds (julian,year,month,day,sec)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL,INTENT(IN) :: julian
+!-
+  INTEGER,INTENT(OUT) :: year,month,day
+  REAL,INTENT(OUT)    :: sec
+!-
+  INTEGER :: julian_day
+  REAL    :: julian_sec
+!---------------------------------------------------------------------
+  julian_day = INT(julian)
+  julian_sec = (julian-julian_day)*one_day
+!-
+  CALL ju2ymds_internal(julian_day,julian_sec,year,month,day,sec)
+!---------------------
+END SUBROUTINE ju2ymds
+!-
+!===
+!-
+SUBROUTINE ju2ymds_internal (julian_day,julian_sec,year,month,day,sec)
+!---------------------------------------------------------------------
+!- This subroutine computes from the julian day the year,
+!- month, day and seconds
+!-
+!- In 1968 in a letter to the editor of Communications of the ACM
+!- (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel
+!- and Thomas C. Van Flandern presented such an algorithm.
+!-
+!- See also : http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm
+!-
+!- In the case of the Gregorian calendar we have chosen to use
+!- the Lilian day numbers. This is the day counter which starts
+!- on the 15th October 1582. This is the day at which Pope
+!- Gregory XIII introduced the Gregorian calendar.
+!- Compared to the true Julian calendar, which starts some 7980
+!- years ago, the Lilian days are smaler and are dealt with easily
+!- on 32 bit machines. With the true Julian days you can only the
+!- fraction of the day in the real part to a precision of a 1/4 of
+!- a day with 32 bits.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: julian_day
+  REAL,INTENT(IN)    :: julian_sec
+!-
+  INTEGER,INTENT(OUT) :: year,month,day
+  REAL,INTENT(OUT)    :: sec
+!-
+  INTEGER :: l,n,i,jd,j,d,m,y,ml
+  INTEGER :: add_day
+  REAL :: eps_day
+!---------------------------------------------------------------------
+  eps_day = SPACING(one_day)
+  lock_one_year = .TRUE.
+!-
+  jd = julian_day
+  sec = julian_sec
+  IF (sec > (one_day-eps_day)) THEN
+    add_day = INT(sec/one_day)
+    sec = sec-add_day*one_day
+    jd = jd+add_day
+  ENDIF
+  IF (sec < -eps_day) THEN
+    sec = sec+one_day
+    jd = jd-1
+  ENDIF
+!-
+  IF ( (one_year > 365.0).AND.(one_year < 366.0) ) THEN
+!-- Gregorian
+    jd = jd+2299160
+!-
+    l = jd+68569
+    n = (4*l)/146097
+    l = l-(146097*n+3)/4
+    i = (4000*(l+1))/1461001
+    l = l-(1461*i)/4+31
+    j = (80*l)/2447
+    d = l-(2447*j)/80
+    l = j/11
+    m = j+2-(12*l)
+    y = 100*(n-49)+i+l
+  ELSE IF (    (ABS(one_year-365.0) <= EPSILON(one_year)) &
+ &         .OR.(ABS(one_year-366.0) <= EPSILON(one_year)) ) THEN
+!-- No leap or All leap
+    y = jd/NINT(one_year)
+    l = jd-y*NINT(one_year)
+    m = 1
+    ml = 0
+    DO WHILE (ml+mon_len(m) <= l)
+      ml = ml+mon_len(m)
+      m = m+1
+    ENDDO
+    d = l-ml+1
+  ELSE
+!-- others
+    ml = NINT(one_year/12.)
+    y = jd/NINT(one_year)
+    l = jd-y*NINT(one_year)
+    m = (l/ml)+1
+    d = l-(m-1)*ml+1
+  ENDIF
+!-
+  day = d
+  month = m
+  year = y
+!------------------------------
+END SUBROUTINE ju2ymds_internal
+!-
+!===
+!-
+SUBROUTINE tlen2itau (input_str,dt,date,itau)
+!---------------------------------------------------------------------
+!- This subroutine transforms a string containing a time length
+!- into a number of time steps.
+!- To do this operation the date (in julian days is needed as the
+!- length of the month varies.
+!- The following convention is used :
+!-   n   : n time steps
+!-   nS  : n seconds is transformed into itaus
+!-   nH  : n hours
+!-   nD  : n days
+!-   nM  : n month
+!-   nY  : n years
+!- Combinations are also possible
+!-   nYmD : nyears plus m days !
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: input_str
+  REAL,INTENT(IN)             :: dt,date
+!-
+  INTEGER,INTENT(OUT)         :: itau
+!-
+  INTEGER           :: y_pos,m_pos,d_pos,h_pos,s_pos
+  INTEGER           :: read_time
+  CHARACTER(LEN=13) :: fmt
+  CHARACTER(LEN=80) :: tmp_str
+!-
+  INTEGER :: year,month,day
+  REAL    :: sec,date_new,dd,ss
+!---------------------------------------------------------------------
+  itau = 0
+  CALL ju2ymds (date,year,month,day,sec)
+!-
+  y_pos = MAX(INDEX(input_str,'y'),INDEX(input_str,'Y'))
+  m_pos = MAX(INDEX(input_str,'m'),INDEX(input_str,'M'))
+  d_pos = MAX(INDEX(input_str,'d'),INDEX(input_str,'D'))
+  h_pos = MAX(INDEX(input_str,'h'),INDEX(input_str,'H'))
+  s_pos = MAX(INDEX(input_str,'s'),INDEX(input_str,'S'))
+!-
+  IF (MAX(y_pos,m_pos,d_pos,s_pos) > 0) THEN
+    tmp_str = input_str
+    DO WHILE ( MAX(y_pos,m_pos,d_pos,s_pos) > 0)
+!---- WRITE(*,*) tmp_str
+!---- WRITE(*,*) y_pos,m_pos,d_pos,s_pos
+      IF (y_pos > 0) THEN
+        WRITE(fmt,'("(I",I10.10,")")') y_pos-1
+        READ(tmp_str(1:y_pos-1),fmt) read_time
+        CALL ymds2ju (year+read_time,month,day,sec,date_new)
+        dd = date_new-date
+        ss = INT(dd)*one_day+dd-INT(dd)
+        itau = itau+NINT(ss/dt)
+        tmp_str = tmp_str(y_pos+1:LEN_TRIM(tmp_str))
+      ELSE IF (m_pos > 0) THEN
+        WRITE(fmt,'("(I",I10.10,")")') m_pos-1
+        READ(tmp_str(1:m_pos-1),fmt) read_time
+        CALL ymds2ju (year,month+read_time,day,sec,date_new)
+        dd = date_new-date
+        ss = INT(dd)*one_day+dd-INT(dd)
+        itau = itau+NINT(ss/dt)
+        tmp_str = tmp_str(m_pos+1:LEN_TRIM(tmp_str))
+      ELSE IF (d_pos > 0) THEN
+        WRITE(fmt,'("(I",I10.10,")")') d_pos-1
+        READ(tmp_str(1:d_pos-1),fmt) read_time
+        itau = itau+NINT(read_time*one_day/dt)
+        tmp_str = tmp_str(d_pos+1:LEN_TRIM(tmp_str))
+      ELSE IF (h_pos > 0) THEN
+        WRITE(fmt,'("(I",I10.10,")")') h_pos-1
+        READ(tmp_str(1:h_pos-1),fmt) read_time
+        itau = itau+NINT(read_time*60.*60./dt)
+        tmp_str = tmp_str(d_pos+1:LEN_TRIM(tmp_str))
+      ELSE IF  (s_pos > 0) THEN
+        WRITE(fmt,'("(I",I10.10,")")') s_pos-1
+        READ(tmp_str(1:s_pos-1),fmt) read_time
+        itau = itau+NINT(read_time/dt)
+        tmp_str = tmp_str(s_pos+1:LEN_TRIM(tmp_str))
+      ENDIF
+!-
+      y_pos = MAX(INDEX(tmp_str,'y'),INDEX(tmp_str,'Y'))
+      m_pos = MAX(INDEX(tmp_str,'m'),INDEX(tmp_str,'M'))
+      d_pos = MAX(INDEX(tmp_str,'d'),INDEX(tmp_str,'D'))
+      h_pos = MAX(INDEX(tmp_str,'h'),INDEX(tmp_str,'H'))
+      s_pos = MAX(INDEX(tmp_str,'s'),INDEX(tmp_str,'S'))
+    ENDDO
+  ELSE
+    WRITE(fmt,'("(I",I10.10,")")') LEN_TRIM(input_str)
+    READ(input_str(1:LEN_TRIM(input_str)),fmt) itau
+  ENDIF
+!-----------------------
+END SUBROUTINE tlen2itau
+!-
+!===
+!-
+REAL FUNCTION itau2date (itau,date0,deltat)
+!---------------------------------------------------------------------
+!- This function transforms itau into a date. The date with which
+!- the time axis is going to be labeled
+!-
+!- INPUT
+!-   itau   : current time step
+!-   date0  : Date at which itau was equal to 0
+!-   deltat : time step between itau s
+!-
+!- OUTPUT
+!-   itau2date : Date for the given itau
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER  :: itau
+  REAL     :: date0,deltat
+!---------------------------------------------------------------------
+  itau2date = REAL(itau)*deltat/one_day+date0
+!---------------------
+END FUNCTION itau2date
+!-
+!===
+!-
+SUBROUTINE itau2ymds (itau,deltat,year,month,day,sec)
+!---------------------------------------------------------------------
+!- This subroutine transforms itau into a date. The date with which
+!- the time axis is going to be labeled
+!-
+!- INPUT
+!-   itau   : current time step
+!-   deltat : time step between itau s
+!-
+!- OUTPUT
+!-   year  : year
+!-   month : month
+!-   day   : day
+!-   sec   : seconds since midnight
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: itau
+  REAL,INTENT(IN)    :: deltat
+!-
+  INTEGER,INTENT(OUT) :: year,month,day
+  REAL,INTENT(OUT)    :: sec
+!-
+  INTEGER :: julian_day
+  REAL    :: julian_sec
+!---------------------------------------------------------------------
+  IF (.NOT.lock_startdate) THEN
+    CALL ipslerr (2,'itau2ymds', &
+ &   'You try to call this function, itau2ymds, but you didn''t', &
+ &   ' call ioconf_startdate to initialize date0 in calendar.', &
+ &   ' Please call ioconf_startdate before itau2ymds.')
+  ENDIF
+  julian_day = start_day
+  julian_sec = start_sec+REAL(itau)*deltat
+  CALL ju2ymds_internal (julian_day,julian_sec,year,month,day,sec)
+!-----------------------
+END SUBROUTINE itau2ymds
+!-
+!===
+!-
+REAL FUNCTION dtchdate (itau,date0,old_dt,new_dt)
+!---------------------------------------------------------------------
+!- This function changes the date so that the simulation can
+!- continue with the same itau but a different dt.
+!-
+!- INPUT
+!-   itau   : current time step
+!-   date0  : Date at which itau was equal to 0
+!-   old_dt : Old time step between itaus
+!-   new_dt : New time step between itaus
+!-
+!- OUTPUT
+!-   dtchdate : Date for the given itau
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: itau
+  REAL,INTENT(IN)    :: date0,old_dt,new_dt
+!-
+  REAL :: rtime
+!---------------------------------------------------------------------
+  rtime = itau2date (itau,date0,old_dt)
+  dtchdate = rtime-REAL(itau)*new_dt/one_day
+!--------------------
+END FUNCTION dtchdate
+!-
+!===
+!-
+SUBROUTINE isittime &
+ &  (itau,date0,dt,freq,last_action,last_check,do_action)
+!---------------------------------------------------------------------
+!- This subroutine checks the time as come for a given action.
+!- This is computed from the current time-step(itau).
+!- Thus we need to have the time delta (dt), the frequency
+!- of the action (freq) and the last time it was done
+!- (last_action in units of itau).
+!- In order to extrapolate when will be the next check we need
+!- the time step of the last call (last_check).
+!-
+!- The test is done on the following condition :
+!- the distance from the current time to the time for the next
+!- action is smaller than the one from the next expected
+!- check to the next action.
+!- When the test is done on the time steps simplifactions make
+!- it more difficult to read in the code.
+!- For the real time case it is easier to understand !
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: itau
+  REAL,INTENT(IN)    :: dt,freq
+  INTEGER,INTENT(IN) :: last_action,last_check
+  REAL,INTENT(IN)    :: date0
+!-
+  LOGICAL,INTENT(OUT)  :: do_action
+!-
+  REAL :: dt_action,dt_check
+  REAL :: date_last_act,date_next_check,date_next_act, &
+ &        date_now,date_mp1,date_mpf
+  INTEGER :: year,month,monthp1,day,next_check_itau,next_act_itau
+  INTEGER :: yearp,dayp
+  REAL :: sec,secp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) THEN
+    WRITE(*,*) &
+ &    "isittime 1.0 ",itau,date0,dt,freq,last_action,last_check
+  ENDIF
+!-
+  IF (last_check >= 0) THEN
+    dt_action = (itau-last_action)*dt
+    dt_check = (itau-last_check)*dt
+    next_check_itau = itau+(itau-last_check)
+!-
+!-- We are dealing with frequencies in seconds and thus operation
+!-- can be done on the time steps.
+!-
+    IF (freq > 0) THEN
+      IF (ABS(dt_action-freq) <= ABS(dt_action+dt_check-freq)) THEN
+        do_action = .TRUE.
+      ELSE
+        do_action = .FALSE.
+      ENDIF
+!-
+!---- Here we deal with frequencies in month and work on julian days.
+!-
+    ELSE
+      date_now = itau2date (itau,date0,dt)
+      date_last_act = itau2date (last_action,date0,dt)
+      CALL ju2ymds (date_last_act,year,month,day,sec)
+      monthp1 = month-freq
+      yearp = year
+!-
+!---- Here we compute what logically should be the next month
+!-
+      IF (month >= 13) THEN
+        yearp = year+1
+        monthp1 = monthp1-12
+      ENDIF
+      CALL ymds2ju (year,monthp1,day,sec,date_mpf)
+!-
+!---- But it could be that because of a shorter month or a bad
+!---- starting date that we end up further than we should be.
+!---- Thus we compute the first day of the next month.
+!---- We can not be beyond this date and if we are close
+!---- then we will take it as it is better.
+!-
+      monthp1 = month+ABS(freq)
+      yearp=year
+      IF (monthp1 >= 13) THEN
+        yearp = year+1
+        monthp1 = monthp1 -12
+      ENDIF
+      dayp = 1
+      secp = 0.0
+      CALL ymds2ju (yearp,monthp1,dayp,secp,date_mp1)
+!-
+!---- If date_mp1 is smaller than date_mpf or only less than 4 days
+!---- larger then we take it. This needed to ensure that short month
+!---- like February do not mess up the thing !
+!-
+      IF (date_mp1-date_mpf < 4.) THEN
+        date_next_act = date_mp1
+      ELSE
+        date_next_act = date_mpf
+      ENDIF
+      date_next_check = itau2date (next_check_itau,date0,dt)
+!-
+!---- Transform the dates into time-steps for the needed precisions.
+!-
+      next_act_itau = &
+ &      last_action+INT((date_next_act-date_last_act)*(one_day/dt))
+!-----
+      IF (   ABS(itau-next_act_itau) &
+ &        <= ABS( next_check_itau-next_act_itau)) THEN
+        do_action = .TRUE.
+        IF (check) THEN
+          WRITE(*,*) &
+ &         'ACT-TIME : itau, next_act_itau, next_check_itau : ', &
+ &         itau,next_act_itau,next_check_itau
+          CALL ju2ymds (date_now,year,month,day,sec)
+          WRITE(*,*) 'ACT-TIME : y, m, d, s : ',year,month,day,sec
+          WRITE(*,*) &
+ &         'ACT-TIME : date_mp1, date_mpf : ',date_mp1,date_mpf
+        ENDIF
+      ELSE
+        do_action = .FALSE.
+      ENDIF
+    ENDIF
+!-
+    IF (check) THEN
+      WRITE(*,*) "isittime 2.0 ", &
+ &     date_next_check,date_next_act,ABS(dt_action-freq), &
+ &     ABS(dt_action+dt_check-freq),dt_action,dt_check, &
+ &     next_check_itau,do_action
+    ENDIF
+  ELSE
+    do_action=.FALSE.
+  ENDIF
+!----------------------
+END SUBROUTINE isittime
+!-
+!===
+!-
+SUBROUTINE ioconf_calendar (str)
+!---------------------------------------------------------------------
+!- This routine allows to configure the calendar to be used.
+!- This operation is only allowed once and the first call to
+!- ymds2ju or ju2ymsd will lock the current configuration.
+!- the argument to ioconf_calendar can be any of the following :
+!-  - gregorian : This is the gregorian calendar (default here)
+!-  - noleap    : A calendar without leap years = 365 days
+!-  - xxxd      : A calendar of xxx days (has to be a modulo of 12)
+!-                with 12 month of equal length
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: str
+!-
+  INTEGER :: leng,ipos
+  CHARACTER(LEN=20) :: str_w
+!---------------------------------------------------------------------
+!-
+! Clean up the string !
+!-
+  str_w = str
+  CALL strlowercase (str_w)
+!-
+  IF (.NOT.lock_one_year) THEN
+!---
+    lock_one_year=.TRUE.
+!---
+    SELECT CASE(TRIM(str_w))
+    CASE('gregorian','standard','proleptic_gregorian')
+      calendar_used = 'gregorian'
+      one_year = 365.2425
+      mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/)
+    CASE('noleap','365_day','365d')
+      calendar_used = 'noleap'
+      one_year = 365.0
+      mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/)
+    CASE('all_leap','366_day','366d')
+      calendar_used = 'all_leap'
+      one_year = 366.0
+      mon_len(:)=(/31,29,31,30,31,30,31,31,30,31,30,31/)
+    CASE('360_day','360d')
+      calendar_used = '360d'
+      one_year = 360.0
+      mon_len(:)=(/30,30,30,30,30,30,30,30,30,30,30,30/)
+    CASE('julian')
+      calendar_used = 'julian'
+      one_year = 365.25
+      mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/)
+    CASE DEFAULT
+      ipos = INDEX(str_w,'d')
+      IF (ipos == 4) THEN
+        READ(str_w(1:3),'(I3)') leng
+        IF ( (MOD(leng,12) == 0).AND.(leng > 1) ) THEN
+          calendar_used = str_w
+          one_year = leng
+          mon_len(:) = leng/12
+        ELSE
+          CALL ipslerr (3,'ioconf_calendar', &
+ &         'The length of the year as to be a modulo of 12', &
+ &         'so that it can be divided into 12 month of equal length', &
+ &         TRIM(str_w))
+        ENDIF
+      ELSE
+        CALL ipslerr (3,'ioconf_calendar', &
+ &       'Unrecognized input, please check the man pages.', &
+ &       TRIM(str_w),' ')
+      ENDIF
+    END SELECT
+  ELSE IF (TRIM(str_w) /= TRIM(calendar_used)) THEN
+    WRITE(str_w,'(f10.4)') one_year
+    CALL ipslerr (2,'ioconf_calendar', &
+ &   'The calendar was already used or configured to : '// &
+ &    TRIM(calendar_used)//'.', &
+ &   'You are not allowed to change it to : '//TRIM(str)//'.', &
+ &   'The following length of year is used : '//TRIM(ADJUSTL(str_w)))
+  ENDIF
+!-----------------------------
+END SUBROUTINE ioconf_calendar
+!-
+!===
+!-
+SUBROUTINE ioconf_startdate_simple (julian)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL,INTENT(IN) :: julian
+!-
+  INTEGER :: julian_day
+  REAL    :: julian_sec
+!---------------------------------------------------------------------
+  julian_day = INT(julian)
+  julian_sec = (julian-julian_day)*one_day
+!-
+  CALL ioconf_startdate_internal (julian_day,julian_sec)
+!-------------------------------------
+END SUBROUTINE ioconf_startdate_simple
+!-
+!===
+!-
+SUBROUTINE ioconf_startdate_ymds (year,month,day,sec)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year,month,day
+  REAL,INTENT(IN)    :: sec
+!-
+  INTEGER :: julian_day
+  REAL    :: julian_sec
+!---------------------------------------------------------------------
+  CALL ymds2ju_internal (year,month,day,sec,julian_day,julian_sec)
+!-
+  CALL ioconf_startdate_internal (julian_day,julian_sec)
+!-----------------------------------
+END SUBROUTINE ioconf_startdate_ymds
+!-
+!===
+!-
+SUBROUTINE ioconf_startdate_internal (julian_day,julian_sec)
+!---------------------------------------------------------------------
+! This subroutine allows to set the startdate for later
+! use. It allows the applications to access the date directly from
+! the timestep. In order to avoid any problems the start date will
+! be locked and can not be changed once set.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN)  :: julian_day
+  REAL,INTENT(IN)     :: julian_sec
+!-
+  CHARACTER(len=70) :: str70a,str70b
+!---------------------------------------------------------------------
+  IF (.NOT.lock_startdate) THEN
+    start_day = julian_day
+    start_sec = julian_sec
+    lock_startdate = .TRUE.
+  ELSE
+    WRITE(str70a,'("The date you tried to set : ",f10.4)') &
+ &   julian_day,julian_sec/one_day
+    WRITE(str70b, &
+ &   '("The date which was already set in the calendar : ",f10.4)') &
+ &   start_day+start_sec/one_day
+    CALL ipslerr (2,'ioconf_startdate', &
+ &   'The start date has already been set and you tried to change it', &
+ &   str70a,str70b)
+  ENDIF
+!---------------------------------------
+END SUBROUTINE ioconf_startdate_internal
+!-
+!===
+!-
+SUBROUTINE ioget_calendar_str (str)
+!---------------------------------------------------------------------
+!- This subroutine returns the name of the calendar used here.
+!- Three options exist :
+!-  - gregorian : This is the gregorian calendar (default here)
+!-  - noleap    : A calendar without leap years = 365 days
+!-  - xxxd      : A calendar of xxx days (has to be a modulo of 12)
+!-                with 12 month of equal length
+!-
+!- This routine will lock the calendar.
+!- You do not want it to change after your inquiry.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(OUT) :: str
+!---------------------------------------------------------------------
+  lock_one_year = .TRUE.
+!-
+  str = calendar_used
+!--------------------------------
+END SUBROUTINE ioget_calendar_str
+!-
+!===
+!-
+SUBROUTINE ioget_calendar_real1 (long_year)
+!---------------------------------------------------------------------
+!- This subroutine returns the name of the calendar used here.
+!- Three options exist :
+!-  - gregorian : This is the gregorian calendar (default here)
+!-  - noleap    : A calendar without leap years = 365 days
+!-  - xxxd      : A calendar of xxx days (has to be a modulo of 12)
+!-                with 12 month of equal length
+!-
+!- This routine will lock the calendar.
+!- You do not want it to change after your inquiry.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL,INTENT(OUT) :: long_year
+!---------------------------------------------------------------------
+  long_year = one_year
+  lock_one_year = .TRUE.
+!----------------------------------
+END SUBROUTINE ioget_calendar_real1
+!-
+!===
+!-
+SUBROUTINE ioget_calendar_real2 (long_year,long_day)
+!---------------------------------------------------------------------
+!- This subroutine returns the name of the calendar used here.
+!- Three options exist :
+!-  - gregorian : This is the gregorian calendar (default here)
+!-  - noleap    : A calendar without leap years = 365 days
+!-  - xxxd      : A calendar of xxx days (has to be a modulo of 12)
+!-                with 12 month of equal length
+!-
+!- This routine will lock the calendar.
+!- You do not want it to change after your inquiry.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL,INTENT(OUT) :: long_year,long_day
+!---------------------------------------------------------------------
+  long_year = one_year
+  long_day  = one_day
+  lock_one_year = .TRUE.
+!----------------------------------
+END SUBROUTINE ioget_calendar_real2
+!-
+!===
+!-
+INTEGER FUNCTION ioget_mon_len (year,month)
+!!--------------------------------------------------------------------
+!! The "ioget_mon_len" function returns
+!! the number of days in a "month" of a "year",
+!! in the current calendar.
+!!
+!! INTEGER FUNCTION ioget_mon_len (year,month)
+!!
+!! INPUT
+!!
+!! (I) year  : year
+!! (I) month : month in the year (1 --> 12)
+!!
+!! OUTPUT
+!!
+!! (I) ioget_mon_len : number of days in the month
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year,month
+!-
+  INTEGER :: ml
+!---------------------------------------------------------------------
+  IF ( (month >= 1).AND.(month <= 12) ) THEN
+    IF ( (one_year > 365.0).AND.(one_year < 366.0) ) THEN
+!---- "Gregorian" or "Julian"
+      ml = mon_len(month)
+      IF (month == 2) THEN
+        IF (ABS(one_year-365.2425) <= EPSILON(one_year) ) THEN
+!-------- "Gregorian"
+          IF (    ((MOD(year,4) == 0).AND.(MOD(year,100) /= 0)) &
+              .OR.(MOD(year,400) == 0) ) THEN
+            ml = ml+1
+          ENDIF
+        ELSE
+!-------- "Julian"
+          IF (MOD(year,4) == 0) THEN
+            ml = ml+1
+          ENDIF
+        ENDIF
+      ENDIF
+      ioget_mon_len = ml
+    ELSE
+!---- "No leap" or "All leap" or "Calendar with regular month"
+      ioget_mon_len = mon_len(month)
+    ENDIF
+  ELSE
+    CALL ipslerr (3,'ioget_mon_len', &
+ &    'The number of the month','must be between','1 and 12')
+  ENDIF
+!-------------------------
+END FUNCTION ioget_mon_len
+!-
+!===
+!-
+INTEGER FUNCTION ioget_year_len (year)
+!!--------------------------------------------------------------------
+!! The "ioget_year_len" function returns
+!! the number of days in "year", in the current calendar.
+!!
+!! INTEGER FUNCTION ioget_year_len (year)
+!!
+!! INPUT
+!!
+!! (I) year  : year
+!!
+!! OUTPUT
+!!
+!! (I) ioget_year_len : number of days in the year
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year
+!-
+  INTEGER :: yl
+!---------------------------------------------------------------------
+  SELECT CASE(TRIM(calendar_used))
+  CASE('gregorian')
+    yl = 365
+    IF (    ((MOD(year,4) == 0).AND.(MOD(year,100) /= 0)) &
+        .OR.(MOD(year,400) == 0) ) THEN
+      yl = yl+1
+    ENDIF
+  CASE('julian')
+    yl = 365
+    IF (MOD(year,4) == 0) THEN
+      yl = yl+1
+    ENDIF
+  CASE DEFAULT
+    yl = NINT(one_year)
+  END SELECT
+  ioget_year_len = yl
+!--------------------------
+END FUNCTION ioget_year_len
+!-
+!===
+!-
+SUBROUTINE ioget_timestamp (string)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=30),INTENT(OUT) :: string
+!-
+  INTEGER :: date_time(8)
+  CHARACTER(LEN=10) :: bigben(3)
+!---------------------------------------------------------------------
+  IF (INDEX(time_stamp,'XXXXXX') > 0) THEN
+    CALL DATE_AND_TIME (bigben(1),bigben(2),bigben(3),date_time)
+!---
+    WRITE(time_stamp, &
+ &   "(I4.4,'-',A3,'-',I2.2,' ',I2.2,':',I2.2,':',I2.2,' GMT',a5)") &
+ &   date_time(1),cal(date_time(2)),date_time(3),date_time(5), &
+ &   date_time(6),date_time(7),bigben(3)
+  ENDIF
+!-
+  string = time_stamp
+!-----------------------------
+END SUBROUTINE ioget_timestamp
+!-
+!===
+!-
+SUBROUTINE time_add &
+ &  (year_s,month_s,day_s,sec_s,sec_increment, &
+ &   year_e,month_e,day_e,sec_e)
+!---------------------------------------------------------------------
+!- This subroutine allows to increment a date by a number of seconds.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year_s,month_s,day_s
+  REAL,INTENT(IN)    :: sec_s
+!-
+! Time in seconds to be added to the date
+!-
+  REAL,INTENT(IN)    :: sec_increment
+!-
+  INTEGER,INTENT(OUT) :: year_e,month_e,day_e
+  REAL,INTENT(OUT)    :: sec_e
+!-
+  INTEGER :: julian_day
+  REAL    :: julian_sec
+!---------------------------------------------------------------------
+  CALL ymds2ju_internal &
+ &  (year_s,month_s,day_s,sec_s,julian_day,julian_sec)
+!-
+  julian_sec = julian_sec+sec_increment
+!-
+  CALL ju2ymds_internal &
+ &  (julian_day,julian_sec,year_e,month_e,day_e,sec_e)
+!----------------------
+END SUBROUTINE time_add
+!-
+!===
+!-
+SUBROUTINE time_diff &
+ &  (year_s,month_s,day_s,sec_s,year_e,month_e,day_e,sec_e,sec_diff)
+!---------------------------------------------------------------------
+!- This subroutine allows to determine the number of seconds
+!- between two dates.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: year_s,month_s,day_s
+  REAL,INTENT(IN)    :: sec_s
+  INTEGER,INTENT(IN) :: year_e,month_e,day_e
+  REAL,INTENT(IN)    :: sec_e
+!-
+! Time in seconds between the two dates
+!-
+  REAL,INTENT(OUT)    :: sec_diff
+!-
+  INTEGER :: julian_day_s,julian_day_e,day_diff
+  REAL    :: julian_sec_s,julian_sec_e
+!---------------------------------------------------------------------
+  CALL ymds2ju_internal &
+ &  (year_s,month_s,day_s,sec_s,julian_day_s,julian_sec_s)
+  CALL ymds2ju_internal &
+ &  (year_e,month_e,day_e,sec_e,julian_day_e,julian_sec_e)
+!-
+  day_diff = julian_day_e-julian_day_s
+  sec_diff = julian_sec_e-julian_sec_s
+!-
+  sec_diff = sec_diff+day_diff*one_day
+!-----------------------
+END SUBROUTINE time_diff
+!-
+!===
+!-
+END MODULE calendar
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/defprec.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/defprec.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/defprec.f90	(revision 329)
@@ -0,0 +1,23 @@
+! @author Jacques Bellier, Marie-Alice Foujols, Jan Polcher
+! @Version : $Revision: 2.1 $, $Date: 2005/06/24 09:57:17 $
+! $Header: /home/ioipsl/CVSROOT/IOIPSL/src/def.prec,v 2.1 2005/06/24 09:57:17 adm Exp $
+!
+MODULE defprec 
+!!--------------------------------------------------------------------
+!! The module "defprec" set default precision for computation
+!!
+!! This module should be used by every modules
+!! to keep the right precision for every variable
+!!--------------------------------------------------------------------
+!?INTEGERS of KIND 1 are not supported on all computers
+!?INTEGER,PARAMETER :: i_1=SELECTED_INT_KIND(2)
+  INTEGER,PARAMETER :: i_2=SELECTED_INT_KIND(4)
+  INTEGER,PARAMETER :: i_4=SELECTED_INT_KIND(9)
+  INTEGER,PARAMETER :: i_8=SELECTED_INT_KIND(13)
+  INTEGER,PARAMETER :: r_4=SELECTED_REAL_KIND(6,37)
+  INTEGER,PARAMETER :: r_8=SELECTED_REAL_KIND(15,307)
+!#-P-I4R4   INTEGER,PARAMETER :: i_std=i_4, r_std=r_4
+  INTEGER,PARAMETER :: i_std=i_4, r_std=r_8
+!#-P-I8R8   INTEGER,PARAMETER :: i_std=i_8, r_std=r_8
+!-----------------
+END MODULE defprec
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/errioipsl.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/errioipsl.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/errioipsl.f90	(revision 329)
@@ -0,0 +1,215 @@
+MODULE errioipsl
+!-
+!$Id: errioipsl.f90 759 2009-10-22 08:53:27Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+IMPLICIT NONE
+!-
+PRIVATE
+!-
+PUBLIC :: ipslnlf, ipslerr, ipslerr_act, ipslerr_inq, histerr, ipsldbg
+!-
+  INTEGER :: n_l=6, ilv_cur=0, ilv_max=0
+  LOGICAL :: ioipsl_debug=.FALSE., lact_mode=.TRUE.
+!-
+!===
+CONTAINS
+!===
+SUBROUTINE ipslnlf (new_number,old_number)
+!!--------------------------------------------------------------------
+!! The "ipslnlf" routine allows to know and modify
+!! the current logical number for the messages.
+!!
+!! SUBROUTINE ipslnlf (new_number,old_number)
+!!
+!! Optional INPUT argument
+!!
+!! (I) new_number : new logical number of the file
+!!
+!! Optional OUTPUT argument
+!!
+!! (I) old_number : current logical number of the file
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,OPTIONAL,INTENT(IN)  :: new_number
+  INTEGER,OPTIONAL,INTENT(OUT) :: old_number
+!---------------------------------------------------------------------
+  IF (PRESENT(old_number)) THEN
+    old_number = n_l
+  ENDIF
+  IF (PRESENT(new_number)) THEN
+    n_l = new_number
+  ENDIF
+!---------------------
+END SUBROUTINE ipslnlf
+!===
+SUBROUTINE ipslerr (plev,pcname,pstr1,pstr2,pstr3)
+!---------------------------------------------------------------------
+!! The "ipslerr" routine
+!! allows to handle the messages to the user.
+!!
+!! INPUT
+!!
+!! plev   : Category of message to be reported to the user
+!!          1 = Note to the user
+!!          2 = Warning to the user
+!!          3 = Fatal error
+!! pcname : Name of subroutine which has called ipslerr
+!! pstr1   
+!! pstr2  : Strings containing the explanations to the user
+!! pstr3
+!---------------------------------------------------------------------
+   IMPLICIT NONE
+!-
+   INTEGER :: plev
+   CHARACTER(LEN=*) :: pcname,pstr1,pstr2,pstr3
+!-
+   CHARACTER(LEN=30),DIMENSION(3) :: pemsg = &
+  &  (/ "NOTE TO THE USER FROM ROUTINE ", &
+  &     "WARNING FROM ROUTINE          ", &
+  &     "FATAL ERROR FROM ROUTINE      " /)
+!---------------------------------------------------------------------
+   IF ( (plev >= 1).AND.(plev <= 3) ) THEN
+     ilv_cur = plev
+     ilv_max = MAX(ilv_max,plev)
+     WRITE(n_l,'(/,A," ",A)') TRIM(pemsg(plev)),TRIM(pcname)
+     WRITE(n_l,'(3(" --> ",A,/))') TRIM(pstr1),TRIM(pstr2),TRIM(pstr3)
+   ENDIF
+   IF ( (plev == 3).AND.lact_mode) THEN
+     WRITE(n_l,'("Fatal error from IOIPSL. STOP in ipslerr with code")')
+     STOP 1
+   ENDIF
+!---------------------
+END SUBROUTINE ipslerr
+!===
+SUBROUTINE ipslerr_act (new_mode,old_mode)
+!!--------------------------------------------------------------------
+!! The "ipslerr_act" routine allows to know and modify
+!! the current "action mode" for the error messages,
+!! and reinitialize the error level values.
+!!
+!! SUBROUTINE ipslerr_act (new_mode,old_mode)
+!!
+!! Optional INPUT argument
+!!
+!! (I) new_mode : new error action mode
+!!                .TRUE.  -> STOP     in case of fatal error
+!!                .FALSE. -> CONTINUE in case of fatal error
+!!
+!! Optional OUTPUT argument
+!!
+!! (I) old_mode : current error action mode
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  LOGICAL,OPTIONAL,INTENT(IN)  :: new_mode
+  LOGICAL,OPTIONAL,INTENT(OUT) :: old_mode
+!---------------------------------------------------------------------
+  IF (PRESENT(old_mode)) THEN
+    old_mode = lact_mode
+  ENDIF
+  IF (PRESENT(new_mode)) THEN
+    lact_mode = new_mode
+  ENDIF
+  ilv_cur = 0
+  ilv_max = 0
+!-------------------------
+END SUBROUTINE ipslerr_act
+!===
+SUBROUTINE ipslerr_inq (current_level,maximum_level)
+!!--------------------------------------------------------------------
+!! The "ipslerr_inq" routine allows to know
+!! the current level of the error messages
+!! and the maximum level encountered since the
+!! last call to "ipslerr_act".
+!!
+!! SUBROUTINE ipslerr_inq (current_level,maximum_level)
+!!
+!! Optional OUTPUT argument
+!!
+!! (I) current_level : current error level
+!! (I) maximum_level : maximum error level
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,OPTIONAL,INTENT(OUT) :: current_level,maximum_level
+!---------------------------------------------------------------------
+  IF (PRESENT(current_level)) THEN
+    current_level = ilv_cur
+  ENDIF
+  IF (PRESENT(maximum_level)) THEN
+    maximum_level = ilv_max
+  ENDIF
+!-------------------------
+END SUBROUTINE ipslerr_inq
+!===
+SUBROUTINE histerr (plev,pcname,pstr1,pstr2,pstr3)
+!---------------------------------------------------------------------
+!- INPUT
+!- plev   : Category of message to be reported to the user
+!-          1 = Note to the user
+!-          2 = Warning to the user
+!-          3 = Fatal error
+!- pcname : Name of subroutine which has called histerr
+!- pstr1   
+!- pstr2  : String containing the explanations to the user
+!- pstr3
+!---------------------------------------------------------------------
+   IMPLICIT NONE
+!-
+   INTEGER :: plev
+   CHARACTER(LEN=*) :: pcname,pstr1,pstr2,pstr3
+!-
+   CHARACTER(LEN=30),DIMENSION(3) :: pemsg = &
+  &  (/ "NOTE TO THE USER FROM ROUTINE ", &
+  &     "WARNING FROM ROUTINE          ", &
+  &     "FATAL ERROR FROM ROUTINE      " /)
+!---------------------------------------------------------------------
+   IF ( (plev >= 1).AND.(plev <= 3) ) THEN
+     WRITE(*,'("     ")')
+     WRITE(*,'(A," ",A)') TRIM(pemsg(plev)),TRIM(pcname)
+     WRITE(*,'(" --> ",A)') pstr1
+     WRITE(*,'(" --> ",A)') pstr2
+     WRITE(*,'(" --> ",A)') pstr3
+   ENDIF
+   IF (plev == 3) THEN
+     STOP 'Fatal error from IOIPSL. See stdout for more details'
+   ENDIF
+!---------------------
+END SUBROUTINE histerr
+!===
+SUBROUTINE ipsldbg (new_status,old_status)
+!!--------------------------------------------------------------------
+!! The "ipsldbg" routine
+!! allows to activate or deactivate the debug,
+!! and to know the current status of the debug.
+!!
+!! SUBROUTINE ipsldbg (new_status,old_status)
+!!
+!! Optional INPUT argument
+!!
+!! (L) new_status : new status of the debug
+!!
+!! Optional OUTPUT argument
+!!
+!! (L) old_status : current status of the debug
+!!--------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  LOGICAL,OPTIONAL,INTENT(IN)  :: new_status
+  LOGICAL,OPTIONAL,INTENT(OUT) :: old_status
+!---------------------------------------------------------------------
+  IF (PRESENT(old_status)) THEN
+    old_status = ioipsl_debug
+  ENDIF
+  IF (PRESENT(new_status)) THEN
+    ioipsl_debug = new_status
+  ENDIF
+!---------------------
+END SUBROUTINE ipsldbg
+!===
+!-------------------
+END MODULE errioipsl
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/flincom.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/flincom.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/flincom.f90	(revision 329)
@@ -0,0 +1,1939 @@
+MODULE flincom
+!-
+!$Id: flincom.f90 427 2008-10-16 07:55:13Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+  USE netcdf
+!-
+  USE calendar,  ONLY : ju2ymds, ymds2ju, ioconf_calendar
+  USE errioipsl, ONLY : histerr
+  USE stringop,  ONLY : strlowercase
+!-
+  IMPLICIT NONE
+!-
+  PRIVATE
+  PUBLIC :: flinput, flincre, flinget, flinclo, &
+            flinopen, flininfo, flininspect, flinquery_var
+!-
+  INTERFACE flinopen
+!---------------------------------------------------------------------
+!- The "flinopen" routines will open an input file
+!-
+!- INPUT
+!-
+!- filename  : Name of the netCDF file to be opened
+!-
+!- iideb     : index i for zoom     !
+!- iilen     : length  of  zoom     !   for
+!- jjdeb     : index j for zoom     !   zoom
+!- jjlen     : length  of  zoom     !
+!-
+!- do_test   : A flag that enables the testing of the content
+!-             of the file against the input from the model
+!-
+!- INPUT if do_test=TRUE      OUTPUT else
+!-
+!- iim       : size in the x direction in the file (longitude)
+!- jjm       : size in the y direction
+!- llm       : number of levels
+!-             (llm = 0 means no axis to be expected)
+!- lon       : array of (iilen,jjlen) (zoom), or (iim,jjm) (no zoom),
+!-             that contains the longitude of each point
+!- lat       : same for latitude
+!- lev       : An array of llm for the latitude
+!-
+!- WARNING :
+!- In the case of do_test=FALSE it is for the user to check
+!- that the dimensions of lon lat and lev are correct when passed to
+!- flinopen. This can be done after the call when iim and jjm have
+!- been retrieved from the netCDF file. In F90 this problem will
+!- be solved with an internal assign
+!- IF iim, jjm, llm or ttm are parameters in the calling program and
+!- you use the option do_test=FALSE it will create a segmentation fault
+!-
+!-  OUTPUT
+!-
+!-  ttm       : size of time axis
+!-  itaus     : Time steps within this file
+!-  date0     : Julian date at which itau = 0
+!-  dt        : length of the time steps of the data
+!-  fid       : returned file ID which is later used to read the data
+!---------------------------------------------------------------------
+    MODULE PROCEDURE flinopen_zoom2d, flinopen_nozoom
+  END INTERFACE
+!-
+  INTERFACE flinput
+!---------------------------------------------------------------------
+!- The "flinput" routines will put a variable
+!- on the netCDF file created by flincre.
+!- If the sizes of the axis do not match the one of the IDs
+!- then a new axis is created.
+!- That is we loose the possibility of writting hyperslabs of data.
+!-
+!- Again here if iim = jjm = llm = ttm = 0
+!- then a global attribute is added to the file.
+!-
+!- INPUT
+!-
+!- fid      : Identification of the file in which we will write
+!- varname  : Name of variable to be written
+!- iim      : size in x of variable
+!- nlonid   : ID of x axis which could fit for this axis
+!- jjm      : size in y of variable
+!- nlatid   : ID of y axis which could fit for this axis
+!- llm      : size in z of variable
+!- zdimid   : ID of z axis which could fit for this axis
+!- ttm      : size in t of variable
+!- tdimid   : ID of t axis which could fit for this axis
+!-
+!- OUTPUT
+!-
+!- NONE
+!---------------------------------------------------------------------
+    MODULE PROCEDURE flinput_r4d, flinput_r3d, flinput_r2d, &
+                     flinput_r1d, flinput_scal
+  END INTERFACE
+!-
+  INTERFACE flinget
+    MODULE PROCEDURE flinget_r4d, flinget_r3d, flinget_r2d, &
+                     flinget_r1d, flinget_scal, &
+                     flinget_r4d_zoom2d, flinget_r3d_zoom2d, &
+                     flinget_r2d_zoom2d
+  END INTERFACE
+!-
+! This is the data we keep on each file we open
+!-
+  INTEGER, PARAMETER :: nbfile_max = 200
+  INTEGER, SAVE :: nbfiles = 0
+  INTEGER, SAVE :: ncids(nbfile_max), ncnbd(nbfile_max), &
+                   ncfunli(nbfile_max), ncnba(nbfile_max)
+  INTEGER, SAVE :: ncnbva(nbfile_max), ncdims(nbfile_max,4)
+  LOGICAL, SAVE :: ncfileopen(nbfile_max)=.FALSE.
+!-
+  INTEGER, SAVE :: cind_vid, cind_fid, cind_len
+  INTEGER,DIMENSION(:),ALLOCATABLE,SAVE :: cindex
+!-
+  INTEGER,DIMENSION(4) :: w_sta, w_len, w_dim
+!-
+CONTAINS
+!-
+!===
+!-
+SUBROUTINE flincre &
+  (filename, iim1, jjm1, lon1, lat1, llm1, lev1, ttm1, itaus, &
+   time0, dt, fid_out, nlonid1, nlatid1, zdimid1, tdimid1)
+!---------------------------------------------------------------------
+!- This is a "low level" subroutine for opening netCDF files wich
+!- contain the major coordinate system of the model.
+!- Other coordinates needed for other variables
+!- will be added as they are needed.
+!-
+!- INPUT
+!-
+!- filename    : Name of the file to be created
+!- iim1, jjm1  : Horizontal size of the grid
+!-               which will be stored in the file
+!- lon1, lat1  : Horizontal grids
+!- llm1        : Size of the vertical grid
+!- lev1        : Vertical grid
+!- ttm1        : Size of time axis
+!- itaus       : time steps on the time axis
+!- time0       : Time in julian days at which itau = 0
+!- dt          : time step in seconds between itaus
+!-               (one step of itau)
+!-
+!- OUTPUT
+!-
+!- fid         : File identification
+!- nlonid1     : Identification of longitudinal axis
+!- nlatid1     : Identification of latitudinal axis
+!- zdimid1     : ID of vertical axis
+!- tdimid1     : ID of time axis
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  CHARACTER(LEN=*) :: filename
+  INTEGER :: iim1, jjm1, llm1, ttm1
+  REAL :: lon1(iim1,jjm1)
+  REAL :: lat1(iim1,jjm1)
+  REAL :: lev1(llm1)
+  INTEGER :: itaus(ttm1)
+  REAL :: time0
+  REAL :: dt
+  INTEGER :: fid_out, zdimid1, nlonid1, nlatid1, tdimid1
+!-
+! LOCAL
+!-
+  INTEGER :: iret, lll, fid
+  INTEGER :: lonid, latid, levid, timeid
+  INTEGER :: year, month, day
+  REAL :: sec
+  CHARACTER(LEN=250):: name
+!-
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  lll = LEN_TRIM(filename)
+  IF (filename(lll-2:lll) /= '.nc') THEN
+    name=filename(1:lll)//'.nc'
+  ELSE
+    name=filename(1:lll)
+  ENDIF
+!-
+  iret = NF90_CREATE (name, NF90_CLOBBER, fid)
+!-
+  iret = NF90_DEF_DIM (fid, 'x',     iim1, nlonid1)
+  iret = NF90_DEF_DIM (fid, 'y',     jjm1, nlatid1)
+  iret = NF90_DEF_DIM (fid, 'lev',   llm1, zdimid1)
+  iret = NF90_DEF_DIM (fid, 'tstep', ttm1, tdimid1)
+!-
+! Vertical axis
+!-
+  IF (check) WRITE(*,*) 'flincre Vertical axis'
+!-
+  iret = NF90_DEF_VAR (fid, 'lev', NF90_FLOAT, zdimid1, levid)
+  iret = NF90_PUT_ATT (fid, levid, 'units',     '-')
+  iret = NF90_PUT_ATT (fid, levid, 'title',     'levels')
+  iret = NF90_PUT_ATT (fid, levid, 'long_name', 'Sigma Levels')
+!-
+! Time axis
+!-
+  IF (check) WRITE(*,*) 'flincre time axis'
+!-
+  iret = NF90_DEF_VAR (fid, 'tstep', NF90_FLOAT, tdimid1, timeid)
+  iret = NF90_PUT_ATT (fid, timeid, 'units',     '-')
+  iret = NF90_PUT_ATT (fid, timeid, 'title',     'time')
+  iret = NF90_PUT_ATT (fid, timeid, 'long_name', 'time steps')
+!-
+! The longitude
+!-
+  IF (check) WRITE(*,*) 'flincre Longitude axis'
+!-
+  iret = NF90_DEF_VAR (fid, "nav_lon", NF90_FLOAT, &
+                       (/ nlonid1, nlatid1 /), lonid)
+  iret = NF90_PUT_ATT (fid, lonid, 'units', "degrees_east")
+  iret = NF90_PUT_ATT (fid, lonid, 'title', "Longitude")
+  iret = NF90_PUT_ATT (fid, lonid, 'nav_model', &
+                       "Lambert projection of PROMES")
+  iret = NF90_PUT_ATT (fid, lonid, 'valid_min', &
+                       REAL(MINVAL(lon1),KIND=4))
+  iret = NF90_PUT_ATT (fid, lonid, 'valid_max', &
+                       REAL(MAXVAL(lon1),KIND=4))
+!-
+! The Latitude
+!-
+  IF (check) WRITE(*,*) 'flincre Latitude axis'
+!-
+  iret = NF90_DEF_VAR (fid, "nav_lat", NF90_FLOAT, &
+                     (/ nlonid1, nlatid1 /), latid)
+  iret = NF90_PUT_ATT (fid, latid, 'units', "degrees_north")
+  iret = NF90_PUT_ATT (fid, latid, 'title', "Latitude")
+  iret = NF90_PUT_ATT (fid, latid, 'nav_model', &
+                       "Lambert projection of PROMES")
+  iret = NF90_PUT_ATT (fid, latid, 'valid_min', &
+                       REAL(MINVAL(lat1),KIND=4))
+  iret = NF90_PUT_ATT (fid, latid, 'valid_max', &
+                       REAL(MAXVAL(lat1),KIND=4))
+!-
+! The time coordinates
+!-
+  iret = NF90_PUT_ATT (fid, NF90_GLOBAL, 'delta_tstep_sec', &
+                       REAL(dt,KIND=4))
+!-
+  CALL ju2ymds (time0, year, month, day, sec)
+!-
+  iret = NF90_PUT_ATT (fid, NF90_GLOBAL, 'year0',  REAL(year,KIND=4))
+  iret = NF90_PUT_ATT (fid, NF90_GLOBAL, 'month0', REAL(month,KIND=4))
+  iret = NF90_PUT_ATT (fid, NF90_GLOBAL, 'day0',   REAL(day,KIND=4))
+  iret = NF90_PUT_ATT (fid, NF90_GLOBAL, 'sec0',   REAL(sec,KIND=4))
+!-
+  iret = NF90_ENDDEF (fid)
+!-
+  IF (check) WRITE(*,*) 'flincre Variable'
+!-
+  iret = NF90_PUT_VAR (fid, levid, lev1(1:llm1))
+!-
+  IF (check) WRITE(*,*) 'flincre Time Variable'
+!-
+  iret = NF90_PUT_VAR (fid, timeid, REAL(itaus(1:ttm1)))
+!-
+  IF (check) WRITE(*,*) 'flincre Longitude'
+!-
+  iret = NF90_PUT_VAR (fid, lonid, lon1(1:iim1,1:jjm1))
+!-
+  IF (check) WRITE(*,*) 'flincre Latitude'
+!-
+  iret = NF90_PUT_VAR (fid, latid, lat1(1:iim1,1:jjm1))
+!-
+! Keep all this information
+!-
+  nbfiles = nbfiles+1
+!-
+  IF (nbfiles > nbfile_max) THEN
+    CALL histerr (3,'flincre', &
+     'Too many files. Please increase nbfil_max', &
+     'in program flincom.F90.',' ')
+  ENDIF
+!-
+  ncids(nbfiles) = fid
+  ncnbd(nbfiles) = 4
+!-
+  ncdims(nbfiles,1:4) = (/ iim1, jjm1, llm1, ttm1 /)
+!-
+  ncfunli(nbfiles) = -1
+  ncnba(nbfiles)   =  4
+  ncnbva(nbfiles)  =  0
+  ncfileopen(nbfiles) = .TRUE.
+!-
+  fid_out = nbfiles
+!---------------------
+END SUBROUTINE flincre
+!-
+!===
+!-
+SUBROUTINE flinopen_zoom2d &
+  (filename, iideb, iilen, jjdeb, jjlen, do_test, &
+  iim, jjm, llm, lon, lat, lev, ttm, itaus, date0, dt, fid_out)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  CHARACTER(LEN=*) :: filename
+  LOGICAL :: do_test
+  INTEGER :: iim, jjm, llm, ttm, iideb, iilen, jjdeb, jjlen
+  REAL :: lon(iilen,jjlen), lat(iilen,jjlen), lev(llm)
+  INTEGER :: itaus(ttm)
+  REAL :: date0, dt
+  INTEGER :: fid_out
+!-
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE (*,*) ' iideb, iilen, jjdeb, jjlen, iim, jjm ', &
+                           iideb, iilen, jjdeb, jjlen, iim, jjm
+  IF (check) WRITE (*,*) ' lon ', lon(1,1), lon(iilen,jjlen)
+  IF (check) WRITE (*,*) ' lat ', lat(1,1), lat(iilen,jjlen)
+!-
+  CALL flinopen_work &
+    (filename, iideb, iilen, jjdeb, jjlen, do_test, &
+     iim, jjm, llm, lon, lat, lev, ttm, itaus, date0, dt, fid_out)
+!-----------------------------
+END SUBROUTINE flinopen_zoom2d
+!-
+!===
+!-
+SUBROUTINE flinopen_nozoom &
+  (filename, do_test, iim, jjm, llm, lon, lat, lev, ttm, &
+   itaus, date0, dt, fid_out)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  CHARACTER(LEN=*) :: filename
+  LOGICAL :: do_test
+  INTEGER :: iim, jjm, llm, ttm
+  REAL :: lon(iim,jjm), lat(iim,jjm), lev(llm)
+  INTEGER :: itaus(ttm)
+  REAL :: date0, dt
+  INTEGER :: fid_out
+!---------------------------------------------------------------------
+  CALL flinopen_work &
+    (filename, 1, iim, 1, jjm, do_test, &
+     iim, jjm, llm, lon, lat, lev, ttm, itaus, date0, dt, fid_out)
+!-------------------------
+END SUBROUTINE flinopen_nozoom
+!-
+!===
+!-
+SUBROUTINE flinopen_work &
+  (filename, iideb, iilen, jjdeb, jjlen, do_test, &
+   iim, jjm, llm, lon, lat, lev, ttm, itaus, date0, dt, fid_out)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  CHARACTER(LEN=*) :: filename
+  LOGICAL :: do_test
+  INTEGER :: iim, jjm, llm, ttm, iideb, iilen, jjdeb, jjlen
+  REAL :: lon(iilen,jjlen), lat(iilen,jjlen), lev(llm)
+  INTEGER :: itaus(ttm)
+  REAL :: date0, dt
+  INTEGER :: fid_out
+!-
+! LOCAL
+!-
+  REAL, PARAMETER :: eps = 1.e-4
+!-
+  INTEGER :: iret, vid, fid, nbdim, i, iilast, jjlast
+  INTEGER :: gdtt_id, old_id, iv, gdtmaf_id
+  CHARACTER(LEN=250) :: name
+  CHARACTER(LEN=80) :: units, calendar
+  INTEGER :: tmp_iim, tmp_jjm, tmp_llm, tmp_ttm
+  REAL :: x_first, x_last
+  INTEGER :: year, month, day
+  REAL :: r_year, r_month, r_day
+  INTEGER :: year0, month0, day0, hours0, minutes0, seci
+  REAL :: sec, sec0
+  CHARACTER :: strc
+!-
+  REAL,DIMENSION(:),ALLOCATABLE :: vec_tmp
+!-
+  LOGICAL :: open_file
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  iilast = iideb+iilen-1
+  jjlast = jjdeb+jjlen-1
+  IF (check) WRITE (*,*) &
+    ' flinopen_work zoom 2D information '// &
+    ' iideb, iilen, iilast, jjdeb, jjlen, jjlast ', &
+      iideb, iilen, iilast, jjdeb, jjlen, jjlast
+!-
+! 1.0 get all infos on the file
+!-
+! Either the fid_out has not been initialized (0 or very large)
+! then we have to open anyway. Else we only need to open the file
+! if it has not been opened before.
+!-
+  IF ( (fid_out < 1).OR.(fid_out > nbfile_max) ) THEN
+    open_file = .TRUE.
+  ELSE IF (.NOT.ncfileopen(fid_out)) THEN
+    open_file = .TRUE.
+  ELSE
+    open_file = .FALSE.
+  ENDIF
+!-
+  IF (open_file) THEN
+    CALL flininfo (filename,tmp_iim,tmp_jjm,tmp_llm,tmp_ttm,fid_out)
+  ELSE
+!-- The user has already opened the file
+!-- and we trust that he knows the dimensions
+    tmp_iim = iim
+    tmp_jjm = jjm
+    tmp_llm = llm
+    tmp_ttm = ttm
+  ENDIF
+!-
+  IF (check) &
+    WRITE(*,*) 'OUT OF flininfo :',tmp_iim,tmp_jjm,tmp_llm,tmp_ttm
+!-
+  fid = ncids(fid_out)
+!-
+! 2.0 get the sizes and names of the different coordinates
+!     and do a first set of verification.
+!-
+! 2.2 We test the axis if we have to.
+!-
+  IF (check) &
+    WRITE(*,*) 'flininfo 2.2 We test if we have to test : ',do_test
+!-
+  IF (do_test) THEN
+    IF      (iim /= tmp_iim) THEN
+      CALL histerr (3,'flinopen', &
+        'file '//filename//' does not have the ', &
+        'required dimension in x direction (longitude)',' ')
+    ELSE IF (jjm /= tmp_jjm) THEN
+      CALL histerr (3,'flinopen', &
+        'file '//filename//' does not have the ', &
+        'required dimension in y direction (latitude)',' ')
+    ELSE IF ( llm /= tmp_llm .AND. llm > 0 ) THEN
+      CALL histerr (3,'flinopen', &
+        'file '//filename//' does not have the ', &
+        'required dimension in the vertical',' ')
+    ENDIF
+  ELSE
+!---
+!-- 2.3 Else the sizes of the axes are returned to the user
+!---
+    IF (check) WRITE(*,*) 'flinopen 2.3 Else sizes are returned'
+!---
+    iim = tmp_iim
+    jjm = tmp_jjm
+    llm = tmp_llm
+  ENDIF
+!-
+  ttm = tmp_ttm
+!-
+! 3.0 Check if we are realy talking about the same coodinate system
+!     if not then we get the lon, lat and lev variables from the file
+!-
+  IF (check) WRITE(*,*) 'flinopen 3.0 we are realy talking'
+!-
+  IF (do_test) THEN
+!---
+    CALL flinfindcood (fid_out, 'lon', vid, nbdim)
+    iret = NF90_GET_VAR (fid, vid, x_first, start=(/ iideb, jjdeb /))
+    iret = NF90_GET_VAR (fid, vid, x_last, start=(/ iilast, jjlast /))
+!---
+    IF (check) &
+      WRITE(*,*) 'from file lon first and last, modulo 360. ', &
+        x_first, x_last, MODULO(x_first,360.), MODULO(x_last,360.)
+    IF (check) &
+      WRITE(*,*) 'from model lon first and last, modulo 360. ', &
+        lon(1,1),lon(iilen,jjlen), &
+        MODULO(lon(1,1),360.), MODULO(lon(iilen,jjlen),360.)
+    IF (    (ABS( MODULO(x_first,360.) &
+                 -MODULO(lon(1,1),360.)) > eps) &
+        .OR.(ABS( MODULO(x_last,360.) &
+                 -MODULO(lon(iilen ,jjlen),360.)) > eps ) ) THEN
+      CALL histerr (3,'flinopen', &
+        'file '//filename//' and the model do not', &
+        'share the same longitude coordinate', &
+        'Obtained by comparing the first and last values ')
+    ENDIF
+!---
+    CALL flinfindcood (fid_out, 'lat', vid, nbdim)
+    iret = NF90_GET_VAR (fid, vid, x_first, start=(/ iideb, jjdeb /))
+    iret = NF90_GET_VAR (fid, vid, x_last, start=(/ iilast, jjlast /))
+!---
+    IF (check) WRITE(*,*) &
+      'from file lat first and last ',x_first,x_last
+    IF (check) WRITE(*,*) &
+      'from model lat first and last ',lat(1,1),lat(iilen,jjlen)
+!---
+    IF (    (ABS(x_first-lat(1,1)) > eps) &
+        .OR.(ABS(x_last-lat(iilen,jjlen)) > eps) ) THEN
+      CALL histerr (3,'flinopen', &
+        'file '//filename//' and the model do not', &
+        'share the same latitude coordinate', &
+        'Obtained by comparing the first and last values ')
+    ENDIF
+!---
+    IF (llm > 0) THEN
+      CALL flinfindcood (fid_out, 'lev', vid, nbdim)
+      iret = NF90_GET_VAR (fid, vid, x_first, start=(/ 1 /))
+      iret = NF90_GET_VAR (fid, vid, x_last, start=(/ llm /))
+!-----
+      IF (check) WRITE(*,*) &
+        'from file lev first and last ',x_first ,x_last
+      IF (check) WRITE(*,*) &
+        'from model lev first and last ',lev(1),lev(llm)
+!-----
+      IF (    (ABS(x_first-lev(1)) > eps) &
+          .OR.(ABS(x_last-lev(llm)) > eps) ) THEN
+        CALL histerr (3,'flinopen', &
+          'file '//filename//' and the model do not', &
+          'share the same vertical coordinate', &
+          'Obtained by comparing the first and last values')
+      ENDIF
+    ENDIF
+!---
+  ELSE
+!---
+!-- 4.0 extracting the coordinates if we do not check
+!---
+    IF (check) WRITE(*,*) 'flinopen 4.0 extracting the coordinates'
+!---
+    CALL flinfindcood (fid_out, 'lon', vid, nbdim)
+    IF (nbdim == 2) THEN
+      iret = NF90_GET_VAR (fid, vid, lon, &
+               start=(/ iideb, jjdeb /), count=(/ iilen, jjlen /))
+    ELSE
+      ALLOCATE(vec_tmp(iilen))
+      iret = NF90_GET_VAR (fid, vid, vec_tmp, &
+               start=(/ iideb /), count=(/ iilen /))
+      DO i=1,jjlen
+        lon(:,i) = vec_tmp(:)
+      ENDDO
+      DEALLOCATE(vec_tmp)
+    ENDIF
+!---
+    CALL flinfindcood (fid_out, 'lat', vid, nbdim)
+    IF (nbdim == 2) THEN
+      iret = NF90_GET_VAR (fid, vid, lat, &
+               start=(/ iideb, jjdeb /), count=(/ iilen, jjlen /))
+    ELSE
+      ALLOCATE(vec_tmp(jjlen))
+      iret = NF90_GET_VAR (fid, vid, vec_tmp, &
+               start=(/ jjdeb /), count=(/ jjlen /))
+      DO i=1,iilen
+        lat(i,:) = vec_tmp(:)
+      ENDDO
+      DEALLOCATE(vec_tmp)
+    ENDIF
+!---
+    IF (llm > 0) THEN
+      CALL flinfindcood (fid_out, 'lev', vid, nbdim)
+      IF (nbdim == 1) THEN
+        iret = NF90_GET_VAR (fid, vid, lev, &
+                 start=(/ 1 /), count=(/ llm /))
+      ELSE
+        CALL histerr (3,'flinopen', &
+          'Can not handle vertical coordinates that have more',&
+          'than 1 dimension',' ')
+      ENDIF
+    ENDIF
+  ENDIF
+!-
+! 5.0 Get all the details for the time if possible needed
+!-
+  IF (check) WRITE(*,*) 'flinopen 5.0 Get time'
+!-
+  IF (ttm > 0) THEN
+!---
+!-- 5.1 Find the time axis. Prefered method is the 'timestep since'
+!---
+    gdtmaf_id = -1
+    gdtt_id = -1
+    old_id = -1
+    DO iv=1,ncnbva(fid_out)
+      name=''
+      iret = NF90_INQUIRE_VARIABLE (fid, iv, name=name)
+      units=''
+      iret = NF90_GET_ATT (fid, iv, 'units', units)
+      IF (INDEX(units,'seconds since') > 0) gdtmaf_id = iv
+      IF (INDEX(units,'timesteps since') > 0) gdtt_id = iv
+      IF (INDEX(name, 'tstep') > 0) old_id = iv
+    ENDDO
+!---
+    IF (gdtt_id > 0) THEN
+      vid = gdtt_id
+    ELSE IF (gdtmaf_id > 0) THEN
+      vid = gdtmaf_id
+    ELSE IF (old_id > 0) THEN
+      vid = old_id
+    ELSE
+      CALL histerr (3, 'flinopen', 'No time axis found',' ',' ')
+    ENDIF
+!---
+    ALLOCATE(vec_tmp(ttm))
+    iret = NF90_GET_VAR (fid,vid,vec_tmp,start=(/ 1 /),count=(/ ttm /))
+    itaus(1:ttm) = NINT(vec_tmp(1:ttm))
+    DEALLOCATE(vec_tmp)
+!---
+    IF (check) WRITE(*,*) 'flinopen 5.1 Times ',itaus
+!---
+!-- Getting all the details for the time axis
+!---
+!-- Find the calendar
+    calendar = ''
+    iret = NF90_GET_ATT (fid,gdtmaf_id,'calendar',calendar)
+    IF (iret == NF90_NOERR) THEN
+      CALL ioconf_calendar(calendar)
+    ENDIF
+!--
+    units = ''
+    iret = NF90_GET_ATT (fid,vid,'units',units)
+    IF (gdtt_id > 0) THEN
+      units = units(INDEX(units,'since')+6:LEN_TRIM(units))
+      READ (units,'(I4.4,5(a,I2.2))') &
+        year0, strc, month0, strc, day0, &
+               strc, hours0, strc, minutes0, strc, seci
+      sec0 = hours0*3600. + minutes0*60. + seci
+      CALL ymds2ju (year0, month0, day0, sec0, date0)
+      IF (check) &
+        WRITE(*,*) 'flinopen 5.1 gdtt_id year0 ... date0 ', &
+                   year0, month0, day0, sec0, date0
+!-----
+      iret = NF90_GET_ATT (fid, gdtt_id, 'tstep_sec', dt)
+    ELSE IF (gdtmaf_id > 0) THEN
+      units = units(INDEX(units,'since')+6:LEN_TRIM(units))
+      READ (units,'(I4.4,5(a,I2.2))') &
+        year0, strc, month0, strc, day0, &
+               strc, hours0, strc, minutes0, strc, seci
+      sec0 = hours0*3600. + minutes0*60. + seci
+      CALL ymds2ju (year0, month0, day0, sec0, date0)
+!-----
+      IF (check) &
+        WRITE(*,*) 'flinopen 5.1 gdtmaf_id year0 ... date0 ', &
+                   year0, month0, day0, sec0, date0
+    ELSE IF (old_id > 0) THEN
+      iret = NF90_GET_ATT (fid, NF90_GLOBAL, 'delta_tstep_sec', dt)
+      iret = NF90_GET_ATT (fid, NF90_GLOBAL, 'day0', r_day)
+      iret = NF90_GET_ATT (fid, NF90_GLOBAL, 'sec0', sec)
+      iret = NF90_GET_ATT (fid, NF90_GLOBAL, 'year0', r_year)
+      iret = NF90_GET_ATT (fid, NF90_GLOBAL, 'month0', r_month)
+!-----
+      day = INT(r_day)
+      month = INT(r_month)
+      year = INT(r_year)
+!-----
+      CALL ymds2ju (year, month, day, sec, date0)
+    ENDIF
+  ENDIF
+!-
+  IF (check) WRITE(*,*) 'flinopen 6.0 File opened', date0, dt
+!---------------------------
+END SUBROUTINE flinopen_work
+!-
+!===
+!-
+SUBROUTINE flininfo (filename, iim, jjm, llm, ttm, fid_out)
+!---------------------------------------------------------------------
+!- This subroutine allows to get some information.
+!- It is usualy done within flinopen but the user may want to call
+!- it before in order to allocate the space needed to extract the
+!- data from the file.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  CHARACTER(LEN=*) :: filename
+  INTEGER :: iim, jjm, llm, ttm, fid_out
+!-
+! LOCAL
+!-
+  INTEGER :: iret, fid, ndims, nvars, nb_atts, id_unlim
+  INTEGER :: iv, lll
+  INTEGER :: xid, yid, zid, tid
+  CHARACTER(LEN=80) :: name
+  CHARACTER(LEN=30) :: axname
+!-
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  lll = LEN_TRIM(filename)
+  IF (filename(lll-2:lll) /= '.nc') THEN
+    name = filename(1:lll)//'.nc'
+  ELSE
+    name = filename(1:lll)
+  ENDIF
+!-
+  iret = NF90_OPEN (name, NF90_NOWRITE, fid)
+  IF (iret /= NF90_NOERR) THEN
+    CALL histerr(3, 'flininfo','Could not open file :',TRIM(name),' ')
+  ENDIF
+!-
+  iret = NF90_INQUIRE (fid, nDimensions=ndims, nVariables=nvars, &
+                      nAttributes=nb_atts, unlimitedDimId=id_unlim)
+!-
+  xid = -1; iim = 0;
+  yid = -1; jjm = 0;
+  zid = -1; llm = 0;
+  tid = -1; ttm = 0;
+!-
+  DO iv=1,ndims
+!---
+    iret = NF90_INQUIRE_DIMENSION (fid, iv, name=axname, len=lll)
+    CALL strlowercase (axname)
+    axname = ADJUSTL(axname)
+!---
+    IF (check) WRITE(*,*) &
+      'flininfo - getting axname',iv,axname,lll
+!---
+    IF      (    (INDEX(axname,'x') == 1) &
+             .OR.(INDEX(axname,'lon') == 1) ) THEN
+      xid = iv; iim = lll;
+    ELSE IF (    (INDEX(axname,'y') == 1) &
+             .OR.(INDEX(axname,'lat') == 1) ) THEN
+      yid = iv; jjm = lll;
+    ELSE IF (    (INDEX(axname,'lev') == 1) &
+             .OR.(INDEX(axname,'plev') == 1) &
+             .OR.(INDEX(axname,'z') == 1) &
+             .OR.(INDEX(axname,'depth') == 1) ) THEN
+      zid = iv; llm = lll;
+    ELSE IF (    (INDEX(axname,'tstep') == 1) &
+             .OR.(INDEX(axname,'time_counter') == 1) ) THEN
+!---- For the time we certainly need to allow for other names
+      tid = iv; ttm = lll;
+    ELSE IF (ndims == 1) THEN
+!---- Nothing was found and ndims=1 then we have a vector of data
+      xid = 1; iim = lll;
+    ENDIF
+!---
+  ENDDO
+!-
+! Keep all this information
+!-
+  nbfiles = nbfiles+1
+!-
+  IF (nbfiles > nbfile_max) THEN
+    CALL histerr (3,'flininfo', &
+      'Too many files. Please increase nbfil_max', &
+      'in program flincom.F90.',' ')
+  ENDIF
+!-
+  ncids(nbfiles) = fid
+  ncnbd(nbfiles) = ndims
+!-
+  ncdims(nbfiles,1:4) = (/ iim, jjm, llm, ttm /)
+!-
+  ncfunli(nbfiles) = id_unlim
+  ncnba(nbfiles)   = nb_atts
+  ncnbva(nbfiles)  = nvars
+  ncfileopen(nbfiles) = .TRUE.
+!-
+  fid_out = nbfiles
+!----------------------
+END SUBROUTINE flininfo
+!-
+!===
+!-
+SUBROUTINE flinput_r1d &
+  (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, nlonid, jjm, nlatid, llm, zdimid, ttm, tdimid
+  REAL :: var(:)
+!-
+  INTEGER :: fid, ncvarid, ndim, iret
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,*) &
+     "flinput_r1d : SIZE(var) = ",SIZE(var)
+!-
+  CALL flinput_mat &
+    (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid, &
+     fid,ncvarid,ndim)
+!-
+  iret = NF90_PUT_VAR (fid, ncvarid, var, &
+           start=w_sta(1:ndim), count=w_len(1:ndim))
+!-------------------------
+END SUBROUTINE flinput_r1d
+!-
+!===
+!-
+SUBROUTINE flinput_r2d &
+  (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, nlonid, jjm, nlatid, llm, zdimid, ttm, tdimid
+  REAL :: var(:,:)
+!-
+  INTEGER :: fid, ncvarid, ndim, iret
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,*) &
+     "flinput_r2d : SIZE(var) = ",SIZE(var)
+!-
+  CALL flinput_mat &
+    (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid, &
+     fid,ncvarid,ndim)
+!-
+  iret = NF90_PUT_VAR (fid, ncvarid, var, &
+           start=w_sta(1:ndim), count=w_len(1:ndim))
+!-------------------------
+END SUBROUTINE flinput_r2d
+!-
+!===
+!-
+SUBROUTINE flinput_r3d &
+  (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, nlonid, jjm, nlatid, llm, zdimid, ttm, tdimid
+  REAL :: var(:,:,:)
+!-
+  INTEGER :: fid, ncvarid, ndim, iret
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,*) &
+     "flinput_r3d : SIZE(var) = ",SIZE(var)
+!-
+  CALL flinput_mat &
+    (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid, &
+     fid,ncvarid,ndim)
+!-
+  iret = NF90_PUT_VAR (fid, ncvarid, var, &
+           start=w_sta(1:ndim), count=w_len(1:ndim))
+!-------------------------
+END SUBROUTINE flinput_r3d
+!-
+!===
+!-
+SUBROUTINE flinput_r4d &
+  (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, nlonid, jjm, nlatid, llm, zdimid, ttm, tdimid
+  REAL :: var(:,:,:,:)
+!-
+  INTEGER :: fid, ncvarid, ndim, iret
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,*) &
+     "flinput_r4d : SIZE(var) = ",SIZE(var)
+!-
+  CALL flinput_mat &
+    (fid_in,varname,iim,nlonid,jjm,nlatid,llm,zdimid,ttm,tdimid, &
+     fid,ncvarid,ndim)
+!-
+  iret = NF90_PUT_VAR (fid, ncvarid, var, &
+           start=w_sta(1:ndim), count=w_len(1:ndim))
+!-------------------------
+END SUBROUTINE flinput_r4d
+!-
+!===
+!-
+SUBROUTINE flinput_mat &
+  (fid_in,varname,iim,nlonid,jjm,nlatid, &
+                  llm,zdimid,ttm,tdimid,fid,ncvarid,ndim)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, nlonid, jjm, nlatid, llm, zdimid, ttm, tdimid
+  INTEGER :: fid, ncvarid, ndim
+!-
+! LOCAL
+!-
+  INTEGER :: iret
+!---------------------------------------------------------------------
+  fid = ncids(fid_in)
+!-
+  w_sta(1:4) = (/      1,      1,  1,  1 /)
+  w_len(1:2) = (/    iim,    jjm /)
+  w_dim(1:2) = (/ nlonid, nlatid /)
+!-
+  IF ( (llm > 0).AND.(ttm > 0) ) THEN
+    ndim = 4
+    w_len(3:4) = (/    llm,    ttm /)
+    w_dim(3:4) = (/ zdimid, tdimid /)
+  ELSE IF (llm > 0) THEN
+    ndim = 3
+    w_dim(3) = zdimid
+    w_len(3) = llm
+  ELSE IF (ttm > 0) THEN
+    ndim = 3
+    w_dim(3) = tdimid
+    w_len(3) = ttm
+  ELSE
+    ndim = 2
+  ENDIF
+!-
+  iret = NF90_REDEF   (fid)
+  iret = NF90_DEF_VAR (fid,varname,NF90_FLOAT,w_dim(1:ndim),ncvarid)
+  iret = NF90_PUT_ATT (fid,ncvarid,'short_name',TRIM(varname))
+  iret = NF90_ENDDEF  (fid)
+!--------------------------
+END  SUBROUTINE flinput_mat
+!-
+!===
+!-
+SUBROUTINE flinput_scal &
+  (fid_in, varname, iim, nlonid, jjm, nlatid, &
+                    llm, zdimid, ttm, tdimid, var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, nlonid, jjm, nlatid, llm, zdimid, ttm, tdimid
+  REAL :: var
+!-
+! LOCAL
+!-
+  INTEGER :: fid, iret
+!---------------------------------------------------------------------
+  fid = ncids(fid_in)
+!-
+  iret = NF90_REDEF   (fid)
+  iret = NF90_PUT_ATT (fid, NF90_GLOBAL, varname, REAL(var,KIND=4))
+  iret = NF90_ENDDEF  (fid)
+!---------------------------
+END  SUBROUTINE flinput_scal
+!-
+!===
+!-
+SUBROUTINE flinget_r1d &
+  (fid_in,varname,iim,jjm,llm,ttm,itau_dep,itau_fin,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, jjm, llm, ttm, itau_dep, itau_fin
+  REAL :: var(:)
+!-
+  INTEGER :: jl, ji
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r1d : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r1d : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,1,iim,1,jjm,buff_tmp)
+!-
+  jl=0
+  DO ji=1,SIZE(var,1)
+    jl=jl+1
+    var(ji) = buff_tmp(jl)
+  ENDDO
+!-------------------------
+END SUBROUTINE flinget_r1d
+!-
+!===
+!-
+SUBROUTINE flinget_r2d &
+  (fid_in,varname,iim,jjm,llm,ttm,itau_dep,itau_fin,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, jjm, llm, ttm, itau_dep, itau_fin
+  REAL :: var(:,:)
+!-
+  INTEGER :: jl, jj, ji
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r2d : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r2d : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,1,iim,1,jjm,buff_tmp)
+!-
+  jl=0
+  DO jj=1,SIZE(var,2)
+    DO ji=1,SIZE(var,1)
+      jl=jl+1
+      var(ji,jj) = buff_tmp(jl)
+    ENDDO
+  ENDDO
+!-------------------------
+END SUBROUTINE flinget_r2d
+!-
+!===
+!-
+SUBROUTINE flinget_r2d_zoom2d &
+  (fid_in,varname,iim,jjm,llm,ttm, &
+   itau_dep,itau_fin,iideb,iilen,jjdeb,jjlen,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim,jjm,llm,ttm,itau_dep,itau_fin,iideb,jjdeb,iilen,jjlen
+  REAL :: var(:,:)
+!-
+  INTEGER :: jl, jj, ji
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r2d_zoom : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r2d_zoom : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,iideb,iilen,jjdeb,jjlen,buff_tmp)
+!-
+  jl=0
+  DO jj=1,SIZE(var,2)
+    DO ji=1,SIZE(var,1)
+      jl=jl+1
+      var(ji,jj) = buff_tmp(jl)
+    ENDDO
+  ENDDO
+!--------------------------------
+END SUBROUTINE flinget_r2d_zoom2d
+!-
+!===
+!-
+SUBROUTINE flinget_r3d &
+  (fid_in,varname,iim,jjm,llm,ttm,itau_dep,itau_fin,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, jjm, llm, ttm, itau_dep, itau_fin
+  REAL :: var(:,:,:)
+!-
+  INTEGER :: jl, jk, jj, ji
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r3d : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r3d : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,1,iim,1,jjm,buff_tmp)
+!-
+  jl=0
+  DO jk=1,SIZE(var,3)
+    DO jj=1,SIZE(var,2)
+      DO ji=1,SIZE(var,1)
+        jl=jl+1
+        var(ji,jj,jk) = buff_tmp(jl)
+      ENDDO
+    ENDDO
+  ENDDO
+!-------------------------
+END SUBROUTINE flinget_r3d
+!-
+!===
+!-
+SUBROUTINE flinget_r3d_zoom2d &
+  (fid_in,varname,iim,jjm,llm,ttm, &
+   itau_dep,itau_fin,iideb,iilen,jjdeb,jjlen,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim,jjm,llm,ttm,itau_dep,itau_fin,iideb,jjdeb,iilen,jjlen
+  REAL :: var(:,:,:)
+!-
+  INTEGER :: jl, jk, jj, ji
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r3d_zoom : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r3d_zoom : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,iideb,iilen,jjdeb,jjlen,buff_tmp)
+!-
+  jl=0
+  DO jk=1,SIZE(var,3)
+    DO jj=1,SIZE(var,2)
+      DO ji=1,SIZE(var,1)
+        jl=jl+1
+        var(ji,jj,jk) = buff_tmp(jl)
+      ENDDO
+    ENDDO
+  ENDDO
+!--------------------------------
+END SUBROUTINE flinget_r3d_zoom2d
+!-
+!===
+!-
+SUBROUTINE flinget_r4d &
+  (fid_in,varname,iim,jjm,llm,ttm,itau_dep,itau_fin,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, jjm, llm, ttm, itau_dep, itau_fin
+  REAL :: var(:,:,:,:)
+!-
+  INTEGER :: jl, jk, jj, ji, jm
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r4d : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r4d : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,1,iim,1,jjm,buff_tmp)
+!-
+  jl=0
+  DO jm=1,SIZE(var,4)
+    DO jk=1,SIZE(var,3)
+      DO jj=1,SIZE(var,2)
+        DO ji=1,SIZE(var,1)
+          jl=jl+1
+          var(ji,jj,jk,jm) = buff_tmp(jl)
+        ENDDO
+      ENDDO
+    ENDDO
+  ENDDO
+!-------------------------
+END SUBROUTINE flinget_r4d
+!-
+!===
+!-
+SUBROUTINE flinget_r4d_zoom2d &
+  (fid_in,varname,iim,jjm,llm,ttm, &
+   itau_dep,itau_fin,iideb,iilen,jjdeb,jjlen,var)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim,jjm,llm,ttm,itau_dep,itau_fin,iideb,jjdeb,iilen,jjlen
+  REAL :: var(:,:,:,:)
+!-
+  INTEGER :: jl, jk, jj, ji, jm
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: buff_tmp
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (.NOT.ALLOCATED(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r4d_zoom : allocate buff_tmp for buff_sz = ",SIZE(var)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ELSE IF (SIZE(var) > SIZE(buff_tmp)) THEN
+    IF (check) WRITE(*,*) &
+      "flinget_r4d_zoom : re-allocate buff_tmp for buff_sz = ",SIZE(var)
+    DEALLOCATE (buff_tmp)
+    ALLOCATE (buff_tmp(SIZE(var)))
+  ENDIF
+!-
+  CALL flinget_mat (fid_in,varname,iim,jjm,llm,ttm, &
+                    itau_dep,itau_fin,iideb,iilen,jjdeb,jjlen,buff_tmp)
+!-
+  jl=0
+  DO jm=1,SIZE(var,4)
+    DO jk=1,SIZE(var,3)
+      DO jj=1,SIZE(var,2)
+        DO ji=1,SIZE(var,1)
+          jl=jl+1
+          var(ji,jj,jk,jm) = buff_tmp(jl)
+        ENDDO
+      ENDDO
+    ENDDO
+  ENDDO
+!--------------------------------
+END SUBROUTINE flinget_r4d_zoom2d
+!-
+!===
+!-
+SUBROUTINE flinget_mat &
+  (fid_in, varname, iim, jjm, llm, ttm, itau_dep, &
+   itau_fin, iideb, iilen, jjdeb, jjlen, var)
+!---------------------------------------------------------------------
+!- This subroutine will read the variable named varname from
+!- the file previously opened by flinopen and identified by fid
+!-
+!- It is checked that the dimensions of the variable to be read
+!- correspond to what the user requested when he specified
+!- iim, jjm and llm. The only exception which is allowed is
+!- for compressed data where the horizontal grid is not expected
+!- to be iim x jjm.
+!-
+!- If variable is of size zero a global attribute is read.
+!- This global attribute will be of type real
+!-
+!- INPUT
+!-
+!- fid      : File ID returned by flinopen
+!- varname  : Name of the variable to be read from the file
+!- iim      : | These three variables give the size of the variables
+!- jjm      : | to be read. It will be verified that the variables
+!- llm      : | fits in there.
+!- ttm      : |
+!- itau_dep : Time step at which we will start to read
+!- itau_fin : Time step until which we are going to read
+!-            For the moment this is done on indexes
+!-            but it should be in the physical space.
+!-            If there is no time-axis in the file then use a
+!-            itau_fin < itau_dep, this will tell flinget not to
+!-            expect a time-axis in the file.
+!- iideb    : index i for zoom
+!- iilen    : length of zoom
+!- jjdeb    : index j for zoom
+!- jjlen    : length of zoom
+!-
+!- OUTPUT
+!-
+!- var      : array that will contain the data
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, jjm, llm, ttm
+  INTEGER :: itau_dep, itau_fin, iideb, iilen, jjdeb, jjlen
+  REAL :: var(:)
+!-
+! LOCAL
+!-
+  INTEGER :: iret, fid
+  INTEGER :: vid, cvid, clen
+  CHARACTER(LEN=70) :: str1
+  CHARACTER(LEN=250) :: att_n, tmp_n
+  CHARACTER(LEN=5) :: axs_l
+  INTEGER :: tmp_i
+  REAL,SAVE :: mis_v=0.
+  REAL :: tmp_r
+  INTEGER :: ndims, x_typ, nb_atts
+  INTEGER,DIMENSION(NF90_MAX_VAR_DIMS) :: dimids
+  INTEGER :: i, nvars, i2d, cnd
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: var_tmp
+  LOGICAL :: uncompress = .FALSE.
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  fid = ncids(fid_in)
+!-
+  IF (check) THEN
+    WRITE(*,*) &
+    'flinget_mat : fid_in, fid, varname :', fid_in, fid, TRIM(varname)
+    WRITE(*,*) &
+    'flinget_mat : iim, jjm, llm, ttm, itau_dep, itau_fin :', &
+    iim, jjm, llm, ttm, itau_dep, itau_fin
+    WRITE(*,*) &
+    'flinget_mat : iideb, iilen, jjdeb, jjlen :', &
+    iideb, iilen, jjdeb, jjlen
+  ENDIF
+!-
+  uncompress = .FALSE.
+!-
+! 1.0 We get first all the details on this variable from the file
+!-
+  nvars = ncnbva(fid_in)
+!-
+  vid = -1
+  iret = NF90_INQ_VARID (fid, varname, vid)
+!-
+  IF (vid < 0 .OR. iret /= NF90_NOERR) THEN
+    CALL histerr (3,'flinget', &
+      'Variable '//TRIM(varname)//' not found in file',' ',' ')
+  ENDIF
+!-
+  iret = NF90_INQUIRE_VARIABLE (fid, vid, &
+           ndims=ndims, dimids=dimids, nAtts=nb_atts)
+  IF (check) THEN
+    WRITE(*,*) &
+    'flinget_mat : fid, vid :', fid, vid
+    WRITE(*,*) &
+    'flinget_mat : ndims, dimids(1:ndims), nb_atts :', &
+    ndims, dimids(1:ndims), nb_atts
+  ENDIF
+!-
+  w_dim(:) = 0
+  DO i=1,ndims
+    iret  = NF90_INQUIRE_DIMENSION (fid, dimids(i), len=w_dim(i))
+  ENDDO
+  IF (check) WRITE(*,*) &
+    'flinget_mat : w_dim :', w_dim(1:ndims)
+!-
+  mis_v = 0.0; axs_l = ' ';
+!-
+  IF (nb_atts > 0) THEN
+    IF (check) THEN
+      WRITE(*,*) 'flinget_mat : attributes for variable :'
+    ENDIF
+  ENDIF
+  DO i=1,nb_atts
+    iret = NF90_INQ_ATTNAME (fid, vid, i, att_n)
+    iret = NF90_INQUIRE_ATTRIBUTE (fid, vid, att_n, xtype=x_typ)
+    CALL strlowercase (att_n)
+    IF      (    (x_typ == NF90_INT).OR.(x_typ == NF90_SHORT) &
+             .OR.(x_typ == NF90_BYTE) ) THEN
+      iret = NF90_GET_ATT (fid, vid, att_n, tmp_i)
+      IF (check) THEN
+        WRITE(*,*) '   ',TRIM(att_n),' : ',tmp_i
+      ENDIF
+    ELSE IF ( (x_typ == NF90_FLOAT).OR.(x_typ == NF90_DOUBLE) ) THEN
+      iret = NF90_GET_ATT (fid, vid, att_n, tmp_r)
+      IF (check) THEN
+        WRITE(*,*) '   ',TRIM(att_n),' : ',tmp_r
+      ENDIF
+      IF (index(att_n,'missing_value') > 0) THEN
+        mis_v = tmp_r
+      ENDIF
+    ELSE
+      tmp_n = ''
+      iret = NF90_GET_ATT (fid, vid, att_n, tmp_n)
+      IF (check) THEN
+        WRITE(*,*) '   ',TRIM(att_n),' : ',TRIM(tmp_n)
+      ENDIF
+      IF (index(att_n,'axis') > 0) THEN
+        axs_l = tmp_n
+      ENDIF
+    ENDIF
+  ENDDO
+!?
+!!!!!!!!!! We will need a verification on the type of the variable
+!?
+!-
+! 2.0 The dimensions are analysed to determine what is to be read
+!-
+! 2.1 the longitudes
+!-
+  IF ( w_dim(1) /= iim .OR. w_dim(2) /= jjm) THEN
+!---
+!-- There is a possibility that we have to deal with a compressed axis !
+!---
+    iret = NF90_INQUIRE_DIMENSION (fid, dimids(1), &
+             name=tmp_n, len=clen)
+    iret = NF90_INQ_VARID (fid, tmp_n, cvid)
+!---
+    IF (check) WRITE(*,*) &
+      'Dimname, iret , NF90_NOERR : ',TRIM(tmp_n),iret,NF90_NOERR
+!---
+!-- If we have an axis which has the same name
+!-- as the dimension we can see if it is compressed
+!---
+!-- TODO TODO for zoom2d
+!---
+    IF (iret == NF90_NOERR) THEN
+      iret = NF90_GET_ATT (fid, cvid, 'compress', str1)
+!-----
+      IF (iret == NF90_NOERR) THEN
+        iret = NF90_INQUIRE_VARIABLE (fid,cvid,xtype=x_typ,ndims=cnd)
+!-------
+        IF ( cnd /= 1 .AND. x_typ /= NF90_INT) THEN
+          CALL histerr (3,'flinget', &
+            'Variable '//TRIM(tmp_n)//' can not be a compressed axis', &
+            'Either it has too many dimensions'// &
+            ' or it is not of type integer', ' ')
+        ELSE
+!---------
+!-------- Let us see if we already have that index table
+!---------
+          IF (    (cind_len /= clen).OR.(cind_vid /= cvid) &
+              .OR.(cind_fid /= fid) ) THEN
+            IF (ALLOCATED(cindex))   DEALLOCATE(cindex)
+            ALLOCATE(cindex(clen))
+            cind_len = clen
+            cind_vid = cvid
+            cind_fid = fid
+            iret = NF90_GET_VAR (fid, cvid, cindex)
+          ENDIF
+!---------
+!-------- In any case we need to set the slab of data to be read
+!---------
+          uncompress = .TRUE.
+          w_sta(1) = 1
+          w_len(1) = clen
+          i2d = 1
+        ENDIF
+      ELSE
+        str1 = 'The horizontal dimensions of '//varname
+        CALL histerr (3,'flinget',str1, &
+          'is not compressed and does not'// &
+          ' correspond to the requested size',' ')
+      ENDIF
+    ELSE
+      IF (w_dim(1) /= iim) THEN
+        str1 = 'The longitude dimension of '//varname
+        CALL histerr (3,'flinget',str1, &
+          'in the file is not equal to the dimension', &
+          'that should be read')
+      ENDIF
+      IF (w_dim(2) /= jjm) THEN
+        str1 = 'The latitude dimension of '//varname
+        CALL histerr (3,'flinget',str1, &
+          'in the file is not equal to the dimension', &
+          'that should be read')
+      ENDIF
+    ENDIF
+  ELSE
+    w_sta(1:2) = (/ iideb, jjdeb /)
+    w_len(1:2) = (/ iilen, jjlen /)
+    i2d = 2
+  ENDIF
+!-
+! 2.3 Now the difficult part, the 3rd dimension which can be
+! time or levels.
+!-
+! Priority is given to the time axis if only three axes are present.
+!-
+  IF (ndims > i2d) THEN
+!---
+!-- 2.3.1 We have a vertical axis
+!---
+    IF (llm == 1 .AND. ndims == i2d+2 .OR. llm == w_dim(i2d+1)) THEN
+!-----
+      IF (w_dim(i2d+1) /= llm) THEN
+        CALL histerr (3,'flinget', &
+          'The vertical dimension of '//varname, &
+          'in the file is not equal to the dimension', &
+          'that should be read')
+      ELSE
+        w_sta(i2d+1) = 1
+        IF (llm > 0) THEN
+          w_len(i2d+1) = llm
+        ELSE
+          w_len(i2d+1) = w_sta(i2d+1)
+        ENDIF
+      ENDIF
+!-----
+      IF ((itau_fin-itau_dep) >= 0) THEN
+        IF      (ndims /= i2d+2) THEN
+          CALL histerr (3,'flinget', &
+            'You attempt to read a time slab', &
+            'but there is no time axis on this variable', varname)
+        ELSE IF ((itau_fin - itau_dep) <= w_dim(i2d+2)) THEN
+          w_sta(i2d+2) = itau_dep
+          w_len(i2d+2) = itau_fin-itau_dep+1
+        ELSE
+          CALL histerr (3,'flinget', &
+            'The time step you try to read is not', &
+            'in the file (1)', varname)
+        ENDIF
+      ELSE IF (ndims == i2d+2 .AND. w_dim(i2d+2) > 1) THEN
+        CALL histerr (3,'flinget', &
+          'There is a time axis in the file but no', &
+          'time step give in the call', varname)
+      ELSE
+        w_sta(i2d+2) = 1
+        w_len(i2d+2) = 1
+      ENDIF
+    ELSE
+!-----
+!---- 2.3.2 We do not have any vertical axis
+!-----
+      IF (ndims == i2d+2) THEN
+        CALL histerr (3,'flinget', &
+          'The file contains 4 dimensions', &
+          'but only 3 are requestes for variable ', varname)
+      ENDIF
+      IF ((itau_fin-itau_dep) >= 0) THEN
+        IF (ndims == i2d+1) THEN
+          IF ((itau_fin-itau_dep) < w_dim(i2d+1) ) THEN
+            w_sta(i2d+1) = itau_dep
+            w_len(i2d+1) = itau_fin-itau_dep+1
+          ELSE
+            CALL histerr (3,'flinget', &
+              'The time step you try to read is not', &
+              'in the file (2)', varname)
+          ENDIF
+        ELSE
+          CALL histerr (3,'flinget', &
+            'From your input you sould have 3 dimensions', &
+            'in the file but there are 4', varname)
+        ENDIF
+      ELSE
+        IF (ndims == i2d+1 .AND. w_dim(i2d+1) > 1) THEN
+          CALL histerr (3,'flinget', &
+            'There is a time axis in the file but no', &
+            'time step given in the call', varname)
+        ELSE
+          w_sta(i2d+1) = 1
+          w_len(i2d+1) = 1
+        ENDIF
+      ENDIF
+    ENDIF
+  ELSE
+!---
+!-- 2.3.3 We do not have any vertical axis
+!---
+    w_sta(i2d+1:i2d+2) = (/ 0, 0 /)
+    w_len(i2d+1:i2d+2) = (/ 0, 0 /)
+  ENDIF
+!-
+! 3.0 Reading the data
+!-
+  IF (check) WRITE(*,*) &
+    'flinget_mat 3.0 : ', uncompress, w_sta, w_len
+!---
+  IF (uncompress) THEN
+!---
+    IF (ALLOCATED(var_tmp)) THEN
+      IF (SIZE(var_tmp) < clen) THEN
+        DEALLOCATE(var_tmp)
+        ALLOCATE(var_tmp(clen))
+      ENDIF
+    ELSE
+      ALLOCATE(var_tmp(clen))
+    ENDIF
+!---
+    iret = NF90_GET_VAR (fid, vid, var_tmp, &
+             start=w_sta(:), count=w_len(:))
+!---
+    var(:) = mis_v
+    var(cindex(:)) = var_tmp(:)
+!---
+  ELSE
+    iret = NF90_GET_VAR (fid, vid, var, &
+             start=w_sta(:), count=w_len(:))
+  ENDIF
+!-
+  IF (check) WRITE(*,*) 'flinget_mat 3.1 : ',NF90_STRERROR (iret)
+!--------------------------
+END  SUBROUTINE flinget_mat
+!-
+!===
+!-
+SUBROUTINE flinget_scal &
+  (fid_in, varname, iim, jjm, llm, ttm, itau_dep, itau_fin, var)
+!---------------------------------------------------------------------
+!- This subroutine will read the variable named varname from
+!- the file previously opened by flinopen and identified by fid
+!-
+!- If variable is of size zero a global attribute is read. This
+!- global attribute will be of type real
+!-
+!- INPUT
+!-
+!- fid      : File ID returned by flinopen
+!- varname  : Name of the variable to be read from the file
+!- iim      : | These three variables give the size of the variables
+!- jjm      : | to be read. It will be verified that the variables
+!- llm      : | fits in there.
+!- ttm      : |
+!- itau_dep : Time step at which we will start to read
+!- itau_fin : Time step until which we are going to read
+!-           For the moment this is done on indeces but it should be
+!-           in the physical space
+!-           If there is no time-axis in the file then use a
+!-           itau_fin < itau_dep, this will tell flinget not to
+!-           expect a time-axis in the file.
+!-
+!- OUTPUT
+!-
+!- var      : scalar that will contain the data
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim, jjm, llm, ttm, itau_dep, itau_fin
+  REAL :: var
+!-
+! LOCAL
+!-
+  INTEGER :: iret, fid
+!-
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) THEN
+    WRITE (*,*) 'flinget_scal in file with id ',fid_in
+  ENDIF
+!-
+  fid = ncids(fid_in)
+!-
+! 1.0 Reading a global attribute
+!-
+  iret = NF90_GET_ATT (fid, NF90_GLOBAL, varname, var)
+!---------------------------
+END  SUBROUTINE flinget_scal
+!-
+!===
+!-
+SUBROUTINE flinfindcood (fid_in, axtype, vid, ndim)
+!---------------------------------------------------------------------
+!- This subroutine explores the file in order to find
+!- the coordinate according to a number of rules
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  INTEGER :: fid_in, vid, ndim
+  CHARACTER(LEN=3) :: axtype
+!-
+! LOCAL
+!-
+  INTEGER :: iv, iret, dimnb
+  CHARACTER(LEN=40) :: dimname, dimuni1, dimuni2, dimuni3
+  CHARACTER(LEN=80) :: str1
+  LOGICAL :: found_rule = .FALSE.
+!---------------------------------------------------------------------
+  vid = -1
+!-
+! Make sure all strings are invalid
+!-
+  dimname = '?-?'
+  dimuni1 = '?-?'
+  dimuni2 = '?-?'
+  dimuni3 = '?-?'
+!-
+! First rule : we look for the correct units
+! lon : east
+! lat : north
+! We make an exact check as it would be too easy to mistake
+! some units by just comparing the substrings.
+!-
+  SELECTCASE(axtype)
+  CASE ('lon')
+    dimuni1 = 'degree_e'
+    dimuni2 = 'degrees_e'
+    found_rule = .TRUE.
+  CASE('lat')
+    dimuni1 = 'degree_n'
+    dimuni2 = 'degrees_n'
+    found_rule = .TRUE.
+  CASE('lev')
+    dimuni1 = 'm'
+    dimuni2 = 'km'
+    dimuni3 = 'hpa'
+    found_rule = .TRUE.
+  CASE DEFAULT
+    found_rule = .FALSE.
+  END SELECT
+!-
+  IF (found_rule) THEN
+    iv = 0
+    DO WHILE ( (vid < 0).AND.(iv < ncnbva(fid_in)) )
+      iv = iv+1
+      str1 = ''
+      iret = NF90_GET_ATT (ncids(fid_in), iv, 'units', str1)
+      IF (iret == NF90_NOERR) THEN
+        CALL strlowercase (str1)
+        IF (    (INDEX(str1, TRIM(dimuni1)) == 1) &
+            .OR.(INDEX(str1, TRIM(dimuni2)) == 1) &
+            .OR.(INDEX(str1, TRIM(dimuni3)) == 1) ) THEN
+          vid = iv
+          iret = NF90_INQUIRE_VARIABLE (ncids(fid_in), iv, ndims=ndim)
+        ENDIF
+      ENDIF
+    ENDDO
+  ENDIF
+!-
+! Second rule : we find specific names :
+! lon : nav_lon
+! lat : nav_lat
+! Here we can check if we find the substring as the
+! names are more specific.
+!-
+  SELECTCASE(axtype)
+  CASE ('lon')
+    dimname = 'nav_lon lon longitude'
+    found_rule = .TRUE.
+  CASE('lat')
+    dimname = 'nav_lat lat latitude'
+    found_rule = .TRUE.
+  CASE('lev')
+    dimname = 'plev level depth deptht'
+    found_rule = .TRUE.
+  CASE DEFAULT
+    found_rule = .FALSE.
+  END SELECT
+!-
+  IF (found_rule) THEN
+    iv = 0
+    DO WHILE ( (vid < 0).AND.(iv < ncnbva(fid_in)) )
+      iv = iv+1
+      str1=''
+      iret = NF90_INQUIRE_VARIABLE (ncids(fid_in), iv, &
+                                    name=str1, ndims=ndim)
+      IF (INDEX(dimname,TRIM(str1)) >= 1) THEN
+        vid = iv
+      ENDIF
+    ENDDO
+  ENDIF
+!-
+! Third rule : we find a variable with the same name as the dimension
+! lon = 1
+! lat = 2
+! lev = 3
+!-
+  IF (vid < 0) THEN
+    SELECTCASE(axtype)
+    CASE ('lon')
+      dimnb = 1
+      found_rule = .TRUE.
+    CASE('lat')
+      dimnb = 2
+      found_rule = .TRUE.
+    CASE('lev')
+      dimnb = 3
+      found_rule = .TRUE.
+    CASE DEFAULT
+      found_rule = .FALSE.
+    END SELECT
+!---
+    IF (found_rule) THEN
+      iret = NF90_INQUIRE_DIMENSION (ncids(fid_in), dimnb, name=dimname)
+      iv = 0
+      DO WHILE ( (vid < 0).AND.(iv < ncnbva(fid_in)) )
+        iv = iv+1
+        str1=''
+        iret = NF90_INQUIRE_VARIABLE (ncids(fid_in), iv, &
+                                      name=str1, ndims=ndim)
+        IF (INDEX(dimname,TRIM(str1)) == 1) THEN
+          vid = iv
+        ENDIF
+      ENDDO
+    ENDIF
+  ENDIF
+!-
+! Stop the program if no coordinate was found
+!-
+  IF (vid < 0) THEN
+    CALL histerr (3,'flinfindcood', &
+           'No coordinate axis was found in the file', &
+           'The data in this file can not be used', axtype)
+  ENDIF
+!--------------------------
+END SUBROUTINE flinfindcood
+!-
+!===
+!-
+SUBROUTINE flinclo (fid_in)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+!-
+  INTEGER :: iret
+!---------------------------------------------------------------------
+  iret = NF90_CLOSE (ncids(fid_in))
+  ncfileopen(fid_in) = .FALSE.
+!---------------------
+END SUBROUTINE flinclo
+!-
+!===
+!-
+SUBROUTINE flinquery_var(fid_in, varname, exists)
+!---------------------------------------------------------------------
+!- Queries the existance of a variable in the file.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid_in
+  CHARACTER(LEN=*) varname
+  LOGICAL :: exists
+!-
+  INTEGER :: iret, fid, vid
+!---------------------------------------------------------------------
+  fid = ncids(fid_in)
+  vid = -1
+  iret = NF90_INQ_VARID (fid, varname, vid)
+!-
+  exists = ( (vid >= 0).AND.(iret == NF90_NOERR) )
+!---------------------------
+END SUBROUTINE flinquery_var
+!-
+!===
+!-
+SUBROUTINE flininspect (fid_in)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! fid : File id to inspect
+!-
+  INTEGER :: fid_in
+!-
+!- LOCAL
+!-
+  INTEGER :: iim, jjm, llm, ttm, fid_out
+  INTEGER :: iret, fid, ndims, nvars, nb_atts, id_unlim
+  INTEGER :: iv, in, lll
+  INTEGER :: xid, yid, zid, tid
+  INTEGER,DIMENSION(NF90_MAX_VAR_DIMS) :: idimid
+  CHARACTER(LEN=80) :: name
+  CHARACTER(LEN=30) :: axname
+!---------------------------------------------------------------------
+  fid = ncids(fid_in)
+!-
+  iret = NF90_INQUIRE (fid, nDimensions=ndims, nVariables=nvars, &
+                       nAttributes=nb_atts, unlimitedDimId=id_unlim)
+!-
+  WRITE (*,*) 'IOIPSL ID                   : ',fid_in
+  WRITE (*,*) 'NetCDF ID                   : ',fid
+  WRITE (*,*) 'Number of dimensions        : ',ndims
+  WRITE (*,*) 'Number of variables         : ',nvars
+  WRITE (*,*) 'Number of global attributes : ',nb_atts
+  WRITE (*,*) 'ID unlimited                : ',id_unlim
+!-
+  xid = -1; iim = 0;
+  yid = -1; jjm = 0;
+  zid = -1; llm = 0;
+  tid = -1; ttm = 0;
+!-
+  DO iv=1,ndims
+!---
+    iret = NF90_INQUIRE_DIMENSION (fid, iv, name=axname, len=lll)
+    CALL strlowercase (axname)
+    axname = ADJUSTL(axname)
+!---
+    WRITE (*,*) 'Dimension number : ',iv
+    WRITE (*,*) 'Dimension name   : ',TRIM(axname)
+!---
+    IF      (    (INDEX(axname,'x') == 1) &
+             .OR.(INDEX(axname,'lon') == 1)) THEN
+      xid = iv; iim = lll;
+      WRITE (*,*) 'Dimension X size   : ',iim
+    ELSE IF (    (INDEX(axname,'y') == 1) &
+             .OR.(INDEX(axname,'lat') == 1)) THEN
+      yid = iv; jjm = lll;
+      WRITE (*,*) 'Dimension Y size   : ',jjm
+    ELSE IF (    (INDEX(axname,'lev') == 1) &
+             .OR.(INDEX(axname,'plev') == 1) &
+             .OR.(INDEX(axname,'z') == 1) &
+             .OR.(INDEX(axname,'depth') == 1)) THEN
+      zid = iv; llm = lll;
+      WRITE (*,*) 'Dimension Z size   : ',llm
+    ELSE IF (    (INDEX(axname,'tstep') == 1) &
+             .OR.(INDEX(axname,'time_counter') == 1)) THEN
+!---- For the time we certainly need to allow for other names
+      tid = iv; ttm = lll;
+    ELSE IF (ndims == 1) THEN
+!---- Nothing was found and ndims=1 then we have a vector of data
+      xid = 1; iim = lll;
+    ENDIF
+!---
+  ENDDO
+!-
+! Keep all this information
+!-
+  nbfiles = nbfiles+1
+!-
+  IF (nbfiles > nbfile_max) THEN
+    CALL histerr(3,'flininspect', &
+      'Too many files. Please increase nbfil_max', &
+      'in program flincom.F90.',' ')
+  ENDIF
+!-
+  ncids(nbfiles) = fid
+  ncnbd(nbfiles) = ndims
+!-
+  ncdims(nbfiles,1:4) = (/ iim, jjm, llm, ttm /)
+!-
+  ncfunli(nbfiles) = id_unlim
+  ncnba(nbfiles)   = nb_atts
+  ncnbva(nbfiles)  = nvars
+  ncfileopen(nbfiles) = .TRUE.
+!-
+  fid_out = nbfiles
+!-
+  DO in=1,nvars
+    iret = NF90_INQUIRE_VARIABLE (fid, in, &
+             name=name, ndims=ndims, dimids=idimid, nAtts=nb_atts)
+    WRITE (*,*) 'Variable number  ------------ > ', in
+    WRITE (*,*) 'Variable name        : ', TRIM(name)
+    WRITE (*,*) 'Number of dimensions : ', ndims
+    WRITE (*,*) 'Dimensions ID''s     : ', idimid(1:ndims)
+    WRITE (*,*) 'Number of attributes : ', nb_atts
+  ENDDO
+!-------------------------
+END SUBROUTINE flininspect
+!-
+!===
+!-
+END MODULE flincom
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/fliocom.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/fliocom.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/fliocom.f90	(revision 329)
@@ -0,0 +1,5044 @@
+MODULE fliocom
+!-
+!$Id: fliocom.f90 760 2009-10-26 14:10:32Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+USE netcdf
+!-
+USE defprec
+USE calendar,  ONLY : lock_calendar,ioget_calendar, &
+ &                    ioconf_calendar,ju2ymds,ymds2ju
+USE errioipsl, ONLY : ipslerr,ipsldbg
+USE stringop,  ONLY : strlowercase
+!-
+IMPLICIT NONE
+!-
+PRIVATE
+!-
+PUBLIC :: &
+ &  fliocrfd, fliopstc, fliodefv, flioputv, flioputa, &
+ &  flioopfd, flioinqf, flioinqn, fliogstc, &
+ &  flioinqv, fliogetv, flioinqa, fliogeta, &
+ &  fliorenv, fliorena, fliodela, fliocpya, &
+ &  flioqstc, fliosync, flioclo,  fliodmpf, &
+ &  flio_dom_set,    flio_dom_unset, &
+ &  flio_dom_defset, flio_dom_defunset, flio_dom_definq, &
+ &  flio_dom_file,   flio_dom_att
+!-
+!!--------------------------------------------------------------------
+!! The following PUBLIC parameters (with "flio_" prefix)
+!! are used in the module "fliocom" :
+!!
+!! flio_max_files     : maximum number of simultaneously opened files
+!! flio_max_dims      : maximum number of dimensions for a file
+!! flio_max_var_dims  : maximum number of dimensions for a variable
+!!
+!! FLIO_DOM_NONE    : "named constant" for no_domain identifier
+!! FLIO_DOM_DEFAULT : "named constant" for default_domain identifier
+!!
+!! flio_i  : standard INTEGER external type
+!! flio_r  : standard REAL external type
+!! flio_c  : CHARACTER external type
+!! flio_i1 : INTEGER*1 external type
+!! flio_i2 : INTEGER*2 external type
+!! flio_i4 : INTEGER*4 external type
+!! flio_r4 : REAL*4 external type
+!! flio_r8 : REAL*8 external type
+!!--------------------------------------------------------------------
+  INTEGER,PARAMETER,PUBLIC :: &
+ &  flio_max_files=100, flio_max_dims=10, flio_max_var_dims=5
+  INTEGER,PARAMETER,PUBLIC :: &
+ &  flio_i = -1,        flio_r = -2,        flio_c =nf90_char, &
+ &  flio_i1=nf90_int1,  flio_i2=nf90_int2,  flio_i4=nf90_int4, &
+ &  flio_r4=nf90_real4, flio_r8=nf90_real8
+!-
+  INTEGER,PARAMETER,PUBLIC :: FLIO_DOM_NONE    =-1
+  INTEGER,PARAMETER,PUBLIC :: FLIO_DOM_DEFAULT = 0
+!-
+!!--------------------------------------------------------------------
+!! The "fliocrfd" routine creates a model file
+!! which contains the dimensions needed.
+!!
+!! SUBROUTINE fliocrfd (f_n,f_d_n,f_d_l,f_i,id_dom,mode,c_f_n)
+!!
+!! INPUT
+!!
+!! (C) f_n      : Name of the file to be created
+!! (C) f_d_n(:) : Array of (max nb_fd_mx) names of the dimensions
+!! (I) f_d_l(:) : Array of (max nb_fd_mx) lengths of the dimensions
+!!                For an unlimited dimension, enter a length of -1.
+!!                Actually, only one unlimited dimension is supported.
+!!
+!! OUTPUT
+!!
+!! (I) f_i  : Model file identifier
+!!
+!! Optional INPUT arguments
+!!
+!! (I) id_dom : Identifier of a domain defined by calling
+!!              "flio_dom_set". If this argument is present,
+!!              and not equal to FLIO_DOM_NONE, it will be
+!!              appended to the file name and
+!!              the attributes describing the related DOMAIN
+!!              will be put in the created file.
+!!              This argument can be equal to FLIO_DOM_DEFAULT
+!!              (see "flio_dom_defset").
+!! (C) mode   : Mode used to create the file.
+!!              Supported modes : REPLACE, REP, 32, 64, REP32, REP64.
+!!              If this argument is present with the value "REP[32/64]"
+!!              or the value "REPLACE", the file will be created
+!!              in mode "CLOBBER", else the file will be created
+!!              in mode "NOCLOBBER".
+!!              "32/64" defines the offset mode.
+!!              The default offset mode is 32 bits.
+!!
+!! Optional OUTPUT arguments
+!!
+!! (C) c_f_n : Name of the created file.
+!!             This name can be different of "f_n",
+!!             if a suffix is added to the original name
+!!             (".nc" or "DOMAIN_identifier.nc").
+!!             The length of "c_f_n" must be sufficient
+!!             to receive the created file name.
+!!
+!!- NOTES
+!!
+!! The names used to identify the spatio-temporal dimensions
+!! (dimension associated to a coordinate variable)
+!! are the following :
+!!
+!!  Axis       Names
+!!
+!!    x        'x[...]'  'lon[...]'
+!!    y        'y[...]'  'lat[...]'
+!!    z        'z[...]'  'lev[...]'  'plev[...]'   'depth[...]'
+!!    t        't'       'time'      'tstep[...]'  'time_counter[...]'
+!!
+!! Please, apply these rules so that coordinates are
+!! correctly defined.
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliopstc" routine defines the major coordinates system
+!! (spatio-temporal axis) of the model file (created by fliocrfd).
+!!
+!! SUBROUTINE fliopstc &
+!! & (f_i,x_axis,x_axis_2d,y_axis,y_axis_2d,z_axis, &
+!! &      t_axis,t_init,t_step,t_calendar)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!!
+!! Optional INPUT arguments
+!!
+!! (R) x_axis(:)      : longitudinal grids
+!! (R) x_axis_2d(:,:) : longitudinal grids
+!! (R) y_axis(:)      : latitudinal grids
+!! (R) y_axis_2d(:,:) : latitudinal grids
+!! (R) z_axis(:)      : vertical grid
+!! (I) t_axis(:)      : timesteps on the time axis
+!! (R) t_init         : date in julian days at the beginning
+!! (R) t_step         : timestep in seconds between t_axis steps
+!! (C) t_calendar     : calendar
+!!
+!! [x/y]_axis and [x/y]_axis_2d are mutually exclusive.
+!!
+!!- NOTES
+!!
+!! The variables corresponding to the spatio-temporal coordinates
+!! are created according to the following characteristics :
+!!
+!!- Longitude axis     x_axis / x_axis_2d
+!!   Variable name     'lon'  / 'nav_lon'
+!!   Attributes        Values
+!!   'axis'            "X"
+!!   'standard_name'   "longitude"
+!!   'units'           "degrees_east"
+!!   'valid_min'       MINVAL(x_axis/x_axis_2d)
+!!   'valid_max'       MAXVAL(x_axis/x_axis_2d)
+!!
+!!- Latitude axis      y_axis / y_axis_2d
+!!   Variable name     'lat'  / 'nav_lat'
+!!   Attributes        Values
+!!   'axis'            "Y"
+!!   'standard_name'   "latitude"
+!!   'units'           "degrees_north"
+!!   'valid_min'       MINVAL(y_axis/y_axis_2d)
+!!   'valid_max'       MAXVAL(y_axis/y_axis_2d)
+!!
+!!- Vertical axis      z_axis
+!!   Variable name     'lev'
+!!   Attributes        Values
+!!   'axis'            "Z"
+!!   'standard_name'   "model_level_number"
+!!   'units'           "sigma_level"
+!!   'long_name'       "Sigma Levels"
+!!   'valid_min'       MINVAL(z_axis)
+!!   'valid_max'       MAXVAL(z_axis)
+!!
+!!- Time axis          t_axis
+!!   Variable name     'time'
+!!   Attributes        Values
+!!   'axis'            "T"
+!!   'standard_name'   "time"
+!!   'long_name'       "time steps"
+!!  ['calendar'        user/default valued]
+!!   'units'           calculated
+!!
+!! If you are not satisfied, it is possible
+!! to rename variables ("fliorenv")
+!! or overload the values of attributes ("flioputa").
+!! Be careful : the new values you use must allow to read variables
+!! as coordinates.
+!!
+!! The dimensions associated to the coordinates variables
+!! are searched according to their names (see "fliocrfd")
+!!--------------------------------------------------------------------
+!-
+INTERFACE fliodefv
+!!--------------------------------------------------------------------
+!! The "fliodefv" routines define a variable in a model file.
+!!
+!! SUBROUTINE fliodefv &
+!! & (f_i,v_n,[v_d],v_t, &
+!! &  axis,standard_name,long_name,units,valid_min,valid_max)
+!!
+!! INPUT
+!!
+!! (I)  f_i  : Model file identifier
+!! (C)  v_n  : Name of variable to be defined
+!! (I) [v_d] :
+!!             "not present"
+!!                --> scalar variable
+!!             "array of one or several integers containing
+!!              the identifiers of the dimensions of the variable
+!!              (in the order specified to "fliocrfd"
+!!               or obtained from "flioopfd")"
+!!                --> multidimensioned variable
+!!
+!! Optional INPUT arguments
+!!
+!! (I) v_t : External type of the variable
+!!           "present"     --> see flio_..
+!!           "not present" --> type of standard real
+!! (C) axis,standard_name,long_name,units : Attributes
+!!     (axis should be used only for coordinates)
+!! (R) valid_min,valid_max : Attributes
+!!--------------------------------------------------------------------
+  MODULE PROCEDURE &
+ &  fliodv_r0d,fliodv_rnd
+END INTERFACE
+!-
+INTERFACE flioputv
+!!--------------------------------------------------------------------
+!! The "flioputv" routines put a variable (defined by fliodefv)
+!! in a model file.
+!!
+!! SUBROUTINE flioputv (f_i,v_n,v_v,start,count)
+!!
+!! INPUT
+!!
+!! (I) f_i    : model file identifier
+!! (C) v_n    : name of the variable to be written
+!! (R/I) v_v  : scalar or array (up to flio_max_var_dims dimensions)
+!!              containing the (standard) real/integer values
+!!
+!! Optional INPUT arguments
+!!
+!! (I) start(:) : array of integers specifying the index
+!!                where the first data value will be written
+!! (I) count(:) : array of integers specifying the number of
+!!                indices that will be written along each dimension
+!!                (not present if v_v is a scalar)
+!!--------------------------------------------------------------------
+!?INTEGERS of KIND 1 are not supported on all computers
+  MODULE PROCEDURE &
+ & fliopv_i40,fliopv_i41,fliopv_i42,fliopv_i43,fliopv_i44,fliopv_i45, &
+ & fliopv_i20,fliopv_i21,fliopv_i22,fliopv_i23,fliopv_i24,fliopv_i25, &
+!& fliopv_i10,fliopv_i11,fliopv_i12,fliopv_i13,fliopv_i14,fliopv_i15, &
+ & fliopv_r40,fliopv_r41,fliopv_r42,fliopv_r43,fliopv_r44,fliopv_r45, &
+ & fliopv_r80,fliopv_r81,fliopv_r82,fliopv_r83,fliopv_r84,fliopv_r85
+END INTERFACE
+!-
+INTERFACE flioputa
+!!--------------------------------------------------------------------
+!! The "flioputa" routines put a value for an attribute
+!! in a model file.
+!! If this attribute does not exist, it will be created.
+!!
+!! SUBROUTINE flioputa (f_i,v_n,a_n,a_v)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!! (C) v_n  : Name of variable to which the attribute is assigned.
+!!            If this name is "?", the attribute will be global.
+!! (C) a_n  : Name of the attribute to be defined.
+!! ( ) a_v  : scalar or array of real (kind 4 or 8) or integer values,
+!!            or character string
+!!--------------------------------------------------------------------
+  MODULE PROCEDURE &
+ &  fliopa_r4_0d,fliopa_r4_1d,fliopa_r8_0d,fliopa_r8_1d, &
+ &  fliopa_i4_0d,fliopa_i4_1d,fliopa_tx_0d
+END INTERFACE
+!-
+!!--------------------------------------------------------------------
+!! The "flioopfd" routine opens an existing model file,
+!! and returns the dimensions used in the file and a file identifier.
+!! This information can be used to allocate the space needed
+!! to extract the data from the file.
+!!
+!! SUBROUTINE flioopfd (f_n,f_i,mode,nb_dim,nb_var,nb_gat)
+!!
+!! INPUT
+!!
+!! (C) f_n     : Name of the file to be opened
+!!
+!! OUTPUT
+!!
+!! (I) f_i      : Model file identifier
+!!
+!! Optional INPUT arguments
+!!
+!! (C) mode : Access mode to the file.
+!!            If this argument is present with the value "WRITE",
+!!            the file will be accessed in mode "READ-WRITE",
+!!            else the file will be accessed in mode "READ-ONLY".
+!!
+!! Optional OUTPUT arguments
+!!
+!! (I) nb_dim : number of dimensions
+!! (I) nb_var : number of variables
+!! (I) nb_gat : number of global attributes
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "flioinqf" routine returns information
+!! about an opened model file given its identifier.
+!!
+!! SUBROUTINE flioinqf &
+!! & (f_i,nb_dim,nb_var,nb_gat,id_uld,id_dim,ln_dim)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!!
+!! Optional OUTPUT arguments
+!!
+!! (I) nb_dim    : number of dimensions
+!! (I) nb_var    : number of variables
+!! (I) nb_gat    : number of global attributes
+!! (I) id_uld    : identifier of the unlimited dimension (0 if none)
+!! (I) id_dim(:) : identifiers of the dimensions
+!! (I) ln_dim(:) : lengths of the dimensions
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "flioinqn" routine returns the names
+!! of the entities encountered in an opened model file.
+!!
+!! SUBROUTINE flioinqn &
+!! & (f_i,cn_dim,cn_var,cn_gat,cn_uld, &
+!! &  id_start,id_count,iv_start,iv_count,ia_start,ia_count)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!!
+!! Optional OUTPUT arguments
+!!
+!! (C) cn_dim(:) : names of dimensions
+!! (C) cn_var(:) : names of variables
+!! (C) cn_gat(:) : names of global attributes
+!! (C) cn_uld    : names of the unlimited dimension
+!!
+!! Optional INPUT arguments
+!!
+!! (I) id_start,id_count,iv_start,iv_count,ia_start,ia_count
+!!
+!!  The prefix ( id       / iv      / ia              ) specifies
+!!         the (dimensions/variables/global attributes) entities
+!!
+!!  The suffix "start" specify the index from which
+!!  the first name will be retrieved (1 by default)
+!!
+!!  The suffix "count" specifies the number of names to be retrieved
+!!  (all by default)
+!!
+!!  If a requested entity is not available, a "?" will be returned.
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliogstc" routine extracts the major coordinates system
+!! (spatio-temporal axis) of the model file (opened by flioopfd).
+!!
+!! SUBROUTINE fliogstc &
+!! & (f_i,x_axis,x_axis_2d,y_axis,y_axis_2d,z_axis, &
+!! &      t_axis,t_init,t_step,t_calendar, &
+!! &      x_start,x_count,y_start,y_count, &
+!! &      z_start,z_count,t_start,t_count)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!!
+!! Optional OUTPUT arguments
+!!
+!! (R) x_axis(:)      : longitudinal grids
+!! (R) x_axis_2d(:,:) : longitudinal grids
+!! (R) y_axis(:)      : latitudinal grids
+!! (R) y_axis_2d(:,:) : latitudinal grids
+!! (R) z_axis(:)      : vertical grid
+!! (I) t_axis(:)      : timesteps on the time axis
+!! (R) t_init         : date in julian days at the beginning
+!! (R) t_step         : timestep in seconds between t_axis steps
+!! (C) t_calendar     : calendar attribute
+!!                      (the value is "not found" if the attribute
+!!                       is not present in the model file)
+!!
+!! [x/y]_axis and [x/y]_axis_2d are mutually exclusive.
+!!
+!! Optional INPUT arguments
+!!
+!! (I) x_start,x_count,y_start,y_count,z_start,z_count,t_start,t_count
+!!
+!!  The prefix (x/y/z/t) specifies the concerned direction.
+!!
+!!  The suffix "start" specify the index from which
+!!  the first data value will be read (1 by default)
+!!
+!!  The suffix "count" specifies the number of values to be read
+!!  (all by default)
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "flioinqv" routine returns information about a model
+!! variable given its name.
+!! This information can be used to allocate the space needed
+!! to extract the variable from the file.
+!!
+!! SUBROUTINE flioinqv &
+!! & (f_i,v_n,l_ex,nb_dims,len_dims,id_dims, &
+!! &  nb_atts,cn_atts,ia_start,ia_count)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!! (C) v_n  : Name of the variable
+!!
+!! OUTPUT
+!!
+!! (L) l_ex  : Existence of the variable
+!!
+!! Optional OUTPUT arguments
+!!
+!! (I) v_t          : External type of the variable (see flio_..)
+!! (I) nb_dims      : number of dimensions of the variable
+!! (I) len_dims(:)  : list of dimension lengths of the variable
+!! (I) id_dims(:)   : list of dimension identifiers of the variable
+!! (I) nb_atts      : number of attributes of the variable
+!! (C) cn_atts(:)   : names of the attributes
+!!
+!! Optional INPUT arguments
+!!
+!! (I) ia_start : index of the first attribute whose the name
+!!                will be retrieved (1 by default)
+!! (I) ia_count : number of names to be retrieved (all by default)
+!!
+!!  If a requested entity is not available, a "?" will be returned.
+!!--------------------------------------------------------------------
+!-
+INTERFACE fliogetv
+!!--------------------------------------------------------------------
+!! The "fliogetv" routines get a variable from a model file.
+!!
+!! SUBROUTINE fliogetv (f_i,v_n,v_v,start,count)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!! (C) v_n  : Name of the variable to be read
+!!
+!! OUTPUT
+!!
+!! (R/I) v_v  : scalar or array (up to flio_max_var_dims dimensions)
+!!              that will contain the (standard) real/integer values
+!!
+!! Optional INPUT arguments
+!!
+!! (I) start(:) : array of integers specifying the index
+!!                from which the first data value will be read
+!! (I) count(:) : array of integers specifying the number of
+!!                indices that will be read along each dimension
+!!                (not present if v_v is a scalar)
+!!--------------------------------------------------------------------
+!?INTEGERS of KIND 1 are not supported on all computers
+  MODULE PROCEDURE &
+ & fliogv_i40,fliogv_i41,fliogv_i42,fliogv_i43,fliogv_i44,fliogv_i45, &
+ & fliogv_i20,fliogv_i21,fliogv_i22,fliogv_i23,fliogv_i24,fliogv_i25, &
+!& fliogv_i10,fliogv_i11,fliogv_i12,fliogv_i13,fliogv_i14,fliogv_i15, &
+ & fliogv_r40,fliogv_r41,fliogv_r42,fliogv_r43,fliogv_r44,fliogv_r45, &
+ & fliogv_r80,fliogv_r81,fliogv_r82,fliogv_r83,fliogv_r84,fliogv_r85
+END INTERFACE
+!-
+!!--------------------------------------------------------------------
+!! The "flioinqa" routine returns information about an
+!! attribute of a variable given their names, in a model file.
+!! Information about a variable includes its existence,
+!! and the number of values currently stored in the attribute.
+!! For a string-valued attribute, this is the number of
+!! characters in the string.
+!! This information can be used to allocate the space needed
+!! to extract the attribute from the file.
+!!
+!! SUBROUTINE flioinqa (f_i,v_n,a_n,l_ex,a_t,a_l)
+!!
+!! INPUT
+!!
+!! (I) f_i : Model file identifier
+!! (C) v_n : Name of variable to which the attribute is assigned.
+!!           This name is "?" for a global attribute.
+!! (C) a_n : Name of the concerned attribute.
+!!
+!! OUTPUT
+!!
+!! (L) l_ex : existence of the variable
+!!
+!! Optional OUTPUT arguments
+!!
+!! (I) a_t : external type of the attribute
+!! (I) a_l : number of values of the attribute
+!!--------------------------------------------------------------------
+!-
+INTERFACE fliogeta
+!!--------------------------------------------------------------------
+!! The "fliogeta" routines get a value for an attribute
+!! in a model file.
+!!
+!! SUBROUTINE fliogeta (f_i,v_n,a_n,a_v)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!! (C) v_n  : Name of variable to which the attribute is assigned.
+!!            This name is "?" for a global attribute.
+!! (C) a_n  : Name of the attribute to be retrieved.
+!! ( ) a_v  : scalar or array of real (kind 4 or 8) or integer values,
+!!            or character string
+!!--------------------------------------------------------------------
+  MODULE PROCEDURE &
+ &  flioga_r4_0d,flioga_r4_1d,flioga_r8_0d,flioga_r8_1d, &
+ &  flioga_i4_0d,flioga_i4_1d,flioga_tx_0d
+END INTERFACE
+!-
+!!--------------------------------------------------------------------
+!! The "fliorenv" routine renames a variable, in a model file.
+!!
+!! SUBROUTINE fliorenv (f_i,v_o_n,v_n_n)
+!!
+!! INPUT
+!!
+!! (I) f_i    : Model file identifier
+!! (C) v_o_n  : Old name of the variable
+!! (C) v_n_n  : New name of the variable
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliorena" routine renames an attribute
+!! of a variable, in a model file.
+!!
+!! SUBROUTINE fliorena (f_i,v_n,a_o_n,a_n_n)
+!!
+!! INPUT
+!!
+!! (I) f_i    : Model file identifier
+!! (C) v_n    : Name of variable to which the attribute is assigned.
+!!              This name is "?" for a global attribute.
+!! (C) a_o_n  : Old name of the concerned attribute.
+!! (C) a_n_n  : New name of the concerned attribute.
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliodela" routine deletes an attribute in a model file.
+!!
+!! SUBROUTINE fliodela (f_i,v_n,a_n)
+!!
+!! INPUT
+!!
+!! (I) f_i  : Model file identifier
+!! (C) v_n  : Name of variable to which the attribute is assigned.
+!!            This name is "?" for a global attribute.
+!! (C) a_n  : Name of the concerned attribute.
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliocpya" routine copies an attribute
+!! from one open model file to another.
+!! It can also be used to copy an attribute from
+!! one variable to another within the same model file.
+!!
+!! SUBROUTINE fliocpya (f_i_i,v_n_i,a_n,f_i_o,v_n_o)
+!!
+!! INPUT
+!!
+!! (I) f_i_i : Identifier of the input  model file
+!! (C) v_n_i : Name of the input variable
+!!             This name is "?" for a global attribute.
+!! (C) a_n   : Name of the concerned attribute.
+!! (I) f_i_o : Identifier of the output model file
+!!             It can be the same as the input identifier.
+!! (C) v_n_o : Name of the output variable
+!!             This name is "?" for a global attribute.
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "flioqstc" routine search for a spatio-temporal coordinate
+!! in a model file and returns its name.
+!!
+!! SUBROUTINE flioqstc (f_i,c_type,l_ex,c_name)
+!!
+!! INPUT
+!!
+!! (I) f_i     : Model file identifier
+!! (C) c_type  : Type of the coordinate ("x"/"y"/"z"/"t")
+!!
+!! OUTPUT
+!!
+!! (L) l_ex    : existence of the coordinate
+!! (C) c_name  : name of the coordinate
+!!
+!!- NOTES
+!!
+!! The following rules are used for searching variables
+!! which are spatio-temporal coordinates (x/y/z/t).
+!!
+!!-- Rule 1 : we look for a variable with one dimension
+!!--          and which has the same name as its dimension
+!!
+!!-- Rule 2 : we look for a correct "axis" attribute
+!!
+!!  Axis       Axis attribute             Number of dimensions
+!!             (case insensitive)
+!!
+!!    x         X                         1/2
+!!    y         Y                         1/2
+!!    z         Z                         1
+!!    t         T                         1
+!!
+!!-- Rule 3 : we look for a correct "standard_name" attribute
+!!
+!!  Axis       Axis attribute          Number of dimensions
+!!             (case insensitive)
+!!
+!!    x         longitude              1/2
+!!    y         latitude               1/2
+!!    z         model_level_number     1
+!!    t         time                   1
+!!
+!!-- Rule 4 : we look for a specific name
+!!
+!!  Axis   Names
+!!
+!!    x    'nav_lon' 'lon'    'longitude'
+!!    y    'nav_lat' 'lat'    'latitude'
+!!    z    'depth'   'deptht' 'height'      'level'
+!!         'lev'     'plev'   'sigma_level' 'layer'
+!!    t    'time'    'tstep'  'timesteps'
+!!
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliosync" routine synchronise one or all opened model files,
+!! to minimize data loss in case of abnormal termination.
+!!
+!! SUBROUTINE fliosync (f_i)
+!!
+!! Optional INPUT arguments
+!!
+!! (I) f_i  : Model file identifier
+!!            If this argument is not present,
+!!            all the opened model files are synchronised.
+!---------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "flioclo" routine closes one or all opened model files
+!! and frees the space needed to keep information about the files
+!!
+!! SUBROUTINE flioclo (f_i)
+!!
+!! Optional INPUT arguments
+!!
+!! (I) f_i  : Model file identifier
+!!            If this argument is not present,
+!!            all the opened model files are closed.
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! The "fliodmpf" routine dumps a model file
+!! and prints the result on the standard output.
+!!
+!! SUBROUTINE fliodmpf (f_n)
+!!
+!! INPUT
+!!
+!! (C) f_n  : Name of the model file to be dumped
+!!--------------------------------------------------------------------
+!-
+!!--------------------------------------------------------------------
+!! This "flio_dom_set" sets up the domain activity of IOIPSL.
+!! It stores all the domain information and allows it to be stored
+!! in the model file and change the file names.
+!!
+!! This routine must be called by the user before opening
+!! the model file.
+!!
+!! SUBROUTINE flio_dom_set &
+!!  & (dtnb,dnb,did,dsg,dsl,dpf,dpl,dhs,dhe,cdnm,id_dom)
+!!
+!! INPUT
+!!
+!! (I) dtnb   : total number of domains
+!! (I) dnb    : domain number
+!! (I) did(:) : distributed dimensions identifiers
+!!              (up to 5 dimensions are supported)
+!! (I) dsg(:) : total number of points for each dimension
+!! (I) dsl(:) : local number of points for each dimension
+!! (I) dpf(:) : position of first local point for each dimension
+!! (I) dpl(:) : position of last local point for each dimension
+!! (I) dhs(:) : start halo size for each dimension
+!! (I) dhe(:) : end halo size for each dimension
+!! (C) cdnm   : Model domain definition name.
+!!              The names actually supported are :
+!!              "BOX", "APPLE", "ORANGE".
+!!              These names are case insensitive.
+!!
+!! OUTPUT argument
+!!
+!! (I) id_dom : Model domain identifier
+!!
+!!--------------------------------------------------------------------
+!!
+!!--------------------------------------------------------------------
+!! The "flio_dom_unset" routine unsets one or all set domains
+!! and frees the space needed to keep information about the domains
+!!
+!! This routine should be called by the user to free useless domains.
+!!
+!! SUBROUTINE flio_dom_unset (id_dom)
+!!
+!! Optional INPUT arguments
+!!
+!! (I) id_dom : Model domain identifier
+!!      >=1 & <= dom_max_nb : the domain is closed
+!!      not present         : all the set model domains are unset
+!!--------------------------------------------------------------------
+!!
+!!--------------------------------------------------------------------
+!! The "flio_dom_defset" sets
+!! the default domain identifier.
+!!
+!! SUBROUTINE flio_dom_defset (id_dom)
+!!
+!! INPUT argument
+!!
+!! (I) id_dom : Model default domain identifier
+!!     ( >=1 & <= dom_max_nb )
+!!     This identifier will be able to be taken by calling
+!!     "flio_dom_definq" and used to create model files
+!!     with the corresponding domain definitions
+!!--------------------------------------------------------------------
+!!
+!!--------------------------------------------------------------------
+!! The "flio_dom_defunset" routine unsets
+!! the default domain identifier.
+!!
+!! SUBROUTINE flio_dom_defunset ()
+!!
+!!--------------------------------------------------------------------
+!!
+!!--------------------------------------------------------------------
+!! The "flio_dom_definq" routine inquires about
+!! the default domain identifier.
+!! You should call this procedure to safeguard the current
+!! default domain identifier if you wish to use locally
+!! another default domain, in order to restore it.
+!!
+!! SUBROUTINE flio_dom_definq (id_dom)
+!!
+!! OUTPUT argument
+!!
+!! (I) id_dom : Model default domain identifier
+!!     IF no default domain identifier has been set,
+!!     the returned value is "FLIO_DOM_NONE".
+!!--------------------------------------------------------------------
+!-
+!---------------------------------------------------------------------
+! This is the data we keep concerning each file we open
+!---------------------------------------------------------------------
+!- For each file
+!- (I) nw_id(f_i)   : index to access at this file
+!- (I) nw_nd(f_i)   : number of dimensions
+!- (I) nw_nv(f_i)   : number of variables
+!- (I) nw_na(f_i)   : number of global attributes
+!- (I) nw_un(f_i)   : ID of the first unlimited dimension
+!- (L) lw_hm(f_i)   : for mode handling (.TRUE. define, .FALSE. data)
+!- (I) nw_di(:,f_i) : dimension IDs in the file "f_i"
+!- (I) nw_dl(:,f_i) : dimension lengths in the file "f_i"
+!- (I) nw_ai(:,f_i) : dimension Ids for the axis in the file "f_i"
+!---------------------------------------------------------------------
+  INTEGER,PARAMETER :: &
+ &  nb_fi_mx=flio_max_files, &
+ &  nb_fd_mx=flio_max_dims, &
+ &  nb_vd_mx=flio_max_var_dims
+  INTEGER,PARAMETER :: nb_ax_mx=4
+!-
+  INTEGER,PARAMETER :: k_lon=1, k_lat=2, k_lev=3, k_tim=4
+!-
+  INTEGER,DIMENSION(nb_fi_mx),SAVE :: &
+ &  nw_id=-1,nw_nd,nw_nv,nw_na,nw_un
+  LOGICAL,DIMENSION(nb_fi_mx),SAVE :: lw_hm
+  INTEGER,DIMENSION(nb_fd_mx,nb_fi_mx),SAVE :: nw_di=-1,nw_dl=-1
+  INTEGER,DIMENSION(nb_ax_mx,nb_fi_mx),SAVE :: nw_ai=-1
+!-
+! Maximum number of simultaneously defined domains
+  INTEGER,PARAMETER :: dom_max_nb=10
+!-
+! Maximum number of distributed dimensions for each domain
+  INTEGER,PARAMETER :: dom_max_dims=5
+!-
+! Default domain identifier
+  INTEGER,SAVE :: id_def_dom=FLIO_DOM_NONE
+!-
+! Supported domain definition names
+  INTEGER,PARAMETER :: n_dns=3, l_dns=7
+  CHARACTER(LEN=l_dns),DIMENSION(n_dns),SAVE :: &
+ &  c_dns=(/ "box    ","apple  ","orange "/)
+!-
+! DOMAINS related variables
+  INTEGER,DIMENSION(1:dom_max_nb),SAVE :: &
+ &  d_d_n=-1, d_n_t=0, d_n_c=0
+  INTEGER,DIMENSION(1:dom_max_dims,1:dom_max_nb),SAVE :: &
+ &  d_d_i, d_s_g, d_s_l, d_p_f, d_p_l, d_h_s, d_h_e
+  CHARACTER(LEN=l_dns),DIMENSION(1:dom_max_nb),SAVE :: c_d_t
+!-
+!===
+CONTAINS
+!===
+!-
+!---------------------------------------------------------------------
+!- Public procedures
+!---------------------------------------------------------------------
+!-
+!===
+SUBROUTINE fliocrfd (f_n,f_d_n,f_d_l,f_i,id_dom,mode,c_f_n)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: f_n
+  CHARACTER(LEN=*),DIMENSION(:),INTENT(IN) :: f_d_n
+  INTEGER,DIMENSION(:),INTENT(IN) :: f_d_l
+  INTEGER,INTENT(OUT) :: f_i
+  INTEGER,OPTIONAL,INTENT(IN) :: id_dom
+  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: mode
+  CHARACTER(LEN=*),OPTIONAL,INTENT(OUT) :: c_f_n
+!-
+  INTEGER :: i_rc,f_e,idid,ii,m_c,n_u
+  CHARACTER(LEN=NF90_MAX_NAME) :: f_nw
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliocrfd - file name : ",TRIM(f_n)
+  ENDIF
+!-
+! Search for a free local identifier
+  f_i = flio_rid()
+  IF (f_i < 0) THEN
+    CALL ipslerr (3,'fliocrfd', &
+ &   'Too many files.','Please increase nb_fi_mx', &
+ &   'in module fliocom.f90.')
+  ENDIF
+!-
+! Update the name of the file
+  f_nw = f_n
+  CALL flio_dom_file (f_nw,id_dom)
+!-
+! Check the dimensions
+  IF (SIZE(f_d_l) /= SIZE(f_d_n)) THEN
+    CALL ipslerr (3,'fliocrfd', &
+ &   'The number of names is not equal to the number of lengths', &
+ &   'for the dimensions of the file',TRIM(f_nw))
+  ENDIF
+  IF (SIZE(f_d_l) > nb_fd_mx) THEN
+    CALL ipslerr (3,'fliocrfd', &
+ &   'Too many dimensions','to create the file',TRIM(f_nw))
+  ENDIF
+!-
+! Check the mode
+  IF (PRESENT(mode)) THEN
+    SELECT CASE (TRIM(mode))
+    CASE('REPLACE','REP','REP64')
+      m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
+    CASE('REP32')
+      m_c = NF90_CLOBBER
+    CASE('32')
+      m_c = NF90_NOCLOBBER
+    CASE('64')
+      m_c = IOR(NF90_NOCLOBBER,NF90_64BIT_OFFSET)
+    CASE DEFAULT
+      m_c = IOR(NF90_NOCLOBBER,NF90_64BIT_OFFSET)
+    END SELECT
+  ELSE
+    m_c = IOR(NF90_NOCLOBBER,NF90_64BIT_OFFSET)
+  ENDIF
+!-
+! Create file (and enter the definition mode)
+  i_rc = NF90_CREATE(f_nw,m_c,f_e)
+  lw_hm(f_i) = .TRUE.
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (3,'fliocrfd', &
+ &   'Could not create file :',TRIM(f_nw), &
+ &   TRIM(NF90_STRERROR(i_rc))//' (Netcdf)')
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) '  fliocrfd, external model file-id : ',f_e
+  ENDIF
+!-
+! Create dimensions
+  n_u = 0
+  DO ii=1,SIZE(f_d_l)
+    IF (f_d_l(ii) == -1) THEN
+      IF (n_u == 0) THEN
+        i_rc = NF90_DEF_DIM(f_e,TRIM(f_d_n(ii)),NF90_UNLIMITED,idid)
+        n_u = n_u+1
+      ELSE
+        CALL ipslerr (3,'fliocrfd', &
+ &       'Can not handle more than one unlimited dimension', &
+ &       'for file :',TRIM(f_nw))
+      ENDIF
+    ELSE IF (f_d_l(ii) > 0) THEN
+      i_rc = NF90_DEF_DIM(f_e,TRIM(f_d_n(ii)),f_d_l(ii),idid)
+    ENDIF
+    IF ( ((f_d_l(ii) == -1).OR.(f_d_l(ii) > 0)) &
+ &      .AND.(i_rc /= NF90_NOERR) ) THEN
+      CALL ipslerr (3,'fliocrfd', &
+ &     'One dimension can not be defined', &
+ &     'for the file :',TRIM(f_nw))
+    ENDIF
+  ENDDO
+!-
+! Define "Conventions" global attribute
+  i_rc = NF90_PUT_ATT(f_e,NF90_GLOBAL,'Conventions',"CF-1.1")
+!-
+! Add the DOMAIN attributes if needed
+  CALL flio_dom_att (f_e,id_dom)
+!-
+! Keep the file information
+  nw_id(f_i) = f_e
+  CALL flio_inf (f_e, &
+ &  nb_dims=nw_nd(f_i),id_unlm=nw_un(f_i),nb_atts=nw_na(f_i), &
+ &  nn_idm=nw_di(:,f_i),nn_ldm=nw_dl(:,f_i),nn_aid=nw_ai(:,f_i))
+!-
+! Return the created file name if needed
+  IF (PRESENT(c_f_n)) THEN
+    IF (LEN(c_f_n) >= LEN_TRIM(f_nw)) THEN
+      c_f_n = TRIM(f_nw)
+    ELSE
+      CALL ipslerr (3,'fliocrfd', &
+ &     'the length of "c_f_n" is not sufficient to receive', &
+ &     'the name of the created file :',TRIM(f_nw))
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) '<-fliocrfd'
+  ENDIF
+!----------------------
+END SUBROUTINE fliocrfd
+!===
+SUBROUTINE fliopstc &
+ & (f_i,x_axis,x_axis_2d,y_axis,y_axis_2d,z_axis, &
+ &      t_axis,t_init,t_step,t_calendar)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  REAL,DIMENSION(:),OPTIONAL,INTENT(IN)    :: x_axis,y_axis
+  REAL,DIMENSION(:,:),OPTIONAL,INTENT(IN)  :: x_axis_2d,y_axis_2d
+  REAL,DIMENSION(:),OPTIONAL,INTENT(IN)    :: z_axis
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: t_axis
+  CHARACTER(LEN=*),OPTIONAL,INTENT(IN)     :: t_calendar
+  REAL,OPTIONAL,INTENT(IN)                 :: t_init,t_step
+!-
+  INTEGER :: i_rc,f_e
+  INTEGER :: lonid,latid,levid,timeid
+  INTEGER :: j_yy,j_mo,j_dd,j_hh,j_mn,j_ss
+  REAL    :: dt,r_ss,v_min,v_max
+  INTEGER :: k,k_1,k_2
+  LOGICAL :: l_tmp
+  CHARACTER(LEN=20) :: c_tmp1
+  CHARACTER(LEN=40) :: c_tmp2
+  CHARACTER(LEN=80) :: c_tmp3
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliopstc"
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliopstc',f_i,f_e)
+!-
+! Validate the coherence of the arguments
+!-
+  IF (    (PRESENT(x_axis).AND.PRESENT(x_axis_2d)) &
+ &    .OR.(PRESENT(y_axis).AND.PRESENT(y_axis_2d)) ) THEN
+    CALL ipslerr (3,'fliopstc', &
+ &    'The [x/y]_axis arguments', &
+ &    'are not coherent :',&
+ &    'can not handle two [x/y]_axis')
+  ENDIF
+!-
+  IF (    PRESENT(x_axis).OR.PRESENT(x_axis_2d) &
+ &    .OR.PRESENT(y_axis).OR.PRESENT(y_axis_2d) ) THEN
+    k_1=nw_ai(k_lon,f_i); k_2=nw_ai(k_lat,f_i);
+  ENDIF
+!-
+! Define the longitude axis
+!-
+  IF (PRESENT(x_axis).OR.PRESENT(x_axis_2d)) THEN
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Define the Longitude axis'
+    ENDIF
+!---
+    IF (PRESENT(x_axis)) THEN
+      IF (SIZE(x_axis) /= nw_dl(k_1,f_i)) THEN
+        CALL ipslerr (3,'fliopstc', &
+ &       'Invalid x_axis dimension :', &
+ &       'not equal to the dimension', &
+ &       'defined at the creation of the file')
+      ENDIF
+    ELSE
+      IF (    (SIZE(x_axis_2d,DIM=1) /= nw_dl(k_1,f_i)) &
+ &        .OR.(SIZE(x_axis_2d,DIM=2) /= nw_dl(k_2,f_i)) ) THEN
+        CALL ipslerr (3,'fliopstc', &
+ &       'Invalid x_axis_2d dimensions :', &
+ &       'not equal to the dimensions', &
+ &       'defined at the creation of the file')
+      ENDIF
+    ENDIF
+!---
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    IF (PRESENT(x_axis)) THEN
+      i_rc = NF90_DEF_VAR(f_e,"lon",NF90_REAL4, &
+ &                        nw_di(k_1,f_i),lonid)
+      v_min = MINVAL(x_axis)
+      v_max = MAXVAL(x_axis)
+    ELSE
+      i_rc = NF90_DEF_VAR(f_e,"nav_lon",NF90_REAL4, &
+ &             nw_di((/k_1,k_2/),f_i),lonid)
+      v_min = MINVAL(x_axis_2d)
+      v_max = MAXVAL(x_axis_2d)
+    ENDIF
+    i_rc = NF90_PUT_ATT(f_e,lonid,"axis","X")
+    i_rc = NF90_PUT_ATT(f_e,lonid,'standard_name',"longitude")
+    i_rc = NF90_PUT_ATT(f_e,lonid,'units',"degrees_east")
+    i_rc = NF90_PUT_ATT(f_e,lonid,'valid_min',REAL(v_min,KIND=4))
+    i_rc = NF90_PUT_ATT(f_e,lonid,'valid_max',REAL(v_max,KIND=4))
+  ENDIF
+!-
+! Define the Latitude axis
+!-
+  IF (PRESENT(y_axis).OR.PRESENT(y_axis_2d)) THEN
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Define the Latitude axis'
+    ENDIF
+!---
+    IF (PRESENT(y_axis)) THEN
+      IF (SIZE(y_axis) /= nw_dl(k_2,f_i)) THEN
+        CALL ipslerr (3,'fliopstc', &
+ &       'Invalid y_axis dimension :', &
+ &       'not equal to the dimension', &
+ &       'defined at the creation of the file')
+      ENDIF
+    ELSE
+      IF (    (SIZE(y_axis_2d,DIM=1) /= nw_dl(k_1,f_i)) &
+ &        .OR.(SIZE(y_axis_2d,DIM=2) /= nw_dl(k_2,f_i)) ) THEN
+        CALL ipslerr (3,'fliopstc', &
+ &       'Invalid y_axis_2d dimensions :', &
+ &       'not equal to the dimensions', &
+ &       'defined at the creation of the file')
+      ENDIF
+    ENDIF
+!---
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    IF (PRESENT(y_axis)) THEN
+      i_rc = NF90_DEF_VAR(f_e,"lat",NF90_REAL4, &
+ &                        nw_di(k_2,f_i),latid)
+      v_min = MINVAL(y_axis)
+      v_max = MAXVAL(y_axis)
+    ELSE
+      i_rc = NF90_DEF_VAR(f_e,"nav_lat",NF90_REAL4, &
+ &             nw_di((/k_1,k_2/),f_i),latid)
+      v_min = MINVAL(y_axis_2d)
+      v_max = MAXVAL(y_axis_2d)
+    ENDIF
+    i_rc = NF90_PUT_ATT(f_e,latid,"axis","Y")
+    i_rc = NF90_PUT_ATT(f_e,latid,'standard_name',"latitude")
+    i_rc = NF90_PUT_ATT(f_e,latid,'units',"degrees_north")
+    i_rc = NF90_PUT_ATT(f_e,latid,'valid_min',REAL(v_min,KIND=4))
+    i_rc = NF90_PUT_ATT(f_e,latid,'valid_max',REAL(v_max,KIND=4))
+  ENDIF
+!-
+! Define the Vertical axis
+!-
+  IF (PRESENT(z_axis)) THEN
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Define the Vertical axis'
+    ENDIF
+!---
+    k_1=nw_ai(k_lev,f_i);
+!---
+    IF (SIZE(z_axis) /= nw_dl(k_1,f_i)) THEN
+      CALL ipslerr (3,'fliopstc', &
+ &     'Invalid z_axis dimension :', &
+ &     'not equal to the dimension', &
+ &     'defined at the creation of the file')
+    ENDIF
+!---
+    v_min = MINVAL(z_axis)
+    v_max = MAXVAL(z_axis)
+!---
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    i_rc = NF90_DEF_VAR(f_e,'lev',NF90_REAL4, &
+ &                      nw_di(k_1,f_i),levid)
+    i_rc = NF90_PUT_ATT(f_e,levid,"axis","Z")
+    i_rc = NF90_PUT_ATT(f_e,levid,'standard_name','model_level_number')
+    i_rc = NF90_PUT_ATT(f_e,levid,'units','sigma_level')
+    i_rc = NF90_PUT_ATT(f_e,levid,'long_name','Sigma Levels')
+    i_rc = NF90_PUT_ATT(f_e,levid,'valid_min',REAL(v_min,KIND=4))
+    i_rc = NF90_PUT_ATT(f_e,levid,'valid_max',REAL(v_max,KIND=4))
+  ENDIF
+!-
+! Define the Time axis
+!-
+  IF (PRESENT(t_axis).AND.PRESENT(t_init).AND.PRESENT(t_step)) THEN
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Define the Time axis'
+    ENDIF
+!---
+    k_1=nw_ai(k_tim,f_i);
+!---
+    IF (     (nw_dl(k_1,f_i) /= 0) &
+ &      .AND.(SIZE(t_axis) /= nw_dl(k_1,f_i)) ) THEN
+      CALL ipslerr (3,'fliopstc', &
+ &     'Invalid t_axis dimension :', &
+ &     'not equal to the dimension', &
+ &     'defined at the creation of the file')
+    ENDIF
+!-- Retrieve the calendar date
+    CALL lock_calendar (old_status=l_tmp)
+    IF (PRESENT(t_calendar)) THEN
+      CALL ioget_calendar (c_tmp1)
+      CALL lock_calendar (new_status=.FALSE.)
+      CALL ioconf_calendar (TRIM(t_calendar))
+    ENDIF
+    CALL ju2ymds (t_init,j_yy,j_mo,j_dd,r_ss)
+    IF (PRESENT(t_calendar)) THEN
+      CALL lock_calendar (new_status=.FALSE.)
+      CALL ioconf_calendar (TRIM(c_tmp1))
+    ENDIF
+    CALL lock_calendar (new_status=l_tmp)
+!--
+    k=NINT(r_ss)
+    j_hh=k/3600
+    k=k-3600*j_hh
+    j_mn=k/60
+    j_ss=k-60*j_mn
+!-- Calculate the step unit
+    IF      (ABS(t_step) >= 604800.) THEN
+      dt = t_step/604800.
+      c_tmp2 = 'weeks'
+    ELSE IF (ABS(t_step) >= 86400.) THEN
+      dt = t_step/86400.
+      c_tmp2 = 'days'
+    ELSE IF (ABS(t_step) >=  3600.) THEN
+      dt = t_step/3600.
+      c_tmp2 = 'hours'
+    ELSE IF (ABS(t_step) >=    60.) THEN
+      dt = t_step/60.
+      c_tmp2 = 'minutes'
+    ELSE
+      dt = t_step
+      c_tmp2 = 'seconds'
+    ENDIF
+!---
+    c_tmp1 = ''
+    IF (ABS(dt-NINT(dt)) <= ABS(10.*EPSILON(dt))) THEN
+      IF (NINT(dt) /= 1) THEN
+        WRITE (UNIT=c_tmp1,FMT='(I15)') NINT(dt)
+      ENDIF
+    ELSE
+      IF (dt < 1.) THEN
+       WRITE (UNIT=c_tmp1,FMT='(F8.5)') dt
+      ELSE
+       WRITE (UNIT=c_tmp1,FMT='(F17.5)') dt
+      ENDIF
+      DO k=LEN_TRIM(c_tmp1),1,-1
+        IF (c_tmp1(k:k) /= '0') THEN
+          EXIT
+        ELSE
+          c_tmp1(k:k) = ' '
+        ENDIF
+      ENDDO
+    ENDIF
+    c_tmp2 = TRIM(c_tmp1)//' '//TRIM(c_tmp2)
+    WRITE (UNIT=c_tmp3, &
+ &   FMT='(A,I4.4,"-",I2.2,"-",I2.2," ",I2.2,":",I2.2,":",I2.2)') &
+ &    TRIM(ADJUSTL(c_tmp2))//' since ',j_yy,j_mo,j_dd,j_hh,j_mn,j_ss
+!---
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    i_rc = NF90_DEF_VAR(f_e,'time',NF90_REAL4, &
+ &                      nw_di(k_1,f_i),timeid)
+    i_rc = NF90_PUT_ATT(f_e,timeid,"axis",'T')
+    i_rc = NF90_PUT_ATT(f_e,timeid,'standard_name','time')
+    i_rc = NF90_PUT_ATT(f_e,timeid,'long_name','time steps')
+    IF (PRESENT(t_calendar)) THEN
+      i_rc = NF90_PUT_ATT(f_e,timeid,'calendar',TRIM(t_calendar))
+    ENDIF
+    i_rc = NF90_PUT_ATT(f_e,timeid,'units',TRIM(c_tmp3))
+  ELSE IF (PRESENT(t_axis).OR.PRESENT(t_init).OR.PRESENT(t_step)) THEN
+    CALL ipslerr (3,'fliopstc', &
+ &   'For time axis and coordinates', &
+ &   'arguments t_axis AND t_init AND t_step', &
+ &   'must be PRESENT')
+  ENDIF
+!-
+! Ensuring data mode
+!-
+    CALL flio_hdm (f_i,f_e,.FALSE.)
+!-
+! Create the longitude axis
+!-
+  IF (PRESENT(x_axis).OR.PRESENT(x_axis_2d)) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Create the Longitude axis'
+    ENDIF
+    IF (PRESENT(x_axis)) THEN
+      i_rc = NF90_PUT_VAR(f_e,lonid,x_axis(:))
+    ELSE
+      i_rc = NF90_PUT_VAR(f_e,lonid,x_axis_2d(:,:))
+    ENDIF
+  ENDIF
+!-
+! Create the Latitude axis
+!-
+  IF (PRESENT(y_axis).OR.PRESENT(y_axis_2d)) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Create the Latitude axis'
+    ENDIF
+    IF (PRESENT(y_axis)) THEN
+      i_rc = NF90_PUT_VAR(f_e,latid,y_axis(:))
+    ELSE
+      i_rc = NF90_PUT_VAR(f_e,latid,y_axis_2d(:,:))
+    ENDIF
+  ENDIF
+!-
+! Create the Vertical axis
+!-
+  IF (PRESENT(z_axis)) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Create the Vertical axis'
+    ENDIF
+    i_rc = NF90_PUT_VAR(f_e,levid,z_axis(:))
+  ENDIF
+!-
+! Create the Time axis
+!-
+  IF (PRESENT(t_axis)) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliopstc : Create the Time axis'
+    ENDIF
+    i_rc = NF90_PUT_VAR(f_e,timeid,REAL(t_axis(:)))
+  ENDIF
+!-
+! Keep all this information
+!-
+  CALL flio_inf (f_e,nb_vars=nw_nv(f_i),nb_atts=nw_na(f_i))
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliopstc"
+  ENDIF
+!----------------------
+END SUBROUTINE fliopstc
+!===
+SUBROUTINE fliodv_r0d &
+ & (f_i,v_n,v_t, &
+ &  axis,standard_name,long_name,units,valid_min,valid_max)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER,OPTIONAL,INTENT(IN) :: v_t
+  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: &
+ & axis,standard_name,long_name,units
+  REAL,OPTIONAL,INTENT(IN) :: valid_min,valid_max
+!---------------------------------------------------------------------
+  CALL flio_udv &
+ &  (f_i,0,v_n,(/0/),v_t, &
+ &   axis,standard_name,long_name,units,valid_min,valid_max)
+!------------------------
+END SUBROUTINE fliodv_r0d
+!===
+SUBROUTINE fliodv_rnd &
+ & (f_i,v_n,v_d,v_t, &
+ &  axis,standard_name,long_name,units,valid_min,valid_max)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER,DIMENSION(:),INTENT(IN) :: v_d
+  INTEGER,OPTIONAL,INTENT(IN) :: v_t
+  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: &
+ & axis,standard_name,long_name,units
+  REAL,OPTIONAL,INTENT(IN) :: valid_min,valid_max
+!---------------------------------------------------------------------
+  CALL flio_udv &
+ &  (f_i,SIZE(v_d),v_n,v_d,v_t, &
+ &   axis,standard_name,long_name,units,valid_min,valid_max)
+!------------------------
+END SUBROUTINE fliodv_rnd
+!===
+SUBROUTINE flio_udv &
+ & (f_i,n_d,v_n,v_d,v_t, &
+ &  axis,standard_name,long_name,units,valid_min,valid_max)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i,n_d
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER,DIMENSION(:),INTENT(IN) :: v_d
+  INTEGER,OPTIONAL,INTENT(IN) :: v_t
+  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: &
+ & axis,standard_name,long_name,units
+  REAL,OPTIONAL,INTENT(IN) :: valid_min,valid_max
+!-
+  INTEGER :: f_e,m_k,i_v,i_rc,ii,idd
+  INTEGER,DIMENSION(nb_vd_mx) :: a_i
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliodefv ",TRIM(v_n)," ",n_d,"D"
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliodefv',f_i,f_e)
+!-
+  IF (n_d > 0) THEN
+    IF (n_d > nb_vd_mx) THEN
+      CALL ipslerr (3,'fliodefv', &
+ &     'Too many dimensions', &
+ &     'required for the variable',TRIM(v_n))
+    ENDIF
+  ENDIF
+!-
+  DO ii=1,n_d
+    IF ( (v_d(ii) >= 1).AND.(v_d(ii) <= nb_fd_mx) ) THEN
+      idd = nw_di(v_d(ii),f_i)
+      IF (idd > 0) THEN
+        a_i(ii) = idd
+      ELSE
+        CALL ipslerr (3,'fliodefv', &
+ &       'Invalid dimension identifier','(not defined)',' ')
+      ENDIF
+    ELSE
+      CALL ipslerr (3,'fliodefv', &
+ &     'Invalid dimension identifier','(not supported)',' ')
+    ENDIF
+  ENDDO
+!-
+  i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+!---
+    IF (PRESENT(v_t)) THEN
+      IF      (v_t == flio_i) THEN
+        IF (i_std == i_8) THEN
+!-------- Not yet supported by NETCDF
+!-------- m_k = flio_i8
+          m_k = flio_i4
+        ELSE
+          m_k = flio_i4
+        ENDIF
+      ELSE IF (v_t == flio_r) THEN
+        IF (r_std == r_8) THEN
+          m_k = flio_r8
+        ELSE
+          m_k = flio_r4
+        ENDIF
+      ELSE
+        m_k = v_t
+      ENDIF
+    ELSE IF (r_std == r_8) THEN
+      m_k = flio_r8
+    ELSE
+      m_k = flio_r4
+    ENDIF
+    IF (n_d > 0) THEN
+      i_rc = NF90_DEF_VAR(f_e,v_n,m_k,a_i(1:n_d),i_v)
+    ELSE
+      i_rc = NF90_DEF_VAR(f_e,v_n,m_k,i_v)
+    ENDIF
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliodefv', &
+ &      'Variable '//TRIM(v_n)//' not defined','Error :', &
+ &      TRIM(NF90_STRERROR(i_rc)))
+    ENDIF
+    nw_nv(f_i) = nw_nv(f_i)+1
+!---
+    IF (PRESENT(axis)) THEN
+      i_rc = NF90_PUT_ATT(f_e,i_v,'axis',TRIM(axis))
+    ENDIF
+    IF (PRESENT(standard_name)) THEN
+      i_rc = NF90_PUT_ATT(f_e,i_v,'standard_name',TRIM(standard_name))
+    ENDIF
+    IF (PRESENT(long_name)) THEN
+      i_rc = NF90_PUT_ATT(f_e,i_v,'long_name',TRIM(long_name))
+    ENDIF
+    IF (PRESENT(units)) THEN
+      i_rc = NF90_PUT_ATT(f_e,i_v,'units',TRIM(units))
+    ENDIF
+    IF (PRESENT(valid_min)) THEN
+      i_rc = NF90_PUT_ATT(f_e,i_v,'valid_min',valid_min)
+    ENDIF
+    IF (PRESENT(valid_max)) THEN
+      i_rc = NF90_PUT_ATT(f_e,i_v,'valid_max',valid_max)
+    ENDIF
+!---
+  ELSE
+    CALL ipslerr (3,'fliodefv','Variable',TRIM(v_n),'already exist')
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliodefv"
+  ENDIF
+!----------------------
+END SUBROUTINE flio_udv
+!===
+SUBROUTINE fliopv_i40 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_40=v_v,start=start)
+!------------------------
+END SUBROUTINE fliopv_i40
+!===
+SUBROUTINE fliopv_i41 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_41=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i41
+!===
+SUBROUTINE fliopv_i42 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_42=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i42
+!===
+SUBROUTINE fliopv_i43 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_43=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i43
+!===
+SUBROUTINE fliopv_i44 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_44=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i44
+!===
+SUBROUTINE fliopv_i45 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_45=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i45
+!===
+SUBROUTINE fliopv_i20 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_20=v_v,start=start)
+!------------------------
+END SUBROUTINE fliopv_i20
+!===
+SUBROUTINE fliopv_i21 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_21=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i21
+!===
+SUBROUTINE fliopv_i22 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_22=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i22
+!===
+SUBROUTINE fliopv_i23 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_23=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i23
+!===
+SUBROUTINE fliopv_i24 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_24=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i24
+!===
+SUBROUTINE fliopv_i25 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,i_25=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_i25
+!===
+!?INTEGERS of KIND 1 are not supported on all computers
+!?SUBROUTINE fliopv_i10 (f_i,v_n,v_v,start)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),INTENT(IN) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!?!---------------------------------------------------------------------
+!?  CALL flio_upv (f_i,v_n,i_10=v_v,start=start)
+!?!------------------------
+!?END SUBROUTINE fliopv_i10
+!?!===
+!?SUBROUTINE fliopv_i11 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:),INTENT(IN) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_upv (f_i,v_n,i_11=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliopv_i11
+!?!===
+!?SUBROUTINE fliopv_i12 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:),INTENT(IN) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_upv (f_i,v_n,i_12=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliopv_i12
+!?!===
+!?SUBROUTINE fliopv_i13 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:,:),INTENT(IN) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_upv (f_i,v_n,i_13=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliopv_i13
+!?!===
+!?SUBROUTINE fliopv_i14 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:,:,:),INTENT(IN) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_upv (f_i,v_n,i_14=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliopv_i14
+!?!===
+!?SUBROUTINE fliopv_i15 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:,:,:,:),INTENT(IN) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_upv (f_i,v_n,i_15=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliopv_i15
+!===
+SUBROUTINE fliopv_r40 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_40=v_v,start=start)
+!------------------------
+END SUBROUTINE fliopv_r40
+!===
+SUBROUTINE fliopv_r41 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_41=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r41
+!===
+SUBROUTINE fliopv_r42 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_42=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r42
+!===
+SUBROUTINE fliopv_r43 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_43=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r43
+!===
+SUBROUTINE fliopv_r44 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_44=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r44
+!===
+SUBROUTINE fliopv_r45 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_45=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r45
+!===
+SUBROUTINE fliopv_r80 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_80=v_v,start=start)
+!------------------------
+END SUBROUTINE fliopv_r80
+!===
+SUBROUTINE fliopv_r81 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_81=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r81
+!===
+SUBROUTINE fliopv_r82 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_82=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r82
+!===
+SUBROUTINE fliopv_r83 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_83=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r83
+!===
+SUBROUTINE fliopv_r84 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_84=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r84
+!===
+SUBROUTINE fliopv_r85 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:,:,:,:),INTENT(IN) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_upv (f_i,v_n,r_85=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliopv_r85
+!===
+SUBROUTINE flio_upv &
+ & (f_i,v_n, &
+ &  i_40,i_41,i_42,i_43,i_44,i_45, &
+ &  i_20,i_21,i_22,i_23,i_24,i_25, &
+!? &  i_10,i_11,i_12,i_13,i_14,i_15, &
+ &  r_40,r_41,r_42,r_43,r_44,r_45, &
+ &  r_80,r_81,r_82,r_83,r_84,r_85, &
+ &  start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),INTENT(IN),OPTIONAL :: i_40
+  INTEGER(KIND=i_4),DIMENSION(:),INTENT(IN),OPTIONAL :: i_41
+  INTEGER(KIND=i_4),DIMENSION(:,:),INTENT(IN),OPTIONAL :: i_42
+  INTEGER(KIND=i_4),DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: i_43
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:),INTENT(IN),OPTIONAL :: i_44
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:,:),INTENT(IN),OPTIONAL :: i_45
+  INTEGER(KIND=i_2),INTENT(IN),OPTIONAL :: i_20
+  INTEGER(KIND=i_2),DIMENSION(:),INTENT(IN),OPTIONAL :: i_21
+  INTEGER(KIND=i_2),DIMENSION(:,:),INTENT(IN),OPTIONAL :: i_22
+  INTEGER(KIND=i_2),DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: i_23
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:),INTENT(IN),OPTIONAL :: i_24
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:,:),INTENT(IN),OPTIONAL :: i_25
+!?INTEGERS of KIND 1 are not supported on all computers
+!?INTEGER(KIND=i_1),INTENT(IN),OPTIONAL :: i_10
+!?INTEGER(KIND=i_1),DIMENSION(:),INTENT(IN),OPTIONAL :: i_11
+!?INTEGER(KIND=i_1),DIMENSION(:,:),INTENT(IN),OPTIONAL :: i_12
+!?INTEGER(KIND=i_1),DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: i_13
+!?INTEGER(KIND=i_1),DIMENSION(:,:,:,:),INTENT(IN),OPTIONAL :: i_14
+!?INTEGER(KIND=i_1),DIMENSION(:,:,:,:,:),INTENT(IN),OPTIONAL :: i_15
+  REAL(KIND=r_4),INTENT(IN),OPTIONAL :: r_40
+  REAL(KIND=r_4),DIMENSION(:),INTENT(IN),OPTIONAL :: r_41
+  REAL(KIND=r_4),DIMENSION(:,:),INTENT(IN),OPTIONAL :: r_42
+  REAL(KIND=r_4),DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: r_43
+  REAL(KIND=r_4),DIMENSION(:,:,:,:),INTENT(IN),OPTIONAL :: r_44
+  REAL(KIND=r_4),DIMENSION(:,:,:,:,:),INTENT(IN),OPTIONAL :: r_45
+  REAL(KIND=r_8),INTENT(IN),OPTIONAL :: r_80
+  REAL(KIND=r_8),DIMENSION(:),INTENT(IN),OPTIONAL :: r_81
+  REAL(KIND=r_8),DIMENSION(:,:),INTENT(IN),OPTIONAL :: r_82
+  REAL(KIND=r_8),DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: r_83
+  REAL(KIND=r_8),DIMENSION(:,:,:,:),INTENT(IN),OPTIONAL :: r_84
+  REAL(KIND=r_8),DIMENSION(:,:,:,:,:),INTENT(IN),OPTIONAL :: r_85
+  INTEGER,DIMENSION(:),INTENT(IN),OPTIONAL :: start,count
+!-
+  INTEGER :: f_e,i_v,i_rc
+  CHARACTER(LEN=5) :: cvr_d
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    IF      (PRESENT(i_40)) THEN; cvr_d = "I1 0D";
+    ELSE IF (PRESENT(i_41)) THEN; cvr_d = "I1 1D";
+    ELSE IF (PRESENT(i_42)) THEN; cvr_d = "I1 2D";
+    ELSE IF (PRESENT(i_43)) THEN; cvr_d = "I1 3D";
+    ELSE IF (PRESENT(i_44)) THEN; cvr_d = "I1 4D";
+    ELSE IF (PRESENT(i_45)) THEN; cvr_d = "I1 5D";
+    ELSE IF (PRESENT(i_20)) THEN; cvr_d = "I2 0D";
+    ELSE IF (PRESENT(i_21)) THEN; cvr_d = "I2 1D";
+    ELSE IF (PRESENT(i_22)) THEN; cvr_d = "I2 2D";
+    ELSE IF (PRESENT(i_23)) THEN; cvr_d = "I2 3D";
+    ELSE IF (PRESENT(i_24)) THEN; cvr_d = "I2 4D";
+    ELSE IF (PRESENT(i_25)) THEN; cvr_d = "I2 5D";
+!?  ELSE IF (PRESENT(i_10)) THEN; cvr_d = "I4 0D";
+!?  ELSE IF (PRESENT(i_11)) THEN; cvr_d = "I4 1D";
+!?  ELSE IF (PRESENT(i_12)) THEN; cvr_d = "I4 2D";
+!?  ELSE IF (PRESENT(i_13)) THEN; cvr_d = "I4 3D";
+!?  ELSE IF (PRESENT(i_14)) THEN; cvr_d = "I4 4D";
+!?  ELSE IF (PRESENT(i_15)) THEN; cvr_d = "I4 5D";
+    ELSE IF (PRESENT(r_40)) THEN; cvr_d = "R4 0D";
+    ELSE IF (PRESENT(r_41)) THEN; cvr_d = "R4 1D";
+    ELSE IF (PRESENT(r_42)) THEN; cvr_d = "R4 2D";
+    ELSE IF (PRESENT(r_43)) THEN; cvr_d = "R4 3D";
+    ELSE IF (PRESENT(r_44)) THEN; cvr_d = "R4 4D";
+    ELSE IF (PRESENT(r_45)) THEN; cvr_d = "R4 5D";
+    ELSE IF (PRESENT(r_80)) THEN; cvr_d = "R8 0D";
+    ELSE IF (PRESENT(r_81)) THEN; cvr_d = "R8 1D";
+    ELSE IF (PRESENT(r_82)) THEN; cvr_d = "R8 2D";
+    ELSE IF (PRESENT(r_83)) THEN; cvr_d = "R8 3D";
+    ELSE IF (PRESENT(r_84)) THEN; cvr_d = "R8 4D";
+    ELSE IF (PRESENT(r_85)) THEN; cvr_d = "R8 5D";
+    ENDIF
+    WRITE(*,*) "->flioputv ",TRIM(v_n)," ",TRIM(cvr_d)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('flioputv',f_i,f_e)
+!-
+! Ensuring data mode
+!-
+  CALL flio_hdm (f_i,f_e,.FALSE.)
+!-
+  i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+  IF (i_rc == NF90_NOERR) THEN
+    IF      (PRESENT(i_40)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_40,start=start)
+    ELSE IF (PRESENT(i_41)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_41,start=start,count=count)
+    ELSE IF (PRESENT(i_42)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_42,start=start,count=count)
+    ELSE IF (PRESENT(i_43)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_43,start=start,count=count)
+    ELSE IF (PRESENT(i_44)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_44,start=start,count=count)
+    ELSE IF (PRESENT(i_45)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_45,start=start,count=count)
+    ELSE IF (PRESENT(i_20)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_20,start=start)
+    ELSE IF (PRESENT(i_21)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_21,start=start,count=count)
+    ELSE IF (PRESENT(i_22)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_22,start=start,count=count)
+    ELSE IF (PRESENT(i_23)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_23,start=start,count=count)
+    ELSE IF (PRESENT(i_24)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_24,start=start,count=count)
+    ELSE IF (PRESENT(i_25)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,i_25,start=start,count=count)
+!?  ELSE IF (PRESENT(i_10)) THEN
+!?    i_rc = NF90_PUT_VAR(f_e,i_v,i_10,start=start)
+!?  ELSE IF (PRESENT(i_11)) THEN
+!?    i_rc = NF90_PUT_VAR(f_e,i_v,i_11,start=start,count=count)
+!?  ELSE IF (PRESENT(i_12)) THEN
+!?    i_rc = NF90_PUT_VAR(f_e,i_v,i_12,start=start,count=count)
+!?  ELSE IF (PRESENT(i_13)) THEN
+!?    i_rc = NF90_PUT_VAR(f_e,i_v,i_13,start=start,count=count)
+!?  ELSE IF (PRESENT(i_14)) THEN
+!?    i_rc = NF90_PUT_VAR(f_e,i_v,i_14,start=start,count=count)
+!?  ELSE IF (PRESENT(i_15)) THEN
+!?    i_rc = NF90_PUT_VAR(f_e,i_v,i_15,start=start,count=count)
+    ELSE IF (PRESENT(r_40)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_40,start=start)
+    ELSE IF (PRESENT(r_41)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_41,start=start,count=count)
+    ELSE IF (PRESENT(r_42)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_42,start=start,count=count)
+    ELSE IF (PRESENT(r_43)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_43,start=start,count=count)
+    ELSE IF (PRESENT(r_44)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_44,start=start,count=count)
+    ELSE IF (PRESENT(r_45)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_45,start=start,count=count)
+    ELSE IF (PRESENT(r_80)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_80,start=start)
+    ELSE IF (PRESENT(r_81)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_81,start=start,count=count)
+    ELSE IF (PRESENT(r_82)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_82,start=start,count=count)
+    ELSE IF (PRESENT(r_83)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_83,start=start,count=count)
+    ELSE IF (PRESENT(r_84)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_84,start=start,count=count)
+    ELSE IF (PRESENT(r_85)) THEN
+      i_rc = NF90_PUT_VAR(f_e,i_v,r_85,start=start,count=count)
+    ENDIF
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'flioputv', &
+ &      'Variable '//TRIM(v_n)//' not put','Error :', &
+ &      TRIM(NF90_STRERROR(i_rc)))
+    ENDIF
+  ELSE
+    CALL ipslerr (3,'flioputv','Variable',TRIM(v_n),'not defined')
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioputv"
+  ENDIF
+!----------------------
+END SUBROUTINE flio_upv
+!===
+SUBROUTINE fliopa_r4_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=4),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,1,v_n,a_n,avr4=(/a_v/))
+!--------------------------
+END SUBROUTINE fliopa_r4_0d
+!===
+SUBROUTINE fliopa_r4_1d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=4),DIMENSION(:),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,SIZE(a_v),v_n,a_n,avr4=a_v)
+!--------------------------
+END SUBROUTINE fliopa_r4_1d
+!===
+SUBROUTINE fliopa_r8_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=8),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,1,v_n,a_n,avr8=(/a_v/))
+!--------------------------
+END SUBROUTINE fliopa_r8_0d
+!===
+SUBROUTINE fliopa_r8_1d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=8),DIMENSION(:),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,SIZE(a_v),v_n,a_n,avr8=a_v)
+!--------------------------
+END SUBROUTINE fliopa_r8_1d
+!===
+SUBROUTINE fliopa_i4_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  INTEGER(KIND=4),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,1,v_n,a_n,avi4=(/a_v/))
+!--------------------------
+END SUBROUTINE fliopa_i4_0d
+!===
+SUBROUTINE fliopa_i4_1d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,SIZE(a_v),v_n,a_n,avi4=a_v)
+!--------------------------
+END SUBROUTINE fliopa_i4_1d
+!===
+SUBROUTINE fliopa_tx_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  CHARACTER(LEN=*),INTENT(IN) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_upa (f_i,1,v_n,a_n,avtx=a_v)
+!--------------------------
+END SUBROUTINE fliopa_tx_0d
+!===
+SUBROUTINE flio_upa (f_i,l_a,v_n,a_n,avr4,avr8,avi4,avtx)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i,l_a
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=4),DIMENSION(:),OPTIONAL,INTENT(IN) :: avr4
+  REAL(KIND=8),DIMENSION(:),OPTIONAL,INTENT(IN) :: avr8
+  INTEGER(KIND=4),DIMENSION(:),OPTIONAL,INTENT(IN) :: avi4
+  CHARACTER(LEN=*),OPTIONAL,INTENT(IN) :: avtx
+!-
+  INTEGER :: f_e,i_v,i_a,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioputa ",TRIM(v_n)," ",TRIM(a_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('flioputa',f_i,f_e)
+!-
+  IF (TRIM(v_n) == '?') THEN
+    i_v = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'flioputa', &
+       'Variable :',TRIM(v_n),'not found')
+    ENDIF
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,i_v,a_n,attnum=i_a)
+  IF ( (i_v == NF90_GLOBAL).AND.(i_rc /= NF90_NOERR) ) THEN
+    nw_na(f_i) = nw_na(f_i)+1
+  ENDIF
+  CALL flio_hdm (f_i,f_e,.TRUE.)
+  IF      (PRESENT(avr4)) THEN
+    i_rc = NF90_PUT_ATT(f_e,i_v,a_n,avr4(1:l_a))
+  ELSE IF (PRESENT(avr8)) THEN
+    i_rc = NF90_PUT_ATT(f_e,i_v,a_n,avr8(1:l_a))
+  ELSE IF (PRESENT(avi4)) THEN
+    i_rc = NF90_PUT_ATT(f_e,i_v,a_n,avi4(1:l_a))
+  ELSE IF (PRESENT(avtx)) THEN
+    i_rc = NF90_PUT_ATT(f_e,i_v,a_n,TRIM(avtx))
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioputa"
+  ENDIF
+!----------------------
+END SUBROUTINE flio_upa
+!===
+SUBROUTINE flioopfd (f_n,f_i,mode,nb_dim,nb_var,nb_gat)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: f_n
+  INTEGER,INTENT(OUT) :: f_i
+  CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: mode
+  INTEGER,OPTIONAL,INTENT(OUT) :: nb_dim,nb_var,nb_gat
+!-
+  INTEGER :: i_rc,f_e,m_c
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) '->flioopfd, file name : ',TRIM(f_n)
+  ENDIF
+!-
+! Search for a free local identifier
+!-
+  f_i = flio_rid()
+  IF (f_i < 0) THEN
+    CALL ipslerr (3,'flioopfd', &
+      'Too many files.','Please increase nb_fi_mx', &
+      'in module fliocom.f90.')
+  ENDIF
+!-
+! Check the mode
+!-
+  IF (PRESENT(mode)) THEN
+    IF (TRIM(MODE) == "WRITE") THEN
+      m_c = NF90_WRITE
+    ELSE
+      m_c = NF90_NOWRITE
+    ENDIF
+  ELSE
+    m_c = NF90_NOWRITE
+  ENDIF
+!-
+! Open the file.
+!-
+  i_rc = NF90_OPEN(TRIM(f_n),m_c,f_e)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (3,'flioopfd', &
+ &   'Could not open file :',TRIM(f_n), &
+ &   TRIM(NF90_STRERROR(i_rc))//' (Netcdf)')
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) '  flioopfd, model file-id : ',f_e
+  ENDIF
+!-
+! Retrieve and keep information about the file
+!-
+  nw_id(f_i) = f_e
+  lw_hm(f_i) = .FALSE.
+  CALL flio_inf (f_e, &
+ &  nb_dims=nw_nd(f_i),nb_vars=nw_nv(f_i), &
+ &  nb_atts=nw_na(f_i),id_unlm=nw_un(f_i), &
+ &  nn_idm=nw_di(:,f_i),nn_ldm=nw_dl(:,f_i),nn_aid=nw_ai(:,f_i))
+!-
+! Return information to the user
+!-
+  IF (PRESENT(nb_dim)) THEN
+    nb_dim = nw_nd(f_i)
+  ENDIF
+  IF (PRESENT(nb_var)) THEN
+    nb_var = nw_nv(f_i)
+  ENDIF
+  IF (PRESENT(nb_gat)) THEN
+    nb_gat = nw_na(f_i)
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,'("   flioopfd - dimensions :",/,(5(1X,I10),:))') &
+ &    nw_dl(:,f_i)
+    WRITE(*,*) "<-flioopfd"
+  ENDIF
+!----------------------
+END SUBROUTINE flioopfd
+!===
+SUBROUTINE flioinqf &
+ & (f_i,nb_dim,nb_var,nb_gat,id_uld,id_dim,ln_dim)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  INTEGER,OPTIONAL,INTENT(OUT) :: nb_dim,nb_var,nb_gat,id_uld
+  INTEGER,OPTIONAL,INTENT(OUT),DIMENSION(:) :: id_dim,ln_dim
+!-
+  INTEGER :: lll
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioinqf"
+  ENDIF
+!-
+  IF ( (f_i < 1).OR.(f_i > nb_fi_mx) ) THEN
+    CALL ipslerr (2,'flioinqf', &
+ &   'Invalid file identifier',' ',' ')
+  ELSE IF (nw_id(f_i) <= 0) THEN
+    CALL ipslerr (2,'flioinqf', &
+ &   'Unable to inquire about the file :','probably','not opened')
+  ELSE
+    IF (PRESENT(nb_dim)) THEN
+      nb_dim = nw_nd(f_i)
+    ENDIF
+    IF (PRESENT(nb_var)) THEN
+      nb_var = nw_nv(f_i)
+    ENDIF
+    IF (PRESENT(nb_gat)) THEN
+      nb_gat = nw_na(f_i)
+    ENDIF
+    IF (PRESENT(id_uld)) THEN
+      id_uld = nw_un(f_i)
+    ENDIF
+    IF (PRESENT(id_dim)) THEN
+      lll = SIZE(id_dim)
+      IF (lll < nw_nd(f_i)) THEN
+        CALL ipslerr (2,'flioinqf', &
+ &       'Only the first identifiers', &
+ &       'of the dimensions','will be returned')
+      ENDIF
+      lll=MIN(SIZE(id_dim),nw_nd(f_i))
+      id_dim(1:lll) = nw_di(1:lll,f_i)
+    ENDIF
+    IF (PRESENT(ln_dim)) THEN
+      lll = SIZE(ln_dim)
+      IF (lll < nw_nd(f_i)) THEN
+        CALL ipslerr (2,'flioinqf', &
+ &       'Only the first lengths', &
+ &       'of the dimensions','will be returned')
+      ENDIF
+      lll=MIN(SIZE(ln_dim),nw_nd(f_i))
+      ln_dim(1:lll) = nw_dl(1:lll,f_i)
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioinqf"
+  ENDIF
+!----------------------
+END SUBROUTINE flioinqf
+!===
+SUBROUTINE flioinqn &
+ & (f_i,cn_dim,cn_var,cn_gat,cn_uld, &
+ &  id_start,id_count,iv_start,iv_count,ia_start,ia_count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL,INTENT(OUT) :: &
+ & cn_dim,cn_var,cn_gat
+  CHARACTER(LEN=*),OPTIONAL,INTENT(OUT) :: &
+ & cn_uld
+  INTEGER,OPTIONAL,INTENT(IN) :: &
+ & id_start,id_count,iv_start,iv_count,ia_start,ia_count
+!-
+  INTEGER :: f_e,i_s,i_w,iws,iwc,i_rc
+  LOGICAL :: l_ok
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioinqn"
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('flioinqn',f_i,f_e)
+!-
+  IF (PRESENT(cn_dim)) THEN
+    l_ok = .TRUE.
+    i_s = SIZE(cn_dim)
+    DO i_w=1,i_s
+      cn_dim(i_w)(:) = '?'
+    ENDDO
+    IF (PRESENT(id_start)) THEN
+      iws = id_start
+    ELSE
+      iws = 1
+    ENDIF
+    IF (PRESENT(id_count)) THEN
+      iwc = id_count
+    ELSE
+      iwc = nw_nd(f_i)
+    ENDIF
+    IF (iws > nw_nd(f_i)) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The start index of requested dimensions', &
+ &     'is greater than the number of dimensions', &
+ &     'in the file')
+    ELSE IF (iws < 1) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The start index of requested dimensions', &
+ &     'is invalid', &
+ &     '( < 1 )')
+    ENDIF
+    IF ((iws+iwc-1) > nw_nd(f_i)) THEN
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of requested dimensions', &
+ &     'is greater than the number of dimensions', &
+ &     'in the file')
+    ENDIF
+    IF (iwc > i_s) THEN
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of dimensions to retrieve', &
+ &     'is greater than the size of the array,', &
+ &     'only the first dimensions of the file will be returned')
+    ELSE IF (iwc < 1) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of requested dimensions', &
+ &     'is invalid', &
+ &     '( < 1 )')
+    ENDIF
+    IF (l_ok) THEN
+      DO i_w=1,MIN(iwc,i_s,nw_nd(f_i)-iws+1)
+        i_rc = NF90_INQUIRE_DIMENSION(f_e,i_w+iws-1,name=cn_dim(i_w))
+      ENDDO
+    ENDIF
+  ENDIF
+!-
+  IF (PRESENT(cn_var)) THEN
+    l_ok = .TRUE.
+    i_s = SIZE(cn_var)
+    DO i_w=1,i_s
+      cn_var(i_w)(:) = '?'
+    ENDDO
+    IF (PRESENT(iv_start)) THEN
+      iws = iv_start
+    ELSE
+      iws = 1
+    ENDIF
+    IF (PRESENT(iv_count)) THEN
+      iwc = iv_count
+    ELSE
+      iwc = nw_nv(f_i)
+    ENDIF
+    IF (iws > nw_nv(f_i)) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The start index of requested variables', &
+ &     'is greater than the number of variables', &
+ &     'in the file')
+    ELSE IF (iws < 1) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The start index of requested variables', &
+ &     'is invalid', &
+ &     '( < 1 )')
+    ENDIF
+    IF ((iws+iwc-1) > nw_nv(f_i)) THEN
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of requested variables', &
+ &     'is greater than the number of variables', &
+ &     'in the file')
+    ENDIF
+    IF (iwc > i_s) THEN
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of variables to retrieve', &
+ &     'is greater than the size of the array,', &
+ &     'only the first variables of the file will be returned')
+    ELSE IF (iwc < 1) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of requested variables', &
+ &     'is invalid', &
+ &     '( < 1 )')
+    ENDIF
+    IF (l_ok) THEN
+      DO i_w=1,MIN(iwc,i_s,nw_nv(f_i)-iws+1)
+        i_rc = NF90_INQUIRE_VARIABLE(f_e,i_w+iws-1,name=cn_var(i_w))
+      ENDDO
+    ENDIF
+  ENDIF
+!-
+  IF (PRESENT(cn_gat)) THEN
+    l_ok = .TRUE.
+    i_s = SIZE(cn_gat)
+    DO i_w=1,i_s
+      cn_gat(i_w)(:) = '?'
+    ENDDO
+    IF (PRESENT(ia_start)) THEN
+      iws = ia_start
+    ELSE
+      iws = 1
+    ENDIF
+    IF (PRESENT(ia_count)) THEN
+      iwc = ia_count
+    ELSE
+      iwc = nw_na(f_i)
+    ENDIF
+    IF (iws > nw_na(f_i)) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The start index of requested global attributes', &
+ &     'is greater than the number of global attributes', &
+ &     'in the file')
+    ELSE IF (iws < 1) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The start index of requested global attributes', &
+ &     'is invalid', &
+ &     '( < 1 )')
+    ENDIF
+    IF ((iws+iwc-1) > nw_na(f_i)) THEN
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of requested global attributes', &
+ &     'is greater than the number of global attributes', &
+ &     'in the file')
+    ENDIF
+    IF (iwc > i_s) THEN
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of global attributes to retrieve', &
+ &     'is greater than the size of the array,', &
+ &     'only the first global attributes of the file will be returned')
+    ELSE IF (iwc < 1) THEN
+      l_ok = .FALSE.
+      CALL ipslerr (2,'flioinqn', &
+ &     'The number of requested global attributes', &
+ &     'is invalid', &
+ &     '( < 1 )')
+    ENDIF
+    IF (l_ok) THEN
+      DO i_w=1,MIN(iwc,i_s,nw_na(f_i)-iws+1)
+        i_rc = NF90_INQ_ATTNAME(f_e, &
+ &              NF90_GLOBAL,i_w+iws-1,name=cn_gat(i_w))
+      ENDDO
+    ENDIF
+  ENDIF
+!-
+  IF (PRESENT(cn_uld)) THEN
+    cn_uld = '?'
+    IF (nw_un(f_i) > 0) THEN
+      i_rc = NF90_INQUIRE_DIMENSION(f_e,nw_un(f_i),name=cn_uld)
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioinqn"
+  ENDIF
+!----------------------
+END SUBROUTINE flioinqn
+!===
+SUBROUTINE fliogstc &
+ & (f_i,x_axis,x_axis_2d,y_axis,y_axis_2d,z_axis, &
+ &      t_axis,t_init,t_step,t_calendar, &
+ &      x_start,x_count,y_start,y_count, &
+ &      z_start,z_count,t_start,t_count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  REAL,DIMENSION(:),OPTIONAL,INTENT(OUT)    :: x_axis,y_axis
+  REAL,DIMENSION(:,:),OPTIONAL,INTENT(OUT)  :: x_axis_2d,y_axis_2d
+  REAL,DIMENSION(:),OPTIONAL,INTENT(OUT)    :: z_axis
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(OUT) :: t_axis
+  REAL,OPTIONAL,INTENT(OUT)                 :: t_init,t_step
+  CHARACTER(LEN=*),OPTIONAL,INTENT(OUT)     :: t_calendar
+  INTEGER,OPTIONAL,INTENT(IN) :: &
+ &  x_start,x_count,y_start,y_count,z_start,z_count,t_start,t_count
+!-
+  INTEGER :: i_rc,f_e,i_v,it_t,nbdim,kv
+  INTEGER :: m_x,i_x,l_x,m_y,i_y,l_y,m_z,i_z,l_z,m_t,i_t,l_t
+  CHARACTER(LEN=NF90_MAX_NAME) :: name
+  CHARACTER(LEN=80) :: units
+  CHARACTER(LEN=20) :: c_tmp
+  CHARACTER(LEN=1) :: c_1
+  REAL    :: r_yy,r_mo,r_dd,r_ss,dtv,dtn
+  INTEGER :: j_yy,j_mo,j_dd,j_hh,j_mn,j_ss
+  LOGICAL :: l_ok,l_tmp
+!-
+  REAL,DIMENSION(:),ALLOCATABLE :: v_tmp
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliogstc"
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliogstc',f_i,f_e)
+!-
+! Validate the coherence of the arguments
+!-
+  IF (    (PRESENT(x_axis).AND.PRESENT(x_axis_2d)) &
+ &    .OR.(PRESENT(y_axis).AND.PRESENT(y_axis_2d)) ) THEN
+    CALL ipslerr (3,'fliogstc', &
+ &    'The [x/y]_axis arguments', &
+ &    'are not coherent :',&
+ &    'can not handle two [x/y]_axis')
+  ENDIF
+!-
+! Retrieve spatio-temporal dimensions
+!-
+  IF (nw_ai(k_lon,f_i) > 0) THEN
+    m_x = nw_dl(nw_ai(k_lon,f_i),f_i);
+  ELSE
+    m_x = -1;
+  ENDIF
+  IF (nw_ai(k_lat,f_i) > 0) THEN
+    m_y = nw_dl(nw_ai(k_lat,f_i),f_i);
+  ELSE
+    m_y = -1;
+  ENDIF
+  IF (nw_ai(k_lev,f_i) > 0) THEN
+    m_z = nw_dl(nw_ai(k_lev,f_i),f_i);
+  ELSE
+    m_z = -1;
+  ENDIF
+  IF (nw_ai(k_tim,f_i) > 0) THEN
+    m_t = nw_dl(nw_ai(k_tim,f_i),f_i);
+  ELSE
+    m_t = -1;
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,'("   fliogstc - dimensions :",/,(5(1X,I10),:))') &
+ &    m_x,m_y,m_z,m_t
+  ENDIF
+!-
+! Initialize the x-y indices
+!-
+  IF (    PRESENT(x_axis)    &
+ &    .OR.PRESENT(x_axis_2d) &
+ &    .OR.PRESENT(y_axis_2d) ) THEN
+    IF (PRESENT(x_start)) THEN
+      i_x = x_start
+    ELSE
+      i_x = 1
+    ENDIF
+    IF (PRESENT(x_count)) THEN
+      l_x = x_count
+    ELSE
+      l_x = m_x-i_x+1
+    ENDIF
+  ENDIF
+  IF (    PRESENT(y_axis)    &
+ &    .OR.PRESENT(y_axis_2d) &
+ &    .OR.PRESENT(x_axis_2d) ) THEN
+    IF (PRESENT(y_start)) THEN
+      i_y = y_start
+    ELSE
+      i_y = 1
+    ENDIF
+    IF (PRESENT(y_count)) THEN
+      l_y = y_count
+    ELSE
+      l_y = m_y-i_y+1
+    ENDIF
+  ENDIF
+  IF (PRESENT(x_axis)) THEN
+    IF (m_x <= 0) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'Requested x_axis', &
+ &      'but the coordinate is not present','in the file')
+    ELSE IF ((i_x+l_x-1) > m_x) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'The requested size for the x_axis', &
+ &      'is greater than the size of the coordinate','in the file')
+    ENDIF
+  ENDIF
+  IF (PRESENT(y_axis)) THEN
+    IF (m_y <= 0) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'Requested y_axis', &
+ &      'but the coordinate is not present','in the file')
+    ELSE IF ((i_y+l_y-1) > m_y) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'The requested size for the y_axis', &
+ &      'is greater than the size of the coordinate','in the file')
+    ENDIF
+  ENDIF
+  IF (PRESENT(x_axis_2d).OR.PRESENT(y_axis_2d) )THEN
+    IF ( (m_x <= 0).OR.(m_y <= 0) ) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'Requested [x/y]_axis_2d', &
+ &      'but the coordinates are not iboth present','in the file')
+    ELSE IF ( ((i_x+l_x-1) > m_x).OR.((i_y+l_y-1) > m_y) ) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'The requested size for the [x/y]_axis_2d', &
+ &      'is greater than the size of the coordinate','in the file')
+    ENDIF
+  ENDIF
+!-
+! Ensuring data mode
+!-
+  CALL flio_hdm (f_i,f_e,.FALSE.)
+!-
+! Extracting the x coordinate, if needed
+!-
+  IF (PRESENT(x_axis).OR.PRESENT(x_axis_2d)) THEN
+    CALL flio_qax (f_i,'x',i_v,nbdim)
+    IF (i_v > 0) THEN
+      IF      (nbdim == 1) THEN
+        IF (PRESENT(x_axis)) THEN
+          i_rc = NF90_GET_VAR(f_e,i_v,x_axis, &
+ &                 start=(/i_x/),count=(/l_x/))
+        ELSE
+          ALLOCATE(v_tmp(l_x))
+          i_rc = NF90_GET_VAR(f_e,i_v,v_tmp, &
+ &                 start=(/i_x/),count=(/l_x/))
+          DO kv=1,l_y
+            x_axis_2d(:,kv) = v_tmp(:)
+          ENDDO
+          DEALLOCATE(v_tmp)
+        ENDIF
+      ELSE IF (nbdim == 2) THEN
+        IF (PRESENT(x_axis)) THEN
+          l_ok = .TRUE.
+          IF (l_y > 1) THEN
+            ALLOCATE(v_tmp(l_y))
+            DO kv=i_x,i_x+l_x-1
+              i_rc = NF90_GET_VAR(f_e,i_v,v_tmp, &
+ &                     start=(/kv,i_y/),count=(/1,l_y/))
+              IF (ANY(v_tmp(2:l_y) /= v_tmp(1))) THEN
+                l_ok = .FALSE.
+                EXIT
+              ENDIF
+            ENDDO
+            DEALLOCATE(v_tmp)
+          ENDIF
+          IF (l_ok) THEN
+            i_rc = NF90_GET_VAR(f_e,i_v,x_axis, &
+ &                   start=(/i_x,i_y/),count=(/l_x,1/))
+          ELSE
+            CALL ipslerr (3,'fliogstc', &
+ &            'Requested 1D x_axis', &
+ &            'which have 2 not regular dimensions', &
+ &            'in the file')
+          ENDIF
+        ELSE
+          i_rc = NF90_GET_VAR(f_e,i_v,x_axis_2d, &
+ &                 start=(/i_x,i_y/),count=(/l_x,l_y/))
+        ENDIF
+      ELSE
+        CALL ipslerr (3,'fliogstc', &
+ &        'Can not handle x_axis', &
+ &        'that have more than 2 dimensions', &
+ &        'in the file')
+      ENDIF
+    ELSE
+      CALL ipslerr (3,'fliogstc','No x_axis found','in the file',' ')
+    ENDIF
+  ENDIF
+!-
+! Extracting the y coordinate, if needed
+!-
+  IF (PRESENT(y_axis).OR.PRESENT(y_axis_2d)) THEN
+    CALL flio_qax (f_i,'y',i_v,nbdim)
+    IF (i_v > 0) THEN
+      IF      (nbdim == 1) THEN
+        IF (PRESENT(y_axis)) THEN
+          i_rc = NF90_GET_VAR(f_e,i_v,y_axis, &
+ &                 start=(/i_y/),count=(/l_y/))
+        ELSE
+          ALLOCATE(v_tmp(l_y))
+          i_rc = NF90_GET_VAR(f_e,i_v,v_tmp, &
+ &                 start=(/i_y/),count=(/l_y/))
+          DO kv=1,l_x
+            y_axis_2d(kv,:) = v_tmp(:)
+          ENDDO
+          DEALLOCATE(v_tmp)
+        ENDIF
+      ELSE IF (nbdim == 2) THEN
+        IF (PRESENT(y_axis)) THEN
+          l_ok = .TRUE.
+          IF (l_x > 1) THEN
+            ALLOCATE(v_tmp(l_x))
+            DO kv=i_y,i_y+l_y-1
+              i_rc = NF90_GET_VAR(f_e,i_v,v_tmp, &
+ &                     start=(/i_x,kv/),count=(/l_x,1/))
+              IF (ANY(v_tmp(2:l_x) /= v_tmp(1))) THEN
+                l_ok = .FALSE.
+                EXIT
+              ENDIF
+            ENDDO
+            DEALLOCATE(v_tmp)
+          ENDIF
+          IF (l_ok) THEN
+            i_rc = NF90_GET_VAR(f_e,i_v,y_axis, &
+ &                   start=(/i_x,i_y/),count=(/1,l_y/))
+          ELSE
+            CALL ipslerr (3,'fliogstc', &
+ &            'Requested 1D y_axis', &
+ &            'which have 2 not regular dimensions', &
+ &            'in the file')
+          ENDIF
+        ELSE
+          i_rc = NF90_GET_VAR(f_e,i_v,y_axis_2d, &
+ &                 start=(/i_x,i_y/),count=(/l_x,l_y/))
+        ENDIF
+      ELSE
+        CALL ipslerr (3,'fliogstc', &
+ &        'Can not handle y axis', &
+ &        'that have more than 2 dimensions', &
+ &        'in the file')
+      ENDIF
+    ELSE
+      CALL ipslerr (3,'fliogstc','No y_axis found','in the file',' ')
+    ENDIF
+  ENDIF
+!-
+! Extracting the z coordinate, if needed
+!-
+  IF (PRESENT(z_axis)) THEN
+    IF (PRESENT(z_start)) THEN
+      i_z = z_start
+    ELSE
+      i_z = 1
+    ENDIF
+    IF (PRESENT(z_count)) THEN
+      l_z = z_count
+    ELSE
+      l_z = m_z-i_z+1
+    ENDIF
+    IF ((i_z+l_z-1) > m_z) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'The requested size for the z axis', &
+ &      'is greater than the size of the coordinate',&
+ &      'in the file')
+    ENDIF
+    CALL flio_qax (f_i,'z',i_v,nbdim)
+    IF (i_v > 0) THEN
+      IF (nbdim == 1) THEN
+        i_rc = NF90_GET_VAR(f_e,i_v,z_axis, &
+ &               start=(/i_z/),count=(/l_z/))
+      ELSE
+        CALL ipslerr (3,'fliogstc', &
+ &        'Can not handle z_axis', &
+ &        'that have more than 1 dimension', &
+ &        'in the file')
+      ENDIF
+    ELSE
+      CALL ipslerr (3,'fliogstc','No z_axis found','in the file',' ')
+    ENDIF
+  ENDIF
+!-
+! Extracting the t coordinate, if needed
+!-
+  IF (PRESENT(t_axis).OR.PRESENT(t_init).OR.PRESENT(t_step)) THEN
+    CALL flio_qax (f_i,'t',i_v,nbdim)
+    IF (i_v < 0) THEN
+      CALL ipslerr (3,'fliogstc','No t_axis found','in the file',' ')
+    ENDIF
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliogstc - get time details'
+    ENDIF
+!---
+!-- Get all the details for the time
+!-- Prefered method is '"time_steps" since'
+!---
+    name=''
+    i_rc = NF90_INQUIRE_VARIABLE(f_e,i_v,name=name)
+    units=''
+    i_rc = NF90_GET_ATT(f_e,i_v,'units',units)
+    IF      (INDEX(units,' since ') > 0) THEN
+      it_t = 1
+    ELSE IF (INDEX(name,'tstep') > 0) THEN
+      it_t = 2
+    ELSE
+      it_t = 0;
+    ENDIF
+  ENDIF
+!-
+! Extracting the t coordinate, if needed
+!-
+  IF (PRESENT(t_axis)) THEN
+    IF (PRESENT(t_start)) THEN
+      i_t = t_start
+    ELSE
+      i_t = 1
+    ENDIF
+    IF (PRESENT(t_count)) THEN
+      l_t = t_count
+    ELSE
+      l_t = m_t-i_t+1
+    ENDIF
+    IF ((i_t+l_t-1) > m_t) THEN
+      CALL ipslerr (3,'fliogstc', &
+ &      'The requested size for the t axis', &
+ &      'is greater than the size of the coordinate',&
+ &      'in the file')
+    ENDIF
+    ALLOCATE(v_tmp(l_t))
+    i_rc = NF90_GET_VAR(f_e,i_v,v_tmp, &
+ &           start=(/i_t/),count=(/l_t/))
+    t_axis(1:l_t) = NINT(v_tmp(1:l_t))
+    DEALLOCATE(v_tmp)
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliogstc - first time : ',t_axis(1:1)
+    ENDIF
+  ENDIF
+!-
+! Extracting the time at the beginning, if needed
+!-
+  IF (PRESENT(t_init)) THEN
+!-- Find the calendar
+    CALL lock_calendar (old_status=l_tmp)
+    CALL ioget_calendar (c_tmp)
+    units = ''
+    i_rc = NF90_GET_ATT(f_e,i_v,'calendar',units)
+    IF (i_rc == NF90_NOERR) THEN
+      CALL lock_calendar (new_status=.FALSE.)
+      CALL ioconf_calendar (TRIM(units))
+    ENDIF
+    IF (it_t == 1) THEN
+      units = ''
+      i_rc = NF90_GET_ATT(f_e,i_v,'units',units)
+      units = units(INDEX(units,' since ')+7:LEN_TRIM(units))
+      READ (units,'(I4.4,5(A,I2.2))') &
+ &      j_yy,c_1,j_mo,c_1,j_dd,c_1,j_hh,c_1,j_mn,c_1,j_ss
+      r_ss = j_hh*3600.+j_mn*60.+j_ss
+      CALL ymds2ju (j_yy,j_mo,j_dd,r_ss,t_init)
+    ELSE IF (it_t == 2) THEN
+      i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,'year0',r_yy)
+      i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,'month0',r_mo)
+      i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,'day0',r_dd)
+      i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,'sec0',r_ss)
+      j_yy = NINT(r_yy); j_mo = NINT(r_mo); j_dd = NINT(r_dd);
+      CALL ymds2ju (j_yy,j_mo,j_dd,r_ss,t_init)
+    ELSE
+      t_init = 0.
+    ENDIF
+    CALL lock_calendar (new_status=.FALSE.)
+    CALL ioconf_calendar (TRIM(c_tmp))
+    CALL lock_calendar (new_status=l_tmp)
+    IF (l_dbg) THEN
+      WRITE(*,*) '  fliogstc - time_type : '
+      WRITE(*,*) it_t
+      WRITE(*,*) '  fliogstc - year month day second t_init : '
+      WRITE(*,*) j_yy,j_mo,j_dd,r_ss,t_init
+    ENDIF
+  ENDIF
+!-
+! Extracting the timestep in seconds, if needed
+!-
+  IF (PRESENT(t_step)) THEN
+    IF      (it_t == 1) THEN
+      units = ''
+      i_rc = NF90_GET_ATT(f_e,i_v,'units',units)
+      units = ADJUSTL(units(1:INDEX(units,' since ')-1))
+      dtn = 1.
+      IF      (INDEX(units,"week") /= 0) THEN
+        kv  = INDEX(units,"week")
+        dtv = 604800.
+      ELSE IF (INDEX(units,"day")  /= 0) THEN
+        kv  = INDEX(units,"day")
+        dtv = 86400.
+      ELSE IF (INDEX(units,"h")    /= 0) THEN
+        kv  = INDEX(units,"h")
+        dtv = 3600.
+      ELSE IF (INDEX(units,"min")  /= 0) THEN
+        kv  = INDEX(units,"min")
+        dtv = 60.
+      ELSE IF (INDEX(units,"sec")  /= 0) THEN
+        kv  = INDEX(units,"sec")
+        dtv = 1.
+      ELSE IF (INDEX(units,"timesteps") /= 0) THEN
+        kv  = INDEX(units,"timesteps")
+        i_rc = NF90_GET_ATT(f_e,i_v,'tstep_sec',dtv)
+        IF (i_rc /= NF90_NOERR) THEN
+          CALL ipslerr (3,'fliogstc','"timesteps" value', &
+ &                        'not found','in the file')
+        ENDIF
+      ELSE
+        kv  = 1
+        dtv = 1.
+      ENDIF
+      IF (kv > 1) THEN
+        READ (unit=units(1:kv-1),FMT=*) dtn
+      ENDIF
+      t_step = dtn*dtv
+    ELSE IF (it_t == 2) THEN
+      i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,'delta_tstep_sec',t_step)
+    ELSE
+      t_step = 1.
+    ENDIF
+  ENDIF
+!-
+! Extracting the calendar attribute, if needed
+!-
+  IF (PRESENT(t_calendar)) THEN
+    units = ''
+    i_rc = NF90_GET_ATT(f_e,i_v,'calendar',units)
+    IF (i_rc == NF90_NOERR) THEN
+      t_calendar = units
+    ELSE
+      t_calendar = "not found"
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliogstc"
+  ENDIF
+!----------------------
+END SUBROUTINE fliogstc
+!===
+SUBROUTINE flioinqv &
+ & (f_i,v_n,l_ex,v_t,nb_dims,len_dims,id_dims, &
+ &  nb_atts,cn_atts,ia_start,ia_count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  LOGICAL,INTENT(OUT) :: l_ex
+  INTEGER,OPTIONAL,INTENT(OUT) :: v_t,nb_dims,nb_atts
+  INTEGER,OPTIONAL,INTENT(OUT),DIMENSION(:) :: len_dims,id_dims
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL,INTENT(OUT) :: cn_atts
+  INTEGER,OPTIONAL,INTENT(IN) :: ia_start,ia_count
+!-
+  INTEGER :: f_e,i_v,n_w,i_s,i_w,iws,iwc,i_rc
+  LOGICAL :: l_ok
+  INTEGER,DIMENSION(NF90_MAX_VAR_DIMS) :: dim_ids
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioinqv ",TRIM(v_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('flioinqv',f_i,f_e)
+!-
+  i_v = -1
+  i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+!-
+  l_ex = ( (i_v >= 0).AND.(i_rc == NF90_NOERR) )
+!-
+  IF (l_ex) THEN
+    IF (PRESENT(v_t)) THEN
+      i_rc = NF90_INQUIRE_VARIABLE(f_e,i_v,xtype=v_t)
+    ENDIF
+    n_w = -1
+    IF (PRESENT(nb_dims).OR.PRESENT(len_dims)) THEN
+      i_rc = NF90_INQUIRE_VARIABLE(f_e,i_v, &
+ &             ndims=n_w,dimids=dim_ids)
+      IF (PRESENT(nb_dims)) THEN
+        nb_dims = n_w
+      ENDIF
+      IF (PRESENT(len_dims)) THEN
+        i_s = SIZE(len_dims)
+        len_dims(:) = -1
+        IF (i_s < n_w) THEN
+          CALL ipslerr (2,'flioinqv', &
+ &         'Only the first dimensions of the variable', &
+ &         TRIM(v_n),'will be returned')
+        ENDIF
+        DO i_w=1,MIN(n_w,i_s)
+          i_rc = NF90_INQUIRE_DIMENSION(f_e,dim_ids(i_w), &
+ &                                      len=len_dims(i_w))
+        ENDDO
+      ENDIF
+      IF (PRESENT(id_dims)) THEN
+        i_s = SIZE(id_dims)
+        id_dims(:) = -1
+        IF (i_s < n_w) THEN
+          CALL ipslerr (2,'flioinqv', &
+ &         'The number of dimensions to retrieve', &
+ &         'is greater than the size of the array,', &
+ &         'only the first dimensions of "' &
+ &           //TRIM(v_n)//'" will be returned')
+        ENDIF
+        i_w = MIN(n_w,i_s)
+        id_dims(1:i_w) = dim_ids(1:i_w)
+      ENDIF
+    ENDIF
+    IF (PRESENT(nb_atts).OR.PRESENT(cn_atts)) THEN
+      i_rc = NF90_INQUIRE_VARIABLE(f_e,i_v,nAtts=n_w)
+      IF (PRESENT(nb_atts)) THEN
+        nb_atts = n_w
+      ENDIF
+      IF (PRESENT(cn_atts)) THEN
+        l_ok = .TRUE.
+        i_s = SIZE(cn_atts)
+        DO i_w=1,i_s
+          cn_atts(i_w)(:) = '?'
+        ENDDO
+        IF (PRESENT(ia_start)) THEN
+          iws = ia_start
+        ELSE
+          iws = 1
+        ENDIF
+        IF (PRESENT(ia_count)) THEN
+          iwc = ia_count
+        ELSE
+          iwc = n_w
+        ENDIF
+        IF (iws > n_w) THEN
+          l_ok = .FALSE.
+          CALL ipslerr (2,'flioinqv', &
+ &         'The start index of requested attributes', &
+ &         'is greater than the number of attributes of', &
+ &         '"'//TRIM(v_n)//'"')
+        ELSE IF (iws < 1) THEN
+          l_ok = .FALSE.
+          CALL ipslerr (2,'flioinqv', &
+ &         'The start index of requested attributes', &
+ &         'is invalid ( < 1 ) for', &
+ &         '"'//TRIM(v_n)//'"')
+        ENDIF
+        IF ((iws+iwc-1) > n_w) THEN
+          CALL ipslerr (2,'flioinqv', &
+ &         'The number of requested attributes', &
+ &         'is greater than the number of attributes of', &
+ &         '"'//TRIM(v_n)//'"')
+        ENDIF
+        IF (iwc > i_s) THEN
+          CALL ipslerr (2,'flioinqv', &
+ &         'The number of attributes to retrieve', &
+ &         'is greater than the size of the array,', &
+ &         'only the first attributes of "' &
+ &           //TRIM(v_n)//'" will be returned')
+        ELSE IF (iwc < 1) THEN
+          l_ok = .FALSE.
+          CALL ipslerr (2,'flioinqv', &
+ &         'The number of requested attributes', &
+ &         'is invalid ( < 1 ) for', &
+ &         '"'//TRIM(v_n)//'"')
+        ENDIF
+        IF (l_ok) THEN
+          DO i_w=1,MIN(iwc,i_s,n_w-iws+1)
+            i_rc = NF90_INQ_ATTNAME(f_e, &
+ &                  i_v,i_w+iws-1,name=cn_atts(i_w))
+          ENDDO
+        ENDIF
+      ENDIF
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioinqv"
+  ENDIF
+!----------------------
+END SUBROUTINE flioinqv
+!===
+SUBROUTINE fliogv_i40 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_40=v_v,start=start)
+!------------------------
+END SUBROUTINE fliogv_i40
+!===
+SUBROUTINE fliogv_i41 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_41=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i41
+!===
+SUBROUTINE fliogv_i42 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_42=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i42
+!===
+SUBROUTINE fliogv_i43 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_43=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i43
+!===
+SUBROUTINE fliogv_i44 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_44=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i44
+!===
+SUBROUTINE fliogv_i45 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_45=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i45
+!===
+SUBROUTINE fliogv_i20 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_20=v_v,start=start)
+!------------------------
+END SUBROUTINE fliogv_i20
+!===
+SUBROUTINE fliogv_i21 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_21=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i21
+!===
+SUBROUTINE fliogv_i22 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_22=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i22
+!===
+SUBROUTINE fliogv_i23 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_23=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i23
+!===
+SUBROUTINE fliogv_i24 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_24=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i24
+!===
+SUBROUTINE fliogv_i25 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,i_25=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_i25
+!===
+!?INTEGERS of KIND 1 are not supported on all computers
+!?SUBROUTINE fliogv_i10 (f_i,v_n,v_v,start)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),INTENT(OUT) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!?!---------------------------------------------------------------------
+!?  CALL flio_ugv (f_i,v_n,i_10=v_v,start=start)
+!?!------------------------
+!?END SUBROUTINE fliogv_i10
+!?!===
+!?SUBROUTINE fliogv_i11 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:),INTENT(OUT) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_ugv (f_i,v_n,i_11=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliogv_i11
+!?!===
+!?SUBROUTINE fliogv_i12 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:),INTENT(OUT) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_ugv (f_i,v_n,i_12=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliogv_i12
+!?!===
+!?SUBROUTINE fliogv_i13 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:,:),INTENT(OUT) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_ugv (f_i,v_n,i_13=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliogv_i13
+!?!===
+!?SUBROUTINE fliogv_i14 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:,:,:),INTENT(OUT) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_ugv (f_i,v_n,i_14=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliogv_i14
+!?!===
+!?SUBROUTINE fliogv_i15 (f_i,v_n,v_v,start,count)
+!?!---------------------------------------------------------------------
+!?  IMPLICIT NONE
+!?!-
+!?  INTEGER,INTENT(IN) :: f_i
+!?  CHARACTER(LEN=*),INTENT(IN) :: v_n
+!?  INTEGER(KIND=i_1),DIMENSION(:,:,:,:,:),INTENT(OUT) :: v_v
+!?  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!?!---------------------------------------------------------------------
+!?  CALL flio_ugv (f_i,v_n,i_15=v_v,start=start,count=count)
+!?!------------------------
+!?END SUBROUTINE fliogv_i15
+!===
+SUBROUTINE fliogv_r40 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_40=v_v,start=start)
+!------------------------
+END SUBROUTINE fliogv_r40
+!===
+SUBROUTINE fliogv_r41 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_41=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r41
+!===
+SUBROUTINE fliogv_r42 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_42=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r42
+!===
+SUBROUTINE fliogv_r43 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_43=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r43
+!===
+SUBROUTINE fliogv_r44 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_44=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r44
+!===
+SUBROUTINE fliogv_r45 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_4),DIMENSION(:,:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_45=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r45
+!===
+SUBROUTINE fliogv_r80 (f_i,v_n,v_v,start)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_80=v_v,start=start)
+!------------------------
+END SUBROUTINE fliogv_r80
+!===
+SUBROUTINE fliogv_r81 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_81=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r81
+!===
+SUBROUTINE fliogv_r82 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_82=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r82
+!===
+SUBROUTINE fliogv_r83 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_83=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r83
+!===
+SUBROUTINE fliogv_r84 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_84=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r84
+!===
+SUBROUTINE fliogv_r85 (f_i,v_n,v_v,start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  REAL(KIND=r_8),DIMENSION(:,:,:,:,:),INTENT(OUT) :: v_v
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(IN) :: start,count
+!---------------------------------------------------------------------
+  CALL flio_ugv (f_i,v_n,r_85=v_v,start=start,count=count)
+!------------------------
+END SUBROUTINE fliogv_r85
+!===
+SUBROUTINE flio_ugv &
+ & (f_i,v_n, &
+ &  i_40,i_41,i_42,i_43,i_44,i_45, &
+ &  i_20,i_21,i_22,i_23,i_24,i_25, &
+!? &  i_10,i_11,i_12,i_13,i_14,i_15, &
+ &  r_40,r_41,r_42,r_43,r_44,r_45, &
+ &  r_80,r_81,r_82,r_83,r_84,r_85, &
+ &  start,count)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n
+  INTEGER(KIND=i_4),INTENT(OUT),OPTIONAL :: i_40
+  INTEGER(KIND=i_4),DIMENSION(:),INTENT(OUT),OPTIONAL :: i_41
+  INTEGER(KIND=i_4),DIMENSION(:,:),INTENT(OUT),OPTIONAL :: i_42
+  INTEGER(KIND=i_4),DIMENSION(:,:,:),INTENT(OUT),OPTIONAL :: i_43
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:),INTENT(OUT),OPTIONAL :: i_44
+  INTEGER(KIND=i_4),DIMENSION(:,:,:,:,:),INTENT(OUT),OPTIONAL :: i_45
+  INTEGER(KIND=i_2),INTENT(OUT),OPTIONAL :: i_20
+  INTEGER(KIND=i_2),DIMENSION(:),INTENT(OUT),OPTIONAL :: i_21
+  INTEGER(KIND=i_2),DIMENSION(:,:),INTENT(OUT),OPTIONAL :: i_22
+  INTEGER(KIND=i_2),DIMENSION(:,:,:),INTENT(OUT),OPTIONAL :: i_23
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:),INTENT(OUT),OPTIONAL :: i_24
+  INTEGER(KIND=i_2),DIMENSION(:,:,:,:,:),INTENT(OUT),OPTIONAL :: i_25
+!?INTEGERS of KIND 1 are not supported on all computers
+!?INTEGER(KIND=i_1),INTENT(OUT),OPTIONAL :: i_10
+!?INTEGER(KIND=i_1),DIMENSION(:),INTENT(OUT),OPTIONAL :: i_11
+!?INTEGER(KIND=i_1),DIMENSION(:,:),INTENT(OUT),OPTIONAL :: i_12
+!?INTEGER(KIND=i_1),DIMENSION(:,:,:),INTENT(OUT),OPTIONAL :: i_13
+!?INTEGER(KIND=i_1),DIMENSION(:,:,:,:),INTENT(OUT),OPTIONAL :: i_14
+!?INTEGER(KIND=i_1),DIMENSION(:,:,:,:,:),INTENT(OUT),OPTIONAL :: i_15
+  REAL(KIND=r_4),INTENT(OUT),OPTIONAL :: r_40
+  REAL(KIND=r_4),DIMENSION(:),INTENT(OUT),OPTIONAL :: r_41
+  REAL(KIND=r_4),DIMENSION(:,:),INTENT(OUT),OPTIONAL :: r_42
+  REAL(KIND=r_4),DIMENSION(:,:,:),INTENT(OUT),OPTIONAL :: r_43
+  REAL(KIND=r_4),DIMENSION(:,:,:,:),INTENT(OUT),OPTIONAL :: r_44
+  REAL(KIND=r_4),DIMENSION(:,:,:,:,:),INTENT(OUT),OPTIONAL :: r_45
+  REAL(KIND=r_8),INTENT(OUT),OPTIONAL :: r_80
+  REAL(KIND=r_8),DIMENSION(:),INTENT(OUT),OPTIONAL :: r_81
+  REAL(KIND=r_8),DIMENSION(:,:),INTENT(OUT),OPTIONAL :: r_82
+  REAL(KIND=r_8),DIMENSION(:,:,:),INTENT(OUT),OPTIONAL :: r_83
+  REAL(KIND=r_8),DIMENSION(:,:,:,:),INTENT(OUT),OPTIONAL :: r_84
+  REAL(KIND=r_8),DIMENSION(:,:,:,:,:),INTENT(OUT),OPTIONAL :: r_85
+  INTEGER,DIMENSION(:),INTENT(IN),OPTIONAL :: start,count
+!-
+  INTEGER :: f_e,i_v,i_rc
+  CHARACTER(LEN=5) :: cvr_d
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    IF      (PRESENT(i_40)) THEN; cvr_d = "I1 0D";
+    ELSE IF (PRESENT(i_41)) THEN; cvr_d = "I1 1D";
+    ELSE IF (PRESENT(i_42)) THEN; cvr_d = "I1 2D";
+    ELSE IF (PRESENT(i_43)) THEN; cvr_d = "I1 3D";
+    ELSE IF (PRESENT(i_44)) THEN; cvr_d = "I1 4D";
+    ELSE IF (PRESENT(i_45)) THEN; cvr_d = "I1 5D";
+    ELSE IF (PRESENT(i_20)) THEN; cvr_d = "I2 0D";
+    ELSE IF (PRESENT(i_21)) THEN; cvr_d = "I2 1D";
+    ELSE IF (PRESENT(i_22)) THEN; cvr_d = "I2 2D";
+    ELSE IF (PRESENT(i_23)) THEN; cvr_d = "I2 3D";
+    ELSE IF (PRESENT(i_24)) THEN; cvr_d = "I2 4D";
+    ELSE IF (PRESENT(i_25)) THEN; cvr_d = "I2 5D";
+!?  ELSE IF (PRESENT(i_10)) THEN; cvr_d = "I4 0D";
+!?  ELSE IF (PRESENT(i_11)) THEN; cvr_d = "I4 1D";
+!?  ELSE IF (PRESENT(i_12)) THEN; cvr_d = "I4 2D";
+!?  ELSE IF (PRESENT(i_13)) THEN; cvr_d = "I4 3D";
+!?  ELSE IF (PRESENT(i_14)) THEN; cvr_d = "I4 4D";
+!?  ELSE IF (PRESENT(i_15)) THEN; cvr_d = "I4 5D";
+    ELSE IF (PRESENT(r_40)) THEN; cvr_d = "R4 0D";
+    ELSE IF (PRESENT(r_41)) THEN; cvr_d = "R4 1D";
+    ELSE IF (PRESENT(r_42)) THEN; cvr_d = "R4 2D";
+    ELSE IF (PRESENT(r_43)) THEN; cvr_d = "R4 3D";
+    ELSE IF (PRESENT(r_44)) THEN; cvr_d = "R4 4D";
+    ELSE IF (PRESENT(r_45)) THEN; cvr_d = "R4 5D";
+    ELSE IF (PRESENT(r_80)) THEN; cvr_d = "R8 0D";
+    ELSE IF (PRESENT(r_81)) THEN; cvr_d = "R8 1D";
+    ELSE IF (PRESENT(r_82)) THEN; cvr_d = "R8 2D";
+    ELSE IF (PRESENT(r_83)) THEN; cvr_d = "R8 3D";
+    ELSE IF (PRESENT(r_84)) THEN; cvr_d = "R8 4D";
+    ELSE IF (PRESENT(r_85)) THEN; cvr_d = "R8 5D";
+    ENDIF
+    WRITE(*,*) "->fliogetv ",TRIM(v_n)," ",TRIM(cvr_d)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliogetv',f_i,f_e)
+!-
+! Ensuring data mode
+!-
+  CALL flio_hdm (f_i,f_e,.FALSE.)
+!-
+  i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+  IF (i_rc == NF90_NOERR) THEN
+    IF      (PRESENT(i_40)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_40,start=start)
+    ELSE IF (PRESENT(i_41)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_41,start=start,count=count)
+    ELSE IF (PRESENT(i_42)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_42,start=start,count=count)
+    ELSE IF (PRESENT(i_43)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_43,start=start,count=count)
+    ELSE IF (PRESENT(i_44)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_44,start=start,count=count)
+    ELSE IF (PRESENT(i_45)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_45,start=start,count=count)
+    ELSE IF (PRESENT(i_20)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_20,start=start)
+    ELSE IF (PRESENT(i_21)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_21,start=start,count=count)
+    ELSE IF (PRESENT(i_22)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_22,start=start,count=count)
+    ELSE IF (PRESENT(i_23)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_23,start=start,count=count)
+    ELSE IF (PRESENT(i_24)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_24,start=start,count=count)
+    ELSE IF (PRESENT(i_25)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,i_25,start=start,count=count)
+!?  ELSE IF (PRESENT(i_10)) THEN
+!?    i_rc = NF90_GET_VAR(f_e,i_v,i_10,start=start)
+!?  ELSE IF (PRESENT(i_11)) THEN
+!?    i_rc = NF90_GET_VAR(f_e,i_v,i_11,start=start,count=count)
+!?  ELSE IF (PRESENT(i_12)) THEN
+!?    i_rc = NF90_GET_VAR(f_e,i_v,i_12,start=start,count=count)
+!?  ELSE IF (PRESENT(i_13)) THEN
+!?    i_rc = NF90_GET_VAR(f_e,i_v,i_13,start=start,count=count)
+!?  ELSE IF (PRESENT(i_14)) THEN
+!?    i_rc = NF90_GET_VAR(f_e,i_v,i_14,start=start,count=count)
+!?  ELSE IF (PRESENT(i_15)) THEN
+!?    i_rc = NF90_GET_VAR(f_e,i_v,i_15,start=start,count=count)
+    ELSE IF (PRESENT(r_40)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_40,start=start)
+    ELSE IF (PRESENT(r_41)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_41,start=start,count=count)
+    ELSE IF (PRESENT(r_42)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_42,start=start,count=count)
+    ELSE IF (PRESENT(r_43)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_43,start=start,count=count)
+    ELSE IF (PRESENT(r_44)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_44,start=start,count=count)
+    ELSE IF (PRESENT(r_45)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_45,start=start,count=count)
+    ELSE IF (PRESENT(r_80)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_80,start=start)
+    ELSE IF (PRESENT(r_81)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_81,start=start,count=count)
+    ELSE IF (PRESENT(r_82)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_82,start=start,count=count)
+    ELSE IF (PRESENT(r_83)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_83,start=start,count=count)
+    ELSE IF (PRESENT(r_84)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_84,start=start,count=count)
+    ELSE IF (PRESENT(r_85)) THEN
+      i_rc = NF90_GET_VAR(f_e,i_v,r_85,start=start,count=count)
+    ENDIF
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliogetv', &
+ &      'Variable '//TRIM(v_n)//' not get','Error :', &
+ &      TRIM(NF90_STRERROR(i_rc)))
+    ENDIF
+  ELSE
+    CALL ipslerr (3,'fliogetv','Variable',TRIM(v_n),'not found')
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliogetv"
+  ENDIF
+!----------------------
+END SUBROUTINE flio_ugv
+!===
+SUBROUTINE flioinqa (f_i,v_n,a_n,l_ex,a_t,a_l)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  LOGICAL,INTENT(OUT) :: l_ex
+  INTEGER,OPTIONAL,INTENT(OUT) :: a_t,a_l
+!-
+  INTEGER :: i_rc,f_e,i_v,t_ea,l_ea
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioinqa ",TRIM(v_n),"-",TRIM(a_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('flioinqa',f_i,f_e)
+!-
+  IF (TRIM(v_n) == '?') THEN
+    i_v = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'flioinqa', &
+       'Variable :',TRIM(v_n),'not found')
+    ENDIF
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,i_v,a_n,xtype=t_ea,len=l_ea)
+!-
+  l_ex = (i_rc == NF90_NOERR)
+!-
+  IF (l_ex) THEN
+    IF (PRESENT(a_t)) THEN
+      a_t = t_ea
+    ENDIF
+    IF (PRESENT(a_l)) THEN
+      a_l = l_ea
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioinqa"
+  ENDIF
+!----------------------
+END SUBROUTINE flioinqa
+!===
+SUBROUTINE flioga_r4_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=4),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avr_4_0=a_v)
+!---------------------------
+END SUBROUTINE flioga_r4_0d
+!===
+SUBROUTINE flioga_r4_1d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=4),DIMENSION(:),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avr_4_1=a_v)
+!--------------------------
+END SUBROUTINE flioga_r4_1d
+!===
+SUBROUTINE flioga_r8_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=8),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avr_8_0=a_v)
+!---------------------------
+END SUBROUTINE flioga_r8_0d
+!===
+SUBROUTINE flioga_r8_1d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=8),DIMENSION(:),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avr_8_1=a_v)
+!--------------------------
+END SUBROUTINE flioga_r8_1d
+!===
+SUBROUTINE flioga_i4_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  INTEGER(KIND=4),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avi_4_0=a_v)
+!---------------------------
+END SUBROUTINE flioga_i4_0d
+!===
+SUBROUTINE flioga_i4_1d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  INTEGER(KIND=4),DIMENSION(:),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avi_4_1=a_v)
+!--------------------------
+END SUBROUTINE flioga_i4_1d
+!===
+SUBROUTINE flioga_tx_0d (f_i,v_n,a_n,a_v)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  CHARACTER(LEN=*),INTENT(OUT) :: a_v
+!---------------------------------------------------------------------
+  CALL flio_uga (f_i,v_n,a_n,avtx=a_v)
+!---------------------------
+END SUBROUTINE flioga_tx_0d
+!===
+SUBROUTINE flio_uga &
+ & (f_i,v_n,a_n, &
+ &  avr_4_0,avr_4_1,avr_8_0,avr_8_1,avi_4_0,avi_4_1,avtx)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+  REAL(KIND=4),OPTIONAL,INTENT(OUT) :: avr_4_0
+  REAL(KIND=4),DIMENSION(:),OPTIONAL,INTENT(OUT) :: avr_4_1
+  REAL(KIND=8),OPTIONAL,INTENT(OUT) :: avr_8_0
+  REAL(KIND=8),DIMENSION(:),OPTIONAL,INTENT(OUT) :: avr_8_1
+  INTEGER(KIND=4),OPTIONAL,INTENT(OUT) :: avi_4_0
+  INTEGER(KIND=4),DIMENSION(:),OPTIONAL,INTENT(OUT) :: avi_4_1
+  CHARACTER(LEN=*),OPTIONAL,INTENT(OUT) :: avtx
+!-
+  INTEGER :: f_e,l_ua,i_v,t_ea,l_ea,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliogeta ",TRIM(v_n)," ",TRIM(a_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliogeta',f_i,f_e)
+!-
+  IF (TRIM(v_n) == '?') THEN
+    i_v = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliogeta', &
+       'Variable :',TRIM(v_n),'not found')
+    ENDIF
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,i_v,a_n,xtype=t_ea,len=l_ea)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (3,'fliogeta', &
+ &   'Attribute :',TRIM(a_n),'not found')
+  ENDIF
+!-
+  IF ( (.NOT.PRESENT(avtx).AND.(t_ea == NF90_CHAR)) &
+ &      .OR.(PRESENT(avtx).AND.(t_ea /= NF90_CHAR)) ) THEN
+    CALL ipslerr (3,'fliogeta', &
+ &   'The external type of the attribute :',TRIM(a_n), &
+ &   'is not compatible with the type of the argument')
+  ENDIF
+!-
+  IF      (PRESENT(avr_4_1)) THEN
+    l_ua = SIZE(avr_4_1)
+  ELSE IF (PRESENT(avr_8_1)) THEN
+    l_ua = SIZE(avr_8_1)
+  ELSE IF (PRESENT(avi_4_1)) THEN
+    l_ua = SIZE(avi_4_1)
+  ELSE IF (PRESENT(avtx)) THEN
+    l_ua = LEN(avtx)
+  ELSE
+    l_ua = 1
+  ENDIF
+!-
+  IF (l_ua < l_ea) THEN
+    CALL ipslerr (3,'fliogeta', &
+     'Insufficient size of the argument', &
+ &   'to receive the values of the attribute :',TRIM(a_n))
+  ENDIF
+!-
+  IF      (PRESENT(avr_4_0)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avr_4_0)
+  ELSE IF (PRESENT(avr_4_1)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avr_4_1(1:l_ea))
+  ELSE IF (PRESENT(avr_8_0)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avr_8_0)
+  ELSE IF (PRESENT(avr_8_1)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avr_8_1(1:l_ea))
+  ELSE IF (PRESENT(avi_4_0)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avi_4_0)
+  ELSE IF (PRESENT(avi_4_1)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avi_4_1(1:l_ea))
+  ELSE IF (PRESENT(avtx)) THEN
+    i_rc = NF90_GET_ATT(f_e,i_v,a_n,avtx)
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliogeta"
+  ENDIF
+!----------------------
+END SUBROUTINE flio_uga
+!===
+SUBROUTINE fliorenv (f_i,v_o_n,v_n_n)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_o_n,v_n_n
+!-
+  INTEGER :: f_e,i_v,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) &
+ &    "->fliorenv ",TRIM(v_o_n),"->",TRIM(v_n_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliorenv',f_i,f_e)
+!-
+  i_rc = NF90_INQ_VARID(f_e,v_o_n,i_v)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (2,'fliorenv', &
+     'Variable :',TRIM(v_o_n),'not found')
+  ELSE
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    i_rc = NF90_RENAME_VAR(f_e,i_v,v_n_n)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (2,'fliorenv', &
+       'Variable :',TRIM(v_o_n),'can not be renamed')
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliorenv"
+  ENDIF
+!----------------------
+END SUBROUTINE fliorenv
+!===
+SUBROUTINE fliorena (f_i,v_n,a_o_n,a_n_n)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_o_n,a_n_n
+!-
+  INTEGER :: f_e,i_v,i_a,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) &
+ &    "->fliorena ",TRIM(v_n),"-",TRIM(a_o_n),"->",TRIM(a_n_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliorena',f_i,f_e)
+!-
+  IF (TRIM(v_n) == '?') THEN
+    i_v = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliorena', &
+       'Variable :',TRIM(v_n),'not found')
+    ENDIF
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,i_v,a_o_n,attnum=i_a)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (2,'fliorena', &
+     'Attribute :',TRIM(a_o_n),'not found')
+  ELSE
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    i_rc = NF90_RENAME_ATT(f_e,i_v,a_o_n,a_n_n)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (2,'fliorena', &
+       'Attribute :',TRIM(a_o_n),'can not be renamed')
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliorena"
+  ENDIF
+!----------------------
+END SUBROUTINE fliorena
+!===
+SUBROUTINE fliodela (f_i,v_n,a_n)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: v_n,a_n
+!-
+  INTEGER :: f_e,i_v,i_a,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliodela ",TRIM(v_n),"-",TRIM(a_n)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliodela',f_i,f_e)
+!-
+  IF (TRIM(v_n) == '?') THEN
+    i_v = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e,v_n,i_v)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliodela', &
+ &     'Variable :',TRIM(v_n),'not found')
+    ENDIF
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,i_v,a_n,attnum=i_a)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (2,'fliodela', &
+ &   'Attribute :',TRIM(a_n),'not found')
+  ELSE
+    IF (i_v == NF90_GLOBAL) THEN
+      nw_na(f_i) = nw_na(f_i)-1
+    ENDIF
+    CALL flio_hdm (f_i,f_e,.TRUE.)
+    i_rc = NF90_DEL_ATT(f_e,i_v,a_n)
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliodela"
+  ENDIF
+!----------------------
+END SUBROUTINE fliodela
+!===
+SUBROUTINE fliocpya (f_i_i,v_n_i,a_n,f_i_o,v_n_o)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i_i,f_i_o
+  CHARACTER(LEN=*),INTENT(IN) :: v_n_i,a_n,v_n_o
+!-
+  INTEGER :: f_e_i,f_e_o,i_v_i,i_v_o,i_a,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliocpya - file",f_i_i,"-",TRIM(v_n_i),"-",TRIM(a_n)
+    WRITE(*,*) "  copied to file ",f_i_o,"-",TRIM(v_n_o)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('fliocpya',f_i_i,f_e_i)
+  CALL flio_qvid ('fliocpya',f_i_o,f_e_o)
+!-
+  IF (TRIM(v_n_i) == '?') THEN
+    i_v_i = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e_i,v_n_i,i_v_i)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliocpya', &
+ &     'Variable :',TRIM(v_n_i),'not found')
+    ENDIF
+  ENDIF
+!-
+  IF (TRIM(v_n_o) == '?') THEN
+    i_v_o = NF90_GLOBAL
+  ELSE
+    i_rc = NF90_INQ_VARID(f_e_o,v_n_o,i_v_o)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliocpya', &
+ &     'Variable :',TRIM(v_n_o),'not found')
+    ENDIF
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE_ATTRIBUTE(f_e_i,i_v_i,a_n,attnum=i_a)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (3,'fliocpya', &
+     'Attribute :',TRIM(a_n),'not found')
+  ELSE
+    i_rc = NF90_INQUIRE_ATTRIBUTE(f_e_o,i_v_o,a_n,attnum=i_a)
+    IF ( (i_v_o == NF90_GLOBAL).AND.(i_rc /= NF90_NOERR) ) THEN
+      nw_na(f_i_o) = nw_na(f_i_o)+1
+    ENDIF
+    CALL flio_hdm (f_i_o,f_e_o,.TRUE.)
+    i_rc = NF90_COPY_ATT(f_e_i,i_v_i,a_n,f_e_o,i_v_o)
+    IF (i_rc /= NF90_NOERR) THEN
+      CALL ipslerr (3,'fliocpya', &
+ &      'Attribute '//TRIM(a_n)//' not copied','Error :', &
+ &      TRIM(NF90_STRERROR(i_rc)))
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliocpya"
+  ENDIF
+!----------------------
+END SUBROUTINE fliocpya
+!===
+SUBROUTINE flioqstc (f_i,c_type,l_ex,c_name)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i
+  CHARACTER(LEN=*),INTENT(IN) :: c_type
+  LOGICAL,INTENT(OUT) :: l_ex
+  CHARACTER(LEN=*),INTENT(OUT) :: c_name
+!-
+  CHARACTER(LEN=1) :: c_ax
+  INTEGER :: f_e,idc,ndc,i_rc
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioqstc ",TRIM(c_type)
+  ENDIF
+!-
+! Retrieve the external file index
+  CALL flio_qvid ('flioqstc',f_i,f_e)
+!-
+  c_ax = TRIM(c_type)
+  IF (    (LEN_TRIM(c_type) == 1) &
+ &    .AND.(    (c_ax == 'x').OR.(c_ax == 'y') &
+ &          .OR.(c_ax == 'z').OR.(c_ax == 't')) ) THEN
+    CALL flio_qax (f_i,c_ax,idc,ndc)
+    l_ex = (idc > 0)
+    IF (l_ex) THEN
+      i_rc = NF90_INQUIRE_VARIABLE(f_e,idc,name=c_name)
+    ENDIF
+  ELSE
+    l_ex = .FALSE.
+    CALL ipslerr (2,'flioqstc', &
+ &   'The name of the coordinate,',TRIM(c_type),'is not valid')
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioqstc"
+  ENDIF
+!----------------------
+END SUBROUTINE flioqstc
+!===
+SUBROUTINE fliosync (f_i)
+!---------------------------------------------------------------------
+  INTEGER,INTENT(in),OPTIONAL :: f_i
+!-
+  INTEGER :: i_f,f_e,i_rc,i_s,i_e
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->fliosync"
+  ENDIF
+!-
+  IF (PRESENT(f_i)) THEN
+    IF ( (f_i >= 1).AND.(f_i <= nb_fi_mx) ) THEN
+      i_s = f_i
+      i_e = f_i
+    ELSE
+      i_s = 1
+      i_e = 0
+      CALL ipslerr (2,'fliosync', &
+ &     'Invalid file identifier',' ',' ')
+    ENDIF
+  ELSE
+    i_s = 1
+    i_e = nb_fi_mx
+  ENDIF
+!-
+! Ensuring data mode
+!-
+  CALL flio_hdm (f_i,f_e,.FALSE.)
+!-
+  DO i_f=i_s,i_e
+    f_e = nw_id(i_f)
+    IF (f_e > 0) THEN
+      IF (l_dbg) THEN
+        WRITE(*,*) '  fliosync - synchronising file number ',i_f
+      ENDIF
+      i_rc = NF90_SYNC(f_e)
+    ELSE IF (PRESENT(f_i)) THEN
+      CALL ipslerr (2,'fliosync', &
+ &     'Unable to synchronise the file :','probably','not opened')
+    ENDIF
+  ENDDO
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-fliosync"
+  ENDIF
+!----------------------
+END SUBROUTINE fliosync
+!===
+SUBROUTINE flioclo (f_i)
+!---------------------------------------------------------------------
+  INTEGER,INTENT(in),OPTIONAL :: f_i
+!-
+  INTEGER :: i_f,f_e,i_rc,i_s,i_e
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flioclo"
+  ENDIF
+!-
+  IF (PRESENT(f_i)) THEN
+    IF ( (f_i >= 1).AND.(f_i <= nb_fi_mx) ) THEN
+      i_s = f_i
+      i_e = f_i
+    ELSE
+      i_s = 1
+      i_e = 0
+      CALL ipslerr (2,'flioclo', &
+ &     'Invalid file identifier',' ',' ')
+    ENDIF
+  ELSE
+    i_s = 1
+    i_e = nb_fi_mx
+  ENDIF
+!-
+  DO i_f=i_s,i_e
+    f_e = nw_id(i_f)
+    IF (f_e > 0) THEN
+      IF (l_dbg) THEN
+        WRITE(*,*) '  flioclo - closing file number ',i_f
+      ENDIF
+      i_rc = NF90_CLOSE(f_e)
+      nw_id(i_f) = -1
+    ELSE IF (PRESENT(f_i)) THEN
+      CALL ipslerr (2,'flioclo', &
+ &     'Unable to close the file :','probably','not opened')
+    ENDIF
+  ENDDO
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flioclo"
+  ENDIF
+!---------------------
+END SUBROUTINE flioclo
+!===
+SUBROUTINE fliodmpf (f_n)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: f_n
+!-
+  INTEGER :: f_e,n_dims,n_vars,n_atts,i_unlm
+  INTEGER :: i_rc,i_n,k_n,t_ea,l_ea
+  INTEGER :: tmp_i
+  REAL    :: tmp_r
+  INTEGER,DIMENSION(:),ALLOCATABLE :: tma_i
+  REAL,DIMENSION(:),ALLOCATABLE    :: tma_r
+  CHARACTER(LEN=256) :: tmp_c
+  INTEGER,DIMENSION(nb_fd_mx) :: n_idim,n_ldim
+  INTEGER,DIMENSION(nb_ax_mx) :: n_ai
+  CHARACTER(LEN=NF90_MAX_NAME),DIMENSION(nb_fd_mx) :: c_ndim
+  INTEGER,DIMENSION(NF90_MAX_VAR_DIMS) :: idimid
+  CHARACTER(LEN=NF90_MAX_NAME) :: c_name
+!---------------------------------------------------------------------
+  i_rc = NF90_OPEN(TRIM(f_n),NF90_NOWRITE,f_e)
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (3,'fliodmpf', &
+ &   'Could not open file :',TRIM(f_n), &
+ &   TRIM(NF90_STRERROR(i_rc))//' (Netcdf)')
+  ENDIF
+!-
+  WRITE (*,*) "---"
+  WRITE (*,*) "--- File '",TRIM(f_n),"'"
+  WRITE (*,*) "---"
+!-
+  CALL flio_inf &
+ &  (f_e,nb_dims=n_dims,nb_vars=n_vars, &
+ &       nb_atts=n_atts,id_unlm=i_unlm, &
+ &       nn_idm=n_idim,nn_ldm=n_ldim,cc_ndm=c_ndim,nn_aid=n_ai)
+!-
+  WRITE (*,*) 'External model identifier   : ',f_e
+  WRITE (*,*) 'Number of dimensions        : ',n_dims
+  WRITE (*,*) 'Number of variables         : ',n_vars
+  WRITE (*,*) 'ID unlimited                : ',i_unlm
+!-
+  WRITE (*,*) "---"
+  WRITE (*,*) 'Presumed axis dimensions identifiers :'
+  IF (n_ai(k_lon) > 0) THEN
+    WRITE (*,*) 'x axis : ',n_ai(k_lon)
+  ELSE
+    WRITE (*,*) 'x axis : NONE'
+  ENDIF
+  IF (n_ai(k_lat) > 0) THEN
+    WRITE (*,*) 'y axis : ',n_ai(k_lat)
+  ELSE
+    WRITE (*,*) 'y axis : NONE'
+  ENDIF
+  IF (n_ai(k_lev) > 0) THEN
+    WRITE (*,*) 'z axis : ',n_ai(k_lev)
+  ELSE
+    WRITE (*,*) 'z axis : NONE'
+  ENDIF
+  IF (n_ai(k_tim) > 0) THEN
+    WRITE (*,*) 't axis : ',n_ai(k_tim)
+  ELSE
+    WRITE (*,*) 't axis : NONE'
+  ENDIF
+!-
+  WRITE (*,*) "---"
+  WRITE (*,*) 'Number of global attributes : ',n_atts
+  DO k_n=1,n_atts
+    i_rc = NF90_INQ_ATTNAME(f_e,NF90_GLOBAL,k_n,c_name)
+    i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,NF90_GLOBAL,c_name, &
+ &                                xtype=t_ea,len=l_ea)
+    IF      (    (t_ea == NF90_INT4).OR.(t_ea == NF90_INT2) &
+             .OR.(t_ea == NF90_INT1) ) THEN
+      IF (l_ea > 1) THEN
+        ALLOCATE(tma_i(l_ea))
+        i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,c_name,tma_i)
+        WRITE (*,'("    ",A," :",/,(5(1X,I10),:))') &
+ &        TRIM(c_name),tma_i(1:l_ea)
+        DEALLOCATE(tma_i)
+      ELSE
+        i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,c_name,tmp_i)
+        WRITE(*,*) '   ',TRIM(c_name),' : ',tmp_i
+      ENDIF
+    ELSE IF ( (t_ea == NF90_REAL4).OR.(t_ea == NF90_REAL8) ) THEN
+      IF (l_ea > 1) THEN
+        ALLOCATE(tma_r(l_ea))
+        i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,c_name,tma_r)
+        WRITE (*,'("    ",A," :",/,(5(1X,1PE11.3),:))') &
+ &        TRIM(c_name),tma_r(1:l_ea)
+        DEALLOCATE(tma_r)
+      ELSE
+        i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,c_name,tmp_r)
+        WRITE(*,*) '   ',TRIM(c_name),' : ',tmp_r
+      ENDIF
+    ELSE
+      tmp_c = ''
+      i_rc = NF90_GET_ATT(f_e,NF90_GLOBAL,c_name,tmp_c)
+      WRITE(*,*) '   ',TRIM(c_name),' : "',TRIM(tmp_c),'"'
+    ENDIF
+  ENDDO
+!-
+  DO i_n=1,nb_fd_mx
+    IF (n_idim(i_n) > 0) THEN
+      WRITE (*,*) "---"
+      WRITE (*,*) 'Dimension id   : ',n_idim(i_n)
+      WRITE (*,*) 'Dimension name : ',TRIM(c_ndim(i_n))
+      WRITE (*,*) 'Dimension size : ',n_ldim(i_n)
+    ENDIF
+  ENDDO
+!-
+  DO i_n=1,n_vars
+    i_rc = NF90_INQUIRE_VARIABLE(f_e,i_n, &
+ &           name=c_name,ndims=n_dims,dimids=idimid,nAtts=n_atts)
+    WRITE (*,*) "---"
+    WRITE (*,*) "Variable name        : ",TRIM(c_name)
+    WRITE (*,*) "Variable identifier  : ",i_n
+    WRITE (*,*) "Number of dimensions : ",n_dims
+    IF (n_dims > 0) THEN
+      WRITE (*,*) "Dimensions ID's      : ",idimid(1:n_dims)
+    ENDIF
+    WRITE (*,*) "Number of attributes : ",n_atts
+    DO k_n=1,n_atts
+      i_rc = NF90_INQ_ATTNAME(f_e,i_n,k_n,c_name)
+      i_rc = NF90_INQUIRE_ATTRIBUTE(f_e,i_n,c_name, &
+ &                                  xtype=t_ea,len=l_ea)
+      IF      (    (t_ea == NF90_INT4).OR.(t_ea == NF90_INT2) &
+ &             .OR.(t_ea == NF90_INT1) ) THEN
+        IF (l_ea > 1) THEN
+          ALLOCATE(tma_i(l_ea))
+          i_rc = NF90_GET_ATT(f_e,i_n,c_name,tma_i)
+          WRITE (*,'("    ",A," :",/,(5(1X,I10),:))') &
+ &              TRIM(c_name),tma_i(1:l_ea)
+          DEALLOCATE(tma_i)
+        ELSE
+          i_rc = NF90_GET_ATT(f_e,i_n,c_name,tmp_i)
+          WRITE(*,*) '   ',TRIM(c_name),' : ',tmp_i
+        ENDIF
+      ELSE IF ( (t_ea == NF90_REAL4).OR.(t_ea == NF90_REAL8) ) THEN
+        IF (l_ea > 1) THEN
+          ALLOCATE(tma_r(l_ea))
+          i_rc = NF90_GET_ATT(f_e,i_n,c_name,tma_r)
+          WRITE (*,'("    ",A," :",/,(5(1X,1PE11.3),:))') &
+ &          TRIM(c_name),tma_r(1:l_ea)
+          DEALLOCATE(tma_r)
+        ELSE
+          i_rc = NF90_GET_ATT(f_e,i_n,c_name,tmp_r)
+          WRITE(*,*) '   ',TRIM(c_name),' : ',tmp_r
+        ENDIF
+      ELSE
+        tmp_c = ''
+        i_rc = NF90_GET_ATT(f_e,i_n,c_name,tmp_c)
+        WRITE(*,*) '   ',TRIM(c_name),' : "',TRIM(tmp_c),'"'
+      ENDIF
+    ENDDO
+  ENDDO
+  WRITE (*,*) "---"
+!-
+  i_rc = NF90_CLOSE(f_e)
+!----------------------
+END SUBROUTINE fliodmpf
+!===
+SUBROUTINE flio_dom_set &
+ & (dtnb,dnb,did,dsg,dsl,dpf,dpl,dhs,dhe,cdnm,id_dom)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: dtnb,dnb
+  INTEGER,DIMENSION(:),INTENT(IN) :: did,dsg,dsl,dpf,dpl,dhs,dhe
+  CHARACTER(LEN=*),INTENT(IN) :: cdnm
+  INTEGER,INTENT(OUT) :: id_dom
+!-
+  INTEGER :: k_w,i_w,i_s
+  CHARACTER(LEN=l_dns) :: cd_p,cd_w
+!---------------------------------------------------------------------
+  k_w = flio_dom_rid()
+  IF (k_w < 0) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'too many domains simultaneously defined', &
+ &   'please unset useless domains', &
+ &   'by calling flio_dom_unset')
+  ENDIF
+  id_dom = k_w
+!-
+  d_n_t(k_w) = dtnb
+  d_n_c(k_w) = dnb
+!-
+  i_s = SIZE(did)
+  IF (i_s > dom_max_dims) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'too many distributed dimensions', &
+ &   'simultaneously defined',' ')
+  ENDIF
+  d_d_n(k_w) = i_s
+  d_d_i(1:i_s,k_w) = did(1:i_s)
+!-
+  i_w = SIZE(dsg)
+  IF (i_w /= i_s) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'the size of the DOMAIN_size_global array', &
+ &   'is not equal to the size', &
+ &   'of the distributed dimensions array')
+  ENDIF
+  d_s_g(1:i_w,k_w) = dsg(1:i_w)
+!-
+  i_w = SIZE(dsl)
+  IF (i_w /= i_s) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'the size of the DOMAIN_size_local array', &
+ &   'is not equal to the size', &
+ &   'of the distributed dimensions array')
+  ENDIF
+  d_s_l(1:i_w,k_w) = dsl(1:i_w)
+!-
+  i_w = SIZE(dpf)
+  IF (i_w /= i_s) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'the size of the DOMAIN_position_first array', &
+ &   'is not equal to the size', &
+ &   'of the distributed dimensions array')
+  ENDIF
+  d_p_f(1:i_w,k_w) = dpf(1:i_w)
+!-
+  i_w = SIZE(dpl)
+  IF (i_w /= i_s) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'the size of the DOMAIN_position_last array', &
+ &   'is not equal to the size', &
+ &   'of the distributed dimensions array')
+  ENDIF
+  d_p_l(1:i_w,k_w) = dpl(1:i_w)
+!-
+  i_w = SIZE(dhs)
+  IF (i_w /= i_s) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'the size of the DOMAIN_halo_size_start array', &
+ &   'is not equal to the size', &
+ &   'of the distributed dimensions array')
+  ENDIF
+  d_h_s(1:i_w,k_w) = dhs(1:i_w)
+!-
+  i_w = SIZE(dhe)
+  IF (i_w /= i_s) THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'the size of the DOMAIN_halo_size_end array', &
+ &   'is not equal to the size', &
+ &   'of the distributed dimensions array')
+  ENDIF
+  d_h_e(1:i_w,k_w) = dhe(1:i_w)
+!-
+  cd_p = "unknown"
+  cd_w = cdnm; CALL strlowercase (cd_w)
+  DO i_w=1,n_dns
+    IF (TRIM(cd_w) == TRIM(c_dns(i_w))) THEN
+      cd_p = cd_w; EXIT;
+    ENDIF
+  ENDDO
+  IF (TRIM(cd_p) == "unknown") THEN
+    CALL ipslerr (3,'flio_dom_set', &
+ &   'DOMAIN_type "'//TRIM(cdnm)//'"', &
+ &   'is actually not supported', &
+ &   'please use one of the supported names')
+  ENDIF
+  c_d_t(k_w) = cd_p
+!--------------------------
+END SUBROUTINE flio_dom_set
+!===
+SUBROUTINE flio_dom_unset (id_dom)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN),OPTIONAL :: id_dom
+!-
+  INTEGER :: i_w
+!---------------------------------------------------------------------
+  IF (PRESENT(id_dom)) THEN
+    IF ( (id_dom >= 1).AND.(id_dom <= dom_max_nb) ) THEN
+      IF (d_d_n(id_dom) > 0) THEN
+        d_d_n(id_dom) = -1
+      ELSE
+        CALL ipslerr (2,'flio_dom_unset', &
+ &       'The domain is not set',' ',' ')
+      ENDIF
+    ELSE
+      CALL ipslerr (2,'flio_dom_unset', &
+ &     'Invalid file identifier',' ',' ')
+    ENDIF
+  ELSE
+    DO i_w=1,dom_max_nb
+      d_d_n(id_dom) = -1
+    ENDDO
+  ENDIF
+!----------------------------
+END SUBROUTINE flio_dom_unset
+!===
+SUBROUTINE flio_dom_defset (id_dom)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: id_dom
+!---------------------------------------------------------------------
+  IF ( (id_dom >= 1).AND.(id_dom <= dom_max_nb) ) THEN
+    id_def_dom = id_dom
+  ELSE
+    CALL ipslerr (3,'flio_dom_defset', &
+ &   'Invalid domain identifier',' ',' ')
+  ENDIF
+!-----------------------------
+END SUBROUTINE flio_dom_defset
+!===
+SUBROUTINE flio_dom_defunset ()
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!---------------------------------------------------------------------
+  id_def_dom = FLIO_DOM_NONE
+!-------------------------------
+END SUBROUTINE flio_dom_defunset
+!===
+SUBROUTINE flio_dom_definq (id_dom)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(OUT) :: id_dom
+!---------------------------------------------------------------------
+  id_dom = id_def_dom
+!-----------------------------
+END SUBROUTINE flio_dom_definq
+!===
+!-
+!---------------------------------------------------------------------
+!- Semi-public procedures
+!---------------------------------------------------------------------
+!-
+!===
+SUBROUTINE flio_dom_file (f_n,id_dom)
+!---------------------------------------------------------------------
+!- Update the model file name to include the ".nc" suffix and
+!- the DOMAIN number on which this copy of IOIPSL runs, if needed.
+!- This routine is called by IOIPSL and not by user anyway.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(INOUT) :: f_n
+  INTEGER,OPTIONAL,INTENT(IN) :: id_dom
+!-
+  INTEGER :: il,iw
+  CHARACTER(LEN=4) :: str
+!---------------------------------------------------------------------
+!-
+! Add the ".nc" suffix if needed
+  il = LEN_TRIM(f_n)
+  IF (f_n(il-2:il) /= '.nc') THEN
+    f_n = f_n(1:il)//'.nc'
+  ENDIF
+!-
+! Add the DOMAIN identifier if needed
+  IF (PRESENT(id_dom)) THEN
+    IF (id_dom == FLIO_DOM_DEFAULT) THEN
+      CALL flio_dom_definq (iw)
+    ELSE
+      iw = id_dom
+    ENDIF
+    IF (iw /= FLIO_DOM_NONE) THEN
+      IF ( (id_dom >= 1).AND.(id_dom <= dom_max_nb) ) THEN
+        IF (d_d_n(iw) > 0) THEN
+          WRITE(str,'(I4.4)') d_n_c(iw)
+          il = INDEX(f_n,'.nc')
+          f_n = f_n(1:il-1)//'_'//str//'.nc'
+        ELSE
+          CALL ipslerr (3,'flio_dom_file', &
+ &         'The domain has not been defined', &
+ &         'please call flio_dom_set', &
+ &         'before calling flio_dom_file')
+        ENDIF
+      ELSE
+        CALL ipslerr (3,'flio_dom_file', &
+ &       'Invalid domain identifier',' ',' ')
+      ENDIF
+    ENDIF
+  ENDIF
+!---------------------------
+END SUBROUTINE flio_dom_file
+!===
+SUBROUTINE flio_dom_att (f_e,id_dom)
+!---------------------------------------------------------------------
+!- Add the DOMAIN attributes to the NETCDF file.
+!- This routine is called by IOIPSL and not by user anyway.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(in) :: f_e
+  INTEGER,OPTIONAL,INTENT(IN) :: id_dom
+!-
+  INTEGER :: iw,i_rc,i_n
+  CHARACTER(LEN=15) :: c_ddim
+  INTEGER :: n_idim
+  CHARACTER(LEN=NF90_MAX_NAME) :: c_ndim
+!---------------------------------------------------------------------
+  IF (PRESENT(id_dom)) THEN
+    IF (id_dom == FLIO_DOM_DEFAULT) THEN
+      CALL flio_dom_definq (iw)
+    ELSE
+      iw = id_dom
+    ENDIF
+    IF (iw /= FLIO_DOM_NONE) THEN
+      IF ( (id_dom >= 1).AND.(id_dom <= dom_max_nb) ) THEN
+        IF (d_d_n(iw) > 0) THEN
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_number_total',d_n_t(iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_number',d_n_c(iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_dimensions_ids',d_d_i(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_size_global',d_s_g(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_size_local',d_s_l(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_position_first',d_p_f(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_position_last',d_p_l(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_halo_size_start',d_h_s(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_halo_size_end',d_h_e(1:d_d_n(iw),iw))
+          i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL, &
+ &          'DOMAIN_type',TRIM(c_d_t(iw)))
+          i_rc = NF90_INQUIRE (f_e,nDimensions=n_idim)
+          DO i_n=1,n_idim
+            i_rc = NF90_INQUIRE_DIMENSION (f_e,i_n,name=c_ndim)
+            WRITE (UNIT=c_ddim,FMT='("DOMAIN_DIM_N",I3.3)') i_n
+            i_rc = NF90_PUT_ATT (f_e,NF90_GLOBAL,c_ddim,TRIM(c_ndim))
+          ENDDO
+        ELSE
+          CALL ipslerr (3,'flio_dom_att', &
+ &         'The domain has not been defined', &
+ &         'please call flio_dom_set', &
+ &         'before calling flio_dom_att')
+        ENDIF
+      ELSE
+        CALL ipslerr (3,'flio_dom_att', &
+ &       'Invalid domain identifier',' ',' ')
+      ENDIF
+    ENDIF
+  ENDIF
+!--------------------------
+END SUBROUTINE flio_dom_att
+!===
+!-
+!---------------------------------------------------------------------
+!- Local procedures
+!---------------------------------------------------------------------
+!-
+!===
+INTEGER FUNCTION flio_rid()
+!---------------------------------------------------------------------
+!- returns a free index in nw_id(:)
+!---------------------------------------------------------------------
+  INTEGER,DIMENSION(1:1) :: nfi
+!-
+  IF (ANY(nw_id < 0)) THEN
+    nfi = MINLOC(nw_id,MASK=nw_id < 0)
+    flio_rid = nfi(1)
+  ELSE
+    flio_rid = -1
+  ENDIF
+!--------------------
+END FUNCTION flio_rid
+!===
+INTEGER FUNCTION flio_dom_rid()
+!---------------------------------------------------------------------
+!- returns a free index in d_d_n(:)
+!---------------------------------------------------------------------
+  INTEGER,DIMENSION(1:1) :: nd
+!---------------------------------------------------------------------
+  IF (ANY(d_d_n < 0)) THEN
+    nd = MINLOC(d_d_n,MASK=d_d_n < 0)
+    flio_dom_rid = nd(1)
+  ELSE
+    flio_dom_rid = -1
+  ENDIF
+!------------------------
+END FUNCTION flio_dom_rid
+!===
+INTEGER FUNCTION flio_qid(iid)
+!---------------------------------------------------------------------
+!- returns the external index associated with the internal index "iid"
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: iid
+!---------------------------------------------------------------------
+  IF ( (iid >= 1).AND.(iid <= nb_fi_mx) ) THEN
+    flio_qid = nw_id(iid)
+  ELSE
+    flio_qid = -1
+  ENDIF
+!--------------------
+END FUNCTION flio_qid
+!===
+SUBROUTINE flio_qvid (cpg,iid,ixd)
+!---------------------------------------------------------------------
+!- This subroutine, called by the procedure "cpg",
+!- validates and returns the external file index "ixd"
+!- associated with the internal file index "iid"
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: cpg
+  INTEGER,INTENT(IN)  :: iid
+  INTEGER,INTENT(OUT) :: ixd
+!-
+  CHARACTER(LEN=20) :: c_t
+!---------------------------------------------------------------------
+  ixd = flio_qid(iid)
+  IF (ixd < 0) THEN
+    WRITE (UNIT=c_t,FMT='(I15)') iid
+    CALL ipslerr (3,TRIM(cpg), &
+ &    'Invalid internal file index :',TRIM(ADJUSTL(c_t)),' ')
+  ENDIF
+!-----------------------
+END SUBROUTINE flio_qvid
+!===
+SUBROUTINE flio_hdm (f_i,f_e,lk_hm)
+!---------------------------------------------------------------------
+!- This subroutine handles the "define/data mode" of NETCDF.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_i,f_e
+  LOGICAL,INTENT(IN) :: lk_hm
+!-
+  INTEGER :: i_rc
+!---------------------------------------------------------------------
+  i_rc = NF90_NOERR
+!-
+  IF      ( (.NOT.lw_hm(f_i)).AND.(lk_hm) ) THEN
+    i_rc = NF90_REDEF(f_e)
+    lw_hm(f_i) = .TRUE.
+  ELSE IF ( (lw_hm(f_i)).AND.(.NOT.lk_hm) ) THEN
+    i_rc = NF90_ENDDEF(f_e)
+    lw_hm(f_i) = .FALSE.
+  ENDIF
+!-
+  IF (i_rc /= NF90_NOERR) THEN
+    CALL ipslerr (3,'flio_hdm', &
+ &    'Internal error ','in define/data mode :', &
+ &    TRIM(NF90_STRERROR(i_rc)))
+  ENDIF
+!----------------------
+END SUBROUTINE flio_hdm
+!===
+SUBROUTINE flio_inf (f_e, &
+ & nb_dims,nb_vars,nb_atts,id_unlm,nn_idm,nn_ldm,nn_aid,cc_ndm)
+!---------------------------------------------------------------------
+!- This subroutine allows to get some information concerning
+!- the model file whose the external identifier is "f_e".
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: f_e
+  INTEGER,OPTIONAL,INTENT(OUT) :: nb_dims,nb_vars,nb_atts,id_unlm
+  INTEGER,DIMENSION(:),OPTIONAL,INTENT(OUT) :: nn_idm,nn_ldm,nn_aid
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL,INTENT(OUT) :: cc_ndm
+!-
+  INTEGER :: nm_dims,nm_vars,nm_atts,nm_unlm,ml
+  INTEGER :: i_rc,kv
+  CHARACTER(LEN=NF90_MAX_NAME) :: f_d_n
+!-
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "->flio_inf"
+  ENDIF
+!-
+  i_rc = NF90_INQUIRE(f_e,nDimensions=nm_dims,nVariables=nm_vars, &
+ &                    nAttributes=nm_atts,unlimitedDimId=nm_unlm)
+!-
+  IF (PRESENT(nb_dims))  nb_dims = nm_dims;
+  IF (PRESENT(nb_vars))  nb_vars = nm_vars;
+  IF (PRESENT(nb_atts))  nb_atts = nm_atts;
+  IF (PRESENT(id_unlm))  id_unlm = nm_unlm;
+!-
+  IF (PRESENT(nn_idm))  nn_idm(:) =  -1;
+  IF (PRESENT(nn_ldm))  nn_ldm(:) =   0;
+  IF (PRESENT(cc_ndm))  cc_ndm(:) = ' ';
+  IF (PRESENT(nn_aid))  nn_aid(:) =  -1;
+!-
+  DO kv=1,nm_dims
+!---
+    i_rc = NF90_INQUIRE_DIMENSION(f_e,kv,name=f_d_n,len=ml)
+    CALL strlowercase (f_d_n)
+    f_d_n = ADJUSTL(f_d_n)
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) "  flio_inf ",kv,ml," ",TRIM(f_d_n)
+    ENDIF
+!---
+    IF (PRESENT(nn_idm))  nn_idm(kv)=kv;
+    IF (PRESENT(nn_ldm))  nn_ldm(kv)=ml;
+    IF (PRESENT(cc_ndm))  cc_ndm(kv)=TRIM(f_d_n);
+!---
+    IF      (    (INDEX(f_d_n,'x') == 1)   &
+ &           .OR.(INDEX(f_d_n,'lon') == 1) ) THEN
+      IF (PRESENT(nn_aid)) THEN
+        IF (nn_aid(k_lon) < 0) THEN
+          nn_aid(k_lon)=kv;
+        ENDIF
+      ENDIF
+    ELSE IF (    (INDEX(f_d_n,'y') == 1)   &
+ &           .OR.(INDEX(f_d_n,'lat') == 1) ) THEN
+      IF (PRESENT(nn_aid)) THEN
+        IF (nn_aid(k_lat) < 0) THEN
+          nn_aid(k_lat)=kv;
+        ENDIF
+      ENDIF
+    ELSE IF (    (INDEX(f_d_n,'z') == 1)     &
+ &           .OR.(INDEX(f_d_n,'lev') == 1)   &
+ &           .OR.(INDEX(f_d_n,'plev') == 1)  &
+ &           .OR.(INDEX(f_d_n,'depth') == 1) ) THEN
+      IF (PRESENT(nn_aid)) THEN
+        IF (nn_aid(k_lev) < 0) THEN
+          nn_aid(k_lev)=kv;
+        ENDIF
+      ENDIF
+    ELSE IF (    (TRIM(f_d_n) == 't')         &
+ &           .OR.(TRIM(f_d_n) == 'time')      &
+ &           .OR.(INDEX(f_d_n,'tstep') == 1)  &
+ &           .OR.(INDEX(f_d_n,'time_counter') == 1) ) THEN
+!---- For the time we certainly need to allow for other names
+      IF (PRESENT(nn_aid)) THEN
+        IF (nn_aid(k_tim) < 0) THEN
+          nn_aid(k_tim)=kv;
+        ENDIF
+      ENDIF
+    ENDIF
+!---
+  ENDDO
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "<-flio_inf"
+  ENDIF
+!----------------------
+END SUBROUTINE flio_inf
+!===
+SUBROUTINE flio_qax (f_i,axtype,i_v,nbd)
+!---------------------------------------------------------------------
+!- This subroutine explores the file in order to find
+!- an axis (x/y/z/t) according to a number of rules
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: f_i,i_v,nbd
+  CHARACTER(LEN=*) :: axtype
+!-
+  INTEGER :: kv,k,n_r,l_d,n_d,i_rc,dimnb
+  CHARACTER(LEN=1)  :: c_ax
+  CHARACTER(LEN=9)  :: c_sn
+  CHARACTER(LEN=15),DIMENSION(10) :: c_r
+  CHARACTER(LEN=40) :: c_t1,c_t2
+!---------------------------------------------------------------------
+  i_v = -1; nbd = -1;
+!---
+!- Keep the name of the axis
+!---
+  c_ax = TRIM(axtype)
+!-
+! Validate axis type
+!-
+  IF (    (LEN_TRIM(axtype) == 1) &
+ &    .AND.(    (c_ax == 'x').OR.(c_ax == 'y') &
+ &          .OR.(c_ax == 'z').OR.(c_ax == 't')) ) THEN
+!---
+!-- Define the maximum number of dimensions for the coordinate
+!---
+      SELECT CASE (c_ax)
+      CASE('x')
+        l_d = 2
+        c_sn = 'longitude'
+      CASE('y')
+        l_d = 2
+        c_sn = 'latitude'
+      CASE('z')
+        l_d = 1
+        c_sn = 'model_level_number'
+      CASE('t')
+        l_d = 1
+        c_sn = 'time'
+      END SELECT
+!---
+!-- Rule 1 : we look for a variable with one dimension
+!--          and which has the same name as its dimension (NUG)
+!---
+    IF (i_v < 0) THEN
+      SELECT CASE (c_ax)
+      CASE('x')
+        k = nw_ai(k_lon,f_i)
+      CASE('y')
+        k = nw_ai(k_lat,f_i)
+      CASE('z')
+        k = nw_ai(k_lev,f_i)
+      CASE('t')
+        k = nw_ai(k_tim,f_i)
+      END SELECT
+      IF ( (k >= 1).AND.(k <= nb_ax_mx) ) THEN
+        dimnb = nw_di(k,f_i)
+      ELSE
+        dimnb = -1
+      ENDIF
+!-----
+      i_rc = NF90_INQUIRE_DIMENSION(nw_id(f_i),dimnb,name=c_t1)
+      IF (i_rc == NF90_NOERR) THEN
+        CALL strlowercase (c_t1)
+        L_R1: DO kv=1,nw_nv(f_i)
+          i_rc = NF90_INQUIRE_VARIABLE &
+ &                 (nw_id(f_i),kv,name=c_t2,ndims=n_d)
+          IF (n_d == 1) THEN
+            CALL strlowercase (c_t2)
+            IF (TRIM(c_t1) == TRIM(c_t2)) THEN
+              i_v = kv; nbd = n_d;
+              EXIT L_R1
+            ENDIF
+          ENDIF
+        ENDDO L_R1
+      ENDIF
+    ENDIF
+!---
+!-- Rule 2 : we look for a correct "axis" attribute (CF)
+!---
+    IF (i_v < 0) THEN
+      L_R2: DO kv=1,nw_nv(f_i)
+        i_rc = NF90_GET_ATT(nw_id(f_i),kv,'axis',c_t1)
+        IF (i_rc == NF90_NOERR) THEN
+          CALL strlowercase (c_t1)
+          IF (TRIM(c_t1) == c_ax) THEN
+            i_rc = NF90_INQUIRE_VARIABLE(nw_id(f_i),kv,ndims=n_d)
+            IF (n_d <= l_d) THEN
+              i_v = kv; nbd = n_d;
+              EXIT L_R2
+            ENDIF
+          ENDIF
+        ENDIF
+      ENDDO L_R2
+    ENDIF
+!---
+!-- Rule 3 : we look for a correct "standard_name" attribute (CF)
+!---
+    IF (i_v < 0) THEN
+      L_R3: DO kv=1,nw_nv(f_i)
+        i_rc = NF90_GET_ATT(nw_id(f_i),kv,'standard_name',c_t1)
+        IF (i_rc == NF90_NOERR) THEN
+          CALL strlowercase (c_t1)
+          IF (TRIM(c_t1) == TRIM(c_sn)) THEN
+            i_rc = NF90_INQUIRE_VARIABLE(nw_id(f_i),kv,ndims=n_d)
+            IF (n_d <= l_d) THEN
+              i_v = kv; nbd = n_d;
+              EXIT L_R3
+            ENDIF
+          ENDIF
+        ENDIF
+      ENDDO L_R3
+    ENDIF
+!---
+!-- Rule 4 : we look for a specific name (IOIPSL)
+!---
+    IF (i_v < 0) THEN
+      SELECT CASE (c_ax)
+      CASE('x')
+        n_r = 3
+        c_r(1)='nav_lon'; c_r(2)='lon'; c_r(3)='longitude';
+      CASE('y')
+        n_r = 3
+        c_r(1)='nav_lat'; c_r(2)='lat'; c_r(3)='latitude';
+      CASE('z')
+        n_r = 8
+        c_r(1)='depth'; c_r(2)='deptht'; c_r(3)='height';
+        c_r(4)='level'; c_r(5)='lev'; c_r(6)='plev';
+        c_r(7)='sigma_level'; c_r(8)='layer';
+      CASE('t')
+        n_r = 3
+        c_r(1)='time'; c_r(2)='tstep'; c_r(3)='timesteps';
+      END SELECT
+!-----
+      L_R4: DO kv=1,nw_nv(f_i)
+        i_rc = NF90_INQUIRE_VARIABLE &
+ &               (nw_id(f_i),kv,name=c_t1,ndims=n_d)
+        IF (i_rc == NF90_NOERR) THEN
+          CALL strlowercase (c_t1)
+          IF (n_d <= l_d) THEN
+            DO k=1,n_r
+              IF (TRIM(c_t1) == TRIM(c_r(k))) THEN
+                i_v = kv; nbd = n_d;
+                EXIT L_R4
+              ENDIF
+            ENDDO
+          ENDIF
+        ENDIF
+      ENDDO L_R4
+    ENDIF
+!---
+  ENDIF
+!----------------------
+END SUBROUTINE flio_qax
+!-
+!===
+!-
+END MODULE fliocom
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/getincom.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/getincom.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/getincom.f90	(revision 329)
@@ -0,0 +1,1975 @@
+MODULE getincom
+!-
+!$Id: getincom.f90 536 2009-01-30 11:46:27Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+USE errioipsl, ONLY : ipslerr
+USE stringop, &
+ &   ONLY : nocomma,cmpblank,strlowercase
+!-
+IMPLICIT NONE
+!-
+PRIVATE
+PUBLIC :: getin, getin_dump
+!-
+INTERFACE getin
+!!--------------------------------------------------------------------
+!! The "getin" routines get a variable.
+!! We first check if we find it in the database
+!! and if not we get it from the run.def file.
+!!
+!! SUBROUTINE getin (target,ret_val)
+!!
+!! INPUT
+!!
+!! (C) target : Name of the variable
+!!
+!! OUTPUT
+!!
+!! (I/R/C/L) ret_val : scalar, vector or matrix that will contain
+!!                     that will contain the (standard)
+!!                     integer/real/character/logical values
+!!--------------------------------------------------------------------
+  MODULE PROCEDURE getinrs, getinr1d, getinr2d, &
+ &                 getinis, getini1d, getini2d, &
+ &                 getincs, getinc1d, getinc2d, &
+ &                 getinls, getinl1d, getinl2d
+END INTERFACE
+!-
+!!--------------------------------------------------------------------
+!! The "getin_dump" routine will dump the content of the database
+!! into a file which has the same format as the run.def file.
+!! The idea is that the user can see which parameters were used
+!! and re-use the file for another run.
+!!
+!!  SUBROUTINE getin_dump (fileprefix)
+!!
+!! OPTIONAL INPUT argument
+!!
+!! (C) fileprefix : allows the user to change the name of the file
+!!                  in which the data will be archived
+!!--------------------------------------------------------------------
+!-
+  INTEGER,PARAMETER :: max_files=100
+  CHARACTER(LEN=100),DIMENSION(max_files),SAVE :: filelist
+  INTEGER,SAVE      :: nbfiles
+!-
+  INTEGER,PARAMETER :: i_txtslab=1000,l_n=30
+  INTEGER,SAVE :: nb_lines,i_txtsize=0
+  CHARACTER(LEN=100),SAVE,ALLOCATABLE,DIMENSION(:) :: fichier
+  CHARACTER(LEN=l_n),SAVE,ALLOCATABLE,DIMENSION(:) :: targetlist
+  INTEGER,SAVE,ALLOCATABLE,DIMENSION(:) :: fromfile,compline
+!-
+  INTEGER,PARAMETER :: n_d_fmt=5,max_msgs=15
+  CHARACTER(LEN=6),SAVE :: c_i_fmt = '(I5.5)'
+!-
+! The data base of parameters
+!-
+  INTEGER,PARAMETER :: memslabs=200
+  INTEGER,PARAMETER :: compress_lim=20
+!-
+  INTEGER,SAVE :: nb_keys=0
+  INTEGER,SAVE :: keymemsize=0
+!-
+! keystr definition
+! name of a key
+!-
+! keystatus definition
+! keystatus = 1 : Value comes from run.def
+! keystatus = 2 : Default value is used
+! keystatus = 3 : Some vector elements were taken from default
+!-
+! keytype definition
+! keytype = 1 : Integer
+! keytype = 2 : Real
+! keytype = 3 : Character
+! keytype = 4 : Logical
+!-
+  INTEGER,PARAMETER :: k_i=1, k_r=2, k_c=3, k_l=4
+!-
+! Allow compression for keys (only for integer and real)
+! keycompress < 0 : not compressed
+! keycompress > 0 : number of repeat of the value
+!-
+TYPE :: t_key
+  CHARACTER(LEN=l_n) :: keystr
+  INTEGER :: keystatus, keytype, keycompress, &
+ &           keyfromfile, keymemstart, keymemlen
+END TYPE t_key
+!-
+  TYPE(t_key),SAVE,ALLOCATABLE,DIMENSION(:) :: key_tab
+!-
+  INTEGER,SAVE,ALLOCATABLE,DIMENSION(:) :: i_mem
+  INTEGER,SAVE :: i_memsize=0, i_mempos=0
+  REAL,SAVE,ALLOCATABLE,DIMENSION(:) :: r_mem
+  INTEGER,SAVE :: r_memsize=0, r_mempos=0
+  CHARACTER(LEN=100),SAVE,ALLOCATABLE,DIMENSION(:) :: c_mem
+  INTEGER,SAVE :: c_memsize=0, c_mempos=0
+  LOGICAL,SAVE,ALLOCATABLE,DIMENSION(:) :: l_mem
+  INTEGER,SAVE :: l_memsize=0, l_mempos=0
+!-
+CONTAINS
+!-
+!=== INTEGER INTERFACE
+!-
+SUBROUTINE getinis (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  INTEGER :: ret_val
+!-
+  INTEGER,DIMENSION(1) :: tmp_ret_val
+  INTEGER :: pos,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  tmp_ret_val(1) = ret_val
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,i_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,1,i_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,1,target,i_val=tmp_ret_val)
+  ENDIF
+  ret_val = tmp_ret_val(1)
+!---------------------
+END SUBROUTINE getinis
+!===
+SUBROUTINE getini1d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  INTEGER,DIMENSION(:) :: ret_val
+!-
+  INTEGER,DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+  tmp_ret_val(1:size_of_in) = ret_val(1:size_of_in)
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,i_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,i_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,i_val=tmp_ret_val)
+  ENDIF
+  ret_val(1:size_of_in) = tmp_ret_val(1:size_of_in)
+!----------------------
+END SUBROUTINE getini1d
+!===
+SUBROUTINE getini2d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  INTEGER,DIMENSION(:,:) :: ret_val
+!-
+  INTEGER,DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,size_1,size_2,status=0,fileorig
+  INTEGER :: jl,jj,ji
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  size_1 = SIZE(ret_val,1)
+  size_2 = SIZE(ret_val,2)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      tmp_ret_val(jl) = ret_val(ji,jj)
+    ENDDO
+  ENDDO
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,i_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,i_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,i_val=tmp_ret_val)
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      ret_val(ji,jj) = tmp_ret_val(jl)
+    ENDDO
+  ENDDO
+!----------------------
+END SUBROUTINE getini2d
+!-
+!=== REAL INTERFACE
+!-
+SUBROUTINE getinrs (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  REAL :: ret_val
+!-
+  REAL,DIMENSION(1) :: tmp_ret_val
+  INTEGER :: pos,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  tmp_ret_val(1) = ret_val
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,r_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,1,r_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,1,target,r_val=tmp_ret_val)
+  ENDIF
+  ret_val = tmp_ret_val(1)
+!---------------------
+END SUBROUTINE getinrs
+!===
+SUBROUTINE getinr1d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  REAL,DIMENSION(:) :: ret_val
+!-
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+  tmp_ret_val(1:size_of_in) = ret_val(1:size_of_in)
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,r_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,r_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,r_val=tmp_ret_val)
+  ENDIF
+  ret_val(1:size_of_in) = tmp_ret_val(1:size_of_in)
+!----------------------
+END SUBROUTINE getinr1d
+!===
+SUBROUTINE getinr2d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  REAL,DIMENSION(:,:) :: ret_val
+!-
+  REAL,DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,size_1,size_2,status=0,fileorig
+  INTEGER :: jl,jj,ji
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  size_1 = SIZE(ret_val,1)
+  size_2 = SIZE(ret_val,2)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      tmp_ret_val(jl) = ret_val(ji,jj)
+    ENDDO
+  ENDDO
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,r_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,r_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,r_val=tmp_ret_val)
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      ret_val(ji,jj) = tmp_ret_val(jl)
+    ENDDO
+  ENDDO
+!----------------------
+END SUBROUTINE getinr2d
+!-
+!=== CHARACTER INTERFACE
+!-
+SUBROUTINE getincs (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  CHARACTER(LEN=*) :: ret_val
+!-
+  CHARACTER(LEN=100),DIMENSION(1) :: tmp_ret_val
+  INTEGER :: pos,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  tmp_ret_val(1) = ret_val
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,c_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,1,c_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,1,target,c_val=tmp_ret_val)
+  ENDIF
+  ret_val = tmp_ret_val(1)
+!---------------------
+END SUBROUTINE getincs
+!===
+SUBROUTINE getinc1d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  CHARACTER(LEN=*),DIMENSION(:) :: ret_val
+!-
+  CHARACTER(LEN=100),DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+  tmp_ret_val(1:size_of_in) = ret_val(1:size_of_in)
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,c_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,c_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,c_val=tmp_ret_val)
+  ENDIF
+  ret_val(1:size_of_in) = tmp_ret_val(1:size_of_in)
+!----------------------
+END SUBROUTINE getinc1d
+!===
+SUBROUTINE getinc2d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  CHARACTER(LEN=*),DIMENSION(:,:) :: ret_val
+!-
+  CHARACTER(LEN=100),DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,size_1,size_2,status=0,fileorig
+  INTEGER :: jl,jj,ji
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  size_1 = SIZE(ret_val,1)
+  size_2 = SIZE(ret_val,2)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      tmp_ret_val(jl) = ret_val(ji,jj)
+    ENDDO
+  ENDDO
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,c_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,c_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,c_val=tmp_ret_val)
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      ret_val(ji,jj) = tmp_ret_val(jl)
+    ENDDO
+  ENDDO
+!----------------------
+END SUBROUTINE getinc2d
+!-
+!=== LOGICAL INTERFACE
+!-
+SUBROUTINE getinls (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  LOGICAL :: ret_val
+!-
+  LOGICAL,DIMENSION(1) :: tmp_ret_val
+  INTEGER :: pos,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  tmp_ret_val(1) = ret_val
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,l_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,1,l_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,1,target,l_val=tmp_ret_val)
+  ENDIF
+  ret_val = tmp_ret_val(1)
+!---------------------
+END SUBROUTINE getinls
+!===
+SUBROUTINE getinl1d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  LOGICAL,DIMENSION(:) :: ret_val
+!-
+  LOGICAL,DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,status=0,fileorig
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+  tmp_ret_val(1:size_of_in) = ret_val(1:size_of_in)
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,l_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,l_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,l_val=tmp_ret_val)
+  ENDIF
+  ret_val(1:size_of_in) = tmp_ret_val(1:size_of_in)
+!----------------------
+END SUBROUTINE getinl1d
+!===
+SUBROUTINE getinl2d (target,ret_val)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  LOGICAL,DIMENSION(:,:) :: ret_val
+!-
+  LOGICAL,DIMENSION(:),ALLOCATABLE,SAVE :: tmp_ret_val
+  INTEGER,SAVE :: tmp_ret_size = 0
+  INTEGER :: pos,size_of_in,size_1,size_2,status=0,fileorig
+  INTEGER :: jl,jj,ji
+!---------------------------------------------------------------------
+!-
+! Do we have this target in our database ?
+!-
+  CALL get_findkey (1,target,pos)
+!-
+  size_of_in = SIZE(ret_val)
+  size_1 = SIZE(ret_val,1)
+  size_2 = SIZE(ret_val,2)
+  IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
+    ALLOCATE (tmp_ret_val(size_of_in))
+  ELSE IF (size_of_in > tmp_ret_size) THEN
+    DEALLOCATE (tmp_ret_val)
+    ALLOCATE (tmp_ret_val(size_of_in))
+    tmp_ret_size = size_of_in
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      tmp_ret_val(jl) = ret_val(ji,jj)
+    ENDDO
+  ENDDO
+!-
+  IF (pos < 0) THEN
+!-- Get the information out of the file
+    CALL get_fil (target,status,fileorig,l_val=tmp_ret_val)
+!-- Put the data into the database
+    CALL get_wdb &
+ &   (target,status,fileorig,size_of_in,l_val=tmp_ret_val)
+  ELSE
+!-- Get the value out of the database
+    CALL get_rdb (pos,size_of_in,target,l_val=tmp_ret_val)
+  ENDIF
+!-
+  jl=0
+  DO jj=1,size_2
+    DO ji=1,size_1
+      jl=jl+1
+      ret_val(ji,jj) = tmp_ret_val(jl)
+    ENDDO
+  ENDDO
+!----------------------
+END SUBROUTINE getinl2d
+!-
+!=== Generic file/database INTERFACE
+!-
+SUBROUTINE get_fil (target,status,fileorig,i_val,r_val,c_val,l_val)
+!---------------------------------------------------------------------
+!- Subroutine that will extract from the file the values
+!- attributed to the keyword target
+!-
+!- (C) target    : target for which we will look in the file
+!- (I) status    : tells us from where we obtained the data
+!- (I) fileorig  : index of the file from which the key comes
+!- (I) i_val(:)  : INTEGER(nb_to_ret)   values
+!- (R) r_val(:)  : REAL(nb_to_ret)      values
+!- (L) l_val(:)  : LOGICAL(nb_to_ret)   values
+!- (C) c_val(:)  : CHARACTER(nb_to_ret) values
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  INTEGER,INTENT(OUT) :: status,fileorig
+  INTEGER,DIMENSION(:),OPTIONAL          :: i_val
+  REAL,DIMENSION(:),OPTIONAL             :: r_val
+  LOGICAL,DIMENSION(:),OPTIONAL          :: l_val
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL :: c_val
+!-
+  INTEGER :: k_typ,nb_to_ret,it,pos,len_str,status_cnt,io_err
+  CHARACTER(LEN=n_d_fmt)  :: cnt
+  CHARACTER(LEN=80) :: str_READ,str_READ_lower
+  CHARACTER(LEN=9)  :: c_vtyp
+  LOGICAL,DIMENSION(:),ALLOCATABLE :: found
+  LOGICAL :: def_beha,compressed
+  CHARACTER(LEN=10) :: c_fmt
+  INTEGER :: i_cmpval
+  REAL    :: r_cmpval
+  INTEGER :: ipos_tr,ipos_fl
+!---------------------------------------------------------------------
+!-
+! Get the type of the argument
+  CALL get_qtyp (k_typ,c_vtyp,i_val,r_val,c_val,l_val)
+  SELECT CASE (k_typ)
+  CASE(k_i)
+    nb_to_ret = SIZE(i_val)
+  CASE(k_r)
+    nb_to_ret = SIZE(r_val)
+  CASE(k_c)
+    nb_to_ret = SIZE(c_val)
+  CASE(k_l)
+    nb_to_ret = SIZE(l_val)
+  CASE DEFAULT
+    CALL ipslerr (3,'get_fil', &
+ &   'Internal error','Unknown type of data',' ')
+  END SELECT
+!-
+! Read the file(s)
+  CALL getin_read
+!-
+! Allocate and initialize the memory we need
+  ALLOCATE(found(nb_to_ret))
+  found(:) = .FALSE.
+!-
+! See what we find in the files read
+  DO it=1,nb_to_ret
+!---
+!-- First try the target as it is
+    CALL get_findkey (2,target,pos)
+!---
+!-- Another try
+!---
+    IF (pos < 0) THEN
+      WRITE(UNIT=cnt,FMT=c_i_fmt) it
+      CALL get_findkey (2,TRIM(target)//'__'//cnt,pos)
+    ENDIF
+!---
+!-- We dont know from which file the target could come.
+!-- Thus by default we attribute it to the first file :
+    fileorig = 1
+!---
+    IF (pos > 0) THEN
+!-----
+      found(it) = .TRUE.
+      fileorig = fromfile(pos)
+!-----
+!---- DECODE
+!-----
+      str_READ = ADJUSTL(fichier(pos))
+      str_READ_lower = str_READ
+      CALL strlowercase (str_READ_lower)
+!-----
+      IF (    (TRIM(str_READ_lower) == 'def')     &
+ &        .OR.(TRIM(str_READ_lower) == 'default') ) THEN
+        def_beha = .TRUE.
+      ELSE
+        def_beha = .FALSE.
+        len_str = LEN_TRIM(str_READ)
+        io_err = 0
+        SELECT CASE (k_typ)
+        CASE(k_i)
+          WRITE (UNIT=c_fmt,FMT='("(I",I3.3,")")') len_str
+          READ (UNIT=str_READ(1:len_str), &
+ &              FMT=c_fmt,IOSTAT=io_err) i_val(it)
+        CASE(k_r)
+          READ (UNIT=str_READ(1:len_str), &
+ &              FMT=*,IOSTAT=io_err) r_val(it)
+        CASE(k_c)
+          c_val(it) = str_READ(1:len_str)
+        CASE(k_l)
+          ipos_tr = -1
+          ipos_fl = -1
+          ipos_tr = MAX(INDEX(str_READ_lower,'tru'), &
+ &                      INDEX(str_READ_lower,'y'))
+          ipos_fl = MAX(INDEX(str_READ_lower,'fal'), &
+ &                      INDEX(str_READ_lower,'n'))
+          IF (ipos_tr > 0) THEN
+            l_val(it) = .TRUE.
+          ELSE IF (ipos_fl > 0) THEN
+            l_val(it) = .FALSE.
+          ELSE
+            io_err = 100
+          ENDIF
+        END SELECT
+        IF (io_err /= 0) THEN
+          CALL ipslerr (3,'get_fil', &
+ &         'Target '//TRIM(target), &
+ &         'is not of '//TRIM(c_vtyp)//' type',' ')
+        ENDIF
+      ENDIF
+!-----
+      IF ( (k_typ == k_i).OR.(k_typ == k_r) ) THEN
+!-------
+!------ Is this the value of a compressed field ?
+        compressed = (compline(pos) > 0)
+        IF (compressed) THEN
+          IF (compline(pos) /= nb_to_ret) THEN
+            CALL ipslerr (2,'get_fil', &
+ &           'For key '//TRIM(target)//' we have a compressed field', &
+ &           'which does not have the right size.', &
+ &           'We will try to fix that.')
+          ENDIF
+          IF      (k_typ == k_i) THEN
+            i_cmpval = i_val(it)
+          ELSE IF (k_typ == k_r) THEN
+            r_cmpval = r_val(it)
+          ENDIF
+        ENDIF
+      ENDIF
+    ELSE
+      found(it) = .FALSE.
+      def_beha = .FALSE.
+      compressed = .FALSE.
+    ENDIF
+  ENDDO
+!-
+  IF ( (k_typ == k_i).OR.(k_typ == k_r) ) THEN
+!---
+!-- If this is a compressed field then we will uncompress it
+    IF (compressed) THEN
+      DO it=1,nb_to_ret
+        IF (.NOT.found(it)) THEN
+          IF      (k_typ == k_i) THEN
+            i_val(it) = i_cmpval
+          ELSE IF (k_typ == k_r) THEN
+          ENDIF
+          found(it) = .TRUE.
+        ENDIF
+      ENDDO
+    ENDIF
+  ENDIF
+!-
+! Now we set the status for what we found
+  IF (def_beha) THEN
+    status = 2
+    WRITE(*,*) 'USING DEFAULT BEHAVIOUR FOR ',TRIM(target)
+  ELSE
+    status_cnt = 0
+    DO it=1,nb_to_ret
+      IF (.NOT.found(it)) THEN
+        status_cnt = status_cnt+1
+        IF      (status_cnt <= max_msgs) THEN
+          WRITE (UNIT=*,FMT='(" USING DEFAULTS : ",A)', &
+ &               ADVANCE='NO') TRIM(target)
+          IF (nb_to_ret > 1) THEN
+            WRITE (UNIT=*,FMT='("__")',ADVANCE='NO')
+            WRITE (UNIT=*,FMT=c_i_fmt,ADVANCE='NO') it
+          ENDIF
+          SELECT CASE (k_typ)
+          CASE(k_i)
+            WRITE (UNIT=*,FMT=*) "=",i_val(it)
+          CASE(k_r)
+            WRITE (UNIT=*,FMT=*) "=",r_val(it)
+          CASE(k_c)
+            WRITE (UNIT=*,FMT=*) "=",c_val(it)
+          CASE(k_l)
+            WRITE (UNIT=*,FMT=*) "=",l_val(it)
+          END SELECT
+        ELSE IF (status_cnt == max_msgs+1) THEN
+          WRITE (UNIT=*,FMT='(" USING DEFAULTS ... ",A)')
+        ENDIF
+      ENDIF
+    ENDDO
+!---
+    IF (status_cnt == 0) THEN
+      status = 1
+    ELSE IF (status_cnt == nb_to_ret) THEN
+      status = 2
+    ELSE
+      status = 3
+    ENDIF
+  ENDIF
+! Deallocate the memory
+  DEALLOCATE(found)
+!---------------------
+END SUBROUTINE get_fil
+!===
+SUBROUTINE get_rdb (pos,size_of_in,target,i_val,r_val,c_val,l_val)
+!---------------------------------------------------------------------
+!- Read the required variable in the database
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: pos,size_of_in
+  CHARACTER(LEN=*) :: target
+  INTEGER,DIMENSION(:),OPTIONAL          :: i_val
+  REAL,DIMENSION(:),OPTIONAL             :: r_val
+  LOGICAL,DIMENSION(:),OPTIONAL          :: l_val
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL :: c_val
+!-
+  INTEGER :: k_typ,k_beg,k_end
+  CHARACTER(LEN=9) :: c_vtyp
+!---------------------------------------------------------------------
+!-
+! Get the type of the argument
+  CALL get_qtyp (k_typ,c_vtyp,i_val,r_val,c_val,l_val)
+  IF (     (k_typ /= k_i).AND.(k_typ /= k_r) &
+ &    .AND.(k_typ /= k_c).AND.(k_typ /= k_l) )THEN
+    CALL ipslerr (3,'get_rdb', &
+ &   'Internal error','Unknown type of data',' ')
+  ENDIF
+!-
+  IF (key_tab(pos)%keytype /= k_typ) THEN
+    CALL ipslerr (3,'get_rdb', &
+ &   'Wrong data type for keyword '//TRIM(target), &
+ &   '(NOT '//TRIM(c_vtyp)//')',' ')
+  ENDIF
+!-
+  IF (key_tab(pos)%keycompress > 0) THEN
+    IF (    (key_tab(pos)%keycompress /= size_of_in) &
+ &      .OR.(key_tab(pos)%keymemlen /= 1) ) THEN
+      CALL ipslerr (3,'get_rdb', &
+ &     'Wrong compression length','for keyword '//TRIM(target),' ')
+    ELSE
+      SELECT CASE (k_typ)
+      CASE(k_i)
+        i_val(1:size_of_in) = i_mem(key_tab(pos)%keymemstart)
+      CASE(k_r)
+        r_val(1:size_of_in) = r_mem(key_tab(pos)%keymemstart)
+      END SELECT
+    ENDIF
+  ELSE
+    IF (key_tab(pos)%keymemlen /= size_of_in) THEN
+      CALL ipslerr (3,'get_rdb', &
+ &     'Wrong array length','for keyword '//TRIM(target),' ')
+    ELSE
+      k_beg = key_tab(pos)%keymemstart
+      k_end = k_beg+key_tab(pos)%keymemlen-1
+      SELECT CASE (k_typ)
+      CASE(k_i)
+        i_val(1:size_of_in) = i_mem(k_beg:k_end)
+      CASE(k_r)
+        r_val(1:size_of_in) = r_mem(k_beg:k_end)
+      CASE(k_c)
+        c_val(1:size_of_in) = c_mem(k_beg:k_end)
+      CASE(k_l)
+        l_val(1:size_of_in) = l_mem(k_beg:k_end)
+      END SELECT
+    ENDIF
+  ENDIF
+!---------------------
+END SUBROUTINE get_rdb
+!===
+SUBROUTINE get_wdb &
+ &  (target,status,fileorig,size_of_in, &
+ &   i_val,r_val,c_val,l_val)
+!---------------------------------------------------------------------
+!- Write data into the data base
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: target
+  INTEGER :: status,fileorig,size_of_in
+  INTEGER,DIMENSION(:),OPTIONAL          :: i_val
+  REAL,DIMENSION(:),OPTIONAL             :: r_val
+  LOGICAL,DIMENSION(:),OPTIONAL          :: l_val
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL :: c_val
+!-
+  INTEGER :: k_typ
+  CHARACTER(LEN=9) :: c_vtyp
+  INTEGER :: k_mempos,k_memsize,k_beg,k_end
+  LOGICAL :: l_cmp
+!---------------------------------------------------------------------
+!-
+! Get the type of the argument
+  CALL get_qtyp (k_typ,c_vtyp,i_val,r_val,c_val,l_val)
+  IF (     (k_typ /= k_i).AND.(k_typ /= k_r) &
+ &    .AND.(k_typ /= k_c).AND.(k_typ /= k_l) )THEN
+    CALL ipslerr (3,'get_wdb', &
+ &   'Internal error','Unknown type of data',' ')
+  ENDIF
+!-
+! First check if we have sufficiant space for the new key
+  IF (nb_keys+1 > keymemsize) THEN
+    CALL getin_allockeys ()
+  ENDIF
+!-
+  SELECT CASE (k_typ)
+  CASE(k_i)
+    k_mempos = i_mempos; k_memsize = i_memsize;
+    l_cmp = (MINVAL(i_val) == MAXVAL(i_val)) &
+ &         .AND.(size_of_in > compress_lim)
+  CASE(k_r)
+    k_mempos = r_mempos; k_memsize = r_memsize;
+    l_cmp = (MINVAL(r_val) == MAXVAL(r_val)) &
+ &         .AND.(size_of_in > compress_lim)
+  CASE(k_c)
+    k_mempos = c_mempos; k_memsize = c_memsize;
+    l_cmp = .FALSE.
+  CASE(k_l)
+    k_mempos = l_mempos; k_memsize = l_memsize;
+    l_cmp = .FALSE.
+  END SELECT
+!-
+! Fill out the items of the data base
+  nb_keys = nb_keys+1
+  key_tab(nb_keys)%keystr = target(1:MIN(LEN_TRIM(target),l_n))
+  key_tab(nb_keys)%keystatus = status
+  key_tab(nb_keys)%keytype = k_typ
+  key_tab(nb_keys)%keyfromfile = fileorig
+  key_tab(nb_keys)%keymemstart = k_mempos+1
+  IF (l_cmp) THEN
+    key_tab(nb_keys)%keycompress = size_of_in
+    key_tab(nb_keys)%keymemlen = 1
+  ELSE
+    key_tab(nb_keys)%keycompress = -1
+    key_tab(nb_keys)%keymemlen = size_of_in
+  ENDIF
+!-
+! Before writing the actual size lets see if we have the space
+  IF (key_tab(nb_keys)%keymemstart+key_tab(nb_keys)%keymemlen &
+ &    > k_memsize) THEN
+    CALL getin_allocmem (k_typ,key_tab(nb_keys)%keymemlen)
+  ENDIF
+!-
+  k_beg = key_tab(nb_keys)%keymemstart
+  k_end = k_beg+key_tab(nb_keys)%keymemlen-1
+  SELECT CASE (k_typ)
+  CASE(k_i)
+    i_mem(k_beg:k_end) = i_val(1:key_tab(nb_keys)%keymemlen)
+    i_mempos = k_end
+  CASE(k_r)
+    r_mem(k_beg:k_end) = r_val(1:key_tab(nb_keys)%keymemlen)
+    r_mempos = k_end
+  CASE(k_c)
+    c_mem(k_beg:k_end) = c_val(1:key_tab(nb_keys)%keymemlen)
+    c_mempos = k_end
+  CASE(k_l)
+    l_mem(k_beg:k_end) = l_val(1:key_tab(nb_keys)%keymemlen)
+    l_mempos = k_end
+  END SELECT
+!---------------------
+END SUBROUTINE get_wdb
+!-
+!===
+!-
+SUBROUTINE getin_read
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,SAVE :: allread=0
+  INTEGER,SAVE :: current
+!---------------------------------------------------------------------
+  IF (allread == 0) THEN
+!-- Allocate a first set of memory.
+    CALL getin_alloctxt ()
+    CALL getin_allockeys ()
+    CALL getin_allocmem (k_i,0)
+    CALL getin_allocmem (k_r,0)
+    CALL getin_allocmem (k_c,0)
+    CALL getin_allocmem (k_l,0)
+!-- Start with reading the files
+    nbfiles = 1
+    filelist(1) = 'run.def'
+    current = 1
+!--
+    DO WHILE (current <= nbfiles)
+      CALL getin_readdef (current)
+      current = current+1
+    ENDDO
+    allread = 1
+    CALL getin_checkcohe ()
+  ENDIF
+!------------------------
+END SUBROUTINE getin_read
+!-
+!===
+!-
+  SUBROUTINE getin_readdef(current)
+!---------------------------------------------------------------------
+!- This subroutine will read the files and only keep the
+!- the relevant information. The information is kept as it
+!- found in the file. The data will be analysed later.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: current
+!-
+  CHARACTER(LEN=100) :: READ_str,NEW_str,last_key,key_str
+  CHARACTER(LEN=n_d_fmt) :: cnt
+  CHARACTER(LEN=10) :: c_fmt
+  INTEGER :: nb_lastkey
+!-
+  INTEGER :: eof,ptn,len_str,i,it,iund,io_err
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  eof = 0
+  ptn = 1
+  nb_lastkey = 0
+!-
+  IF (check) THEN
+    WRITE(*,*) 'getin_readdef : Open file ',TRIM(filelist(current))
+  ENDIF
+!-
+  OPEN (UNIT=22,FILE=filelist(current),STATUS="OLD",IOSTAT=io_err)
+  IF (io_err /= 0) THEN
+    CALL ipslerr (2,'getin_readdef', &
+ &  'Could not open file '//TRIM(filelist(current)),' ',' ')
+    RETURN
+  ENDIF
+!-
+  DO WHILE (eof /= 1)
+!---
+    CALL getin_skipafew (22,READ_str,eof,nb_lastkey)
+    len_str = LEN_TRIM(READ_str)
+    ptn = INDEX(READ_str,'=')
+!---
+    IF (ptn > 0) THEN
+!---- Get the target
+      key_str = TRIM(ADJUSTL(READ_str(1:ptn-1)))
+!---- Make sure that a vector keyword has the right length
+      iund = INDEX(key_str,'__')
+      IF (iund > 0) THEN
+        WRITE (UNIT=c_fmt,FMT='("(I",I3.3,")")') &
+ &        LEN_TRIM(key_str)-iund-1
+        READ(UNIT=key_str(iund+2:LEN_TRIM(key_str)), &
+ &           FMT=c_fmt,IOSTAT=io_err) it
+        IF ( (io_err == 0).AND.(it > 0) ) THEN
+          WRITE(UNIT=cnt,FMT=c_i_fmt) it
+          key_str = key_str(1:iund+1)//cnt
+        ELSE
+          CALL ipslerr (3,'getin_readdef', &
+ &         'A very strange key has just been found :', &
+ &         TRIM(key_str),' ')
+        ENDIF
+      ENDIF
+!---- Prepare the content
+      NEW_str = TRIM(ADJUSTL(READ_str(ptn+1:len_str)))
+      CALL nocomma (NEW_str)
+      CALL cmpblank (NEW_str)
+      NEW_str  = TRIM(ADJUSTL(NEW_str))
+      IF (check) THEN
+        WRITE(*,*) &
+ &        '--> getin_readdef : ',TRIM(key_str),' :: ',TRIM(NEW_str)
+      ENDIF
+!---- Decypher the content of NEW_str
+!-
+!---- This has to be a new key word, thus :
+      nb_lastkey = 0
+!----
+      CALL getin_decrypt (current,key_str,NEW_str,last_key,nb_lastkey)
+!----
+    ELSE IF (len_str > 0) THEN
+!---- Prepare the key if we have an old one to which
+!---- we will add the line just read
+      IF (nb_lastkey > 0) THEN
+        iund =  INDEX(last_key,'__')
+        IF (iund > 0) THEN
+!-------- We only continue a keyword, thus it is easy
+          key_str = last_key(1:iund-1)
+        ELSE
+          IF (nb_lastkey /= 1) THEN
+            CALL ipslerr (3,'getin_readdef', &
+ &           'We can not have a scalar keyword', &
+ &           'and a vector content',' ')
+          ENDIF
+!-------- The last keyword needs to be transformed into a vector.
+          WRITE(UNIT=cnt,FMT=c_i_fmt) 1
+          targetlist(nb_lines) = &
+ &         last_key(1:MIN(LEN_TRIM(last_key),l_n-n_d_fmt-2))//'__'//cnt
+          key_str = last_key(1:LEN_TRIM(last_key))
+        ENDIF
+      ENDIF
+!---- Prepare the content
+      NEW_str = TRIM(ADJUSTL(READ_str(1:len_str)))
+      CALL getin_decrypt (current,key_str,NEW_str,last_key,nb_lastkey)
+    ELSE
+!---- If we have an empty line then the keyword finishes
+      nb_lastkey = 0
+      IF (check) THEN
+        WRITE(*,*) 'getin_readdef : Have found an emtpy line '
+      ENDIF
+    ENDIF
+  ENDDO
+!-
+  CLOSE(UNIT=22)
+!-
+  IF (check) THEN
+    OPEN (UNIT=22,file='run.def.test')
+    DO i=1,nb_lines
+      WRITE(UNIT=22,FMT=*) targetlist(i)," : ",fichier(i)
+    ENDDO
+    CLOSE(UNIT=22)
+  ENDIF
+!---------------------------
+END SUBROUTINE getin_readdef
+!-
+!===
+!-
+SUBROUTINE getin_decrypt(current,key_str,NEW_str,last_key,nb_lastkey)
+!---------------------------------------------------------------------
+!- This subroutine is going to decypher the line.
+!- It essentialy checks how many items are included and
+!- it they can be attached to a key.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! ARGUMENTS
+!-
+  INTEGER :: current,nb_lastkey
+  CHARACTER(LEN=*) :: key_str,NEW_str,last_key
+!-
+! LOCAL
+!-
+  INTEGER :: len_str,blk,nbve,starpos
+  CHARACTER(LEN=100) :: tmp_str,new_key,mult
+  CHARACTER(LEN=n_d_fmt) :: cnt
+  CHARACTER(LEN=10) :: c_fmt
+!---------------------------------------------------------------------
+  len_str = LEN_TRIM(NEW_str)
+  blk = INDEX(NEW_str(1:len_str),' ')
+  tmp_str = NEW_str(1:len_str)
+!-
+! If the key is a new file then we take it up. Else
+! we save the line and go on.
+!-
+  IF (INDEX(key_str,'INCLUDEDEF') > 0) THEN
+    DO WHILE (blk > 0)
+      IF (nbfiles+1 > max_files) THEN
+        CALL ipslerr (3,'getin_decrypt', &
+ &       'Too many files to include',' ',' ')
+      ENDIF
+!-----
+      nbfiles = nbfiles+1
+      filelist(nbfiles) = tmp_str(1:blk)
+!-----
+      tmp_str = TRIM(ADJUSTL(tmp_str(blk+1:LEN_TRIM(tmp_str))))
+      blk = INDEX(tmp_str(1:LEN_TRIM(tmp_str)),' ')
+    ENDDO
+!---
+    IF (nbfiles+1 > max_files) THEN
+      CALL ipslerr (3,'getin_decrypt', &
+ &     'Too many files to include',' ',' ')
+    ENDIF
+!---
+    nbfiles =  nbfiles+1
+    filelist(nbfiles) = TRIM(ADJUSTL(tmp_str))
+!---
+    last_key = 'INCLUDEDEF'
+    nb_lastkey = 1
+  ELSE
+!-
+!-- We are working on a new line of input
+!-
+    IF (nb_lines+1 > i_txtsize) THEN
+      CALL getin_alloctxt ()
+    ENDIF
+    nb_lines = nb_lines+1
+!-
+!-- First we solve the issue of conpressed information. Once
+!-- this is done all line can be handled in the same way.
+!-
+    starpos = INDEX(NEW_str(1:len_str),'*')
+    IF ( (starpos > 0).AND.(tmp_str(1:1) /= '"') &
+ &                    .AND.(tmp_str(1:1) /= "'") ) THEN
+!-----
+      IF (INDEX(key_str(1:LEN_TRIM(key_str)),'__') > 0) THEN
+        CALL ipslerr (3,'getin_decrypt', &
+ &       'We can not have a compressed field of values', &
+ &       'in a vector notation (TARGET__n).', &
+ &       'The key at fault : '//TRIM(key_str))
+      ENDIF
+!-
+!---- Read the multiplied
+!-
+      mult = TRIM(ADJUSTL(NEW_str(1:starpos-1)))
+!---- Construct the new string and its parameters
+      NEW_str = TRIM(ADJUSTL(NEW_str(starpos+1:len_str)))
+      len_str = LEN_TRIM(NEW_str)
+      blk = INDEX(NEW_str(1:len_str),' ')
+      IF (blk > 1) THEN
+        CALL ipslerr (2,'getin_decrypt', &
+ &       'This is a strange behavior','you could report',' ')
+      ENDIF
+      WRITE (UNIT=c_fmt,FMT='("(I",I5.5,")")') LEN_TRIM(mult)
+      READ(UNIT=mult,FMT=c_fmt) compline(nb_lines)
+!---
+    ELSE
+      compline(nb_lines) = -1
+    ENDIF
+!-
+!-- If there is no space wthin the line then the target is a scalar
+!-- or the element of a properly written vector.
+!-- (ie of the type TARGET__00001)
+!-
+    IF (    (blk <= 1) &
+ &      .OR.(tmp_str(1:1) == '"') &
+ &      .OR.(tmp_str(1:1) == "'") ) THEN
+!-
+      IF (nb_lastkey == 0) THEN
+!------ Save info of current keyword as a scalar
+!------ if it is not a continuation
+        targetlist(nb_lines) = key_str(1:MIN(LEN_TRIM(key_str),l_n))
+        last_key = key_str(1:MIN(LEN_TRIM(key_str),l_n))
+        nb_lastkey = 1
+      ELSE
+!------ We are continuing a vector so the keyword needs
+!------ to get the underscores
+        WRITE(UNIT=cnt,FMT=c_i_fmt) nb_lastkey+1
+        targetlist(nb_lines) = &
+ &        key_str(1:MIN(LEN_TRIM(key_str),l_n-n_d_fmt-2))//'__'//cnt
+        last_key = &
+ &        key_str(1:MIN(LEN_TRIM(key_str),l_n-n_d_fmt-2))//'__'//cnt
+        nb_lastkey = nb_lastkey+1
+      ENDIF
+!-----
+      fichier(nb_lines) = NEW_str(1:len_str)
+      fromfile(nb_lines) = current
+    ELSE
+!-
+!---- If there are blanks whithin the line then we are dealing
+!---- with a vector and we need to split it in many entries
+!---- with the TARGET__n notation.
+!----
+!---- Test if the targer is not already a vector target !
+!-
+      IF (INDEX(TRIM(key_str),'__') > 0) THEN
+        CALL ipslerr (3,'getin_decrypt', &
+ &       'We have found a mixed vector notation (TARGET__n).', &
+ &       'The key at fault : '//TRIM(key_str),' ')
+      ENDIF
+!-
+      nbve = nb_lastkey
+      nbve = nbve+1
+      WRITE(UNIT=cnt,FMT=c_i_fmt) nbve
+!-
+      DO WHILE (blk > 0)
+!-
+!------ Save the content of target__nbve
+!-
+        fichier(nb_lines) = tmp_str(1:blk)
+        new_key = &
+ &       key_str(1:MIN(LEN_TRIM(key_str),l_n-n_d_fmt-2))//'__'//cnt
+        targetlist(nb_lines) = new_key(1:MIN(LEN_TRIM(new_key),l_n))
+        fromfile(nb_lines) = current
+!-
+        tmp_str = TRIM(ADJUSTL(tmp_str(blk+1:LEN_TRIM(tmp_str))))
+        blk = INDEX(TRIM(tmp_str),' ')
+!-
+        IF (nb_lines+1 > i_txtsize) THEN
+          CALL getin_alloctxt ()
+        ENDIF
+        nb_lines = nb_lines+1
+        nbve = nbve+1
+        WRITE(UNIT=cnt,FMT=c_i_fmt) nbve
+!-
+      ENDDO
+!-
+!---- Save the content of the last target
+!-
+      fichier(nb_lines) = tmp_str(1:LEN_TRIM(tmp_str))
+      new_key = &
+ &      key_str(1:MIN(LEN_TRIM(key_str),l_n-n_d_fmt-2))//'__'//cnt
+      targetlist(nb_lines) = new_key(1:MIN(LEN_TRIM(new_key),l_n))
+      fromfile(nb_lines) = current
+!-
+      last_key = &
+ &      key_str(1:MIN(LEN_TRIM(key_str),l_n-n_d_fmt-2))//'__'//cnt
+      nb_lastkey = nbve
+!-
+    ENDIF
+!-
+  ENDIF
+!---------------------------
+END SUBROUTINE getin_decrypt
+!-
+!===
+!-
+SUBROUTINE getin_checkcohe ()
+!---------------------------------------------------------------------
+!- This subroutine checks for redundancies.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: line,n_k,k
+!---------------------------------------------------------------------
+  DO line=1,nb_lines-1
+!-
+    n_k = 0
+    DO k=line+1,nb_lines
+      IF (TRIM(targetlist(line)) == TRIM(targetlist(k))) THEN
+        n_k = k
+        EXIT
+      ENDIF
+    ENDDO
+!---
+!-- IF we have found it we have a problem to solve.
+!---
+    IF (n_k > 0) THEN
+      WRITE(*,*) 'COUNT : ',n_k
+      WRITE(*,*) &
+ &  'getin_checkcohe : Found a problem on key ',TRIM(targetlist(line))
+      WRITE(*,*) &
+ &  'getin_checkcohe : The following values were encoutered :'
+      WRITE(*,*) &
+ &  '                ',TRIM(targetlist(line)),' == ',fichier(line)
+      WRITE(*,*) &
+ &  '                ',TRIM(targetlist(k)),' == ',fichier(k)
+      WRITE(*,*) &
+ &  'getin_checkcohe : We will keep only the last value'
+      targetlist(line) = ' '
+    ENDIF
+  ENDDO
+!-----------------------------
+END SUBROUTINE getin_checkcohe
+!-
+!===
+!-
+SUBROUTINE getin_skipafew (unit,out_string,eof,nb_lastkey)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: unit,eof,nb_lastkey
+  CHARACTER(LEN=100) :: dummy
+  CHARACTER(LEN=100) :: out_string
+  CHARACTER(LEN=1) :: first
+!---------------------------------------------------------------------
+  first="#"
+  eof = 0
+  out_string = "    "
+!-
+  DO WHILE (first == "#")
+    READ (UNIT=unit,FMT='(A)',ERR=9998,END=7778) dummy
+    dummy = TRIM(ADJUSTL(dummy))
+    first=dummy(1:1)
+    IF (first == "#") THEN
+      nb_lastkey = 0
+    ENDIF
+  ENDDO
+  out_string=dummy
+!-
+  RETURN
+!-
+9998 CONTINUE
+  CALL ipslerr (3,'getin_skipafew','Error while reading file',' ',' ')
+!-
+7778 CONTINUE
+  eof = 1
+!----------------------------
+END SUBROUTINE getin_skipafew
+!-
+!===
+!-
+SUBROUTINE getin_allockeys ()
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  TYPE(t_key),ALLOCATABLE,DIMENSION(:) :: tmp_key_tab
+  CHARACTER(LEN=100),ALLOCATABLE :: tmp_str(:)
+!-
+  INTEGER :: ier
+  CHARACTER(LEN=20) :: c_tmp
+!---------------------------------------------------------------------
+  IF (keymemsize == 0) THEN
+!---
+!-- Nothing exists in memory arrays and it is easy to do.
+!---
+    WRITE (UNIT=c_tmp,FMT=*) memslabs
+    ALLOCATE(key_tab(memslabs),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_allockeys', &
+ &     'Can not allocate key_tab', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+    ENDIF
+    nb_keys = 0
+    keymemsize = memslabs
+    key_tab(:)%keycompress = -1
+!---
+  ELSE
+!---
+!-- There is something already in the memory,
+!-- we need to transfer and reallocate.
+!---
+    WRITE (UNIT=c_tmp,FMT=*) keymemsize
+    ALLOCATE(tmp_key_tab(keymemsize),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_allockeys', &
+ &     'Can not allocate tmp_key_tab', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+    ENDIF
+    WRITE (UNIT=c_tmp,FMT=*) keymemsize+memslabs
+    tmp_key_tab(1:keymemsize) = key_tab(1:keymemsize)
+    DEALLOCATE(key_tab)
+    ALLOCATE(key_tab(keymemsize+memslabs),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_allockeys', &
+ &     'Can not allocate key_tab', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+    ENDIF
+    key_tab(:)%keycompress = -1
+    key_tab(1:keymemsize) = tmp_key_tab(1:keymemsize)
+    DEALLOCATE(tmp_key_tab)
+    keymemsize = keymemsize+memslabs
+  ENDIF
+!-----------------------------
+END SUBROUTINE getin_allockeys
+!-
+!===
+!-
+SUBROUTINE getin_allocmem (type,len_wanted)
+!---------------------------------------------------------------------
+!- Allocate the memory of the data base for all 4 types of memory
+!- INTEGER / REAL / CHARACTER / LOGICAL
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: type,len_wanted
+!-
+  INTEGER,ALLOCATABLE :: tmp_int(:)
+  REAL,ALLOCATABLE :: tmp_real(:)
+  CHARACTER(LEN=100),ALLOCATABLE :: tmp_char(:)
+  LOGICAL,ALLOCATABLE :: tmp_logic(:)
+  INTEGER :: ier
+  CHARACTER(LEN=20) :: c_tmp
+!---------------------------------------------------------------------
+  SELECT CASE (type)
+  CASE(k_i)
+    IF (i_memsize == 0) THEN
+      ALLOCATE(i_mem(memslabs),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) memslabs
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate db-memory', &
+ &       'i_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      i_memsize=memslabs
+    ELSE
+      ALLOCATE(tmp_int(i_memsize),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) i_memsize
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate tmp_int', &
+ &       'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      tmp_int(1:i_memsize) = i_mem(1:i_memsize)
+      DEALLOCATE(i_mem)
+      ALLOCATE(i_mem(i_memsize+MAX(memslabs,len_wanted)),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) i_memsize+MAX(memslabs,len_wanted)
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to re-allocate db-memory', &
+ &       'i_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      i_mem(1:i_memsize) = tmp_int(1:i_memsize)
+      i_memsize = i_memsize+MAX(memslabs,len_wanted)
+      DEALLOCATE(tmp_int)
+    ENDIF
+  CASE(k_r)
+    IF (r_memsize == 0) THEN
+      ALLOCATE(r_mem(memslabs),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) memslabs
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate db-memory', &
+ &       'r_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      r_memsize =  memslabs
+    ELSE
+      ALLOCATE(tmp_real(r_memsize),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) r_memsize
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate tmp_real', &
+ &       'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      tmp_real(1:r_memsize) = r_mem(1:r_memsize)
+      DEALLOCATE(r_mem)
+      ALLOCATE(r_mem(r_memsize+MAX(memslabs,len_wanted)),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) r_memsize+MAX(memslabs,len_wanted)
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to re-allocate db-memory', &
+ &       'r_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      r_mem(1:r_memsize) = tmp_real(1:r_memsize)
+      r_memsize = r_memsize+MAX(memslabs,len_wanted)
+      DEALLOCATE(tmp_real)
+    ENDIF
+  CASE(k_c)
+    IF (c_memsize == 0) THEN
+      ALLOCATE(c_mem(memslabs),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) memslabs
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate db-memory', &
+ &       'c_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      c_memsize = memslabs
+    ELSE
+      ALLOCATE(tmp_char(c_memsize),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) c_memsize
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate tmp_char', &
+ &       'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      tmp_char(1:c_memsize) = c_mem(1:c_memsize)
+      DEALLOCATE(c_mem)
+      ALLOCATE(c_mem(c_memsize+MAX(memslabs,len_wanted)),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) c_memsize+MAX(memslabs,len_wanted)
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to re-allocate db-memory', &
+ &       'c_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      c_mem(1:c_memsize) = tmp_char(1:c_memsize)
+      c_memsize = c_memsize+MAX(memslabs,len_wanted)
+      DEALLOCATE(tmp_char)
+    ENDIF
+  CASE(k_l)
+    IF (l_memsize == 0) THEN
+      ALLOCATE(l_mem(memslabs),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) memslabs
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate db-memory', &
+ &       'l_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      l_memsize = memslabs
+    ELSE
+      ALLOCATE(tmp_logic(l_memsize),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) l_memsize
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to allocate tmp_logic', &
+ &       'to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      tmp_logic(1:l_memsize) = l_mem(1:l_memsize)
+      DEALLOCATE(l_mem)
+      ALLOCATE(l_mem(l_memsize+MAX(memslabs,len_wanted)),stat=ier)
+      IF (ier /= 0) THEN
+        WRITE (UNIT=c_tmp,FMT=*) l_memsize+MAX(memslabs,len_wanted)
+        CALL ipslerr (3,'getin_allocmem', &
+ &       'Unable to re-allocate db-memory', &
+ &       'l_mem to size '//TRIM(ADJUSTL(c_tmp)),' ')
+      ENDIF
+      l_mem(1:l_memsize) = tmp_logic(1:l_memsize)
+      l_memsize = l_memsize+MAX(memslabs,len_wanted)
+      DEALLOCATE(tmp_logic)
+    ENDIF
+  CASE DEFAULT
+    CALL ipslerr (3,'getin_allocmem','Unknown type of data',' ',' ')
+  END SELECT
+!----------------------------
+END SUBROUTINE getin_allocmem
+!-
+!===
+!-
+SUBROUTINE getin_alloctxt ()
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=100),ALLOCATABLE :: tmp_fic(:)
+  CHARACTER(LEN=l_n),ALLOCATABLE :: tmp_tgl(:)
+  INTEGER,ALLOCATABLE :: tmp_int(:)
+!-
+  INTEGER :: ier
+  CHARACTER(LEN=20) :: c_tmp1,c_tmp2
+!---------------------------------------------------------------------
+  IF (i_txtsize == 0) THEN
+!---
+!-- Nothing exists in memory arrays and it is easy to do.
+!---
+    WRITE (UNIT=c_tmp1,FMT=*) i_txtslab
+    ALLOCATE(fichier(i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate fichier', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+!---
+    ALLOCATE(targetlist(i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate targetlist', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+!---
+    ALLOCATE(fromfile(i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate fromfile', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+!---
+    ALLOCATE(compline(i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate compline', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+!---
+    nb_lines = 0
+    i_txtsize = i_txtslab
+  ELSE
+!---
+!-- There is something already in the memory,
+!-- we need to transfer and reallocate.
+!---
+    WRITE (UNIT=c_tmp1,FMT=*) i_txtsize
+    WRITE (UNIT=c_tmp2,FMT=*) i_txtsize+i_txtslab
+    ALLOCATE(tmp_fic(i_txtsize),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate tmp_fic', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+    tmp_fic(1:i_txtsize) = fichier(1:i_txtsize)
+    DEALLOCATE(fichier)
+    ALLOCATE(fichier(i_txtsize+i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate fichier', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp2)),' ')
+    ENDIF
+    fichier(1:i_txtsize) = tmp_fic(1:i_txtsize)
+    DEALLOCATE(tmp_fic)
+!---
+    ALLOCATE(tmp_tgl(i_txtsize),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate tmp_tgl', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+    tmp_tgl(1:i_txtsize) = targetlist(1:i_txtsize)
+    DEALLOCATE(targetlist)
+    ALLOCATE(targetlist(i_txtsize+i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate targetlist', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp2)),' ')
+    ENDIF
+    targetlist(1:i_txtsize) = tmp_tgl(1:i_txtsize)
+    DEALLOCATE(tmp_tgl)
+!---
+    ALLOCATE(tmp_int(i_txtsize),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate tmp_int', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp1)),' ')
+    ENDIF
+    tmp_int(1:i_txtsize) = fromfile(1:i_txtsize)
+    DEALLOCATE(fromfile)
+    ALLOCATE(fromfile(i_txtsize+i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate fromfile', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp2)),' ')
+    ENDIF
+    fromfile(1:i_txtsize) = tmp_int(1:i_txtsize)
+!---
+    tmp_int(1:i_txtsize) = compline(1:i_txtsize)
+    DEALLOCATE(compline)
+    ALLOCATE(compline(i_txtsize+i_txtslab),stat=ier)
+    IF (ier /= 0) THEN
+      CALL ipslerr (3,'getin_alloctxt', &
+ &     'Can not allocate compline', &
+ &     'to size '//TRIM(ADJUSTL(c_tmp2)),' ')
+    ENDIF
+    compline(1:i_txtsize) = tmp_int(1:i_txtsize)
+    DEALLOCATE(tmp_int)
+!---
+    i_txtsize = i_txtsize+i_txtslab
+  ENDIF
+!----------------------------
+END SUBROUTINE getin_alloctxt
+!-
+!===
+!-
+SUBROUTINE getin_dump (fileprefix)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(*),OPTIONAL :: fileprefix
+!-
+  CHARACTER(LEN=80) :: usedfileprefix
+  INTEGER :: ikey,if,iff,iv
+  CHARACTER(LEN=20) :: c_tmp
+  CHARACTER(LEN=100) :: tmp_str,used_filename
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (PRESENT(fileprefix)) THEN
+    usedfileprefix = fileprefix(1:MIN(LEN_TRIM(fileprefix),80))
+  ELSE
+    usedfileprefix = "used"
+  ENDIF
+!-
+  DO if=1,nbfiles
+!---
+    used_filename = TRIM(usedfileprefix)//'_'//TRIM(filelist(if))
+    IF (check) THEN
+      WRITE(*,*) &
+ &      'GETIN_DUMP : opens file : ',TRIM(used_filename),' if = ',if
+      WRITE(*,*) 'GETIN_DUMP : NUMBER OF KEYS : ',nb_keys
+    ENDIF
+    OPEN (UNIT=22,FILE=used_filename)
+!---
+!-- If this is the first file we need to add the list
+!-- of file which belong to it
+    IF ( (if == 1).AND.(nbfiles > 1) ) THEN
+      WRITE(22,*) '# '
+      WRITE(22,*) '# This file is linked to the following files :'
+      WRITE(22,*) '# '
+      DO iff=2,nbfiles
+        WRITE(22,*) 'INCLUDEDEF = ',TRIM(filelist(iff))
+      ENDDO
+      WRITE(22,*) '# '
+    ENDIF
+!---
+    DO ikey=1,nb_keys
+!-----
+!---- Is this key from this file ?
+      IF (key_tab(ikey)%keyfromfile == if) THEN
+!-------
+!------ Write some comments
+        WRITE(22,*) '#'
+        SELECT CASE (key_tab(ikey)%keystatus)
+        CASE(1)
+          WRITE(22,*) '# Values of ', &
+ &          TRIM(key_tab(ikey)%keystr),' comes from the run.def.'
+        CASE(2)
+          WRITE(22,*) '# Values of ', &
+ &          TRIM(key_tab(ikey)%keystr),' are all defaults.'
+        CASE(3)
+          WRITE(22,*) '# Values of ', &
+ &          TRIM(key_tab(ikey)%keystr), &
+ &          ' are a mix of run.def and defaults.'
+        CASE DEFAULT
+          WRITE(22,*) '# Dont know from where the value of ', &
+ &          TRIM(key_tab(ikey)%keystr),' comes.'
+        END SELECT
+        WRITE(22,*) '#'
+!-------
+!------ Write the values
+        SELECT CASE (key_tab(ikey)%keytype)
+        CASE(k_i)
+          IF (key_tab(ikey)%keymemlen == 1) THEN
+            IF (key_tab(ikey)%keycompress < 0) THEN
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr), &
+ &              ' = ',i_mem(key_tab(ikey)%keymemstart)
+            ELSE
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr), &
+ &              ' = ',key_tab(ikey)%keycompress, &
+ &              ' * ',i_mem(key_tab(ikey)%keymemstart)
+            ENDIF
+          ELSE
+            DO iv=0,key_tab(ikey)%keymemlen-1
+              WRITE(UNIT=c_tmp,FMT=c_i_fmt) iv+1
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr), &
+ &              '__',TRIM(ADJUSTL(c_tmp)), &
+ &              ' = ',i_mem(key_tab(ikey)%keymemstart+iv)
+            ENDDO
+          ENDIF
+        CASE(k_r)
+          IF (key_tab(ikey)%keymemlen == 1) THEN
+            IF (key_tab(ikey)%keycompress < 0) THEN
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr), &
+ &              ' = ',r_mem(key_tab(ikey)%keymemstart)
+            ELSE
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr), &
+ &              ' = ',key_tab(ikey)%keycompress, &
+                   & ' * ',r_mem(key_tab(ikey)%keymemstart)
+            ENDIF
+          ELSE
+            DO iv=0,key_tab(ikey)%keymemlen-1
+              WRITE(UNIT=c_tmp,FMT=c_i_fmt) iv+1
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr),'__',TRIM(ADJUSTL(c_tmp)), &
+ &              ' = ',r_mem(key_tab(ikey)%keymemstart+iv)
+            ENDDO
+          ENDIF
+        CASE(k_c)
+          IF (key_tab(ikey)%keymemlen == 1) THEN
+            tmp_str = c_mem(key_tab(ikey)%keymemstart)
+            WRITE(22,*) TRIM(key_tab(ikey)%keystr), &
+ &              ' = ',TRIM(tmp_str)
+          ELSE
+            DO iv=0,key_tab(ikey)%keymemlen-1
+              WRITE(UNIT=c_tmp,FMT=c_i_fmt) iv+1
+              tmp_str = c_mem(key_tab(ikey)%keymemstart+iv)
+              WRITE(22,*) &
+ &              TRIM(key_tab(ikey)%keystr), &
+ &              '__',TRIM(ADJUSTL(c_tmp)), &
+ &              ' = ',TRIM(tmp_str)
+            ENDDO
+          ENDIF
+        CASE(k_l)
+          IF (key_tab(ikey)%keymemlen == 1) THEN
+            IF (l_mem(key_tab(ikey)%keymemstart)) THEN
+              WRITE(22,*) TRIM(key_tab(ikey)%keystr),' = TRUE '
+            ELSE
+              WRITE(22,*) TRIM(key_tab(ikey)%keystr),' = FALSE '
+            ENDIF
+          ELSE
+            DO iv=0,key_tab(ikey)%keymemlen-1
+              WRITE(UNIT=c_tmp,FMT=c_i_fmt) iv+1
+              IF (l_mem(key_tab(ikey)%keymemstart+iv)) THEN
+                WRITE(22,*) TRIM(key_tab(ikey)%keystr),'__', &
+ &                          TRIM(ADJUSTL(c_tmp)),' = TRUE '
+              ELSE
+                WRITE(22,*) TRIM(key_tab(ikey)%keystr),'__', &
+ &                          TRIM(ADJUSTL(c_tmp)),' = FALSE '
+              ENDIF
+            ENDDO
+          ENDIF
+        CASE DEFAULT
+          CALL ipslerr (3,'getin_dump', &
+ &         'Unknown type for variable '//TRIM(key_tab(ikey)%keystr), &
+ &         ' ',' ')
+        END SELECT
+      ENDIF
+    ENDDO
+!-
+    CLOSE(UNIT=22)
+!-
+  ENDDO
+!------------------------
+END SUBROUTINE getin_dump
+!===
+SUBROUTINE get_qtyp (k_typ,c_vtyp,i_v,r_v,c_v,l_v)
+!---------------------------------------------------------------------
+!- Returns the type of the argument (mutually exclusive)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(OUT) :: k_typ
+  CHARACTER(LEN=*),INTENT(OUT) :: c_vtyp
+  INTEGER,DIMENSION(:),OPTIONAL          :: i_v
+  REAL,DIMENSION(:),OPTIONAL             :: r_v
+  LOGICAL,DIMENSION(:),OPTIONAL          :: l_v
+  CHARACTER(LEN=*),DIMENSION(:),OPTIONAL :: c_v
+!---------------------------------------------------------------------
+  k_typ = 0
+  IF (COUNT((/PRESENT(i_v),PRESENT(r_v),PRESENT(c_v),PRESENT(l_v)/)) &
+ &    /= 1) THEN
+    CALL ipslerr (3,'get_qtyp', &
+ &   'Invalid number of optional arguments','(/= 1)',' ')
+  ENDIF
+!-
+  IF     (PRESENT(i_v)) THEN
+    k_typ = k_i
+    c_vtyp = 'INTEGER'
+  ELSEIF (PRESENT(r_v)) THEN
+    k_typ = k_r
+    c_vtyp = 'REAL'
+  ELSEIF (PRESENT(c_v)) THEN
+    k_typ = k_c
+    c_vtyp = 'CHARACTER'
+  ELSEIF (PRESENT(l_v)) THEN
+    k_typ = k_l
+    c_vtyp = 'LOGICAL'
+  ENDIF
+!----------------------
+END SUBROUTINE get_qtyp
+!===
+SUBROUTINE get_findkey (i_tab,c_key,pos)
+!---------------------------------------------------------------------
+!- This subroutine looks for a key in a table
+!---------------------------------------------------------------------
+!- INPUT
+!-   i_tab  : 1 -> search in key_tab(1:nb_keys)%keystr
+!-            2 -> search in targetlist(1:nb_lines)
+!-   c_key  : Name of the key we are looking for
+!- OUTPUT
+!-   pos    : -1 if key not found, else value in the table
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(in) :: i_tab
+  CHARACTER(LEN=*),INTENT(in) :: c_key
+  INTEGER,INTENT(out) :: pos
+!-
+  INTEGER :: ikey_max,ikey
+  CHARACTER(LEN=l_n) :: c_q_key
+!---------------------------------------------------------------------
+  pos = -1
+  IF     (i_tab == 1) THEN
+    ikey_max = nb_keys
+  ELSEIF (i_tab == 2) THEN
+    ikey_max = nb_lines
+  ELSE
+    ikey_max = 0
+  ENDIF
+  IF ( ikey_max > 0 ) THEN
+    DO ikey=1,ikey_max
+      IF (i_tab == 1) THEN
+        c_q_key = key_tab(ikey)%keystr
+      ELSE
+        c_q_key = targetlist(ikey)
+      ENDIF
+      IF (TRIM(c_q_key) == TRIM(c_key)) THEN
+        pos = ikey
+        EXIT
+      ENDIF
+    ENDDO
+  ENDIF
+!-------------------------
+END SUBROUTINE get_findkey
+!===
+!------------------
+END MODULE getincom
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/histcom.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/histcom.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/histcom.f90	(revision 329)
@@ -0,0 +1,2573 @@
+MODULE histcom
+!-
+!$Id: histcom.f90 760 2009-10-26 14:10:32Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!-
+  USE netcdf
+!-
+  USE stringop, ONLY : nocomma,cmpblank,findpos,find_str,strlowercase
+  USE mathelp,  ONLY : mathop,moycum,buildop
+  USE fliocom,  ONLY : flio_dom_file,flio_dom_att
+  USE calendar
+  USE errioipsl, ONLY : ipslerr,ipsldbg
+!-
+  IMPLICIT NONE
+!-
+  PRIVATE
+  PUBLIC :: histbeg,histdef,histhori,histvert,histend, &
+ &          histwrite,histclo,histsync,ioconf_modname
+!---------------------------------------------------------------------
+!- Some confusing vocabulary in this code !
+!- =========================================
+!-
+!- A REGULAR grid is a grid which is i,j indexes
+!- and thus it is stored in a 2D matrix.
+!- This is opposed to a IRREGULAR grid which is only in a vector
+!- and where we do not know which neighbors we have.
+!- As a consequence we need the bounds for each grid-cell.
+!-
+!- A RECTILINEAR grid is a special case of a regular grid
+!- in which all longitudes for i constant are equal
+!- and all latitudes for j constant.
+!- In other words we do not need the full 2D matrix
+!- to describe the grid, just two vectors.
+!---------------------------------------------------------------------
+!-
+  INTERFACE histbeg
+    MODULE PROCEDURE histbeg_totreg,histbeg_regular,histbeg_irregular
+  END INTERFACE
+!-
+  INTERFACE histhori
+    MODULE PROCEDURE histhori_regular,histhori_irregular
+  END INTERFACE
+!-
+  INTERFACE histwrite
+!---------------------------------------------------------------------
+!- The "histwrite" routines will give the data to the I/O system.
+!- It will trigger the operations to be performed,
+!- and the writting to the file if needed
+!-
+!- We test for the work to be done at this time here so that at a
+!- later stage we can call different operation and write subroutine
+!- for the REAL and INTEGER interfaces
+!-
+!- INPUT
+!- pfileid  : The ID of the file on which this variable is to be,
+!-            written. The variable should have been defined in
+!-            this file before.
+!- pvarname : The short name of the variable
+!- pitau    : Current timestep
+!- pdata    : The variable, I mean the real data !
+!- nbindex  : The number of indexes provided. If it is equal to
+!-            the size of the full field as provided in histdef
+!-            then nothing is done.
+!- nindex   : The indices used to expand the variable (pdata)
+!-            onto the full field.
+!---------------------------------------------------------------------
+!- histwrite - we have to prepare different type of fields :
+!-             real and integer, 1,2 or 3D
+    MODULE PROCEDURE histwrite_r1d,histwrite_r2d,histwrite_r3d
+  END INTERFACE
+!-
+! Fixed parameter
+!-
+  INTEGER,PARAMETER :: nb_files_max=20,nb_var_max=400, &
+ &                     nb_hax_max=5,nb_zax_max=10,nbopp_max=10
+  REAL,PARAMETER :: missing_val=nf90_fill_real
+  INTEGER,PARAMETER,PUBLIC :: &
+ &  hist_r4=nf90_real4, hist_r8=nf90_real8
+!-
+! Variable derived type
+!-
+TYPE T_D_V
+  INTEGER :: ncvid
+  INTEGER :: nbopp
+  CHARACTER(LEN=20) :: v_name,unit_name
+  CHARACTER(LEN=80) :: title,fullop
+  CHARACTER(LEN=7)  :: topp
+  CHARACTER(LEN=7),DIMENSION(nbopp_max) :: sopps
+  REAL,DIMENSION(nbopp_max) :: scal
+!-External type (for R4/R8)
+  INTEGER :: v_typ
+!-Sizes of the associated grid and zommed area
+  INTEGER,DIMENSION(3) :: scsize,zorig,zsize
+!-Sizes for the data as it goes through the various math operations
+  INTEGER,DIMENSION(3) :: datasz_in = -1
+  INTEGER :: datasz_max = -1
+!-
+  INTEGER :: h_axid,z_axid,t_axid
+!-
+  REAL,DIMENSION(2) :: hist_minmax
+  LOGICAL :: hist_calc_rng=.FALSE.,hist_wrt_rng=.FALSE.
+!-Book keeping of the axes
+  INTEGER :: tdimid,tax_last
+  CHARACTER(LEN=40) :: tax_name
+!-
+  REAL :: freq_opp,freq_wrt
+  INTEGER :: &
+ &  last_opp,last_wrt,last_opp_chk,last_wrt_chk,nb_opp,nb_wrt,point
+!- For future optimization
+!#  REAL,ALLOCATABLE,DIMENSION(:) :: V_1_D
+!#  REAL,ALLOCATABLE,DIMENSION(:,:) :: V_2_D
+!#  REAL,ALLOCATABLE,DIMENSION(:,:,:) :: V_3_D
+END TYPE T_D_V
+!-
+! File derived type
+!-
+TYPE :: T_D_F
+!-NETCDF IDs for file
+  INTEGER :: ncfid
+!-Time variables
+  INTEGER :: itau0=0
+  REAL :: date0,deltat
+!-Counter of elements (variables, time-horizontal-vertical axis
+  INTEGER :: n_var=0,n_tax=0,n_hax=0,n_zax=0
+!-NETCDF dimension IDs for time-longitude-latitude
+  INTEGER :: tid,xid,yid
+!-General definitions in the NETCDF file
+  INTEGER,DIMENSION(2) :: full_size=0,slab_ori,slab_sz
+!-The horizontal axes
+  CHARACTER(LEN=25),DIMENSION(nb_hax_max,2) :: hax_name
+!-The vertical axes
+  INTEGER,DIMENSION(nb_zax_max) :: zax_size,zax_ids
+  CHARACTER(LEN=20),DIMENSION(nb_zax_max) :: zax_name
+!-
+  LOGICAL :: regular=.TRUE.
+!-DOMAIN ID
+  INTEGER :: dom_id_svg=-1
+!-
+  TYPE(T_D_V),DIMENSION(nb_var_max) :: W_V
+END TYPE T_D_F
+!-
+TYPE(T_D_F),DIMENSION(nb_files_max),SAVE :: W_F
+!-
+! Counter of elements
+!-
+  INTEGER,SAVE :: nb_files=0
+!-
+! Book keeping for the buffers
+!-
+  INTEGER,SAVE :: buff_pos=0
+  REAL,ALLOCATABLE,DIMENSION(:),SAVE :: buffer
+!-
+! A list of functions which require special action
+! (Needs to be updated when functions are added
+!  but they are well located here)
+!-
+  CHARACTER(LEN=30),SAVE :: fuchnbout = 'scatter, fill'
+!- Some configurable variables with locks
+  CHARACTER(LEN=80),SAVE :: model_name='An IPSL model'
+  LOGICAL,SAVE :: lock_modname=.FALSE.
+!-
+!===
+CONTAINS
+!===
+!-
+SUBROUTINE histbeg_totreg                 &
+ & (pfilename,pim,plon,pjm,plat,          &
+ &  par_orix,par_szx,par_oriy,par_szy,    &
+ &  pitau0,pdate0,pdeltat,phoriid,pfileid,domain_id,nb_bits)
+!---------------------------------------------------------------------
+!- This is just an interface for histbeg_regular in case when
+!- the user provides plon and plat as vectors.
+!- Obviously this can only be used for very regular grids.
+!-
+!- INPUT
+!-
+!- pfilename : Name of the netcdf file to be created
+!- pim       : Size of arrays in longitude direction
+!- plon      : Coordinates of points in longitude
+!- pjm       : Size of arrays in latitude direction
+!- plat      : Coordinates of points in latitude
+!-
+!- The next 4 arguments allow to define a horizontal zoom
+!- for this file. It is assumed that all variables to come
+!- have the same index space. This can not be assumed for
+!- the z axis and thus we define the zoom in histdef.
+!-
+!- par_orix  : Origin of the slab of data within the X axis (pim)
+!- par_szx   : Size of the slab of data in X
+!- par_oriy  : Origin of the slab of data within the Y axis (pjm)
+!- par_szy   : Size of the slab of data in Y
+!-
+!- pitau0    : time step at which the history tape starts
+!- pdate0    : The Julian date at which the itau was equal to 0
+!- pdeltat   : Time step, in seconds, of the counter itau
+!-             used in histwrite for instance
+!-
+!- OUTPUT
+!-
+!- phoriid   : ID of the horizontal grid
+!- pfileid   : ID of the netcdf file
+!-
+!- Optional INPUT arguments
+!-
+!- domain_id       : Domain identifier
+!-
+!- TO DO
+!-
+!- This package should be written in f90
+!- and use the following features :
+!-    - structures for the meta-data of the files and variables
+!-    - memory allocation as needed
+!-    - Pointers
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: pfilename
+  INTEGER,INTENT(IN) :: pim,pjm
+  REAL,DIMENSION(pim),INTENT(IN) :: plon
+  REAL,DIMENSION(pjm),INTENT(IN) :: plat
+  INTEGER,INTENT(IN):: par_orix,par_szx,par_oriy,par_szy
+  INTEGER,INTENT(IN) :: pitau0
+  REAL,INTENT(IN) :: pdate0,pdeltat
+  INTEGER,INTENT(OUT) :: pfileid,phoriid
+  INTEGER,INTENT(IN),OPTIONAL :: domain_id,nb_bits
+!-
+  REAL,ALLOCATABLE,DIMENSION(:,:) :: lon_tmp,lat_tmp
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_totreg"
+!-
+  ALLOCATE(lon_tmp(pim,pjm),lat_tmp(pim,pjm))
+!-
+  lon_tmp(:,:) = SPREAD(plon(:),2,pjm)
+  lat_tmp(:,:) = SPREAD(plat(:),1,pim)
+!-
+  CALL histbeg_regular &
+ &  (pfilename,pim,lon_tmp,pjm,lat_tmp, &
+ &   par_orix,par_szx,par_oriy,par_szy, &
+ &   pitau0,pdate0,pdeltat,phoriid,pfileid, &
+ &   .TRUE.,domain_id,nb_bits)
+!-
+  DEALLOCATE(lon_tmp,lat_tmp)
+!----------------------------
+END SUBROUTINE histbeg_totreg
+!===
+SUBROUTINE histbeg_regular &
+ & (pfilename,pim,plon,pjm,plat,           &
+ &  par_orix,par_szx,par_oriy,par_szy,     &
+ &  pitau0,pdate0,pdeltat,phoriid,pfileid, &
+ &  opt_rectilinear,domain_id,nb_bits)
+!---------------------------------------------------------------------
+!- This subroutine initializes a netcdf file and returns the ID.
+!- It will set up the geographical space on which the data will be
+!- stored and offers the possibility of seting a zoom.
+!- It also gets the global parameters into the I/O subsystem.
+!-
+!- INPUT
+!-
+!- pfilename : Name of the netcdf file to be created
+!- pim       : Size of arrays in longitude direction
+!- plon      : Coordinates of points in longitude
+!- pjm       : Size of arrays in latitude direction
+!- plat      : Coordinates of points in latitude
+!-
+!- The next 4 arguments allow to define a horizontal zoom
+!- for this file. It is assumed that all variables to come
+!- have the same index space. This can not be assumed for
+!- the z axis and thus we define the zoom in histdef.
+!-
+!- par_orix  : Origin of the slab of data within the X axis (pim)
+!- par_szx   : Size of the slab of data in X
+!- par_oriy  : Origin of the slab of data within the Y axis (pjm)
+!- par_szy   : Size of the slab of data in Y
+!-
+!- pitau0    : time step at which the history tape starts
+!- pdate0    : The Julian date at which the itau was equal to 0
+!- pdeltat   : Time step, in seconds, of the counter itau
+!-             used in histwrite for instance
+!-
+!- OUTPUT
+!-
+!- phoriid   : ID of the horizontal grid
+!- pfileid   : ID of the netcdf file
+!-
+!- Optional INPUT arguments
+!-
+!- opt_rectilinear : If true we know the grid is rectilinear
+!- domain_id       : Domain identifier
+!-
+!- TO DO
+!-
+!- This package should be written in F90 and use the following
+!- feature :
+!-   - structures for the meta-data of the files and variables
+!-   - memory allocation as needed
+!-   - Pointers
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: pfilename
+  INTEGER,INTENT(IN) :: pim,pjm
+  REAL,DIMENSION(pim,pjm),INTENT(IN) :: plon,plat
+  INTEGER,INTENT(IN):: par_orix,par_szx,par_oriy,par_szy
+  INTEGER,INTENT(IN) :: pitau0
+  REAL,INTENT(IN) :: pdate0,pdeltat
+  INTEGER,INTENT(OUT) :: pfileid,phoriid
+  LOGICAL,INTENT(IN),OPTIONAL :: opt_rectilinear
+  INTEGER,INTENT(IN),OPTIONAL :: domain_id,nb_bits
+!-
+  INTEGER :: nfid,iret,m_c
+  CHARACTER(LEN=120) :: file
+  CHARACTER(LEN=30) :: timenow
+  LOGICAL :: rectilinear
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_regular 0.0"
+!-
+  nb_files = nb_files+1
+  IF (nb_files > nb_files_max) THEN
+    CALL ipslerr (3,"histbeg", &
+   &  'Table of files too small. You should increase nb_files_max', &
+   &  'in histcom.f90 in order to accomodate all these files',' ')
+  ENDIF
+  pfileid  = nb_files
+!-
+! 1.0 Transfering into the common for future use
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_regular 1.0"
+!-
+  W_F(pfileid)%itau0  = pitau0
+  W_F(pfileid)%date0  = pdate0
+  W_F(pfileid)%deltat = pdeltat
+!-
+  IF (PRESENT(opt_rectilinear)) THEN
+    rectilinear = opt_rectilinear
+  ELSE
+    rectilinear = .FALSE.
+  ENDIF
+!-
+! 2.0 Initializes all variables for this file
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_regular 2.0"
+!-
+  W_F(pfileid)%n_var = 0
+  W_F(pfileid)%n_tax = 0
+  W_F(pfileid)%n_hax = 0
+  W_F(pfileid)%n_zax = 0
+!-
+  W_F(pfileid)%slab_ori(1:2) = (/ par_orix,par_oriy /)
+  W_F(pfileid)%slab_sz(1:2)  = (/ par_szx, par_szy  /)
+!-
+! 3.0 Opening netcdf file and defining dimensions
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_regular 3.0"
+!-
+! Add DOMAIN number and ".nc" suffix in file name if needed
+!-
+  file = pfilename
+  CALL flio_dom_file (file,domain_id)
+!-
+! Check the mode
+  IF (PRESENT(nb_bits)) THEN
+    SELECT CASE (nb_bits)
+    CASE(32)
+      m_c = NF90_CLOBBER
+    CASE(64)
+      m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
+    CASE DEFAULT
+      CALL ipslerr (3,"histbeg", &
+ &      'Invalid argument nb_bits for file :',TRIM(file), &
+ &      'Supported values are 32 or 64')
+    END SELECT
+  ELSE
+    m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
+  ENDIF
+!-
+! Create file
+  iret = NF90_CREATE (file,m_c,nfid)
+!-
+  IF (rectilinear) THEN
+    iret = NF90_DEF_DIM (nfid,'lon',par_szx,W_F(pfileid)%xid)
+    iret = NF90_DEF_DIM (nfid,'lat',par_szy,W_F(pfileid)%yid)
+  ELSE
+    iret = NF90_DEF_DIM (nfid,'x',par_szx,W_F(pfileid)%xid)
+    iret = NF90_DEF_DIM (nfid,'y',par_szy,W_F(pfileid)%yid)
+  ENDIF
+!-
+! 4.0 Declaring the geographical coordinates and other attributes
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_regular 4.0"
+!-
+! 4.3 Global attributes
+!-
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'Conventions','CF-1.1')
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'file_name',TRIM(file))
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'production',TRIM(model_name))
+  lock_modname = .TRUE.
+  CALL ioget_timestamp (timenow)
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'TimeStamp',TRIM(timenow))
+!-
+! 5.0 Saving some important information on this file in the common
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_regular 5.0"
+!-
+  IF (PRESENT(domain_id)) THEN
+    W_F(pfileid)%dom_id_svg = domain_id
+  ENDIF
+  W_F(pfileid)%ncfid = nfid
+  W_F(pfileid)%full_size(1:2) = (/ pim,pjm /)
+!-
+! 6.0 storing the geographical coordinates
+!-
+  W_F(pfileid)%regular=.TRUE.
+!-
+  CALL histhori_regular (pfileid,pim,plon,pjm,plat, &
+ &  ' ','Default grid',phoriid,rectilinear)
+!-----------------------------
+END SUBROUTINE histbeg_regular
+!===
+SUBROUTINE histbeg_irregular &
+ &  (pfilename,pim,plon,plon_bounds,plat,plat_bounds,   &
+ &   pitau0,pdate0,pdeltat,phoriid,pfileid,domain_id,nb_bits)
+!---------------------------------------------------------------------
+!- This subroutine initializes a netcdf file and returns the ID.
+!- This version is for totaly irregular grids. In this case all
+!- all the data comes in as vectors and for the grid we have
+!- the coordinates of the 4 corners.
+!- It also gets the global parameters into the I/O subsystem.
+!-
+!- INPUT
+!-
+!- pfilename   : Name of the netcdf file to be created
+!- pim         : Size of arrays in longitude direction
+!- plon        : Coordinates of points in longitude
+!- plon_bounds : The 2 corners of the grid in longitude
+!- plat        : Coordinates of points in latitude
+!- plat_bounds : The 2 corners of the grid in latitude
+!-
+!- pitau0    : time step at which the history tape starts
+!- pdate0    : The Julian date at which the itau was equal to 0
+!- pdeltat   : Time step, in seconds, of the counter itau
+!-             used in histwrite for instance
+!-
+!- OUTPUT
+!-
+!- phoriid   : ID of the horizontal grid
+!- pfileid   : ID of the netcdf file
+!-
+!- Optional INPUT arguments
+!-
+!- domain_id       : Domain identifier
+!-
+!- TO DO
+!-
+!- This package should be written in F90 and use the following
+!- feature :
+!-   - structures for the meta-data of the files and variables
+!-   - memory allocation as needed
+!-   - Pointers
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: pfilename
+  INTEGER,INTENT(IN) :: pim
+  REAL,DIMENSION(pim),INTENT(IN) :: plon,plat
+  REAL,DIMENSION(:,:),INTENT(IN) :: plon_bounds,plat_bounds
+  INTEGER,INTENT(IN) :: pitau0
+  REAL,INTENT(IN) :: pdate0,pdeltat
+  INTEGER,INTENT(OUT) :: pfileid,phoriid
+  INTEGER,INTENT(IN),OPTIONAL :: domain_id,nb_bits
+!-
+  INTEGER :: nfid,iret,m_c
+  CHARACTER(LEN=120) :: file
+  CHARACTER(LEN=30) :: timenow
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_irregular 0.0"
+!-
+  nb_files = nb_files+1
+  IF (nb_files > nb_files_max) THEN
+    CALL ipslerr (3,"histbeg", &
+ &    'Table of files too small. You should increase nb_files_max', &
+ &    'in histcom.f90 in order to accomodate all these files',' ')
+  ENDIF
+  pfileid  = nb_files
+!-
+! 1.0 Transfering into the common for future use
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_irregular 1.0"
+!-
+  W_F(pfileid)%itau0  = pitau0
+  W_F(pfileid)%date0  = pdate0
+  W_F(pfileid)%deltat = pdeltat
+!-
+! 2.0 Initializes all variables for this file
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_irregular 2.0"
+!-
+  W_F(pfileid)%n_var = 0
+  W_F(pfileid)%n_tax = 0
+  W_F(pfileid)%n_hax = 0
+  W_F(pfileid)%n_zax = 0
+!-
+  W_F(pfileid)%slab_ori(1:2) = (/ 1,1 /)
+  W_F(pfileid)%slab_sz(1:2)  = (/ pim,1 /)
+!-
+! 3.0 Opening netcdf file and defining dimensions
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_irregular 3.0"
+!-
+! Add DOMAIN number and ".nc" suffix in file name if needed
+!-
+  file  = pfilename
+  CALL flio_dom_file (file,domain_id)
+!-
+! Check the mode
+  IF (PRESENT(nb_bits)) THEN
+    SELECT CASE (nb_bits)
+    CASE(32)
+      m_c = NF90_CLOBBER
+    CASE(64)
+      m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
+    CASE DEFAULT
+      CALL ipslerr (3,"histbeg", &
+ &      'Invalid argument nb_bits for file :',TRIM(file), &
+ &      'Supported values are 32 or 64')
+    END SELECT
+  ELSE
+    m_c = IOR(NF90_CLOBBER,NF90_64BIT_OFFSET)
+  ENDIF
+!-
+! Create file
+  iret = NF90_CREATE (file,m_c,nfid)
+!-
+  iret = NF90_DEF_DIM (nfid,'x',pim,W_F(pfileid)%xid)
+  W_F(pfileid)%yid = 0
+!-
+! 4.0 Declaring the geographical coordinates and other attributes
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_irregular 4.0"
+!-
+! 4.3 Global attributes
+!-
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'Conventions','CF-1.1')
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'file_name',TRIM(file))
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'production',TRIM(model_name))
+  lock_modname = .TRUE.
+  CALL ioget_timestamp (timenow)
+  iret = NF90_PUT_ATT (nfid,NF90_GLOBAL,'TimeStamp',TRIM(timenow))
+!-
+! 5.0 Saving some important information on this file in the common
+!-
+  IF (l_dbg) WRITE(*,*) "histbeg_irregular 5.0"
+!-
+  IF (PRESENT(domain_id)) THEN
+    W_F(pfileid)%dom_id_svg = domain_id
+  ENDIF
+  W_F(pfileid)%ncfid = nfid
+  W_F(pfileid)%full_size(1:2) = (/ pim,1 /)
+!-
+! 6.0 storing the geographical coordinates
+!-
+  W_F(pfileid)%regular=.FALSE.
+!-
+  CALL histhori_irregular &
+ &  (pfileid,pim,plon,plon_bounds,plat,plat_bounds, &
+ &   ' ','Default grid',phoriid)
+!-------------------------------
+END SUBROUTINE histbeg_irregular
+!===
+SUBROUTINE histhori_regular &
+ &  (pfileid,pim,plon,pjm,plat,phname,phtitle,phid,opt_rectilinear)
+!---------------------------------------------------------------------
+!- This subroutine is made to declare a new horizontale grid.
+!- It has to have the same number of points as
+!- the original and thus in this routine we will only
+!- add two variable (longitude and latitude).
+!- Any variable in the file can thus point to this pair
+!- through an attribute. This routine is very usefull
+!- to allow staggered grids.
+!-
+!- INPUT
+!-
+!- pfileid : The id of the file to which the grid should be added
+!- pim     : Size in the longitude direction
+!- plon    : The longitudes
+!- pjm     : Size in the latitude direction
+!- plat    : The latitudes
+!- phname  : The name of grid
+!- phtitle : The title of the grid
+!-
+!- OUTPUT
+!-
+!- phid    : Id of the created grid
+!-
+!- OPTIONAL
+!-
+!- opt_rectilinear : If true we know the grid is rectilinear.
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pim,pjm
+  REAL,INTENT(IN),DIMENSION(pim,pjm) :: plon,plat
+  CHARACTER(LEN=*),INTENT(IN) :: phname,phtitle
+  INTEGER,INTENT(OUT) :: phid
+  LOGICAL,INTENT(IN),OPTIONAL :: opt_rectilinear
+!-
+  CHARACTER(LEN=25) :: lon_name,lat_name
+  CHARACTER(LEN=80) :: tmp_title,tmp_name
+  INTEGER :: ndim
+  INTEGER,DIMENSION(2) :: dims
+  INTEGER :: nlonid,nlatid
+  INTEGER :: orix,oriy,par_szx,par_szy
+  INTEGER :: iret,nfid
+  LOGICAL :: rectilinear
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Check that all fits in the buffers
+!-
+  IF (    (pim /= W_F(pfileid)%full_size(1)) &
+ &    .OR.(pjm /= W_F(pfileid)%full_size(2)) ) THEN
+    CALL ipslerr (3,"histhori", &
+ &   'The new horizontal grid does not have the same size', &
+ &   'as the one provided to histbeg. This is not yet ', &
+ &   'possible in the hist package.')
+  ENDIF
+!-
+  IF (PRESENT(opt_rectilinear)) THEN
+    rectilinear = opt_rectilinear
+  ELSE
+    rectilinear = .FALSE.
+  ENDIF
+!-
+! 1.1 Create all the variables needed
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_regular 1.0"
+!-
+  nfid = W_F(pfileid)%ncfid
+!-
+  ndim = 2
+  dims(1:2) = (/ W_F(pfileid)%xid,W_F(pfileid)%yid /)
+!-
+  tmp_name = phname
+  IF (rectilinear) THEN
+    IF (W_F(pfileid)%n_hax == 0) THEN
+      lon_name = 'lon'
+      lat_name = 'lat'
+    ELSE
+      lon_name = 'lon_'//TRIM(tmp_name)
+      lat_name = 'lat_'//TRIM(tmp_name)
+    ENDIF
+  ELSE
+    IF (W_F(pfileid)%n_hax == 0) THEN
+      lon_name = 'nav_lon'
+      lat_name = 'nav_lat'
+    ELSE
+      lon_name = 'nav_lon_'//TRIM(tmp_name)
+      lat_name = 'nav_lat_'//TRIM(tmp_name)
+    ENDIF
+  ENDIF
+!-
+! 1.2 Save the informations
+!-
+  phid = W_F(pfileid)%n_hax+1
+  W_F(pfileid)%n_hax = phid
+  W_F(pfileid)%hax_name(phid,1:2) = (/ lon_name,lat_name /)
+  tmp_title = phtitle
+!-
+! 2.0 Longitude
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_regular 2.0"
+!-
+  IF (rectilinear) THEN
+    ndim = 1
+    dims(1:1) = (/ W_F(pfileid)%xid /)
+  ENDIF
+  iret = NF90_DEF_VAR (nfid,lon_name,NF90_FLOAT,dims(1:ndim),nlonid)
+  IF (rectilinear) THEN
+    iret = NF90_PUT_ATT (nfid,nlonid,'axis',"X")
+  ENDIF
+  iret = NF90_PUT_ATT (nfid,nlonid,'standard_name',"longitude")
+  iret = NF90_PUT_ATT (nfid,nlonid,'units',"degrees_east")
+  iret = NF90_PUT_ATT (nfid,nlonid,'valid_min', &
+ &                     REAL(MINVAL(plon),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlonid,'valid_max', &
+ &                     REAL(MAXVAL(plon),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlonid,'long_name',"Longitude")
+  iret = NF90_PUT_ATT (nfid,nlonid,'nav_model',TRIM(tmp_title))
+!-
+! 3.0 Latitude
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_regular 3.0"
+!-
+  IF (rectilinear) THEN
+    ndim = 1
+    dims(1:1) = (/ W_F(pfileid)%yid /)
+  ENDIF
+  iret = NF90_DEF_VAR (nfid,lat_name,NF90_FLOAT,dims(1:ndim),nlatid)
+  IF (rectilinear) THEN
+    iret = NF90_PUT_ATT (nfid,nlatid,'axis',"Y")
+  ENDIF
+  iret = NF90_PUT_ATT (nfid,nlatid,'standard_name',"latitude")
+  iret = NF90_PUT_ATT (nfid,nlatid,'units',"degrees_north")
+  iret = NF90_PUT_ATT (nfid,nlatid,'valid_min', &
+ &                     REAL(MINVAL(plat),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlatid,'valid_max', &
+ &                     REAL(MAXVAL(plat),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlatid,'long_name',"Latitude")
+  iret = NF90_PUT_ATT (nfid,nlatid,'nav_model',TRIM(tmp_title))
+!-
+  iret = NF90_ENDDEF (nfid)
+!-
+! 4.0 storing the geographical coordinates
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_regular 4.0"
+!-
+  orix = W_F(pfileid)%slab_ori(1)
+  oriy = W_F(pfileid)%slab_ori(2)
+  par_szx = W_F(pfileid)%slab_sz(1)
+  par_szy = W_F(pfileid)%slab_sz(2)
+!-
+! Transfer the longitude
+!-
+  IF (rectilinear) THEN
+    iret = NF90_PUT_VAR (nfid,nlonid,plon(orix:orix+par_szx-1,1))
+  ELSE
+    iret = NF90_PUT_VAR (nfid,nlonid, &
+ &           plon(orix:orix+par_szx-1,oriy:oriy+par_szy-1))
+  ENDIF
+!-
+! Transfer the latitude
+!-
+  IF (rectilinear) THEN
+    iret = NF90_PUT_VAR (nfid,nlatid,plat(1,oriy:oriy+par_szy-1))
+  ELSE
+    iret = NF90_PUT_VAR (nfid,nlatid, &
+ &           plat(orix:orix+par_szx-1,oriy:oriy+par_szy-1))
+  ENDIF
+!-
+  iret = NF90_REDEF (nfid)
+!------------------------------
+END SUBROUTINE histhori_regular
+!===
+SUBROUTINE histhori_irregular &
+ &  (pfileid,pim,plon,plon_bounds,plat,plat_bounds, &
+ &   phname,phtitle,phid)
+!---------------------------------------------------------------------
+!- This subroutine is made to declare a new horizontale grid.
+!- It has to have the same number of points as
+!- the original and thus in this routine we will only
+!- add two variable (longitude and latitude).
+!- Any variable in the file can thus point to this pair
+!- through an attribute. This routine is very usefull
+!- to allow staggered grids.
+!-
+!- INPUT
+!-
+!- pfileid     : The id of the file to which the grid should be added
+!- pim         : Size in the longitude direction
+!- plon        : The longitudes
+!- plon_bounds : The boundaries of the grid in longitude
+!- plat        : The latitudes
+!- plat_bounds : Boundaries of the grid in latitude
+!- phname      : The name of grid
+!- phtitle     : The title of the grid
+!-
+!- OUTPUT
+!-
+!- phid    : Id of the created grid
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pim
+  REAL,DIMENSION(pim),INTENT(IN) :: plon,plat
+  REAL,DIMENSION(:,:),INTENT(IN) :: plon_bounds,plat_bounds
+  CHARACTER(LEN=*),INTENT(IN) :: phname,phtitle
+  INTEGER,INTENT(OUT) :: phid
+!-
+  CHARACTER(LEN=25) :: lon_name,lat_name
+  CHARACTER(LEN=30) :: lonbound_name,latbound_name
+  CHARACTER(LEN=80) :: tmp_title,tmp_name,longname
+  INTEGER :: ndim,dims(2)
+  INTEGER :: ndimb,dimsb(2)
+  INTEGER :: nbbounds
+  INTEGER :: nlonid,nlatid,nlonidb,nlatidb
+  INTEGER :: iret,nfid,twoid
+  LOGICAL :: transp = .FALSE.
+  REAL,ALLOCATABLE,DIMENSION(:,:) :: bounds_trans
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Check that all fits in the buffers
+!-
+  IF (    (pim /= W_F(pfileid)%full_size(1)) &
+ &    .OR.(W_F(pfileid)%full_size(2) /= 1) ) THEN
+    CALL ipslerr (3,"histhori", &
+ &   'The new horizontal grid does not have the same size', &
+ &   'as the one provided to histbeg. This is not yet ', &
+ &   'possible in the hist package.')
+  ENDIF
+!-
+! 1.1 Create all the variables needed
+!-
+  IF (l_dbg) WRITE(*,*) 'histhori_irregular 1.0'
+!-
+  nfid = W_F(pfileid)%ncfid
+!-
+  IF     (SIZE(plon_bounds,DIM=1) == pim) THEN
+    nbbounds = SIZE(plon_bounds,DIM=2)
+    transp = .TRUE.
+  ELSEIF (SIZE(plon_bounds,DIM=2) == pim) THEN
+    nbbounds = SIZE(plon_bounds,DIM=1)
+    transp = .FALSE.
+  ELSE
+    CALL ipslerr (3,"histhori", &
+   &  'The boundary variable does not have any axis corresponding', &
+   &  'to the size of the longitude or latitude variable', &
+   &  '.')
+  ENDIF
+!-
+  ALLOCATE(bounds_trans(nbbounds,pim))
+!-
+  iret = NF90_DEF_DIM (nfid,'nbnd',nbbounds,twoid)
+  ndim = 1
+  dims(1) = W_F(pfileid)%xid
+  ndimb = 2
+  dimsb(1:2) = (/ twoid,W_F(pfileid)%xid /)
+!-
+  tmp_name = phname
+  IF (W_F(pfileid)%n_hax == 0) THEN
+    lon_name = 'nav_lon'
+    lat_name = 'nav_lat'
+  ELSE
+    lon_name = 'nav_lon_'//TRIM(tmp_name)
+    lat_name = 'nav_lat_'//TRIM(tmp_name)
+  ENDIF
+  lonbound_name = TRIM(lon_name)//'_bounds'
+  latbound_name = TRIM(lat_name)//'_bounds'
+!-
+! 1.2 Save the informations
+!-
+  phid = W_F(pfileid)%n_hax+1
+  W_F(pfileid)%n_hax = phid
+  W_F(pfileid)%hax_name(phid,1:2) = (/ lon_name,lat_name /)
+  tmp_title = phtitle
+!-
+! 2.0 Longitude
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_irregular 2.0"
+!-
+  iret = NF90_DEF_VAR (nfid,lon_name,NF90_FLOAT,dims(1:ndim),nlonid)
+  iret = NF90_PUT_ATT (nfid,nlonid,'standard_name',"longitude")
+  iret = NF90_PUT_ATT (nfid,nlonid,'units',"degrees_east")
+  iret = NF90_PUT_ATT (nfid,nlonid,'valid_min', &
+ &                     REAL(MINVAL(plon),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlonid,'valid_max', &
+ &                     REAL(MAXVAL(plon),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlonid,'long_name',"Longitude")
+  iret = NF90_PUT_ATT (nfid,nlonid,'nav_model',TRIM(tmp_title))
+!-
+! 2.1 Longitude bounds
+!-
+  iret = NF90_PUT_ATT (nfid,nlonid,'bounds',TRIM(lonbound_name))
+  iret = NF90_DEF_VAR (nfid,lonbound_name,NF90_FLOAT, &
+ &                     dimsb(1:ndimb),nlonidb)
+  longname = 'Boundaries for coordinate variable '//TRIM(lon_name)
+  iret = NF90_PUT_ATT (nfid,nlonidb,'long_name',TRIM(longname))
+!-
+! 3.0 Latitude
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_irregular 3.0"
+!-
+  iret = NF90_DEF_VAR (nfid,lat_name,NF90_FLOAT,dims(1:ndim),nlatid)
+  iret = NF90_PUT_ATT (nfid,nlatid,'standard_name',"latitude")
+  iret = NF90_PUT_ATT (nfid,nlatid,'units',"degrees_north")
+  iret = NF90_PUT_ATT (nfid,nlatid,'valid_min', &
+ &                     REAL(MINVAL(plat),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlatid,'valid_max', &
+ &                     REAL(MAXVAL(plat),KIND=4))
+  iret = NF90_PUT_ATT (nfid,nlatid,'long_name',"Latitude")
+  iret = NF90_PUT_ATT (nfid,nlatid,'nav_model',TRIM(tmp_title))
+!-
+! 3.1 Latitude bounds
+!-
+  iret = NF90_PUT_ATT (nfid,nlatid,'bounds',TRIM(latbound_name))
+  iret = NF90_DEF_VAR (nfid,latbound_name,NF90_FLOAT, &
+ &                     dimsb(1:ndimb),nlatidb)
+  longname = 'Boundaries for coordinate variable '//TRIM(lat_name)
+  iret = NF90_PUT_ATT (nfid,nlatidb,'long_name',TRIM(longname))
+!-
+  iret = NF90_ENDDEF (nfid)
+!-
+! 4.0 storing the geographical coordinates
+!-
+  IF (l_dbg) WRITE(*,*) "histhori_irregular 4.0"
+!-
+! 4.1 Write the longitude
+!-
+  iret = NF90_PUT_VAR (nfid,nlonid,plon(1:pim))
+!-
+! 4.2 Write the longitude bounds
+!-
+  IF (transp) THEN
+    bounds_trans = TRANSPOSE(plon_bounds)
+  ELSE
+    bounds_trans = plon_bounds
+  ENDIF
+  iret = NF90_PUT_VAR (nfid,nlonidb,bounds_trans(1:nbbounds,1:pim))
+!-
+! 4.3 Write the latitude
+!-
+  iret = NF90_PUT_VAR (nfid,nlatid,plat(1:pim))
+!-
+! 4.4 Write the latitude bounds
+!-
+  IF (transp) THEN
+    bounds_trans = TRANSPOSE(plat_bounds)
+  ELSE
+    bounds_trans = plat_bounds
+  ENDIF
+  iret = NF90_PUT_VAR (nfid,nlatidb,bounds_trans(1:nbbounds,1:pim))
+!-
+  DEALLOCATE(bounds_trans)
+!-
+  iret = NF90_REDEF (nfid)
+!--------------------------------
+END SUBROUTINE histhori_irregular
+!===
+SUBROUTINE histvert (pfileid,pzaxname,pzaxtitle,pzaxunit, &
+ &                   pzsize,pzvalues,pzaxid,pdirect)
+!---------------------------------------------------------------------
+!- This subroutine defines a vertical axis and returns it s id.
+!- It gives the user the possibility to the user to define many
+!- different vertical axes. For each variable defined with histdef a
+!- vertical axis can be specified with by it s ID.
+!-
+!- INPUT
+!-
+!- pfileid  : ID of the file the variable should be archived in
+!- pzaxname : Name of the vertical axis
+!- pzaxtitle: title of the vertical axis
+!- pzaxunit : Units of the vertical axis (no units if blank string)
+!- pzsize   : size of the vertical axis
+!- pzvalues : Coordinate values of the vetical axis
+!-
+!- pdirect  : is an optional argument which allows to specify the
+!-            the positive direction of the axis : up or down.
+!- OUTPUT
+!-
+!- pzaxid   : Returns the ID of the axis.
+!-            Note that this is not the netCDF ID !
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pzsize
+  CHARACTER(LEN=*),INTENT(IN) :: pzaxname,pzaxunit,pzaxtitle
+  REAL,INTENT(IN) :: pzvalues(pzsize)
+  INTEGER,INTENT(OUT) :: pzaxid
+  CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: pdirect
+!-
+  INTEGER :: pos,iv,zdimid,zaxid_tmp
+  CHARACTER(LEN=70) :: str71
+  CHARACTER(LEN=80) :: str80
+  CHARACTER(LEN=20) :: direction
+  INTEGER :: iret,leng,nfid
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Verifications :
+!    Do we have enough space for an extra axis ?
+!    Is the name already in use ?
+!-
+  IF (l_dbg) WRITE(*,*) "histvert : 1.0 Verifications", &
+ &                      pzaxname,'---',pzaxunit,'---',pzaxtitle
+!-
+! - Direction of axis. Can we get if from the user.
+!   If not we put unknown.
+!-
+  IF (PRESENT(pdirect)) THEN
+    direction = TRIM(pdirect)
+    CALL strlowercase (direction)
+  ELSE
+    direction = 'unknown'
+  ENDIF
+!-
+! Check the consistency of the attribute
+!-
+  IF (     (direction /= 'unknown') &
+ &    .AND.(direction /= 'up')      &
+ &    .AND.(direction /= 'down')   ) THEN
+    direction = 'unknown'
+    str80 = 'The specified axis was : '//TRIM(direction)
+    CALL ipslerr (2,"histvert",&
+   & "The specified direction for the vertical axis is not possible.",&
+   & "it is replaced by : unknown",str80)
+  ENDIF
+!-
+  IF (W_F(pfileid)%n_zax+1 > nb_zax_max) THEN
+    CALL ipslerr (3,"histvert", &
+   &  'Table of vertical axes too small. You should increase ',&
+   &  'nb_zax_max in histcom.f90 in order to accomodate all ', &
+   &  'these variables ')
+  ENDIF
+!-
+  iv = W_F(pfileid)%n_zax
+  IF (iv > 1) THEN
+    CALL find_str (W_F(pfileid)%zax_name(1:iv-1),pzaxname,pos)
+  ELSE
+    pos = 0
+  ENDIF
+!-
+  IF (pos > 0) THEN
+    WRITE(str71,'("Check variable ",A," in file",I3)') &
+ &    TRIM(pzaxname),pfileid
+    CALL ipslerr (3,"histvert", &
+ &    "Vertical axis already exists",TRIM(str71), &
+ &    "Can also be a wrong file ID in another declaration")
+  ENDIF
+!-
+  iv = W_F(pfileid)%n_zax+1
+!-
+! 2.0 Add the information to the file
+!-
+  IF (l_dbg) &
+ &  WRITE(*,*) "histvert : 2.0 Add the information to the file"
+!-
+  nfid = W_F(pfileid)%ncfid
+!-
+  leng = MIN(LEN_TRIM(pzaxname),20)
+  iret = NF90_DEF_DIM (nfid,pzaxname(1:leng),pzsize,zaxid_tmp)
+  iret = NF90_DEF_VAR (nfid,pzaxname(1:leng),NF90_FLOAT, &
+ &                     zaxid_tmp,zdimid)
+  iret = NF90_PUT_ATT (nfid,zdimid,'axis',"Z")
+  iret = NF90_PUT_ATT (nfid,zdimid,'standard_name',"model_level_number")
+  leng = MIN(LEN_TRIM(pzaxunit),20)
+  IF (leng > 0) THEN
+    iret = NF90_PUT_ATT (nfid,zdimid,'units',pzaxunit(1:leng))
+  ENDIF
+  iret = NF90_PUT_ATT (nfid,zdimid,'positive',TRIM(direction))
+  iret = NF90_PUT_ATT (nfid,zdimid,'valid_min', &
+ &                     REAL(MINVAL(pzvalues(1:pzsize)),KIND=4))
+  iret = NF90_PUT_ATT (nfid,zdimid,'valid_max', &
+ &                     REAL(MAXVAL(pzvalues(1:pzsize)),KIND=4))
+  leng = MIN(LEN_TRIM(pzaxname),20)
+  iret = NF90_PUT_ATT (nfid,zdimid,'title',pzaxname(1:leng))
+  leng = MIN(LEN_TRIM(pzaxtitle),80)
+  iret = NF90_PUT_ATT (nfid,zdimid,'long_name',pzaxtitle(1:leng))
+!-
+  iret = NF90_ENDDEF (nfid)
+!-
+  iret = NF90_PUT_VAR (nfid,zdimid,pzvalues(1:pzsize))
+!-
+  iret = NF90_REDEF (nfid)
+!-
+!- 3.0 add the information to the common
+!-
+  IF (l_dbg) &
+  &  WRITE(*,*) "histvert : 3.0 add the information to the common"
+!-
+  W_F(pfileid)%n_zax = iv
+  W_F(pfileid)%zax_size(iv) = pzsize
+  W_F(pfileid)%zax_name(iv) = pzaxname
+  W_F(pfileid)%zax_ids(iv) = zaxid_tmp
+  pzaxid = iv
+!----------------------
+END SUBROUTINE histvert
+!===
+SUBROUTINE histdef (pfileid,pvarname,ptitle,punit, &
+ &                  pxsize,pysize,phoriid,pzsize,  &
+ &                  par_oriz,par_szz,pzid,         &
+ &                  pnbbyt,popp,pfreq_opp,pfreq_wrt,var_range)
+!---------------------------------------------------------------------
+!- With this subroutine each variable to be archived on the history
+!- tape should be declared.
+!-
+!- It gives the user the choise of operation
+!- to be performed on the variables, the frequency of this operation
+!- and finaly the frequency of the archiving.
+!-
+!- INPUT
+!-
+!- pfileid  : ID of the file the variable should be archived in
+!- pvarname : Name of the variable, short and easy to remember
+!- ptitle   : Full name of the variable
+!- punit    : Units of the variable (no units if blank string)
+!-
+!- The next 3 arguments give the size of that data
+!- that will be passed to histwrite. The zoom will be
+!- done there with the horizontal information obtained
+!- in histbeg and the vertical information to follow.
+!-
+!- pxsize   : Size in X direction (size of the data that will be
+!-            given to histwrite)
+!- pysize   : Size in Y direction
+!- phoriid  : ID of the horizontal axis
+!-
+!- The next two arguments give the vertical zoom to use.
+!-
+!- pzsize   : Size in Z direction (If 1 then no axis is declared
+!-            for this variable and pzid is not used)
+!- par_oriz : Off set of the zoom
+!- par_szz  : Size of the zoom
+!-
+!- pzid     : ID of the vertical axis to use. It has to have
+!-            the size of the zoom.
+!- pnbbyt   : External netCDF type (hist_r4/hist_r8)
+!- popp     : Operation to be performed. The following options
+!-            exist today :
+!- inst : keeps instantaneous values for writting
+!- ave  : Computes the average from call between writes
+!- pfreq_opp: Frequency of this operation (in seconds)
+!- pfreq_wrt: Frequency at which the variable should be
+!-            written (in seconds)
+!- var_range: Range of the variable.
+!-            If the minimum is greater than the maximum,
+!-            the values will be calculated.
+!-
+!- VERSION
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pxsize,pysize,pzsize,pzid
+  INTEGER,INTENT(IN) :: par_oriz,par_szz,pnbbyt,phoriid
+  CHARACTER(LEN=*),INTENT(IN) :: pvarname,punit,popp,ptitle
+  REAL,INTENT(IN) :: pfreq_opp,pfreq_wrt
+  REAL,DIMENSION(2),OPTIONAL,INTENT(IN) :: var_range
+!-
+  INTEGER :: iv,i
+  CHARACTER(LEN=70) :: str70,str71,str72
+  CHARACTER(LEN=20) :: tmp_name
+  CHARACTER(LEN=40) :: str40
+  CHARACTER(LEN=10) :: str10
+  CHARACTER(LEN=80) :: tmp_str80
+  CHARACTER(LEN=7) :: tmp_topp,tmp_sopp(nbopp_max)
+  CHARACTER(LEN=120) :: ex_topps
+  REAL :: tmp_scal(nbopp_max),un_an,un_jour,test_fopp,test_fwrt
+  INTEGER :: pos,buff_sz
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  ex_topps = 'ave, inst, t_min, t_max, t_sum, once, never, l_max, l_min'
+!-
+  W_F(pfileid)%n_var = W_F(pfileid)%n_var+1
+  iv = W_F(pfileid)%n_var
+!-
+  IF (iv > nb_var_max) THEN
+    CALL ipslerr (3,"histdef", &
+   &  'Table of variables too small. You should increase nb_var_max',&
+   &  'in histcom.f90 in order to accomodate all these variables', &
+   &  ' ')
+  ENDIF
+!-
+! 1.0 Transfer informations on the variable to the common
+!     and verify that it does not already exist
+!-
+  IF (l_dbg) WRITE(*,*) "histdef : 1.0"
+!-
+  IF (iv > 1) THEN
+    CALL find_str (W_F(pfileid)%W_V(1:iv-1)%v_name,pvarname,pos)
+  ELSE
+    pos = 0
+  ENDIF
+!-
+  IF (pos > 0) THEN
+    str70 = "Variable already exists"
+    WRITE(str71,'("Check variable  ",a," in file",I3)') &
+ &    TRIM(pvarname),pfileid
+    str72 = "Can also be a wrong file ID in another declaration"
+    CALL ipslerr (3,"histdef",str70,str71,str72)
+  ENDIF
+!-
+  W_F(pfileid)%W_V(iv)%v_name = pvarname
+  W_F(pfileid)%W_V(iv)%title = ptitle
+  W_F(pfileid)%W_V(iv)%unit_name = punit
+  tmp_name = W_F(pfileid)%W_V(iv)%v_name
+!-
+! 1.1 decode the operations
+!-
+  W_F(pfileid)%W_V(iv)%fullop = popp
+  tmp_str80 = popp
+  CALL buildop &
+ &  (tmp_str80,ex_topps,tmp_topp,nbopp_max,missing_val, &
+ &   tmp_sopp,tmp_scal,W_F(pfileid)%W_V(iv)%nbopp)
+!-
+  W_F(pfileid)%W_V(iv)%topp = tmp_topp
+  DO i=1,W_F(pfileid)%W_V(iv)%nbopp
+    W_F(pfileid)%W_V(iv)%sopps(i) = tmp_sopp(i)
+    W_F(pfileid)%W_V(iv)%scal(i) = tmp_scal(i)
+  ENDDO
+!-
+! 1.2 If we have an even number of operations
+!     then we need to add identity
+!-
+  IF (    2*INT(W_F(pfileid)%W_V(iv)%nbopp/2.0) &
+ &     == W_F(pfileid)%W_V(iv)%nbopp) THEN
+    W_F(pfileid)%W_V(iv)%nbopp = W_F(pfileid)%W_V(iv)%nbopp+1
+    W_F(pfileid)%W_V(iv)%sopps(W_F(pfileid)%W_V(iv)%nbopp) = 'ident'
+    W_F(pfileid)%W_V(iv)%scal(W_F(pfileid)%W_V(iv)%nbopp) = missing_val
+  ENDIF
+!-
+! 1.3 External type of the variable
+!-
+  IF (pnbbyt == hist_r8) THEN
+    W_F(pfileid)%W_V(iv)%v_typ = hist_r8
+  ELSE
+    W_F(pfileid)%W_V(iv)%v_typ = hist_r4
+  ENDIF
+!-
+! 2.0 Put the size of the variable in the common and check
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "histdef : 2.0",pfileid,iv,W_F(pfileid)%W_V(iv)%nbopp, &
+ &    W_F(pfileid)%W_V(iv)%sopps(1:W_F(pfileid)%W_V(iv)%nbopp), &
+ &    W_F(pfileid)%W_V(iv)%scal(1:W_F(pfileid)%W_V(iv)%nbopp)
+  ENDIF
+!-
+  W_F(pfileid)%W_V(iv)%scsize(1:3) = (/ pxsize,pysize,pzsize /)
+  W_F(pfileid)%W_V(iv)%zorig(1:3) = &
+ &  (/ W_F(pfileid)%slab_ori(1),W_F(pfileid)%slab_ori(2),par_oriz /)
+  W_F(pfileid)%W_V(iv)%zsize(1:3) = &
+ &  (/ W_F(pfileid)%slab_sz(1),W_F(pfileid)%slab_sz(2),par_szz /)
+!-
+! Is the size of the full array the same as that of the coordinates ?
+!-
+  IF (    (pxsize > W_F(pfileid)%full_size(1)) &
+ &    .OR.(pysize > W_F(pfileid)%full_size(2)) ) THEN
+!-
+    str70 = "The size of the variable is different "// &
+ &          "from the one of the coordinates"
+    WRITE(str71,'("Size of coordinates :",2I4)') &
+ &   W_F(pfileid)%full_size(1),W_F(pfileid)%full_size(2)
+    WRITE(str72,'("Size declared for variable ",a," :",2I4)') &
+ &   TRIM(tmp_name),pxsize,pysize
+    CALL ipslerr (3,"histdef",str70,str71,str72)
+  ENDIF
+!-
+! Is the size of the zoom smaller than the coordinates ?
+!-
+  IF (    (W_F(pfileid)%full_size(1) < W_F(pfileid)%slab_sz(1)) &
+ &    .OR.(W_F(pfileid)%full_size(2) < W_F(pfileid)%slab_sz(2)) ) THEN
+    str70 = &
+ &   "Size of variable should be greater or equal to those of the zoom"
+    WRITE(str71,'("Size of XY zoom :",2I4)') &
+ &   W_F(pfileid)%slab_sz(1),W_F(pfileid)%slab_sz(2)
+    WRITE(str72,'("Size declared for variable ",A," :",2I4)') &
+ &   TRIM(tmp_name),pxsize,pysize
+    CALL ipslerr (3,"histdef",str70,str71,str72)
+  ENDIF
+!-
+! 2.1 We store the horizontal grid information with minimal
+!     and a fall back onto the default grid
+!-
+  IF ( (phoriid > 0).AND.(phoriid <= W_F(pfileid)%n_hax) ) THEN
+    W_F(pfileid)%W_V(iv)%h_axid = phoriid
+  ELSE
+    W_F(pfileid)%W_V(iv)%h_axid = 1
+    CALL ipslerr (2,"histdef", &
+   &  'We use the default grid for variable as an invalide',&
+   &  'ID was provided for variable : ',TRIM(pvarname))
+  ENDIF
+!-
+! 2.2 Check the vertical coordinates if needed
+!-
+  IF (par_szz > 1) THEN
+!-
+!-- Does the vertical coordinate exist ?
+!-
+    IF (pzid > W_F(pfileid)%n_zax) THEN
+      WRITE(str70, &
+ &    '("The vertical coordinate chosen for variable ",a)') &
+ &     TRIM(tmp_name)
+      str71 = " Does not exist."
+      CALL ipslerr (3,"histdef",str70,str71," ")
+    ENDIF
+!-
+!-- Is the vertical size of the variable equal to that of the axis ?
+!-
+    IF (par_szz /= W_F(pfileid)%zax_size(pzid)) THEN
+      str70 = "The size of the zoom does not correspond "// &
+ &            "to the size of the chosen vertical axis"
+      WRITE(str71,'("Size of zoom in z :",I4)') par_szz
+      WRITE(str72,'("Size declared for axis ",A," :",I4)') &
+ &     TRIM(W_F(pfileid)%zax_name(pzid)),W_F(pfileid)%zax_size(pzid)
+      CALL ipslerr (3,"histdef",str70,str71,str72)
+    ENDIF
+!-
+!-- Is the zoom smaller that the total size of the variable ?
+!-
+    IF (pzsize < par_szz) THEN
+      str70 = "The vertical size of variable "// &
+ &            "is smaller than that of the zoom."
+      WRITE(str71,'("Declared vertical size of data :",I5)') pzsize
+      WRITE(str72,'("Size of zoom for variable ",a," = ",I5)') &
+ &     TRIM(tmp_name),par_szz
+      CALL ipslerr (3,"histdef",str70,str71,str72)
+    ENDIF
+    W_F(pfileid)%W_V(iv)%z_axid = pzid
+  ELSE
+    W_F(pfileid)%W_V(iv)%z_axid = -99
+  ENDIF
+!-
+! 3.0 Determine the position of the variable in the buffer
+!     If it is instantaneous output then we do not use the buffer
+!-
+  IF (l_dbg) WRITE(*,*) "histdef : 3.0"
+!-
+! 3.1 We get the size of the arrays histwrite will get and check
+!     that they fit into the tmp_buffer
+!-
+  buff_sz = W_F(pfileid)%W_V(iv)%zsize(1) &
+ &         *W_F(pfileid)%W_V(iv)%zsize(2) &
+ &         *W_F(pfileid)%W_V(iv)%zsize(3)
+!-
+! 3.2 move the pointer of the buffer array for operation
+!     which need bufferisation
+!-
+  IF (     (TRIM(tmp_topp) /= "inst") &
+ &    .AND.(TRIM(tmp_topp) /= "once") &
+ &    .AND.(TRIM(tmp_topp) /= "never") )THEN
+    W_F(pfileid)%W_V(iv)%point = buff_pos+1
+    buff_pos = buff_pos+buff_sz
+    IF (l_dbg) THEN
+      WRITE(*,*) "histdef : 3.2 bufpos for iv = ",iv, &
+ &      " pfileid = ",pfileid," is = ",W_F(pfileid)%W_V(iv)%point
+    ENDIF
+  ENDIF
+!-
+! 4.0 Transfer the frequency of the operations and check
+!     for validity. We have to pay attention to negative values
+!     of the frequency which indicate monthly time-steps.
+!     The strategy is to bring it back to seconds for the tests
+!-
+  IF (l_dbg) WRITE(*,*) "histdef : 4.0"
+!-
+  W_F(pfileid)%W_V(iv)%freq_opp = pfreq_opp
+  W_F(pfileid)%W_V(iv)%freq_wrt = pfreq_wrt
+!-
+  CALL ioget_calendar(un_an,un_jour)
+  IF (pfreq_opp < 0) THEN
+    CALL ioget_calendar(un_an)
+    test_fopp = pfreq_opp*(-1.)*un_an/12.*un_jour
+  ELSE
+    test_fopp = pfreq_opp
+  ENDIF
+  IF (pfreq_wrt < 0) THEN
+    CALL ioget_calendar(un_an)
+    test_fwrt = pfreq_wrt*(-1.)*un_an/12.*un_jour
+  ELSE
+    test_fwrt = pfreq_wrt
+  ENDIF
+!-
+! 4.1 Frequency of operations and output should be larger than deltat !
+!-
+  IF (test_fopp < W_F(pfileid)%deltat) THEN
+    str70 = 'Frequency of operations should be larger than deltat'
+    WRITE(str71,'("It is not the case for variable ",a," :",F10.4)') &
+ &   TRIM(tmp_name),pfreq_opp
+    str72 = "PATCH : frequency set to deltat"
+!-
+    CALL ipslerr (2,"histdef",str70,str71,str72)
+!-
+    W_F(pfileid)%W_V(iv)%freq_opp = W_F(pfileid)%deltat
+  ENDIF
+!-
+  IF (test_fwrt < W_F(pfileid)%deltat) THEN
+    str70 = 'Frequency of output should be larger than deltat'
+    WRITE(str71,'("It is not the case for variable ",a," :",F10.4)') &
+ &   TRIM(tmp_name),pfreq_wrt
+    str72 = "PATCH : frequency set to deltat"
+!-
+    CALL ipslerr (2,"histdef",str70,str71,str72)
+!-
+    W_F(pfileid)%W_V(iv)%freq_wrt = W_F(pfileid)%deltat
+  ENDIF
+!-
+! 4.2 First the existence of the operation is tested and then
+!     its compaticility with the choice of frequencies
+!-
+  IF (TRIM(tmp_topp) == "inst") THEN
+    IF (test_fopp /= test_fwrt) THEN
+      str70 = 'For instantaneous output the frequency '// &
+ &            'of operations and output'
+      WRITE(str71, &
+ &     '("should be the same, this was not case for variable ",a)') &
+ &      TRIM(tmp_name)
+      str72 = "PATCH : The smalest frequency of both is used"
+      CALL ipslerr (2,"histdef",str70,str71,str72)
+      IF (test_fopp < test_fwrt) THEN
+        W_F(pfileid)%W_V(iv)%freq_opp = pfreq_opp
+        W_F(pfileid)%W_V(iv)%freq_wrt = pfreq_opp
+      ELSE
+        W_F(pfileid)%W_V(iv)%freq_opp = pfreq_wrt
+        W_F(pfileid)%W_V(iv)%freq_wrt = pfreq_wrt
+      ENDIF
+    ENDIF
+  ELSE IF (INDEX(ex_topps,TRIM(tmp_topp)) > 0) THEN
+    IF (test_fopp > test_fwrt) THEN
+      str70 = 'For averages the frequency of operations '// &
+&             'should be smaller or equal'
+      WRITE(str71, &
+ &     '("to that of output. It is not the case for variable ",a)') &
+ &     TRIM(tmp_name)
+      str72 = 'PATCH : The output frequency is used for both'
+      CALL ipslerr (2,"histdef",str70,str71,str72)
+      W_F(pfileid)%W_V(iv)%freq_opp = pfreq_wrt
+    ENDIF
+  ELSE
+    WRITE (str70,'("Operation on variable ",a," is unknown")') &
+&    TRIM(tmp_name)
+    WRITE (str71,'("operation requested is :",a)') tmp_topp
+    WRITE (str72,'("File ID :",I3)') pfileid
+    CALL ipslerr (3,"histdef",str70,str71,str72)
+  ENDIF
+!-
+! 5.0 Initialize other variables of the common
+!-
+  IF (l_dbg) WRITE(*,*) "histdef : 5.0"
+!-
+  W_F(pfileid)%W_V(iv)%hist_wrt_rng = (PRESENT(var_range))
+  IF (W_F(pfileid)%W_V(iv)%hist_wrt_rng) THEN
+    W_F(pfileid)%W_V(iv)%hist_calc_rng = (var_range(1) > var_range(2))
+    IF (W_F(pfileid)%W_V(iv)%hist_calc_rng) THEN
+      W_F(pfileid)%W_V(iv)%hist_minmax(1:2) = &
+ &      (/ ABS(missing_val),-ABS(missing_val) /)
+    ELSE
+      W_F(pfileid)%W_V(iv)%hist_minmax(1:2) = var_range(1:2)
+    ENDIF
+  ENDIF
+!-
+! - freq_opp(pfileid,iv)/2./deltat(pfileid)
+  W_F(pfileid)%W_V(iv)%last_opp = W_F(pfileid)%itau0
+! - freq_wrt(pfileid,iv)/2./deltat(pfileid)
+  W_F(pfileid)%W_V(iv)%last_wrt = W_F(pfileid)%itau0
+! - freq_opp(pfileid,iv)/2./deltat(pfileid)
+  W_F(pfileid)%W_V(iv)%last_opp_chk = W_F(pfileid)%itau0
+! - freq_wrt(pfileid,iv)/2./deltat(pfileid)
+  W_F(pfileid)%W_V(iv)%last_wrt_chk = W_F(pfileid)%itau0
+  W_F(pfileid)%W_V(iv)%nb_opp = 0
+  W_F(pfileid)%W_V(iv)%nb_wrt = 0
+!-
+! 6.0 Get the time axis for this variable
+!-
+  IF (l_dbg) WRITE(*,*) "histdef : 6.0"
+!-
+  IF (W_F(pfileid)%W_V(iv)%freq_wrt > 0) THEN
+    WRITE(str10,'(I8.8)') INT(W_F(pfileid)%W_V(iv)%freq_wrt)
+    str40 = TRIM(tmp_topp)//"_"//TRIM(str10)
+  ELSE
+    WRITE(str10,'(I2.2,"month")') ABS(INT(W_F(pfileid)%W_V(iv)%freq_wrt))
+    str40 = TRIM(tmp_topp)//"_"//TRIM(str10)
+  ENDIF
+  CALL find_str (W_F(pfileid)%W_V(1:W_F(pfileid)%n_tax)%tax_name,str40,pos)
+!-
+! No time axis for once, l_max, l_min or never operation
+!-
+  IF (     (TRIM(tmp_topp) /= 'once')  &
+ &    .AND.(TRIM(tmp_topp) /= 'never') &
+ &    .AND.(TRIM(tmp_topp) /= 'l_max') &
+ &    .AND.(TRIM(tmp_topp) /= 'l_min') ) THEN
+    IF (pos < 0) THEN
+      W_F(pfileid)%n_tax = W_F(pfileid)%n_tax+1
+      W_F(pfileid)%W_V(W_F(pfileid)%n_tax)%tax_name = str40
+      W_F(pfileid)%W_V(W_F(pfileid)%n_tax)%tax_last = 0
+      W_F(pfileid)%W_V(iv)%t_axid = W_F(pfileid)%n_tax
+    ELSE
+      W_F(pfileid)%W_V(iv)%t_axid = pos
+    ENDIF
+  ELSE
+    IF (l_dbg)   WRITE(*,*) "histdef : 7.0 ",TRIM(tmp_topp),'----'
+    W_F(pfileid)%W_V(iv)%t_axid = -99
+  ENDIF
+!-
+! 7.0 prepare frequence of writing and operation
+!     for never or once operation
+!-
+  IF (    (TRIM(tmp_topp) == 'once')  &
+ &    .OR.(TRIM(tmp_topp) == 'never') ) THEN
+    W_F(pfileid)%W_V(iv)%freq_opp = 0.
+    W_F(pfileid)%W_V(iv)%freq_wrt = 0.
+  ENDIF
+!---------------------
+END SUBROUTINE histdef
+!===
+SUBROUTINE histend (pfileid)
+!---------------------------------------------------------------------
+!- This subroutine end the decalaration of variables and sets the
+!- time axes in the netcdf file and puts it into the write mode.
+!-
+!- INPUT
+!-
+!- pfileid : ID of the file to be worked on
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid
+!-
+  INTEGER :: nfid,nvid,iret,ndim,iv,itx,ziv,itax,dim_cnt
+  INTEGER,DIMENSION(4) :: dims
+  INTEGER :: year,month,day,hours,minutes
+  REAL :: sec
+  REAL :: rtime0
+  CHARACTER(LEN=30) :: str30
+  CHARACTER(LEN=120) :: assoc
+  CHARACTER(LEN=70) :: str70
+  CHARACTER(LEN=3),DIMENSION(12) :: cal =   &
+ &  (/ 'JAN','FEB','MAR','APR','MAY','JUN', &
+ &     'JUL','AUG','SEP','OCT','NOV','DEC' /)
+  CHARACTER(LEN=7) :: tmp_opp
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  nfid = W_F(pfileid)%ncfid
+!-
+! 1.0 Create the time axes
+!-
+  IF (l_dbg) WRITE(*,*) "histend : 1.0"
+!---
+  iret = NF90_DEF_DIM (nfid,'time_counter', &
+ &                     NF90_UNLIMITED,W_F(pfileid)%tid)
+!-
+! 1.1 Define all the time axes needed for this file
+!-
+  DO itx=1,W_F(pfileid)%n_tax
+    dims(1) = W_F(pfileid)%tid
+    IF (W_F(pfileid)%n_tax > 1) THEN
+      str30 = "t_"//W_F(pfileid)%W_V(itx)%tax_name
+    ELSE
+      str30 = "time_counter"
+    ENDIF
+    iret = NF90_DEF_VAR (nfid,str30,NF90_DOUBLE, &
+ &           dims(1),W_F(pfileid)%W_V(itx)%tdimid)
+    IF (W_F(pfileid)%n_tax <= 1) THEN
+      iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid,'axis',"T")
+    ENDIF
+    iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid, &
+ &           'standard_name',"time")
+!---
+!   To transform the current itau into a real date and take it
+!   as the origin of the file requires the time counter to change.
+!   Thus it is an operation the user has to ask for.
+!   This function should thus only be re-instated
+!   if there is a ioconf routine to control it.
+!---
+!-- rtime0 = itau2date(itau0(pfileid),date0(pfileid),deltat(pfileid))
+    rtime0 = W_F(pfileid)%date0
+!-
+    CALL ju2ymds(rtime0,year,month,day,sec)
+!---
+!   Catch any error induced by a change in calendar !
+!---
+    IF (year < 0) THEN
+      year = 2000+year
+    ENDIF
+!-
+    hours = INT(sec/(60.*60.))
+    minutes = INT((sec-hours*60.*60.)/60.)
+    sec = sec-(hours*60.*60.+minutes*60.)
+!-
+    WRITE (UNIT=str70, &
+ &   FMT='(A,I4.4,"-",I2.2,"-",I2.2," ",I2.2,":",I2.2,":",I2.2)') &
+ &    'seconds since ',year,month,day,hours,minutes,INT(sec)
+    iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid, &
+ &           'units',TRIM(str70))
+!-
+    CALL ioget_calendar (str30)
+    iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid, &
+ &           'calendar',TRIM(str30))
+!-
+    iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid, &
+ &           'title','Time')
+!-
+    iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid, &
+ &           'long_name','Time axis')
+!-
+    WRITE (UNIT=str70, &
+ &   FMT='(" ",I4.4,"-",A3,"-",I2.2," ",I2.2,":",I2.2,":",I2.2)') &
+ &    year,cal(month),day,hours,minutes,INT(sec)
+    iret = NF90_PUT_ATT (nfid,W_F(pfileid)%W_V(itx)%tdimid, &
+ &           'time_origin',TRIM(str70))
+  ENDDO
+!-
+! 2.0 declare the variables
+!-
+  IF (l_dbg) WRITE(*,*) "histend : 2.0"
+!-
+  DO iv=1,W_F(pfileid)%n_var
+!---
+    itax = W_F(pfileid)%W_V(iv)%t_axid
+!---
+    IF (W_F(pfileid)%regular) THEN
+      dims(1:2) = (/ W_F(pfileid)%xid,W_F(pfileid)%yid /)
+      dim_cnt = 2
+    ELSE
+      dims(1) = W_F(pfileid)%xid
+      dim_cnt = 1
+    ENDIF
+!---
+    tmp_opp = W_F(pfileid)%W_V(iv)%topp
+    ziv = W_F(pfileid)%W_V(iv)%z_axid
+!---
+!   2.1 dimension of field
+!---
+    IF ((TRIM(tmp_opp) /= 'never')) THEN
+      IF (     (TRIM(tmp_opp) /= 'once')  &
+     &    .AND.(TRIM(tmp_opp) /= 'l_max') &
+     &    .AND.(TRIM(tmp_opp) /= 'l_min') ) THEN
+        IF (ziv == -99) THEN
+          ndim = dim_cnt+1
+          dims(dim_cnt+1:dim_cnt+2) = (/ W_F(pfileid)%tid,0 /)
+        ELSE
+          ndim = dim_cnt+2
+          dims(dim_cnt+1:dim_cnt+2) = &
+ &         (/ W_F(pfileid)%zax_ids(ziv),W_F(pfileid)%tid /)
+        ENDIF
+      ELSE
+        IF (ziv == -99) THEN
+          ndim = dim_cnt
+          dims(dim_cnt+1:dim_cnt+2) = (/ 0,0 /)
+        ELSE
+          ndim = dim_cnt+1
+          dims(dim_cnt+1:dim_cnt+2) = (/ W_F(pfileid)%zax_ids(ziv),0 /)
+        ENDIF
+      ENDIF
+!-
+      iret = NF90_DEF_VAR (nfid,TRIM(W_F(pfileid)%W_V(iv)%v_name), &
+ &             W_F(pfileid)%W_V(iv)%v_typ,dims(1:ABS(ndim)),nvid)
+!-
+      W_F(pfileid)%W_V(iv)%ncvid = nvid
+!-
+      IF (LEN_TRIM(W_F(pfileid)%W_V(iv)%unit_name) > 0) THEN
+        iret = NF90_PUT_ATT (nfid,nvid,'units', &
+ &                           TRIM(W_F(pfileid)%W_V(iv)%unit_name))
+      ENDIF
+      iret = NF90_PUT_ATT (nfid,nvid,'standard_name', &
+ &                         TRIM(W_F(pfileid)%W_V(iv)%title))
+!-
+      iret = NF90_PUT_ATT (nfid,nvid,'_FillValue', &
+ &                         REAL(missing_val,KIND=4))
+      IF (W_F(pfileid)%W_V(iv)%hist_wrt_rng) THEN
+        iret = NF90_PUT_ATT (nfid,nvid,'valid_min', &
+ &               REAL(W_F(pfileid)%W_V(iv)%hist_minmax(1),KIND=4))
+        iret = NF90_PUT_ATT (nfid,nvid,'valid_max', &
+ &               REAL(W_F(pfileid)%W_V(iv)%hist_minmax(2),KIND=4))
+      ENDIF
+      iret = NF90_PUT_ATT (nfid,nvid,'long_name', &
+ &                         TRIM(W_F(pfileid)%W_V(iv)%title))
+      iret = NF90_PUT_ATT (nfid,nvid,'online_operation', &
+ &                         TRIM(W_F(pfileid)%W_V(iv)%fullop))
+!-
+      SELECT CASE(ndim)
+      CASE(-3,2:4)
+      CASE DEFAULT
+        CALL ipslerr (3,"histend", &
+       &  'less than 2 or more than 4 dimensions are not', &
+       &  'allowed at this stage',' ')
+      END SELECT
+!-
+      assoc=TRIM(W_F(pfileid)%hax_name(W_F(pfileid)%W_V(iv)%h_axid,2)) &
+ &   //' '//TRIM(W_F(pfileid)%hax_name(W_F(pfileid)%W_V(iv)%h_axid,1))
+!-
+      ziv = W_F(pfileid)%W_V(iv)%z_axid
+      IF (ziv > 0) THEN
+        str30 = W_F(pfileid)%zax_name(ziv)
+        assoc = TRIM(str30)//' '//TRIM(assoc)
+      ENDIF
+!-
+      IF (itax > 0) THEN
+        IF (W_F(pfileid)%n_tax > 1) THEN
+          str30 = "t_"//W_F(pfileid)%W_V(itax)%tax_name
+        ELSE
+          str30 = "time_counter"
+        ENDIF
+        assoc = TRIM(str30)//' '//TRIM(assoc)
+!-
+        IF (l_dbg) THEN
+          WRITE(*,*) "histend : 2.0.n, freq_opp, freq_wrt", &
+ &          W_F(pfileid)%W_V(iv)%freq_opp,W_F(pfileid)%W_V(iv)%freq_wrt
+        ENDIF
+!-
+        iret = NF90_PUT_ATT (nfid,nvid,'interval_operation', &
+ &                           REAL(W_F(pfileid)%W_V(iv)%freq_opp,KIND=4))
+        iret = NF90_PUT_ATT (nfid,nvid,'interval_write', &
+ &                           REAL(W_F(pfileid)%W_V(iv)%freq_wrt,KIND=4))
+      ENDIF
+      iret = NF90_PUT_ATT (nfid,nvid,'coordinates',TRIM(assoc))
+    ENDIF
+  ENDDO
+!-
+! 2.2 Add DOMAIN attributes if needed
+!-
+  IF (W_F(pfileid)%dom_id_svg >= 0) THEN
+    CALL flio_dom_att (nfid,W_F(pfileid)%dom_id_svg)
+  ENDIF
+!-
+! 3.0 Put the netcdf file into write mode
+!-
+  IF (l_dbg) WRITE(*,*) "histend : 3.0"
+!-
+  iret = NF90_ENDDEF (nfid)
+!-
+! 4.0 Give some informations to the user
+!-
+  IF (l_dbg) WRITE(*,*) "histend : 4.0"
+!-
+  WRITE(str70,'("All variables have been initialized on file :",I3)') pfileid
+  CALL ipslerr (1,'histend',str70,'',' ')
+!---------------------
+END SUBROUTINE histend
+!===
+SUBROUTINE histwrite_r1d (pfileid,pvarname,pitau,pdata,nbindex,nindex)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pitau,nbindex
+  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
+  REAL,DIMENSION(:),INTENT(IN) :: pdata
+  CHARACTER(LEN=*),INTENT(IN) :: pvarname
+!---------------------------------------------------------------------
+  CALL histw_rnd (pfileid,pvarname,pitau,nbindex,nindex,pdata_1d=pdata)
+!---------------------------
+END SUBROUTINE histwrite_r1d
+!===
+SUBROUTINE histwrite_r2d (pfileid,pvarname,pitau,pdata,nbindex,nindex)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pitau,nbindex
+  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
+  REAL,DIMENSION(:,:),INTENT(IN) :: pdata
+  CHARACTER(LEN=*),INTENT(IN) :: pvarname
+!---------------------------------------------------------------------
+  CALL histw_rnd (pfileid,pvarname,pitau,nbindex,nindex,pdata_2d=pdata)
+!---------------------------
+END SUBROUTINE histwrite_r2d
+!===
+SUBROUTINE histwrite_r3d (pfileid,pvarname,pitau,pdata,nbindex,nindex)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pitau,nbindex
+  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
+  REAL,DIMENSION(:,:,:),INTENT(IN) :: pdata
+  CHARACTER(LEN=*),INTENT(IN) :: pvarname
+!---------------------------------------------------------------------
+  CALL histw_rnd (pfileid,pvarname,pitau,nbindex,nindex,pdata_3d=pdata)
+!---------------------------
+END SUBROUTINE histwrite_r3d
+!===
+SUBROUTINE histw_rnd (pfileid,pvarname,pitau,nbindex,nindex, &
+  &                   pdata_1d,pdata_2d,pdata_3d)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pitau,nbindex
+  INTEGER,DIMENSION(nbindex),INTENT(IN) :: nindex
+  CHARACTER(LEN=*),INTENT(IN) :: pvarname
+  REAL,DIMENSION(:),INTENT(IN),OPTIONAL     :: pdata_1d
+  REAL,DIMENSION(:,:),INTENT(IN),OPTIONAL   :: pdata_2d
+  REAL,DIMENSION(:,:,:),INTENT(IN),OPTIONAL :: pdata_3d
+!-
+  LOGICAL :: do_oper,do_write,largebuf,l1d,l2d,l3d
+  INTEGER :: varid,io,nbpt_out
+  INTEGER              :: nbpt_in1
+  INTEGER,DIMENSION(2) :: nbpt_in2
+  INTEGER,DIMENSION(3) :: nbpt_in3
+  REAL,ALLOCATABLE,DIMENSION(:),SAVE :: buff_tmp
+  INTEGER,SAVE :: buff_tmp_sz
+  CHARACTER(LEN=7) :: tmp_opp
+  CHARACTER(LEN=13) :: c_nam
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  l1d=PRESENT(pdata_1d); l2d=PRESENT(pdata_2d); l3d=PRESENT(pdata_3d);
+  IF      (l1d) THEN
+    c_nam = 'histwrite_r1d'
+  ELSE IF (l2d) THEN
+    c_nam = 'histwrite_r2d'
+  ELSE IF (l3d) THEN
+    c_nam = 'histwrite_r3d'
+  ENDIF
+!-
+! 1.0 Try to catch errors like specifying the wrong file ID.
+!     Thanks Marine for showing us what errors users can make !
+!-
+  IF ( (pfileid < 1).OR.(pfileid > nb_files) ) THEN
+    CALL ipslerr (3,"histwrite", &
+ &    'Illegal file ID in the histwrite of variable',pvarname,' ')
+  ENDIF
+!-
+! 1.1 Find the id of the variable to be written and the real time
+!-
+  CALL histvar_seq (pfileid,pvarname,varid)
+!-
+! 2.0 do nothing for never operation
+!-
+  tmp_opp = W_F(pfileid)%W_V(varid)%topp
+!-
+  IF (TRIM(tmp_opp) == "never") THEN
+    W_F(pfileid)%W_V(varid)%last_opp_chk = -99
+    W_F(pfileid)%W_V(varid)%last_wrt_chk = -99
+  ENDIF
+!-
+! 3.0 We check if we need to do an operation
+!-
+  IF (W_F(pfileid)%W_V(varid)%last_opp_chk == pitau) THEN
+    CALL ipslerr (3,"histwrite", &
+ &    'This variable has already been analysed at the present', &
+ &    'time step',TRIM(pvarname))
+  ENDIF
+!-
+  CALL isittime &
+ &  (pitau,W_F(pfileid)%date0,W_F(pfileid)%deltat, &
+ &   W_F(pfileid)%W_V(varid)%freq_opp, &
+ &   W_F(pfileid)%W_V(varid)%last_opp, &
+ &   W_F(pfileid)%W_V(varid)%last_opp_chk,do_oper)
+!-
+! 4.0 We check if we need to write the data
+!-
+  IF (W_F(pfileid)%W_V(varid)%last_wrt_chk == pitau) THEN
+    CALL ipslerr (3,"histwrite", &
+ &    'This variable as already been written for the present', &
+ &    'time step',' ')
+  ENDIF
+!-
+  CALL isittime &
+ &  (pitau,W_F(pfileid)%date0,W_F(pfileid)%deltat, &
+ &   W_F(pfileid)%W_V(varid)%freq_wrt, &
+ &   W_F(pfileid)%W_V(varid)%last_wrt, &
+ &   W_F(pfileid)%W_V(varid)%last_wrt_chk,do_write)
+!-
+! 5.0 histwrite called
+!-
+  IF (do_oper.OR.do_write) THEN
+!-
+!-- 5.1 Get the sizes of the data we will handle
+!-
+    IF (W_F(pfileid)%W_V(varid)%datasz_in(1) <= 0) THEN
+!---- There is the risk here that the user has over-sized the array.
+!---- But how can we catch this ?
+!---- In the worst case we will do impossible operations
+!---- on part of the data !
+      W_F(pfileid)%W_V(varid)%datasz_in(1:3) = -1
+      IF      (l1d) THEN
+        W_F(pfileid)%W_V(varid)%datasz_in(1) = SIZE(pdata_1d)
+      ELSE IF (l2d) THEN
+        W_F(pfileid)%W_V(varid)%datasz_in(1) = SIZE(pdata_2d,DIM=1)
+        W_F(pfileid)%W_V(varid)%datasz_in(2) = SIZE(pdata_2d,DIM=2)
+      ELSE IF (l3d) THEN
+        W_F(pfileid)%W_V(varid)%datasz_in(1) = SIZE(pdata_3d,DIM=1)
+        W_F(pfileid)%W_V(varid)%datasz_in(2) = SIZE(pdata_3d,DIM=2)
+        W_F(pfileid)%W_V(varid)%datasz_in(3) = SIZE(pdata_3d,DIM=3)
+      ENDIF
+    ENDIF
+!-
+!-- 5.2 The maximum size of the data will give the size of the buffer
+!-
+    IF (W_F(pfileid)%W_V(varid)%datasz_max <= 0) THEN
+      largebuf = .FALSE.
+      DO io=1,W_F(pfileid)%W_V(varid)%nbopp
+        IF (INDEX(fuchnbout,W_F(pfileid)%W_V(varid)%sopps(io)) > 0) THEN
+          largebuf = .TRUE.
+        ENDIF
+      ENDDO
+      IF (largebuf) THEN
+        W_F(pfileid)%W_V(varid)%datasz_max = &
+ &        W_F(pfileid)%W_V(varid)%scsize(1) &
+ &       *W_F(pfileid)%W_V(varid)%scsize(2) &
+ &       *W_F(pfileid)%W_V(varid)%scsize(3)
+      ELSE
+        IF      (l1d) THEN
+          W_F(pfileid)%W_V(varid)%datasz_max = &
+ &          W_F(pfileid)%W_V(varid)%datasz_in(1)
+        ELSE IF (l2d) THEN
+          W_F(pfileid)%W_V(varid)%datasz_max = &
+ &          W_F(pfileid)%W_V(varid)%datasz_in(1) &
+ &         *W_F(pfileid)%W_V(varid)%datasz_in(2)
+        ELSE IF (l3d) THEN
+          W_F(pfileid)%W_V(varid)%datasz_max = &
+ &          W_F(pfileid)%W_V(varid)%datasz_in(1) &
+ &         *W_F(pfileid)%W_V(varid)%datasz_in(2) &
+ &         *W_F(pfileid)%W_V(varid)%datasz_in(3)
+        ENDIF
+      ENDIF
+    ENDIF
+!-
+    IF (.NOT.ALLOCATED(buff_tmp)) THEN
+      IF (l_dbg) THEN
+        WRITE(*,*) &
+ &       c_nam//" : allocate buff_tmp for buff_sz = ", &
+ &       W_F(pfileid)%W_V(varid)%datasz_max
+      ENDIF
+      ALLOCATE(buff_tmp(W_F(pfileid)%W_V(varid)%datasz_max))
+      buff_tmp_sz = W_F(pfileid)%W_V(varid)%datasz_max
+    ELSE IF (W_F(pfileid)%W_V(varid)%datasz_max > buff_tmp_sz) THEN
+      IF (l_dbg) THEN
+        WRITE(*,*) &
+ &       c_nam//" : re-allocate buff_tmp for buff_sz = ", &
+ &       W_F(pfileid)%W_V(varid)%datasz_max
+      ENDIF
+      DEALLOCATE(buff_tmp)
+      ALLOCATE(buff_tmp(W_F(pfileid)%W_V(varid)%datasz_max))
+      buff_tmp_sz = W_F(pfileid)%W_V(varid)%datasz_max
+    ENDIF
+!-
+!-- We have to do the first operation anyway.
+!-- Thus we do it here and change the ranke
+!-- of the data at the same time. This should speed up things.
+!-
+    nbpt_out = W_F(pfileid)%W_V(varid)%datasz_max
+    IF      (l1d) THEN
+      nbpt_in1 = W_F(pfileid)%W_V(varid)%datasz_in(1)
+      CALL mathop (W_F(pfileid)%W_V(varid)%sopps(1),nbpt_in1,pdata_1d, &
+ &                 missing_val,nbindex,nindex, &
+ &                 W_F(pfileid)%W_V(varid)%scal(1),nbpt_out,buff_tmp)
+    ELSE IF (l2d) THEN
+      nbpt_in2(1:2) = W_F(pfileid)%W_V(varid)%datasz_in(1:2)
+      CALL mathop (W_F(pfileid)%W_V(varid)%sopps(1),nbpt_in2,pdata_2d, &
+ &                 missing_val,nbindex,nindex, &
+ &                 W_F(pfileid)%W_V(varid)%scal(1),nbpt_out,buff_tmp)
+    ELSE IF (l3d) THEN
+      nbpt_in3(1:3) = W_F(pfileid)%W_V(varid)%datasz_in(1:3)
+      CALL mathop (W_F(pfileid)%W_V(varid)%sopps(1),nbpt_in3,pdata_3d, &
+ &                 missing_val,nbindex,nindex, &
+ &                 W_F(pfileid)%W_V(varid)%scal(1),nbpt_out,buff_tmp)
+    ENDIF
+    CALL histwrite_real (pfileid,varid,pitau,nbpt_out, &
+ &            buff_tmp,nbindex,nindex,do_oper,do_write)
+  ENDIF
+!-
+! 6.0 Manage time steps
+!-
+  IF ((TRIM(tmp_opp) /= "once").AND.(TRIM(tmp_opp) /= "never")) THEN
+    W_F(pfileid)%W_V(varid)%last_opp_chk = pitau
+    W_F(pfileid)%W_V(varid)%last_wrt_chk = pitau
+  ELSE
+    W_F(pfileid)%W_V(varid)%last_opp_chk = -99
+    W_F(pfileid)%W_V(varid)%last_wrt_chk = -99
+  ENDIF
+!-----------------------
+END SUBROUTINE histw_rnd
+!===
+SUBROUTINE histwrite_real &
+ & (pfileid,varid,pitau,nbdpt,buff_tmp,nbindex,nindex,do_oper,do_write)
+!---------------------------------------------------------------------
+!- This subroutine is internal and does the calculations and writing
+!- if needed. At a later stage it should be split into an operation
+!- and writing subroutines.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: pfileid,pitau,varid, &
+ &                      nbindex,nindex(nbindex),nbdpt
+  REAL,DIMENSION(:)  :: buff_tmp
+  LOGICAL,INTENT(IN) :: do_oper,do_write
+!-
+  INTEGER :: tsz,nfid,nvid,i,iret,ipt,itax,io,nbin,nbout
+  INTEGER :: nx,ny,nz,ky,kz,kt,kc
+  INTEGER,DIMENSION(4) :: corner,edges
+  INTEGER :: itime
+!-
+  REAL :: rtime
+  CHARACTER(LEN=7) :: tmp_opp
+  REAL,ALLOCATABLE,DIMENSION(:),SAVE :: buff_tmp2,buffer_used
+  INTEGER,SAVE :: buff_tmp2_sz,buffer_sz
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) "histwrite 0.0 : VAR : ",W_F(pfileid)%W_V(varid)%v_name
+    WRITE(*,*) "histwrite 0.0 : nbindex,nindex :", &
+ &  nbindex,nindex(1:MIN(3,nbindex)),'...',nindex(MAX(1,nbindex-3):nbindex)
+  ENDIF
+!-
+! The sizes which can be encoutered
+!-
+  tsz =  W_F(pfileid)%W_V(varid)%zsize(1) &
+ &      *W_F(pfileid)%W_V(varid)%zsize(2) &
+ &      *W_F(pfileid)%W_V(varid)%zsize(3)
+!-
+! 1.0 We allocate the memory needed to store the data between write
+!     and the temporary space needed for operations.
+!     We have to keep precedent buffer if needed
+!-
+  IF (.NOT. ALLOCATED(buffer)) THEN
+    IF (l_dbg) WRITE(*,*) "histwrite_real 1.0 allocate buffer ",buff_pos
+    ALLOCATE(buffer(buff_pos))
+    buffer_sz = buff_pos
+    buffer(:)=0.0
+  ELSE IF (buffer_sz < buff_pos) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) "histwrite_real 1.0.1 re-allocate buffer for ", &
+ &      buff_pos," instead of ",SIZE(buffer)
+    ENDIF
+    IF (SUM(buffer)/=0.0) THEN
+      IF (l_dbg) WRITE (*,*) 'histwrite : buffer has been used. ', &
+ &      'We have to save it before re-allocating.'
+      ALLOCATE(buffer_used(buffer_sz))
+      buffer_used(:)=buffer(:)
+      DEALLOCATE(buffer)
+      ALLOCATE(buffer(buff_pos))
+      buffer_sz = buff_pos
+      buffer(:)=0.0
+      buffer(:SIZE(buffer_used))=buffer_used
+      DEALLOCATE(buffer_used)
+    ELSE
+      IF (l_dbg) WRITE (*,*) 'histwrite : buffer has not been used. ', &
+ &      'We have just to re-allocate it.'
+      DEALLOCATE(buffer)
+      ALLOCATE(buffer(buff_pos))
+      buffer_sz = buff_pos
+      buffer(:)=0.0
+    ENDIF
+  ENDIF
+!-
+! The buffers are only deallocated when more space is needed. This
+! reduces the umber of allocates but increases memory needs.
+!-
+  IF (.NOT.ALLOCATED(buff_tmp2)) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) "histwrite_real 1.1 allocate buff_tmp2 ",SIZE(buff_tmp)
+    ENDIF
+    ALLOCATE(buff_tmp2(W_F(pfileid)%W_V(varid)%datasz_max))
+    buff_tmp2_sz = W_F(pfileid)%W_V(varid)%datasz_max
+  ELSE IF (W_F(pfileid)%W_V(varid)%datasz_max > buff_tmp2_sz) THEN
+    IF (l_dbg) THEN
+      WRITE(*,*) "histwrite_real 1.2 re-allocate buff_tmp2 : ", &
+     & SIZE(buff_tmp)," instead of ",SIZE(buff_tmp2)
+    ENDIF
+    DEALLOCATE(buff_tmp2)
+    ALLOCATE(buff_tmp2(W_F(pfileid)%W_V(varid)%datasz_max))
+    buff_tmp2_sz = W_F(pfileid)%W_V(varid)%datasz_max
+  ENDIF
+!-
+  rtime = pitau*W_F(pfileid)%deltat
+  tmp_opp = W_F(pfileid)%W_V(varid)%topp
+!-
+! 3.0 Do the operations or transfer the slab of data into buff_tmp
+!-
+  IF (l_dbg) WRITE(*,*) "histwrite: 3.0",pfileid
+!-
+! 3.1 DO the Operations only if needed
+!-
+  IF (do_oper) THEN
+    i = pfileid
+    nbout = nbdpt
+!-
+!-- 3.4 We continue the sequence of operations
+!--     we started in the interface routine
+!-
+    DO io=2,W_F(i)%W_V(varid)%nbopp,2
+      nbin = nbout
+      nbout = W_F(i)%W_V(varid)%datasz_max
+      CALL mathop(W_F(i)%W_V(varid)%sopps(io),nbin,buff_tmp, &
+ &      missing_val,nbindex,nindex,W_F(i)%W_V(varid)%scal(io), &
+ &      nbout,buff_tmp2)
+      IF (l_dbg) THEN
+        WRITE(*,*) &
+ &       "histwrite: 3.4a nbout : ",nbin,nbout,W_F(i)%W_V(varid)%sopps(io)
+      ENDIF
+!-
+      nbin = nbout
+      nbout = W_F(i)%W_V(varid)%datasz_max
+      CALL mathop(W_F(i)%W_V(varid)%sopps(io+1),nbin,buff_tmp2, &
+ &      missing_val,nbindex,nindex,W_F(i)%W_V(varid)%scal(io+1), &
+ &      nbout,buff_tmp)
+      IF (l_dbg) THEN
+        WRITE(*,*) &
+ &     "histwrite: 3.4b nbout : ",nbin,nbout,W_F(i)%W_V(varid)%sopps(io+1)
+      ENDIF
+    ENDDO
+!-
+!   3.5 Zoom into the data
+!-
+    IF (l_dbg) THEN
+      WRITE(*,*) &
+ &     "histwrite: 3.5 size(buff_tmp) : ",SIZE(buff_tmp)
+      WRITE(*,*) &
+ &     "histwrite: 3.5 slab in X :", &
+ &     W_F(i)%W_V(varid)%zorig(1),W_F(i)%W_V(varid)%zsize(1)
+      WRITE(*,*) &
+ &     "histwrite: 3.5 slab in Y :", &
+ &     W_F(i)%W_V(varid)%zorig(2),W_F(i)%W_V(varid)%zsize(2)
+      WRITE(*,*) &
+ &     "histwrite: 3.5 slab in Z :", &
+ &     W_F(i)%W_V(varid)%zorig(3),W_F(i)%W_V(varid)%zsize(3)
+      WRITE(*,*) &
+ &     "histwrite: 3.5 slab of input:", &
+ &     W_F(i)%W_V(varid)%scsize(1), &
+ &     W_F(i)%W_V(varid)%scsize(2), &
+ &     W_F(i)%W_V(varid)%scsize(3)
+    ENDIF
+!---
+!-- We have to consider blocks of contiguous data
+!---
+    nx=MAX(W_F(i)%W_V(varid)%zsize(1),1)
+    ny=MAX(W_F(i)%W_V(varid)%zsize(2),1)
+    nz=MAX(W_F(i)%W_V(varid)%zsize(3),1)
+    IF     (     (W_F(i)%W_V(varid)%zorig(1) == 1) &
+ &          .AND.(   W_F(i)%W_V(varid)%zsize(1) &
+ &                == W_F(i)%W_V(varid)%scsize(1)) &
+ &          .AND.(W_F(i)%W_V(varid)%zorig(2) == 1) &
+ &          .AND.(   W_F(i)%W_V(varid)%zsize(2) &
+ &                == W_F(i)%W_V(varid)%scsize(2))) THEN
+      kt = (W_F(i)%W_V(varid)%zorig(3)-1)*nx*ny
+      buff_tmp2(1:nx*ny*nz) = buff_tmp(kt+1:kt+nx*ny*nz)
+    ELSEIF (     (W_F(i)%W_V(varid)%zorig(1) == 1) &
+ &          .AND.(   W_F(i)%W_V(varid)%zsize(1) &
+ &                == W_F(i)%W_V(varid)%scsize(1))) THEN
+      kc = -nx*ny
+      DO kz=W_F(i)%W_V(varid)%zorig(3),W_F(i)%W_V(varid)%zorig(3)+nz-1
+        kc = kc+nx*ny
+        kt = ( (kz-1)*W_F(i)%W_V(varid)%scsize(2) &
+ &            +W_F(i)%W_V(varid)%zorig(2)-1)*nx
+        buff_tmp2(kc+1:kc+nx*ny) = buff_tmp(kt+1:kt+nx*ny)
+      ENDDO
+    ELSE
+      kc = -nx
+      DO kz=W_F(i)%W_V(varid)%zorig(3),W_F(i)%W_V(varid)%zorig(3)+nz-1
+        DO ky=W_F(i)%W_V(varid)%zorig(2),W_F(i)%W_V(varid)%zorig(2)+ny-1
+          kc = kc+nx
+          kt = ((kz-1)*W_F(i)%W_V(varid)%scsize(2)+ky-1) &
+ &            *W_F(i)%W_V(varid)%scsize(1) &
+ &            +W_F(i)%W_V(varid)%zorig(1)-1
+          buff_tmp2(kc+1:kc+nx) = buff_tmp(kt+1:kt+nx)
+        ENDDO
+      ENDDO
+    ENDIF
+!-
+!-- 4.0 Get the min and max of the field (buff_tmp)
+!-
+    IF (l_dbg) WRITE(*,*) "histwrite: 4.0 buff_tmp",pfileid,varid, &
+ &    TRIM(tmp_opp),' ---- ',LEN_TRIM(tmp_opp),nbindex
+!-
+    IF (W_F(pfileid)%W_V(varid)%hist_calc_rng) THEN
+      W_F(pfileid)%W_V(varid)%hist_minmax(1) = &
+ &      MIN(W_F(pfileid)%W_V(varid)%hist_minmax(1), &
+ &      MINVAL(buff_tmp2(1:tsz),MASK=buff_tmp2(1:tsz) /= missing_val))
+      W_F(pfileid)%W_V(varid)%hist_minmax(2) = &
+ &      MAX(W_F(pfileid)%W_V(varid)%hist_minmax(2), &
+ &      MAXVAL(buff_tmp2(1:tsz),MASK=buff_tmp2(1:tsz) /= missing_val))
+    ENDIF
+!-
+!-- 5.0 Do the operations if needed. In the case of instantaneous
+!--     output we do not transfer to the buffer.
+!-
+    IF (l_dbg) WRITE(*,*) "histwrite: 5.0",pfileid,"tsz :",tsz
+!-
+    ipt = W_F(pfileid)%W_V(varid)%point
+!-
+!   WRITE(*,*) 'OPE ipt, buffer :',pvarname,ipt,varid
+!-
+    IF (     (TRIM(tmp_opp) /= "inst") &
+ &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
+      CALL moycum(tmp_opp,tsz,buffer(ipt:), &
+ &           buff_tmp2,W_F(pfileid)%W_V(varid)%nb_opp)
+    ENDIF
+!-
+    W_F(pfileid)%W_V(varid)%last_opp = pitau
+    W_F(pfileid)%W_V(varid)%nb_opp = W_F(pfileid)%W_V(varid)%nb_opp+1
+!-
+  ENDIF
+!-
+! 6.0 Write to file if needed
+!-
+  IF (l_dbg) WRITE(*,*) "histwrite: 6.0",pfileid
+!-
+  IF (do_write) THEN
+!-
+    nfid = W_F(pfileid)%ncfid
+    nvid = W_F(pfileid)%W_V(varid)%ncvid
+!-
+!-- 6.1 Do the operations that are needed before writting
+!-
+    IF (l_dbg) WRITE(*,*) "histwrite: 6.1",pfileid
+!-
+    IF (     (TRIM(tmp_opp) /= "inst") &
+ &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
+      rtime = ( rtime &
+ &             +W_F(pfileid)%W_V(varid)%last_wrt*W_F(pfileid)%deltat)/2.0
+    ENDIF
+!-
+!-- 6.2 Add a value to the time axis of this variable if needed
+!-
+    IF (     (TRIM(tmp_opp) /= "l_max") &
+ &      .AND.(TRIM(tmp_opp) /= "l_min") &
+ &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
+!-
+      IF (l_dbg) WRITE(*,*) "histwrite: 6.2",pfileid
+!-
+      itax = W_F(pfileid)%W_V(varid)%t_axid
+      itime = W_F(pfileid)%W_V(varid)%nb_wrt+1
+!-
+      IF (W_F(pfileid)%W_V(itax)%tax_last < itime) THEN
+        iret = NF90_PUT_VAR (nfid,W_F(pfileid)%W_V(itax)%tdimid, &
+ &               (/ rtime /),start=(/ itime /),count=(/ 1 /))
+        W_F(pfileid)%W_V(itax)%tax_last = itime
+      ENDIF
+    ELSE
+      itime=1
+    ENDIF
+!-
+!-- 6.3 Write the data. Only in the case of instantaneous output
+!       we do not write the buffer.
+!-
+    IF (l_dbg) THEN
+      WRITE(*,*) "histwrite: 6.3",pfileid,nfid,nvid,varid,itime
+    ENDIF
+!-
+    IF (W_F(pfileid)%W_V(varid)%scsize(3) == 1) THEN
+      IF (W_F(pfileid)%regular) THEN
+        corner(1:4) = (/ 1,1,itime,0 /)
+        edges(1:4) = (/ W_F(pfileid)%W_V(varid)%zsize(1), &
+ &                      W_F(pfileid)%W_V(varid)%zsize(2),1,0 /)
+      ELSE
+        corner(1:4) = (/ 1,itime,0,0 /)
+        edges(1:4) = (/ W_F(pfileid)%W_V(varid)%zsize(1),1,0,0 /)
+      ENDIF
+    ELSE
+      IF (W_F(pfileid)%regular) THEN
+        corner(1:4) = (/ 1,1,1,itime /)
+        edges(1:4) = (/ W_F(pfileid)%W_V(varid)%zsize(1), &
+ &                      W_F(pfileid)%W_V(varid)%zsize(2), &
+ &                      W_F(pfileid)%W_V(varid)%zsize(3),1 /)
+      ELSE
+        corner(1:4) = (/ 1,1,itime,0 /)
+        edges(1:4) = (/ W_F(pfileid)%W_V(varid)%zsize(1), &
+ &                      W_F(pfileid)%W_V(varid)%zsize(3),1,0 /)
+      ENDIF
+    ENDIF
+!-
+    ipt = W_F(pfileid)%W_V(varid)%point
+!-
+    IF (     (TRIM(tmp_opp) /= "inst") &
+ &      .AND.(TRIM(tmp_opp) /= "once") ) THEN
+      iret = NF90_PUT_VAR (nfid,nvid,buffer(ipt:), &
+ &                       start=corner(1:4),count=edges(1:4))
+    ELSE
+      iret = NF90_PUT_VAR (nfid,nvid,buff_tmp2, &
+ &                       start=corner(1:4),count=edges(1:4))
+    ENDIF
+!-
+    W_F(pfileid)%W_V(varid)%last_wrt = pitau
+    W_F(pfileid)%W_V(varid)%nb_wrt = W_F(pfileid)%W_V(varid)%nb_wrt+1
+    W_F(pfileid)%W_V(varid)%nb_opp = 0
+!---
+!   After the write the file can be synchronized so that no data is
+!   lost in case of a crash. This feature gives up on the benefits of
+!   buffering and should only be used in debuging mode. A flag is
+!   needed here to switch to this mode.
+!---
+!   iret = NF90_SYNC (nfid)
+!-
+  ENDIF
+!----------------------------
+END SUBROUTINE histwrite_real
+!===
+SUBROUTINE histvar_seq (pfid,pvarname,pvid)
+!---------------------------------------------------------------------
+!- This subroutine optimized the search for the variable in the table.
+!- In a first phase it will learn the succession of the variables
+!- called and then it will use the table to guess what comes next.
+!- It is the best solution to avoid lengthy searches through array
+!- vectors.
+!-
+!- ARGUMENTS :
+!-
+!- pfid  : id of the file on which we work
+!- pvarname : The name of the variable we are looking for
+!- pvid     : The var id we found
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(in)  :: pfid
+  CHARACTER(LEN=*),INTENT(IN) :: pvarname
+  INTEGER,INTENT(out) :: pvid
+!-
+  LOGICAL,SAVE :: learning(nb_files_max)=.TRUE.
+  INTEGER,SAVE :: overlap(nb_files_max) = -1
+  INTEGER,SAVE :: varseq(nb_files_max,nb_var_max*3)
+  INTEGER,SAVE :: varseq_len(nb_files_max) = 0
+  INTEGER,SAVE :: varseq_pos(nb_files_max)
+  INTEGER,SAVE :: varseq_err(nb_files_max) = 0
+  INTEGER      :: ib,sp,nn,pos
+  CHARACTER(LEN=70) :: str70
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'histvar_seq, start of the subroutine :',learning(pfid)
+  ENDIF
+!-
+  IF (learning(pfid)) THEN
+!-
+!-- 1.0 We compute the length over which we are going
+!--     to check the overlap
+!-
+    IF (overlap(pfid) <= 0) THEN
+      IF (W_F(pfid)%n_var > 6) THEN
+        overlap(pfid) = W_F(pfid)%n_var/3*2
+      ELSE
+        overlap(pfid) = W_F(pfid)%n_var
+      ENDIF
+    ENDIF
+!-
+!-- 1.1 Find the position of this string
+!-
+    CALL find_str (W_F(pfid)%W_V(1:W_F(pfid)%n_var)%v_name,pvarname,pos)
+    IF (pos > 0) THEN
+      pvid = pos
+    ELSE
+      CALL ipslerr (3,"histvar_seq", &
+ &      'The name of the variable you gave has not been declared', &
+ &      'You should use subroutine histdef for declaring variable', &
+ &      TRIM(pvarname))
+    ENDIF
+!-
+!-- 1.2 If we have not given up we store the position
+!--     in the sequence of calls
+!-
+    IF (varseq_err(pfid) >= 0) THEN
+      sp = varseq_len(pfid)+1
+      IF (sp <= nb_var_max*3) THEN
+        varseq(pfid,sp) = pvid
+        varseq_len(pfid) = sp
+      ELSE
+        CALL ipslerr (2,"histvar_seq",&
+ &       'The learning process has failed and we give up. '// &
+ &       'Either you sequence is',&
+ &       'too complex or I am too dumb. '// &
+ &       'This will only affect the efficiency',&
+ &       'of your code. Thus if you wish to save time'// &
+ &       ' contact the IOIPSL team. ')
+        WRITE(*,*) 'The sequence we have found up to now :'
+        WRITE(*,*) varseq(pfid,1:sp-1)
+        varseq_err(pfid) = -1
+      ENDIF
+!-
+!---- 1.3 Check if we have found the right overlap
+!-
+      IF (varseq_len(pfid) >= overlap(pfid)*2) THEN
+!-
+!------ We skip a few variables if needed as they could come
+!------ from the initialisation of the model.
+!-
+        DO ib = 0,sp-overlap(pfid)*2
+          IF ( learning(pfid) .AND.&
+            & SUM(ABS(varseq(pfid,ib+1:ib+overlap(pfid)) -&
+            & varseq(pfid,sp-overlap(pfid)+1:sp))) == 0 ) THEN
+            learning(pfid) = .FALSE.
+            varseq_len(pfid) = sp-overlap(pfid)-ib
+            varseq_pos(pfid) = overlap(pfid)+ib
+            varseq(pfid,1:varseq_len(pfid)) = &
+ &            varseq(pfid,ib+1:ib+varseq_len(pfid))
+          ENDIF
+        ENDDO
+      ENDIF
+    ENDIF
+  ELSE
+!-
+!-- 2.0 Now we know how the calls to histwrite are sequenced
+!--     and we can get a guess at the var ID
+!-
+    nn = varseq_pos(pfid)+1
+    IF (nn > varseq_len(pfid)) nn = 1
+!-
+    pvid = varseq(pfid,nn)
+!-
+    IF (TRIM(W_F(pfid)%W_V(pvid)%v_name) /= TRIM(pvarname)) THEN
+      CALL find_str (W_F(pfid)%W_V(1:W_F(pfid)%n_var)%v_name,pvarname,pos)
+      IF (pos > 0) THEN
+        pvid = pos
+      ELSE
+        CALL ipslerr (3,"histvar_seq", &
+ &  'The name of the variable you gave has not been declared',&
+ &  'You should use subroutine histdef for declaring variable', &
+ &  TRIM(pvarname))
+      ENDIF
+      varseq_err(pfid) = varseq_err(pfid)+1
+    ELSE
+!-
+!---- We only keep the new position if we have found the variable
+!---- this way. This way an out of sequence call to histwrite does
+!---- not defeat the process.
+!-
+      varseq_pos(pfid) = nn
+    ENDIF
+!-
+    IF (varseq_err(pfid) >= 10) THEN
+      WRITE(str70,'("for file ",I3)') pfid
+      CALL ipslerr (2,"histvar_seq", &
+ &  'There were 10 errors in the learned sequence of variables',&
+ &  str70,'This looks like a bug, please report it.')
+         varseq_err(pfid) = 0
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) &
+ &   'histvar_seq, end of the subroutine :',TRIM(pvarname),pvid
+  ENDIF
+!-------------------------
+END SUBROUTINE histvar_seq
+!===
+SUBROUTINE histsync (file)
+!---------------------------------------------------------------------
+!- This subroutine will synchronise all
+!- (or one if defined) opened files.
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! file  : optional argument for fileid
+  INTEGER,INTENT(in),OPTIONAL :: file
+!-
+  INTEGER :: ifile,nfid,iret
+!-
+  LOGICAL :: file_exists
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) WRITE(*,*) 'Entering loop on files : ',nb_files
+!-
+! 1.The loop on files to synchronise
+!-
+  DO ifile=1,nb_files
+!-
+    IF (PRESENT(file)) THEN
+      file_exists = (ifile == file)
+    ELSE
+      file_exists = .TRUE.
+    ENDIF
+!-
+    IF (file_exists) THEN
+      IF (l_dbg) THEN
+        WRITE(*,*) 'Synchronising specified file number :',file
+      ENDIF
+      nfid = W_F(ifile)%ncfid
+      iret = NF90_SYNC (nfid)
+    ENDIF
+!-
+  ENDDO
+!----------------------
+END SUBROUTINE histsync
+!===
+SUBROUTINE histclo (fid)
+!---------------------------------------------------------------------
+!- This subroutine will close all (or one if defined) opened files
+!-
+!- VERSION
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+! fid  : optional argument for fileid
+  INTEGER,INTENT(in),OPTIONAL :: fid
+!-
+  INTEGER :: ifile,nfid,nvid,iret,iv
+  INTEGER :: start_loop,end_loop
+  CHARACTER(LEN=70) :: str70
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) WRITE(*,*) 'Entering loop on files :',nb_files
+!-
+  IF (PRESENT(fid)) THEN
+    start_loop = fid
+    end_loop = fid
+  ELSE
+    start_loop = 1
+    end_loop = nb_files
+  ENDIF
+!-
+  DO ifile=start_loop,end_loop
+    IF (l_dbg) WRITE(*,*) 'Closing specified file number :',ifile
+    nfid = W_F(ifile)%ncfid
+    iret = NF90_REDEF (nfid)
+!---
+!-- 1. Loop on the number of variables to add some final information
+!---
+    IF (l_dbg) WRITE(*,*) 'Entering loop on vars : ',W_F(ifile)%n_var
+    DO iv=1,W_F(ifile)%n_var
+      IF (W_F(ifile)%W_V(iv)%hist_wrt_rng) THEN
+        IF (l_dbg) THEN
+          WRITE(*,*) 'min value for file :',ifile,' var n. :',iv, &
+         &           ' is : ',W_F(ifile)%W_V(iv)%hist_minmax(1)
+          WRITE(*,*) 'max value for file :',ifile,' var n. :',iv, &
+         &           ' is : ',W_F(ifile)%W_V(iv)%hist_minmax(2)
+        ENDIF
+        IF (W_F(ifile)%W_V(iv)%hist_calc_rng) THEN
+!-------- Put the min and max values on the file
+          nvid = W_F(ifile)%W_V(iv)%ncvid
+          iret = NF90_PUT_ATT (nfid,nvid,'valid_min', &
+ &                 REAL(W_F(ifile)%W_V(iv)%hist_minmax(1),KIND=4))
+          iret = NF90_PUT_ATT (nfid,nvid,'valid_max', &
+ &                 REAL(W_F(ifile)%W_V(iv)%hist_minmax(2),KIND=4))
+        ENDIF
+      ENDIF
+    ENDDO
+!---
+!-- 2. Close the file
+!---
+    IF (l_dbg) WRITE(*,*) 'close file :',nfid
+    iret = NF90_CLOSE (nfid)
+    IF (iret /= NF90_NOERR) THEN
+      WRITE(str70,'("This file has been already closed :",I3)') ifile
+      CALL ipslerr (2,'histclo',str70,'','')
+    ENDIF
+  ENDDO
+!---------------------
+END SUBROUTINE histclo
+!===
+SUBROUTINE ioconf_modname (str)
+!---------------------------------------------------------------------
+!- This subroutine allows to configure the name
+!- of the model written into the file
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: str
+!---------------------------------------------------------------------
+  IF (.NOT.lock_modname) THEN
+    model_name = str(1:MIN(LEN_TRIM(str),80))
+    lock_modname = .TRUE.
+  ELSE
+    CALL ipslerr (2,"ioconf_modname", &
+   &  'The model name can only be changed once and only', &
+   &  'before it is used. It is now set to :',model_name)
+  ENDIF
+!----------------------------
+END SUBROUTINE ioconf_modname
+!-
+!===
+!-
+!-----------------
+END MODULE histcom
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/ioipsl.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/ioipsl.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/ioipsl.f90	(revision 329)
@@ -0,0 +1,17 @@
+MODULE ioipsl
+!
+!$Id: ioipsl.f90 386 2008-09-04 08:38:48Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!
+  USE errioipsl 
+  USE stringop
+  USE mathelp    
+  USE getincom
+  USE calendar   
+  USE fliocom    
+  USE flincom    
+  USE histcom    
+  USE restcom
+END MODULE ioipsl
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/mathelp.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/mathelp.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/mathelp.f90	(revision 329)
@@ -0,0 +1,3116 @@
+MODULE mathelp
+!-
+!$Id: mathelp.f90 440 2008-11-26 10:58:38Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+  USE errioipsl,ONLY : ipslerr
+  USE stringop
+!-
+  PRIVATE
+  PUBLIC :: mathop,moycum,buildop
+!-
+  INTERFACE mathop
+    MODULE PROCEDURE mathop_r11,mathop_r21,mathop_r31
+  END INTERFACE
+!-
+!- Variables used to detect and identify the operations
+!-
+  CHARACTER(LEN=80),SAVE :: &
+ &  seps='( ) , + - / * ^', ops = '+ - * / ^', mima = 'min max'
+  CHARACTER(LEN=250),SAVE :: &
+ &  funcs = 'sin cos tan asin acos atan exp log sqrt chs abs '&
+ & //'cels kelv deg rad gather scatter fill coll undef only ident'
+  CHARACTER(LEN=120),SAVE :: &
+ &  indexfu = 'gather, scatter, fill, coll, undef, only'
+!---------------------------------------------------------------------
+CONTAINS
+!===
+SUBROUTINE buildop (str,ex_topps,topp,nbops_max, &
+ &                  missing_val,opps,scal,nbops)
+!---------------------------------------------------------------------
+!- This subroutine decomposes the input string in the elementary
+!- functions which need to be applied to the vector of data.
+!- This vector is represented by X in the string.
+!- This subroutine is the driver of the decomposition and gets
+!- the time operation but then call decoop for the other operations
+!-
+!- INPUT
+!-
+!- str      : String containing the operations
+!- ex_toops : The time operations that can be expected
+!-            within the string
+!-
+!- OUTPUT
+!-
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=80) :: str
+  CHARACTER(LEN=*) :: ex_topps
+  CHARACTER(LEN=7) :: topp
+  INTEGER :: nbops_max,nbops
+  CHARACTER(LEN=7) :: opps(nbops_max)
+  REAL :: scal(nbops_max),missing_val
+!-
+  CHARACTER(LEN=80) :: new_str
+  INTEGER :: leng,ind_opb,ind_clb
+!-
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,*) 'buildop : Some preliminary cleaning'
+!-
+  leng = LEN_TRIM(str)
+  IF ( str(1:1) == '(' .AND. str(leng:leng) == ')' ) THEN
+    str = str(2:leng-1)
+    leng = leng-2
+  ENDIF
+!-
+  IF (check) &
+ &  WRITE(*,*) 'buildop : Starting to test the various options'
+!-
+  IF (leng <= 5 .AND. INDEX(ex_topps,str(1:leng)) > 0) THEN
+    IF (check) WRITE(*,*) 'buildop : Time operation only'
+    nbops = 0
+    topp = str(1:leng)
+  ELSE
+    IF (check) THEN
+      WRITE(*,*) 'buildop : Time operation and something else'
+    ENDIF
+!--
+    ind_opb = INDEX(str(1:leng),'(')
+    IF (ind_opb > 0) THEN
+      IF (INDEX(ex_topps,str(1:ind_opb-1)) > 0) THEN
+        IF (check) THEN
+          WRITE(*,'(2a)') &
+ &          ' buildop : Extract time operation from : ',str
+        ENDIF
+        topp = str(1:ind_opb-1)
+        ind_clb = INDEX(str(1:leng),')',BACK=.TRUE.)
+        new_str = str(ind_opb+1:ind_clb-1)
+        IF (check) THEN
+          WRITE(*,'(2a,2I3)') &
+ &          ' buildop : Call decoop ',new_str,ind_opb,ind_clb
+        ENDIF
+        CALL decoop (new_str,nbops_max,missing_val,opps,scal,nbops)
+      ELSE
+        CALL ipslerr(3,'buildop', &
+ &        'time operation does not exist',str(1:ind_opb-1),' ')
+      ENDIF
+    ELSE
+      CALL ipslerr(3,'buildop', &
+ &      'some long operation exists but wihout parenthesis', &
+ &      str(1:leng),' ')
+    ENDIF
+  ENDIF
+!-
+  IF (check) THEN
+    DO leng=1,nbops
+      WRITE(*,*) &
+ &      'buildop : i -- opps, scal : ',leng,opps(leng),scal(leng)
+    ENDDO
+  ENDIF
+!---------------------
+END SUBROUTINE buildop
+!===
+SUBROUTINE decoop (pstr,nbops_max,missing_val,opps,scal,nbops)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=80) :: pstr
+  INTEGER :: nbops_max,nbops
+  CHARACTER(LEN=7) :: opps(nbops_max)
+  REAL :: scal(nbops_max),missing_val
+!-
+  CHARACTER(LEN=1) :: f_char(2),s_char(2)
+  INTEGER :: nbsep,f_pos(2),s_pos(2)
+  CHARACTER(LEN=20) :: opp_str,scal_str
+  CHARACTER(LEN=80) :: str
+  INTEGER :: xpos,leng,ppos,epos,int_tmp
+  CHARACTER(LEN=3) :: tl,dl
+  CHARACTER(LEN=10) :: fmt
+!-
+  LOGICAL :: check = .FALSE.,prio
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,'(2a)') ' decoop : Incoming string : ',pstr
+!-
+  nbops = 0
+  str = pstr
+!-
+  CALL findsep (str,nbsep,f_char,f_pos,s_char,s_pos)
+  IF (check) WRITE(*,*) 'decoop : Out of findsep',nbsep
+  DO WHILE (nbsep > 0)
+    xpos = INDEX(str,'X')
+    leng = LEN_TRIM(str)
+    nbops = nbops+1
+!--
+    IF (check) THEN
+      WRITE(*,*) 'decoop : str -->',str(1:leng)
+      WRITE(*,*) s_char(1),'-',f_char(1),'|',f_char(2),'-',s_char(2)
+      WRITE(*,*) s_pos(1),'-',f_pos(1),'|',f_pos(2),'-',s_pos(2)
+    ENDIF
+!--
+    IF (nbops > nbops_max-1) THEN
+      CALL ipslerr(3,'decoop','Expression too complex',str,' ')
+    ENDIF
+!--
+    IF (check) WRITE(*,*) 'decoop : --',nbops,' ',str(1:leng)
+!---
+!-- Start the analysis of the syntax. 3 types of constructs
+!-- are recognized.  They are scanned sequentialy
+!---
+    IF (nbsep == 1) THEN
+      IF (check) WRITE(*,*) 'decoop : Only one operation'
+      IF (INDEX(ops,f_char(1)) > 0) THEN
+!------ Type : scal+X
+        IF (f_char(1) == '-' .OR. f_char(1) == '/') THEN
+          opp_str = f_char(1)//'I'
+        ELSE
+          opp_str = f_char(1)
+        ENDIF
+        scal_str = str(s_pos(1)+1:f_pos(1)-1)
+        str = 'X'
+      ELSE IF (INDEX(ops,f_char(2)) > 0) THEN
+!------ Type : X+scal
+        opp_str = f_char(2)
+        scal_str = str(f_pos(2)+1:s_pos(2)-1)
+        str = 'X'
+      ELSE
+        CALL ipslerr(3,'decoop', &
+ &        'Unknown operations of type X+scal',f_char(1),pstr)
+      ENDIF
+    ELSE
+      IF (check) WRITE(*,*) 'decoop : More complex operation'
+      IF ( f_char(1) == '(' .AND. f_char(2) == ')' ) THEN
+!------ Type : sin(X)
+        opp_str = str(s_pos(1)+1:f_pos(1)-1)
+        scal_str = '?'
+        str = str(1:s_pos(1))//'X'//str(f_pos(2)+1:leng)
+      ELSE IF (    (f_char(1) == '(' .AND. f_char(2) == ',')&
+ &             .OR.(f_char(1) == ',' .AND. f_char(2) == ')')) THEN
+!------ Type : max(X,scal) or max(scal,X)
+        IF (f_char(1) == '(' .AND. s_char(2) == ')') THEN
+!-------- Type : max(X,scal)
+          opp_str = str(f_pos(1)-3:f_pos(1)-1)
+          scal_str = str(f_pos(2)+1:s_pos(2)-1)
+          str = str(1:f_pos(1)-4)//'X'//str(s_pos(2)+1:leng)
+        ELSE IF (f_char(1) == ',' .AND. s_char(1) == '(') THEN
+!-------- Type : max(scal,X)
+          opp_str = str(s_pos(1)-3:s_pos(1)-1)
+          scal_str = str(s_pos(1)+1:f_pos(1)-1)
+          str = str(1:s_pos(1)-4)//'X'//str(f_pos(2)+1:leng)
+        ELSE
+          CALL ipslerr(3,'decoop','Syntax error 1',str,' ')
+        ENDIF
+      ELSE
+        prio = (f_char(2) == '*').OR.(f_char(2) == '^')
+        IF (     (INDEX(ops,f_char(1)) > 0) &
+ &          .AND.(xpos-f_pos(1) == 1).AND.(.NOT.prio) ) THEN
+!-------- Type : ... scal+X ...
+          IF (f_char(1) == '-' .OR. f_char(1) == '/') THEN
+            opp_str = f_char(1)//'I'
+          ELSE
+            opp_str = f_char(1)
+          ENDIF
+          scal_str = str(s_pos(1)+1:f_pos(1)-1)
+          str = str(1:s_pos(1))//'X'//str(f_pos(1)+2:leng)
+        ELSE IF (     (INDEX(ops,f_char(2)) > 0) &
+ &               .AND.(f_pos(2)-xpos == 1) ) THEN
+!-------- Type : ... X+scal ...
+          opp_str = f_char(2)
+          scal_str = str(f_pos(2)+1:s_pos(2)-1)
+          str = str(1:f_pos(2)-2)//'X'//str(s_pos(2):leng)
+        ELSE
+          CALL ipslerr(3,'decoop','Syntax error 2',str,' ')
+        ENDIF
+      ENDIF
+    ENDIF
+!---
+    IF (check) WRITE(*,*) 'decoop : Finished syntax,str = ',TRIM(str)
+!---
+!-- Now that the different components of the operation are identified
+!-- we transform them into what is going to be used in the program
+!---
+    IF (INDEX(scal_str,'?') > 0) THEN
+      IF (INDEX(funcs,opp_str(1:LEN_TRIM(opp_str))) > 0) THEN
+        opps(nbops) = opp_str(1:LEN_TRIM(opp_str))
+        scal(nbops) =  missing_val
+      ELSE
+        CALL ipslerr(3,'decoop', &
+ &        'Unknown function',opp_str(1:LEN_TRIM(opp_str)),' ')
+      ENDIF
+    ELSE
+      leng = LEN_TRIM(opp_str)
+      IF (INDEX(mima,opp_str(1:leng)) > 0) THEN
+        opps(nbops) = 'fu'//opp_str(1:leng)
+      ELSE
+        IF (INDEX(opp_str(1:leng),'+') > 0) THEN
+          opps(nbops) = 'add'
+        ELSE IF (INDEX(opp_str(1:leng),'-I') > 0) THEN
+          opps(nbops) = 'subi'
+        ELSE IF (INDEX(opp_str(1:leng),'-') > 0) THEN
+          opps(nbops) = 'sub'
+        ELSE IF (INDEX(opp_str(1:leng),'*') > 0) THEN
+          opps(nbops) = 'mult'
+        ELSE IF (INDEX(opp_str(1:leng),'/') > 0) THEN
+          opps(nbops) = 'div'
+        ELSE IF (INDEX(opp_str(1:leng),'/I') > 0) THEN
+          opps(nbops) = 'divi'
+        ELSE IF (INDEX(opp_str(1:leng),'^') > 0) THEN
+          opps(nbops) = 'power'
+        ELSE
+          CALL ipslerr(3,'decoop', &
+ &          'Unknown operation',opp_str(1:leng),' ')
+        ENDIF
+      ENDIF
+!-----
+      leng = LEN_TRIM(scal_str)
+      ppos = INDEX(scal_str,'.')
+      epos = INDEX(scal_str,'e')
+      IF (epos == 0) epos = INDEX(scal_str,'E')
+!-----
+!---- Try to catch a few errors
+!-----
+      IF (INDEX(ops,scal_str) > 0) THEN
+        CALL ipslerr(3,'decoop', &
+ &        'Strange scalar you have here ',scal_str,pstr)
+      ENDIF
+      IF (epos > 0) THEN
+        WRITE(tl,'(I3.3)') leng
+        WRITE(dl,'(I3.3)') epos-ppos-1
+        fmt='(e'//tl//'.'//dl//')'
+        READ(scal_str,fmt) scal(nbops)
+      ELSE IF (ppos > 0) THEN
+        WRITE(tl,'(I3.3)') leng
+        WRITE(dl,'(I3.3)') leng-ppos
+        fmt='(f'//tl//'.'//dl//')'
+        READ(scal_str,fmt) scal(nbops)
+      ELSE
+        WRITE(tl,'(I3.3)') leng
+        fmt = '(I'//tl//')'
+        READ(scal_str,fmt) int_tmp
+        scal(nbops) = REAL(int_tmp)
+      ENDIF
+    ENDIF
+    IF (check) WRITE(*,*) 'decoop : Finished interpretation'
+    CALL findsep(str,nbsep,f_char,f_pos,s_char,s_pos)
+  ENDDO
+!--------------------
+END SUBROUTINE decoop
+!===
+SUBROUTINE findsep (str,nbsep,f_char,f_pos,s_char,s_pos)
+!---------------------------------------------------------------------
+!- Subroutine finds all separators in a given string
+!- It returns the following information about str :
+!-   f_char : The first separation character
+!-            (1 for before and 2 for after)
+!-   f_pos  : The position of the first separator
+!-   s_char : The second separation character
+!-            (1 for before and 2 for after)
+!-   s_pos  : The position of the second separator
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=80) :: str
+  INTEGER :: nbsep
+  CHARACTER(LEN=1),DIMENSION(2) :: f_char,s_char
+  INTEGER,DIMENSION(2) :: f_pos,s_pos
+!-
+  CHARACTER(LEN=70) :: str_tmp
+  LOGICAL :: f_found,s_found
+  INTEGER :: ind,xpos,leng,i
+!-
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  IF (check) WRITE(*,*) 'findsep : call cleanstr: ',TRIM(str)
+!-
+  CALL cleanstr(str)
+!-
+  IF (check) WRITE(*,*) 'findsep : out of cleanstr: ',TRIM(str)
+!-
+  xpos = INDEX(str,'X')
+  leng = LEN_TRIM(str)
+!-
+  f_pos(1:2) = (/ 0,leng+1 /)
+  f_char(1:2) = (/ '?','?' /)
+  s_pos(1:2) = (/ 0,leng+1 /)
+  s_char(1:2) = (/ '?','?' /)
+!-
+  nbsep = 0
+!-
+  f_found = .FALSE.
+  s_found = .FALSE.
+  IF (xpos > 1) THEN
+    DO i=xpos-1,1,-1
+      ind = INDEX(seps,str(i:i))
+      IF (ind > 0) THEN
+        IF (.NOT.f_found) THEN
+          f_char(1) = str(i:i)
+          f_pos(1) = i
+          nbsep = nbsep+1
+          f_found = .TRUE.
+        ELSE IF (.NOT.s_found) THEN
+          s_char(1) = str(i:i)
+          s_pos(1) = i
+          nbsep = nbsep+1
+          s_found = .TRUE.
+        ENDIF
+      ENDIF
+    ENDDO
+  ENDIF
+!-
+  f_found = .FALSE.
+  s_found = .FALSE.
+  IF (xpos < leng) THEN
+    DO i=xpos+1,leng
+      ind = INDEX(seps,str(i:i))
+      IF (ind > 0) THEN
+        IF (.NOT.f_found) THEN
+          f_char(2) = str(i:i)
+          f_pos(2) = i
+          nbsep = nbsep+1
+          f_found = .TRUE.
+        ELSE IF (.NOT.s_found) THEN
+          s_char(2) = str(i:i)
+          s_pos(2) = i
+          nbsep = nbsep+1
+          s_found = .TRUE.
+        ENDIF
+      ENDIF
+    ENDDO
+  ENDIF
+!-
+  IF (nbsep > 4) THEN
+    WRITE(str_tmp,'("number :",I3)') nbsep
+    CALL ipslerr(3,'findsep', &
+ &    'How can I find that many separators',str_tmp,str)
+  ENDIF
+!-
+  IF (check) WRITE(*,*) 'Finished findsep : ',nbsep,leng
+!---------------------
+END SUBROUTINE findsep
+!===
+SUBROUTINE cleanstr(str)
+!---------------------------------------------------------------------
+!- We clean up the string by taking out the extra () and puting
+!- everything in lower case except for the X describing the variable
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=80) :: str
+!-
+  INTEGER :: ind,leng,ic,it
+  LOGICAL :: check = .FALSE.
+!---------------------------------------------------------------------
+  leng = LEN_TRIM(str)
+  CALL strlowercase(str)
+!-
+  ind = INDEX(str,'x')
+  IF (check) THEN
+    WRITE (*,*) 'cleanstr 1.0 : ind = ',ind, &
+&               ' str = ',str(1:leng),'---'
+  ENDIF
+!-
+! If the character before the x is not a letter then we can assume
+! that it is the variable and promote it to a capital letter
+!-
+  DO WHILE (ind > 0)
+    ic = 0
+    IF (ind > 1) ic = IACHAR(str(ind-1:ind-1))
+    IF (ic < 97 .OR. ic > 122) THEN
+      str(ind:ind) = 'X'
+    ENDIF
+    it = INDEX(str(ind+1:leng),'x')
+    IF (it > 0) THEN
+      ind = ind+it
+    ELSE
+      ind = it
+    ENDIF
+  ENDDO
+!-
+  IF (check) WRITE (*,*) 'cleanstr 2.0 : str = ',str(1:leng),'---'
+!-
+  IF ( str(1:1) == '(' .AND. str(leng:leng) == ')' ) THEN
+    str = str(2:leng-1)
+  ENDIF
+!-
+  IF (check) WRITE (*,*) 'cleanstr 3.0 : str = ',str(1:leng),'---'
+!-
+  leng = LEN_TRIM(str)
+  ind = INDEX(str,'((X))')
+  IF (ind > 0) THEN
+    str=str(1:ind-1)//'(X)'//str(ind+5:leng)//'  '
+  ENDIF
+!-
+  IF (check) WRITE (*,*) 'cleanstr 4.0 : str = ',str(1:leng),'---'
+!-
+  leng = LEN_TRIM(str)
+  ind = INDEX(str,'(X)')
+  IF (ind > 0 .AND. ind+3 < leng) THEN
+    IF (      (INDEX(seps,str(ind-1:ind-1)) > 0) &
+ &      .AND. (INDEX(seps,str(ind+3:ind+3)) > 0) ) THEN
+      str=str(1:ind-1)//'X'//str(ind+3:leng)//'  '
+    ENDIF
+  ENDIF
+!-
+  IF (check) WRITE (*,*) 'cleanstr 5.0 : str = ',str(1:leng),'---'
+!-
+  leng = LEN_TRIM(str)
+  ind = INDEX(str(1:leng),' ')
+  DO WHILE (ind > 0)
+    str=str(1:ind-1)//str(ind+1:leng)//' '
+    leng = LEN_TRIM(str)
+    ind = INDEX(str(1:leng),' ')
+  ENDDO
+!-
+  IF (check) WRITE (*,*) 'cleanstr 6.0 : str = ',str(1:leng),'---'
+!----------------------
+END SUBROUTINE cleanstr
+!===
+!===
+SUBROUTINE mathop_r11 &
+ &  (fun,nb,work_in,miss_val,nb_index,nindex,scal,nb_max,work_out)
+!---------------------------------------------------------------------
+!- This subroutines gives an interface to the various operation
+!- which are allowed. The interface is general enough to allow its use
+!- for other cases.
+!-
+!- INPUT
+!-
+!- fun      : function to be applied to the vector of data
+!- nb       : Length of input vector
+!- work_in  : Input vector of data (REAL)
+!- miss_val : The value of the missing data flag (it has to be a
+!-            maximum value, in f90 : huge( a real ))
+!- nb_index : Length of index vector
+!- nindex   : Vector of indices
+!- scal     : A scalar value for vector/scalar operations
+!- nb_max   : maximum length of output vector
+!-
+!- OUTPUT
+!-
+!- nb_max   : Actual length of output variable
+!- work_out : Output vector after the operation was applied
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=7) :: fun
+  INTEGER :: nb,nb_max,nb_index
+  INTEGER :: nindex(nb_index)
+  REAL :: work_in(nb),scal,miss_val
+  REAL :: work_out(nb_max)
+!-
+  INTEGER :: ierr
+!-
+  INTRINSIC SIN,COS,TAN,ASIN,ACOS,ATAN,EXP,LOG,SQRT,ABS
+!---------------------------------------------------------------------
+  ierr = 0
+!-
+  IF (scal >= miss_val-1.) THEN
+    IF (INDEX(indexfu,fun(1:LEN_TRIM(fun))) == 0) THEN
+      SELECT CASE (fun)
+      CASE('sin')
+        ierr = ma_sin_r11(nb,work_in,nb_max,work_out)
+      CASE('cos')
+        ierr = ma_cos_r11(nb,work_in,nb_max,work_out)
+      CASE('tan')
+        ierr = ma_tan_r11(nb,work_in,nb_max,work_out)
+      CASE('asin')
+        ierr = ma_asin_r11(nb,work_in,nb_max,work_out)
+      CASE('acos')
+        ierr = ma_acos_r11(nb,work_in,nb_max,work_out)
+      CASE('atan')
+        ierr = ma_atan_r11(nb,work_in,nb_max,work_out)
+      CASE('exp')
+        ierr = ma_exp_r11(nb,work_in,nb_max,work_out)
+      CASE('log')
+        ierr = ma_log_r11(nb,work_in,nb_max,work_out)
+      CASE('sqrt')
+        ierr = ma_sqrt_r11(nb,work_in,nb_max,work_out)
+      CASE('chs')
+        ierr = ma_chs_r11(nb,work_in,nb_max,work_out)
+      CASE('abs')
+        ierr = ma_abs_r11(nb,work_in,nb_max,work_out)
+      CASE('cels')
+        ierr = ma_cels_r11(nb,work_in,nb_max,work_out)
+      CASE('kelv')
+        ierr = ma_kelv_r11(nb,work_in,nb_max,work_out)
+      CASE('deg')
+        ierr = ma_deg_r11(nb,work_in,nb_max,work_out)
+      CASE('rad')
+        ierr = ma_rad_r11(nb,work_in,nb_max,work_out)
+      CASE('ident')
+        ierr = ma_ident_r11(nb,work_in,nb_max,work_out)
+      CASE DEFAULT
+        CALL ipslerr(3,"mathop", &
+ &        'scalar variable undefined and no indexing', &
+ &        'but still unknown function',fun)
+      END SELECT
+      IF (ierr > 0) THEN
+        CALL ipslerr(3,"mathop", &
+ &        'Error while executing a simple function',fun,' ')
+      ENDIF
+    ELSE
+      SELECT CASE (fun)
+      CASE('gather')
+        ierr = ma_fugath_r11(nb,work_in,nb_index,nindex, &
+&                            miss_val,nb_max,work_out)
+      CASE('scatter')
+        IF (nb_index > nb) THEN
+          work_out(1:nb_max) = miss_val
+          ierr=1
+        ELSE
+          ierr = ma_fuscat_r11(nb,work_in,nb_index,nindex, &
+&                              miss_val,nb_max,work_out)
+        ENDIF
+      CASE('coll')
+        ierr = ma_fucoll_r11(nb,work_in,nb_index,nindex, &
+&                            miss_val,nb_max,work_out)
+      CASE('fill')
+        ierr = ma_fufill_r11(nb,work_in,nb_index,nindex, &
+&                            miss_val,nb_max,work_out)
+      CASE('undef')
+        ierr = ma_fuundef_r11(nb,work_in,nb_index,nindex, &
+&                            miss_val,nb_max,work_out)
+      CASE('only')
+        ierr = ma_fuonly_r11(nb,work_in,nb_index,nindex, &
+&                            miss_val,nb_max,work_out)
+      CASE DEFAULT
+        CALL ipslerr(3,"mathop", &
+ &        'scalar variable undefined and indexing',&
+ &        'was requested but with unknown function',fun)
+      END SELECT
+      IF (ierr > 0) THEN
+        CALL ipslerr(3,"mathop_r11", &
+ &        'Error while executing an indexing function',fun,' ')
+      ENDIF
+    ENDIF
+  ELSE
+    SELECT CASE (fun)
+    CASE('fumin')
+      ierr = ma_fumin_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('fumax')
+      ierr = ma_fumax_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('add')
+      ierr = ma_add_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('subi')
+      ierr = ma_subi_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('sub')
+      ierr = ma_sub_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('mult')
+      ierr = ma_mult_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('div')
+      ierr = ma_div_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('divi')
+      ierr = ma_divi_r11(nb,work_in,scal,nb_max,work_out)
+    CASE('power')
+      ierr = ma_power_r11(nb,work_in,scal,nb_max,work_out)
+    CASE DEFAULT
+      CALL ipslerr(3,"mathop", &
+ &      'Unknown operation with a scalar',fun,' ')
+    END SELECT
+    IF (ierr > 0) THEN
+      CALL ipslerr(3,"mathop", &
+ &      'Error while executing a scalar function',fun,' ')
+    ENDIF
+  ENDIF
+!------------------------
+END SUBROUTINE mathop_r11
+!-
+!=== FUNCTIONS (only one argument)
+!-
+INTEGER FUNCTION ma_sin_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = SIN(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_sin_r11 = 0
+!----------------------
+END FUNCTION ma_sin_r11
+!===
+INTEGER FUNCTION ma_cos_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = COS(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_cos_r11 = 0
+!----------------------
+END FUNCTION ma_cos_r11
+!===
+INTEGER FUNCTION ma_tan_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = TAN(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_tan_r11 = 0
+!----------------------
+END FUNCTION ma_tan_r11
+!===
+INTEGER FUNCTION ma_asin_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = ASIN(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_asin_r11 = 0
+!-----------------------
+END FUNCTION ma_asin_r11
+!===
+INTEGER FUNCTION ma_acos_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = ACOS(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_acos_r11 = 0
+!-----------------------
+END FUNCTION ma_acos_r11
+!===
+INTEGER FUNCTION ma_atan_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = ATAN(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_atan_r11 = 0
+!-----------------------
+END FUNCTION ma_atan_r11
+!===
+INTEGER FUNCTION ma_exp_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = EXP(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_exp_r11 = 0
+!----------------------
+END FUNCTION ma_exp_r11
+!===
+INTEGER FUNCTION ma_log_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = log(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_log_r11 = 0
+!----------------------
+END FUNCTION ma_log_r11
+!===
+INTEGER FUNCTION ma_sqrt_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = SQRT(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_sqrt_r11 = 0
+!-----------------------
+END FUNCTION ma_sqrt_r11
+!===
+INTEGER FUNCTION ma_abs_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = ABS(x(i))
+  ENDDO
+!-
+  nbo = nb
+  ma_abs_r11 = 0
+!----------------------
+END FUNCTION ma_abs_r11
+!===
+INTEGER FUNCTION ma_chs_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)*(-1.)
+  ENDDO
+!-
+  nbo = nb
+  ma_chs_r11 = 0
+!----------------------
+END FUNCTION ma_chs_r11
+!===
+INTEGER FUNCTION ma_cels_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)-273.15
+  ENDDO
+!-
+  nbo = nb
+  ma_cels_r11 = 0
+!-----------------------
+END FUNCTION ma_cels_r11
+!===
+INTEGER FUNCTION ma_kelv_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)+273.15
+  ENDDO
+!-
+  nbo = nb
+  ma_kelv_r11 = 0
+!-----------------------
+END FUNCTION ma_kelv_r11
+!===
+INTEGER FUNCTION ma_deg_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)*57.29577951
+  ENDDO
+!-
+  nbo = nb
+  ma_deg_r11 = 0
+!-----------------------
+END FUNCTION ma_deg_r11
+!===
+INTEGER FUNCTION ma_rad_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)*0.01745329252
+  ENDDO
+!-
+  nbo = nb
+  ma_rad_r11 = 0
+!----------------------
+END FUNCTION ma_rad_r11
+!===
+INTEGER FUNCTION ma_ident_r11(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,i
+  REAL :: x(nb),y(nbo)
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)
+  ENDDO
+!-
+  nbo = nb
+  ma_ident_r11 = 0
+!------------------------
+END FUNCTION ma_ident_r11
+!-
+!=== OPERATIONS (two argument)
+!-
+INTEGER FUNCTION ma_add_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)+s
+  ENDDO
+!-
+  nbo = nb
+  ma_add_r11 = 0
+!-----------------------
+  END FUNCTION ma_add_r11
+!===
+INTEGER FUNCTION ma_sub_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)-s
+  ENDDO
+!-
+  nbo = nb
+  ma_sub_r11 = 0
+!----------------------
+END FUNCTION ma_sub_r11
+!===
+INTEGER FUNCTION ma_subi_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) =  s-x(i)
+  ENDDO
+!-
+  nbo = nb
+  ma_subi_r11 = 0
+!-----------------------
+END FUNCTION ma_subi_r11
+!===
+INTEGER FUNCTION ma_mult_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)*s
+  ENDDO
+!-
+  nbo = nb
+  ma_mult_r11 = 0
+!-----------------------
+END FUNCTION ma_mult_r11
+!===
+INTEGER FUNCTION ma_div_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)/s
+  ENDDO
+!-
+  nbo = nb
+  ma_div_r11 = 0
+!-----------------------
+  END FUNCTION ma_div_r11
+!===
+INTEGER FUNCTION ma_divi_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = s/x(i)
+  ENDDO
+!-
+  nbo = nb
+  ma_divi_r11 = 0
+!-----------------------
+END FUNCTION ma_divi_r11
+!===
+INTEGER FUNCTION ma_power_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = x(i)**s
+  ENDDO
+!-
+  nbo = nb
+  ma_power_r11 = 0
+!-----------------------
+END FUNCTION ma_power_r11
+!===
+INTEGER FUNCTION ma_fumin_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = MIN(x(i),s)
+  ENDDO
+!-
+  nbo = nb
+  ma_fumin_r11 = 0
+!------------------------
+END FUNCTION ma_fumin_r11
+!===
+INTEGER FUNCTION ma_fumax_r11(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo
+  REAL :: x(nb),s,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,nb
+    y(i) = MAX(x(i),s)
+  ENDDO
+!-
+  nbo = nb
+  ma_fumax_r11 = 0
+!------------------------
+END FUNCTION ma_fumax_r11
+!===
+INTEGER FUNCTION ma_fuscat_r11(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb),miss_val,y(nbo)
+!-
+  INTEGER :: i,ii,ipos
+!---------------------------------------------------------------------
+  ma_fuscat_r11 = 0
+!-
+  y(1:nbo) = miss_val
+!-
+  IF (nbi <= nb) THEN
+    ipos = 0
+    DO i=1,nbi
+      IF (ind(i) <= nbo .AND. ind(i) > 0) THEN
+        ipos = ipos+1
+        y(ind(i)) = x(ipos)
+      ELSE
+        IF (ind(i) > nbo) ma_fuscat_r11  = ma_fuscat_r11+1
+      ENDIF
+    ENDDO
+!-- Repeat the data if needed
+    IF (MINVAL(ind) < 0) THEN
+      DO i=1,nbi
+        IF (ind(i) <= 0) THEN
+          DO ii=1,ABS(ind(i))-1
+            IF (ind(i+1)+ii <= nbo) THEN
+              y(ind(i+1)+ii) = y(ind(i+1))
+            ELSE
+              ma_fuscat_r11  = ma_fuscat_r11+1
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+    ma_fuscat_r11  = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fuscat_r11
+!===
+INTEGER FUNCTION ma_fugath_r11(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb),miss_val,y(nbo)
+!-
+  INTEGER :: i,ipos
+!---------------------------------------------------------------------
+  IF (nbi <= nbo) THEN
+    ma_fugath_r11 = 0
+    y(1:nbo) = miss_val
+    ipos = 0
+    DO i=1,nbi
+      IF (ipos+1 <= nbo) THEN
+        IF (ind(i) > 0) THEN
+          ipos = ipos+1
+          y(ipos) = x(ind(i))
+        ENDIF
+      ELSE
+        IF (ipos+1 > nbo) ma_fugath_r11  = ma_fugath_r11+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fugath_r11 = 1
+  ENDIF
+!-
+  nbo = ipos
+!-------------------------
+END FUNCTION ma_fugath_r11
+!===
+INTEGER FUNCTION ma_fufill_r11(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb),miss_val,y(nbo)
+!-
+  INTEGER :: i,ii,ipos
+!---------------------------------------------------------------------
+  ma_fufill_r11 = 0
+!-
+  IF (nbi <= nb) THEN
+    ipos = 0
+    DO i=1,nbi
+      IF (ind(i) <= nbo .AND. ind(i) > 0) THEN
+        ipos = ipos+1
+        y(ind(i)) = x(ipos)
+      ELSE
+        IF (ind(i) > nbo) ma_fufill_r11  = ma_fufill_r11+1
+      ENDIF
+    ENDDO
+!-- Repeat the data if needed
+    IF (MINVAL(ind) < 0) THEN
+      DO i=1,nbi
+        IF (ind(i) <= 0) THEN
+          DO ii=1,ABS(ind(i))-1
+            IF (ind(i+1)+ii <= nbo) THEN
+              y(ind(i+1)+ii) = y(ind(i+1))
+            ELSE
+              ma_fufill_r11  = ma_fufill_r11+1
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+    ma_fufill_r11  = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fufill_r11
+!===
+INTEGER FUNCTION ma_fucoll_r11(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb),miss_val,y(nbo)
+!-
+  INTEGER :: i,ipos
+!---------------------------------------------------------------------
+  IF (nbi <= nbo) THEN
+    ma_fucoll_r11 = 0
+    ipos = 0
+    DO i=1,nbi
+      IF (ipos+1 <= nbo) THEN
+        IF (ind(i) > 0) THEN
+          ipos = ipos+1
+          y(ipos) = x(ind(i))
+        ENDIF
+      ELSE
+        IF (ipos+1 > nbo) ma_fucoll_r11  = ma_fucoll_r11+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fucoll_r11 = 1
+  ENDIF
+!-
+  nbo = ipos
+!-------------------------
+END FUNCTION ma_fucoll_r11
+!===
+INTEGER FUNCTION ma_fuundef_r11(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb),miss_val,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  IF (nbi <= nbo .AND. nbo == nb) THEN
+    ma_fuundef_r11 = 0
+    DO i=1,nbo
+      y(i) = x(i)
+    ENDDO
+    DO i=1,nbi
+      IF (ind(i) <= nbo .AND. ind(i) > 0) THEN
+        y(ind(i)) =  miss_val
+      ELSE
+        IF (ind(i) > nbo) ma_fuundef_r11  = ma_fuundef_r11+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fuundef_r11 = 1
+  ENDIF
+!--------------------------
+END FUNCTION ma_fuundef_r11
+!===
+INTEGER FUNCTION ma_fuonly_r11(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb,nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb),miss_val,y(nbo)
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  IF (     (nbi <= nbo).AND.(nbo == nb) &
+ &    .AND.ALL(ind(1:nbi) <= nbo) ) THEN
+    ma_fuonly_r11 = 0
+    y(1:nbo) = miss_val
+    DO i=1,nbi
+      IF (ind(i) > 0) THEN
+        y(ind(i)) =  x(ind(i))
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fuonly_r11 = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fuonly_r11
+!===
+!===
+SUBROUTINE mathop_r21 &
+ &  (fun,nb,work_in,miss_val,nb_index,nindex,scal,nb_max,work_out)
+!---------------------------------------------------------------------
+!- This subroutines gives an interface to the various operations
+!- which are allowed. The interface is general enough to allow its use
+!- for other cases.
+!-
+!- INPUT
+!-
+!- fun      : function to be applied to the vector of data
+!- nb       : Length of input vector
+!- work_in  : Input vector of data (REAL)
+!- miss_val : The value of the missing data flag (it has to be a
+!-            maximum value, in f90 : huge( a real ))
+!- nb_index : Length of index vector
+!- nindex   : Vector of indices
+!- scal     : A scalar value for vector/scalar operations
+!- nb_max   : maximum length of output vector
+!-
+!- OUTPUT
+!-
+!- nb_max   : Actual length of output variable
+!- work_out : Output vector after the operation was applied
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=7) :: fun
+  INTEGER :: nb(2),nb_max,nb_index
+  INTEGER :: nindex(nb_index)
+  REAL :: work_in(nb(1),nb(2)),scal,miss_val
+  REAL :: work_out(nb_max)
+!-
+  INTEGER :: ierr
+!-
+  INTRINSIC SIN,COS,TAN,ASIN,ACOS,ATAN,EXP,LOG,SQRT,ABS
+!---------------------------------------------------------------------
+  ierr = 0
+!-
+  IF (scal >= miss_val-1.) THEN
+    IF (INDEX(indexfu,fun(1:LEN_TRIM(fun))) == 0) THEN
+      SELECT CASE (fun)
+      CASE('sin')
+        ierr = ma_sin_r21(nb,work_in,nb_max,work_out)
+      CASE('cos')
+        ierr = ma_cos_r21(nb,work_in,nb_max,work_out)
+      CASE('tan')
+        ierr = ma_tan_r21(nb,work_in,nb_max,work_out)
+      CASE('asin')
+        ierr = ma_asin_r21(nb,work_in,nb_max,work_out)
+      CASE('acos')
+        ierr = ma_acos_r21(nb,work_in,nb_max,work_out)
+      CASE('atan')
+        ierr = ma_atan_r21(nb,work_in,nb_max,work_out)
+      CASE('exp')
+        ierr = ma_exp_r21(nb,work_in,nb_max,work_out)
+      CASE('log')
+        ierr = ma_log_r21(nb,work_in,nb_max,work_out)
+      CASE('sqrt')
+        ierr = ma_sqrt_r21(nb,work_in,nb_max,work_out)
+      CASE('chs')
+        ierr = ma_chs_r21(nb,work_in,nb_max,work_out)
+      CASE('abs')
+        ierr = ma_abs_r21(nb,work_in,nb_max,work_out)
+      CASE('cels')
+        ierr = ma_cels_r21(nb,work_in,nb_max,work_out)
+      CASE('kelv')
+        ierr = ma_kelv_r21(nb,work_in,nb_max,work_out)
+      CASE('deg')
+        ierr = ma_deg_r21(nb,work_in,nb_max,work_out)
+      CASE('rad')
+        ierr = ma_rad_r21(nb,work_in,nb_max,work_out)
+      CASE('ident')
+        ierr = ma_ident_r21(nb,work_in,nb_max,work_out)
+      CASE DEFAULT
+        CALL ipslerr(3,"mathop", &
+ &        'scalar variable undefined and no indexing', &
+ &        'but still unknown function',fun)
+      END SELECT
+      IF (ierr > 0) THEN
+        CALL ipslerr(3,"mathop", &
+ &        'Error while executing a simple function',fun,' ')
+      ENDIF
+    ELSE
+      SELECT CASE (fun)
+      CASE('gather')
+        ierr = ma_fugath_r21(nb,work_in,nb_index,nindex, &
+ &                            miss_val,nb_max,work_out)
+      CASE('scatter')
+        IF (nb_index > (nb(1)*nb(2)) ) THEN
+          work_out(1:nb_max) = miss_val
+          ierr=1
+        ELSE
+          ierr = ma_fuscat_r21(nb,work_in,nb_index,nindex, &
+ &                             miss_val,nb_max,work_out)
+        ENDIF
+      CASE('coll')
+        ierr = ma_fucoll_r21(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('fill')
+        ierr = ma_fufill_r21(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('undef')
+        ierr = ma_fuundef_r21(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('only')
+        ierr = ma_fuonly_r21(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE DEFAULT
+        CALL ipslerr(3,"mathop", &
+ &        'scalar variable undefined and indexing', &
+ &        'was requested but with unknown function',fun)
+      END SELECT
+      IF (ierr > 0) THEN
+        CALL ipslerr(3,"mathop_r21", &
+ &        'Error while executing an indexing function',fun,' ')
+      ENDIF
+    ENDIF
+  ELSE
+    SELECT CASE (fun)
+    CASE('fumin')
+      ierr = ma_fumin_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('fumax')
+      ierr = ma_fumax_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('add')
+      ierr = ma_add_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('subi')
+      ierr = ma_subi_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('sub')
+      ierr = ma_sub_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('mult')
+      ierr = ma_mult_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('div')
+      ierr = ma_div_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('divi')
+      ierr = ma_divi_r21(nb,work_in,scal,nb_max,work_out)
+    CASE('power')
+      ierr = ma_power_r21(nb,work_in,scal,nb_max,work_out)
+    CASE DEFAULT
+      CALL ipslerr(3,"mathop", &
+ &      'Unknown operation with a scalar',fun,' ')
+    END SELECT
+    IF (ierr > 0) THEN
+      CALL ipslerr(3,"mathop", &
+ &      'Error while executing a scalar function',fun,' ')
+    ENDIF
+  ENDIF
+!------------------------
+END SUBROUTINE mathop_r21
+!-
+!=== FUNCTIONS (only one argument)
+!-
+INTEGER FUNCTION ma_sin_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = SIN(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_sin_r21 = 0
+!----------------------
+END FUNCTION ma_sin_r21
+!===
+INTEGER FUNCTION ma_cos_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = COS(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_cos_r21 = 0
+!----------------------
+END FUNCTION ma_cos_r21
+!===
+INTEGER FUNCTION ma_tan_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = TAN(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_tan_r21 = 0
+!----------------------
+END FUNCTION ma_tan_r21
+!===
+  INTEGER FUNCTION ma_asin_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = ASIN(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_asin_r21 = 0
+!-----------------------
+END FUNCTION ma_asin_r21
+!===
+INTEGER FUNCTION ma_acos_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = ACOS(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_acos_r21 = 0
+!-----------------------
+END FUNCTION ma_acos_r21
+!===
+INTEGER FUNCTION ma_atan_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = ATAN(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_atan_r21 = 0
+!-----------------------
+END FUNCTION ma_atan_r21
+!===
+INTEGER FUNCTION ma_exp_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = EXP(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_exp_r21 = 0
+!----------------------
+END FUNCTION ma_exp_r21
+!===
+INTEGER FUNCTION ma_log_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = LOG(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_log_r21 = 0
+!----------------------
+END FUNCTION ma_log_r21
+!===
+INTEGER FUNCTION ma_sqrt_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = SQRT(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_sqrt_r21 = 0
+!-----------------------
+END FUNCTION ma_sqrt_r21
+!===
+INTEGER FUNCTION ma_abs_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = ABS(x(i,j))
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_abs_r21 = 0
+!----------------------
+END FUNCTION ma_abs_r21
+!===
+INTEGER FUNCTION ma_chs_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)*(-1.)
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_chs_r21 = 0
+!----------------------
+END FUNCTION ma_chs_r21
+!===
+INTEGER FUNCTION ma_cels_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)-273.15
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_cels_r21 = 0
+!-----------------------
+END FUNCTION ma_cels_r21
+!===
+INTEGER FUNCTION ma_kelv_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)+273.15
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_kelv_r21 = 0
+!-----------------------
+END FUNCTION ma_kelv_r21
+!===
+INTEGER FUNCTION ma_deg_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)*57.29577951
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_deg_r21 = 0
+!----------------------
+END FUNCTION ma_deg_r21
+!===
+INTEGER FUNCTION ma_rad_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)*0.01745329252
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_rad_r21 = 0
+!----------------------
+END FUNCTION ma_rad_r21
+!===
+INTEGER FUNCTION ma_ident_r21(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,i,j,ij
+  REAL :: x(nb(1),nb(2)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_ident_r21 = 0
+!------------------------
+END FUNCTION ma_ident_r21
+!-
+!=== OPERATIONS (two argument)
+!-
+INTEGER FUNCTION ma_add_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)+s
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_add_r21 = 0
+!----------------------
+END FUNCTION ma_add_r21
+!===
+INTEGER FUNCTION ma_sub_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)-s
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_sub_r21 = 0
+!----------------------
+END FUNCTION ma_sub_r21
+!===
+INTEGER FUNCTION ma_subi_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) =  s-x(i,j)
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_subi_r21 = 0
+!-----------------------
+END FUNCTION ma_subi_r21
+!===
+INTEGER FUNCTION ma_mult_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)*s
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_mult_r21 = 0
+!-----------------------
+END FUNCTION ma_mult_r21
+!===
+INTEGER FUNCTION ma_div_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j)/s
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_div_r21 = 0
+!----------------------
+END FUNCTION ma_div_r21
+!===
+INTEGER FUNCTION ma_divi_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = s/x(i,j)
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_divi_r21 = 0
+!-----------------------
+END FUNCTION ma_divi_r21
+!===
+INTEGER FUNCTION ma_power_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = x(i,j) ** s
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_power_r21 = 0
+!------------------------
+END FUNCTION ma_power_r21
+!===
+INTEGER FUNCTION ma_fumin_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = MIN(x(i,j),s)
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_fumin_r21 = 0
+!------------------------
+END FUNCTION ma_fumin_r21
+!===
+INTEGER FUNCTION ma_fumax_r21(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo
+  REAL :: x(nb(1),nb(2)),s,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO j=1,nb(2)
+    DO i=1,nb(1)
+      ij = ij+1
+      y(ij) = MAX(x(i,j),s)
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)
+  ma_fumax_r21 = 0
+!------------------------
+END FUNCTION ma_fumax_r21
+!===
+INTEGER FUNCTION ma_fuscat_r21(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,ij,ii,ipos
+!---------------------------------------------------------------------
+  ma_fuscat_r21 = 0
+!-
+  y(1:nbo) = miss_val
+!-
+  IF (nbi <= nb(1)*nb(2)) THEN
+    ipos = 0
+    DO ij=1,nbi
+       IF (ind(ij) <= nbo .AND. ind(ij) > 0) THEN
+         ipos = ipos+1
+         j = ((ipos-1)/nb(1))+1
+         i = (ipos-(j-1)*nb(1))
+         y(ind(ij)) = x(i,j)
+       ELSE
+         IF (ind(ij) > nbo) ma_fuscat_r21  = ma_fuscat_r21+1
+       ENDIF
+    ENDDO
+!-- Repeat the data if needed
+    IF (MINVAL(ind) < 0) THEN
+      DO i=1,nbi
+        IF (ind(i) <= 0) THEN
+          DO ii=1,ABS(ind(i))-1
+            IF (ind(i+1)+ii <= nbo) THEN
+              y(ind(i+1)+ii) = y(ind(i+1))
+            ELSE
+              ma_fuscat_r21  = ma_fuscat_r21+1
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+    ma_fuscat_r21  = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fuscat_r21
+!===
+INTEGER FUNCTION ma_fugath_r21(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,ij,ipos
+!---------------------------------------------------------------------
+  IF (nbi <= nbo) THEN
+    ma_fugath_r21 = 0
+    y(1:nbo) = miss_val
+    ipos = 0
+    DO ij=1,nbi
+      IF (ipos+1 <= nbo) THEN
+        IF (ind(ij) > 0) THEN
+          j = ((ind(ij)-1)/nb(1))+1
+          i = (ind(ij)-(j-1)*nb(1))
+          ipos = ipos+1
+          y(ipos) = x(i,j)
+        ENDIF
+      ELSE
+        IF (ipos+1 > nbo) ma_fugath_r21  = ma_fugath_r21+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fugath_r21 = 1
+  ENDIF
+  nbo = ipos
+!-------------------------
+END FUNCTION ma_fugath_r21
+!===
+INTEGER FUNCTION ma_fufill_r21(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,ij,ii,ipos
+!---------------------------------------------------------------------
+  ma_fufill_r21 = 0
+!-
+  IF (nbi <= nb(1)*nb(2)) THEN
+    ipos = 0
+    DO ij=1,nbi
+      IF (ind(ij) <= nbo .AND. ind(ij) > 0) THEN
+        ipos = ipos+1
+        j = ((ipos-1)/nb(1))+1
+        i = (ipos-(j-1)*nb(1))
+        y(ind(ij)) = x(i,j)
+      ELSE
+        IF (ind(ij) > nbo) ma_fufill_r21  = ma_fufill_r21+1
+      ENDIF
+    ENDDO
+!-- Repeat the data if needed
+    IF (MINVAL(ind) < 0) THEN
+      DO i=1,nbi
+        IF (ind(i) <= 0) THEN
+          DO ii=1,ABS(ind(i))-1
+            IF (ind(i+1)+ii <= nbo) THEN
+              y(ind(i+1)+ii) = y(ind(i+1))
+            ELSE
+              ma_fufill_r21  = ma_fufill_r21+1
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+    ma_fufill_r21  = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fufill_r21
+!===
+INTEGER FUNCTION ma_fucoll_r21(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,ij,ipos
+!---------------------------------------------------------------------
+  IF (nbi <= nbo) THEN
+    ma_fucoll_r21 = 0
+    ipos = 0
+    DO ij=1,nbi
+      IF (ipos+1 <= nbo) THEN
+        IF (ind(ij) > 0) THEN
+          j = ((ind(ij)-1)/nb(1))+1
+          i = (ind(ij)-(j-1)*nb(1))
+          ipos = ipos+1
+          y(ipos) = x(i,j)
+        ENDIF
+      ELSE
+        IF (ipos+1 > nbo) ma_fucoll_r21  = ma_fucoll_r21+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fucoll_r21 = 1
+  ENDIF
+  nbo = ipos
+!-------------------------
+END FUNCTION ma_fucoll_r21
+!===
+INTEGER FUNCTION ma_fuundef_r21(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  IF (nbi <= nbo .AND. nbo == nb(1)*nb(2)) THEN
+    ma_fuundef_r21 = 0
+    DO ij=1,nbo
+      j = ((ij-1)/nb(1))+1
+      i = (ij-(j-1)*nb(1))
+      y(ij) = x(i,j)
+    ENDDO
+    DO i=1,nbi
+      IF (ind(i) <= nbo .AND. ind(i) > 0) THEN
+        y(ind(i)) =  miss_val
+      ELSE
+        IF (ind(i) > nbo) ma_fuundef_r21 = ma_fuundef_r21+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fuundef_r21 = 1
+  ENDIF
+!--------------------------
+END FUNCTION ma_fuundef_r21
+!===
+INTEGER FUNCTION ma_fuonly_r21(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(2),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,ij
+!---------------------------------------------------------------------
+  IF (     (nbi <= nbo).AND.(nbo == nb(1)*nb(2)) &
+ &    .AND.ALL(ind(1:nbi) <= nbo) ) THEN
+    ma_fuonly_r21 = 0
+    y(1:nbo) = miss_val
+    DO ij=1,nbi
+      IF (ind(ij) > 0) THEN
+        j = ((ind(ij)-1)/nb(1))+1
+        i = (ind(ij)-(j-1)*nb(1))
+        y(ind(ij)) =  x(i,j)
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fuonly_r21 = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fuonly_r21
+!===
+!===
+SUBROUTINE mathop_r31 &
+ &  (fun,nb,work_in,miss_val,nb_index,nindex,scal,nb_max,work_out)
+!---------------------------------------------------------------------
+!- This subroutines gives an interface to the various operations
+!- which are allowed. The interface is general enough to allow its use
+!- for other cases.
+!-
+!- INPUT
+!-
+!- fun      : function to be applied to the vector of data
+!- nb       : Length of input vector
+!- work_in  : Input vector of data (REAL)
+!- miss_val : The value of the missing data flag (it has to be a
+!-            maximum value, in f90 : huge( a real ))
+!- nb_index : Length of index vector
+!- nindex   : Vector of indices
+!- scal     : A scalar value for vector/scalar operations
+!- nb_max   : maximum length of output vector
+!-
+!- OUTPUT
+!-
+!- nb_max   : Actual length of output variable
+!- work_out : Output vector after the operation was applied
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=7) :: fun
+  INTEGER :: nb(3),nb_max,nb_index
+  INTEGER :: nindex(nb_index)
+  REAL :: work_in(nb(1),nb(2),nb(3)),scal,miss_val
+  REAL :: work_out(nb_max)
+!-
+  INTEGER :: ierr
+!-
+  INTRINSIC SIN,COS,TAN,ASIN,ACOS,ATAN,EXP,LOG,SQRT,ABS
+!---------------------------------------------------------------------
+  ierr = 0
+!-
+  IF (scal >= miss_val-1.) THEN
+    IF (INDEX(indexfu,fun(1:LEN_TRIM(fun))) == 0) THEN
+      SELECT CASE (fun)
+      CASE('sin')
+        ierr = ma_sin_r31(nb,work_in,nb_max,work_out)
+      CASE('cos')
+        ierr = ma_cos_r31(nb,work_in,nb_max,work_out)
+      CASE('tan')
+        ierr = ma_tan_r31(nb,work_in,nb_max,work_out)
+      CASE('asin')
+        ierr = ma_asin_r31(nb,work_in,nb_max,work_out)
+      CASE('acos')
+        ierr = ma_acos_r31(nb,work_in,nb_max,work_out)
+      CASE('atan')
+        ierr = ma_atan_r31(nb,work_in,nb_max,work_out)
+      CASE('exp')
+        ierr = ma_exp_r31(nb,work_in,nb_max,work_out)
+      CASE('log')
+        ierr = ma_log_r31(nb,work_in,nb_max,work_out)
+      CASE('sqrt')
+        ierr = ma_sqrt_r31(nb,work_in,nb_max,work_out)
+      CASE('chs')
+        ierr = ma_chs_r31(nb,work_in,nb_max,work_out)
+      CASE('abs')
+        ierr = ma_abs_r31(nb,work_in,nb_max,work_out)
+      CASE('cels')
+        ierr = ma_cels_r31(nb,work_in,nb_max,work_out)
+      CASE('kelv')
+        ierr = ma_kelv_r31(nb,work_in,nb_max,work_out)
+      CASE('deg')
+        ierr = ma_deg_r31(nb,work_in,nb_max,work_out)
+      CASE('rad')
+        ierr = ma_rad_r31(nb,work_in,nb_max,work_out)
+      CASE('ident')
+        ierr = ma_ident_r31(nb,work_in,nb_max,work_out)
+      CASE DEFAULT
+        CALL ipslerr(3,"mathop", &
+ &        'scalar variable undefined and no indexing', &
+ &        'but still unknown function',fun)
+      END SELECT
+      IF (ierr > 0) THEN
+         CALL ipslerr(3,"mathop", &
+ &        'Error while executing a simple function',fun,' ')
+      ENDIF
+    ELSE
+      SELECT CASE (fun)
+      CASE('gather')
+        ierr = ma_fugath_r31(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('scatter')
+        IF (nb_index > (nb(1)*nb(2)*nb(3))) THEN
+          work_out(1:nb_max) = miss_val
+          ierr=1
+        ELSE
+          ierr = ma_fuscat_r31(nb,work_in,nb_index,nindex, &
+ &                             miss_val,nb_max,work_out)
+        ENDIF
+      CASE('coll')
+        ierr = ma_fucoll_r31(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('fill')
+        ierr = ma_fufill_r31(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('undef')
+        ierr = ma_fuundef_r31(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE('only')
+        ierr = ma_fuonly_r31(nb,work_in,nb_index,nindex, &
+ &                           miss_val,nb_max,work_out)
+      CASE DEFAULT
+        CALL ipslerr(3,"mathop", &
+ &        'scalar variable undefined and indexing', &
+ &        'was requested but with unknown function',fun)
+      END SELECT
+      IF (ierr > 0) THEN
+        CALL ipslerr(3,"mathop_r31", &
+ &        'Error while executing an indexing function',fun,' ')
+      ENDIF
+    ENDIF
+  ELSE
+    SELECT CASE (fun)
+    CASE('fumin')
+      ierr = ma_fumin_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('fumax')
+      ierr = ma_fumax_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('add')
+      ierr = ma_add_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('subi')
+      ierr = ma_subi_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('sub')
+      ierr = ma_sub_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('mult')
+      ierr = ma_mult_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('div')
+      ierr = ma_div_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('divi')
+      ierr = ma_divi_r31(nb,work_in,scal,nb_max,work_out)
+    CASE('power')
+      ierr = ma_power_r31(nb,work_in,scal,nb_max,work_out)
+    CASE DEFAULT
+      CALL ipslerr(3,"mathop", &
+ &      'Unknown operation with a scalar',fun,' ')
+    END SELECT
+    IF (ierr > 0) THEN
+      CALL ipslerr(3,"mathop", &
+ &      'Error while executing a scalar function',fun,' ')
+    ENDIF
+  ENDIF
+!------------------------
+END SUBROUTINE mathop_r31
+!-
+!=== FUNCTIONS (only one argument)
+!-
+INTEGER FUNCTION ma_sin_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = SIN(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_sin_r31 = 0
+!----------------------
+END FUNCTION ma_sin_r31
+!===
+INTEGER FUNCTION ma_cos_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = COS(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_cos_r31 = 0
+!----------------------
+END FUNCTION ma_cos_r31
+!===
+INTEGER FUNCTION ma_tan_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = TAN(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_tan_r31 = 0
+!----------------------
+END FUNCTION ma_tan_r31
+!===
+INTEGER FUNCTION ma_asin_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = ASIN(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_asin_r31 = 0
+!-----------------------
+END FUNCTION ma_asin_r31
+!===
+INTEGER FUNCTION ma_acos_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = ACOS(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_acos_r31 = 0
+!-----------------------
+END FUNCTION ma_acos_r31
+!===
+INTEGER FUNCTION ma_atan_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = ATAN(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_atan_r31 = 0
+!-----------------------
+  END FUNCTION ma_atan_r31
+!===
+INTEGER FUNCTION ma_exp_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = EXP(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_exp_r31 = 0
+!----------------------
+END FUNCTION ma_exp_r31
+!===
+INTEGER FUNCTION ma_log_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = LOG(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_log_r31 = 0
+!----------------------
+END FUNCTION ma_log_r31
+!===
+INTEGER FUNCTION ma_sqrt_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = SQRT(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_sqrt_r31 = 0
+!-----------------------
+END FUNCTION ma_sqrt_r31
+!===
+INTEGER FUNCTION ma_abs_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = ABS(x(i,j,k))
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_abs_r31 = 0
+!----------------------
+END FUNCTION ma_abs_r31
+!===
+INTEGER FUNCTION ma_chs_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)*(-1.)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_chs_r31 = 0
+!----------------------
+END FUNCTION ma_chs_r31
+!===
+INTEGER FUNCTION ma_cels_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)-273.15
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_cels_r31 = 0
+!-----------------------
+END FUNCTION ma_cels_r31
+!===
+INTEGER FUNCTION ma_kelv_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)+273.15
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_kelv_r31 = 0
+!-----------------------
+  END FUNCTION ma_kelv_r31
+!===
+INTEGER FUNCTION ma_deg_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)*57.29577951
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_deg_r31 = 0
+!----------------------
+END FUNCTION ma_deg_r31
+!===
+INTEGER FUNCTION ma_rad_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)*0.01745329252
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_rad_r31 = 0
+!----------------------
+END FUNCTION ma_rad_r31
+!===
+INTEGER FUNCTION ma_ident_r31(nb,x,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,i,j,k,ij
+  REAL :: x(nb(1),nb(2),nb(3)),y(nbo)
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_ident_r31 = 0
+!------------------------
+END FUNCTION ma_ident_r31
+!-
+!=== OPERATIONS (two argument)
+!-
+INTEGER FUNCTION ma_add_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)+s
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_add_r31 = 0
+!----------------------
+END FUNCTION ma_add_r31
+!===
+INTEGER FUNCTION ma_sub_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)-s
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_sub_r31 = 0
+!----------------------
+END FUNCTION ma_sub_r31
+!===
+INTEGER FUNCTION ma_subi_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) =  s-x(i,j,k)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_subi_r31 = 0
+!-----------------------
+END FUNCTION ma_subi_r31
+!===
+INTEGER FUNCTION ma_mult_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)*s
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_mult_r31 = 0
+!-----------------------
+END FUNCTION ma_mult_r31
+!===
+INTEGER FUNCTION ma_div_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)/s
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_div_r31 = 0
+!----------------------
+END FUNCTION ma_div_r31
+!===
+INTEGER FUNCTION ma_divi_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = s/x(i,j,k)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_divi_r31 = 0
+!-----------------------
+END FUNCTION ma_divi_r31
+!===
+INTEGER FUNCTION ma_power_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = x(i,j,k)**s
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_power_r31 = 0
+!------------------------
+END FUNCTION ma_power_r31
+!===
+INTEGER FUNCTION ma_fumin_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = MIN(x(i,j,k),s)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_fumin_r31 = 0
+!------------------------
+END FUNCTION ma_fumin_r31
+!===
+INTEGER FUNCTION ma_fumax_r31(nb,x,s,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo
+  REAL :: x(nb(1),nb(2),nb(3)),s,y(nbo)
+!-
+  INTEGER :: i,j,k,ij
+!---------------------------------------------------------------------
+  ij = 0
+  DO k=1,nb(3)
+    DO j=1,nb(2)
+      DO i=1,nb(1)
+        ij = ij+1
+        y(ij) = MAX(x(i,j,k),s)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  nbo = nb(1)*nb(2)*nb(3)
+  ma_fumax_r31 = 0
+!------------------------
+END FUNCTION ma_fumax_r31
+!===
+INTEGER FUNCTION ma_fuscat_r31(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2),nb(3)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,k,ij,ii,ipos,ipp,isb
+!---------------------------------------------------------------------
+  ma_fuscat_r31 = 0
+!-
+  y(1:nbo) = miss_val
+!-
+  IF (nbi <= nb(1)*nb(2)*nb(3)) THEN
+    ipos = 0
+    isb = nb(1)*nb(2)
+    DO ij=1,nbi
+      IF (ind(ij) <= nbo .AND. ind(ij) > 0) THEN
+        ipos = ipos+1
+        k = ((ipos-1)/isb)+1
+        ipp = ipos-(k-1)*isb
+        j = ((ipp-1)/nb(1))+1
+        i = (ipp-(j-1)*nb(1))
+        y(ind(ij)) = x(i,j,k)
+      ELSE
+        IF (ind(ij) > nbo) ma_fuscat_r31  = ma_fuscat_r31+1
+      ENDIF
+    ENDDO
+!-- Repeat the data if needed
+    IF (MINVAL(ind) < 0) THEN
+      DO i=1,nbi
+        IF (ind(i) <= 0) THEN
+          DO ii=1,ABS(ind(i))-1
+            IF (ind(i+1)+ii <= nbo) THEN
+              y(ind(i+1)+ii) = y(ind(i+1))
+            ELSE
+              ma_fuscat_r31  = ma_fuscat_r31+1
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+    ma_fuscat_r31  = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fuscat_r31
+!===
+INTEGER FUNCTION ma_fugath_r31(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2),nb(3)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,k,ij,ipos,ipp,isb
+!---------------------------------------------------------------------
+  IF (nbi <= nbo) THEN
+    ma_fugath_r31 = 0
+    y(1:nbo) = miss_val
+    ipos = 0
+    isb = nb(1)*nb(2)
+    DO ij=1,nbi
+      IF (ipos+1 <= nbo) THEN
+        IF (ind(ij) > 0) THEN
+          k = ((ind(ij)-1)/isb)+1
+          ipp = ind(ij)-(k-1)*isb
+          j = ((ipp-1)/nb(1))+1
+          i = (ipp-(j-1)*nb(1))
+          ipos = ipos+1
+          y(ipos) = x(i,j,k)
+        ENDIF
+      ELSE
+        IF (ipos+1 > nbo) ma_fugath_r31  = ma_fugath_r31+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fugath_r31 = 1
+  ENDIF
+  nbo = ipos
+!-------------------------
+END FUNCTION ma_fugath_r31
+!===
+INTEGER FUNCTION ma_fufill_r31(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2),nb(3)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,k,ij,ii,ipos,ipp,isb
+!---------------------------------------------------------------------
+  ma_fufill_r31 = 0
+  IF (nbi <= nb(1)*nb(2)*nb(3)) THEN
+    ipos = 0
+    isb = nb(1)*nb(2)
+    DO ij=1,nbi
+      IF (ind(ij) <= nbo .AND. ind(ij) > 0) THEN
+        ipos = ipos+1
+        k = ((ipos-1)/isb)+1
+        ipp = ipos-(k-1)*isb
+        j = ((ipp-1)/nb(1))+1
+        i = (ipp-(j-1)*nb(1))
+        y(ind(ij)) = x(i,j,k)
+      ELSE
+        IF (ind(ij) > nbo) ma_fufill_r31  = ma_fufill_r31+1
+      ENDIF
+    ENDDO
+!-- Repeat the data if needed
+    IF (MINVAL(ind) < 0) THEN
+      DO i=1,nbi
+        IF (ind(i) <= 0) THEN
+          DO ii=1,ABS(ind(i))-1
+            IF (ind(i+1)+ii <= nbo) THEN
+              y(ind(i+1)+ii) = y(ind(i+1))
+            ELSE
+              ma_fufill_r31  = ma_fufill_r31+1
+            ENDIF
+          ENDDO
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+    ma_fufill_r31  = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fufill_r31
+!===
+INTEGER FUNCTION ma_fucoll_r31(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2),nb(3)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,k,ij,ipos,ipp,isb
+!---------------------------------------------------------------------
+  IF (nbi <= nbo) THEN
+    ma_fucoll_r31 = 0
+    ipos = 0
+    isb = nb(1)*nb(2)
+    DO ij=1,nbi
+      IF (ipos+1 <= nbo) THEN
+        IF (ind(ij) > 0) THEN
+          k = ((ind(ij)-1)/isb)+1
+          ipp = ind(ij)-(k-1)*isb
+          j = ((ipp-1)/nb(1))+1
+          i = (ipp-(j-1)*nb(1))
+          ipos = ipos+1
+          y(ipos) = x(i,j,k)
+        ENDIF
+      ELSE
+        IF (ipos+1 > nbo) ma_fucoll_r31  = ma_fucoll_r31+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fucoll_r31 = 1
+  ENDIF
+  nbo = ipos
+!-------------------------
+END FUNCTION ma_fucoll_r31
+!===
+INTEGER FUNCTION ma_fuundef_r31(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2),nb(3)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,k,ij,ipp,isb
+!---------------------------------------------------------------------
+  IF (nbi <= nbo .AND. nbo == nb(1)*nb(2)*nb(3)) THEN
+    ma_fuundef_r31 = 0
+    isb = nb(1)*nb(2)
+    DO ij=1,nbo
+      k = ((ij-1)/isb)+1
+      ipp = ij-(k-1)*isb
+      j = ((ipp-1)/nb(1))+1
+      i = (ipp-(j-1)*nb(1))
+      y(ij) = x(i,j,k)
+    ENDDO
+    DO i=1,nbi
+      IF (ind(i) <= nbo .AND. ind(i) > 0) THEN
+        y(ind(i)) =  miss_val
+      ELSE
+        IF (ind(i) > nbo) ma_fuundef_r31  = ma_fuundef_r31+1
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fuundef_r31 = 1
+  ENDIF
+!--------------------------
+END FUNCTION ma_fuundef_r31
+!===
+INTEGER FUNCTION ma_fuonly_r31(nb,x,nbi,ind,miss_val,nbo,y)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb(3),nbo,nbi
+  INTEGER :: ind(nbi)
+  REAL :: x(nb(1),nb(2),nb(3)),miss_val,y(nbo)
+!-
+  INTEGER :: i,j,k,ij,ipp,isb
+!---------------------------------------------------------------------
+  IF (     (nbi <= nbo).AND.(nbo == nb(1)*nb(2)*nb(3)) &
+ &    .AND.ALL(ind(1:nbi) <= nbo) ) THEN
+    ma_fuonly_r31 = 0
+    y(1:nbo) = miss_val
+    isb = nb(1)*nb(2)
+    DO ij=1,nbi
+      IF (ind(ij) > 0) THEN
+        k = ((ind(ij)-1)/isb)+1
+        ipp = ind(ij)-(k-1)*isb
+        j = ((ipp-1)/nb(1))+1
+        i = (ipp-(j-1)*nb(1))
+        y(ind(ij)) = x(i,j,k)
+      ENDIF
+    ENDDO
+  ELSE
+    ma_fuonly_r31 = 1
+  ENDIF
+!-------------------------
+END FUNCTION ma_fuonly_r31
+!===
+SUBROUTINE moycum (opp,np,px,py,pwx)
+!---------------------------------------------------------------------
+!- Does time operations
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=7) :: opp
+  INTEGER :: np
+  REAL,DIMENSION(:) :: px,py
+  INTEGER :: pwx
+!---------------------------------------------------------------------
+  IF (pwx /= 0) THEN
+    IF      (opp == 'ave') THEN
+      px(1:np)=(px(1:np)*pwx+py(1:np))/REAL(pwx+1)
+    ELSE IF (opp == 't_sum') THEN
+      px(1:np)=px(1:np)+py(1:np)
+    ELSE IF ( (opp == 'l_min').OR.(opp == 't_min') ) THEN
+      px(1:np)=MIN(px(1:np),py(1:np))
+    ELSE IF ( (opp == 'l_max').OR.(opp == 't_max') ) THEN
+      px(1:np)=MAX(px(1:np),py(1:np))
+    ELSE
+      CALL ipslerr(3,"moycum",'Unknown time operation',opp,' ')
+    ENDIF
+  ELSE
+    IF      (opp == 'l_min') THEN
+      px(1:np)=MIN(px(1:np),py(1:np))
+    ELSE IF (opp == 'l_max') THEN
+      px(1:np)=MAX(px(1:np),py(1:np))
+    ELSE
+      px(1:np)=py(1:np)
+    ENDIF
+  ENDIF
+!--------------------
+END SUBROUTINE moycum
+!===
+!-----------------
+END MODULE mathelp
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/restcom.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/restcom.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/restcom.f90	(revision 329)
@@ -0,0 +1,2546 @@
+MODULE restcom
+!-
+!$Id: restcom.f90 430 2008-10-23 14:33:11Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!-
+USE netcdf
+!-
+USE errioipsl, ONLY : ipslerr,ipsldbg
+USE stringop
+USE calendar
+USE mathelp
+USE fliocom,   ONLY : flio_dom_file,flio_dom_att
+!-
+IMPLICIT NONE
+!-
+PRIVATE
+!-
+PUBLIC :: &
+ &  restini, restget, restput, restclo, &
+ &  ioconf_setatt, ioget_vname, ioconf_expval, &
+ &  ioget_expval, ioget_vdim
+!-
+INTERFACE restput
+  MODULE PROCEDURE &
+ &  restput_r3d, restput_r2d, restput_r1d, &
+ &  restput_opp_r2d, restput_opp_r1d
+END INTERFACE
+!-
+INTERFACE restget
+  MODULE PROCEDURE &
+ &  restget_r3d,restget_r2d,restget_r1d, &
+ &  restget_opp_r2d,restget_opp_r1d
+END INTERFACE
+!-
+! We do not use allocatable arrays because these sizes are safe
+! and we do not know from start how many variables will be in
+! the out file.
+!-
+  INTEGER,PARAMETER :: &
+ &  max_var=500, max_file=50, max_dim=NF90_MAX_VAR_DIMS
+!-
+  CHARACTER(LEN=9),SAVE :: calend_str='unknown'
+!-
+! The IDs of the netCDF files are going in pairs.
+! The input one (netcdf_id(?,1)) and the output one (netcdf_id(?,2))
+!-
+  INTEGER,SAVE :: nb_fi = 0
+  INTEGER,DIMENSION(max_file,2),SAVE :: netcdf_id = -1
+!-
+! Description of the content of the 'in' files and the 'out' files.
+!   Number of variables   : nbvar_*
+!   Number of dimensions  : nbdim_*
+!   ID of the time axis   : tdimid_*
+!-
+  INTEGER,SAVE :: nbvar_in(max_file), nbvar_out(max_file)
+  INTEGER,SAVE :: tdimid_in(max_file), tdimid_out(max_file)
+!-
+! Variables for one or the other file
+!-
+! Number of dimensions in the input file               : nbdim_in
+! Number of variables read so far from the input file  : nbvar_read
+! Type of variable read from the input file            : vartyp_in
+!   (Could be used later to test if we have a restart file)
+!-
+  INTEGER,SAVE :: nbdim_in(max_file), nbvar_read(max_file)
+  INTEGER,SAVE :: vartyp_in(max_file, max_var)
+!-
+! Time step and time origine in the input file.
+!-
+  REAL,DIMENSION(max_file),SAVE :: deltat,timeorig
+!-
+! Description of the axes in the output file
+!-
+!   tstp_out  : Index on the tie axis currently beeing written
+!   itau_out  : Time step which is written on this index of the file
+!-
+  INTEGER,DIMENSION(max_file),SAVE :: tstp_out,itau_out
+!-
+! Description of the axes in the output file
+!-
+! For the ?ax_infs variable the following order is used :
+!   ?ax_infs (if,in,1) = size of axis
+!   ?ax_infs (if,in,2) = id of dimension
+! Number of x,y and z axes in the output file :
+!   ?ax_nb(if)
+!-
+  INTEGER,DIMENSION(max_file,max_dim,2),SAVE :: &
+ &  xax_infs,yax_infs,zax_infs
+  INTEGER,DIMENSION(max_file),SAVE :: &
+ &  xax_nb=0,yax_nb=0,zax_nb=0
+!-
+! Description of the time axes in the input and output files
+!-
+!   ID of the variable which contains the itaus :
+!     tind_varid_*
+!   ID of the variables which contains the seconds since date :
+!     tax_varid_*
+!   Size of the time axis in the input file :
+!     tax_size_in
+!-
+  INTEGER,SAVE :: tind_varid_in(max_file),  tax_varid_in(max_file), &
+ &                tind_varid_out(max_file), tax_varid_out(max_file)
+  INTEGER,SAVE :: tax_size_in(max_file)=1
+!-
+! The two time axes we have in the input file :
+!   t_index   : dates in itaus
+!               (thus the variable has a tstep_sec attribute)
+!   t_julian  : Julian days of the time axis
+!-
+  INTEGER,SAVE,ALLOCATABLE :: t_index(:,:)
+  REAL,SAVE,ALLOCATABLE :: t_julian(:,:)
+!-
+! Here we save a number of informations on the variables
+! in the files we are handling
+!-
+! Name of variables :                                    varname_*
+! ID of the variables :                                  varid_*
+! Number of dimensions of the variable :                 varnbdim_*
+! Dimensions which are used for the variable :           vardims_*
+! Number of attributes for a variables :                 varatt_*
+! A flag which markes the variables we have worked on :  touched_*
+!-
+  CHARACTER(LEN=20),DIMENSION(max_file,max_var),SAVE :: &
+ &  varname_in,varname_out
+  INTEGER,DIMENSION(max_file,max_var),SAVE :: &
+ &  varid_in,varid_out,varnbdim_in,varatt_in
+  INTEGER,DIMENSION(max_file,max_var,max_dim),SAVE :: &
+ &  vardims_in
+  LOGICAL,DIMENSION(max_file,max_var),SAVE :: &
+ &  touched_in,touched_out
+!-
+  CHARACTER(LEN=120),SAVE :: indchfun= 'scatter, fill, gather, coll'
+  REAL,PARAMETER :: missing_val=1.e20
+!                or HUGE(1.0) (maximum real number)
+!-
+! The default value we will use for variables
+! which are not present in the restart file
+!-
+  REAL,SAVE :: val_exp =  999999.
+  LOGICAL,SAVE :: lock_valexp = .FALSE.
+!-
+! Temporary variables in which we store the attributed which are going
+! to be given to a new variable which is going to be defined.
+!-
+  CHARACTER(LEN=80),SAVE :: rest_units='XXXXX',rest_lname='XXXXX'
+!-
+! For allocations
+!-
+  REAL,ALLOCATABLE,DIMENSION(:),SAVE :: buff_tmp1,buff_tmp2
+!-
+!===
+CONTAINS
+!===
+!-
+SUBROUTINE restini &
+ & (fnamein,iim,jjm,lon,lat,llm,lev, &
+ &  fnameout,itau,date0,dt,fid,owrite_time_in,domain_id)
+!---------------------------------------------------------------------
+!- This subroutine sets up all the restart process.
+!- It will call the subroutine which opens the input
+!- and output files.
+!- The time step (itau), date of origine (date0) and time step are
+!- READ from the input file.
+!- A file ID, which is common to the input and output file is returned
+!-
+!- If fnamein = fnameout then the same file is used for the reading
+!- the restart conditions and writing the new restart.
+!-
+!- A special mode can be switched in with filename='NONE'.
+!- This means that no restart file is present.
+!- Usefull for creating the first restart file
+!- or to get elements in a file without creating an output file.
+!-
+!- A mode needs to be written in which itau, date0 and dt
+!- are given to the restart process and thus
+!- written into the output restart file.
+!-
+!- INPUT
+!-
+!- fnamein  : name of the file for the restart
+!- iim      : Dimension in x
+!- jjm      : Dimension in y
+!- lon      : Longitude in the x,y domain
+!- lat      : Latitude in the x,y domain
+!- llm      : Dimension in the vertical
+!- lev      : Positions of the levels
+!- fnameout :
+!-
+!- OUTPUT
+!-
+!- itau     : Time step of the restart file and at which the model
+!-            should restart
+!- date0    : Time at which itau = 0
+!- dt       : time step in seconds between two succesiv itaus
+!- fid      : File identification of the restart file
+!-
+!- Optional INPUT arguments
+!-
+!- owrite_time_in : logical  argument which allows to
+!-                  overwrite the time in the restart file
+!- domain_id      : Domain identifier
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(IN) :: fnamein,fnameout
+  INTEGER :: iim,jjm,llm,fid,itau
+  REAL :: lon(iim,jjm),lat(iim,jjm),lev(llm)
+  REAL :: date0,dt
+  LOGICAL,OPTIONAL :: owrite_time_in
+  INTEGER,INTENT(IN),OPTIONAL :: domain_id
+!-
+  INTEGER :: ncfid
+  REAL :: dt_tmp,date0_tmp
+  LOGICAL :: l_fi,l_fo,l_rw
+  LOGICAL :: overwrite_time
+  CHARACTER(LEN=120) :: fname
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 0.0 Prepare the configuration before opening any files
+!-
+  IF (.NOT.PRESENT(owrite_time_in)) THEN
+    overwrite_time = .FALSE.
+  ELSE
+    overwrite_time = owrite_time_in
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'restini 0.0 : ',TRIM(fnamein),' , ',TRIM(fnameout)
+  ENDIF
+!-
+  nb_fi = nb_fi+1
+!-
+  IF (nb_fi > max_file) THEN
+    CALL ipslerr (3,'restini',&
+ &   'Too many restart files are used. The problem can be',&
+ &   'solved by increasing max_file in restcom.f90 ',&
+ &   'and recompiling ioipsl.')
+  ENDIF
+!-
+! 0.1 Define the open flags
+!-
+  l_fi = (TRIM(fnamein)  /= 'NONE')
+  l_fo = (TRIM(fnameout) /= 'NONE')
+  IF ((.NOT.l_fi).AND.(.NOT.l_fo)) THEN
+    CALL ipslerr (3,'restini',&
+ &   'Input and output file names are both to NONE.',&
+ &   'It is probably an error.','Verify your logic.')
+  ENDIF
+  l_rw = l_fi.AND.l_fo.AND.(TRIM(fnamein) == TRIM(fnameout))
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'restini 0.1 l_fi, l_fo, l_rw : ',l_fi,l_fo,l_rw
+  ENDIF
+!-
+! 1.0 Open the input file.
+!-
+  IF (l_fi) THEN
+!---
+    IF (l_dbg) WRITE(*,*) 'restini 1.0 : Open input file'
+!-- Add DOMAIN number and ".nc" suffix in file names if needed
+    fname = fnamein
+    CALL flio_dom_file (fname,domain_id)
+!-- Open the file
+    CALL restopenin (nb_fi,fname,l_rw,iim,jjm,lon,lat,llm,lev,ncfid)
+    netcdf_id(nb_fi,1) = ncfid
+!---
+!-- 1.3 Extract the time information
+!---
+    IF (overwrite_time) THEN
+       date0_tmp = date0
+    ENDIF
+    CALL restsett (dt_tmp,date0_tmp,itau,overwrite_time)
+    IF (.NOT.overwrite_time) THEN
+      dt = dt_tmp
+      date0 = date0_tmp
+    ENDIF
+!---
+  ELSE
+!---
+!-- 2.0 The case of a missing restart file is dealt with
+!---
+    IF (l_dbg) WRITE(*,*) 'restini 2.0'
+!---
+    IF (     (ALL(MINLOC(lon(:iim,:jjm)) == MAXLOC(lon(:iim,:jjm)))) &
+        .AND.(iim > 1) ) THEN
+      CALL ipslerr (3,'restini',&
+        & 'For creating a restart file the longitudes of the',&
+        & 'grid need to be provided to restini. This ',&
+        & 'information is needed for the restart files')
+    ENDIF
+    IF (     (ALL(MINLOC(lat(:iim,:jjm)) == MAXLOC(lat(:iim,:jjm)))) &
+        .AND.(jjm > 1) ) THEN
+      CALL ipslerr (3,'restini',&
+        & 'For creating a restart file the latitudes of the',&
+        & 'grid need to be provided to restini. This ',&
+        & 'information is needed for the restart files')
+    ENDIF
+    IF (     (ALL(MINLOC(lev(:llm)) == MAXLOC(lev(:llm)))) &
+        .AND.(llm > 1) ) THEN
+      CALL ipslerr (3,'restini',&
+        & 'For creating a restart file the levels of the',&
+        & 'grid need to be provided to restini. This',&
+        & 'information is needed for the restart files')
+    ENDIF
+!---
+!-- 2.2 Allocate the time axes and write the inputed variables
+!---
+    tax_size_in(nb_fi) = 1
+    CALL rest_atim (l_dbg,'restini')
+    t_index(nb_fi,1) = itau
+    t_julian(nb_fi,1) = date0
+  ENDIF
+!-
+  IF (l_fo.AND.(.NOT.l_rw)) THEN
+!-- Add DOMAIN number and ".nc" suffix in file names if needed
+    fname = fnameout
+    CALL flio_dom_file (fname,domain_id)
+!-- Open the file
+    CALL restopenout &
+      (nb_fi,fname,iim,jjm,lon,lat,llm,lev,dt,date0,ncfid,domain_id)
+    netcdf_id(nb_fi,2) = ncfid
+  ELSE IF (l_fi.AND.l_fo) THEN
+    netcdf_id(nb_fi,2) = netcdf_id(nb_fi,1)
+    varname_out(nb_fi,:) = varname_in(nb_fi,:)
+    nbvar_out(nb_fi) = nbvar_in(nb_fi)
+    tind_varid_out(nb_fi) = tind_varid_in(nb_fi)
+    tax_varid_out(nb_fi) = tax_varid_in(nb_fi)
+    varid_out(nb_fi,:) = varid_in(nb_fi,:)
+    touched_out(nb_fi,:) = .TRUE.
+  ENDIF
+!-
+! 2.3 Set the calendar for the run.
+!     This should not produce any error message if
+!     This does not mean any change in calendar
+!     (to be modified in ioconf_calendar)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'restini 2.3 : Configure calendar if needed : ', &
+                calend_str
+  ENDIF
+!-
+  IF (INDEX(calend_str,'unknown') < 1) THEN
+    CALL ioconf_calendar (calend_str)
+    IF (l_dbg) THEN
+      WRITE(*,*) 'restini 2.3b : new calendar : ',calend_str
+    ENDIF
+  ENDIF
+!-
+! Save some data in the module
+!-
+  deltat(nb_fi) = dt
+!-
+! Prepare the variables which will be returned
+!-
+  fid = nb_fi
+  IF (l_dbg) THEN
+    WRITE(*,*) 'SIZE of t_index :',SIZE(t_index), &
+               SIZE(t_index,dim=1),SIZE(t_index,dim=2)
+    WRITE(*,*) 't_index = ',t_index(fid,:)
+  ENDIF
+  itau = t_index(fid,1)
+!-
+  IF (l_dbg) WRITE(*,*) 'restini END'
+!---------------------
+END SUBROUTINE restini
+!===
+SUBROUTINE restopenin &
+  (fid,fname,l_rw,iim,jjm,lon,lat,llm,lev,ncfid)
+!---------------------------------------------------------------------
+!- Opens the restart file and checks that it belongsd to the model.
+!- This means that the coordinates of the model are compared to the
+!- ones in the file.
+!-
+!- The number and name of variable in the file are exctracted. Also
+!- the time details.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: fid,iim,jjm,llm
+  CHARACTER(LEN=*),INTENT(IN) :: fname
+  REAL :: lon(iim,jjm),lat(iim,jjm),lev(llm)
+  LOGICAL,INTENT(IN) :: l_rw
+  INTEGER,INTENT(OUT) :: ncfid
+!-
+  INTEGER,DIMENSION(max_dim) :: var_dims,dimlen
+  INTEGER :: nb_dim,nb_var,id_unl,id,iv
+  INTEGER :: iread,jread,lread,iret
+  INTEGER :: lon_vid,lat_vid
+  REAL :: lon_read(iim,jjm),lat_read(iim,jjm)
+  REAL :: lev_read(llm)
+  REAL :: mdlon,mdlat
+  CHARACTER(LEN=80) :: units
+  CHARACTER(LEN=NF90_max_name),DIMENSION(max_dim) :: dimname
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! If we reuse the same file for input and output
+! then we open it in write mode
+!-
+  IF (l_rw) THEN; id = NF90_WRITE; ELSE; id = NF90_NOWRITE; ENDIF
+  iret = NF90_OPEN(fname,id,ncfid)
+  IF (iret /= NF90_NOERR) THEN
+    CALL ipslerr (3,'restopenin','Could not open file :',fname,' ')
+  ENDIF
+!-
+  IF (l_dbg) WRITE (*,*) "restopenin 0.0 ",TRIM(fname)
+  iret = NF90_INQUIRE(ncfid,nDimensions=nb_dim, &
+ &         nVariables=nb_var,unlimitedDimId=id_unl)
+  tdimid_in(fid) = id_unl
+!-
+  IF (nb_dim > max_dim) THEN
+    CALL ipslerr (3,'restopenin',&
+      & 'More dimensions present in file that can be store',&
+      & 'Please increase max_dim in the global variables ',&
+      & 'in restcom.F90')
+  ENDIF
+  IF (nb_var > max_var) THEN
+    CALL ipslerr (3,'restopenin',&
+      & 'More variables present in file that can be store',&
+      & 'Please increase max_var in the global variables ',&
+      & 'in restcom.F90')
+  ENDIF
+!-
+  nbvar_in(fid) = nb_var
+  nbdim_in(fid) = nb_dim
+  iread = -1; jread = -1; lread = -1;
+  DO id=1,nb_dim
+    iret = NF90_INQUIRE_DIMENSION(ncfid,id, &
+ &           len=dimlen(id),name=dimname(id))
+    IF (l_dbg) THEN
+      WRITE (*,*) "restopenin 0.0 dimname",id,TRIM(dimname(id))
+    ENDIF
+    IF      (TRIM(dimname(id)) == 'x') THEN
+      iread = dimlen(id)
+      IF (l_dbg) WRITE (*,*) "iread",iread
+    ELSE IF (TRIM(dimname(id)) == 'y') THEN
+      jread = dimlen(id)
+      IF (l_dbg) WRITE (*,*) "jread",jread
+    ELSE IF (TRIM(dimname(id)) == 'z') THEN
+      lread = dimlen(id)
+      IF (l_dbg) WRITE (*,*) "lread",lread
+    ENDIF
+  ENDDO
+!-
+  IF (id_unl > 0) THEN
+!---
+!-- 0.1 If we are going to add values to this file
+!--     we need to know where it ends
+!--     We also need to have all the dimensions in the file
+!---
+    IF (l_rw) THEN
+      tstp_out(fid) = dimlen(id_unl)
+      itau_out(fid) = -1
+      tdimid_out(fid) =  tdimid_in(fid)
+      IF (l_dbg) THEN
+        WRITE (*,*) &
+ &       "restopenin 0.0 unlimited axis dimname", &
+ &       dimname(id_unl),tstp_out(fid)
+      ENDIF
+!-----
+      xax_nb(fid) = 0
+      yax_nb(fid) = 0
+      zax_nb(fid) = 0
+!-----
+      DO id=1,nb_dim
+        IF      (dimname(id)(1:1) == 'x') THEN
+          xax_nb(fid) = xax_nb(fid)+1
+          xax_infs(fid,xax_nb(fid),1) = dimlen(id)
+          xax_infs(fid,xax_nb(fid),2) = id
+        ELSE IF (dimname(id)(1:1) == 'y') THEN
+          yax_nb(fid) = yax_nb(fid)+1
+          yax_infs(fid,yax_nb(fid),1) = dimlen(id)
+          yax_infs(fid,yax_nb(fid),2) = id
+        ELSE IF (dimname(id)(1:1) == 'z') THEN
+          zax_nb(fid) = zax_nb(fid)+1
+          zax_infs(fid,zax_nb(fid),1) = dimlen(id)
+          zax_infs(fid,zax_nb(fid),2) = id
+        ENDIF
+      ENDDO
+    ENDIF
+  ELSE
+!---
+!-- Still need to find a method for dealing with this
+!---
+!  CALL ipslerr (3,'restopenin',&
+!    & ' We do not deal yet with files without time axis.',' ',' ')
+  ENDIF
+!-
+! 1.0 First let us check that we have the righ restart file
+!-
+  IF ((iread /= iim).OR.(jread /= jjm).OR.(lread /= llm)) THEN
+    CALL ipslerr (3,'restopenin',&
+ &    'The grid of the restart file does not correspond',&
+ &    'to that of the model',' ')
+  ENDIF
+!-
+! 2.0 Get the list of variables
+!-
+  IF (l_dbg) WRITE(*,*) 'restopenin 1.2'
+!-
+  lat_vid = -1
+  lon_vid = -1
+  tind_varid_in(fid) = -1
+  tax_varid_in(fid) = -1
+!-
+  DO iv=1,nb_var
+!---
+    varid_in(fid,iv) = iv
+    var_dims(:) = 0
+    iret = NF90_INQUIRE_VARIABLE(ncfid,iv, &
+ &           name=varname_in(fid,iv),xtype=vartyp_in(fid,iv), &
+ &           ndims=varnbdim_in(fid,iv),dimids=var_dims, &
+ &           nAtts=varatt_in(fid,iv))
+!---
+    DO id=1,varnbdim_in(fid,iv)
+      iret = NF90_INQUIRE_DIMENSION &
+ &             (ncfid,var_dims(id),len=vardims_in(fid,iv,id))
+    ENDDO
+!---
+!-- 2.1 Read the units of the variable
+!---
+    units=''
+    iret = NF90_GET_ATT(ncfid,iv,'units',units)
+    CALL strlowercase (units)
+    CALL cmpblank (units)
+!---
+!-- 2.2 Catch the time variables
+!---
+    IF (varnbdim_in(fid,iv) == 1) THEN
+      IF (     (INDEX(units,'timesteps since') > 0) &
+          .AND.(tind_varid_in(fid) < 0) ) THEN
+        tind_varid_in(fid) = iv
+        tax_size_in(fid) = vardims_in(fid,iv,1)
+      ENDIF
+      IF (     (INDEX(units,'seconds since') > 0) &
+          .AND.(tax_varid_in(fid) < 0) ) THEN
+        tax_varid_in(fid) = iv
+        tax_size_in(fid) = vardims_in(fid,iv,1)
+      ENDIF
+    ENDIF
+!---
+!-- 2.3 Catch longitude and latitude variables
+!---
+    IF      (INDEX(units,'degrees_nort') > 0) THEN
+      lat_vid = iv
+    ELSE IF (INDEX(units,'degrees_east') > 0) THEN
+      lon_vid = iv
+    ENDIF
+!---
+  ENDDO
+!-
+! 2.4 None of the variables was yet read
+!-
+  nbvar_read(fid) = 0
+  touched_in(fid,:) = .FALSE.
+!-
+! 3.0 Reading the coordinates from the input restart file
+!-
+  lon_read = missing_val
+  lat_read = missing_val
+!-
+  IF (lon_vid < 0 .OR. lat_vid < 0) THEN
+    CALL ipslerr (3,'restopenin',&
+      & ' No variables containing longitude or latitude were ',&
+      & ' found in the restart file.',' ')
+  ELSE
+    iret = NF90_GET_VAR(ncfid,lon_vid,lon_read)
+    iret = NF90_GET_VAR(ncfid,lat_vid,lat_read)
+!---
+    IF (  (ABS( MAXVAL(lon(:,:)) &
+ &             -MINVAL(lon(:,:))) < EPSILON(MAXVAL(lon(:,:)))) &
+ &   .AND.(ABS( MAXVAL(lat(:,:)) &
+ &             -MINVAL(lat(:,:))) < EPSILON(MAXVAL(lat(:,:)))) ) THEN
+!-----
+!---- 3.1 No longitude nor latitude are provided thus
+!---- they are taken from the restart file
+!-----
+      lon(:,:) = lon_read(:,:)
+      lat(:,:) = lat_read(:,:)
+    ELSE
+!-----
+!---- 3.2 We check that the longitudes and latitudes
+!----     in the file and the model are the same
+!-----
+      mdlon = MAXVAL(ABS(lon_read-lon))
+      mdlat = MAXVAL(ABS(lat_read-lat))
+!-----
+!---- We can not test against epsilon here as the longitude
+!---- can be stored at another precision in the netCDF file.
+!---- The test here does not need to be very precise.
+!-----
+      IF (mdlon > 1.e-4 .OR. mdlat > 1.e-4) THEN
+        CALL ipslerr (3,'restopenin',&
+          & ' The longitude or latitude found in the restart ',&
+          & ' file are not the same as the ones used in the model.',&
+          & ' ')
+      ENDIF
+    ENDIF
+  ENDIF
+!------------------------
+END SUBROUTINE restopenin
+!===
+SUBROUTINE restsett (timestep,date0,itau,owrite_time_in)
+!---------------------------------------------------------------------
+!- Here we get all the time information from the file.
+!-
+!- The time information can come in three forms :
+!- -global attributes which give the time origine and the
+!-  time step is taken from the input to restinit
+!- -A physical time exists and thus the julian date from the
+!-  input is used for positioning using the itau as input
+!- -A time-step axis exists and itau is positioned on it.
+!-
+!- What takes precedence : the model
+!-
+!- itau     : Time step of the model
+!-
+!- Optional INPUT arguments
+!-
+!- owrite_time_in : logical  argument which allows to
+!-                  overwrite the time in the restart file
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL :: date0,timestep
+  INTEGER :: itau
+  LOGICAL,OPTIONAL :: owrite_time_in
+!-
+  INTEGER :: ncfid,iret,it,iax,iv
+  CHARACTER(LEN=80) :: itau_orig,tax_orig,calendar
+  CHARACTER(LEN=9) :: tmp_cal
+  INTEGER :: year0,month0,day0,hours0,minutes0,seci
+  REAL :: sec0,one_day,one_year,date0_ju,ttmp
+  CHARACTER :: strc
+  LOGICAL :: ow_time
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (PRESENT(owrite_time_in)) THEN
+    ow_time = owrite_time_in
+  ELSE
+    ow_time = .FALSE.
+  ENDIF
+!-
+  ncfid = netcdf_id(nb_fi,1)
+!-
+! Allocate the space we need for the time axes
+!-
+  CALL rest_atim (l_dbg,'restsett')
+!-
+! Get the calendar if possible. Else it will be gregorian.
+!-
+  IF (tax_size_in(nb_fi) > 0) THEN
+    calendar = ' '
+    iret = NF90_GET_ATT(ncfid,tax_varid_in(nb_fi),'calendar',calendar)
+    IF (iret == NF90_NOERR) THEN
+      CALL ioconf_calendar (calendar)
+      IF (l_dbg) THEN
+        WRITE(*,*) 'restsett : calendar of the restart ',calendar
+      ENDIF
+    ENDIF
+  ENDIF
+  CALL ioget_calendar (one_year,one_day)
+  IF (l_dbg) THEN
+    WRITE(*,*) 'one_year,one_day = ',one_year,one_day
+  ENDIF
+!-
+  itau_orig = 'XXXXX'
+  tax_orig  = 'XXXXX'
+!-
+! Get the time steps of the time axis if available on the restart file
+!-
+  IF (tind_varid_in(nb_fi) > 0) THEN
+    IF (ow_time) THEN
+      t_index(nb_fi,:) = itau
+      IF (l_dbg) THEN
+        WRITE(*,*) "nb_fi,t_index",nb_fi,t_index(nb_fi,:)
+      ENDIF
+      CALL ju2ymds (date0,year0,month0,day0,sec0)
+      hours0 = NINT(sec0/3600)
+      sec0 = sec0 - 3600 * hours0
+      minutes0 = NINT(sec0 / 60)
+      sec0 = sec0 - 60 * minutes0
+      seci = NINT(sec0)
+      strc=':'
+      IF (l_dbg) THEN
+        WRITE(*,*) date0
+        WRITE (UNIT=itau_orig,FMT='(I4.4,5(A,I2.2))') &
+ &       year0,'-',month0,'-',day0,' ',hours0,':',minutes0,':',seci
+        WRITE(*,*) "itau_orig : ",itau_orig
+      ENDIF
+    ELSE
+      iret = NF90_GET_VAR(ncfid,tind_varid_in(nb_fi),t_index(nb_fi,:))
+      IF (l_dbg) THEN
+        WRITE(*,*) "restsett, time axis : ",t_index(nb_fi,:)
+      ENDIF
+      iret = NF90_GET_ATT(ncfid,tind_varid_in(nb_fi),'units',itau_orig)
+      itau_orig = &
+ &      itau_orig(INDEX(itau_orig,'since')+6:LEN_TRIM(itau_orig))
+      iret = &
+ &      NF90_GET_ATT(ncfid,tind_varid_in(nb_fi),'tstep_sec',timestep)
+!-----
+!---- This time origin will dominate as it is linked to the time steps.
+!-----
+      READ (UNIT=itau_orig,FMT='(I4.4,5(A,I2.2))') &
+ &      year0,strc,month0,strc,day0,strc, &
+ &      hours0,strc,minutes0,strc,seci
+      sec0 = REAL(seci)
+      sec0 = hours0*3600.+minutes0*60.+sec0
+      CALL ymds2ju (year0,month0,day0,sec0,date0)
+    ENDIF
+  ENDIF
+!-
+! If a julian day time axis is available then we get it
+!-
+  IF (tax_varid_in(nb_fi) > 0) THEN
+    iret = NF90_GET_VAR(ncfid,tax_varid_in(nb_fi),t_julian(nb_fi,:))
+    iret = NF90_GET_ATT(ncfid,tax_varid_in(nb_fi),'units',tax_orig)
+    tax_orig = tax_orig(INDEX(tax_orig,'since')+6:LEN_TRIM(tax_orig))
+    tmp_cal = ' '
+    iret = NF90_GET_ATT(ncfid,tax_varid_in(nb_fi),'calendar',tmp_cal)
+    IF (l_dbg) THEN
+      WRITE(*,*) 'restsett : tmp_calendar of the restart ',tmp_cal
+    ENDIF
+!---
+    CALL strlowercase (tmp_cal)
+    IF (INDEX(calend_str,tmp_cal) < 1) THEN
+      IF (INDEX(calend_str,'unknown') > 0) THEN
+        calend_str = tmp_cal
+      ELSE
+        CALL ipslerr (2,'restsett', &
+ &       ' In the restart files two different calendars were found.', &
+ &       ' Please check the files you have used.',' ')
+      ENDIF
+    ENDIF
+!---
+!-- We need to transform that into julian days
+!-- to get ride of the intial date.
+!---
+    IF (l_dbg) WRITE(*,*) 'tax_orig : ',TRIM(tax_orig)
+    READ (UNIT=tax_orig,FMT='(I4.4,5(a,I2.2))') &
+      year0,strc,month0,strc,day0,strc, &
+      hours0,strc,minutes0,strc,seci
+    sec0 = REAL(seci)
+    sec0 = hours0*3600.+minutes0*60.+sec0
+    CALL ymds2ju (year0,month0,day0,sec0,date0_ju)
+    t_julian(nb_fi,:) = t_julian(nb_fi,:)/one_day+date0_ju
+  ENDIF
+!-
+  IF (     (INDEX(itau_orig,'XXXXX') > 0) &
+      .AND.(INDEX(tax_orig,'XXXXX')  < 1) ) THEN
+!!- Compute the t_itau from the date read and the timestep in the input
+  ENDIF
+!-
+  IF (     (INDEX(tax_orig,'XXXXX')  > 0) &
+      .AND.(INDEX(itau_orig,'XXXXX') < 1) ) THEN
+    DO it=1,tax_size_in(nb_fi)
+      t_julian(nb_fi,it) = itau2date(t_index(nb_fi,it),date0,timestep)
+    ENDDO
+  ENDIF
+!-
+! If neither the indices or time is present then get global attributes
+! This is for compatibility reasons and should not be used.
+!-
+  IF ((tax_varid_in(nb_fi) < 0).AND.(tind_varid_in(nb_fi) < 0)) THEN
+    iax = -1
+    DO iv=1,nbvar_in(nb_fi)
+      IF (    (INDEX(varname_in(nb_fi,iv),'tsteps') > 0) &
+ &        .OR.(INDEX(varname_in(nb_fi,iv),'time_steps') > 0)) THEN
+        iax = iv
+      ENDIF
+    ENDDO
+!---
+    IF (iax < 0) THEN
+      CALL ipslerr (3,'restsett',&
+        & 'No time axis was found in the restart file. Please check',&
+        & 'that it corresponds to the convention used in restsett',&
+        & ' ')
+    ELSE
+      iret = NF90_GET_VAR(ncfid,tind_varid_in(nb_fi),t_index(nb_fi,:))
+      iret = NF90_GET_ATT(ncfid,NF90_GLOBAL,'delta_tstep_sec',timestep)
+      iret = NF90_GET_ATT(ncfid,NF90_GLOBAL,'year0',ttmp)
+      year0 = NINT(ttmp)
+      iret = NF90_GET_ATT(ncfid,NF90_GLOBAL,'month0',ttmp)
+      month0 = NINT(ttmp)
+      iret = NF90_GET_ATT(ncfid,NF90_GLOBAL,'day0',ttmp)
+      day0 = NINT(ttmp)
+      iret = NF90_GET_ATT(ncfid,NF90_GLOBAL,'sec0',sec0)
+!---
+      CALL ymds2ju (year0,month0,day0,sec0,date0)
+      t_julian(nb_fi,1) = itau2date(t_index(nb_fi,1),date0,timestep)
+    ENDIF
+  ENDIF
+!----------------------
+END SUBROUTINE restsett
+!===
+SUBROUTINE restopenout &
+  (fid,fname,iim,jjm, &
+   lon,lat,llm,lev,timestep,date,ncfid,domain_id)
+!---------------------------------------------------------------------
+!- Opens the restart file for output.
+!- The longitude and time variables are written.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: fid,iim,jjm,llm
+  CHARACTER(LEN=*) :: fname
+  REAL :: date,timestep
+  REAL :: lon(iim,jjm),lat(iim,jjm),lev(llm)
+  INTEGER,INTENT(OUT) :: ncfid
+  INTEGER,INTENT(IN),OPTIONAL :: domain_id
+!-
+  INTEGER :: iret
+  CHARACTER(LEN=70) :: str_t
+  INTEGER :: x_id,y_id,z_id,itauid
+  INTEGER :: nlonid,nlatid,nlevid,timeid
+  INTEGER :: year,month,day,hours,minutes
+  REAL :: sec
+  CHARACTER(LEN=3),DIMENSION(12) :: &
+    cal = (/'JAN','FEB','MAR','APR','MAY','JUN', &
+            'JUL','AUG','SEP','OCT','NOV','DEC'/)
+  CHARACTER(LEN=30) :: timenow
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout 0.0 ",TRIM(fname)
+!-
+!  If we use the same file for input and output
+!- we will not even call restopenout
+!-
+  iret = NF90_CREATE(fname,NF90_NOCLOBBER,ncfid)
+  IF (iret == -35) THEN
+    CALL ipslerr (3,'restopenout',&
+      & ' The restart file aready exists on the disc. IOIPSL ',&
+      & ' will not overwrite it. You should remove the old one or ',&
+      & ' generate the new one with another name')
+  ENDIF
+!-
+  iret = NF90_DEF_DIM(ncfid,'x',iim,x_id)
+  xax_nb(fid) = xax_nb(fid)+1
+  xax_infs(fid,xax_nb(fid),1) = iim
+  xax_infs(fid,xax_nb(fid),2) = x_id
+!-
+  iret = NF90_DEF_DIM(ncfid,'y',jjm,y_id)
+  yax_nb(fid)  = yax_nb(fid)+1
+  yax_infs(fid,yax_nb(fid),1) = jjm
+  yax_infs(fid,yax_nb(fid),2) = y_id
+!-
+  iret = NF90_DEF_DIM(ncfid,'z',llm,z_id)
+  zax_nb(fid) = zax_nb(fid)+1
+  zax_infs(fid,zax_nb(fid),1) = llm
+  zax_infs(fid,zax_nb(fid),2) = z_id
+!-
+  iret = NF90_DEF_DIM(ncfid,'time',NF90_UNLIMITED,tdimid_out(fid))
+!-
+! 1.0 Longitude
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout 1.0"
+!-
+  iret = NF90_DEF_VAR(ncfid,"nav_lon",NF90_FLOAT,(/x_id,y_id/),nlonid)
+  iret = NF90_PUT_ATT(ncfid,nlonid,'units',"degrees_east")
+  iret = NF90_PUT_ATT(ncfid,nlonid,'valid_min',REAL(-180.,KIND=4))
+  iret = NF90_PUT_ATT(ncfid,nlonid,'valid_max',REAL( 180.,KIND=4))
+  iret = NF90_PUT_ATT(ncfid,nlonid,'long_name',"Longitude")
+!-
+! 2.0 Latitude
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout 2.0"
+!-
+  iret = NF90_DEF_VAR(ncfid,"nav_lat",NF90_FLOAT,(/x_id,y_id/),nlatid)
+  iret = NF90_PUT_ATT(ncfid,nlatid,'units',"degrees_north")
+  iret = NF90_PUT_ATT(ncfid,nlatid,'valid_min',REAL(-90.,KIND=4))
+  iret = NF90_PUT_ATT(ncfid,nlatid,'valid_max',REAL( 90.,KIND=4))
+  iret = NF90_PUT_ATT(ncfid,nlatid,'long_name',"Latitude")
+!-
+! 3.0 Levels
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout 3.0"
+!-
+  iret = NF90_DEF_VAR(ncfid,"nav_lev",NF90_FLOAT,z_id,nlevid)
+  iret = NF90_PUT_ATT(ncfid,nlevid,'units',"model_levels")
+  iret = NF90_PUT_ATT(ncfid,nlevid,'valid_min', &
+ &                     REAL(MINVAL(lev),KIND=4))
+  iret = NF90_PUT_ATT(ncfid,nlevid,'valid_max', &
+ &                     REAL(MAXVAL(lev),KIND=4))
+  iret = NF90_PUT_ATT(ncfid,nlevid,'long_name',"Model levels")
+!-
+! 4.0 Time axis, this is the seconds since axis
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout 4.0"
+!-
+  iret = NF90_DEF_VAR(ncfid,"time",NF90_FLOAT, &
+                       tdimid_out(fid),timeid)
+  tax_varid_out(fid) = timeid
+!-
+  timeorig(fid) = date
+  CALL ju2ymds (date,year,month,day,sec)
+  hours   = INT(sec/(60.*60.))
+  minutes = INT((sec-hours*60.*60.)/60.)
+  sec     = sec-(hours*60.*60.+minutes*60.)
+  WRITE (UNIT=str_t, &
+   FMT='("seconds since ",I4.4,2("-",I2.2)," ",I2.2,2(":",I2.2))') &
+ &  year,month,day,hours,minutes,INT(sec)
+  iret = NF90_PUT_ATT(ncfid,timeid,'units',TRIM(str_t))
+!-
+  CALL ioget_calendar (str_t)
+  iret = NF90_PUT_ATT(ncfid,timeid,'calendar',TRIM(str_t))
+  iret = NF90_PUT_ATT(ncfid,timeid,'title','Time')
+  iret = NF90_PUT_ATT(ncfid,timeid,'long_name','Time axis')
+!-
+  WRITE(UNIT=str_t, &
+   FMT='(" ",I4.4,"-",A3,"-",I2.2," ",I2.2,2(":",I2.2))') &
+ &  year,cal(month),day,hours,minutes,INT(sec)
+  iret = NF90_PUT_ATT(ncfid,timeid,'time_origin',TRIM(str_t))
+!-
+! 5.0 Time axis, this is the time steps since axis
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout 5.0"
+!-
+  iret = NF90_DEF_VAR(ncfid,"time_steps",NF90_INT, &
+ &                    tdimid_out(fid),itauid)
+  tind_varid_out(fid) = itauid
+!-
+  CALL ju2ymds (date,year,month,day,sec)
+!-
+  hours   = INT(sec/(60.*60.))
+  minutes = INT((sec-hours*60.*60.)/60.)
+  sec     = sec-(hours*60.*60.+minutes*60.)
+!-
+  WRITE (UNIT=str_t, &
+   FMT='("timesteps since ",I4.4,2("-",I2.2)," ",I2.2,2(":",I2.2))') &
+ &  year,month,day,hours,minutes,INT(sec)
+!-
+  iret = NF90_PUT_ATT(ncfid,itauid,'units',TRIM(str_t))
+  iret = NF90_PUT_ATT(ncfid,itauid,'title','Time steps')
+  iret = NF90_PUT_ATT(ncfid,itauid,'tstep_sec',REAL(timestep,KIND=4))
+  iret = NF90_PUT_ATT(ncfid,itauid,'long_name','Time step axis')
+!-
+  WRITE(UNIT=str_t, &
+   FMT='(" ",I4.4,"-",A3,"-",I2.2," ",I2.2,2(":",I2.2))') &
+ &  year,cal(month),day,hours,minutes,INT(sec)
+  iret = NF90_PUT_ATT(ncfid,itauid,'time_origin',TRIM(str_t))
+!-
+!  5.2 Write global attributes
+!-
+  iret = NF90_PUT_ATT(ncfid,NF90_GLOBAL,'Conventions',"CF-1.1")
+  iret = NF90_PUT_ATT(ncfid,NF90_GLOBAL,'file_name',TRIM(fname))
+!!  TO BE DONE LATER
+!!   iret = NF90_PUT_ATT(ncfid,NF90_GLOBAL, &
+!!                       'production',TRIM(model_name))
+!!   lock_modname = .TRUE.
+  CALL ioget_timestamp (timenow)
+  iret = NF90_PUT_ATT(ncfid,NF90_GLOBAL,'TimeStamp',TRIM(timenow))
+!-
+! Add DOMAIN attributes if needed
+!-
+  CALL flio_dom_att (ncfid,domain_id)
+!-
+! 6.0 The coordinates are written to the file
+!-
+  iret = NF90_ENDDEF(ncfid)
+!-
+  iret = NF90_PUT_VAR(ncfid,nlonid,lon)
+  iret = NF90_PUT_VAR(ncfid,nlatid,lat)
+  iret = NF90_PUT_VAR(ncfid,nlevid,lev)
+!-
+! 7.0 Set a few variables related to the out file
+!-
+  nbvar_out(fid) = 0
+  itau_out(fid) = -1
+  tstp_out(fid) = 0
+  touched_out(fid,:) = .FALSE.
+!-
+! 7.1 The file is put back in define mode.
+!     This will last until itau_out >= 0
+!-
+  iret = NF90_REDEF(ncfid)
+!-
+  IF (l_dbg) WRITE(*,*) "restopenout END"
+!-------------------------
+END SUBROUTINE restopenout
+!===
+SUBROUTINE restget_opp_r1d &
+ & (fid,vname_q,iim,jjm,llm,itau,def_beha, &
+ &  var,MY_OPERATOR,nbindex,ijndex)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restget_real
+!-
+!- Should work as restput_opp_r1d but the other way around !
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  LOGICAL def_beha
+  REAL :: var(:)
+  CHARACTER(LEN=*) :: MY_OPERATOR
+  INTEGER :: nbindex,ijndex(nbindex)
+!-
+  INTEGER :: req_sz,siz1
+  REAL :: scal
+  CHARACTER(LEN=7) :: topp
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 0.0 What size should be the data in the file
+!-
+  req_sz = 1
+  IF (nbindex == iim .AND. jjm <= 1 .AND. llm <= 1) THEN
+    IF (xax_infs(fid,1,1) > 0) req_sz = req_sz*xax_infs(fid,1,1)
+    IF (yax_infs(fid,1,1) > 0) req_sz = req_sz*yax_infs(fid,1,1)
+    IF (zax_infs(fid,1,1) > 0) req_sz = req_sz*zax_infs(fid,1,1)
+  ELSE
+    CALL ipslerr (3,'resget_opp_r1d', &
+      'Unable to performe an operation on this variable as it has',&
+      'a second and third dimension',vname_q)
+  ENDIF
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var)
+  CALL rest_alloc (1,siz1,l_dbg,'restget_opp_r1d')
+  CALL rest_alloc (2,req_sz,l_dbg,'restget_opp_r1d')
+!-
+! 2.0 Here we get the variable from the restart file
+!-
+  CALL restget_real &
+    (fid,vname_q,xax_infs(fid,1,1),yax_infs(fid,1,1), &
+     zax_infs(fid,1,1),itau,def_beha,buff_tmp2)
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  topp = MY_OPERATOR(1:MIN(LEN_TRIM(MY_OPERATOR),7))
+!-
+  IF (INDEX(indchfun,topp(:LEN_TRIM(topp))) > 0) THEN
+    scal = missing_val
+    CALL mathop (topp,req_sz,buff_tmp2,missing_val, &
+ &               nbindex,ijndex,scal,siz1,buff_tmp1)
+    var(:) = buff_tmp1(1:siz1)
+  ELSE
+    CALL ipslerr (3,'resget_opp_r1d', &
+      'The operation you wish to do on the variable for the ',&
+      'restart file is not allowed.',topp)
+  ENDIF
+!-----------------------------
+END SUBROUTINE restget_opp_r1d
+!===
+SUBROUTINE restget_opp_r2d &
+ & (fid,vname_q,iim,jjm,llm,itau,def_beha, &
+ &  var,MY_OPERATOR,nbindex,ijndex)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restget_real
+!-
+!- Should work as restput_opp_r2d but the other way around !
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  LOGICAL def_beha
+  REAL :: var(:,:)
+  CHARACTER(LEN=*) :: MY_OPERATOR
+  INTEGER :: nbindex,ijndex(nbindex)
+!-
+  INTEGER :: jj,req_sz,ist,var_sz,siz1
+  REAL :: scal
+  CHARACTER(LEN=7) :: topp
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 0.0 What size should be the data in the file
+!-
+  req_sz = 1
+  IF (nbindex == iim  .AND. llm <= 1) THEN
+    IF (xax_infs(fid,1,1) > 0) req_sz = req_sz*xax_infs(fid,1,1)
+    IF (yax_infs(fid,1,1) > 0) req_sz = req_sz*yax_infs(fid,1,1)
+  ELSE
+    CALL ipslerr (3,'resget_opp_r2d', &
+      'Unable to performe an operation on this variable as it has', &
+      'a second and third dimension',vname_q)
+  ENDIF
+!-
+  IF (jjm < 1) THEN
+    CALL ipslerr (3,'resget_opp_r2d', &
+      'Please specify a second dimension which is the', &
+      'layer on which the operations are performed',vname_q)
+  ENDIF
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var,1)
+  CALL rest_alloc (1,siz1,l_dbg,'restget_opp_r2d')
+  CALL rest_alloc (2,req_sz*jjm,l_dbg,'restget_opp_r2d')
+!-
+! 2.0 Here we get the full variable from the restart file
+!-
+  CALL restget_real &
+ & (fid,vname_q,xax_infs(fid,1,1),yax_infs(fid,1,1), &
+ &  jjm,itau,def_beha,buff_tmp2)
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  topp = MY_OPERATOR(1:MIN(LEN_TRIM(MY_OPERATOR),7))
+!-
+  IF (INDEX(indchfun,topp(:LEN_TRIM(topp))) > 0) THEN
+    scal = missing_val
+    var_sz = siz1
+    DO jj = 1,jjm
+      ist = (jj-1)*req_sz+1
+      CALL mathop (topp,req_sz,buff_tmp2(ist:ist+req_sz-1), &
+ &      missing_val,nbindex,ijndex,scal,var_sz,buff_tmp1)
+      var(:,jj) = buff_tmp1(1:siz1)
+    ENDDO
+  ELSE
+    CALL ipslerr (3,'resget_opp_r2d', &
+      'The operation you wish to do on the variable for the ',&
+      'restart file is not allowed.',topp)
+  ENDIF
+!-----------------------------
+END SUBROUTINE restget_opp_r2d
+!===
+SUBROUTINE restget_r1d &
+ & (fid,vname_q,iim,jjm,llm,itau,def_beha,var)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restget_real
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  LOGICAL :: def_beha
+  REAL :: var(:)
+!-
+  INTEGER :: ji,jl,req_sz,var_sz,siz1
+  CHARACTER(LEN=70) :: str,str2
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var)
+  var_sz = siz1
+  CALL rest_alloc (1,var_sz,l_dbg,'restget_r1d')
+!-
+! 2.0 Here we could check if the sizes specified agree
+!     with the size of the variable provided
+!-
+  req_sz = 1
+  IF (iim > 0) req_sz = req_sz*iim
+  IF (jjm > 0) req_sz = req_sz*jjm
+  IF (llm > 0) req_sz = req_sz*llm
+  IF (req_sz > var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable requested from file should be ",I6)') req_sz
+    WRITE(str2, &
+ &    '("but the provided variable can only hold ",I6)') var_sz
+    CALL ipslerr (3,'restget_r1d',str,str2,' ')
+  ENDIF
+  IF (req_sz < var_sz) THEN
+    WRITE(str, &
+ &    '("the size of variable requested from file is ",I6)') req_sz
+    WRITE(str2, &
+ &    '("but the provided variable can hold ",I6)') var_sz
+    CALL ipslerr (2,'restget_r1d', &
+      'There could be a problem here :',str,str2)
+  ENDIF
+!-
+  CALL restget_real &
+ & (fid,vname_q,iim,jjm,llm,itau,def_beha,buff_tmp1)
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  jl=0
+  DO ji=1,siz1
+    jl=jl+1
+    var(ji) = buff_tmp1(jl)
+  ENDDO
+!-------------------------
+END SUBROUTINE restget_r1d
+!===
+SUBROUTINE restget_r2d &
+ & (fid,vname_q,iim,jjm,llm,itau,def_beha,var)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restget_real
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  LOGICAL :: def_beha
+  REAL :: var(:,:)
+!-
+  INTEGER :: ji,jj,jl,req_sz,var_sz,siz1,siz2
+  CHARACTER(LEN=70) :: str,str2
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var,1)
+  siz2 = SIZE(var,2)
+  var_sz = siz1*siz2
+  CALL rest_alloc (1,var_sz,l_dbg,'restget_r2d')
+!-
+! 2.0 Here we check if the sizes specified agree
+!     with the size of the variable provided
+!-
+  req_sz = 1
+  IF (iim > 0) req_sz = req_sz*iim
+  IF (jjm > 0) req_sz = req_sz*jjm
+  IF (llm > 0) req_sz = req_sz*llm
+  IF (req_sz > var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable ",A, &
+ &      //" requested from file should be ",I6)') TRIM(vname_q),req_sz
+    WRITE(str2, &
+ &    '("but the provided variable can only hold ",I6)') var_sz
+    CALL ipslerr (3,'restget_r2d',str,str2,' ')
+  ENDIF
+  IF (req_sz < var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable ",A, &
+ &      //" requested from file is ",I6)') TRIM(vname_q),req_sz
+    WRITE(str2,'("but the provided variable can hold ",I6)') var_sz
+    CALL ipslerr (2,'restget_r2d', &
+      'There could be a problem here :',str,str2)
+  ENDIF
+!-
+  CALL restget_real &
+ & (fid,vname_q,iim,jjm,llm,itau,def_beha,buff_tmp1)
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  jl=0
+  DO jj=1,siz2
+    DO ji=1,siz1
+      jl=jl+1
+      var(ji,jj) = buff_tmp1(jl)
+    ENDDO
+  ENDDO
+!-------------------------
+END SUBROUTINE restget_r2d
+!===
+SUBROUTINE restget_r3d &
+  (fid,vname_q,iim,jjm,llm,itau,def_beha,var)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restget_real
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  LOGICAL def_beha
+  REAL :: var(:,:,:)
+!-
+  INTEGER :: ji,jj,jk,jl,req_sz,var_sz,siz1,siz2,siz3
+  CHARACTER(LEN=70) :: str,str2
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var,1)
+  siz2 = SIZE(var,2)
+  siz3 = SIZE(var,3)
+  var_sz = siz1*siz2*siz3
+  CALL rest_alloc (1,var_sz,l_dbg,'restget_r3d')
+!-
+! 2.0 Here we check if the sizes specified agree
+!     with the size of the variable provided
+!-
+  req_sz = 1
+  IF (iim > 0) req_sz = req_sz*iim
+  IF (jjm > 0) req_sz = req_sz*jjm
+  IF (llm > 0) req_sz = req_sz*llm
+  IF (req_sz > var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable ",A, &
+ &      //" requested from file should be ",I6)') TRIM(vname_q),req_sz
+    WRITE(str2, &
+ &    '("but the provided variable can only hold ",I6)') var_sz
+    CALL ipslerr (3,'restget_r3d',str,str2,' ')
+  ENDIF
+  IF (req_sz < var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable ",A, &
+ &      //" requested from file is ",I6)') TRIM(vname_q),req_sz
+    WRITE(str2,'("but the provided variable can hold ",I6)') var_sz
+    CALL ipslerr (2,'restget_r3d', &
+      'There could be a problem here :',str,str2)
+  ENDIF
+!-
+  CALL restget_real &
+    (fid,vname_q,iim,jjm,llm,itau,def_beha,buff_tmp1)
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  jl=0
+  DO jk=1,siz3
+    DO jj=1,siz2
+      DO ji=1,siz1
+        jl=jl+1
+        var(ji,jj,jk) = buff_tmp1(jl)
+      ENDDO
+    ENDDO
+  ENDDO
+!-------------------------
+END SUBROUTINE restget_r3d
+!===
+SUBROUTINE restget_real &
+  (fid,vname_q,iim,jjm,llm,itau,def_beha,var)
+!---------------------------------------------------------------------
+!- This subroutine is for getting a variable from the restart file.
+!- A number of verifications will be made :
+!- - Is this the first time we read this variable ?
+!- - Are the dimensions correct ?
+!- - Is the correct time step present in the file
+!- - is a default behaviour possible. If not the model is stoped.
+!- Default procedure is to write the content of val_exp on all values.
+!-
+!- INPUT
+!-
+!- fid            : Identification of the file
+!- vname_q        : Name of the variable to be read
+!- iim, jjm ,llm  : Dimensions of the variable that should be read
+!- itau           : Time step at whcih we are when we want
+!-                  to read the variable
+!- def_beha       : If the model can restart without this variable
+!-                  then some strange value is given.
+!-
+!- OUTPUT
+!-
+!- var            : Variable in which the data is put
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  LOGICAL :: def_beha
+  REAL :: var(:)
+!-
+  INTEGER :: vid,vnb,ncfid,iret,index,it,ndim,ia
+  CHARACTER(LEN=70) str,str2
+  CHARACTER(LEN=80) attname
+  INTEGER,DIMENSION(4) :: corner,edge
+!---------------------------------------------------------------------
+  ncfid = netcdf_id(fid,1)
+!-
+  CALL find_str (varname_in(fid,1:nbvar_in(fid)),vname_q,vnb)
+!-
+! 1.0 If the variable is not present then ERROR or filled up
+!     by default values if allowed
+!-
+  IF (vnb < 0) THEN
+    IF (def_beha) THEN
+!-----
+      lock_valexp = .TRUE.
+      var(:) = val_exp
+!----
+      str = 'Variable '//TRIM(vname_q) &
+          //' is not present in the restart file'
+      CALL ipslerr (1,'restget', &
+ &      str,'but default values are used to fill in',' ')
+!----
+      IF (nbvar_in(fid) >= max_var) THEN
+        CALL ipslerr (3,'restget', &
+         'Too many variables for the restcom module', &
+         'Please increase the value of max_var',' ')
+      ENDIF
+      nbvar_in(fid) = nbvar_in(fid)+1
+      vnb = nbvar_in(fid)
+      varname_in(fid,vnb) = vname_q
+      touched_in(fid,vnb) = .TRUE.
+!-----
+      CALL restdefv (fid,vname_q,iim,jjm,llm,.TRUE.)
+!-----
+    ELSE
+      str = 'Variable '//TRIM(vname_q) &
+          //' is not present in the restart file'
+      CALL ipslerr (3,'restget', &
+ &      str,'but it is need to restart the model',' ')
+    ENDIF
+!---
+  ELSE
+!---
+!--  2.0 Check if the variable has not yet been read
+!--      and that the time is OK
+!---
+    vid = varid_in(fid,vnb)
+!---
+    nbvar_read(fid) = nbvar_read(fid)+1
+!---
+    IF (touched_in(fid,vnb)) THEN
+      str = 'Variable '//TRIM(vname_q) &
+          //' has already been read from file'
+      CALL ipslerr (3,'restget',str,' ',' ')
+    ENDIF
+!---
+!-- 3.0 get the time step of the restart file
+!--     and check if it is correct
+!---
+    index = -1
+    DO it=1,tax_size_in(fid)
+      IF (t_index(fid,it) == itau)  index = it
+    ENDDO
+    IF (index < 0) THEN
+      str = 'The time step requested for variable '//TRIM(vname_q)
+      CALL ipslerr (3,'restget', &
+ &      str,'is not available in the current file',' ')
+    ENDIF
+!---
+!-- 4.0 Read the data. Note that the variables in the restart files
+!--     have no time axis is and thus we write -1
+!---
+    str='Incorrect dimension for '//TRIM(vname_q)
+    ndim = 0
+    IF (iim > 0) THEN
+      ndim = ndim+1
+      IF (vardims_in(fid,vnb,ndim) == iim) THEN
+        corner(ndim) = 1
+        edge(ndim) = iim
+      ELSE
+        WRITE (str2,'("Incompatibility for iim : ",I6,I6)') &
+             iim,vardims_in(fid,vnb,ndim)
+        CALL ipslerr (3,'restget',str,str2,' ')
+      ENDIF
+    ENDIF
+!---
+    IF (jjm > 0) THEN
+      ndim = ndim+1
+      IF (vardims_in(fid,vnb,ndim) == jjm) THEN
+        corner(ndim) = 1
+        edge(ndim) = jjm
+      ELSE
+        WRITE (str2,'("Incompatibility for jjm : ",I6,I6)') &
+             jjm,vardims_in(fid,vnb,ndim)
+        CALL ipslerr (3,'restget',str,str2,' ')
+      ENDIF
+    ENDIF
+!---
+    IF (llm > 0) THEN
+      ndim = ndim+1
+      IF (vardims_in(fid,vnb,ndim) == llm) THEN
+        corner(ndim) = 1
+        edge(ndim) = llm
+      ELSE
+        WRITE (str2,'("Incompatibility for llm : ",I6,I6)') &
+             llm,vardims_in(fid,vnb,ndim)
+        CALL ipslerr (3,'restget',str,str2,' ')
+      ENDIF
+    ENDIF
+!---
+!-- Time
+!---
+    ndim = ndim+1
+    corner(ndim) = index
+!!????? edge(ndim) = index
+    edge(ndim) = 1
+!---
+    iret = NF90_GET_VAR(ncfid,vid,var, &
+ &                      start=corner(1:ndim),count=edge(1:ndim))
+!---
+!-- 5.0 The variable we have just read is created
+!--      in the next restart file
+!---
+    IF (     (netcdf_id(fid,1) /= netcdf_id(fid,2))  &
+ &      .AND.(netcdf_id(fid,2) > 0) ) THEN
+!-----
+      CALL restdefv (fid,vname_q,iim,jjm,llm,.FALSE.)
+!-----
+      DO ia = 1,varatt_in(fid,vnb)
+        iret = NF90_INQ_ATTNAME(ncfid,vid,ia,attname)
+        iret = NF90_COPY_ATT(ncfid,vid,attname, &
+ &               netcdf_id(fid,2),varid_out(fid,nbvar_out(fid)))
+      ENDDO
+!-----
+      IF (itau_out(fid) >= 0) THEN
+        iret = NF90_ENDDEF(netcdf_id(fid,2))
+      ENDIF
+    ENDIF
+!---
+  ENDIF
+!--------------------------
+END SUBROUTINE restget_real
+!===
+SUBROUTINE restput_opp_r1d &
+ & (fid,vname_q,iim,jjm,llm,itau,var,MY_OPERATOR,nbindex,ijndex)
+!---------------------------------------------------------------------
+!- This subroutine is the interface to restput_real which allows
+!- to re-index data onto the original grid of the restart file.
+!- The logic we use is still fuzzy in my mind but that is probably
+!- only because I have not yet though through everything.
+!-
+!- In the case iim = nbindex it means that the user attempts
+!- to project a vector back onto the original 2D or 3D field.
+!- This requires that jjm and llm be equal to 1 or 0,
+!- else I would not know what it means.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  REAL :: var(:)
+  CHARACTER(LEN=*) :: MY_OPERATOR
+  INTEGER :: nbindex,ijndex(nbindex)
+!-
+  INTEGER :: req_sz,siz1
+  REAL :: scal
+  CHARACTER(LEN=7) :: topp
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 0.0 What size should be the data in the file
+!-
+  req_sz = 1
+  IF ( nbindex == iim .AND. jjm <= 1 .AND. llm <= 1) THEN
+    IF (xax_infs(fid,1,1) > 0) req_sz = req_sz*xax_infs(fid,1,1)
+    IF (yax_infs(fid,1,1) > 0) req_sz = req_sz*yax_infs(fid,1,1)
+    IF (zax_infs(fid,1,1) > 0) req_sz = req_sz*zax_infs(fid,1,1)
+  ELSE
+    CALL ipslerr (3,'restput_opp_r1d', &
+      'Unable to performe an operation on this variable as it has', &
+      'a second and third dimension',vname_q)
+  ENDIF
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var)
+  CALL rest_alloc (1,siz1,l_dbg,'restput_opp_r1d')
+  CALL rest_alloc (2,req_sz,l_dbg,'restput_opp_r1d')
+!-
+! 2.0 We do the operation needed.
+!     It can only be a re-indexing operation.
+!     You would not want to change the values in a restart file or ?
+!-
+  topp = MY_OPERATOR(1:MIN(LEN_TRIM(MY_OPERATOR),7))
+!-
+  IF (INDEX(indchfun,topp(:LEN_TRIM(topp))) > 0) THEN
+    scal = missing_val
+    buff_tmp1(1:siz1) = var(:)
+    CALL mathop &
+ &    (topp,siz1,buff_tmp1,missing_val,nbindex,ijndex, &
+ &     scal,req_sz,buff_tmp2)
+  ELSE
+    CALL ipslerr (3,'restput_opp_r1d', &
+ &    'The operation you wish to do on the variable for the ', &
+ &    'restart file is not allowed.',topp)
+  ENDIF
+!-
+  CALL restput_real &
+ & (fid,vname_q,xax_infs(fid,1,1),yax_infs(fid,1,1), &
+ &  zax_infs(fid,1,1),itau,buff_tmp2)
+!-----------------------------
+END SUBROUTINE restput_opp_r1d
+!===
+SUBROUTINE restput_opp_r2d &
+ & (fid,vname_q,iim,jjm,llm,itau,var,MY_OPERATOR,nbindex,ijndex)
+!---------------------------------------------------------------------
+!- This subroutine is the interface to restput_real which allows
+!- to re-index data onto the original grid of the restart file.
+!- The logic we use is still fuzzy in my mind but that is probably
+!- only because I have not yet though through everything.
+!-
+!- In the case iim = nbindex it means that the user attempts
+!- to project the first dimension of the matrix back onto a 3D field
+!- where jjm will be the third dimension.
+!- Here we do not allow for 4D data, thus we will take the first
+!- two dimensions in the file and require that llm = 1.
+!- These are pretty heavy constraints but I do not know how
+!- to make it more general. I need to think about it some more.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  REAL :: var(:,:)
+  CHARACTER(LEN=*) :: MY_OPERATOR
+  INTEGER :: nbindex,ijndex(nbindex)
+!-
+  INTEGER :: jj,req_sz,ist,siz1
+  REAL :: scal
+  CHARACTER(LEN=7) :: topp
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 0.0 What size should be the data in the file
+!-
+  req_sz = 1
+  IF ( nbindex == iim .AND. llm <= 1) THEN
+    IF (xax_infs(fid,1,1) > 0) req_sz = req_sz*xax_infs(fid,1,1)
+    IF (yax_infs(fid,1,1) > 0) req_sz = req_sz*yax_infs(fid,1,1)
+  ELSE
+    CALL ipslerr (3,'restput_opp_r2d', &
+      'Unable to performe an operation on this variable as it has', &
+      'a second and third dimension',vname_q)
+  ENDIF
+!-
+  IF (jjm < 1) THEN
+    CALL ipslerr (3,'restput_opp_r2d', &
+      'Please specify a second dimension which is the', &
+      'layer on which the operations are performed',vname_q)
+  ENDIF
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var,1)
+  CALL rest_alloc (1,siz1,l_dbg,'restput_opp_r2d')
+  CALL rest_alloc (2,req_sz*jjm,l_dbg,'restput_opp_r2d')
+!-
+! 2.0 We do the operation needed.
+!     It can only be a re-indexing operation.
+!     You would not want to change the values in a restart file or ?
+!-
+  topp = MY_OPERATOR(1:MIN(LEN_TRIM(MY_OPERATOR),7))
+!-
+  IF (INDEX(indchfun,topp(:LEN_TRIM(topp))) > 0) THEN
+    scal = missing_val
+    DO jj = 1,jjm
+      buff_tmp1(1:siz1) = var(:,jj)
+      ist = (jj-1)*req_sz+1
+      CALL mathop &
+ &      (topp,siz1,buff_tmp1,missing_val,nbindex,ijndex, &
+ &       scal,req_sz,buff_tmp2(ist:ist+req_sz-1))
+    ENDDO
+  ELSE
+    CALL ipslerr (3,'restput_opp_r2d', &
+ &    'The operation you wish to do on the variable for the ', &
+ &    'restart file is not allowed.',topp)
+  ENDIF
+!-
+  CALL restput_real &
+ & (fid,vname_q,xax_infs(fid,1,1),yax_infs(fid,1,1), &
+ &  jjm,itau,buff_tmp2)
+!-----------------------------
+END SUBROUTINE restput_opp_r2d
+!===
+SUBROUTINE restput_r1d (fid,vname_q,iim,jjm,llm,itau,var)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restput_real
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  REAL :: var(:)
+!-
+  INTEGER :: ji,jl,req_sz,var_sz,siz1
+  CHARACTER(LEN=70) :: str,str2
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var)
+  var_sz = siz1
+  CALL rest_alloc (1,var_sz,l_dbg,'restput_r1d')
+!-
+! 2.0 Here we could check if the sizes specified agree
+!     with the size of the variable provided
+!-
+  req_sz = 1
+  IF (iim > 0) req_sz = req_sz*iim
+  IF (jjm > 0) req_sz = req_sz*jjm
+  IF (llm > 0) req_sz = req_sz*llm
+  IF (req_sz > var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable put to the file should be ",I6)') req_sz
+    WRITE(str2, &
+ &    '("but the provided variable is of size ",I6)') var_sz
+    CALL ipslerr (3,'restput_r1d',str,str2,' ')
+  ENDIF
+  IF (req_sz < var_sz) THEN
+    WRITE(str,'("the size of variable put to the file is ",I6)') req_sz
+    WRITE(str2,'("but the provided variable is larger ",I6)') var_sz
+    CALL ipslerr (2,'restput_r1d', &
+      'There could be a problem here :',str,str2)
+  ENDIF
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  jl=0
+  DO ji=1,siz1
+    jl=jl+1
+    buff_tmp1(jl) = var(ji)
+  ENDDO
+!-
+  CALL restput_real (fid,vname_q,iim,jjm,llm,itau,buff_tmp1)
+!-------------------------
+END SUBROUTINE restput_r1d
+!===
+SUBROUTINE restput_r2d (fid,vname_q,iim,jjm,llm,itau,var)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restput_real
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  REAL :: var(:,:)
+!-
+  INTEGER :: ji,jj,jl,req_sz,var_sz,siz1,siz2
+  CHARACTER(LEN=70) :: str,str2
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var,1)
+  siz2 = SIZE(var,2)
+  var_sz = siz1*siz2
+  CALL rest_alloc (1,var_sz,l_dbg,'restput_r2d')
+!-
+! 2.0 Here we could check if the sizes specified agree
+!     with the size of the variable provided
+!-
+  req_sz = 1
+  IF (iim > 0) req_sz = req_sz*iim
+  IF (jjm > 0) req_sz = req_sz*jjm
+  IF (llm > 0) req_sz = req_sz*llm
+  IF (req_sz > var_sz) THEN
+    WRITE(str, &
+&         '("Size of variable put to the file should be ",I6)') req_sz
+    WRITE(str2,'("but the provided variable is of size  ",I6)') var_sz
+    CALL ipslerr (3,'restput_r2d',str,str2,' ')
+  ENDIF
+  IF (req_sz < var_sz) THEN
+    WRITE(str,'("the size of variable put to the file is ",I6)') req_sz
+    WRITE(str2,'("but the provided variable is larger ",I6)')  var_sz
+    CALL ipslerr (2,'restput_r2d', &
+      'There could be a problem here :',str,str2)
+  ENDIF
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  jl=0
+  DO jj=1,siz2
+    DO ji=1,siz1
+      jl=jl+1
+      buff_tmp1(jl) = var(ji,jj)
+    ENDDO
+  ENDDO
+!-
+  CALL restput_real(fid,vname_q,iim,jjm,llm,itau,buff_tmp1)
+!-------------------------
+END SUBROUTINE restput_r2d
+!===
+SUBROUTINE restput_r3d (fid,vname_q,iim,jjm,llm,itau,var)
+!---------------------------------------------------------------------
+!- This subroutine serves as an interface to restput_real
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: iim,jjm,llm,itau
+  REAL :: var(:,:,:)
+!-
+  INTEGER :: ji,jj,jk,jl,req_sz,var_sz,siz1,siz2,siz3
+  CHARACTER(LEN=70) :: str,str2
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 1.0 Allocate the temporary buffer we need
+!     to put the variable in right dimension
+!-
+  siz1 = SIZE(var,1)
+  siz2 = SIZE(var,2)
+  siz3 = SIZE(var,3)
+  var_sz = siz1*siz2*siz3
+  CALL rest_alloc (1,var_sz,l_dbg,'restput_r3d')
+!-
+! 2.0 Here we could check if the sizes specified agree
+!     with the size of the variable provided
+!-
+  req_sz = 1
+  IF (iim > 0) req_sz = req_sz*iim
+  IF (jjm > 0) req_sz = req_sz*jjm
+  IF (llm > 0) req_sz = req_sz*llm
+  IF (req_sz > var_sz) THEN
+    WRITE(str, &
+ &    '("Size of variable put to the file should be ",I6)') req_sz
+    WRITE(str2, &
+ &    '("but the provided variable is of size  ",I6)')  var_sz
+    CALL ipslerr (3,'restput_r3d',str,str2,' ')
+  ENDIF
+  IF (req_sz < var_sz) THEN
+    WRITE(str,'("the size of variable put to the file is ",I6)') req_sz
+    WRITE(str2,'("but the provided variable is larger ",I6)')  var_sz
+    CALL ipslerr (2,'restput_r3d', &
+      'There could be a problem here :',str,str2)
+  ENDIF
+!-
+! 4.0 Transfer the buffer obtained from the restart file
+!     into the variable the model expects
+!-
+  jl=0
+  DO jk=1,siz3
+    DO jj=1,siz2
+      DO ji=1,siz1
+        jl=jl+1
+        buff_tmp1(jl) = var(ji,jj,jk)
+      ENDDO
+    ENDDO
+  ENDDO
+!-
+  CALL restput_real(fid,vname_q,iim,jjm,llm,itau,buff_tmp1)
+!-------------------------
+END SUBROUTINE restput_r3d
+!===
+SUBROUTINE restput_real (fid,vname_q,iim,jjm,llm,itau,var)
+!---------------------------------------------------------------------
+!- This subroutine will put a variable into the restart file.
+!- But it will do a lot of other things if needed :
+!- - Open a file if non is opened for this time-step
+!-   and all variables were written.
+!- - Add an axis if needed
+!- - verify that the variable has the right time step for this file
+!- - If it is time for a new file then it is opened
+!-   and the old one closed
+!- This requires that variables read from the last restart file were all
+!- written
+!-
+!- INPUT
+!-
+!- fid         : Id of the file in which we will write the variable
+!- vname_q     : Name of the variable to be written
+!- iim,jjm,llm : Size in 3D of the variable
+!- itau        : Time step at which the variable is written
+!- var         : Variable
+!-
+!- OUTPUT
+!-
+!- NONE
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER :: fid,iim,jjm,llm,itau
+  REAL :: var(:)
+!-
+  INTEGER :: iret,vid,ncid,iv,vnb
+  INTEGER :: ierr
+  REAL :: secsince,one_day,one_year
+  INTEGER :: ndims
+  INTEGER,DIMENSION(4) :: corner,edge
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+! 0.0 Get some variables
+!-
+  ncid = netcdf_id(fid,2)
+  IF (netcdf_id(fid,2) < 0) THEN
+    CALL ipslerr (3,'restput', &
+ &    'The output restart file is undefined.',' ',' ')
+  ENDIF
+  CALL ioget_calendar (one_year,one_day)
+!-
+! 1.0 Check if the variable is already present
+!-
+  IF (l_dbg) WRITE(*,*) 'RESTPUT 1.0 : ',TRIM(vname_q)
+!-
+  CALL find_str (varname_out(fid,1:nbvar_out(fid)),vname_q,vnb)
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'RESTPUT 1.1 : ',varname_out(fid,1:nbvar_out(fid)),vnb
+  ENDIF
+!-
+! 2.0 If variable is not present then declare it
+!     and add extra dimensions if needed.
+!-
+  IF (vnb <= 0) THEN
+    CALL restdefv (fid,vname_q,iim,jjm,llm,.TRUE.)
+    vnb = nbvar_out(fid)
+  ENDIF
+  vid = varid_out(fid,vnb)
+!-
+  IF (l_dbg) WRITE(*,*) 'RESTPUT 2.0 : ',vnb,vid
+!-
+! 2.1 Is this file already in write mode ?
+!     If itau_out is still negative then we have
+!     never written to it and we need to go into write mode.
+!-
+  IF (itau_out(fid) < 0) THEN
+    iret = NF90_ENDDEF(ncid)
+  ENDIF
+!-
+! 3.0 Is this itau already on the axis ?
+!     If not then check that all variables of previous time is OK.
+!-
+  IF (l_dbg) WRITE(*,*) 'RESTPUT 3.0 : ',itau,itau_out(fid)
+!-
+  IF (itau /= itau_out(fid)) THEN
+!---
+!-- If it is the first time step written on the restart
+!-- then we only check the number
+!-- Else we see if every variable was written
+!---
+    IF (tstp_out(fid) == 0) THEN
+      IF (nbvar_out(fid) < nbvar_read(fid)) THEN
+        WRITE(*,*) "ERROR :",tstp_out(fid), &
+                   nbvar_out(fid),nbvar_read(fid)
+        CALL ipslerr (1,'restput', &
+ &        'There are fewer variables read from the output file', &
+ &        'than written onto the input file.', &
+ &        'We trust you know what you are doing')
+      ENDIF
+    ELSE
+      ierr = 0
+      DO iv=1,nbvar_out(fid)
+        IF (.NOT.touched_out(fid,iv)) ierr = ierr+1
+      ENDDO
+      IF (ierr > 0) THEN
+        WRITE(*,*) "ERROR :",nbvar_out(fid)
+        CALL ipslerr (1,'restput', &
+ &        'There are fewer variables in the output file for this', &
+ &        'time step than for the previous one',' ')
+      ELSE
+        touched_out(fid,:) = .FALSE.
+      ENDIF
+    ENDIF
+!---
+    secsince = itau*deltat(fid)
+    corner(1) =  tstp_out(fid)+1
+    edge(1) = 1
+!---
+!-- 3.1 Here we add the values to the time axes
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) 'RESTPUT 3.1 : ',itau,secsince,corner(1),edge(1)
+    ENDIF
+!---
+    iret = NF90_PUT_VAR(ncid,tind_varid_out(fid),itau, &
+ &                      start=corner(1:1))
+    iret = NF90_PUT_VAR(ncid,tax_varid_out(fid),secsince, &
+ &                      start=corner(1:1))
+!---
+    tstp_out(fid) = tstp_out(fid)+1
+    itau_out(fid) = itau
+  ENDIF
+!-
+! 4.0 Variable and time step should be present
+!     now so we can dump variable
+!-
+  ndims = 0
+  IF (iim > 0) THEN
+    ndims = ndims+1
+    corner(ndims) = 1
+    edge(ndims) = iim
+  ENDIF
+  IF (jjm > 0) THEN
+    ndims = ndims+1
+    corner(ndims) = 1
+    edge(ndims) = jjm
+  ENDIF
+  IF (llm > 0) THEN
+    ndims = ndims+1
+    corner(ndims) = 1
+    edge(ndims) = llm
+  ENDIF
+  ndims = ndims+1
+  corner(ndims) = tstp_out(fid)
+  edge(ndims) = 1
+!-
+  iret = NF90_PUT_VAR(ncid,vid,var, &
+ &                    start=corner(1:ndims),count=edge(1:ndims))
+!-
+  IF (iret /= NF90_NOERR) THEN
+    CALL ipslerr (2,'restput_real',NF90_STRERROR(iret), &
+ &    'Bug in restput.',&
+ &    'Please, verify compatibility between get and put commands.')
+  ENDIF
+!-
+!  5.0 Note that the variables was treated
+!-
+  touched_out(fid,vnb) = .TRUE.
+!---------------------------
+END  SUBROUTINE restput_real
+!===
+SUBROUTINE restdefv (fid,varname,iim,jjm,llm,write_att)
+!---------------------------------------------------------------------
+! This subroutine adds a variable to the output file.
+! The attributes are either taken from.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER ::fid
+  CHARACTER(LEN=*) :: varname
+  INTEGER :: iim,jjm,llm
+  LOGICAL :: write_att
+!-
+  INTEGER :: dims(4),ic,xloc,ndim,ncfid
+  INTEGER :: iret,ax_id
+  CHARACTER(LEN=3) :: str
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  ncfid = netcdf_id(fid,2)
+  IF (nbvar_out(fid) >= max_var) THEN
+    CALL ipslerr (3,'restdefv', &
+      'Too many variables for the restcom module', &
+      'Please increase the value of max_var',' ')
+  ENDIF
+  nbvar_out(fid) = nbvar_out(fid)+1
+  varname_out(fid,nbvar_out(fid)) = varname
+!-
+! 0.0 Put the file in define mode if needed
+!-
+  IF (itau_out(fid) >= 0) THEN
+    iret = NF90_REDEF(ncfid)
+  ENDIF
+!-
+! 1.0 Do we have all dimensions and can we go ahead
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'restdefv 1.0 :',TRIM(varname),nbvar_out(fid)
+  ENDIF
+!-
+  ndim = 0
+!-
+! 1.1 Work on x
+!-
+  IF (iim > 0) THEN
+    ndim = ndim+1
+    xloc = 0
+    DO ic=1,xax_nb(fid)
+      IF (xax_infs(fid,ic,1) == iim) xloc = ic
+    ENDDO
+!---
+    IF (xloc > 0) THEN
+      dims(ndim) = xax_infs(fid,xloc,2)
+    ELSE
+      str='x_'//CHAR(96+xax_nb(fid))
+      iret = NF90_DEF_DIM(ncfid,str,iim,ax_id)
+      xax_nb(fid) = xax_nb(fid)+1
+      xax_infs(fid,xax_nb(fid),1) = iim
+      xax_infs(fid,xax_nb(fid),2) = ax_id
+      dims(ndim) = ax_id
+    ENDIF
+  ENDIF
+!-
+! 1.2 Work on y
+!-
+  IF (jjm > 0) THEN
+    ndim = ndim+1
+    xloc = 0
+    DO ic=1,yax_nb(fid)
+      IF (yax_infs(fid,ic,1) == jjm) xloc = ic
+    ENDDO
+!---
+    IF (xloc > 0) THEN
+      dims(ndim) = yax_infs(fid,xloc,2)
+    ELSE
+      str='y_'//CHAR(96+yax_nb(fid))
+      iret = NF90_DEF_DIM(ncfid,str,jjm,ax_id)
+      yax_nb(fid) = yax_nb(fid)+1
+      yax_infs(fid,yax_nb(fid),1) = jjm
+      yax_infs(fid,yax_nb(fid),2) = ax_id
+      dims(ndim) = ax_id
+    ENDIF
+  ENDIF
+!-
+! 1.3 Work on z
+!-
+  IF (llm > 0) THEN
+    ndim = ndim+1
+    xloc = 0
+    DO ic=1,zax_nb(fid)
+      IF (zax_infs(fid,ic,1) == llm) xloc = ic
+    ENDDO
+!---
+    IF (xloc > 0) THEN
+      dims(ndim) = zax_infs(fid,xloc,2)
+    ELSE
+      str='z_'//CHAR(96+zax_nb(fid))
+      iret = NF90_DEF_DIM(ncfid,str,llm,ax_id)
+      zax_nb(fid) = zax_nb(fid)+1
+      zax_infs(fid,zax_nb(fid),1) = llm
+      zax_infs(fid,zax_nb(fid),2) = ax_id
+      dims(ndim) = ax_id
+    ENDIF
+  ENDIF
+!-
+! 1.4  Time needs to be added
+!-
+  ndim = ndim+1
+  dims(ndim) = tdimid_out(fid)
+!-
+! 2.0  Declare the variable
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) 'restdefv 2.0 :',ndim,' :: ',dims(1:ndim),tdimid_out(fid)
+  ENDIF
+!-
+  iret = NF90_DEF_VAR(ncfid,varname,NF90_DOUBLE,dims(1:ndim), &
+ &                    varid_out(fid,nbvar_out(fid)))
+  IF (iret /= NF90_NOERR) THEN
+    CALL ipslerr (3,'restdefv', &
+      'Could not define new variable in file', &
+      NF90_STRERROR(iret),varname)
+  ENDIF
+!-
+! 3.0 Add the attributes if requested
+!-
+  IF (write_att) THEN
+    IF (rest_units /= 'XXXXX') THEN
+      iret =  NF90_PUT_ATT(ncfid,varid_out(fid,nbvar_out(fid)), &
+ &                         'units',TRIM(rest_units))
+      rest_units = 'XXXXX'
+    ENDIF
+!---
+    IF (rest_lname /= 'XXXXX') THEN
+      iret =  NF90_PUT_ATT(ncfid,varid_out(fid,nbvar_out(fid)), &
+ &                         'long_name',TRIM(rest_lname))
+      rest_lname = 'XXXXX'
+    ENDIF
+!---
+    iret = NF90_PUT_ATT(ncfid,varid_out(fid,nbvar_out(fid)), &
+ &                      'missing_value',REAL(missing_val,KIND=4))
+!---
+    IF (itau_out(fid) >= 0) THEN
+      iret = NF90_ENDDEF(ncfid)
+    ENDIF
+  ENDIF
+!-
+  IF (l_dbg) THEN
+    WRITE(*,*) &
+ &    'restdefv 3.0 : LIST OF VARS ',varname_out(fid,1:nbvar_out(fid))
+  ENDIF
+!----------------------
+END SUBROUTINE restdefv
+!===
+SUBROUTINE rest_atim (l_msg,c_p)
+!---------------------------------------------------------------------
+! Called by "c_p", [re]allocate the time axes
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  LOGICAL,INTENT(IN) :: l_msg
+  CHARACTER(LEN=*),INTENT(IN) :: c_p
+!-
+  INTEGER :: i_err,tszij
+  INTEGER,ALLOCATABLE :: tmp_index(:,:)
+  REAL,ALLOCATABLE :: tmp_julian(:,:)
+!---------------------------------------------------------------------
+!-
+!  Allocate the space we need for the time axes
+!-
+  IF (.NOT.ALLOCATED(t_index) .AND. .NOT.ALLOCATED(t_julian)) THEN
+    IF (l_msg) THEN
+      WRITE(*,*) TRIM(c_p)//' : Allocate times axes at :', &
+ &               max_file,tax_size_in(nb_fi)
+    ENDIF
+!---
+    ALLOCATE(t_index(max_file,tax_size_in(nb_fi)),STAT=i_err)
+    IF (i_err/=0) THEN
+      WRITE(*,*) "ERROR IN ALLOCATION of t_index : ",i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &      'Problem in allocation of t_index','', &
+ &      '(you must increase memory)')
+    ENDIF
+    t_index (:,:) = 0
+!---
+    ALLOCATE(t_julian(max_file,tax_size_in(nb_fi)),STAT=i_err)
+    IF (i_err/=0) THEN
+      WRITE(*,*) "ERROR IN ALLOCATION of t_julian : ",i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &      'Problem in allocation of max_file,tax_size_in','', &
+ &      '(you must increase memory)')
+    ENDIF
+    t_julian (:,:) = 0.0
+  ELSE IF (    (SIZE(t_index,DIM=2)  < tax_size_in(nb_fi)) &
+ &         .OR.(SIZE(t_julian,DIM=2) < tax_size_in(nb_fi)) ) THEN
+    IF (l_msg) THEN
+      WRITE(*,*) TRIM(c_p)//' : Reallocate times axes at :', &
+ &               max_file,tax_size_in(nb_fi)
+    ENDIF
+!---
+    ALLOCATE (tmp_index(max_file,tax_size_in(nb_fi)),STAT=i_err)
+    IF (i_err/=0) THEN
+      WRITE(*,*) "ERROR IN ALLOCATION of tmp_index : ",i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &      'Problem in allocation of tmp_index','', &
+ &      '(you must increase memory)')
+    ENDIF
+    tszij = SIZE(t_index,DIM=2)
+    tmp_index(:,1:tszij) = t_index(:,1:tszij)
+    DEALLOCATE(t_index)
+    ALLOCATE (t_index(max_file,tax_size_in(nb_fi)),STAT=i_err)
+    IF (i_err/=0) THEN
+      WRITE(*,*) "ERROR IN ALLOCATION of t_index : ",i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &     'Problem in reallocation of t_index','', &
+ &     '(you must increase memory)')
+    ENDIF
+    t_index(:,1:tszij) = tmp_index(:,1:tszij)
+!---
+    ALLOCATE (tmp_julian(max_file,tax_size_in(nb_fi)),STAT=i_err)
+    IF (i_err/=0) THEN
+      WRITE(*,*) "ERROR IN ALLOCATION of tmp_julian : ",i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &     'Problem in allocation of tmp_julian','', &
+ &     '(you must increase memory)')
+    ENDIF
+    tszij = SIZE(t_julian,DIM=2)
+    tmp_julian(:,1:tszij) = t_julian(:,1:tszij)
+    DEALLOCATE(t_julian)
+    ALLOCATE (t_julian(max_file,tax_size_in(nb_fi)),STAT=i_err)
+    IF (i_err/=0) THEN
+      WRITE(*,*) "ERROR IN ALLOCATION of t_julian : ",i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &      'Problem in reallocation of t_julian','', &
+ &      '(you must increase memory)')
+    ENDIF
+    t_julian(:,1:tszij) = tmp_julian(:,1:tszij)
+  ENDIF
+!-----------------------
+END SUBROUTINE rest_atim
+!===
+SUBROUTINE rest_alloc (i_buff,i_qsz,l_msg,c_p)
+!---------------------------------------------------------------------
+! Called by "c_p", allocate a temporary buffer
+! (buff_tmp[1/2] depending on "i_buff" value) to the size "i_qsz".
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: i_buff,i_qsz
+  LOGICAL,INTENT(IN) :: l_msg
+  CHARACTER(LEN=*),INTENT(IN) :: c_p
+!-
+  INTEGER :: i_bsz,i_err
+  LOGICAL :: l_alloc1,l_alloc2
+  CHARACTER(LEN=9) :: cbn
+  CHARACTER(LEN=5) :: c_err
+!---------------------------------------------------------------------
+  IF      (i_buff == 1) THEN
+    IF (ALLOCATED(buff_tmp1)) THEN
+      i_bsz = SIZE(buff_tmp1)
+    ELSE
+      i_bsz = 0
+    ENDIF
+    l_alloc1 =    (.NOT.ALLOCATED(buff_tmp1)) &
+ &            .OR.((ALLOCATED(buff_tmp1)).AND.(i_qsz > i_bsz))
+    l_alloc2 = .FALSE.
+    cbn = 'buff_tmp1'
+  ELSE IF (i_buff == 2) THEN
+    IF (ALLOCATED(buff_tmp2)) THEN
+      i_bsz = SIZE(buff_tmp2)
+    ELSE
+      i_bsz = 0
+    ENDIF
+    l_alloc1 = .FALSE.
+    l_alloc2 =    (.NOT.ALLOCATED(buff_tmp2)) &
+ &            .OR.((ALLOCATED(buff_tmp2)).AND.(i_qsz > i_bsz))
+    cbn = 'buff_tmp2'
+  ELSE
+    CALL ipslerr (3,'rest_alloc', &
+ &    'Called by '//TRIM(c_p),'with a wrong value of i_buff','')
+  ENDIF
+!-
+!-
+  IF (l_alloc1.OR.l_alloc2) THEN
+    IF (l_msg) THEN
+      IF (    (l_alloc1.AND.ALLOCATED(buff_tmp1)) &
+ &        .OR.(l_alloc2.AND.ALLOCATED(buff_tmp2)) ) THEN
+        WRITE(*,*) TRIM(c_p)//" : re_allocate "//TRIM(cbn)//"=",i_qsz
+      ELSE
+        WRITE(*,*) TRIM(c_p)//" : allocate "//TRIM(cbn)//"=",i_qsz
+      ENDIF
+    ENDIF
+    IF (l_alloc1) THEN
+      IF (ALLOCATED(buff_tmp1)) THEN
+        DEALLOCATE(buff_tmp1)
+      ENDIF
+      ALLOCATE (buff_tmp1(i_qsz),STAT=i_err)
+    ELSE
+      IF (ALLOCATED(buff_tmp2)) THEN
+        DEALLOCATE(buff_tmp2)
+      ENDIF
+      ALLOCATE (buff_tmp2(i_qsz),STAT=i_err)
+    ENDIF
+    IF (i_err /= 0) THEN
+      WRITE (UNIT=c_err,FMT='(I5)') i_err
+      CALL ipslerr (3,TRIM(c_p), &
+ &      'Problem in allocation of',TRIM(cbn), &
+ &      'Error : '//TRIM(c_err)//' (you must increase memory)')
+    ENDIF
+  ENDIF
+!------------------------
+END SUBROUTINE rest_alloc
+!===
+SUBROUTINE ioconf_setatt (attname,value)
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: attname,value
+!-
+  CHARACTER(LEN=LEN_TRIM(attname)) :: tmp_str
+!---------------------------------------------------------------------
+  tmp_str = attname
+  CALL strlowercase (tmp_str)
+!-
+  SELECT CASE(tmp_str)
+    CASE('units')
+      rest_units = value
+    CASE('long_name')
+      rest_lname = value
+    CASE DEFAULT
+      CALL ipslerr (2,'ioconf_restatt', &
+        'The attribute name provided is unknown',attname,' ')
+  END SELECT
+!---------------------------
+END SUBROUTINE ioconf_setatt
+!===
+SUBROUTINE ioget_vdim (fid,vname_q,varnbdim_max,varnbdim,vardims)
+!---------------------------------------------------------------------
+!- This routine allows the user to get the dimensions
+!- of a field in the restart file.
+!- This is the file which is read.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: fid
+  CHARACTER(LEN=*) :: vname_q
+  INTEGER,INTENT(IN) :: varnbdim_max
+  INTEGER,INTENT(OUT) ::  varnbdim
+  INTEGER,DIMENSION(varnbdim_max),INTENT(OUT) :: vardims
+!-
+  INTEGER :: vnb
+!---------------------------------------------------------------------
+! Find the index of the variable
+  CALL find_str (varname_in(fid,1:nbvar_in(fid)),vname_q,vnb)
+!-
+  IF (vnb > 0) THEN
+    varnbdim = varnbdim_in(fid,vnb)
+    IF (varnbdim_max < varnbdim) THEN
+      CALL ipslerr (3,'ioget_vdim', &
+        'The provided array for the variable dimensions is too small', &
+        '','')
+    ELSE
+      vardims(1:varnbdim) = vardims_in(fid,vnb,1:varnbdim)
+    ENDIF
+  ELSE
+    varnbdim = 0
+    CALL ipslerr (2,'ioget_vdim', &
+      'Variable '//TRIM(vname_q)//' not found','','')
+  ENDIF
+!------------------------
+END SUBROUTINE ioget_vdim
+!===
+SUBROUTINE ioget_vname (fid,nbvar,varnames)
+!---------------------------------------------------------------------
+!- This routine allows the user to extract the list
+!- of variables in an opened restart file.
+!- This is the file which is read
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(IN) :: fid
+  INTEGER,INTENT(OUT) ::  nbvar
+  CHARACTER(LEN=*),INTENT(OUT) :: varnames(:)
+!---------------------------------------------------------------------
+  nbvar = nbvar_in(fid)
+!-
+  IF (SIZE(varnames) < nbvar) THEN
+    CALL ipslerr (3,'ioget_vname', &
+      'The provided array for the variable names is too small','','')
+  ELSE
+    varnames(1:nbvar) = varname_in(fid,1:nbvar)
+  ENDIF
+!-------------------------
+END SUBROUTINE ioget_vname
+!===
+SUBROUTINE ioconf_expval (new_exp_val)
+!---------------------------------------------------------------------
+!- The default value written into the variables which are not
+!- in the restart file can only be changed once.
+!- This avoids further complications.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL :: new_exp_val
+!---------------------------------------------------------------------
+  IF (.NOT.lock_valexp) THEN
+    lock_valexp = .TRUE.
+    val_exp = new_exp_val
+  ELSE
+    CALL ipslerr (2,'ioconf_expval', &
+     'The default value for variable' &
+   //'not available in the restart file ', &
+     'has already been locked and can not be changed at this point', &
+     ' ')
+  ENDIF
+!---------------------------
+END SUBROUTINE ioconf_expval
+!===
+SUBROUTINE ioget_expval (get_exp_val)
+!---------------------------------------------------------------------
+!- Once the user has extracted the default value,
+!- we lock it so that it can not be changed anymore.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  REAL :: get_exp_val
+!---------------------------------------------------------------------
+  get_exp_val = val_exp
+  lock_valexp = .TRUE.
+!--------------------------
+END SUBROUTINE ioget_expval
+!===
+SUBROUTINE restclo (fid)
+!---------------------------------------------------------------------
+!- This subroutine closes one or any opened restart file.
+!-
+!- INPUT
+!-
+!- fid    : File ID in the restcom system (not the netCDF ID)(optional)
+!-
+!- OUTPUT
+!-
+!- NONE
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER,INTENT(in),OPTIONAL :: fid
+!-
+  INTEGER :: iret,ifnc
+  CHARACTER(LEN=6) :: n_e
+  CHARACTER(LEN=3) :: n_f
+  LOGICAL :: l_dbg
+!---------------------------------------------------------------------
+  CALL ipsldbg (old_status=l_dbg)
+!-
+  IF (PRESENT(fid)) THEN
+!---
+    IF (l_dbg) THEN
+      WRITE(*,*) &
+        'restclo : Closing specified restart file number :', &
+        fid,netcdf_id(fid,1:2)
+    ENDIF
+!---
+    IF (netcdf_id(fid,1) > 0) THEN
+      iret = NF90_CLOSE(netcdf_id(fid,1))
+      IF (iret /= NF90_NOERR) THEN
+        WRITE (n_e,'(I6)') iret
+        WRITE (n_f,'(I3)') netcdf_id(fid,1)
+        CALL ipslerr (2,'restclo', &
+          "Error "//n_e//" in closing file : "//n_f,'',' ')
+      ENDIF
+      IF (netcdf_id(fid,1) == netcdf_id(fid,2)) THEN
+        netcdf_id(fid,2) = -1
+      ENDIF
+      netcdf_id(fid,1) = -1
+    ENDIF
+!---
+    IF (netcdf_id(fid,2) > 0)  THEN
+      iret = NF90_CLOSE(netcdf_id(fid,2))
+      IF (iret /= NF90_NOERR) THEN
+        WRITE (n_e,'(I6)') iret
+        WRITE (n_f,'(I3)') netcdf_id(fid,2)
+        CALL ipslerr (2,'restclo', &
+          "Error "//n_e//" in closing file : "//n_f,'',' ')
+      ENDIF
+      netcdf_id(fid,2) = -1
+    ENDIF
+!---
+  ELSE
+!---
+    IF (l_dbg) WRITE(*,*) 'restclo : Closing all files'
+!---
+    DO ifnc=1,nb_fi
+      IF (netcdf_id(ifnc,1) > 0) THEN
+        iret = NF90_CLOSE(netcdf_id(ifnc,1))
+        IF (iret /= NF90_NOERR) THEN
+          WRITE (n_e,'(I6)') iret
+          WRITE (n_f,'(I3)') netcdf_id(ifnc,1)
+          CALL ipslerr (2,'restclo', &
+            "Error "//n_e//" in closing file : "//n_f,'',' ')
+        ENDIF
+        IF (netcdf_id(ifnc,1) == netcdf_id(ifnc,2)) THEN
+          netcdf_id(ifnc,2) = -1
+        ENDIF
+        netcdf_id(ifnc,1) = -1
+      ENDIF
+!-----
+      IF (netcdf_id(ifnc,2) > 0) THEN
+        iret = NF90_CLOSE(netcdf_id(ifnc,2))
+        IF (iret /= NF90_NOERR) THEN
+          WRITE (n_e,'(I6)') iret
+          WRITE (n_f,'(I3)') netcdf_id(ifnc,2)
+          CALL ipslerr (2,'restclo', &
+            "Error "//n_e//" in closing file : "//n_f,'',' ')
+        END IF
+        netcdf_id(ifnc,2) = -1
+      ENDIF
+    ENDDO
+  ENDIF
+!---------------------
+END SUBROUTINE restclo
+!===
+!-----------------
+END MODULE restcom
Index: /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/stringop.f90
===================================================================
--- /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/stringop.f90	(revision 329)
+++ /codes/icosagcm/branches/SATURN_DYNAMICO/ICOSAGCM_OLD/tools/ioipsl/stringop.f90	(revision 329)
@@ -0,0 +1,238 @@
+MODULE stringop
+!-
+!$Id: stringop.f90 386 2008-09-04 08:38:48Z bellier $
+!-
+! This software is governed by the CeCILL license
+! See IOIPSL/IOIPSL_License_CeCILL.txt
+!---------------------------------------------------------------------
+!-
+  INTEGER,DIMENSION(30) :: &
+ & prime=(/1,2,3,5,7,11,13,17,19,23,29,31,37,41,43, &
+ & 47,53,59,61,67,71,73,79,83,89,97,101,103,107,109/)
+!-
+!---------------------------------------------------------------------
+CONTAINS
+!=
+SUBROUTINE cmpblank (str)
+!---------------------------------------------------------------------
+!- Compact blanks
+!---------------------------------------------------------------------
+  CHARACTER(LEN=*),INTENT(inout) :: str
+!-
+  INTEGER :: lcc,ipb
+!---------------------------------------------------------------------
+  lcc = LEN_TRIM(str)
+  ipb = 1
+  DO
+    IF (ipb >= lcc)   EXIT
+    IF (str(ipb:ipb+1) == '  ') THEN
+      str(ipb+1:) = str(ipb+2:lcc)
+      lcc = lcc-1
+    ELSE
+      ipb = ipb+1
+    ENDIF
+  ENDDO
+!----------------------
+END SUBROUTINE cmpblank
+!===
+INTEGER FUNCTION cntpos (c_c,l_c,c_r,l_r)
+!---------------------------------------------------------------------
+!- Finds number of occurences of c_r in c_c
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(in) :: c_c
+  INTEGER,INTENT(IN) :: l_c
+  CHARACTER(LEN=*),INTENT(in) :: c_r
+  INTEGER,INTENT(IN) :: l_r
+!-
+  INTEGER :: ipos,indx
+!---------------------------------------------------------------------
+  cntpos = 0
+  ipos   = 1
+  DO
+    indx = INDEX(c_c(ipos:l_c),c_r(1:l_r))
+    IF (indx > 0) THEN
+      cntpos = cntpos+1
+      ipos   = ipos+indx+l_r-1
+    ELSE
+      EXIT
+    ENDIF
+  ENDDO
+!------------------
+END FUNCTION cntpos
+!===
+INTEGER FUNCTION findpos (c_c,l_c,c_r,l_r)
+!---------------------------------------------------------------------
+!- Finds position of c_r in c_c
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),INTENT(in) :: c_c
+  INTEGER,INTENT(IN) :: l_c
+  CHARACTER(LEN=*),INTENT(in) :: c_r
+  INTEGER,INTENT(IN) :: l_r
+!---------------------------------------------------------------------
+  findpos = INDEX(c_c(1:l_c),c_r(1:l_r))
+  IF (findpos == 0)  findpos=-1
+!-------------------
+END FUNCTION findpos
+!===
+SUBROUTINE find_str (str_tab,str,pos)
+!---------------------------------------------------------------------
+!- This subroutine looks for a string in a table
+!---------------------------------------------------------------------
+!- INPUT
+!-   str_tab  : Table  of strings
+!-   str      : Target we are looking for
+!- OUTPUT
+!-   pos      : -1 if str not found, else value in the table
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*),DIMENSION(:),INTENT(in) :: str_tab
+  CHARACTER(LEN=*),INTENT(in) :: str
+  INTEGER,INTENT(out) :: pos
+!-
+  INTEGER :: nb_str,i
+!---------------------------------------------------------------------
+  pos = -1
+  nb_str=SIZE(str_tab)
+  IF ( nb_str > 0 ) THEN
+    DO i=1,nb_str
+      IF ( TRIM(str_tab(i)) == TRIM(str) ) THEN
+        pos = i
+        EXIT
+      ENDIF
+    ENDDO
+  ENDIF
+!----------------------
+END SUBROUTINE find_str
+!===
+SUBROUTINE nocomma (str)
+!---------------------------------------------------------------------
+!- Replace commas with blanks
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: str
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  DO i=1,LEN_TRIM(str)
+    IF (str(i:i) == ',')   str(i:i) = ' '
+  ENDDO
+!---------------------
+END SUBROUTINE nocomma
+!===
+SUBROUTINE strlowercase (str)
+!---------------------------------------------------------------------
+!- Converts a string into lowercase
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: str
+!-
+  INTEGER :: i,ic
+!---------------------------------------------------------------------
+  DO i=1,LEN_TRIM(str)
+    ic = IACHAR(str(i:i))
+    IF ( (ic >= 65).AND.(ic <= 90) )  str(i:i) = ACHAR(ic+32)
+  ENDDO
+!--------------------------
+END SUBROUTINE strlowercase
+!===
+SUBROUTINE struppercase (str)
+!---------------------------------------------------------------------
+!- Converts a string into uppercase
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: str
+!-
+  INTEGER :: i,ic
+!---------------------------------------------------------------------
+  DO i=1,LEN_TRIM(str)
+    ic = IACHAR(str(i:i))
+    IF ( (ic >= 97).AND.(ic <= 122) )  str(i:i) = ACHAR(ic-32)
+  ENDDO
+!--------------------------
+END SUBROUTINE struppercase
+!===
+SUBROUTINE gensig (str,sig)
+!---------------------------------------------------------------------
+!- Generate a signature from the first 30 characters of the string
+!- This signature is not unique and thus when one looks for the
+!- one needs to also verify the string.
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  CHARACTER(LEN=*) :: str
+  INTEGER          :: sig
+!-
+  INTEGER :: i
+!---------------------------------------------------------------------
+  sig = 0
+  DO i=1,MIN(LEN_TRIM(str),30)
+    sig = sig + prime(i)*IACHAR(str(i:i))
+  ENDDO
+!--------------------
+END SUBROUTINE gensig
+!===
+SUBROUTINE find_sig (nb_sig,str_tab,str,sig_tab,sig,pos)
+!---------------------------------------------------------------------
+!- Find the string signature in a list of signatures
+!---------------------------------------------------------------------
+!- INPUT
+!-   nb_sig      : length of table of signatures
+!-   str_tab     : Table of strings
+!-   str         : Target string we are looking for
+!-   sig_tab     : Table of signatures
+!-   sig         : Target signature we are looking for
+!- OUTPUT
+!-   pos         : -1 if str not found, else value in the table
+!---------------------------------------------------------------------
+  IMPLICIT NONE
+!-
+  INTEGER :: nb_sig
+  CHARACTER(LEN=*),DIMENSION(nb_sig) :: str_tab
+  CHARACTER(LEN=*) :: str
+  INTEGER,DIMENSION(nb_sig) :: sig_tab
+  INTEGER :: sig
+!-
+  INTEGER :: pos
+  INTEGER,DIMENSION(nb_sig) :: loczeros
+!-
+  INTEGER :: il,len
+  INTEGER,DIMENSION(1) :: minpos
+!---------------------------------------------------------------------
+  pos = -1
+  il = LEN_TRIM(str)
+!-
+  IF ( nb_sig > 0 ) THEN
+    loczeros = ABS(sig_tab(1:nb_sig)-sig)
+    IF ( COUNT(loczeros < 1) == 1 ) THEN
+      minpos = MINLOC(loczeros)
+      len = LEN_TRIM(str_tab(minpos(1)))
+      IF (     (INDEX(str_tab(minpos(1)),str(1:il)) > 0) &
+          .AND.(len == il) ) THEN
+        pos = minpos(1)
+      ENDIF
+    ELSE IF ( COUNT(loczeros < 1) > 1 ) THEN
+      DO WHILE (COUNT(loczeros < 1) >= 1 .AND. pos < 0 )
+        minpos = MINLOC(loczeros)
+        len = LEN_TRIM(str_tab(minpos(1)))
+        IF (     (INDEX(str_tab(minpos(1)),str(1:il)) > 0) &
+            .AND.(len == il) ) THEN
+          pos = minpos(1)
+        ELSE
+          loczeros(minpos(1)) = 99999
+        ENDIF
+      ENDDO
+    ENDIF
+  ENDIF
+!-----------------------
+ END SUBROUTINE find_sig
+!===
+!------------------
+END MODULE stringop
