/// <summary> /// Setup as empty map with only one value at 1. /// </summary> /// <param name="pos"></param> /// <param name="fieldEnsemble"></param> /// <param name="startTime"></param> /// <param name="endTime"></param> public void SetupPoint(Int2 pos, int startTime) { // ~~~~~~~~~~~~~~ Copy relevant data ~~~~~~~~~~~~~~ \\ // Count up when advection was executed. CurrentTime = startTime; _startTime = startTime; // ~~~~~~~~~~~~ Load ensemble ~~~~~~~~~~~~ \\ // Load fields first to get the grid size. //Loader ncFile = new Loader(RedSea.Singleton.DataFolder + (_startTime + 1) + RedSea.Singleton.FileName); //ScalarField t0X = ncFile.LoadFieldSlice(_ensembleRanges[0]); //ScalarField t0Y = ncFile.LoadFieldSlice(_ensembleRanges[1]); //ncFile.Close(); LoaderNCF ncFile = RedSea.Singleton.GetLoaderNCF(_startTime); ScalarField t1X = ncFile.LoadFieldSlice(_ensembleRanges[0]); ScalarField t1Y = ncFile.LoadFieldSlice(_ensembleRanges[1]); ncFile.Close(); // ~~~~~~~~~~~~~~ Copy relevant data ~~~~~~~~~~~~~~ \\ // Keep for plane creation and size reference. _ensembleGrid = t1X.Grid as RectlinearGrid; // Mapper for binding the SlimDX texture to CUDA easily. _cudaDxMapper = new CudaGraphicsInteropResourceCollection(); // Tell CUDA which value is a border. _texInvalidValue = t1X.InvalidValue ?? float.MaxValue; // ~~~~~~~~~~~~ Fill CUDA resources ~~~~~~~~~~~~ \\ // All members are above each other. int vHeight = _height * _numMembers; //// vX, t=0 //_t0X = new CudaArray2D(CUArrayFormat.Float, _width, vHeight, CudaArray2DNumChannels.One); //_t0X.CopyFromHostToThis<float>(t0X.Data); //new CudaTextureArray2D(_advectParticlesKernel, "vX_t0", CUAddressMode.Wrap, CUFilterMode.Linear, CUTexRefSetFlags.None, _t0X); //// vY, t=0 //_t0Y = new CudaArray2D(CUArrayFormat.Float, _width, vHeight, CudaArray2DNumChannels.One); //_t0Y.CopyFromHostToThis<float>(t0Y.Data); //new CudaTextureArray2D(_advectParticlesKernel, "vY_t0", CUAddressMode.Wrap, CUFilterMode.Linear, CUTexRefSetFlags.None, _t0Y); // vX, t=1 _t1X = new CudaArray2D(CUArrayFormat.Float, _width, vHeight, CudaArray2DNumChannels.One); _t1X.CopyFromHostToThis <float>(t1X.Data); new CudaTextureArray2D(_advectParticlesKernel, "vX_t1", CUAddressMode.Wrap, CUFilterMode.Linear, CUTexRefSetFlags.None, _t1X); // vY, t=1 _t1Y = new CudaArray2D(CUArrayFormat.Float, _width, vHeight, CudaArray2DNumChannels.One); _t1Y.CopyFromHostToThis <float>(t1Y.Data); new CudaTextureArray2D(_advectParticlesKernel, "vY_t1", CUAddressMode.Wrap, CUFilterMode.Linear, CUTexRefSetFlags.None, _t1Y); // ~~~~~~~~~~~~~ Create texture ~~~~~~~~~~~~~~~~~~~~ \\ // Create texture. Completely zero, except for one point. Texture2DDescription desc = new Texture2DDescription { ArraySize = 1, BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, Format = Format.R32_Float, Width = _width, Height = _height, MipLevels = 1, OptionFlags = ResourceOptionFlags.None, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default }; // Put field data into stream/rectangle object float[] zeros = new float[_width * _height]; Array.Clear(zeros, 0, zeros.Length); // Fill the empty texture. DataRectangle texData = new DataRectangle(_width * sizeof(float), new DataStream(zeros, true, true)); _pongFlowMap = new CudaDeviceVariable <float>(_width * _height);//new Texture2D(_device, desc, texData); // Magically, copy to device happens here. _pongFlowMap = zeros; // Add one pixel for integration. zeros[pos.X + pos.Y * _width] = 1; texData = new DataRectangle(_width * sizeof(float), new DataStream(zeros, true, true)); // Create texture. FlowMap = new Texture2D(_device, desc, texData); // ~~~~~~~~~ Make textures mappable to CUDA ~~~~~~~~~~ \\ _cudaDxMapper.Add(new CudaDirectXInteropResource(FlowMap.ComPointer, CUGraphicsRegisterFlags.None, CudaContext.DirectXVersion.D3D11)); _cudaDxMapper.MapAllResources(); CudaArray2D lastFlowMap = _cudaDxMapper[0].GetMappedArray2D(0, 0); new CudaTextureArray2D(_advectParticlesKernel, "flowMap", CUAddressMode.Wrap, CUFilterMode.Linear, CUTexRefSetFlags.None, lastFlowMap); _cudaDxMapper.UnmapAllResources(); }
protected void BuildGraph() { // Compute ftle. if (LineX == 0) { return; } _graphData = FieldAnalysis.WriteGraphToSun(_okubo, new Vector3(_selection.X, _selection.Y, 0)); _graph = new LineBall(_graphPlane, _graphData, LineBall.RenderEffect.HEIGHT, Colormap, Flat, SliceTimeMain); _graph.LowerBound = -0.05f; _graph.UpperBound = 0.05f; _rebuilt = false; // Load or compute selection by floodfill. Graph2D[] okuboSelection; LineSet okuboLines; if (LoadGraph("OkuboSelection", _selectedCore, out okuboSelection, out okuboLines)) { return; } // Floodfill. int numAngles = _okubo.Length; int numRadii = _okubo[0].Length; HashSet <Int2> toFlood = new HashSet <Int2>(); okuboSelection = new Graph2D[numAngles]; for (int angle = 0; angle < numAngles; ++angle) { toFlood.Add(new Int2(angle, 0)); okuboSelection[angle] = new Graph2D(numRadii); for (int r = 1; r < numRadii; ++r) { okuboSelection[angle].Fx[r] = 0; okuboSelection[angle].X[r] = _okubo[angle].X[r]; } } while (toFlood.Count > 0) { Int2 current = toFlood.Last(); toFlood.Remove(current); okuboSelection[current.X].Fx[current.Y] = 1; // In each direction, go negative and positive. for (int dim = 0; dim < 2; ++dim) { for (int sign = -1; sign <= 1; sign += 2) { Int2 neighbor = new Int2(current); neighbor[dim] += sign; // Wrap angle around. neighbor[0] = (neighbor[0] + numAngles) % numAngles; if (neighbor.Y >= 0 && neighbor.Y < numRadii && _okubo[neighbor.X].Fx[neighbor.Y] <= 0 && okuboSelection[neighbor.X].Fx[neighbor.Y] == 0) { toFlood.Add(neighbor); } } } } LineSet sun = FieldAnalysis.WriteGraphToSun(okuboSelection, new Vector3(_selection, SliceTimeMain)); WriteGraph("OkuboSelection", _selectedCore, okuboSelection, sun); }
public abstract void Subrange(Int2 min, Int2 max, Int2 selection);
public abstract void CompleteRange(Int2 selection);
public static bool Equals(Int2 a, Int2 b) { return(a == b); }
public Int2(Int2 copy) : base(copy) { }
public float this[Int2 index] { get { return(this[index.X][index.Y]); } set { this[index.X][index.Y] = value; } }