Index: dynamico_lmdz/simple_physics/bash/beautify.sh
===================================================================
--- dynamico_lmdz/simple_physics/bash/beautify.sh	(revision 4235)
+++ 	(revision )
@@ -1,17 +1,0 @@
-#!/bin/bash
-
-# NOTE : sed -i seems to work differently on GNU and OSX systems
-# a temporary file is used instead
-
-TMP=$(mktemp)
-
-for x in $* ; do
-    # indent source file using emacs in batch mode
-    # following standard settings of emacs f90-mode
-    emacs -batch $x --eval '(f90-mode)' --eval '(indent-region (point-min) (point-max) nil)' --eval '(delete-trailing-whitespace)' -f save-buffer 2>/dev/null
-    # remove blank lines at end of file
-    sed  -e :a -e '/^\n*$/{$d;N;};/\n$/ba' $x  > $TMP
-    cp -f $TMP $x
-done
-
-rm -f $TMP
Index: dynamico_lmdz/simple_physics/bash/compile_XCodeML.sh
===================================================================
--- dynamico_lmdz/simple_physics/bash/compile_XCodeML.sh	(revision 4235)
+++ dynamico_lmdz/simple_physics/bash/compile_XCodeML.sh	(revision 4236)
@@ -1,4 +1,25 @@
 #!/bin/bash
 
+
+# Compiles the omni-compiler suite, especially the Fortran front-end F_Front 
+# which is used to parse the physics code and (later) check that coding standards are followed.
+
+# F_Front will be installed in the directory from which this script has been invoked. 
+# Before executing this script, cd to the directory where you want to install.
+# e.g. > cd $HOME/local . Then F_Front will be in $HOME/local/bin . 
+
+# There are chances this script fails on OSX if the standard gcc is used. You can try with a more recent gcc, which is easy to 
+# install through Homebrew. The XML library libxml2 will be required too :
+#   * install gcc and libxml2 : > brew install gcc libxml2
+#   * check : > which gfortran
+#   * cd to simple_physics/bash/omnicompiler-1.3.2
+#   * run the configure script with :
+#          > CC=/usr/local/bin/gcc-9 ./configure --prefix=$HOME/local --with-libxml2=/usr/local/Cellar/libxml2/2.9.10/
+#    (your version numbers may be different
+#   * make all install
+#   * even if the full build fails, you may find a working F_Front in xcodeml-tools/F-FrontEnd/src :
+#          > xcodeml-tools/F-FrontEnd/src/F_Front --help
+#   * copy F_Front where desired
+ 
 PREFIX=$(pwd)
 ROOT=$(dirname $0)
Index: dynamico_lmdz/simple_physics/bash/concatenate_all_code.sh
===================================================================
--- dynamico_lmdz/simple_physics/bash/concatenate_all_code.sh	(revision 4235)
+++ 	(revision )
@@ -1,7 +1,0 @@
-#!/bin/bash
-
-# Usage : $0 name1 name2 ...
-
-for src in $* ; do
-    awk "{ print \"$src \" NR \" \" \$0; }" physics/${src}.F90
-done
Index: dynamico_lmdz/simple_physics/bash/makedeps.sh
===================================================================
--- dynamico_lmdz/simple_physics/bash/makedeps.sh	(revision 4235)
+++ 	(revision )
@@ -1,10 +1,0 @@
-#!/bin/bash
-
-# input file $1 is output of bash/concatenate_all_code.sh, see phyparam/Makefile
-
-function print_deps()
-{
-    tr ',' ' ' | awk '{print "obj/" $1 ".o : " "obj/" $4 ".o" }'
-}
-
-grep '\bUSE\b' $1 | grep -i -v 'INTRINSIC' | grep -i -v '\bEND\b' | print_deps
Index: dynamico_lmdz/simple_physics/phyparam/Makefile
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/Makefile	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/Makefile	(revision 4236)
@@ -16,16 +16,20 @@
 all : obj $(OBJECTS) lib/libphyparam.so
 
+py : clean all
+	bash/extract_cython.sh
+	cd python ; rm -rf build *.c ; python setup.py build_ext --inplace
+	cd python ; python -c 'import phyparam as phys ; phys.setup(100.); phys.alloc(30,100) ; phys.coldstart(30, 100.)'
 obj :
 	@rm -rf obj include lib xml tmp *~ */*~
 	@mkdir obj include lib xml tmp
 
-clean :
+clean : nice
 	@rm -rf obj include lib xml tmp *~ */*~
 	@mkdir obj include lib xml tmp
-	@../bash/concatenate_all_code.sh $(NAMES) > tmp/all_code
-	@../bash/makedeps.sh tmp/all_code >  Makefile.inc
+	@bash/concatenate_all_code.sh $(NAMES) > tmp/all_code
+	@bash/makedeps.sh tmp/all_code >  Makefile.inc
 
 nice:
-	../bash/beautify.sh physics/*.F90
+	bash/beautify.sh physics/*.F90
 
 %.so : $(OBJECTS)
Index: dynamico_lmdz/simple_physics/phyparam/bash/beautify.sh
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/bash/beautify.sh	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/bash/beautify.sh	(revision 4236)
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# NOTE : sed -i seems to work differently on GNU and OSX systems
+# a temporary file is used instead
+
+TMP=$(mktemp)
+
+for x in $* ; do
+    # indent source file using emacs in batch mode
+    # following standard settings of emacs f90-mode
+    emacs -batch $x --eval '(f90-mode)' --eval '(indent-region (point-min) (point-max) nil)' --eval '(delete-trailing-whitespace)' -f save-buffer 2>/dev/null
+    # remove blank lines at end of file
+    sed  -e :a -e '/^\n*$/{$d;N;};/\n$/ba' $x  > $TMP
+    cp -f $TMP $x
+done
+
+rm -f $TMP
Index: dynamico_lmdz/simple_physics/phyparam/bash/concatenate_all_code.sh
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/bash/concatenate_all_code.sh	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/bash/concatenate_all_code.sh	(revision 4236)
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Usage : $0 name1 name2 ...
+
+for src in $* ; do
+    awk "{ print \"$src \" NR \" \" \$0; }" physics/${src}.F90
+done
Index: dynamico_lmdz/simple_physics/phyparam/bash/extract_cython.sh
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/bash/extract_cython.sh	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/bash/extract_cython.sh	(revision 4236)
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+function extract_header()
+{
+    grep header tmp/cython | sed -E 's/.*cython.*header//g' | awk '{print "  " $0}'
+}
+
+function extract_wrapper()
+{
+    grep wrapper tmp/cython | sed -n -e 's/^.* wrapper //p'
+}
+
+
+#	grep -v extern python/phyparam.hpxd > python/phyparam.h
+#	cat python/phyparam.hpxd | tr ';' ' ' > python/phyparam.pxd
+#	cd python ; rm -rf build *.c ; python setup.py build_ext --inplace
+
+#cat tmp/all_code | extract_header
+
+grep '!$cython' tmp/all_code > tmp/cython
+
+extract_header > python/phyparam.h
+
+cat <<EOF > python/phyparam.pxd
+cdef extern from "phyparam.h" :
+$(cat python/phyparam.h | tr -d ';')
+EOF
+
+cat <<EOF > python/phyparam.pyx
+# cython: language_level=3
+
+cimport phyparam as phy
+
+#------------------------ wrappers  extracted from Fortran --------------------------#
+
+$(extract_wrapper)
+
+#-------------------------- plugins from python/plugins.pyx -------------------------#
+
+$(cat python/plugins.pyx)
+EOF
Index: dynamico_lmdz/simple_physics/phyparam/bash/makedeps.sh
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/bash/makedeps.sh	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/bash/makedeps.sh	(revision 4236)
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# input file $1 is output of bash/concatenate_all_code.sh, see phyparam/Makefile
+
+function print_deps()
+{
+    tr ',' ' ' | awk '{print "obj/" $1 ".o : " "obj/" $4 ".o" }'
+}
+
+grep '\bUSE\b' $1 | grep -i -v 'INTRINSIC' | grep -i -v '\bEND\b' | print_deps
Index: dynamico_lmdz/simple_physics/phyparam/dynphy_lonlat/iniphysiq_mod.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/dynphy_lonlat/iniphysiq_mod.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/dynphy_lonlat/iniphysiq_mod.F90	(revision 4236)
@@ -87,8 +87,5 @@
     CALL setup_phyparam
 
-    CALL iniphyparam(klon_omp,nlayer, &
-         punjours, &
-         pdayref,ptimestep, &
-         prad,pg,pr,pcpp)
+    CALL iniphyparam(ptimestep, punjours, prad, pg, pr, pcpp)
     
     !$OMP END PARALLEL
Index: dynamico_lmdz/simple_physics/phyparam/physics/error_mod.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/error_mod.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/physics/error_mod.F90	(revision 4236)
@@ -11,5 +11,5 @@
   INTERFACE check_NaN
      MODULE PROCEDURE check_NaN1, check_NaN2
-  END INTERFACE check_NaN
+  END INTERFACE
 
   PUBLIC :: check_NaN
Index: dynamico_lmdz/simple_physics/phyparam/physics/iniphyparam_mod.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/iniphyparam_mod.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/physics/iniphyparam_mod.F90	(revision 4236)
@@ -10,56 +10,70 @@
 CONTAINS
 
-  SUBROUTINE iniphyparam(ngrid,nlayer, &
-       &           punjours,              &
-       &           pdayref,ptimestep,     &
-       &           prad,pg,pr,pcpp)
-    USE callkeys
+  SUBROUTINE read_params(ptimestep) BIND(C, name='phyparam_setup')
+    !$cython header void phyparam_setup(double);
+    !$cython wrapper def setup(timestep) : phy.phyparam_setup(timestep)
+    USE read_param_mod
     USE phys_const, ONLY : planet_rad,g,r,cpp,rcp,dtphys,unjours,mugaz
+    USE astronomy
     USE planet, ONLY : coefir, coefvis
-    USE astronomy
     USE turbulence, ONLY : lmixmin, emin_turb
     USE surface
-    USE read_param_mod
+    USE callkeys
+    REAL, INTENT(IN), VALUE :: ptimestep
 
-    INTEGER, INTENT(IN) :: &
-         ngrid, &       ! Size of the horizontal grid
-         nlayer, &      ! Number of vertical layers.
-         pdayref        ! Day of reference for the simulation
-    REAL, INTENT(IN)  :: ptimestep, prad, pg, pr, pcpp, punjours
-
-    CALL read_param('unjours', 86400., unjours,'unjours')
-    CALL read_param('planet_rad',prad,planet_rad,'planet_rad')
-    CALL read_param('g',9.8           ,g,'g')
-    CALL read_param('cpp',1004.       ,cpp,'cpp')
-    CALL read_param('mugaz',28.       ,mugaz,'mugaz')
+    CALL read_param('planet_rad',6.4e6 ,planet_rad,'planet_rad')
+    CALL read_param('g',9.8            ,g,'g')
+    CALL read_param('cpp',1004.        ,cpp,'cpp')
+    CALL read_param('mugaz',28.        ,mugaz,'mugaz')
     r=perfect_gas_const/mugaz
     rcp=r/cpp
 
-    CALL read_param('year_day',360.   ,year_day,'year_day')
-    CALL read_param('periheli',150.   ,periheli,'periheli')
-    CALL read_param('aphelie',150.    ,aphelie,'aphelie')
-    CALL read_param('peri_day',0.     ,peri_day,'peri_day')
-    CALL read_param('obliquit',23.    ,obliquit,'obliquit')
-    CALL read_param('Cd_mer',.01      ,Cd_mer,'Cd_mer')
-    CALL read_param('Cd_ter',.01      ,Cd_ter,'Cd_ter')
-    CALL read_param('I_mer',3000.    ,I_mer,'I_mer')
-    CALL read_param('I_ter',3000.    ,I_ter,'I_ter')
-    CALL read_param('alb_ter',.112    ,alb_ter,'alb_ter')
-    CALL read_param('alb_mer',.112    ,alb_mer,'alb_mer')
-    CALL read_param('emi_mer',1.      ,emi_mer,'emi_mer')
-    CALL read_param('emi_mer',1.      ,emi_mer,'emi_mer')
+    CALL read_param('unjours', 86400.,  unjours,'unjours')
+    CALL read_param('year_day',360.    ,year_day,'year_day')
+    CALL read_param('periheli',150.    ,periheli,'periheli')
+    CALL read_param('aphelie',150.     ,aphelie,'aphelie')
+    CALL read_param('peri_day',0.      ,peri_day,'peri_day')
+    CALL read_param('obliquit',23.     ,obliquit,'obliquit')
+
+    CALL read_param('Cd_mer',.01       ,Cd_mer,'Cd_mer')
+    CALL read_param('Cd_ter',.01       ,Cd_ter,'Cd_ter')
+    CALL read_param('I_mer',3000.      ,I_mer,'I_mer')
+    CALL read_param('I_ter',3000.      ,I_ter,'I_ter')
+    CALL read_param('alb_ter',.112     ,alb_ter,'alb_ter')
+    CALL read_param('alb_mer',.112     ,alb_mer,'alb_mer')
+    CALL read_param('emi_mer',1.       ,emi_mer,'emi_mer')
+    CALL read_param('emi_mer',1.       ,emi_mer,'emi_mer')
     CALL read_param('emin_turb',1.e-16 ,emin_turb,'emin_turb')
-    CALL read_param('lmixmin',100.    ,lmixmin,'lmixmin')
-    CALL read_param('coefvis',.99     ,coefvis,'coefvis')
-    CALL read_param('coefir',.08      ,coefir,'coefir')
+    CALL read_param('lmixmin',100.     ,lmixmin,'lmixmin')
 
-    CALL read_param('callrad',.true.,callrad,'appel rayonnement')
-    CALL read_param('calldifv',.true.,calldifv,'appel difv')
-    CALL read_param('calladj',.true.,calladj,'appel adj')
-    CALL read_param('callsoil',.true.,callsoil,'appel soil')
-    CALL read_param('season',.true.,season,'with seasonal cycle')
-    CALL read_param('diurnal',.false.,diurnal,'with diurnal cycle')
-    CALL read_param('lverbose',.true.,lverbose,'lverbose')
-    CALL read_param('period_sort',1.,period_sort,'period sorties en jour')
+    CALL read_param('coefvis',.99      ,coefvis,'coefvis')
+    CALL read_param('coefir',.08       ,coefir,'coefir')
+
+    CALL read_param('callrad',  .true.,  callrad,   'appel rayonnement')
+    CALL read_param('calldifv', .true.,  calldifv,  'appel difv')
+    CALL read_param('calladj',  .true.,  calladj,   'appel adj')
+    CALL read_param('callsoil', .true.,  callsoil,  'appel soil')
+    CALL read_param('season',   .true.,  season,    'with seasonal cycle')
+    CALL read_param('diurnal',  .false., diurnal,   'with diurnal cycle')
+    CALL read_param('lverbose', .true.,  lverbose,  'lverbose')
+    CALL read_param('period_sort', 1., period_sort, 'period sorties en jour')
+
+    !   choice of the frequency of the computation of radiations
+    IF(diurnal) THEN
+       iradia=NINT(unjours/(20.*ptimestep))
+    ELSE
+       iradia=NINT(unjours/(4.*ptimestep))
+    ENDIF
+    iradia=1
+
+    dtphys=ptimestep
+  END SUBROUTINE read_params
+
+  SUBROUTINE iniphyparam(ptimestep, punjours, prad, pg, pr, pcpp)
+    USE phys_const, ONLY : planet_rad,g,r,cpp,rcp,dtphys,unjours
+    USE callkeys
+    REAL, INTENT(IN)  :: ptimestep, punjours, prad, pg, pr, pcpp
+
+    CALL read_params(ptimestep)
 
     CALL check_mismatch('unjours', punjours, unjours)
@@ -78,17 +92,8 @@
     WRITELOG(*,*) ' Cycle diurne ',diurnal
 
-    !   choice of the frequency of the computation of radiations
-    IF(diurnal) THEN
-       iradia=NINT(punjours/(20.*ptimestep))
-    ELSE
-       iradia=NINT(punjours/(4.*ptimestep))
-    ENDIF
-    iradia=1
-    WRITELOG(*,*) 'unjours',punjours
+    WRITELOG(*,*) 'unjours',unjours
     WRITELOG(*,*) 'The radiative transfer is computed each ', &
          &   iradia,' physical time-step or each ', &
          &   iradia*ptimestep,' seconds'
-
-    dtphys=ptimestep
 
     LOG_INFO('iniphyparam')
Index: dynamico_lmdz/simple_physics/phyparam/physics/logging.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/logging.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/physics/logging.F90	(revision 4236)
@@ -3,5 +3,4 @@
   ! see also use_logging.h
   ! macro LOGBUF accumulates log output into logging_buffer
-
   IMPLICIT NONE
   SAVE
@@ -9,15 +8,16 @@
 
   INTERFACE  ! Explicit interfaces for plugins
-
      ! Plugin that typically prints all lines in the loggin buffer 'buf' and prepends tags (log level, timestamp, ...)
-     SUBROUTINE plugin(lev, tag, buf)
-       INTEGER, INTENT(IN) :: lev
-       CHARACTER(*), INTENT(IN) :: tag, buf(:)
+     SUBROUTINE plugin(lev, taglen, tag, buflen, bufsize, buf) BIND(C)
+       USE, INTRINSIC :: iso_c_binding, ONLY : c_char, c_null_char, c_int
+       INTEGER(c_int), INTENT(IN), VALUE :: lev, taglen, buflen, bufsize
+       CHARACTER(KIND=c_char), INTENT(IN) :: tag(taglen), buf(buflen, bufsize)
      END SUBROUTINE plugin
 
      ! Plugin that writes into string 'line' information about the gridpoint of index 'index'
-     SUBROUTINE plugin_log_gridpoint(index, line)
-       INTEGER, INTENT(IN) :: index ! index of gridpoint
-       CHARACTER(*), INTENT(OUT) :: line
+     SUBROUTINE plugin_log_gridpoint(index, line_len, line) BIND(C)
+       USE, INTRINSIC :: iso_c_binding, ONLY : c_char, c_null_char, c_int
+       INTEGER(c_int), INTENT(IN), VALUE :: index, line_len ! index of gridpoint, LEN(line)
+       CHARACTER(KIND=c_char), INTENT(OUT) :: line(line_len)
      END SUBROUTINE plugin_log_gridpoint
 
@@ -30,6 +30,7 @@
 #ifndef XCODEML
   ! Note F2003/F2008: XCodeML cannot parse procedure pointers
-  PROCEDURE(plugin), POINTER, PUBLIC :: flush_plugin => NULL()
-  PROCEDURE(plugin_log_gridpoint), POINTER, PUBLIC :: log_gridpoint_plugin => NULL()
+  PUBLIC :: flush_plugin, log_gridpoint_plugin
+  PROCEDURE(plugin), POINTER :: flush_plugin => NULL()
+  PROCEDURE(plugin_log_gridpoint), POINTER :: log_gridpoint_plugin => NULL()
 #endif
 
@@ -49,4 +50,11 @@
 CONTAINS
 
+  SUBROUTINE set_plugins(flush_plugin_c) BIND(C, name='phyparam_set_plugins_logging')
+    !$cython header void phyparam_set_plugins_logging(void *);
+    USE, INTRINSIC :: ISO_C_BINDING
+    TYPE(C_FUNPTR), INTENT(IN), VALUE :: flush_plugin_c
+    CALL C_F_PROCPOINTER(flush_plugin_c, flush_plugin)
+  END SUBROUTINE set_plugins
+
   SUBROUTINE missing_plugin(name, mod)
     CHARACTER(*), INTENT(IN) :: name, mod
@@ -56,4 +64,6 @@
     CALL flush_log(log_level_warn, 'missing_plugin')
   END SUBROUTINE missing_plugin
+
+  !-------------------------------------------------------------------------------------------------
 
   SUBROUTINE flush_log(lev,tag)
@@ -66,19 +76,25 @@
        WRITE(*,*) '        see logging.F90'
     END IF
-    IF(logging_lineno>0 .AND. lev<=max_log_level) CALL flush_plugin(lev, TRIM(tag), logging_buf(1:logging_lineno))
+    IF(logging_lineno>0 .AND. lev<=max_log_level) &
+         CALL flush_plugin(lev, LEN(tag), TRIM(tag), linesize, logging_lineno, logging_buf)
     logging_lineno=0
 #endif
   END SUBROUTINE flush_log
 
-  SUBROUTINE default_flush_plugin(lev, tag, buf)
-    INTEGER, INTENT(IN) :: lev
-    CHARACTER(*), INTENT(IN) :: tag, buf(:)
+  SUBROUTINE default_flush_plugin(lev, taglen, tag, buflen, bufsize, buf)
+    USE, INTRINSIC :: iso_c_binding, ONLY : c_char, c_null_char, c_int
+    INTEGER(c_int), INTENT(IN), VALUE :: lev, taglen, buflen, bufsize
+    CHARACTER(KIND=c_char), INTENT(IN) :: tag(taglen), buf(buflen, bufsize)
     CHARACTER(100) :: prefix
+    CHARACTER(buflen+1) :: line
     INTEGER :: i
     WRITE(prefix,*) '[', dbtag(lev), ' ', tag, ']'
-    DO i=1, SIZE(buf)
-       WRITE(*,*) TRIM(prefix), TRIM(buf(i))
+    DO i=1, bufsize
+       WRITE(line,*) buf(:,i)
+       WRITE(*,*) TRIM(prefix), TRIM(line)
     END DO
   END SUBROUTINE default_flush_plugin
+
+  !-------------------------------------------------------------------------------------------------
 
   SUBROUTINE log_gridpoint(index)
@@ -91,11 +107,12 @@
        WRITE(*,*) '        see logging.F90'
     END IF
-    CALL log_gridpoint_plugin(index, logging_buf(logging_lineno))
+    CALL log_gridpoint_plugin(index, linesize, logging_buf(logging_lineno))
 #endif
   END SUBROUTINE log_gridpoint
 
-  SUBROUTINE default_log_gridpoint(index, line)
-    INTEGER, INTENT(IN) :: index ! index of gridpoint
-    CHARACTER(*), INTENT(OUT) :: line
+  SUBROUTINE default_log_gridpoint(index, line_len, line)
+    USE, INTRINSIC :: iso_c_binding, ONLY : c_char, c_null_char, c_int
+    INTEGER(c_int), INTENT(IN), VALUE :: index, line_len ! index of gridpoint, LEN(line)
+    CHARACTER(KIND=c_char), INTENT(OUT) :: line(line_len)
     line=' '
   END SUBROUTINE default_log_gridpoint
Index: dynamico_lmdz/simple_physics/phyparam/physics/phyparam_mod.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/phyparam_mod.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/physics/phyparam_mod.F90	(revision 4236)
@@ -34,5 +34,5 @@
        &            pplev,pplay,pphi,           &
        &            pu,pv,pt,                   &
-       &            pdu,pdv,pdt,pdpsrf)
+       &            pdu,pdv,pdt,pdpsrf) BIND(C, name='phyparam_phyparam')
     USE phys_const, ONLY : g, rcp, r, unjours
     USE surface,    ONLY : soil
@@ -45,21 +45,23 @@
     !   20 parameters GCM for planetary atmospheres.
     !   It includes:
-    !   raditive transfer (long and shortwave) for CO2 and dust.
+    !   radiative transfer (long and shortwave) for CO2 and dust.
     !   vertical turbulent mixing
     !   convective adjsutment
+    !   heat diffusion in the soil
     !
     !   author: Frederic Hourdin 15 / 10 /93
     !=======================================================================
 
-    INTEGER, INTENT(IN) ::      &
+    INTEGER, INTENT(IN), VALUE :: &
          ngrid,                 & ! Size of the horizontal grid.
          nlayer                   ! Number of vertical layers.
-    LOGICAL, INTENT(IN) ::      &
+    LOGICAL, INTENT(IN), VALUE  :: &
          firstcall,             & ! True at the first call
          lastcall                 ! True at the last call
-    REAL, INTENT(IN)    ::      &
+    REAL, INTENT(IN), VALUE     ::      &
          rjourvrai,             & ! Number of days counted from the North. Spring equinox
          gmtime,                & ! time of the day in seconds
-         ptimestep,             & ! timestep (s)
+         ptimestep                ! timestep (s)
+    REAL, INTENT(IN) :: &
          pplev(ngrid,nlayer+1), & ! Pressure at interfaces between layers (pa)
          pplay(ngrid,nlayer),   & ! Pressure at the middle of the layers (Pa)
@@ -431,8 +433,10 @@
   END SUBROUTINE radiative_tendencies
 
-  SUBROUTINE alloc(ngrid, nlayer)
+  SUBROUTINE alloc(ngrid, nlayer) BIND(C, name='phyparam_alloc')
+    !$cython header void phyparam_alloc(int, int);
+    !$cython wrapper def alloc(ngrid, nlayer) : phy.phyparam_alloc(ngrid, nlayer)
     USE astronomy, ONLY : iniorbit
     USE surface, ONLY : zc,zd
-    INTEGER, INTENT(IN) :: ngrid, nlayer
+    INTEGER, INTENT(IN), VALUE :: ngrid, nlayer
     LOGICAL, PARAMETER :: firstcall=.TRUE.
     ! allocate arrays for internal state
@@ -448,5 +452,7 @@
   END SUBROUTINE alloc
 
-  SUBROUTINE precompute
+  SUBROUTINE precompute() BIND(C, name='phyparam_precompute')
+    !$cython header void phyparam_precompute();
+    !$cython wrapper def precompute() : phy.phyparam_precompute()
     USE surface
     ! precompute time-independent arrays
@@ -458,9 +464,11 @@
   END SUBROUTINE precompute
 
-  SUBROUTINE coldstart(ngrid, ptimestep)
+  SUBROUTINE coldstart(ngrid, ptimestep) BIND(C, name='phyparam_coldstart')
+    !$cython header void phyparam_coldstart(int, double);
+    !$cython wrapper def coldstart (ngrid, timestep): phy.phyparam_coldstart(ngrid, timestep)
     ! create internal state to start a run without a restart file
     USE surface, ONLY : soil
-    INTEGER, INTENT(IN) :: ngrid
-    REAL, INTENT(iN)    :: ptimestep
+    INTEGER, INTENT(IN), VALUE :: ngrid
+    REAL, INTENT(IN),    VALUE :: ptimestep
     tsurf(:)   = tsoil_init
     tsoil(:,:) = tsoil_init
Index: dynamico_lmdz/simple_physics/phyparam/physics/read_param_mod.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/read_param_mod.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/physics/read_param_mod.F90	(revision 4236)
@@ -43,5 +43,5 @@
   INTERFACE read_param
      PROCEDURE read_paramr, read_parami, read_paramb
-  END INTERFACE read_param
+  END INTERFACE
 
   PUBLIC :: read_param
Index: dynamico_lmdz/simple_physics/phyparam/physics/restart.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/restart.F90	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/physics/restart.F90	(revision 4236)
@@ -0,0 +1,57 @@
+MODULE restart
+  IMPLICIT NONE
+  PRIVATE
+  SAVE
+
+  ! right after allocating arrays for persistent data (internal state), the physics
+  ! code calls restart_register for each array
+  ! it is then left to the driver code to either call cold_start or to read data from disk into these arrays
+  ! it is also left to the driver code to write internal state to disk at the end of the time loop
+
+  INTEGER, PARAMETER :: max_restart_field=100, max_len=100
+  INTEGER :: nb_restart_field=0
+
+  TYPE restart_record_t
+     CHARACTER(max_len) :: name
+     REAL, POINTER :: data1(:), data2(:,:)
+  END TYPE restart_record_t
+
+  TYPE(restart_record_t) :: restart_record(max_restart_field)
+
+  INTERFACE restart_register
+     MODULE PROCEDURE restart_register_1D, restart_register_2D
+  END INTERFACE
+
+  PUBLIC :: restart_register
+
+CONTAINS
+
+  SUBROUTINE check_name(name)
+    CHARACTER(*), INTENT(IN) :: name ! unique name of the restart field
+    INTEGER :: id
+    DO id=1, nb_restart_field
+       IF(TRIM(restart_record(id)%name) == name) THEN
+          PRINT *, 'FATAL : Restart field ', name, ' already registered'
+          STOP
+       END IF
+    END DO
+    nb_restart_field = nb_restart_field+1
+  END SUBROUTINE check_name
+
+  SUBROUTINE restart_register_1D(name, field)
+    CHARACTER(*), INTENT(IN) :: name ! unique name of the restart field
+    REAL, INTENT(IN), TARGET :: field(:) ! 1D field to be read/written at checkpoint/restart
+    CALL check_name(name)
+    restart_record(nb_restart_field)%name = name
+    restart_record(nb_restart_field)%data1 => field
+  END SUBROUTINE restart_register_1D
+
+  SUBROUTINE restart_register_2D(name, field)
+    CHARACTER(*), INTENT(IN) :: name ! unique name of the restart field
+    REAL, INTENT(IN), TARGET :: field(:,:) ! 1D field to be read/written at checkpoint/restart
+    CALL check_name(name)
+    restart_record(nb_restart_field)%name = name
+    restart_record(nb_restart_field)%data2 => field
+  END SUBROUTINE restart_register_2D
+
+END MODULE restart
Index: dynamico_lmdz/simple_physics/phyparam/physics/writefield_mod.F90
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/physics/writefield_mod.F90	(revision 4235)
+++ dynamico_lmdz/simple_physics/phyparam/physics/writefield_mod.F90	(revision 4236)
@@ -24,5 +24,5 @@
   INTERFACE writefield
      PROCEDURE writefield1, writefield2
-  END INTERFACE writefield
+  END INTERFACE
 
   PUBLIC :: writefield
Index: dynamico_lmdz/simple_physics/phyparam/python/Extension.help
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/python/Extension.help	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/python/Extension.help	(revision 4236)
@@ -0,0 +1,85 @@
+Help on class Extension in module distutils.extension:
+
+class Extension(builtins.object)
+ |  Extension(name, sources, include_dirs=None, define_macros=None, undef_macros=None, library_dirs=None, libraries=None, runtime_library_dirs=None, extra_objects=None, extra_compile_args=None, extra_link_args=None, export_symbols=None, swig_opts=None, depends=None, language=None, optional=None, **kw)
+ |  
+ |  Just a collection of attributes that describes an extension
+ |  module and everything needed to build it (hopefully in a portable
+ |  way, but there are hooks that let you be as unportable as you need).
+ |  
+ |  Instance attributes:
+ |    name : string
+ |      the full name of the extension, including any packages -- ie.
+ |      *not* a filename or pathname, but Python dotted name
+ |    sources : [string]
+ |      list of source filenames, relative to the distribution root
+ |      (where the setup script lives), in Unix form (slash-separated)
+ |      for portability.  Source files may be C, C++, SWIG (.i),
+ |      platform-specific resource files, or whatever else is recognized
+ |      by the "build_ext" command as source for a Python extension.
+ |    include_dirs : [string]
+ |      list of directories to search for C/C++ header files (in Unix
+ |      form for portability)
+ |    define_macros : [(name : string, value : string|None)]
+ |      list of macros to define; each macro is defined using a 2-tuple,
+ |      where 'value' is either the string to define it to or None to
+ |      define it without a particular value (equivalent of "#define
+ |      FOO" in source or -DFOO on Unix C compiler command line)
+ |    undef_macros : [string]
+ |      list of macros to undefine explicitly
+ |    library_dirs : [string]
+ |      list of directories to search for C/C++ libraries at link time
+ |    libraries : [string]
+ |      list of library names (not filenames or paths) to link against
+ |    runtime_library_dirs : [string]
+ |      list of directories to search for C/C++ libraries at run time
+ |      (for shared extensions, this is when the extension is loaded)
+ |    extra_objects : [string]
+ |      list of extra files to link with (eg. object files not implied
+ |      by 'sources', static library that must be explicitly specified,
+ |      binary resource files, etc.)
+ |    extra_compile_args : [string]
+ |      any extra platform- and compiler-specific information to use
+ |      when compiling the source files in 'sources'.  For platforms and
+ |      compilers where "command line" makes sense, this is typically a
+ |      list of command-line arguments, but for other platforms it could
+ |      be anything.
+ |    extra_link_args : [string]
+ |      any extra platform- and compiler-specific information to use
+ |      when linking object files together to create the extension (or
+ |      to create a new static Python interpreter).  Similar
+ |      interpretation as for 'extra_compile_args'.
+ |    export_symbols : [string]
+ |      list of symbols to be exported from a shared extension.  Not
+ |      used on all platforms, and not generally necessary for Python
+ |      extensions, which typically export exactly one symbol: "init" +
+ |      extension_name.
+ |    swig_opts : [string]
+ |      any extra options to pass to SWIG if a source file has the .i
+ |      extension.
+ |    depends : [string]
+ |      list of files that the extension depends on
+ |    language : string
+ |      extension language (i.e. "c", "c++", "objc"). Will be detected
+ |      from the source extensions if not provided.
+ |    optional : boolean
+ |      specifies that a build failure in the extension should not abort the
+ |      build process, but simply not install the failing extension.
+ |  
+ |  Methods defined here:
+ |  
+ |  __init__(self, name, sources, include_dirs=None, define_macros=None, undef_macros=None, library_dirs=None, libraries=None, runtime_library_dirs=None, extra_objects=None, extra_compile_args=None, extra_link_args=None, export_symbols=None, swig_opts=None, depends=None, language=None, optional=None, **kw)
+ |      Initialize self.  See help(type(self)) for accurate signature.
+ |  
+ |  __repr__(self)
+ |      Return repr(self).
+ |  
+ |  ----------------------------------------------------------------------
+ |  Data descriptors defined here:
+ |  
+ |  __dict__
+ |      dictionary for instance variables (if defined)
+ |  
+ |  __weakref__
+ |      list of weak references to the object (if defined)
+
Index: dynamico_lmdz/simple_physics/phyparam/python/lib
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/python/lib	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/python/lib	(revision 4236)
@@ -0,0 +1,1 @@
+link ../lib
Index: dynamico_lmdz/simple_physics/phyparam/python/plugins.pyx
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/python/plugins.pyx	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/python/plugins.pyx	(revision 4236)
@@ -0,0 +1,28 @@
+#---------------------------------- logging plugin -------------------------------#
+
+cdef to_str(ptrlen, char[] ptr, start=0):
+     return str(bytes([ ptr[i+start*ptrlen] for  i in range(ptrlen)]), encoding='utf8').rstrip()
+
+"""
+  SUBROUTINE default_flush_plugin(lev, taglen, tag, buflen, bufsize, buf)
+    INTEGER(c_int), INTENT(IN), VALUE :: lev, taglen, buflen, bufsize
+    CHARACTER(KIND=c_char), INTENT(IN) :: tag(taglen), buf(buflen, bufsize)
+"""
+
+cdef flush_plugin_wrap(int lev, int taglen, char[] tag, int buflen, int bufsize, char[] buf):
+    flush_plugin(to_str(taglen, tag), [to_str(buflen, buf, i) for i in range(bufsize) ] )
+
+def default_flush_plugin(tag, buf):
+    if tag != 'missing_plugin' :
+        n = len(buf)
+        for i,line in enumerate(buf):
+            print( '[%s %2.2d/%2.2d] %s'%(tag, i+1, n, line) )
+
+def set_flush(plugin):
+    flush_plugin = plugin
+
+#----------------------------- plug plugins in ----------------------------------#
+
+flush_plugin = default_flush_plugin
+
+phy.phyparam_set_plugins_logging(&flush_plugin_wrap)
Index: dynamico_lmdz/simple_physics/phyparam/python/setup.py
===================================================================
--- dynamico_lmdz/simple_physics/phyparam/python/setup.py	(revision 4236)
+++ dynamico_lmdz/simple_physics/phyparam/python/setup.py	(revision 4236)
@@ -0,0 +1,9 @@
+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Build import cythonize
+
+setup( name = "Wrapper to simple physics package",
+       ext_modules = cythonize([ Extension("phyparam",["phyparam.pyx"], 
+                                           libraries=['phyparam'],
+                                           library_dirs=['.'])] )
+       )
