SDDSlib
Loading...
Searching...
No Matches
sddsfindin2dgrid.c
Go to the documentation of this file.
1/**
2 * @file sddsfindin2dgrid.c
3 * @brief Finds locations in a 2D grid based on SDDS input data.
4 *
5 * This program searches a 2D grid to find the location where specified
6 * variables are closest to given values. It supports reading input from
7 * files or via pipes, and can perform linear interpolation to refine
8 * the found location. The output is written in SDDS format.
9 *
10 * ## Usage
11 * ```
12 * sddsfindin2dgrid [<input>] [<output>] [-pipe=[input][,output]]
13 * -gridVariables=<gridColumnName1>,<gridColumnName2>
14 * [-presorted]
15 * -findLocationOf=<columnName1>,<columnName2>
16 * {-valuesFile=<filename> | -atValues=<value1>,<value2>}
17 * [-interpolate]
18 * [-mode={onePairPerPage|reuseFirstPage|all}]
19 * [-inverse]
20 * ```
21 *
22 * ## Options
23 * - `-gridVariables=<gridColumnName1>,<gridColumnName2>`
24 * Names the two columns that are laid out on a grid.
25 *
26 * - `-presorted`
27 * Indicates that the data is pre-sorted by the grid variables, which can save considerable time if data is used repeatedly.
28 *
29 * - `-findLocationOf=<columnName1>,<columnName2>`
30 * Names the two columns to locate on the grid by finding the optimal values of the grid variables.
31 *
32 * - `-valuesFile=<filename>`
33 * Specifies a file containing a series of pairs (`<columnName1>`, `<columnName2>`) from which values will be taken.
34 *
35 * - `-atValues=<value1>,<value2>`
36 * Directly provides values of (`<columnName1>`, `<columnName2>`) to be found. This option may be repeated.
37 *
38 * - `-interpolate`
39 * If specified, performs 2D linear interpolation to refine the location. By default, the location is the optimal point on the grid.
40 *
41 * - `-mode={onePairPerPage|reuseFirstPage|all}`
42 * Determines how value pairs are processed:
43 * - `onePairPerPage` (default): Uses one successive pair of values with each successive page from `<input>`.
44 * - `reuseFirstPage`: Uses all values with the first page of `<input>`, ignoring other pages.
45 * - `all`: Uses all values with all pages.
46 *
47 * - `-inverse`
48 * Performs the inverse operation, executing fast 2D bilinear interpolation to find values of (`<columnName1>`, `<columnName2>`) for given (`<gridColumnName1>`, `<gridColumnName2>`) pairs.
49 *
50 * @copyright
51 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
52 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
53 *
54 * @license
55 * This file is distributed under the terms of the Software License Agreement
56 * found in the file LICENSE included with this distribution.
57 *
58 * @author M. Borland
59 */
60
61#include "mdb.h"
62#include "SDDS.h"
63#include "scan.h"
64#include <stdlib.h>
65#include <stdio.h>
66#include <string.h>
67#include <float.h>
68#include <math.h>
69
70/* Enumeration for option types */
71enum option_type {
72 CLO_FINDLOCATIONOF,
73 CLO_GRIDVARIABLES,
74 CLO_VALUESFILE,
75 CLO_ATVALUES,
76 CLO_PIPE,
77 CLO_INTERPOLATE,
78 CLO_MODE,
79 CLO_PRESORTED,
80 CLO_INVERSE,
81 N_OPTIONS
82};
83
84char *option[N_OPTIONS] = {
85 "findlocationof",
86 "gridvariables",
87 "valuesfile",
88 "atvalues",
89 "pipe",
90 "interpolate",
91 "mode",
92 "presorted",
93 "inverse"
94};
95
96/* Improved usage message for better readability */
97char *USAGE =
98 "Usage: sddsfindin2dgrid [<input>] [<output>] [-pipe=[input][,output]]\n"
99 " -gridVariables=<gridColumnName1>,<gridColumnName2>\n"
100 " [-presorted]\n"
101 " -findLocationOf=<columnName1>,<columnName2>\n"
102 " {-valuesFile=<filename> | -atValues=<value1>,<value2>}\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\n"
121 "Program Information:\n"
122 " Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
123
124#define MODE_ONEPAIRPERPAGE 0x01UL
125#define MODE_REUSEFIRSTPAGE 0x02UL
126#define MODE_ALL 0x04UL
127
128static double *gridValue[2] = {NULL, NULL}, *valueAtLocation[2] = {NULL, NULL};
129static uint64_t ng[2] = {0, 0};
130
131/* Function prototypes */
132void gridifyData(char *gridVariable[2], uint64_t gridPoints, short presorted);
133int findLocationInGrid(double at1, double at2, double *location, double *value, short interpolate);
134
135int main(int argc, char **argv) {
136 long iArg;
137 SDDS_DATASET SDDSin, SDDSout, SDDSvalues;
138 SCANNED_ARG *scanned;
139 unsigned long pipeFlags;
140 uint64_t gridPoints = 0, atValues = 0, iv = 0, irow = 0;
141 char *input = NULL, *output = NULL, *fileForValues = NULL;
142 char *findLocationOf[2] = {NULL, NULL}, *gridVariable[2] = {NULL, NULL};
143 double *atValue[2] = {NULL, NULL}, value[2] = {0.0, 0.0};
144 short interpolate = 0, restarted = 0, needPage = 0, presorted = 0, inverse = 0;
145 unsigned long mode = MODE_ALL;
146
148
149 argc = scanargs(&scanned, argc, argv);
150 if (argc == 1) {
151 fprintf(stderr, "%s", USAGE);
152 exit(EXIT_FAILURE);
153 }
154
155 for (iArg = 1; iArg < argc; iArg++) {
156 if (scanned[iArg].arg_type == OPTION) {
157 /* Process options here */
158 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
159 case CLO_FINDLOCATIONOF:
160 if (scanned[iArg].n_items != 3 ||
161 !strlen(findLocationOf[0] = scanned[iArg].list[1]) ||
162 !strlen(findLocationOf[1] = scanned[iArg].list[2])) {
163 SDDS_Bomb("Invalid -findLocationOf syntax.\n");
164 }
165 if (strcmp(findLocationOf[0], findLocationOf[1]) == 0) {
166 SDDS_Bomb("Invalid -findLocationOf values: two variables are the same.\n");
167 }
168 break;
169 case CLO_GRIDVARIABLES:
170 if (scanned[iArg].n_items != 3 ||
171 !strlen(gridVariable[0] = scanned[iArg].list[1]) ||
172 !strlen(gridVariable[1] = scanned[iArg].list[2])) {
173 SDDS_Bomb("Invalid -gridVariables syntax.\n");
174 }
175 if (strcmp(gridVariable[0], gridVariable[1]) == 0) {
176 SDDS_Bomb("Invalid -gridVariables values: two variables are the same.\n");
177 }
178 break;
179 case CLO_VALUESFILE:
180 if (scanned[iArg].n_items != 2 ||
181 !strlen(fileForValues = scanned[iArg].list[1])) {
182 SDDS_Bomb("Invalid -valuesFile syntax.\n");
183 }
184 if (atValues > 0) {
185 SDDS_Bomb("Cannot use -valuesFile and -atValues together.\n");
186 }
187 break;
188 case CLO_ATVALUES:
189 atValue[0] = SDDS_Realloc(atValue[0], sizeof(double) * (atValues + 1));
190 atValue[1] = SDDS_Realloc(atValue[1], sizeof(double) * (atValues + 1));
191 if (scanned[iArg].n_items != 3 ||
192 sscanf(scanned[iArg].list[1], "%le", &atValue[0][atValues]) != 1 ||
193 sscanf(scanned[iArg].list[2], "%le", &atValue[1][atValues]) != 1) {
194 SDDS_Bomb("Invalid -atValues syntax.\n");
195 }
196 if (fileForValues) {
197 SDDS_Bomb("Cannot use -valuesFile and -atValues together.\n");
198 }
199 atValues++;
200 break;
201 case CLO_PIPE:
202 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
203 SDDS_Bomb("Invalid -pipe syntax.\n");
204 }
205 break;
206 case CLO_INTERPOLATE:
207 interpolate = 1;
208 break;
209 case CLO_PRESORTED:
210 presorted = 1;
211 break;
212 case CLO_MODE:
213 mode = 0;
214 if ((scanned[iArg].n_items -= 1) != 1 ||
215 !scanItemList(&mode, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
216 "onepairperpage", -1, NULL, 0, MODE_ONEPAIRPERPAGE,
217 "reusefirstpage", -1, NULL, 0, MODE_REUSEFIRSTPAGE,
218 "all", -1, NULL, 0, MODE_ALL,
219 NULL) ||
220 bitsSet(mode) != 1) {
221 SDDS_Bomb("Invalid -mode syntax.\n");
222 }
223 break;
224 case CLO_INVERSE:
225 inverse = 1;
226 break;
227 default:
228 fprintf(stderr, "Invalid option: %s\n", scanned[iArg].list[0]);
229 fprintf(stderr, "%s", USAGE);
230 exit(EXIT_FAILURE);
231 }
232 } else {
233 if (!input) {
234 input = scanned[iArg].list[0];
235 } else if (!output) {
236 output = scanned[iArg].list[0];
237 } else {
238 SDDS_Bomb("Too many filenames provided.\n");
239 }
240 }
241 }
242
243 if (!findLocationOf[0] || !findLocationOf[1]) {
244 SDDS_Bomb("Must provide -findLocationOf option.\n");
245 }
246 if (!gridVariable[0] || !gridVariable[1]) {
247 SDDS_Bomb("Must provide -gridVariables option.\n");
248 }
249 if (!atValues && !fileForValues) {
250 SDDS_Bomb("Must provide either -atValues or -valuesFile option.\n");
251 }
252
253 processFilenames("sddsfindin2dgrid", &input, &output, pipeFlags, 0, NULL);
254
255 if (fileForValues) {
256 if (!SDDS_InitializeInput(&SDDSvalues, fileForValues)) {
257 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
258 }
259 if (SDDS_ReadPage(&SDDSvalues) <= 0) {
260 SDDS_Bomb("Unable to read values file.\n");
261 }
262 if ((atValues = SDDS_RowCount(&SDDSvalues)) > 0) {
263 if (inverse) {
264 if (!(atValue[0] = SDDS_GetColumnInDoubles(&SDDSvalues, gridVariable[0]))) {
265 SDDS_Bomb("Unable to retrieve values of first grid variable in values file.\n");
266 }
267 if (!(atValue[1] = SDDS_GetColumnInDoubles(&SDDSvalues, gridVariable[1]))) {
268 SDDS_Bomb("Unable to retrieve values of second grid variable in values file.\n");
269 }
270 } else {
271 if (!(atValue[0] = SDDS_GetColumnInDoubles(&SDDSvalues, findLocationOf[0]))) {
272 SDDS_Bomb("Unable to retrieve values of first findLocationOf variable in values file.\n");
273 }
274 if (!(atValue[1] = SDDS_GetColumnInDoubles(&SDDSvalues, findLocationOf[1]))) {
275 SDDS_Bomb("Unable to retrieve values of second findLocationOf variable in values file.\n");
276 }
277 }
278 }
279 if (SDDS_ReadPage(&SDDSvalues) > 0) {
280 SDDS_Bomb("Values file contains multiple pages, which is not supported.\n");
281 }
282 SDDS_Terminate(&SDDSvalues);
284 }
285
286 if (!SDDS_InitializeInput(&SDDSin, input)) {
287 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
288 }
289
290 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 0, NULL, NULL, output) ||
291 !SDDS_TransferAllParameterDefinitions(&SDDSout, &SDDSin, 0) ||
292 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, gridVariable[0], NULL) ||
293 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, gridVariable[1], NULL) ||
294 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, findLocationOf[0], NULL) ||
295 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, findLocationOf[1], NULL) ||
296 !SDDS_WriteLayout(&SDDSout) ||
297 !SDDS_StartPage(&SDDSout, atValues * 1000)) {
298 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
299 }
301
302 irow = 0;
303 iv = 0;
304 restarted = 0;
305 while (1) {
306 double location[2];
307 needPage = (irow == 0) ? 1 : 0;
308 if (mode == MODE_ONEPAIRPERPAGE) {
309 if (iv == atValues) {
310 break;
311 }
312 needPage = 1;
313 } else if (mode == MODE_REUSEFIRSTPAGE) {
314 if (iv == atValues) {
315 break;
316 }
317 if (iv == 0) {
318 needPage = 1;
319 }
320 } else if (mode == MODE_ALL) {
321 if (iv == atValues) {
322 needPage = 1;
323 iv = 0;
324 restarted = 1; /* Signals that SDDS_ReadPage <= 0 is acceptable */
325 }
326 }
327
328 if (needPage) {
329 if (SDDS_ReadPage(&SDDSin) <= 0) {
330 if (!restarted) {
331 SDDS_Bomb("Too few pages in input file for number of location requests.\n");
332 }
333 break;
334 }
335 if (gridValue[0]) {
336 free(gridValue[0]);
337 free(gridValue[1]);
338 free(valueAtLocation[0]);
339 free(valueAtLocation[1]);
340 gridValue[0] = gridValue[1] = valueAtLocation[0] = valueAtLocation[1] = NULL;
341 }
342 if ((gridPoints = SDDS_RowCount(&SDDSin)) <= 0) {
343 SDDS_Bomb("First page of input file is empty.\n");
344 }
345 if (!(gridValue[0] = SDDS_GetColumnInDoubles(&SDDSin, gridVariable[0])) ||
346 !(gridValue[1] = SDDS_GetColumnInDoubles(&SDDSin, gridVariable[1]))) {
347 SDDS_Bomb("Grid variables are missing from input file.\n");
348 }
349 if (!(valueAtLocation[0] = SDDS_GetColumnInDoubles(&SDDSin, findLocationOf[0])) ||
350 !(valueAtLocation[1] = SDDS_GetColumnInDoubles(&SDDSin, findLocationOf[1]))) {
351 SDDS_Bomb("Location variables are missing from input file.\n");
352 }
353
354 gridifyData(gridVariable, gridPoints, presorted);
355 }
356
357 if (inverse) {
358 /* Perform ordinary 2D interpolation on the grid */
359 double xmin, ymin, xmax, ymax, dx, dy, v1, v2, fx, fy;
360 double x, y;
361 int64_t ix, iy, ig;
362
363 xmin = gridValue[0][0];
364 ymin = gridValue[1][0];
365 xmax = gridValue[0][gridPoints - 1];
366 ymax = gridValue[1][gridPoints - 1];
367 dx = (xmax - xmin) / (ng[0] - 1);
368 dy = (ymax - ymin) / (ng[1] - 1);
369 x = atValue[0][iv];
370 y = atValue[1][iv];
371 ix = (x - xmin) / dx;
372 if (ix < 0) {
373 ix = 0;
374 }
375 if (ix >= (int64_t)(ng[0] - 1)) {
376 ix = ng[0] - 2;
377 }
378 iy = (y - ymin) / dy;
379 if (iy < 0) {
380 iy = 0;
381 }
382 if (iy >= (int64_t)(ng[1] - 1)) {
383 iy = ng[1] - 2;
384 }
385 fx = (x - (ix * dx + xmin)) / dx;
386 fy = (y - (iy * dy + ymin)) / dy;
387
388 ig = ix * ng[1] + iy;
389 v1 = valueAtLocation[0][ig] * (1 - fx) + valueAtLocation[0][ig + ng[1]] * fx;
390 ig = ix * ng[1] + iy + 1;
391 v2 = valueAtLocation[0][ig] * (1 - fx) + valueAtLocation[0][ig + ng[1]] * fx;
392 location[0] = v1 * (1 - fy) + v2 * fy;
393 value[0] = x;
394
395 ig = ix * ng[1] + iy;
396 v1 = valueAtLocation[1][ig] * (1 - fx) + valueAtLocation[1][ig + ng[1]] * fx;
397 ig = ix * ng[1] + iy + 1;
398 v2 = valueAtLocation[1][ig] * (1 - fx) + valueAtLocation[1][ig + ng[1]] * fx;
399 location[1] = v1 * (1 - fy) + v2 * fy;
400 value[1] = y;
401 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, irow++,
402 0, value[0], 1, value[1], 2, location[0], 3, location[1],
403 -1)) {
404 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
405 }
406 } else {
407 if (!findLocationInGrid(atValue[0][iv], atValue[1][iv], &location[0], &value[0], interpolate)) {
408 fprintf(stderr, "Couldn't find location for %s=%.6le, %s=%.6le\n",
409 findLocationOf[0], atValue[0][iv],
410 findLocationOf[1], atValue[1][iv]);
411 exit(EXIT_FAILURE);
412 }
413 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, irow++,
414 0, location[0], 1, location[1], 2, value[0], 3, value[1],
415 -1)) {
416 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
417 }
418 }
419 iv++;
420 }
421
422 if (!SDDS_WritePage(&SDDSout) || !SDDS_Terminate(&SDDSout) ||
423 SDDS_Terminate(&SDDSin)) {
424 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
425 }
426 if (gridValue[0]) {
427 free(gridValue[0]);
428 free(gridValue[1]);
429 free(valueAtLocation[0]);
430 free(valueAtLocation[1]);
431 gridValue[0] = gridValue[1] = valueAtLocation[0] = valueAtLocation[1] = NULL;
432 }
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 return pow(target[0] - v[0], 2) + pow(target[1] - v[1], 2);
477}
478
479int findLocationInGrid(double at1, double at2, double *location, double *value, short interpolate) {
480 uint64_t ix, iy, j;
481 uint64_t ixBest = ng[0] / 2, iyBest = ng[1] / 2;
482 double delta, bestDelta = DBL_MAX;
483 long i;
484
485 for (ix = 0; ix < ng[0]; ix++) {
486 for (iy = 0; iy < ng[1]; iy++) {
487 j = ix * ng[1] + iy;
488 delta = pow(valueAtLocation[0][j] - at1, 2) + pow(valueAtLocation[1][j] - at2, 2);
489 if (delta < bestDelta) {
490 location[0] = gridValue[0][j];
491 location[1] = gridValue[1][j];
492 value[0] = valueAtLocation[0][j];
493 value[1] = valueAtLocation[1][j];
494 ixBest = ix;
495 iyBest = iy;
496 bestDelta = delta;
497 }
498 }
499 }
500
501 if (interpolate) {
502 double result, start[2], step[2], lower[2], upper[2];
503 start[0] = ixBest;
504 start[1] = iyBest;
505 step[0] = step[1] = 0.1;
506 lower[0] = lower[1] = 0;
507 upper[0] = ng[0] - 1;
508 upper[1] = ng[1] - 1;
509 target[0] = at1;
510 target[1] = at2;
511 if (simplexMin(&result, start, step, lower, upper, NULL, 2, 0, 1e-14, distance,
512 NULL, 1500, 3, 12, 3, 1, 0) >= 0) {
513 double a00, a01, a10, a11, a0, a1, fx, fy;
514 ix = start[0];
515 iy = start[1];
516 if (start[0] < 0)
517 ix = 0;
518 if (ix >= (int64_t)(ng[0] - 1))
519 ix = ng[0] - 2;
520 if (start[1] < 0)
521 iy = 0;
522 if (iy >= (int64_t)(ng[1] - 1))
523 iy = ng[1] - 2;
524 fx = start[0] - ix;
525 fy = start[1] - iy;
526
527 for (i = 0; i < 2; i++) {
528 a00 = gridValue[i][(ix + 0) * ng[1] + (iy + 0)];
529 a10 = gridValue[i][(ix + 1) * ng[1] + (iy + 0)];
530 a01 = gridValue[i][(ix + 0) * ng[1] + (iy + 1)];
531 a11 = gridValue[i][(ix + 1) * ng[1] + (iy + 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
543int compareGridLocations(const void *data1, const void *data2) {
544 uint64_t i1 = *((uint64_t *)data1);
545 uint64_t i2 = *((uint64_t *)data2);
546 double diff = -(gridValue[0][i1] - gridValue[0][i2]);
547 if (diff == 0) {
548 diff = -(gridValue[1][i1] - gridValue[1][i2]);
549 }
550
551 return (diff < 0 ? 1 : (diff > 0 ? -1 : 0));
552}
553
554void gridifyData(char *gridVariable[2], uint64_t gridPoints, short presorted) {
555 long i;
556 char s[256];
557 uint64_t j, *index;
558 double *buffer;
559
560 for (i = 0; i < 2; i++) {
561 double *copy = tmalloc(sizeof(double) * gridPoints);
562 memcpy(copy, gridValue[i], gridPoints * sizeof(double));
563 qsort((void *)copy, gridPoints, sizeof(double), double_cmpasc);
564 ng[i] = 1;
565 for (j = 1; j < gridPoints; j++) {
566 if (copy[j - 1] != copy[j]) {
567 ng[i] += 1;
568 }
569 }
570 free(copy);
571 if (ng[i] == gridPoints) {
572 snprintf(s, sizeof(s), "Grid variable %s has only unique values.\n", gridVariable[i]);
573 SDDS_Bomb(s);
574 }
575 if (ng[i] == 1) {
576 snprintf(s, sizeof(s), "Grid variable %s has only one unique value.\n", gridVariable[i]);
577 SDDS_Bomb(s);
578 }
579 }
580 if (ng[0] * ng[1] != gridPoints) {
581 snprintf(s, sizeof(s), "Input data does not form a grid (nx = %" PRIu64 ", ny = %" PRIu64 ", rows = %" PRIu64 ")\n",
582 ng[0], ng[1], gridPoints);
583 SDDS_Bomb(s);
584 }
585
586 if (!presorted) {
587 /* Sort indices for points to place data in gridded order */
588 index = tmalloc(sizeof(uint64_t) * gridPoints);
589 for (j = 0; j < gridPoints; j++) {
590 index[j] = j;
591 }
592
593 qsort((void *)index, gridPoints, sizeof(uint64_t), compareGridLocations);
594
595 /* Copy data into sorted order in the global variables */
596 for (i = 0; i < 2; i++) {
597 buffer = tmalloc(sizeof(double) * gridPoints);
598 for (j = 0; j < gridPoints; j++) {
599 buffer[j] = gridValue[i][index[j]];
600 }
601 free(gridValue[i]);
602 gridValue[i] = buffer;
603
604 buffer = tmalloc(sizeof(double) * gridPoints);
605 for (j = 0; j < gridPoints; j++) {
606 buffer[j] = valueAtLocation[i][index[j]];
607 }
608 free(valueAtLocation[i]);
609 valueAtLocation[i] = buffer;
610 }
611 free(index);
612 }
613}
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:49
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:432
void SDDS_ClearErrors()
Clears all recorded error messages from the SDDS error stack.
Definition SDDS_utils.c:318
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
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:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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:472
int double_cmpasc(const void *a, const void *b)
Compare two doubles in ascending order.