/** * R T _ M E T A B A L L _ T E S S * * Tessellate a metaball. */ int rt_metaball_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol) { struct rt_metaball_internal *mb; fastf_t mtol, radius; point_t center, min, max; fastf_t i, j, k, finalstep = +INFINITY; struct bu_vls times = BU_VLS_INIT_ZERO; struct wdb_metaballpt *mbpt; struct shell *s; int numtri = 0; if (r == NULL || m == NULL) return -1; *r = NULL; NMG_CK_MODEL(m); RT_CK_DB_INTERNAL(ip); mb = (struct rt_metaball_internal *)ip->idb_ptr; RT_METABALL_CK_MAGIC(mb); rt_prep_timer(); /* since this geometry isn't necessarily prepped, we have to figure out the * finalstep and bounding box manually. */ for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) V_MIN(finalstep, mbpt->fldstr); finalstep /= (fastf_t)1e5; radius = rt_metaball_get_bounding_sphere(¢er, mb->threshold, mb); if(radius < 0) { /* no control points */ bu_log("Attempting to tesselate metaball with no control points"); return -1; } rt_metaball_bbox(ip, &min, &max, tol); /* TODO: get better sampling tolerance, unless this is "good enough" */ mtol = ttol->abs; V_MAX(mtol, ttol->rel * radius * 10); V_MAX(mtol, tol->dist); *r = nmg_mrsv(m); /* new empty nmg */ s = BU_LIST_FIRST(shell, &(*r)->s_hd); /* the incredibly naïve approach. Time could be cut in half by simply * caching 4 point values, more by actually marching or doing active * refinement. This is the simplest pattern for now. */ for (i = min[X]; i < max[X]; i += mtol) for (j = min[Y]; j < max[Y]; j += mtol) for (k = min[Z]; k < max[Z]; k += mtol) { point_t p[8]; int pv = 0; /* generate the vertex values */ #define MEH(c,di,dj,dk) VSET(p[c], i+di, j+dj, k+dk); pv |= rt_metaball_point_inside((const point_t *)&p[c], mb) << c; MEH(0, 0, 0, mtol); MEH(1, mtol, 0, mtol); MEH(2, mtol, 0, 0); MEH(3, 0, 0, 0); MEH(4, 0, mtol, mtol); MEH(5, mtol, mtol, mtol); MEH(6, mtol, mtol, 0); MEH(7, 0, mtol, 0); #undef MEH if ( pv != 0 && pv != 255 ) { /* entire cube is either inside or outside */ point_t edges[12]; int rval; /* compute the edge values (if needed) */ #define MEH(a,b,c) if(!(pv&(1<<b)&&pv&(1<<c))) { \ rt_metaball_find_intersection(edges+a, mb, (const point_t *)(p+b), (const point_t *)(p+c), mtol, finalstep); \ } /* magic numbers! an edge, then the two attached vertices. * For edge/vertex mapping, refer to the awesome ascii art * at the beginning of this file. */ MEH(0 ,0,1); MEH(1 ,1,2); MEH(2 ,2,3); MEH(3 ,0,3); MEH(4 ,4,5); MEH(5 ,5,6); MEH(6 ,6,7); MEH(7 ,4,7); MEH(8 ,0,4); MEH(9 ,1,5); MEH(10,2,6); MEH(11,3,7); #undef MEH rval = nmg_mc_realize_cube(s, pv, (point_t *)edges, tol); numtri += rval; if(rval < 0) { bu_log("Error attempting to realize a cube O.o\n"); return rval; } } } nmg_mark_edges_real(&s->l.magic); nmg_region_a(*r, tol); nmg_model_fuse(m, tol); rt_get_timer(×, NULL); bu_log("metaball tesselate (%d triangles): %s\n", numtri, bu_vls_addr(×)); return 0; }
int main ( int arfc, char ** arfv ) { char output_filename[80]={0}; int i, count; int data, * pdata; MPI_Status ms = {0}; pdata = &data; MEH(MPI_Init(&arfc, &arfv)); MEH(MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank)); MEH(MPI_Comm_size(MPI_COMM_WORLD, &mpi_size)); sprintf(output_filename, "output-%d", mpi_rank); if(NULL != (OUTPUT = fopen(output_filename, "w"))) { fprintf(stderr, "[%f] %d opened %s for write\n", MPI_Wtime(), mpi_rank, output_filename); } else { fprintf(OUTPUT, "[%f] %d could not open %s for write, bailing\n", MPI_Wtime(), mpi_rank, output_filename); } srand(time(NULL)); if ( arfc >= 2 ) { count = atoi(arfv[1]); fprintf(OUTPUT, "[%f] %d converting first argument %s to %d\n", MPI_Wtime(), mpi_rank, arfv[1], count); } if ( count < 0 ) count = DEFAULT_COUNT; fprintf(OUTPUT, "[%f] %d attempting %d iterations\n", MPI_Wtime(), mpi_rank, count); for ( i = 0; i < count; ++ i ) { switch(mpi_rank) { case MPI_RANK_MASTER: // MPI_RANK_MASTER receives a number from MPI_RANK_SOURCE and forwards to MPI_RANK_TARGET MEH(MPI_Recv(pdata, 1, MPI_INT, MPI_ANY_SOURCE, ARBITRARY_TAG, MPI_COMM_WORLD, &ms)); fprintf(OUTPUT, "[%f] %d received %d from %d, seq %d\n", MPI_Wtime(), mpi_rank, data, ms.MPI_SOURCE, i); MEH(MPI_Send(pdata, 1, MPI_INT, MPI_RANK_TARGET, ARBITRARY_TAG, MPI_COMM_WORLD)); fprintf(OUTPUT, "[%f] %d sent %d to %d, seq %d\n", MPI_Wtime(), mpi_rank, data, MPI_RANK_TARGET, i); break; case MPI_RANK_SOURCE: // MPI_RANK_MASTER generates a pseudorandom number and sends to MPI_RANK_MASTER data = rand(); MEH(MPI_Send(pdata, 1, MPI_INT, MPI_RANK_MASTER, ARBITRARY_TAG, MPI_COMM_WORLD)); fprintf(OUTPUT, "[%f] %d sent %d to %d, seq %d\n", MPI_Wtime(), mpi_rank, data, MPI_RANK_MASTER, i); break; case MPI_RANK_TARGET: // MPI_RANK_TARGET receives a random number from MPI_RANK_MASTER MEH(MPI_Recv(pdata, 1, MPI_INT, MPI_ANY_SOURCE, ARBITRARY_TAG, MPI_COMM_WORLD, &ms)); fprintf(OUTPUT, "[%f] %d received %d from %d, seq %d\n", MPI_Wtime(), mpi_rank, data, ms.MPI_SOURCE, i); break; } } fclose(OUTPUT); MEH(MPI_Finalize()); return 0; }