test_atrstm.c (8649B)
1 /* Copyright (C) 2022, 2023 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2020, 2021 Centre National de la Recherche Scientifique 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "atrstm.h" 18 19 #include <rsys/cstr.h> 20 #include <rsys/mem_allocator.h> 21 #include <rsys/rsys.h> 22 23 #include <getopt.h> 24 #include <stdio.h> 25 #include <string.h> 26 27 struct args { 28 struct atrstm_args atrstm; 29 const char* dump_octree_filename; /* NULL <=> no dump */ 30 int quit; 31 }; 32 33 #define ARGS_DEFAULT__ { ATRSTM_ARGS_DEFAULT__, NULL, 0 } 34 static const struct args ARGS_DEFAULT = ARGS_DEFAULT__; 35 36 /******************************************************************************* 37 * Helper functions 38 ******************************************************************************/ 39 static void 40 print_help(const char* cmd) 41 { 42 ASSERT(cmd); 43 printf( 44 "Usage: %s <option>...\n" 45 "Test the Astoria: Semi-Transparent Medium library.\n", 46 cmd); 47 printf("\n"); 48 printf( 49 " -d OCTREE dump SVX octree to the OCTREE file.\n"); 50 printf( 51 " -f FRACTAL_DIM fractal dimension. Its default value is %g.\n", 52 ATRSTM_ARGS_DEFAULT.fractal_dimension); 53 printf( 54 " -g PREFACTOR fractal prefactor. Its default value is %g.\n", 55 ATRSTM_ARGS_DEFAULT.fractal_prefactor); 56 printf( 57 " -h display this help and exit.\n"); 58 printf( 59 " -m TETRAHEDRA path toward the volumetric mesh.\n"); 60 printf( 61 " -N precompute the tetrahedra normals.\n"); 62 printf( 63 " -n NAME name of the medium. Default is \"%s\".\n", 64 ATRSTM_ARGS_DEFAULT.name); 65 printf( 66 " -O CACHE name of the cache file to use/fill. By default\n" 67 " no cache is used\n"); 68 printf( 69 " -p THERMOPROPS path toward the thermodynamic properties.\n"); 70 printf( 71 " -r REFRACT_ID path toward the per wavelength refractive\n" 72 " indices.\n"); 73 printf( 74 " -T THRESHOLD optical thickness used as threshold during the octree\n" 75 " building. By default its value is %g.\n", 76 ATRSTM_ARGS_DEFAULT.optical_thickness); 77 printf( 78 " -t NTHREADS hint on the number of threads to use. By default use\n" 79 " as many threads as CPU cores.\n"); 80 printf( 81 " -V <DEFINITION|X,Y,Z>\n" 82 " maximum definition of the acceleration grids\n" 83 " along the 3 axis. Its default value is [%u, %u, %u].\n", 84 SPLIT3(ATRSTM_ARGS_DEFAULT.grid_max_definition)); 85 printf( 86 " -v make the program verbose.\n"); 87 printf( 88 " -w WAVELENGTH shortwave wavelength to use, in nanometer.\n" 89 " By default it is set to %g nm\n", 90 ATRSTM_ARGS_DEFAULT.wlen_range[0]); 91 printf("\n"); 92 printf( 93 "This is free software released under the GNU GPL license, version 3 or\n" 94 "later. You are free to change or redistribute it under certain\n" 95 "conditions <http://gnu.org.licenses/gpl.html>\n"); 96 } 97 98 static res_T 99 parse_grid_definition(struct atrstm_args* args, const char* str) 100 { 101 unsigned def[3]; 102 size_t len; 103 res_T res = RES_OK; 104 ASSERT(args && str); 105 106 res = cstr_to_list_uint(str, ',', def, &len, 3); 107 if(res == RES_OK && len == 2) res = RES_OK; 108 if(res != RES_OK) { 109 fprintf(stderr, "Invalid grid definition `%s'.\n", str); 110 goto error; 111 } 112 113 if(len == 1) { 114 if(!def[0]) { 115 fprintf(stderr, "Invalid null grid definition %u.\n", def[0]); 116 res = RES_BAD_ARG; 117 goto error; 118 } 119 args->auto_grid_definition = 1; 120 args->auto_grid_definition_hint = def[0]; 121 122 } else { 123 if(!def[0] || !def[1] || !def[2]) { 124 fprintf(stderr, 125 "Invalid null grid definition [%u, %u, %u].\n", SPLIT3(def)); 126 res = RES_BAD_ARG; 127 goto error; 128 } 129 args->auto_grid_definition = 0; 130 args->grid_max_definition[0] = def[0]; 131 args->grid_max_definition[1] = def[1]; 132 args->grid_max_definition[2] = def[2]; 133 } 134 135 exit: 136 return res; 137 error: 138 goto exit; 139 } 140 141 static void 142 args_release(struct args* args) 143 { 144 ASSERT(args); 145 *args = ARGS_DEFAULT; 146 } 147 148 static res_T 149 args_init(struct args* args, int argc, char** argv) 150 { 151 res_T res = RES_OK; 152 int opt; 153 ASSERT(args && argc && argv); 154 155 *args = ARGS_DEFAULT; 156 157 while((opt = getopt(argc, argv, "d:f:g:hm:Nn:O:p:T:t:r:vV:w:")) != -1) { 158 switch(opt) { 159 case 'd': args->dump_octree_filename = optarg; break; 160 case 'f': 161 res = cstr_to_double(optarg, &args->atrstm.fractal_dimension); 162 if(res == RES_OK && args->atrstm.fractal_dimension <= 0) 163 res = RES_BAD_ARG; 164 break; 165 case 'g': 166 res = cstr_to_double(optarg, &args->atrstm.fractal_prefactor); 167 if(res == RES_OK && args->atrstm.fractal_prefactor <= 0) 168 res = RES_BAD_ARG; 169 break; 170 case 'h': 171 print_help(argv[0]); 172 args_release(args); 173 args->quit = 1; 174 goto exit; 175 case 'm': args->atrstm.sth_filename = optarg; break; 176 case 'N': args->atrstm.precompute_normals = 1; break; 177 case 'n': args->atrstm.name = optarg; break; 178 case 'O': args->atrstm.cache_filename = optarg; break; 179 case 'p': args->atrstm.atrtp_filename = optarg; break; 180 case 'r': args->atrstm.atrri_filename = optarg; break; 181 case 'T': 182 res = cstr_to_double(optarg, &args->atrstm.optical_thickness); 183 if(res == RES_OK && args->atrstm.optical_thickness<0) res = RES_BAD_ARG; 184 break; 185 case 't': 186 res = cstr_to_uint(optarg, &args->atrstm.nthreads); 187 if(res == RES_OK && !args->atrstm.nthreads) res = RES_BAD_ARG; 188 break; 189 case 'V': res = parse_grid_definition(&args->atrstm, optarg); break; 190 case 'v': args->atrstm.verbose = 1; break; 191 case 'w': 192 res = cstr_to_double(optarg, &args->atrstm.wlen_range[0]); 193 if(res == RES_OK && args->atrstm.wlen_range[0] < 0) res = RES_BAD_ARG; 194 args->atrstm.wlen_range[1] = args->atrstm.wlen_range[0]; 195 break; 196 default: res = RES_BAD_ARG; break; 197 } 198 if(res != RES_OK) { 199 if(optarg) { 200 fprintf(stderr, "%s: invalid option argument '%s' -- '%c'\n", 201 argv[0], optarg, opt); 202 } 203 goto error; 204 } 205 } 206 207 /* Check parsed arguments */ 208 if(!args->atrstm.sth_filename) { 209 fprintf(stderr, 210 "Missing the path toward the volumetric mesh -- option '-m'\n"); 211 res = RES_BAD_ARG; 212 goto error; 213 } 214 if(!args->atrstm.atrtp_filename) { 215 fprintf(stderr, 216 "Missing the path of the thermodynamic properties -- option '-p'\n"); 217 res = RES_BAD_ARG; 218 goto error; 219 } 220 if(!args->atrstm.atrri_filename) { 221 fprintf(stderr, 222 "Missing the path of the refractive indices -- option '-r'\n"); 223 res = RES_BAD_ARG; 224 goto error; 225 } 226 227 exit: 228 return res; 229 error: 230 args_release(args); 231 goto exit; 232 } 233 234 /******************************************************************************* 235 * Main function 236 ******************************************************************************/ 237 int 238 main(int argc, char** argv) 239 { 240 struct args args = ARGS_DEFAULT; 241 struct atrstm* atrstm = NULL; 242 FILE* fp_octree = NULL; 243 res_T res = RES_OK; 244 int err = 0; 245 246 res = args_init(&args, argc, argv); 247 if(res != RES_OK) goto error; 248 if(args.quit) goto exit; 249 250 res = atrstm_create(NULL, &mem_default_allocator, &args.atrstm, &atrstm); 251 if(res != RES_OK) goto error; 252 253 if(args.dump_octree_filename) { 254 const struct atrstm_dump_svx_octree_args dump_svx_octree_args = 255 ATRSTM_DUMP_SVX_OCTREE_ARGS_DEFAULT; 256 257 fp_octree = fopen(args.dump_octree_filename, "w"); 258 if(!fp_octree) { 259 fprintf(stderr, "Could not open `%s' -- %s.", 260 args.dump_octree_filename, strerror(errno)); 261 res = RES_IO_ERR; 262 goto error; 263 } 264 265 res = atrstm_dump_svx_octree(atrstm, &dump_svx_octree_args, fp_octree); 266 if(res != RES_OK) goto error; 267 } 268 269 exit: 270 args_release(&args); 271 if(atrstm) ATRSTM(ref_put(atrstm)); 272 if(fp_octree) fclose(fp_octree); 273 if(MEM_ALLOCATED_SIZE(&mem_default_allocator) != 0) { 274 fprintf(stderr, "Memory leaks: %lu bytes\n", 275 (unsigned long)MEM_ALLOCATED_SIZE(&mem_default_allocator)); 276 err = -1; 277 } 278 return err; 279 error: 280 err = -1; 281 goto exit; 282 }