Exemplo n.º 1
0
/* Compute and insert migration along directed edge (may fork child) */
static MIGRATION *
create_migration(RBFNODE *from_rbf, RBFNODE *to_rbf)
{
	const double	end_thresh = 5e-6;
	PRICEMAT	pmtx;
	MIGRATION	*newmig;
	double		*src_rem, *dst_rem;
	double		total_rem = 1., move_amt;
	int		i, j;
						/* check if exists already */
	for (newmig = from_rbf->ejl; newmig != NULL;
			newmig = nextedge(from_rbf,newmig))
		if (newmig->rbfv[1] == to_rbf)
			return(NULL);
						/* else allocate */
#ifdef DEBUG
	fprintf(stderr, "Building path from (theta,phi) (%.0f,%.0f) ",
			get_theta180(from_rbf->invec),
			get_phi360(from_rbf->invec));
	fprintf(stderr, "to (%.0f,%.0f) with %d x %d matrix\n",
			get_theta180(to_rbf->invec),
			get_phi360(to_rbf->invec), 
			from_rbf->nrbf, to_rbf->nrbf);
#endif
	newmig = new_migration(from_rbf, to_rbf);
	if (run_subprocess())
		return(newmig);			/* child continues */
	price_routes(&pmtx, from_rbf, to_rbf);
	src_rem = (double *)malloc(sizeof(double)*from_rbf->nrbf);
	dst_rem = (double *)malloc(sizeof(double)*to_rbf->nrbf);
	if ((src_rem == NULL) | (dst_rem == NULL)) {
		fprintf(stderr, "%s: Out of memory in create_migration()\n",
				progname);
		exit(1);
	}
						/* starting quantities */
	memset(newmig->mtx, 0, sizeof(float)*from_rbf->nrbf*to_rbf->nrbf);
	for (i = from_rbf->nrbf; i--; )
		src_rem[i] = rbf_volume(&from_rbf->rbfa[i]) / from_rbf->vtotal;
	for (j = to_rbf->nrbf; j--; )
		dst_rem[j] = rbf_volume(&to_rbf->rbfa[j]) / to_rbf->vtotal;

	do {					/* move a bit at a time */
		move_amt = migration_step(newmig, src_rem, dst_rem, &pmtx);
		total_rem -= move_amt;
	} while ((total_rem > end_thresh) & (move_amt > 0));

	for (i = from_rbf->nrbf; i--; ) {	/* normalize final matrix */
	    double	nf = rbf_volume(&from_rbf->rbfa[i]);
	    if (nf <= FTINY) continue;
	    nf = from_rbf->vtotal / nf;
	    for (j = to_rbf->nrbf; j--; )
		mtx_coef(newmig,i,j) *= nf;	/* row now sums to 1.0 */
	}
	end_subprocess();			/* exit here if subprocess */
	free_routes(&pmtx);			/* free working arrays */
	free(src_rem);
	free(dst_rem);
	return(newmig);
}
Exemplo n.º 2
0
/* Compute and insert migration along directed edge (may fork child) */
static MIGRATION *
create_migration(RBFNODE *from_rbf, RBFNODE *to_rbf)
{
	MIGRATION	*newmig;
	int		i, j;
						/* check if exists already */
	for (newmig = from_rbf->ejl; newmig != NULL;
			newmig = nextedge(from_rbf,newmig))
		if (newmig->rbfv[1] == to_rbf)
			return(NULL);
						/* else allocate */
#ifdef DEBUG
	fprintf(stderr, "Building path from (theta,phi) (%.1f,%.1f) ",
			get_theta180(from_rbf->invec),
			get_phi360(from_rbf->invec));
	fprintf(stderr, "to (%.1f,%.1f) with %d x %d matrix\n",
			get_theta180(to_rbf->invec),
			get_phi360(to_rbf->invec), 
			from_rbf->nrbf, to_rbf->nrbf);
#endif
	newmig = new_migration(from_rbf, to_rbf);
	if (run_subprocess())
		return(newmig);			/* child continues */

						/* compute transport plan */
	compute_nDSFs(from_rbf, to_rbf);
	plan_transport(newmig);

	for (i = from_rbf->nrbf; i--; ) {	/* normalize final matrix */
	    double	nf = rbf_volume(&from_rbf->rbfa[i]);
	    if (nf <= FTINY) continue;
	    nf = from_rbf->vtotal / nf;
	    for (j = to_rbf->nrbf; j--; )
		mtx_coef(newmig,i,j) *= nf;	/* row now sums to 1.0 */
	}
	end_subprocess();			/* exit here if subprocess */
	return(newmig);
}
Exemplo n.º 3
0
/* Add normal direction if missing */
static void
check_normal_incidence(void)
{
	static FVECT		norm_vec = {.0, .0, 1.};
	const int		saved_nprocs = nprocs;
	RBFNODE			*near_rbf, *mir_rbf, *rbf;
	double			bestd;
	int			n;

	if (dsf_list == NULL)
		return;				/* XXX should be error? */
	near_rbf = dsf_list;
	bestd = input_orient*near_rbf->invec[2];
	if (single_plane_incident) {		/* ordered plane incidence? */
		if (bestd >= 1.-2.*FTINY)
			return;			/* already have normal */
	} else {
		switch (inp_coverage) {
		case INP_QUAD1:
		case INP_QUAD2:
		case INP_QUAD3:
		case INP_QUAD4:
			break;			/* quadrilateral symmetry? */
		default:
			return;			/* else we can interpolate */
		}
		for (rbf = dsf_list; rbf != NULL; rbf = rbf->next) {
			const double	d = input_orient*rbf->invec[2];
			if (d >= 1.-2.*FTINY)
				return;		/* seems we have normal */
			if (d > bestd) {
				near_rbf = rbf;
				bestd = d;
			}
		}
	}
	if (mig_list != NULL) {			/* need to be called first */
		fprintf(stderr, "%s: Late call to check_normal_incidence()\n",
				progname);
		exit(1);
	}
#ifdef DEBUG
	fprintf(stderr, "Interpolating normal incidence by mirroring (%.1f,%.1f)\n",
			get_theta180(near_rbf->invec), get_phi360(near_rbf->invec));
#endif
						/* mirror nearest incidence */
	n = sizeof(RBFNODE) + sizeof(RBFVAL)*(near_rbf->nrbf-1);
	mir_rbf = (RBFNODE *)malloc(n);
	if (mir_rbf == NULL)
		goto memerr;
	memcpy(mir_rbf, near_rbf, n);
	mir_rbf->ord = near_rbf->ord - 1;	/* not used, I think */
	mir_rbf->next = NULL;
	mir_rbf->ejl = NULL;
	rev_rbf_symmetry(mir_rbf, MIRROR_X|MIRROR_Y);
	nprocs = 1;				/* compute migration matrix */
	if (create_migration(mir_rbf, near_rbf) == NULL)
		exit(1);			/* XXX should never happen! */
	norm_vec[2] = input_orient;		/* interpolate normal dist. */
	rbf = e_advect_rbf(mig_list, norm_vec, 0);
	nprocs = saved_nprocs;			/* final clean-up */
	free(mir_rbf);
	free(mig_list);
	mig_list = near_rbf->ejl = NULL;
	insert_dsf(rbf);			/* insert interpolated normal */
	return;
memerr:
	fprintf(stderr, "%s: Out of memory in check_normal_incidence()\n",
				progname);
	exit(1);
}
Exemplo n.º 4
0
/* Count up filled nodes and build RBF representation from current grid */ 
RBFNODE *
make_rbfrep(void)
{
	int	niter = 16;
	double	lastVar, thisVar = 100.;
	int	nn;
	RBFNODE	*newnode;
	RBFVAL	*itera;
	int	i, j;
				/* compute RBF radii */
	compute_radii();
				/* coagulate lobes */
	cull_values();
	nn = 0;			/* count selected bins */
	for (i = 0; i < GRIDRES; i++)
	    for (j = 0; j < GRIDRES; j++)
		nn += dsf_grid[i][j].nval;
				/* compute minimum BSDF */
	comp_bsdf_min();
				/* allocate RBF array */
	newnode = (RBFNODE *)malloc(sizeof(RBFNODE) + sizeof(RBFVAL)*(nn-1));
	if (newnode == NULL)
		goto memerr;
	newnode->ord = -1;
	newnode->next = NULL;
	newnode->ejl = NULL;
	newnode->invec[2] = sin((M_PI/180.)*theta_in_deg);
	newnode->invec[0] = cos((M_PI/180.)*phi_in_deg)*newnode->invec[2];
	newnode->invec[1] = sin((M_PI/180.)*phi_in_deg)*newnode->invec[2];
	newnode->invec[2] = input_orient*sqrt(1. - newnode->invec[2]*newnode->invec[2]);
	newnode->vtotal = 0;
	newnode->nrbf = nn;
	nn = 0;			/* fill RBF array */
	for (i = 0; i < GRIDRES; i++)
	    for (j = 0; j < GRIDRES; j++)
		if (dsf_grid[i][j].nval) {
			newnode->rbfa[nn].peak = dsf_grid[i][j].vsum;
			newnode->rbfa[nn].crad = RSCA*dsf_grid[i][j].crad + .5;
			newnode->rbfa[nn].gx = i;
			newnode->rbfa[nn].gy = j;
			++nn;
		}
				/* iterate to improve interpolation accuracy */
	itera = (RBFVAL *)malloc(sizeof(RBFVAL)*newnode->nrbf);
	if (itera == NULL)
		goto memerr;
	memcpy(itera, newnode->rbfa, sizeof(RBFVAL)*newnode->nrbf);
	do {
		double	dsum = 0, dsum2 = 0;
		nn = 0;
		for (i = 0; i < GRIDRES; i++)
		    for (j = 0; j < GRIDRES; j++)
			if (dsf_grid[i][j].nval) {
				FVECT	odir;
				double	corr;
				ovec_from_pos(odir, i, j);
				itera[nn++].peak *= corr =
					dsf_grid[i][j].vsum /
						eval_rbfrep(newnode, odir);
				dsum += 1. - corr;
				dsum2 += (1.-corr)*(1.-corr);
			}
		memcpy(newnode->rbfa, itera, sizeof(RBFVAL)*newnode->nrbf);
		lastVar = thisVar;
		thisVar = dsum2/(double)nn;
#ifdef DEBUG
		fprintf(stderr, "Avg., RMS error: %.1f%%  %.1f%%\n",
					100.*dsum/(double)nn,
					100.*sqrt(thisVar));
#endif
	} while (--niter > 0 && lastVar-thisVar > 0.02*lastVar);

	free(itera);
	nn = 0;			/* compute sum for normalization */
	while (nn < newnode->nrbf)
		newnode->vtotal += rbf_volume(&newnode->rbfa[nn++]);
#ifdef DEBUG
	fprintf(stderr, "Integrated DSF at (%.1f,%.1f) deg. is %.2f\n",
			get_theta180(newnode->invec), get_phi360(newnode->invec),
			newnode->vtotal);
#endif
	insert_dsf(newnode);

	return(newnode);
memerr:
	fprintf(stderr, "%s: Out of memory in make_rbfrep()\n", progname);
	exit(1);
}