Exemplo n.º 1
0
static long double  ___yn(int n, double *x)
{
	long double   Sum1;
	long double   Sum2;
	long double   Fact1;
	long double   Fact2;
	long double   F1;
	long double   F2;
	long double   y;
	register int  i;
	double        xx;
	long double   Xi;
	unsigned int  My;

	if (EXPD(x[0]) == 0)
		return -1. / 0.;	/* ignore the gcc warning, this is intentional */

	if ((x[0] >= (n >= 32 ? 25.8 : (n < 8 ? 17.4 + 0.1 * n : 16.2 + 0.3 * n)))) {
		Xi = x[0] - M_PI * (n * 0.5 + 0.25);
		My = n * n << 2;

		return sqrt(M_2_PI / x[0]) * (P(My, x) * sin(Xi) + Q(My, x) * cos(Xi));
	}

	Sum1  = Sum2 = F1 = F2 = 0;
	Fact1 = 1. / (xx = x[0] * 0.5);
	Fact2 = 1.;
	y     = xx * xx;

	for (i = 1; i < n; i++)
		Fact1 *= (n - i) / xx;

	for (i = 1; i <= n; i++) {
		Sum1  += Fact1;
		if (i == n)
			break;
		Fact1 *= y / (i * (n - i));
	}

	for (i = 1; i <= n; i++) {
		Fact2 *= xx / i;
		F1    += 1. / i;
	}

	for (i = 1; ; i++) {
		Sum2  += Fact2 * (F1 + F2);
		Fact2 *= -y / (i * (n + i));
		if (EXPL(Sum2) - EXPL(Fact2) > 53 || !EXPL(Fact2))
			break;
		F1 += 1. / (n + i);
		F2 += 1. / i;
	}

	return M_1_PI * (2. * (M_C + log(xx)) * ___jn(n, x) - Sum1 - Sum2);
}
Exemplo n.º 2
0
void diff_tensor_calc_ewald_beenakker( INT i, INT j, DOUBLE* _tD )
{
    DOUBLE sigma_i = coord[ DIMS1 * j + 3 ];
    DOUBLE sigma_j = coord[ DIMS1 * i + 3 ];
    DOUBLE v[3];
    DOUBLE r[3];
    const DOUBLE sigma_sq = 0.5 * (sigma_i * sigma_i + sigma_j * sigma_j);
    INT k, l;
    DOUBLE Op[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    DOUBLE Qp[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    INT f, g, h;
    const DOUBLE preQ = inv_L[0] * inv_L[0] * inv_L[0];
    dist_vec( coord + i*DIMS1, coord + j*DIMS1, r );

    if ( (r[0] * r[0] + r[1] * r[1] + r[2] * r[2]) < (sigma_i + sigma_j)*(sigma_i + sigma_j) && i != j )
    {
        DOUBLE r_norm, r_sq, e[3];
        get_ev2_norms( r[0], r[1], r[2], e, &r_norm, &r_sq );
        {/*add overlapping Dij*/
            DOUBLE sigma = (sigma_i + sigma_j) / 2;
            DOUBLE pre = preDii / sigma;
            DOUBLE part1 = (1 - (9 * r_norm / (32 * sigma)));
            for ( i = 0; i < 3; ++i )
            {
                _tD[ i + 3 * i ] += pre * (part1 + 3 * e[i] * e[i] * r_norm / (32 * sigma));
                for ( j = 0; j < i; ++j )
                {
                    DOUBLE vval = pre * 3 * e[i] * e[j] * r_norm / (32 * sigma);
                    _tD[ j + 3 * i ] += vval;
                    _tD[ i + 3 * j ] += vval;
                }
            }
        }
        {/*remove none overlapping Dij*/
            DOUBLE pre = preDij / r_norm;
            DOUBLE sigm_r = (sigma_i * sigma_i + sigma_j * sigma_j) / r_sq;
            DOUBLE part1 = 1 + sigm_r / 3;
            for ( i = 0; i < 3; ++i )
            {
                _tD[ i + 3 * i ] -= pre*(part1 + e[i] * e[i]*(1 - sigm_r));
                for ( j = 0; j < i; ++j )
                {
                    DOUBLE vval = pre * e[i] * e[j] * (1 - sigm_r);
                    _tD[ j + 3 * i ] -= vval;
                    _tD[ i + 3 * j ] -= vval;
                }
            }
        }
    }

    v[0] = r[0] * inv_L[0];
    v[1] = r[1] * inv_L[1];
    v[2] = r[2] * inv_L[2];

    for ( h = -ewald_rr; h <= ewald_rr; ++h )
    {
        int next_f = (int)SQRTD( rr_sq - h*h );
        for ( f = -next_f; f <= next_f; ++f )
        {
            int next_g = (int)SQRTD( rr_sq - h*h - f*f );
            for ( g = -next_g; g <= next_g; ++g )
            {

                    DOUBLE r_norm, r_sq, e[3];
                    DOUBLE inv_r, inv_r2, inv_r3;
                    DOUBLE sc, sc2;

                    get_ev2_norms( r[0] + box[0]*h, r[1] + box[0]*f, r[2] + box[0]*g, e, &r_norm, &r_sq );
                    if ( r_norm != 0.0f )
                    {
                        inv_r = 1 / r_norm;
                        inv_r2 = 1 / r_sq;
                        inv_r3 = inv_r*inv_r2;
                        sc = ewald_alpha*sigma_sq*inv_r2;
                        sc += 14*alpha3*sigma_sq;
                        sc += -4.5f*ewald_alpha;
                        sc += -20*alpha2*alpha3*sigma_sq*r_sq;
                        sc += 3*alpha3*r_sq;
                        sc += 4*alpha3*alpha2*alpha2*sigma_sq*r_sq*r_sq;
                        sc *= EXPD(-alpha2*r_sq);
                        sc /= SQRTPI;
                        sc += ERFCD( r_norm * ewald_alpha ) * ( 0.75f*inv_r + 0.5f*sigma_sq*inv_r3);

                        sc2 = -3*ewald_alpha*sigma_sq*inv_r2;
                        sc2 += -2*alpha3*sigma_sq;
                        sc2 += 1.5f*ewald_alpha;
                        sc2 += 16*alpha2*alpha3*sigma_sq*r_sq;
                        sc2 += -3*alpha3*r_sq;
                        sc2 += -4*alpha3*alpha2*alpha2*sigma_sq*r_sq*r_sq;
                        sc2 *= EXPD(-alpha2*r_sq);
                        sc2 /= SQRTPI;
                        sc2 += ERFCD( r_norm * ewald_alpha ) * ( 0.75f*inv_r - 1.5f*sigma_sq*inv_r3);

                        for ( k = 0; k < 3; ++k )
                        {
                            DOUBLE sc_ek = e[k] * sc2;
                            Op[ k * 4 ] += sc + sc_ek * e[k];
                            for ( l = 0; l < k; ++l )
                            {
                                Op[ k + l * 3 ] += e[l] * sc_ek;
                            }
                        }
                    }
                /*recip*/
                    get_ev2_norms( h, f, g, e, &r_norm, &r_sq );
                    if ( r_norm != 0.0f )
                    {
                        r_norm *= 2*M_PIF;
                        r_sq *= 4*M_PIF*M_PIF;
                        sc = 1 - sigma_sq*r_sq/3;
                        sc *= 1 + (inv_alpha2*r_sq/4)*(1+inv_alpha2*r_sq/2);
                        sc *= 6* M_PIF *EXPD(-inv_alpha2*r_sq/4)/r_sq;
                        sc *= cos( 2 * M_PIF * (v[0] * h + v[1] * f + v[2] * g) );
                        for ( k = 0; k < 3; ++k )
                        {
                            DOUBLE sc_ek = sc * e[k];
                            Qp[ k * 4 ] += sc - sc_ek * e[k];
                            for ( l = 0; l < k; ++l )
                            {
                                Qp[ k + l * 3 ] -= e[l] * sc_ek;
                            }
                        }
                    }
            }
        }
    }
    for ( k = 0; k < 3; ++k )
    {
        _tD[ k * 4 ] += preDii * ( Op[k * 4] + preQ * Qp[k * 4] );
        for ( l = 0; l < k; ++l )
        {
            _tD[ k + l * 3 ] += preDii * ( Op[ k + l * 3 ] + preQ * Qp[ k + l * 3 ]);
            _tD[ l + k * 3 ] += preDii * ( Op[ k + l * 3 ] + preQ * Qp[ k + l * 3 ]);
        }
    }
}
Exemplo n.º 3
0
/* divide two doubles */
double
__divdf3 (double a1, double a2)
{
    register union double_long fl1, fl2;
    register long long mask,result;
    register int exp, sign;

    fl1.d = a1;
    fl2.d = a2;

    /* subtract exponents */
    exp = EXPD(fl1) - EXPD(fl2) + EXCESSD;

    /* compute sign */
    sign = SIGND(fl1) ^ SIGND(fl2);

    /* numerator zero??? */
    if (fl1.ll == 0) {
	/* divide by zero??? */
	if (fl2.ll == 0)
	    fl1.ll = ((unsigned long long)1<<63)-1;	/* NaN */
	else
	    fl1.ll = 0;
	goto test_done;
    }

    /* return +Inf or -Inf */
    if (fl2.ll == 0) {
	fl1.ll = PACKD_LL(SIGND(fl1),2047,0);
	goto test_done;
    }


    /* now get mantissas */
    fl1.ll = MANTD_LL(fl1);
    fl2.ll = MANTD_LL(fl2);

    /* this assures we have 54 bits of precision in the end */
    if (fl1.ll < fl2.ll) {
	fl1.ll <<= 1;
	exp--;
    }

    /* now we perform repeated subtraction of fl2.ll from fl1.ll */
    mask = (long long)1<<53;
    result = 0;
    while (mask) {
	if (fl1.ll >= fl2.ll)
	{
	    result |= mask;
	    fl1.ll -= fl2.ll;
	}
	fl1.ll <<= 1;
	mask >>= 1;
    }

    /* round */
    result += 1;

    /* normalize down */
    exp++;
    result >>= 1;

    result &= ~HIDDEND_LL;

    /* pack up and go home */
    fl1.ll = PACKD_LL(sign, exp, result);

test_done:
    return (fl1.d);
}
Exemplo n.º 4
0
void diff_tensor_calc_ewald_smith( INT i, INT j, DOUBLE* _tD )
{
    DOUBLE sigma_i = coord[ DIMS1 * j + 3 ];
    DOUBLE sigma_j = coord[ DIMS1 * i + 3 ];
    DOUBLE v[3];
    const DOUBLE sigma_sq = 0.5 * (sigma_i * sigma_i + sigma_j * sigma_j);
    INT k, l;
    DOUBLE Op[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    DOUBLE Qp[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    INT f, g, h;
    const DOUBLE preQ = 0.5 * sigma_sq * inv_L[0] * inv_L[0] * inv_L[0];
    dist_vec( coord + j*DIMS1, coord + i*DIMS1, v );

    if ( (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) < (sigma_i + sigma_j)*(sigma_i + sigma_j) && i != j )
    {
        DOUBLE r_norm, r_sq, e[3];
        get_ev2_norms( v[0], v[1], v[2], e, &r_norm, &r_sq );
        {/*add overlapping Dij*/
            DOUBLE sigma = (sigma_i + sigma_j) / 2;
            DOUBLE pre = preDii / sigma;
            DOUBLE part1 = (1 - (9 * r_norm / (32 * sigma)));
            for ( i = 0; i < 3; ++i )
            {
                _tD[ i + 3 * i ] += pre * (part1 + 3 * e[i] * e[i] * r_norm / (32 * sigma));
                for ( j = 0; j < i; ++j )
                {
                    DOUBLE vval = pre * 3 * e[i] * e[j] * r_norm / (32 * sigma);
                    _tD[ j + 3 * i ] += vval;
                    _tD[ i + 3 * j ] += vval;
                }
            }
        }
        {/*remove none overlapping Dij*/
            DOUBLE pre = preDij / r_norm;
            DOUBLE sigm_r = (sigma_i * sigma_i + sigma_j * sigma_j) / r_sq;
            DOUBLE part1 = 1 + sigm_r / 3;
            for ( i = 0; i < 3; ++i )
            {
                _tD[ i + 3 * i ] -= pre*(part1 + e[i] * e[i]*(1 - sigm_r));
                for ( j = 0; j < i; ++j )
                {
                    DOUBLE vval = pre * e[i] * e[j] * (1 - sigm_r);
                    _tD[ j + 3 * i ] -= vval;
                    _tD[ i + 3 * j ] -= vval;
                }
            }
        }
    }

    v[0] *= inv_L[0];
    v[1] *= inv_L[1];
    v[2] *= inv_L[2];

    for ( h = -ewald_rr; h <= ewald_rr; ++h )
    {
        int next_f = (int)SQRTD( rr_sq - h*h );
        for ( f = -next_f; f <= next_f; ++f )
        {
            int next_g = (int)SQRTD( rr_sq - h*h - f*f );
            for ( g = -next_g; g <= next_g; ++g )
            {
                
                    DOUBLE r_norm, r_sq, e[3];
                    DOUBLE inv_r;
                    DOUBLE inv_r3;
                    DOUBLE sc;
                    DOUBLE sc2;

                    get_ev2_norms( v[0] + h, v[1] + f, v[2] + g, e, &r_norm, &r_sq );
                    if ( r_norm != 0.0f )
                    {
                        inv_r = 1 / r_norm;
                        inv_r3 = 1 / (r_norm * r_sq);
                        sc = ERFCD( r_norm * ewald_alpha ) * inv_r;
                        sc2 = 2 * ewald_alpha * M1_SQRTPI * EXPD( -alpha2 * r_sq );
                        for ( k = 0; k < 3; ++k )
                        {
                            DOUBLE sc_ek = e[k] * (sc + sc2);
                            Op[ k * 4 ] += sc + sc_ek * e[k];
                            for ( l = 0; l < k; ++l )
                            {
                                Op[ k + l * 3 ] += e[l] * sc_ek;
                            }
                        }
                        sc = inv_r3 * (ERFCD( r_norm * ewald_alpha ) + 2 * ewald_alpha * r_norm * M1_SQRTPI * EXPD( -alpha2 * r_sq ));
                        sc2 = -4 * alpha3 * M1_SQRTPI * EXPD( -alpha2 * r_sq );
                        for ( k = 0; k < 3; ++k )
                        {
                            DOUBLE sc_ek = (-3 * sc + sc2) * e[k];
                            Qp[ k * 4 ] += sc + sc_ek * e[k];
                            for ( l = 0; l < k; ++l )
                            {
                                Qp[ k + l * 3 ] += e[l] * sc_ek;
                            }
                        }
                    }
                /*recip*/
                    get_ev2_norms( h, f, g, e, &r_norm, &r_sq );
                    if ( r_norm != 0.0f )
                    {
                        sc = 2 * EXPD( M_PI_ALPHA_SQ * r_sq ) / (M_PIF * r_sq);
                        sc2 = -1 + M_PI_ALPHA_SQ * r_sq;
                        sc *= cos( 2 * M_PIF * (v[0] * h + v[1] * f + v[2] * g) );
                        sc2 *= sc;
                        for ( k = 0; k < 3; ++k )
                        {
                            DOUBLE sc_ek = sc2 * e[k];
                            Op[ k * 4 ] += sc + sc_ek * e[k];
                            for ( l = 0; l < k; ++l )
                            {
                                Op[ k + l * 3 ] += e[l] * sc_ek;
                            }
                        }
                        sc = 4 * M_PIF * EXPD( M_PI_ALPHA_SQ * r_sq );
                        sc *= cos( 2 * M_PIF * (v[0] * h + v[1] * f + v[2] * g) );
                        for ( k = 0; k < 3; ++k )
                        {
                            DOUBLE sc_ek = sc * e[k];
                            Qp[ k * 4 ] += sc_ek * e[k];
                            for ( l = 0; l < k; ++l )
                            {
                                Qp[ k + l * 3 ] += e[l] * sc_ek;
                            }
                        }
                    }
            }
        }
    }
    for ( k = 0; k < 3; ++k )
    {
        _tD[ k * 4 ] += preDii * (preO * Op[k * 4] + preQ * Qp[k * 4]);
        for ( l = 0; l < k; ++l )
        {
            _tD[ k + l * 3 ] += preDii * (preO * Op[ k + l * 3 ] + preQ * Qp[ k + l * 3 ]);
            _tD[ l + k * 3 ] += preDii * (preO * Op[ k + l * 3 ] + preQ * Qp[ k + l * 3 ]);
        }
    }
}