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));
}
Пример #2
0
 // 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();
 }