SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddsfindin2dgrid.c
Go to the documentation of this file.
1/**
2 * @file sddsfindin2dgrid.c
3 * @brief Searches a 2D grid to find locations based on specified SDDS input data.
4 *
5 * @details
6 * This program processes 2D grid data from an SDDS input file to locate points where specific variables
7 * are closest to given target values. It supports both direct and file-based value inputs, optionally
8 * applies interpolation to refine the results, and writes output in SDDS format for further use or analysis.
9 *
10 * @section Usage
11 * ```
12 * sddsfindin2dgrid [<input>] [<output>]
13 * [-pipe=[input][,output]]
14 * -gridVariables=<gridColumnName1>,<gridColumnName2>
15 * -findLocationOf=<columnName1>,<columnName2>
16 * {
17 * [-valuesFile=<filename>] |
18 * [-atValues=<value1>,<value2>]
19 * }
20 * [-presorted]
21 * [-interpolate]
22 * [-mode={onePairPerPage|reuseFirstPage|all}]
23 * [-inverse]
24 * [-verbose]
25 * ```
26 *
27 * @section Options
28 * | Required | Description |
29 * |---------------------------------------|---------------------------------------------------------------------------------------|
30 * | `-gridVariables` | Specifies the two columns representing the grid variables. |
31 * | `-findLocationOf` | Specifies the two columns whose optimal grid values are to be found. |
32 * | `-valuesFile` or `-atValues` | Specifies either a file with values or direct values for location finding. |
33 *
34 * | Optional | Description |
35 * |---------------------------------------|---------------------------------------------------------------------------------------|
36 * | `-pipe` | Use SDDS pipe for input and/or output. |
37 * | `-presorted` | Indicates that input data is pre-sorted, improving processing efficiency. |
38 * | `-interpolate` | Enables linear interpolation for more precise location determination. |
39 * | `-mode` | Sets the processing mode: onePairPerPage, reuseFirstPage, or all. |
40 * | `-inverse` | Performs an inverse operation, finding data values for specified grid inputs. |
41 *
42 * @subsection Incompatibilities
43 * - Only one of `-valuesFile` or `-atValues` may be specified.
44 *
45 * @copyright
46 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
47 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
48 *
49 * @license
50 * This file is distributed under the terms of the Software License Agreement
51 * found in the file LICENSE included with this distribution.
52 *
53 * @author
54 * M. Borland
55 */
56
57#include "mdb.h"
58#include "SDDS.h"
59#include "scan.h"
60#include <stdlib.h>
61#include <stdio.h>
62#include <inttypes.h>
63#include <string.h>
64#include <float.h>
65#include <math.h>
66
67/* Enumeration for option types */
68enum option_type {
69 CLO_FINDLOCATIONOF,
70 CLO_GRIDVARIABLES,
71 CLO_VALUESFILE,
72 CLO_ATVALUES,
73 CLO_PIPE,
74 CLO_INTERPOLATE,
75 CLO_MODE,
76 CLO_PRESORTED,
77 CLO_INVERSE,
78 CLO_VERBOSE,
79 N_OPTIONS
80};
81
82char *option[N_OPTIONS] = {
83 "findlocationof",
84 "gridvariables",
85 "valuesfile",
86 "atvalues",
87 "pipe",
88 "interpolate",
89 "mode",
90 "presorted",
91 "inverse",
92 "verbose"
93};
94
95/* Improved usage message for better readability */
96char *USAGE =
97 "Usage: sddsfindin2dgrid [<input>] [<output>]\n"
98 " [-pipe=[input][,output]]\n"
99 " -gridVariables=<gridColumnName1>,<gridColumnName2>\n"
100 " -findLocationOf=<columnName1>,<columnName2>\n"
101 " {-valuesFile=<filename> | -atValues=<value1>,<value2>}\n"
102 " [-presorted]\n"
103 " [-interpolate] [-mode={onePairPerPage|reuseFirstPage|all}]\n"
104 " [-inverse]\n\n"
105 "Description:\n"
106 " This program searches a 2D grid to find the location (gridColumnName1, gridColumnName2)\n"
107 " where columnName1 and columnName2 are closest to the given values.\n\n"
108 "Options:\n"
109 " -gridVariables Names the two columns that are laid out on a grid.\n"
110 " -presorted Data is sorted by grid variables using 'sddssort'.\n"
111 " Pre-sorting can save considerable time if data is used repeatedly.\n"
112 " -findLocationOf Names the two columns to locate on the grid by finding optimal values.\n"
113 " -valuesFile Specifies a file containing pairs of values to find locations for.\n"
114 " -atValues Directly provides values to be found. This option may be repeated.\n"
115 " -interpolate Performs 2D linear interpolation to refine the location.\n"
116 " -mode Determines processing mode:\n"
117 " onePairPerPage - One pair per input page (default).\n"
118 " reuseFirstPage - Use all pairs with the first input page.\n"
119 " all - Use all pairs with all input pages.\n"
120 " -inverse Performs the inverse operation, interpolating to find values from grid locations.\n"
121 " -verbose Prints possibly useful information while running\n\n"
122 "Program Information:\n"
123 " Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
124
125#define MODE_ONEPAIRPERPAGE 0x01UL
126#define MODE_REUSEFIRSTPAGE 0x02UL
127#define MODE_ALL 0x04UL
128
129static double *gridValue[2] = {NULL, NULL}, *valueAtLocation[2] = {NULL, NULL};
130static uint64_t ng[2] = {0, 0};
131
132/* Function prototypes */
133void gridifyData(char *gridVariable[2], uint64_t gridPoints, short presorted);
134int findLocationInGrid(double at1, double at2, double *location, double *value, short interpolate);
135uint64_t findGridInterval(double value, short dimension);
136
137int main(int argc, char **argv) {
138 long iArg;
139 SDDS_DATASET SDDSin, SDDSout, SDDSvalues;
140 SCANNED_ARG *scanned;
141 unsigned long pipeFlags = 0;
142 uint64_t gridPoints = 0, atValues = 0, iv = 0, irow = 0;
143 char *input = NULL, *output = NULL, *fileForValues = NULL;
144 char *findLocationOf[2] = {NULL, NULL}, *gridVariable[2] = {NULL, NULL};
145 double *atValue[2] = {NULL, NULL}, value[2] = {0.0, 0.0};
146 short interpolate = 0, restarted = 0, needPage = 0, presorted = 0, inverse = 0, verbose = 0;
147 unsigned long mode = MODE_ALL;
148
150
151 argc = scanargs(&scanned, argc, argv);
152 if (argc == 1) {
153 fprintf(stderr, "%s", USAGE);
154 exit(EXIT_FAILURE);
155 }
156
157 for (iArg = 1; iArg < argc; iArg++) {
158 if (scanned[iArg].arg_type == OPTION) {
159 /* Process options here */
160 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
161 case CLO_FINDLOCATIONOF:
162 if (scanned[iArg].n_items != 3 ||
163 !strlen(findLocationOf[0] = scanned[iArg].list[1]) ||
164 !strlen(findLocationOf[1] = scanned[iArg].list[2])) {
165 SDDS_Bomb("Invalid -findLocationOf syntax.\n");
166 }
167 if (strcmp(findLocationOf[0], findLocationOf[1]) == 0) {
168 SDDS_Bomb("Invalid -findLocationOf values: two variables are the same.\n");
169 }
170 break;
171 case CLO_GRIDVARIABLES:
172 if (scanned[iArg].n_items != 3 ||
173 !strlen(gridVariable[0] = scanned[iArg].list[1]) ||
174 !strlen(gridVariable[1] = scanned[iArg].list[2])) {
175 SDDS_Bomb("Invalid -gridVariables syntax.\n");
176 }
177 if (strcmp(gridVariable[0], gridVariable[1]) == 0) {
178 SDDS_Bomb("Invalid -gridVariables values: two variables are the same.\n");
179 }
180 break;
181 case CLO_VALUESFILE:
182 if (scanned[iArg].n_items != 2 ||
183 !strlen(fileForValues = scanned[iArg].list[1])) {
184 SDDS_Bomb("Invalid -valuesFile syntax.\n");
185 }
186 if (atValues > 0) {
187 SDDS_Bomb("Cannot use -valuesFile and -atValues together.\n");
188 }
189 break;
190 case CLO_ATVALUES:
191 atValue[0] = SDDS_Realloc(atValue[0], sizeof(double) * (atValues + 1));
192 atValue[1] = SDDS_Realloc(atValue[1], sizeof(double) * (atValues + 1));
193 if (scanned[iArg].n_items != 3 ||
194 sscanf(scanned[iArg].list[1], "%le", &atValue[0][atValues]) != 1 ||
195 sscanf(scanned[iArg].list[2], "%le", &atValue[1][atValues]) != 1) {
196 SDDS_Bomb("Invalid -atValues syntax.\n");
197 }
198 if (fileForValues) {
199 SDDS_Bomb("Cannot use -valuesFile and -atValues together.\n");
200 }
201 atValues++;
202 break;
203 case CLO_PIPE:
204 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
205 SDDS_Bomb("Invalid -pipe syntax.\n");
206 }
207 break;
208 case CLO_INTERPOLATE:
209 interpolate = 1;
210 break;
211 case CLO_PRESORTED:
212 presorted = 1;
213 break;
214 case CLO_MODE:
215 mode = 0;
216 if ((scanned[iArg].n_items -= 1) != 1 ||
217 !scanItemList(&mode, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
218 "onepairperpage", -1, NULL, 0, MODE_ONEPAIRPERPAGE,
219 "reusefirstpage", -1, NULL, 0, MODE_REUSEFIRSTPAGE,
220 "all", -1, NULL, 0, MODE_ALL,
221 NULL) ||
222 bitsSet(mode) != 1) {
223 SDDS_Bomb("Invalid -mode syntax.\n");
224 }
225 break;
226 case CLO_INVERSE:
227 inverse = 1;
228 break;
229 case CLO_VERBOSE:
230 verbose = 1;
231 break;
232 default:
233 fprintf(stderr, "Invalid option: %s\n", scanned[iArg].list[0]);
234 fprintf(stderr, "%s", USAGE);
235 exit(EXIT_FAILURE);
236 }
237 } else {
238 if (!input) {
239 input = scanned[iArg].list[0];
240 } else if (!output) {
241 output = scanned[iArg].list[0];
242 } else {
243 SDDS_Bomb("Too many filenames provided.\n");
244 }
245 }
246 }
247
248 if (!findLocationOf[0] || !findLocationOf[1]) {
249 SDDS_Bomb("Must provide -findLocationOf option.\n");
250 }
251 if (!gridVariable[0] || !gridVariable[1]) {
252 SDDS_Bomb("Must provide -gridVariables option.\n");
253 }
254 if (!atValues && !fileForValues) {
255 SDDS_Bomb("Must provide either -atValues or -valuesFile option.\n");
256 }
257
258 processFilenames("sddsfindin2dgrid", &input, &output, pipeFlags, 0, NULL);
259
260 if (fileForValues) {
261 if (!SDDS_InitializeInput(&SDDSvalues, fileForValues)) {
262 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
263 }
264 if (SDDS_ReadPage(&SDDSvalues) <= 0) {
265 SDDS_Bomb("Unable to read values file.\n");
266 }
267 if ((atValues = SDDS_RowCount(&SDDSvalues)) > 0) {
268 if (verbose)
269 fprintf(stderr, "%" PRIu64 " values in values file\n", atValues);
270 if (inverse) {
271 if (!(atValue[0] = SDDS_GetColumnInDoubles(&SDDSvalues, gridVariable[0]))) {
272 SDDS_Bomb("Unable to retrieve values of first grid variable in values file.\n");
273 }
274 if (!(atValue[1] = SDDS_GetColumnInDoubles(&SDDSvalues, gridVariable[1]))) {
275 SDDS_Bomb("Unable to retrieve values of second grid variable in values file.\n");
276 }
277 } else {
278 if (!(atValue[0] = SDDS_GetColumnInDoubles(&SDDSvalues, findLocationOf[0]))) {
279 SDDS_Bomb("Unable to retrieve values of first findLocationOf variable in values file.\n");
280 }
281 if (!(atValue[1] = SDDS_GetColumnInDoubles(&SDDSvalues, findLocationOf[1]))) {
282 SDDS_Bomb("Unable to retrieve values of second findLocationOf variable in values file.\n");
283 }
284 }
285 }
286 if (SDDS_ReadPage(&SDDSvalues) > 0) {
287 SDDS_Bomb("Values file contains multiple pages, which is not supported.\n");
288 }
289 SDDS_Terminate(&SDDSvalues);
291 }
292
293 if (!SDDS_InitializeInput(&SDDSin, input)) {
294 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
295 }
296
297 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 0, NULL, NULL, output) ||
298 !SDDS_TransferAllParameterDefinitions(&SDDSout, &SDDSin, 0) ||
299 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, gridVariable[0], NULL) ||
300 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, gridVariable[1], NULL) ||
301 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, findLocationOf[0], NULL) ||
302 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, findLocationOf[1], NULL) ||
303 !SDDS_WriteLayout(&SDDSout) ||
304 !SDDS_StartPage(&SDDSout, atValues * 1000)) {
305 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
306 }
308
309 irow = 0;
310 iv = 0;
311 restarted = 0;
312 while (1) {
313 double location[2];
314 needPage = (irow == 0) ? 1 : 0;
315 if (mode == MODE_ONEPAIRPERPAGE) {
316 if (iv == atValues) {
317 break;
318 }
319 needPage = 1;
320 } else if (mode == MODE_REUSEFIRSTPAGE) {
321 if (iv == atValues) {
322 break;
323 }
324 if (iv == 0) {
325 needPage = 1;
326 }
327 } else if (mode == MODE_ALL) {
328 if (iv == atValues) {
329 needPage = 1;
330 iv = 0;
331 restarted = 1; /* Signals that SDDS_ReadPage <= 0 is acceptable */
332 }
333 }
334
335 if (needPage) {
336 if (SDDS_ReadPage(&SDDSin) <= 0) {
337 if (!restarted) {
338 SDDS_Bomb("Too few pages in input file for number of location requests.\n");
339 }
340 break;
341 }
342 if (gridValue[0]) {
343 free(gridValue[0]);
344 free(gridValue[1]);
345 free(valueAtLocation[0]);
346 free(valueAtLocation[1]);
347 gridValue[0] = gridValue[1] = valueAtLocation[0] = valueAtLocation[1] = NULL;
348 }
349 if ((gridPoints = SDDS_RowCount(&SDDSin)) <= 0) {
350 SDDS_Bomb("First page of input file is empty.\n");
351 }
352 if (!(gridValue[0] = SDDS_GetColumnInDoubles(&SDDSin, gridVariable[0])) ||
353 !(gridValue[1] = SDDS_GetColumnInDoubles(&SDDSin, gridVariable[1]))) {
354 SDDS_Bomb("Grid variables are missing from input file.\n");
355 }
356 if (!(valueAtLocation[0] = SDDS_GetColumnInDoubles(&SDDSin, findLocationOf[0])) ||
357 !(valueAtLocation[1] = SDDS_GetColumnInDoubles(&SDDSin, findLocationOf[1]))) {
358 SDDS_Bomb("Location variables are missing from input file.\n");
359 }
360
361 gridifyData(gridVariable, gridPoints, presorted);
362 }
363
364 if (inverse) {
365 /* Perform ordinary 2D interpolation on the grid */
366 double x0, x1, y0, y1, v1, v2, fx, fy;
367 double x, y;
368 uint64_t ix, iy, ig;
369
370 x = atValue[0][iv];
371 y = atValue[1][iv];
372 ix = findGridInterval(x, 0);
373 iy = findGridInterval(y, 1);
374 x0 = gridValue[0][ix * ng[1]];
375 x1 = gridValue[0][(ix + 1) * ng[1]];
376 y0 = gridValue[1][iy];
377 y1 = gridValue[1][iy + 1];
378 fx = (x - x0) / (x1 - x0);
379 fy = (y - y0) / (y1 - y0);
380
381 ig = ix * ng[1] + iy;
382 v1 = valueAtLocation[0][ig] * (1 - fx) + valueAtLocation[0][ig + ng[1]] * fx;
383 ig = ix * ng[1] + iy + 1;
384 v2 = valueAtLocation[0][ig] * (1 - fx) + valueAtLocation[0][ig + ng[1]] * fx;
385 location[0] = v1 * (1 - fy) + v2 * fy;
386 value[0] = x;
387
388 ig = ix * ng[1] + iy;
389 v1 = valueAtLocation[1][ig] * (1 - fx) + valueAtLocation[1][ig + ng[1]] * fx;
390 ig = ix * ng[1] + iy + 1;
391 v2 = valueAtLocation[1][ig] * (1 - fx) + valueAtLocation[1][ig + ng[1]] * fx;
392 location[1] = v1 * (1 - fy) + v2 * fy;
393 value[1] = y;
394 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, irow++,
395 0, value[0], 1, value[1], 2, location[0], 3, location[1],
396 -1)) {
397 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
398 }
399 } else {
400 if (verbose)
401 fprintf(stderr, "Finding location for values (%le, %le)\n", atValue[0][iv], atValue[1][iv]);
402 if (!findLocationInGrid(atValue[0][iv], atValue[1][iv], &location[0], &value[0], interpolate)) {
403 fprintf(stderr, "Couldn't find location for %s=%.6le, %s=%.6le\n",
404 findLocationOf[0], atValue[0][iv],
405 findLocationOf[1], atValue[1][iv]);
406 exit(EXIT_FAILURE);
407 }
408 if (verbose)
409 fprintf(stderr, "Location is (%le, %le) with values (%le, %le)\n", location[0], location[1], value[0], value[1]);
410 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, irow++,
411 0, location[0], 1, location[1], 2, value[0], 3, value[1],
412 -1)) {
413 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
414 }
415 }
416 iv++;
417 }
418
419 if (!SDDS_WritePage(&SDDSout) || !SDDS_Terminate(&SDDSout) ||
420 !SDDS_Terminate(&SDDSin)) {
421 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
422 }
423 if (gridValue[0]) {
424 free(gridValue[0]);
425 free(gridValue[1]);
426 free(valueAtLocation[0]);
427 free(valueAtLocation[1]);
428 gridValue[0] = gridValue[1] = valueAtLocation[0] = valueAtLocation[1] = NULL;
429 }
430 free(atValue[0]);
431 free(atValue[1]);
432 free_scanargs(&scanned, argc);
433 return EXIT_SUCCESS;
434}
435
436double target[2], achieved[2];
437
438double distance(double *position, long *invalid) {
439 uint64_t ix, iy;
440 double fx, fy;
441 double v[2];
442 long i;
443
444 if (position[0] < 0 || position[0] >= ng[0] || position[1] < 0 || position[1] >= ng[1]) {
445 *invalid = 1;
446 printf("Invalid position: %.6le, %.6le for ng=%" PRIu64 ", %" PRIu64 "\n", position[0], position[1],
447 ng[0], ng[1]);
448 return DBL_MAX;
449 }
450 *invalid = 0;
451
452 ix = position[0];
453 iy = position[1];
454 if (ix == (ng[0] - 1)) {
455 ix--;
456 }
457 if (iy == (ng[1] - 1)) {
458 iy--;
459 }
460
461 fx = position[0] - ix;
462 fy = position[1] - iy;
463
464 for (i = 0; i < 2; i++) {
465 double v00, v10, v01, v11, v0, v1;
466 v00 = valueAtLocation[i][(ix + 0) * ng[1] + (iy + 0)];
467 v10 = valueAtLocation[i][(ix + 1) * ng[1] + (iy + 0)];
468 v01 = valueAtLocation[i][(ix + 0) * ng[1] + (iy + 1)];
469 v11 = valueAtLocation[i][(ix + 1) * ng[1] + (iy + 1)];
470 v0 = v00 + (v10 - v00) * fx;
471 v1 = v01 + (v11 - v01) * fx;
472 v[i] = v0 + (v1 - v0) * fy;
473 achieved[i] = v[i];
474 }
475
476 v[0] = target[0] - v[0];
477 v[1] = target[1] - v[1];
478 return v[0] * v[0] + v[1] * v[1];
479}
480
481int findLocationInGrid(double at1, double at2, double *location, double *value, short interpolate) {
482 uint64_t ix, iy, j;
483 uint64_t ixBest = ng[0] / 2, iyBest = ng[1] / 2;
484 double delta, bestDelta = DBL_MAX;
485 long i;
486
487 for (ix = 0; ix < ng[0]; ix++) {
488 for (iy = 0; iy < ng[1]; iy++) {
489 j = ix * ng[1] + iy;
490 double delta0 = valueAtLocation[0][j] - at1;
491 double delta1 = valueAtLocation[1][j] - at2;
492 delta = delta0 * delta0 + delta1 * delta1;
493 if (delta < bestDelta) {
494 location[0] = gridValue[0][j];
495 location[1] = gridValue[1][j];
496 value[0] = valueAtLocation[0][j];
497 value[1] = valueAtLocation[1][j];
498 ixBest = ix;
499 iyBest = iy;
500 bestDelta = delta;
501 }
502 }
503 }
504
505 if (interpolate) {
506 double result, start[2], step[2], lower[2], upper[2];
507 start[0] = ixBest;
508 start[1] = iyBest;
509 step[0] = step[1] = 0.1;
510 lower[0] = lower[1] = 0;
511 upper[0] = ng[0] - 1;
512 upper[1] = ng[1] - 1;
513 target[0] = at1;
514 target[1] = at2;
515 if (simplexMin(&result, start, step, lower, upper, NULL, 2, 0, 1e-14, distance,
516 NULL, 1500, 3, 12, 3, 1, 0) >= 0) {
517 double a00, a01, a10, a11, a0, a1, fx, fy;
518 int64_t cellX = start[0] < 0 ? 0 : (int64_t)start[0];
519 int64_t cellY = start[1] < 0 ? 0 : (int64_t)start[1];
520 if (cellX >= (int64_t)(ng[0] - 1))
521 cellX = ng[0] - 2;
522 if (cellY >= (int64_t)(ng[1] - 1))
523 cellY = ng[1] - 2;
524 fx = start[0] - cellX;
525 fy = start[1] - cellY;
526
527 for (i = 0; i < 2; i++) {
528 a00 = gridValue[i][(cellX + 0) * ng[1] + (cellY + 0)];
529 a10 = gridValue[i][(cellX + 1) * ng[1] + (cellY + 0)];
530 a01 = gridValue[i][(cellX + 0) * ng[1] + (cellY + 1)];
531 a11 = gridValue[i][(cellX + 1) * ng[1] + (cellY + 1)];
532 a0 = a00 + (a10 - a00) * fx;
533 a1 = a01 + (a11 - a01) * fx;
534 location[i] = a0 + (a1 - a0) * fy;
535 value[i] = achieved[i];
536 }
537 }
538 }
539
540 return 1;
541}
542
543uint64_t findGridInterval(double value, short dimension) {
544 uint64_t lower = 0, upper = ng[dimension] - 1, middle;
545 double coordinate;
546
547 coordinate = dimension == 0 ? gridValue[0][0] : gridValue[1][0];
548 if (value <= coordinate)
549 return 0;
550 coordinate = dimension == 0 ? gridValue[0][upper * ng[1]] : gridValue[1][upper];
551 if (value >= coordinate)
552 return upper - 1;
553
554 while (upper - lower > 1) {
555 middle = lower + (upper - lower) / 2;
556 coordinate = dimension == 0 ? gridValue[0][middle * ng[1]] : gridValue[1][middle];
557 if (value < coordinate)
558 upper = middle;
559 else
560 lower = middle;
561 }
562 return lower;
563}
564
565int compareGridLocations(const void *data1, const void *data2) {
566 uint64_t i1 = *((uint64_t *)data1);
567 uint64_t i2 = *((uint64_t *)data2);
568 double diff = -(gridValue[0][i1] - gridValue[0][i2]);
569 if (diff == 0) {
570 diff = -(gridValue[1][i1] - gridValue[1][i2]);
571 }
572
573 return (diff < 0 ? 1 : (diff > 0 ? -1 : 0));
574}
575
576void gridifyData(char *gridVariable[2], uint64_t gridPoints, short presorted) {
577 long i;
578 char s[256];
579 uint64_t j, *index;
580 double *buffer;
581
582 for (i = 0; i < 2; i++) {
583 double *copy = tmalloc(sizeof(double) * gridPoints);
584 memcpy(copy, gridValue[i], gridPoints * sizeof(double));
585 qsort((void *)copy, gridPoints, sizeof(double), double_cmpasc);
586 ng[i] = 1;
587 for (j = 1; j < gridPoints; j++) {
588 if (copy[j - 1] != copy[j]) {
589 ng[i] += 1;
590 }
591 }
592 free(copy);
593 if (ng[i] == gridPoints) {
594 snprintf(s, sizeof(s), "Grid variable %s has only unique values.\n", gridVariable[i]);
595 SDDS_Bomb(s);
596 }
597 if (ng[i] == 1) {
598 snprintf(s, sizeof(s), "Grid variable %s has only one unique value.\n", gridVariable[i]);
599 SDDS_Bomb(s);
600 }
601 }
602 if (ng[0] * ng[1] != gridPoints) {
603 snprintf(s, sizeof(s), "Input data does not form a grid (nx = %" PRIu64 ", ny = %" PRIu64 ", rows = %" PRIu64 ")\n",
604 ng[0], ng[1], gridPoints);
605 SDDS_Bomb(s);
606 }
607
608 if (!presorted) {
609 /* Sort indices for points to place data in gridded order */
610 index = tmalloc(sizeof(uint64_t) * gridPoints);
611 for (j = 0; j < gridPoints; j++) {
612 index[j] = j;
613 }
614
615 qsort((void *)index, gridPoints, sizeof(uint64_t), compareGridLocations);
616
617 /* Copy data into sorted order in the global variables */
618 for (i = 0; i < 2; i++) {
619 buffer = tmalloc(sizeof(double) * gridPoints);
620 for (j = 0; j < gridPoints; j++) {
621 buffer[j] = gridValue[i][index[j]];
622 }
623 free(gridValue[i]);
624 gridValue[i] = buffer;
625
626 buffer = tmalloc(sizeof(double) * gridPoints);
627 for (j = 0; j < gridPoints; j++) {
628 buffer[j] = valueAtLocation[i][index[j]];
629 }
630 free(valueAtLocation[i]);
631 valueAtLocation[i] = buffer;
632 }
633 free(index);
634 }
635}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions from a source dataset to a target dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474
void SDDS_ClearErrors()
Clears all recorded error messages from the SDDS error stack.
Definition SDDS_utils.c:354
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:65
long bitsSet(unsigned long data)
Counts the number of set bits (1s) in the given data.
Definition binary.c:52
double interpolate(double *f, double *x, int64_t n, double xo, OUTRANGE_CONTROL *belowRange, OUTRANGE_CONTROL *aboveRange, long order, unsigned long *returnCode, long M)
Performs interpolation with range control options.
Definition interp.c:160
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:357
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:391
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:588
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
long simplexMin(double *yReturn, double *xGuess, double *dxGuess, double *xLowerLimit, double *xUpperLimit, short *disable, long dimensions, double target, double tolerance, double(*func)(double *x, long *invalid), void(*report)(double ymin, double *xmin, long pass, long evals, long dims), long maxEvaluations, long maxPasses, long maxDivisions, double divisorFactor, double passRangeFactor, unsigned long flags)
Top-level convenience function for simplex-based minimization.
Definition simplex.c:502
int double_cmpasc(const void *a, const void *b)
Compare two doubles in ascending order.