Repository: openmc-dev/openmc

Issue:
module 'openmc' has no attribute 'lib'
When running a previously working example on the develop branch a new error appears.

![Screenshot from 2021-10-25 09-43-02](https://user-images.githubusercontent.com/8583900/138663657-0b237214-4f8a-448e-99a3-8a80a6b6c702.png)

To reproduce I've been running this is jupyter lab (hence the ! signs to run terminal commands)

```python
import openmc
import json
import os

# MATERIALS

breeder_material = openmc.Material(1, "PbLi")  # Pb84.2Li15.8
breeder_material.add_element('Pb', 84.2, percent_type='ao')
breeder_material.add_element('Li', 15.8, percent_type='ao', enrichment=50.0, enrichment_target='Li6', enrichment_type='ao')  # 50% enriched
breeder_material.set_density('atom/b-cm', 3.2720171e-2)  # around 11 g/cm3


steel = openmc.Material(name='steel')
steel.set_density('g/cm3', 7.75)
steel.add_element('Fe', 0.95, percent_type='wo')
steel.add_element('C', 0.05, percent_type='wo')

mats = openmc.Materials([breeder_material, steel])


# GEOMETRY

# surfaces
vessel_inner = openmc.Sphere(r=500)
first_wall_outer_surface = openmc.Sphere(r=510)
breeder_blanket_outer_surface = openmc.Sphere(r=610, boundary_type='vacuum')


# cells
inner_vessel_region = -vessel_inner
inner_vessel_cell = openmc.Cell(region=inner_vessel_region)

first_wall_region = -first_wall_outer_surface & +vessel_inner
first_wall_cell = openmc.Cell(region=first_wall_region)
first_wall_cell.fill = steel

breeder_blanket_region = +first_wall_outer_surface & -breeder_blanket_outer_surface
breeder_blanket_cell = openmc.Cell(region=breeder_blanket_region)
breeder_blanket_cell.fill = breeder_material

universe = openmc.Universe(cells=[inner_vessel_cell, first_wall_cell, breeder_blanket_cell])
geom = openmc.Geometry(universe)


# SIMULATION SETTINGS

# Instantiate a Settings object
sett = openmc.Settings()
sett.batches = 10
sett.inactive = 0
sett.particles = 500
sett.run_mode = 'fixed source'

# Create a DT point source
source = openmc.Source()
source.space = openmc.stats.Point((0, 0, 0))
source.angle = openmc.stats.Isotropic()
source.energy = openmc.stats.Discrete([14e6], [1])
sett.source = source


tallies = openmc.Tallies()

# added a cell tally for tritium production
cell_filter = openmc.CellFilter(breeder_blanket_cell)
tbr_tally = openmc.Tally(name='TBR')
tbr_tally.filters = [cell_filter]
tbr_tally.scores = ['(n,Xt)']  # Where X is a wildcard character, this catches any tritium production
tallies.append(tbr_tally)

# Run OpenMC!
model = openmc.model.Model(geom, mats, sett, tallies)
!rm *.h5
sp_filename = model.run()
```

However when exporting the xml files and running using the executable then everything works
```python
model.export_to_xml()
!openmc
```


Discussion:
Oof. I did that. I'll get a fix in today. Sorry about that. In the meantime it will work if you explicitly import openmc.lib in your session

Resolving patch:
diff --git a/openmc/model/model.py b/openmc/model/model.py
--- a/openmc/model/model.py
+++ b/openmc/model/model.py
@@ -1,11 +1,8 @@
 from collections.abc import Iterable
-import operator
 import os
 from pathlib import Path
 from numbers import Integral
 import time
-import warnings
-import subprocess
 from contextlib import contextmanager
 
 import h5py
@@ -137,7 +134,11 @@ def plots(self):
 
     @property
     def is_initialized(self):
-        return openmc.lib.is_initialized
+        try:
+            import openmc.lib
+            return openmc.lib.is_initialized
+        except ImportError:
+            return False
 
     @geometry.setter
     def geometry(self, geometry):
@@ -235,6 +236,8 @@ def init_lib(self, threads=None, geometry_debug=False, restart_file=None,
             MPI intracommunicator
         """
 
+        import openmc.lib
+
         # TODO: right now the only way to set most of the above parameters via
         # the C API are at initialization time despite use-cases existing to
         # set them for individual runs. For now this functionality is exposed
@@ -273,6 +276,8 @@ def finalize_lib(self):
 
         """
 
+        import openmc.lib
+
         openmc.lib.finalize()
 
     def deplete(self, timesteps, method='cecm', final_step=True,
@@ -409,6 +414,8 @@ def import_properties(self, filename):
         openmc.lib.export_properties
 
         """
+        import openmc.lib
+
         cells = self.geometry.get_all_cells()
         materials = self.geometry.get_all_materials()
 
@@ -512,7 +519,8 @@ def run(self, particles=None, threads=None, geometry_debug=False,
                 for arg_name, arg, default in zip(
                     ['threads', 'geometry_debug', 'restart_file', 'tracks'],
                     [threads, geometry_debug, restart_file, tracks],
-                    [None, False, None, False]):
+                    [None, False, None, False]
+                ):
                     if arg != default:
                         msg = f"{arg_name} must be set via Model.is_initialized(...)"
                         raise ValueError(msg)
@@ -688,12 +696,13 @@ def _change_py_lib_attribs(self, names_or_ids, value, obj_type,
         if obj_type == 'cell':
             by_name = self._cells_by_name
             by_id = self._cells_by_id
-            obj_by_id = openmc.lib.cells
+            if self.is_initialized:
+                obj_by_id = openmc.lib.cells
         else:
             by_name = self._materials_by_name
             by_id = self._materials_by_id
-            obj_by_id = openmc.lib.materials
-
+            if self.is_initialized:
+                obj_by_id = openmc.lib.materials
         # Get the list of ids to use if converting from names and accepting
         # only values that have actual ids
         ids = []


Test patch: