Source code for omfit_classes.omfit_bout

try:
    # framework is running
    from .startup_choice import *
except ImportError as _excp:
    # class is imported by itself
    if (
        'attempted relative import with no known parent package' in str(_excp)
        or 'No module named \'omfit_classes\'' in str(_excp)
        or "No module named '__main__.startup_choice'" in str(_excp)
    ):
        from startup_choice import *
    else:
        raise

__all__ = ['boutdata', 'boututils', 'OMFITbout', 'OMFITboutinp']

from omfit_classes.omfit_data import OMFITncDataset, DataArray, Dataset
from omfit_classes.omfit_ini import OMFITini

if 'BOUT_TOP' in os.environ:
    _bout_pythonpath = os.path.abspath(os.environ['BOUT_TOP'] + os.sep + 'tools' + os.sep + 'pylib')
    if _bout_pythonpath not in [os.path.abspath(_path) for _path in sys.path]:
        sys.path.insert(1, _bout_pythonpath)
        print('* Path to BOUT python tools has been added: ' + _bout_pythonpath)
    else:
        print('* Path to BOUT python tools was found' + _bout_pythonpath)
    if 'PYTHONPATH' in os.environ and os.environ['PYTHONPATH']:
        if _bout_pythonpath not in os.environ['PYTHONPATH']:
            os.environ['PYTHONPATH'] = _bout_pythonpath + ':' + os.environ['PYTHONPATH']
    else:
        os.environ['PYTHONPATH'] = _bout_pythonpath

try:
    import netCDF4

    with quiet_environment():
        import boutdata
        import boututils
except Exception as _excp:
    boututils = boutdata = None
    warnings.warn('No `boutdata` and `boututils` support (BOUT_TOP environment variable): ' + repr(_excp))


[docs]class OMFITbout(OMFITncDataset): def __init__(self, filename, grid=None, tlim=None, **kw): if os.path.isdir(filename): filename = filename + os.sep + 'BOUT.dmp.0.nc' directory = os.path.split(filename)[0] # data already collected if not re.match(r'.*BOUT\.dmp\.[0-9]*\.nc', filename): OMFITncDataset.__init__(self, filename, **kw) # collect else: printi('Collecting BOUT++ quantities to a single file') tind = None if tlim is not None: t_array = boutdata.collect('t_array', path=directory, info=False) tind = [max([0, len(t_array) - tlim]), len(t_array)] OMFITncDataset.__init__(self, 'BOUT.dmp.nc') self.dynaLoad = False with netCDF4.Dataset(filename) as f: keys = list(f.variables.keys()) for k, uvar in enumerate(keys): var = str(uvar) printi('[% 3d/% 3d] %s' % (k + 1, len(keys), var)) dims = list(f.variables[uvar].dimensions) if len(dims) == 0: continue self[var] = DataArray(boutdata.collect(var, path=directory, info=False, tind=tind), dims=dims) # add grid information if grid is not None: self.add_grid(grid)
[docs] def add_grid(self, grid): if grid is not None: self.update(grid)
[docs] def pol_slice(self, var3d, n=1, zangle=0.0, info=True): """ return 2D data from 3D array with x, y, z dimensions :param var3d: variable to process (string or 3D variable) :param n: toroidal mode number :param zangle: toroidal angle :param info: print info to screent :return: 2d data """ n = int(n) zangle = float(zangle) if isinstance(var3d, str): var3d = self[var3d].values s = np.shape(var3d) if len(s) != 3: raise Exception('ERROR: pol_slice expects a 3D variable') nx, ny, nz = s dz = 2.0 * np.pi / float(n * (nz - 1)) # Check the grid size is correct if self['nx'] != nx: raise Exception('ERROR: Grid X size is different to the variable') if self['ny'] != ny: raise Exception('ERROR: Grid Y size is different to the variable') # Get the toroidal shift if 'qinty' in self: zShift = self['qinty'].values if infp: print('Using qinty as toroidal shift angle') elif 'zShift' in self: zShift = self['zShift'].values if info: print('Using zShift as toroidal shift angle') else: raise Exception('ERROR: Neither qinty nor zShift found') var2d = np.zeros([nx, ny]) ###################################### # Perform 2D slice zind = (zangle - zShift) / dz z0f = np.floor(zind) z0 = z0f.astype(int) p = zind - z0f # Make z0 between 0 and (nz-2) z0 = ((z0 % (nz - 1)) + (nz - 1)) % (nz - 1) # Get z+ and z- zp = (z0 + 1) % (nz - 1) zm = (z0 - 1 + (nz - 1)) % (nz - 1) # There may be some more cunning way to do this indexing for x in np.arange(nx): for y in np.arange(ny): var2d[x, y] = ( 0.5 * p[x, y] * (p[x, y] - 1.0) * var3d[x, y, zm[x, y]] + (1.0 - p[x, y] * p[x, y]) * var3d[x, y, z0[x, y]] + 0.5 * p[x, y] * (p[x, y] + 1.0) * var3d[x, y, zp[x, y]] ) return var2d
[docs]class OMFITboutinp(OMFITini): """ OMFIT class used to interface with BOUT++ configuration files (INP files). This class is based on the configobj class https://configobj.readthedocs.io/en/latest/index.html :param filename: filename passed to OMFITascii class :param \**kw: keyword dictionary passed to OMFITascii class """ def __init__(self, filename, **kw): super().__init__(filename, **kw) self.list_values = False
############################################ if '__main__' == __name__: test_classes_main_header() tmp = OMFITboutinp(f'{OMFITsrc}/../samples/BOUT.inp') tmp.load()