forked from ESCOMP/HEMCO_CESM
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhemco_interface.F90
2550 lines (2137 loc) · 110 KB
/
hemco_interface.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#define VERIFY_(A) if(.not.HCO_ESMF_VRFY(A,subname,__LINE__)) stop -1
#define ASSERT_(A) if(.not.HCO_ESMF_ASRT(A,subname,__LINE__)) stop -1
!------------------------------------------------------------------------------
! Harmonized Emissions Component (HEMCO) !
!------------------------------------------------------------------------------
!BOP
!
! !MODULE: hemco_interface
!
! !DESCRIPTION: Module HEMCO\_INTERFACE is the HEMCO-CESM interface module.
! CESM operates on chunks thus the interface is called HCOI\_Chunk.
! Internally it uses a gridded component to interact with the CAM
! physics grid; these functions are internal and called HCO\_GC...
!\\
!\\
! !INTERFACE:
!
module hemco_interface
!
! !USES:
!
! ESMF function wrappers
use hco_esmf_wrappers, only: HCO_ESMF_VRFY, HCO_ESMF_ASRT
! HEMCO ESMF Grid helpers and properties
use hco_esmf_grid, only: HCO_Grid_Init, HCO_Grid_UpdateRegrid
use hco_esmf_grid, only: HCO_Grid_HCO2CAM_2D, HCO_Grid_HCO2CAM_3D
use hco_esmf_grid, only: HCO_Grid_CAM2HCO_2D, HCO_Grid_CAM2HCO_3D
use hco_esmf_grid, only: IM, JM, LM
use hco_esmf_grid, only: XMid, XEdge, YMid, YEdge, YEdge_R, YSin, AREA_M2, Ap, Bp
use hco_esmf_grid, only: my_IM, my_JM
use hco_esmf_grid, only: my_IS, my_IE, my_JS, my_JE, my_CE
! CAM export helpers
use hco_cam_exports, only: HCO_Exports_Init
use hco_cam_exports, only: HCO_Export_Pbuf_AddField
use hco_cam_exports, only: HCO_Export_History_CAM2D, HCO_Export_History_CAM3D
use hco_cam_exports, only: HCO_Export_Pbuf_CAM2D, HCO_Export_Pbuf_CAM3D
use hco_cam_exports, only: hco_pbuf2d ! Allow for pbuf handler to be passed to exports component.
! CAM import helpers
use hco_cam_convert_state_mod,only: HCOI_Allocate_All, CAM_GetBefore_HCOI, CAM_RegridSet_HCOI
! Controls
use cam_abortutils, only: endrun ! fatal terminator
use cam_logfile, only: iulog ! output log handle
! Species information
use constituents, only: pcnst ! # of species
use constituents, only: cnst_name ! species names
use constituents, only: cnst_mw ! advected mass
use mo_chem_utls, only: get_spc_ndx ! IND_ equivalent
! Check chemistry option
use chemistry, only: chem_is
! Grid
use ppgrid, only: pcols, pver ! Cols, verts
use ppgrid, only: begchunk, endchunk ! Chunk idxs
! Time
use time_manager, only: get_curr_time, get_prev_time, get_curr_date
use time_manager, only: get_step_size
! ESMF types
use ESMF, only: ESMF_State, ESMF_Clock, ESMF_GridComp
use ESMF, only: ESMF_KIND_R8, ESMF_KIND_I4, ESMF_SUCCESS
! HEMCO types
use HCO_Error_Mod, only: hp ! HEMCO precision
use HCO_Error_Mod, only: sp ! HEMCO single precision used for Ptrs
use HCO_Error_Mod, only: HCO_SUCCESS, HCO_FAIL, HCO_VERSION
use HCO_State_Mod, only: HCO_State
use HCOX_State_Mod, only: Ext_State
use HCO_Types_Mod, only: ConfigObj
use shr_kind_mod, only: r8 => shr_kind_r8
implicit none
private
!
! !PRIVATE MEMBER FUNCTIONS:
!
private :: HCO_GC_Init
private :: HCO_GC_SetServices
private :: HCO_GC_Run
private :: HCO_GC_Final
private :: HCOI_Initialize_Pbuf
!
! !PUBLIC MEMBER FUNCTIONS:
!
public :: hemco_readnl
public :: HCOI_Chunk_Init
public :: HCOI_Chunk_Run
public :: HCOI_Chunk_Final
!
! !REMARKS:
! This file is both the interface of HEMCO component to CAM and the manager of the
! underlying HEMCO gridded component (HCO\_GC\_*).
!
! The whole file is getting a little long in the tooth, though. It might be reorg-
! anized in the future to service hemco_init/run/final which manages the gridded
! components, which in turn call the HEMCO chunk interface (HCOI\_Chunk\_*).
!
! For now, the HEMCO chunk interfaces (HCOI\_Chunk\_*) are called in directly from
! CAM cam_control.F90. I am not in the mood of writing a wrapper for now, but this
! could be abstracted in the future. (hplin, 3/29/20)
!
! On a side note, this is the 8th day of living in the 2019-nCoV scare. I miss
! matcha tea and would die to eat some sweets.
!
! It is now October 29 and COVID-19 is still raging across the globe; it feels
! like time has frozen itself since March 21, and we've all been "on one long Zoom call"
! ever since.
!
! All I hope for 2021, is that the world does not pull a "You can now play as Luigi" on me.
!
! Updated 2/24/21 from T. Fritz: Now uses constituents list, since short-term species are
! not emitted. See PR: https://github.com/jimmielin/HEMCO_CESM/pull/5
!
! It is now May 15, 2021 and I am vaccinated. Can we visit other peoples homes now?
! ref: xkcd.com/2454
!
! !REVISION HISTORY:
! 29 Jan 2020 - H.P. Lin - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !PRIVATE TYPES:
!
type(ESMF_GridComp) :: HCO_GridComp ! HEMCO GridComp
type(ESMF_State) :: HCO_GridCompState ! HEMCO GridComp Import/Export State
character(len=256) :: HcoRoot ! HEMCO data root path
character(len=256) :: HcoConfigFile ! HEMCO configuration file path
character(len=256) :: HcoDiagnFile ! HEMCO diagnostics config file path
type(ConfigObj), pointer :: HcoConfig => NULL()
type(HCO_State), pointer, public :: HcoState => NULL()
type(Ext_State), pointer, public :: ExtState => NULL()
! HEMCO internal grid parameters
integer :: HcoGridIM ! # of lons
integer :: HcoGridJM ! # of lats
! HEMCO configuration parameters that are set by namelist in CESM
integer :: HcoFixYY ! if > 0, force 'Emission year'
! Last execution times for the HEMCO component. We are assuming that time
! flows unidirectionally (and forwards, for now). (hplin, 3/30/20)
integer :: last_HCO_day, last_HCO_second
! Meteorological fields used by HEMCO to be regridded to the HEMCO grid (hplin, 3/31/20)
! We have to store the fields because the regridding can only take place within the GridComp.
! Fields are allocated after the internal grid is initialized (so my_* are avail)
!
! Moved to hco_cam_convert_state_mod, 12/16/20
contains
!EOC
!------------------------------------------------------------------------------
! Harmonized Emissions Component (HEMCO) !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: hemco_readnl
!
! !DESCRIPTION: Reads the namelist from cam/src/control/runtime_opts.
!\\
!\\
! !INTERFACE:
!
subroutine hemco_readnl( nlfile )
!
! !USES:
!
use namelist_utils, only: find_group_name
use units, only: getunit, freeunit
use spmd_utils, only: mpi_real8, mpi_logical, mpi_integer, mpi_character
use spmd_utils, only: masterproc, mpicom, masterprocid
!
! !INPUT PARAMETERS:
!
character(len=*), intent(in) :: nlfile ! namelist file
!
! !REVISION HISTORY:
! 31 Jan 2020 - H.P. Lin - Initial version
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
integer :: unitn, ierr
character(len=*), parameter :: subname = 'hemco_readnl'
character(len=256) :: hemco_data_root = ''
character(len=256) :: hemco_config_file = 'HEMCO_Config.rc'
character(len=256) :: hemco_diagn_file = 'HEMCO_Diagn.rc'
integer :: hemco_grid_xdim = 0
integer :: hemco_grid_ydim = 0
integer :: hemco_emission_year = -1
namelist /hemco_nl/ hemco_data_root, hemco_config_file, hemco_diagn_file, hemco_grid_xdim, hemco_grid_ydim, hemco_emission_year
! Read namelist on master proc
! ...
if(masterproc) then
unitn = getunit()
open(unitn, file=trim(nlfile), status='old')
call find_group_name(unitn, 'hemco_nl', status=ierr)
if(ierr == 0) then
read(unitn, hemco_nl, iostat=ierr)
if(ierr /= 0) then
call endrun(subname // ':: ERROR reading namelist')
endif
endif
close(unitn)
call freeunit(unitn)
write(iulog,*) "hemco_readnl: hemco data root is at = ", trim(hemco_data_root)
write(iulog,*) "hemco_readnl: hemco config file = ", trim(hemco_config_file)
write(iulog,*) "hemco_readnl: hemco diagn file = ", trim(hemco_diagn_file)
write(iulog,*) "hemco_readnl: hemco internal grid dimensions will be ", hemco_grid_xdim, " x ", hemco_grid_ydim
if(hemco_emission_year .gt. 0) then
write(iulog,*) "hemco_readnl: hemco will force emissions year at = ", hemco_emission_year
else
write(iulog,*) "hemco_readnl: hemco will use emissions from the CESM clock"
endif
endif
! MPI Broadcast Namelist variables
call mpi_bcast(hemco_data_root, len(hemco_data_root), mpi_character, masterprocid, mpicom, ierr)
call mpi_bcast(hemco_config_file, len(hemco_config_file), mpi_character, masterprocid, mpicom, ierr)
call mpi_bcast(hemco_diagn_file, len(hemco_diagn_file), mpi_character, masterprocid, mpicom, ierr)
call mpi_bcast(hemco_grid_xdim, 1, mpi_integer, masterprocid, mpicom, ierr)
call mpi_bcast(hemco_grid_ydim, 1, mpi_integer, masterprocid, mpicom, ierr)
call mpi_bcast(hemco_emission_year, 1, mpi_integer, masterprocid, mpicom, ierr)
! Save this to the module information
HcoRoot = hemco_data_root
HcoConfigFile = hemco_config_file
HcoDiagnFile = hemco_diagn_file
HcoGridIM = hemco_grid_xdim
HcoGridJM = hemco_grid_ydim
HcoFixYY = hemco_emission_year
end subroutine hemco_readnl
!EOC
!------------------------------------------------------------------------------
! Harmonized Emissions Component (HEMCO) !
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: HCOI_Chunk_Init
!
! !DESCRIPTION: HCOI\_Chunk\_Init is the initialization method for the CAM
! interface to HEMCO.
!\\
!\\
! !INTERFACE:
!
subroutine HCOI_Chunk_Init()
!
! !USES:
!
use cam_logfile, only: iulog
use spmd_utils, only: masterproc, mpicom, masterprocid
use spmd_utils, only: npes, iam
use perf_mod, only: t_startf, t_stopf
use mpi, only: MPI_INTEGER
use ESMF, only: ESMF_VM, ESMF_VMGetCurrent, ESMF_VMGet
use ESMF, only: ESMF_GridCompCreate, ESMF_GridCompInitialize
use ESMF, only: ESMF_GridCompSetServices
use ESMF, only: ESMF_StateCreate
use ESMF, only: ESMF_Initialize, ESMF_LOGKIND_MULTI
! CAM instance information
use cam_instance, only: inst_index, inst_name
! CAM history output (to be moved somewhere later)
use cam_history, only: addfld, add_default, horiz_only
! Get extfrc list check for 3-D emissions capability
use mo_chem_utls, only: get_extfrc_ndx
! HEMCO Initialization
use HCO_Config_Mod, only: Config_ReadFile, ConfigInit
use HCO_Driver_Mod, only: HCO_Init
use HCO_Error_Mod, only: HCO_LOGFILE_OPEN
use HCO_LogFile_Mod, only: HCO_Spec2Log
use HCO_State_Mod, only: HcoState_Init
use HCO_Types_Mod, only: ConfigObj
use HCO_Types_Mod, only: ListCont
use HCO_VertGrid_Mod, only: HCO_VertGrid_Define
! For some overriding work in HEMCO configuration
use HCO_ExtList_Mod, only: CoreNr
use HCO_Types_Mod, only: Opt, Ext
! HEMCO extensions initialization
use HCOX_Driver_Mod, only: HCOX_Init
!
! !REMARKS:
! None currently.
!
! !REVISION HISTORY:
! 06 Feb 2020 - H.P. Lin - Initial version
! 15 Dec 2020 - H.P. Lin - Implement HEMCO extensions that do require met
! 23 Mar 2021 - H.P. Lin - Now export for diagnostics too
! 12 Jan 2023 - H.P. Lin - Optimize memory usage by only allocating 2-D/3-D as needed
! 15 Jun 2023 - H.P. Lin - Now override HEMCO_Diagn.rc file path and ROOT path in CESM env.
!EOP
!------------------------------------------------------------------------------
!BOC
!
! !LOCAL VARIABLES:
!
character(len=*), parameter :: subname = 'HCOI_Chunk_Init'
integer :: RC ! ESMF return code
integer :: HMRC ! HEMCO return code
integer :: N ! Loop idx
! Gridded component properties.
! Note that while edyn_grid_comp initializes the GridComp directly using
! cam_instance's inst_name, I think this may cause namespace clashing.
! So I'll be prefixing this with hco_ just incase.
character(len=32) :: HCO_GC_InstName = ''
type(ESMF_VM) :: hco_esmf_vm
! MPI stuff
integer :: localPET, PETcount
integer, allocatable :: PETlist(:) ! PETs for each instance of the physics grid
! HEMCO properties
integer :: nHcoSpc
! Temporary string for species naming in exports
character(len=128) :: exportName, exportDesc
character(len=128) :: exportNameTmp
! Timing properties
integer :: year, month, day, tod
integer :: hour, minute, second, dt
integer :: prev_day, prev_s, now_day, now_s
integer :: stepsize_tmp
! Temporaries
logical :: IsExtfrc3DEmis
! Temporaries for HEMCO cycling
logical :: OptFound
type(Ext), pointer :: ThisExt
type(Opt), pointer :: ThisOpt
!-----------------------------------------------------------------------
call t_startf('HCOI_Chunk_Init')
if(masterproc) then
write(iulog,*) "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
write(iulog,*) "HEMCO: Harmonized Emissions Component"
write(iulog,*) "https://doi.org/10.5194/gmd-14-5487-2021 (Lin et al., 2021)"
write(iulog,*) "HEMCO_CESM interface version 1.3.0"
write(iulog,*) "You are using HEMCO version ", ADJUSTL(HCO_VERSION)
write(iulog,*) "ROOT: ", HcoRoot
write(iulog,*) "Config File: ", HcoConfigFile
write(iulog,*) "Diagn File: ", HcoDiagnFile
write(iulog,*) "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
endif
! Assume success
RC = ESMF_SUCCESS
HMRC = HCO_SUCCESS
!-----------------------------------------------------------------------
! Get time properties
!-----------------------------------------------------------------------
call get_prev_time(prev_day, prev_s) ! 0 0
call get_curr_time(now_day, now_s) ! 0 0
call get_curr_date(year, month, day, tod) ! 2005 1 1 0
last_HCO_day = now_day
last_HCO_second = now_s ! This means first timestep is not ran
!-----------------------------------------------------------------------
! Setup ESMF wrapper gridded component
! Adapted from edyn_grid_comp_init
!-----------------------------------------------------------------------
call ESMF_VMGetCurrent(hco_esmf_vm, rc=RC)
ASSERT_(RC==ESMF_SUCCESS)
call ESMF_VMGet(hco_esmf_vm, localPet=localPET, petCount=PETcount, rc=RC)
ASSERT_(RC==ESMF_SUCCESS)
! Allocate and collect PETs for each instance of the physics grid
allocate(PETlist(npes))
! sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, ierror
call mpi_allgather(localPET, 1, MPI_INTEGER, PETlist, 1, MPI_INTEGER, mpicom, RC)
! Create ESMF gridded component
! This gridded component's IRF routines are defined in hemco_interface::HCO_GC_SetServices
! See there for more information. (hplin, 2/6/20)
HCO_GC_InstName = 'HCO_' // trim(inst_name)
HCO_GridComp = ESMF_GridCompCreate(name=trim(HCO_GC_InstName), petList=PETlist, rc=RC)
ASSERT_(RC==ESMF_SUCCESS)
! Create a dummy import / export state.
call ESMF_GridCompSetServices(HCO_GridComp, HCO_GC_SetServices, rc=RC)
ASSERT_(RC==ESMF_SUCCESS)
HCO_GridCompState = ESMF_StateCreate(name='HEMCO GridComp State', rc=RC)
ASSERT_(RC==ESMF_SUCCESS)
call ESMF_GridCompInitialize(HCO_GridComp, importState=HCO_GridCompState, exportState=HCO_GridCompState, rc=RC)
ASSERT_(RC==ESMF_SUCCESS)
!if(masterproc) then
! write(iulog,*) "> Initialized ESMF environment successfully! localPET, PETcount", localPET, PETcount
! write(iulog,*) "> iam, npes", iam, npes
! write(iulog,*) "> PETlist", PETlist
!endif
!-----------------------------------------------------------------------
! Setup a lat-lon "HEMCO" intermediate grid
!-----------------------------------------------------------------------
! TODO: For now, # of PEs to use for HEMCO will be total # of PEs.
! These will all have to be specified in the HEMCO namelist later on.
! The number of grid dimensions can be specified in atm namelist for
! hemco_grid_xdim, hemco_grid_ydim. note that half-sized polar boxes are made
! so increase the y-dim by one.
! 288x201 = 0.9x1.25
! 144x91 = 2.0x2.5
! Verify that the grid is in a reasonable state
if(HcoGridIM .le. 1 .or. HcoGridJM .le. 1) then
call endrun("Invalid HEMCO grid parameters - too small - in &hemco namelist. Specify hemco_grid_xdim and hemco_grid_ydim as # of grid boxes in each dimension")
endif
if(mod(HcoGridJM, 2) .ne. 1) then
call endrun("Invalid HEMCO grid parameters - hemco_grid_ydim needs to be odd - in &hemco namelist. This is because y-dim has half-sized polar boxes.")
endif
! Initialize the HEMCO intermediate grid
call HCO_Grid_Init (IM_in = HcoGridIM, JM_in = HcoGridJM, nPET_in = npes, RC=RC)
ASSERT_(RC==ESMF_SUCCESS)
if(masterproc) then
write(iulog,*) "> Initialized HEMCO Grid environment successfully!"
write(iulog,*) "> Global Dimensions: ", HcoGridIM, HcoGridJM, LM
write(iulog,*) "> my_IM, my_JM, LM, my_CE", my_IM, my_JM, LM, my_CE
endif
!-----------------------------------------------------------------------
! Update HEMCO regrid descriptors for the first time.
!-----------------------------------------------------------------------
call HCO_Grid_UpdateRegrid(RC=RC)
ASSERT_(RC==ESMF_SUCCESS)
if(masterproc) then
write(iulog,*) "> First refresh of HEMCO Regrid descriptors"
endif
!-----------------------------------------------------------------------
! Allocate HEMCO meteorological objects
! We are allocating globally for the whole HEMCO component here. This may
! clash if my_CE changes (multiple CAM instances). To be verified.
! Should be a easy fix regardless, simply allocate and dealloc in the run
! (hplin, 3/31/20)
!-----------------------------------------------------------------------
call HCOI_Allocate_All()
if(masterproc) then
write(iulog,*) "> Allocated HEMCO temporary met fields"
endif
!-----------------------------------------------------------------------
! Initialize CAM export component
!-----------------------------------------------------------------------
call HCO_Exports_Init()
if(masterproc) then
write(iulog,*) "> Initialize HEMCO/CAM exports component"
endif
! Test only hplin 3/3/20: add a dummy history field in CAM to test HEMCO
! grid is correctly reflected.
! HCO_TEST outputs in the physics mesh.
! AvgFlag: (cam_history) A mean, B mean00z, I instant, X max, M min, S stddev
!
! This call should eventually be reflected elsewhere?
call addfld("DIAG_CAM_TEST", (/'lev'/), 'I', '1', &
'HEMCO Debug, PETID written on CAM', &
gridname="physgrid")
! Enable default for debugging:
! call add_default("DIAG_CAM_TEST", 2, 'I') ! Make this field always ON
call addfld("DIAG_HCO_TEST", (/'lev'/), 'I', '1', &
'HEMCO Debug Data', &
gridname="physgrid")
! Enable default for debugging:
! call add_default("DIAG_HCO_TEST", 2, 'I') ! Make this field always ON
!-----------------------------------------------------------------------
! Initialize the HEMCO configuration object...
!-----------------------------------------------------------------------
!if(masterproc) write(iulog,*) "> Initializing HCO configuration object"
! We are using pcnst here, which is # of constituents.
nHcoSpc = pcnst ! # of hco species?
call ConfigInit(HcoConfig, HMRC, nModelSpecies=nHcoSpc)
ASSERT_(HMRC==HCO_SUCCESS)
HcoConfig%amIRoot = masterproc
! HcoConfig%amIRoot = .true. ! for debug only so verbosity is higher
HcoConfig%MetField = 'MERRA2'
HcoConfig%GridRes = ''
!-----------------------------------------------------------------------
! Retrieve the species list and register exports
!-----------------------------------------------------------------------
! Below we directly use nHcoSpc which corresponds to the number of constituents
! (nHcoSpc = pcnst). Only constituents may be advected.
HcoConfig%nModelSpc = nHcoSpc
HcoConfig%nModelAdv = nHcoSpc ! # of adv spc?
!if(masterproc) write(iulog,*) "> Initializing HCO species list!"
do N = 1, nHcoSpc
HcoConfig%ModelSpc(N)%ModID = N ! model id
HcoConfig%ModelSpc(N)%SpcName = trim(cnst_name(N)) ! only constituents can be emitted
!----------------------------------------------
! Register export properties.
!----------------------------------------------
! History output (this will be moved to hco_cam_exports soon hopefully)
exportName = 'HCO_' // trim(HcoConfig%ModelSpc(N)%SpcName)
!if(masterproc) write(iulog,*) "Exported exportName " // trim(exportName) // " to history"
! Physics buffer
! Note that _AddField will prepend HCO_, so do not add it here
!
! Update hplin 1/13/23: Verify if part of extfrc_lst. If yes,
! then allocate as 3-D. Otherwise, this field can be allocated
! as 2-D. This scan is somewhat intensive as it uses get_extfrc_ndx
! which loops through extcnt in extfrc_lst.
IsExtfrc3DEmis = (get_extfrc_ndx(trim(HcoConfig%ModelSpc(N)%SpcName)) .gt. 0)
if(masterproc) write(iulog,*) "Setting up HEMCO exportName " // trim(exportName), IsExtfrc3DEmis
if(IsExtfrc3DEmis) then
! 3-D emissions are supported
HcoConfig%ModelSpc(N)%DimMax = 3
exportDesc = "HEMCO 3-D Emissions Species " // trim(HcoConfig%ModelSpc(N)%SpcName)
call addfld(exportName, (/'lev'/), 'I', 'kg/m2/s', &
trim(exportDesc), &
gridname='physgrid')
call HCO_Export_Pbuf_AddField(HcoConfig%ModelSpc(N)%SpcName, 3, hcoID=N)
else
! 2-D emissions only
HcoConfig%ModelSpc(N)%DimMax = 2
exportDesc = "HEMCO 2-D Emissions Species " // trim(HcoConfig%ModelSpc(N)%SpcName)
call addfld(exportName, horiz_only, 'I', 'kg/m2/s', &
trim(exportDesc), &
gridname='physgrid')
call HCO_Export_Pbuf_AddField(HcoConfig%ModelSpc(N)%SpcName, 2, hcoID=N)
endif
enddo
!-----------------------------------------------------------------------
! Read HEMCO configuration file from HcoConfigFile (location in CAM namelist)
!-----------------------------------------------------------------------
!if(masterproc) write(iulog,*) "> Reading HEMCO configuration file..."
! FIXME: Not implementing "Dry-run" functionality in HEMCO_CESM. (hplin, 3/27/20)
! Phase: 0 = all, 1 = sett and switches only, 2 = fields only
call Config_ReadFile(HcoConfig%amIRoot, HcoConfig, HcoConfigFile, 1, HMRC, IsDryRun=.false.)
if(masterproc .and. HMRC /= HCO_SUCCESS) then
write(iulog,*) "******************************************"
write(iulog,*) "HEMCO_CESM: Config_ReadFile has failed (1)! "
write(iulog,*) "THIS ERROR ORIGINATED WITHIN HEMCO! "
write(iulog,*) "HEMCO configuration file could not be read."
write(iulog,*) "This may be due to misconfiguration of the"
write(iulog,*) "hemco_config_file namelist variable, or a"
write(iulog,*) "misformatted HEMCO configuration file."
write(iulog,*) "Please refer to the HEMCO.log log file in your"
write(iulog,*) "case run directory or as configured in HEMCO_Config.rc"
write(iulog,*) "for more information."
write(iulog,*) "******************************************"
endif
ASSERT_(HMRC==HCO_SUCCESS)
! Open the log file
if(masterproc) then
call HCO_LOGFILE_OPEN(HcoConfig%Err, RC=HMRC)
ASSERT_(HMRC==HCO_SUCCESS)
endif
call Config_ReadFile(HcoConfig%amIRoot, HcoConfig, HcoConfigFile, 2, HMRC, IsDryRun=.false.)
if(masterproc .and. HMRC /= HCO_SUCCESS) then
write(iulog,*) "******************************************"
write(iulog,*) "HEMCO_CESM: Config_ReadFile has failed (2)! "
write(iulog,*) "THIS ERROR ORIGINATED WITHIN HEMCO! "
write(iulog,*) "HEMCO configuration file could not be read."
write(iulog,*) "This may be due to misconfiguration of the"
write(iulog,*) "hemco_config_file namelist variable, or a"
write(iulog,*) "misformatted HEMCO configuration file."
write(iulog,*) "Please refer to the HEMCO.log log file in your"
write(iulog,*) "case run directory or as configured in HEMCO_Config.rc"
write(iulog,*) "for more information."
write(iulog,*) "******************************************"
endif
ASSERT_(HMRC==HCO_SUCCESS)
!if(masterproc) write(iulog,*) "> Read HEMCO configuration file OK!"
!-----------------------------------------------------------------------
! Initialize the HEMCO state object
!-----------------------------------------------------------------------
call HcoState_Init(HcoState, HcoConfig, nHcoSpc, HMRC)
ASSERT_(HMRC==HCO_SUCCESS)
!if(masterproc) write(iulog,*) "> Initialize HEMCO state obj OK!"
! Emissions, chemistry and dynamics timestep [s]
! Assume 0.5h until given actual time in HCO_GC_Run!
stepsize_tmp = get_step_size()
if(masterproc) write(iulog,*) "> HEMCO_CESM: Step size is ", stepsize_tmp
HcoState%TS_EMIS = stepsize_tmp * 1.0
HcoState%TS_CHEM = stepsize_tmp * 1.0
HcoState%TS_DYN = stepsize_tmp * 1.0
! Not a MAPL simulation. isESMF is deceiving.
HcoState%Options%isESMF = .false.
! Deposition length scale. Used for computing dry deposition frequencies
! over the entire PBL or the first model layer. Hardcoded for now,
! should load Input_Opt%PBL_DRYDEP from GEOS-Chem-CESM (hplin, 3/29/20)
! !FIXME
HcoState%Options%PBL_DRYDEP = .false.
! Don't support DryRun option (for now)
HcoState%Options%IsDryRun = .false.
!if(masterproc) write(iulog,*) "> Set basic HEMCO state obj OK!"
!-----------------------------------------------------------------------
! Register HEMCO species information (HEMCO state object)
!-----------------------------------------------------------------------
do N = 1, nHcoSpc
HcoState%Spc(N)%ModID = N ! model id
HcoState%Spc(N)%SpcName = trim(cnst_name(N)) ! species name
HcoState%Spc(N)%MW_g = cnst_mw(N) ! mol. weight [g/mol]
! !!! We don't set Henry's law coefficients in HEMCO_CESM !!!
! they are mostly used in HCOX_SeaFlux_Mod, but HCOX are unsupported (for now)
! (hplin, 3/29/20)
! If is CESM-GC, then set Henry's law constants for SeaFlux
! KLUDGE by hplin: 1/3/21
! For defined species, hard code the Henry* values for now so we can work
! with SeaFlux. This fragmentation will cause issues down the road, FIXME
if(HcoState%Spc(N)%SpcName .eq. "CH3I") then
! 101.325_r8
HcoState%Spc(N)%HenryK0 = 0.20265_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 3.6e+3_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
if(HcoState%Spc(N)%SpcName .eq. "DMS") then
! 101.325_r8
HcoState%Spc(N)%HenryK0 = 4.80e-1_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 3100.0_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
if(HcoState%Spc(N)%SpcName .eq. "ACET") then
! 101.325_r8. using new henry constants
HcoState%Spc(N)%HenryK0 = 2.74e+1_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 5500.0_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
if(HcoState%Spc(N)%SpcName .eq. "MOH") then
! 101.325_r8
HcoState%Spc(N)%HenryK0 = 2.03e+2_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 5600.0_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
if(HcoState%Spc(N)%SpcName .eq. "ALD2") then
! 101.325_r8. using new henry constants
HcoState%Spc(N)%HenryK0 = 1.30e-01_r8 * 101.325_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 5900.0_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
if(HcoState%Spc(N)%SpcName .eq. "MENO3") then
! 101.325_r8
HcoState%Spc(N)%HenryK0 = 1.1e+1_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 4700.0_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
if(HcoState%Spc(N)%SpcName .eq. "ETNO3") then
! 101.325_r8
HcoState%Spc(N)%HenryK0 = 1.6_r8 ! [M/atm]
HcoState%Spc(N)%HenryCR = 5400.0_r8 ! [K]
HcoState%Spc(N)%HenryPKA = -999e+0_r8 ! [1] (missing_r8 from species_mod)
endif
! HcoState%Spc(N)%HenryK0 ! [M/atm]
! HcoState%Spc(N)%HenryCR ! [K]
! HcoState%Spc(N)%HenryPKA ! [1]
! Write to log too
if(masterproc) then
!write(iulog,*) ">> Spc", N, " = ", cnst_name(N), "MW_g", cnst_mw(N)
call HCO_Spec2Log(HcoState, N)
endif
enddo
!if(masterproc) write(iulog,*) "> Set HEMCO species info OK!"
!-----------------------------------------------------------------------
! Register HEMCO Grid information
!-----------------------------------------------------------------------
! Note that HEMCO running in the CAM environment is entirely MPI and
! we use the grid dimensions of the local PET. Thus, remember that all
! data and fields are sized my_* and NOT the global indices, although
! all PETs are aware. This is similar to ids, ide, jds, jde ... versus
! its, ite, jts, jte ... in WRF, but here we use my_IS, my_IE, my_JS...
!
! The vertical dimension is not decomposed and follows the CAM vertical,
! whatever that is. This information is all abstracted and propagated within
! HCO_ESMF_Grid. (hplin, 3/29/20)
HcoState%NX = my_IM
HcoState%NY = my_JM
HcoState%NZ = LM
! Pass Ap, Bp values, units [Pa], [unitless]
! later remove masterproc
call HCO_VertGrid_Define(HcoState%Config, &
zGrid = HcoState%Grid%zGrid, &
nz = HcoState%NZ, &
Ap = Ap, &
Bp = Bp, &
RC = HMRC)
ASSERT_(HMRC==HCO_SUCCESS)
! Point to grid variables
HcoState%Grid%XMID%Val => XMid (my_IS:my_IE , my_JS:my_JE )
HcoState%Grid%YMID%Val => YMid (my_IS:my_IE , my_JS:my_JE )
HcoState%Grid%XEdge%Val => XEdge (my_IS:my_IE+1, my_JS:my_JE )
HcoState%Grid%YEdge%Val => YEdge (my_IS:my_IE , my_JS:my_JE+1)
HcoState%Grid%YSin%Val => YSin (my_IS:my_IE , my_JS:my_JE+1)
HcoState%Grid%AREA_M2%Val => AREA_M2(my_IS:my_IE , my_JS:my_JE )
! Debug
! write(6,*) "HCOI_Chunk_Init XMid, YMid(1,1)", HcoState%Grid%XMid%Val(1,1), &
! HcoState%Grid%YMid%Val(1,1), &
! HcoState%Grid%Area_m2%Val(1,1)
!if(masterproc) write(iulog,*) "> Set HEMCO PET-local grid info OK!"
!-----------------------------------------------------------------------
! Override HEMCO diagnostic file and root file paths in CESM environment
! This is so that the configuration file $ROOT and $DiagnFile do not
! have to contain hard-coded paths and can be distributed by cesmdata
! agnostically of the running environment. (hplin, 6/15/23)
!-----------------------------------------------------------------------
! ROOT property. This is retrieved in several forms within the HEMCO code:
! hco_extlist_mod::HCO_ROOT(HcoConfig) --> HcoConfig%ROOT (populated by HCO_SetDefaultToken)
! hco_extlist_mod::HCO_GetOpt(ExtList, 'ROOT', -1) --> extension opt linked list
! looks like most of HEMCO convention will use HcoConfig%ROOT which is good.
! the $ROOT token replacement happens in hco_chartools_mod which uses HCO_ROOT().
!
! the property has to be updated right after HCO_SetDefaultToken and values
! appropriately updated so that retrieval will use the overridden property.
! This means it has to go right after Config_ReadFile.
! This might not be sufficient to update the configuration within the extlist -1.
HcoConfig%ROOT = HcoRoot
! DiagnFile property. This is part of the extension options and we replicate
! some of the functionality in order to override it here. Maybe this work could
! be done upstream.
OptFound = .false.
ThisOpt => NULL()
ThisExt => NULL()
ThisExt => HcoConfig%ExtList
do while(associated(ThisExt))
if(ThisExt%ExtNr /= CoreNr) then ! Looking for the core extension.
ThisExt => ThisExt%NextExt
cycle
endif
ThisOpt => ThisExt%Opts
do while(associated(ThisOpt))
if(trim(ThisOpt%OptName) == "DiagnFile") then
ThisOpt%OptValue = HcoDiagnFile
OptFound = .true.
exit
endif
ThisOpt => ThisOpt%NextOpt
enddo
if(OptFound) then
ThisExt => NULL()
else
ThisExt => ThisExt%NextExt
endif
enddo
ThisOpt => NULL()
ThisExt => NULL()
!-----------------------------------------------------------------------
! Initialize HEMCO!
! The following actions happen during initialization:
! 1) time slice pointers (tIDx_Init)
! 2) clock initialization (HcoClock_Init populates HcoState%Clock)
! 3) HEMCO diagnostic containers are initialized (HcoDiagn_Init)
! 4) configuration file initializes ReadList
! 5) universal scale factor for each HEMCO species (Hco_ScaleInit)
!-----------------------------------------------------------------------
call t_startf('HCO_HCOX_Init')
call HCO_Init(HcoState, HMRC)
if(masterproc .and. HMRC /= HCO_SUCCESS) then
write(iulog,*) "******************************************"
write(iulog,*) "HEMCO_CESM: HCO_Init has failed!"
write(iulog,*) "THIS ERROR ORIGINATED WITHIN HEMCO!"
write(iulog,*) "HEMCO could not be initialized."
write(iulog,*) "This may be due to misconfiguration of the"
write(iulog,*) "HEMCO configuration file."
write(iulog,*) "Please refer to the HEMCO.log log file and"
write(iulog,*) "the cesm.log. log files in your case run directory"
write(iulog,*) "for more information."
write(iulog,*) "******************************************"
endif
ASSERT_(HMRC==HCO_SUCCESS)
if(masterproc) write(iulog,*) "> HEMCO initialized successfully!"
!-----------------------------------------------------------------------
! Initialize HEMCO Extensions!
!-----------------------------------------------------------------------
call HCOX_Init(HcoState, ExtState, HMRC)
ASSERT_(HMRC==HCO_SUCCESS)
if(masterproc) write(iulog,*) "> HEMCO extensions initialized successfully!"
call t_stopf('HCO_HCOX_Init')
!-----------------------------------------------------------------------
! Additional exports: Verify if additional diagnostic quantities
! for HEMCO extensions need to be provisioned.
! (hplin, 3/21/21)
!-----------------------------------------------------------------------
! ParaNOx: Ship NO emissions
! Due to the length limit this is a non-standard name, the HEMCO names are
! PARANOX_O3_DEPOSITION_FLUX and PARANOX_HNO3_DEPOSITION_FLUX
if(ExtState%ParaNOx > 0) then
write(exportnameTmp, '(a)') 'PAR_O3_DEP'
exportName = 'HCO_' // trim(exportNameTmp)
exportDesc = "HEMCO Deposition Flux Name " // trim(exportNameTmp)
call addfld(exportName, horiz_only, 'I', '1', &
trim(exportDesc), &
gridname='physgrid')
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
write(exportnameTmp, '(a)') 'PAR_HNO3_DEP'
exportName = 'HCO_' // trim(exportNameTmp)
exportDesc = "HEMCO Deposition Flux Name " // trim(exportNameTmp)
call addfld(exportName, horiz_only, 'I', '1', &
trim(exportDesc), &
gridname='physgrid')
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
if(masterproc) write(iulog,*) "> HEMCO ParaNOx extension exports (PAR_O3_DEP, PAR_HNO3_DEP) initialized successfully"
endif
!-----------------------------------------------------------------------
! Additional exports: Verify if we need to add additional exports
! for integration with CESM-GC. (hplin, 4/15/20)
!-----------------------------------------------------------------------
! Do additional exports!
! Removed debug into history output because it does not seem necessary (hplin, 9/23/22)
if(chem_is('GEOS-Chem')) then
do N = 0, 72
! LANDTYPExx
write(exportNameTmp, '(a,i2.2)') 'LANDTYPE', N
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! XLAIxx
write(exportNameTmp, '(a,i2.2)') 'XLAI', N
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
enddo
! VMR_CH3CL
write(exportnameTmp, '(a)') 'VMR_CH3CL'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CH2CL2
write(exportnameTmp, '(a)') 'VMR_CH2CL2'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CHCL3
write(exportnameTmp, '(a)') 'VMR_CHCL3'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CH3BR
write(exportnameTmp, '(a)') 'VMR_CH3BR'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CCL4
write(exportnameTmp, '(a)') 'VMR_CCL4'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CFC113
write(exportnameTmp, '(a)') 'VMR_CFC113'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CFC114
write(exportnameTmp, '(a)') 'VMR_CFC114'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CFC115
write(exportnameTmp, '(a)') 'VMR_CFC115'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CFC11
write(exportnameTmp, '(a)') 'VMR_CFC11'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CFC12
write(exportnameTmp, '(a)') 'VMR_CFC12'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_CH3CCL3
write(exportnameTmp, '(a)') 'VMR_CH3CCL3'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_H1211
write(exportnameTmp, '(a)') 'VMR_H1211'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_H1301
write(exportnameTmp, '(a)') 'VMR_H1301'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_H2402
write(exportnameTmp, '(a)') 'VMR_H2402'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_HCFC141b
write(exportnameTmp, '(a)') 'VMR_HCFC141B'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_HCFC142B
write(exportnameTmp, '(a)') 'VMR_HCFC142B'
exportName = 'HCO_' // trim(exportNameTmp)
call HCO_Export_Pbuf_AddField(exportNameTmp, 2)
! VMR_HCFC22