Example #1
0
    def _read_amr(self):
        """Open the oct file, read in octs level-by-level.
        For each oct, only the position, index, level and domain
        are needed - its position in the octree is found automatically.
        The most important is finding all the information to feed
        oct_handler.add
        """
        self.oct_handler = RAMSESOctreeContainer(
            self.ds.domain_dimensions / 2,
            self.ds.domain_left_edge,
            self.ds.domain_right_edge,
        )
        root_nodes = self.amr_header["numbl"][self.ds.min_level, :].sum()
        self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
        mylog.debug(
            "Reading domain AMR % 4i (%0.3e, %0.3e)",
            self.domain_id,
            self.total_oct_count.sum(),
            self.ngridbound.sum(),
        )

        f = self.amr_file
        f.seek(self.amr_offset)

        min_level = self.ds.min_level
        max_level = read_amr(
            f, self.amr_header, self.ngridbound, min_level, self.oct_handler
        )

        self.max_level = max_level
        self.oct_handler.finalize()

        # Close AMR file
        f.close()
Example #2
0
class RAMSESDomainFile:
    _last_mask = None
    _last_selector_id = None

    def __init__(self, ds, domain_id):
        self.ds = ds
        self.domain_id = domain_id

        num = os.path.basename(ds.parameter_filename).split(".")[0].split("_")[1]
        rootdir = ds.root_folder
        basedir = os.path.abspath(os.path.dirname(ds.parameter_filename))
        basename = "%s/%%s_%s.out%05i" % (basedir, num, domain_id)
        part_file_descriptor = f"{basedir}/part_file_descriptor.txt"
        if ds.num_groups > 0:
            igroup = ((domain_id - 1) // ds.group_size) + 1
            basename = "%s/group_%05i/%%s_%s.out%05i" % (
                rootdir,
                igroup,
                num,
                domain_id,
            )
        else:
            basename = "%s/%%s_%s.out%05i" % (basedir, num, domain_id)
        for t in ["grav", "amr"]:
            setattr(self, f"{t}_fn", basename % t)
        self._part_file_descriptor = part_file_descriptor
        self._read_amr_header()

        # Autodetect field files
        field_handlers = [FH(self) for FH in get_field_handlers() if FH.any_exist(ds)]
        self.field_handlers = field_handlers
        for fh in field_handlers:
            mylog.debug("Detected fluid type %s in domain_id=%s", fh.ftype, domain_id)
            fh.detect_fields(ds)
            # self._add_ftype(fh.ftype)

        # Autodetect particle files
        particle_handlers = [
            PH(self) for PH in get_particle_handlers() if PH.any_exist(ds)
        ]
        self.particle_handlers = particle_handlers
        for ph in particle_handlers:
            mylog.debug(
                "Detected particle type %s in domain_id=%s", ph.ptype, domain_id
            )
            ph.read_header()
            # self._add_ptype(ph.ptype)

        # Load the AMR structure
        self._read_amr()

    _hydro_offset = None
    _level_count = None

    def __repr__(self):
        return "RAMSESDomainFile: %i" % self.domain_id

    @property
    def level_count(self):
        lvl_count = None
        for fh in self.field_handlers:
            fh.offset
            if lvl_count is None:
                lvl_count = fh.level_count.copy()
            else:
                lvl_count += fh._level_count
        return lvl_count

    @property
    def amr_file(self):
        if hasattr(self, "_amr_file"):
            self._amr_file.seek(0)
            return self._amr_file

        f = fpu(self.amr_fn)
        self._amr_file = f
        f.seek(0)
        return f

    def _read_amr_header(self):
        hvals = {}
        f = self.amr_file
        f.seek(0)

        for header in ramses_header(hvals):
            hvals.update(f.read_attrs(header))
        # For speedup, skip reading of 'headl' and 'taill'
        f.skip(2)
        hvals["numbl"] = f.read_vector("i")

        # That's the header, now we skip a few.
        hvals["numbl"] = np.array(hvals["numbl"]).reshape(
            (hvals["nlevelmax"], hvals["ncpu"])
        )
        f.skip()
        if hvals["nboundary"] > 0:
            f.skip(2)
            self.ngridbound = f.read_vector("i").astype("int64")
        else:
            self.ngridbound = np.zeros(hvals["nlevelmax"], dtype="int64")
        free_mem = f.read_attrs((("free_mem", 5, "i"),))  # NOQA
        ordering = f.read_vector("c")  # NOQA
        f.skip(4)
        # Now we're at the tree itself
        # Now we iterate over each level and each CPU.
        self.amr_header = hvals
        # update levelmax
        force_max_level, convention = self.ds._force_max_level
        if convention == "yt":
            force_max_level += self.ds.min_level + 1
        self.amr_header["nlevelmax"] = min(
            force_max_level, self.amr_header["nlevelmax"]
        )
        self.amr_offset = f.tell()
        self.local_oct_count = hvals["numbl"][
            self.ds.min_level :, self.domain_id - 1
        ].sum()
        self.total_oct_count = hvals["numbl"][self.ds.min_level :, :].sum(axis=0)

    def _read_amr(self):
        """Open the oct file, read in octs level-by-level.
        For each oct, only the position, index, level and domain
        are needed - its position in the octree is found automatically.
        The most important is finding all the information to feed
        oct_handler.add
        """
        self.oct_handler = RAMSESOctreeContainer(
            self.ds.domain_dimensions / 2,
            self.ds.domain_left_edge,
            self.ds.domain_right_edge,
        )
        root_nodes = self.amr_header["numbl"][self.ds.min_level, :].sum()
        self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
        mylog.debug(
            "Reading domain AMR % 4i (%0.3e, %0.3e)",
            self.domain_id,
            self.total_oct_count.sum(),
            self.ngridbound.sum(),
        )

        f = self.amr_file
        f.seek(self.amr_offset)

        min_level = self.ds.min_level
        max_level = read_amr(
            f, self.amr_header, self.ngridbound, min_level, self.oct_handler
        )

        self.max_level = max_level
        self.oct_handler.finalize()

        # Close AMR file
        f.close()

    def included(self, selector):
        if getattr(selector, "domain_id", None) is not None:
            return selector.domain_id == self.domain_id
        domain_ids = self.oct_handler.domain_identify(selector)
        return self.domain_id in domain_ids
Example #3
0
    def _read_amr(self):
        """Open the oct file, read in octs level-by-level.
           For each oct, only the position, index, level and domain
           are needed - its position in the octree is found automatically.
           The most important is finding all the information to feed
           oct_handler.add
        """
        self.oct_handler = RAMSESOctreeContainer(self.ds.domain_dimensions / 2,
                                                 self.ds.domain_left_edge,
                                                 self.ds.domain_right_edge)
        root_nodes = self.amr_header['numbl'][self.ds.min_level, :].sum()
        self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
        mylog.debug("Reading domain AMR % 4i (%0.3e, %0.3e)", self.domain_id,
                    self.total_oct_count.sum(), self.ngridbound.sum())

        f = self.amr_file

        f.seek(self.amr_offset)

        def _ng(c, l):
            if c < self.amr_header['ncpu']:
                ng = self.amr_header['numbl'][l, c]
            else:
                ng = self.ngridbound[c - self.amr_header['ncpu'] +
                                     self.amr_header['nboundary'] * l]
            return ng

        min_level = self.ds.min_level
        # yt max level is not the same as the RAMSES one.
        # yt max level is the maximum number of additional refinement levels
        # so for a uni grid run with no refinement, it would be 0.
        # So we initially assume that.
        max_level = 0
        nx, ny, nz = (((i - 1.0) / 2.0) for i in self.amr_header['nx'])
        for level in range(self.amr_header['nlevelmax']):
            # Easier if do this 1-indexed
            for cpu in range(self.amr_header['nboundary'] +
                             self.amr_header['ncpu']):
                #ng is the number of octs on this level on this domain
                ng = _ng(cpu, level)
                if ng == 0: continue
                ind = fpu.read_vector(f, "I").astype("int64")  # NOQA
                fpu.skip(f, 2)
                pos = np.empty((ng, 3), dtype='float64')
                pos[:, 0] = fpu.read_vector(f, "d") - nx
                pos[:, 1] = fpu.read_vector(f, "d") - ny
                pos[:, 2] = fpu.read_vector(f, "d") - nz
                #pos *= self.ds.domain_width
                #pos += self.dataset.domain_left_edge
                fpu.skip(f, 31)
                #parents = fpu.read_vector(f, "I")
                #fpu.skip(f, 6)
                #children = np.empty((ng, 8), dtype='int64')
                #for i in range(8):
                #    children[:,i] = fpu.read_vector(f, "I")
                #cpu_map = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    cpu_map[:,i] = fpu.read_vector(f, "I")
                #rmap = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    rmap[:,i] = fpu.read_vector(f, "I")
                # We don't want duplicate grids.
                # Note that we're adding *grids*, not individual cells.
                if level >= min_level:
                    assert (pos.shape[0] == ng)
                    n = self.oct_handler.add(cpu + 1,
                                             level - min_level,
                                             pos,
                                             count_boundary=1)
                    self._error_check(cpu, level, pos, n, ng, (nx, ny, nz))
                    if n > 0: max_level = max(level - min_level, max_level)
        self.max_level = max_level
        self.oct_handler.finalize()

        # Close AMR file
        f.close()
Example #4
0
class RAMSESDomainFile(object):
    _last_mask = None
    _last_selector_id = None

    def __init__(self, ds, domain_id):
        self.ds = ds
        self.domain_id = domain_id

        num = os.path.basename(
            ds.parameter_filename).split(".")[0].split("_")[1]
        basedir = os.path.abspath(os.path.dirname(ds.parameter_filename))
        basename = "%s/%%s_%s.out%05i" % (basedir, num, domain_id)
        part_file_descriptor = "%s/part_file_descriptor.txt" % basedir
        for t in ['grav', 'amr']:
            setattr(self, "%s_fn" % t, basename % t)
        self._part_file_descriptor = part_file_descriptor
        self._read_amr_header()
        # self._read_hydro_header()

        # Autodetect field files
        field_handlers = [
            FH(self) for FH in get_field_handlers() if FH.any_exist(ds)
        ]
        self.field_handlers = field_handlers
        for fh in field_handlers:
            mylog.debug('Detected fluid type %s in domain_id=%s' %
                        (fh.ftype, domain_id))
            fh.detect_fields(ds)
            # self._add_ftype(fh.ftype)

        # Autodetect particle files
        particle_handlers = [
            PH(ds, domain_id) for PH in get_particle_handlers()
            if PH.any_exist(ds)
        ]
        self.particle_handlers = particle_handlers
        for ph in particle_handlers:
            mylog.debug('Detected particle type %s in domain_id=%s' %
                        (ph.ptype, domain_id))
            ph.read_header()
            # self._add_ptype(ph.ptype)

        # Load the AMR structure
        self._read_amr()

    _hydro_offset = None
    _level_count = None

    def __repr__(self):
        return "RAMSESDomainFile: %i" % self.domain_id

    @property
    def level_count(self):
        lvl_count = None
        for fh in self.field_handlers:
            fh.offset
            if lvl_count is None:
                lvl_count = fh.level_count.copy()
            else:
                lvl_count += fh._level_count
        return lvl_count

    @property
    def amr_file(self):
        if hasattr(self, '_amr_file'):
            self._amr_file.seek(0)
            return self._amr_file

        f = open(self.amr_fn, "rb")
        self._amr_file = f
        f.seek(0)
        return f

    def _read_amr_header(self):
        hvals = {}
        f = self.amr_file

        f.seek(0)

        for header in ramses_header(hvals):
            hvals.update(fpu.read_attrs(f, header))
        # For speedup, skip reading of 'headl' and 'taill'
        fpu.skip(f, 2)
        hvals['numbl'] = fpu.read_vector(f, 'i')

        # That's the header, now we skip a few.
        hvals['numbl'] = np.array(hvals['numbl']).reshape(
            (hvals['nlevelmax'], hvals['ncpu']))
        fpu.skip(f)
        if hvals['nboundary'] > 0:
            fpu.skip(f, 2)
            self.ngridbound = fpu.read_vector(f, 'i').astype("int64")
        else:
            self.ngridbound = np.zeros(hvals['nlevelmax'], dtype='int64')
        free_mem = fpu.read_attrs(f, (('free_mem', 5, 'i'), ))  # NOQA
        ordering = fpu.read_vector(f, 'c')  # NOQA
        fpu.skip(f, 4)
        # Now we're at the tree itself
        # Now we iterate over each level and each CPU.
        self.amr_header = hvals
        self.amr_offset = f.tell()
        self.local_oct_count = hvals['numbl'][self.ds.min_level:,
                                              self.domain_id - 1].sum()
        self.total_oct_count = hvals['numbl'][self.ds.min_level:, :].sum(
            axis=0)

    def _read_amr(self):
        """Open the oct file, read in octs level-by-level.
           For each oct, only the position, index, level and domain
           are needed - its position in the octree is found automatically.
           The most important is finding all the information to feed
           oct_handler.add
        """
        self.oct_handler = RAMSESOctreeContainer(self.ds.domain_dimensions / 2,
                                                 self.ds.domain_left_edge,
                                                 self.ds.domain_right_edge)
        root_nodes = self.amr_header['numbl'][self.ds.min_level, :].sum()
        self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
        mylog.debug("Reading domain AMR % 4i (%0.3e, %0.3e)", self.domain_id,
                    self.total_oct_count.sum(), self.ngridbound.sum())

        f = self.amr_file

        f.seek(self.amr_offset)

        def _ng(c, l):
            if c < self.amr_header['ncpu']:
                ng = self.amr_header['numbl'][l, c]
            else:
                ng = self.ngridbound[c - self.amr_header['ncpu'] +
                                     self.amr_header['nboundary'] * l]
            return ng

        min_level = self.ds.min_level
        # yt max level is not the same as the RAMSES one.
        # yt max level is the maximum number of additional refinement levels
        # so for a uni grid run with no refinement, it would be 0.
        # So we initially assume that.
        max_level = 0
        nx, ny, nz = (((i - 1.0) / 2.0) for i in self.amr_header['nx'])
        for level in range(self.amr_header['nlevelmax']):
            # Easier if do this 1-indexed
            for cpu in range(self.amr_header['nboundary'] +
                             self.amr_header['ncpu']):
                #ng is the number of octs on this level on this domain
                ng = _ng(cpu, level)
                if ng == 0: continue
                ind = fpu.read_vector(f, "I").astype("int64")  # NOQA
                fpu.skip(f, 2)
                pos = np.empty((ng, 3), dtype='float64')
                pos[:, 0] = fpu.read_vector(f, "d") - nx
                pos[:, 1] = fpu.read_vector(f, "d") - ny
                pos[:, 2] = fpu.read_vector(f, "d") - nz
                #pos *= self.ds.domain_width
                #pos += self.dataset.domain_left_edge
                fpu.skip(f, 31)
                #parents = fpu.read_vector(f, "I")
                #fpu.skip(f, 6)
                #children = np.empty((ng, 8), dtype='int64')
                #for i in range(8):
                #    children[:,i] = fpu.read_vector(f, "I")
                #cpu_map = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    cpu_map[:,i] = fpu.read_vector(f, "I")
                #rmap = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    rmap[:,i] = fpu.read_vector(f, "I")
                # We don't want duplicate grids.
                # Note that we're adding *grids*, not individual cells.
                if level >= min_level:
                    assert (pos.shape[0] == ng)
                    n = self.oct_handler.add(cpu + 1,
                                             level - min_level,
                                             pos,
                                             count_boundary=1)
                    self._error_check(cpu, level, pos, n, ng, (nx, ny, nz))
                    if n > 0: max_level = max(level - min_level, max_level)
        self.max_level = max_level
        self.oct_handler.finalize()

        # Close AMR file
        f.close()

    def _error_check(self, cpu, level, pos, n, ng, nn):
        # NOTE: We have the second conditional here because internally, it will
        # not add any octs in that case.
        if n == ng or cpu + 1 > self.oct_handler.num_domains:
            return
        # This is where we now check for issues with creating the new octs, and
        # we attempt to determine what precisely is going wrong.
        # These are all print statements.
        print("We have detected an error with the construction of the Octree.")
        print("  The number of Octs to be added :  %s" % ng)
        print("  The number of Octs added       :  %s" % n)
        print("  Level                          :  %s" % level)
        print("  CPU Number (0-indexed)         :  %s" % cpu)
        for i, ax in enumerate('xyz'):
            print("  extent [%s]                     :  %s %s" % \
            (ax, pos[:,i].min(), pos[:,i].max()))
        print("  domain left                    :  %s" % \
            (self.ds.domain_left_edge,))
        print("  domain right                   :  %s" % \
            (self.ds.domain_right_edge,))
        print("  offset applied                 :  %s %s %s" % \
            (nn[0], nn[1], nn[2]))
        print("AMR Header:")
        for key in sorted(self.amr_header):
            print("   %-30s: %s" % (key, self.amr_header[key]))
        raise RuntimeError

    def included(self, selector):
        if getattr(selector, "domain_id", None) is not None:
            return selector.domain_id == self.domain_id
        domain_ids = self.oct_handler.domain_identify(selector)
        return self.domain_id in domain_ids
Example #5
0
from yt.geometry.fake_octree import create_fake_octree
from yt.geometry.oct_container import RAMSESOctreeContainer, ParticleOctreeContainer
import numpy as np

nocts = 3
max_level = 12
dn = 2
dd = np.ones(3, dtype='i4') * dn
dle = np.ones(3, dtype='f8') * 0.0
dre = np.ones(3, dtype='f8')
fsub = 0.25
domain = 1

oct_handler = RAMSESOctreeContainer(dd, dle, dre)
leaves = create_fake_octree(oct_handler, nocts, max_level, dd, dle, dre, fsub)
mask = np.ones((nocts, 8), dtype='bool')
cell_count = nocts * 8
oct_counts = oct_handler.count_levels(max_level, 1, mask)
level_counts = np.concatenate(([
    0,
], np.cumsum(oct_counts)))
fc = oct_handler.fcoords(domain, mask, cell_count, level_counts.copy())
leavesb = oct_handler.count_leaves(mask)
assert leaves == leavesb

#Now take the fcoords, call them particles and recreate the same octree
print "particle-based recreate"
oct_handler2 = ParticleOctreeContainer(dd, dle, dre)
oct_handler2.allocate_domains([nocts])
oct_handler2.n_ref = 1  #specifically make a maximum of 1 particle per oct
oct_handler2.add(fc, 1)
Example #6
0
class RAMSESDomainFile(object):
    _last_mask = None
    _last_selector_id = None

    def __init__(self, ds, domain_id):
        self.ds = ds
        self.domain_id = domain_id
        self.nvar = 0  # Set this later!
        num = os.path.basename(
            ds.parameter_filename).split(".")[0].split("_")[1]
        basename = "%s/%%s_%s.out%05i" % (os.path.abspath(
            os.path.dirname(ds.parameter_filename)), num, domain_id)
        for t in ['grav', 'hydro', 'part', 'amr']:
            setattr(self, "%s_fn" % t, basename % t)
        self._read_amr_header()
        self._read_hydro_header()
        self._read_particle_header()
        self._read_amr()

    _hydro_offset = None
    _level_count = None

    def __repr__(self):
        return "RAMSESDomainFile: %i" % self.domain_id

    def _is_hydro(self):
        '''
        Does the output include hydro?
        '''
        return os.path.exists(self.hydro_fn)

    @property
    def level_count(self):
        if self._level_count is not None: return self._level_count
        self.hydro_offset
        return self._level_count

    @property
    def hydro_offset(self):
        if self._hydro_offset is not None: return self._hydro_offset
        # We now have to open the file and calculate it
        f = open(self.hydro_fn, "rb")
        fpu.skip(f, 6)
        # It goes: level, CPU, 8-variable
        min_level = self.ds.min_level
        n_levels = self.amr_header['nlevelmax'] - min_level
        hydro_offset = np.zeros(n_levels, dtype='int64')
        hydro_offset -= 1
        level_count = np.zeros(n_levels, dtype='int64')
        skipped = []
        for level in range(self.amr_header['nlevelmax']):
            for cpu in range(self.amr_header['nboundary'] +
                             self.amr_header['ncpu']):
                header = (('file_ilevel', 1, 'I'), ('file_ncache', 1, 'I'))
                try:
                    hvals = fpu.read_attrs(f, header, "=")
                except AssertionError:
                    print "You are running with the wrong number of fields."
                    print "If you specified these in the load command, check the array length."
                    print "In this file there are %s hydro fields." % skipped
                    #print "The last set of field sizes was: %s" % skipped
                    raise
                if hvals['file_ncache'] == 0: continue
                assert (hvals['file_ilevel'] == level + 1)
                if cpu + 1 == self.domain_id and level >= min_level:
                    hydro_offset[level - min_level] = f.tell()
                    level_count[level - min_level] = hvals['file_ncache']
                skipped = fpu.skip(f, 8 * self.nvar)
        self._hydro_offset = hydro_offset
        self._level_count = level_count
        return self._hydro_offset

    def _read_hydro_header(self):
        # If no hydro file is found, return
        if not self._is_hydro():
            return
        if self.nvar > 0: return self.nvar
        # Read the number of hydro  variables
        f = open(self.hydro_fn, "rb")
        fpu.skip(f, 1)
        self.nvar = fpu.read_vector(f, "i")[0]

    def _read_particle_header(self):
        if not os.path.exists(self.part_fn):
            self.local_particle_count = 0
            self.particle_field_offsets = {}
            return
        f = open(self.part_fn, "rb")
        f.seek(0, os.SEEK_END)
        flen = f.tell()
        f.seek(0)
        hvals = {}
        attrs = (('ncpu', 1, 'I'), ('ndim', 1, 'I'), ('npart', 1, 'I'))
        hvals.update(fpu.read_attrs(f, attrs))
        fpu.read_vector(f, 'I')

        attrs = (('nstar_tot', 1, 'I'), ('mstar_tot', 1, 'd'),
                 ('mstar_lost', 1, 'd'), ('nsink', 1, 'I'))
        hvals.update(fpu.read_attrs(f, attrs))
        self.particle_header = hvals
        self.local_particle_count = hvals['npart']
        particle_fields = [("particle_position_x", "d"),
                           ("particle_position_y", "d"),
                           ("particle_position_z", "d"),
                           ("particle_velocity_x", "d"),
                           ("particle_velocity_y", "d"),
                           ("particle_velocity_z", "d"),
                           ("particle_mass", "d"),
                           ("particle_identifier", "I"),
                           ("particle_refinement_level", "I")]
        if hvals["nstar_tot"] > 0:
            particle_fields += [("particle_age", "d"),
                                ("particle_metallicity", "d")]
        field_offsets = {}
        _pfields = {}
        for field, vtype in particle_fields:
            if f.tell() >= flen: break
            field_offsets["io", field] = f.tell()
            _pfields["io", field] = vtype
            fpu.skip(f, 1)
        self.particle_field_offsets = field_offsets
        self.particle_field_types = _pfields
        self.particle_types = self.particle_types_raw = ("io", )

    def _read_amr_header(self):
        hvals = {}
        f = open(self.amr_fn, "rb")
        for header in ramses_header(hvals):
            hvals.update(fpu.read_attrs(f, header))
        # That's the header, now we skip a few.
        hvals['numbl'] = np.array(hvals['numbl']).reshape(
            (hvals['nlevelmax'], hvals['ncpu']))
        fpu.skip(f)
        if hvals['nboundary'] > 0:
            fpu.skip(f, 2)
            self.ngridbound = fpu.read_vector(f, 'i').astype("int64")
        else:
            self.ngridbound = np.zeros(hvals['nlevelmax'], dtype='int64')
        free_mem = fpu.read_attrs(f, (('free_mem', 5, 'i'), ))
        ordering = fpu.read_vector(f, 'c')
        fpu.skip(f, 4)
        # Now we're at the tree itself
        # Now we iterate over each level and each CPU.
        self.amr_header = hvals
        self.amr_offset = f.tell()
        self.local_oct_count = hvals['numbl'][self.ds.min_level:,
                                              self.domain_id - 1].sum()
        self.total_oct_count = hvals['numbl'][self.ds.min_level:, :].sum(
            axis=0)

    def _read_amr(self):
        """Open the oct file, read in octs level-by-level.
           For each oct, only the position, index, level and domain 
           are needed - its position in the octree is found automatically.
           The most important is finding all the information to feed
           oct_handler.add
        """
        self.oct_handler = RAMSESOctreeContainer(self.ds.domain_dimensions / 2,
                                                 self.ds.domain_left_edge,
                                                 self.ds.domain_right_edge)
        root_nodes = self.amr_header['numbl'][self.ds.min_level, :].sum()
        self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
        fb = open(self.amr_fn, "rb")
        fb.seek(self.amr_offset)
        f = cStringIO.StringIO()
        f.write(fb.read())
        f.seek(0)
        mylog.debug("Reading domain AMR % 4i (%0.3e, %0.3e)", self.domain_id,
                    self.total_oct_count.sum(), self.ngridbound.sum())

        def _ng(c, l):
            if c < self.amr_header['ncpu']:
                ng = self.amr_header['numbl'][l, c]
            else:
                ng = self.ngridbound[c - self.amr_header['ncpu'] +
                                     self.amr_header['nboundary'] * l]
            return ng

        min_level = self.ds.min_level
        max_level = min_level
        nx, ny, nz = (((i - 1.0) / 2.0) for i in self.amr_header['nx'])
        for level in range(self.amr_header['nlevelmax']):
            # Easier if do this 1-indexed
            for cpu in range(self.amr_header['nboundary'] +
                             self.amr_header['ncpu']):
                #ng is the number of octs on this level on this domain
                ng = _ng(cpu, level)
                if ng == 0: continue
                ind = fpu.read_vector(f, "I").astype("int64")
                fpu.skip(f, 2)
                pos = np.empty((ng, 3), dtype='float64')
                pos[:, 0] = fpu.read_vector(f, "d") - nx
                pos[:, 1] = fpu.read_vector(f, "d") - ny
                pos[:, 2] = fpu.read_vector(f, "d") - nz
                #pos *= self.ds.domain_width
                #pos += self.dataset.domain_left_edge
                fpu.skip(f, 31)
                #parents = fpu.read_vector(f, "I")
                #fpu.skip(f, 6)
                #children = np.empty((ng, 8), dtype='int64')
                #for i in range(8):
                #    children[:,i] = fpu.read_vector(f, "I")
                #cpu_map = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    cpu_map[:,i] = fpu.read_vector(f, "I")
                #rmap = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    rmap[:,i] = fpu.read_vector(f, "I")
                # We don't want duplicate grids.
                # Note that we're adding *grids*, not individual cells.
                if level >= min_level:
                    assert (pos.shape[0] == ng)
                    n = self.oct_handler.add(cpu + 1,
                                             level - min_level,
                                             pos,
                                             count_boundary=1)
                    self._error_check(cpu, level, pos, n, ng, (nx, ny, nz))
                    if n > 0: max_level = max(level - min_level, max_level)
        self.max_level = max_level
        self.oct_handler.finalize()

    def _error_check(self, cpu, level, pos, n, ng, nn):
        # NOTE: We have the second conditional here because internally, it will
        # not add any octs in that case.
        if n == ng or cpu + 1 > self.oct_handler.num_domains:
            return
        # This is where we now check for issues with creating the new octs, and
        # we attempt to determine what precisely is going wrong.
        # These are all print statements.
        print "We have detected an error with the construction of the Octree."
        print "  The number of Octs to be added :  %s" % ng
        print "  The number of Octs added       :  %s" % n
        print "  Level                          :  %s" % level
        print "  CPU Number (0-indexed)         :  %s" % cpu
        for i, ax in enumerate('xyz'):
            print "  extent [%s]                     :  %s %s" % \
            (ax, pos[:,i].min(), pos[:,i].max())
        print "  domain left                    :  %s" % \
            (self.ds.domain_left_edge,)
        print "  domain right                   :  %s" % \
            (self.ds.domain_right_edge,)
        print "  offset applied                 :  %s %s %s" % \
            (nn[0], nn[1], nn[2])
        print "AMR Header:"
        for key in sorted(self.amr_header):
            print "   %-30s: %s" % (key, self.amr_header[key])
        raise RuntimeError

    def included(self, selector):
        if getattr(selector, "domain_id", None) is not None:
            return selector.domain_id == self.domain_id
        domain_ids = self.oct_handler.domain_identify(selector)
        return self.domain_id in domain_ids
class RAMSESDomainFile(object):
    _last_mask = None
    _last_selector_id = None

    def __init__(self, ds, domain_id):
        self.ds = ds
        self.domain_id = domain_id
        self.nvar = 0 # Set this later!
        num = os.path.basename(ds.parameter_filename).split("."
                )[0].split("_")[1]
        basename = "%s/%%s_%s.out%05i" % (
            os.path.abspath(
              os.path.dirname(ds.parameter_filename)),
            num, domain_id)
        for t in ['grav', 'hydro', 'part', 'amr']:
            setattr(self, "%s_fn" % t, basename % t)
        self._read_amr_header()
        self._read_hydro_header()
        self._read_particle_header()
        self._read_amr()

    _hydro_offset = None
    _level_count = None

    def __repr__(self):
        return "RAMSESDomainFile: %i" % self.domain_id

    def _is_hydro(self):
        '''
        Does the output include hydro?
        '''
        return os.path.exists(self.hydro_fn)

    @property
    def level_count(self):
        if self._level_count is not None: return self._level_count
        self.hydro_offset
        return self._level_count

    @property
    def hydro_offset(self):
        if self._hydro_offset is not None: return self._hydro_offset
        # We now have to open the file and calculate it
        f = open(self.hydro_fn, "rb")
        fpu.skip(f, 6)
        # It goes: level, CPU, 8-variable
        min_level = self.ds.min_level
        n_levels = self.amr_header['nlevelmax'] - min_level
        hydro_offset = np.zeros(n_levels, dtype='int64')
        hydro_offset -= 1
        level_count = np.zeros(n_levels, dtype='int64')
        skipped = []
        for level in range(self.amr_header['nlevelmax']):
            for cpu in range(self.amr_header['nboundary'] +
                             self.amr_header['ncpu']):
                header = ( ('file_ilevel', 1, 'I'),
                           ('file_ncache', 1, 'I') )
                try:
                    hvals = fpu.read_attrs(f, header, "=")
                except AssertionError:
                    print("You are running with the wrong number of fields.")
                    print("If you specified these in the load command, check the array length.")
                    print("In this file there are %s hydro fields." % skipped)
                    #print "The last set of field sizes was: %s" % skipped
                    raise
                if hvals['file_ncache'] == 0: continue
                assert(hvals['file_ilevel'] == level+1)
                if cpu + 1 == self.domain_id and level >= min_level:
                    hydro_offset[level - min_level] = f.tell()
                    level_count[level - min_level] = hvals['file_ncache']
                skipped = fpu.skip(f, 8 * self.nvar)
        self._hydro_offset = hydro_offset
        self._level_count = level_count
        return self._hydro_offset

    def _read_hydro_header(self):
        # If no hydro file is found, return
        if not self._is_hydro():
            return
        if self.nvar > 0: return self.nvar
        # Read the number of hydro  variables
        f = open(self.hydro_fn, "rb")
        fpu.skip(f, 1)
        self.nvar = fpu.read_vector(f, "i")[0]

    def _read_particle_header(self):
        if not os.path.exists(self.part_fn):
            self.local_particle_count = 0
            self.particle_field_offsets = {}
            return
        f = open(self.part_fn, "rb")
        f.seek(0, os.SEEK_END)
        flen = f.tell()
        f.seek(0)
        hvals = {}
        attrs = ( ('ncpu', 1, 'I'),
                  ('ndim', 1, 'I'),
                  ('npart', 1, 'I') )
        hvals.update(fpu.read_attrs(f, attrs))
        fpu.read_vector(f, 'I')

        attrs = ( ('nstar_tot', 1, 'I'),
                  ('mstar_tot', 1, 'd'),
                  ('mstar_lost', 1, 'd'),
                  ('nsink', 1, 'I') )
        hvals.update(fpu.read_attrs(f, attrs))
        self.particle_header = hvals
        self.local_particle_count = hvals['npart']
        particle_fields = [
                ("particle_position_x", "d"),
                ("particle_position_y", "d"),
                ("particle_position_z", "d"),
                ("particle_velocity_x", "d"),
                ("particle_velocity_y", "d"),
                ("particle_velocity_z", "d"),
                ("particle_mass", "d"),
                ("particle_identifier", "I"),
                ("particle_refinement_level", "I")]
        if hvals["nstar_tot"] > 0:
            particle_fields += [("particle_age", "d"),
                                ("particle_metallicity", "d")]

        field_offsets = {}
        _pfields = {}
        for field, vtype in particle_fields:
            if f.tell() >= flen: break
            field_offsets["io", field] = f.tell()
            _pfields["io", field] = vtype
            fpu.skip(f, 1)
        self.particle_field_offsets = field_offsets
        self.particle_field_types = _pfields
        self.particle_types = self.particle_types_raw = ("io",)

    def _read_amr_header(self):
        hvals = {}
        f = open(self.amr_fn, "rb")
        for header in ramses_header(hvals):
            hvals.update(fpu.read_attrs(f, header))
        # That's the header, now we skip a few.
        hvals['numbl'] = np.array(hvals['numbl']).reshape(
            (hvals['nlevelmax'], hvals['ncpu']))
        fpu.skip(f)
        if hvals['nboundary'] > 0:
            fpu.skip(f, 2)
            self.ngridbound = fpu.read_vector(f, 'i').astype("int64")
        else:
            self.ngridbound = np.zeros(hvals['nlevelmax'], dtype='int64')
        free_mem = fpu.read_attrs(f, (('free_mem', 5, 'i'), ) )
        ordering = fpu.read_vector(f, 'c')
        fpu.skip(f, 4)
        # Now we're at the tree itself
        # Now we iterate over each level and each CPU.
        self.amr_header = hvals
        self.amr_offset = f.tell()
        self.local_oct_count = hvals['numbl'][self.ds.min_level:, self.domain_id - 1].sum()
        self.total_oct_count = hvals['numbl'][self.ds.min_level:,:].sum(axis=0)

    def _read_amr(self):
        """Open the oct file, read in octs level-by-level.
           For each oct, only the position, index, level and domain 
           are needed - its position in the octree is found automatically.
           The most important is finding all the information to feed
           oct_handler.add
        """
        self.oct_handler = RAMSESOctreeContainer(self.ds.domain_dimensions/2,
                self.ds.domain_left_edge, self.ds.domain_right_edge)
        root_nodes = self.amr_header['numbl'][self.ds.min_level,:].sum()
        self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
        fb = open(self.amr_fn, "rb")
        fb.seek(self.amr_offset)
        f = BytesIO()
        f.write(fb.read())
        f.seek(0)
        mylog.debug("Reading domain AMR % 4i (%0.3e, %0.3e)",
            self.domain_id, self.total_oct_count.sum(), self.ngridbound.sum())
        def _ng(c, l):
            if c < self.amr_header['ncpu']:
                ng = self.amr_header['numbl'][l, c]
            else:
                ng = self.ngridbound[c - self.amr_header['ncpu'] +
                                self.amr_header['nboundary']*l]
            return ng
        min_level = self.ds.min_level
        # yt max level is not the same as the RAMSES one.
        # yt max level is the maximum number of additional refinement levels
        # so for a uni grid run with no refinement, it would be 0. 
        # So we initially assume that.
        max_level = 0
        nx, ny, nz = (((i-1.0)/2.0) for i in self.amr_header['nx'])
        for level in range(self.amr_header['nlevelmax']):
            # Easier if do this 1-indexed
            for cpu in range(self.amr_header['nboundary'] + self.amr_header['ncpu']):
                #ng is the number of octs on this level on this domain
                ng = _ng(cpu, level)
                if ng == 0: continue
                ind = fpu.read_vector(f, "I").astype("int64")
                fpu.skip(f, 2)
                pos = np.empty((ng, 3), dtype='float64')
                pos[:,0] = fpu.read_vector(f, "d") - nx
                pos[:,1] = fpu.read_vector(f, "d") - ny
                pos[:,2] = fpu.read_vector(f, "d") - nz
                #pos *= self.ds.domain_width
                #pos += self.dataset.domain_left_edge
                fpu.skip(f, 31)
                #parents = fpu.read_vector(f, "I")
                #fpu.skip(f, 6)
                #children = np.empty((ng, 8), dtype='int64')
                #for i in range(8):
                #    children[:,i] = fpu.read_vector(f, "I")
                #cpu_map = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    cpu_map[:,i] = fpu.read_vector(f, "I")
                #rmap = np.empty((ng, 8), dtype="int64")
                #for i in range(8):
                #    rmap[:,i] = fpu.read_vector(f, "I")
                # We don't want duplicate grids.
                # Note that we're adding *grids*, not individual cells.
                if level >= min_level:
                    assert(pos.shape[0] == ng)
                    n = self.oct_handler.add(cpu + 1, level - min_level, pos,
                                count_boundary = 1)
                    self._error_check(cpu, level, pos, n, ng, (nx, ny, nz))
                    if n > 0: max_level = max(level - min_level, max_level)
        self.max_level = max_level
        self.oct_handler.finalize()

    def _error_check(self, cpu, level, pos, n, ng, nn):
        # NOTE: We have the second conditional here because internally, it will
        # not add any octs in that case.
        if n == ng or cpu + 1 > self.oct_handler.num_domains:
            return
        # This is where we now check for issues with creating the new octs, and
        # we attempt to determine what precisely is going wrong.
        # These are all print statements.
        print("We have detected an error with the construction of the Octree.")
        print("  The number of Octs to be added :  %s" % ng)
        print("  The number of Octs added       :  %s" % n)
        print("  Level                          :  %s" % level)
        print("  CPU Number (0-indexed)         :  %s" % cpu)
        for i, ax in enumerate('xyz'):
            print("  extent [%s]                     :  %s %s" % \
            (ax, pos[:,i].min(), pos[:,i].max()))
        print("  domain left                    :  %s" % \
            (self.ds.domain_left_edge,))
        print("  domain right                   :  %s" % \
            (self.ds.domain_right_edge,))
        print("  offset applied                 :  %s %s %s" % \
            (nn[0], nn[1], nn[2]))
        print("AMR Header:")
        for key in sorted(self.amr_header):
            print("   %-30s: %s" % (key, self.amr_header[key]))
        raise RuntimeError

    def included(self, selector):
        if getattr(selector, "domain_id", None) is not None:
            return selector.domain_id == self.domain_id
        domain_ids = self.oct_handler.domain_identify(selector)
        return self.domain_id in domain_ids
 def _read_amr(self):
     """Open the oct file, read in octs level-by-level.
        For each oct, only the position, index, level and domain 
        are needed - its position in the octree is found automatically.
        The most important is finding all the information to feed
        oct_handler.add
     """
     self.oct_handler = RAMSESOctreeContainer(self.ds.domain_dimensions/2,
             self.ds.domain_left_edge, self.ds.domain_right_edge)
     root_nodes = self.amr_header['numbl'][self.ds.min_level,:].sum()
     self.oct_handler.allocate_domains(self.total_oct_count, root_nodes)
     fb = open(self.amr_fn, "rb")
     fb.seek(self.amr_offset)
     f = BytesIO()
     f.write(fb.read())
     f.seek(0)
     mylog.debug("Reading domain AMR % 4i (%0.3e, %0.3e)",
         self.domain_id, self.total_oct_count.sum(), self.ngridbound.sum())
     def _ng(c, l):
         if c < self.amr_header['ncpu']:
             ng = self.amr_header['numbl'][l, c]
         else:
             ng = self.ngridbound[c - self.amr_header['ncpu'] +
                             self.amr_header['nboundary']*l]
         return ng
     min_level = self.ds.min_level
     # yt max level is not the same as the RAMSES one.
     # yt max level is the maximum number of additional refinement levels
     # so for a uni grid run with no refinement, it would be 0. 
     # So we initially assume that.
     max_level = 0
     nx, ny, nz = (((i-1.0)/2.0) for i in self.amr_header['nx'])
     for level in range(self.amr_header['nlevelmax']):
         # Easier if do this 1-indexed
         for cpu in range(self.amr_header['nboundary'] + self.amr_header['ncpu']):
             #ng is the number of octs on this level on this domain
             ng = _ng(cpu, level)
             if ng == 0: continue
             ind = fpu.read_vector(f, "I").astype("int64")
             fpu.skip(f, 2)
             pos = np.empty((ng, 3), dtype='float64')
             pos[:,0] = fpu.read_vector(f, "d") - nx
             pos[:,1] = fpu.read_vector(f, "d") - ny
             pos[:,2] = fpu.read_vector(f, "d") - nz
             #pos *= self.ds.domain_width
             #pos += self.dataset.domain_left_edge
             fpu.skip(f, 31)
             #parents = fpu.read_vector(f, "I")
             #fpu.skip(f, 6)
             #children = np.empty((ng, 8), dtype='int64')
             #for i in range(8):
             #    children[:,i] = fpu.read_vector(f, "I")
             #cpu_map = np.empty((ng, 8), dtype="int64")
             #for i in range(8):
             #    cpu_map[:,i] = fpu.read_vector(f, "I")
             #rmap = np.empty((ng, 8), dtype="int64")
             #for i in range(8):
             #    rmap[:,i] = fpu.read_vector(f, "I")
             # We don't want duplicate grids.
             # Note that we're adding *grids*, not individual cells.
             if level >= min_level:
                 assert(pos.shape[0] == ng)
                 n = self.oct_handler.add(cpu + 1, level - min_level, pos,
                             count_boundary = 1)
                 self._error_check(cpu, level, pos, n, ng, (nx, ny, nz))
                 if n > 0: max_level = max(level - min_level, max_level)
     self.max_level = max_level
     self.oct_handler.finalize()
from __future__ import print_function
from yt.geometry.fake_octree import create_fake_octree
from yt.geometry.oct_container import RAMSESOctreeContainer, ParticleOctreeContainer
import numpy as np

nocts= 3
max_level = 12
dn = 2
dd = np.ones(3,dtype='i4')*dn
dle = np.ones(3,dtype='f8')*0.0
dre = np.ones(3,dtype='f8')
fsub = 0.25
domain = 1

oct_handler = RAMSESOctreeContainer(dd,dle,dre)
leaves = create_fake_octree(oct_handler, nocts, max_level, dd, dle, dre, fsub)
mask = np.ones((nocts,8),dtype='bool')
cell_count = nocts*8
oct_counts = oct_handler.count_levels(max_level, 1, mask)
level_counts = np.concatenate(([0,],np.cumsum(oct_counts)))
fc = oct_handler.fcoords(domain,mask,cell_count, level_counts.copy())
leavesb = oct_handler.count_leaves(mask)
assert leaves == leavesb

#Now take the fcoords, call them particles and recreate the same octree
print("particle-based recreate")
oct_handler2 = ParticleOctreeContainer(dd,dle,dre)
oct_handler2.allocate_domains([nocts])
oct_handler2.n_ref = 1 #specifically make a maximum of 1 particle per oct
oct_handler2.add(fc, 1)
print("added particles")