const Real GreensFunction2DAbs::p_int_theta_second(const Real r, const Real theta, const Real t) const { const Real r_0(this->getr0()); const Real a(this->geta()); const Real minusDt(-1e0 * this->getD() * t); const Integer num_in_term_use(100); const Integer num_out_term_use(100); const Real threshold(CUTOFF); Real sum(0e0); Real term(0e0); Integer n(1); for(; n < num_out_term_use; ++n) { Real in_sum(0e0); Real in_term(0e0); Real in_term1(0e0); Real in_term2(0e0); Real in_term3(0e0); Real a_alpha_mn(0e0); Real alpha_mn(0e0); Real Jn_r_alpha_mn(0e0); Real Jn_r0_alpha_mn(0e0); Real Jn_d_1_a_alpha_mn(0e0);// J_n-1(a alpha_mn) Real Jn_p_1_a_alpha_mn(0e0);// J_n+1(a alpha_mn) Real n_real(static_cast<double>(n)); int n_int(static_cast<int>(n)); Integer m(1); for(; m < num_in_term_use; ++m) { a_alpha_mn = gsl_sf_bessel_zero_Jnu(n_real, m); alpha_mn = a_alpha_mn / a; Jn_r_alpha_mn = gsl_sf_bessel_Jn(n_int, r * alpha_mn); Jn_r0_alpha_mn = gsl_sf_bessel_Jn(n_int, r_0 * alpha_mn); Jn_d_1_a_alpha_mn = gsl_sf_bessel_Jn(n_int - 1, a_alpha_mn); Jn_p_1_a_alpha_mn = gsl_sf_bessel_Jn(n_int + 1, a_alpha_mn); in_term1 = std::exp(alpha_mn * alpha_mn * minusDt); in_term2 = Jn_r_alpha_mn * Jn_r0_alpha_mn; in_term3 = Jn_d_1_a_alpha_mn - Jn_p_1_a_alpha_mn; in_term = in_term1 * in_term2 / (in_term3 * in_term3); in_sum += in_term; // std::cout << "inner sum " << in_sum << ", term" << in_term << std::endl; if(fabs(in_term/in_sum) < threshold) { // std::cout << "normal exit. m = " << m << " second term" << std::endl; break; } } if(m == num_in_term_use) std::cout << "warning: use term over num_in_term_use" << std::endl; // term = in_sum * std::cos(n_real * theta); term = in_sum * std::sin(n_real * theta) / n_real; sum += term; // std::cout << "outer sum " << sum << ", term" << term << std::endl; if(fabs(in_sum / (n_real * sum)) < threshold) { /* if n * theta is a multiple of \pi, the term may be zero and * * term/sum become also zero. this is a problem. sin is in a * * regeon [-1, 1], so the order of term does not depend on * * value of sin, so this considers only (in_sum / n_real). */ // std::cout << "normal exit. n = " << n << " second term" << std::endl; break; } } if(n == num_out_term_use) std::cout << "warning: use term over num_out_term_use" << std::endl; return (8e0 * sum / (M_PI * a * a)); }
// http://www.uoxray.uoregon.edu/tnt/manual/node104.html // http://lists.bioxray.dk/pipermail/o-info/2002/001921.html void write_dsn6_map( std::string const& file_name, cctbx::uctbx::unit_cell const& unit_cell, af::int3 const& gridding_first, af::int3 const& gridding_last, af::const_ref<double, af::c_grid_padded_periodic<3> > const& map_data) { af::double6 const& unit_cell_parameters = unit_cell.parameters(); af::tiny<int, 3> n_real(af::adapt(map_data.accessor().focus())); int dim[3]; for (unsigned i = 0; i < 3; i++) { dim[i] = (gridding_last[i] - gridding_first[i] + 1); } double rho_max = 0, rho_min = 2.e16; for (unsigned i = 0; i < map_data.size(); i++) { double rho = map_data[i]; if (rho > rho_max) rho_max = rho; if (rho < rho_min) rho_min = rho; } int i1 = 80; //, i2 = 100; for (unsigned i = 0; i < 6; i++) { double param = unit_cell_parameters[i]; if (i1 * param > 32760) { i1 = std::min(i1, int (32760 / (float) ((int) (0.999 + param)))); i1 = std::max(1, i1); } } double rho_range = rho_max - rho_min; IOTBX_ASSERT(rho_range > 0); std::ofstream mapfile(file_name.c_str(), std::ios::out | std::ios::binary); // origin for (unsigned i = 0; i < 3; i++) { short n = static_cast<short>(gridding_first[i]); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // extent for (unsigned i = 0; i < 3; i++) { short n = static_cast<short>(dim[i]); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // unit cell grid dimensions for (unsigned i = 0; i < 3; i++) { short n = static_cast<short>(n_real[i]); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // unit cell parameters for (unsigned i = 0; i < 6; i++) { short n = static_cast<short>(i1 * unit_cell_parameters[i]); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // header(16) double header_16 = 100 * 250 / rho_range; { short n = static_cast<short>(header_16); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // header(17) double header_17 = (3*rho_max - 253*rho_min) / rho_range; { short n = static_cast<short>(header_17); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // header(18) - unit cell scaling factor { short n = static_cast<short>(i1); SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } // header(19) - just 100 { short n = 100; SWAP_BYTES_INTEGER(n); mapfile.write((char *) &n, 2); } for (unsigned i = 20; i <= 256; i++) { char n = 0; mapfile.write(&n, 1); mapfile.write(&n, 1); } // END of header int n_blocks[3]; for (unsigned i = 0; i < 3; i++) { n_blocks[i] = (int) std::ceil(((float) dim[i]) / 8.0); } char brick[512]; char brick_swapped[512]; double scale_factor = header_16 / 100; for (int zz = 0; zz < n_blocks[2]; zz++) { for (int yy = 0; yy < n_blocks[1]; yy++) { for (int xx = 0; xx < n_blocks[0]; xx++) { unsigned i_byte = 0; for (int z = 0; z < 8; z++) { for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { int i = (xx * 8) + x + gridding_first[0]; int j = (yy * 8) + y + gridding_first[1]; int k = (zz * 8) + z + gridding_first[2]; double rho = map_data(i,j,k); double rho_scaled = (rho - rho_min) * scale_factor; char rhoc = static_cast<char>(rho_scaled); brick[i_byte++] = rhoc; }}} IOTBX_ASSERT(i_byte == 512); // XXX not sure about the byte swapping here, but this was // necessary to be able to read DSN6 maps from the EDS... for (unsigned i = 0; i < 256; i++) { brick_swapped[i*2] = brick[(i*2)+1]; brick_swapped[(i*2)+1] = brick[i*2]; } mapfile.write(brick_swapped, 512); }}} mapfile.close(); }