mirror of
https://github.com/PhasicFlow/phasicFlow.git
synced 2025-07-08 03:07:03 +00:00
Zoltan is added as thirdParty package
This commit is contained in:
883
thirdParty/Zoltan/src/hsfc/hsfc.c
vendored
Normal file
883
thirdParty/Zoltan/src/hsfc/hsfc.c
vendored
Normal file
@ -0,0 +1,883 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Andy Bauer's Space Filling Curve (SFC) partitioning modified by Bob Heaphy */
|
||||
|
||||
/* This code uses the Inverse Hilbert Space-Filling Curve to map 1-3 dimensional
|
||||
problems to the unit interval, [0,1]. It then partitions the unit interval
|
||||
into non-overlapping segments each containing equal weights of computational
|
||||
objects. For details concerning the algorithm, please read the Developers
|
||||
Guide. For instructions on using this partitioning algorithm, please read the
|
||||
Users Guide.
|
||||
*/
|
||||
|
||||
|
||||
#include "hsfc.h"
|
||||
#include "hsfc_params.h"
|
||||
#include "zz_const.h"
|
||||
#include <float.h>
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int partition_stats(ZZ *zz, int ndots,
|
||||
Dots *dots, int *obj_sizes,
|
||||
float *work_fraction, int *parts, int *new_parts);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* Zoltan_HSFC - Main routine, Load Balance: Hilbert Space Filling Curve */
|
||||
int Zoltan_HSFC(
|
||||
ZZ *zz,
|
||||
float *part_sizes, /* Input: Array of size zz->Num_Global_Parts
|
||||
containing the percentage of work to be
|
||||
assigned to each partition. */
|
||||
int *num_import, /* -1 indicates imports not used */
|
||||
ZOLTAN_ID_PTR *import_gids, /* ignored */
|
||||
ZOLTAN_ID_PTR *import_lids, /* ignored */
|
||||
int **import_procs, /* ignored */
|
||||
int **import_to_part, /* ignored */
|
||||
int *num_export, /* number of objects to export to lb */
|
||||
ZOLTAN_ID_PTR *export_gids, /* list of Global IDs of exported objects */
|
||||
ZOLTAN_ID_PTR *export_lids, /* optional: Local IDs of exported objects */
|
||||
int **export_procs, /* corresponding processor destinations */
|
||||
int **export_to_parts /* partition assignments for export */
|
||||
)
|
||||
{
|
||||
/* malloc'd arrays that need to be freed before completion */
|
||||
Dots *dots = NULL;
|
||||
ZOLTAN_ID_PTR gids = NULL;
|
||||
ZOLTAN_ID_PTR lids = NULL;
|
||||
int *parts = NULL; /* initial partitions for objects */
|
||||
int *new_proc = NULL; /* new processor assignments for dots */
|
||||
int *new_part = NULL; /* new partition assignments for dots */
|
||||
Partition *grand_partition = NULL; /* fine partition of [0,1] */
|
||||
double *partition = NULL; /* course partition of [0,1] */
|
||||
double *grand_weight = NULL; /* "binned" weights on grand partition */
|
||||
double *temp_weight = NULL; /* local binning before MPI_Allreduce */
|
||||
float *weights = NULL; /* to get original local dots' wt vec */
|
||||
float *target = NULL; /* desired weight in each partition */
|
||||
float *work_fraction = NULL; /* % of load in each partition */
|
||||
double *delta = NULL; /* refinement interval */
|
||||
double *tsum = NULL;
|
||||
double *geom_vec = NULL; /* Temporary coordinates array. */
|
||||
HSFC_Data *d = NULL; /* pointer to persistant data storage */
|
||||
|
||||
/* other (non malloc'd) variables */
|
||||
int ndots; /* number of dots on this machine */
|
||||
int pcount; /* number of partitions in grand partition */
|
||||
int new_map; /* flag indicating whether parts were
|
||||
remapped */
|
||||
double start_time=0.0L, end_time=0.0L; /* used to time execution */
|
||||
double start_stat_time=0.0L, total_stat_time=0.0L;
|
||||
double total_weight = 0.0;
|
||||
|
||||
/* temporary variables, loop counters, etc. */
|
||||
int tmp;
|
||||
int i, j, k; /* loop counters */
|
||||
double sum;
|
||||
int done, out_of_tolerance=0; /* binary flags */
|
||||
Partition *p = NULL;
|
||||
int loop = 0;
|
||||
double actual, desired, correction;
|
||||
double temp, in[6], out[6];
|
||||
int err;
|
||||
int final_output;
|
||||
int param;
|
||||
int idummy;
|
||||
double ddummy;
|
||||
int dim;
|
||||
char *yo = "Zoltan_HSFC";
|
||||
|
||||
/* begin program with trace, timing, and initializations */
|
||||
ZOLTAN_TRACE_ENTER (zz, yo);
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_ATIME) {
|
||||
MPI_Barrier(zz->Communicator);
|
||||
start_time = Zoltan_Time(zz->Timer);
|
||||
}
|
||||
*num_export = *num_import = -1; /* in case of early error exit */
|
||||
Zoltan_Bind_Param (HSFC_params, "FINAL_OUTPUT", (void*) &final_output);
|
||||
Zoltan_Bind_Param (HSFC_params, "KEEP_CUTS", (void*) ¶m);
|
||||
Zoltan_Bind_Param (HSFC_params, "REDUCE_DIMENSIONS", (void*) &idummy);
|
||||
Zoltan_Bind_Param (HSFC_params, "DEGENERATE_RATIO", (void*) &ddummy);
|
||||
param = idummy = final_output = 0;
|
||||
ddummy = 0.0;
|
||||
Zoltan_Assign_Param_Vals (zz->Params, HSFC_params, zz->Debug_Level, zz->Proc,
|
||||
zz->Debug_Proc);
|
||||
|
||||
if (sizeof (int) != 4) {
|
||||
ZOLTAN_HSFC_ERROR(ZOLTAN_FATAL,
|
||||
"HSFC implemented only for 32-bit integers");
|
||||
}
|
||||
|
||||
/* allocate persistent storage required by box assign and point assign */
|
||||
|
||||
if (zz->LB.Data_Structure == NULL){
|
||||
zz->LB.Data_Structure = (void*) ZOLTAN_MALLOC (sizeof (HSFC_Data));
|
||||
if (zz->LB.Data_Structure == NULL){
|
||||
ZOLTAN_HSFC_ERROR(ZOLTAN_MEMERR, "Error returned by malloc");
|
||||
}
|
||||
|
||||
d = (HSFC_Data*) zz->LB.Data_Structure;
|
||||
memset ((void*)d, 0, sizeof (HSFC_Data));
|
||||
Zoltan_Initialize_Transformation(&(d->tran));
|
||||
}
|
||||
else{
|
||||
d = (HSFC_Data*) zz->LB.Data_Structure;
|
||||
ZOLTAN_FREE (&d->final_partition);
|
||||
}
|
||||
|
||||
/* obtain dot information: gids, lids, weights */
|
||||
err = Zoltan_Get_Obj_List (zz, &ndots, &gids, &lids, zz->Obj_Weight_Dim,
|
||||
&weights, &parts);
|
||||
if (err)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "Error in Zoltan_Get_Obj_List.");
|
||||
|
||||
MPI_Allreduce(&ndots, &i, 1, MPI_INT, MPI_MAX, zz->Communicator);
|
||||
if (i < 1){
|
||||
if (zz->Proc == 0)
|
||||
ZOLTAN_PRINT_WARN(zz->Proc, yo, "No objects to partition")
|
||||
*num_export = 0;
|
||||
goto EndReporting;
|
||||
}
|
||||
|
||||
/* allocate storage for dots and their corresponding gids, lids, weights */
|
||||
if (ndots > 0) {
|
||||
dots = (Dots*) ZOLTAN_MALLOC (sizeof(Dots) * ndots);
|
||||
if (dots == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Failed to ZOLTAN_MALLOC dots.");
|
||||
}
|
||||
|
||||
/* set dot weights from object weights, if none set to one */
|
||||
if (zz->Obj_Weight_Dim > 1)
|
||||
ZOLTAN_PRINT_WARN(zz->Proc, yo,"Only one weight per GID can be processed");
|
||||
if (zz->Obj_Weight_Dim < 1)
|
||||
for (i = 0; i < ndots; i++)
|
||||
dots[i].weight = DEFAULT_WEIGHT;
|
||||
else
|
||||
for (i = 0; i < ndots; i++)
|
||||
dots[i].weight = weights [i * zz->Obj_Weight_Dim]; /* 1 dimension only */
|
||||
ZOLTAN_FREE (&weights);
|
||||
|
||||
/* get dots' coordinates */
|
||||
err = Zoltan_Get_Coordinates(zz, ndots, gids, lids, &(d->ndimension),
|
||||
&geom_vec);
|
||||
|
||||
if (err != 0)
|
||||
ZOLTAN_HSFC_ERROR(ZOLTAN_FATAL, "Error in Zoltan_Get_Coordinates.");
|
||||
|
||||
if (d->tran.Target_Dim > 0){ /* degenerate geometry */
|
||||
dim = d->tran.Target_Dim;
|
||||
}
|
||||
else{
|
||||
dim = d->ndimension;
|
||||
}
|
||||
|
||||
for (i = 0, tmp=0; i < ndots; i++, tmp += d->ndimension) {
|
||||
for (j = 0; j < d->ndimension; j++){
|
||||
dots[i].x[j] = geom_vec[tmp + j];
|
||||
}
|
||||
}
|
||||
|
||||
ZOLTAN_FREE(&geom_vec);
|
||||
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "Obtained dot information");
|
||||
|
||||
/* allocate storage for partitions and "binned" weights */
|
||||
pcount = N * (zz->LB.Num_Global_Parts - 1) + 1;
|
||||
target =(float*) ZOLTAN_MALLOC(sizeof(float) *zz->LB.Num_Global_Parts);
|
||||
partition =(double*)ZOLTAN_MALLOC(sizeof(double)*zz->LB.Num_Global_Parts);
|
||||
delta =(double*)ZOLTAN_MALLOC(sizeof(double)*zz->LB.Num_Global_Parts);
|
||||
tsum =(double*)ZOLTAN_MALLOC(sizeof(double)*zz->LB.Num_Global_Parts);
|
||||
grand_weight =(double*)ZOLTAN_MALLOC(sizeof(double) * pcount*3);/*max,min,sum*/
|
||||
temp_weight =(double*)ZOLTAN_MALLOC(sizeof(double) * pcount*3);/*max,min,sum*/
|
||||
grand_partition = (Partition*)ZOLTAN_MALLOC (sizeof (Partition) * pcount);
|
||||
|
||||
if (target == NULL || partition == NULL || delta == NULL || tsum == NULL
|
||||
|| grand_weight == NULL || temp_weight == NULL || grand_partition == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Malloc error for partitions, targets");
|
||||
|
||||
if (zz->Obj_Weight_Dim <= 1)
|
||||
work_fraction = part_sizes;
|
||||
else {
|
||||
work_fraction =(float*)ZOLTAN_MALLOC(sizeof(float)*zz->LB.Num_Global_Parts);
|
||||
if (work_fraction == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Malloc error for work_fraction");
|
||||
|
||||
/* HSFC supports only the first weight; select the appropriate part_sizes */
|
||||
/* entries for the first weight. */
|
||||
for (i = 0; i < zz->LB.Num_Global_Parts; i++)
|
||||
work_fraction[i] = part_sizes[i*zz->Obj_Weight_Dim];
|
||||
}
|
||||
|
||||
/* Get bounding box, smallest coordinate aligned box containing all dots */
|
||||
for (i = 0; i < dim; i++)
|
||||
out[i] = in[i] = -HUGE_VAL;
|
||||
for (i = dim; i < 2*dim; i++)
|
||||
out[i] = in[i] = HUGE_VAL;
|
||||
for (i = 0; i < ndots; i++) {
|
||||
for (j = 0; j < dim; j++) {
|
||||
/* get maximum bound box coordinates: */
|
||||
if(dots[i].x[j]>in[j]) in[j]=dots[i].x[j];
|
||||
}
|
||||
for (j = dim; j < 2*dim; j++) {
|
||||
/* get minimum bound box coordinates: */
|
||||
if(dots[i].x[j-dim]<in[j]) in[j]=dots[i].x[j-dim];
|
||||
}
|
||||
}
|
||||
err = MPI_Allreduce(in,out,dim,MPI_DOUBLE,MPI_MAX,zz->Communicator);
|
||||
err = MPI_Allreduce(in+dim,out+dim,dim,MPI_DOUBLE,MPI_MIN,zz->Communicator);
|
||||
if (err != MPI_SUCCESS)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "Bounding box MPI_Allreduce error");
|
||||
|
||||
/* Enlarge bounding box to make points on faces become interior (Andy) */
|
||||
for (i = 0; i < dim; i++) {
|
||||
temp = (out[i] - out[i+dim]) * HSFC_EPSILON;
|
||||
d->bbox_hi[i] = out[i] + temp;
|
||||
d->bbox_lo[i] = out[i+dim] - temp;
|
||||
d->bbox_extent[i] = d->bbox_hi[i] - d->bbox_lo[i];
|
||||
if (d->bbox_extent[i] == 0.0)
|
||||
d->bbox_extent[i] = 1.0; /* degenerate axis, avoid divide by zero */
|
||||
}
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "Determined problem bounding box");
|
||||
|
||||
/* Save appropriate HSFC function for later use below and in point_assign() */
|
||||
if (dim== 1) d->fhsfc = Zoltan_HSFC_InvHilbert1d;
|
||||
else if (dim== 2) d->fhsfc = Zoltan_HSFC_InvHilbert2d;
|
||||
else if (dim== 3) d->fhsfc = Zoltan_HSFC_InvHilbert3d;
|
||||
|
||||
/* Scale coordinates to bounding box, compute HSFC */
|
||||
for (i = 0; i < ndots; i++) {
|
||||
for (j = 0; j < dim; j++)
|
||||
out[j] = (dots[i].x[j] - d->bbox_lo[j]) / d->bbox_extent[j];
|
||||
dots[i].fsfc = d->fhsfc (zz, out); /* Note, this is a function call */
|
||||
}
|
||||
|
||||
/* Initialize grand partition to equally spaced intervals on [0,1] */
|
||||
for (i = 0; i < pcount; i++) {
|
||||
grand_partition[i].index = i;
|
||||
grand_partition[i].r = (i+1) / (double)pcount;
|
||||
grand_partition[i].l = i / (double)pcount;
|
||||
}
|
||||
grand_partition[pcount-1].r += (2.0 * FLT_EPSILON) ;
|
||||
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "About to enter main loop\n");
|
||||
|
||||
|
||||
/* This loop is the real guts of the partitioning algorithm */
|
||||
for (loop = 0; loop < MAX_LOOPS; loop++) {
|
||||
/* initialize bins, DEFAULT_BIN_MAX is less than any possible max,... */
|
||||
for (i = 0; i < pcount; i++)
|
||||
grand_weight[i] = temp_weight[i] = 0.0; /* SUM */
|
||||
for (i = pcount; i < 2*pcount; i++)
|
||||
grand_weight[i] = temp_weight[i] = DEFAULT_BIN_MAX;
|
||||
for (i = 2*pcount; i < 3*pcount; i++)
|
||||
grand_weight[i] = temp_weight[i] = DEFAULT_BIN_MIN;
|
||||
|
||||
/* bin weights, max, min for all dots using current grand partition */
|
||||
for (i = 0; i < ndots; i++) {
|
||||
if (loop > 0
|
||||
&& dots[i].fsfc < grand_partition[dots[i].part].r
|
||||
&& dots[i].fsfc >= grand_partition[dots[i].part].l)
|
||||
p = &grand_partition[dots[i].part]; /* short cut if unchanged */
|
||||
else
|
||||
p = (Partition*) bsearch (&dots[i].fsfc, grand_partition, pcount,
|
||||
sizeof(Partition), Zoltan_HSFC_compare);
|
||||
if (p == NULL) /* programming error if NULL */
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "BSEARCH RETURNED ERROR");
|
||||
|
||||
dots[i].part = p->index;
|
||||
temp_weight [p->index] += dots[i].weight; /* local wt sum */
|
||||
if (dots[i].fsfc > temp_weight[p->index + pcount])
|
||||
temp_weight [p->index + pcount] = dots[i].fsfc; /*local indx max*/
|
||||
if (dots[i].fsfc < temp_weight[p->index + 2 * pcount])
|
||||
temp_weight [p->index + pcount * 2] = dots[i].fsfc;/*local indx min*/
|
||||
}
|
||||
err = MPI_Allreduce(temp_weight, grand_weight, pcount,
|
||||
MPI_DOUBLE, MPI_SUM, zz->Communicator);
|
||||
err = MPI_Allreduce(temp_weight+pcount, grand_weight+pcount, pcount,
|
||||
MPI_DOUBLE, MPI_MAX, zz->Communicator);
|
||||
err = MPI_Allreduce(temp_weight+2*pcount, grand_weight+2*pcount, pcount,
|
||||
MPI_DOUBLE, MPI_MIN, zz->Communicator);
|
||||
if (err != MPI_SUCCESS)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "MPI_Allreduce returned error");
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "Complete main loop MPI_Allreduce");
|
||||
|
||||
/* Allocate ideal weights per partition -- once is sufficient */
|
||||
if (loop == 0) {
|
||||
total_weight = 0.0;
|
||||
for (i = 0; i < pcount; i++)
|
||||
total_weight += grand_weight[i];
|
||||
for (i = 0; i < zz->LB.Num_Global_Parts; i++)
|
||||
target[i] = work_fraction[i] * total_weight;
|
||||
}
|
||||
|
||||
/* debug: print target and grand partition values */
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL && zz->Proc == 0) {
|
||||
printf ("\n\nTarget %.2f, loop %d\n", target[0], loop);
|
||||
for (i = 0; i < pcount; i++)
|
||||
printf ("Grand Partition %3d, weight %3.0f, left = %0.6f, right"
|
||||
"= %0.6f, delta = %19.14f\n", i, grand_weight[i],
|
||||
grand_partition[i].l, grand_partition[i].r, grand_weight[i+pcount]
|
||||
- grand_weight[i+2*pcount]);
|
||||
}
|
||||
|
||||
/* create new partition by summing contiguous bins l to r until target */
|
||||
for (i = 0; i < pcount; i++) /* since grand weight modified below */
|
||||
temp_weight[i] = grand_weight[i];
|
||||
for (k = 0; k < zz->LB.Num_Global_Parts; k++) {
|
||||
partition[k] = 1.0;
|
||||
delta[k] = 0.0;
|
||||
}
|
||||
done = 1; /* flag, 1 means done is true */
|
||||
sum = 0.0;
|
||||
for (k = i = 0; i < pcount && k < zz->LB.Num_Global_Parts - 1; )
|
||||
if (sum + grand_weight[i] <= target[k])
|
||||
sum += grand_weight[i++];
|
||||
else {
|
||||
/* stop current summing to set new partition coordinate */
|
||||
partition[k] = grand_partition[i].l;
|
||||
delta[k] = (grand_partition[i].r - grand_partition[i].l)/(N-1);
|
||||
|
||||
/* If a "bin" holds multiple processors worth of dots: */
|
||||
if (k > 0 && partition[k-1] >= partition[k]) {
|
||||
partition[k] = 0.5 * (grand_partition[i].r - partition[k-1])
|
||||
+ partition[k-1];
|
||||
delta[k] = delta[k-1] = delta[k-1] * 0.5;
|
||||
}
|
||||
|
||||
/* max - min test if current bin is capable of further refinement */
|
||||
temp = grand_weight[i+pcount] - grand_weight[i+2*pcount];
|
||||
if (i < pcount && temp > REFINEMENT_LIMIT)
|
||||
done = 0; /* not done, at least this bin is refinable */
|
||||
|
||||
/* get ready for next loop */
|
||||
grand_weight[i] -= (target[k] - sum); /* prevents systematic bias */
|
||||
sum = 0.0;
|
||||
k++;
|
||||
}
|
||||
if (done) /* this is the actual loop stopping criterion */
|
||||
break; /* no bin with "cut" is refinable, time to quit */
|
||||
|
||||
/* determine new grand partition by refining new partition boundary */
|
||||
for (k = i = 0; i < zz->LB.Num_Global_Parts - 1; i++)
|
||||
for (j = 0; j < N; j++, k++)
|
||||
grand_partition[k+1].l = grand_partition[k].r
|
||||
= partition[i] + j * delta[i];
|
||||
grand_partition[0].l = 0.0;
|
||||
grand_partition[pcount-1].r = 1.0 + (2.0 * FLT_EPSILON) ;
|
||||
} /* end of loop */
|
||||
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "Exited main loop");
|
||||
Zoltan_Multifree (__FILE__, __LINE__, 3, &grand_weight, &partition, &delta);
|
||||
if (zz->Obj_Weight_Dim > 1)
|
||||
ZOLTAN_FREE (&work_fraction);
|
||||
|
||||
d->final_partition = (Partition*) ZOLTAN_MALLOC(sizeof(Partition)
|
||||
* zz->LB.Num_Global_Parts);
|
||||
if (d->final_partition == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Unable to malloc final_partition");
|
||||
|
||||
/* initializations required to start loop below */
|
||||
d->final_partition[0].l = 0.0;
|
||||
for (k = 0; k < zz->LB.Num_Global_Parts; k++) {
|
||||
tsum[k] = 0.0;
|
||||
d->final_partition[k].index = k;
|
||||
}
|
||||
actual = desired = total_weight;
|
||||
i = k = 0;
|
||||
correction = 1.0;
|
||||
|
||||
/* set new partition on [0,1] by summing grand_weights until targets met */
|
||||
/* k counts partitions and i counts grand partitions */
|
||||
while (1) {
|
||||
if (k >= zz->LB.Num_Global_Parts || i >= pcount)
|
||||
break;
|
||||
|
||||
/* case: current partition should remain empty */
|
||||
if (target[k] == 0.0) {
|
||||
d->final_partition[k].r = grand_partition[i].l;
|
||||
k++;
|
||||
if (k < zz->LB.Num_Global_Parts)
|
||||
d->final_partition[k].l = grand_partition[i].l;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* case: current bin weights fit into current partition */
|
||||
temp = correction * target[k];
|
||||
if (tsum[k] + temp_weight[i] <= temp) {
|
||||
tsum[k] += temp_weight[i];
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* case: current bin weights overfill current partition */
|
||||
if (temp - tsum[k] > tsum[k] + temp_weight[i] - temp) {
|
||||
tsum[k] += temp_weight[i];
|
||||
actual -= tsum[k];
|
||||
desired -= target[k];
|
||||
d->final_partition[k].r = grand_partition[i].r;
|
||||
k++;
|
||||
if (k < zz->LB.Num_Global_Parts)
|
||||
d->final_partition[k].l = grand_partition[i].r;
|
||||
i++;
|
||||
}
|
||||
else { /* don't include current bin weight in current partition */
|
||||
actual -= tsum[k];
|
||||
desired -= target[k];
|
||||
d->final_partition[k].r = grand_partition[i].l;
|
||||
k++;
|
||||
if (k < zz->LB.Num_Global_Parts)
|
||||
d->final_partition[k].l = grand_partition[i].l;
|
||||
}
|
||||
|
||||
/* correct target[]s for cumulative partitioning errors (Bruce H.) */
|
||||
correction = ((desired == 0) ? 1.0 : actual/desired);
|
||||
}
|
||||
/* check if we didn't close out last sum, fix right boundary if needed */
|
||||
if (i == pcount && k < zz->LB.Num_Global_Parts)
|
||||
{
|
||||
d->final_partition[k].r = 1.0 + (2.0 * FLT_EPSILON) ;
|
||||
k++;
|
||||
}
|
||||
|
||||
/* if last partition(s) is empty, loop stops w/o setting final_partition(s) */
|
||||
for (i = k; i < zz->LB.Num_Global_Parts; i++) {
|
||||
d->final_partition[i].r = 1.0 + (2.0 * FLT_EPSILON);
|
||||
d->final_partition[i].l = 1.0 + (2.0 * FLT_EPSILON);
|
||||
}
|
||||
|
||||
out_of_tolerance = 0;
|
||||
for (k = 0; k < zz->LB.Num_Global_Parts; k++)
|
||||
if (tsum[k] > target[k] * zz->LB.Imbalance_Tol[0])
|
||||
out_of_tolerance = 1;
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "Determined final partition");
|
||||
|
||||
new_part = (int *) ZOLTAN_MALLOC(2 * ndots * sizeof(int));
|
||||
if (ndots && !new_part)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Memory error.");
|
||||
new_proc = new_part + ndots;
|
||||
|
||||
/* Set the final part number for all dots */
|
||||
for (i = 0; i < ndots; i++) {
|
||||
j = dots[i].part / N; /* grand_partition is N times final_partition parts*/
|
||||
if (dots[i].fsfc < d->final_partition[j].r
|
||||
&& dots[i].fsfc >= d->final_partition[j].l)
|
||||
p = d->final_partition + j;
|
||||
else
|
||||
p = (Partition*) bsearch (&dots[i].fsfc, d->final_partition,
|
||||
zz->LB.Num_Global_Parts, sizeof(Partition), Zoltan_HSFC_compare);
|
||||
if (p == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "BSEARCH RETURNED ERROR");
|
||||
|
||||
dots[i].part = p->index;
|
||||
new_part[i] = dots[i].part;
|
||||
new_proc[i] = Zoltan_LB_Part_To_Proc(zz, p->index,
|
||||
gids + i * zz->Num_GID);
|
||||
}
|
||||
|
||||
/* Remap partitions to reduce data movement. */
|
||||
if (zz->LB.Remap_Flag) {
|
||||
err = Zoltan_LB_Remap(zz, &new_map, ndots, new_proc, parts, new_part, 1);
|
||||
if (err < 0)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL,"Error returned from Zoltan_LB_Remap");
|
||||
}
|
||||
|
||||
total_stat_time = 0.0;
|
||||
if (final_output){
|
||||
int *objSizes = NULL;
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_ATIME) {
|
||||
start_stat_time = Zoltan_Time(zz->Timer);
|
||||
}
|
||||
if ((ndots > 0) && ((zz->Get_Obj_Size_Multi) || (zz->Get_Obj_Size))){
|
||||
|
||||
objSizes = (int *) ZOLTAN_MALLOC(ndots * sizeof(int));
|
||||
if (!objSizes){
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Failed to ZOLTAN_MALLOC sizes.");
|
||||
}
|
||||
|
||||
if (zz->Get_Obj_Size_Multi) {
|
||||
zz->Get_Obj_Size_Multi(zz->Get_Obj_Size_Multi_Data,
|
||||
zz->Num_GID, zz->Num_LID, ndots,
|
||||
gids, lids, objSizes, &err);
|
||||
if (err < 0) {
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "Error returned from "
|
||||
"ZOLTAN_OBJ_SIZE_MULTI function.");
|
||||
}
|
||||
}
|
||||
else if (zz->Get_Obj_Size) {
|
||||
for (i = 0; i < ndots; i++) {
|
||||
ZOLTAN_ID_PTR lid = (zz->Num_LID ? &(lids[i*zz->Num_LID]):NULL);
|
||||
objSizes[i] = zz->Get_Obj_Size(zz->Get_Obj_Size_Data,
|
||||
zz->Num_GID, zz->Num_LID,
|
||||
&(gids[i*zz->Num_GID]),
|
||||
lid, &err);
|
||||
if (err < 0) {
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "Error returned from "
|
||||
"ZOLTAN_OBJ_SIZE function.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = partition_stats(zz, ndots, dots, objSizes, work_fraction,
|
||||
parts, new_part);
|
||||
|
||||
if (err != ZOLTAN_OK){
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "statistics");
|
||||
}
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_ATIME) {
|
||||
total_stat_time = Zoltan_Time(zz->Timer) - start_stat_time;
|
||||
}
|
||||
|
||||
ZOLTAN_FREE(&objSizes);
|
||||
}
|
||||
|
||||
/* free stuff before next required allocations */
|
||||
Zoltan_Multifree (__FILE__, __LINE__, 3, &temp_weight, &grand_partition,
|
||||
&target);
|
||||
|
||||
/* Count the number of objects to export from this processor */
|
||||
*num_export = 0;
|
||||
for (i = 0; i < ndots; i++) {
|
||||
if (new_part[i] != parts[i] || zz->Proc != new_proc[i])
|
||||
++(*num_export);
|
||||
}
|
||||
|
||||
EndReporting:
|
||||
|
||||
if (!zz->LB.Return_Lists)
|
||||
*num_export = -1;
|
||||
else if (zz->LB.Return_Lists == ZOLTAN_LB_CANDIDATE_LISTS) {
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "Candidate Lists not supported in HSFC;"
|
||||
"change RETURN_LISTS parameter");
|
||||
}
|
||||
else if (*num_export > 0) {
|
||||
/* allocate storage for export information and fill in data */
|
||||
if (!Zoltan_Special_Malloc (zz, (void**) export_gids, *num_export,
|
||||
ZOLTAN_SPECIAL_MALLOC_GID))
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Failed to malloc global ids");
|
||||
|
||||
if (zz->Num_LID > 0) {
|
||||
if (!Zoltan_Special_Malloc (zz, (void**) export_lids, *num_export,
|
||||
ZOLTAN_SPECIAL_MALLOC_LID)){
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Failed to malloc local ids");
|
||||
}
|
||||
}
|
||||
|
||||
if (!Zoltan_Special_Malloc (zz, (void**) export_procs, *num_export,
|
||||
ZOLTAN_SPECIAL_MALLOC_INT))
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Failed to malloc export proc list");
|
||||
|
||||
if (!Zoltan_Special_Malloc (zz, (void**) export_to_parts, *num_export,
|
||||
ZOLTAN_SPECIAL_MALLOC_INT))
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Failed to malloc export part list");
|
||||
|
||||
/* Fill in export arrays */
|
||||
for (j = i = 0; i < ndots; i++) {
|
||||
if (new_part[i] != parts[i] || zz->Proc != new_proc[i]) {
|
||||
*((*export_procs) +j) = new_proc[i];
|
||||
*((*export_to_parts)+j) = new_part[i];
|
||||
if (zz->Num_GID > 0)
|
||||
ZOLTAN_SET_GID(zz, *export_gids+j*zz->Num_GID, gids+i*zz->Num_GID);
|
||||
if (zz->Num_LID > 0)
|
||||
ZOLTAN_SET_LID(zz, *export_lids+j*zz->Num_LID, lids+i*zz->Num_LID);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ZOLTAN_TRACE_DETAIL (zz, yo, "Filled in export information");
|
||||
|
||||
/* DEBUG: print useful information */
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL && zz->Proc == 0)
|
||||
printf ("<%d> Number of loops = %d\n", zz->Proc, loop + 1);
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_LIST && zz->Proc == 0)
|
||||
printf ("<%d> export count %d, ndots %d\n", zz->Proc, *num_export, ndots);
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_LIST)
|
||||
for (i = 0; i < ndots; i++) {
|
||||
printf ("<%d> GID: ", zz->Proc);
|
||||
ZOLTAN_PRINT_GID (zz, &gids[i*zz->Num_GID]);
|
||||
if (lids || zz->Num_LID > 0) {
|
||||
printf (" LID: ");
|
||||
ZOLTAN_PRINT_LID (zz, &lids[i*zz->Num_LID]);
|
||||
}
|
||||
printf (" Part: %d Weight %.1f HSFC %.6f\n", new_part[i],
|
||||
dots[i].weight, dots[i].fsfc);
|
||||
printf ("PROC %d DOT " ZOLTAN_ID_SPEC "\n", p->index, gids[i]);
|
||||
}
|
||||
|
||||
ZOLTAN_FREE(&new_part);
|
||||
|
||||
/* done, do we keep data structure for box drop and point drop? */
|
||||
|
||||
if (!param && /* we don't need partitions */
|
||||
(d->tran.Target_Dim < 0)){ /* we don't need transformation */
|
||||
Zoltan_HSFC_Free_Structure (zz);
|
||||
}
|
||||
|
||||
/* really done now, now free dynamic storage and exit with return status */
|
||||
err = ((out_of_tolerance) ? ZOLTAN_WARN : ZOLTAN_OK);
|
||||
if (zz->Proc == 0 && err == ZOLTAN_WARN && zz->Debug_Level >ZOLTAN_DEBUG_NONE)
|
||||
ZOLTAN_PRINT_WARN (zz->Proc, yo, "HSFC: Imbalance exceeds user limit");
|
||||
|
||||
End:
|
||||
|
||||
if (err != ZOLTAN_OK && err != ZOLTAN_WARN) {
|
||||
Zoltan_Special_Free(zz, (void **)export_gids, ZOLTAN_SPECIAL_MALLOC_GID);
|
||||
Zoltan_Special_Free(zz, (void **)export_lids, ZOLTAN_SPECIAL_MALLOC_LID);
|
||||
Zoltan_Special_Free(zz, (void **)export_procs, ZOLTAN_SPECIAL_MALLOC_INT);
|
||||
Zoltan_Special_Free(zz, (void **)export_to_parts,
|
||||
ZOLTAN_SPECIAL_MALLOC_INT);
|
||||
}
|
||||
Zoltan_Multifree (__FILE__, __LINE__, 12, &dots, &gids, &lids, &partition,
|
||||
&grand_partition, &grand_weight, &temp_weight, &weights, &target, &delta,
|
||||
&parts, &tsum);
|
||||
if (zz->Obj_Weight_Dim > 1)
|
||||
ZOLTAN_FREE (&work_fraction);
|
||||
|
||||
if (zz->Debug_Level >= ZOLTAN_DEBUG_ATIME) {
|
||||
MPI_Barrier(zz->Communicator);
|
||||
end_time = Zoltan_Time(zz->Timer);
|
||||
if (zz->Debug_Proc == zz->Proc)
|
||||
printf ("HSFC Processing Time is %.6f seconds\n",
|
||||
end_time-start_time-total_stat_time);
|
||||
}
|
||||
|
||||
ZOLTAN_TRACE_EXIT (zz, yo);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* routine for bsearch locating the partition segment holding key */
|
||||
int Zoltan_HSFC_compare (const void *key, const void *arg)
|
||||
{
|
||||
if ( *(double*) key >= ((Partition*) arg)->r) return 1;
|
||||
if ( *(double*) key < ((Partition*) arg)->l) return -1;
|
||||
|
||||
return 0; /* key in arg interval [l,r) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* free state memory needed by point & box drop routines */
|
||||
void Zoltan_HSFC_Free_Structure (ZZ *zz)
|
||||
{
|
||||
HSFC_Data *data = (HSFC_Data*) zz->LB.Data_Structure;
|
||||
if (data != NULL)
|
||||
ZOLTAN_FREE (&data->final_partition);
|
||||
ZOLTAN_FREE (&zz->LB.Data_Structure);
|
||||
}
|
||||
|
||||
/* Copy an hsfc data structure */
|
||||
|
||||
int Zoltan_HSFC_Copy_Structure(ZZ *toZZ, ZZ const *fromZZ)
|
||||
{
|
||||
char *yo = "Zoltan_HSFC_Copy_Structure";
|
||||
int len;
|
||||
HSFC_Data *to;
|
||||
HSFC_Data const *from;
|
||||
|
||||
Zoltan_HSFC_Free_Structure(toZZ);
|
||||
from = (HSFC_Data const *)fromZZ->LB.Data_Structure;
|
||||
|
||||
if (!from){
|
||||
return ZOLTAN_OK;
|
||||
}
|
||||
|
||||
to = (HSFC_Data *)ZOLTAN_MALLOC(sizeof(HSFC_Data));
|
||||
if (!to){
|
||||
ZOLTAN_PRINT_ERROR(fromZZ->Proc, yo, "Insufficient memory.");
|
||||
return ZOLTAN_MEMERR;
|
||||
}
|
||||
|
||||
toZZ->LB.Data_Structure = (void *)to;
|
||||
|
||||
*to = *from;
|
||||
|
||||
if (from->final_partition){
|
||||
len = sizeof(Partition) * fromZZ->LB.Num_Global_Parts;
|
||||
|
||||
to->final_partition = (Partition*) ZOLTAN_MALLOC(len);
|
||||
|
||||
if (!to->final_partition){
|
||||
Zoltan_HSFC_Free_Structure(toZZ);
|
||||
ZOLTAN_PRINT_ERROR(fromZZ->Proc, yo, "Insufficient memory.");
|
||||
return ZOLTAN_MEMERR;
|
||||
}
|
||||
|
||||
memcpy(to->final_partition, from->final_partition, len);
|
||||
}
|
||||
|
||||
return ZOLTAN_OK;
|
||||
}
|
||||
|
||||
/* function to read HSFC parameters: */
|
||||
int Zoltan_HSFC_Set_Param (char *name, char *val)
|
||||
{
|
||||
int index;
|
||||
PARAM_UTYPE result;
|
||||
|
||||
return Zoltan_Check_Param (name, val, HSFC_params, &result, &index);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
static int partition_stats(ZZ *zz, int ndots,
|
||||
Dots *dots, int *obj_sizes,
|
||||
float *work_fraction, int *parts, int *new_parts)
|
||||
{
|
||||
int wgtDim = zz->Obj_Weight_Dim;
|
||||
int proc = zz->Proc;
|
||||
int i, j, max, numParts;
|
||||
double move, gmove, bal, max_imbal, ib;
|
||||
double lwtot, gwtot;
|
||||
double *lpartWgt = NULL;
|
||||
double *gpartWgt = NULL;
|
||||
|
||||
lwtot = 0.0;
|
||||
for (i = 0, max=0; i < ndots; i++){
|
||||
if (new_parts[i] > max) max = new_parts[i];
|
||||
if (wgtDim){
|
||||
lwtot += dots[i * wgtDim].weight;
|
||||
}
|
||||
else{
|
||||
lwtot += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
MPI_Reduce(&lwtot,&gwtot,1,MPI_DOUBLE, MPI_SUM, 0, zz->Communicator);
|
||||
|
||||
MPI_Allreduce(&max,&numParts,1,MPI_INT, MPI_MAX, zz->Communicator);
|
||||
numParts++;
|
||||
|
||||
lpartWgt = (double *)ZOLTAN_CALLOC(numParts, sizeof(double));
|
||||
gpartWgt = (double *)ZOLTAN_MALLOC(numParts * sizeof(double));
|
||||
|
||||
if (numParts && (!lpartWgt || !gpartWgt)){
|
||||
ZOLTAN_FREE(&lpartWgt);
|
||||
ZOLTAN_FREE(&gpartWgt);
|
||||
ZOLTAN_PRINT_ERROR(zz->Proc, "partition_stats", "Insufficient memory.");
|
||||
return ZOLTAN_MEMERR;
|
||||
}
|
||||
|
||||
for (i = 0, j=0, move=0.0; i < ndots; i++, j += wgtDim){
|
||||
if (wgtDim)
|
||||
lpartWgt[new_parts[i]] += (double)dots[j].weight;
|
||||
else
|
||||
lpartWgt[new_parts[i]] += 1.0;
|
||||
|
||||
if (parts[i] != new_parts[i]){
|
||||
if (obj_sizes)
|
||||
move += (double)obj_sizes[i];
|
||||
else
|
||||
move += 1;
|
||||
}
|
||||
}
|
||||
|
||||
MPI_Reduce(lpartWgt, gpartWgt, numParts, MPI_DOUBLE, MPI_SUM,
|
||||
0, zz->Communicator);
|
||||
MPI_Reduce(&move, &gmove, 1, MPI_DOUBLE, MPI_SUM, 0, zz->Communicator);
|
||||
|
||||
ZOLTAN_FREE(&lpartWgt);
|
||||
|
||||
if (proc == 0) {
|
||||
static int nRuns=0;
|
||||
static double balsum, balmax, balmin;
|
||||
static double movesum, movemax, movemin;
|
||||
char *countType;
|
||||
|
||||
max_imbal = 0.0;
|
||||
|
||||
if (gwtot) {
|
||||
for (i = 0; i < numParts; i++){
|
||||
if (work_fraction[i]) {
|
||||
ib= (gpartWgt[i]-work_fraction[i]*gwtot)/(work_fraction[i]*gwtot);
|
||||
if (ib>max_imbal)
|
||||
max_imbal = ib;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bal = 1.0 + max_imbal;
|
||||
|
||||
if (nRuns){
|
||||
if (gmove > movemax) movemax = gmove;
|
||||
if (gmove < movemin) movemin = gmove;
|
||||
if (bal > balmax) balmax = bal;
|
||||
if (bal < balmin) balmin = bal;
|
||||
movesum += gmove;
|
||||
balsum += bal;
|
||||
}
|
||||
else{
|
||||
movemax = movemin = movesum = gmove;
|
||||
balmax = balmin = balsum = bal;
|
||||
}
|
||||
|
||||
countType = "moveCnt";
|
||||
if (obj_sizes){
|
||||
countType = "moveVol";
|
||||
}
|
||||
|
||||
nRuns++;
|
||||
printf(" STATS Runs %d bal CURRENT %f MAX %f MIN %f AVG %f\n",
|
||||
nRuns, bal, balmax, balmin, balsum/nRuns);
|
||||
printf(" STATS Runs %d %s CURRENT %f MAX %f MIN %f AVG %f\n",
|
||||
nRuns, countType, gmove, movemax, movemin, movesum/nRuns);
|
||||
}
|
||||
|
||||
ZOLTAN_FREE(&gpartWgt);
|
||||
MPI_Barrier(zz->Communicator);
|
||||
|
||||
return ZOLTAN_OK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
132
thirdParty/Zoltan/src/hsfc/hsfc.h
vendored
Normal file
132
thirdParty/Zoltan/src/hsfc/hsfc.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifndef ZOLTAN_HSFC_H
|
||||
#define ZOLTAN_HSFC_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "zz_const.h"
|
||||
#include "all_allo_const.h"
|
||||
#include "params_const.h"
|
||||
#include "zoltan_util.h"
|
||||
#include "hsfc_hilbert_const.h"
|
||||
#include "hsfc_const.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Andy's value * 1.6, points on face of bounding box must become interior */
|
||||
static const double HSFC_EPSILON = 1.6e-7;
|
||||
|
||||
/* limit at which bin can't be divided */
|
||||
static const double REFINEMENT_LIMIT = 10.0 * DBL_EPSILON;
|
||||
|
||||
/* when dots have no weight, use this */
|
||||
static const double DEFAULT_WEIGHT = 1.0;
|
||||
|
||||
/* number of "bins per processor", small positive integer */
|
||||
static const int N = 8;
|
||||
|
||||
/* refinement now hitting limit of double precision */
|
||||
static const int MAX_LOOPS = 16;
|
||||
|
||||
|
||||
/* The following are used in determining the max/min hsfc coordinates in
|
||||
a bin, if bin empty */
|
||||
static const double DEFAULT_BIN_MAX = -2.0;
|
||||
static const double DEFAULT_BIN_MIN = 2.0;
|
||||
|
||||
|
||||
#define ZOLTAN_HSFC_ERROR(error,str) {err = error; \
|
||||
ZOLTAN_PRINT_ERROR(zz->Proc, yo, str); goto End;}
|
||||
|
||||
|
||||
typedef struct Partition {
|
||||
double r; /* rightmost boundary of partition interval */
|
||||
double l; /* leftmost boundary of partition interval */
|
||||
int index; /* number of "owner" of data in interval */
|
||||
} Partition; /* interval is half open, [l,r) */
|
||||
|
||||
|
||||
|
||||
typedef struct HSFC_Data {
|
||||
Partition *final_partition;
|
||||
double bbox_hi[3]; /* smallest bounding box, high point */
|
||||
double bbox_lo[3]; /* smallest bounding box, low point */
|
||||
double bbox_extent[3]; /* length of each side of bounding box */
|
||||
int ndimension; /* number of dimensions in problem (2 or 3) */
|
||||
double (*fhsfc)(ZZ*, double*); /* space filling curve function */
|
||||
ZZ_Transform tran; /* transformation for degenerate geometry */
|
||||
} HSFC_Data; /* data preserved for point & box drop later */
|
||||
|
||||
|
||||
|
||||
typedef struct Dots {
|
||||
double fsfc; /* computed normalized SFC coordinate */
|
||||
double x[3]; /* dots coordinates in problem domain */
|
||||
float weight; /* scalar computed from weight vector */
|
||||
int part; /* partition to which dot is assigned */
|
||||
} Dots; /* represents objects being load-balanced */
|
||||
|
||||
|
||||
extern int Zoltan_HSFC_compare (const void *key, const void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
614
thirdParty/Zoltan/src/hsfc/hsfc_box_assign.c
vendored
Normal file
614
thirdParty/Zoltan/src/hsfc/hsfc_box_assign.c
vendored
Normal file
@ -0,0 +1,614 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hsfc.h"
|
||||
#include "zz_const.h"
|
||||
#include "zz_util_const.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/* For a detailed description of the following algorithm, please see the
|
||||
Developers Guide. For instructions on use, please see the Users
|
||||
Guide. This code assumes a 32 bit integer length!!! For a note on
|
||||
increasing the precision see the end of this file. */
|
||||
|
||||
static double next_query_2d (ZZ*, double *lquerybox, double *hquerybox, double);
|
||||
static double next_query_3d (ZZ*, double *lquerybox, double *hquerybox, double);
|
||||
|
||||
|
||||
/* returns list of processors and partitions intersecting the user's query box */
|
||||
int Zoltan_HSFC_Box_Assign (
|
||||
ZZ *zz, double xlo, double ylo, double zlo, /* low query box vertex */
|
||||
double xhi, double yhi, double zhi, /* high query box vertex */
|
||||
int *procs, int *proc_count, int *parts, int *part_count)
|
||||
{
|
||||
double xintl[3], xinth[3]; /* low and high bounded query box */
|
||||
int *part_array = NULL;
|
||||
int *proc_array = NULL;
|
||||
HSFC_Data *d; /* HFSC's portion of Zoltan data structure */
|
||||
int n, i, loop; /* loop counters */
|
||||
int tmp, dim = 0;
|
||||
int first_proc, last_proc;
|
||||
double fsfc, starting;
|
||||
double lo[3], hi[3];
|
||||
Partition *p;
|
||||
const double FUZZY = 1.0e-9; /* to build region about a query point or line */
|
||||
/* Erik suggested that this value be tied to */
|
||||
/* the actual precision available (dimension */
|
||||
/* specific - 2^18 in 3d, 2^27 in 2d. */
|
||||
int err = ZOLTAN_OK;
|
||||
int *remap;
|
||||
char *yo = "Zoltan_HSFC_Box_Assign";
|
||||
|
||||
ZOLTAN_TRACE_ENTER (zz, yo);
|
||||
d = (HSFC_Data *) zz->LB.Data_Structure; /* persistant HSFC data */
|
||||
if (d == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL,
|
||||
"No Decomposition Data available; use KEEP_CUTS parameter.");
|
||||
|
||||
/* allocate memory to store results */
|
||||
*part_count = *proc_count = 0;
|
||||
part_array = (int *) ZOLTAN_MALLOC ((zz->LB.Num_Global_Parts + zz->Num_Proc)
|
||||
* sizeof (int));
|
||||
if (part_array == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_MEMERR, "Memory allocation error.");
|
||||
proc_array = part_array + zz->LB.Num_Global_Parts;
|
||||
memset (part_array, 0, (zz->LB.Num_Global_Parts + zz->Num_Proc)*sizeof (int));
|
||||
|
||||
/* One dimensional case is trival, do it and exit */
|
||||
if (d->ndimension == 1) {
|
||||
remap = zz->LB.Remap; /* Don't let Point_Assign remap IDs.*/
|
||||
zz->LB.Remap = NULL; /* We will do this at "fini". */
|
||||
Zoltan_HSFC_Point_Assign (zz, &xlo, NULL, &n);
|
||||
Zoltan_HSFC_Point_Assign (zz, &xhi, NULL, &loop);
|
||||
for (i = n; i <= loop; i++)
|
||||
part_array[i] = 1;
|
||||
zz->LB.Remap = remap;
|
||||
goto fini;
|
||||
}
|
||||
|
||||
if (d->tran.Target_Dim > 0){ /* It must be 1 or 2 */
|
||||
/*
|
||||
* Degenerate geometry:
|
||||
* Transform query box into coordinates that were used for partitioning,
|
||||
* and place an axis aligned bounding box around it. This box in the new
|
||||
* coordinates may encompass more "dots" than did the original box, but
|
||||
* it won't miss any dots.
|
||||
*/
|
||||
lo[0] = xlo; lo[1] = ylo; lo[2] = zlo;
|
||||
hi[0] = xhi; hi[1] = yhi; hi[2] = zhi;
|
||||
|
||||
Zoltan_Transform_Box(lo, hi, d->tran.Transformation, d->tran.Permutation,
|
||||
d->ndimension, d->tran.Target_Dim);
|
||||
|
||||
xlo = lo[0]; xhi = hi[0];
|
||||
ylo = 0.0; yhi = 0.0;
|
||||
zlo = 0.0; zhi = 0.0;
|
||||
|
||||
if (d->tran.Target_Dim == 2){
|
||||
ylo = lo[1]; yhi = hi[1];
|
||||
dim = d->tran.Target_Dim;
|
||||
}
|
||||
else if (d->tran.Target_Dim == 1){
|
||||
/*
|
||||
* Don't let Point_Assign transform coordinates (we already
|
||||
* did that) or remap partition numbers (we'll do that at "fini").
|
||||
*/
|
||||
dim = d->ndimension;
|
||||
remap = zz->LB.Remap;
|
||||
d->tran.Target_Dim = 0; /* don't transform coordinates */
|
||||
d->ndimension = 1; /* partitions were calculated as 1D */
|
||||
zz->LB.Remap = NULL; /* don't remap partition numbers */
|
||||
Zoltan_HSFC_Point_Assign (zz, &xlo, NULL, &n);
|
||||
Zoltan_HSFC_Point_Assign (zz, &xhi, NULL, &loop);
|
||||
for (i = n; i <= loop; i++) /* loop < n */
|
||||
part_array[i] = 1;
|
||||
d->tran.Target_Dim = 1;
|
||||
d->ndimension = dim;
|
||||
zz->LB.Remap = remap;
|
||||
goto fini;
|
||||
}
|
||||
}
|
||||
else{
|
||||
dim = d->ndimension;
|
||||
}
|
||||
|
||||
/* determine intersection of bounding box and query box */
|
||||
xintl[0] = (xlo - d->bbox_lo[0]) / d->bbox_extent[0];
|
||||
if (xintl[0] < FUZZY) xintl[0] = FUZZY;
|
||||
else if (xintl[0] > 1.0-FUZZY) xintl[0] = 1.0-FUZZY;
|
||||
|
||||
xinth[0] = (xhi - d->bbox_lo[0]) / d->bbox_extent[0];
|
||||
if (xinth[0] < FUZZY) xinth[0] = FUZZY;
|
||||
else if (xinth[0] > 1.0-FUZZY) xinth[0] = 1.0-FUZZY;
|
||||
|
||||
xintl[1] = (ylo - d->bbox_lo[1]) / d->bbox_extent[1];
|
||||
if (xintl[1] < FUZZY) xintl[1] = FUZZY;
|
||||
else if (xintl[1] > 1.0-FUZZY) xintl[1] = 1.0-FUZZY;
|
||||
|
||||
xinth[1] = (yhi - d->bbox_lo[1]) / d->bbox_extent[1];
|
||||
if (xinth[1] < FUZZY) xinth[1] = FUZZY;
|
||||
else if (xinth[1] > 1.0-FUZZY) xinth[1] = 1.0-FUZZY;
|
||||
|
||||
/* application programs need to add "dots" even if query box doesn't actually
|
||||
intersect unit cube. FUZZY forces closest virtual overlap. */
|
||||
if (xinth[0] - xintl[0] < FUZZY) {
|
||||
xintl[0] -= (FUZZY/2.0);
|
||||
xinth[0] += (FUZZY/2.0);
|
||||
}
|
||||
|
||||
if (xinth[1] - xintl[1] < FUZZY) {
|
||||
xintl[1] -= (FUZZY/2.0);
|
||||
xinth[1] += (FUZZY/2.0);
|
||||
}
|
||||
|
||||
if (dim == 2)
|
||||
for (i = 0; i < zz->LB.Num_Global_Parts; i++) {
|
||||
if (d->final_partition[i].l == d->final_partition[i].r)
|
||||
continue; /* ignore empty partitions */
|
||||
|
||||
/* find next query result in range [0.0, 1.0] */
|
||||
starting = (d->final_partition[i].l == 0.0)
|
||||
? 0.0 : (d->final_partition[i].l + FUZZY);
|
||||
fsfc = next_query_2d (zz, xintl, xinth, starting);
|
||||
if (fsfc < 0.0)
|
||||
break; /* done indication, no more partitions to be found */
|
||||
|
||||
/* Find next nonempty partition entering or already in query region */
|
||||
p = (Partition *) bsearch (&fsfc, d->final_partition,
|
||||
zz->LB.Num_Global_Parts, sizeof (Partition), Zoltan_HSFC_compare);
|
||||
if (p == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "programming error, can't happen");
|
||||
if (d->final_partition[p->index].l != d->final_partition[p->index].r)
|
||||
part_array [p->index] = 1; /* mark non empty partitions */
|
||||
i = p->index;
|
||||
}
|
||||
|
||||
if (dim == 3) {
|
||||
/* complete the z axis information, as above */
|
||||
xintl[2] = (zlo - d->bbox_lo[2]) / d->bbox_extent[2];
|
||||
if (xintl[2] < 0.0) xintl[2] = FUZZY;
|
||||
else if (xintl[2] > 1.0) xintl[2] = 1.0-FUZZY;
|
||||
|
||||
xinth[2] = (zhi - d->bbox_lo[2]) / d->bbox_extent[2];
|
||||
if (xinth[2] < 0.0) xinth[2] = FUZZY;
|
||||
else if (xinth[2] > 1.0) xinth[2] = 1.0-FUZZY;
|
||||
|
||||
if (xinth[2] - xintl[2] < FUZZY) {
|
||||
xintl[2] -= (FUZZY/2.0);
|
||||
xinth[2] += (FUZZY/2.0);
|
||||
}
|
||||
|
||||
for (i = 0; i < zz->LB.Num_Global_Parts; i++) {
|
||||
if (d->final_partition[i].l == d->final_partition[i].r)
|
||||
continue; /* ignore empty partition */
|
||||
|
||||
/* find next query result in range [0.0. 1.0] */
|
||||
starting = (d->final_partition[i].l == 0.0)
|
||||
? 0.0 : (d->final_partition[i].l + FUZZY);
|
||||
fsfc = next_query_3d (zz, xintl, xinth, starting);
|
||||
if (fsfc < 0.0)
|
||||
break; /* done, no more to be found */
|
||||
|
||||
/* Find partition containing point and return its number */
|
||||
p = (Partition *) bsearch (&fsfc, d->final_partition,
|
||||
zz->LB.Num_Global_Parts, sizeof (Partition), Zoltan_HSFC_compare);
|
||||
if (p == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "programming error, can't happen");
|
||||
if (d->final_partition[p->index].l != d->final_partition[p->index].r)
|
||||
part_array [p->index] = 1; /* ignore empty partitions */
|
||||
i = p->index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* move results to user supplied arrays & hope they are big enough */
|
||||
fini:
|
||||
*part_count = 0;
|
||||
if (parts) {
|
||||
*part_count = 0;
|
||||
for (i = 0; i < zz->LB.Num_Global_Parts; i++)
|
||||
if (part_array[i] > 0) {
|
||||
if (zz->LB.Remap)
|
||||
parts[(*part_count)++] = zz->LB.Remap[i];
|
||||
else
|
||||
parts[(*part_count)++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (procs) {
|
||||
for (i = 0; i < zz->LB.Num_Global_Parts; i++)
|
||||
if (part_array[i] > 0) {
|
||||
tmp = (zz->LB.Remap ? zz->LB.Remap[i] : i);
|
||||
first_proc = Zoltan_LB_Part_To_Proc(zz, tmp, NULL);
|
||||
proc_array[first_proc] = 1;
|
||||
if (!zz->LB.Single_Proc_Per_Part) {
|
||||
/* Part may be spread across multiple procs. Include them all. */
|
||||
int j;
|
||||
if (tmp < zz->LB.Num_Global_Parts - 1)
|
||||
last_proc = Zoltan_LB_Part_To_Proc (zz, tmp + 1, NULL);
|
||||
else
|
||||
last_proc = zz->Num_Proc;
|
||||
|
||||
for (j = first_proc + 1; j < last_proc; j++)
|
||||
proc_array[j] = 1;
|
||||
}
|
||||
}
|
||||
*proc_count = 0;
|
||||
for (i = 0; i < zz->Num_Proc; i++)
|
||||
if (proc_array[i] > 0)
|
||||
procs[(*proc_count)++] = i;
|
||||
}
|
||||
|
||||
End:
|
||||
ZOLTAN_FREE (&part_array);
|
||||
ZOLTAN_TRACE_EXIT (zz, yo);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns the first Hilbert coordinate in [s,1] to enter the user's query box */
|
||||
static double next_query_2d (ZZ *zz, double *lquerybox, double *hquerybox,
|
||||
double s)
|
||||
{
|
||||
int state, newstate=0, savelevel, prune, backtrack;
|
||||
unsigned int temp, x, y;
|
||||
unsigned int savestate=0, savequad=0, savenpt=0; /* saved info for backtracking */
|
||||
unsigned int qlox, qloy, qhix, qhiy; /* query box bounds */
|
||||
unsigned int nptx, npty, keyx, keyy, newnpt=0;
|
||||
unsigned int start[2], startbits=0;
|
||||
unsigned int intersect_hi, intersect_lo;
|
||||
double t;
|
||||
unsigned i, level, quadrant; /* loop counters */
|
||||
static const unsigned int *dk[]
|
||||
= {data2d, data2d +4, data2d +8, data2d +12};
|
||||
static const unsigned int *st[]
|
||||
= {state2d, state2d +4, state2d +8, state2d +12};
|
||||
static const unsigned int MAXLEVEL = 28; /* only 56 significant bits, 28 per dimension */
|
||||
|
||||
/* convert floating normalized, intersected query box corners to integers */
|
||||
qlox = (unsigned int) (lquerybox[0] * (double) IMAX);
|
||||
qloy = (unsigned int) (lquerybox[1] * (double) IMAX);
|
||||
qhix = (unsigned int) (hquerybox[0] * (double) IMAX);
|
||||
qhiy = (unsigned int) (hquerybox[1] * (double) IMAX);
|
||||
|
||||
/* convert floating minimum query hilbert coordinate to integer */
|
||||
start[1] = (unsigned int) (modf (s * (double) IMAX, &t) * (double) IMAX);
|
||||
start[0] = (unsigned int) t;
|
||||
|
||||
/* initializations before starting main loop */
|
||||
state = 0;
|
||||
prune = 1;
|
||||
backtrack = 1;
|
||||
savelevel = -1;
|
||||
nptx = npty = 0;
|
||||
keyx = keyy = 0;
|
||||
|
||||
/* now loop over each level of hilbert curve refinement */
|
||||
for (level = 0; level < MAXLEVEL; level++) {
|
||||
if (prune) {
|
||||
/* get next 2 bits of start for pruning from its shift register */
|
||||
startbits = start[0] >> 30; /* extract top two bits */
|
||||
start[0] = (start[0] << 2) | (start[1] >> 30); /* shift hi word */
|
||||
start[1] = start[1] << 2; /* shift lo word */
|
||||
}
|
||||
|
||||
/* compute current search space intersected with the query region */
|
||||
temp = IMAX >> level; /* top of range ends in all 1 bits */
|
||||
x = ((nptx | temp) > qhix) ? qhix : (nptx | temp);
|
||||
y = ((npty | temp) > qhiy) ? qhiy : (npty | temp);
|
||||
intersect_hi = (((x >> (30-level)) & 2) | ((y >> (31-level)) & 1));
|
||||
|
||||
temp = ~temp; /* bottom of range ends in all 0 bits */
|
||||
x = ((nptx & temp) < qlox) ? qlox : (nptx & temp);
|
||||
y = ((npty & temp) < qloy) ? qloy : (npty & temp);
|
||||
intersect_lo = (((x >> (30-level)) & 2) | ((y >> (31-level)) & 1));
|
||||
|
||||
/* loop over subquadrants in hilbert curve order to find lowest numbered
|
||||
quad that intersects with query region and is larger than start key */
|
||||
temp = (prune) ? startbits : 0;
|
||||
for (quadrant = temp; quadrant < 4; quadrant++) {
|
||||
newnpt = *(dk[state] + quadrant); /* get new 2 bit npt value */
|
||||
if (!((newnpt ^ intersect_hi) & (newnpt ^ intersect_lo)))
|
||||
break; /* successfully found intersecting quadrant at this level */
|
||||
}
|
||||
if (quadrant < 4) {
|
||||
newstate = *(st[state] + quadrant);
|
||||
if (prune && (quadrant > startbits))
|
||||
prune = 0; /* no more pruning required */
|
||||
}
|
||||
|
||||
/* determine backtracking point, in case backtracking is needed */
|
||||
if (backtrack)
|
||||
for (i = quadrant+1; i < 4; i++) {
|
||||
/* intersect test - subquad intersecting with search/query region */
|
||||
temp = *(dk[state] + i); /* get new npt */
|
||||
if (!((temp ^ intersect_hi) & (temp ^ intersect_lo))) {
|
||||
savelevel = level;
|
||||
savestate = *(st[state] + i);
|
||||
savenpt = temp;
|
||||
savequad = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* test if this round was successful (quadrant < 4), backtrack if not */
|
||||
if (quadrant == 4) {
|
||||
if (savelevel == -1)
|
||||
return -1.0; /* report that no solution is available */
|
||||
|
||||
/* restore all conditions to backtrack point */
|
||||
level = savelevel;
|
||||
newstate = savestate;
|
||||
newnpt = savenpt;
|
||||
quadrant = savequad;
|
||||
prune = 0; /* no longer need to prune previous branches */
|
||||
backtrack = 0; /* only 1 backtrack ever required, now done */
|
||||
|
||||
/* discard results below backtrack level */
|
||||
keyx &= ~(IMAX >> savelevel);
|
||||
keyy &= ~(IMAX >> savelevel);
|
||||
|
||||
nptx &= ~(IMAX >> savelevel);
|
||||
nptx &= ~(IMAX >> savelevel);
|
||||
}
|
||||
|
||||
/* append current derived key and npoint to cumulative total */
|
||||
keyx |= ((quadrant & 2) << (30-level));
|
||||
keyy |= ((quadrant & 1) << (31-level));
|
||||
|
||||
nptx |= ((newnpt & 2) << (30-level));
|
||||
npty |= ((newnpt & 1) << (31-level));
|
||||
|
||||
state = newstate;
|
||||
}
|
||||
|
||||
/* now convert final derived key to floating point representation and exit */
|
||||
start[0] = start[1] = 0;
|
||||
for (i = 0; i < MAXLEVEL; i++) {
|
||||
start[0] = (start[0] << 2) | (start[1] >> 30);
|
||||
start[1] = (start[1] << 2) | ((keyx >> (30-i)) & 2)
|
||||
| ((keyy >> (31-i)) & 1);
|
||||
}
|
||||
return ldexp ((double) start[0], -24) + ldexp((double) start[1], -56);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns the first Hilbert coordinate in [s,1] to enter the user's query box */
|
||||
static double next_query_3d (ZZ *zz, double *lquerybox, double *hquerybox,
|
||||
double s)
|
||||
{
|
||||
int state, newstate = 0, savelevel, prune, backtrack;
|
||||
unsigned int temp, x, y, z;
|
||||
unsigned int savestate = 0, savequad = 0, savenpt = 0;
|
||||
unsigned int qlox, qloy, qloz, qhix, qhiy, qhiz;
|
||||
unsigned int nptx, npty, nptz, keyx, keyy, keyz, newnpt = 0;
|
||||
unsigned int start[2], startbits = 0;
|
||||
unsigned int intersect_hi, intersect_lo;
|
||||
double t;
|
||||
unsigned i, quadrant, level;
|
||||
static const unsigned int *dk[] =
|
||||
{data3d, data3d +8, data3d +16, data3d +24,
|
||||
data3d +32, data3d +40, data3d +48, data3d +56,
|
||||
data3d +64, data3d +72, data3d +80, data3d +88,
|
||||
data3d +96, data3d +104, data3d +112, data3d +120,
|
||||
data3d +128, data3d +136, data3d +144, data3d +152,
|
||||
data3d +160, data3d +168, data3d +176, data3d +184};
|
||||
|
||||
static const unsigned int *st[] =
|
||||
{state3d, state3d +8, state3d +16, state3d +24,
|
||||
state3d +32, state3d +40, state3d +48, state3d +56,
|
||||
state3d +64, state3d +72, state3d +80, state3d +88,
|
||||
state3d +96, state3d +104, state3d +112, state3d +120,
|
||||
state3d +128, state3d +136, state3d +144, state3d +152,
|
||||
state3d +160, state3d +168, state3d +176, state3d +184};
|
||||
|
||||
static const unsigned int MAXLEVEL = 18; /* only 56 significant bits, 18 per dimension */
|
||||
|
||||
/* convert floating query box corners to integers */
|
||||
qlox = (unsigned int) (lquerybox[0] * (double) IMAX);
|
||||
qloy = (unsigned int) (lquerybox[1] * (double) IMAX);
|
||||
qloz = (unsigned int) (lquerybox[2] * (double) IMAX);
|
||||
|
||||
qhix = (unsigned int) (hquerybox[0] * (double) IMAX);
|
||||
qhiy = (unsigned int) (hquerybox[1] * (double) IMAX);
|
||||
qhiz = (unsigned int) (hquerybox[2] * (double) IMAX);
|
||||
|
||||
/* convert floating minimum query hilbert coordinate to integer */
|
||||
start[1] = (unsigned int) (modf (s * (double) IMAX, &t) * (double) IMAX);
|
||||
start[0] = (unsigned int) t;
|
||||
|
||||
/* initializations before main loop */
|
||||
state = 0;
|
||||
prune = 1;
|
||||
backtrack = 1;
|
||||
savelevel = -1;
|
||||
nptx = npty = nptz = 0;
|
||||
keyx = keyy = keyz = 0;
|
||||
|
||||
/* now loop over each level of hilbert curve refinement */
|
||||
for (level = 0; level < MAXLEVEL; level++) {
|
||||
if (prune) {
|
||||
/* get next 3 bits of start for pruning, treat as shift register */
|
||||
startbits = start[0] >> 29; /* extract top two bits */
|
||||
start[0] = (start[0] << 3) | (start[1] >> 29); /* shift hi word */
|
||||
start[1] = start[1] << 3; /* shift lo word */
|
||||
}
|
||||
|
||||
/* compute current search space intersected with the query region */
|
||||
temp = IMAX >> level; /* top of range ends in all 1 bits */
|
||||
x = ((nptx | temp) > qhix) ? qhix : (nptx | temp);
|
||||
y = ((npty | temp) > qhiy) ? qhiy : (npty | temp);
|
||||
z = ((nptz | temp) > qhiz) ? qhiz : (nptz | temp);
|
||||
intersect_hi = ((x >> (29-level)) & 4)
|
||||
| ((y >> (30-level)) & 2)
|
||||
| ((z >> (31-level)) & 1);
|
||||
|
||||
temp = ~temp; /* bottom of range ends in all 0 bits */
|
||||
x = ((nptx & temp) < qlox) ? qlox : (nptx & temp);
|
||||
y = ((npty & temp) < qloy) ? qloy : (npty & temp);
|
||||
z = ((nptz & temp) < qloz) ? qloz : (nptz & temp);
|
||||
intersect_lo = ((x >> (29-level)) & 4)
|
||||
| ((y >> (30-level)) & 2)
|
||||
| ((z >> (31-level)) & 1);
|
||||
|
||||
/* loop over subquadrants in hilbert curve order to find lowest numbered
|
||||
quad that intersects with query region and is larger than start key */
|
||||
temp = (prune) ? startbits : 0;
|
||||
for (quadrant = temp; quadrant < 8; quadrant++) {
|
||||
newnpt = *(dk[state] + quadrant); /* get new 3 bit npt value */
|
||||
if (!((newnpt ^ intersect_hi) & (newnpt ^ intersect_lo)))
|
||||
break; /* successfully found intersecting quadrant at this level */
|
||||
}
|
||||
if (quadrant < 8) {
|
||||
newstate = *(st[state] + quadrant);
|
||||
if (prune && (quadrant > startbits))
|
||||
prune = 0; /* no more pruning required */
|
||||
}
|
||||
|
||||
/* determine backtracking point, in case backtracking is needed */
|
||||
if (backtrack)
|
||||
for (i = quadrant+1; i < 8; i++) {
|
||||
temp = *(dk[state] + i); /* get new npt */
|
||||
|
||||
/* intersect test - subquad intersecting with search/query region */
|
||||
if (!((temp ^ intersect_hi) & (temp ^ intersect_lo))) {
|
||||
savelevel = level;
|
||||
savestate = *(st[state] + i);
|
||||
savenpt = temp;
|
||||
savequad = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* test if this round was successful (quadrant < 8), backtrack if not */
|
||||
if (quadrant == 8) {
|
||||
if (savelevel == -1)
|
||||
return -1.0; /* no solution available, report failure */
|
||||
|
||||
/* restore all conditions to backtrack point */
|
||||
level = savelevel;
|
||||
newstate = savestate;
|
||||
newnpt = savenpt;
|
||||
quadrant = savequad;
|
||||
prune = 0; /* no longer need to prune previous branches */
|
||||
backtrack = 0; /* only 1 backtrack ever required, now done */
|
||||
|
||||
/* discard results below backtrack level */
|
||||
keyx &= ~(IMAX >> savelevel);
|
||||
keyy &= ~(IMAX >> savelevel);
|
||||
keyz &= ~(IMAX >> savelevel);
|
||||
|
||||
nptx &= ~(IMAX >> savelevel);
|
||||
npty &= ~(IMAX >> savelevel);
|
||||
nptz &= ~(IMAX >> savelevel);
|
||||
}
|
||||
|
||||
/* append current derived key and npoint to cumulative total */
|
||||
state = newstate;
|
||||
|
||||
keyx |= ((quadrant & 4) << (29-level));
|
||||
keyy |= ((quadrant & 2) << (30-level));
|
||||
keyz |= ((quadrant & 1) << (31-level));
|
||||
|
||||
nptx |= ((newnpt & 4) << (29-level));
|
||||
npty |= ((newnpt & 2) << (30-level));
|
||||
nptz |= ((newnpt & 1) << (31-level));
|
||||
}
|
||||
|
||||
/* now convert final derived key to floating point representation and exit */
|
||||
start[0] = start[1] = 0;
|
||||
for (i = 0; i < MAXLEVEL; i++) {
|
||||
start[0] = (start[0] << 3) | (start[1] >> 29);
|
||||
start[1] = (start[1] << 3) | ((keyx >> (29-i)) & 4)
|
||||
| ((keyy >> (30-i)) & 2)
|
||||
| ((keyz >> (31-i)) & 1);
|
||||
}
|
||||
return ldexp ((double) start[0], -22) + ldexp((double) start[1], -54);
|
||||
}
|
||||
|
||||
|
||||
/* Maintenance Note: Per the review 04.15.03, the following section addresses
|
||||
increasing the precision of this box assign.
|
||||
|
||||
The next_query_xx() routines can be extended to arbitrary precision. Currently
|
||||
they reflect the precision limitation of using a double for the starting
|
||||
Hilbert coordinate and the returned value:
|
||||
static double next_query_3d (ZZ *zz, double *lquerybox, double *hquerybox,
|
||||
double s)
|
||||
Change this to:
|
||||
static int* next_query_3d (ZZ *zz, double *lquerybox, double *hquerybox,
|
||||
int *start).
|
||||
Represent the Hilbert coordinate as an array of ints (2 for 2d, 3 for 3d) rather
|
||||
than the double representation currently used.
|
||||
Change the declaration:
|
||||
static const int MAXLEVEL = 18; (3d or 28 in 2d)
|
||||
to
|
||||
static const int MAXLEVEL = 32;
|
||||
Change the return statement:
|
||||
return ldexp ((double) start[0], -22) + ldexp((double) start[1], -54);
|
||||
to
|
||||
return start;
|
||||
|
||||
Please see the related remarks in the file hsfc_hilbert.c.
|
||||
|
||||
The last change is to replace the criteria for the binary lookup of a hilbert
|
||||
coordinate to find its partition to use the int arrays rather than double.
|
||||
This requires a trivial change to hsfc.c to use int arrays for the hilbert
|
||||
coordinate as well.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
64
thirdParty/Zoltan/src/hsfc/hsfc_const.h
vendored
Normal file
64
thirdParty/Zoltan/src/hsfc/hsfc_const.h
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifndef ZOLTAN_HSFC_CONST_H
|
||||
#define ZOLTAN_HSFC_CONST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
int Zoltan_HSFC_Set_Param (char *name, char *val) ;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
332
thirdParty/Zoltan/src/hsfc/hsfc_hilbert.c
vendored
Normal file
332
thirdParty/Zoltan/src/hsfc/hsfc_hilbert.c
vendored
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "hsfc_hilbert_const.h" /* contains state tables and documentation */
|
||||
#include "hsfc.h"
|
||||
#include "zz_const.h"
|
||||
|
||||
/* see maintenance note at the end of this file for information about extending
|
||||
the precision of these routines. */
|
||||
|
||||
/* Given a 1-d coordinate in [0,1], returns it as the Hilbert key) */
|
||||
double Zoltan_HSFC_InvHilbert1d (ZZ *zz, double *coord)
|
||||
{
|
||||
char *yo = "Zoltan_HSFC_InvHilbert1d";
|
||||
|
||||
/* sanity check for input arguments */
|
||||
if (coord[0] < 0.0)
|
||||
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Spatial Coordinates out of range.");
|
||||
|
||||
return *coord;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given x,y coordinates in [0,1]x[0,1], returns the Hilbert key [0,1] */
|
||||
double Zoltan_HSFC_InvHilbert2d (ZZ *zz, double *coord)
|
||||
{
|
||||
static const unsigned *d[]={idata2d, idata2d +4, idata2d +8, idata2d +12};
|
||||
static const unsigned *s[]={istate2d, istate2d +4, istate2d +8, istate2d +12};
|
||||
|
||||
int level;
|
||||
unsigned int key[2], c[2], temp, state;
|
||||
const int MAXLEVEL = 28; /* 56 bits of significance, 28 per dimension */
|
||||
char *yo = "Zoltan_HSFC_InvHilbert2d";
|
||||
|
||||
/* sanity check for input arguments */
|
||||
if ((coord[0] < 0.0) || (coord[0] > 1.0) || (coord[1] < 0.0)
|
||||
|| (coord[1] > 1.0))
|
||||
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Spatial Coordinates out of range.");
|
||||
|
||||
/* convert x,y coordinates to integers in range [0, IMAX] */
|
||||
c[0] = (unsigned int) (coord[0] * (double) IMAX); /* x */
|
||||
c[1] = (unsigned int) (coord[1] * (double) IMAX); /* y */
|
||||
|
||||
/* use state tables to convert nested quadrant's coordinates level by level */
|
||||
key[0] = key[1] = 0;
|
||||
state = 0;
|
||||
for (level = 0; level < MAXLEVEL; level++) {
|
||||
temp = ((c[0] >> (30-level)) & 2) /* extract 2 bits at current level */
|
||||
| ((c[1] >> (31-level)) & 1);
|
||||
|
||||
/* treat key[] as long shift register, shift in converted coordinate */
|
||||
key[0] = (key[0] << 2) | (key[1] >> 30);
|
||||
key[1] = (key[1] << 2) | *(d[state] + temp);
|
||||
|
||||
state = *(s[state] + temp);
|
||||
}
|
||||
|
||||
/* convert 2 part Hilbert key to double and return */
|
||||
return ldexp ((double) key[0], -24) + ldexp ((double) key[1], -56);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given x,y,z coordinates in [0,1]x[0,1]x[0,1], returns Hilbert key in [0,1] */
|
||||
double Zoltan_HSFC_InvHilbert3d (ZZ *zz, double *coord)
|
||||
{
|
||||
static const unsigned int *d[] =
|
||||
{idata3d, idata3d +8, idata3d +16, idata3d +24,
|
||||
idata3d +32, idata3d +40, idata3d +48, idata3d +56,
|
||||
idata3d +64, idata3d +72, idata3d +80, idata3d +88,
|
||||
idata3d +96, idata3d +104, idata3d +112, idata3d +120,
|
||||
idata3d +128, idata3d +136, idata3d +144, idata3d +152,
|
||||
idata3d +160, idata3d +168, idata3d +176, idata3d +184};
|
||||
|
||||
static const unsigned int *s[] =
|
||||
{istate3d, istate3d +8, istate3d +16, istate3d +24,
|
||||
istate3d +32, istate3d +40, istate3d +48, istate3d +56,
|
||||
istate3d +64, istate3d +72, istate3d +80, istate3d +88,
|
||||
istate3d +96, istate3d +104, istate3d +112, istate3d +120,
|
||||
istate3d +128, istate3d +136, istate3d +144, istate3d +152,
|
||||
istate3d +160, istate3d +168, istate3d +176, istate3d +184};
|
||||
|
||||
int level;
|
||||
unsigned int key[2], c[3], temp, state;
|
||||
const int MAXLEVEL = 19; /* 56 bits of significance, 18+ per dimension */
|
||||
char *yo = "Zoltan_HSFC_InvHilbert3d";
|
||||
|
||||
/* sanity check for input arguments */
|
||||
if ((coord[0] < 0.0) || (coord[0] > 1.0) || (coord[1] < 0.0)
|
||||
|| (coord[1] > 1.0) || (coord[2] < 0.0) || (coord[2] > 1.0))
|
||||
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Spatial Coordinates out of range.");
|
||||
|
||||
/* convert x,y,z coordinates to integers in range [0,IMAX] */
|
||||
c[0] = (unsigned int) (coord[0] * (double) IMAX); /* x */
|
||||
c[1] = (unsigned int) (coord[1] * (double) IMAX); /* y */
|
||||
c[2] = (unsigned int) (coord[2] * (double) IMAX); /* z */
|
||||
|
||||
/* use state tables to convert nested quadrant's coordinates level by level */
|
||||
key[0] = key[1] = 0;
|
||||
state = 0;
|
||||
for (level = 0; level < MAXLEVEL; level++) {
|
||||
temp = ((c[0] >> (29-level)) & 4) /* extract 3 bits at current level */
|
||||
| ((c[1] >> (30-level)) & 2)
|
||||
| ((c[2] >> (31-level)) & 1);
|
||||
|
||||
/* treat key[] as long shift register, shift in converted coordinate */
|
||||
key[0] = (key[0] << 3) | (key[1] >> 29);
|
||||
key[1] = (key[1] << 3) | *(d[state] + temp);
|
||||
|
||||
state = *(s[state] + temp);
|
||||
}
|
||||
|
||||
/* convert 2 part Hilbert key to double and return */
|
||||
return ldexp ((double) key[0], -25) + ldexp ((double) key[1], -57);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Note: the following code has been tested and is fine. It was necessary
|
||||
during the testing for the new box assign algorithm. Since it is potentially
|
||||
useful, I am leaving this code intact, but ifdef'ing it out because of the
|
||||
SQA coverage requirement. */
|
||||
|
||||
#ifdef RTHRTH
|
||||
/* Given the Hilbert key, returns it as the coordinate in [0,1] */
|
||||
void Zoltan_HSFC_Hilbert1d (ZZ *zz, double *coord, double key)
|
||||
{
|
||||
char *yo = "Zoltan_HSFC_Hilbert1d";
|
||||
|
||||
/* sanity check for input argument */
|
||||
if ((key < 0.0) || (key > 1.0))
|
||||
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Hilbert coordinate out of range.");
|
||||
|
||||
*coord = key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given the Hilbert key, returns the 2-d coordinates in [0,1]x[0,1] */
|
||||
void Zoltan_HSFC_Hilbert2d (ZZ *zz, double *coord, double key)
|
||||
{
|
||||
static const unsigned *d[] = {data2d, data2d +4, data2d +8, data2d +12};
|
||||
static const unsigned *s[] = {state2d, state2d +4, state2d +8, state2d +12};
|
||||
int level, state;
|
||||
unsigned int c[2], ikey[2], temp;
|
||||
double t;
|
||||
static const int MAXLEVEL = 28; /* only 56 significant bits, 28 per dimension */
|
||||
char *yo = "Zoltan_HSFC_Hilbert2d";
|
||||
|
||||
/* sanity check for input argument */
|
||||
if ((key < 0.0) || (key > 1.0))
|
||||
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Hilbert coordinate out of range.");
|
||||
|
||||
ikey[1] = (unsigned int) (modf (key * (double) IMAX, &t) * (double) IMAX);
|
||||
ikey[0] = (unsigned int) t;
|
||||
|
||||
/* use state tables to convert nested quadrant's coordinates level by level */
|
||||
c[0] = c[1] = 0;
|
||||
state = 0;
|
||||
for (level = 0; level < MAXLEVEL; level++) {
|
||||
temp = *(d[state] + (ikey[0] >> 30)); /* 2 bits: xy */
|
||||
state = *(s[state] + (ikey[0] >> 30));
|
||||
|
||||
c[0] |= ((temp & 2) << (30-level)); /* insert x bit */
|
||||
c[1] |= ((temp & 1) << (31-level)); /* insert y bit */
|
||||
|
||||
/* treating ikey[] as shift register, shift next 2 bits in place */
|
||||
ikey[0] = (ikey[0] << 2) | (ikey[1] >> 30);
|
||||
ikey[1] = ikey[1] << 2;
|
||||
}
|
||||
|
||||
/* convert integer coordinates to doubles */
|
||||
coord[0] = (double) c[0] / (double) IMAX; /* x in [0,1] */
|
||||
coord[1] = (double) c[1] / (double) IMAX; /* y in [0,1] */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given the Hilbert key, returns the 3-d coordinates in [0,1]x[0,1]x[0,1] */
|
||||
void Zoltan_HSFC_Hilbert3d (ZZ *zz, double *coord, double key)
|
||||
{
|
||||
static const unsigned int *d[] =
|
||||
{data3d, data3d +8, data3d +16, data3d +24,
|
||||
data3d +32, data3d +40, data3d +48, data3d +56,
|
||||
data3d +64, data3d +72, data3d +80, data3d +88,
|
||||
data3d +96, data3d +104, data3d +112, data3d +120,
|
||||
data3d +128, data3d +136, data3d +144, data3d +152,
|
||||
data3d +160, data3d +168, data3d +176, data3d +184};
|
||||
|
||||
static const unsigned int *s[] =
|
||||
{state3d, state3d +8, state3d +16, state3d +24,
|
||||
state3d +32, state3d +40, state3d +48, state3d +56,
|
||||
state3d +64, state3d +72, state3d +80, state3d +88,
|
||||
state3d +96, state3d +104, state3d +112, state3d +120,
|
||||
state3d +128, state3d +136, state3d +144, state3d +152,
|
||||
state3d +160, state3d +168, state3d +176, state3d +184};
|
||||
|
||||
int level, state;
|
||||
unsigned int c[3], ikey[2], temp;
|
||||
double t;
|
||||
static const int MAXLEVEL = 19; /* 56 significant bits, 18+ per dimension */
|
||||
char *yo = "Zoltan_HSFC_Hilbert3d";
|
||||
|
||||
/* sanity check for input argument */
|
||||
if ((key < 0.0) || (key > 1.0))
|
||||
ZOLTAN_PRINT_ERROR (zz->Proc, yo, "Hilbert coordinate out of range.");
|
||||
|
||||
ikey[1] = (unsigned int) (modf (key * (double) IMAX, &t) * (double) IMAX);
|
||||
ikey[0] = (unsigned int) t;
|
||||
|
||||
/* use state tables to convert nested quadrant's coordinates level by level */
|
||||
c[0] = c[1] = c[2] = 0;
|
||||
state = 0;
|
||||
for (level = 0; level < MAXLEVEL; level++) {
|
||||
temp = *(d[state] + (ikey[0] >> 29)); /* get next 3 bits: xyz */
|
||||
state = *(s[state] + (ikey[0] >> 29));
|
||||
|
||||
c[0] |= ((temp & 4) << (29-level)); /* insert x bit */
|
||||
c[1] |= ((temp & 2) << (30-level)); /* insert y bit */
|
||||
c[2] |= ((temp & 1) << (31-level)); /* insert z bit */
|
||||
|
||||
/* treating ikey[] as shift register, shift next 3 bits in place */
|
||||
ikey[0] = (ikey[0] << 3) | (ikey[1] >> 29);
|
||||
ikey[1] = ikey[1] << 3;
|
||||
}
|
||||
|
||||
/* convert coordinates to doubles */
|
||||
coord[0] = (double) c[0] / (double) IMAX; /* x in [0,1] */
|
||||
coord[1] = (double) c[1] / (double) IMAX; /* y in [0,1] */
|
||||
coord[2] = (double) c[2] / (double) IMAX; /* z in [0,1] */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* MAINTENANCE NOTE: Per the design review 04/15/03, this section discusses
|
||||
how to increase the precision of the routines in this file. The table driven
|
||||
logic can be extended to arbitrary precision. Currently, these routines only
|
||||
take or return the precision of a double.
|
||||
|
||||
First, consider how to extend the Zoltan_HSFC_InvHilbertxx() routines to return
|
||||
the full precision for the 2 or 3 dimensional input:
|
||||
The statement
|
||||
c[0] = (unsigned int) (coord[0] * (double) IMAX); (etc. for each dimension)
|
||||
returns about 32 bits of usable information per dimension.
|
||||
Change the declaration:
|
||||
const int MAXLEVEL = 28;
|
||||
to
|
||||
const int MAXLEVEL = 32;
|
||||
Then the key array contains 64 bits in 2d or 96 bits in 3d. Change its
|
||||
declaration to either 2 or 3 ints as appropriate.
|
||||
The easiest thing is to modify the routine to return the key array itself to
|
||||
preserve the maximum precision. This requires changing the function definition:
|
||||
double Zoltan_HSFC_InvHilbert2d (ZZ *zz, double *coord)
|
||||
to
|
||||
int *Zoltan_HSFC_InvHilbert2d (ZZ *zz, double *coord).
|
||||
and changing the return statement:
|
||||
return ldexp ((double) key[0], -24) + ldexp ((double) key[1], -56);
|
||||
to
|
||||
return key;
|
||||
|
||||
|
||||
Second, consider how to extend the Zoltan_HSFC_Hilbertxx() routines. If the key
|
||||
array is used as the return argument above, then these Hilbertxx routines should
|
||||
be modified to accept the key array as the Hilbert coordinate rather than the
|
||||
current double. This requires changing the function definition:
|
||||
void Zoltan_HSFC_Hilbert2d (ZZ *zz, double *coord, double key)
|
||||
to
|
||||
void Zoltan_HSFC_Hilbert2d (ZZ *zz, double *coord, int* ikey)
|
||||
Change the declaration
|
||||
static const int MAXLEVEL = 28; (2d or 19 in 3d)
|
||||
to
|
||||
static const int MAXLEVEL = 32;
|
||||
Eliminate the lines that convert the orginal double arguement of key to ikey.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
||||
|
244
thirdParty/Zoltan/src/hsfc/hsfc_hilbert_const.h
vendored
Normal file
244
thirdParty/Zoltan/src/hsfc/hsfc_hilbert_const.h
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifndef __HSFC_HILBERT_CONST_H
|
||||
#define __HSFC_HILBERT_CONST_H
|
||||
|
||||
#include "zz_const.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* The modules and data arrays in hsfc_hilbert.c and hsfc_box_assign.c are
|
||||
* influenced by a series of papers:
|
||||
* "Load balancing for the parallel adaptive solution of partial differential
|
||||
* equations", 1994, deCougny, Devine, Flaherty, Loy, Ozturan, Shephard
|
||||
* "Adaptive Local Refinement with Octree Load-Balancing for the parallel
|
||||
* solution of three-dimensional conservation laws", 1998, Loy, (Ph.D.)
|
||||
* "The Performance of an Octree Load Balancer for Parallel Adaptive Finite
|
||||
* Element Computation", 2001, Campbell
|
||||
* "Using State Diagrams for Hilbert Curve Mappings", Lawder, 2000
|
||||
* "Querying Multi-demensional Data Indexed Using the Hilbert Space-Filling
|
||||
* Curve", Lawder, King, 2000
|
||||
* "Calculation of Mappings between One and n-dimensional Values Using the
|
||||
* Hilbert Space-filling Curve", Lawder, 2000
|
||||
* "Using Space-filling Curves for Multi-dimensional Indexing", Lawder, King,
|
||||
* 2000
|
||||
*
|
||||
* A useful reference discussing the Hilbert curve for spatial data indexing,
|
||||
* data queries, etc. is "Fundamentals of Spatial Information Systems, 1992,
|
||||
* Laurini, Thompson.
|
||||
*
|
||||
* Useful code examples for the generation of Hilbert and Inverse Hilbert
|
||||
* coordinates came from Octree (in above papers) also using state tables,
|
||||
* H. Carter Edwards (1997), (Ph.D. dissertation, code copyrighted 1997),
|
||||
* Doug Moore, Rice University (copyrighted 1998-2000) whose code also
|
||||
* includes an implimenation of a query search for box like regions in the
|
||||
* Hilbert space as well as other database oriented functions.
|
||||
*
|
||||
* This code is closest in spirit to Lawder, but with significant differences:
|
||||
* octree state tables modified to match existing HSFC direction
|
||||
* (Note, Lawder tables are incorrect!),
|
||||
* no binary search, greatly simplifing the test for intersection,
|
||||
* backtracking does not explicitly work backwards up the tree,
|
||||
* query region and search region intersection calculated fresh at each level,
|
||||
* partitioning rather than database application.
|
||||
* (Note, no code examples were available in Lawder's publications, so this
|
||||
* is an original adaptation.)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
static unsigned const int IMAX = ~(0U);
|
||||
|
||||
|
||||
|
||||
static unsigned const int idata2d[] = /* 2 dimension to nkey conversion */
|
||||
{0, 3, 1, 2,
|
||||
0, 1, 3, 2,
|
||||
2, 3, 1, 0,
|
||||
2, 1, 3, 0};
|
||||
|
||||
static unsigned const int istate2d[] = /* 2 dimension to nkey state transitions */
|
||||
{1, 2, 0, 0,
|
||||
0, 1, 3, 1,
|
||||
2, 0, 2, 3,
|
||||
3, 3, 1, 2};
|
||||
|
||||
static unsigned const int data2d[] = /* nkey to 2 dimension conversion */
|
||||
{0, 2, 3, 1,
|
||||
0, 1, 3, 2,
|
||||
3, 2, 0, 1,
|
||||
3, 1, 0, 2};
|
||||
|
||||
static unsigned const int state2d[] = /* nkey to 2 dimension state transitions */
|
||||
{1, 0, 0, 2,
|
||||
0, 1, 1, 3,
|
||||
3, 2, 2, 0,
|
||||
2, 3, 3, 1};
|
||||
|
||||
static unsigned const data3d [] = { /* nkey to 3 dimension conversion */
|
||||
0, 4, 6, 2, 3, 7, 5, 1,
|
||||
0, 1, 3, 2, 6, 7, 5, 4,
|
||||
0, 4, 5, 1, 3, 7, 6, 2,
|
||||
5, 4, 0, 1, 3, 2, 6, 7,
|
||||
6, 7, 3, 2, 0, 1, 5, 4,
|
||||
3, 7, 6, 2, 0, 4, 5, 1,
|
||||
5, 4, 6, 7, 3, 2, 0, 1,
|
||||
0, 1, 5, 4, 6, 7, 3, 2,
|
||||
5, 1, 0, 4, 6, 2, 3, 7,
|
||||
5, 1, 3, 7, 6, 2, 0, 4,
|
||||
0, 2, 6, 4, 5, 7, 3, 1,
|
||||
3, 1, 0, 2, 6, 4, 5, 7,
|
||||
5, 7, 6, 4, 0, 2, 3, 1,
|
||||
6, 7, 5, 4, 0, 1, 3, 2,
|
||||
3, 1, 5, 7, 6, 4, 0, 2,
|
||||
0, 2, 3, 1, 5, 7, 6, 4,
|
||||
3, 2, 0, 1, 5, 4, 6, 7,
|
||||
3, 2, 6, 7, 5, 4, 0, 1,
|
||||
6, 2, 0, 4, 5, 1, 3, 7,
|
||||
3, 7, 5, 1, 0, 4, 6, 2,
|
||||
5, 7, 3, 1, 0, 2, 6, 4,
|
||||
6, 2, 3, 7, 5, 1, 0, 4,
|
||||
6, 4, 0, 2, 3, 1, 5, 7,
|
||||
6, 4, 5, 7, 3, 1, 0, 2};
|
||||
|
||||
static unsigned const state3d [] = { /* nkey to 3 dimension state transitions */
|
||||
1, 2, 0, 3, 4, 0, 5, 6,
|
||||
0, 7, 1, 8, 5, 1, 4, 9,
|
||||
15, 0, 2, 22, 20, 2, 19, 23,
|
||||
20, 6, 3, 23, 15, 3, 16, 22,
|
||||
22, 13, 4, 12, 11, 4, 1, 20,
|
||||
11, 19, 5, 20, 22, 5, 0, 12,
|
||||
9, 3, 6, 2, 21, 6, 17, 0,
|
||||
10, 1, 7, 11, 12, 7, 13, 14,
|
||||
12, 9, 8, 14, 10, 8, 18, 11,
|
||||
6, 8, 9, 7, 17, 9, 21, 1,
|
||||
7, 15, 10, 16, 13, 10, 12, 17,
|
||||
5, 14, 11, 9, 0, 11, 22, 8,
|
||||
8, 20, 12, 19, 18, 12, 10, 5,
|
||||
18, 4, 13, 5, 8, 13, 7, 19,
|
||||
17, 11, 14, 1, 6, 14, 23, 7,
|
||||
2, 10, 15, 18, 19, 15, 20, 21,
|
||||
19, 17, 16, 21, 2, 16, 3, 18,
|
||||
14, 16, 17, 15, 23, 17, 6, 10,
|
||||
13, 21, 18, 17, 7, 18, 8, 16,
|
||||
16, 5, 19, 4, 3, 19, 2, 13,
|
||||
3, 12, 20, 13, 16, 20, 15, 4,
|
||||
23, 18, 21, 10, 14, 21, 9, 15,
|
||||
4, 23, 22, 6, 1, 22, 11, 3,
|
||||
21, 22, 23, 0, 9, 23, 14, 2};
|
||||
|
||||
static unsigned const idata3d [] = { /* 3 dimension to nkey conversion */
|
||||
0, 7, 3, 4, 1, 6, 2, 5,
|
||||
0, 1, 3, 2, 7, 6, 4, 5,
|
||||
0, 3, 7, 4, 1, 2, 6, 5,
|
||||
2, 3, 5, 4, 1, 0, 6, 7,
|
||||
4, 5, 3, 2, 7, 6, 0, 1,
|
||||
4, 7, 3, 0, 5, 6, 2, 1,
|
||||
6, 7, 5, 4, 1, 0, 2, 3,
|
||||
0, 1, 7, 6, 3, 2, 4, 5,
|
||||
2, 1, 5, 6, 3, 0, 4, 7,
|
||||
6, 1, 5, 2, 7, 0, 4, 3,
|
||||
0, 7, 1, 6, 3, 4, 2, 5,
|
||||
2, 1, 3, 0, 5, 6, 4, 7,
|
||||
4, 7, 5, 6, 3, 0, 2, 1,
|
||||
4, 5, 7, 6, 3, 2, 0, 1,
|
||||
6, 1, 7, 0, 5, 2, 4, 3,
|
||||
0, 3, 1, 2, 7, 4, 6, 5,
|
||||
2, 3, 1, 0, 5, 4, 6, 7,
|
||||
6, 7, 1, 0, 5, 4, 2, 3,
|
||||
2, 5, 1, 6, 3, 4, 0, 7,
|
||||
4, 3, 7, 0, 5, 2, 6, 1,
|
||||
4, 3, 5, 2, 7, 0, 6, 1,
|
||||
6, 5, 1, 2, 7, 4, 0, 3,
|
||||
2, 5, 3, 4, 1, 6, 0, 7,
|
||||
6, 5, 7, 4, 1, 2, 0, 3};
|
||||
|
||||
static unsigned const istate3d [] ={ /* 3 dimension to nkey state transitions */
|
||||
1, 6, 3, 4, 2, 5, 0, 0,
|
||||
0, 7, 8, 1, 9, 4, 5, 1,
|
||||
15, 22, 23, 20, 0, 2, 19, 2,
|
||||
3, 23, 3, 15, 6, 20, 16, 22,
|
||||
11, 4, 12, 4, 20, 1, 22, 13,
|
||||
22, 12, 20, 11, 5, 0, 5, 19,
|
||||
17, 0, 6, 21, 3, 9, 6, 2,
|
||||
10, 1, 14, 13, 11, 7, 12, 7,
|
||||
8, 9, 8, 18, 14, 12, 10, 11,
|
||||
21, 8, 9, 9, 1, 6, 17, 7,
|
||||
7, 17, 15, 12, 16, 13, 10, 10,
|
||||
11, 14, 9, 5, 11, 22, 0, 8,
|
||||
18, 5, 12, 10, 19, 8, 12, 20,
|
||||
8, 13, 19, 7, 5, 13, 18, 4,
|
||||
23, 11, 7, 17, 14, 14, 6, 1,
|
||||
2, 18, 10, 15, 21, 19, 20, 15,
|
||||
16, 21, 17, 19, 16, 2, 3, 18,
|
||||
6, 10, 16, 14, 17, 23, 17, 15,
|
||||
18, 18, 21, 8, 17, 7, 13, 16,
|
||||
3, 4, 13, 16, 19, 19, 2, 5,
|
||||
16, 13, 20, 20, 4, 3, 15, 12,
|
||||
9, 21, 18, 21, 15, 14, 23, 10,
|
||||
22, 22, 6, 1, 23, 11, 4, 3,
|
||||
14, 23, 2, 9, 22, 23, 21, 0};
|
||||
|
||||
|
||||
|
||||
double Zoltan_HSFC_InvHilbert1d (ZZ*, double *coord);
|
||||
double Zoltan_HSFC_InvHilbert2d (ZZ*, double *coord);
|
||||
double Zoltan_HSFC_InvHilbert3d (ZZ*, double *coord);
|
||||
|
||||
void Zoltan_HSFC_Hilbert1d (ZZ*, double *coord, double key);
|
||||
void Zoltan_HSFC_Hilbert2d (ZZ*, double *coord, double key);
|
||||
void Zoltan_HSFC_Hilbert3d (ZZ*, double *coord, double key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
70
thirdParty/Zoltan/src/hsfc/hsfc_params.h
vendored
Normal file
70
thirdParty/Zoltan/src/hsfc/hsfc_params.h
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifndef __HSFC_PARAMS_H
|
||||
#define __HSFC_PARAMS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "zz_const.h"
|
||||
|
||||
/* This structure is the Zoltan convention for user settable parameters */
|
||||
static PARAM_VARS HSFC_params[] =
|
||||
{{"KEEP_CUTS", NULL, "INT", 0},
|
||||
{ "REDUCE_DIMENSIONS", NULL, "INT", 0 },
|
||||
{ "DEGENERATE_RATIO", NULL, "DOUBLE", 0 },
|
||||
{"FINAL_OUTPUT", NULL, "INT", 0},
|
||||
{NULL, NULL, NULL, 0}};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
133
thirdParty/Zoltan/src/hsfc/hsfc_point_assign.c
vendored
Normal file
133
thirdParty/Zoltan/src/hsfc/hsfc_point_assign.c
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* @HEADER
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
|
||||
* Copyright 2012 Sandia Corporation
|
||||
*
|
||||
* Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
* the U.S. Government retains certain rights in this software.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the Corporation nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Questions? Contact Karen Devine kddevin@sandia.gov
|
||||
* Erik Boman egboman@sandia.gov
|
||||
*
|
||||
* ***********************************************************************
|
||||
*
|
||||
* @HEADER
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* if C++, define the rest of this header file as extern C */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "hsfc.h"
|
||||
#include "zz_const.h"
|
||||
#include "zz_util_const.h"
|
||||
|
||||
/* For a detailed explaination of this module, please see the Developers
|
||||
Guide. For instructions on its use, please see the Users Guide. */
|
||||
|
||||
|
||||
/* Point drop for refinement after above partitioning */
|
||||
int Zoltan_HSFC_Point_Assign (
|
||||
ZZ *zz,
|
||||
double *x,
|
||||
int *proc,
|
||||
int *part)
|
||||
{
|
||||
double scaled[3];
|
||||
double pt[3];
|
||||
double fsfc;
|
||||
Partition *p;
|
||||
int i;
|
||||
int dim;
|
||||
HSFC_Data *d;
|
||||
int err;
|
||||
char *yo = "Zoltan_HSFC_Point_Assign";
|
||||
|
||||
ZOLTAN_TRACE_ENTER (zz, yo);
|
||||
d = (HSFC_Data *) zz->LB.Data_Structure;
|
||||
if (d == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL,
|
||||
"No Decomposition Data available; use KEEP_CUTS parameter.");
|
||||
|
||||
for (i=0; i<d->ndimension; i++){
|
||||
pt[i] = x[i]; /* we don't want to change caller's "x" */
|
||||
}
|
||||
|
||||
if (d->tran.Target_Dim > 0){ /* degenerate geometry */
|
||||
dim = d->tran.Target_Dim;
|
||||
Zoltan_Transform_Point(pt, d->tran.Transformation, d->tran.Permutation,
|
||||
d->ndimension, dim, pt);
|
||||
}
|
||||
else{
|
||||
dim = d->ndimension;
|
||||
}
|
||||
|
||||
/* Calculate scaled coordinates, calculate HSFC coordinate */
|
||||
for (i = 0; i < dim; i++)
|
||||
{
|
||||
scaled[i] = (pt[i] - d->bbox_lo[i]) / d->bbox_extent[i];
|
||||
if (scaled[i] < HSFC_EPSILON) scaled[i] = HSFC_EPSILON;
|
||||
if (scaled[i] > 1.0 - HSFC_EPSILON) scaled[i] = 1.0 - HSFC_EPSILON;
|
||||
}
|
||||
fsfc = d->fhsfc (zz, scaled); /* Note, this is a function call */
|
||||
|
||||
/* Find partition containing point and return its number */
|
||||
p = (Partition *) bsearch (&fsfc, d->final_partition, zz->LB.Num_Global_Parts,
|
||||
sizeof (Partition), Zoltan_HSFC_compare);
|
||||
|
||||
if (p == NULL)
|
||||
ZOLTAN_HSFC_ERROR (ZOLTAN_FATAL, "programming error, shouldn't happen");
|
||||
if (part != NULL) {
|
||||
if (zz->LB.Remap)
|
||||
*part = zz->LB.Remap[p->index];
|
||||
else
|
||||
*part = p->index;
|
||||
}
|
||||
if (proc != NULL) {
|
||||
if (zz->LB.Remap)
|
||||
*proc = Zoltan_LB_Part_To_Proc(zz, zz->LB.Remap[p->index], NULL);
|
||||
else
|
||||
*proc = Zoltan_LB_Part_To_Proc(zz, p->index, NULL);
|
||||
}
|
||||
err = ZOLTAN_OK;
|
||||
|
||||
End:
|
||||
ZOLTAN_TRACE_EXIT (zz, yo);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing bracket for extern "C" */
|
||||
#endif
|
Reference in New Issue
Block a user