blob: 03db19356f3e860dfc9369772bfa92434bede1a9 [file] [log] [blame]
// ************************************************************************
//
// miniAMR: stencil computations with boundary exchange and AMR.
//
// Copyright (2014) Sandia Corporation. Under the terms of Contract
// DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
// retains certain rights in this software.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Questions? Contact Courtenay T. Vaughan (ctvaugh@sandia.gov)
// Richard F. Barrett (rfbarre@sandia.gov)
//
// ************************************************************************
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "block.h"
#include "timer.h"
#include "proto.h"
int main(int argc, char** argv)
{
int i, ierr, object_num;
int params[35];
double *objs;
#include "param.h"
my_pe = 0;
num_pes = 1;
counter_malloc = 0;
size_malloc = 0.0;
/* set initial values */
for (i = 1; i < argc; i++)
if (!strcmp(argv[i], "--max_blocks"))
max_num_blocks = atoi(argv[++i]);
else if (!strcmp(argv[i], "--target_active"))
target_active = atoi(argv[++i]);
else if (!strcmp(argv[i], "--target_max"))
target_max = atoi(argv[++i]);
else if (!strcmp(argv[i], "--target_min"))
target_min = atoi(argv[++i]);
else if (!strcmp(argv[i], "--num_refine"))
num_refine = atoi(argv[++i]);
else if (!strcmp(argv[i], "--block_change"))
block_change = atoi(argv[++i]);
else if (!strcmp(argv[i], "--uniform_refine"))
uniform_refine = atoi(argv[++i]);
else if (!strcmp(argv[i], "--nx"))
x_block_size = atoi(argv[++i]);
else if (!strcmp(argv[i], "--ny"))
y_block_size = atoi(argv[++i]);
else if (!strcmp(argv[i], "--nz"))
z_block_size = atoi(argv[++i]);
else if (!strcmp(argv[i], "--num_vars"))
num_vars = atoi(argv[++i]);
else if (!strcmp(argv[i], "--comm_vars"))
comm_vars = atoi(argv[++i]);
else if (!strcmp(argv[i], "--init_x"))
init_block_x = atoi(argv[++i]);
else if (!strcmp(argv[i], "--init_y"))
init_block_y = atoi(argv[++i]);
else if (!strcmp(argv[i], "--init_z"))
init_block_z = atoi(argv[++i]);
else if (!strcmp(argv[i], "--refine_freq"))
refine_freq = atoi(argv[++i]);
else if (!strcmp(argv[i], "--report_diffusion"))
report_diffusion = atoi(argv[++i]);
else if (!strcmp(argv[i], "--error_tol"))
error_tol = atoi(argv[++i]);
else if (!strcmp(argv[i], "--num_tsteps"))
num_tsteps = atoi(argv[++i]);
else if (!strcmp(argv[i], "--stages_per_ts"))
stages_per_ts = atoi(argv[++i]);
else if (!strcmp(argv[i], "--checksum_freq"))
checksum_freq = atoi(argv[++i]);
else if (!strcmp(argv[i], "--stencil"))
stencil = atoi(argv[++i]);
else if (!strcmp(argv[i], "--permute"))
permute = 1;
else if (!strcmp(argv[i], "--report_perf"))
report_perf = atoi(argv[++i]);
else if (!strcmp(argv[i], "--plot_freq"))
plot_freq = atoi(argv[++i]);
else if (!strcmp(argv[i], "--code"))
code = atoi(argv[++i]);
else if (!strcmp(argv[i], "--refine_ghost"))
refine_ghost = 1;
else if (!strcmp(argv[i], "--num_objects")) {
num_objects = atoi(argv[++i]);
objects = (object *) ma_malloc(num_objects*sizeof(object),
__FILE__, __LINE__);
object_num = 0;
} else if (!strcmp(argv[i], "--object")) {
if (object_num >= num_objects) {
printf("object number greater than num_objects\n");
exit(-1);
}
objects[object_num].type = atoi(argv[++i]);
objects[object_num].bounce = atoi(argv[++i]);
objects[object_num].cen[0] = atof(argv[++i]);
objects[object_num].cen[1] = atof(argv[++i]);
objects[object_num].cen[2] = atof(argv[++i]);
objects[object_num].move[0] = atof(argv[++i]);
objects[object_num].move[1] = atof(argv[++i]);
objects[object_num].move[2] = atof(argv[++i]);
objects[object_num].size[0] = atof(argv[++i]);
objects[object_num].size[1] = atof(argv[++i]);
objects[object_num].size[2] = atof(argv[++i]);
objects[object_num].inc[0] = atof(argv[++i]);
objects[object_num].inc[1] = atof(argv[++i]);
objects[object_num].inc[2] = atof(argv[++i]);
object_num++;
} else if (!strcmp(argv[i], "--help")) {
print_help_message();
exit(0);
} else {
printf("** Error ** Unknown input parameter %s\n", argv[i]);
print_help_message();
exit(-1);
}
if (check_input())
exit(-1);
if (!block_change)
block_change = num_refine;
for (object_num = 0; object_num < num_objects; object_num++)
for (i = 0; i < 3; i++) {
objects[object_num].orig_cen[i] = objects[object_num].cen[i];
objects[object_num].orig_move[i] = objects[object_num].move[i];
objects[object_num].orig_size[i] = objects[object_num].size[i];
}
allocate();
driver();
profile();
deallocate();
exit(0);
}
// =================================== print_help_message ====================
void print_help_message(void)
{
printf("(Optional) command line input is of the form: \n\n");
printf("--nx - block size x (even && > 0)\n");
printf("--ny - block size y (even && > 0)\n");
printf("--nz - block size z (even && > 0)\n");
printf("--init_x - initial blocks in x (> 0)\n");
printf("--init_y - initial blocks in y (> 0)\n");
printf("--init_z - initial blocks in z (> 0)\n");
printf("--reorder - ordering of blocks if initial number > 1\n");
printf("--max_blocks - maximun number of blocks per core\n");
printf("--num_refine - (>= 0) number of levels of refinement\n");
printf("--block_change - (>= 0) number of levels a block can change in a timestep\n");
printf("--uniform_refine - if 1, then grid is uniformly refined\n");
printf("--refine_freq - frequency (in timesteps) of checking for refinement\n");
printf("--target_active - (>= 0) target number of blocks per core, none if 0\n");
printf("--target_max - (>= 0) max number of blocks per core, none if 0\n");
printf("--target_min - (>= 0) min number of blocks per core, none if 0\n");
printf("--num_vars - number of variables (> 0)\n");
printf("--comm_vars - number of vars to communicate together\n");
printf("--num_tsteps - number of timesteps (> 0)\n");
printf("--stages_per_ts - number of comm/calc stages per timestep\n");
printf("--checksum_freq - number of stages between checksums\n");
printf("--stencil - 7 or 27 point (27 will not work with refinement (except uniform))\n");
printf("--error_tol - (e^{-error_tol} ; >= 0) \n");
printf("--report_diffusion - (>= 0) none if 0\n");
printf("--report_perf - 0, 1, 2\n");
printf("--refine_freq - frequency (timesteps) of plotting (0 for none)\n");
printf("--code - closely minic communication of different codes\n");
printf(" 0 minimal sends, 1 send ghosts, 2 send ghosts and process on send\n");
printf("--permute - altenates directions in communication\n");
printf("--refine_ghost - use full extent of block (including ghosts) to determine if block is refined\n");
printf("--num_objects - (>= 0) number of objects to cause refinement\n");
printf("--object - type, position, movement, size, size rate of change\n");
printf("All associated settings are integers except for objects\n");
}
// =================================== allocate ==============================
void allocate(void)
{
int i, j, k, m, n;
num_blocks = (int *) ma_malloc((num_refine+1)*sizeof(int),
__FILE__, __LINE__);
num_blocks[0] = num_pes*init_block_x*init_block_y*init_block_z;
num_blocks[0] = init_block_x*init_block_y*init_block_z;
blocks = (block *) ma_malloc(max_num_blocks*sizeof(block),
__FILE__, __LINE__);
for (n = 0; n < max_num_blocks; n++) {
blocks[n].number = -1;
blocks[n].array = (double ****) ma_malloc(num_vars*sizeof(double ***),
__FILE__, __LINE__);
for (m = 0; m < num_vars; m++) {
blocks[n].array[m] = (double ***)
ma_malloc((x_block_size+2)*sizeof(double **),
__FILE__, __LINE__);
for (i = 0; i < x_block_size+2; i++) {
blocks[n].array[m][i] = (double **)
ma_malloc((y_block_size+2)*sizeof(double *),
__FILE__, __LINE__);
for (j = 0; j < y_block_size+2; j++)
blocks[n].array[m][i][j] = (double *)
ma_malloc((z_block_size+2)*sizeof(double),
__FILE__, __LINE__);
}
}
}
sorted_list = (sorted_block *)ma_malloc(max_num_blocks*sizeof(sorted_block),
__FILE__, __LINE__);
sorted_index = (int *) ma_malloc((num_refine+2)*sizeof(int),
__FILE__, __LINE__);
max_num_parents = max_num_blocks; // Guess at number needed
parents = (parent *) ma_malloc(max_num_parents*sizeof(parent),
__FILE__, __LINE__);
for (n = 0; n < max_num_parents; n++)
parents[n].number = -1;
grid_sum = (double *)ma_malloc(num_vars*sizeof(double), __FILE__, __LINE__);
p8 = (int *) ma_malloc((num_refine+2)*sizeof(int), __FILE__, __LINE__);
p2 = (int *) ma_malloc((num_refine+2)*sizeof(int), __FILE__, __LINE__);
block_start = (int *) ma_malloc((num_refine+1)*sizeof(int),
__FILE__, __LINE__);
}
// =================================== deallocate ============================
void deallocate(void)
{
int i, j, m, n;
for (n = 0; n < max_num_blocks; n++) {
for (m = 0; m < num_vars; m++) {
for (i = 0; i < x_block_size+2; i++) {
for (j = 0; j < y_block_size+2; j++)
free(blocks[n].array[m][i][j]);
free(blocks[n].array[m][i]);
}
free(blocks[n].array[m]);
}
free(blocks[n].array);
}
free(blocks);
free(sorted_list);
free(sorted_index);
free(objects);
free(grid_sum);
free(p8);
free(p2);
}
int check_input(void)
{
int error = 0;
if (init_block_x < 1 || init_block_y < 1 || init_block_z < 1) {
printf("initial blocks on processor must be positive\n");
error = 1;
}
if (max_num_blocks < init_block_x*init_block_y*init_block_z) {
printf("max_num_blocks not large enough\n");
error = 1;
}
if (x_block_size < 1 || y_block_size < 1 || z_block_size < 1) {
printf("block size must be positive\n");
error = 1;
}
if (((x_block_size/2)*2) != x_block_size) {
printf("block size in x direction must be even\n");
error = 1;
}
if (((y_block_size/2)*2) != y_block_size) {
printf("block size in y direction must be even\n");
error = 1;
}
if (((z_block_size/2)*2) != z_block_size) {
printf("block size in z direction must be even\n");
error = 1;
}
if (target_active && target_max) {
printf("Only one of target_active and target_max can be used\n");
error = 1;
}
if (target_active && target_min) {
printf("Only one of target_active and target_min can be used\n");
error = 1;
}
if (target_active < 0 || target_active > max_num_blocks) {
printf("illegal value for target_active\n");
error = 1;
}
if (target_max < 0 || target_max > max_num_blocks ||
target_max < target_active) {
printf("illegal value for target_max\n");
error = 1;
}
if (target_min < 0 || target_min > max_num_blocks ||
target_min > target_active || target_min > target_max) {
printf("illegal value for target_min\n");
error = 1;
}
if (num_refine < 0) {
printf("number of refinement levels must be non-negative\n");
error = 1;
}
if (block_change < 0) {
printf("number of refinement levels must be non-negative\n");
error = 1;
}
if (num_vars < 1) {
printf("number of variables must be positive\n");
error = 1;
}
if (num_pes != npx*npy*npz) {
printf("number of processors used does not match number allocated\n");
error = 1;
}
if (stencil != 7 && stencil != 27) {
printf("illegal value for stencil\n");
error = 1;
}
if (stencil == 27 && num_refine && !uniform_refine)
printf("WARNING: 27 point stencil with non-uniform refinement: answers may diverge\n");
if (comm_vars == 0 || comm_vars > num_vars)
comm_vars = num_vars;
if (code < 0 || code > 2) {
printf("code must be 0, 1, or 2\n");
error = 1;
}
return (error);
}