source: LMDZ6/trunk/libf/phylmd/carbon_cycle_mod.F90 @ 3443

Last change on this file since 3443 was 3435, checked in by Laurent Fairhead, 6 years ago

"Historic" :-) commit merging the physics branch used for DYNAMICO with the LMDZ trunk.
The same physics branch can now be used seamlessly with the traditional lon-lat LMDZ
dynamical core and DYNAMICO.
Testing consisted in running a lon-lat LMDZ bucket simulation with the NPv6.1 physics package
with the original trunk sources and the merged sources. Tests were succesful in the sense that
numeric continuity was preserved in the restart files from both simulation. Further tests
included running both versions of the physics codes for one year in a LMDZOR setting in which
the restart files also came out identical.

Caution:

  • as the physics package now manages unstructured grids, grid information needs to be transmitted

to the surface scheme ORCHIDEE. This means that the interface defined in surf_land_orchidee_mod.F90
is only compatible with ORCHIDEE version orchidee2.1 and later versions. If previous versions of
ORCHIDEE need to be used, the CPP key ORCHIDEE_NOUNSTRUCT needs to be set at compilation time.
This is done automatically if makelmdz/makelmdz_fcm are called with the veget orchidee2.0 switch

  • due to a limitation in XIOS, the time at which limit conditions will be read in by DYNAMICO will be

delayed by one physic timestep with respect to the time it is read in by the lon-lat model. This is caused
by the line

IF (MOD(itime-1, lmt_pas) == 0 .OR. (jour_lu /= jour .AND. grid_type /= unstructured)) THEN ! time to read

in limit_read_mod.F90

Work still needed on COSP integration and XML files for DYNAMICO

EM, YM, LF

  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
File size: 33.3 KB
RevLine 
[1227]1MODULE carbon_cycle_mod
[3387]2!=======================================================================
3!   Authors: Patricia Cadule and Laurent Fairhead
4!            base sur un travail anterieur mene par Patricia Cadule et Josefine Ghattas
5!
6!  Purpose and description:
7!  -----------------------
8! Control module for the carbon CO2 tracers :
[1454]9!   - Identification
10!   - Get concentrations comming from coupled model or read from file to tracers
11!   - Calculate new RCO2 for radiation scheme
12!   - Calculate new carbon flux for sending to coupled models (PISCES and ORCHIDEE)
13!
[3387]14! Module permettant de mettre a jour les champs (puits et sources) pour le
15! transport de CO2 en online (IPSL-CM et LMDZOR) et offline (lecture de carte)
16!
17! Le cas online/offline est defini par le flag carbon_cycle_cpl (y/n)
18! Le transport du traceur CO2 est defini par le flag carbon_cycle_tr (y/n)
19! la provenance des champs (termes de puits) est denini par le flag level_coupling_esm
20!
21! level_coupling_esm : level of coupling of the biogeochemical fields between
22! LMDZ, ORCHIDEE and NEMO
23! Definitions of level_coupling_esm in physiq.def
24! level_coupling_esm = 0  ! No field exchange between LMDZ and ORCHIDEE models
25!                         ! No field exchange between LMDZ and NEMO
26! level_coupling_esm = 1  ! Field exchange between LMDZ and ORCHIDEE models
27!                         ! No field exchange between LMDZ and NEMO models
28! level_coupling_esm = 2  ! No field exchange between LMDZ and ORCHIDEE models
29!                         ! Field exchange between LMDZ and NEMO models
30! level_coupling_esm = 3  ! Field exchange between LMDZ and ORCHIDEE models
31!                         ! Field exchange between LMDZ and NEMO models
32!=======================================================================
[1227]33
34  IMPLICIT NONE
35  SAVE
36  PRIVATE
[3387]37  PUBLIC :: carbon_cycle_init, carbon_cycle, infocfields_init
[1227]38
39! Variables read from parmeter file physiq.def
[1250]40  LOGICAL, PUBLIC :: carbon_cycle_tr        ! 3D transport of CO2 in the atmosphere, parameter read in conf_phys
[1249]41!$OMP THREADPRIVATE(carbon_cycle_tr)
[1250]42  LOGICAL, PUBLIC :: carbon_cycle_cpl       ! Coupling of CO2 fluxes between LMDZ/ORCHIDEE and LMDZ/OCEAN(PISCES)
[1249]43!$OMP THREADPRIVATE(carbon_cycle_cpl)
[3387]44  INTEGER, PUBLIC :: level_coupling_esm ! Level of coupling for the ESM - 0, 1, 2, 3
[3384]45!$OMP THREADPRIVATE(level_coupling_esm)
[1454]46
[1759]47  LOGICAL :: carbon_cycle_emis_comp_omp=.FALSE.
[1227]48  LOGICAL :: carbon_cycle_emis_comp=.FALSE. ! Calculation of emission compatible
[1454]49!$OMP THREADPRIVATE(carbon_cycle_emis_comp)
[1227]50
[1759]51  LOGICAL :: RCO2_inter_omp
[1454]52  LOGICAL :: RCO2_inter  ! RCO2 interactive : if true calculate new value RCO2 for the radiation scheme
53!$OMP THREADPRIVATE(RCO2_inter)
54
[3385]55! Scalare values when no transport, from physiq.def
56  REAL :: fos_fuel_s_omp
57  REAL :: fos_fuel_s  ! carbon_cycle_fos_fuel dans physiq.def
58!$OMP THREADPRIVATE(fos_fuel_s)
[1227]59  REAL :: emis_land_s ! not yet implemented
[1250]60!$OMP THREADPRIVATE(emis_land_s)
[1227]61
[1454]62  REAL :: airetot     ! Total area of the earth surface
63!$OMP THREADPRIVATE(airetot)
[1250]64
[3385]65  INTEGER :: ntr_co2  ! Number of tracers concerning the carbon cycle
[1454]66!$OMP THREADPRIVATE(ntr_co2)
67
[3385]68! fco2_ocn_day : flux CO2 from ocean for 1 day (cumulated) [gC/m2/d]. Allocation and initalization done in cpl_mod
69  REAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: fco2_ocn_day
70!$OMP THREADPRIVATE(fco2_ocn_day)
[1454]71
[3385]72  REAL, DIMENSION(:), ALLOCATABLE :: fco2_land_day   ! flux CO2 from land for 1 day (cumulated)  [gC/m2/d]
73!$OMP THREADPRIVATE(fco2_land_day)
74  REAL, DIMENSION(:), ALLOCATABLE :: fco2_lu_day     ! Emission from land use change for 1 day (cumulated) [gC/m2/d]
75!$OMP THREADPRIVATE(fco2_lu_day)
[3421]76  REAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: fco2_ff ! Emission from fossil fuel [kgCO2/m2/s]
77!$OMP THREADPRIVATE(fco2_ff)
78  REAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: fco2_bb ! Emission from biomass burning [kgCO2/m2/s]
79!$OMP THREADPRIVATE(fco2_bb)
[1227]80
[1454]81  REAL, DIMENSION(:,:), ALLOCATABLE :: dtr_add       ! Tracer concentration to be injected
82!$OMP THREADPRIVATE(dtr_add)
83
[3385]84! Following 2 fields will be allocated and initialized in surf_land_orchidee
85  REAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: fco2_land_inst  ! flux CO2 from land at one time step
86!$OMP THREADPRIVATE(fco2_land_inst)
87  REAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: fco2_lu_inst    ! Emission from land use change at one time step
88!$OMP THREADPRIVATE(fco2_lu_inst)
[1227]89
[3385]90! Calculated co2 field to be send to the ocean via the coupler and to ORCHIDEE
[1454]91  REAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: co2_send ! Field allocated in phyetat0
[1250]92!$OMP THREADPRIVATE(co2_send)
[1227]93
[3387]94! nbfields : total number of fields
95  INTEGER, PUBLIC :: nbcf
96!$OMP THREADPRIVATE(nbcf)
[1454]97
[3387]98! nbcf_in : number of fields IN
99  INTEGER, PUBLIC  :: nbcf_in
100!$OMP THREADPRIVATE(nbcf_in)
101
102! nbcf_in_orc : number of fields IN
103  INTEGER, PUBLIC  :: nbcf_in_orc
104!$OMP THREADPRIVATE(nbcf_in_orc)
105
106! nbcf_in_inca : number of fields IN (from INCA)
107  INTEGER, PUBLIC  :: nbcf_in_inca
108!$OMP THREADPRIVATE(nbcf_in_inca)
109
110! nbcf_in_nemo : number of fields IN (from nemo)
111  INTEGER, PUBLIC  :: nbcf_in_nemo
112!$OMP THREADPRIVATE(nbcf_in_nemo)
113
114! nbcf_in_ant : number of fields IN (from anthropogenic sources)
115  INTEGER, PUBLIC  :: nbcf_in_ant
116!$OMP THREADPRIVATE(nbcf_in_ant)
117
118! nbcf_out : number of fields OUT
119  INTEGER, PUBLIC :: nbcf_out
120!$OMP THREADPRIVATE(nbcf_out)
121
122! Name of variables
123  CHARACTER(len=25), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfname     ! coupling field short name for restart (?) and diagnostics
124!$OMP THREADPRIVATE(cfname)
125
126  CHARACTER(len=25), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfname_in  ! coupling field short name for restart (?) and diagnostics
127!$OMP THREADPRIVATE(cfname_in)
128
129  CHARACTER(len=25), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfname_out ! coupling field short name for restart (?) and diagnostics
130!$OMP THREADPRIVATE(cfname_out)
131
132  CHARACTER(len=15), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfunits_in  !  coupling field units for diagnostics
133!$OMP THREADPRIVATE(cfunits_in)
134
135  CHARACTER(len=15), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfunits_out !  coupling field units for diagnostics
136!$OMP THREADPRIVATE(cfunits_out)
137
138  CHARACTER(len=120), ALLOCATABLE, DIMENSION(:), PUBLIC :: cftext_in  ! coupling field long name for diagnostics
139!$OMP THREADPRIVATE(cftext_in)
140
141  CHARACTER(len=120), ALLOCATABLE, DIMENSION(:), PUBLIC :: cftext_out ! coupling field long name for diagnostics
142!$OMP THREADPRIVATE(cftext_out)
143
144  CHARACTER(len=5), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfmod1 ! model 1 (rreference) : LMDz
145!$OMP THREADPRIVATE(cfmod1)
146
147  CHARACTER(len=5), ALLOCATABLE, DIMENSION(:), PUBLIC :: cfmod2 ! model 2
148!$OMP THREADPRIVATE(cfmod2)
149
[3391]150  CHARACTER(LEN=20), ALLOCATABLE, DIMENSION(:), PUBLIC :: field_out_names
151!$OMP THREADPRIVATE(field_out_names)
[3387]152
[3391]153  CHARACTER(LEN=20), ALLOCATABLE, DIMENSION(:), PUBLIC :: field_in_names
154!$OMP THREADPRIVATE(field_in_names)
[3387]155
[3391]156  REAL, ALLOCATABLE, DIMENSION(:,:), PUBLIC :: fields_in   !  klon,nbcf_in
157!$OMP THREADPRIVATE(fields_in)
158
159  REAL, ALLOCATABLE, DIMENSION(:,:), PUBLIC :: yfields_in  !  knon,nbcf_in
160!$OMP THREADPRIVATE(yfields_in)
161
162  REAL, ALLOCATABLE, DIMENSION(:,:), PUBLIC :: fields_out  !  klon,nbcf_out
163!$OMP THREADPRIVATE(fields_out)
164
165  REAL, ALLOCATABLE, DIMENSION(:,:), PUBLIC :: yfields_out !  knon,nbcf_out
166!$OMP THREADPRIVATE(yfields_out)
167
[3390]168  TYPE, PUBLIC :: co2_trac_type
[1454]169     CHARACTER(len = 8) :: name       ! Tracer name in tracer.def
170     INTEGER            :: id         ! Index in total tracer list, tr_seri
171     CHARACTER(len=30)  :: file       ! File name
[3385]172     LOGICAL            :: cpl        ! True if this tracers is coupled from ORCHIDEE or PISCES.
[1454]173                                      ! False if read from file.
174     INTEGER            :: updatefreq ! Frequence to inject in second
175     INTEGER            :: readstep   ! Actual time step to read in file
176     LOGICAL            :: updatenow  ! True if this tracer should be updated this time step
177  END TYPE co2_trac_type
178  INTEGER,PARAMETER :: maxco2trac=5  ! Maximum number of different CO2 fluxes
179  TYPE(co2_trac_type), DIMENSION(maxco2trac) :: co2trac
180
[1227]181CONTAINS
182 
[1454]183  SUBROUTINE carbon_cycle_init(tr_seri, pdtphys, aerosol, radio)
184! This subroutine is called from traclmdz_init, only at first timestep.
185! - Read controle parameters from .def input file
186! - Search for carbon tracers and set default values
187! - Allocate variables
188! - Test for compatibility
189
[1227]190    USE dimphy
[2351]191    USE geometry_mod, ONLY : cell_area
[1454]192    USE mod_phys_lmdz_transfert_para
[2320]193    USE infotrac_phy, ONLY: nbtr, nqo, niadv, tname
[1227]194    USE IOIPSL
195    USE surface_data, ONLY : ok_veget, type_ocean
[1454]196    USE phys_cal_mod, ONLY : mth_len
[2311]197    USE print_control_mod, ONLY: lunout
[1227]198
199    IMPLICIT NONE
200    INCLUDE "clesphys.h"
201 
202! Input argument
203    REAL,DIMENSION(klon,klev,nbtr),INTENT(IN) :: tr_seri ! Concentration Traceur [U/KgA] 
[1454]204    REAL,INTENT(IN)                           :: pdtphys ! length of time step in physiq (sec)
[1227]205
206! InOutput arguments
207    LOGICAL,DIMENSION(nbtr), INTENT(INOUT) :: aerosol
208    LOGICAL,DIMENSION(nbtr), INTENT(INOUT) :: radio
209
210! Local variables
[1454]211    INTEGER               :: ierr, it, iiq, itc
212    INTEGER               :: teststop
[1227]213
[1454]214! 1) Read controle parameters from .def input file
215! ------------------------------------------------
216    ! Read fosil fuel value if no transport
217    IF (.NOT. carbon_cycle_tr) THEN
[1759]218!$OMP MASTER
[3385]219       fos_fuel_s_omp = 0.
220       CALL getin ('carbon_cycle_fos_fuel',fos_fuel_s_omp)
[1759]221!$OMP END MASTER
222!$OMP BARRIER
[3385]223       fos_fuel_s=fos_fuel_s_omp
224       WRITE(lunout,*) 'carbon_cycle_fos_fuel = ', fos_fuel_s
[1227]225    END IF
226
[1454]227    ! Read parmeter for calculation compatible emission
228    IF (.NOT. carbon_cycle_tr) THEN
[1759]229!$OMP MASTER
230       carbon_cycle_emis_comp_omp=.FALSE.
231       CALL getin('carbon_cycle_emis_comp',carbon_cycle_emis_comp_omp)
232!$OMP END MASTER
233!$OMP BARRIER
234       carbon_cycle_emis_comp=carbon_cycle_emis_comp_omp
[1454]235       WRITE(lunout,*) 'carbon_cycle_emis_comp = ',carbon_cycle_emis_comp
236       IF (carbon_cycle_emis_comp) THEN
[2311]237          CALL abort_physic('carbon_cycle_init', 'carbon_cycle_emis_comp option not yet implemented!!',1)
[1454]238       END IF
239    END IF
[1227]240
[1454]241    ! Read parameter for interactive calculation of the CO2 value for the radiation scheme
[1759]242!$OMP MASTER
243    RCO2_inter_omp=.FALSE.
244    CALL getin('RCO2_inter',RCO2_inter_omp)
245!$OMP END MASTER
246!$OMP BARRIER
247    RCO2_inter=RCO2_inter_omp
[1454]248    WRITE(lunout,*) 'RCO2_inter = ', RCO2_inter
249    IF (RCO2_inter) THEN
250       WRITE(lunout,*) 'RCO2 will be recalculated once a day'
251       WRITE(lunout,*) 'RCO2 initial = ', RCO2
252    END IF
[1227]253
[1454]254
[3385]255! 2) Search for carbon tracers and set default values
[1454]256! ---------------------------------------------------
257    itc=0
[3385]258    DO it=1,nbtr
259!!       iiq=niadv(it+2)                                                            ! jyg
260       iiq=niadv(it+nqo)                                                            ! jyg
261       
262       SELECT CASE(tname(iiq))
263       CASE("fCO2_ocn")
[1454]264          itc = itc + 1
[3385]265          co2trac(itc)%name='fCO2_ocn'
266          co2trac(itc)%id=it
267          co2trac(itc)%file='fl_co2_ocean.nc'
268          IF (carbon_cycle_cpl .AND. type_ocean=='couple') THEN
269             co2trac(itc)%cpl=.TRUE.
270             co2trac(itc)%updatefreq = 86400 ! Once a day as the coupling with OASIS/PISCES
271          ELSE
272             co2trac(itc)%cpl=.FALSE.
273             co2trac(itc)%updatefreq = 86400*mth_len ! Once a month
[1227]274          END IF
[3385]275       CASE("fCO2_land")
[1454]276          itc = itc + 1
[3385]277          co2trac(itc)%name='fCO2_land'
278          co2trac(itc)%id=it
279          co2trac(itc)%file='fl_co2_land.nc'
[1454]280          IF (carbon_cycle_cpl .AND. ok_veget) THEN
[3385]281             co2trac(itc)%cpl=.TRUE.
282             co2trac(itc)%updatefreq = INT(pdtphys) ! Each timestep as the coupling with ORCHIDEE
[1454]283          ELSE
[3385]284             co2trac(itc)%cpl=.FALSE.
285!             co2trac(itc)%updatefreq = 10800   ! 10800sec = 3H
286             co2trac(itc)%updatefreq = 86400*mth_len ! Once a month
[1454]287          END IF
[3385]288       CASE("fCO2_land_use")
[1454]289          itc = itc + 1
[3385]290          co2trac(itc)%name='fCO2_land_use'
291          co2trac(itc)%id=it
292          co2trac(itc)%file='fl_co2_land_use.nc'
[1454]293          IF (carbon_cycle_cpl .AND. ok_veget) THEN
[3385]294             co2trac(it)%cpl=.TRUE.
295             co2trac(itc)%updatefreq = INT(pdtphys) ! Each timestep as the coupling with ORCHIDEE
[1454]296          ELSE
[3385]297             co2trac(itc)%cpl=.FALSE.
298             co2trac(itc)%updatefreq = 10800   ! 10800sec = 3H
[1454]299          END IF
[3385]300       CASE("fCO2_fos_fuel")
[1454]301          itc = itc + 1
[3385]302          co2trac(itc)%name='fCO2_fos_fuel'
303          co2trac(itc)%id=it
304          co2trac(itc)%file='fossil_fuel.nc'
305          co2trac(itc)%cpl=.FALSE.       ! This tracer always read from file
306!         co2trac(itc)%updatefreq = 86400  ! 86400sec = 24H Cadule case
307          co2trac(itc)%updatefreq = 86400*mth_len ! Once a month
308       CASE("fCO2_bbg")
[1454]309          itc = itc + 1
[3385]310          co2trac(itc)%name='fCO2_bbg'
311          co2trac(itc)%id=it
312          co2trac(itc)%file='fl_co2_bbg.nc'
313          co2trac(itc)%cpl=.FALSE.       ! This tracer always read from file
314          co2trac(itc)%updatefreq = 86400*mth_len ! Once a month
[1454]315       CASE("fCO2")
316          ! fCO2 : One tracer transporting the total CO2 flux
317          itc = itc + 1
[3385]318          co2trac(itc)%name='fCO2'
319          co2trac(itc)%id=it
320          co2trac(itc)%file='fl_co2.nc'
[1454]321          IF (carbon_cycle_cpl) THEN
[3385]322             co2trac(itc)%cpl=.TRUE.
[1454]323          ELSE
[3385]324             co2trac(itc)%cpl=.FALSE.
[1454]325          END IF
[3385]326          co2trac(itc)%updatefreq = 86400
[1454]327          ! DOES THIS WORK ???? Problematic due to implementation of the coupled fluxes...
[2311]328          CALL abort_physic('carbon_cycle_init','transport of total CO2 has to be implemented and tested',1)
[1454]329       END SELECT
330    END DO
[1227]331
[3385]332    ! Total number of carbon CO2 tracers
333    ntr_co2 = itc
334   
[1454]335    ! Definition of control varaiables for the tracers
336    DO it=1,ntr_co2
337       aerosol(co2trac(it)%id) = .FALSE.
338       radio(co2trac(it)%id)   = .FALSE.
339    END DO
340   
341    ! Vector indicating which timestep to read for each tracer
342    ! Always start read in the beginning of the file
343    co2trac(:)%readstep = 0
344   
[1227]345
[1454]346! 3) Allocate variables
347! ---------------------
348    ! Allocate vector for storing fluxes to inject
[3385]349    ALLOCATE(dtr_add(klon,maxco2trac), stat=ierr)
[2311]350    IF (ierr /= 0) CALL abort_physic('carbon_cycle_init', 'pb in allocation 11',1)       
[3385]351   
[1454]352    ! Allocate variables for cumulating fluxes from ORCHIDEE
[3385]353    IF (RCO2_inter) THEN
354       IF (.NOT. carbon_cycle_tr .AND. carbon_cycle_cpl) THEN
355          ALLOCATE(fco2_land_day(klon), stat=ierr)
[2311]356          IF (ierr /= 0) CALL abort_physic('carbon_cycle_init', 'pb in allocation 2',1)
[3385]357          fco2_land_day(1:klon) = 0.
[1454]358         
[3385]359          ALLOCATE(fco2_lu_day(klon), stat=ierr)
[2311]360          IF (ierr /= 0) CALL abort_physic('carbon_cycle_init', 'pb in allocation 3',1)
[3385]361          fco2_lu_day(1:klon)   = 0.
[1227]362       END IF
[3385]363    END IF
[1227]364
[1454]365
366! 4) Test for compatibility
367! -------------------------
368!    IF (carbon_cycle_cpl .AND. type_ocean/='couple') THEN
369!       WRITE(lunout,*) 'Coupling with ocean model is needed for carbon_cycle_cpl'
[2311]370!       CALL abort_physic('carbon_cycle_init', 'coupled ocean is needed for carbon_cycle_cpl',1)
[1454]371!    END IF
372!
373!    IF (carbon_cycle_cpl .AND..NOT. ok_veget) THEN
374!       WRITE(lunout,*) 'Coupling with surface land model ORCHDIEE is needed for carbon_cycle_cpl'
[2311]375!       CALL abort_physic('carbon_cycle_init', 'ok_veget is needed for carbon_cycle_cpl',1)
[1454]376!    END IF
377
378    ! Compiler test : following should never happen
379    teststop=0
380    DO it=1,teststop
[2311]381       CALL abort_physic('carbon_cycle_init', 'Entering loop from 1 to 0',1)
[1454]382    END DO
383
[3385]384    IF (ntr_co2==0) THEN
[1454]385       ! No carbon tracers found in tracer.def. It is not possible to do carbon cycle
[3385]386       WRITE(lunout,*) 'No carbon tracers found in tracer.def. Not ok with carbon_cycle_tr and/or carbon_cycle_cp'
[2311]387       CALL abort_physic('carbon_cycle_init', 'No carbon tracers found in tracer.def',1)
[1227]388    END IF
[1454]389   
390! 5) Calculate total area of the earth surface
391! --------------------------------------------
[2351]392    CALL reduce_sum(SUM(cell_area),airetot)
[1454]393    CALL bcast(airetot)
[1227]394
395  END SUBROUTINE carbon_cycle_init
396
[1454]397  SUBROUTINE carbon_cycle(nstep, pdtphys, pctsrf, tr_seri, source)
398! Subroutine for injection of co2 in the tracers
[1227]399!
[1454]400! - Find out if it is time to update
401! - Get tracer from coupled model or from file
402! - Calculate new RCO2 value for the radiation scheme
403! - Calculate CO2 flux to send to ocean and land models (PISCES and ORCHIDEE)
[1227]404
[2320]405    USE infotrac_phy, ONLY: nbtr
[1227]406    USE dimphy
[1454]407    USE mod_phys_lmdz_transfert_para
[1227]408    USE phys_cal_mod, ONLY : mth_cur, mth_len
409    USE phys_cal_mod, ONLY : day_cur
[1785]410    USE indice_sol_mod
[2311]411    USE print_control_mod, ONLY: lunout
[2351]412    USE geometry_mod, ONLY : cell_area
[1227]413
414    IMPLICIT NONE
415
416    INCLUDE "clesphys.h"
[1454]417    INCLUDE "YOMCST.h"
[1227]418
419! In/Output arguments
420    INTEGER,INTENT(IN) :: nstep      ! time step in physiq
421    REAL,INTENT(IN)    :: pdtphys    ! length of time step in physiq (sec)
[1454]422    REAL,DIMENSION(klon,nbsrf),INTENT(IN) :: pctsrf            ! Surface fraction
423    REAL, DIMENSION(klon,klev,nbtr), INTENT(INOUT)  :: tr_seri ! All tracers
424    REAL, DIMENSION(klon,nbtr), INTENT(INOUT)       :: source  ! Source for all tracers
[1227]425
426! Local variables
[3385]427    INTEGER :: it
[1227]428    LOGICAL :: newmonth ! indicates if a new month just started
429    LOGICAL :: newday   ! indicates if a new day just started
430    LOGICAL :: endday   ! indicated if last time step in a day
431
[3385]432    REAL, PARAMETER :: fact=1.E-15/2.12  ! transformation factor from gC/m2/day => ppm/m2/day
[1454]433    REAL, DIMENSION(klon) :: fco2_tmp
[1227]434    REAL :: sumtmp
435    REAL :: delta_co2_ppm
436   
437
[1454]438! 1) Calculate logicals indicating if it is a new month, new day or the last time step in a day (end day)
439! -------------------------------------------------------------------------------------------------------
440
[3385]441    newday = .FALSE.; endday = .FALSE.; newmonth = .FALSE.
[1227]442
443    IF (MOD(nstep,INT(86400./pdtphys))==1) newday=.TRUE.
444    IF (MOD(nstep,INT(86400./pdtphys))==0) endday=.TRUE.
445    IF (newday .AND. day_cur==1) newmonth=.TRUE.
[1454]446
447! 2)  For each carbon tracer find out if it is time to inject (update)
448! --------------------------------------------------------------------
[3385]449    DO it = 1, ntr_co2
450       IF ( MOD(nstep,INT(co2trac(it)%updatefreq/pdtphys)) == 1 ) THEN
451          co2trac(it)%updatenow = .TRUE.
[1454]452       ELSE
[3385]453          co2trac(it)%updatenow = .FALSE.
[1227]454       END IF
[1454]455    END DO
[1227]456
[1454]457! 3) Get tracer update
458! --------------------------------------
[3385]459    DO it = 1, ntr_co2
460       IF ( co2trac(it)%updatenow ) THEN
461          IF ( co2trac(it)%cpl ) THEN
[1454]462             ! Get tracer from coupled model
[3385]463             SELECT CASE(co2trac(it)%name)
464             CASE('fCO2_land')     ! from ORCHIDEE
465                dtr_add(:,it) = fco2_land_inst(:)*pctsrf(:,is_ter)*fact ! [ppm/m2/day]
466             CASE('fCO2_land_use') ! from ORCHIDEE
467                dtr_add(:,it) = fco2_lu_inst(:)  *pctsrf(:,is_ter)*fact ! [ppm/m2/day]
468             CASE('fCO2_ocn')      ! from PISCES
469                dtr_add(:,it) = fco2_ocn_day(:)  *pctsrf(:,is_oce)*fact ! [ppm/m2/day]
[1454]470             CASE DEFAULT
[3385]471                WRITE(lunout,*) 'Error with tracer ',co2trac(it)%name
[2311]472                CALL abort_physic('carbon_cycle', 'No coupling implemented for this tracer',1)
[1454]473             END SELECT
474          ELSE
475             ! Read tracer from file
[3385]476             co2trac(it)%readstep = co2trac(it)%readstep + 1 ! increment time step in file
477! Patricia   CALL read_map2D(co2trac(it)%file,'fco2',co2trac(it)%readstep,.FALSE.,dtr_add(:,it))
478             CALL read_map2D(co2trac(it)%file,'fco2',co2trac(it)%readstep,.TRUE.,dtr_add(:,it))
[1227]479
[3385]480             ! Converte from kgC/m2/h to kgC/m2/s
481             dtr_add(:,it) = dtr_add(:,it)/3600
[1454]482             ! Add individual treatment of values read from file
[3385]483             SELECT CASE(co2trac(it)%name)
484             CASE('fCO2_land')
[1454]485                dtr_add(:,it) = dtr_add(:,it) *pctsrf(:,is_ter)
[3385]486             CASE('fCO2_land_use')
[1454]487                dtr_add(:,it) = dtr_add(:,it) *pctsrf(:,is_ter)
[3385]488             CASE('fCO2_ocn')
[1454]489                dtr_add(:,it) = dtr_add(:,it) *pctsrf(:,is_oce)
490! Patricia :
491!             CASE('fCO2_fos_fuel')
492!                dtr_add(:,it) = dtr_add(:,it)/mth_len
[3385]493!                co2trac(it)%readstep = 0 ! Always read same value for fossil fuel(Cadule case)
[1454]494             END SELECT
[1227]495          END IF
[1454]496       END IF
497    END DO
[1227]498
[1454]499! 4) Update co2 tracers :
500!    Loop over all carbon tracers and add source
501! ------------------------------------------------------------------
502    IF (carbon_cycle_tr) THEN
503       DO it = 1, ntr_co2
[3385]504          IF (.FALSE.) THEN
505             tr_seri(1:klon,1,co2trac(it)%id) = tr_seri(1:klon,1,co2trac(it)%id) + dtr_add(1:klon,it)
506             source(1:klon,co2trac(it)%id) = 0.
507          ELSE
508             source(1:klon,co2trac(it)%id) = dtr_add(1:klon,it)
509          END IF
[1454]510       END DO
[1227]511    END IF
512
513
[1454]514! 5) Calculations for new CO2 value for the radiation scheme(instead of reading value from .def)
515! ----------------------------------------------------------------------------------------------
[3385]516    IF (RCO2_inter) THEN
517       ! Cumulate fluxes from ORCHIDEE at each timestep
518       IF (.NOT. carbon_cycle_tr .AND. carbon_cycle_cpl) THEN
519          IF (newday) THEN ! Reset cumulative variables once a day
520             fco2_land_day(1:klon) = 0.
521             fco2_lu_day(1:klon)   = 0.
522          END IF
523          fco2_land_day(1:klon) = fco2_land_day(1:klon) + fco2_land_inst(1:klon) ![gC/m2/day]
524          fco2_lu_day(1:klon)   = fco2_lu_day(1:klon)   + fco2_lu_inst(1:klon)   ![gC/m2/day]
525       END IF
[1227]526
[3385]527       ! At the end of a new day, calculate a mean scalare value of CO2
528       ! JG : Ici on utilise uniquement le traceur du premier couche du modele. Est-ce que c'est correcte ?
529       IF (endday) THEN
[1227]530
[1454]531          IF (carbon_cycle_tr) THEN
532             ! Sum all co2 tracers to get the total delta CO2 flux
533             fco2_tmp(:) = 0.
534             DO it = 1, ntr_co2
535                fco2_tmp(1:klon) = fco2_tmp(1:klon) + tr_seri(1:klon,1,co2trac(it)%id)
536             END DO
[3385]537             
538          ELSE IF (carbon_cycle_cpl) THEN ! no carbon_cycle_tr
[1454]539             ! Sum co2 fluxes comming from coupled models and parameter for fossil fuel
[3385]540             fco2_tmp(1:klon) = fos_fuel_s + ((fco2_lu_day(1:klon) + fco2_land_day(1:klon))*pctsrf(1:klon,is_ter) &
541                  + fco2_ocn_day(:)*pctsrf(:,is_oce)) * fact
[1227]542          END IF
543
[1454]544          ! Calculate a global mean value of delta CO2 flux
[3385]545          fco2_tmp(1:klon) = fco2_tmp(1:klon) * cell_area(1:klon)
[1227]546          CALL reduce_sum(SUM(fco2_tmp),sumtmp)
[1454]547          CALL bcast(sumtmp)
[1227]548          delta_co2_ppm = sumtmp/airetot
549         
[1454]550          ! Add initial value for co2_ppm and delta value
551          co2_ppm = co2_ppm0 + delta_co2_ppm
[3385]552         
[1454]553          ! Transformation of atmospheric CO2 concentration for the radiation code
554          RCO2 = co2_ppm * 1.0e-06  * 44.011/28.97
555         
[3385]556          WRITE(lunout,*) 'RCO2 is now updated! RCO2 = ', RCO2
557       END IF ! endday
[1227]558
[3385]559    END IF ! RCO2_inter
[1227]560
561
[1454]562! 6) Calculate CO2 flux to send to ocean and land models : PISCES and ORCHIDEE         
563! ----------------------------------------------------------------------------
[3385]564    IF (carbon_cycle_cpl) THEN
[1454]565
[3385]566       IF (carbon_cycle_tr) THEN
567          ! Sum all co2 tracers to get the total delta CO2 flux at first model layer
568          fco2_tmp(:) = 0.
[1454]569          DO it = 1, ntr_co2
[3385]570             fco2_tmp(1:klon) = fco2_tmp(1:klon) + tr_seri(1:klon,1,co2trac(it)%id)
[1454]571          END DO
572          co2_send(1:klon) = fco2_tmp(1:klon) + co2_ppm0
[1227]573       ELSE
[3385]574          ! Send a scalare value in 2D variable to ocean and land model (PISCES and ORCHIDEE)
[1454]575          co2_send(1:klon) = co2_ppm
[1227]576       END IF
577
[3385]578    END IF
[1227]579
580  END SUBROUTINE carbon_cycle
581 
[3387]582  SUBROUTINE infocfields_init
583
[3435]584!    USE control_mod, ONLY: planet_type
[3387]585    USE phys_cal_mod, ONLY : mth_cur
586    USE mod_synchro_omp
587    USE mod_phys_lmdz_para, ONLY: is_mpi_root, is_omp_root
588    USE mod_phys_lmdz_transfert_para
589    USE mod_phys_lmdz_omp_transfert
590    USE dimphy, ONLY: klon
591
592    IMPLICIT NONE
593
594!=======================================================================
595!
596!   Authors: Patricia Cadule and Laurent Fairhead 
597!   -------
598!
599!  Purpose and description:
600!  -----------------------
601!
602! Infofields
603! this routine enables to define the field exchanges in both directions between
604! the atmospheric circulation model (LMDZ) and ORCHIDEE. In the future this
605! routing might apply to other models (e.g., NEMO, INCA, ...).
606! Therefore, currently with this routine, it is possible to define the coupling
607! fields only between LMDZ and ORCHIDEE.
608! The coupling_fields.def file enables to define the name of the exchanged
609! fields at the coupling interface.
610! field_in_names : the set of names of the exchanged fields in input to ORCHIDEE
611! (LMDZ to ORCHIDEE)
612! field_out_names : the set of names of the exchanged fields in output of
613! ORCHIDEE (ORCHIDEE to LMDZ)
614! n : the number of exchanged fields at th coupling interface
615! nb_fields_in : number of inputs fields to ORCHIDEE (LMDZ to ORCHIDEE)
616! nb_fields_out : number of ouput fields of ORCHIDEE (ORCHIDEE to LMDZ)
617!
618! The syntax for coupling_fields.def is as follows:
619! IMPORTANT: each column entry must be separated from the previous one by 3
620! spaces and only that
621! field name         coupling          model 1         model 2         long_name
622!                    direction
623!   10char  -3spaces-  3char  -3spaces- 4char -3spaces- 4char -3spaces-  30char
624!
625! n
626! FIELD1 IN LMDZ ORC
627! ....
628! FIELD(j) IN LMDZ ORC
629! FIELD(j+1) OUT LMDZ ORC
630! ...
631! FIELDn OUT LMDZ ORC   
632!
633!=======================================================================
634!   ... 22/12/2017 ....
635!-----------------------------------------------------------------------
636! Declarations
637
638  INCLUDE "clesphys.h"
639  INCLUDE "dimensions.h"
640  INCLUDE "iniprint.h"
641
642! Local variables
643
644  INTEGER :: iq,  ierr, stat, error
645
646  CHARACTER(LEN=20), ALLOCATABLE, DIMENSION(:), SAVE  :: cfname_root
647  CHARACTER(LEN=120), ALLOCATABLE, DIMENSION(:), SAVE :: cftext_root
648  CHARACTER(LEN=15), ALLOCATABLE, DIMENSION(:), SAVE  :: cfunits_root
649
650  CHARACTER(len=3), ALLOCATABLE, DIMENSION(:) :: cfintent_root
651  CHARACTER(len=5), ALLOCATABLE, DIMENSION(:) :: cfmod1_root
652  CHARACTER(len=5), ALLOCATABLE, DIMENSION(:) :: cfmod2_root
653
654  LOGICAL, ALLOCATABLE, DIMENSION(:), SAVE :: mask_in_root
655  LOGICAL, ALLOCATABLE, DIMENSION(:), SAVE :: mask_out_root
656
657  CHARACTER(len=*),parameter :: modname="infocfields"
658
[3435]659  CHARACTER(len=10),SAVE :: planet_type="earth"
660
[3387]661!-----------------------------------------------------------------------
662
663nbcf=0
664nbcf_in=0
665nbcf_out=0
666
667IF (planet_type=='earth') THEN
668
669    IF (is_mpi_root .AND. is_omp_root) THEN
670
671       IF (level_coupling_esm.GT.0) THEN
672
673          OPEN(200,file='coupling_fields.def',form='formatted',status='old', iostat=ierr)
674
675          IF (ierr.EQ.0) THEN
676
677             WRITE(lunout,*) trim(modname),': Open coupling_fields.def : ok'
678             READ(200,*) nbcf
679             WRITE(lunout,*) 'infocfields_mod.F90 --- nbcf=',nbcf
[3390]680             ALLOCATE(cfname_root(nbcf))
681             ALLOCATE(cfintent_root(nbcf))
682             ALLOCATE(cfmod1_root(nbcf))
683             ALLOCATE(cfmod2_root(nbcf))
684             ALLOCATE(cftext_root(nbcf))
685             ALLOCATE(cfunits_root(nbcf))
686             ALLOCATE(mask_in_root(nbcf))
687             ALLOCATE(mask_out_root(nbcf))
[3387]688
689             nbcf_in=0
690             nbcf_out=0
[3390]691
[3387]692             DO iq=1,nbcf
693                WRITE(lunout,*) 'infofields : field=',iq
694                READ(200,'(A15,3X,A3,3X,A5,3X,A5,3X,A120,3X,A15)',IOSTAT=ierr) &
695                   cfname_root(iq),cfintent_root(iq),cfmod1_root(iq),cfmod2_root(iq),cftext_root(iq),cfunits_root(iq)
696                cfname_root(iq)=TRIM(cfname_root(iq))
697                cfintent_root(iq)=TRIM(cfintent_root(iq))
698                cfmod1_root(iq)=TRIM(cfmod1_root(iq))
699                cfmod2_root(iq)=TRIM(cfmod2_root(iq))
700                cftext_root(iq)=TRIM(cftext_root(iq))
701                cfunits_root(iq)=TRIM(cfunits_root(iq))
702                WRITE(lunout,*) 'coupling field: ',cfname_root(iq), & 
703                               ', number: ',iq,', INTENT: ',cfintent_root(iq)
704                WRITE(lunout,*) 'coupling field: ',cfname_root(iq), &
705                               ', number: ',iq,', model 1 (ref): ',cfmod1_root(iq),', model 2: ',cfmod2_root(iq)
706                WRITE(lunout,*) 'coupling field: ',cfname_root(iq), &
707                               ', number: ',iq,', long name: ',cftext_root(iq),', units ',cfunits_root(iq)
[3390]708                IF (nbcf_in+nbcf_out.LT.nbcf) THEN
709                  IF (cfintent_root(iq).NE.'OUT') THEN
710                    nbcf_in=nbcf_in+1
711                    mask_in_root(iq)=.TRUE.
712                    mask_out_root(iq)=.FALSE.
713                  ELSE IF (cfintent_root(iq).EQ.'OUT') THEN
714                    nbcf_out=nbcf_out+1
715                    mask_in_root(iq)=.FALSE.
716                    mask_out_root(iq)=.TRUE.
717                  ENDIF
[3387]718                ELSE
[3390]719                  WRITE(lunout,*) 'abort_gcm --- nbcf    : ',nbcf
720                  WRITE(lunout,*) 'abort_gcm --- nbcf_in : ',nbcf_in
[3387]721                  WRITE(lunout,*) 'abort_gcm --- nbcf_out: ',nbcf_out
[3435]722                  CALL abort_physic('infocfields_init','Problem in the definition of the coupling fields',1)
[3387]723               ENDIF
724             ENDDO !DO iq=1,nbcf
725          ELSE
726             WRITE(lunout,*) trim(modname),': infocfields_mod.F90 --- Problem in opening coupling_fields.def'
727             WRITE(lunout,*) trim(modname),': infocfields_mod.F90 --- WARNING using defaut values'
728          ENDIF ! ierr
729          CLOSE(200)
730
731       ENDIF ! level_coupling_esm
732
733    ENDIF !   (is_mpi_root .AND. is_omp_root)
734!$OMP BARRIER
735
736    CALL bcast(nbcf)
737    CALL bcast(nbcf_in)
738    CALL bcast(nbcf_out)
739
[3390]740    WRITE(lunout,*) 'infocfields_mod.F90 --- nbcf    =',nbcf
741    WRITE(lunout,*) 'infocfields_mod.F90 --- nbcf_in =',nbcf_in
[3387]742    WRITE(lunout,*) 'infocfields_mod.F90 --- nbcf_out=',nbcf_out
743
[3390]744    ALLOCATE(cfname(nbcf))
745    ALLOCATE(cfname_in(nbcf_in))
746    ALLOCATE(cftext_in(nbcf_in))
747    ALLOCATE(cfname_out(nbcf_out))
748    ALLOCATE(cftext_out(nbcf_out))
749    ALLOCATE(cfmod1(nbcf))
750    ALLOCATE(cfmod2(nbcf))
751    ALLOCATE(cfunits_in(nbcf_in))
752    ALLOCATE(cfunits_out(nbcf_out))
[3387]753       
754    IF (is_mpi_root .AND. is_omp_root) THEN
755
[3390]756        IF (nbcf.GT.0)     cfname=cfname_root
757        IF (nbcf_in.GT.0)  cfname_in=PACK(cfname_root,mask_in_root)
[3387]758        IF (nbcf_out.GT.0) cfname_out=PACK(cfname_root,mask_out_root)
[3390]759        IF (nbcf_in.GT.0)  cftext_in=PACK(cftext_root,mask_in_root)
[3387]760        IF (nbcf_out.GT.0) cftext_out=PACK(cftext_root,mask_out_root)
[3390]761        IF (nbcf.GT.0)     cfmod1=cfmod1_root
762        IF (nbcf.GT.0)     cfmod2=cfmod2_root
763        IF (nbcf_in.GT.0)  cfunits_in=PACK(cfunits_root,mask_in_root)
[3387]764        IF (nbcf_out.GT.0) cfunits_out=PACK(cfunits_root,mask_out_root)
765
766        nbcf_in_orc=0
767        nbcf_in_nemo=0
768        nbcf_in_inca=0
769        nbcf_in_ant=0
770
771        DO iq=1,nbcf
[3390]772            IF (cfmod1(iq) == "ORC")  nbcf_in_orc  = nbcf_in_orc  + 1 
773            IF (cfmod1(iq) == "NEMO") nbcf_in_nemo = nbcf_in_nemo + 1 
774            IF (cfmod1(iq) == "INCA") nbcf_in_inca = nbcf_in_inca + 1
775            IF (cfmod1(iq) == "ALL")  nbcf_in_orc  = nbcf_in_orc  + 1  ! ALL = ORC/NEMO/INCA
776            IF (cfmod1(iq) == "ALL")  nbcf_in_nemo = nbcf_in_nemo + 1  ! ALL = ORC/NEMO/INCA
777            IF (cfmod1(iq) == "ALL")  nbcf_in_inca = nbcf_in_inca + 1  ! ALL = ORC/NEMO/INCA
778            IF (cfmod1(iq) == "ANT")  nbcf_in_ant  = nbcf_in_ant  + 1 
[3387]779        ENDDO
780
781    ENDIF !   (is_mpi_root .AND. is_omp_root)
782!$OMP BARRIER
783
784    CALL bcast(nbcf_in_orc)
785    CALL bcast(nbcf_in_nemo)
786    CALL bcast(nbcf_in_inca)
787    CALL bcast(nbcf_in_ant)
788
[3390]789    WRITE(lunout,*) 'nbcf_in_orc  =',nbcf_in_orc
790    WRITE(lunout,*) 'nbcf_in_nemo =',nbcf_in_nemo
791    WRITE(lunout,*) 'nbcf_in_inca =',nbcf_in_inca
792    WRITE(lunout,*) 'nbcf_in_ant  =',nbcf_in_ant
[3387]793
794    IF (nbcf_in.GT.0) THEN
795        DO iq=1,nbcf_in
796          CALL bcast(cfname_in(iq))
797          CALL bcast(cftext_in(iq))
798          CALL bcast(cfunits_in(iq))
799        ENDDO
800    ENDIF
801
802    IF (nbcf_out.GT.0) THEN
803        DO iq=1,nbcf_out
804          CALL bcast(cfname_out(iq))
805          CALL bcast(cftext_out(iq))
806          CALL bcast(cfunits_out(iq))
807        ENDDO
808    ENDIF
809
810    IF (nbcf.GT.0) THEN
811        DO iq=1,nbcf
812          CALL bcast(cfmod1(iq))
813          CALL bcast(cfmod2(iq))
814        ENDDO
815    ENDIF
816
[3390]817    IF (nbcf_in.GT.0)  WRITE(lunout,*)'infocfields_mod --- cfname_in: ',cfname_in
[3387]818    IF (nbcf_out.GT.0) WRITE(lunout,*)'infocfields_mod --- cfname_out: ',cfname_out
819
[3390]820    IF (nbcf_in.GT.0)  WRITE(lunout,*)'infocfields_mod --- cftext_in: ',cftext_in
[3387]821    IF (nbcf_out.GT.0) WRITE(lunout,*)'infocfields_mod --- cftext_out: ',cftext_out
822
823    IF (nbcf.GT.0) WRITE(lunout,*)'infocfields_mod --- cfmod1: ',cfmod1
824    IF (nbcf.GT.0) WRITE(lunout,*)'infocfields_mod --- cfmod2: ',cfmod2
825
[3390]826    IF (nbcf_in.GT.0)  WRITE(lunout,*)'infocfunits_mod --- cfunits_in: ',cfunits_in
[3387]827    IF (nbcf_out.GT.0) WRITE(lunout,*)'infocfunits_mod --- cfunits_out: ',cfunits_out
828
[3390]829    IF (nbcf_in.GT.0)  WRITE(*,*)'infocfields_init --- number of fields in to LMDZ: ',nbcf_in
[3387]830    IF (nbcf_out.GT.0) WRITE(*,*)'infocfields_init --- number of fields out of LMDZ: ',nbcf_out
831
832 ELSE
833 ! Default values for other planets
834    nbcf=0
835    nbcf_in=0
836    nbcf_out=0
837 ENDIF ! planet_type
838
[3391]839 ALLOCATE(fields_in(klon,nbcf_in),stat=error)
[3435]840 IF (error /= 0)  CALL abort_physic(modname,'Pb in allocation fields_in',1)
[3391]841 ALLOCATE(yfields_in(klon,nbcf_in),stat=error)
[3435]842 IF (error /= 0)  CALL abort_physic(modname,'Pb in allocation yfields_in',1)
[3391]843 ALLOCATE(fields_out(klon,nbcf_out),stat=error)
[3435]844 IF (error /= 0)  CALL abort_physic(modname,'Pb in allocation fields_out',1)
[3391]845 ALLOCATE(yfields_out(klon,nbcf_out),stat=error)
[3435]846 IF (error /= 0)  CALL abort_physic(modname,'Pb in allocation yfields_out',1)
[3387]847
848END SUBROUTINE infocfields_init
849
[1227]850END MODULE carbon_cycle_mod
Note: See TracBrowser for help on using the repository browser.