Line data Source code
1 : !------------------------------------------------------------------------------
2 : ! Harmonized Emissions Component (HEMCO) !
3 : !------------------------------------------------------------------------------
4 : !BOP
5 : !
6 : ! !MODULE: hco_config_mod.F90
7 : !
8 : ! !DESCRIPTION: Module HCO\_Config\_Mod contains routines related
9 : ! to the HEMCO configuration file. It reads the content of the
10 : ! configuration file, checks which entires therein are actually used
11 : ! for this simulation run, and stores these information. This occurs
12 : ! in two calls: Config\_ReadFile and SetReadList. Config\_ReadFile
13 : ! writes the entire content of the configuration file into buffer
14 : ! except for the input data associated with a disabled extension.
15 : ! SetReadList does many more logical checks and adds all data used
16 : ! by HEMCO to ReadList. Scale factors not used by any of the base
17 : ! emissions and base emission fields (e.g. scale factors that won't
18 : ! be used ) are removed in this step.
19 : !\\
20 : !\\
21 : ! All data fields are saved in individual data containers, which are
22 : ! organized in the ConfigList. Hence, ConfigList is a collection of
23 : ! all HEMCO data containers, with every container representing an
24 : ! entry of the configuration file. Each data container has its unique
25 : ! container ID for identification. All HEMCO lists (ConfigList,
26 : ! ReadList, EmisList) access the same containers.
27 : !\\
28 : !\\
29 : ! The configuration file provides all source file information of the
30 : ! emission fields and scale factors to be used. It must be read at the
31 : ! beginning of a simulation run.
32 : !\\
33 : !\\
34 : ! As of HEMCO v2.0, the ConfigList linked list sits within the HEMCO
35 : ! configuration object (HcoConfig). HcoConfig must be passed to all
36 : ! routines. This allows the parallel usage of multiple invocations
37 : ! of HEMCO that use different input data. HcoConfig is initialized
38 : ! upon reading the HEMCO configuration file (within subroutine
39 : ! Config\_ReadFile).
40 : !\\
41 : !\\
42 : ! !INTERFACE:
43 : !
44 : MODULE HCO_Config_Mod
45 : !
46 : ! !USES:
47 : !
48 : USE HCO_ERROR_MOD
49 : USE HCO_DIAGN_MOD
50 : USE HCO_CHARTOOLS_MOD
51 : USE HCO_TYPES_MOD
52 : USE HCO_STATE_MOD, ONLY : HCO_State
53 :
54 : IMPLICIT NONE
55 : PRIVATE
56 : !
57 : ! !PUBLIC MEMBER FUNCTIONS:
58 : !
59 : PUBLIC :: SetReadList
60 : PUBLIC :: Config_ReadFile
61 : PUBLIC :: Config_GetnSpecies
62 : PUBLIC :: Config_GetSpecNames
63 : PUBLIC :: ConfigInit
64 : !
65 : ! !PRIVATE MEMBER FUNCTIONS:
66 : !
67 : PRIVATE :: ReadSettings
68 : PRIVATE :: ExtSwitch2Buffer
69 : PRIVATE :: ConfigList_AddCont
70 : PRIVATE :: Config_ReadCont
71 : PRIVATE :: RegisterPrepare
72 : PRIVATE :: Get_targetID
73 : PRIVATE :: Calc_Coverage
74 : PRIVATE :: Register_Base
75 : PRIVATE :: Register_Scal
76 : PRIVATE :: ReadAndSplit_Line
77 : PRIVATE :: Config_GetSpecAttr
78 : PRIVATE :: BracketCheck
79 : PRIVATE :: AddZeroScal
80 : PRIVATE :: AddShadowFields
81 : PRIVATE :: ParseEmisL
82 : PRIVATE :: CheckForDuplicateName
83 : PRIVATE :: Hco_GetTagInfo
84 : !
85 : ! !REVISION HISTORY:
86 : ! 18 Jun 2013 - C. Keller - Initialization
87 : ! See https://github.com/geoschem/hemco for complete history
88 : !EOP
89 : !------------------------------------------------------------------------------
90 : !BOC
91 : !
92 : ! !MODULE TYPES/ARGUMENTS:
93 : !
94 :
95 : !----------------------------------------------------------------
96 : ! MODULE ROUTINES follow below
97 : !----------------------------------------------------------------
98 :
99 : CONTAINS
100 : !EOC
101 : !------------------------------------------------------------------------------
102 : ! Harmonized Emissions Component (HEMCO) !
103 : !------------------------------------------------------------------------------
104 : !BOP
105 : !
106 : ! !IROUTINE: Config_Readfile
107 : !
108 : ! !DESCRIPTION: Subroutine CONFIG\_READFILE reads the HEMCO configuration file,
109 : ! archives all HEMCO options and settings (including traceback/error setup),
110 : ! and creates a data container for every (used) emission field in the config.
111 : ! file. All containers become linked through the ConfigList linked list.
112 : ! Note that lists EmisList and ReadList (created lateron) will point to the
113 : ! same containers, but will order the containers in a manner that is most
114 : ! efficient for the respective purpose.
115 : ! Argument HcoConfig represents the HEMCO configuration object. It contains
116 : ! pointers to the HEMCO traceback and error information as well as a pointer
117 : ! to ConfigList. If undefined, HcoConfig becomes initialized as part of this
118 : ! routine.
119 : !\\
120 : !\\
121 : ! !INTERFACE:
122 : !
123 0 : SUBROUTINE Config_ReadFile( am_I_Root, HcoConfig, ConfigFile, Phase, &
124 : RC, IsNest, IsDryRun )
125 : !
126 : ! !USES:
127 : !
128 : USE HCO_inquireMod, ONLY : findFreeLUN
129 : USE HCO_CharPak_Mod, ONLY : STRREPL
130 : USE HCO_EXTLIST_MOD, ONLY : AddExt, CoreNr, ExtNrInUse
131 : !
132 : ! !INPUT PARAMETERS:
133 : !
134 : LOGICAL, INTENT(IN) :: am_I_Root ! root CPU?
135 : TYPE(ConfigObj), POINTER :: HcoConfig ! HEMCO config obj
136 : CHARACTER(LEN=*), INTENT(IN) :: ConfigFile ! Full file name
137 : INTEGER, INTENT(IN) :: Phase ! 0: all
138 : ! 1: Settings and switches only
139 : ! 2: fields only
140 : LOGICAL, INTENT(IN), OPTIONAL :: IsNest ! Nested call?
141 : LOGICAL, INTENT(IN), OPTIONAL :: IsDryRun ! Dry-run?
142 : !
143 : ! !INPUT/OUTPUT PARAMETERS:
144 : !
145 : INTEGER, INTENT(INOUT) :: RC ! Success?
146 : !
147 : ! !REVISION HISTORY:
148 : ! 17 Sep 2012 - C. Keller - Initialization
149 : ! See https://github.com/geoschem/hemco for complete history
150 : !EOP
151 : !------------------------------------------------------------------------------
152 : !BOC
153 : !
154 : ! !LOCAL VARIABLES:
155 : !
156 : ! Scalars
157 : LOGICAL :: EOF
158 : LOGICAL :: EXISTS, NEST, DoDryRUn
159 : INTEGER :: NN
160 : INTEGER :: IU_HCO, IOS
161 :
162 : ! Strings
163 : CHARACTER(LEN=255) :: loc, fileMsg
164 : CHARACTER(LEN=512) :: msg
165 : CHARACTER(LEN=2047) :: CFDIR
166 : CHARACTER(LEN=2047) :: LINE
167 :
168 : !======================================================================
169 : ! Config_ReadFile begins here
170 : !======================================================================
171 :
172 : ! Enter
173 0 : RC = HCO_SUCCESS
174 0 : msg = ''
175 0 : loc = 'Config_ReadFile (hco_config_mod.F90)'
176 :
177 : ! Initialize config object if not already initialized
178 0 : IF ( .NOT. ASSOCIATED(HcoConfig) ) THEN
179 0 : CALL ConfigInit( HcoConfig, RC )
180 0 : HcoConfig%ConfigFileName = TRIM(ConfigFile)
181 : ENDIF
182 :
183 : ! Initialize
184 0 : HcoConfig%amIRoot = am_I_Root
185 :
186 : ! Leave here if configuration file is already read
187 0 : IF ( HcoConfig%ConfigFileRead ) THEN
188 0 : RETURN
189 : ENDIF
190 :
191 : ! Nested call?
192 0 : IF ( PRESENT( IsNest ) ) THEN
193 0 : NEST = IsNest
194 : ELSE
195 : NEST = .FALSE.
196 : ENDIF
197 :
198 : ! Is this a dry-run simulation?
199 0 : IF ( PRESENT( IsDryRun) ) THEN
200 0 : DoDryRun= IsDryRun
201 : ELSE
202 : DoDryRun = .FALSE.
203 : ENDIF
204 :
205 : ! Prompt to standard output (only on the root core
206 0 : IF ( HcoConfig%amIRoot ) THEN
207 :
208 0 : IF ( DoDryRun ) THEN
209 :
210 : !-----------------------------------------------------------------
211 : ! For dry-run simulations: state if the configuration file
212 : ! is found on disk, or not. Only write this message once.
213 : !-----------------------------------------------------------------
214 :
215 : ! Test if the file exists
216 0 : INQUIRE( FILE=TRIM( ConfigFile ), EXIST=Exists )
217 :
218 : ! Test if the file exists and define an output string
219 0 : IF ( Exists ) THEN
220 0 : FileMsg = 'HEMCO (INIT): Opening '
221 : ELSE
222 0 : FileMsg = 'HEMCO (INIT): REQUIRED FILE NOT FOUND '
223 : ENDIF
224 :
225 : ! Write message to stdout
226 0 : WRITE( 6, 300 ) TRIM( FileMsg ), TRIM( ConfigFile )
227 : 300 FORMAT( a, ' ./', a )
228 :
229 : ELSE
230 :
231 : !-----------------------------------------------------------------
232 : ! For regular simulations, write a message containing
233 : ! the configuration file as well as the Phase value.
234 : !-----------------------------------------------------------------
235 0 : WRITE(6,*) ' '
236 0 : IF ( Phase == 1 ) THEN
237 0 : WRITE( 6, 310 ) TRIM(ConfigFile)
238 : 310 FORMAT( 'Reading settings & switches of HEMCO configuration file: ', a )
239 :
240 0 : ELSEIF ( Phase == 2 ) THEN
241 0 : WRITE( 6, 320 ) TRIM(ConfigFile)
242 : 320 FORMAT( 'Reading fields of HEMCO configuration file: ', a )
243 :
244 : ELSE
245 0 : WRITE( 6, 330 ) TRIM(ConfigFile)
246 : 330 FORMAT( 'Reading entire HEMCO configuration file: ', a )
247 : ENDIF
248 : ENDIF
249 : ENDIF
250 :
251 : ! Extract configuration file directory. This is the directory containing
252 : ! the configuration file. Any tokens $CFDIR in the given configuration
253 : ! file will be replaced with the configuration file directory
254 0 : CALL HCO_GetBase( ConfigFile, CFDIR, RC )
255 0 : IF ( RC /= HCO_SUCCESS ) THEN
256 0 : msg = 'Could not replace $CFDIR token in: ' // TRIM( ConfigFile )
257 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
258 0 : RETURN
259 : ENDIF
260 :
261 : ! Find free LUN
262 0 : IU_HCO = findFreeLUN()
263 :
264 0 : INQUIRE( FILE=TRIM(ConfigFile), EXIST=EXISTS )
265 0 : IF ( .NOT. EXISTS ) THEN
266 0 : IF ( HcoConfig%amIRoot ) THEN
267 0 : WRITE(*,*) 'Cannot read file - it does not exist: ', TRIM(ConfigFile)
268 : ENDIF
269 0 : RC = HCO_FAIL
270 0 : RETURN
271 : ENDIF
272 :
273 : ! Open configuration file
274 0 : OPEN ( IU_HCO, FILE=TRIM( ConfigFile ), STATUS='OLD', IOSTAT=IOS )
275 0 : IF ( IOS /= 0 ) THEN
276 0 : IF ( HcoConfig%amIRoot ) THEN
277 0 : WRITE(*,*) 'Error reading ', TRIM(ConfigFile)
278 : ENDIF
279 0 : RC = HCO_FAIL
280 0 : RETURN
281 : ENDIF
282 :
283 : ! Register HEMCO core as extension Nr. CoreNr (default). The
284 : ! core module is used by all HEMCO simulations, and the overall
285 : ! HEMCO settings are stored as options of this extension.
286 : ! Note: cannot use HCO_GetOpt('Wildcard') for species here because
287 : ! this is linked to the core extension...
288 0 : IF ( .NOT. ExtNrInUse( HcoConfig%ExtList, CoreNr ) ) THEN
289 0 : CALL AddExt( HcoConfig, 'CORE', CoreNr, .TRUE., 'all', RC )
290 0 : IF ( RC /= HCO_SUCCESS ) THEN
291 0 : msg = 'Error adding CORE extension'
292 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
293 0 : RC = HCO_FAIL
294 0 : RETURN
295 : ENDIF
296 : ENDIF
297 :
298 : ! NN counts how many sections have ben read already
299 0 : NN = 0
300 :
301 : ! Loop until EOF
302 : DO
303 :
304 : ! Read a line from the file, exit if EOF
305 0 : CALL HCO_ReadLine ( IU_HCO, LINE, EOF, RC )
306 0 : IF ( RC /= HCO_SUCCESS ) THEN
307 0 : msg = 'Error in HEMCO_Config.rc @ line: ' // TRIM( Line )
308 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
309 0 : RETURN
310 : ENDIF
311 0 : IF ( EOF ) EXIT
312 :
313 : ! Replace tab characters in LINE (if any) w/ spaces
314 0 : CALL STRREPL( LINE, HCO_TAB, HCO_SPC )
315 :
316 : ! Read settings if this is beginning of settings section
317 : ! This reads all settings into buffer and initializes the
318 : ! HEMCO traceback/error options.
319 0 : IF ( INDEX ( LINE, 'BEGIN SECTION SETTINGS' ) > 0 ) THEN
320 :
321 0 : IF ( PHASE < 2 ) THEN
322 0 : CALL ReadSettings( HcoConfig, IU_HCO, EOF, RC )
323 0 : IF ( RC /= HCO_SUCCESS ) THEN
324 0 : msg = 'Error in HEMCO_Config.rc @ section ' // TRIM( line )
325 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
326 0 : RETURN
327 : ENDIF
328 0 : IF ( EOF ) EXIT
329 :
330 : ! Increase counter
331 0 : NN = NN + 1
332 :
333 : ! Can we leave here?
334 0 : IF ( PHASE == 1 .AND. NN == 2 ) EXIT
335 : ENDIF
336 :
337 : ! Read extension switches. This registers all enabled extensions.
338 : ! This must include the core extension.
339 0 : ELSEIF ( INDEX ( LINE, 'BEGIN SECTION EXTENSION SWITCHES' ) > 0 ) THEN
340 :
341 0 : IF ( PHASE < 2 ) THEN
342 0 : CALL ExtSwitch2Buffer( HcoConfig, IU_HCO, EOF, RC )
343 0 : IF ( RC /= HCO_SUCCESS ) THEN
344 0 : msg = 'Error in HEMCO_Config,rc @ section: ' // TRIM( line )
345 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
346 0 : RETURN
347 : ENDIF
348 0 : IF ( EOF ) EXIT
349 :
350 : ! Increase counter
351 0 : NN = NN + 1
352 :
353 : ! Can we leave here?
354 0 : IF ( PHASE == 1 .AND. NN == 2 ) EXIT
355 : ENDIF
356 :
357 : ! Read base emissions. This creates a new data container for each
358 : ! base emission field.
359 0 : ELSEIF ( INDEX ( LINE, 'BEGIN SECTION BASE EMISSIONS' ) > 0 ) THEN
360 :
361 : ! Read data and write into container
362 : ! For dry-run simulations, print name of any
363 : ! nested configuration files (e.g. for standalone)
364 0 : IF ( PHASE == 0 .OR. PHASE == 2 ) THEN
365 : CALL Config_ReadCont( HcoConfig, IU_HCO, CFDIR, &
366 : HCO_DCTTYPE_BASE, EOF, RC, &
367 0 : IsDryRun=IsDryRun )
368 0 : IF ( RC /= HCO_SUCCESS ) THEN
369 0 : msg = 'Error in HEMCO_Config.rc @ section: ' // TRIM( Line )
370 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
371 0 : RETURN
372 : ENDIF
373 0 : IF ( EOF ) EXIT
374 :
375 : ! Increase counter
376 0 : NN = NN + 1
377 : ENDIF
378 :
379 : ! Read scale factors. This creates a new data container for each
380 : ! scale factor.
381 0 : ELSE IF ( INDEX ( LINE, 'BEGIN SECTION SCALE FACTORS' ) > 0 ) THEN
382 :
383 : CALL Config_ReadCont( HcoConfig, IU_HCO, CFDIR, &
384 0 : HCO_DCTTYPE_SCAL, EOF, RC )
385 0 : IF ( RC /= HCO_SUCCESS ) THEN
386 0 : msg= 'Error in HEMCO_Config.rc @ section: ' // TRIM( Line )
387 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
388 0 : RETURN
389 : ENDIF
390 0 : IF ( EOF ) EXIT
391 :
392 : ! Read masks. This creates a new data container for each mask
393 0 : ELSE IF ( INDEX ( LINE, 'BEGIN SECTION MASKS' ) > 0 ) THEN
394 :
395 0 : IF ( PHASE == 0 .OR. PHASE == 2 ) THEN
396 : CALL Config_ReadCont( HcoConfig, IU_HCO, CFDIR, &
397 0 : HCO_DCTTYPE_MASK, EOF, RC )
398 0 : IF ( RC /= HCO_SUCCESS ) THEN
399 0 : msg = 'Error in HEMCO_Config.rc @ line: ' // TRIM( Line )
400 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
401 0 : RETURN
402 : ENDIF
403 0 : IF ( EOF ) EXIT
404 :
405 : ! Increase counter
406 0 : NN = NN + 1
407 : ENDIF
408 :
409 : ENDIF
410 : ENDDO
411 :
412 : ! Check if we caught all sections. Do that only for phase 1.
413 : ! Sections SETTINGS and extension switches are needed.
414 0 : IF ( PHASE == 1 .AND. NN /= 2 .AND. .NOT. NEST ) THEN
415 0 : WRITE(*,*) 'Expected 2 sections, found/read ', NN
416 0 : WRITE(*,*) 'Should read SETTINGS and EXTENSION SWITCHES'
417 0 : RC = HCO_FAIL
418 0 : RETURN
419 : ENDIF
420 :
421 : ! Close file
422 0 : CLOSE( UNIT=IU_HCO, IOSTAT=IOS )
423 0 : IF ( IOS /= 0 ) THEN
424 0 : msg = 'Error closing ' // TRIM(ConfigFile)
425 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
426 0 : RC = HCO_FAIL
427 0 : RETURN
428 : ENDIF
429 :
430 : ! Configuration file is now read
431 0 : IF ( .NOT. NEST ) THEN
432 0 : IF ( PHASE == 0 .OR. PHASE == 2 ) THEN
433 0 : HcoConfig%ConfigFileRead = .TRUE.
434 : ENDIF
435 : ENDIF
436 :
437 : ! Leave w/ success
438 0 : RC = HCO_SUCCESS
439 :
440 : END SUBROUTINE Config_ReadFile
441 : !EOC
442 : !------------------------------------------------------------------------------
443 : ! Harmonized Emissions Component (HEMCO) !
444 : !------------------------------------------------------------------------------
445 : !BOP
446 : !
447 : ! !IROUTINE: SetReadList
448 : !
449 : ! !DESCRIPTION: Subroutine SetReadList writes data to the data reading
450 : ! lists (ReadList). This routine assumes that the configuration file has
451 : ! been read beforehand (via Config\_ReadFile).
452 : !\\
453 : !\\
454 : ! !INTERFACE:
455 : !
456 0 : SUBROUTINE SetReadList( HcoState, RC )
457 : !
458 : ! !USES:
459 : !
460 : USE HCO_DATACONT_Mod, ONLY : cIDList_Create
461 : USE HCO_READLIST_Mod, ONLY : ReadList_Init, ReadList_Print
462 : !
463 : ! !INPUT PARAMETERS:
464 : !
465 : TYPE(HCO_State), POINTER :: HcoState ! HEMCO state
466 : !
467 : ! !INPUT/OUTPUT PARAMETERS:
468 : !
469 : INTEGER, INTENT(INOUT) :: RC ! Error stat
470 : !
471 : ! !REVISION HISTORY:
472 : ! 18 Jun 2013 - C. Keller: Initialization
473 : ! See https://github.com/geoschem/hemco for complete history
474 : !EOP
475 : !------------------------------------------------------------------------------
476 : !BOC
477 :
478 : CHARACTER(LEN=255) :: loc
479 : CHARACTER(LEN=512) :: msg
480 :
481 : !======================================================================
482 : ! SetReadList begins here
483 : !======================================================================
484 0 : msg = ''
485 0 : loc = 'SetReadList (HCO_CONFIG_MOD.F90)'
486 :
487 : ! Init
488 0 : CALL HCO_ENTER ( HcoState%Config%Err, LOC, RC )
489 0 : IF ( RC /= HCO_SUCCESS ) THEN
490 0 : msg = 'Error encountered in routine "HCO_Enter"!'
491 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
492 0 : RETURN
493 : ENDIF
494 :
495 : ! Return w/ error if configuration file hasn't been read yet!
496 0 : IF ( .NOT. ASSOCIATED(HcoState%Config) ) THEN
497 0 : msg = 'HEMCO configuration object in HEMCO state is empty!'
498 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
499 0 : RETURN
500 : ENDIF
501 0 : IF ( .NOT. HcoState%Config%ConfigFileRead ) THEN
502 0 : msg = 'HEMCO configuration file not read!'
503 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
504 0 : RETURN
505 : ENDIF
506 :
507 : ! Only if not yet done so...
508 0 : IF ( .NOT. HcoState%SetReadListCalled ) THEN
509 :
510 : ! Initialize ReadList
511 0 : CALL ReadList_Init ( HcoState%ReadLists, RC )
512 0 : IF ( RC /= HCO_SUCCESS ) THEN
513 0 : PRINT *,'Error in ReadList_Init called from HEMCO SetReadList'
514 0 : RETURN
515 : ENDIF
516 :
517 : ! Prepare data in buffer. This call identifies all base fields
518 : ! that have to be read by this CPU. It also kicks out base
519 : ! fields for emissions with an invalid species ID (if any) or
520 : ! if there are other base fields with higher priority.
521 0 : CALL RegisterPrepare ( HcoState, RC )
522 0 : IF ( RC /= HCO_SUCCESS ) THEN
523 0 : PRINT *,'Error in RegisterPrepare called from HEMCO SetReadList'
524 0 : RETURN
525 : ENDIF
526 :
527 : ! Register base emissions. In this step, we also redefine the
528 : ! list UnqScalIDs to make sure that only those scale factors
529 : ! will be registered that are effectively used in the next step.
530 0 : CALL Register_Base( HcoState, RC )
531 0 : IF ( RC /= HCO_SUCCESS ) THEN
532 0 : PRINT *,'Error in Register_Base called from HEMCO SetReadList'
533 0 : RETURN
534 : ENDIF
535 :
536 : ! Register scale factors based upon UnqScalIDs.
537 0 : CALL Register_Scal( HcoState, RC )
538 0 : IF ( RC /= HCO_SUCCESS ) THEN
539 0 : PRINT *,'Error in Register_Scal called from HEMCO SetReadList'
540 0 : RETURN
541 : ENDIF
542 :
543 : ! Create cIDList which allows quick access to all data containers
544 : ! based on their container IDs cID
545 0 : CALL cIDList_Create ( HcoState, HcoState%Config%ConfigList, RC )
546 0 : IF ( RC /= HCO_SUCCESS ) THEN
547 0 : PRINT *,'Error in cIDList_Create called from HEMCO SetReadlist'
548 0 : RETURN
549 : ENDIF
550 :
551 : ! Don't need internal lists anymore.
552 0 : CALL ScalID_Cleanup ( HcoState%Config%ScalIDList )
553 0 : CALL SpecName_Cleanup( HcoState%Config%SpecNameList )
554 :
555 : ENDIF ! SetReadListCalled
556 :
557 : ! SetReadList has now been called
558 0 : HcoState%SetReadListCalled = .TRUE.
559 :
560 : ! Debug
561 0 : IF ( HCO_IsVerb( HcoState%Config%Err ) ) THEN
562 0 : CALL ReadList_Print( HcoState, HcoState%ReadLists )
563 : ENDIF
564 :
565 : ! Leave w/ success
566 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
567 :
568 : END SUBROUTINE SetReadList
569 : !EOC
570 : !------------------------------------------------------------------------------
571 : ! Harmonized Emissions Component (HEMCO) !
572 : !------------------------------------------------------------------------------
573 : !BOP
574 : !
575 : ! !IROUTINE: Config_ReadCont
576 : !
577 : ! !DESCRIPTION: Subroutine CONFIG\_READCONT reads the given line into a
578 : ! list container. Depending on the specified data type, the line is
579 : ! assumed to hold base emissions, scale factors, or mask information.
580 : !\\
581 : !\\
582 : ! !INTERFACE:
583 : !
584 0 : SUBROUTINE Config_ReadCont( HcoConfig, IU_HCO, CFDIR, &
585 : DctType, EOF, RC, IsDryRun )
586 : !
587 : ! !USES:
588 : !
589 : USE HCO_CHARPAK_MOD, ONLY : StrSplit
590 : USE HCO_EXTLIST_MOD, ONLY : ExtNrInUse, HCO_GetOpt
591 : USE HCO_TIDX_Mod, ONLY : HCO_ExtractTime
592 : USE HCO_FILEDATA_Mod, ONLY : FileData_Init
593 : USE HCO_DATACONT_Mod, ONLY : CatMax, ZeroScalID
594 : !
595 : ! !INPUT PARAMETERS:
596 : !
597 : TYPE(ConfigObj), POINTER :: HcoConfig ! Config object
598 : INTEGER, INTENT(IN ) :: IU_HCO ! Logfile LUN
599 : CHARACTER(LEN=*), INTENT(IN ) :: CFDIR ! Configuration file directory
600 : INTEGER, INTENT(IN ) :: DctType ! 1=base; 2=scale; 3=mask
601 : LOGICAL, OPTIONAL :: IsDryRun ! Is this a HEMCO dry-run?
602 : !
603 : ! !INPUT/OUTPUT PARAMETERS:
604 : !
605 : LOGICAL, INTENT(INOUT) :: EOF ! end of file encountered?
606 : !
607 : ! !OUTPUT PARAMETERS:
608 : !
609 : INTEGER, INTENT( OUT) :: RC ! error code
610 : !
611 : ! !REVISION HISTORY:
612 : ! 03 Jan 2014 - C. Keller - Initial version
613 : ! See https://github.com/geoschem/hemco for complete history
614 : !EOP
615 : !------------------------------------------------------------------------------
616 : !BOC
617 : !
618 : ! !LOCAL VARIABLES:
619 : !
620 : ! Scalars
621 : INTEGER :: I, N, nEdges
622 : INTEGER :: nScl
623 : INTEGER :: STAT
624 : INTEGER :: Int1
625 : INTEGER :: Int2
626 : INTEGER :: Int3
627 : INTEGER :: Int4
628 : INTEGER :: nCat
629 : INTEGER :: Cats(CatMax)
630 : INTEGER :: STRLEN
631 : INTEGER :: levScal1
632 : INTEGER :: levScal2
633 : INTEGER :: nTags
634 : LOGICAL :: SKIP
635 : LOGICAL :: Found
636 : CHARACTER(LEN= 63) :: cName
637 : CHARACTER(LEN=255) :: srcFile
638 : CHARACTER(LEN=100) :: srcVar
639 : CHARACTER(LEN= 31) :: srcTime
640 : CHARACTER(LEN= 31) :: TmCycle
641 : CHARACTER(LEN= 1) :: WildCard
642 : CHARACTER(LEN= 1) :: Separator
643 : CHARACTER(LEN= 31) :: srcDim
644 : CHARACTER(LEN= 31) :: srcUnit
645 : CHARACTER(LEN= 31) :: SpcName
646 : CHARACTER(LEN=255) :: Char1
647 : CHARACTER(LEN=255) :: Char2
648 : CHARACTER(LEN=255) :: loc
649 : CHARACTER(LEN=255) :: LINE
650 : CHARACTER(LEN=255) :: tagId
651 : CHARACTER(LEN=255) :: tagName
652 : CHARACTER(LEN=255) :: tagcName
653 : CHARACTER(LEN=255) :: ItemPrefix
654 : CHARACTER(LEN=512) :: msg
655 :
656 : ! Arrays
657 : INTEGER :: SplitInts(255)
658 : CHARACTER(LEN=255) :: SubStrs(255)
659 :
660 : ! Pointers
661 : TYPE(ListCont), POINTER :: Lct
662 : TYPE(ListCont), POINTER :: Tmp
663 : TYPE(FileData), POINTER :: Dta
664 :
665 : !=================================================================
666 : ! Config_ReadCont begins here!
667 : !=================================================================
668 :
669 : ! Enter
670 0 : loc = 'Config_ReadCont (hco_config_mod.F90)'
671 :
672 : ! Initialize
673 0 : SKIP = .FALSE.
674 0 : nCat = -1
675 0 : Lct => NULL()
676 0 : Tmp => NULL()
677 0 : Dta => NULL()
678 :
679 : ! Get tokens
680 0 : WildCard = HCO_GetOpt( HcoConfig%ExtList, 'Wildcard' )
681 0 : Separator = HCO_GetOpt( HcoConfig%ExtList, 'Separator' )
682 :
683 : ! Repeat until end of the given section is found
684 : DO
685 :
686 : ! Zero loop variables for safety's sake (bmy, 07 Mar 2022)
687 0 : srcFile = ''
688 0 : srcVar = ''
689 0 : srcTime = ''
690 0 : tmCycle = ''
691 0 : srcDim = ''
692 0 : srcUnit = ''
693 0 : spcName = ''
694 0 : char1 = ''
695 0 : char2 = ''
696 0 : int1 = 0
697 0 : int2 = 0
698 0 : int3 = 0
699 :
700 : !==============================================================
701 : ! Read line and get desired character strings
702 : ! Since base emissions, scale factors and masks have different
703 : ! configuration file input parameter, need to use a different
704 : ! call for the three data types.
705 : !==============================================================
706 0 : IF ( DctType == HCO_DCTTYPE_BASE ) THEN
707 : CALL ReadAndSplit_Line ( HcoConfig, IU_HCO, cName, 2, &
708 : srcFile, 3, srcVar, 4, &
709 : srcTime, 5, TmCycle, 6, &
710 : srcDim, 7, srcUnit, 8, &
711 : SpcName, 9, Char1, 10, &
712 : Char2, 11, &
713 : Int1, -1, Int2, 12, &
714 : Int3, 1, STAT, &
715 0 : OutLine=LINE )
716 :
717 0 : ELSEIF ( DctType == HCO_DCTTYPE_SCAL ) THEN
718 : CALL ReadAndSplit_Line ( HcoConfig, IU_HCO, cName, 2, &
719 : srcFile, 3, srcVar, 4, &
720 : srcTime, 5, TmCycle, 6, &
721 : srcDim, 7, srcUnit, 8, &
722 : SpcName, -1, Char1, -1, &
723 : Char2, -1, &
724 : Int1, 1, Int2, 9, &
725 : Int3, 10, STAT, &
726 0 : optcl=10 , OutLine=LINE )
727 :
728 0 : ELSEIF ( DctType == HCO_DCTTYPE_MASK ) THEN
729 : CALL ReadAndSplit_Line ( HcoConfig, IU_HCO, cName, 2, &
730 : srcFile, 3, srcVar, 4, &
731 : srcTime, 5, TmCycle, 6, &
732 : srcDim, 7, srcUnit, 8, &
733 : SpcName, -1, Char1, 10, &
734 : Char2, 11, &
735 : Int1, 1, Int2, 9, &
736 : Int3, -1, STAT, &
737 0 : optcl=11, OutLine=LINE )
738 : ENDIF
739 :
740 : !--------------------------------------------------------------
741 : ! Error checks
742 : !--------------------------------------------------------------
743 :
744 : ! Check for end of file
745 0 : IF ( STAT < 0 ) THEN
746 0 : EOF = .TRUE.
747 0 : EXIT
748 : ENDIF
749 :
750 : ! Skip this entry if commented line
751 0 : IF ( STAT == 1 ) THEN
752 : CYCLE
753 : ENDIF
754 :
755 : ! Leave routine here if end of section encountered
756 0 : IF ( STAT == 10 ) THEN
757 : EXIT
758 : ENDIF
759 :
760 : ! Error if not enough entries found
761 0 : IF ( STAT == 100 ) THEN
762 0 : msg = 'STAT == 100; not enough entries found!'
763 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
764 0 : RETURN
765 : ENDIF
766 :
767 : ! -------------------------------------------------------------
768 : ! Check for emission shortcuts. Fields can be bracketed into
769 : ! 'collections'.
770 : ! -------------------------------------------------------------
771 0 : CALL BracketCheck( HcoConfig, STAT, LINE, SKIP, RC )
772 0 : IF ( RC /= HCO_SUCCESS ) THEN
773 0 : msg = 'Bracket error in HEMCO_Config.rc @ line ' // TRIM( line )
774 0 : CALL HCO_ERROR( msg, RC, thisLoc=loc )
775 0 : RETURN
776 : ENDIF
777 :
778 : ! Skip if needed
779 0 : IF ( SKIP ) CYCLE
780 :
781 : ! Can advance to next line if this was a bracket line: nothing
782 : ! else to do with this line.
783 0 : IF ( STAT == 5 .OR. STAT == 6 ) CYCLE
784 :
785 : ! Read include file. Configuration files can be 'nested', e.g.
786 : ! configuration files can be included into the 'main' configuration
787 : ! file. These files must be listed as '>>>include FileName', where
788 : ! FileName is the actual path of the file.
789 0 : IF ( STAT == 1000 ) THEN
790 :
791 : ! Call the parser. This is to make sure that any $ROOT statements
792 : ! will be evaluated properly. The configuration file must not
793 : ! contain any data tokens ($YR, $MM, etc.).
794 0 : CALL HCO_CharParse ( HcoConfig, LINE, 0, 0, 0, 0, 0, RC )
795 0 : IF ( RC /= HCO_SUCCESS ) THEN
796 0 : msg = 'Parse error in HEMCO_Config.rc @ line: ' // TRIM( line )
797 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
798 0 : RETURN
799 : ENDIF
800 :
801 : CALL Config_ReadFile( HcoConfig%amIRoot, HcoConfig, LINE, 0, RC, &
802 0 : IsNest=.TRUE., IsDryRun=IsDryRun )
803 0 : IF ( RC /= HCO_SUCCESS ) THEN
804 0 : msg = 'Error reading HEMCO_Config.rc @ line: ' // TRIM( line )
805 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
806 0 : RETURN
807 : ENDIF
808 :
809 : ! All done with this line
810 : CYCLE
811 : ENDIF
812 :
813 : ! Output status should be 0 if none of the statuses above applies
814 0 : IF ( STAT /= 0 ) THEN
815 0 : msg = 'STAT /= 0; indicates I/O error!'
816 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
817 0 : RETURN
818 : ENDIF
819 :
820 : ! For base fields, check if this extension number is indeed in
821 : ! use. Otherwise, we can ignore this line completely! The
822 : ! extension switches are read and evaluated prior to the
823 : ! extension data!
824 0 : IF ( DctType == HCO_DCTTYPE_BASE .AND. &
825 : .NOT. ExtNrInUse( HcoConfig%ExtList, Int3 ) ) CYCLE
826 :
827 : !==============================================================
828 : ! Create and fill list container and add to ConfigList
829 : !==============================================================
830 :
831 : ! Test if wildcard is present
832 0 : IF ( INDEX( srcVar, '?' ) > 0 ) THEN
833 :
834 : ! Split the name to get wildcard and string prior to wildcard
835 0 : CALL StrSplit( srcVar, '?', SubStrs, N )
836 0 : tagId = SubStrs(N-1)
837 0 : ItemPrefix = SubStrs(1)
838 :
839 : ! Get number of tags for this wildcard
840 0 : CALL Hco_GetTagInfo( tagId, HcoConfig, Found, RC, nTags=nTags )
841 :
842 : ! Add each tagged name as a separate item in the collection
843 0 : DO N = 1, nTags
844 : ! Construct the item name
845 0 : tagcName = ''
846 :
847 : ! Get tag, if any
848 : CALL Hco_GetTagInfo( tagId, HcoConfig, Found, RC, N=N, &
849 0 : tagName=tagName )
850 0 : IF ( RC /= HCO_SUCCESS ) THEN
851 : msg = 'Error retrieving tag name for' // &
852 0 : ' wildcard ' // TRIM(tagId)
853 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
854 0 : RETURN
855 : ENDIF
856 :
857 : ! Append the tag name to the output name
858 0 : srcVar = TRIM( ItemPrefix ) // TRIM( tagName )
859 0 : tagcName = TRIM( cName ) // TRIM( tagName )
860 : ! Do not overwrite species name for now. Use HEMCO wildcard
861 : ! to read all external model species.
862 : !spcName = TRIM( tagName )
863 :
864 : ! -------------------------------------------------------------
865 : ! Fill data container
866 : ! -------------------------------------------------------------
867 :
868 : ! Add blank list container (ListCont object) to ConfigList.
869 : ! The container is placed at the beginning of the list.
870 0 : CALL ConfigList_AddCont ( Lct, HcoConfig%ConfigList )
871 :
872 : ! Check if name exists already
873 0 : CALL CheckForDuplicateName( HcoConfig, tagcName, RC )
874 0 : IF ( RC /= HCO_SUCCESS ) THEN
875 0 : msg = 'Duplicate container name: ' // TRIM( tagcName )
876 0 : CALL HCO_ERROR( msg, RC, thisLoc=loc )
877 0 : RETURN
878 : ENDIF
879 :
880 : ! Attributes used by all data types: data type number and
881 : ! container name.
882 0 : Lct%Dct%DctType = DctType
883 0 : Lct%Dct%cName = ADJUSTL( tagcName )
884 :
885 : ! Set species name, extension number, emission category,
886 : ! hierarchy
887 0 : Lct%Dct%SpcName = ADJUSTL( SpcName )
888 0 : Lct%Dct%Hier = Int2
889 0 : Lct%Dct%ExtNr = Int3
890 :
891 : ! Extract category from character 2. This can be up to
892 : ! CatMax integers, or empty.
893 0 : CALL HCO_CharSplit( Char2, Separator, Wildcard, Cats, nCat, RC )
894 0 : IF ( RC /= HCO_SUCCESS ) THEN
895 0 : msg = 'Could not extract category at line: ' // TRIM( char2 )
896 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
897 0 : RETURN
898 : ENDIF
899 0 : IF ( nCat == 0 ) THEN
900 0 : Lct%Dct%Cat = -999
901 : ELSE
902 0 : Lct%Dct%Cat = Cats(1)
903 : ENDIF
904 :
905 : ! Set scale factor IDs into Scal_cID. These values will be
906 : ! replaced lateron with the container IDs (in register_base)!
907 : CALL HCO_CharSplit( Char1, Separator, Wildcard, &
908 0 : SplitInts, nScl, RC )
909 0 : IF ( RC /= HCO_SUCCESS ) THEN
910 : msg = 'Could not get scale factor ID''s in line: ' // &
911 0 : TRIM( char1 )
912 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
913 0 : RETURN
914 : ENDIF
915 0 : IF ( nScl > 0 ) THEN
916 0 : ALLOCATE ( Lct%Dct%Scal_cID(nScl) )
917 0 : Lct%Dct%Scal_cID(1:nScl) = SplitInts(1:nScl)
918 0 : Lct%Dct%nScalID = nScl
919 : ENDIF
920 :
921 : ! Register species name. A list of all species names can be
922 : ! returned to the atmospheric model to match HEMCO species
923 : ! with model species (see Config\_GetSpecNames).
924 0 : CALL SpecName_Register ( HcoConfig, ADJUSTL(SpcName), RC )
925 0 : IF ( RC /= HCO_SUCCESS ) THEN
926 0 : msg = 'Could not register species name: ' // TRIM(SpcName)
927 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
928 0 : RETURN
929 : ENDIF
930 :
931 : ! -------------------------------------------------------------
932 : ! Create and fill file data object. Use previous file data
933 : ! object if filename is undefined. Do not yet update the
934 : ! DoShare and DtaHome flags of the data file object and data
935 : ! container, respectively, since we still don't know which
936 : ! data containers will be effectively used for emission
937 : ! calculation (containers may be dropped lateron because the
938 : ! emission category / hierarchy is too low, species is not
939 : ! used, etc.). The DoShare and DtaHome flags will be set the
940 : ! first time that data is read (in hco_readlist_mod.F90).
941 : ! Here, we only set the DtaHome flag to -1000 instead of the
942 : ! default value of -999 to be able to identify data objects
943 : ! used by multiple containers.
944 : ! -------------------------------------------------------------
945 0 : IF ( TRIM( srcFile ) == '-' ) THEN
946 :
947 : ! The current entry of the configuration file specifies that
948 : ! we will get data from the file listed immediately above it.
949 : ! Thus we have to reuse a previously-defined FileData object
950 : ! (aka Dta). Stop if Dta is not initialized.
951 0 : IF ( .not. ASSOCIATED( Dta ) ) THEN
952 0 : MSG = 'Cannot use previous data container: '//TRIM(tagcName)
953 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
954 0 : RETURN
955 : ENDIF
956 :
957 : ! Reuse the file metadata specified in PrevDta for
958 : ! this entry of the HEMCO configuration file.
959 0 : Lct%Dct%DtaHome = Lct%Dct%DtaHome - 1
960 :
961 : ELSE
962 :
963 : ! The current entry of the configuration file specifies that
964 : ! we will read data from a file. We thus need to initialize
965 : ! a new FileData object to keep track of the file metadata.
966 : !
967 : ! >>> NOTE: This seems to cause a memory leak! <<<
968 : ! >>> We will look into this at a later date. <<<
969 0 : CALL FileData_Init( Dta )
970 :
971 : ! Set source file name. Check if the read file name starts
972 : ! with the configuration file token '$CFDIR', in which case
973 : ! we replace this value with the passed CFDIR value.
974 0 : STRLEN = LEN( srcFile )
975 : IF ( STRLEN > 6 ) THEN
976 0 : IF ( srcFile(1:6) == '$CFDIR' ) THEN
977 0 : srcFile = TRIM( CFDIR ) // TRIM( srcFile(7:STRLEN) )
978 : ENDIF
979 : ENDIF
980 0 : Dta%ncFile = srcFile
981 :
982 : ! Set source variable and original data unit.
983 0 : Dta%ncPara = ADJUSTL( srcVar )
984 0 : Dta%OrigUnit = ADJUSTL( srcUnit )
985 :
986 : ! If the parameter ncPara is not defined, attempt to read data
987 : ! directly from configuration file instead of netCDF.
988 : ! These data are always assumed to be in local time. Gridded
989 : ! data read from netCDF is always in UTC, except for weekdaily
990 : ! data that is treated in local time. The corresponding
991 : ! IsLocTime flag is updated when reading the data (see
992 : ! hcoio_dataread_mod.F90).
993 0 : IF ( TRIM( Dta%ncPara ) == '-' ) THEN
994 0 : Dta%ncRead = .FALSE.
995 0 : Dta%IsLocTime = .TRUE.
996 : ENDIF
997 :
998 : ! Extract information from time stamp character and pass values
999 : ! to the corresponding container variables. If no time string is
1000 : ! defined, keep default values (-1 for all of them)
1001 0 : IF ( TRIM(srcTime) /= '-' ) THEN
1002 0 : CALL HCO_ExtractTime( HcoConfig, srcTime, Dta, RC )
1003 0 : IF ( RC /= HCO_SUCCESS ) THEN
1004 0 : msg = 'Could not extract time cycle information!'
1005 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1006 0 : RETURN
1007 : ENDIF
1008 : ENDIF
1009 :
1010 : #if defined(ESMF_)
1011 : ! In an ESMF environment, the source data will be imported
1012 : ! through ExtData by name, hence need to set ncFile equal to
1013 : ! container name!
1014 : IF ( Dta%ncRead ) THEN
1015 : Dta%ncFile = ADJUSTL( tagcName )
1016 : ENDIF
1017 : #endif
1018 :
1019 : ! Update the properties of the data container
1020 : ! NOTE: This routine abstracts the big IF/ELSE block that
1021 : ! processes the time cycle information (bmy, 07 Mar 2022)
1022 : CALL UpdateDtaProperties( &
1023 : dctType = dctType, &
1024 : int3 = int3, &
1025 : char1 = TRIM( char1 ), &
1026 : char2 = char2(1:1), &
1027 : tagCName = TRIM( tagCName ), &
1028 : tmCycle = TRIM( tmCycle ), &
1029 : separator = TRIM( separator ), &
1030 : srcDim = TRIM( srcDim ), &
1031 : wildCard = TRIM( wildCard ), &
1032 : HcoConfig = HcoConfig, &
1033 : Lct = Lct, &
1034 : Dta = Dta, &
1035 0 : RC = RC )
1036 :
1037 : ! Trap potential errors
1038 0 : IF ( RC /= HCO_Success ) THEN
1039 0 : MSG = 'Error encountered in routine "UpdateDtaProperties"'
1040 0 : CALL HCO_Error( MSG, RC, thisLoc=loc )
1041 0 : RETURN
1042 : ENDIF
1043 :
1044 : ENDIF
1045 :
1046 : ! Connect this FileData object to the HcoState%HcoConfigList.
1047 0 : Lct%Dct%Dta => Dta
1048 :
1049 : ! Free list container for next cycle
1050 0 : Lct => NULL()
1051 :
1052 : ENDDO
1053 :
1054 : ! If no wildcard is present in variable name
1055 : ELSE
1056 :
1057 : ! -------------------------------------------------------------
1058 : ! Fill data container
1059 : ! -------------------------------------------------------------
1060 :
1061 : ! Add blank list container (ListCont object) to ConfigList.
1062 : ! The container is placed at the beginning of the list.
1063 0 : CALL ConfigList_AddCont ( Lct, HcoConfig%ConfigList )
1064 :
1065 : ! Check if name exists already
1066 0 : CALL CheckForDuplicateName( HcoConfig, cName, RC )
1067 0 : IF ( RC /= HCO_SUCCESS ) THEN
1068 0 : msg = 'Duplicate name: ' // TRIM( cName )
1069 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1070 0 : RETURN
1071 : ENDIF
1072 :
1073 : ! Attributes used by all data types: data type number and
1074 : ! container name.
1075 0 : Lct%Dct%DctType = DctType
1076 0 : Lct%Dct%cName = ADJUSTL(cName)
1077 :
1078 : ! Base container specific attributes
1079 0 : IF ( DctType == HCO_DCTTYPE_BASE ) THEN
1080 :
1081 : ! Set species name, extension number, emission category,
1082 : ! hierarchy
1083 0 : Lct%Dct%SpcName = ADJUSTL( SpcName )
1084 0 : Lct%Dct%Hier = Int2
1085 0 : Lct%Dct%ExtNr = Int3
1086 :
1087 : ! Extract category from character 2. This can be up to
1088 : ! CatMax integers, or empty.
1089 0 : CALL HCO_CharSplit( Char2, Separator, Wildcard, Cats, nCat, RC )
1090 0 : IF ( RC /= HCO_SUCCESS ) THEN
1091 0 : msg = 'Could not extract category from: ' // TRIM( char2 )
1092 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1093 0 : RETURN
1094 : ENDIF
1095 0 : IF ( nCat == 0 ) THEN
1096 0 : Lct%Dct%Cat = -999
1097 : ELSE
1098 0 : Lct%Dct%Cat = Cats(1)
1099 : ENDIF
1100 :
1101 : ! Set scale factor IDs into Scal_cID. These values will be
1102 : ! replaced lateron with the container IDs (in register_base)!
1103 : CALL HCO_CharSplit( Char1, Separator, Wildcard, &
1104 0 : SplitInts, nScl, RC )
1105 0 : IF ( RC /= HCO_SUCCESS ) THEN
1106 0 : msg = 'Could not get scale factor IDs from: ' // TRIM( char1 )
1107 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1108 0 : RETURN
1109 : ENDIF
1110 0 : IF ( nScl > 0 ) THEN
1111 0 : ALLOCATE ( Lct%Dct%Scal_cID(nScl) )
1112 0 : Lct%Dct%Scal_cID(1:nScl) = SplitInts(1:nScl)
1113 0 : Lct%Dct%nScalID = nScl
1114 : ENDIF
1115 :
1116 : ! Register species name. A list of all species names can be
1117 : ! returned to the atmospheric model to match HEMCO species
1118 : ! with model species (see Config\_GetSpecNames).
1119 0 : CALL SpecName_Register ( HcoConfig, ADJUSTL(SpcName), RC )
1120 0 : IF ( RC /= HCO_SUCCESS ) THEN
1121 0 : msg = 'Could not register species: ' // TRIM( SpcName )
1122 0 : CALL HCO_ERROR( msg, RC, thisLoc=loc )
1123 0 : RETURN
1124 : ENDIF
1125 :
1126 : ! Scale factor & mask specific attributes
1127 0 : ELSE IF ( DctType == HCO_DCTTYPE_SCAL .OR. &
1128 : DctType == HCO_DCTTYPE_MASK ) THEN
1129 :
1130 : ! Set scale factor ID and data operator
1131 0 : Lct%Dct%ScalID = Int1
1132 0 : Lct%Dct%Oper = Int2
1133 :
1134 : ! Make sure that negative scale factors are always read
1135 0 : IF ( Lct%Dct%ScalID < 0 ) THEN
1136 0 : CALL ScalID2List( HcoConfig%ScalIDList, Lct%Dct%ScalID, RC )
1137 0 : IF ( RC /= HCO_SUCCESS ) THEN
1138 : msg = 'Could not make sure that negative scale ' // &
1139 0 : 'are always read!'
1140 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1141 0 : RETURN
1142 : ENDIF
1143 : ENDIF
1144 :
1145 : ELSE
1146 0 : msg = 'Invalid data type!'
1147 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1148 0 : RETURN
1149 : ENDIF
1150 :
1151 : ! -------------------------------------------------------------
1152 : ! Create and fill file data object. Use previous file data
1153 : ! object if filename is undefined. Do not yet update the
1154 : ! DoShare and DtaHome flags of the data file object and data
1155 : ! container, respectively, since we still don't know which
1156 : ! data containers will be effectively used for emission
1157 : ! calculation (containers may be dropped lateron because the
1158 : ! emission category / hierarchy is too low, species is not
1159 : ! used, etc.). The DoShare and DtaHome flags will be set the
1160 : ! first time that data is read (in hco_readlist_mod.F90).
1161 : ! Here, we only set the DtaHome flag to -1000 instead of the
1162 : ! default value of -999 to be able to identify data objects
1163 : ! used by multiple containers.
1164 : ! -------------------------------------------------------------
1165 0 : IF ( TRIM( srcFile ) == '-' ) THEN
1166 :
1167 : ! The current entry of the configuration file specifies that
1168 : ! we will get data from the file listed immediately above it.
1169 : ! Thus we have to reuse a previously-defined FileData object
1170 : ! (aka Dta). Stop if Dta is not initialized.
1171 0 : IF ( .NOT. ASSOCIATED(Dta) ) THEN
1172 0 : MSG = 'Cannot use previous data container: '//TRIM(cName)
1173 0 : CALL HCO_Error( msg, RC, thisLoc=loc)
1174 0 : RETURN
1175 : ENDIF
1176 :
1177 : ! Reuse the file metadata specified in Dta for
1178 : ! this entry of the HEMCO configuration file.
1179 0 : Lct%Dct%DtaHome = Lct%Dct%DtaHome - 1
1180 :
1181 : ELSE
1182 :
1183 : ! The current entry of the configuration file specifies that
1184 : ! we will read data from a file. We thus need to initialize
1185 : ! a new FileData object to keep track of the file metadata.
1186 : !
1187 : ! >>> NOTE: This seems to cause a memory leak; <<<
1188 : ! >>> We will look into this at a later date <<<
1189 0 : CALL FileData_Init( Dta )
1190 :
1191 : ! Set source file name. Check if the read file name starts
1192 : ! with the configuration file token '$CFDIR', in which case
1193 : ! we replace this value with the passed CFDIR value.
1194 0 : STRLEN = LEN( srcFile )
1195 : IF ( STRLEN > 6 ) THEN
1196 0 : IF ( srcFile(1:6) == '$CFDIR' ) THEN
1197 0 : srcFile = TRIM( CFDIR ) // TRIM( srcFile(7:STRLEN) )
1198 : ENDIF
1199 : ENDIF
1200 0 : Dta%ncFile = srcFile
1201 :
1202 : ! Set source variable and original data unit.
1203 0 : Dta%ncPara = ADJUSTL( srcVar )
1204 0 : Dta%OrigUnit = ADJUSTL( srcUnit )
1205 :
1206 : ! If the parameter ncPara is not defined, attempt to read data
1207 : ! directly from configuration file instead of netCDF.
1208 : ! These data are always assumed to be in local time. Gridded
1209 : ! data read from netCDF is always in UTC, except for weekdaily
1210 : ! data that is treated in local time. The corresponding
1211 : ! IsLocTime flag is updated when reading the data (see
1212 : ! hcoio_dataread_mod.F90).
1213 0 : IF ( TRIM( Dta%ncPara ) == '-' ) THEN
1214 0 : Dta%ncRead = .FALSE.
1215 0 : Dta%IsLocTime = .TRUE.
1216 : ENDIF
1217 :
1218 : ! Extract information from time stamp character and pass values
1219 : ! to the corresponding container variables. If no time string is
1220 : ! defined, keep default values (-1 for all of them)
1221 0 : IF ( TRIM(srcTime) /= '-' ) THEN
1222 0 : CALL HCO_ExtractTime( HcoConfig, srcTime, Dta, RC )
1223 0 : IF ( RC /= HCO_SUCCESS ) THEN
1224 0 : msg = 'Could not extract time information!'
1225 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1226 0 : RETURN
1227 : ENDIF
1228 : ENDIF
1229 :
1230 : #if defined(ESMF_)
1231 : ! In an ESMF environment, the source data will be imported
1232 : ! through ExtData by name, hence need to set ncFile equal to
1233 : ! container name!
1234 : IF ( Dta%ncRead ) THEN
1235 : Dta%ncFile = ADJUSTL( cName )
1236 : ENDIF
1237 : #endif
1238 :
1239 : ! Update the properties of the data container
1240 : ! NOTE: This routine abstracts the big IF/ELSE block that
1241 : ! processes the time cycle information (bmy, 07 Mar 2022)
1242 : CALL UpdateDtaProperties( &
1243 : dctType = dctType, &
1244 : int3 = int3, &
1245 : char1 = TRIM( char1 ), &
1246 : char2 = char2(1:1), &
1247 : tagCName = TRIM( tagCName ), &
1248 : tmCycle = TRIM( tmCycle ), &
1249 : separator = TRIM( separator ), &
1250 : srcDim = TRIM( srcDim ), &
1251 : wildCard = TRIM( wildCard ), &
1252 : HcoConfig = HcoConfig, &
1253 : Lct = Lct, &
1254 : Dta = Dta, &
1255 0 : RC = RC )
1256 :
1257 : ! Trap potential errors
1258 0 : IF ( RC /= HCO_Success ) THEN
1259 0 : MSG = 'Error encountered in routine "UpdateDtaProperties"'
1260 0 : CALL HCO_Error( MSG, RC, thisLoc=loc )
1261 0 : RETURN
1262 : ENDIF
1263 :
1264 : ENDIF
1265 :
1266 : ! Connect FileData object to the HcoState%HcoConfigList
1267 0 : Lct%Dct%Dta => Dta
1268 :
1269 : ! If a base emission field covers multiple emission categories,
1270 : ! create a 'shadow' container for each additional category.
1271 : ! These shadow container have the same information as the main
1272 : ! container except that a scale factor of zero will be applied in
1273 : ! addition. This makes sure that the inventory cancels out other
1274 : ! inventories with lower hierarchy for every specified category,
1275 : ! while emission totals are not changed. All emissions of a base
1276 : ! field with multiple categories is written into the category
1277 : ! listed first.
1278 0 : IF ( nCat > 1 ) THEN
1279 :
1280 : ! nCat cannot exceed CatMax
1281 0 : IF ( nCat > CatMax ) THEN
1282 0 : MSG = 'Exceeded maximum number of categories!'
1283 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1284 0 : RETURN
1285 : ENDIF
1286 :
1287 0 : CALL AddShadowFields( HcoConfig, Lct, Cats, nCat, RC )
1288 0 : IF ( RC /= HCO_SUCCESS ) THEN
1289 0 : msg = 'Could not create shadow emission container!'
1290 0 : CALL HCO_ERROR( msg, RC, thisLoc=loc )
1291 0 : RETURN
1292 : ENDIF
1293 :
1294 : ! Reset nCat
1295 0 : nCat = -1
1296 : ENDIF
1297 :
1298 : ! Free list container for next cycle
1299 0 : Lct => NULL()
1300 :
1301 : ENDIF
1302 :
1303 : ENDDO
1304 :
1305 : ! Leave w/ success
1306 0 : Dta => NULL()
1307 0 : RC = HCO_SUCCESS
1308 :
1309 : END SUBROUTINE Config_ReadCont
1310 : !EOC
1311 : !------------------------------------------------------------------------------
1312 : ! Harmonized Emissions Component (HEMCO) !
1313 : !------------------------------------------------------------------------------
1314 : !BOP
1315 : !
1316 : ! !IROUTINE: BracketCheck
1317 : !
1318 : ! !DESCRIPTION: Subroutine BracketCheck checks if base emission data is within
1319 : ! a bracket and if that field shall be ignored or not. Brackets can be used to
1320 : ! lump entires of the HEMCO configuration file into collections that can be
1321 : ! collectively enabled or disabled. The first entry of a collection is marked
1322 : ! adding an 'opening bracket' to the HEMCO configuration file (on the line
1323 : ! above the entry). Opening brackets must start with three opening brackets,
1324 : ! e.g.: '(((TEST'. Similarly, the end of a collection is marked by placing a
1325 : ! closing bracket after the last entry of the collection: '))))TEST'.
1326 : ! Brackets can be enabled / disabled in the EXTENSION SWITCH section of the
1327 : ! HEMCO configuration file:
1328 : ! \# ExtNr ExtName on/off Species
1329 : ! 0 Base : on *
1330 : ! --> TEST : true
1331 : !\\
1332 : !\\
1333 : ! It is also possible to use 'opposite' brackets, e.g. to use a collection
1334 : ! only if the given setting is *disabled*. This can be achieved by precede
1335 : ! the collection word with '.not.', e.g. '(((.not.TEST' and '))).not.TEST'.
1336 : ! Similarly, multiple collections can be combined to be evaluated together,
1337 : ! e.g. NAME1.or.NAME2.
1338 : !\\
1339 : !\\
1340 : ! !INTERFACE:
1341 : !
1342 0 : SUBROUTINE BracketCheck( HcoConfig, STAT, LINE, SKIP, RC )
1343 : !
1344 : ! !USES:
1345 : !
1346 : USE HCO_EXTLIST_MOD, ONLY : GetExtOpt, GetExtNr
1347 : !
1348 : ! !INPUT PARAMETERS:
1349 : !
1350 : INTEGER, INTENT(IN) :: STAT !
1351 : CHARACTER(LEN=*), INTENT(IN) :: LINE !
1352 : !
1353 : ! !INPUT/OUTPUT PARAMETERS:
1354 : !
1355 : TYPE(ConfigObj), POINTER :: HcoConfig ! Config object
1356 : LOGICAL, INTENT(INOUT) :: SKIP ! Skip
1357 : INTEGER, INTENT(INOUT) :: RC ! Success/failure
1358 : !
1359 : ! !REVISION HISTORY:
1360 : ! 15 Feb 2015 - C. Keller - Initial version.
1361 : ! See https://github.com/geoschem/hemco for complete history
1362 : !EOP
1363 : !------------------------------------------------------------------------------
1364 : !BOC
1365 : !
1366 : ! !LOCAL VARIABLES:
1367 : !
1368 : ! Maximum number of nested brackets
1369 : INTEGER, PARAMETER :: MAXBRACKNEST = 10
1370 : INTEGER :: IDX, STRLEN, ExtNr
1371 : LOGICAL :: FOUND
1372 : LOGICAL :: UseBracket, UseThis
1373 : LOGICAL :: verb
1374 : LOGICAL :: REV
1375 : INTEGER, SAVE :: NEST = 0
1376 : INTEGER, SAVE :: SKIPLEVEL = 0
1377 : CHARACTER(LEN=255), SAVE :: AllBrackets(MAXBRACKNEST) = ''
1378 : CHARACTER(LEN=255) :: TmpBracket, CheckBracket, ThisBracket
1379 : CHARACTER(LEN=512) :: msg
1380 :
1381 : CHARACTER(LEN=255), PARAMETER :: LOC = 'BracketCheck (hco_config_mod.F90)'
1382 :
1383 : !======================================================================
1384 : ! BracketCheck begins here
1385 : !======================================================================
1386 :
1387 : ! Init
1388 0 : verb = HCO_IsVerb( HcoConfig%Err )
1389 :
1390 : ! Get name of this bracket
1391 0 : IF ( STAT == 5 .OR. STAT == 6 ) THEN
1392 0 : STRLEN = LEN(LINE)
1393 0 : IF ( STRLEN < 4 ) THEN
1394 0 : msg = 'Illegal bracket length: ' // TRIM(line)
1395 0 : CALL HCO_ERROR ( msg, RC, thisLoc=loc )
1396 0 : RETURN
1397 : ELSE
1398 0 : TmpBracket = TRIM(LINE(4:STRLEN))
1399 : ENDIF
1400 : ENDIF
1401 :
1402 : ! Open a bracket. Save out the bracket name in the list of all
1403 : ! opened brackets. This is primarily to ensure that every opening
1404 : ! brackets is properly closed. Only register it as skipping bracket
1405 : ! if needed.
1406 0 : IF ( STAT == 5 ) THEN
1407 :
1408 : ! Archive bracket name
1409 0 : NEST = NEST + 1
1410 0 : IF ( NEST > MAXBRACKNEST ) THEN
1411 0 : MSG = 'Too many nested brackets'
1412 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
1413 0 : RETURN
1414 : ENDIF
1415 0 : AllBrackets(NEST) = TmpBracket
1416 :
1417 : ! Check if this bracket content shall be skipped. Always skip
1418 : ! if this is a nested bracket in an already skipped bracket.
1419 0 : IF ( .NOT. SKIP ) THEN
1420 :
1421 : ! Check for 'inverse' bracket. These start with '.not.'
1422 0 : CheckBracket = TmpBracket
1423 0 : REV = .FALSE.
1424 0 : IF ( STRLEN > 5 ) THEN
1425 0 : IF ( TmpBracket(1:5) == '.not.' ) THEN
1426 0 : STRLEN = LEN(TmpBracket)
1427 0 : CheckBracket = TmpBracket(6:STRLEN)
1428 0 : REV = .TRUE.
1429 : ENDIF
1430 : ENDIF
1431 :
1432 : ! Check if the evaluation of CheckBracket returns true, i.e.
1433 : ! if any of the elements of CheckBracket is enabled. These
1434 : ! can be multiple settings separated by '.or.'.
1435 : ! By default, don't use the content of the bracket
1436 0 : UseBracket = .FALSE.
1437 :
1438 : ! Make sure variable ThisBracket is initialized. Needed in the
1439 : ! DO loop below
1440 0 : ThisBracket = ''
1441 :
1442 : ! Pack the following into a DO loop to check for multiple
1443 : ! flags separated by '.or.'.
1444 : DO
1445 :
1446 : ! Leave do loop if ThisBracket is equal to CheckBracket.
1447 : ! In this case, the entire bracket has already been
1448 : ! evaluated.
1449 0 : IF ( TRIM(CheckBracket) == TRIM(ThisBracket) ) EXIT
1450 :
1451 : ! Evaluate bracket for '.or.':
1452 0 : IDX = INDEX(TRIM(CheckBracket),'.or.')
1453 :
1454 : ! If '.or.' is a substring of the whole bracket, get
1455 : ! substring up to the first '.or.' and write it into variable
1456 : ! ThisBracket, which will be evaluated below. The tail
1457 : ! (everything after the first '.or.') is written into
1458 : ! CheckBracket.
1459 0 : IF ( IDX > 0 ) THEN
1460 0 : ThisBracket = CheckBracket(1:(IDX-1))
1461 0 : STRLEN = LEN(CheckBracket)
1462 0 : CheckBracket = CheckBracket((IDX+4):STRLEN)
1463 :
1464 : ! If there is no '.or.' in the bracket, simply evaluate the
1465 : ! whole bracket.
1466 : ELSE
1467 0 : ThisBracket = CheckBracket
1468 : ENDIF
1469 :
1470 : ! Check if this bracket has been registered as being used.
1471 : ! Scan all extensions, including the core one.
1472 : CALL GetExtOpt( HcoConfig, -999, TRIM(ThisBracket), &
1473 0 : OptValBool=UseThis, FOUND=FOUND, RC=RC )
1474 0 : IF ( RC /= HCO_SUCCESS ) THEN
1475 0 : msg = 'Error when checking '// TRIM( thisBracket ) // '!'
1476 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1477 0 : RETURN
1478 : ENDIF
1479 :
1480 : ! If bracket name was found in options, update the UseBracket
1481 : ! variable accordingly.
1482 0 : IF ( FOUND ) THEN
1483 0 : UseBracket = UseThis
1484 :
1485 : ! If bracket name was not found, check if this is an extension
1486 : ! name
1487 : ELSE
1488 0 : ExtNr = GetExtNr( HcoConfig%ExtList, TRIM(ThisBracket) )
1489 0 : IF ( ExtNr > 0 ) THEN
1490 0 : UseBracket = .TRUE.
1491 : ENDIF
1492 :
1493 : ENDIF
1494 :
1495 : ! As soon as UseBracket is true, we don't need to evaluate
1496 : ! further
1497 0 : IF ( UseBracket ) EXIT
1498 :
1499 : ENDDO
1500 :
1501 : ! We need to skip the content of this bracket?
1502 0 : SKIP = .NOT. UseBracket
1503 :
1504 : ! Eventually reverse the skip flag
1505 0 : IF ( REV ) THEN
1506 0 : SKIP = .NOT. SKIP
1507 : ENDIF
1508 :
1509 : ! If bracket is skipped, adjust skip level accordingly.
1510 : ! This is so that we know when it's time to flip back to
1511 : ! a bracket that is being used (if brackets are nested).
1512 0 : IF ( SKIP ) THEN
1513 0 : SKIPLEVEL = NEST
1514 : ENDIF
1515 : ENDIF
1516 :
1517 : ! Verbose mode
1518 0 : IF ( verb ) THEN
1519 0 : MSG = 'Opened shortcut bracket: '//TRIM(TmpBracket)
1520 0 : CALL HCO_MSG( HcoConfig%Err, msg )
1521 0 : WRITE(MSG,*) ' - Skip content of this bracket: ', SKIP
1522 0 : CALL HCO_MSG( HcoConfig%Err, msg )
1523 : ENDIF
1524 : ENDIF
1525 :
1526 : ! Close a bracket
1527 0 : IF ( STAT == 6 ) THEN
1528 :
1529 : ! This must be the latest opened bracket
1530 0 : IF ( TRIM(TmpBracket) /= TRIM(AllBrackets(NEST)) ) THEN
1531 : MSG = 'Closing bracket does not match opening bracket: '// &
1532 0 : TRIM(TmpBracket)//', expected: '//TRIM(AllBrackets(NEST))
1533 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
1534 0 : RETURN
1535 : ENDIF
1536 :
1537 : ! If that was the latest opened bracket that was disabled
1538 0 : IF ( SKIPLEVEL == NEST ) THEN
1539 0 : SKIP = .FALSE.
1540 : ENDIF
1541 :
1542 : ! Update nesting level
1543 0 : AllBrackets(NEST) = ''
1544 0 : NEST = NEST - 1
1545 :
1546 : ! Verbose mode
1547 0 : IF ( verb ) THEN
1548 0 : MSG = 'Closed shortcut bracket: '//TRIM(TmpBracket)
1549 0 : CALL HCO_MSG( HcoConfig%Err, msg )
1550 0 : WRITE(MSG,*) ' - Skip following lines: ', SKIP
1551 0 : CALL HCO_MSG( HcoConfig%Err, msg )
1552 : ENDIF
1553 : ENDIF
1554 :
1555 : ! Return w/ success
1556 0 : RC = HCO_SUCCESS
1557 :
1558 : END SUBROUTINE BracketCheck
1559 : !EOC
1560 : !------------------------------------------------------------------------------
1561 : ! Harmonized Emissions Component (HEMCO) !
1562 : !------------------------------------------------------------------------------
1563 : !BOP
1564 : !
1565 : ! !IROUTINE: AddShadowFields
1566 : !
1567 : ! !DESCRIPTION: Subroutine AddShadowFields adds a shadow container for every
1568 : ! additional category of a base emission field. These container contain the
1569 : ! same container as the 'mother' container, but an additional scale factor
1570 : ! of zero will be applied to them. This makes sure that no additional emissions
1571 : ! are created by the virtue of the shadow container.
1572 : !\\
1573 : !\\
1574 : ! !INTERFACE:
1575 : !
1576 0 : SUBROUTINE AddShadowFields( HcoConfig, Lct, Cats, nCat, RC )
1577 : !
1578 : ! !USES:
1579 : !
1580 : USE HCO_DATACONT_MOD, ONLY : CatMax, ZeroScalID
1581 : !
1582 : ! !INPUT PARAMETERS:
1583 : !
1584 : TYPE(ConfigObj), POINTER :: HcoConfig ! Config object
1585 : TYPE(ListCont), POINTER :: Lct ! List container of interest
1586 : INTEGER, INTENT(IN) :: Cats(CatMax) ! Category numbers
1587 : INTEGER, INTENT(IN) :: nCat ! number of categories
1588 : !
1589 : ! !INPUT/OUTPUT PARAMETERS:
1590 : !
1591 : INTEGER, INTENT(INOUT) :: RC ! Success/failure
1592 : !
1593 : ! !REVISION HISTORY:
1594 : ! 15 Feb 2015 - C. Keller - Initial version.
1595 : ! See https://github.com/geoschem/hemco for complete history
1596 : !EOP
1597 : !------------------------------------------------------------------------------
1598 : !BOC
1599 : !
1600 : ! !LOCAL VARIABLES:
1601 : !
1602 : LOGICAL :: verb
1603 : INTEGER :: I, N
1604 : TYPE(ListCont), POINTER :: Shd
1605 : CHARACTER(LEN=512) :: msg
1606 : CHARACTER(LEN=5) :: C5
1607 :
1608 : CHARACTER(LEN=255), PARAMETER :: LOC = 'AddShadowFields (hco_config_mod.F90)'
1609 :
1610 : !======================================================================
1611 : ! AddShadowFields begins here
1612 : !======================================================================
1613 :
1614 : ! Nothing to do if ncat is only 1
1615 0 : IF ( nCat <= 1 ) THEN
1616 0 : RC = HCO_SUCCESS
1617 0 : RETURN
1618 : ENDIF
1619 :
1620 : ! Init
1621 0 : verb = HCO_IsVerb( HcoConfig%Err )
1622 0 : Shd => NULL()
1623 :
1624 :
1625 : ! ! Get number of currently used scale factors
1626 : ! N = 0
1627 : ! DO I = 1, SclMax
1628 : ! IF ( Lct%Dct%Scal_cID(I) < 0 ) EXIT
1629 : ! N = N + 1
1630 : ! ENDDO
1631 : !
1632 : ! ! There has to be space for scale factor zero.
1633 : ! IF ( N >= SclMax ) THEN
1634 : ! MSG = 'Cannot add shadow scale factor (zeros) - : ' // &
1635 : ! 'All scale factors already used: ' // TRIM(Lct%Dct%cName)
1636 : ! CALL HCO_ERROR ( MSG, RC, THISLOC=LOC )
1637 : ! RETURN
1638 : ! ENDIF
1639 :
1640 : ! Get number of scale factor IDs. Will add one more scale factor of
1641 : ! zero to this list.
1642 0 : N = Lct%Dct%nScalID
1643 :
1644 : ! Create 'shadow' container for every additional category.
1645 : ! Add scale factor zero to it, so that emissions will all be zero.
1646 0 : DO I = 2, nCat
1647 :
1648 : ! Create new data container (ListCont object)
1649 0 : CALL ConfigList_AddCont ( Shd, HcoConfig%ConfigList )
1650 :
1651 : ! Character of category
1652 0 : Write(C5,'(I5.5)') Cats(I)
1653 :
1654 : ! Shadow variables. Append category name to name
1655 0 : Shd%Dct%DctType = Lct%Dct%DctType
1656 0 : Shd%Dct%cName = TRIM(Lct%Dct%cName) // '_Cat' // TRIM(C5)
1657 0 : Shd%Dct%SpcName = Lct%Dct%SpcName
1658 0 : Shd%Dct%Hier = Lct%Dct%Hier
1659 0 : Shd%Dct%ExtNr = Lct%Dct%ExtNr
1660 0 : Shd%Dct%Cat = Cats(I)
1661 :
1662 : ! Pass scale factors, add scale factor of zero to it
1663 0 : ALLOCATE ( Shd%Dct%Scal_cID(N+1) )
1664 0 : IF ( N > 0 ) THEN
1665 0 : Shd%Dct%Scal_cID(1:N) = Lct%Dct%Scal_cID(1:N)
1666 : ENDIF
1667 0 : Shd%Dct%Scal_cID(N+1) = ZeroScalID
1668 0 : Shd%Dct%nScalID = N + 1
1669 :
1670 : ! Connect to data from main container. Make sure the new container
1671 : ! is not identified as the home container (only points to the file
1672 : ! data container of another data container.
1673 0 : Shd%Dct%DtaHome = Shd%Dct%DtaHome - 1
1674 0 : Shd%Dct%Dta => Lct%Dct%Dta
1675 :
1676 : ! verbose mode
1677 0 : IF ( verb ) THEN
1678 0 : MSG = 'Created shadow base emission field: ' // TRIM(Shd%Dct%cName)
1679 0 : CALL HCO_MSG( HcoConfig%Err, msg )
1680 : ENDIF
1681 :
1682 : ! Cleanup
1683 0 : Shd => NULL()
1684 : ENDDO !I
1685 :
1686 : ! Add zero scale factor container
1687 0 : CALL AddZeroScal( HcoConfig, RC )
1688 0 : IF ( RC /= HCO_SUCCESS ) THEN
1689 0 : msg = 'Call to AddZeroScal could not add zero scale factor container!'
1690 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1691 0 : RETURN
1692 : ENDIF
1693 :
1694 : ! Return w/ success
1695 0 : RC = HCO_SUCCESS
1696 :
1697 : END SUBROUTINE AddShadowFields
1698 : !EOC
1699 : !------------------------------------------------------------------------------
1700 : ! Harmonized Emissions Component (HEMCO) !
1701 : !------------------------------------------------------------------------------
1702 : !BOP
1703 : !
1704 : ! !IROUTINE: AddZeroScal
1705 : !
1706 : ! !DESCRIPTION: Subroutine AddZeroScal adds a scale factor of zero to the
1707 : ! configuration container list. This scale factor is an internal scale factor
1708 : ! used in combination with the 'shadow' containers. Its scale factor ID is
1709 : ! defined in Hco\_DataCont\_Mod and must not be used otherwise, e.g. there
1710 : ! must not be another scale factor in the HEMCO configuration file with the
1711 : ! same scale factor ID. Otherwise, HEMCO will create an error lateron.
1712 : !\\
1713 : !\\
1714 : ! !INTERFACE:
1715 : !
1716 0 : SUBROUTINE AddZeroScal( HcoConfig, RC )
1717 : !
1718 : ! !USES:
1719 : !
1720 : USE HCO_DATACONT_MOD, ONLY : ZeroScalID
1721 : USE HCO_DATACONT_MOD, ONLY : ListCont_Find
1722 : USE HCO_FILEDATA_MOD, ONLY : FileData_Init
1723 : !
1724 : ! !INPUT PARAMETERS:
1725 : !
1726 : TYPE(ConfigObj), POINTER :: HcoConfig ! Config object
1727 : !
1728 : ! !INPUT/OUTPUT PARAMETERS:
1729 : !
1730 : INTEGER, INTENT(INOUT) :: RC ! Success/failure
1731 : !
1732 : ! !REVISION HISTORY:
1733 : ! 15 Feb 2015 - C. Keller - Initial version.
1734 : ! See https://github.com/geoschem/hemco for complete history
1735 : !EOP
1736 : !------------------------------------------------------------------------------
1737 : !BOC
1738 : !
1739 : ! !LOCAL VARIABLES:
1740 : !
1741 : TYPE(ListCont), POINTER :: Lct
1742 : TYPE(FileData), POINTER :: Dta
1743 : CHARACTER(LEN=255) :: MSG
1744 :
1745 : LOGICAL :: FOUND
1746 : CHARACTER(LEN=255), PARAMETER :: LOC = 'AddZeroScal (hco_config_mod.F90)'
1747 :
1748 : !======================================================================
1749 : ! AddZeroScal begins here
1750 : !======================================================================
1751 :
1752 : ! Initialize
1753 0 : Lct => NULL()
1754 0 : Dta => NULL()
1755 :
1756 : ! Check if this container already exists
1757 0 : CALL ListCont_Find ( HcoConfig%ConfigList, 'DUMMYSCALE_ZERO', FOUND )
1758 :
1759 : ! Only do on first call
1760 0 : IF ( .NOT. FOUND ) THEN
1761 :
1762 : ! Add new container to configuration list and set data container
1763 : ! attributes.
1764 0 : CALL ConfigList_AddCont ( Lct, HcoConfig%ConfigList )
1765 0 : Lct%Dct%DctType = HCO_DCTTYPE_SCAL
1766 0 : Lct%Dct%cName = 'DUMMYSCALE_ZERO'
1767 0 : Lct%Dct%ScalID = ZeroScalID
1768 0 : Lct%Dct%Oper = 1
1769 :
1770 : ! Create new file data container and fill it with values.
1771 0 : CALL FileData_Init ( Dta )
1772 0 : Dta%ncFile = '0.0'
1773 0 : Dta%ncPara = '-'
1774 0 : Dta%OrigUnit = 'unitless'
1775 0 : Dta%CycleFlag = HCO_CFLAG_CYCLE
1776 0 : Dta%SpaceDim = 2
1777 0 : Dta%ncRead = .FALSE.
1778 0 : Dta%IsLocTime = .TRUE.
1779 :
1780 : ! Connect data container
1781 0 : Lct%Dct%Dta => Dta
1782 :
1783 : ! verbose mode
1784 0 : IF ( HCO_IsVerb( HcoConfig%Err ) ) THEN
1785 0 : MSG = 'Created a fake scale factor with zeros'
1786 0 : CALL HCO_MSG(HcoConfig%Err,MSG)
1787 : MSG = 'This field will be used to artificially expand ' // &
1788 0 : 'over multiple emission categories'
1789 0 : CALL HCO_MSG(HcoConfig%Err,MSG)
1790 : ENDIF
1791 :
1792 : ! Cleanup
1793 0 : Lct => NULL()
1794 0 : Dta => NULL()
1795 : ENDIF
1796 :
1797 : ! Return w/ success
1798 0 : RC = HCO_SUCCESS
1799 :
1800 0 : END SUBROUTINE AddZeroScal
1801 : !EOC
1802 : !------------------------------------------------------------------------------
1803 : ! Harmonized Emissions Component (HEMCO) !
1804 : !------------------------------------------------------------------------------
1805 : !BOP
1806 : !
1807 : ! !IROUTINE: ExtSwitch2Buffer
1808 : !
1809 : ! !DESCRIPTION: Subroutine ExtSwitch2Buffer reads the HEMCO extension
1810 : ! switches and registers all enabled extensions.
1811 : !\\
1812 : !\\
1813 : ! !INTERFACE:
1814 : !
1815 0 : SUBROUTINE ExtSwitch2Buffer( HcoConfig, IU_HCO, EOF, RC )
1816 : !
1817 : ! !USES:
1818 : !
1819 : USE HCO_CHARPAK_Mod, ONLY : STRREPL, STRSPLIT, TRANLC
1820 : USE HCO_EXTLIST_MOD, ONLY : AddExt, AddExtOpt, HCO_GetOpt
1821 : USE HCO_EXTLIST_MOD, ONLY : GetExtNr, GetExtOpt
1822 : !
1823 : ! !INPUT PARAMETERS:
1824 : !
1825 : TYPE(ConfigObj), POINTER :: HcoConfig ! Config object
1826 : INTEGER, INTENT(IN) :: IU_HCO ! HEMCO configfile LUN
1827 : !
1828 : ! !INPUT/OUTPUT PARAMETERS:
1829 : !
1830 : LOGICAL, INTENT(INOUT) :: EOF ! End of file?
1831 : INTEGER, INTENT(INOUT) :: RC ! Success/failure
1832 : !
1833 : ! !REVISION HISTORY:
1834 : ! 17 Sep 2013 - C. Keller - Initialization (update)
1835 : ! See https://github.com/geoschem/hemco for complete history
1836 : !EOP
1837 : !------------------------------------------------------------------------------
1838 : !BOC
1839 : !
1840 : ! !LOCAL VARIABLES:
1841 : !
1842 : INTEGER :: I, N, Idx, ExtNr
1843 : LOGICAL :: Enabled, NewExt
1844 : LOGICAL :: DoEmis, Found, LTMP
1845 : CHARACTER(LEN=255) :: loc
1846 : CHARACTER(LEN=512) :: msg
1847 : CHARACTER(LEN=1023) :: OPTS
1848 : CHARACTER(LEN=2047) :: LINE
1849 : CHARACTER(LEN=2047) :: SUBSTR(255), SPECS(255)
1850 :
1851 : !======================================================================
1852 : ! ExtSwitch2Buffer begins here
1853 : !======================================================================
1854 :
1855 : ! Enter
1856 0 : RC = HCO_SUCCESS
1857 0 : msg = ''
1858 0 : loc = 'ExtSwitch2Buffer (hco_config_mod.F90)'
1859 0 : ExtNr = -1
1860 :
1861 : ! Initialize
1862 0 : DoEmis= .TRUE.
1863 0 : Found = .FALSE.
1864 :
1865 : ! Do until exit
1866 : DO
1867 :
1868 : ! Read line
1869 0 : CALL HCO_ReadLine ( IU_HCO, LINE, EOF, RC )
1870 0 : IF ( RC /= HCO_SUCCESS ) THEN
1871 0 : msg = 'Error in HEMCO_Config.rc @ line: ' // TRIM( line )
1872 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
1873 0 : RETURN
1874 : ENDIF
1875 :
1876 : ! Return if EOF
1877 0 : IF ( EOF ) RETURN
1878 :
1879 : ! Exit here if end of section encountered. Place this before the
1880 : ! test for comment to allow for "### END SECTION" tags (bmy, 4/21/15)
1881 0 : IF ( INDEX ( LINE, 'END SECTION' ) > 0 ) RETURN
1882 :
1883 : ! Jump to next line if line is commented out
1884 0 : IF ( LINE(1:1) == HCO_CMT ) CYCLE
1885 :
1886 : ! Check if these are options
1887 0 : IF ( INDEX(LINE,'-->') > 0 ) THEN
1888 : ! Only add if extension is defined!
1889 0 : IF ( ExtNr >= 0 .AND. Enabled ) THEN
1890 : CALL AddExtOpt( HcoConfig, TRIM(LINE), &
1891 0 : ExtNr, RC, IgnoreIfExist=.TRUE. )
1892 0 : IF ( RC /= HCO_SUCCESS ) THEN
1893 0 : msg = 'Error in HEMCO_Config.rc @ line: ' // TRIM( line )
1894 0 : CALL HCO_ERROR( msg, RC, thisLoc=loc )
1895 0 : RETURN
1896 : ENDIF
1897 : ENDIF
1898 :
1899 : ! Check if EMISSIONS setting is found. If so, overwrite DoEmis.
1900 0 : IF ( .not. Found ) THEN
1901 : CALL GetExtOpt( HcoConfig, -999, 'EMISSIONS', &
1902 0 : OptValBool=LTMP, FOUND=Found, RC=RC )
1903 0 : IF ( RC /= HCO_SUCCESS ) THEN
1904 0 : msg = 'Error encountered in "GetExtOpt( EMISSIONS )"!'
1905 0 : CALL HCO_Error( msg, RC, ThisLoc=loc )
1906 0 : RETURN
1907 : ENDIF
1908 0 : IF ( Found ) DoEmis = LTMP
1909 : ENDIF
1910 : CYCLE
1911 : ENDIF
1912 :
1913 : ! ---------------------------------------------------------------------
1914 : ! If the line is not an extension option, treat it as an extension
1915 : ! definition (e.g. 108 MEGAN : on ISOP/ACET/PRPE/C2H4/ALD2)
1916 : ! ---------------------------------------------------------------------
1917 :
1918 : ! Split character string
1919 0 : CALL STRREPL ( LINE, HCO_TAB, HCO_TAB )
1920 0 : CALL STRSPLIT( LINE, HCO_SPC, SUBSTR, N )
1921 :
1922 : ! Jump to next line if this line is empty
1923 0 : IF ( N <= 1 ) CYCLE
1924 :
1925 : ! Check if extension already exists, e.g. if this is a nested HEMCO configuration
1926 : ! file and the same extension has already been defined. In that case, use the
1927 : ! on/off toggle that has already been defined.
1928 0 : ExtNr = GetExtNr( HcoConfig%ExtList, TRIM(SUBSTR(2)) )
1929 :
1930 : ! Three possibilities:
1931 : ! - ExtNr is -999 --> extension does not yet exist
1932 : ! - ExtNr is a positive number --> extension exists and is enabled
1933 : ! - ExtNr is -1 --> extension exists and is disabled
1934 0 : IF ( ExtNr == -999 ) THEN
1935 : NewExt = .TRUE.
1936 0 : ELSEIF ( ExtNr >= 0 ) THEN
1937 0 : NewExt = .FALSE.
1938 0 : Enabled = .TRUE.
1939 : ELSE
1940 0 : NewExt = .FALSE.
1941 0 : Enabled = .FALSE.
1942 : ENDIF
1943 :
1944 : ! The following needs to be done for new extensions only
1945 : IF ( NewExt ) THEN
1946 :
1947 : ! Check for on-switch. This is either the
1948 : ! 3rd or the 4th substring, depending on the
1949 : ! location of the colon sign!
1950 0 : IF ( TRIM(SUBSTR(3)) /= ':' ) THEN
1951 : idx = 3
1952 : ELSE
1953 : idx = 4
1954 : ENDIF
1955 0 : CALL TRANLC( TRIM(SUBSTR(idx)) )
1956 0 : IF ( TRIM(SUBSTR(idx)) == 'on' ) THEN
1957 0 : Enabled = .TRUE.
1958 : ELSE
1959 0 : Enabled = .FALSE.
1960 : ENDIF
1961 :
1962 : ! Disable extension if EMISSIONS logical is false
1963 0 : IF ( .not. DoEmis ) THEN
1964 0 : Enabled = .FALSE.
1965 : ENDIF
1966 :
1967 : ! Register extension name, number and species
1968 : ! idx is the position of the species names
1969 0 : idx = idx+1
1970 0 : READ( SUBSTR(1), * ) ExtNr
1971 : CALL AddExt ( HcoConfig, TRIM(SUBSTR(2)), &
1972 0 : ExtNr, Enabled, SUBSTR(idx), RC )
1973 0 : IF ( RC /= HCO_SUCCESS ) THEN
1974 0 : CALL HCO_ERROR( 'ERROR 32', RC, THISLOC=LOC )
1975 0 : RETURN
1976 : ENDIF
1977 :
1978 : ! Register species (specNames)
1979 0 : IF ( Enabled ) THEN
1980 :
1981 : CALL STRSPLIT( SUBSTR(idx), &
1982 0 : HCO_GetOpt(HcoConfig%ExtList,'Separator'), SPECS, N )
1983 0 : IF ( N < 1 ) THEN
1984 0 : CALL HCO_ERROR ( 'No species defined', RC, THISLOC=LOC )
1985 0 : RETURN
1986 : ENDIF
1987 0 : DO I = 1, N
1988 0 : CALL SpecName_Register ( HcoConfig, SPECS(I), RC )
1989 0 : IF ( RC /= HCO_SUCCESS ) THEN
1990 0 : msg = 'Error encountered in "SpecName_Register"!'
1991 0 : CALL HCO_ERROR( msg, RC, thisLoc=LOC )
1992 0 : RETURN
1993 : ENDIF
1994 : ENDDO
1995 : ENDIF
1996 : ENDIF ! NextExt
1997 : ENDDO
1998 :
1999 : ! Leave w/ success
2000 : RC = HCO_SUCCESS
2001 :
2002 : END SUBROUTINE ExtSwitch2Buffer
2003 : !EOC
2004 : !------------------------------------------------------------------------------
2005 : ! Harmonized Emissions Component (HEMCO) !
2006 : !------------------------------------------------------------------------------
2007 : !BOP
2008 : !
2009 : ! !ROUTINE: ReadSettings
2010 : !
2011 : ! !DESCRIPTION: Subroutine ReadSettings reads the HEMCO settings,
2012 : ! stores them as HEMCO core extension options, and also evaluates
2013 : ! some of the values (e.g. to initialize the HEMCO error module).
2014 : !\\
2015 : !\\
2016 : ! !INTERFACE:
2017 : !
2018 0 : SUBROUTINE ReadSettings( HcoConfig, IU_HCO, EOF, RC )
2019 : !
2020 : ! !USES:
2021 : !
2022 : USE HCO_EXTLIST_MOD, ONLY : AddExtOpt, GetExtOpt, CoreNr
2023 : USE HCO_EXTLIST_MOD, ONLY : HCO_SetDefaultToken
2024 : USE HCO_EXTLIST_MOD, ONLY : HCO_GetOpt
2025 : USE HCO_CHARPAK_MOD, ONLY : STRREPL, STRSPLIT, TRANLC
2026 : !
2027 : ! !INPUT PARAMETERS:
2028 : !
2029 : TYPE(ConfigObj), POINTER :: HcoConfig ! Config obj
2030 : INTEGER, INTENT(IN) :: IU_HCO ! HEMCO configfile LUN
2031 : !
2032 : ! !INPUT/OUTPUT PARAMETERS:
2033 : !
2034 : LOGICAL, INTENT(INOUT) :: EOF ! End of file?
2035 : INTEGER, INTENT(INOUT) :: RC ! Success/failure
2036 : !
2037 : ! !REVISION HISTORY:
2038 : ! 17 Sep 2013 - C. Keller - Initialization (update)
2039 : ! See https://github.com/geoschem/hemco for complete history
2040 : !EOP
2041 : !------------------------------------------------------------------------------
2042 : !BOC
2043 : !
2044 : ! !LOCAL VARIABLES:
2045 : !
2046 : ! Scalars
2047 : LOGICAL :: doVerbose, doVerboseOnRoot, found
2048 : INTEGER :: I, N, POS
2049 :
2050 : ! Strings
2051 : CHARACTER(LEN=10) :: onCores
2052 : CHARACTER(LEN=15) :: verboseMsg
2053 : CHARACTER(LEN=255) :: line
2054 : CHARACTER(LEN=255) :: loc
2055 : CHARACTER(LEN=255) :: LogFile
2056 : CHARACTER(LEN=255) :: DiagnPrefix
2057 : CHARACTER(LEN=255) :: MetField
2058 : CHARACTER(LEN=255) :: GridRes
2059 : CHARACTER(LEN=512) :: msg
2060 :
2061 : !======================================================================
2062 : ! ReadSettings begins here
2063 : !======================================================================
2064 :
2065 : ! Enter
2066 0 : Loc = 'ReadSettings (hco_config_mod.F90)'
2067 :
2068 :
2069 : !-----------------------------------------------------------------------
2070 : ! Read settings and add them as options to core extensions
2071 : !-----------------------------------------------------------------------
2072 :
2073 : ! Do until exit
2074 : DO
2075 :
2076 : ! Read line
2077 0 : CALL HCO_ReadLine ( IU_HCO, LINE, EOF, RC )
2078 0 : IF ( RC /= HCO_SUCCESS ) THEN
2079 0 : msg = 'Error in HEMCO_Config.rc @ line: ' // TRIM( Line )
2080 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2081 0 : RETURN
2082 : ENDIF
2083 :
2084 : ! Return if EOF
2085 0 : IF ( EOF ) EXIT
2086 :
2087 : ! Exit here if end of section encountered
2088 0 : IF ( INDEX ( LINE, 'END SECTION' ) > 0 ) EXIT
2089 :
2090 : ! Jump to next line if line is commented out
2091 0 : IF ( LINE(1:1) == HCO_CMT ) CYCLE
2092 :
2093 : ! Ignore empty lines
2094 0 : IF ( TRIM(LINE) == '' ) CYCLE
2095 :
2096 : ! Add this option to HEMCO core
2097 : CALL AddExtOpt ( HcoConfig, TRIM(LINE), &
2098 0 : CoreNr, RC, IgnoreIfExist=.TRUE. )
2099 0 : IF ( RC /= HCO_SUCCESS ) THEN
2100 0 : msg = 'Error in HEMCO_Config.rc @ line: ' // TRIM( Line )
2101 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2102 0 : RETURN
2103 : ENDIF
2104 :
2105 : ENDDO
2106 :
2107 : #ifndef MODEL_GEOS
2108 : #ifndef MODEL_WRF
2109 : #ifndef MODEL_CESM
2110 : #ifndef ESMF_
2111 : !=======================================================================
2112 : ! Look for met field and grid resolution. When running the HEMCO
2113 : ! standalone these will need to be read from the configuration file.
2114 : ! Otherwise, HEMCO will inherit the met field and grid resolution
2115 : ! of the parent model (GC-Classic, GCHP, etc.)
2116 : !
2117 : ! NOTE: Only do this check if not using GEOS-Chem in an external ESM!
2118 : !=======================================================================
2119 :
2120 : ! Look for met field
2121 : CALL GetExtOpt( HcoConfig, CoreNr, 'MET', &
2122 : OptValChar=MetField, FOUND=FOUND, RC=RC )
2123 : IF ( FOUND ) THEN
2124 : HcoConfig%MetField = TRIM( MetField )
2125 : ENDIF
2126 :
2127 : ! Look for grid resolution
2128 : ! Make sure resolution string is in the proper FlexGrid format
2129 : CALL GetExtOpt( HcoConfig, CoreNr, 'RES', &
2130 : OptValChar=GridRes, FOUND=FOUND, RC=RC )
2131 : IF ( FOUND ) THEN
2132 : SELECT CASE( TRIM( GridRes ) )
2133 : CASE( '4x5' )
2134 : GridRes = '4.0x5.0'
2135 : CASE( '2x25', '2x2.5' )
2136 : GridRes = '2.0x2.5'
2137 : CASE( '05x0625', '0.5x0.625' )
2138 : GridRes = '0.5x0.625'
2139 : CASE( '025x03125', '0.25x0.3125' )
2140 : GridRes = '0.25x0.3125'
2141 : CASE DEFAULT
2142 : Msg = 'Improperly formatted grid resolution: ' // TRIM( GridRes )
2143 : CALL HCO_Error( Msg, RC, Loc )
2144 : RETURN
2145 : END SELECT
2146 : HcoConfig%GridRes = TRIM( GridRes )
2147 : ENDIF
2148 : #endif
2149 : #endif
2150 : #endif
2151 : #endif
2152 :
2153 : !-----------------------------------------------------------------------
2154 : ! Initialize error object if needed.
2155 : ! Extract values to initialize error module and set some further
2156 : ! HEMCO variables. Only the first time the settings are read (settings
2157 : ! can be read multiple times if nested HEMCO configuration files are
2158 : ! used)
2159 : !-----------------------------------------------------------------------
2160 0 : IF ( .NOT. ASSOCIATED(HcoConfig%Err) ) THEN
2161 :
2162 : ! Initialize
2163 0 : doVerbose = .FALSE.
2164 0 : doVerboseOnRoot = .FALSE.
2165 0 : onCores = ''
2166 :
2167 : ! First look for Verbose
2168 : CALL GetExtOpt( HcoConfig, CoreNr, 'Verbose', &
2169 0 : OptValBool=doVerbose, found=found, RC=RC )
2170 0 : IF ( RC /= HCO_SUCCESS ) THEN
2171 0 : msg = 'Error looking for "Verbose" in HEMCO_Config.rc!'
2172 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2173 0 : RETURN
2174 : ENDIF
2175 :
2176 : ! First look for Verbose (logical). This is now the default
2177 : ! inthe HEMCO_Config.rc file for HEMCO 3.7.0 and later.
2178 : CALL GetExtOpt( HcoConfig, CoreNr, 'VerboseOnCores', &
2179 0 : OptValChar=onCores, found=found, RC=RC )
2180 0 : IF ( RC /= HCO_SUCCESS ) THEN
2181 0 : msg = 'Error looking for "VerboseOnCores in HEMCO_Config.rc!'
2182 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2183 0 : RETURN
2184 : ENDIF
2185 :
2186 : ! Set a flag if Verbose output is to be done on the root core only
2187 : ! (if false, it will be done on all cores)
2188 0 : CALL TranLC( onCores )
2189 0 : doVerboseOnRoot = ( TRIM( onCores ) == "root" )
2190 :
2191 : ! Print status message
2192 0 : IF ( doVerbose ) THEN
2193 0 : msg = NEW_LINE( 'A' ) // 'HEMCO verbose output is ON '
2194 0 : IF ( doVerboseOnRoot ) THEN
2195 0 : msg = TRIM( msg ) // ' (root core only)'
2196 : ELSE
2197 0 : msg = TRIM( msg ) // ' (all cores)'
2198 : ENDIF
2199 : ELSE
2200 0 : msg = NEW_LINE( 'A' ) // 'HEMCO verbose output is OFF'
2201 : ENDIF
2202 0 : IF ( HcoConfig%amIRoot ) CALL HCO_Msg( msg, verb=.TRUE. )
2203 :
2204 : ! Logfile to write into
2205 : CALL GetExtOpt( HcoConfig, CoreNr, 'Logfile', &
2206 0 : OptValChar=Logfile, FOUND=FOUND, RC=RC )
2207 0 : IF ( RC /= HCO_SUCCESS ) THEN
2208 0 : msg = 'Error looking for "Logfile" in HEMCO_Config.rc!'
2209 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2210 0 : RETURN
2211 : ENDIF
2212 0 : IF ( .NOT. FOUND ) THEN
2213 0 : LogFile = 'HEMCO.log'
2214 0 : WRITE(*,*) 'Setting `Logfile` not found in HEMCO logfile - use `HEMCO.log`'
2215 : ENDIF
2216 :
2217 : ! Initialize (standard) HEMCO tokens
2218 0 : CALL HCO_SetDefaultToken( HcoConfig, RC )
2219 0 : IF ( RC /= HCO_SUCCESS ) THEN
2220 0 : msg = 'Error encountered in routine "HCO_SetDefaultToken"!'
2221 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2222 0 : RETURN
2223 : ENDIF
2224 :
2225 : ! If LogFile is equal to wildcard character, set LogFile to asterik
2226 : ! character. This will ensure that all output is written to standard
2227 : ! output!
2228 0 : IF ( TRIM(LogFile) == HCO_GetOpt(HcoConfig%ExtList,'Wildcard') ) &
2229 0 : LogFile = '*'
2230 :
2231 : ! We should now have everything to define the HEMCO error settings
2232 : CALL HCO_ERROR_SET( HcoConfig%amIRoot, HcoConfig%Err, LogFile, &
2233 0 : doVerbose, doVerboseOnRoot, RC )
2234 0 : IF ( RC /= HCO_SUCCESS ) THEN
2235 0 : msg = 'Error encountered in routine "Hco_Error_Set"!'
2236 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2237 0 : RETURN
2238 : ENDIF
2239 :
2240 : ENDIF
2241 :
2242 : ! Leave w/ success
2243 0 : RC = HCO_SUCCESS
2244 :
2245 : END SUBROUTINE ReadSettings
2246 : !EOC
2247 : !------------------------------------------------------------------------------
2248 : ! Harmonized Emissions Component (HEMCO) !
2249 : !------------------------------------------------------------------------------
2250 : !BOP
2251 : !
2252 : ! !IROUTINE: RegisterPrepare
2253 : !
2254 : ! !DESCRIPTION: Subroutine RegisterPrepare extracts the spatial
2255 : ! coverages of all mask fields as well as the HEMCO species IDs of
2256 : ! all base emissions.
2257 : !\\
2258 : !\\
2259 : ! The species IDs are determined by matching the species name read
2260 : ! from the configuration file (in ConfigList) and the species names
2261 : ! defined in the HEMCO state object HcoState.
2262 : !\\
2263 : !\\
2264 : ! Mask coverages are defined based upon the passed horizontal grid
2265 : ! extensions on this CPU (xrng and yrng).
2266 : !\\
2267 : !\\
2268 : ! !INTERFACE:
2269 : !
2270 0 : SUBROUTINE RegisterPrepare( HcoState, RC )
2271 : !
2272 : ! !USES:
2273 : !
2274 : USE HCO_EXTLIST_MOD, ONLY : ExtNrInUse
2275 : USE HCO_STATE_Mod, ONLY : HCO_GetHcoID
2276 : USE HCO_DATACONT_MOD, ONLY : ListCont_NextCont
2277 : !
2278 : ! !INPUT PARAMETERS:
2279 : !
2280 : TYPE(HCO_State), POINTER :: HcoState ! HEMCO state obj.
2281 : !
2282 : ! !OUTPUT PARAMETERS:
2283 : !
2284 : INTEGER, INTENT(INOUT) :: RC
2285 : !
2286 : ! !REVISION HISTORY:
2287 : ! 18 Sep 2013 - C. Keller - Initial version (update)
2288 : ! See https://github.com/geoschem/hemco for complete history
2289 : !EOP
2290 : !------------------------------------------------------------------------------
2291 : !BOC
2292 : !
2293 : ! !LOCAL VARIABLES:
2294 : !
2295 : TYPE(ListCont), POINTER :: Lct
2296 : INTEGER :: ThisCover, ThisHcoID, FLAG
2297 : INTEGER :: lon1, lon2, lat1, lat2
2298 : INTEGER :: cpux1, cpux2, cpuy1, cpuy2
2299 : CHARACTER(LEN=255) :: loc
2300 : CHARACTER(LEN=512) :: msg
2301 :
2302 : !=================================================================
2303 : ! RegisterPrepare begins here!
2304 : !=================================================================
2305 0 : loc = 'RegisterPrepare (HCO_CONFIG_MOD.F90)'
2306 :
2307 : ! Enter
2308 0 : CALL HCO_ENTER ( HcoState%Config%Err, LOC, RC )
2309 0 : IF ( RC /= HCO_SUCCESS ) THEN
2310 0 : msg = 'Error encountered in routine "HCO_Enter"!'
2311 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2312 0 : RETURN
2313 : ENDIF
2314 :
2315 : ! Initialize
2316 0 : Lct => NULL()
2317 :
2318 : ! Grid boundaries on this CPU. Will be needed to calculate
2319 : ! coverages.
2320 : ! NOTE: Use midpoints here because only those become defined in
2321 : ! the ESMF environment (xedge and yedge are not used anywhere
2322 : ! else in ESMF!).
2323 0 : cpux1 = FLOOR(MINVAL(HcoState%Grid%XMID%Val))
2324 0 : cpux2 = FLOOR(MAXVAL(HcoState%Grid%XMID%Val))
2325 0 : cpuy1 = CEILING(MINVAL(HcoState%Grid%YMID%Val))
2326 0 : cpuy2 = CEILING(MAXVAL(HcoState%Grid%YMID%Val))
2327 :
2328 : ! Make sure values are within -180.0 to 180.0
2329 0 : IF ( cpux1 >= 180 ) cpux1 = cpux1 - 360
2330 0 : IF ( cpux2 >= 180 ) cpux2 = cpux2 - 360
2331 :
2332 : ! verbose
2333 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2334 0 : WRITE(MSG,*) 'Start to prepare fields for registering!'
2335 0 : CALL HCO_MSG(HcoState%Config%Err,MSG)
2336 0 : WRITE(MSG,*) 'This CPU x-range: ', cpux1, cpux2
2337 0 : CALL HCO_MSG(HcoState%Config%Err,MSG)
2338 0 : WRITE(MSG,*) 'This CPU y-range: ', cpuy1, cpuy2
2339 0 : CALL HCO_MSG(HcoState%Config%Err,MSG)
2340 : ENDIF
2341 :
2342 : ! Get next (first) line of ConfigList
2343 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2344 :
2345 : ! Loop over all lines
2346 0 : DO WHILE ( FLAG == HCO_SUCCESS )
2347 :
2348 : ! Check if data container defined
2349 0 : IF ( .NOT. ASSOCIATED(Lct%Dct) ) THEN
2350 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2351 0 : CYCLE
2352 : ENDIF
2353 :
2354 : ! verbose
2355 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2356 0 : WRITE(MSG,*) 'Prepare ', TRIM(Lct%Dct%cName)
2357 0 : CALL HCO_MSG(HcoState%Config%Err,MSG)
2358 : ENDIF
2359 :
2360 : ! For base fields or data fields used in one of the HEMCO
2361 : ! extensions:
2362 0 : IF ( Lct%Dct%DctType == HCO_DCTTYPE_BASE ) THEN
2363 :
2364 : ! Only do for entries that will be used!
2365 0 : IF ( ExtNrInUse( HcoState%Config%ExtList, Lct%Dct%ExtNr ) ) THEN
2366 :
2367 : ! Extract HEMCO species ID. This will return -1 for
2368 : ! undefined species and 0 for wildcard character.
2369 0 : ThisHcoID = HCO_GetHcoID( Lct%Dct%SpcName, HcoState )
2370 0 : Lct%Dct%HcoID = ThisHcoID
2371 :
2372 : ! verbose
2373 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2374 0 : WRITE(MSG,*) 'Assigned HEMCO species ID: ', Lct%Dct%HcoID
2375 0 : CALL HCO_MSG(HcoState%Config%Err,MSG)
2376 : ENDIF
2377 :
2378 : ! Else: assign default value. These containers will be
2379 : ! removed in the next step!
2380 : ELSE
2381 0 : Lct%Dct%HcoID = -999
2382 : ENDIF
2383 :
2384 : ! Calculate coverage for masks
2385 0 : ELSE IF ( Lct%Dct%DctType == HCO_DCTTYPE_MASK .AND. &
2386 : Lct%Dct%Dta%Cover == -999 ) THEN
2387 :
2388 : ! The mask coverage calculation (which only has three values)
2389 : ! is used to simplify I/O and CPU operations in code below.
2390 : !
2391 : ! However, there are two distinct bugs related to this:
2392 : !
2393 : ! (1)
2394 : ! There appear to be some issues with full masks coverages
2395 : ! when working in an MPI environment. Specifically, masks
2396 : ! can be seen as fully covering a given CPU even though in
2397 : ! reality it may only cover parts of it. Thus, in ESMF mode
2398 : ! always set coverage to zero or partial (ckeller, 3/17/16).
2399 : !
2400 : ! This appears to be related to masking for two inventories
2401 : ! with overlapping temporal coverage. For example, if inventory
2402 : ! A is 2013-2015, and B is 2010-2018 with higher hierarchy,
2403 : ! but not the same mask (maybe A covers regions that B does not).
2404 : ! If both masks are set to ThisCover == 1 (full coverage), because
2405 : ! a certain CPU might be overlapped by lon1/lat1/lon2/lat2 even
2406 : ! though the actual netCDF shape of the mask is different,
2407 : ! then a simulation running 2013-2015 will see inventory B on that CPU
2408 : ! decide it has full coverage (only through lon1/..), and skip
2409 : ! inventory A altogether, resulting in missing emissions.
2410 : ! This behavior is in the line
2411 : ! IF ( (tmpLct%Dct%Hier > Hier) .AND. (tmpCov==1) ) THEN below.
2412 : !
2413 : ! (2)
2414 : ! Another artifact caused by MPI environments:
2415 : ! where lon1/lat1/... is set too small, resulting in certain CPUs not
2416 : ! having overlap (defined by cpux/y) with lon1/lat1/..., and thus
2417 : ! skipping the base inventory as a bug. This behavior is in the line
2418 : ! IF ( (mskLct%Dct%DctType == HCO_DCTTYPE_MASK ) .AND. &
2419 : ! (mskLct%Dct%Dta%Cover == 0 ) ) THEN
2420 : !
2421 : ! Because the code only distinguishes between full/partial and zero
2422 : ! coverage, and skips reading the base field if coverage is zero,
2423 : ! this may cause issues with MPI environments in WRF and CESM where
2424 : ! the mask lon1/lat1/lon2/lat2 boundaries are set too small compared
2425 : ! to the mask, and result in the base field being skipped over small
2426 : ! CPU decompositions where it should not have been. The above fix
2427 : ! does not fix the issue where ThisCover == 0, which is the root
2428 : ! cause in WRF and CESM. Thus, always set to partial coverage
2429 : ! (hplin, 8/19/22)
2430 : !
2431 : ! Thus, the following fix needs to be applied for ESMF environments,
2432 : ! skipping a lot of the calculations below.
2433 : #if defined ( ESMF_ ) || defined( MODEL_WRF ) || defined( MODEL_CESM )
2434 0 : ThisCover = -1
2435 : #else
2436 : ! Get mask edges
2437 : lon1 = Lct%Dct%Dta%ncYrs(1)
2438 : lat1 = Lct%Dct%Dta%ncYrs(2)
2439 : lon2 = Lct%Dct%Dta%ncMts(1)
2440 : lat2 = Lct%Dct%Dta%ncMts(2)
2441 :
2442 : ! If ncFile is passed as the lon1/lat1/lon2/lat2 instead
2443 : ! of netCDF file name, then set ncRead to false, so that
2444 : ! HEMCO won't try to read a file from disk. Also set the
2445 : ! IsLocTime flag to TRUE. This should fix Github issue
2446 : ! https://github.com/geoschem/HEMCO/issues/153.
2447 : ! -- Bob Yantosca (12 Jul 2022)
2448 : !
2449 : ! Also allow for the .$NC replaceable token, see:
2450 : ! https://github.com/geoschem/HEMCO/issues/204
2451 : ! -- Melissa Sulprizio & Bob Yantosca (11 Apr 2023)
2452 : IF ( INDEX( Lct%Dct%Dta%ncFile, ".nc" ) == 0 ) THEN
2453 : IF ( INDEX( Lct%Dct%Dta%ncFile, ".$NC" ) == 0 ) THEN
2454 : Lct%Dct%Dta%ncRead = .FALSE.
2455 : Lct%Dct%Dta%IsLocTime = .TRUE.
2456 : ENDIF
2457 : ENDIF
2458 :
2459 : ThisCover = CALC_COVERAGE( lon1, lon2, lat1, lat2, &
2460 : cpux1, cpux2, cpuy1, cpuy2 )
2461 : #endif
2462 :
2463 : ! Update container information
2464 0 : Lct%Dct%Dta%Cover = ThisCover
2465 0 : Lct%Dct%Dta%ncYrs(:) = -999
2466 0 : Lct%Dct%Dta%ncMts(:) = -999
2467 :
2468 0 : IF ( HCO_IsVerb(HcoSTate%Config%Err ) ) THEN
2469 0 : WRITE(MSG,*) 'Coverage: ', Lct%Dct%Dta%Cover
2470 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
2471 : ENDIF
2472 : ENDIF
2473 :
2474 : ! Advance to next line
2475 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2476 : ENDDO
2477 :
2478 : ! Cleanup
2479 0 : Lct => NULL()
2480 :
2481 : ! Return w/ success
2482 0 : CALL HCO_LEAVE ( HcoState%Config%Err, RC )
2483 :
2484 : END SUBROUTINE RegisterPrepare
2485 : !EOC
2486 : !------------------------------------------------------------------------------
2487 : ! Harmonized Emissions Component (HEMCO) !
2488 : !------------------------------------------------------------------------------
2489 : !BOP
2490 : !
2491 : ! !IROUTINE: Register_Base
2492 : !
2493 : ! !DESCRIPTION: Subroutine Register\_Base registers all base emission
2494 : ! data and writes out all associated scale factor IDs.
2495 : !\\
2496 : !\\
2497 : ! !INTERFACE:
2498 : !
2499 0 : SUBROUTINE Register_Base( HcoState, RC )
2500 : !
2501 : ! !USES:
2502 : !
2503 : USE HCO_READLIST_Mod, ONLY : ReadList_Set
2504 : USE HCO_DATACONT_Mod, ONLY : DataCont_Cleanup
2505 : USE HCO_DATACONT_MOD, ONLY : ListCont_NextCont
2506 : !
2507 : ! !INPUT/OUTPUT PARAMETERS:
2508 : !
2509 : TYPE(HCO_State), POINTER :: HcoState ! HEMCO state object
2510 : !
2511 : ! !INPUT/OUTPUT PARAMETERS:
2512 : !
2513 : INTEGER, INTENT(INOUT) :: RC ! Success or failure
2514 : !
2515 : ! !REVISION HISTORY:
2516 : ! 18 Jun 2013 - C. Keller: Initialization
2517 : ! See https://github.com/geoschem/hemco for complete history
2518 : !EOP
2519 : !------------------------------------------------------------------------------
2520 : !BOC
2521 : !
2522 : ! !LOCAL VARIABLES:
2523 : !
2524 : ! Pointers
2525 : TYPE(ListCont), POINTER :: Lct
2526 :
2527 : ! Scalars
2528 : INTEGER :: N, cID, HcoID
2529 : INTEGER :: targetID, FLAG
2530 : LOGICAL :: Ignore, Add
2531 : CHARACTER(LEN=255) :: LOC
2532 : CHARACTER(LEN=512) :: msg
2533 :
2534 : !======================================================================
2535 : ! Register_Base begins here
2536 : !======================================================================
2537 0 : loc = 'Register_Base (HCO_CONFIG_MOD.F90)'
2538 :
2539 : ! Enter
2540 0 : CALL HCO_ENTER ( HcoState%Config%Err, loc, RC )
2541 0 : IF ( RC /= HCO_SUCCESS ) THEN
2542 0 : msg = 'Error encountered in routine "HCO_Enter"!'
2543 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2544 0 : RETURN
2545 : ENDIF
2546 :
2547 : ! Initialize
2548 0 : Lct => NULL()
2549 :
2550 : ! Point to next (first) line in ConfigList
2551 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2552 :
2553 : ! Loop over temporary arrays
2554 0 : DO WHILE ( FLAG == HCO_SUCCESS )
2555 :
2556 : ! Reset ignore flag
2557 0 : Ignore = .FALSE.
2558 :
2559 : ! Skip entry if data container not defined
2560 0 : IF ( .NOT. ASSOCIATED(Lct%Dct) ) THEN
2561 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2562 0 : CYCLE
2563 : ENDIF
2564 :
2565 : ! Skip entry if it's not a base field
2566 0 : IF ( (Lct%Dct%DctType /= HCO_DCTTYPE_BASE) ) THEN
2567 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2568 0 : CYCLE
2569 : ENDIF
2570 :
2571 : ! If this base field is not used (either because it belongs to
2572 : ! an extension that is not enabled or because its HEMCO or
2573 : ! model species ID is undefined), we don't need this container
2574 : ! any more. Hence remove it.
2575 : ! Note: Routine RegisterPrepare assigns negative HcoID's to all
2576 : ! base fields with invalid ExtNr's, so it is ok to check only
2577 : ! for HcoID here. If data is used in one of the HEMCO extensions
2578 : ! and has a species flag of '*' (= always read), its species ID
2579 : ! becomes set to 0 in RegisterPrepare.
2580 0 : HcoID = Lct%Dct%HcoID
2581 0 : IF ( HcoID < 0 ) THEN
2582 : Ignore = .TRUE.
2583 0 : ELSE IF ( HcoID > 0 ) THEN
2584 0 : IF ( HcoState%Spc(HcoID)%ModID < 0 ) Ignore = .TRUE.
2585 : ENDIF
2586 :
2587 : IF ( Ignore ) THEN
2588 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2589 : WRITE(MSG,*) &
2590 0 : 'Register_Base: Ignore (and remove) base field ', &
2591 0 : TRIM(Lct%Dct%cName)
2592 0 : CALL HCO_MSG(HcoState%Config%Err,MSG,SEP1='-')
2593 : ENDIF
2594 :
2595 : ! Remove data container from list.
2596 0 : CALL DataCont_Cleanup ( Lct%Dct )
2597 0 : Lct%Dct => NULL()
2598 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2599 0 : CYCLE
2600 : ENDIF
2601 :
2602 : ! Verbose mode
2603 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2604 0 : WRITE(MSG,*) 'Register_Base: Checking ', TRIM(Lct%Dct%cName)
2605 0 : CALL HCO_MSG(HcoState%Config%Err,MSG,SEP1='-')
2606 : ENDIF
2607 :
2608 : ! -------------------------------------------------------------
2609 : ! Extract vector of scale factor container IDs to be applied
2610 : ! to this base field (vector Scal_cID). For now, this container
2611 : ! contains the scale factor IDs, hence need to convert to
2612 : ! container IDs. Beforehand, add scale factor IDs to internal
2613 : ! list of used scale factors (UnqScalIDs).
2614 0 : CALL ScalID_Register ( Lct%Dct, HcoState%Config, RC )
2615 0 : IF ( RC /= HCO_SUCCESS ) THEN
2616 0 : PRINT *,'Error in ScaleID_Register called from Register_Base'
2617 0 : RETURN
2618 : ENDIF
2619 :
2620 : ! Get target ID of this container. The targetID corresponds
2621 : ! to the container ID cID into which emissions data of the
2622 : ! current container (Lct) will be added to. Typically,
2623 : ! targetID is equal to cID, i.e. a container holds the data
2624 : ! array corresponding to its source data information. In
2625 : ! cases where multiple base emissions have same properties,
2626 : ! however, we can merge these fields prior to emission
2627 : ! calculation to save some calculation operations.
2628 : ! Requirement is that these base emissions have same species
2629 : ! ID, emission category and hierarchy, ext. number, scale
2630 : ! factors, and update frequency.
2631 0 : CALL Get_targetID( HcoState, Lct, targetID, RC)
2632 0 : IF ( RC /= HCO_SUCCESS ) THEN
2633 0 : PRINT *,'Error in Get_targetID called from Register_Base'
2634 0 : RETURN
2635 : ENDIF
2636 :
2637 : ! verbose
2638 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2639 0 : WRITE(MSG,*) 'Container ID : ', Lct%Dct%cID
2640 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
2641 0 : WRITE(MSG,*) 'Assigned targetID: ', targetID
2642 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
2643 : ENDIF
2644 :
2645 : ! Negative targetID is assigned to base data that doesn't need
2646 : ! to be considered either because it's a regional inventory
2647 : ! with no spatial overlap with the region domain on this CPU,
2648 : ! or because there exist another inventory with higher
2649 : ! priority (and same category) that will overwrite these
2650 : ! emissions data anyway!
2651 0 : IF ( targetID <= 0 ) THEN
2652 0 : CALL DataCont_Cleanup ( Lct%Dct )
2653 0 : Lct%Dct => NULL()
2654 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2655 0 : CYCLE
2656 : ENDIF
2657 :
2658 : ! Pass targetID to container
2659 0 : Lct%Dct%targetID = targetID
2660 :
2661 : ! Register container in ReadList. Containers will be listed
2662 : ! in the reading lists sorted by cID.
2663 0 : CALL ReadList_Set( HcoState, Lct%Dct, RC )
2664 0 : IF ( RC /= HCO_SUCCESS ) THEN
2665 0 : msg = 'Error encountered in routine "ReadList_Set"!'
2666 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2667 0 : RETURN
2668 : ENDIF
2669 :
2670 : ! Print some information if verbose mode is on
2671 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2672 0 : WRITE(MSG,*) 'Base field registered: ', TRIM(Lct%Dct%cName)
2673 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
2674 : ENDIF
2675 :
2676 : ! Advance to next line
2677 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2678 : ENDDO
2679 :
2680 : ! Cleanup
2681 0 : Lct => NULL()
2682 :
2683 : ! Return w/ success
2684 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
2685 :
2686 : END SUBROUTINE Register_Base
2687 : !EOC
2688 : !------------------------------------------------------------------------------
2689 : ! Harmonized Emissions Component (HEMCO) !
2690 : !------------------------------------------------------------------------------
2691 : !BOP
2692 : !
2693 : ! !IROUTINE: Register_Scal
2694 : !
2695 : ! !DESCRIPTION: Subroutine Register\_Scal registers all scale factors.
2696 : !\\
2697 : !\\
2698 : ! !INTERFACE:
2699 : !
2700 0 : SUBROUTINE Register_Scal( HcoState, RC )
2701 : !
2702 : ! !USES:
2703 : !
2704 : USE HCO_ReadList_Mod, ONLY : ReadList_Set
2705 : USE HCO_DATACONT_MOD, ONLY : ListCont_NextCont
2706 :
2707 : !
2708 : ! !INPUT PARAMETERS:
2709 : !
2710 : TYPE(HCO_State), POINTER :: HcoState ! HEMCO state object
2711 : !
2712 : ! !INPUT/OUTPUT PARAMETERS:
2713 : !
2714 : INTEGER, INTENT(INOUT) :: RC ! Success or failure
2715 : !
2716 : ! !REVISION HISTORY:
2717 : ! 18 Jun 2013 - C. Keller - Initialization
2718 : ! See https://github.com/geoschem/hemco for complete history
2719 : !EOP
2720 : !------------------------------------------------------------------------------
2721 : !BOC
2722 : !
2723 : ! !LOCAL VARIABLES:
2724 : !
2725 : ! Pointers
2726 : TYPE(ListCont), POINTER :: Lct
2727 : TYPE(ScalIDCont), POINTER :: TmpScalIDCont
2728 :
2729 : ! Scalars
2730 : INTEGER :: cID, FLAG
2731 : CHARACTER(LEN=255) :: LOC
2732 : CHARACTER(LEN=512) :: msg
2733 : CHARACTER(LEN= 5) :: strID
2734 : INTEGER :: ThisScalID
2735 :
2736 : !======================================================================
2737 : ! Register_Scal begins here
2738 : !======================================================================
2739 0 : loc = 'Register_Scal (HCO_CONFIG_MOD.F90)'
2740 :
2741 : ! Enter
2742 0 : CALL HCO_ENTER ( HcoState%Config%Err, loc, RC )
2743 0 : IF ( RC /= HCO_SUCCESS ) THEN
2744 0 : msg = 'Error encountered in routine "HCO_Enter"!'
2745 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2746 0 : RETURN
2747 : ENDIF
2748 :
2749 : ! Loop over all scale factor ids
2750 0 : Lct => NULL()
2751 0 : TmpScalIDCont => HcoState%Config%ScalIDList
2752 0 : DO WHILE ( ASSOCIATED( TmpScalIDCont ) )
2753 :
2754 : ! Extract this scale factor ID
2755 0 : ThisScalID = TmpScalIDCont%ScalID
2756 :
2757 : ! Make ThisLine point to first element of ConfigList
2758 0 : Lct => NULL()
2759 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2760 :
2761 : ! Loop over all lines in input file and find the one with the
2762 : ! correct scale factor ID
2763 0 : DO WHILE ( FLAG == HCO_SUCCESS )
2764 :
2765 : ! Leave if this is the wanted container.
2766 0 : IF ( ASSOCIATED(Lct%Dct)) THEN
2767 0 : IF ( Lct%Dct%ScalID == ThisScalID ) EXIT
2768 : ENDIF
2769 :
2770 : ! Advance to next line otherwise
2771 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, Lct, FLAG )
2772 : ENDDO
2773 :
2774 : ! Return error if scale factor ID not found
2775 0 : IF ( .NOT. ASSOCIATED(Lct) ) THEN
2776 0 : WRITE ( strID, * ) ThisScalID
2777 0 : msg = 'Container ID not found: ' // strID
2778 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2779 0 : RETURN
2780 : ENDIF
2781 :
2782 : ! Return w/ error if container not scale factor or mask
2783 0 : IF ( Lct%Dct%DctType == HCO_DCTTYPE_BASE ) THEN
2784 0 : WRITE ( strID, * ) ThisScalID
2785 0 : MSG = 'Container ID belongs to base field: ' // strID
2786 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2787 0 : RETURN
2788 : ENDIF
2789 :
2790 : ! Check if this scale factor has a mask field assigned to
2791 : ! it, in which case we have to make sure that the mask field
2792 : ! becomes registered in the scale factor list ScalIDList.
2793 : ! We can do this while evaluating ScalIDList due to the dynamic
2794 : ! structure of the linked list with new containers simply being
2795 : ! added to the end of the list.
2796 0 : IF ( Lct%Dct%nScalID > 0 ) THEN
2797 0 : CALL ScalID_Register ( Lct%Dct, HcoState%Config, RC )
2798 0 : IF ( RC /= HCO_SUCCESS ) THEN
2799 0 : msg = 'Error encountered in routine "ScalID_Register"!'
2800 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2801 0 : RETURN
2802 : ENDIF
2803 : ENDIF
2804 :
2805 : ! Register container in ReadList. Containers will be listed
2806 : ! in the reading lists sorted by cID.
2807 0 : CALL ReadList_Set( HcoState, Lct%Dct, RC )
2808 0 : IF ( RC /= HCO_SUCCESS ) THEN
2809 0 : msg = 'Error encountered in "ReadList_Set"!'
2810 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2811 0 : RETURN
2812 : ENDIF
2813 :
2814 : ! Print some information if verbose mode is on
2815 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2816 0 : WRITE(MSG,*) 'Scale field registered: ', TRIM(Lct%Dct%cName)
2817 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
2818 : ENDIF
2819 :
2820 : ! Advance
2821 0 : TmpScalIDCont => TmpScalIDCont%NEXT
2822 :
2823 : ENDDO
2824 :
2825 : ! Cleanup
2826 0 : Lct => NULL()
2827 0 : TmpScalIDCont => NULL()
2828 :
2829 : ! Return w/ success
2830 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
2831 :
2832 : END SUBROUTINE Register_Scal
2833 : !EOC
2834 : !------------------------------------------------------------------------------
2835 : ! Harmonized Emissions Component (HEMCO) !
2836 : !------------------------------------------------------------------------------
2837 : !BOP
2838 : !
2839 : ! !IROUTINE: Get_targetID
2840 : !
2841 : ! !DESCRIPTION: Subroutine Get\_targetID returns the target ID of a
2842 : ! container. The target ID can point to the container ID (cID) of
2843 : ! another base field if multiple emissions shall be added together
2844 : ! prior to emission calculation, e.g. sectoral emissions data with
2845 : ! same species ID, category, hierarchy, extension number, scale factors,
2846 : ! etc.
2847 : !\\
2848 : !\\
2849 : ! Target ID is set to -999 if there exists another inventory over
2850 : ! the full spatial region covered by this CPU for this species but
2851 : ! with higher hierarchy. In this case, we can ignore the current
2852 : ! container from here onwards!
2853 : !\\
2854 : !\\
2855 : ! !INTERFACE:
2856 : !
2857 0 : SUBROUTINE Get_targetID( HcoState, Lct, targetID, RC )
2858 : !
2859 : ! !USES:
2860 : !
2861 : USE HCO_DataCont_Mod, ONLY : ListCont_Find
2862 : USE HCO_DataCont_Mod, ONLY : ListCont_NextCont
2863 : !
2864 : ! !INPUT PARAMETERS:
2865 : !
2866 : TYPE(HCO_State), POINTER :: HcoState
2867 : TYPE(ListCont), POINTER :: Lct
2868 : !
2869 : ! !OUTPUT PARAMETERS:
2870 : !
2871 : INTEGER, INTENT( OUT) :: targetID
2872 : !
2873 : ! !INPUT/OUTPUT PARAMETERS:
2874 : !
2875 : INTEGER, INTENT(INOUT) :: RC
2876 : !
2877 : ! !NOTE: If data from multiple containers are added, the target ID
2878 : ! is always set to the lowest cID of all involved containers, i.e.
2879 : ! data are added to the container with the lowest cID. This makes
2880 : ! sure that data is not accidentally overwritten, e.g. when updating
2881 : ! container contents!
2882 : !
2883 : ! !REVISION HISTORY:
2884 : ! 11 Apr 2013 - C. Keller - Initialization
2885 : ! See https://github.com/geoschem/hemco for complete history
2886 : !EOP
2887 : !------------------------------------------------------------------------------
2888 : !BOC
2889 : !
2890 : ! !LOCAL VARIABLES:
2891 : !
2892 : ! Pointers
2893 : TYPE(ListCont), POINTER :: tmpLct
2894 : TYPE(ListCont), POINTER :: mskLct
2895 :
2896 : ! Scalars
2897 : INTEGER :: HcoID, Cat, Hier, Scal, ExtNr, cID
2898 : INTEGER :: tmpID
2899 : INTEGER :: I, J, FLAG1, tmpCov
2900 : LOGICAL :: found, sameCont
2901 : CHARACTER(LEN=255) :: loc
2902 : CHARACTER(LEN=512) :: msg
2903 : CHARACTER(LEN= 7) :: strID
2904 :
2905 : !======================================================================
2906 : ! Get_targetID begins here
2907 : !======================================================================
2908 0 : loc = 'Get_targetID (HCO_CONFIG_MOD.F90)'
2909 :
2910 : ! Enter
2911 0 : CALL HCO_ENTER ( HcoState%Config%Err, LOC, RC )
2912 0 : IF ( RC /= HCO_SUCCESS ) THEN
2913 0 : msg = 'Error encountered in routine "HCO_Enter"!'
2914 0 : CALL HCO_ERROR( msg, RC, thisLoc=LOC )
2915 0 : RETURN
2916 : ENDIF
2917 :
2918 : ! Initialize
2919 0 : tmpLct => NULL()
2920 0 : mskLct => NULL()
2921 :
2922 : ! Get Tracer ID, category and hierarchy of entry to be checked
2923 0 : cID = Lct%Dct%cID
2924 0 : ExtNr = Lct%Dct%ExtNr
2925 0 : Cat = Lct%Dct%Cat
2926 0 : Hier = Lct%Dct%Hier
2927 0 : HcoID = Lct%Dct%HcoID
2928 :
2929 : ! By default, set target ID to container ID
2930 0 : targetID = cID
2931 :
2932 : ! If ExtNr is -999, always read this field. ExtNr becomes zero
2933 : ! if the extension number entry in the configuration file is the
2934 : ! wildcard character
2935 0 : IF ( ExtNr == -999 ) THEN
2936 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
2937 0 : RETURN
2938 : ENDIF
2939 :
2940 : ! If species ID is zero, always read this field as is, i.e. don't
2941 : ! skip it and don't add it to another field!
2942 : ! Species ID become zero if the species ID entry in the
2943 : ! configuration file is the wildcard character.
2944 0 : IF ( HcoID == 0 ) THEN
2945 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
2946 0 : RETURN
2947 : ENDIF
2948 :
2949 : ! Check all scale factors of the current container to see if one
2950 : ! of them is a mask that has no valid entries over the domain of
2951 : ! this CPU. In this case we don't have to consider this field at
2952 : ! all!
2953 0 : IF ( Lct%Dct%nScalID > 0 ) THEN
2954 0 : DO I = 1, Lct%Dct%nScalID
2955 :
2956 : ! Check if it's a valid scale factor
2957 0 : IF ( Lct%Dct%Scal_cID(I) < 0 ) CYCLE
2958 :
2959 : ! Find container with this container ID
2960 : ! Note: this should always look up the container ID, but make
2961 : ! check for safety's sake.
2962 0 : tmpID = Lct%Dct%Scal_cID(I)
2963 0 : IF ( .NOT. Lct%Dct%Scal_cID_set ) THEN
2964 : CALL ListCont_Find ( HcoState%Config%ConfigList, &
2965 0 : tmpID, 1, FOUND, mskLct )
2966 : ELSE
2967 : CALL ListCont_Find ( HcoState%Config%ConfigList, &
2968 0 : tmpID, 0, FOUND, mskLct )
2969 : ENDIF
2970 :
2971 : ! Error if scale factor not found
2972 0 : IF ( .NOT. FOUND ) THEN
2973 0 : WRITE ( strID, * ) Lct%Dct%Scal_cID(I)
2974 0 : msg = 'No scale factor with cID: ' // TRIM(strID)
2975 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
2976 0 : RETURN
2977 : ENDIF
2978 :
2979 : ! Check if this is a mask with zero coverage over this CPU, in
2980 : ! which case we don't need to consider the base field at all!
2981 0 : IF ( (mskLct%Dct%DctType == HCO_DCTTYPE_MASK ) .AND. &
2982 0 : (mskLct%Dct%Dta%Cover == 0 ) ) THEN
2983 0 : targetID = -999
2984 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
2985 : WRITE(MSG,*) 'Data not defined over this CPU, skip ' // &
2986 0 : TRIM(Lct%Dct%cName)
2987 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
2988 : ENDIF
2989 :
2990 : ! Return
2991 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
2992 0 : RETURN
2993 : ENDIF
2994 : ENDDO ! I
2995 : ENDIF
2996 :
2997 : ! Now find out if there is another base field for the same species,
2998 : ! emission category and extension number, but higher hierarchy.
2999 : ! Such a field also needs to have full coverage over this CPU,
3000 : ! then we can ignore the current container.
3001 :
3002 : ! Initialize looping pointer
3003 0 : tmpLct => NULL()
3004 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3005 :
3006 : ! Loop over containers
3007 0 : DO WHILE ( FLAG1 == HCO_SUCCESS )
3008 :
3009 : ! Advance to next container if data container not defined
3010 0 : IF ( .NOT. ASSOCIATED(tmpLct%Dct) ) THEN
3011 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3012 0 : CYCLE
3013 : ENDIF
3014 :
3015 : ! Advance to next container if this is the current container
3016 0 : IF ( tmpLct%Dct%cID == cID ) THEN
3017 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3018 0 : CYCLE
3019 : ENDIF
3020 :
3021 : ! Advance to next container if this is not a base field
3022 0 : IF ( tmpLct%Dct%DctType /= HCO_DCTTYPE_BASE ) THEN
3023 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3024 0 : CYCLE
3025 : ENDIF
3026 :
3027 : ! Advance to next container if not the same extension nr
3028 0 : IF ( tmpLct%Dct%ExtNr /= ExtNr ) THEN
3029 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3030 0 : CYCLE
3031 : ENDIF
3032 :
3033 : ! Advance to next container if not the same species
3034 0 : IF ( tmpLct%Dct%HcoID /= HcoID ) THEN
3035 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3036 0 : CYCLE
3037 : ENDIF
3038 :
3039 : ! Advance to next container if not the same category
3040 0 : IF ( tmpLct%Dct%Cat /= Cat ) THEN
3041 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3042 0 : CYCLE
3043 : ENDIF
3044 :
3045 : ! Advance to next container if lower hierarchy
3046 0 : IF ( tmpLct%Dct%Hier < Hier ) THEN
3047 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3048 0 : CYCLE
3049 : ENDIF
3050 :
3051 : ! Advance to next container if this container has limited time
3052 : ! coverage. Emissions with limited time coverage may not be used
3053 : ! during all of the simulation time, so it's important to keep the
3054 : ! lower hierarchy emission fields in memory in case that those need
3055 : ! to be used instead (e.g. if EDGAR shall only be used between years
3056 : ! 2005 and 2013, we should keep GEIA in case that we are outside of
3057 : ! that time window).
3058 : IF ( ( tmpLct%Dct%Dta%CycleFlag == HCO_CFLAG_RANGE ) .OR. &
3059 0 : ( tmpLct%Dct%Dta%CycleFlag == HCO_CFLAG_EXACT ) .OR. &
3060 : ( tmpLct%Dct%Dta%CycleFlag == HCO_CFLAG_RANGEAVG ) ) THEN
3061 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3062 0 : CYCLE
3063 : ENDIF
3064 :
3065 : ! Check for coverage of tmpLct. Default = full coverage (1)
3066 0 : tmpCov = 1
3067 :
3068 : ! Check all scale factors of tmpLct to see if this base
3069 : ! field has full coverage over this CPU domain or not.
3070 0 : IF ( tmpLct%Dct%nScalID > 0 ) THEN
3071 0 : DO I = 1, tmpLct%Dct%nScalID
3072 :
3073 : ! Check if it's a valid scale factor
3074 0 : IF ( tmpLct%Dct%Scal_cID(I) < 0 ) CYCLE
3075 :
3076 0 : tmpID = tmpLct%Dct%Scal_cID(I)
3077 0 : IF ( .NOT. tmpLct%Dct%Scal_cID_set ) THEN
3078 : CALL ListCont_Find ( HcoState%Config%ConfigList, &
3079 0 : tmpID, 1, FOUND, mskLct )
3080 : ELSE
3081 : CALL ListCont_Find ( HcoState%Config%ConfigList, &
3082 0 : tmpID, 0, FOUND, mskLct )
3083 : ENDIF
3084 :
3085 : ! Error if container not found
3086 0 : IF ( .NOT. FOUND ) THEN
3087 0 : WRITE(MSG,*) 'No scale factor with ID: ', tmpID
3088 0 : CALL HCO_Error( msg, RC, thisLoc=loc )
3089 0 : RETURN
3090 : ENDIF
3091 :
3092 : ! Write out coverage.
3093 : ! Note: If one mask has only partial coverage, retain that
3094 : ! value! If we encounter a mask with no coverage, set coverage
3095 : ! to zero and leave immediately.
3096 0 : IF ( (mskLct%Dct%DctType == HCO_DCTTYPE_MASK) ) THEN
3097 0 : IF ( mskLct%Dct%Dta%Cover == -1 ) THEN
3098 : tmpCov = -1
3099 0 : ELSEIF ( mskLct%Dct%Dta%Cover == 0 ) THEN
3100 : tmpCov = 0
3101 : EXIT
3102 : ENDIF
3103 : ENDIF
3104 : ENDDO ! I
3105 : ENDIF
3106 :
3107 : ! If tmpLct has no coverage, we can ignore this tmpLct as
3108 : ! it will never overwrite data of currCont
3109 0 : IF ( tmpCov == 0 ) THEN
3110 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3111 0 : CYCLE
3112 : ENDIF
3113 :
3114 : ! If we made it up to here and tmpLct has full coverage, then
3115 : ! tmpLct has the same species ID, category, ext. nr.,
3116 : ! and a higher (or the same) hierarchy as Lct.
3117 :
3118 : ! If hierarchy of tmpLct is higher than Lct and this
3119 : ! container has total coverage over this CPU, it will always
3120 : ! replace all values of Lct. Hence, set targetID to -999
3121 : ! (= ignore container) and return here.
3122 0 : IF ( (tmpLct%Dct%Hier > Hier) .AND. (tmpCov==1) ) THEN
3123 0 : IF ( HCO_IsVerb(HcoState%Config%Err ) ) THEN
3124 0 : WRITE(MSG,*) 'Skip container ', TRIM(Lct%Dct%cName), &
3125 0 : ' because of ', TRIM(tmpLct%Dct%cName)
3126 0 : CALL HCO_MSG( HcoState%Config%Err, msg )
3127 : ENDIF
3128 :
3129 : ! Return
3130 0 : targetID = -999
3131 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
3132 0 : RETURN
3133 : ENDIF
3134 :
3135 : ! If currCont and tmpLct have same hierarchy, scale factors,
3136 : ! and update frequencies, we may add the two fields together
3137 : ! in order to make emission calculation more efficient.
3138 : ! Thus, set target ID to the lower of the two container IDs.
3139 : ! This procedure will ensure that emission data are added
3140 : ! when registering/updating containers in the emissions list
3141 : ! (EmisList). Since containers are sorted in ReadList with
3142 : ! increasing cID, pick the lowest cID to make sure that all
3143 : ! fields are properly added.
3144 : ! Note: this option is currently disabled for ESMF applications.
3145 0 : IF ( tmpLct%Dct%Hier == Hier .AND. .NOT. HcoState%Options%isESMF ) THEN
3146 :
3147 : ! temporary flag
3148 0 : sameCont = .TRUE.
3149 :
3150 : ! Check for same scale factors
3151 0 : IF ( tmpLct%Dct%nScalID /= Lct%Dct%nScalID ) THEN
3152 : sameCont = .FALSE.
3153 : ELSE
3154 0 : DO I = 1, tmpLct%Dct%nScalID
3155 0 : IF ( tmpLct%Dct%Scal_cID(I) /= &
3156 0 : Lct%Dct%Scal_cID(I) ) THEN
3157 : sameCont = .FALSE.
3158 : EXIT
3159 : ENDIF
3160 : ENDDO
3161 : ENDIF
3162 :
3163 : ! Check for same update frequencies
3164 0 : IF ( sameCont ) THEN
3165 0 : IF (tmpLct%Dct%Dta%ncYrs(1)/=Lct%Dct%Dta%ncYrs(1)) THEN
3166 : sameCont = .FALSE.
3167 0 : ELSEIF(tmpLct%Dct%Dta%ncYrs(2)/=Lct%Dct%Dta%ncYrs(2)) THEN
3168 : sameCont = .FALSE.
3169 0 : ELSEIF(tmpLct%Dct%Dta%ncMts(1)/=Lct%Dct%Dta%ncMts(1)) THEN
3170 : sameCont = .FALSE.
3171 0 : ELSEIF(tmpLct%Dct%Dta%ncMts(2)/=Lct%Dct%Dta%ncMts(2)) THEN
3172 : sameCont = .FALSE.
3173 0 : ELSEIF(tmpLct%Dct%Dta%ncDys(1)/=Lct%Dct%Dta%ncDys(1)) THEN
3174 : sameCont = .FALSE.
3175 0 : ELSEIF(tmpLct%Dct%Dta%ncDys(2)/=Lct%Dct%Dta%ncDys(2)) THEN
3176 : sameCont = .FALSE.
3177 0 : ELSEIF(tmpLct%Dct%Dta%ncHrs(1)/=Lct%Dct%Dta%ncHrs(1)) THEN
3178 : sameCont = .FALSE.
3179 0 : ELSEIF(tmpLct%Dct%Dta%ncHrs(2)/=Lct%Dct%Dta%ncHrs(2)) THEN
3180 : sameCont = .FALSE.
3181 : ENDIF
3182 : ENDIF
3183 :
3184 : ! Check for same emitted level
3185 : IF ( sameCont ) THEN
3186 : IF ( ( tmpLct%Dct%Dta%SpaceDim /= Lct%Dct%Dta%SpaceDim ) .OR. &
3187 : ( tmpLct%Dct%Dta%Levels /= Lct%Dct%Dta%Levels ) .OR. &
3188 0 : ( tmpLct%Dct%Dta%EmisL1 /= Lct%Dct%Dta%EmisL1 ) .OR. &
3189 : ( tmpLct%Dct%Dta%EmisL2 /= Lct%Dct%Dta%EmisL2 ) ) THEN
3190 : sameCont = .FALSE.
3191 : ENDIF
3192 : ENDIF
3193 :
3194 : ! Finally, check for "same" container names. This checks the
3195 : ! container names ignoring the name 'tags'.
3196 : IF ( sameCont ) THEN
3197 0 : sameCont = Check_ContNames( tmpLct, Lct )
3198 : ENDIF
3199 :
3200 : ! If "same" containers, set target ID to container ID of
3201 : ! tmpLct if this value is lower than current target ID.
3202 0 : IF ( sameCont ) THEN
3203 0 : targetID = MIN( targetID, tmpLct%Dct%cID )
3204 : ENDIF
3205 :
3206 : ENDIF
3207 :
3208 : ! Advance to next line
3209 : ! Don't return here, because it is still possible that there is
3210 : ! another inventory in the list coming up which overwrites this
3211 : ! inventory (or another field emissions shall be added to which
3212 : ! has lower container ID and hence needs to be the target
3213 : ! container!).
3214 0 : CALL ListCont_NextCont ( HcoState%Config%ConfigList, tmpLct, FLAG1 )
3215 :
3216 : ENDDO !Loop over all entries in ConfigList (tmpLct)
3217 :
3218 : ! Free pointers
3219 0 : tmpLct => NULL()
3220 0 : mskLct => NULL()
3221 :
3222 : ! Leave w/ success
3223 0 : CALL HCO_LEAVE( HcoState%Config%Err, RC )
3224 :
3225 : END SUBROUTINE Get_targetID
3226 : !EOC
3227 : !------------------------------------------------------------------------------
3228 : ! Harmonized Emissions Component (HEMCO) !
3229 : !------------------------------------------------------------------------------
3230 : !BOP
3231 : !
3232 : ! !IROUTINE: Calc_Coverage
3233 : !
3234 : ! !DESCRIPTION: Function Calc\_Coverage calculates the coverage of
3235 : ! the specified lon/lat box with the area covered by the inventory.
3236 : ! Returns 0 if no overlap, 1 if complete overlap, and -1 for partial
3237 : ! overlap.
3238 : !\\
3239 : !\\
3240 : ! !INTERFACE:
3241 : !
3242 : FUNCTION Calc_Coverage( msk_x1, msk_x2, msk_y1, msk_y2, &
3243 : cpu_x1, cpu_x2, cpu_y1, cpu_y2 ) RESULT ( COVERAGE )
3244 : !
3245 : ! !INPUT PARAMETERS:
3246 : !
3247 : INTEGER, INTENT(IN) :: msk_x1
3248 : INTEGER, INTENT(IN) :: msk_x2
3249 : INTEGER, INTENT(IN) :: msk_y1
3250 : INTEGER, INTENT(IN) :: msk_y2
3251 : INTEGER, INTENT(IN) :: cpu_x1
3252 : INTEGER, INTENT(IN) :: cpu_x2
3253 : INTEGER, INTENT(IN) :: cpu_y1
3254 : INTEGER, INTENT(IN) :: cpu_y2
3255 : !
3256 : ! !RETURN VALUE:
3257 : !
3258 : INTEGER :: COVERAGE
3259 : !
3260 : ! !REVISION HISTORY:
3261 : ! 11 Apr 2013 - C. Keller: Initialization
3262 : ! See https://github.com/geoschem/hemco for complete history
3263 : !EOP
3264 : !------------------------------------------------------------------------------
3265 : !BOC
3266 :
3267 : !======================================================================
3268 : ! CALC_COVERAGE begins here
3269 : !======================================================================
3270 :
3271 : ! Check if specified area does not overlap with inventory
3272 : COVERAGE = 1
3273 : IF ( (msk_x1 > cpu_x2) .OR. (msk_x2 < cpu_x1) .OR. &
3274 : (msk_y1 > cpu_y2) .OR. (msk_y2 < cpu_y1) ) THEN
3275 : COVERAGE = 0
3276 : RETURN
3277 : ENDIF
3278 :
3279 : ! Check for partial coverage
3280 : IF ( (msk_x1 > cpu_x1) .OR. (msk_x2 < cpu_x2) .OR. &
3281 : (msk_y1 > cpu_y1) .OR. (msk_y2 < cpu_y2) ) THEN
3282 : COVERAGE = -1
3283 : ENDIF
3284 :
3285 : END FUNCTION Calc_Coverage
3286 : !EOC
3287 : !------------------------------------------------------------------------------
3288 : ! Harmonized Emissions Component (HEMCO) !
3289 : !------------------------------------------------------------------------------
3290 : !BOP
3291 : !
3292 : ! !IROUTINE: ReadAndSplit_Line
3293 : !
3294 : ! !DESCRIPTION: Subroutine ReadAndSplit\_Line reads a line from the HEMCO
3295 : ! config file and parses the specified columns into the passed integer
3296 : ! and character variables. If the optional argument inLine is provided,
3297 : ! this line will be parsed, otherwise a new line will be read from the config
3298 : ! file. If the optional argument outLine is provided, this variable will hold
3299 : ! the parsed line.
3300 : !\\
3301 : !\\
3302 : ! This routine splits the input line (or the next line of an open file with
3303 : ! ID IU\_HCO), using the HEMCO separator (default: space) as separator. The
3304 : ! resulting elements are then passed to the specified output characters and
3305 : ! integers. For example, to pass the 5th element of a line to variable int1,
3306 : ! set int1cl to 5, etc. An error will be returned (STAT=100) if any of the
3307 : ! output columns exceeds the number of line elements. The optional argument
3308 : ! optcl can be used to denote an optional value, e.g. no error is returned
3309 : ! if the value at position optcl cannot be read. Only one optional value can
3310 : ! be specified.
3311 : !\\
3312 : !\\
3313 : ! !INTERFACE:
3314 : !
3315 0 : SUBROUTINE ReadAndSplit_Line( HcoConfig, IU_HCO, char1, chr1cl, &
3316 : char2, chr2cl, char3, chr3cl, &
3317 : char4, chr4cl, char5, chr5cl, &
3318 : char6, chr6cl, char7, chr7cl, &
3319 : char8, chr8cl, char9, chr9cl, &
3320 : char10, chr10cl, &
3321 : int1, int1cl, int2, int2cl, &
3322 0 : int3, int3cl, STAT, inLine, &
3323 0 : outLine, optcl )
3324 : !
3325 : ! !USES:
3326 : !
3327 : USE HCO_CHARPAK_Mod, ONLY : STRREPL, STRSPLIT
3328 : !
3329 : ! !INPUT PARAMETERS:
3330 : !
3331 : TYPE(ConfigObj), POINTER :: HcoConfig
3332 : INTEGER, INTENT(IN ) :: IU_HCO
3333 : INTEGER, INTENT(IN ) :: chr1cl
3334 : INTEGER, INTENT(IN ) :: chr2cl
3335 : INTEGER, INTENT(IN ) :: chr3cl
3336 : INTEGER, INTENT(IN ) :: chr4cl
3337 : INTEGER, INTENT(IN ) :: chr5cl
3338 : INTEGER, INTENT(IN ) :: chr6cl
3339 : INTEGER, INTENT(IN ) :: chr7cl
3340 : INTEGER, INTENT(IN ) :: chr8cl
3341 : INTEGER, INTENT(IN ) :: chr9cl
3342 : INTEGER, INTENT(IN ) :: chr10cl
3343 : INTEGER, INTENT(IN ) :: int1cl
3344 : INTEGER, INTENT(IN ) :: int2cl
3345 : INTEGER, INTENT(IN ) :: int3cl
3346 : CHARACTER(LEN=255), INTENT(IN ), OPTIONAL :: inLINE
3347 : INTEGER, INTENT(IN ), OPTIONAL :: optcl
3348 : !
3349 : ! !OUTPUT PARAMETERS:
3350 : !
3351 : CHARACTER(LEN=*), INTENT(INOUT) :: char1
3352 : CHARACTER(LEN=*), INTENT(INOUT) :: char2
3353 : CHARACTER(LEN=*), INTENT(INOUT) :: char3
3354 : CHARACTER(LEN=*), INTENT(INOUT) :: char4
3355 : CHARACTER(LEN=*), INTENT(INOUT) :: char5
3356 : CHARACTER(LEN=*), INTENT(INOUT) :: char6
3357 : CHARACTER(LEN=*), INTENT(INOUT) :: char7
3358 : CHARACTER(LEN=*), INTENT(INOUT) :: char8
3359 : CHARACTER(LEN=*), INTENT(INOUT) :: char9
3360 : CHARACTER(LEN=*), INTENT(INOUT) :: char10
3361 : INTEGER, INTENT(INOUT) :: int1
3362 : INTEGER, INTENT(INOUT) :: int2
3363 : INTEGER, INTENT(INOUT) :: int3
3364 : CHARACTER(LEN=255), INTENT( OUT), OPTIONAL :: outLINE
3365 : !
3366 : ! !INPUT/OUTPUT PARAMETERS:
3367 : !
3368 : INTEGER, INTENT(INOUT) :: STAT
3369 : !
3370 : ! !REVISION HISTORY:
3371 : ! 28 Aug 2013 - C. Keller - Initial version
3372 : ! See https://github.com/geoschem/hemco for complete history
3373 : !EOP
3374 : !------------------------------------------------------------------------------
3375 : !BOC
3376 : !
3377 : ! !LOCAL VARIABLES:
3378 : !
3379 : INTEGER :: N, OPT, STRLEN, RC
3380 : CHARACTER(LEN=255) :: LINE
3381 : CHARACTER(LEN=255) :: SUBSTR(255)
3382 : LOGICAL :: EOF
3383 :
3384 : !======================================================================
3385 : ! ReadAndSplit_Line begins here
3386 : !======================================================================
3387 :
3388 : ! Output status
3389 0 : STAT = 0
3390 :
3391 : ! ---------------------------------------------------------------------
3392 : ! Read line and split column
3393 : ! ---------------------------------------------------------------------
3394 0 : IF ( PRESENT(inLINE) ) THEN
3395 0 : LINE = inLINE
3396 : ELSE
3397 : ! Read line
3398 0 : CALL HCO_READLINE( IU_HCO, LINE, EOF, RC )
3399 :
3400 : ! Return w/ error
3401 0 : IF ( RC /= HCO_SUCCESS ) THEN
3402 0 : STAT = 999
3403 0 : RETURN
3404 : ENDIF
3405 :
3406 : ! End of file
3407 0 : IF ( EOF ) THEN
3408 0 : STAT = -999
3409 0 : RETURN
3410 : ENDIF
3411 : ENDIF
3412 :
3413 : ! Check for output line
3414 0 : IF ( PRESENT(outLINE) ) outLINE = LINE
3415 :
3416 : ! Return here with flag = 10 if line starts with 'END SECTION'.
3417 0 : IF ( INDEX ( LINE, 'END SECTION' ) > 0 ) THEN
3418 0 : STAT = 10
3419 0 : RETURN
3420 : ENDIF
3421 :
3422 : ! Return here with flag = 1 if line is commented
3423 0 : IF ( LINE(1:1) == HCO_CMT ) THEN
3424 0 : STAT = 1
3425 0 : RETURN
3426 : ENDIF
3427 :
3428 : ! Get string length
3429 0 : STRLEN = LEN(TRIM(LINE))
3430 :
3431 : ! Return here with flag = 5 is line is opening a (shortcut) bracket.
3432 0 : IF ( STRLEN > 3 ) THEN
3433 0 : IF ( LINE(1:3) == '(((' ) THEN
3434 0 : STAT = 5
3435 0 : RETURN
3436 : ENDIF
3437 :
3438 : ! Return here with flag = 6 is line is opening a (shortcut) bracket.
3439 0 : IF ( LINE(1:3) == ')))' ) THEN
3440 0 : STAT = 6
3441 0 : RETURN
3442 : ENDIF
3443 : ENDIF
3444 :
3445 : ! Return with flag = 1000 if this is a link to an include file.
3446 0 : IF ( STRLEN > 11 ) THEN
3447 0 : IF ( LINE(1:10) == '>>>include' ) THEN
3448 0 : IF ( PRESENT(outLINE) ) outLINE = outLINE(12:STRLEN)
3449 0 : STAT = 1000
3450 0 : RETURN
3451 : ENDIF
3452 : ENDIF
3453 :
3454 : ! Split line into columns
3455 0 : CALL STRREPL ( LINE, HCO_TAB, HCO_SPC )
3456 0 : CALL STRSPLIT( LINE, HCO_SPC, SUBSTR, N )
3457 :
3458 : ! Also ignore empty lines
3459 0 : IF ( N <= 1 ) THEN
3460 0 : STAT = 1
3461 0 : RETURN
3462 : ENDIF
3463 :
3464 : ! Are there any optional lines?
3465 0 : IF ( PRESENT(optcl) ) THEN
3466 0 : OPT = optcl
3467 : ELSE
3468 0 : OPT = -1
3469 : ENDIF
3470 :
3471 : ! ---------------------------------------------------------------------
3472 : ! Read characters as specified and write them into given variables
3473 : ! ---------------------------------------------------------------------
3474 :
3475 0 : CALL READCHAR( LINE, SUBSTR, N, chr1cl, char1, OPT, STAT )
3476 0 : IF ( STAT == 100 ) RETURN
3477 0 : CALL READCHAR( LINE, SUBSTR, N, chr2cl, char2, OPT, STAT )
3478 0 : IF ( STAT == 100 ) RETURN
3479 0 : CALL READCHAR( LINE, SUBSTR, N, chr3cl, char3, OPT, STAT )
3480 0 : IF ( STAT == 100 ) RETURN
3481 0 : CALL READCHAR( LINE, SUBSTR, N, chr4cl, char4, OPT, STAT )
3482 0 : IF ( STAT == 100 ) RETURN
3483 0 : CALL READCHAR( LINE, SUBSTR, N, chr5cl, char5, OPT, STAT )
3484 0 : IF ( STAT == 100 ) RETURN
3485 0 : CALL READCHAR( LINE, SUBSTR, N, chr6cl, char6, OPT, STAT )
3486 0 : IF ( STAT == 100 ) RETURN
3487 0 : CALL READCHAR( LINE, SUBSTR, N, chr7cl, char7, OPT, STAT )
3488 0 : IF ( STAT == 100 ) RETURN
3489 0 : CALL READCHAR( LINE, SUBSTR, N, chr8cl, char8, OPT, STAT )
3490 0 : IF ( STAT == 100 ) RETURN
3491 0 : CALL READCHAR( LINE, SUBSTR, N, chr9cl, char9, OPT, STAT )
3492 0 : IF ( STAT == 100 ) RETURN
3493 0 : CALL READCHAR( LINE, SUBSTR, N, chr10cl, char10, OPT, STAT )
3494 0 : IF ( STAT == 100 ) RETURN
3495 :
3496 : ! ---------------------------------------------------------------------
3497 : ! Read integers as specified and write them into given variables.
3498 : ! Value -999 is returned for wildcard characters.
3499 : ! ---------------------------------------------------------------------
3500 :
3501 0 : CALL READINT( HcoConfig%ExtList, LINE, SUBSTR, N, int1cl, int1, OPT, STAT )
3502 0 : IF ( STAT == 100 ) RETURN
3503 0 : CALL READINT( HcoConfig%ExtList, LINE, SUBSTR, N, int2cl, int2, OPT, STAT )
3504 0 : IF ( STAT == 100 ) RETURN
3505 0 : CALL READINT( HcoConfig%ExtList, LINE, SUBSTR, N, int3cl, int3, OPT, STAT )
3506 0 : IF ( STAT == 100 ) RETURN
3507 :
3508 : END SUBROUTINE ReadAndSplit_Line
3509 : !EOC
3510 : !------------------------------------------------------------------------------
3511 : ! Harmonized Emissions Component (HEMCO) !
3512 : !------------------------------------------------------------------------------
3513 : !BOP
3514 : !
3515 : ! !IROUTINE: READCHAR
3516 : !
3517 : ! !DESCRIPTION: Subroutine READCHAR is a helper routine to read character
3518 : ! values from the HEMCO configuration file.
3519 : !\\
3520 : !\\
3521 : ! !INTERFACE:
3522 : !
3523 0 : SUBROUTINE READCHAR ( LINE, SUBSTR, N, chrcl, charout, OPT, STAT )
3524 : !
3525 : ! !INPUT PARAMETERS:
3526 : !
3527 : CHARACTER(LEN=255), INTENT(IN ) :: LINE
3528 : CHARACTER(LEN=255), INTENT(IN ) :: SUBSTR(255)
3529 : INTEGER, INTENT(IN ) :: N
3530 : INTEGER, INTENT(IN ) :: chrcl
3531 : INTEGER, INTENT(IN ) :: OPT
3532 : !
3533 : ! !INPUT/OUTPUT PARAMETERS:
3534 : !
3535 : CHARACTER(LEN=*), INTENT(INOUT) :: charout
3536 : INTEGER, INTENT(INOUT) :: STAT
3537 : !
3538 : ! !REVISION HISTORY:
3539 : ! 29 Dec 2014 - C. Keller - Initial version
3540 : ! See https://github.com/geoschem/hemco for complete history
3541 : !EOP
3542 : !------------------------------------------------------------------------------
3543 : !BOC
3544 : !
3545 0 : IF ( chrcl > 0 ) THEN
3546 0 : IF ( chrcl > N ) THEN
3547 0 : IF ( chrcl /= OPT ) THEN
3548 0 : WRITE(*,*) 'Not enough elements in: '//TRIM(LINE)
3549 0 : STAT = 100
3550 0 : RETURN
3551 : ELSE
3552 0 : charout = ''
3553 : ENDIF
3554 : ELSE
3555 0 : READ( SUBSTR(chrcl), '(a)' ) charout
3556 : ENDIF
3557 : ENDIF
3558 0 : charout = ADJUSTL(charout)
3559 :
3560 0 : END SUBROUTINE READCHAR
3561 : !EOC
3562 : !------------------------------------------------------------------------------
3563 : ! Harmonized Emissions Component (HEMCO) !
3564 : !------------------------------------------------------------------------------
3565 : !BOP
3566 : !
3567 : ! !IROUTINE: READINT
3568 : !
3569 : ! !DESCRIPTION: Subroutine READINT is a helper routine to read integer
3570 : ! values from the HEMCO configuration file.
3571 : !\\
3572 : !\\
3573 : ! !INTERFACE:
3574 : !
3575 0 : SUBROUTINE READINT ( ExtList, LINE, SUBSTR, N, intcl, intout, OPT, STAT )
3576 : !
3577 : ! !USES:
3578 : !
3579 : USE HCO_EXTLIST_MOD, ONLY : HCO_GetOpt
3580 : !
3581 : ! !INPUT PARAMETERS:
3582 : !
3583 : TYPE(Ext), POINTER :: ExtList
3584 : CHARACTER(LEN=255), INTENT(IN ) :: LINE
3585 : CHARACTER(LEN=255), INTENT(IN ) :: SUBSTR(255)
3586 : INTEGER, INTENT(IN ) :: N
3587 : INTEGER, INTENT(IN ) :: intcl
3588 : INTEGER, INTENT(IN ) :: OPT
3589 : !
3590 : ! !INPUT/OUTPUT PARAMETERS:
3591 : !
3592 : INTEGER, INTENT(INOUT) :: intout
3593 : INTEGER, INTENT(INOUT) :: STAT
3594 : !
3595 : ! !REVISION HISTORY:
3596 : ! 29 Dec 2014 - C. Keller - Initial version
3597 : ! See https://github.com/geoschem/hemco for complete history
3598 : !EOP
3599 : !------------------------------------------------------------------------------
3600 : !BOC
3601 : !
3602 0 : IF ( intcl > 0 ) THEN
3603 0 : IF ( intcl > N ) THEN
3604 0 : IF ( intcl /= OPT ) THEN
3605 0 : WRITE(*,*) 'Not enough elements in: '//TRIM(LINE)
3606 0 : STAT = 100
3607 0 : RETURN
3608 : ELSE
3609 0 : intout = -999
3610 : ENDIF
3611 : ELSE
3612 : ! Check for wildcard
3613 0 : IF ( SUBSTR(intcl) == TRIM(HCO_GetOpt(ExtList,'Wildcard')) ) THEN
3614 0 : intout = -999
3615 : ELSE
3616 0 : READ( SUBSTR(intcl), * ) intout
3617 : ENDIF
3618 : ENDIF
3619 : ENDIF
3620 :
3621 : END SUBROUTINE READINT
3622 : !EOC
3623 : !------------------------------------------------------------------------------
3624 : ! Harmonized Emissions Component (HEMCO) !
3625 : !------------------------------------------------------------------------------
3626 : !BOP
3627 : !
3628 : ! !IROUTINE: Get_cID
3629 : !
3630 : ! !DESCRIPTION: Subroutine Get\_cID searches the whole ConfigList for an entry
3631 : ! with the given ScalID and returns the corresponding container ID cID.
3632 : !\\
3633 : !\\
3634 : ! !INTERFACE:
3635 : !
3636 0 : SUBROUTINE Get_cID( ScalID, HcoConfig, cID, RC )
3637 : !
3638 : ! !INPUT PARAMETERS:
3639 : !
3640 : INTEGER, INTENT(IN ) :: scalID
3641 : TYPE(ConfigObj), POINTER :: HcoConfig
3642 : !
3643 : ! !OUTPUT PARAMETERS:
3644 : !
3645 : INTEGER, INTENT( OUT) :: cID
3646 : !
3647 : ! !INPUT/OUTPUTP PARAMETERS:
3648 : !
3649 : INTEGER, INTENT(INOUT) :: RC
3650 : !
3651 : ! !REVISION HISTORY:
3652 : ! 18 Sep 2013 - C. Keller - Initial version
3653 : ! See https://github.com/geoschem/hemco for complete history
3654 : !EOP
3655 : !------------------------------------------------------------------------------
3656 : !BOC
3657 : !
3658 : ! !LOCAL VARIABLES:
3659 : !
3660 : ! Pointers
3661 : TYPE(ListCont), POINTER :: Lct
3662 :
3663 : ! Scalars
3664 : CHARACTER(LEN=255) :: MSG, LOC
3665 : CHARACTER(LEN= 31) :: strID
3666 :
3667 : ! Enter
3668 0 : LOC = 'Get_cID (hco_config_mod.F90)'
3669 0 : cID = -999
3670 :
3671 : ! Loop over all containers
3672 0 : Lct => HcoConfig%ConfigList
3673 0 : DO WHILE ( ASSOCIATED ( Lct ) )
3674 :
3675 : ! Skip if data container not defined
3676 0 : IF ( .NOT. ASSOCIATED(Lct%Dct) ) THEN
3677 0 : Lct => Lct%NextCont
3678 0 : CYCLE
3679 : ENDIF
3680 :
3681 : ! Check if this container has desired scalID
3682 0 : IF ( Lct%Dct%ScalID == ScalID ) THEN
3683 0 : cID = Lct%Dct%cID
3684 0 : EXIT
3685 : ENDIF
3686 :
3687 : ! Move to archived next line
3688 0 : Lct => Lct%NextCont
3689 : ENDDO
3690 :
3691 : ! Free pointer
3692 0 : Lct => NULL()
3693 :
3694 : ! cID must be positive!
3695 0 : IF ( cID <= 0 ) THEN
3696 0 : WRITE ( strID, * ) ScalID
3697 0 : MSG = 'Cannot find ScalID' // TRIM(strID)
3698 0 : PRINT *,'cID negative in HEMCO Get_cID'
3699 0 : PRINT *, TRIM(MSG)
3700 0 : RETURN
3701 : ENDIF
3702 :
3703 : ! Leave w/ success
3704 0 : RC = HCO_SUCCESS
3705 :
3706 : END SUBROUTINE Get_cID
3707 : !EOC
3708 : !------------------------------------------------------------------------------
3709 : ! Harmonized Emissions Component (HEMCO) !
3710 : !------------------------------------------------------------------------------
3711 : !BOP
3712 : !
3713 : ! !IROUTINE: ConfigList_AddCont
3714 : !
3715 : ! !DESCRIPTION: Subroutine ConfigList\_AddCont adds a new (blank) container to
3716 : ! the ConfigList list.
3717 : !\\
3718 : !\\
3719 : ! !INTERFACE:
3720 : !
3721 0 : SUBROUTINE ConfigList_AddCont( Lct, List )
3722 : !
3723 : ! !USES:
3724 : !
3725 : USE HCO_DATACONT_Mod, ONLY : DataCont_Init
3726 : USE HCO_DATACONT_Mod, ONLY : ListCont_Length
3727 : !
3728 : ! !INPUT/OUTPUT PARAMETERS:
3729 : !
3730 : TYPE(ListCont), POINTER :: Lct
3731 : TYPE(ListCont), POINTER :: List
3732 : !
3733 : ! !REVISION HISTORY:
3734 : ! 17 Sep 2013 - C. Keller: Initialization (update)
3735 : ! See https://github.com/geoschem/hemco for complete history
3736 : !EOP
3737 : !------------------------------------------------------------------------------
3738 : !BOC
3739 : !
3740 : ! !LOCAL VARIABLES:
3741 : !
3742 : INTEGER :: cID
3743 :
3744 : !======================================================================
3745 : ! ConfigList_AddCont begins here
3746 : !======================================================================
3747 :
3748 : ! Allocate container and create data structure.
3749 : ! The DataCont_Init call creates a new data container (type DataCont)
3750 : ! All HEMCO lists (ConfigList, ReadList, EmisList) point to this
3751 : ! container!
3752 0 : ALLOCATE ( Lct )
3753 0 : Lct%Dct => NULL()
3754 0 : Lct%NextCont => NULL()
3755 :
3756 : ! Get # of containers in list. Set new container ID (cID) to # of
3757 : ! containers + 1.
3758 0 : cID = ListCont_Length( List )
3759 0 : cID = cID + 1
3760 0 : CALL DataCont_Init ( Lct%Dct, cID )
3761 :
3762 : ! Connect blank container with ConfigList list.
3763 0 : Lct%NextCont => List
3764 0 : List => Lct
3765 :
3766 :
3767 0 : END SUBROUTINE ConfigList_AddCont
3768 : !EOC
3769 : !------------------------------------------------------------------------------
3770 : ! Harmonized Emissions Component (HEMCO) !
3771 : !------------------------------------------------------------------------------
3772 : !BOP
3773 : !
3774 : ! !IROUTINE: ScalID_Register
3775 : !
3776 : ! !DESCRIPTION: Subroutine ScalID\_Register adds the scale factor IDs ScalIDs
3777 : ! to the list of scale factor IDs.
3778 : !\\
3779 : !\\
3780 : ! !INTERFACE:
3781 : !
3782 0 : SUBROUTINE ScalID_Register( Dct, HcoConfig, RC )
3783 : !
3784 : ! !INPUT PARAMETERS:
3785 : !
3786 : TYPE(DataCont), POINTER :: Dct
3787 : TYPE(ConfigObj), POINTER :: HcoConfig
3788 : !
3789 : ! !INPUT/OUTPUT PARAMETERS:
3790 : !
3791 : INTEGER, INTENT(INOUT) :: RC
3792 : !
3793 : ! !REVISION HISTORY:
3794 : ! 10 Jan 2014 - C. Keller: Initialization (update)
3795 : ! See https://github.com/geoschem/hemco for complete history
3796 : !EOP
3797 : !------------------------------------------------------------------------------
3798 : !BOC
3799 : !
3800 : ! !LOCAL VARIABLES:
3801 : !
3802 : ! Scalars
3803 : INTEGER :: N, cID
3804 :
3805 : !======================================================================
3806 : ! ScalID_Register begins here
3807 : !======================================================================
3808 :
3809 : ! Check for every element of ScalIDs, if this scale factor ID is
3810 : ! already a member of ScalIDList. If not, add it.
3811 0 : DO N = 1, Dct%nScalID
3812 0 : IF ( Dct%Scal_cID(N) < 0 ) CYCLE
3813 :
3814 0 : CALL ScalID2List( HcoConfig%ScalIDList, Dct%Scal_cID(N), RC )
3815 0 : IF ( RC /= HCO_SUCCESS ) THEN
3816 0 : PRINT *,'Error in ScaleID2List called from HEMCO ScalID_Register (1)'
3817 0 : RETURN
3818 : ENDIF
3819 :
3820 : ! Replace scale factor ID with container ID.
3821 0 : CALL Get_cID ( Dct%Scal_cID(N), HcoConfig, cID, RC )
3822 0 : IF ( RC /= HCO_SUCCESS ) THEN
3823 0 : PRINT *,'Error in Get_cID called from HEMCO ScalID_Register (1)'
3824 0 : RETURN
3825 : ENDIF
3826 0 : Dct%Scal_cID(N) = cID
3827 :
3828 : ENDDO
3829 :
3830 : ! Also check for level scale factor IDs
3831 0 : IF ( Dct%levScalID1 > 0 ) THEN
3832 0 : CALL ScalID2List( HcoConfig%ScalIDList, Dct%levScalID1, RC )
3833 0 : IF ( RC /= HCO_SUCCESS ) THEN
3834 0 : PRINT *,'Error in ScalID2List called from HEMCO ScalID_Register (2)'
3835 0 : RETURN
3836 : ENDIF
3837 0 : CALL Get_cID ( Dct%levScalID1, HcoConfig, cID, RC )
3838 0 : IF ( RC /= HCO_SUCCESS ) THEN
3839 0 : PRINT *,'Error in Get_cID called from HEMCO ScalID_Register (2)'
3840 0 : RETURN
3841 : ENDIF
3842 0 : Dct%levScalID1 = cID
3843 : ENDIF
3844 0 : IF ( Dct%levScalID2 > 0 ) THEN
3845 0 : CALL ScalID2List( HcoConfig%ScalIDList, Dct%levScalID2, RC )
3846 0 : IF ( RC /= HCO_SUCCESS ) THEN
3847 0 : PRINT *,'Error in ScaleID2List called from HEMCO ScalID_Register (3)'
3848 0 : RETURN
3849 : ENDIF
3850 0 : CALL Get_cID ( Dct%levScalID2, HcoConfig, cID, RC )
3851 0 : IF ( RC /= HCO_SUCCESS ) THEN
3852 0 : PRINT *,'Error in Get_cID called from HEMCO ScalID_Register (3)'
3853 0 : RETURN
3854 : ENDIF
3855 0 : Dct%levScalID2 = cID
3856 : ENDIF
3857 :
3858 : ! Vector Scal_cID of this container now points to cIDs
3859 0 : Dct%Scal_cID_Set = .TRUE.
3860 :
3861 : ! Leave w/ success
3862 0 : RC = HCO_SUCCESS
3863 :
3864 : END SUBROUTINE ScalID_Register
3865 : !EOC
3866 : !------------------------------------------------------------------------------
3867 : ! Harmonized Emissions Component (HEMCO) !
3868 : !------------------------------------------------------------------------------
3869 : !BOP
3870 : !
3871 : ! !IROUTINE: ScalID2List
3872 : !
3873 : ! !DESCRIPTION: Subroutine ScalID2List adds the scale factor IDs ScalIDs
3874 : ! to the list of scale factor IDs.
3875 : !\\
3876 : !\\
3877 : ! !INTERFACE:
3878 : !
3879 0 : SUBROUTINE ScalID2List( ScalIDList, ID, RC )
3880 : !
3881 : ! !INPUT PARAMETERS:
3882 : !
3883 : TYPE(ScalIDCont), POINTER :: ScalIDList
3884 : INTEGER, INTENT(IN ) :: ID
3885 : !
3886 : ! !INPUT/OUTPUT PARAMETERS:
3887 : !
3888 : INTEGER, INTENT(INOUT) :: RC
3889 : !
3890 : ! !REVISION HISTORY:
3891 : ! 10 Jan 2014 - C. Keller: Initialization (update)
3892 : ! See https://github.com/geoschem/hemco for complete history
3893 : !EOP
3894 : !------------------------------------------------------------------------------
3895 : !BOC
3896 : !
3897 : ! !LOCAL VARIABLES:
3898 : !
3899 : ! Pointers
3900 : TYPE(ScalIDCont), POINTER :: NewScalIDCont
3901 : TYPE(ScalIDCont), POINTER :: TmpScalIDCont
3902 : TYPE(ScalIDCont), POINTER :: PrvScalIDCont
3903 :
3904 : ! Scalars
3905 : LOGICAL :: IsInList
3906 :
3907 : !======================================================================
3908 : ! ScalID2List begins here
3909 : !======================================================================
3910 :
3911 : ! Initialize
3912 0 : NewScalIDCont => NULL()
3913 0 : TmpScalIDCont => NULL()
3914 0 : PrvScalIDCont => NULL()
3915 :
3916 : ! Check for every element of ScalIDs, if this scale factor ID is
3917 : ! already a member of ScalIDList. If not, add it.
3918 :
3919 : ! Check if already in list
3920 0 : IsInList = .FALSE.
3921 0 : TmpScalIDCont => ScalIDList
3922 0 : PrvScalIDCont => TmpScalIDCont
3923 0 : DO WHILE ( ASSOCIATED(TmpScalIDCont) )
3924 0 : IF ( TmpScalIDCont%ScalID == ID ) THEN
3925 : IsInList = .TRUE.
3926 : EXIT
3927 : ENDIF
3928 0 : PrvScalIDCont => TmpScalIDCont
3929 0 : TmpScalIDCont => TmpScalIDCont%NEXT
3930 : ENDDO
3931 :
3932 : ! Add new container w/ this scal ID to (end of) list
3933 0 : IF ( .NOT. IsInList ) THEN
3934 0 : ALLOCATE ( NewScalIDCont )
3935 0 : NewScalIDCont%ScalID = ID
3936 0 : NewScalIDCont%NEXT => NULL()
3937 0 : IF ( .NOT. ASSOCIATED(PrvScalIDCont) ) THEN
3938 0 : ScalIDList => NewScalIDCont
3939 : ELSE
3940 0 : PrvScalIDCont%NEXT => NewScalIDCont
3941 : ENDIF
3942 : ! NewScalIDCont%NEXT => ScalIDList
3943 : ! ScalIDList => NewScalIDCont
3944 : ! NewScalIDCont => NULL()
3945 : ENDIF
3946 :
3947 : ! Cleanup
3948 0 : TmpScalIDCont => NULL()
3949 :
3950 : ! Leave w/ success
3951 0 : RC = HCO_SUCCESS
3952 :
3953 0 : END SUBROUTINE ScalID2List
3954 : !EOC
3955 : !------------------------------------------------------------------------------
3956 : ! Harmonized Emissions Component (HEMCO) !
3957 : !------------------------------------------------------------------------------
3958 : !BOP
3959 : !
3960 : ! !IROUTINE: ScalID_Cleanup
3961 : !
3962 : ! !DESCRIPTION: Subroutine ScalID\_Cleanup cleans up the internal ScalID
3963 : ! list.
3964 : !\\
3965 : !\\
3966 : ! !INTERFACE:
3967 : !
3968 0 : SUBROUTINE ScalID_Cleanup( ScalIDList )
3969 : !
3970 : ! !INPUT ARGUMENTS:
3971 : !
3972 : TYPE(ScalIDCont), POINTER :: ScalIDList
3973 : !
3974 : ! !REVISION HISTORY:
3975 : ! 10 Jan 2014 - C. Keller: Initialization (update)
3976 : ! See https://github.com/geoschem/hemco for complete history
3977 : !EOP
3978 : !------------------------------------------------------------------------------
3979 : !BOC
3980 : !
3981 : ! !LOCAL VARIABLES:
3982 : !
3983 : ! Pointers
3984 : TYPE(ScalIDCont), POINTER :: TmpScalIDCont
3985 : TYPE(ScalIDCont), POINTER :: NxtScalIDCont
3986 :
3987 : !======================================================================
3988 : ! ScalID_Cleanup begins here
3989 : !======================================================================
3990 :
3991 : ! Walk through list and remove each element
3992 0 : NxtScalIDCont => NULL()
3993 0 : TmpScalIDCont => ScalIDList
3994 0 : DO WHILE ( ASSOCIATED(TmpScalIDCont) )
3995 :
3996 0 : NxtScalIDCont => TmpScalIDCont%NEXT
3997 0 : TmpScalIDCont%NEXT => NULL()
3998 0 : DEALLOCATE ( TmpScalIDCont )
3999 :
4000 0 : TmpScalIDCont => NxtScalIDCont
4001 : ENDDO
4002 :
4003 : ! Exit
4004 0 : TmpScalIDCont => NULL()
4005 0 : NxtScalIDCont => NULL()
4006 0 : ScalIDList => NULL()
4007 :
4008 0 : END SUBROUTINE ScalID_Cleanup
4009 : !EOC
4010 : !------------------------------------------------------------------------------
4011 : ! Harmonized Emissions Component (HEMCO) !
4012 : !------------------------------------------------------------------------------
4013 : !BOP
4014 : !
4015 : ! !IROUTINE: SpecName_Register
4016 : !
4017 : ! !DESCRIPTION: Subroutine SpecName\_Register adds the species name SpecName
4018 : ! to the list of species names.
4019 : !\\
4020 : !\\
4021 : ! !INTERFACE:
4022 : !
4023 0 : SUBROUTINE SpecName_Register( HcoConfig, SpecName, RC )
4024 : !
4025 : ! !USES:
4026 : !
4027 : USE HCO_EXTLIST_MOD, ONLY : HCO_GetOpt
4028 : !
4029 : ! !INPUT PARAMETERS:
4030 : !
4031 : TYPE(ConfigObj), POINTER :: HcoConfig
4032 : CHARACTER(LEN=*), INTENT(IN ) :: SpecName
4033 : !
4034 : ! !INPUT/OUTPUT PARAMETERS:
4035 : !
4036 : INTEGER, INTENT(INOUT) :: RC
4037 : !
4038 : ! !REVISION HISTORY:
4039 : ! 10 Jan 2014 - C. Keller: Initialization (update)
4040 : ! See https://github.com/geoschem/hemco for complete history
4041 : !EOP
4042 : !------------------------------------------------------------------------------
4043 : !BOC
4044 : !
4045 : ! !LOCAL ARGUMENTS:
4046 : !
4047 : TYPE(SpecNameCont), POINTER :: NewSpecNameCont
4048 : TYPE(SpecNameCont), POINTER :: TmpSpecNameCont
4049 : LOGICAL :: IsInList
4050 :
4051 : !======================================================================
4052 : ! SpecName_Register begins here
4053 : !======================================================================
4054 :
4055 : ! Ignore if wildcard character. These fields will always be used!
4056 0 : IF ( TRIM(SpecName) == TRIM(HCO_GetOpt(HcoConfig%ExtList,'Wildcard')) ) THEN
4057 0 : RC = HCO_SUCCESS
4058 0 : RETURN
4059 : ENDIF
4060 :
4061 : ! Initialize
4062 0 : NewSpecNameCont => NULL()
4063 0 : TmpSpecNameCont => NULL()
4064 :
4065 : ! Check if already in list
4066 0 : IsInList = .FALSE.
4067 0 : TmpSpecNameCont => HcoConfig%SpecNameList
4068 0 : DO WHILE ( ASSOCIATED(TmpSpecNameCont) )
4069 0 : IF ( TRIM(TmpSpecNameCont%SpecName) == TRIM(SpecName) ) THEN
4070 0 : IsInList = .TRUE.
4071 0 : EXIT
4072 : ENDIF
4073 0 : TmpSpecNameCont => TmpSpecNameCont%NEXT
4074 : ENDDO
4075 :
4076 : ! Add new container w/ this scal ID to (beginning) of list
4077 : IF ( .NOT. IsInList ) THEN
4078 0 : ALLOCATE ( NewSpecNameCont )
4079 0 : NewSpecNameCont%SpecName = SpecName
4080 0 : NewSpecNameCont%NEXT => HcoConfig%SpecNameList
4081 0 : HcoConfig%SpecNameList => NewSpecNameCont
4082 0 : NewSpecNameCont => NULL()
4083 : ENDIF
4084 :
4085 : ! Cleanup
4086 0 : TmpSpecNameCont => NULL()
4087 :
4088 : ! Leave w/ success
4089 0 : RC = HCO_SUCCESS
4090 :
4091 0 : END SUBROUTINE SpecName_Register
4092 : !EOC
4093 : !------------------------------------------------------------------------------
4094 : ! Harmonized Emissions Component (HEMCO) !
4095 : !------------------------------------------------------------------------------
4096 : !BOP
4097 : !
4098 : ! !IROUTINE: SpecName_Cleanup
4099 : !
4100 : ! !DESCRIPTION: Subroutine SpecName\_Cleanup cleans up the internal SpecName
4101 : ! list.
4102 : !\\
4103 : !\\
4104 : ! !INTERFACE:
4105 : !
4106 0 : SUBROUTINE SpecName_Cleanup ( SpecNameList )
4107 : !
4108 : ! !INPUT/OUTPUT ARGUMENT:
4109 : !
4110 : TYPE(SpecNameCont), POINTER :: SpecNameList
4111 : !
4112 : ! !REVISION HISTORY:
4113 : ! 10 Jan 2014 - C. Keller: Initialization (update)
4114 : ! See https://github.com/geoschem/hemco for complete history
4115 : !EOP
4116 : !------------------------------------------------------------------------------
4117 : !BOC
4118 : !
4119 : ! !LOCAL ARGUMENTS:
4120 : !
4121 : ! Pointers
4122 : TYPE(SpecNameCont), POINTER :: TmpSpecNameCont
4123 : TYPE(SpecNameCont), POINTER :: NxtSpecNameCont
4124 :
4125 : !======================================================================
4126 : ! SpecName_Cleanup begins here
4127 : !======================================================================
4128 :
4129 : ! Initialize
4130 0 : TmpSpecNameCont => NULL()
4131 0 : NxtSpecNameCont => NULL()
4132 :
4133 : ! Walk through list and remove each element
4134 0 : TmpSpecNameCont => SpecNameList
4135 0 : DO WHILE ( ASSOCIATED(TmpSpecNameCont) )
4136 :
4137 0 : NxtSpecNameCont => TmpSpecNameCont%NEXT
4138 0 : TmpSpecNameCont%NEXT => NULL()
4139 0 : DEALLOCATE ( TmpSpecNameCont )
4140 :
4141 0 : TmpSpecNameCont => NxtSpecNameCont
4142 : ENDDO
4143 :
4144 : ! Exit
4145 0 : TmpSpecNameCont => NULL()
4146 0 : NxtSpecNameCont => NULL()
4147 0 : SpecNameList => NULL()
4148 :
4149 0 : END SUBROUTINE SpecName_Cleanup
4150 : !EOC
4151 : !------------------------------------------------------------------------------
4152 : ! Harmonized Emissions Component (HEMCO) !
4153 : !------------------------------------------------------------------------------
4154 : !BOP
4155 : !
4156 : ! !IROUTINE: Config_GetnSpecies
4157 : !
4158 : ! !DESCRIPTION: Function Config\_GetnSpecies is a wrapper function to
4159 : ! get the number of (unique) species names in SpecNameList.
4160 : !\\
4161 : !\\
4162 : ! !INTERFACE:
4163 : !
4164 0 : FUNCTION Config_GetnSpecies( HcoConfig ) RESULT( nSpecies )
4165 : !
4166 : ! !INPUT ARGUMENT:
4167 : !
4168 : TYPE(ConfigObj), POINTER :: HcoConfig
4169 : !
4170 : ! !RETURN VALUE:
4171 : !
4172 : INTEGER :: nSpecies
4173 : !
4174 : ! !REVISION HISTORY:
4175 : ! 10 Jan 2014 - C. Keller: Initialization (update)
4176 : ! See https://github.com/geoschem/hemco for complete history
4177 : !EOP
4178 : !------------------------------------------------------------------------------
4179 : !BOC
4180 : !
4181 : ! !LOCAL VARIABLES:
4182 : !
4183 : INTEGER :: THISRC
4184 :
4185 : !======================================================================
4186 : ! Config_GetnSpecies begins here
4187 : !======================================================================
4188 :
4189 0 : CALL Config_GetSpecAttr( HcoConfig, N=nSpecies, RC = THISRC )
4190 :
4191 0 : END FUNCTION Config_GetnSpecies
4192 : !EOC
4193 : !------------------------------------------------------------------------------
4194 : ! Harmonized Emissions Component (HEMCO) !
4195 : !------------------------------------------------------------------------------
4196 : !BOP
4197 : !
4198 : ! !IROUTINE: Config_GetSpecNames
4199 : !
4200 : ! !DESCRIPTION: Subroutine Config\_GetSpecNames is a wrapper routine to
4201 : ! obtain the list of (unique) species names defined in SpecNameList.
4202 : !\\
4203 : !\\
4204 : ! !INTERFACE:
4205 : !
4206 0 : SUBROUTINE Config_GetSpecNames( HcoConfig, SpecNames, nSpecies, RC )
4207 : !
4208 : ! !INPUT ARGUMENT:
4209 : !
4210 : TYPE(ConfigObj), POINTER :: HcoConfig
4211 : !
4212 : ! !OUTPUT PARAMTERS:
4213 : !
4214 : CHARACTER(LEN=*), POINTER :: SpecNames(:)
4215 : !
4216 : ! !INPUT/OUTPUT PARAMETERS:
4217 : !
4218 : INTEGER, INTENT(INOUT) :: nSpecies
4219 : INTEGER, INTENT(INOUT) :: RC
4220 : !
4221 : ! !REVISION HISTORY:
4222 : ! 10 Jan 2014 - C. Keller: Initialization (update)
4223 : ! See https://github.com/geoschem/hemco for complete history
4224 : !EOP
4225 : !------------------------------------------------------------------------------
4226 : !BOC
4227 : !======================================================================
4228 : ! Config_GetSpecNames begins here
4229 : !======================================================================
4230 :
4231 0 : CALL Config_GetSpecAttr( HcoConfig, N=nSpecies, SpecNames=SpecNames, RC=RC )
4232 :
4233 0 : END SUBROUTINE Config_GetSpecNames
4234 : !EOC
4235 : !------------------------------------------------------------------------------
4236 : ! Harmonized Emissions Component (HEMCO) !
4237 : !------------------------------------------------------------------------------
4238 : !BOP
4239 : !
4240 : ! !IROUTINE: Config_getSpecAttr
4241 : !
4242 : ! !DESCRIPTION: Subroutine Config\_GetSpecAttr returns the number of
4243 : ! species names N and the vector of species names SpecNames.
4244 : ! SpecNames must be of length nnSpecs, i.e. in order to obtain
4245 : ! SpecNames, Config\_getSpecAttr has to be called twice:
4246 : ! N = 0
4247 : ! CALL Config\_getSpecAttr ( N=N, RC=RC )
4248 : ! ALLOCATE(SpecNames(N))
4249 : ! CALL Config\_getSpecAttr ( N=N, SpecNames=SpecNames, RC=RC )
4250 : !\\
4251 : !\\
4252 : ! !INTERFACE:
4253 : !
4254 0 : SUBROUTINE Config_GetSpecAttr( HcoConfig, N, SpecNames, RC )
4255 : !
4256 : ! !INPUT ARGUMENT:
4257 : !
4258 : TYPE(ConfigObj), POINTER :: HcoConfig
4259 : !
4260 : ! !INPUT/OUTPUT PARAMETERS:
4261 : !
4262 : INTEGER, INTENT(INOUT) :: N
4263 : INTEGER, INTENT(INOUT) :: RC
4264 : !
4265 : ! !OUTPUT PARAMETERS:
4266 : !
4267 : CHARACTER(LEN=*), POINTER, OPTIONAL :: SpecNames(:)
4268 : !
4269 : ! !REVISION HISTORY:
4270 : ! 10 Jan 2014 - C. Keller: Initialization (update)
4271 : ! See https://github.com/geoschem/hemco for complete history
4272 : !EOP
4273 : !------------------------------------------------------------------------------
4274 : !BOC
4275 : !
4276 : ! !LOCAL VARIABLES:
4277 : !
4278 : TYPE(SpecNameCont), POINTER :: TmpSpecNameCont
4279 : INTEGER :: AS
4280 : CHARACTER(LEN=255), PARAMETER :: &
4281 : LOC = 'Config_GetSpecAttr (hco_config_mod.F90)'
4282 : CHARACTER(LEN=512) :: errMsg
4283 :
4284 : !======================================================================
4285 : ! Config_GetSpecAttr begins here
4286 : !======================================================================
4287 :
4288 : ! Initialize
4289 0 : TmpSpecNameCont => NULL()
4290 :
4291 : ! Eventually allocate pointer
4292 0 : IF ( PRESENT(SpecNames) ) THEN
4293 0 : IF ( .NOT. ASSOCIATED(SpecNames) ) THEN
4294 0 : IF ( N <= 0 ) THEN
4295 0 : errMsg = 'Cannot allocate SpecNames - N is size 0 or smaller'
4296 0 : CALL HCO_Error( errMsg, RC, thisLoc=LOC )
4297 0 : RETURN
4298 : ENDIF
4299 0 : ALLOCATE(SpecNames(N), STAT=AS )
4300 0 : IF ( AS/= 0 ) THEN
4301 0 : errMsg = 'Could not allocate the SpcNames array!'
4302 0 : CALL HCO_Error( errMsg, RC, thisLoc=LOC )
4303 0 : RETURN
4304 : ENDIF
4305 0 : SpecNames(:) = ''
4306 0 : ELSEIF ( SIZE(SpecNames) /= N ) THEN
4307 0 : errMsg = 'Size(SpecNames) does not match the passed N argument!'
4308 0 : CALL HCO_Error( errMsg, RC, thisLoc=LOC )
4309 0 : RETURN
4310 : ENDIF
4311 : ENDIF
4312 :
4313 : ! Init
4314 0 : N = 0
4315 :
4316 : ! Loop over entire list. Count number of containers and eventually
4317 : ! write out the species names.
4318 0 : TmpSpecNameCont => HcoConfig%SpecNameList
4319 0 : DO WHILE ( ASSOCIATED(TmpSpecNameCont) )
4320 0 : N = N + 1
4321 0 : IF ( PRESENT(SpecNames) ) THEN
4322 0 : SpecNames(N) = TRIM(TmpSpecNameCont%SpecName)
4323 : ENDIF
4324 0 : TmpSpecNameCont => TmpSpecNameCont%NEXT
4325 : ENDDO
4326 :
4327 : ! Cleanup and return w/ success
4328 0 : TmpSpecNameCont => NULL()
4329 :
4330 0 : RC = HCO_SUCCESS
4331 :
4332 0 : END SUBROUTINE Config_GetSpecAttr
4333 : !EOC
4334 : !------------------------------------------------------------------------------
4335 : ! Harmonized Emissions Component (HEMCO) !
4336 : !------------------------------------------------------------------------------
4337 : !BOP
4338 : !
4339 : ! !IROUTINE: Check_ContNames
4340 : !
4341 : ! !DESCRIPTION: Function Check\_Contnames compares the container names of
4342 : ! two containers, ignoring the name 'tags', i.e. ignoring everything that
4343 : ! follows double underscore (\_\_). For example, two containers with names
4344 : ! "EDGAR\_NOX\_\_PNT" and "EDGAR\_NOX\_\_MOB" are considered equal, while
4345 : ! "EDGAR\_NOX\_PNT" and "EDGAR\_NOX\_MOB" are not.
4346 : !\\
4347 : !\\
4348 : ! !INTERFACE:
4349 : !
4350 0 : FUNCTION Check_ContNames( Lct1, Lct2 ) RESULT( SameName )
4351 : !
4352 : ! !INPUT/OUTPUT PARAMETERS:
4353 : !
4354 : TYPE(ListCont), POINTER :: Lct1
4355 : TYPE(ListCont), POINTER :: Lct2
4356 : !
4357 : ! !RETURN VALUE:
4358 : !
4359 : LOGICAL :: SameName
4360 : !
4361 : ! !REVISION HISTORY:
4362 : ! 10 Jan 2014 - C. Keller: Initialization (update)
4363 : ! See https://github.com/geoschem/hemco for complete history
4364 : !EOP
4365 : !------------------------------------------------------------------------------
4366 : !BOC
4367 : !
4368 : ! !LOCAL VARIABLES:
4369 : !
4370 : CHARACTER(LEN=63) :: name1, name2
4371 : INTEGER :: idx
4372 :
4373 : !======================================================================
4374 : ! Check_ContNames begins here!
4375 : !======================================================================
4376 :
4377 0 : SameName = .FALSE.
4378 0 : name1 = 'a'
4379 0 : name2 = 'b'
4380 :
4381 0 : idx = INDEX( TRIM(Lct1%Dct%cName), '__' )
4382 0 : IF ( idx > 0 ) THEN
4383 0 : name1 = Lct1%Dct%cName(1:idx)
4384 : ELSE
4385 0 : name1 = Lct1%Dct%cName
4386 : ENDIF
4387 :
4388 0 : idx = INDEX( TRIM(Lct2%Dct%cName), '__' )
4389 0 : IF ( idx > 0 ) THEN
4390 0 : name2 = Lct2%Dct%cName(1:idx)
4391 : ELSE
4392 0 : name2 = Lct2%Dct%cName
4393 : ENDIF
4394 :
4395 0 : IF ( TRIM(name1) == TRIM(name2) ) THEN
4396 : SameName = .TRUE.
4397 : ELSE
4398 0 : SameName = .FALSE.
4399 : ENDIF
4400 :
4401 0 : END FUNCTION Check_ContNames
4402 : !EOC
4403 : !------------------------------------------------------------------------------
4404 : ! Harmonized Emissions Component (HEMCO) !
4405 : !------------------------------------------------------------------------------
4406 : !BOP
4407 : !
4408 : ! !IROUTINE: ExtractSrcDim
4409 : !
4410 : ! !DESCRIPTION: Subroutine ExtractSrcDim extracts the source dimension
4411 : ! attribute. Specifically, it checks if the field is expected to be 2D
4412 : ! (xy) or 3D. Default 3D data is xyz, but it is also possible to explicitly
4413 : ! define the number of vertical levels to be read, as well as the reading
4414 : ! direction (up or down). For example, 'xy1' will be interpreted as reading
4415 : ! only the first level, and 'xy27' will only read the first 27 levels. To
4416 : ! reverse the vertical axis, use e.g. 'xy-1' to read only the top level,
4417 : ! or 'xy-27' to read the top 27 levels, with the topmost level being put
4418 : ! into the surface level.
4419 : !\\
4420 : !\\
4421 : ! !INTERFACE:
4422 : !
4423 0 : SUBROUTINE ExtractSrcDim( HcoConfig, SrcDim, Dta, Lscal1, Lscal2, RC )
4424 : !
4425 : ! !INPUT PARAMETERS:
4426 : !
4427 : TYPE(ConfigObj), POINTER :: HcoConfig
4428 : CHARACTER(LEN=*), INTENT(IN ) :: SrcDim
4429 : TYPE(FileData), POINTER :: Dta
4430 : !
4431 : ! !OUTPUT PARAMETERS:
4432 : !
4433 : INTEGER, INTENT( OUT) :: Lscal1
4434 : INTEGER, INTENT( OUT) :: Lscal2
4435 : !
4436 : ! !INPUT/OUTPUT PARAMETERS:
4437 : !
4438 : INTEGER, INTENT(INOUT) :: RC
4439 : !
4440 : ! !REVISION HISTORY:
4441 : ! 20 May 2015 - C. Keller - Initial version
4442 : ! See https://github.com/geoschem/hemco for complete history
4443 : !EOP
4444 : !------------------------------------------------------------------------------
4445 : !BOC
4446 : !
4447 : ! !LOCAL VARIABLES:
4448 : !
4449 : INTEGER :: i, idx, idx2
4450 : INTEGER :: strLen
4451 : INTEGER :: EmisUnit
4452 : REAL(hp) :: EmisL
4453 : CHARACTER(LEN=255) :: str1, str2, tmpstr
4454 : CHARACTER(LEN=255) :: MSG
4455 : CHARACTER(LEN=255) :: LOC = 'ExtractSrcDim (hco_config_mod.F90)'
4456 :
4457 : !======================================================================
4458 : ! ExtractSrcDim begins here
4459 : !======================================================================
4460 :
4461 : msg = 'Illegal source dimension ' // TRIM(srcDim) // &
4462 : ' for file ' // TRIM(Dta%ncFile) // &
4463 0 : '. Valid entries are e.g. xy or xyz.'
4464 :
4465 : ! Init output
4466 0 : Lscal1 = -1
4467 0 : Lscal2 = -1
4468 :
4469 : ! See if there is an arbitrary additional dimension. This must be added
4470 : ! at the end of the string and be separated by a '+' sign
4471 0 : idx = INDEX( TRIM(srcDim), '+' )
4472 0 : IF ( idx > 0 ) THEN
4473 0 : str1 = srcDim(1:(idx-1))
4474 0 : str2 = srcDim((idx+1):LEN(srcDim))
4475 : ELSE
4476 0 : str1 = srcDim
4477 0 : str2 = ''
4478 : ENDIF
4479 :
4480 : ! 2D data:
4481 0 : IF ( TRIM(str1) == 'xy' .OR. TRIM(str1) == '-' ) THEN
4482 0 : Dta%SpaceDim = 2
4483 :
4484 : ! All other cases
4485 : ELSE
4486 : ! Character length
4487 0 : strLen = LEN(TRIM(str1))
4488 :
4489 : ! There must be at least 3 characters (e.g. xyz)
4490 0 : IF ( strLen < 3 ) THEN
4491 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
4492 0 : RETURN
4493 : ENDIF
4494 :
4495 : ! First two entries must be xy
4496 0 : IF ( str1(1:2) /= 'xy' ) THEN
4497 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
4498 0 : RETURN
4499 : ENDIF
4500 :
4501 : ! If third entry is 'L', this means we have 2D data that shall be put
4502 : ! into a particular level, e.g. xyL4 will cause the 2D data to be
4503 : ! emitted into level 4.
4504 0 : IF ( str1(3:3) == 'L' .OR. str1(3:3) == 'l' ) THEN
4505 0 : IF ( strLen < 4 ) THEN
4506 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
4507 0 : RETURN
4508 : ENDIF
4509 0 : Dta%SpaceDim = 2
4510 0 : Dta%EmisLmode = 1 ! Dilute emissions vertically
4511 :
4512 : ! Read levels to put emissions into:
4513 0 : i=4
4514 0 : IF ( str1(i:i) == '=' ) i = i + 1
4515 :
4516 : ! Reduce to data to be read
4517 0 : tmpstr = str1(i:strLen)
4518 :
4519 : ! Check if range of levels is provided, i.e. xyL=1:5
4520 0 : idx = INDEX( TRIM(tmpstr), ':' )
4521 :
4522 : ! If multiple levels are provided (e.g. xyL=1:5)
4523 0 : IF ( idx > 0 ) THEN
4524 :
4525 : ! Check for PBL flag. It is possible to emit stuff
4526 : ! from the PBL up to e.g. level 30 (xyL=PBL:30)
4527 : ! The call to ParseEmisL now returns three arguments: the emission
4528 : ! level, the emission unit, and the emission scale factor. Ignore
4529 : ! emission level and unit if scale factor is given.
4530 0 : CALL ParseEmisL( tmpstr(1:(idx-1)), EmisL, EmisUnit, Lscal1 )
4531 0 : Dta%EmisL1 = EmisL
4532 0 : Dta%EmisL1Unit = EmisUnit
4533 0 : CALL ParseEmisL( tmpstr((idx+1):LEN(tmpstr)), EmisL, EmisUnit, Lscal2 )
4534 0 : Dta%EmisL2 = EmisL
4535 0 : Dta%EmisL2Unit = EmisUnit
4536 0 : Dta%EmisLmode = 1
4537 :
4538 : ! If only one value is provided (e.g. xyL5, xyL=5, xyL*)
4539 : ELSE
4540 :
4541 : ! Check if wildcard provided, i.e. xyL*
4542 0 : idx = INDEX( TRIM(tmpstr), '*' )
4543 :
4544 : ! Wildcard tells HEMCO to emit same value to all emission levels
4545 : ! A scale factor should be applied to distribute the emissions
4546 : ! vertically
4547 0 : IF ( idx > 0 ) THEN
4548 :
4549 0 : Dta%EmisL1 = 1.0_hp
4550 0 : Dta%EmisL1Unit = HCO_EMISL_LEV
4551 0 : Dta%EmisL2 = 0.0_hp
4552 0 : Dta%EmisL2Unit = HCO_EMISL_TOP
4553 0 : Dta%EmisLmode = 2 ! Copy data to all levels
4554 :
4555 : ! Emissions are allocated to one level
4556 : ELSE
4557 :
4558 0 : CALL ParseEmisL( tmpstr, EmisL, EmisUnit, Lscal1 )
4559 0 : Dta%EmisL1 = EmisL
4560 0 : Dta%EmisL1Unit = EmisUnit
4561 0 : Lscal2 = Lscal1
4562 0 : Dta%EmisL2 = Dta%EmisL1
4563 0 : Dta%EmisL2Unit = Dta%EmisL1Unit
4564 :
4565 : ENDIF
4566 : ENDIF
4567 : ELSE
4568 :
4569 : ! If we get to here, it's 3D data
4570 0 : Dta%SpaceDim = 3
4571 :
4572 : ! The third entry determines the vertical dimension.
4573 : ! This can be 'z' (standard) or a number to explicitly define
4574 : ! the vertical extension and direction.
4575 0 : IF ( str1(3:3) /= 'z' ) THEN
4576 0 : READ(str1(3:strLen),*) Dta%Levels
4577 : ENDIF
4578 : ENDIF
4579 : ENDIF
4580 :
4581 : ! Eventually set additional dimension name and value
4582 0 : IF ( TRIM(str2) /= '' ) THEN
4583 : MSG = 'Cannot extract arbitrary dimension from ' &
4584 : // TRIM(srcDim) // ' for file ' // TRIM(Dta%ncFile) &
4585 : // ' - arbitrary dimensions must follow a `+` sign ' &
4586 0 : // 'and contain the name/value pair, e.g. xyz+"ens"=3'
4587 0 : idx = INDEX( TRIM(str2), '=' )
4588 0 : IF ( idx <= 0 ) THEN
4589 0 : CALL HCO_Error( msg, RC, thisLoc=LOC )
4590 0 : RETURN
4591 : ENDIF
4592 :
4593 : ! Extract dimension name. Eventually remove '"' character at
4594 : ! beginning
4595 0 : IF ( str2(1:1) == '"' .OR. &
4596 : str2(1:1) == '`' ) THEN
4597 0 : Dta%ArbDimName = str2(2:(idx-1))
4598 : ELSE
4599 0 : Dta%ArbDimName = str2(1:(idx-1))
4600 : ENDIF
4601 :
4602 : ! Extract dimension value. Eventually remove trailing '"'
4603 : ! character. The string value itself will be evaluated when
4604 : ! reading the file (in hcoio_dataread_mod.F90).
4605 0 : strlen = LEN(TRIM(str2))
4606 0 : IF ( str2(strlen:strlen) == '"' .OR. &
4607 : str2(strlen:strlen) == '`' ) THEN
4608 0 : Dta%ArbDimVal = str2((idx+1):(strlen-1))
4609 : ELSE
4610 0 : Dta%ArbDimVal = str2((idx+1):(strlen))
4611 : ENDIF
4612 :
4613 : ! Verbose
4614 0 : IF ( HcoConfig%amIRoot .AND. HCO_IsVerb(HcoConfig%Err ) ) THEN
4615 0 : WRITE(MSG,*) 'Will use additional dimension on file ', &
4616 0 : TRIM(Dta%ncFile), ': ', TRIM(Dta%ArbDimName), ' = ', &
4617 0 : TRIM(Dta%ArbDimVal)
4618 0 : CALL HCO_Msg( HcoConfig%Err, msg )
4619 : ENDIF
4620 : ENDIF
4621 :
4622 : ! Leave w/ success
4623 0 : RC = HCO_SUCCESS
4624 :
4625 0 : END SUBROUTINE ExtractSrcDim
4626 : !EOC
4627 : !------------------------------------------------------------------------------
4628 : ! Harmonized Emissions Component (HEMCO) !
4629 : !------------------------------------------------------------------------------
4630 : !BOP
4631 : !
4632 : ! !IROUTINE: ConfigInit
4633 : !
4634 : ! !DESCRIPTION: Subroutine ConfigInit is a wrapper routine to initialize the
4635 : ! HEMCO configuration object.
4636 : !\\
4637 : !\\
4638 : ! !INTERFACE:
4639 : !
4640 0 : SUBROUTINE ConfigInit ( HcoConfig, RC, nModelSpecies )
4641 : !
4642 : ! !INPUT PARAMETERS:
4643 : !
4644 : INTEGER, INTENT(IN), OPTIONAL :: nModelSpecies ! # model species
4645 : !
4646 : ! !INPUT/OUTPUT PARAMETERS:
4647 : !
4648 : TYPE(ConfigObj), POINTER :: HcoConfig
4649 : INTEGER, INTENT(INOUT) :: RC ! Success/fail
4650 : !
4651 : ! !REVISION HISTORY:
4652 : ! 16 Feb 2016 - C. Keller: Initialization (update)
4653 : ! See https://github.com/geoschem/hemco for complete history
4654 : !EOP
4655 : !------------------------------------------------------------------------------
4656 : !BOC
4657 : !
4658 : ! !LOCAL VARIABLES:
4659 : !
4660 : INTEGER :: I, AS
4661 : CHARACTER(LEN=255) :: thisLoc
4662 : CHARACTER(LEN=512) :: errMsg
4663 :
4664 : !=====================================================================
4665 : ! ConfigInit begins here!
4666 : !=====================================================================
4667 :
4668 0 : ALLOCATE(HcoConfig)
4669 0 : HcoConfig%ConfigFileName = ''
4670 0 : HcoConfig%ROOT = ''
4671 0 : HcoConfig%ConfigFileRead = .FALSE.
4672 0 : HcoConfig%ConfigList => NULL()
4673 0 : HcoConfig%ScalIDList => NULL()
4674 0 : HcoConfig%SpecNameList => NULL()
4675 0 : HcoConfig%ExtList => NULL()
4676 0 : HcoConfig%Err => NULL()
4677 :
4678 0 : IF ( PRESENT( nModelSpecies ) ) THEN
4679 :
4680 : ! Initialize strings
4681 0 : errMsg = ''
4682 0 : thisLoc = 'ConfigInit (in module hco_config_mod.F90)'
4683 :
4684 : ! Initialize vector w/ species information
4685 0 : HcoConfig%nModelSpc = nModelSpecies
4686 0 : IF ( nModelSpecies > 0 ) THEN
4687 0 : ALLOCATE ( HcoConfig%ModelSpc( nModelSpecies ), STAT=AS )
4688 0 : IF ( AS /= 0 ) THEN
4689 0 : errMsg = 'Could not allocate "ModelSpecies" array!'
4690 0 : CALL HCO_Error( errMsg, RC, thisLoc )
4691 0 : RETURN
4692 : ENDIF
4693 :
4694 : ! Initalize species information. The effective values for species
4695 : ! names, model IDs, etc. are set in the HEMCO-model interface
4696 : ! routine.
4697 0 : DO I = 1, nModelSpecies
4698 0 : HcoConfig%ModelSpc(I)%HcoID = I
4699 0 : HcoConfig%ModelSpc(I)%ModID = -1
4700 0 : HcoConfig%ModelSpc(I)%SpcName = ''
4701 : ENDDO
4702 : ENDIF
4703 :
4704 : ENDIF
4705 :
4706 : END SUBROUTINE ConfigInit
4707 : !EOC
4708 : !------------------------------------------------------------------------------
4709 : ! Harmonized Emissions Component (HEMCO) !
4710 : !------------------------------------------------------------------------------
4711 : !BOP
4712 : !
4713 : ! !IROUTINE: ParseEmisL
4714 : !
4715 : ! !DESCRIPTION: parses the emission level.
4716 : !\\
4717 : !\\
4718 : ! !INTERFACE:
4719 : !
4720 0 : SUBROUTINE ParseEmisL ( str, EmisL, EmisUnit, ScalID )
4721 : !
4722 : ! !INPUT PARAMETERS:
4723 : !
4724 : CHARACTER(LEN=*), INTENT(IN ) :: str
4725 : !
4726 : ! !INPUT/OUTPUT PARAMETERS:
4727 : !
4728 : REAL(hp), INTENT(OUT) :: EmisL
4729 : INTEGER, INTENT(OUT) :: EmisUnit
4730 : INTEGER, INTENT(OUT) :: ScalID
4731 : !
4732 : ! !REVISION HISTORY:
4733 : ! 09 May 2016 - C. Keller: Intial version.
4734 : ! See https://github.com/geoschem/hemco for complete history
4735 : !EOP
4736 : !------------------------------------------------------------------------------
4737 : !BOC
4738 : !
4739 : ! !LOCAL VARIABLES:
4740 : !
4741 : INTEGER :: nchar, idx
4742 :
4743 : !======================================================================
4744 : ! ParseEmisL begins here!
4745 : !======================================================================
4746 :
4747 : ! Init
4748 0 : EmisUnit = HCO_EMISL_LEV
4749 0 : ScalID = -1
4750 :
4751 0 : IF ( TRIM(str) == 'PBL' ) THEN
4752 0 : EmisL = 0.0_hp
4753 0 : EmisUnit = HCO_EMISL_PBL
4754 : ELSE
4755 : ! extract scale factor if string starts with 'SCAL' or 'scal'
4756 0 : nchar = LEN(str)
4757 0 : IF ( nchar > 4 ) THEN
4758 0 : IF ( str(1:4)=='SCAL' .OR. str(1:4)=='scal' ) THEN
4759 0 : READ(str(5:nchar),*) ScalID
4760 0 : EmisUnit = -1
4761 0 : EmisL = -1.0
4762 : ENDIF
4763 : ENDIF
4764 :
4765 : ! check for elevation unit flag (e.g. 1000m)
4766 0 : IF ( ScalID < 0 ) THEN
4767 0 : idx = INDEX(TRIM(str),'m')
4768 0 : IF ( idx > 0 ) THEN
4769 0 : READ(str(1:(idx-1)),*) EmisL
4770 0 : EmisUnit = HCO_EMISL_M
4771 : ELSE
4772 0 : READ(str,*) EmisL
4773 : ENDIF
4774 : ENDIF
4775 : ENDIF
4776 :
4777 0 : END SUBROUTINE ParseEmisL
4778 : !EOC
4779 : !------------------------------------------------------------------------------
4780 : ! Harmonized Emissions Component (HEMCO) !
4781 : !------------------------------------------------------------------------------
4782 : !BOP
4783 : !
4784 : ! !IROUTINE: CheckForDuplicateName
4785 : !
4786 : ! !DESCRIPTION: Subroutine CheckForDuplicateName checks if there is a
4787 : ! container in the container linked list that has the same name as the
4788 : ! name given as input argument.
4789 : !\\
4790 : !\\
4791 : ! !INTERFACE:
4792 : !
4793 0 : Subroutine CheckForDuplicateName( HcoConfig, cName, RC )
4794 : !
4795 : ! !INPUT ARGUMENT:
4796 : !
4797 : TYPE(ConfigObj) , POINTER :: HcoConfig ! HEMCO config obj
4798 : CHARACTER(LEN=*), INTENT(IN) :: cName
4799 : !
4800 : ! !OUTPUT ARGUMENT:
4801 : !
4802 : INTEGER, INTENT(INOUT) :: RC
4803 : !
4804 : ! !REVISION HISTORY:
4805 : ! 20 Jul 2018 - C. Keller: Initial version
4806 : ! See https://github.com/geoschem/hemco for complete history
4807 : !EOP
4808 : !------------------------------------------------------------------------------
4809 : !BOC
4810 : !
4811 : ! !LOCAL VARIABLES:
4812 : !
4813 : TYPE(ListCont), POINTER :: ThisLct => NULL()
4814 : LOGICAL :: Duplicate
4815 : CHARACTER(LEN=255) :: tmpName, thisLoc
4816 : CHARACTER(LEN=512) :: errMsg
4817 :
4818 : !======================================================================
4819 : ! CheckForDuplicateName begins here!
4820 : !======================================================================
4821 :
4822 : ! Init
4823 0 : RC = HCO_SUCCESS
4824 0 : errMsg = ''
4825 0 : thisLoc = 'CheckForDuplicateName (in module hco_config_mod.F90)'
4826 0 : Duplicate = .FALSE.
4827 :
4828 : ! Pass name to clear spaces
4829 0 : tmpName = ADJUSTL(cName)
4830 :
4831 : ! Walk through list and check for duplicate. Exit if found
4832 0 : ThisLct => HcoConfig%ConfigList
4833 0 : DO WHILE ( ASSOCIATED ( ThisLct ) )
4834 :
4835 : ! Skip if data container not defined
4836 0 : IF ( .NOT. ASSOCIATED(ThisLct%Dct) ) THEN
4837 0 : ThisLct => ThisLct%NextCont
4838 0 : CYCLE
4839 : ENDIF
4840 :
4841 : ! Check if this container has desired scalID
4842 0 : IF ( TRIM(ThisLct%Dct%cName) == TRIM(tmpName) ) THEN
4843 0 : Duplicate = .TRUE.
4844 0 : EXIT
4845 : ENDIF
4846 :
4847 : ! Move to next container
4848 0 : ThisLct => ThisLct%NextCont
4849 : ENDDO
4850 :
4851 : IF ( Duplicate ) THEN
4852 0 : errMsg = 'Error: HEMCO field already exists:'//TRIM(cName)
4853 0 : CALL HCO_Error( errMsg, RC, thisLoc )
4854 0 : RETURN
4855 : ENDIF
4856 :
4857 0 : END SUBROUTINE CheckForDuplicateName
4858 : !EOC
4859 : !------------------------------------------------------------------------------
4860 : ! GEOS-Chem Global Chemical Transport Model !
4861 : !------------------------------------------------------------------------------
4862 : !BOP
4863 : !
4864 : ! !IROUTINE: Hco_GetTagInfo
4865 : !
4866 : ! !DESCRIPTION: Subroutine HCO\_GETTAGINFO retrieves basic information about
4867 : ! tags given a wildcard string.
4868 : !\\
4869 : !\\
4870 : ! !INTERFACE:
4871 : !
4872 0 : SUBROUTINE Hco_GetTagInfo( tagID, HcoConfig, Found, &
4873 0 : RC, N, tagName, nTags )
4874 : !
4875 : ! !USES:
4876 : !
4877 : !
4878 : ! !INPUT PARAMETERS:
4879 : !
4880 : CHARACTER(LEN=*), INTENT(IN) :: tagID ! ID of tag (e.g. wildcard)
4881 : TYPE(ConfigObj), POINTER :: HcoConfig ! HEMCO Config object
4882 : INTEGER, OPTIONAL :: N ! index (1 to # tags)
4883 : !
4884 : ! !OUTPUT PARAMETERS:
4885 : !
4886 : LOGICAL, INTENT(OUT) :: Found ! Item found?
4887 : INTEGER, INTENT(OUT) :: RC ! Return code
4888 : CHARACTER(LEN=255), OPTIONAL :: tagName ! tag name for index N
4889 : INTEGER, OPTIONAL :: nTags ! # tags
4890 : !
4891 : ! !REMARKS:
4892 : !
4893 : ! !REVISION HISTORY:
4894 : ! 23 Oct 2018 - M. Sulprizio- Initial version based on routine Get_TagInfo in
4895 : ! GEOS-Chem's Headers/state_diag_mod.F90
4896 : ! See https://github.com/geoschem/hemco for complete history
4897 : !EOP
4898 : !------------------------------------------------------------------------------
4899 : !BOC
4900 : !
4901 : ! !LOCAL VARIABLES:
4902 : !
4903 : ! Scalars
4904 : INTEGER :: D, numTags
4905 : LOGICAL :: isNumTags, isTagName, isN
4906 :
4907 : ! Strings
4908 : CHARACTER(LEN=255) :: thisLoc, Nstr
4909 : CHARACTER(LEN=512) :: errMsg
4910 :
4911 : !=======================================================================
4912 : ! Hco_GetTagInfo begins here
4913 : !=======================================================================
4914 :
4915 : ! Initialize
4916 0 : errMsg = ''
4917 0 : thisLoc = 'Hco_Get_TagInfo (in module hco_config_mod.F90)'
4918 0 : Found = .TRUE.
4919 0 : numTags = 0
4920 :
4921 : ! Optional arguments present?
4922 0 : isN = PRESENT( N )
4923 0 : isTagName = PRESENT( TagName )
4924 0 : isNumTags = PRESENT( nTags )
4925 :
4926 : ! Exit with error if getting tag name but index not specified
4927 0 : IF ( isTagName .AND. .NOT. isN ) THEN
4928 0 : ErrMsg = 'Index must be specified if retrieving an individual tag name'
4929 0 : CALL HCO_Error( errMsg, RC, thisLoc )
4930 0 : RETURN
4931 : ENDIF
4932 :
4933 : !=======================================================================
4934 : ! Get number of tags
4935 : !=======================================================================
4936 0 : SELECT CASE( TRIM( tagId ) )
4937 : CASE( 'ALL' )
4938 0 : numTags = HcoConfig%nModelSpc
4939 : CASE( 'ADV' )
4940 0 : numTags = HcoConfig%nModelAdv
4941 : CASE DEFAULT
4942 0 : FOUND = .FALSE.
4943 : ErrMsg = 'Handling of tagId ' // TRIM(tagId) // &
4944 0 : ' is not implemented for getting number of tags'
4945 0 : CALL HCO_Error( errMsg, RC, thisLoc )
4946 0 : RETURN
4947 : END SELECT
4948 :
4949 : !=======================================================================
4950 : ! Sanity checks -- exit under certain conditions
4951 : !=======================================================================
4952 :
4953 : ! If not getting tag name then set nTags and exit
4954 0 : IF ( .NOT. isTagName ) THEN
4955 0 : nTags = numTags
4956 0 : RETURN
4957 : ENDIF
4958 :
4959 : ! Exit with error if index exceeds number of tags for this wildcard
4960 : IF ( isTagName .AND. .NOT. isN ) THEN
4961 : errMsg = &
4962 : 'Index must be greater than total number of tags for wildcard' &
4963 : // TRIM(tagId)
4964 : CALL HCO_Error( errMsg, RC, thisLoc )
4965 : RETURN
4966 : ENDIF
4967 :
4968 : !=======================================================================
4969 : ! Get mapping index
4970 : !=======================================================================
4971 0 : SELECT CASE( TRIM( tagID ) )
4972 : CASE( 'ALL', 'ADV' )
4973 0 : D = N
4974 : CASE DEFAULT
4975 0 : FOUND = .FALSE.
4976 : errMsg = 'Handling of tagId ' // TRIM( tagId ) // &
4977 0 : ' is not implemented for getting tag name'
4978 0 : CALL HCO_Error( errMsg, RC, thisLoc )
4979 0 : RETURN
4980 : END SELECT
4981 :
4982 : !=======================================================================
4983 : ! Return the tag name
4984 : !=======================================================================
4985 0 : tagName = HcoConfig%ModelSpc(D)%SpcName
4986 :
4987 : END SUBROUTINE Hco_GetTagInfo
4988 : !EOC
4989 : !------------------------------------------------------------------------------
4990 : ! GEOS-Chem Global Chemical Transport Model !
4991 : !------------------------------------------------------------------------------
4992 : !BOP
4993 : !
4994 : ! !IROUTINE: UpdateDtaProperties
4995 : !
4996 : ! !DESCRIPTION: Updates metdata about the current data container that is
4997 : ! being created (e.g. time cycle information, level information, etc.)
4998 : !\\
4999 : !\\
5000 : ! !INTERFACE:
5001 : !
5002 0 : SUBROUTINE UpdateDtaProperties( char1, char2, dctType, int3, &
5003 : separator, srcDim, tagCName, tmCycle, &
5004 : wildCard, HcoConfig, Lct, Dta, &
5005 : RC )
5006 : !
5007 : ! !INPUT PARAMETERS:
5008 : !
5009 : CHARACTER(LEN=*), INTENT(IN) :: char1 !
5010 : CHARACTER(LEN=1), INTENT(IN) :: char2 !
5011 : INTEGER, INTENT(IN) :: dctType ! 1=base; 2=scale; 3=mask
5012 : INTEGER, INTENT(IN) :: int3 !
5013 : CHARACTER(LEN=*), INTENT(IN) :: separator ! Separator character
5014 : CHARACTER(LEN=*), INTENT(IN) :: srcDim ! e.g. "xyz", "xy", etc.
5015 : CHARACTER(LEN=*), INTENT(IN) :: tagCName ! Contaniner name
5016 : CHARACTER(LEN=*), INTENT(IN) :: tmCycle ! Tioe cycle flag setting
5017 : CHARACTER(LEN=*), INTENT(IN) :: wildCard ! Wild card character
5018 : TYPE(ConfigObj), POINTER :: HcoConfig ! HEMCO configuration object
5019 : !
5020 : ! !INPUT/OUTPUT PARAMETERS:
5021 : !
5022 : TYPE(ListCont), POINTER :: Lct ! List container object
5023 : TYPE(FileData), POINTER :: Dta ! Data container object
5024 : !
5025 : ! !OUTPUT PARAMETERS:
5026 : !
5027 : INTEGER, INTENT(OUT) :: RC ! Success or failure
5028 : !
5029 : ! !REMARKS:
5030 : ! Abstracted from routine Config_ReadCont.
5031 : !EOP
5032 : !------------------------------------------------------------------------------
5033 : !BOC
5034 : !
5035 : ! !LOCAL VARIABLES:
5036 : !
5037 : ! Scalars
5038 : INTEGER :: levScal1
5039 : INTEGER :: levScal2
5040 : INTEGER :: nEdges
5041 :
5042 : ! Arrays
5043 : INTEGER :: splitInts(255)
5044 :
5045 : ! Strings
5046 : CHARACTER(LEN=255) :: thisLoc
5047 : CHARACTER(LEN=512) :: errMsg
5048 :
5049 : ! String arrays
5050 : CHARACTER(LEN=255) :: SubStrs(255)
5051 :
5052 : !========================================================================
5053 : ! UpdateDtaProperties begins here!
5054 : !========================================================================
5055 :
5056 : ! Initialize
5057 0 : RC = HCO_SUCCESS
5058 0 : levScal1 = 0
5059 0 : levScal2 = 0
5060 0 : nEdges = 0
5061 0 : splitInts = 0
5062 0 : errMsg = ''
5063 : thisLoc = &
5064 0 : ' -> at UpdateDtaProperties (in module HEMCO/src/Core/hco_config_mod.F90)'
5065 :
5066 : !========================================================================
5067 : ! Set time cycling behaviour. Possible values are:
5068 : ! - "C" : cycling <-- DEFAULT
5069 : ! - "CS" : cycling, skip if not exist
5070 : ! - "CY" : cycling, always use simulation year
5071 : ! - "CYS" : cycling, always use simulation yr, skip if not exist
5072 : ! - "R" : range
5073 : ! - "RA" : range, average outside
5074 : ! - "RF" : range, forced (error if not in range)
5075 : ! - "RFY" : range, forced, always use simulation year
5076 : ! - "RFY3 : range, forced, always use simulation year, 3-hourly
5077 : ! - "RY" : range, always use simulation year
5078 : ! - "E" : exact, read/query once
5079 : ! - "EF" : exact, forced (error if not exist), read/query once
5080 : ! - "EFY" : exact, forced, always use sim year
5081 : ! - "EFYO": exact, forced, always use sim year, read once
5082 : ! - "EC" : exact, read/query continuously (e.g. for ESMF interface)
5083 : ! - "ECF" : exact, forced, read/query continuously
5084 : ! - "EY" : exact, always use simulation year, read/query once
5085 : ! - "A" : average
5086 : ! - "I" : interpolate
5087 : ! - "ID" : interpolate, discontinuous dataset
5088 : !========================================================================
5089 :
5090 : ! Zero logical fields of Dta for safety's sake
5091 0 : Dta%MustFind = .FALSE.
5092 0 : Dta%UseSimYear = .FALSE.
5093 0 : Dta%Discontinuous = .FALSE.
5094 :
5095 : ! Look for time cycle values
5096 0 : SELECT CASE( TRIM( TmCycle ) )
5097 : CASE( "C" )
5098 0 : Dta%CycleFlag = HCO_CFLAG_CYCLE
5099 0 : Dta%MustFind = .TRUE.
5100 : CASE( "CS" )
5101 0 : Dta%CycleFlag = HCO_CFLAG_CYCLE
5102 0 : Dta%MustFind = .FALSE.
5103 : CASE( "CY" )
5104 0 : Dta%CycleFlag = HCO_CFLAG_CYCLE
5105 0 : Dta%MustFind = .TRUE.
5106 0 : Dta%UseSimYear = .TRUE.
5107 : CASE( "CYS" )
5108 0 : Dta%CycleFlag = HCO_CFLAG_CYCLE
5109 0 : Dta%MustFind = .FALSE.
5110 0 : Dta%UseSimYear = .TRUE.
5111 : CASE( "R" )
5112 0 : Dta%CycleFlag = HCO_CFLAG_RANGE
5113 : CASE( "RA" )
5114 0 : Dta%CycleFlag = HCO_CFLAG_RANGEAVG
5115 : CASE( "RF" )
5116 0 : Dta%CycleFlag = HCO_CFLAG_RANGE
5117 0 : Dta%MustFind = .TRUE.
5118 : CASE( "RFY" )
5119 0 : Dta%CycleFlag = HCO_CFLAG_RANGE
5120 0 : Dta%MustFind = .TRUE.
5121 0 : Dta%UseSimYear = .TRUE.
5122 : CASE( "RFY3" )
5123 0 : Dta%CycleFlag = HCO_CFLAG_RANGE
5124 0 : Dta%MustFind = .TRUE.
5125 0 : Dta%UseSimYear = .TRUE.
5126 0 : Dta%UpdtFlag = HCO_UFLAG_3HR
5127 : CASE( "RY" )
5128 0 : Dta%CycleFlag = HCO_CFLAG_RANGE
5129 0 : Dta%UseSimYear = .TRUE.
5130 : CASE( "E" )
5131 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5132 0 : Dta%UpdtFlag = HCO_UFLAG_ONCE
5133 : CASE( "EF" )
5134 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5135 0 : Dta%UpdtFlag = HCO_UFLAG_ONCE
5136 0 : Dta%MustFind = .TRUE.
5137 : CASE( "EFY" )
5138 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5139 0 : Dta%MustFind = .TRUE.
5140 0 : Dta%UseSimYear = .TRUE.
5141 : CASE( "EFYO" )
5142 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5143 0 : Dta%UpdtFlag = HCO_UFLAG_ONCE
5144 0 : Dta%MustFind = .TRUE.
5145 0 : Dta%UseSimYear = .TRUE.
5146 : CASE( "EC" )
5147 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5148 : CASE( "ECF" )
5149 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5150 0 : Dta%MustFind = .TRUE.
5151 : CASE( "EY" )
5152 0 : Dta%CycleFlag = HCO_CFLAG_EXACT
5153 0 : Dta%UpdtFlag = HCO_UFLAG_ONCE
5154 0 : Dta%UseSimYear = .TRUE.
5155 : CASE( "A" )
5156 0 : Dta%CycleFlag = HCO_CFLAG_AVERG
5157 : CASE( "I" )
5158 0 : Dta%CycleFlag = HCO_CFLAG_INTER
5159 : CASE( "ID" )
5160 0 : Dta%CycleFlag = HCO_CFLAG_INTER
5161 0 : Dta%Discontinuous = .TRUE.
5162 : CASE( "-" )
5163 0 : Dta%CycleFlag = HCO_CFLAG_CYCLE
5164 : CASE DEFAULT
5165 : errMsg = 'Invalid time cycling attribute: ' // tmCycle // &
5166 0 : ' - in ' // tagcName
5167 0 : CALL HCO_Error( errMsg, RC, thisLoc )
5168 0 : RETURN
5169 : END SELECT
5170 :
5171 : !========================================================================
5172 : ! Set space dimension. This will determine the dimension of the
5173 : ! data array vector, i.e. 3D or 2D. Different time slices will
5174 : ! be stored as different vector elements.
5175 : ! For 3D data, it is now possible to explicitly set the number
5176 : ! of vertical levels to be used, as well as the 'reading
5177 : ! direction' (up or down). These information is also extracted
5178 : ! from srcDim and will be stored in variable Dta%Levels.
5179 : ! (ckeller, 5/20/15)
5180 : ! ExtractSrcDim now also returns possible scale factors for the
5181 : ! injection level, which will be stored in container variable
5182 : ! levScalID1 (bottom level) and levScalID2 (top level).
5183 : !========================================================================
5184 0 : CALL ExtractSrcDim( HcoConfig, srcDim, Dta, levScal1, levScal2, RC )
5185 0 : IF ( RC /= HCO_SUCCESS ) THEN
5186 0 : errMsg = 'Error encountered in routine "ExtractSrcDim"!'
5187 0 : CALL HCO_Error( errMsg, RC, thisLoc )
5188 0 : RETURN
5189 : ENDIF
5190 :
5191 : ! Set level scale factor index
5192 0 : IF ( levScal1 > 0 ) Lct%Dct%levScalID1 = levScal1
5193 0 : IF ( levScal2 > 0 ) Lct%Dct%levScalID2 = levScal2
5194 :
5195 : !========================================================================
5196 : ! For scale factors: check if a mask is assigned to this scale factor.
5197 : ! In this case, pass mask ID to first slot of Scal_cID vector. This
5198 : ! value will be set to the container ID of the corresponding mask
5199 : ! field later on.
5200 : !========================================================================
5201 0 : IF ( DctType == HCO_DCTTYPE_SCAL .AND. Int3 > 0 ) THEN
5202 0 : ALLOCATE ( Lct%Dct%Scal_cID(1) )
5203 0 : Lct%Dct%Scal_cID(1) = Int3
5204 0 : Lct%Dct%nScalID = 1
5205 : ENDIF
5206 :
5207 : !========================================================================
5208 : ! For masks: extract grid box edges. These will be used later on to
5209 : ! determine if emissions have to be considered by this CPU.
5210 : !========================================================================
5211 0 : IF ( DctType == HCO_DCTTYPE_MASK ) THEN
5212 :
5213 : ! Extract grid box edges. Need to be four values.
5214 : CALL HCO_CharSplit( char1, separator, wildcard, &
5215 0 : splitInts, nEdges, RC )
5216 0 : IF ( RC /= HCO_SUCCESS ) THEN
5217 0 : errMsg = 'Error encountered in routine "HCO_CharSplit"!'
5218 0 : CALL HCO_Error( errMsg, RC, thisLoc )
5219 0 : RETURN
5220 : ENDIF
5221 0 : IF ( nEdges /= 4 ) THEN
5222 : errMsg = 'Cannot properly read mask coverage: ' // &
5223 0 : TRIM( Lct%Dct%cName )
5224 0 : CALL HCO_Error( errMsg, RC, thisLoc )
5225 0 : RETURN
5226 : ENDIF
5227 :
5228 : ! Save temporarily in year and month range. Will be
5229 : ! reset lateron.
5230 0 : Dta%ncYrs(1) = splitInts(1)
5231 0 : Dta%ncYrs(2) = splitInts(2)
5232 0 : Dta%ncMts(1) = splitInts(3)
5233 0 : Dta%ncMts(2) = splitInts(4)
5234 :
5235 : ! Make sure that masks are always being read if specified so.
5236 0 : IF ( char2 == 'y' .OR. char2 == 'Y' ) THEN
5237 0 : CALL ScalID2List( HcoConfig%ScalIDList, Lct%Dct%ScalID, RC )
5238 0 : IF ( RC /= HCO_SUCCESS ) THEN
5239 0 : errMsg = 'Error encountered in routine "ScalID2List"!'
5240 0 : CALL HCO_Error( errMsg, RC, thisLoc )
5241 0 : RETURN
5242 : ENDIF
5243 : ENDIF
5244 : ENDIF
5245 :
5246 0 : END SUBROUTINE UpdateDtaProperties
5247 : !EOC
5248 : END MODULE HCO_Config_Mod
|