Ejemplo n.º 1
0
void Points::GenerateKernel(int L, int point_count, std::string title)
{

    int g=point_count, m=0;

    LEGENDRE P_lm;
    LEGENDRE Y_P;
    LEGENDRE dP_lm;

    std::vector<std::vector<double> > d_kern(g); //kernel for derivative reconstruction
    std::vector<std::vector<double> > f_kern(g); //kernel for function (test) reconstruction
    std::vector<std::vector<double> > WT(g);

    std::complex<double> Y(0,0), Ylm(0,0), dYlm(0,0), Ymp1(0,0), ej(0,0), function(0,0), derivative(0,0);
    std::complex<double> im(0,1);

    double th1=0, ph1=0, sign=0;



    std::cout << title << std::endl;
    std::ofstream kernel(title);
    kernel.precision(15);




    for(int i=0; i<g; i++)
    {
        d_kern[i].resize(g);
        f_kern[i].resize(g);
        WT[i].resize(g);

        for(int j=0; j<g; j++)
        {
            for(double l=0; l<=L; l++)
            {
                for(double m_it=0; m_it<=(2*l); m_it++)
                {

                    m=0;

                    m = l-m_it;

                    //std::cout << "m = " <<  m << ", l = " << l <<  std::endl;

                    ej = m;
                    sign=pow(-1.0,m_it);

                    std::complex<double> exponential_prime(cos( Points::Phi[i]), (-1)*sin(Points::Phi[i]));
                    std::complex<double> exponential(cos(m*Points::Phi[j]), sin(m*Points::Phi[j]));


                    Ylm = P_lm.Yml(m, l, Points::Theta[i], Points::Phi[i]);
                    Y = Y_P.Yml(m, l, Points::Theta[j], Points::Phi[j]);

                    if( Theta[i] != 0 && ((m+1)<=l) )
                    {
                        Ymp1 = m * (1.0/tan(Points::Theta[i])) * dP_lm.Yml(m, l, Points::Theta[i], Points::Phi[i]) + sqrt( (l-m)*(l+m+1) ) * exponential_prime * dP_lm.Yml(m+1, l, Points::Theta[i], Points::Phi[i]);

                    }

                    ///fill arrays with f=Y*Y for the function kernel and derivative kernel

                    f_kern[i][j] += (conj(Y)*Ylm).real();//Y_real*Y_prime_real;
                    d_kern[i][j] += (conj(Y)*Ymp1).real();

                }

            }

            ///absorb weights into kernel

            WT[i][j] = Points::Weight[j]*4.0*PI;
            kernel << d_kern[i][j]*Points::Weight[j]*4.0*PI  << "      " << f_kern[i][j]*Points::Weight[j]*4.0*PI << "      " << WT[i][j] << std::endl;

        }
    }

    kernel.close();

}
Ejemplo n.º 2
0
void SaLSA::dumpDensities(const char* filenamePattern) const
{	PCM::dumpDensities(filenamePattern);
	
	//Dump effective site densities:
	double chiRot = 0., chiPol = 0.;
	for(const auto& c: fsp.components)
	{	chiRot += c->Nbulk * c->molecule.getDipole().length_squared()/(3.*fsp.T);
		chiPol += c->Nbulk * c->molecule.getAlphaTot();
	}
	double sqrtCrot = (epsBulk>epsInf && chiRot) ? sqrt((epsBulk-epsInf)/(4.*M_PI*chiRot)) : 1.;
	const double bessel_jl_by_Gl_zero[4] = {1., 1./3, 1./15, 1./105}; //G->0 limit of j_l(G)/G^l
	
	for(const auto& c: fsp.components)
	{	ScalarFieldTildeArray Ntilde(c->molecule.sites.size());
		for(int l=0; l<=fsp.lMax; l++)
		{	double prefac = sqrt(4.*M_PI*c->Nbulk/fsp.T) * (l==1 ? sqrtCrot : 1.);
			for(int m=-l; m<=+l; m++)
			{	const double dG = 0.02, Gmax = gInfo.GmaxGrid;
				unsigned nGradial = unsigned(ceil(Gmax/dG))+5;
				std::vector<double> VtotSamples(nGradial);
				std::vector< std::vector<double> > VsiteSamples(c->molecule.sites.size(), std::vector<double>(nGradial));
				for(unsigned iG=0; iG<nGradial; iG++)
				{	double G = iG*dG;
					for(unsigned iSite=0; iSite<c->molecule.sites.size(); iSite++)
					{	const auto& site = c->molecule.sites[iSite];
						for(const vector3<>& r: site->positions)
						{	double rLength = r.length();
							double bessel_jl_by_Gl = G ? bessel_jl(l,G*rLength)/pow(G,l) : bessel_jl_by_Gl_zero[l]*pow(rLength,l);
							vector3<> rHat = (rLength ? 1./rLength : 0.) * r;
							double Ylm_rHat = Ylm(l, m, rHat);
							VtotSamples[iG] += prefac * site->chargeKernel(G) * bessel_jl_by_Gl * Ylm_rHat;
							VsiteSamples[iSite][iG] += prefac * bessel_jl_by_Gl * Ylm_rHat;
						}
					}
				}
				
				RadialFunctionG Vtot; Vtot.init(0, VtotSamples, dG);
				ScalarFieldTilde temp = lDivergence(J(shape * I(lGradient(Vtot * state, l))), l);
				Vtot.free();
				for(unsigned iSite=0; iSite<c->molecule.sites.size(); iSite++)
				{	RadialFunctionG Vsite; Vsite.init(0, VsiteSamples[iSite], dG);
					Ntilde[iSite] -= (pow(-1,l) * 4*M_PI/(2*l+1)) * (Vsite * temp);
					Vsite.free();
				}
			}
		}
		char filename[256]; 
		for(unsigned j=0; j<c->molecule.sites.size(); j++)
		{	
			const Molecule::Site& s = *(c->molecule.sites[j]);
			ScalarField N;
			N=I(Ntilde[j])+c->Nbulk*siteShape[j];
			ostringstream oss; oss << "N_" << c->molecule.name;
			if(c->molecule.sites.size()>1) oss << "_" << s.name;
			sprintf(filename, filenamePattern, oss.str().c_str());
			logPrintf("Dumping %s... ", filename); logFlush();
			if(mpiUtil->isHead()) saveRawBinary(N, filename);
			{
				//debug sphericalized site densities
				ostringstream oss; oss << "Nspherical_" << c->molecule.name;
				if(c->molecule.sites.size()>1) oss << "_" << s.name;
				sprintf(filename, filenamePattern, oss.str().c_str());
				saveSphericalized(&N,1,filename);
			}
			logPrintf("Done.\n"); logFlush();
		}
	}
}
Ejemplo n.º 3
0
SaLSA::SaLSA(const Everything& e, const FluidSolverParams& fsp)
: PCM(e, fsp), siteShape(fsp.solvents[0]->molecule.sites.size())
{	
	logPrintf("   Initializing non-local response weight functions:\n");
	const double dG = gInfo.dGradial, Gmax = gInfo.GmaxGrid;
	unsigned nGradial = unsigned(ceil(Gmax/dG))+5;

	//Initialize fluid molecule's spherically-averaged electron density kernel:
	const auto& solvent = fsp.solvents[0];
	std::vector<double> nFluidSamples(nGradial);
	for(unsigned i=0; i<nGradial; i++)
	{	double G = i*dG;
		nFluidSamples[i] = 0.;
		for(const auto& site: solvent->molecule.sites)
		{	double nTilde = site->elecKernel(G);
			for(const vector3<>& r: site->positions)
				nFluidSamples[i] += nTilde * bessel_jl(0, G*r.length());
		}
	}
	nFluid.init(0, nFluidSamples, dG);
	
	//Determine dipole correlation factors:
	double chiRot = 0., chiPol = 0.;
	for(const auto& c: fsp.components)
	{	chiRot += c->Nbulk * c->molecule.getDipole().length_squared()/(3.*fsp.T);
		chiPol += c->Nbulk * c->molecule.getAlphaTot();
	}
	double sqrtCrot = (epsBulk>epsInf && chiRot) ? sqrt((epsBulk-epsInf)/(4.*M_PI*chiRot)) : 1.;
	double epsInfEff = chiRot ? epsInf : epsBulk; //constrain to epsBulk for molecules with no rotational susceptibility
	double sqrtCpol = (epsInfEff>1. && chiPol) ? sqrt((epsInfEff-1.)/(4.*M_PI*chiPol)) : 1.;
	
	//Rotational and translational response (includes ionic response):
	const double bessel_jl_by_Gl_zero[4] = {1., 1./3, 1./15, 1./105}; //G->0 limit of j_l(G)/G^l
	for(const auto& c: fsp.components)
		for(int l=0; l<=fsp.lMax; l++)
		{	//Calculate radial densities for all m:
			gsl_matrix* V = gsl_matrix_calloc(nGradial, 2*l+1); //allocate and set to zero
			double prefac = sqrt(4.*M_PI*c->Nbulk/fsp.T);
			for(unsigned iG=0; iG<nGradial; iG++)
			{	double G = iG*dG;
				for(const auto& site: c->molecule.sites)
				{	double Vsite = prefac * site->chargeKernel(G);
					for(const vector3<>& r: site->positions)
					{	double rLength = r.length();
						double bessel_jl_by_Gl = G ? bessel_jl(l,G*rLength)/pow(G,l) : bessel_jl_by_Gl_zero[l]*pow(rLength,l);
						vector3<> rHat = (rLength ? 1./rLength : 0.) * r;
						for(int m=-l; m<=+l; m++)
							*gsl_matrix_ptr(V,iG,l+m) += Vsite * bessel_jl_by_Gl * Ylm(l,m, rHat);
					}
				}
			}
			//Scale dipole active modes:
			for(int lm=0; lm<2l+1; lm++)
				if(l==1 && fabs(gsl_matrix_get(V,0,lm))>1e-6)
					for(unsigned iG=0; iG<nGradial; iG++)
						*gsl_matrix_ptr(V,iG,lm) *= sqrtCrot;
			//Get linearly-independent non-zero modes by performing an SVD:
			gsl_vector* S = gsl_vector_alloc(2*l+1);
			gsl_matrix* U = gsl_matrix_alloc(2*l+1, 2*l+1);
			gsl_matrix* tmpMat = gsl_matrix_alloc(2*l+1, 2*l+1);
			gsl_vector* tmpVec = gsl_vector_alloc(2*l+1);
			gsl_linalg_SV_decomp_mod(V, tmpMat, U, S, tmpVec);
			gsl_vector_free(tmpVec);
			gsl_matrix_free(tmpMat);
			gsl_matrix_free(U);
			//Add response functions for non-singular modes:
			for(int mode=0; mode<2*l+1; mode++)
			{	double Smode = gsl_vector_get(S, mode);
				if(Smode*Smode < 1e-3) break;
				std::vector<double> Vsamples(nGradial);
				for(unsigned iG=0; iG<nGradial; iG++)
					Vsamples[iG] = Smode * gsl_matrix_get(V, iG, mode);
				response.push_back(std::make_shared<MultipoleResponse>(l, -1, 1, Vsamples, dG));
			}
			gsl_vector_free(S);
			gsl_matrix_free(V);
		}
	
	//Polarizability response:
	for(unsigned iSite=0; iSite<solvent->molecule.sites.size(); iSite++)
	{	const Molecule::Site& site = *(solvent->molecule.sites[iSite]);
		if(site.polKernel)
		{	std::vector<double> Vsamples(nGradial);
			double prefac = sqrtCpol * sqrt(solvent->Nbulk * site.alpha);
			for(unsigned iG=0; iG<nGradial; iG++)
				Vsamples[iG] = prefac * site.polKernel(iG*dG);
			response.push_back(std::make_shared<MultipoleResponse>(1, iSite, site.positions.size(), Vsamples, dG));
		}
	}
	
	const double GzeroTol = 1e-12;
	
	//Compute bulk properties and print summary:
	double epsBulk = 1.; double k2factor = 0.; std::map<int,int> lCount;
	for(const std::shared_ptr<MultipoleResponse>& resp: response)
	{	lCount[resp->l]++;
		double respGzero = (4*M_PI) * pow(resp->V(0), 2) * resp->siteMultiplicity;
		if(resp->l==0) k2factor += respGzero;
		if(resp->l==1) epsBulk += respGzero;
	}
	for(auto lInfo: lCount)
		logPrintf("      l: %d  #weight-functions: %d\n", lInfo.first, lInfo.second);
	logPrintf("   Bulk dielectric-constant: %lg", epsBulk);
	if(k2factor > GzeroTol) logPrintf("   screening-length: %lg bohrs.\n", sqrt(epsBulk/k2factor));
	else logPrintf("\n");
	if(fsp.lMax >= 1) myassert(fabs(epsBulk-this->epsBulk) < 1e-3); //verify consistency of correlation factors
	myassert(fabs(k2factor-this->k2factor) < 1e-3); //verify consistency of site charges
	
	//Initialize preconditioner kernel:
	std::vector<double> KkernelSamples(nGradial);
	for(unsigned i=0; i<nGradial; i++)
	{	double G = i*dG, G2=G*G;
		//Compute diagonal part of the hessian ( 4pi(Vc^-1 + chi) ):
		double diagH = G2;
		for(const auto& resp: response)
			diagH += pow(G2,resp->l) * pow(resp->V(G), 2);
		//Set its inverse square-root as the preconditioner:
		KkernelSamples[i] = (diagH>GzeroTol) ? 1./sqrt(diagH) : 0.;
	}
	Kkernel.init(0, KkernelSamples, dG);
	
	//MPI division:
	TaskDivision(response.size(), mpiUtil).myRange(rStart, rStop);
}
Ejemplo n.º 4
0
/*******************************************************************************
 ** Compute complex q_lm (sum over eq. 3 from Stukowski paper), for each atom
 *******************************************************************************/
static void complex_qlm(int NVisibleIn, int *visibleAtoms, struct NeighbourList *nebList, double *pos, double *cellDims,
        int *PBC, struct AtomStructureResults *results)
{
    int visIndex;


    /* loop over atoms */
    #pragma omp parallel for num_threads(prefs_numThreads)
    for (visIndex = 0; visIndex < NVisibleIn; visIndex++)
    {
        int index, m;
        double xpos1, ypos1, zpos1;

        /* atom 1 position */
        index = visibleAtoms[visIndex];
        xpos1 = pos[3*index];
        ypos1 = pos[3*index+1];
        zpos1 = pos[3*index+2];

        /* loop over m, l = 6 */
        for (m = -6; m < 7; m++)
        {
            int i;
            double real_part, img_part;

            /* loop over neighbours */
            real_part = 0.0;
            img_part = 0.0;
            for (i = 0; i < nebList[visIndex].neighbourCount; i++)
            {
                int visIndex2, index2;
                double xpos2, ypos2, zpos2, sepVec[3];
                double theta, phi, realYlm, complexYlm;

                /* atom 2 position */
                visIndex2 = nebList[visIndex].neighbour[i];
                index2 = visibleAtoms[visIndex2];
                xpos2 = pos[3*index2];
                ypos2 = pos[3*index2+1];
                zpos2 = pos[3*index2+2];

                /* calculate separation vector between atoms */
                atomSeparationVector(sepVec, xpos1, ypos1, zpos1, xpos2, ypos2, zpos2, cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);

                /* convert to spherical coordinates */
                convertToSphericalCoordinates(sepVec[0], sepVec[1], sepVec[2], nebList[visIndex].neighbourSep[i], &phi, &theta);

                /* calculate Ylm */
                if (m < 0)
                {
                    Ylm(6, abs(m), theta, phi, &realYlm, &complexYlm);
                    realYlm = pow(-1.0, m) * realYlm;
                    complexYlm = pow(-1.0, m) * complexYlm;
                }
                else
                {
                    Ylm(6, m, theta, phi, &realYlm, &complexYlm);
                }

                /* sum */
                real_part += realYlm;
                img_part += complexYlm;
            }

            /* divide by number of neighbours */
            results[visIndex].realQ6[m+6] = real_part / ((double) nebList[visIndex].neighbourCount);
            results[visIndex].imgQ6[m+6] = img_part / ((double) nebList[visIndex].neighbourCount);
        }

        /* loop over m, l = 4 */
        for (m = -4; m < 5; m++)
        {
            int i;
            double real_part, img_part;

            /* loop over neighbours */
            real_part = 0.0;
            img_part = 0.0;
            for (i = 0; i < nebList[visIndex].neighbourCount; i++)
            {
                int visIndex2, index2;
                double xpos2, ypos2, zpos2, sepVec[3];
                double theta, phi, realYlm, complexYlm;

                /* atom 2  position */
                visIndex2 = nebList[visIndex].neighbour[i];
                index2 = visibleAtoms[visIndex2];
                xpos2 = pos[3*index2];
                ypos2 = pos[3*index2+1];
                zpos2 = pos[3*index2+2];

                /* calculate separation vector */
                atomSeparationVector(sepVec, xpos1, ypos1, zpos1, xpos2, ypos2, zpos2, cellDims[0], cellDims[1], cellDims[2], PBC[0], PBC[1], PBC[2]);

                /* convert to spherical coordinates */
                convertToSphericalCoordinates(sepVec[0], sepVec[1], sepVec[2], nebList[visIndex].neighbourSep[i], &phi, &theta);

                /* calculate Ylm */
                if (m < 0)
                {
                    Ylm(4, abs(m), theta, phi, &realYlm, &complexYlm);
                    realYlm = pow(-1.0, m) * realYlm;
                    complexYlm = pow(-1.0, m) * complexYlm;
                }
                else
                {
                    Ylm(4, m, theta, phi, &realYlm, &complexYlm);
                }

                /* sum */
                real_part += realYlm;
                img_part += complexYlm;
            }

            /* divide by number of neighbours */
            results[visIndex].realQ4[m+4] = real_part / ((double) nebList[visIndex].neighbourCount);
            results[visIndex].imgQ4[m+4] = img_part / ((double) nebList[visIndex].neighbourCount);
        }
    }
}