prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  _DECAY_ENERGIES not cleared when changing chain in openmc.config
  <!--
  If you are a user of OpenMC and are running into trouble with the code or are
  seeking general user support, we highly recommend posting on the OpenMC
  discourse forum first. GitHub issues should be used specifically for bug reports
  and feature requests.
  
  https://openmc.discourse.group/
  
  -->
  
  ## Bug Description
  This causes incorrect sets of decay energies to be used. The PR which solves this has a more in-depth description of the problem.
  
  
  ## Steps to Reproduce
  Run two depletion calcs, each with a different chain. Then, try to postprocess the decay heats from each chain within the same python script by changing `openmc.config['chain_file']`. The decay heats will use energies from the first one we loaded, but not the second. This is because the decay heats are cached in `openmc/data/decay.py` and we're not clearing that dictionary upon changing the chain.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `openmc/config.py`
  Content:
  ```
  1 from collections.abc import MutableMapping
  2 import os
  3 from pathlib import Path
  4 import warnings
  5 
  6 from openmc.data import DataLibrary
  7 from openmc.data.decay import _DECAY_PHOTON_ENERGY
  8 
  9 __all__ = ["config"]
  10 
  11 
  12 class _Config(MutableMapping):
  13     def __init__(self, data=()):
  14         self._mapping = {}
  15         self.update(data)
  16 
  17     def __getitem__(self, key):
  18         return self._mapping[key]
  19 
  20     def __delitem__(self, key):
  21         del self._mapping[key]
  22         if key == 'cross_sections':
  23             del os.environ['OPENMC_CROSS_SECTIONS']
  24         elif key == 'mg_cross_sections':
  25             del os.environ['OPENMC_MG_CROSS_SECTIONS']
  26         elif key == 'chain_file':
  27             del os.environ['OPENMC_CHAIN_FILE']
  28             # Reset photon source data since it relies on chain file
  29             _DECAY_PHOTON_ENERGY.clear()
  30 
  31     def __setitem__(self, key, value):
  32         if key == 'cross_sections':
  33             # Force environment variable to match
  34             self._set_path(key, value)
  35             os.environ['OPENMC_CROSS_SECTIONS'] = str(value)
  36         elif key == 'mg_cross_sections':
  37             self._set_path(key, value)
  38             os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value)
  39         elif key == 'chain_file':
  40             self._set_path(key, value)
  41             os.environ['OPENMC_CHAIN_FILE'] = str(value)
  42             # Reset photon source data since it relies on chain file
  43             _DECAY_PHOTON_ENERGY.clear()
  44         else:
  45             raise KeyError(f'Unrecognized config key: {key}. Acceptable keys '
  46                            'are "cross_sections", "mg_cross_sections" and '
  47                            '"chain_file"')
  48 
  49     def __iter__(self):
  50         return iter(self._mapping)
  51 
  52     def __len__(self):
  53         return len(self._mapping)
  54 
  55     def __repr__(self):
  56         return repr(self._mapping)
  57 
  58     def _set_path(self, key, value):
  59         self._mapping[key] = p = Path(value)
  60         if not p.exists():
  61             warnings.warn(f"'{value}' does not exist.")
  62 
  63 
  64 def _default_config():
  65     """Return default configuration"""
  66     config = _Config()
  67 
  68     # Set cross sections using environment variable
  69     if "OPENMC_CROSS_SECTIONS" in os.environ:
  70         config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"]
  71     if "OPENMC_MG_CROSS_SECTIONS" in os.environ:
  72         config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"]
  73 
  74     # Set depletion chain
  75     chain_file = os.environ.get("OPENMC_CHAIN_FILE")
  76     if (chain_file is None and
  77         config.get('cross_sections') is not None and
  78         config['cross_sections'].exists()
  79     ):
  80         # Check for depletion chain in cross_sections.xml
  81         data = DataLibrary.from_xml(config['cross_sections'])
  82         for lib in reversed(data.libraries):
  83             if lib['type'] == 'depletion_chain':
  84                 chain_file = lib['path']
  85                 break
  86     if chain_file is not None:
  87         config['chain_file'] = chain_file
  88 
  89     return config
  90 
  91 
  92 config = _default_config()
  93
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/openmc/config.py b/openmc/config.py
  --- a/openmc/config.py
  +++ b/openmc/config.py
  @@ -4,7 +4,7 @@
   import warnings
   
   from openmc.data import DataLibrary
  -from openmc.data.decay import _DECAY_PHOTON_ENERGY
  +from openmc.data.decay import _DECAY_ENERGY, _DECAY_PHOTON_ENERGY
   
   __all__ = ["config"]
   
  @@ -41,6 +41,7 @@
               os.environ['OPENMC_CHAIN_FILE'] = str(value)
               # Reset photon source data since it relies on chain file
               _DECAY_PHOTON_ENERGY.clear()
  +            _DECAY_ENERGY.clear()
           else:
               raise KeyError(f'Unrecognized config key: {key}. Acceptable keys '
                              'are "cross_sections", "mg_cross_sections" and '
  @@ -76,7 +77,7 @@
       if (chain_file is None and
           config.get('cross_sections') is not None and
           config['cross_sections'].exists()
  -    ):
  +        ):
           # Check for depletion chain in cross_sections.xml
           data = DataLibrary.from_xml(config['cross_sections'])
           for lib in reversed(data.libraries):
  
verification_info: {"golden_diff": "diff --git a/openmc/config.py b/openmc/config.py\n--- a/openmc/config.py\n+++ b/openmc/config.py\n@@ -4,7 +4,7 @@\n import warnings\n \n from openmc.data import DataLibrary\n-from openmc.data.decay import _DECAY_PHOTON_ENERGY\n+from openmc.data.decay import _DECAY_ENERGY, _DECAY_PHOTON_ENERGY\n \n __all__ = [\"config\"]\n \n@@ -41,6 +41,7 @@\n             os.environ['OPENMC_CHAIN_FILE'] = str(value)\n             # Reset photon source data since it relies on chain file\n             _DECAY_PHOTON_ENERGY.clear()\n+            _DECAY_ENERGY.clear()\n         else:\n             raise KeyError(f'Unrecognized config key: {key}. Acceptable keys '\n                            'are \"cross_sections\", \"mg_cross_sections\" and '\n@@ -76,7 +77,7 @@\n     if (chain_file is None and\n         config.get('cross_sections') is not None and\n         config['cross_sections'].exists()\n-    ):\n+        ):\n         # Check for depletion chain in cross_sections.xml\n         data = DataLibrary.from_xml(config['cross_sections'])\n         for lib in reversed(data.libraries):\n", "issue": "_DECAY_ENERGIES not cleared when changing chain in openmc.config\n<!--\r\nIf you are a user of OpenMC and are running into trouble with the code or are\r\nseeking general user support, we highly recommend posting on the OpenMC\r\ndiscourse forum first. GitHub issues should be used specifically for bug reports\r\nand feature requests.\r\n\r\nhttps://openmc.discourse.group/\r\n\r\n-->\r\n\r\n## Bug Description\r\nThis causes incorrect sets of decay energies to be used. The PR which solves this has a more in-depth description of the problem.\r\n\r\n\r\n## Steps to Reproduce\r\nRun two depletion calcs, each with a different chain. Then, try to postprocess the decay heats from each chain within the same python script by changing `openmc.config['chain_file']`. The decay heats will use energies from the first one we loaded, but not the second. This is because the decay heats are cached in `openmc/data/decay.py` and we're not clearing that dictionary upon changing the chain.\r\n\n", "before_files": [{"content": "from collections.abc import MutableMapping\nimport os\nfrom pathlib import Path\nimport warnings\n\nfrom openmc.data import DataLibrary\nfrom openmc.data.decay import _DECAY_PHOTON_ENERGY\n\n__all__ = [\"config\"]\n\n\nclass _Config(MutableMapping):\n    def __init__(self, data=()):\n        self._mapping = {}\n        self.update(data)\n\n    def __getitem__(self, key):\n        return self._mapping[key]\n\n    def __delitem__(self, key):\n        del self._mapping[key]\n        if key == 'cross_sections':\n            del os.environ['OPENMC_CROSS_SECTIONS']\n        elif key == 'mg_cross_sections':\n            del os.environ['OPENMC_MG_CROSS_SECTIONS']\n        elif key == 'chain_file':\n            del os.environ['OPENMC_CHAIN_FILE']\n            # Reset photon source data since it relies on chain file\n            _DECAY_PHOTON_ENERGY.clear()\n\n    def __setitem__(self, key, value):\n        if key == 'cross_sections':\n            # Force environment variable to match\n            self._set_path(key, value)\n            os.environ['OPENMC_CROSS_SECTIONS'] = str(value)\n        elif key == 'mg_cross_sections':\n            self._set_path(key, value)\n            os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value)\n        elif key == 'chain_file':\n            self._set_path(key, value)\n            os.environ['OPENMC_CHAIN_FILE'] = str(value)\n            # Reset photon source data since it relies on chain file\n            _DECAY_PHOTON_ENERGY.clear()\n        else:\n            raise KeyError(f'Unrecognized config key: {key}. Acceptable keys '\n                           'are \"cross_sections\", \"mg_cross_sections\" and '\n                           '\"chain_file\"')\n\n    def __iter__(self):\n        return iter(self._mapping)\n\n    def __len__(self):\n        return len(self._mapping)\n\n    def __repr__(self):\n        return repr(self._mapping)\n\n    def _set_path(self, key, value):\n        self._mapping[key] = p = Path(value)\n        if not p.exists():\n            warnings.warn(f\"'{value}' does not exist.\")\n\n\ndef _default_config():\n    \"\"\"Return default configuration\"\"\"\n    config = _Config()\n\n    # Set cross sections using environment variable\n    if \"OPENMC_CROSS_SECTIONS\" in os.environ:\n        config['cross_sections'] = os.environ[\"OPENMC_CROSS_SECTIONS\"]\n    if \"OPENMC_MG_CROSS_SECTIONS\" in os.environ:\n        config['mg_cross_sections'] = os.environ[\"OPENMC_MG_CROSS_SECTIONS\"]\n\n    # Set depletion chain\n    chain_file = os.environ.get(\"OPENMC_CHAIN_FILE\")\n    if (chain_file is None and\n        config.get('cross_sections') is not None and\n        config['cross_sections'].exists()\n    ):\n        # Check for depletion chain in cross_sections.xml\n        data = DataLibrary.from_xml(config['cross_sections'])\n        for lib in reversed(data.libraries):\n            if lib['type'] == 'depletion_chain':\n                chain_file = lib['path']\n                break\n    if chain_file is not None:\n        config['chain_file'] = chain_file\n\n    return config\n\n\nconfig = _default_config()\n", "path": "openmc/config.py"}], "after_files": [{"content": "from collections.abc import MutableMapping\nimport os\nfrom pathlib import Path\nimport warnings\n\nfrom openmc.data import DataLibrary\nfrom openmc.data.decay import _DECAY_ENERGY, _DECAY_PHOTON_ENERGY\n\n__all__ = [\"config\"]\n\n\nclass _Config(MutableMapping):\n    def __init__(self, data=()):\n        self._mapping = {}\n        self.update(data)\n\n    def __getitem__(self, key):\n        return self._mapping[key]\n\n    def __delitem__(self, key):\n        del self._mapping[key]\n        if key == 'cross_sections':\n            del os.environ['OPENMC_CROSS_SECTIONS']\n        elif key == 'mg_cross_sections':\n            del os.environ['OPENMC_MG_CROSS_SECTIONS']\n        elif key == 'chain_file':\n            del os.environ['OPENMC_CHAIN_FILE']\n            # Reset photon source data since it relies on chain file\n            _DECAY_PHOTON_ENERGY.clear()\n\n    def __setitem__(self, key, value):\n        if key == 'cross_sections':\n            # Force environment variable to match\n            self._set_path(key, value)\n            os.environ['OPENMC_CROSS_SECTIONS'] = str(value)\n        elif key == 'mg_cross_sections':\n            self._set_path(key, value)\n            os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value)\n        elif key == 'chain_file':\n            self._set_path(key, value)\n            os.environ['OPENMC_CHAIN_FILE'] = str(value)\n            # Reset photon source data since it relies on chain file\n            _DECAY_PHOTON_ENERGY.clear()\n            _DECAY_ENERGY.clear()\n        else:\n            raise KeyError(f'Unrecognized config key: {key}. Acceptable keys '\n                           'are \"cross_sections\", \"mg_cross_sections\" and '\n                           '\"chain_file\"')\n\n    def __iter__(self):\n        return iter(self._mapping)\n\n    def __len__(self):\n        return len(self._mapping)\n\n    def __repr__(self):\n        return repr(self._mapping)\n\n    def _set_path(self, key, value):\n        self._mapping[key] = p = Path(value)\n        if not p.exists():\n            warnings.warn(f\"'{value}' does not exist.\")\n\n\ndef _default_config():\n    \"\"\"Return default configuration\"\"\"\n    config = _Config()\n\n    # Set cross sections using environment variable\n    if \"OPENMC_CROSS_SECTIONS\" in os.environ:\n        config['cross_sections'] = os.environ[\"OPENMC_CROSS_SECTIONS\"]\n    if \"OPENMC_MG_CROSS_SECTIONS\" in os.environ:\n        config['mg_cross_sections'] = os.environ[\"OPENMC_MG_CROSS_SECTIONS\"]\n\n    # Set depletion chain\n    chain_file = os.environ.get(\"OPENMC_CHAIN_FILE\")\n    if (chain_file is None and\n        config.get('cross_sections') is not None and\n        config['cross_sections'].exists()\n        ):\n        # Check for depletion chain in cross_sections.xml\n        data = DataLibrary.from_xml(config['cross_sections'])\n        for lib in reversed(data.libraries):\n            if lib['type'] == 'depletion_chain':\n                chain_file = lib['path']\n                break\n    if chain_file is not None:\n        config['chain_file'] = chain_file\n\n    return config\n\n\nconfig = _default_config()\n", "path": "openmc/config.py"}]}