1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 
11 #include <vtkm/cont/CellSetStructured.h>
12 #include <vtkm/cont/DataSetBuilderUniform.h>
13 #include <vtkm/cont/DynamicCellSet.h>
14 #include <vtkm/cont/testing/MakeTestDataSet.h>
15 #include <vtkm/cont/testing/Testing.h>
16 
17 #include <algorithm>
18 #include <random>
19 #include <time.h>
20 #include <vector>
21 
22 namespace DataSetBuilderUniformNamespace
23 {
24 
25 std::mt19937 g_RandomGenerator;
26 
ValidateDataSet(const vtkm::cont::DataSet & ds,int dim,vtkm::Id numPoints,vtkm::Id numCells,vtkm::Bounds bounds)27 void ValidateDataSet(const vtkm::cont::DataSet& ds,
28                      int dim,
29                      vtkm::Id numPoints,
30                      vtkm::Id numCells,
31                      vtkm::Bounds bounds)
32 {
33   //Verify basics..
34 
35   VTKM_TEST_ASSERT(ds.GetNumberOfFields() == 2, "Wrong number of fields.");
36   VTKM_TEST_ASSERT(ds.GetNumberOfCoordinateSystems() == 1, "Wrong number of coordinate systems.");
37   VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == numPoints, "Wrong number of coordinates.");
38   VTKM_TEST_ASSERT(ds.GetNumberOfCells() == numCells, "Wrong number of cells.");
39 
40   // test various field-getting methods and associations
41   try
42   {
43     ds.GetCellField("cellvar");
44   }
45   catch (...)
46   {
47     VTKM_TEST_FAIL("Failed to get field 'cellvar' with Association::CELL_SET.");
48   }
49 
50   try
51   {
52     ds.GetPointField("pointvar");
53   }
54   catch (...)
55   {
56     VTKM_TEST_FAIL("Failed to get field 'pointvar' with ASSOC_POINT_SET.");
57   }
58 
59   //Make sure bounds are correct.
60   vtkm::Bounds res = ds.GetCoordinateSystem().GetBounds();
61   VTKM_TEST_ASSERT(test_equal(bounds, res), "Bounds of coordinates do not match");
62   if (dim == 1)
63   {
64     vtkm::cont::CellSetStructured<1> cellSet;
65     ds.GetCellSet().CopyTo(cellSet);
66     vtkm::IdComponent shape = cellSet.GetCellShape();
67     VTKM_TEST_ASSERT(shape == vtkm::CELL_SHAPE_LINE, "Wrong element type");
68   }
69   else if (dim == 2)
70   {
71     vtkm::cont::CellSetStructured<2> cellSet;
72     ds.GetCellSet().CopyTo(cellSet);
73     vtkm::IdComponent shape = cellSet.GetCellShape();
74     VTKM_TEST_ASSERT(shape == vtkm::CELL_SHAPE_QUAD, "Wrong element type");
75   }
76   else if (dim == 3)
77   {
78     vtkm::cont::CellSetStructured<3> cellSet;
79     ds.GetCellSet().CopyTo(cellSet);
80     vtkm::IdComponent shape = cellSet.GetCellShape();
81     VTKM_TEST_ASSERT(shape == vtkm::CELL_SHAPE_HEXAHEDRON, "Wrong element type");
82   }
83 }
84 
85 template <typename T>
FillMethod(vtkm::IdComponent method,vtkm::Id dimensionSize,T & origin,T & spacing)86 vtkm::Range FillMethod(vtkm::IdComponent method, vtkm::Id dimensionSize, T& origin, T& spacing)
87 {
88   switch (method)
89   {
90     case 0:
91       origin = 0;
92       spacing = 1;
93       break;
94     case 1:
95       origin = 0;
96       spacing = static_cast<T>(1.0 / static_cast<double>(dimensionSize));
97       break;
98     case 2:
99       origin = 0;
100       spacing = 2;
101       break;
102     case 3:
103       origin = static_cast<T>(-(dimensionSize - 1));
104       spacing = 1;
105       break;
106     case 4:
107       origin = static_cast<T>(2.780941);
108       spacing = static_cast<T>(182.381901);
109       break;
110     default:
111       origin = 0;
112       spacing = 0;
113       break;
114   }
115 
116   return vtkm::Range(origin, origin + static_cast<T>(dimensionSize - 1) * spacing);
117 }
118 
GetRangeByIndex(vtkm::Bounds & bounds,int comp)119 vtkm::Range& GetRangeByIndex(vtkm::Bounds& bounds, int comp)
120 {
121   VTKM_ASSERT(comp >= 0 && comp < 3);
122   switch (comp)
123   {
124     case 0:
125       return bounds.X;
126     case 1:
127       return bounds.Y;
128     default:
129       return bounds.Z;
130   }
131 }
132 
133 template <typename T>
UniformTests()134 void UniformTests()
135 {
136   const vtkm::Id NUM_TRIALS = 10;
137   const vtkm::Id MAX_DIM_SIZE = 20;
138   const vtkm::Id NUM_FILL_METHODS = 5;
139 
140   vtkm::cont::DataSetBuilderUniform dataSetBuilder;
141 
142   std::uniform_int_distribution<vtkm::Id> randomDim(2, MAX_DIM_SIZE);
143   std::uniform_int_distribution<vtkm::IdComponent> randomFill(0, NUM_FILL_METHODS - 1);
144   std::uniform_int_distribution<vtkm::IdComponent> randomAxis(0, 2);
145 
146   for (vtkm::Id trial = 0; trial < NUM_TRIALS; trial++)
147   {
148     std::cout << "Trial " << trial << std::endl;
149 
150     vtkm::Id3 dimensions(
151       randomDim(g_RandomGenerator), randomDim(g_RandomGenerator), randomDim(g_RandomGenerator));
152 
153     vtkm::IdComponent fillMethodX = randomFill(g_RandomGenerator);
154     vtkm::IdComponent fillMethodY = randomFill(g_RandomGenerator);
155     vtkm::IdComponent fillMethodZ = randomFill(g_RandomGenerator);
156     std::cout << "Fill methods: [" << fillMethodX << "," << fillMethodY << "," << fillMethodZ << "]"
157               << std::endl;
158 
159     vtkm::Vec<T, 3> origin;
160     vtkm::Vec<T, 3> spacing;
161     vtkm::Range ranges[3];
162     ranges[0] = FillMethod(fillMethodX, dimensions[0], origin[0], spacing[0]);
163     ranges[1] = FillMethod(fillMethodY, dimensions[1], origin[1], spacing[1]);
164     ranges[2] = FillMethod(fillMethodZ, dimensions[2], origin[2], spacing[2]);
165 
166     std::cout << "3D cellset" << std::endl;
167     {
168       vtkm::Id3 dims = dimensions;
169       vtkm::Bounds bounds(ranges[0], ranges[1], ranges[2]);
170 
171       std::cout << "\tdimensions: " << dims << std::endl;
172       std::cout << "\toriging: " << origin << std::endl;
173       std::cout << "\tspacing: " << spacing << std::endl;
174       std::cout << "\tbounds: " << bounds << std::endl;
175 
176       vtkm::Id numPoints = dims[0] * dims[1] * dims[2];
177       vtkm::Id numCells = (dims[0] - 1) * (dims[1] - 1) * (dims[2] - 1);
178 
179       std::vector<T> pointvar(static_cast<unsigned long>(numPoints));
180       std::iota(pointvar.begin(), pointvar.end(), T(1.1));
181       std::vector<T> cellvar(static_cast<unsigned long>(numCells));
182       std::iota(cellvar.begin(), cellvar.end(), T(1.1));
183 
184       vtkm::cont::DataSet dataSet;
185       dataSet = dataSetBuilder.Create(dims, origin, spacing);
186       dataSet.AddPointField("pointvar", pointvar);
187       dataSet.AddCellField("cellvar", cellvar);
188 
189       ValidateDataSet(dataSet, 3, numPoints, numCells, bounds);
190     }
191 
192     std::cout << "2D cellset, 2D parameters" << std::endl;
193     {
194       vtkm::Id2 dims(dimensions[0], dimensions[1]);
195       vtkm::Bounds bounds(ranges[0], ranges[1], vtkm::Range(0, 0));
196       vtkm::Vec<T, 2> org(origin[0], origin[1]);
197       vtkm::Vec<T, 2> spc(spacing[0], spacing[1]);
198 
199       std::cout << "\tdimensions: " << dims << std::endl;
200       std::cout << "\toriging: " << org << std::endl;
201       std::cout << "\tspacing: " << spc << std::endl;
202       std::cout << "\tbounds: " << bounds << std::endl;
203 
204       vtkm::Id numPoints = dims[0] * dims[1];
205       vtkm::Id numCells = (dims[0] - 1) * (dims[1] - 1);
206 
207       std::vector<T> pointvar(static_cast<unsigned long>(numPoints));
208       std::iota(pointvar.begin(), pointvar.end(), T(1.1));
209       std::vector<T> cellvar(static_cast<unsigned long>(numCells));
210       std::iota(cellvar.begin(), cellvar.end(), T(1.1));
211 
212       vtkm::cont::DataSet dataSet;
213       dataSet = dataSetBuilder.Create(dims, org, spc);
214       dataSet.AddPointField("pointvar", pointvar);
215       dataSet.AddCellField("cellvar", cellvar);
216 
217       ValidateDataSet(dataSet, 2, numPoints, numCells, bounds);
218     }
219 
220     std::cout << "2D cellset, 3D parameters" << std::endl;
221     {
222       vtkm::Id3 dims = dimensions;
223       vtkm::Bounds bounds(ranges[0], ranges[1], ranges[2]);
224 
225       int x = randomAxis(g_RandomGenerator);
226       dims[x] = 1;
227       GetRangeByIndex(bounds, x).Max = ranges[x].Min;
228 
229       std::cout << "\tdimensions: " << dims << std::endl;
230       std::cout << "\toriging: " << origin << std::endl;
231       std::cout << "\tspacing: " << spacing << std::endl;
232       std::cout << "\tbounds: " << bounds << std::endl;
233 
234       vtkm::Id numPoints = dims[(x + 1) % 3] * dims[(x + 2) % 3];
235       vtkm::Id numCells = (dims[(x + 1) % 3] - 1) * (dims[(x + 2) % 3] - 1);
236 
237       std::vector<T> pointvar(static_cast<unsigned long>(numPoints));
238       std::iota(pointvar.begin(), pointvar.end(), T(1.1));
239       std::vector<T> cellvar(static_cast<unsigned long>(numCells));
240       std::iota(cellvar.begin(), cellvar.end(), T(1.1));
241 
242       vtkm::cont::DataSet dataSet;
243       dataSet = dataSetBuilder.Create(dims, origin, spacing);
244       dataSet.AddPointField("pointvar", pointvar);
245       dataSet.AddCellField("cellvar", cellvar);
246 
247       ValidateDataSet(dataSet, 2, numPoints, numCells, bounds);
248     }
249 
250     std::cout << "1D cellset, 1D parameters" << std::endl;
251     {
252       vtkm::Bounds bounds(ranges[0], vtkm::Range(0, 0), vtkm::Range(0, 0));
253 
254       std::cout << "\tdimensions: " << dimensions[0] << std::endl;
255       std::cout << "\toriging: " << origin[0] << std::endl;
256       std::cout << "\tspacing: " << spacing[0] << std::endl;
257       std::cout << "\tbounds: " << bounds << std::endl;
258 
259       vtkm::Id numPoints = dimensions[0];
260       vtkm::Id numCells = dimensions[0] - 1;
261 
262       std::vector<T> pointvar(static_cast<unsigned long>(numPoints));
263       std::iota(pointvar.begin(), pointvar.end(), T(1.1));
264       std::vector<T> cellvar(static_cast<unsigned long>(numCells));
265       std::iota(cellvar.begin(), cellvar.end(), T(1.1));
266 
267       vtkm::cont::DataSet dataSet;
268       dataSet = dataSetBuilder.Create(dimensions[0], origin[0], spacing[0]);
269       dataSet.AddPointField("pointvar", pointvar);
270       dataSet.AddCellField("cellvar", cellvar);
271 
272       ValidateDataSet(dataSet, 1, numPoints, numCells, bounds);
273     }
274 
275     std::cout << "1D cellset, 2D parameters" << std::endl;
276     {
277       vtkm::Id2 dims(dimensions[0], dimensions[1]);
278       vtkm::Bounds bounds(ranges[0], ranges[1], vtkm::Range(0, 0));
279       vtkm::Vec<T, 2> org(origin[0], origin[1]);
280       vtkm::Vec<T, 2> spc(spacing[0], spacing[1]);
281 
282       int x = randomAxis(g_RandomGenerator) % 2;
283       dims[x] = 1;
284       GetRangeByIndex(bounds, x).Max = ranges[x].Min;
285 
286       std::cout << "\tdimensions: " << dims << std::endl;
287       std::cout << "\toriging: " << org << std::endl;
288       std::cout << "\tspacing: " << spc << std::endl;
289       std::cout << "\tbounds: " << bounds << std::endl;
290 
291       vtkm::Id numPoints = dims[(x + 1) % 2];
292       vtkm::Id numCells = dims[(x + 1) % 2] - 1;
293 
294       std::vector<T> pointvar(static_cast<unsigned long>(numPoints));
295       std::iota(pointvar.begin(), pointvar.end(), T(1.1));
296       std::vector<T> cellvar(static_cast<unsigned long>(numCells));
297       std::iota(cellvar.begin(), cellvar.end(), T(1.1));
298 
299       vtkm::cont::DataSet dataSet;
300       dataSet = dataSetBuilder.Create(dims, org, spc);
301       dataSet.AddPointField("pointvar", pointvar);
302       dataSet.AddCellField("cellvar", cellvar);
303 
304       ValidateDataSet(dataSet, 1, numPoints, numCells, bounds);
305     }
306 
307     std::cout << "1D cellset, 3D parameters" << std::endl;
308     {
309       vtkm::Id3 dims = dimensions;
310       vtkm::Bounds bounds(ranges[0], ranges[1], ranges[2]);
311 
312       int x = randomAxis(g_RandomGenerator);
313       int x1 = (x + 1) % 3;
314       int x2 = (x + 2) % 3;
315       dims[x1] = dims[x2] = 1;
316       GetRangeByIndex(bounds, x1).Max = ranges[x1].Min;
317       GetRangeByIndex(bounds, x2).Max = ranges[x2].Min;
318 
319       std::cout << "\tdimensions: " << dims << std::endl;
320       std::cout << "\toriging: " << origin << std::endl;
321       std::cout << "\tspacing: " << spacing << std::endl;
322       std::cout << "\tbounds: " << bounds << std::endl;
323 
324       vtkm::Id numPoints = dims[x];
325       vtkm::Id numCells = dims[x] - 1;
326 
327       std::vector<T> pointvar(static_cast<unsigned long>(numPoints));
328       std::iota(pointvar.begin(), pointvar.end(), T(1.1));
329       std::vector<T> cellvar(static_cast<unsigned long>(numCells));
330       std::iota(cellvar.begin(), cellvar.end(), T(1.1));
331 
332       vtkm::cont::DataSet dataSet;
333       dataSet = dataSetBuilder.Create(dims, origin, spacing);
334       dataSet.AddPointField("pointvar", pointvar);
335       dataSet.AddCellField("cellvar", cellvar);
336 
337       ValidateDataSet(dataSet, 1, numPoints, numCells, bounds);
338     }
339   }
340 }
341 
TestDataSetBuilderUniform()342 void TestDataSetBuilderUniform()
343 {
344   vtkm::UInt32 seed = static_cast<vtkm::UInt32>(time(nullptr));
345   std::cout << "Seed: " << seed << std::endl;
346   g_RandomGenerator.seed(seed);
347 
348   std::cout << "======== Float32 ==========================" << std::endl;
349   UniformTests<vtkm::Float32>();
350   std::cout << "======== Float64 ==========================" << std::endl;
351   UniformTests<vtkm::Float64>();
352 }
353 
354 } // namespace DataSetBuilderUniformNamespace
355 
UnitTestDataSetBuilderUniform(int argc,char * argv[])356 int UnitTestDataSetBuilderUniform(int argc, char* argv[])
357 {
358   using namespace DataSetBuilderUniformNamespace;
359   return vtkm::cont::testing::Testing::Run(TestDataSetBuilderUniform, argc, argv);
360 }
361