Example #1
0
    void AggregateClusters(uint uParentLayer)
    {
        // number of cells in each grid cluster
        uint[] pClusterDims = mInfluenceTree.GetDecimations((int)uParentLayer);

        uint[] numCells = { mInfluenceTree[uParentLayer].GetNumCells(0), mInfluenceTree[uParentLayer].GetNumCells(1), mInfluenceTree[uParentLayer].GetNumCells(2) };
        uint   numXY    = mInfluenceTree[uParentLayer].GetNumPoints(0) * mInfluenceTree[uParentLayer].GetNumPoints(1);

        // (Since this loop writes to each parent cell, it should readily parallelize without contention.)
        uint[] idxParent = new uint[3];
        for (idxParent[2] = 0; idxParent[2] < numCells[2]; ++idxParent[2])
        {
            uint offsetZ = idxParent[2] * numXY;
            for (idxParent[1] = 0; idxParent[1] < numCells[1]; ++idxParent[1])
            {
                uint offsetYZ = idxParent[1] * mInfluenceTree[uParentLayer].GetNumPoints(0) + offsetZ;
                for (idxParent[0] = 0; idxParent[0] < numCells[0]; ++idxParent[0])
                {   // For each cell in the parent layer...
                    uint offsetXYZ = idxParent[0] + offsetYZ;

                    UniformGrid <Vorton> rChildLayer = mInfluenceTree[uParentLayer - 1];
                    VortonClusterAux     vortAux     = new VortonClusterAux();
                    uint[] clusterMinIndices         = mInfluenceTree.GetChildClusterMinCornerIndex(pClusterDims, idxParent);;

                    uint[] increment  = { 0, 0, 0 };
                    uint   numXchild  = rChildLayer.GetNumPoints(0);
                    uint   numXYchild = numXchild * rChildLayer.GetNumPoints(1);
                    // For each cell of child layer in this grid cluster...
                    for (increment[2] = 0; increment[2] < pClusterDims[2]; ++increment[2])
                    {
                        uint childOffsetZ = (clusterMinIndices[2] + increment[2]) * numXYchild;
                        for (increment[1] = 0; increment[1] < pClusterDims[1]; ++increment[1])
                        {
                            uint childOffsetYZ = (clusterMinIndices[1] + increment[1]) * numXchild + childOffsetZ;
                            for (increment[0] = 0; increment[0] < pClusterDims[0]; ++increment[0])
                            {
                                uint   childOffsetXYZ = (clusterMinIndices[0] + increment[0]) + childOffsetYZ;
                                Vorton rVortonChild   = rChildLayer[childOffsetXYZ];
                                float  vortMag        = rVortonChild.vorticity.magnitude;

                                // Aggregate vorton cluster from child layer into parent layer:
                                mInfluenceTree[uParentLayer][offsetXYZ].position  += rVortonChild.position * vortMag;
                                mInfluenceTree[uParentLayer][offsetXYZ].vorticity += rVortonChild.vorticity;
                                vortAux.mVortNormSum += vortMag;
                                if (rVortonChild.radius != 0.0f)
                                {
                                    mInfluenceTree[uParentLayer][offsetXYZ].radius = rVortonChild.radius;
                                }
                            }
                        }
                    }
                    // Normalize weighted position sum to obtain center-of-vorticity.
                    // (See analogous code in MakeBaseVortonGrid.)
                    mInfluenceTree[uParentLayer][offsetXYZ].position /= vortAux.mVortNormSum;
                }
            }
        }
    }
Example #2
0
    /*
     *  Create base layer of vorton influence tree.
     *
     *  This is the leaf layer, where each grid cell corresponds(on average) to
     *  a single vorton.Some cells might contain multiple vortons and some zero.
     *
     *  Each cell effectively has a single "supervorton" which its parent layers
     *  in the influence tree will in turn aggregate.
     *
     *  This implementation of gridifying the base layer is NOT suitable
     *  for Eulerian operations like approximating spatial derivatives
     *
     *  of vorticity or solving a vector Poisson equation, because this
     *  routine associates each vortex with a single corner point of the
     *  grid cell that contains it.  To create a grid for Eulerian calculations,
     *  each vorton would contribute to all 8 corner points of the grid
     *  cell that contains it.
     *
     *  We could rewrite this to suit "Eulerian" operations, in which case
     *  we would want to omit "size" and "position" since the grid would
     *
     *  implicitly represent that information.  That concern goes hand-in-hand
     *  with the method used to compute velocity from vorticity.
     *
     *  Ultimately we need to make sure theoretically conserved quantities behave as expected.
     *
     *  This method assumes the influence tree skeleton has already been created,
     *  and the leaf layer initialized to all "zeros", meaning it contains no vortons.
     */
    public void MakeBaseVortonGrid()
    {
        int numVortons = mVortons.Count;

        UniformGrid <VortonClusterAux> ugAux = new UniformGrid <VortonClusterAux>(mInfluenceTree[0]); // Temporary auxilliary information used during aggregation.

        ugAux.Init();

        // Compute preliminary vorticity grid.
        for (int uVorton = 0; uVorton < numVortons; ++uVorton)
        {   // For each vorton in this simulation...
            Vector3 position = mVortons[uVorton].position;
            uint    uOffset  = mInfluenceTree[0].OffsetOfPosition(position);

            float vortMag = mVortons[uVorton].vorticity.magnitude;

            mInfluenceTree[0][uOffset].position  += mVortons[uVorton].position * vortMag; // Compute weighted position -- to be normalized later.
            mInfluenceTree[0][uOffset].vorticity += mVortons[uVorton].vorticity;          // Tally vorticity sum.
            mInfluenceTree[0][uOffset].radius     = mVortons[uVorton].radius;             // Assign volume element size.
            // OBSOLETE. See comments below: UpdateBoundingBox( rVortonAux.mMinCorner , rVortonAux.mMaxCorner , rVorton.mPosition ) ;
            ugAux[uOffset].mVortNormSum += vortMag;                                       // Accumulate vorticity on the VortonClusterAux
        }

        // Post-process preliminary grid (VortonClusterAux); normalize center-of-vorticity and compute sizes, for each grid cell.
        uint[] num =
        {
            mInfluenceTree[0].GetNumPoints(0),
            mInfluenceTree[0].GetNumPoints(1),
            mInfluenceTree[0].GetNumPoints(2)
        };
        uint numXY = num[0] * num[1];

        uint[] idx = new uint[3];
        for (idx[2] = 0; idx[2] < num[2]; ++idx[2])
        {
            uint zShift = idx[2] * numXY;
            for (idx[1] = 0; idx[1] < num[1]; ++idx[1])
            {
                uint yzShift = idx[1] * num[0] + zShift;
                for (idx[0] = 0; idx[0] < num[0]; ++idx[0])
                {
                    uint             offset     = idx[0] + yzShift;
                    VortonClusterAux rVortonAux = ugAux[offset];
                    if (rVortonAux.mVortNormSum != float.Epsilon)
                    {   // This cell contains at least one vorton.
                        // Normalize weighted position sum to obtain center-of-vorticity.
                        mInfluenceTree[0][offset].position /= rVortonAux.mVortNormSum;
                    }
                }
            }
        }
    }