ScalarFieldTilde SaLSA::chi(const ScalarFieldTilde& phiTilde) const { ScalarFieldTilde rhoTilde; for(int r=rStart; r<rStop; r++) { const MultipoleResponse& resp = *response[r]; const ScalarField& s = resp.iSite<0 ? shape : siteShape[resp.iSite]; if(resp.l>6) die("Angular momenta l > 6 not supported.\n"); double prefac = pow(-1,resp.l) * 4*M_PI/(2*resp.l+1); rhoTilde -= prefac * (resp.V * lDivergence(J(s * I(lGradient(resp.V * phiTilde, resp.l))), resp.l)); } nullToZero(rhoTilde, gInfo); rhoTilde->allReduce(MPIUtil::ReduceSum); return rhoTilde; }
void myCoolBar::drawBackground(QPainter *painter) { painter->save(); QLinearGradient lGradient(QPointF(0,0),QPointF(0,height())); lGradient.setColorAt(1.0,QColor(230,230,230)); lGradient.setColorAt(0.8,QColor(60,60,60)); lGradient.setColorAt(0.2,QColor(60,60,60)); lGradient.setColorAt(0.0,QColor(230,230,230)); painter->setBrush(lGradient); painter->drawRect(this->rect()); painter->restore(); }
double SaLSA::get_Adiel_and_grad_internal(ScalarFieldTilde& Adiel_rhoExplicitTilde, ScalarFieldTilde& Adiel_nCavityTilde, IonicGradient* extraForces, bool electricOnly) const { EnergyComponents& Adiel = ((SaLSA*)this)->Adiel; const ScalarFieldTilde& phi = state; // that's what we solved for in minimize //First-order correct estimate of electrostatic energy: ScalarFieldTilde phiExt = coulomb(rhoExplicitTilde); Adiel["Electrostatic"] = -0.5*dot(phi, O(hessian(phi))) + dot(phi - 0.5*phiExt, O(rhoExplicitTilde)); //Gradient w.r.t rhoExplicitTilde: Adiel_rhoExplicitTilde = phi - phiExt; //The "cavity" gradient is computed by chain rule via the gradient w.r.t to the shape function: const auto& solvent = fsp.solvents[0]; ScalarField Adiel_shape; ScalarFieldArray Adiel_siteShape(solvent->molecule.sites.size()); for(int r=rStart; r<rStop; r++) { const MultipoleResponse& resp = *response[r]; ScalarField& Adiel_s = resp.iSite<0 ? Adiel_shape : Adiel_siteShape[resp.iSite]; if(resp.l>6) die("Angular momenta l > 6 not supported.\n"); double prefac = 0.5 * 4*M_PI/(2*resp.l+1); ScalarFieldArray IlGradVphi = I(lGradient(resp.V * phi, resp.l)); for(int lpm=0; lpm<(2*resp.l+1); lpm++) Adiel_s -= prefac * (IlGradVphi[lpm]*IlGradVphi[lpm]); } for(unsigned iSite=0; iSite<solvent->molecule.sites.size(); iSite++) if(Adiel_siteShape[iSite]) Adiel_shape += I(Sf[iSite] * J(Adiel_siteShape[iSite])); nullToZero(Adiel_shape, gInfo); Adiel_shape->allReduce(MPIUtil::ReduceSum); //Propagate shape gradients to A_nCavity: ScalarField Adiel_nCavity; propagateCavityGradients(Adiel_shape, Adiel_nCavity, Adiel_rhoExplicitTilde, electricOnly); Adiel_nCavityTilde = nFluid * J(Adiel_nCavity); setExtraForces(extraForces, Adiel_nCavityTilde); return Adiel; }
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(); } } }