/ given a volume, fill in the dims[] and dirs[] arrays */ describing the array slice needed to store field data for */ all grid points in the volume. */ / return value is rank of array slice. */ / if caller_data is non-NULL, it should point to a */ caller-allocated array_slice_data structure which will be */ initialized appo
| 445 | /* get_array_slice. */ |
| 446 | /***************************************************************/ |
| 447 | int fields::get_array_slice_dimensions(const volume &where, size_t dims[3], direction dirs[3], |
| 448 | bool collapse_empty_dimensions, bool snap_empty_dimensions, |
| 449 | vec *min_max_loc, void *caller_data, component cgrid) { |
| 450 | am_now_working_on(FieldOutput); |
| 451 | |
| 452 | // use a local data structure if the caller didn't provide one |
| 453 | array_slice_data local_data; |
| 454 | array_slice_data *data = (array_slice_data *)caller_data; |
| 455 | if (data == 0) data = &local_data; |
| 456 | |
| 457 | data->min_corner = gv.round_vec(where.get_max_corner()) + one_ivec(gv.dim); |
| 458 | data->max_corner = gv.round_vec(where.get_min_corner()) - one_ivec(gv.dim); |
| 459 | data->num_chunks = 0; |
| 460 | |
| 461 | data->min_max_loc = min_max_loc; |
| 462 | vec *min_loc = 0, *max_loc = 0; |
| 463 | if (min_max_loc) { |
| 464 | min_loc = min_max_loc + 0; |
| 465 | max_loc = min_max_loc + 1; |
| 466 | LOOP_OVER_DIRECTIONS(gv.dim, d) { |
| 467 | min_loc->set_direction(d, +infinity); |
| 468 | max_loc->set_direction(d, -infinity); |
| 469 | } |
| 470 | } |
| 471 | |
| 472 | bool use_symmetry = true; |
| 473 | loop_in_chunks(get_array_slice_dimensions_chunkloop, (void *)data, where, cgrid, use_symmetry, |
| 474 | snap_empty_dimensions); |
| 475 | |
| 476 | am_now_working_on(MpiAllTime); |
| 477 | data->min_corner = -max_to_all(-data->min_corner); // i.e., min_to_all |
| 478 | data->max_corner = max_to_all(data->max_corner); |
| 479 | if (min_max_loc) LOOP_OVER_DIRECTIONS(gv.dim, d) { |
| 480 | min_loc->set_direction(d, -1.0 * max_to_all(-1.0 * min_loc->in_direction(d))); |
| 481 | max_loc->set_direction(d, max_to_all(max_loc->in_direction(d))); |
| 482 | } |
| 483 | data->num_chunks = sum_to_all(data->num_chunks); |
| 484 | finished_working(); |
| 485 | if (data->num_chunks == 0 || !(data->min_corner <= data->max_corner)) |
| 486 | return 0; // no data to write; |
| 487 | |
| 488 | int rank = 0; |
| 489 | size_t slice_size = 1; |
| 490 | LOOP_OVER_DIRECTIONS(gv.dim, d) { |
| 491 | if (rank >= 3) meep::abort("too many dimensions in array_slice"); |
| 492 | size_t n = (data->max_corner.in_direction(d) - data->min_corner.in_direction(d)) / 2 + 1; |
| 493 | if (where.in_direction(d) == 0.0 && collapse_empty_dimensions) n = 1; |
| 494 | if (n > 1) { |
| 495 | data->ds[rank] = d; |
| 496 | dims[rank++] = n; |
| 497 | slice_size *= n; |
| 498 | } |
| 499 | } |
| 500 | for (int r = 0; r < rank; r++) |
| 501 | dirs[r] = data->ds[r]; |
| 502 | data->rank = rank; |
| 503 | data->slice_size = slice_size; |
| 504 | finished_working(); |