double DLL_FUNC integrated_refraction( const double latitude, const double observed_alt, const double wavelength_microns, const double height_in_meters, const double rel_humid_pct, const double temp_kelvins, const double pressure_mb) { const double g_bar = 9.784 * (1. - .0026 * cos( 2. * latitude) - 2.8e-7 * height_in_meters); /* (3.281-4) */ const double Pw0 = rel_humid_pct * pow( temp_kelvins / 247.1, delta) / 100.; const double l2 = wavelength_microns * wavelength_microns; const double A = (273.15e-6 / 1013.25) * (287.607 + 1.6288 / l2 + .0136 / (l2 * l2)); REFRACT ref; double c5, rval; LOCALS l0, lt, ls; ref.r0 = re + height_in_meters; ref.c2 = g_bar * Md / R; ref.gamma = ref.c2 / alpha; /* = C3 */ c5 = Pw0 * (1. - Mw / Md) * ref.gamma / (delta - ref.gamma); ref.c6 = A * (pressure_mb + c5) / temp_kelvins; ref.c7 = (A * c5 + 11.2684e-6 * Pw0) / temp_kelvins; ref.c8 = alpha * (ref.gamma - 1.) * ref.c6 / temp_kelvins; ref.c9 = alpha * (delta - 1.) * ref.c7 / temp_kelvins; ref.temp_0 = temp_kelvins; l0.r = ref.r0; compute_refractive_index( &ref, &l0, 1); l0.z = PI / 2. - observed_alt; compute_integrand( &l0); lt.r = rt; compute_refractive_index( &ref, <, 1); lt.z = asin( l0.n * ref.r0 * sin( l0.z) / (lt.n * rt)); /* (3.281-9) */ compute_integrand( <); ref.nt = lt.n; ref.n0_r0_sin_z0 = l0.n * l0.r * sin( l0.z); rval = total_refraction( &ref, &l0, <, 1, 0); /* Now for the stratospheric portion... we need to recompute */ /* dn/dr at the tropopause, because there's a discontinuity */ /* in the derivative as r crosses that point; which also */ /* means we gotta recompute the integrand at r = rt. So: */ compute_refractive_index( &ref, <, 0); compute_integrand( <); ls.r = rs; compute_refractive_index( &ref, &ls, 0); ls.z = asin( ls.n * ref.r0 * sin( l0.z) / (ls.n * rs)); compute_integrand( &ls); return( rval + total_refraction( &ref, <, &ls, 0, 0)); }
float LineEnergy::calc_energy() { // The surface energy of a simple torus is the path integral of the square // of the principal curvatures along the arm (as opposed to around it). double energy = 0.0; int numPoints = torus->getNumControlPoints(); double dt = 1.0/numPoints; for (int v = 0; v < numPoints; v++) { energy += compute_integrand(((double) v)/numPoints, dt); } double twist = torus->getGlobalTwist() * PI / 180; energy += twist_weight * (twist*twist); return (float) energy; }
static double total_refraction( const REFRACT *ref, const LOCALS *l1, const LOCALS *l2, const int is_troposphere, const int recursion_depth) { LOCALS mid; double change; const double iteration_limit = 1.; /* get 'r' within a meter */ const double integration_tolerance = .0001; const int max_recursion_depth = 20; mid.z = (l1->z + l2->z) * .5; mid.r = (l1->r + l2->r) * .5; do { compute_refractive_index( ref, &mid, is_troposphere); change = -(mid.n * mid.r - ref->n0_r0_sin_z0 / sin( mid.z)); change /= mid.n + mid.r * mid.dn_dr; /* (3.281-5) */ mid.r += change; } while( fabs( change) > iteration_limit); compute_integrand( &mid); /* Compute difference between a Simpson's rule integration */ /* and a trapezoidal one... */ change = 2. * mid.integrand - (l1->integrand + l2->integrand); // if( recursion_depth >= max_recursion_depth) // printf( "!!! recursed too deep\n"); /* ...and if it's too great, recurse with each half: */ if( fabs( change) > integration_tolerance && recursion_depth < max_recursion_depth) return( total_refraction( ref, l1, &mid, is_troposphere, recursion_depth + 1) + total_refraction( ref, &mid, l2, is_troposphere, recursion_depth + 1)); else { /* Simpson's rule is good enough: */ const double h = (l2->z - l1->z) / 6.; return( h * (4. * mid.integrand + l1->integrand + l2->integrand)); } }