Repository: ESMCI/cime

Issue:
NLCOMP has an error when namelist contain *

CAM namelists can have fields which contain *.  When they do, NLCOMP exits with the following error. We are using cime5.2.0-alpha.22.

```
2017-02-02` 13:55:16: Exception during namelist operations:
ERROR: Incorrect usage of multiplication in token ''O3_Prod = NO_HO2 + CH3O2_NO + PO2_NO + CH3CO3_NO + C2H5O2_NO + .92*ISOPAO2_NO + .92*ISOPBO2_NO + MACRO2_NOa + MCO3_NO + C3H7O2_NO + RO2_NO + XO2_NO + .9*TOLO2_NO &''
Traceback (most recent call last):
  File "/glade/u/home/fvitt/camdev/chem_cam5_4_106/cime/scripts/Tools/../../utils/python/CIME/case_cmpgen_namelists.py", line 123, in case_cmpgen_namelists
    success, output = _do_full_nl_comp(case, test_name, compare_name, baseline_root)
  File "/glade/u/home/fvitt/camdev/chem_cam5_4_106/cime/scripts/Tools/../../utils/python/CIME/case_cmpgen_namelists.py", line 44, in _do_full_nl_comp
    if is_namelist_file(item):
  File "/glade/u/home/fvitt/camdev/chem_cam5_4_106/cime/scripts/Tools/../../utils/python/CIME/compare_namelists.py", line 540, in is_namelist_file
    assert "does not appear to be a namelist file" in str(e), str(e)
AssertionError: ERROR: Incorrect usage of multiplication in token ''O3_Prod = NO_HO2 + CH3O2_NO + PO2_NO + CH3CO3_NO + C2H5O2_NO + .92*ISOPAO2_NO + .92*ISOPBO2_NO + MACRO2_NOa + MCO3_NO + C3H7O2_NO + RO2_NO + XO2_NO + .9*TOLO2_NO &'`


Discussion:

Resolving patch:
diff --git a/utils/python/CIME/compare_namelists.py b/utils/python/CIME/compare_namelists.py
--- a/utils/python/CIME/compare_namelists.py
+++ b/utils/python/CIME/compare_namelists.py
@@ -71,11 +71,15 @@ def _interpret_value(value_str, filename):
         new_tokens = []
         for token in tokens:
             if "*" in token:
-                # the following ensure that the following to namelist settings trigger a match
-                # nmlvalue = 1,1,1 versus nmlvalue = 3*1
-                sub_tokens = [item.strip() for item in token.split("*")]
-                expect(len(sub_tokens) == 2, "Incorrect usage of multiplication in token '%s'" % token)
-                new_tokens.extend([sub_tokens[1]] * int(sub_tokens[0]))
+                try:
+                    # the following ensure that the following to namelist settings trigger a match
+                    # nmlvalue = 1,1,1 versus nmlvalue = 3*1
+                    sub_tokens = [item.strip() for item in token.split("*")]
+                    expect(len(sub_tokens) == 2, "Incorrect usage of multiplication in token '%s'" % token)
+                    new_tokens.extend([sub_tokens[1]] * int(sub_tokens[0]))
+                except:
+                    # User probably did not intend to use the * operator as a namelist multiplier
+                    new_tokens.append(token)
             else:
                 new_tokens.append(token)
 
@@ -112,6 +116,14 @@ def _parse_namelists(namelist_lines, filename):
     >>> _parse_namelists(teststr.splitlines(), 'foo')
     OrderedDict([('nml', OrderedDict([('val', "'foo'"), ('aval', ["'one'", "'two'", "'three'"]), ('maval', ["'one'", "'two'", "'three'", "'four'"]), ('dval', OrderedDict([('one', 'two'), ('three', 'four')])), ('mdval', OrderedDict([('one', 'two'), ('three', 'four'), ('five', 'six')])), ('nval', '1850')])), ('nml2', OrderedDict([('val2', '.false.')]))])
 
+    >>> teststr = '''&fire_emis_nl
+    ... fire_emis_factors_file = 'fire_emis_factors_c140116.nc'
+    ... fire_emis_specifier = 'bc_a1 = BC', 'pom_a1 = 1.4*OC', 'pom_a2 = A*B*C', 'SO2 = SO2'
+    ... /
+    ... '''
+    >>> _parse_namelists(teststr.splitlines(), 'foo')
+    OrderedDict([('fire_emis_nl', OrderedDict([('fire_emis_factors_file', "'fire_emis_factors_c140116.nc'"), ('fire_emis_specifier', ["'bc_a1 = BC'", "'pom_a1 = 1.4*OC'", "'pom_a2 = A*B*C'", "'SO2 = SO2'"])]))])
+
     >>> _parse_namelists('blah', 'foo')
     Traceback (most recent call last):
         ...


Test patch: