/* * Calculate the extent of the geometry in the directions indicated * by the orthonormal eigenvectors of the inertial matrix. This is * essentially the dimensions of an oriented bounding box around * the geometry. */ static void projected_distances(ZZ *zz, double *coords, int num_obj, double *cm, double (*evecs)[3], double *d, int dim, int aa, int *order) { int i, j; double val, min[3], max[3], *c, tmp; int Tflops_Special, proc, nprocs, proclower; MPI_Comm local_comm; Tflops_Special = zz->Tflops_Special; proc = zz->Proc; nprocs = zz->Num_Proc; proclower = 0; local_comm = zz->Communicator; if (aa){ /* special case - eigenvectors are axis aligned */ for (j=0; j<dim; j++){ min[j] = max[j] = coords[j]; } for (i=1, c = coords+dim; i<num_obj; i++, c += dim){ for (j=0; j<dim; j++){ if (c[j] < min[j]) min[j] = c[j]; else if (c[j] > max[j]) max[j] = c[j]; } } for (i=0; i<dim; i++){ tmp = max[i]; MPI_Allreduce(&tmp, max + i, 1, MPI_DOUBLE, MPI_MAX, local_comm); tmp = min[i]; MPI_Allreduce(&tmp, min + i, 1, MPI_DOUBLE, MPI_MIN, local_comm); } for (j=0; j<dim; j++){ /* distance along the j'th eigenvector */ d[j] = max[order[j]] - min[order[j]]; } return; } for (i=0; i<dim; i++){ for (j=0, c=coords; j<num_obj; j++, c+=dim){ val = (((c[0] - cm[0]) * evecs[0][i]) + ((c[1] - cm[1]) * evecs[1][i])); if (dim == 3){ val += ((c[2] - cm[2]) * evecs[2][i]); } if (j){ if (val < min[i]) min[i] = val; else if (val > max[i]) max[i] = val; } else{ min[i] = max[i] = val; } } } if (Tflops_Special){ for (i=0; i<dim; i++){ Zoltan_RIB_min_max(min+i, max+i, proclower, proc, nprocs, local_comm); d[i] = max[i] - min[i]; } } else { for (i=0; i<dim; i++){ tmp = max[i]; MPI_Allreduce(&tmp, max + i, 1, MPI_DOUBLE, MPI_MAX, local_comm); tmp = min[i]; MPI_Allreduce(&tmp, min + i, 1, MPI_DOUBLE, MPI_MIN, local_comm); d[i] = max[i] - min[i]; } } return; }
static int compute_rib_direction( ZZ *zz, int Tflops_Special, /* Tflops_Special flag for special processing. Should be 0 when called by serial_rib. */ int num_geom, /* number of dimensions */ double *valuelo, /* smallest value of value[i] */ double *valuehi, /* largest value of value[i] */ struct Dot_Struct *dotpt, /* local dot array */ int *dindx, /* index array into dotpt; if NULL, access dotpt directly */ int dotnum, /* number of dots */ int wgtflag, /* (0) do not (1) do use weights. Multidimensional weights not supported */ double *cm, /* Center of mass of objects */ double *evec, /* Eigenvector defining direction */ double *value, /* temp array for median_find; rotated coords */ MPI_Comm local_comm, /* MPI communicator for set */ int proc, /* Current processor; needed for Tflops_Special */ int nprocs, /* Number of procs in operation; needed for Tflops_Special */ int proclower /* Lowest numbered proc; needed for Tflops_Special */ ) { int i, ierr = 0; double tmp; RIB_STRUCT *rib; rib = (RIB_STRUCT *)zz->LB.Data_Structure; if (rib->Tran.Target_Dim > 0){ num_geom = rib->Tran.Target_Dim; /* degenerate geometry */ } switch (num_geom) { case 3: ierr = Zoltan_RIB_inertial3d(Tflops_Special, dotpt, dindx, dotnum, wgtflag, cm, evec, value, local_comm, proc, nprocs, proclower); break; case 2: ierr = Zoltan_RIB_inertial2d(Tflops_Special, dotpt, dindx, dotnum, wgtflag, cm, evec, value, local_comm, proc, nprocs, proclower); break; case 1: ierr = Zoltan_RIB_inertial1d(dotpt, dindx, dotnum, wgtflag, cm, evec, value); break; } *valuelo = DBL_MAX; *valuehi = -DBL_MAX; for (i = 0; i < dotnum; i++) { if (value[i] < *valuelo) *valuelo = value[i]; if (value[i] > *valuehi) *valuehi = value[i]; } if (Tflops_Special) Zoltan_RIB_min_max(valuelo, valuehi, proclower, proc, nprocs, local_comm); else { tmp = *valuehi; MPI_Allreduce(&tmp, valuehi, 1, MPI_DOUBLE, MPI_MAX, local_comm); tmp = *valuelo; MPI_Allreduce(&tmp, valuelo, 1, MPI_DOUBLE, MPI_MIN, local_comm); } return ierr; }