%debug

"""
Explanation: Problem
There's a fundamental problem with what I'm trying to do. It's that stupid connect1!!! What I should do is grep for all occurences of mesh_id = int(ftype[-1]) - 1 because any time that code occurs, it's going to disrupt what I'm trying to do. For now, I'm going to try this one more substituion in cartesian_coordinates.py and then it's time to call it a day.
End of explanation
"""


def createGenerator():
    mylist = range(3)
    for i in mylist:
        yield i*i
        
my_generator_function = createGenerator()
print(my_generator_function)

"""
Explanation: Ok, here is some stuff going down:

We start off by creating a YTSlice object.
We call YTSlice.get_data() since apparently YTSlice inherits from YTSelectionContainer
The first thing the get_data() routine does is call: self.index._identify_base_chunk(self)
Here's the hierarchy of indexes: ExodusIIUnstructuredIndex(/frontends/exodusii/data_structures) -> UnstructuredIndex(/geometry/unstructured_mesh_handler) -> Index(/geometry/geometry_handler)
The _identify_base_chunk routine is implemented in the UnstructuredIndex class
In that method, the first thing done is: dobj._chunk_info = self.meshes. Recall that dobj refers to the YTSlice object and self currently is the UnstructuredIndex object
The next important piece of code executed is: dobj._current_chunk = list(self._chunk_all(dobj))[0]
This calls the _chunk_all method implemented in the UnstructuredIndex class
The _chunk_all method creates a generator. In this case list(self._chunk_all(dobj)) is a list of length 1, presumably because we're using an "all" method.
_chunk_all creates a a YTDataChunk instance through yield YTDataChunk(dobj, "all", oobjs, dobj.size, cache)
Note that oobjs were created like this: oobjs = getattr(dobj._current_chunk, "objs", dobj._chunk_info). So essentially oobjs = dobj._chunk_info = self.meshes
The YTDataChunk __init__ routine looks like this:
def __init__(self, dobj, chunk_type, objs, data_size = None,
                 field_type = None, cache = False, fast_index = None):
        self.dobj = dobj
        self.chunk_type = chunk_type
        self.objs = objs
        self.data_size = data_size
        self._field_type = field_type
        self._cache = cache
        self._fast_index = fast_index
So translating: dobj is the YTSlice object, chunk_type = "all" and the objs are equal to the list of UnstructuredMeshes

To summarize, the YTSlice _current_chunk attribute is equal to a YTDataChunk instance with attributes of self.dobj equal to the YTSlice instance and self.objs equal to the list of UnstructuredMeshes.
However, what we actually pass to the the all (or maybe) important io._read_fluid_selection routine is chunks created from the _chunk_io(dobj) routine.

The _chunk_io function also creates a generator; this time a generator that if it was converted into a list would be of length equal to the number of meshes.
In more detail it (UnstructuredIndex._chunk_io) passes (in list form): chunks = [YTDataChunk_0 with dobj = YTSlice and objs = [UnstructuredMesh0], YTDataChunk_1 with dobj = YTSlice and objs = [UnstructuredMesh1], ..., YTDataChunk_N-1 with dobj = YTSlice and objs = [UnstructuredMeshN-1]
While UnstructuredIndex._chunk_all passes (in list form): chunks = [YTDataChunk with dobj = YTSlice and objs = [UnstructuredMesh0, UnstructuredMesh1, ..., UnstructuredMeshN-1]]

Exploring Generators
Just when you think you're starting to make serious progress, you run into another new fundamental concept!
Here's a generator function I think:
End of explanation
"""


def createFunction():
    mylist = range(3)
    for i in mylist:
        return i*i
        
my_regular_function = createFunction()
print(my_regular_function)

"""
Explanation: And here's a regular function:
End of explanation
"""


for i in my_generator_function:
    print(i)

list_from_gen = list(createGenerator())
print(list_from_gen)
print(len(list_from_gen))

slice.show()

print(array1)
print(array2)

slice = yt.SlicePlot(ds2, 'z', [('all','diffused')])

array1 = ad2[('connect1','diffused')]
array2 = ad2[('connect2','diffused')]
print(array1.shape)
print(array2.shape)

my_io_handler = yt.frontends.exodus_ii.IOHandlerExodusII(ds2)

variables = my_io_handler.handler.variables
print(variables)

ci = variables['connect1'][:] - 1
ci2 = variables['connect2'][:] - 1

print(ci)

print(ci.shape)
print(ci2.shape)

import numpy as np

all_array = np.concatenate((ci, ci2))
print(all_array.shape)

print(variables['vals_nod_var1'][-1][all_array])

print(all_array)

newarray = ci + ci2
print(newarray.shape)

type(ci)

print(variables['vals_nod_var1'].shape)

print(variables['vals_nod_var1'][1])

print(variables['vals_nod_var1'][-1][:])
print(variables['vals_nod_var1'][-1][:].shape)

print(variables['vals_nod_var1'][-1])
print(variables['vals_nod_var1'][-1].shape)

print(variables['vals_nod_var1'][-1][ci])
print(variables['vals_nod_var1'][-1][ci].shape)

print(variables['vals_nod_var1'][ci])
print(variables['vals_nod_var1'][ci].shape)

print(my_io_handler.ds.step)

"""
Explanation: Psych! A function with a regular return returns as soon it hits return the first time.
End of explanation
"""


