class SIMRA3DMeshReader(SIMRAMeshReader): reader_name = "SIMRA-3D" filename: Path mesh: FortranFile nodeshape: Shape @classmethod def applicable(cls, filename: Path) -> bool: _, u4_type = dtypes(config.input_endianness) try: with FortranFile(filename, 'r', header_dtype=u4_type) as f: assert f._read_size() == 6 * 4 return True except: return False def __init__(self, filename: Path): super().__init__() self.filename = filename def __enter__(self): self.mesh = FortranFile(self.filename, 'r', header_dtype=self.u4_type).__enter__() with save_excursion(self.mesh._fp): _, _, imax, jmax, kmax, _ = self.mesh.read_ints(self.u4_type) if config.fix_orientation: self.nodeshape = (jmax, imax, kmax) else: self.nodeshape = (imax, jmax, kmax) return self def __exit__(self, *args): self.mesh.__exit__(*args) @cache(1) def patch(self) -> Patch: i, j, k = self.nodeshape return Patch(('geometry',), StructuredTopology((j-1, i-1, k-1), celltype=Hex())) @cache(1) def nodes(self) -> Array2D: with save_excursion(self.mesh._fp): fortran_skip_record(self.mesh) nodes = transpose(self.mesh.read_reals(self.f4_type), self.nodeshape) nodes = ensure_native(nodes) return translate(self.filename.parent, nodes)
class SIMRADataReader(SIMRAReader): result_fn: Path mesh_fn: Path input_fn: Path result: FortranFile mesh: SIMRA3DMeshReader input_data: Dict[str, Any] f4_type: np.dtype u4_type: np.dtype def __enter__(self): self.result = FortranFile(self.result_fn, 'r', header_dtype=self.u4_type).__enter__() self.mesh = SIMRA3DMeshReader(self.mesh_fn).__enter__() return self def __exit__(self, *args): self.mesh.__exit__(*args) self.result.__exit__(*args) def __init__(self, result_fn: Path): super().__init__() self.result_fn = Path(result_fn) self.mesh_fn = Path(config.mesh_file) if config.mesh_file else self.result_fn.with_name('mesh.dat') self.input_fn = self.result_fn.with_name('simra.in') if not self.mesh_fn.is_file(): raise IOError(f"Unable to find mesh file: {self.mesh_fn}") if self.input_fn.is_file(): self.input_data = f90nml.read(self.input_fn) else: self.input_data = {} log.warning(f"SIMRA input file not found, scales will be missing") def patch(self) -> Patch: return self.mesh.patch() def nodes(self) -> Array2D: return self.mesh.nodes() def scale(self, name: str) -> float: return self.input_data.get('param_data', {}).get(name, 1.0) def fields(self, apply_scales: bool = True) -> Iterable[Field]: yield from self.mesh.fields() uref = self.scale('uref') if apply_scales else 1.0 lref = self.scale('lenref') if apply_scales else 1.0 yield SIMRAField('u', 0, 3, self, scale=uref) yield SIMRAField('ps', 3, 1, self, scale=uref**2) yield SIMRAField('tk', 4, 1, self, scale=uref**2) yield SIMRAField('td', 5, 1, self, scale=uref**3/lref) yield SIMRAField('vtef', 6, 1, self, scale=uref*lref) yield SIMRAField('pt', 7, 1, self) yield SIMRAField('pts', 8, 1, self) yield SIMRAField('rho', 9, 1, self) yield SIMRAField('rhos', 10, 1, self) # yield SIMRAField('pressure', 0, 1, self, cells=True) @abstractmethod def data(self, stepid: int) -> Tuple[Array2D, Array2D]: pass