1 // Copyright 2009-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #include "rawToAMR.h"
5 
6 static const std::string description = R"description(
7 Creates an adaptive mesh refinement (AMR) representation of the provided
8 structured volume data.
9 
10 The input structured volume data is used as the highest refinement level
11 (i.e. the finest resolution data). From this level, data that does not meet
12 the user-provided variance threshold is discarded. The average of the
13 discarded block is used in the next level down.
14 
15 This simulates the effect that an adaptive simulation would have created
16 regions of higher refinement in the highly varying portions of the volume.
17 )description";
18 
19 static const std::string usage =
20     R"usage([-h | --help] input_volume variable_type x_dim y_dim z_dim num_levels
21     block_size refinement_factor threshold output_basename
22 )usage";
23 
24 static const std::string help = R"help(
25 input_volume        Structured volume in binary brick-of-data format
26                     (string filepath)
27 variable_type       Type of structured volume, must be exactly one of:
28                         float
29                     (string)
30 x_dim               X dimensions of the structured volume grid (int)
31 y_dim               Y dimensions of the structured volume grid (int)
32 z_dim               Z dimensions of the structured volume grid (int)
33 num_levels          Number of refinement levels to simulate (int)
34 block_size          Size of blocks at each level in terms of cells. Blocks
35                     are defined as cubes with this number of cells per edge.
36                     Note that refinement levels change the width of the
37                     cells, NOT the width of the blocks. Blocks will always
38                     be this provided size in cell extents, but the width of
39                     the cells will be smaller/larger depending on level.
40                     For example, a block of 4x4x4 cells at the highest
41                     refinement level will be converted into a single cell
42                     at the next lower level, which would be part of that
43                     level's block of 4x4x4 cells. (int)
44 refinement_factor   How much larger/smaller, in terms of cell extents, each
45                     level's grid will be. Note that this is independent of
46                     block_size above! For example, if the input data is a
47                     512^3 grid, and block_size is 4^3, the highest
48                     refinement level will have a 128^3 block grid. If this
49                     value is 2, the next level will have a 64^3 block grid,
50                     but will still be comprised of 4^3 blocks. That is, the
51                     number of cells decreases from 512^3 to 256^3, and the
52                     cell width increases to accommodate. (int)
53 threshold           Variance threshold used to determine whether a block
54                     belongs to a higher refinement level. If the variance
55                     within a block is above this threshold, it remains at
56                     the current level. Otherwise, if the variance is low,
57                     this block would have not have been selected for mesh
58                     refinement by a numerical simulation, so this block is
59                     discarded at this level. (variable_type, converted to
60                     float)
61 output_basename     Basename for the output files. This application creates
62                     three files with different extensions, with this basename
63                     in common. (string)
64 )help";
65 
66 using namespace rkcommon::math;
67 
68 static std::string inFileName;
69 static std::string format;
70 static vec3i inDims;
71 static int numLevels;
72 static int blockSize;
73 static int refinementLevel;
74 static float threshold;
75 static std::string outFileBase;
76 
parseArguments(int argc,char ** argv)77 bool parseArguments(int argc, char **argv)
78 {
79   if (argc != 11) {
80     if (argc > 1
81         && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help")) {
82       std::cerr << description << std::endl;
83       std::cerr << "Usage: " << argv[0] << " " << usage << std::endl;
84       std::cerr << help << std::endl;
85     } else {
86       std::cerr << argc - 1 << " argument"
87                 << ((argc == 1 || argc > 2) ? "s " : " ");
88       std::cerr << "provided, but 10 are needed" << std::endl;
89       std::cerr << "Usage: " << argv[0] << " " << usage << std::endl;
90     }
91     return false;
92   }
93 
94   inFileName = argv[1];
95   format = argv[2];
96   inDims.x = atoi(argv[3]);
97   inDims.y = atoi(argv[4]);
98   inDims.z = atoi(argv[5]);
99   numLevels = atoi(argv[6]);
100   blockSize = atoi(argv[7]);
101   refinementLevel = atoi(argv[8]);
102   threshold = atof(argv[9]);
103   outFileBase = argv[10];
104 
105   return true;
106 }
107 
main(int argc,char ** argv)108 int main(int argc, char **argv)
109 {
110   bool parseSucceed = parseArguments(argc, argv);
111   if (!parseSucceed) {
112     return 1;
113   }
114 
115   // ALOK: TODO:
116   // support more than float
117   std::vector<float> in;
118   if (format == "float") {
119     in = ospray::amr::mmapRAW<float>(inFileName, inDims);
120   } else {
121     throw std::runtime_error("unsupported input voxel format");
122   }
123 
124   std::vector<box3i> blockBounds;
125   std::vector<int> refinementLevels;
126   std::vector<float> cellWidths;
127   std::vector<std::vector<float>> brickData;
128 
129   ospray::amr::makeAMR(in,
130       inDims,
131       numLevels,
132       blockSize,
133       refinementLevel,
134       threshold,
135       blockBounds,
136       refinementLevels,
137       cellWidths,
138       brickData);
139   ospray::amr::outputAMR(outFileBase,
140       blockBounds,
141       refinementLevels,
142       cellWidths,
143       brickData,
144       blockSize);
145 
146   return 0;
147 }
148