From c1b477a1b2b796617c4e345a7296a8d429d7a067 Mon Sep 17 00:00:00 2001 From: Ian Jauslin Date: Sun, 26 Feb 2023 18:36:05 -0500 Subject: Update to v0.4 feature: compute the 2-point correlation function in easyeq. feature: compute the Fourier transform of the 2-point correlation function in anyeq and easyeq. feature: compute the local maximum of the 2-point correlation function and its Fourier transform. feature: compute the compressibility for anyeq. feature: allow for linear spacing of rho's. feature: print the scattering length. change: ux and uk now return real numbers. fix: error in the computation of the momentum distribution: wrong definition of delta functions. fix: various minor bugs. optimization: assign explicit types to variables. --- src/easyeq.jl | 1040 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 854 insertions(+), 186 deletions(-) (limited to 'src/easyeq.jl') diff --git a/src/easyeq.jl b/src/easyeq.jl index 0bde3ab..2dbbd1a 100644 --- a/src/easyeq.jl +++ b/src/easyeq.jl @@ -1,4 +1,4 @@ -## Copyright 2021 Ian Jauslin +## Copyright 2021-2023 Ian Jauslin ## ## Licensed under the Apache License, Version 2.0 (the "License"); ## you may not use this file except in compliance with the License. @@ -19,47 +19,65 @@ end # compute energy -function easyeq_energy(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,approx) +function easyeq_energy( + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) # compute gaussian quadrature weights weights=gausslegendre(order) - # compute initial guess from previous rho - (u,E,err)=easyeq_hatu(easyeq_init_u(a0,order,weights),order,(10.)^minlrho_init,v,maxiter,tolerance,weights,approx) - for j in 2:nlrho_init - rho_tmp=10^(minlrho_init+(log10(rho)-minlrho_init)*(j-1)/(nlrho_init-1)) - (u,E,err)=easyeq_hatu(u,order,rho_tmp,v,maxiter,tolerance,weights,approx) - end + # compute u + (u,E,err)= easyeq_compute_u_prevrho([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) # print energy @printf("% .15e % .15e\n",real(E),err) end # compute energy as a function of rho -function easyeq_energy_rho(rhos,order,a0,v,maxiter,tolerance,approx) +function easyeq_energy_rho( + rhos::Array{Float64,1}, + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) # compute gaussian quadrature weights weights=gausslegendre(order) - # init u - u=easyeq_init_u(a0,order,weights) + # compute u + (us,es,errs)= easyeq_compute_u_prevrho(rhos,minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) for j in 1:length(rhos) - # compute u (init newton with previously computed u) - (u,E,err)=easyeq_hatu(u,order,rhos[j],v,maxiter,tolerance,weights,approx) - - @printf("% .15e % .15e % .15e\n",rhos[j],real(E),err) - + @printf("% .15e % .15e % .15e\n",rhos[j],real(es[j]),errs[j]) end end # compute u(k) -function easyeq_uk(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,approx) +function easyeq_uk( + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) weights=gausslegendre(order) - # compute initial guess from previous rho - (u,E,err)=easyeq_hatu(easyeq_init_u(a0,order,weights),order,(10.)^minlrho_init,v,maxiter,tolerance,weights,approx) - for j in 2:nlrho_init - rho_tmp=10^(minlrho_init+(log10(rho)-minlrho_init)*(j-1)/(nlrho_init-1)) - (u,E,err)=easyeq_hatu(u,order,rho_tmp,v,maxiter,tolerance,weights,approx) - end + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) for i in 1:order k=(1-weights[1][i])/(1+weights[1][i]) @@ -68,15 +86,24 @@ function easyeq_uk(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,appr end # compute u(x) -function easyeq_ux(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,xmin,xmax,nx,approx) +function easyeq_ux( + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + xmin::Float64, + xmax::Float64, + nx::Int64, + approx::Easyeq_approx +) weights=gausslegendre(order) - # compute initial guess from previous rho - (u,E,err)=easyeq_hatu(easyeq_init_u(a0,order,weights),order,(10.)^minlrho_init,v,maxiter,tolerance,weights,approx) - for j in 2:nlrho_init - rho_tmp=10^(minlrho_init+(log10(rho)-minlrho_init)*(j-1)/(nlrho_init-1)) - (u,E,err)=easyeq_hatu(u,order,rho_tmp,v,maxiter,tolerance,weights,approx) - end + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) for i in 1:nx x=xmin+(xmax-xmin)*i/nx @@ -85,15 +112,24 @@ function easyeq_ux(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,xmin end # compute 2u(x)-rho u*u(x) -function easyeq_uux(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,xmin,xmax,nx,approx) +function easyeq_uux( + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + xmin::Float64, + xmax::Float64, + nx::Int64, + approx::Easyeq_approx +) weights=gausslegendre(order) - # compute initial guess from previous rho - (u,E,err)=easyeq_hatu(easyeq_init_u(a0,order,weights),order,(10.)^minlrho_init,v,maxiter,tolerance,weights,approx) - for j in 2:nlrho_init - rho_tmp=10^(minlrho_init+(log10(rho)-minlrho_init)*(j-1)/(nlrho_init-1)) - (u,E,err)=easyeq_hatu(u,order,rho_tmp,v,maxiter,tolerance,weights,approx) - end + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) for i in 1:nx x=xmin+(xmax-xmin)*i/nx @@ -102,16 +138,22 @@ function easyeq_uux(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,xmi end # condensate fraction -function easyeq_condensate_fraction(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,approx) +function easyeq_condensate_fraction( + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) # compute gaussian quadrature weights weights=gausslegendre(order) - # compute initial guess from previous rho - (u,E,err)=easyeq_hatu(easyeq_init_u(a0,order,weights),order,(10.)^minlrho_init,v,maxiter,tolerance,weights,approx) - for j in 2:nlrho_init - rho_tmp=10^(minlrho_init+(log10(rho)-minlrho_init)*(j-1)/(nlrho_init-1)) - (u,E,err)=easyeq_hatu(u,order,rho_tmp,v,maxiter,tolerance,weights,approx) - end + # compute u + (u,E,err)= easyeq_compute_u_prevrho([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) # compute eta eta=easyeq_eta(u,order,rho,v,maxiter,tolerance,weights,approx) @@ -121,25 +163,350 @@ function easyeq_condensate_fraction(minlrho_init,nlrho_init,order,rho,a0,v,maxit end # condensate fraction as a function of rho -function easyeq_condensate_fraction_rho(rhos,order,a0,v,maxiter,tolerance,approx) +function easyeq_condensate_fraction_rho( + rhos::Array{Float64,1}, + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) weights=gausslegendre(order) - # init u - u=easyeq_init_u(a0,order,weights) + # compute u + (us,es,errs)= easyeq_compute_u_prevrho(rhos,minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) for j in 1:length(rhos) - # compute u (init newton with previously computed u) - (u,E,err)=easyeq_hatu(u,order,rhos[j],v,maxiter,tolerance,weights,approx) - # compute eta - eta=easyeq_eta(u,order,rhos[j],v,maxiter,tolerance,weights,approx) + eta=easyeq_eta(us[j],order,rhos[j],v,maxiter,tolerance,weights,approx) + @printf("% .15e % .15e % .15e\n",rhos[j],eta,errs[j]) + end +end + +# 2 pt correlation function +function easyeq_2pt( + xmin::Float64, + xmax::Float64, + nx::Int64, + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) - @printf("% .15e % .15e % .15e\n",rhos[j],eta,err) + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + (E,S,A,T,B,X)=easyeq_ESATBX(rho*u,V,V0,Eta,Eta0,weights,rho,approx) + + # compute C2 + for j in 1:nx + x=xmin+(xmax-xmin)/nx*j + C2=easyeq_C2(x,u,windowL,rho,weights,Eta,Eta0,approx,E,S,A,T,B,X) + @printf("% .15e % .15e\n",x,C2) end end +# maximum of 2 point correlation function +function easyeq_2pt_max( + dx::Float64, + x0::Float64, # initial guess is x0/rho^(1/3) + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, + rho::Float64, + a0::Float64, + v::Function, + maxstep::Float64, + maxiter::Int64, + tolerance::Float64, + tolerance_max::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) -# initialize u -@everywhere function easyeq_init_u(a0,order,weights) + (x,f)=easyeq_C2_max(u,x0/rho^(1/3),dx,maxstep,maxiter,tolerance_max,windowL,rho,weights,V,V0,Eta,Eta0,approx) + + if(x==Inf) + @printf(stderr,"max search failed for rho=%e\n",rho) + else + @printf("% .15e % .15e\n",x,f) + end +end + +# maximum of 2 point correlation function as a function of rho +function easyeq_2pt_max_rho( + rhos::Array{Float64,1}, + dx::Float64, + x0::Float64, # initial guess is x0/rho^(1/3) + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, + a0::Float64, + v::Function, + maxstep::Float64, + maxiter::Int64, + tolerance::Float64, + tolerance_max::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (us,es,errs)= easyeq_compute_u_prevrho_error(rhos,minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + + # save result from each task + xs=Array{Float64,1}(undef,length(rhos)) + fs=Array{Float64,1}(undef,length(rhos)) + + # spawn workers + work=spawn_workers(length(rhos)) + + count=0 + # for each worker + @sync for p in 1:length(work) + # for each task + @async for j in work[p] + count=count+1 + if count>=length(work) + progress(count,length(rhos),10000) + end + # run the task + (xs[j],fs[j])=remotecall_fetch(easyeq_C2_max,workers()[p],us[j],x0/rhos[j]^(1/3),dx,maxstep,maxiter,tolerance_max,windowL,rhos[j],weights,V,V0,Eta,Eta0,approx) + end + end + + for j in 1:length(rhos) + if(xs[j]==Inf) + @printf(stderr,"max search failed for rho=%e\n",rhos[j]) + else + @printf("% .15e % .15e % .15e\n",rhos[j],xs[j],fs[j]) + end + end +end + + +# Fourier transform of 2 pt correlation function +function easyeq_2pt_fourier( + kmin::Float64, + kmax::Float64, + nk::Int64, + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + (E,S,A,T,B,X)=easyeq_ESATBX(rho*u,V,V0,Eta,Eta0,weights,rho,approx) + + # compute C2 + for j in 1:nk + k=kmin+(kmax-kmin)/nk*j + C2=easyeq_C2_fourier(k,u,windowL,rho,weights,Eta,Eta0,approx,E,S,A,T,B,X) + @printf("% .15e % .15e\n",k,C2) + end +end + +# maximum of Fourier transform of 2 point correlation function +function easyeq_2pt_fourier_max( + dk::Float64, + k0::Float64, # initial guess is k0*rho^(1/3) + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, + rho::Float64, + a0::Float64, + v::Function, + maxstep::Float64, + maxiter::Int64, + tolerance::Float64, + tolerance_max::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + + (k,f)=easyeq_C2_fourier_max(u,k0*rho^(1/3),dk,maxstep,maxiter,tolerance_max,windowL,rho,weights,V,V0,Eta,Eta0,approx) + + if(k==Inf) + @printf(stderr,"max search failed for rho=%e\n",rho) + else + @printf("% .15e % .15e\n",k,f) + end +end + +# maximum of Fourier transform of 2 point correlation function as a function of rho +function easyeq_2pt_fourier_max_rho( + rhos::Array{Float64,1}, + dk::Float64, + k0::Float64, # initial guess is k0*rho^(1/3) + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, + a0::Float64, + v::Function, + maxstep::Float64, + maxiter::Int64, + tolerance::Float64, + tolerance_max::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (us,es,errs)= easyeq_compute_u_prevrho_error(rhos,minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + + # save result from each task + ks=Array{Float64,1}(undef,length(rhos)) + fs=Array{Float64,1}(undef,length(rhos)) + + # spawn workers + work=spawn_workers(length(rhos)) + + count=0 + # for each worker + @sync for p in 1:length(work) + # for each task + @async for j in work[p] + count=count+1 + if count>=length(work) + progress(count,length(rhos),10000) + end + # run the task + (ks[j],fs[j])=remotecall_fetch(easyeq_C2_fourier_max,workers()[p],us[j],k0*rhos[j]^(1/3),dk,maxstep,maxiter,tolerance_max,windowL,rhos[j],weights,V,V0,Eta,Eta0,approx) + end + end + + for j in 1:length(rhos) + if(ks[j]==Inf) + @printf(stderr,"max search failed for rho=%e\n",rhos[j]) + else + @printf("% .15e % .15e % .15e\n",rhos[j],ks[j],fs[j]) + end + end +end + +# momentum distribution +function easyeq_momentum_distribution( + kmin::Float64, + kmax::Float64, + minlrho_init::Float64, + nlrho_init::Int64, + order::Int64, + windowL::Float64, #L=windowL/k^2 + rho::Float64, + a0::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + approx::Easyeq_approx +) + # compute gaussian quadrature weights + weights=gausslegendre(order) + + # compute u + (u,E,err)= easyeq_compute_u_prevrho_error([rho],minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + + # compute useful terms + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + (E,S,A,T,B,X)=easyeq_ESATBX(rho*u,V,V0,Eta,Eta0,weights,rho,approx) + # dXi/dlambda without the delta function and u + dXidlambda=(dotPhi(B.*T./((X.+1).^2))./(2*(X.+1))+B.*T./(2*(X.+1).^3).*dotdPhi(B.*T./(X.+1).^2))./A*(16*pi^3) + + dXi=inv(easyeq_dXi(rho*u,Eta,Eta0,weights,rho,approx,E,S,A,T,B,X)) + + # compute momentum distribution + for j in 1:order + q=(1-weights[1][j])/(1+weights[1][j]) + # drop if not in k interval + if qkmax + continue + end + + # delta(k_i,q) + delta=Array{Float64,1}(undef,order) + L=windowL/q^2 + for i in 1:order + k=(1-weights[1][i])/(1+weights[1][i]) + delta[i]=(1.)/(2*k*q*L)*(gaussian(k-q,(1.)/L)-gaussian(k+q,(1.)/L)) + end + + # du/dlambda + du=-dXi*(dXidlambda.*delta*u[j]) + # rescale u + du=du/rho + + # compute M + M=-integrate_legendre_sampled(y->(1-y)/y^3,Eta0.*du,0.,1.,weights)*rho/(16*pi^3) + + @printf("% .15e % .15e\n",q,M) + end +end + + +# initialize u from scattering solution +@everywhere function easyeq_init_u( + a0::Float64, + order::Int64, + weights::Tuple{Array{Float64,1},Array{Float64,1}} +) u=zeros(Float64,order) for j in 1:order # transformed k @@ -150,8 +517,100 @@ end return u end +# compute u for an array of rhos +# use scattering solution for the first one, and the previous rho for the others +@everywhere function easyeq_compute_u_rho( + rhos::Array{Float64,1}, + a0::Float64, + order::Int64, + v::Function, + maxiter::Int64, + tolerance::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + approx::Easyeq_approx +) + us=Array{Array{Float64,1}}(undef,length(rhos)) + es=Array{Float64,1}(undef,length(rhos)) + errs=Array{Float64,1}(undef,length(rhos)) + + (us[1],es[1],errs[1])=easyeq_hatu(easyeq_init_u(a0,order,weights),order,rhos[1],v,maxiter,tolerance,weights,approx) + for j in 2:length(rhos) + (us[j],es[j],errs[j])=easyeq_hatu(us[j-1],order,rhos[j],v,maxiter,tolerance,weights,approx) + end + + return (us,es,errs) +end + +# compute u for an array of rhos +# start from a smaller rho and work up to rhos[1] +@everywhere function easyeq_compute_u_prevrho( + rhos::Array{Float64,1}, + minlrho_init::Float64, + nlrho_init::Int64, + a0::Float64, + order::Int64, + v::Function, + maxiter::Int64, + tolerance::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + approx::Easyeq_approx +) + + # only work up to rhos[1] if nlrho_init>0 + if nlrho_init>0 + rhos_init=Array{Float64,1}(undef,nlrho_init) + for j in 0:nlrho_init-1 + rhos_init[j+1]=(nlrho_init==1 ? 10^minlrho_init : 10^(minlrho_init+(log10(rhos[1])-minlrho_init)/(nlrho_init-1)*j)) + end + append!(rhos_init,rhos) + # start from rhos[1] if nlrho_init=0 + else + rhos_init=rhos + end + (us,es,errs)=easyeq_compute_u_rho(rhos_init,a0,order,v,maxiter,tolerance,weights,approx) + + # return a single value if there was a single input + if length(rhos)==1 + return (us[nlrho_init+1],es[nlrho_init+1],errs[nlrho_init+1]) + else + return (us[nlrho_init+1:length(us)],es[nlrho_init+1:length(es)],errs[nlrho_init+1:length(errs)]) + end +end +# with error message if the computation failed to be accurate enough +@everywhere function easyeq_compute_u_prevrho_error( + rhos::Array{Float64,1}, + minlrho_init::Float64, + nlrho_init::Int64, + a0::Float64, + order::Int64, + v::Function, + maxiter::Int64, + tolerance::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + approx::Easyeq_approx +) + (us,es,errs)=easyeq_compute_u_prevrho(rhos,minlrho_init,nlrho_init,a0,order,v,maxiter,tolerance,weights,approx) + # check errs + for j in 1:length(errs) + if errs[j]>tolerance + print(stderr,"warning: computation of u failed for rho=",rhos[j],"\n") + end + end + return (us,es,errs) +end + + # \hat u(k) computed using Newton -@everywhere function easyeq_hatu(u0,order,rho,v,maxiter,tolerance,weights,approx) +@everywhere function easyeq_hatu( + u0::Array{Float64,1}, + order::Int64, + rho::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + approx::Easyeq_approx +) # initialize V and Eta (V,V0)=easyeq_init_v(weights,v) (Eta,Eta0)=easyeq_init_H(weights,v) @@ -162,7 +621,8 @@ end # iterate err=Inf for i in 1:maxiter-1 - new=u-inv(easyeq_dXi(u,V,V0,Eta,Eta0,weights,rho,approx))*easyeq_Xi(u,V,V0,Eta,Eta0,weights,rho,approx) + (E,S,A,T,B,X)=easyeq_ESATBX(u,V,V0,Eta,Eta0,weights,rho,approx) + new=u-inv(easyeq_dXi(u,Eta,Eta0,weights,rho,approx,E,S,A,T,B,X))*easyeq_Xi(u,order,S,A,T,B,X) err=norm(new-u)/norm(u) if(errt ? 2*t/x : 2)* integrate_legendre(y->2*pi*((x+t)*y+abs(x-t)*(1-y))*v((x+t)*y+abs(x-t)*(1-y)),0,1,weights) +@everywhere function easyeq_H( + x::Float64, + t::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + v::Function +) + return (x>t ? 2*t/x : 2)* integrate_legendre(y->2*pi*((x+t)*y+abs(x-t)*(1-y))*v((x+t)*y+abs(x-t)*(1-y)),0.,1.,weights) end # initialize V -@everywhere function easyeq_init_v(weights,v) +@everywhere function easyeq_init_v( + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + v::Function +) order=length(weights[1]) - V=Array{Float64}(undef,order) - V0=v(0) + V=Array{Float64,1}(undef,order) + V0=v(0.) for i in 1:order k=(1-weights[1][i])/(1+weights[1][i]) V[i]=v(k) @@ -193,29 +661,58 @@ end end # initialize Eta -@everywhere function easyeq_init_H(weights,v) +@everywhere function easyeq_init_H( + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + v::Function +) order=length(weights[1]) - Eta=Array{Array{Float64}}(undef,order) - Eta0=Array{Float64}(undef,order) + Eta=Array{Array{Float64,1},1}(undef,order) + Eta0=Array{Float64,1}(undef,order) for i in 1:order k=(1-weights[1][i])/(1+weights[1][i]) - Eta[i]=Array{Float64}(undef,order) + Eta[i]=Array{Float64,1}(undef,order) for j in 1:order y=(weights[1][j]+1)/2 Eta[i][j]=easyeq_H(k,(1-y)/y,weights,v) end y=(weights[1][i]+1)/2 - Eta0[i]=easyeq_H(0,(1-y)/y,weights,v) + Eta0[i]=easyeq_H(0.,(1-y)/y,weights,v) end return(Eta,Eta0) end # Xi(u) -@everywhere function easyeq_Xi(u,V,V0,Eta,Eta0,weights,rho,approx) +@everywhere function easyeq_Xi( + u::Array{Float64,1}, + order::Int64, + S::Array{Float64,1}, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) + return u.-T./(2*(X.+1)).*dotPhi(B.*T./(X.+1).^2) +end + +# compute E,S,A,T,B,X +@everywhere function easyeq_ESATBX( + u::Array{Float64,1}, + V::Array{Float64,1}, + V0::Float64, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + rho::Float64, + approx::Easyeq_approx +) order=length(weights[1]) # init - out=zeros(Float64,order) + S=zeros(Float64,order) + A=zeros(Float64,order) + T=zeros(Float64,order) + B=zeros(Float64,order) + X=zeros(Float64,order) # compute E before running the loop E=easyeq_en(u,V0,Eta0,rho,weights) @@ -224,188 +721,359 @@ end # k_i k=(1-weights[1][i])/(1+weights[1][i]) # S_i - S=V[i]-1/(rho*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta[i].*u,0,1,weights) + S[i]=V[i]-1/(rho*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta[i].*u,0.,1.,weights) # A_K,i - A=0. + A[i]=0. if approx.bK!=0. - A+=approx.bK*S + A[i]+=approx.bK*S[i] end if approx.bK!=1. - A+=(1-approx.bK)*E + A[i]+=(1-approx.bK)*E end - # T + # T_i if approx.bK==1. - T=1. + T[i]=1. else - T=S/A + T[i]=S[i]/A[i] end - # B + # B_i if approx.bK==approx.bL - B=1. + B[i]=1. else - B=(approx.bL*S+(1-approx.bL*E))/(approx.bK*S+(1-approx.bK*E)) + B[i]=(approx.bL*S[i]+(1-approx.bL*E))/(approx.bK*S[i]+(1-approx.bK*E)) end # X_i - X=k^2/(2*A*rho) - - # U_i - out[i]=u[i]-T/(2*(X+1))*Phi(B*T/(X+1)^2) + X[i]=k^2/(2*A[i]*rho) end - return out + return (E,S,A,T,B,X) end # derivative of Xi -@everywhere function easyeq_dXi(u,V,V0,Eta,Eta0,weights,rho,approx) +@everywhere function easyeq_dXi( + u::Array{Float64,1}, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + rho::Float64, + approx::Easyeq_approx, + E::Float64, + S::Array{Float64,1}, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) order=length(weights[1]) # init out=zeros(Float64,order,order) - # compute E before the loop - E=easyeq_en(u,V0,Eta0,rho,weights) - for i in 1:order # k_i k=(1-weights[1][i])/(1+weights[1][i]) - # S_i - S=V[i]-1/(rho*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta[i].*u,0,1,weights) - - # A_K,i - A=0. - if approx.bK!=0. - A+=approx.bK*S - end - if approx.bK!=1. - A+=(1-approx.bK)*E - end - - # T - if approx.bK==1. - T=1. - else - T=S/A - end - - # B - if approx.bK==approx.bL - B=1. - else - B=(approx.bL*S+(1-approx.bL*E))/(approx.bK*S+(1-approx.bK*E)) - end - - # X_i - X=k^2/(2*A*rho) for j in 1:order y=(weights[1][j]+1)/2 dS=-1/rho*(1-y)*Eta[i][j]/(2*(2*pi)^3*y^3)*weights[2][j] dE=-1/rho*(1-y)*Eta0[j]/(2*(2*pi)^3*y^3)*weights[2][j] + dU=(i==j ? 1. : 0.) - # dA - dA=0. - if approx.bK!=0. - dA+=approx.bK*dS - end - if approx.bK!=1. - dA+=(1-approx.bK)*dE - end + out[i,j]=easyeq_dXi_of_dSdEdU(k,dS,dE,dU,E,S[i],A[i],T[i],B[i],X[i],rho,approx) + end + end + + return out +end - # dT - if approx.bK==1. - dT=0. - else - dT=(1-approx.bK)*(E*dS-S*dE)/A^2 - end +# dXi given dS, dE and dU +@everywhere function easyeq_dXi_of_dSdEdU( + k::Float64, + dS::Float64, + dE::Float64, + dU::Float64, + E::Float64, + S::Float64, + A::Float64, + T::Float64, + B::Float64, + X::Float64, + rho::Float64, + approx::Easyeq_approx +) + # dA + dA=0. + if approx.bK!=0. + dA+=approx.bK*dS + end + if approx.bK!=1. + dA+=(1-approx.bK)*dE + end - # dB - if approx.bK==approx.bL - dB=0. - else - dB=(approx.bL*(1-approx.bK)-approx.bK*(1-approx.bL))*(E*dS-S*dE)/(approx.bK*S+(1-approx.bK*E))^2 - end + # dT,dB + # nothing to do if bK=bL=1 + if approx.bK!=1. || approx.bK!=approx.bL + dB=(E*dS-S*dE)/A^2 + end + if approx.bK==1. + dT=0. + else + dT=(1-approx.bK)*dB + end + if approx.bK==approx.bL + dB=0. + else + dB=(approx.bL*(1-approx.bK)-approx.bK*(1-approx.bL))*dB + end - dX=-k^2/(2*A^2*rho)*dA + dX=-k^2/(2*A^2*rho)*dA - out[i,j]=(i==j ? 1 : 0)-(dT-T*dX/(X+1))/(2*(X+1))*Phi(B*T/(X+1)^2)-T/(2*(X+1)^3)*(B*dT+T*dB-2*B*T*dX/(X+1))*dPhi(B*T/(X+1)^2) - end + return dU-(dT-T*dX/(X+1))/(2*(X+1))*Phi(B*T/(X+1)^2)-T/(2*(X+1)^3)*(B*dT+T*dB-2*B*T*dX/(X+1))*dPhi(B*T/(X+1)^2) +end + +# derivative of Xi with respect to mu +@everywhere function easyeq_dXidmu( + u::Array{Float64,1}, + order::Int64, + rho::Float64, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) + # init + out=zeros(Float64,order) + for i in 1:order + out[i]=T[i]/(2*rho*A[i]*(X[i]+1)^2)*Phi(B[i]*T[i]/(X[i]+1)^2)+B[i]*T[i]^2/(rho*A[i]*(X[i]+1)^4)*dPhi(B[i]*T[i]/(X[i]+1)^2) end return out end -# derivative of Xi with respect to mu -@everywhere function easyeq_dXidmu(u,V,V0,Eta,Eta0,weights,rho,approx) +# energy +@everywhere function easyeq_en( + u::Array{Float64,1}, + V0::Float64, + Eta0::Array{Float64,1}, + rho::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}} +) + return V0-1/(rho*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta0.*u,0.,1.,weights) +end + +# condensate fraction +@everywhere function easyeq_eta( + u::Array{Float64,1}, + order::Int64, + rho::Float64, + v::Function, + maxiter::Int64, + tolerance::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + approx::Easyeq_approx +) + (V,V0)=easyeq_init_v(weights,v) + (Eta,Eta0)=easyeq_init_H(weights,v) + + (E,S,A,T,B,X)=easyeq_ESATBX(rho*u,V,V0,Eta,Eta0,weights,rho,approx) + du=-inv(easyeq_dXi(rho*u,Eta,Eta0,weights,rho,approx,E,S,A,T,B,X))*easyeq_dXidmu(rho*u,order,rho,A,T,B,X) + + eta=-1/(2*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta0.*du,0.,1.,weights) + + return eta +end + +# inverse Fourier transform +@everywhere function easyeq_u_x( + x::Float64, + u::Array{Float64,1}, + weights::Tuple{Array{Float64,1},Array{Float64,1}} +) + order=length(weights[1]) + out=integrate_legendre_sampled(y->(1-y)/y^3*sin(x*(1-y)/y)/x/(2*pi^2),u,0.,1.,weights) + return out +end + + +# correlation function +@everywhere function easyeq_C2( + x::Float64, + u::Array{Float64,1}, + windowL::Float64, + rho::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + approx::Easyeq_approx, + E::Float64, + S::Array{Float64,1}, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) + g=(r,x)->(r>0. ? sin(r*x)/(r*x)*hann(r,windowL) : hann(r,windowL)) + (dEta,dEta0)=easyeq_init_H(weights,k->g(k,x)) + du=easyeq_dudv(g,x,u,rho,weights,Eta,Eta0,dEta,dEta0,approx,E,S,A,T,B,X) + + return rho^2*(1-integrate_legendre_sampled(y->(1-y)/y^3,dEta0.*u+Eta0.*du,0.,1.,weights)/(8*pi^3)) +end + +# derivative of u with respect to v in direction g +@everywhere function easyeq_dudv( + g::Function,# should be of the form g(k,x) where x is a parameter + x::Float64, + u::Array{Float64,1}, + rho::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + dEta::Array{Array{Float64,1},1}, + dEta0::Array{Float64,1}, + approx::Easyeq_approx, + E::Float64, + S::Array{Float64,1}, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) + # initialize dV and dEta + (dV,dV0)=easyeq_init_v(weights,k->g(k,x)) + + du=-inv(easyeq_dXi(rho*u,Eta,Eta0,weights,rho,approx,E,S,A,T,B,X))*easyeq_dXidv(rho*u,dV,dV0,dEta,dEta0,weights,rho,approx,E,S,A,T,B,X) + # rescale rho + du=du/rho + + return du +end + +# derivative of Xi with respect to potential +@everywhere function easyeq_dXidv( + u::Array{Float64,1}, + dv::Array{Float64,1}, + dv0::Float64, + dEta::Array{Array{Float64,1},1}, + dEta0::Array{Float64,1}, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + rho::Float64, + approx::Easyeq_approx, + E::Float64, + S::Array{Float64,1}, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) + order=length(weights[1]) # init out=zeros(Float64,order) - # compute E before running the loop - E=easyeq_en(u,V0,Eta0,rho,weights) - for i in 1:order # k_i k=(1-weights[1][i])/(1+weights[1][i]) - # S_i - S=V[i]-1/(rho*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta[i].*u,0,1,weights) - # A_K,i - A=0. - if approx.bK!=0. - A+=approx.bK*S - end - if approx.bK!=1. - A+=(1-approx.bK)*E - end - - # T - if approx.bK==1. - T=1. - else - T=S/A - end - - # B - if approx.bK==approx.bL - B=1. - else - B=(approx.bL*S+(1-approx.bL*E))/(approx.bK*S+(1-approx.bK*E)) + dS=dv[i] + dE=dv0 + for j in 1:order + y=(weights[1][j]+1)/2 + dS+=-1/rho*(1-y)*u[j]*dEta[i][j]/(2*(2*pi)^3*y^3)*weights[2][j] + dE+=-1/rho*(1-y)*u[j]*dEta0[j]/(2*(2*pi)^3*y^3)*weights[2][j] end - # X_i - X=k^2/(2*A*rho) - - out[i]=T/(2*rho*A*(X+1)^2)*Phi(B*T/(X+1)^2)+B*T^2/(rho*A*(X+1)^4)*dPhi(B*T/(X+1)^2) + out[i]=easyeq_dXi_of_dSdEdU(k,dS,dE,0.,E,S[i],A[i],T[i],B[i],X[i],rho,approx) end return out end -# energy -@everywhere function easyeq_en(u,V0,Eta0,rho,weights) - return V0-1/(rho*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta0.*u,0,1,weights) +# maximum of 2 point correlation function +@everywhere function easyeq_C2_max( + u::Array{Float64,1}, + x0::Float64, + dx::Float64, + maxstep::Float64, + maxiter::Int64, + tolerance::Float64, + windowL::Float64, + rho::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + V::Array{Float64,1}, + V0::Float64, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + approx::Easyeq_approx +) + # compute some useful terms + (E,S,A,T,B,X)=easyeq_ESATBX(rho*u,V,V0,Eta,Eta0,weights,rho,approx) + + (x,f)=newton_maximum(y->easyeq_C2(y,u,windowL,rho,weights,Eta,Eta0,approx,E,S,A,T,B,X),x0,dx,maxiter,tolerance,maxstep) + + return(x,f) end -# condensate fraction -@everywhere function easyeq_eta(u,order,rho,v,maxiter,tolerance,weights,approx) - (V,V0)=easyeq_init_v(weights,v) - (Eta,Eta0)=easyeq_init_H(weights,v) - - du=-inv(easyeq_dXi(rho*u,V,V0,Eta,Eta0,weights,rho,approx))*easyeq_dXidmu(rho*u,V,V0,Eta,Eta0,weights,rho,approx) +# Fourier transform of correlation function +@everywhere function easyeq_C2_fourier( + q::Float64, + u::Array{Float64,1}, + windowL::Float64, + rho::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + approx::Easyeq_approx, + E::Float64, + S::Array{Float64,1}, + A::Array{Float64,1}, + T::Array{Float64,1}, + B::Array{Float64,1}, + X::Array{Float64,1} +) + # direction in which to differentiate u + g=(r,x)->(r>0. ? (1.)/(2*x*r*windowL)*(gaussian(x-r,(1.)/windowL)-gaussian(x+r,(1.)/windowL)) : gaussian(x,(1.)/windowL)) + (dEta,dEta0)=easyeq_init_H(weights,k->g(k,q)) + du=easyeq_dudv(g,q,u,rho,weights,Eta,Eta0,dEta,dEta0,approx,E,S,A,T,B,X) + + return rho^2*(-integrate_legendre_sampled(y->(1-y)/y^3,dEta0.*u+Eta0.*du,0.,1.,weights)/(8*pi^3)) +end - eta=-1/(2*(2*pi)^3)*integrate_legendre_sampled(y->(1-y)/y^3,Eta0.*du,0,1,weights) - return eta +# maximum of Fourier transform of 2 point correlation function +@everywhere function easyeq_C2_fourier_max( + u::Array{Float64,1}, + k0::Float64, + dk::Float64, + maxstep::Float64, + maxiter::Int64, + tolerance::Float64, + windowL::Float64, + rho::Float64, + weights::Tuple{Array{Float64,1},Array{Float64,1}}, + V::Array{Float64,1}, + V0::Float64, + Eta::Array{Array{Float64,1},1}, + Eta0::Array{Float64,1}, + approx::Easyeq_approx +) + # compute some useful terms + (E,S,A,T,B,X)=easyeq_ESATBX(rho*u,V,V0,Eta,Eta0,weights,rho,approx) + + (k,f)=newton_maximum(y->easyeq_C2_fourier(y,u,windowL,rho,weights,Eta,Eta0,approx,E,S,A,T,B,X),k0,dk,maxiter,tolerance,maxstep) + + return (k,f) end -# inverse Fourier transform -@everywhere function easyeq_u_x(x,u,weights) - order=length(weights[1]) - out=integrate_legendre_sampled(y->(1-y)/y^3*sin(x*(1-y)/y)/x/(2*pi^2),u,0,1,weights) - return out + +@everywhere function barEta( + q::Float64, + y::Float64, + t::Float64 +) + return (t>=abs(y-q) && t<=y+q ? pi/y/q : 0.) end -- cgit v1.2.3-70-g09d2