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