484 |
|
} |
485 |
|
} |
486 |
|
} |
487 |
+ |
|
488 |
+ |
/* Add normal direction if missing */ |
489 |
+ |
static void |
490 |
+ |
check_normal_incidence(void) |
491 |
+ |
{ |
492 |
+ |
const int saved_nprocs = nprocs; |
493 |
+ |
RBFNODE *near_rbf, *mir_rbf, *rbf; |
494 |
+ |
double bestd; |
495 |
+ |
int n, i, j; |
496 |
+ |
|
497 |
+ |
if (dsf_list == NULL) |
498 |
+ |
return; /* XXX should be error? */ |
499 |
+ |
near_rbf = dsf_list; |
500 |
+ |
bestd = input_orient*near_rbf->invec[2]; |
501 |
+ |
if (single_plane_incident) { /* ordered plane incidence? */ |
502 |
+ |
if (bestd >= 1.-2.*FTINY) |
503 |
+ |
return; /* already have normal */ |
504 |
+ |
} else { |
505 |
+ |
switch (inp_coverage) { |
506 |
+ |
case INP_QUAD1: |
507 |
+ |
case INP_QUAD2: |
508 |
+ |
case INP_QUAD3: |
509 |
+ |
case INP_QUAD4: |
510 |
+ |
break; /* quadrilateral symmetry? */ |
511 |
+ |
default: |
512 |
+ |
return; /* else we can interpolate */ |
513 |
+ |
} |
514 |
+ |
for (rbf = near_rbf->next; rbf != NULL; rbf = rbf->next) { |
515 |
+ |
const double d = input_orient*rbf->invec[2]; |
516 |
+ |
if (d >= 1.-2.*FTINY) |
517 |
+ |
return; /* seems we have normal */ |
518 |
+ |
if (d > bestd) { |
519 |
+ |
near_rbf = rbf; |
520 |
+ |
bestd = d; |
521 |
+ |
} |
522 |
+ |
} |
523 |
+ |
} |
524 |
+ |
if (mig_list != NULL) { /* need to be called first */ |
525 |
+ |
fprintf(stderr, "%s: Late call to check_normal_incidence()\n", |
526 |
+ |
progname); |
527 |
+ |
exit(1); |
528 |
+ |
} |
529 |
+ |
#ifdef DEBUG |
530 |
+ |
fprintf(stderr, "Interpolating normal incidence by mirroring (%.1f,%.1f)\n", |
531 |
+ |
get_theta180(near_rbf->invec), get_phi360(near_rbf->invec)); |
532 |
+ |
#endif |
533 |
+ |
/* mirror nearest incidence */ |
534 |
+ |
n = sizeof(RBFNODE) + sizeof(RBFVAL)*(near_rbf->nrbf-1); |
535 |
+ |
mir_rbf = (RBFNODE *)malloc(n); |
536 |
+ |
if (mir_rbf == NULL) |
537 |
+ |
goto memerr; |
538 |
+ |
memcpy(mir_rbf, near_rbf, n); |
539 |
+ |
mir_rbf->ord = near_rbf->ord - 1; /* not used, I think */ |
540 |
+ |
mir_rbf->next = NULL; |
541 |
+ |
rev_rbf_symmetry(mir_rbf, MIRROR_X|MIRROR_Y); |
542 |
+ |
nprocs = 1; /* compute migration matrix */ |
543 |
+ |
if (mig_list != create_migration(mir_rbf, near_rbf)) |
544 |
+ |
exit(1); /* XXX should never happen! */ |
545 |
+ |
n = 0; /* count migrating particles */ |
546 |
+ |
for (i = 0; i < mtx_nrows(mig_list); i++) |
547 |
+ |
for (j = 0; j < mtx_ncols(mig_list); j++) |
548 |
+ |
n += (mtx_coef(mig_list,i,j) > FTINY); |
549 |
+ |
rbf = (RBFNODE *)malloc(sizeof(RBFNODE) + sizeof(RBFVAL)*(n-1)); |
550 |
+ |
if (rbf == NULL) |
551 |
+ |
goto memerr; |
552 |
+ |
rbf->next = NULL; rbf->ejl = NULL; |
553 |
+ |
rbf->invec[0] = rbf->invec[1] = 0; rbf->invec[2] = 1.; |
554 |
+ |
rbf->nrbf = n; |
555 |
+ |
rbf->vtotal = .5 + .5*mig_list->rbfv[1]->vtotal/mig_list->rbfv[0]->vtotal; |
556 |
+ |
n = 0; /* advect RBF lobes halfway */ |
557 |
+ |
for (i = 0; i < mtx_nrows(mig_list); i++) { |
558 |
+ |
const RBFVAL *rbf0i = &mig_list->rbfv[0]->rbfa[i]; |
559 |
+ |
const float peak0 = rbf0i->peak; |
560 |
+ |
const double rad0 = R2ANG(rbf0i->crad); |
561 |
+ |
FVECT v0; |
562 |
+ |
float mv; |
563 |
+ |
ovec_from_pos(v0, rbf0i->gx, rbf0i->gy); |
564 |
+ |
for (j = 0; j < mtx_ncols(mig_list); j++) |
565 |
+ |
if ((mv = mtx_coef(mig_list,i,j)) > FTINY) { |
566 |
+ |
const RBFVAL *rbf1j = &mig_list->rbfv[1]->rbfa[j]; |
567 |
+ |
double rad2; |
568 |
+ |
FVECT v; |
569 |
+ |
int pos[2]; |
570 |
+ |
rad2 = R2ANG(rbf1j->crad); |
571 |
+ |
rad2 = .5*(rad0*rad0 + rad2*rad2); |
572 |
+ |
rbf->rbfa[n].peak = peak0 * mv * rbf->vtotal * |
573 |
+ |
rad0*rad0/rad2; |
574 |
+ |
rbf->rbfa[n].crad = ANG2R(sqrt(rad2)); |
575 |
+ |
ovec_from_pos(v, rbf1j->gx, rbf1j->gy); |
576 |
+ |
geodesic(v, v0, v, .5, GEOD_REL); |
577 |
+ |
pos_from_vec(pos, v); |
578 |
+ |
rbf->rbfa[n].gx = pos[0]; |
579 |
+ |
rbf->rbfa[n].gy = pos[1]; |
580 |
+ |
++n; |
581 |
+ |
} |
582 |
+ |
} |
583 |
+ |
rbf->vtotal *= mig_list->rbfv[0]->vtotal; |
584 |
+ |
nprocs = saved_nprocs; /* final clean-up */ |
585 |
+ |
free(mir_rbf); |
586 |
+ |
free(mig_list); |
587 |
+ |
mig_list = near_rbf->ejl = NULL; |
588 |
+ |
insert_dsf(rbf); /* insert interpolated normal */ |
589 |
+ |
return; |
590 |
+ |
memerr: |
591 |
+ |
fprintf(stderr, "%s: Out of memory in check_normal_incidence()\n", |
592 |
+ |
progname); |
593 |
+ |
exit(1); |
594 |
+ |
} |
595 |
|
|
596 |
|
/* Build our triangle mesh from recorded RBFs */ |
597 |
|
void |
600 |
|
double best2 = M_PI*M_PI; |
601 |
|
RBFNODE *shrt_edj[2]; |
602 |
|
RBFNODE *rbf0, *rbf1; |
603 |
+ |
/* add normal if needed */ |
604 |
+ |
check_normal_incidence(); |
605 |
|
/* check if isotropic */ |
606 |
|
if (single_plane_incident) { |
607 |
|
for (rbf0 = dsf_list; rbf0 != NULL; rbf0 = rbf0->next) |