Cloned SEACAS for EXODUS library with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

254 lines
7.7 KiB

/*
* Copyright(C) 1999-2020 National Technology & Engineering Solutions
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
* NTESS, the U.S. Government retains certain rights in this software.
*
* See packages/seacas/LICENSE for details
*/
#include "defs.h"
#include "params.h"
#include "structs.h"
#include <stdlib.h>
/* Figure out how to divide mesh into pieces. Return true if nonstandard. */
int define_submeshes(int nsets, /* number of subsets in this partition */
int cube_or_mesh, /* 0=> hypercube, d=> d-dimensional mesh */
int * mesh_dims, /* shape of mesh */
struct set_info *set, /* set data for set I'm partitioning */
struct set_info *set_info, /* set data for all sets */
int * subsets, /* subsets being created by partition */
int inert, /* using inertial method? */
int * striping, /* should I partition with parallel cuts? */
int * dir, /* directions of each cut */
int hop_mtx_special[MAXSETS][MAXSETS] /* hops values if unusual */
)
{
extern int KL_METRIC; /* 2 => using hops, so generate special values */
int ndims; /* dimension of cut */
int dims[3]; /* local copy of mesh_dims to modify */
int maxdim; /* longest dimension of the mesh */
int mindim; /* intest dimension of mesh */
int start[3]; /* start in each index of submesh */
int width[3]; /* length in each index of submesh */
int nbits[3]; /* values for computing hops */
int coords[3]; /* location of set in logical grid */
int mask[3]; /* values for computing hops */
int setnum; /* number of created set */
int flag; /* return condition */
int snaking; /* is single stripe snaking through grid? */
int reverse; /* should I reverse direction for embedding? */
int i, j, k; /* loop counters */
dims[0] = set->span[0];
dims[1] = set->span[1];
dims[2] = set->span[2];
ndims = 1;
while ((2 << ndims) <= nsets) {
ndims++;
}
/* Find the intest and longest directions in mesh. */
maxdim = -1;
mindim = dims[0];
dir[1] = dir[2] = 0;
for (i = 0; i < cube_or_mesh; i++) {
if (dims[i] > maxdim) {
maxdim = dims[i];
dir[0] = i;
}
if (dims[i] < mindim) {
mindim = dims[i];
}
}
/* Decide whether or not to force striping. */
i = 0;
for (j = 0; j < cube_or_mesh; j++) {
if (set->span[j] > 1) {
i++;
}
}
*striping = (i <= 1 || nsets == 3 ||
(maxdim > nsets && (maxdim > .6 * nsets * mindim || (inert && nsets > 2))));
snaking = !*striping && inert && nsets > 2;
if (!*striping) {
if (nsets >= 4) { /* Find direction of second & third cuts. */
dims[dir[0]] /= 2;
maxdim = -1;
for (i = 0; i < cube_or_mesh; i++) {
if (dims[i] > maxdim) {
maxdim = dims[i];
dir[1] = i;
}
}
}
if (nsets == 8) { /* Find a third direction. */
dims[dir[1]] /= 2;
maxdim = -1;
for (i = 0; i < cube_or_mesh; i++) {
if (dims[i] > maxdim) {
maxdim = dims[i];
dir[2] = i;
}
}
}
nbits[0] = nbits[1] = nbits[2] = 0;
for (i = 0; i < ndims; i++) {
++nbits[dir[i]];
}
for (i = 0; i < 3; i++) {
mask[i] = (1 << nbits[i]) - 1;
}
mask[1] <<= nbits[0];
mask[2] <<= nbits[0] + nbits[1];
}
for (k = nsets - 1; k >= 0; k--) { /* Backwards to not overwrite current set. */
for (i = 0; i < 3; i++) {
start[i] = 0;
width[i] = dims[i] = set->span[i];
}
if (*striping) { /* Use longest direction for all cuts. */
start[dir[0]] = (k * dims[dir[0]] + nsets - 1) / nsets;
width[dir[0]] = ((k + 1) * dims[dir[0]] + nsets - 1) / nsets - start[dir[0]];
}
else { /* Figure out partition based on cut directions. */
coords[0] = k & mask[0];
coords[1] = (k & mask[1]) >> nbits[0];
coords[2] = (k & mask[2]) >> (nbits[0] + nbits[1]);
if (snaking) {
reverse = coords[1] & 1;
if (reverse) {
coords[0] = mask[0] - coords[0];
}
reverse = coords[2] & 1;
if (reverse) {
coords[1] = (mask[1] >> nbits[0]) - coords[1];
}
}
for (j = 0; j < ndims; j++) {
--nbits[dir[j]];
if (coords[dir[j]] & (1 << nbits[dir[j]])) {
/* Right side of partition. */
start[dir[j]] += (width[dir[j]] + 1) / 2;
width[dir[j]] /= 2;
}
else { /* Left side of partition */
width[dir[j]] = (width[dir[j]] + 1) / 2;
}
}
/* Now restore nbits values. */
nbits[0] = nbits[1] = nbits[2] = 0;
for (i = 0; i < ndims; i++) {
++nbits[dir[i]];
}
}
for (i = 0; i < 3; i++) {
start[i] += set->low[i];
}
setnum = (start[2] * mesh_dims[1] + start[1]) * mesh_dims[0] + start[0];
for (i = 0; i < 3; i++) {
set_info[setnum].low[i] = start[i];
set_info[setnum].span[i] = width[i];
}
subsets[k] = setnum;
}
/* Check to see if hop_mtx is nonstandard. */
flag = FALSE;
if (KL_METRIC == 2) {
if (*striping) {
flag = TRUE;
for (i = 0; i < nsets; i++) {
for (j = 0; j < nsets; j++) {
hop_mtx_special[i][j] = abs(i - j);
}
}
}
else if (nsets == 4) {
if (dir[0] == dir[1] || snaking) {
flag = TRUE;
for (i = 0; i < nsets; i++) {
start[0] = i & mask[0];
start[1] = (i & mask[1]) >> nbits[0];
if (snaking) {
reverse = start[1] & 1;
if (reverse) {
start[0] = mask[0] - start[0];
}
}
for (j = i; j < nsets; j++) {
coords[0] = j & mask[0];
coords[1] = (j & mask[1]) >> nbits[0];
if (snaking) {
reverse = coords[1] & 1;
if (reverse) {
coords[0] = mask[0] - coords[0];
}
}
hop_mtx_special[i][j] = hop_mtx_special[j][i] =
abs(start[0] - coords[0]) + abs(start[1] - coords[1]);
}
}
}
}
else if (nsets == 8) {
if (dir[0] == dir[1] || dir[0] == dir[2] || dir[1] == dir[2] || snaking) {
flag = TRUE;
for (i = 0; i < nsets; i++) {
start[0] = i & mask[0];
start[1] = (i & mask[1]) >> nbits[0];
start[2] = (i & mask[2]) >> (nbits[0] + nbits[1]);
if (snaking) {
reverse = start[1] & 1;
if (reverse) {
start[0] = mask[0] - start[0];
}
reverse = start[2] & 1;
if (reverse) {
start[1] = (mask[1] >> nbits[0]) - start[1];
}
}
for (j = i; j < nsets; j++) {
coords[0] = j & mask[0];
coords[1] = (j & mask[1]) >> nbits[0];
coords[2] = (j & mask[2]) >> (nbits[0] + nbits[1]);
if (snaking) {
reverse = coords[1] & 1;
if (reverse) {
coords[0] = mask[0] - coords[0];
}
reverse = coords[2] & 1;
if (reverse) {
coords[1] = (mask[1] >> nbits[0]) - coords[1];
}
}
hop_mtx_special[i][j] = hop_mtx_special[j][i] =
abs(start[0] - coords[0]) + abs(start[1] - coords[1]) + abs(start[2] - coords[2]);
}
}
}
}
}
*striping |= snaking;
return (flag);
}