def databaseFactory(dbName: str, permission: str, version: Optional[str] = None): """ Return an appropriate object for interacting with a database file. Parameters ---------- dbName: str Path to db file, e.g. `baseCase.h5` permission: str String defining permission, `r` for read only. See armi.bookeeping.db.permissions version: str, optional Version of database you want to read or write. In many cases ARMI will auto-detect. For advanced users. Notes ----- This is not a proper factory, as the different database versions do not present a common interface. However, this is useful code, since it at least creates an object based on some knowledge of how to probe around. This allows client code to just interrogate the type of the returned object to figure out to do based on whatever it needs. """ import h5py # if it's not an hdf5 file, we dont even know where to start... if os.path.splitext(dbName)[1] != ".h5": raise RuntimeError("Unknown database format for {}".format(dbName)) if permission in permissions.Permissions.read: if version is not None: raise ValueError("Cannot specify version when reading a database.") # probe for the database version. We started adding these with "database 3", so if # databaseVersion is not present, assume it's the "old" version version = "2" tempDb = h5py.File(dbName, "r") if "databaseVersion" in tempDb.attrs: version = tempDb.attrs["databaseVersion"] del tempDb majorversion = version.split(".")[0] if version else "2" if majorversion == "2": return XTViewDatabase(dbName, permission) if majorversion == "3": return Database3(dbName, permission) raise ValueError( "Unable to determine Database version for {}".format(dbName)) elif permission in permissions.Permissions.write: majorversion = version.split(".")[0] if version else "3" if majorversion == "2": return XTViewDatabase(dbName, permission) if majorversion == "3": return Database3(dbName, permission)
def test_variousTypesWork(self): with Database3(self.dbName, "r") as db: r2 = db.load(1, 3) b1 = self.r.core.getFirstBlock(Flags.FUEL) b2 = r2.core.getFirstBlock(Flags.FUEL) self.assertIsInstance(b1.p.mgFlux, numpy.ndarray) self.assertIsInstance(b2.p.mgFlux, numpy.ndarray) assert_allclose(b1, b2) c1 = b1.getComponent(Flags.FUEL) c2 = b2.getComponent(Flags.FUEL) self.assertIsInstance(c1.p.numberDensities, dict) self.assertIsInstance(c2.p.numberDensities, dict) keys1 = set(c1.p.numberDensities.keys()) keys2 = set(c2.p.numberDensities.keys()) self.assertEqual(keys1, keys2) numDensVec1, numDensVec2 = [], [] for k in keys1: numDensVec1.append(c1.p.numberDensities[k]) numDensVec2.append(c2.p.numberDensities[k]) assert_allclose(numDensVec1, numDensVec2)
def test_readWritten(self): with Database3(self.dbName, "r") as db: r2 = db.load(0, 0, self.cs, self.bp) for a1, a2 in zip(self.r.core, r2.core): # assemblies assign a name based on assemNum at initialization self.assertEqual(a1.name, a2.name) assert_equal(a1.spatialLocator.indices, a2.spatialLocator.indices) self.assertEqual(a1.p.assemNum, a2.p.assemNum) self.assertEqual(a1.p.serialNum, a2.p.serialNum) for b1, b2 in zip(a1, a2): # blocks assign a name based on assemNum at initialization self.assertEqual(b1.name, b2.name) assert_equal(b1.spatialLocator.indices, b2.spatialLocator.indices) self.assertEqual(b1.p.serialNum, b2.p.serialNum) for c1, c2 in zip(sorted(b1), sorted(b2)): self.assertEqual(c1.name, c2.name) assert_equal(c1.spatialLocator.indices, c2.spatialLocator.indices) self.assertEqual(c1.p.serialNum, c2.p.serialNum) # volume is pretty difficult to get right. it relies upon linked dimensions v1 = b1.getVolume() v2 = b2.getVolume() assert_allclose(v1, v2) self.assertEqual(b1.p.serialNum, b2.p.serialNum) self.assertEqual( self.r.core.childrenByLocator[0, 0, 0].p.serialNum, r2.core.childrenByLocator[0, 0, 0].p.serialNum, )
def test_readWithoutInputs(self): with Database3(self.dbName, "r") as db: r2 = db.load(0, 0) for b1, b2 in zip(self.r.core.getBlocks(), r2.core.getBlocks()): for c1, c2 in zip(sorted(b1), sorted(b2)): self.assertEqual(c1.name, c2.name) for bi, b in enumerate(r2.core.getBlocks()): assert_allclose(b.p.flux, 1e6 * bi)
def databaseFactory(dbName: str, permission: str, version: Optional[str] = None): """ Return an appropriate object for interacting with a database file. This is not a proper factory, as the different database versions do not present a common interface. However, this is useful code, since it at least creates an object based on some knowledge of how to probe around. This allows client code to just interrogate the type of the returned object to figure out to do based on whatever it needs. """ import h5py # if it's not an hdf5 file, we dont even know where to start... if os.path.splitext(dbName)[1] != ".h5": raise RuntimeError("Unknown database format for {}".format(dbName)) if permission in permissions.Permissions.read: if version is not None: raise ValueError("Cannot specify version when reading a database.") # probe for the database version. We started adding these with "database 3", so if # databaseVersion is not present, assume it's the "old" version version = "2" tempDb = h5py.File(dbName, "r") if "databaseVersion" in tempDb.attrs: version = tempDb.attrs["databaseVersion"] del tempDb if version == "2": return XTViewDatabase(dbName, permission) if version == "3": return Database3(dbName, permission) raise ValueError("Unable to determine Database version for {}".format(dbName)) elif permission in permissions.Permissions.write: version = version or "3" if version == "2": return XTViewDatabase(dbName, permission) if version == "3": return Database3(dbName, permission)
def interactEveryNode(self, cycle, node): """Loads from db if necessary.""" if self.cs["loadStyle"] == "fromDB" and self.cs["loadFromDBEveryNode"]: if cycle == 0 and node == 0: # skip at BOL because interactBOL handled it. pass else: with Database3(self.cs["reloadDBName"], "r") as db: r = db.load(cycle, node, self.cs, self.r.blueprints, self.r.geom) self.o.reattach(r, self.cs)
def test_growToFullCoreWithCS(self): with Database3(self.dbName, "r") as db: r = db.load(0, 0, allowMissing=True) r.core.growToFullCore(self.cs) self.assertEqual(r.core.numRings, 9) self.assertEqual(r.p.cycle, 0) self.assertEqual(len(r.core.assembliesByName), 217) self.assertEqual(len(r.core.circularRingList), 0) self.assertEqual(len(r.core.blocksByName), 1085)
def invoke(self): from armi.bookkeeping.db.database3 import Database3 if all( li is None for li in [self.args.blueprints, self.args.geom, self.args.settings] ): runLog.error( "No settings, blueprints, or geometry files specified; " "nothing to do." ) return -1 bp = None settings = None geom = None if self.args.blueprints is not None: with open(self.args.blueprints, "r") as f: bp = f.read() if self.args.geom is not None: with open(self.args.geom, "r") as f: geom = f.read() if self.args.settings is not None: with open(self.args.settings, "r") as f: settings = f.read() db = Database3(self.args.h5db, "a") with db: # Not calling writeInputsToDb, since it makes too many assumptions about # where the inputs are coming from, and which ones we want to write. # Instead, we assume that we know where to store them, and do it ourselves. for data, key in [ (bp, "blueprints"), (geom, "geomFile"), (settings, "settings"), ]: if data is not None: del db.h5db["inputs/" + key] db.h5db["inputs/" + key] = data
def invoke(self): from armi.bookkeeping.db.database3 import Database3 db = Database3(self.args.h5db, "r") with db: settings, geom, bp = db.readInputsFromDB() settingsExt = ".yaml" if settings.lstrip()[0] == "<": settingsExt = ".xml" settingsPath = self.args.output_base + "_settings" + settingsExt bpPath = self.args.output_base + "_blueprints.yaml" geomPath = None if geom: geomExt = ".xml" if geom.lstrip()[0] == "<" else ".yaml" geomPath = self.args.output_base + "_geom" + geomExt bail = False for path in [settingsPath, bpPath, geomPath]: if os.path.exists(settingsPath): runLog.error("`{}` already exists. Aborting.".format(path)) bail = True if bail: return -1 for path, data, inp in [ (settingsPath, settings, "settings"), (bpPath, bp, "blueprints"), (geomPath, geom, "geometry"), ]: if path is None: continue runLog.info("Writing {} to `{}`".format(inp, path)) if isinstance(data, bytes): data = data.decode() with open(path, "w") as f: f.write(data)