Ian Jauslin
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Jauslin <ian.jauslin@rutgers.edu>2023-02-26 18:36:05 -0500
committerIan Jauslin <ian.jauslin@rutgers.edu>2023-02-26 18:36:05 -0500
commitc1b477a1b2b796617c4e345a7296a8d429d7a067 (patch)
tree8a8a2fc0fb6e7da5f4b0b271382740f858ee4372
parente72af82c3ed16b81cdb5043c58abbdbb3cf02102 (diff)
Update to v0.4v0.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.
-rw-r--r--Changelog25
-rw-r--r--NOTICE2
-rw-r--r--README11
-rw-r--r--doc/Makefile2
-rw-r--r--doc/bibliography/bibliography.tex7
-rw-r--r--doc/libs/code.sty2
-rw-r--r--doc/libs/dlmf.sty2
-rw-r--r--doc/libs/ian.cls53
-rw-r--r--doc/libs/iantheo.sty2
-rw-r--r--doc/libs/largearray.sty2
-rw-r--r--doc/libs/point.sty12
-rw-r--r--doc/simplesolv-doc.tex1110
-rw-r--r--src/anyeq.jl1485
-rw-r--r--src/chebyshev.jl323
-rw-r--r--src/easyeq.jl1040
-rw-r--r--src/integration.jl50
-rw-r--r--src/interpolation.jl36
-rw-r--r--src/main.jl168
-rw-r--r--src/multithread.jl16
-rw-r--r--src/optimization.jl94
-rw-r--r--src/potentials.jl58
-rw-r--r--src/print.jl2
-rw-r--r--src/simpleq-Kv.jl68
-rw-r--r--src/simpleq-hardcore.jl494
-rw-r--r--src/simpleq-iteration.jl49
-rw-r--r--src/tools.jl22
26 files changed, 4302 insertions, 833 deletions
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..9e363cf
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,25 @@
+0.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.
+
diff --git a/NOTICE b/NOTICE
index 216093f..ea2be90 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,4 +1,4 @@
simplesolv:
Licensed under the Apache 2.0 License (see LICENSE for details)
-Copyright Ian Jauslin 2021
+Copyright Ian Jauslin 2021-2023
diff --git a/README b/README
index ffc52d5..5a22d6a 100644
--- a/README
+++ b/README
@@ -29,7 +29,9 @@ published in the following papers:
* E.A. Carlen, I. Jauslin, E.H. Lieb - Analysis of a simple equation for the
ground state energy of the Bose gas II: Monotonicity, Convexity and
- Condensate Fraction, to appear in the SIAM Journal on Mathematical Analysis
+ Condensate Fraction, SIAM Journal on Mathematical Analysis, volume 53,
+ number 5, pages 5322-5360, 2021
+ https://doi.org/10.1137/20M13768
https://arxiv.org/abs/2010.13882
http://ian.jauslin.org/publications/20cjl
@@ -40,6 +42,13 @@ published in the following papers:
https://arxiv.org/abs/2011.10869
http://ian.jauslin.org/publications/20chjl
+ * I. Jauslin - The Simplified approach to the Bose gas without translation
+ invariance, 2023
+ http://ian.jauslin.org/publications/23j
+
+ * I. Jauslin - Evidence of a liquid phase in repulsive Bosonic systems using
+ the Simplified approach to the Bose gas, 2023
+ http://ian.jauslin.org/publications/23j_b
Dependencies:
diff --git a/doc/Makefile b/doc/Makefile
index 4b58b3c..d0c4c64 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -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.
diff --git a/doc/bibliography/bibliography.tex b/doc/bibliography/bibliography.tex
index 53454da..e8893ca 100644
--- a/doc/bibliography/bibliography.tex
+++ b/doc/bibliography/bibliography.tex
@@ -4,10 +4,13 @@ doi:{\tt\color{blue}\href{http://dx.doi.org/10.1103/PhysRevA.103.053309}{10.1103
\bibitem[CJL20]{CJL20}E.A. Carlen, I. Jauslin, E.H. Lieb - {\it Analysis of a simple equation for the ground state energy of the Bose gas}, Pure and Applied Analysis, volume~\-2, issue~\-3, pages~\-659-684, 2020,\par\penalty10000
doi:{\tt\color{blue}\href{http://dx.doi.org/10.2140/paa.2020.2.659}{10.2140/paa.2020.2.659}}, arxiv:{\tt\color{blue}\href{http://arxiv.org/abs/1912.04987}{1912.04987}}.\par\medskip
-\bibitem[CJL20b]{CJL20b}E.A. Carlen, I. Jauslin, E.H. Lieb - {\it Analysis of a simple equation for the ground state of the Bose gas II: Monotonicity, Convexity and Condensate Fraction}, 2020, to appear in the SIAM journal of Mathematical Analysis,\par\penalty10000
-arxiv:{\tt\color{blue}\href{http://arxiv.org/abs/2010.13882}{2010.13882}}.\par\medskip
+\bibitem[CJL21]{CJL21}E.A. Carlen, I. Jauslin, E.H. Lieb - {\it Analysis of a Simple Equation for the Ground State of the Bose Gas II: Monotonicity, Convexity, and Condensate Fraction}, SIAM Journal on Mathematical Analysis, volume~\-53, number~\-5, pages~\-5322-5360, 2021,\par\penalty10000
+doi:{\tt\color{blue}\href{http://dx.doi.org/10.1137/20M1376820}{10.1137/20M1376820}}, arxiv:{\tt\color{blue}\href{http://arxiv.org/abs/2010.13882}{2010.13882}}.\par\medskip
\bibitem[DLMF]{DLMF1.1.3}F.W.J. Olver, A.B. Olde Daalhuis, D.W. Lozier, B.I. Schneider, R.F. Boisvert, C.W. Clark, B.R. Miller, B.V. Saunders, H.S. Cohl, M.A. McClain (editors) - {\it NIST Digital Library of Mathematical Functions}, Release~\-1.1.3 of~\-2021-09-15, 2021.\par\medskip
+\bibitem[Ja23]{Ja23}I. Jauslin - {\it The Simplified approach to the Bose gas without translation invariance}, 2023\par\penalty10000
+{\tt\color{blue}\href{http://ian.jauslin.org/publications/23j/}{http://ian.jauslin.org/publications/23j/}}.\par\medskip
+
\bibitem[Ta87]{Ta87}Y. Taguchi - {\it Fourier coefficients of periodic functions of Gevrey classes and ultradistributions}, Yokohama Mathematical Journal, volume~\-35, pages~\-51-60, 1987.\par\medskip
diff --git a/doc/libs/code.sty b/doc/libs/code.sty
index d4f4070..e067dfe 100644
--- a/doc/libs/code.sty
+++ b/doc/libs/code.sty
@@ -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.
diff --git a/doc/libs/dlmf.sty b/doc/libs/dlmf.sty
index f435e96..f66157b 100644
--- a/doc/libs/dlmf.sty
+++ b/doc/libs/dlmf.sty
@@ -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.
diff --git a/doc/libs/ian.cls b/doc/libs/ian.cls
index f29e6bd..762f679 100644
--- a/doc/libs/ian.cls
+++ b/doc/libs/ian.cls
@@ -219,6 +219,7 @@
% counters
\stepcounter{subsectioncount}
\setcounter{subsubsectioncount}{0}
+ \setcounter{subsubsubsectioncount}{0}
\ifsubsectionsineq
\setcounter{seqcount}0
\fi
@@ -268,6 +269,7 @@
\def\subsubsection#1{
% counters
\stepcounter{subsubsectioncount}
+ \setcounter{subsubsubsectioncount}{0}
% space before subsubsection (if not first)
\ifnum\thesubsubsectioncount>1
@@ -302,6 +304,49 @@
\medskip\penalty10000
}
+%% subsubsubsection
+% counter
+\newcounter{subsubsubsectioncount}
+% space before subsubsubsection
+\newlength\subsubsubsecskip
+\setlength\subsubsubsecskip{20pt}
+\def\subsubsubsection#1{
+ % counters
+ \stepcounter{subsubsubsectioncount}
+
+ % space before subsubsubsection (if not first)
+ \ifnum\thesubsubsubsectioncount>1
+ \vskip\subsubsubsecskip
+ \penalty-500
+ \fi
+
+ % hyperref anchor
+ \hrefanchor
+ % define tag (for \label)
+ \xdef\tag{\sectionprefix\thesectioncount.\thesubsectioncount.\thesubsubsectioncount.\thesubsubsubsectioncount}
+
+ % get widths
+ \def\@secnum{{\bf\hskip1.5cm\sectionprefix\thesectioncount.\thesubsectioncount.\thesubsubsectioncount.\thesubsubsubsectioncount.\hskip5pt}}
+ \settowidth\secnumwidth{\@secnum}
+ \setlength\sectitlewidth\textwidth
+ \addtolength\sectitlewidth{-\secnumwidth}
+ % print name
+ \parbox{\textwidth}{
+ \@secnum
+ \parbox[t]{\sectitlewidth}{\bf #1}}
+
+ % write to table of contents
+ \iftoc
+ % save lncount in aux variable which is written to toc
+ \immediate\write\tocoutput{\noexpand\expandafter\noexpand\edef\noexpand\csname toc@subsubsubsec.\thesectioncount.\thesubsectioncount.\thesubsubsectioncount.\thesubsubsubsectioncount\endcsname{\thelncount}}
+ \write\tocoutput{\noexpand\tocsubsubsubsection{#1}{\thepage}}
+ \fi
+
+ % space
+ \par\penalty10000
+ \medskip\penalty10000
+}
+
%% itemize
\newlength\itemizeskip
% left margin for items
@@ -638,6 +683,7 @@
\stepcounter{tocsectioncount}
\setcounter{tocsubsectioncount}{0}
\setcounter{tocsubsubsectioncount}{0}
+ \setcounter{tocsubsubsubsectioncount}{0}
% write
\smallskip\hyperlink{ln.\csname toc@sec.\thetocsectioncount\endcsname}{{\bf \tocsectionprefix\thetocsectioncount}.\hskip5pt {\color{blue}#1}\leaderfill#2}\par
}
@@ -645,6 +691,7 @@
\def\tocsubsection #1#2{
\stepcounter{tocsubsectioncount}
\setcounter{tocsubsubsectioncount}{0}
+ \setcounter{tocsubsubsubsectioncount}{0}
% write
{\hskip10pt\hyperlink{ln.\csname toc@subsec.\thetocsectioncount.\thetocsubsectioncount\endcsname}{{\bf \thetocsectioncount.\thetocsubsectioncount}.\hskip5pt {\color{blue}\small #1}\leaderfill#2}}\par
}
@@ -654,6 +701,12 @@
% write
{\hskip20pt\hyperlink{ln.\csname toc@subsubsec.\thetocsectioncount.\thetocsubsectioncount.\thetocsubsubsectioncount\endcsname}{{\bf \thetocsectioncount.\thetocsubsectioncount.\thetocsubsubsectioncount}.\hskip5pt {\color{blue}\small #1}\leaderfill#2}}\par
}
+\newcounter{tocsubsubsubsectioncount}
+\def\tocsubsubsubsection #1#2{
+ \stepcounter{tocsubsubsubsectioncount}
+ % write
+ {\hskip30pt\hyperlink{ln.\csname toc@subsubsubsec.\thetocsectioncount.\thetocsubsectioncount.\thetocsubsubsectioncount.\thetocsubsubsubsectioncount\endcsname}{{\bf \thetocsectioncount.\thetocsubsectioncount.\thetocsubsubsectioncount.\thetocsubsubsubsectioncount}.\hskip5pt {\color{blue}\small #1}\leaderfill#2}}\par
+}
\def\tocappendices{
\medskip
\setcounter{tocsectioncount}0
diff --git a/doc/libs/iantheo.sty b/doc/libs/iantheo.sty
index 1945a5f..31842a4 100644
--- a/doc/libs/iantheo.sty
+++ b/doc/libs/iantheo.sty
@@ -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.
diff --git a/doc/libs/largearray.sty b/doc/libs/largearray.sty
index cf9075f..3a8762e 100644
--- a/doc/libs/largearray.sty
+++ b/doc/libs/largearray.sty
@@ -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.
diff --git a/doc/libs/point.sty b/doc/libs/point.sty
index a396d1c..796e0d2 100644
--- a/doc/libs/point.sty
+++ b/doc/libs/point.sty
@@ -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.
@@ -33,12 +33,15 @@
\newif\ifresetatsubsubsection
\DeclareOption{reset_at_subsubsection}{\resetatsubsubsectiontrue}
\DeclareOption{no_reset_at_subsubsection}{\resetatsubsubsectionfalse}
+\newif\ifresetatsubsubsubsection
+\DeclareOption{reset_at_subsubsubsection}{\resetatsubsubsubsectiontrue}
+\DeclareOption{no_reset_at_subsubsubsection}{\resetatsubsubsubsectionfalse}
\newif\ifresetattheo
\DeclareOption{reset_at_theo}{\resetattheotrue}
\DeclareOption{no_reset_at_theo}{\resetattheofalse}
\def\point@defaultoptions{
- \ExecuteOptions{reset_at_section, reset_at_subsection, reset_at_subsubsection, no_reset_at_theo}
+ \ExecuteOptions{reset_at_section, reset_at_subsection, reset_at_subsubsection, reset_at_subsubsubsection, no_reset_at_theo}
\ProcessOptions
%% reset at every new section
@@ -56,6 +59,11 @@
\let\point@oldsubsubsection\subsubsection
\gdef\subsubsection{\resetpointcounter\point@oldsubsubsection}
\fi
+ %% reset at every new subsubsubsection
+ \ifresetatsubsubsubsection
+ \let\point@oldsubsubsubsection\subsubsubsection
+ \gdef\subsubsubsection{\resetpointcounter\point@oldsubsubsubsection}
+ \fi
%% reset at every new theorem
\ifresetattheo
diff --git a/doc/simplesolv-doc.tex b/doc/simplesolv-doc.tex
index 722282a..23c7247 100644
--- a/doc/simplesolv-doc.tex
+++ b/doc/simplesolv-doc.tex
@@ -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.
@@ -27,7 +27,7 @@
\hfil{\bf\Large
{\tt simplesolv}\par
\medskip
-\hfil \large v0.3
+\hfil \large v0.4
}
\vfill
@@ -41,7 +41,7 @@
\pagestyle{plain}
\indent
-{\tt simplesolv} is a tool to compute the solution of the equations of the ``Simplified approach'' to the repulsive Bose gas introduced in\-~\cite{CJL20,CJL20b,CHe21}.
+{\tt simplesolv} is a tool to compute the solution of the equations of the ``Simplified approach'' to the repulsive Bose gas introduced in\-~\cite{CJL20,CJL21,CHe21}.
This approach provides an approximation to various observables of the ground state of the Hamiltonian
\begin{equation}
H_N=-\frac12\sum_{i=1}^N\Delta_i+\sum_{1\leqslant i\leqslant j\leqslant N}v(|x_i-x_j|)
@@ -85,6 +85,10 @@ The available methods are (see section\-~\ref{sec:methods} for further details)
\item \refname{sec:simpleq-iteration}{{\tt simpleq-iteration}} for the Simple equation with a soft potential using the iteration defined in\-~\cite{CJL20}.
\end{itemize}
Each method is described in detail below, along with the list of commands ({\tt command}) and parameters ({\tt params}) compatible with them.
+In addition, the scattering length can be displayed using the {\tt scattering\_length} command:
+\begin{code}
+ julia \$SIMPLESOLV/src/main.jl scattering\_length
+\end{code}
\bigskip
\indent
@@ -165,10 +169,10 @@ Unless otherwise noted, this method takes the following parameters (specified vi
{\tt order} ({\tt Int64}, default: 100): order used for all Gauss quadratures (denoted by $N$ below).
\item\makelink{param:easyeq_minlrho_init}{}
- {\tt minlrho\_init} ({\tt Float64}, default: {\tt rho}): to initialize the Newton algorithm, we first compute the solution for a smaller $\rho$, {\tt minlrho} is the minimal value for $\log_{10}\rho$ to start this initialization process.
+ {\tt minlrho\_init} ({\tt Float64}, default: $-6$): to initialize the Newton algorithm, we first compute the solution for a smaller $\rho$, {\tt minlrho} is the minimal value for $\log_{10}\rho$ to start this initialization process.
\item\makelink{param:easyeq_nlrho_init}{}
- {\tt nlrho\_init} ({\tt Int64}, default: 1): number of steps in the initialization process described above. Set to 1 to disable the incremental initialization process.
+ {\tt nlrho\_init} ({\tt Int64}, default: 0): number of steps in the initialization process described above. Set to 0 to disable the incremental initialization process.
\item\makelink{param:easyeq_bK}{}
{\tt bK}, {\tt bL} ({\tt Float64}, default: 1, 1): the values of $\beta_K$ and $\beta_L$.
@@ -188,7 +192,7 @@ The available {\tt commands} are the following.
\item {\tt energy\_rho}\makelink{command:easyeq_energy_rho}{}:
compute the energy $e$ as a function of $\rho$.
The Newton algorithm is initialized with the hardcore scattering solution (\ref{easyeq_init}) for the lowest $\rho$, and with the previously computed $\rho$ for the larger densities.\par
- \underline{Disabled parameters}: \refname{param:easyeq_rho}{{\tt rho}}, \refname{param:easyeq_minlrho_init}{{\tt minlrho\_init}} and \refname{param:easyeq_nlrho_init}{{\tt nlrho\_init}}.\par
+ \underline{Disabled parameters}: \refname{param:easyeq_rho}{{\tt rho}}.\par
\underline{Extra parameters}:
\begin{itemize}
\item\makelink{param:easyeq_minlrho}{}
@@ -200,8 +204,18 @@ The available {\tt commands} are the following.
\item\makelink{param:easyeq_nlrho}{}
{\tt nlrho} ({\tt Int64}, default: $100$): number of values for $\rho$ (spaced logarithmically).
+ \item\makelink{param:easyeq_minrho}{}
+ {\tt minrho} ({\tt Float64}, default: $10^{-6}$): minimal value for $\rho$.
+
+ \item\makelink{param:easyeq_maxrho}{}
+ {\tt maxrho} ({\tt Float64}, default: $10^{2}$): maximal value for $\rho$.
+
+ \item\makelink{param:easyeq_nrho}{}
+ {\tt nrho} ({\tt Int64}, default: $0$): number of values for $\rho$ (spaced linearly). If {\tt nrho} is $\neq0$, then the linear spacing will be used, and \refname{param:easyeq_minlrho}{{\tt minlrho}}, \refname{param:easyeq_maxlrho}{{\tt maxlrho}}, \refname{param:easyeq_nlrho}{{\tt nlrho}} will be ignored. Otherwise, the logarithmic spacing will be used and \refname{param:easyeq_minrho}{{\tt minrho}}, \refname{param:easyeq_maxrho}{{\tt maxrho}} will be ignored.
+
\item\makelink{param:easyeq_rhos}{}
- {\tt rhos} ({\tt Array\{Float64\}}, default: $(10^{{\tt minlrho}+\frac{{\tt maxlrho}-{\tt minlrho}}{{\tt nlrho}}n})_n$: list of values for $\rho$, specified as a `{\tt,}' separated list.
+ {\tt rhos} ({\tt Array\{Float64\}}): list of values for $\rho$, specified as a `{\tt,}' separated list.
+ This parameter takes precedence over \refname{param:easyeq_minlrho}{{\tt minlrho}}, \refname{param:easyeq_maxlrho}{{\tt maxlrho}}, \refname{param:easyeq_nlrho}{{\tt nlrho}}, \refname{param:easyeq_minrho}{{\tt minrho}}, \refname{param:easyeq_maxrho}{{\tt maxrho}}, \refname{param:easyeq_nrho}{{\tt nrho}}.
\end{itemize}
\underline{Output} (one line for each value of $\rho$): [$\rho$] [$e$] [Newton error $\epsilon$].
@@ -241,15 +255,100 @@ The available {\tt commands} are the following.
\underline{Extra parameters}: Same as \refname{command:easyeq_ux}{{\tt ux}}.\par
\underline{Output} (one line for each value of $x$): [$|x|$] [$2u(|x|)-\rho u\ast u(|x|)$]
+ \item\makelink{command:easyeq_2pt}{}
+ {\tt 2pt}: compute the spherically averaged two-point correlation function $C_2(|x|)$ at a given $\rho$.\par
+ \underline{Extra parameters}: same as \refname{command:easyeq_ux}{{\tt ux}}, plus\par
+ \begin{itemize}
+ \item\makelink{param:easyeq_window_L}{}
+ {\tt window\_L} ({\tt Float64}, default: $10^3$): size of the Hann window used to numerically invert the Fourier transform in the computation of the two-point correlation function, see\-~(\ref{hann}).
+ \end{itemize}
+ \underline{Output} (one line for each value of $|x|$): [$|x|$] [$C_2(|x|)$]
+
+ \item\makelink{command:easyeq_2pt_max}{}
+ {\tt 2pt\_max}: compute the maximum of the spherically averaged two-point correlation function $C_2(|x|)$ at a given $\rho$.\par
+ \underline{Extra parameters}: \refname{param:easyeq_window_L}{{\tt window\_L}} plus
+ \begin{itemize}
+ \item\makelink{param:easyeq_dx}{}
+ {\tt dx} ({\tt Float64}, default: $10^{-7}$): step used to numerically approximate derivatives.
+
+ \item\makelink{param:easyeq_x0}{}
+ {\tt x0} ({\tt Float64}, default: $1$): initial guess for the maximum is $\rho^{-1/3}\mathrm{\tt x0}$.
+
+ \item\makelink{param:easyeq_maxstep}{}
+ {\tt maxstep} ({\tt Float64}, default: $\infty$): maximal size of single step in maximization algorithm.
+
+ \item\makelink{param:easyeq_tolerance_max}{}
+ {\tt tolerance\_max} ({\tt Float64}, default: \refname{param:easyeq_tolerance}{{\tt tolerance}}): same as \refname{param:easyeq_tolerance}{{\tt tolerance}}, used for the Newton algorithm underlying the maximization algorithm.
+ \end{itemize}
+ \underline{Output}: [$|x_{\mathrm{max}}|$] [$C_2(|x_{\mathrm{max}}|)$]
+
+ \item\makelink{command:easyeq_2pt_max_rho}{}
+ {\tt 2pt\_max\_rho}: compute the maximum of the spherically averaged two-point correlation function $C_2(|x|)$ for a range of $\rho$.\par
+ \underline{Extra parameters}: same as \refname{command:easyeq_2pt_max}{{\tt easyeq\_2pt\_max}} plus those of \refname{command:easyeq_energy_rho}{{\tt energy\_rho}}.\par
+ \underline{Output} (one line for each value of $\rho$): [$\rho$] [$|x_{\mathrm{max}}|$] [$C_2(|x_{\mathrm{max}}|)$]\par
+ \underline{Multithread support}: yes, different values of $\rho$ split up among workers.
+
+ \item\makelink{command:easyeq_2pt_fourier}{}
+ {\tt 2pt\_fourier}: compute the spherically averaged Fourier transform of the two-point correlation function $\hat C_2(|k|)$ at a given $\rho$.\par
+ \underline{Extra parameters}:
+ \begin{itemize}
+ \item\makelink{param:easyeq_kmin}{}
+ {\tt kmin} ({\tt Float64}, default: 0): minimum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:easyeq_kmax}{}
+ {\tt kmax} ({\tt Float64}, default: 10): maximum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:easyeq_nk}{}
+ {\tt nk} ({\tt Int64}, default: 100): number of $|k|$'s to be printed.
+
+ \item\makelink{param:easyeq_2pt_fourier_window_L}{}
+ {\tt window\_L} ({\tt Float64}, default: 1000): what is actually computed is $\hat C_2$ convolved with a Gaussian of variance $1/\sqrt L$ with $L=\mathrm{\tt window\_L}$, see\-~(\ref{easyeq_gaussian}).
+ \end{itemize}
+ \underline{Output} (one line for each value of $|k|$): [$|k|$] [$\hat C_2(|k|)$].\par
+ \underline{Multithread support}: yes, different values of $k$ are split up among workers.
+
+ \item\makelink{command:easyeq_2pt_fourier_max}{}
+ {\tt 2pt\_fourier\_max}: compute the maximum of the spherically averaged Fourier transformed two-point correlation function $\hat C_2(|k|)$.\par
+ \underline{Extra parameters}: \refname{param:easyeq_2pt_fourier_window_L}{{\tt window\_L}}, \refname{param:easyeq_maxstep}{{\tt maxstep}} plus
+ \begin{itemize}
+ \item\makelink{param:easyeq_dk}{}
+ {\tt dk} ({\tt Float64}, default: $10^{-7}$): step used to numerically approximate derivatives.
+
+ \item\makelink{param:easyeq_k0}{}
+ {\tt k0} ({\tt Float64}, default: $1$): initial guess for the maximum is $\rho^{1/3}\mathrm{\tt k0}$.
+ \end{itemize}
+ \underline{Output}: [$|k_{\mathrm{max}}|$] [$\hat C_2(|k_{\mathrm{max}}|)$]\par
+
+ \item\makelink{command:easyeq_2pt_fourier_max_rho}{}
+ {\tt 2pt\_fourier\_max\_rho}: compute the maximum of the spherically averaged Fourier transformed two-point correlation function $\hat C_2(|k|)$ for a range of $\rho$.\par
+ \underline{Extra parameters}: same as those of \refname{command:easyeq_2pt_fourier_max}{{\tt 2pt\_fourier\_max}} plus those of \refname{command:easyeq_energy_rho}{{\tt energy\_rho}}.\par
+ \underline{Output} (one line for each value of $\rho$): [$\rho$] [$|k_{\mathrm{max}}|$] [$\hat C_2(|k_{\mathrm{max}}|)$]\par
+ \underline{Multithread support}: yes, different values of $\rho$ split up among workers.
+
+ \item\makelink{command:easyeq_momentum_distribution}{}
+ {\tt momentum\_distribution}: compute the momentum distribution $\mathcal M(|k|)$ at a given $\rho$. The momentum distribution is computed for $k=k_{l,j}$ (see\-~(\ref{klj})).\par
+ \underline{Extra parameters}:
+ \begin{itemize}
+ \item\makelink{param:easyeq_momentum_kmin}{}
+ {\tt kmin} ({\tt Float64}, default: 0): minimum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:easyeq_momentum_kmax}{}
+ {\tt kmax} ({\tt Float64}, default: 10): maximum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:easyeq_momentum_window_L}{}
+ {\tt window\_L} ({\tt Float64}, default: 1000): what is actually computed is $\mathfrak M_k$ convolved with a Gaussian of variance $1/\sqrt L$ where $L=\sqrt{\mathrm{\tt window\_L}}/k^2$, see\-~(\ref{easyeq_gaussian_momt}).
+ \end{itemize}
+ \underline{Output} (one line for each value of $|k|$): [$|k|$] [$\mathcal M(|k|)$]
+
\end{itemize}
\subsubsection{Description}
-\point{\bf Fourier space formulation.}
+\subsubsubsection{Fourier space formulation}
The computation is carried out in Fourier space.
We take the convention that the Fourier transform of a function $f(|x|)$ is
\begin{equation}
\hat f(|k|)=\int_{\mathbb R^3} dx\ e^{ikx}f(|x|)
- =\frac{4\pi}{|k|}\int_0^\infty dr\ \frac{\sin(|k|r)}rf(r)
+ =\frac{4\pi}{|k|}\int_0^\infty dr\ r\sin(|k|r)f(r)
.
\end{equation}
In Fourier space, (\ref{easyeq}) becomes
@@ -268,6 +367,7 @@ with
,\quad
\hat f\hat\ast\hat g(|k|):=\int_{\mathbb R^3}\frac{dp}{(2\pi)^3}\ \hat f(|k-p|)\hat g(|p|)
.
+ \label{hatS_easyeq}
\end{equation}
We write this as a quadratic equation for $\hat u$, and solve it, keeping the solution that decays as $|k|\to\infty$:
\begin{equation}
@@ -287,6 +387,15 @@ with
\Phi(x):=\frac{2(1-\sqrt{1-x})}x
.
\end{equation}
+We can write this as a root finding problem:
+\begin{equation}
+ \Omega(u):=
+ \rho\hat u(|k|)-
+ \frac{\hat S(|k|)}{2A_K(|k|)(\xi(|k|)+1)}\Phi\left({\textstyle\frac{A_L(|k|)}{A_K^2(|k|)}\frac{\hat S(|k|)}{(\xi(|k|)+1)^2}}\right)
+ =0
+ .
+ \label{Omega_easyeq}
+\end{equation}
Furthermore, using bipolar coordinates (see lemma\-~\ref{lemma:bipolar}), we write $\hat S$ as
\begin{equation}
\hat S(|k|)=\hat v(|k|)-\frac1{8\pi^3}\int_0^\infty dt\ t\hat u(t)\Eta(|k|,t)
@@ -305,7 +414,7 @@ By a simple change of variables,
\end{equation}
\bigskip
-\point{\bf Evaluating integrals.}
+\subsubsubsection{Evaluating integrals}
To compute these integrals numerically, we will use Gauss-Legendre quadratures:
\begin{equation}
\int_0^1 dt\ f(t)\approx\frac12\sum_{i=1}^N w_if\left({\textstyle\frac{r_i+1}2}\right)
@@ -353,6 +462,7 @@ with
\mathbb S_i:=\hat v_i-\frac1{16\pi^3\rho}\sum_{j=1}^N w_j\frac{(1-y_j)\mathbb U_j\Eta(k_i,k_j)}{y_j^3}
,\quad
\mathbb E:=\hat v(0)-\frac1{16\pi^3\rho}\sum_{j=1}^N w_j\frac{(1-y_j)\mathbb U_j\Eta(0,k_j)}{y_j^3}
+ \label{bbSE_easyeq}
\end{equation}
\begin{equation}
\mathbb X_i:=\frac{k_i^2}{2\rho\mathbb A_{K,i}}
@@ -361,12 +471,12 @@ with
This is a discrete equation for the vector $(\mathbb U_i)_{i=1}^N$.
\bigskip
-\point{\bf Main algorithm to compute $\mathbb U$.}\par\penalty10000
+\subsubsubsection{Main algorithm to compute $\mathbb U$}\par\penalty10000
\medskip\penalty10000
-\subpoint
+\point
We rewrite\-~(\ref{bbU_easyeq}) as a root finding problem:
\begin{equation}
- \Xi_i(\mathbb U):=\mathbb U_i-\frac{\mathbb T_i}{2(\mathbb X_i+1)}\Phi\left({\textstyle B_i\frac{\mathbb T_i}{(\mathbb X_i+1)^2}}\right)
+ \Xi_i(\mathbb U):=\mathbb U_i-\frac{\mathbb T_i}{2(\mathbb X_i+1)}\Phi\left({\textstyle\mathbb B_i\frac{\mathbb T_i}{(\mathbb X_i+1)^2}}\right)
=0
\label{root_easyeq}
\end{equation}
@@ -381,7 +491,7 @@ where $D\Xi$ is the Jacobian of $\Xi$:
\end{equation}
\bigskip
-\subpoint
+\point
For small values of $\rho$, we initialize the algorithm with the hardcore scattering solution
\begin{equation}
\hat u_0(k)=\frac{4\pi a_0}{k^2}
@@ -397,7 +507,7 @@ This is a good approximation for small $\rho$.
For larger $\rho$, we choose $\mathbb U^{(0)}$ as the solution of {\tt easyeq} for a slightly smaller $\rho$, and proceed inductively (using the parameters \refname{param:easyeq_minlrho_init}{{\tt minlrho\_init}} and \refname{param:easyeq_nlrho_init}{{\tt nlrho\_init}}).
\bigskip
-\subpoint
+\point
We are left with computing the Jacobian of $\Xi$:
\begin{equation}
\begin{largearray}
@@ -436,7 +546,7 @@ with
\end{equation}
\bigskip
-\subpoint
+\point
We iterate the Newton algorithm until the Newton relative error $\epsilon$ becomes smaller than the \refname{param:easyeq_tolerance}{{\tt tolerance}} parameter.
The Newton error is defined as
\begin{equation}
@@ -466,8 +576,8 @@ and the solution $u$ in real space is obtained by inverting the Fourier transfor
To compute $2u-\rho u\ast u$, we replace $\hat u$ with $2\hat u-\rho\hat u^2$ in the previous equation.
\bigskip
-\point{\bf Condensate fraction.}
-Finally, to compute the uncondensed fraction, we solve the modified {\tt easyeq} (see\-~\cite{CJL20b})
+\subsubsubsection{Condensate fraction}
+Finally, to compute the uncondensed fraction, we solve the modified {\tt easyeq} (see\-~\cite{CJL21})
\begin{equation}
(-\Delta+2\mu)u_\mu=v(1-u_\mu)-2\rho K+\rho^2L
\label{easyeq_mu}
@@ -518,6 +628,351 @@ We then compute, using\-~(\ref{jacobian_easyeq}),
.
\end{equation}
+\subsubsubsection{Correlation function (spherical average)}
+The two-point correlation function is
+\begin{equation}
+ c_2(x):=
+ 2\rho\frac{\delta e}{\delta v(x)}
+\end{equation}
+and its spherical average is
+\begin{equation}
+ C_2(|x|):=\frac1{4\pi|x|^2}\int dy\ \delta(|x|-|y|)c_2(y)
+ .
+\end{equation}
+In Fourier space,
+\begin{equation}
+ c_2(x)=
+ 2\rho
+ \int dk\ e^{ikx}\frac{\delta e}{\delta\hat v(k)}
+\end{equation}
+so
+\begin{equation}
+ C_2(|x|)=
+ 2\rho\int dk\ \left(\frac1{4\pi|x|^2}\int dy\ \delta(|x|-|y|)e^{iky}\right)\frac{\delta e}{\delta\hat v(k)}
+ =2\rho\int dk\ \frac{\sin(|k||x|)}{|k||x|}\frac{\delta e}{\delta\hat v(k)}
+ .
+ \label{easyeq_C2fourier}
+\end{equation}
+\bigskip
+
+\point
+We can compute this quantity by considering a modified {\tt easyeq} in Fourier space, by formally replacing $\hat v$ with
+\begin{equation}
+ \hat v+\lambda g(|k|)
+ ,\quad
+ g(|k|):=\frac{\sin(|k||x|)}{|k||x|}
+ .
+ \label{2pt_addv}
+\end{equation}
+Indeed, if $e_\lambda$ denotes the energy of this modified equation,
+\begin{equation}
+ \partial_\lambda e_\lambda|_{\lambda=0}
+ =\int dk\ \frac{\delta e}{\delta\hat v(k)}\partial_\lambda({\textstyle \hat v(k)+\lambda g(|k|)})
+ =\int dk\ g(|k|)\frac{\delta e}{\delta\hat v(k)}
+ .
+\end{equation}
+So, denoting the solution of the modified equation by $u_\lambda$,
+\begin{equation}
+ C_2(x)=2\rho\partial_\lambda e_\lambda|_{\lambda=0}
+ =\rho^2g(0)-\rho^2\int\frac{dk}{(2\pi)^3}\ (g(k)\hat u(k)+\hat v(k)\partial_\lambda\hat u_\lambda(k)|_{\lambda=0})
+ .
+\end{equation}
+We compute $\partial_\lambda u_\lambda|_{\lambda=0}$ in the same way as the uncondensed fraction: we define $\Xi(\mathbb U,\lambda)$ by formally adding $\lambda g(|k|)$ to $\hat v$, solve $\Xi(\mathbb U,\lambda)=0$, and differentiate:
+\begin{equation}
+ \partial_\lambda\mathbb U|_{\lambda=0}=-(D\Xi)^{-1}\partial_\lambda\Xi|_{\lambda=0}
+ .
+\end{equation}
+\bigskip
+
+\point
+We compute $\partial_\lambda\Xi|_{\lambda=0}$:
+\begin{equation}
+ \begin{largearray}
+ \partial_\lambda\Xi_i
+ =
+ -\frac1{2(\mathbb X_i+1)}\left(
+ \partial_\lambda\mathbb T_i-\frac{\mathbb T_i\partial_\lambda\mathbb X_i}{\mathbb X_i+1}
+ \right)\Phi\left({\textstyle\mathbb B_i\frac{\mathbb T_i}{(\mathbb X_i+1)^2}}\right)
+ \\[0.5cm]\hfill
+ -\frac{\mathbb T_i}{2(\mathbb X_i+1)^3}\left(
+ \mathbb B_i\partial_\lambda\mathbb T_i+\mathbb T_i\partial_\lambda\mathbb B_i-2\frac{\mathbb B_i\mathbb T_i\partial_\lambda\mathbb X_i}{\mathbb X_i+1}
+ \right)\partial\Phi\left({\textstyle\mathbb B_i\frac{\mathbb T_i}{(\mathbb X_i+1)^2}}\right)
+ \end{largearray}
+ \label{dXi_2pt_easyeq}
+\end{equation}
+with
+\begin{equation}
+ \partial_\lambda\mathbb B_i=
+ (\beta_L(1-\beta_K)-\beta_K(1-\beta_L))
+ \frac{\mathbb E\partial_\lambda\mathbb S_i-\mathbb S_i\partial_\lambda\mathbb E}{(\beta_K\mathbb S_i+(1-\beta_K)\mathbb E)^2}
+\end{equation}
+\begin{equation}
+ \partial_\lambda\mathbb T_i=
+ (1-\beta_K)\frac{\mathbb E\partial_\lambda\mathbb S_i-\mathbb S_i\partial_\lambda\mathbb E}{(\beta_K\mathbb S_i+(1-\beta_K)\mathbb E)^2}
+ ,\quad
+ \partial_\lambda\mathbb A_{K,i}=\beta_K\partial_\lambda\mathbb S_i+(1-\beta_K)\partial_\lambda\mathbb E
+\end{equation}
+\begin{equation}
+ \partial_\lambda\mathbb S_i:=g(k_i)
+ -\frac1{16\pi^3\rho}\sum_{j=1}^N w_j\frac{(1-y_j)\mathbb U_j\partial_\lambda\Eta(k_i,k_j)}{y_j^3}
+\end{equation}
+\begin{equation}
+ \partial_\lambda \mathbb E:=g(0)-\frac1{16\pi^3\rho}\sum_{j=1}^N w_j\frac{(1-y_j)\mathbb U_j\partial_\lambda\Eta(0,k_j)}{y_j^3}
+\end{equation}
+\begin{equation}
+ \partial_\lambda\mathbb X_i:=-\frac{k_i^2}{2\rho\mathbb A_{K,i}^2}\partial_\lambda\mathbb A_{K,i}
+\end{equation}
+where $\partial\lambda\Eta$ is computed similarly to $\Eta$\-~(\ref{Eta}) but with $\hat v$ replaced by $g$:
+\begin{equation}
+ \partial_\lambda\Eta(y,t)=
+ 4\pi\left(\mathds 1_{y>t}\frac{t}y+\mathds 1_{y\leqslant t}\right)
+ \int_0^1 ds\ ((y+t)s+|y-t|(1-s))g((y+t)s+|y-t|(1-s))
+ .
+ \label{GG}
+\end{equation}
+\bigskip
+
+\point
+In order to invert the Fourier transform in\-~(\ref{easyeq_C2fourier}) numerically, we will use a Hann window (see appendix\-~\ref{appendix:hann})
+\begin{equation}
+ H_L(k):=\mathds 1_{|k|<\frac L2}\cos^2({\textstyle\frac{\pi|k|}{L}})
+ .
+ \label{hann}
+\end{equation}
+The parameter $L$ is set using \refname{param:easyeq_window_L}{{\tt window\_L}}.
+The computation is changed only in that $g$ is changed to $H_L(k)\frac{\sin(|k||x|)}{|k||x|}$.
+\bigskip
+
+\point
+To compute the maximum of $C_2$, we use a modified Newton algorithm.
+The initial guess for the maximum is $|x_0|=\rho^{-\frac13}$\refname{param:easyeq_x0}{{\tt x0}}.
+The modified Newton algorithm is an iteration:
+\begin{equation}
+ x_{n+1}=x_n+\frac{\partial C_2(|x_n|)}{|\partial^2C_2(|x_n|)|}
+ \label{easyeq_newton_2pt}
+\end{equation}
+in which the derivatives are approximated using finite differences:
+\begin{equation}
+ \partial C_2(x)\approx \frac{C_2(|x|+dx)-C_2(|x|)}{dx}
+ ,\quad
+ \partial^2 C_2(x)\approx \frac{C_2(|x|+dx)+C_2(|x|-dx)-2C_2(|x|)}{dx^2}
+ .
+ \label{easyeq_dx_2pt}
+\end{equation}
+This is a modification of the usual Newton iteration $x_n+\partial C_2/\partial^2C_2$ which is designed to follow the direction of the gradient, and thus to move toward a local maximum.
+In addition, if $|\partial C_2|/|\partial^2 C_2|$ is larger than \refname{param:easyeq_maxstep}{{\tt maxstep}}, then the step is replaced with $\pm$\refname{param:easyeq_maxstep}{{\tt maxstep}}.
+This prevents the algorithm from stepping over a maximum and land on another, further away.
+This is useful if one has a good idea of where the global maximum is, and does not want to get trapped in a smaller local maximum.
+\bigskip
+
+\indent
+The algorithm is run for a maximum of \refname{param:easyeq_maxiter}{{\tt maxiter}} iterations, or until $|x_{n+1}-x_n|$ is smaller than \refname{param:easyeq_tolerance}{{\tt tolerance}}.
+If the maximal number of iterations is reached, or if the solution found is not a local maximum, then the algorithm fails, and returns $+\infty$.
+The point thus computed is therefore a local maximum, but it is not guaranteed to be the global maximum.
+
+\subsubsubsection{Fourier transform of two-point correlation (spherical average)}
+The Fourier transform of the two-point correlation function is
+\begin{equation}
+ \hat c_2(q):=
+ 2\rho\frac{\delta e}{\delta v(q)}
+\end{equation}
+and its spherical average is
+\begin{equation}
+ \hat C_2(|q|):=\frac1{4\pi|q|^2}\int dk\ \delta(|q|-|k|)c_2(k)
+ =
+ \frac\rho{2\pi|q|^2}\int dk\ \delta(|q|-|k|)\frac{\delta e}{\delta\hat v(k)}
+ .
+\end{equation}
+\bigskip
+
+\point
+To compute $\frac{\delta e}{\delta\hat v(q)}$, one idea would be to proceed in the same way as for the two-point correlation function, by replacing $\hat v$ with
+\begin{equation}
+ \hat v+\lambda g(|k|)
+ ,\quad
+ g(|k|):=\frac1{4\pi|q|^2}\delta(|q|-|k|)
+\end{equation}
+where $\delta$ is the Dirac-delta function distribution (compare this with\-~(\ref{2pt_addv})).
+However, the $\delta$ function causes all sorts of problems with the quadratures.
+\bigskip
+
+\point
+Instead, we approximate $\hat C_2$ by convolving it with a normalized Gaussian: let
+\begin{equation}
+ \Gamma_L(|k|):=\left(\frac{L}{2\pi}\right)^{\frac32}e^{-\frac L2k^2}
+ \label{easyeq_gaussian}
+\end{equation}
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)
+ :=
+ \int dp\ \hat C_2(|q-p|)\Gamma_L(|p|)
+ =\int dk\ \int dp\ \frac\rho{2\pi|q-p|^2}\delta(|q-p|-|k|)\frac{\delta e}{\delta\hat v(k)}\Gamma_L(|p|)
+\end{equation}
+which by lemma\-~\ref{lemma:bipolar} is
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)
+ =\int dk\
+ \frac\rho{|q|}
+ \frac{\delta e}{\delta\hat v(k)}
+ \int_0^\infty dt\ \int_{||q|-t|}^{|q|+t}ds\ s\frac{\delta(t-|k|)}t\Gamma_L(s)
+\end{equation}
+that is
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)
+ =\int dk\
+ \frac{\delta e}{\delta\hat v(k)}
+ \frac{\rho}{|q||k|}
+ \int_{||q|-|k||}^{|q|+|k|}ds\ s\Gamma_L(s)
+\end{equation}
+which is the directional derivative of $e$ with respect to $\hat v$ in the direction of $2\rho g$ with
+\begin{equation}
+ g(|k|):=\frac1{2|q||k|}\int_{||q|-|k||}^{|q|+|k|}ds\ s\Gamma_L(s)
+ =
+ \frac1{2|k|rL}(\Gamma_L(|k|-r)-\Gamma_L(|k|+r))
+ .
+ \label{easyeq_2pt_fourier_g}
+\end{equation}
+Note that
+\begin{equation}
+ g(0):=\Gamma_L(|q|)
+ .
+\end{equation}
+To compute this derivative, we replace $\hat v$ with
+\begin{equation}
+ \hat v+\lambda g(|k|)
+\end{equation}
+so, denoting the solution of the modified equation by $u_\lambda$, for $q\neq 0$,
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)=2\rho\partial_\lambda e_\lambda|_{\lambda=0}
+ =\rho^2\left(
+ -\int\frac{dk}{(2\pi)^3}\ g(|k|)\hat u(|k|)
+ -\int\frac{dk}{(2\pi)^3}\ \hat v(|k|)\partial_\lambda\hat u_\lambda(|k|)|_{\lambda=0}
+ \right)
+ .
+\end{equation}
+To compute $\partial_\lambda\hat u_\lambda|_{\lambda=0}$, we differentiate $\Xi(\mathbb U,\lambda)=0$:
+\begin{equation}
+ \partial_\lambda\mathbb U|_{\lambda=0}=-(D\Xi)^{-1}\partial_\lambda\Xi|_{\lambda=0}
+ .
+\end{equation}
+The computation of $\partial_\lambda\Xi|_{\lambda=0}$ is identical to\-~(\ref{dXi_2pt_easyeq}), but with the $g$ defined in\-~(\ref{easyeq_2pt_fourier_g}).
+\bigskip
+
+\point
+To compute the maximum of $\hat C_2$, we proceed as for $C_2$, see\-~(\ref{easyeq_newton_2pt})-(\ref{easyeq_dx_2pt}).
+The only difference is that the algorithm is initialized with $|k_0|=\rho^{\frac13}$\refname{param:easyeq_k0}{{\tt k0}}.
+
+\subsubsubsection{Momentum distribution}
+To compute the momentum distribution (see\-~\cite{CHe21}), we add a parameter $\lambda$ to {\tt easyeq}:
+\begin{equation}
+ -\Delta u_\lambda(|x|)
+ =
+ (1-u_\lambda(|x|))v(|x|)-2\rho K(|x|)+\rho^2 L(|x|)
+ -2\lambda \hat u_0(q)\cos(q\cdot x)
+\end{equation}
+($\hat u_0\equiv\hat u_\lambda|_{\lambda=0}$).
+The momentum distribution is then
+\begin{equation}
+ \mathcal M(q)=\partial_\lambda e|_{\lambda=0}
+ =-\frac\rho2\int\frac{dk}{(2\pi)^3}\ \hat v(k)\partial_\lambda\hat u_\lambda(k)|_{\lambda=0}
+ .
+\end{equation}
+\bigskip
+
+\point
+Note that the Fourier transform of $2\lambda\hat u_0(q)\cos(q\cdot x)$ is
+\begin{equation}
+ -(2\pi)^3\lambda\hat u_0(q)(\delta(q+k)+\delta(q-k))
+ .
+ \label{fouriermomentum}
+\end{equation}
+The presence of delta functions does not play well with the quadratures.
+To get around this, we instead compute a regularization of $\mathcal M(q)$ by convolving it with a peaked spherically symmetric function.
+Let $\Gamma_L$ denote the Gaussian with variance $1/\sqrt L$
+\begin{equation}
+ \Gamma_L(|k|):=\left(\frac{L}{2\pi}\right)^{\frac32}e^{-\frac L2k^2}
+ .
+ \label{easyeq_gaussian_momt}
+\end{equation}
+In fact, we will scale $L$ with $k$, and set $L$ to
+\begin{equation}
+ L=\sqrt{\mathrm{\refname{param:easyeq_momentum_window_L}{{\tt window\_L}}}}/k^2
+ .
+\end{equation}
+To compute
+\begin{equation}
+ \mathfrak M(q):=\mathcal M\ast\Gamma_L(q)
+\end{equation}
+we solve the equation
+\begin{equation}
+ -\Delta u_\lambda(|x|)
+ =
+ (1-u_\lambda(|x|))v(|x|)-2\rho K(|x|)+\rho^2 L(|x|)
+ -2\lambda\int dk\ \hat u_0(k)\cos(k\cdot x)\Gamma_L(q-k)
+ .
+\end{equation}
+Note that the Fourier transform of
+\begin{equation}
+ -2\lambda\int dk\ \hat u_0(k)\cos(k\cdot x)\Gamma_L(q-k)
+\end{equation}
+is
+\begin{equation}
+ -(2\pi)^3\lambda\hat u_0(q)(\Gamma_L(k+q)+\Gamma_L(k-q))
+ .
+\end{equation}
+Since the ground state is unique, $\mathcal M$ is spherically symmetric.
+The term $\Gamma_L(k\pm q)$ is not, so we take its spherical average (which will not change the final result): by lemma\-~\ref{lemma:bipolar},
+\begin{equation}
+ -\frac1{4\pi r^2}\int dq\ \delta(|q|-r)(2\pi)^3\lambda\hat u_0(q)(\Gamma_L(k+q)+\Gamma_L(k-q))
+ =
+ -\frac{(2\pi)^3}{|k|r}\lambda\hat u_0(r)\int_{||k|-r|}^{|k|+r} ds\ s\Gamma_L(s)
+ .
+\end{equation}
+In this setup, the approximation of the delta function is thus
+\begin{equation}
+ \tilde\delta(|k|,r):=
+ \frac1{2|k|r}\int_{||k|-r|}^{|k|+r} ds\ s\Gamma_L(s)
+ =
+ \frac{1}{2|k|rL}(\Gamma_L(|k|-r)-\Gamma_L(|k|+r))
+ .
+\end{equation}
+\bigskip
+
+\point
+To compute the momentum distribution at $q$, we define $\Xi(\mathbb U,\lambda)$ by replacing $\mathbb T$ with
+\begin{equation}
+ \mathbb T_{i}=
+ \frac1{\mathbb A_{K,i}}
+ \left(
+ \mathbb S_i
+ -2(2\pi)^3\lambda \hat u(|q|)\tilde\delta(k_i,|q|)
+ \right)
+ .
+\end{equation}
+Then we solve $\Xi(\mathbb U,\lambda)=0$, and differentiate:
+\begin{equation}
+ \partial_\lambda\mathbb U|_{\lambda=0}=-(D\Xi)^{-1}\partial_\lambda\Xi|_{\lambda=0}
+ .
+\end{equation}
+Finally,
+\begin{equation}
+ \partial_\lambda\Xi_{i}|_{\lambda=0}
+ =
+ -\partial_\lambda\mathbb T_{i}|_{\lambda=0}\left(
+ \frac1{2(\mathbb X_{i}+1)}
+ \Phi\left(\mathbb B_i{\textstyle\frac{\mathbb T_{i}}{(\mathbb X_{i}+1)^2}}\right)
+ +\frac{\mathbb B_i\mathbb T_{i}}{2(\mathbb X_{i}+1)^3}
+ \partial\Phi\left(\mathbb B_i{\textstyle\frac{\mathbb T_{i}}{(\mathbb X_{l,j}+1)^2}}\right)
+ \right)
+\end{equation}
+with
+\begin{equation}
+ \partial_\lambda\mathbb T_{i}|_{\lambda=0}=
+ -\frac{2(2\pi)^3}{\mathbb A_{K,i}} \hat u(|q|)\tilde\delta(k_{i},|q|)
+ .
+\end{equation}
+\bigskip
+
\subsection{\tt anyeq}\label{sec:anyeq}
\indent
This method is used to solve any of the equations in the Simplified approach.
@@ -598,11 +1053,11 @@ Unless otherwise noted, this method takes the following parameters (specified vi
\item\makelink{param:anyeq_J}{}
{\tt J} ({\tt Int64}, default: 10): number of splines (denoted by $J$ below).
- \item\makelink{param:anyeq_minlrho_init}{}
- {\tt minlrho\_init} ({\tt Float64}, default: \refname{param:anyeq_rho}{{\tt rho}}): we initialize the Newton algorithm using the solution of \refname{eq:easyeq_medeq}{{\tt medeq}}, computed using the methods in \refname{sec:easyeq}{{\tt easyeq}}. This option is passed to the underlying \refname{sec:easyeq}{{\tt easyeq}} routine.
-
\item\makelink{param:anyeq_nlrho_init}{}
- {\tt nlrho\_init} ({\tt Int64}, default: 1): this option is passed to the underlying \refname{sec:easyeq}{{\tt easyeq}} routine to initialize the Newton algorithm.
+ {\tt nlrho\_init} ({\tt Int64}, default: 0): we initialize the Newton algorithm using the solution of \refname{eq:easyeq_medeq}{{\tt medeq}}, computed using the methods in \refname{sec:easyeq}{{\tt easyeq}}. If {\tt nlrho\_init} is $\neq 0$, then the solution of \refname{eq:easyeq_medeq}{{\tt medeq}} is first computed for {\tt nlrho} smaller values of $\rho$ starting from $10^{\mathrm{\refname{param:anyeq_minlrho_init}{{\tt minlrho\_init}}}}$. This is useful when $\rho$ is too large for the solution of \refname{eq:easyeq_medeq}{{\tt medeq}} to be computed directly.
+
+ \item\makelink{param:anyeq_minlrho_init}{}
+ {\tt minlrho\_init} ({\tt Float64}, default: $-6$): see \refname{param:anyeq_nlrho_init}{{\tt nlrho\_init}}.
\item\makelink{param:anyeq_aK}{}
{\tt aK}, {\tt bK}, {\tt gK}, {\tt aL1}, {\tt bL1}, {\tt aL2}, {\tt bL2}, {\tt gL2}, {\tt aL3}, {\tt bL3}, {\tt gL3} ({\tt Float64}, default: 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0): the values of $\alpha_K$, $\beta_K$, $\gamma_K$, $\alpha_{L,1}$, $\beta_{L,1}$, $\alpha_{L,2}$, $\beta_{L,2}$, $\gamma_{L,2}$, $\alpha_{L,3}$, $\beta_{L,3}$, $\gamma_{L,3}$.
@@ -623,7 +1078,7 @@ The available {\tt commands} are the following.
\item\makelink{command:anyeq_energy_rho}{}
{\tt energy\_rho}: compute the energy $e$ as a function of $\rho$.
The Newton algorithm is initialized with the solution of \refname{eq:easyeq_medeq}{{\tt medeq}}.\par
- \underline{Disabled parameters}: \refname{param:anyeq_rho}{{\tt rho}}, \refname{param:anyeq_minlrho_init}{{\tt minlrho\_init}} and \refname{param:anyeq_nlrho_init}{{\tt nlrho\_init}}.\par
+ \underline{Disabled parameters}: \refname{param:anyeq_rho}{{\tt rho}}.\par
\underline{Extra parameters}:
\begin{itemize}
\item\makelink{param:anyeq_minlrho}{}
@@ -635,8 +1090,18 @@ The available {\tt commands} are the following.
\item\makelink{param:anyeq_nlrho}{}
{\tt nlrho} ({\tt Int64}, default: $100$): number of values for $\rho$ (spaced logarithmically).
+ \item\makelink{param:anyeq_minrho}{}
+ {\tt minrho} ({\tt Float64}, default: $10^{-6}$): minimal value for $\rho$.
+
+ \item\makelink{param:anyeq_maxrho}{}
+ {\tt maxrho} ({\tt Float64}, default: $10^{2}$): maximal value for $\rho$.
+
+ \item\makelink{param:anyeq_nrho}{}
+ {\tt nrho} ({\tt Int64}, default: $0$): number of values for $\rho$ (spaced linearly). If {\tt nrho} is $\neq0$, then the linear spacing will be used, and \refname{param:anyeq_minlrho}{{\tt minlrho}}, \refname{param:anyeq_maxlrho}{{\tt maxlrho}}, \refname{param:anyeq_nlrho}{{\tt nlrho}} will be ignored. Otherwise, the logarithmic spacing will be used and \refname{param:anyeq_minrho}{{\tt minrho}}, \refname{param:anyeq_maxrho}{{\tt maxrho}} will be ignored.
+
\item\makelink{param:anyeq_rhos}{}
- {\tt rhos} ({\tt Array\{Float64\}}, default: $(10^{{\tt minlrho}+\frac{{\tt maxlrho}-{\tt minlrho}}{{\tt nlrho}}n})_n$: list of values for $\rho$, specified as a `{\tt,}' separated list.
+ {\tt rhos} ({\tt Array\{Float64\}}): list of values for $\rho$, specified as a `{\tt,}' separated list.
+ This parameter takes precedence over \refname{param:anyeq_minlrho}{{\tt minlrho}}, \refname{param:anyeq_maxlrho}{{\tt maxlrho}}, \refname{param:anyeq_nlrho}{{\tt nlrho}}, \refname{param:anyeq_minrho}{{\tt minrho}}, \refname{param:anyeq_maxrho}{{\tt maxrho}}, \refname{param:anyeq_nrho}{{\tt nrho}}.
\end{itemize}
\underline{Output} (one line for each value of $\rho$): [$\rho$] [$e$] [Newton error $\epsilon$].\par
\underline{Multithread support}: yes, different values of $\rho$ split up among workers.
@@ -686,14 +1151,10 @@ The available {\tt commands} are the following.
{\tt nx} ({\tt Int64}, default: 100): number of points to print (linearly spaced).
\end{itemize}
- \underline{Output} (one line for each value of $x$): [$|x|$] [$\mathcal Re(u(|x|))$] [$\mathcal Im(u(|x|))$]
-
- \item\makelink{command:anyeq_momentum_distribution}{}
- {\tt momentum\_distribution}: compute the momentum distribution $\mathfrak M(|k|)$ at a given $\rho$.\par
- \underline{Output} (one line for each value of $|k|$): [$|k|$] [$\mathfrak M(|k|)$]
+ \underline{Output} (one line for each value of $x$): [$|x|$] [$u(|x|)$]
- \item\makelink{command_anyeq_2pt}{}
- {\tt 2pt}: compute the two-point correlation function $C_2(|x|)$ at a given $\rho$.\par
+ \item\makelink{command:anyeq_2pt}{}
+ {\tt 2pt}: compute the spherically averaged two-point correlation function $C_2(|x|)$ at a given $\rho$.\par
\underline{Extra parameters}: same as \refname{command:anyeq_ux}{{\tt ux}}, plus\par
\begin{itemize}
\item\makelink{param:anyeq_window_L}{}
@@ -701,16 +1162,99 @@ The available {\tt commands} are the following.
\end{itemize}
\underline{Output} (one line for each value of $|x|$): [$|x|$] [$C_2(|x|)$]
+ \item\makelink{command:anyeq_2pt_max}{}
+ {\tt 2pt\_max}: compute the maximum of the spherically averaged two-point correlation function $C_2(|x|)$ at a given $\rho$.\par
+ \underline{Extra parameters}: \refname{param:anyeq_window_L}{{\tt window\_L}} plus
+ \begin{itemize}
+ \item\makelink{param:anyeq_dx}{}
+ {\tt dx} ({\tt Float64}, default: $10^{-7}$): step used to numerically approximate derivatives.
+
+ \item\makelink{param:anyeq_x0}{}
+ {\tt x0} ({\tt Float64}, default: $1$): initial guess for the maximum is $\rho^{-1/3}\mathrm{\tt x0}$.
+
+ \item\makelink{param:anyeq_maxstep}{}
+ {\tt maxstep} ({\tt Float64}, default: $\infty$): maximal size of single step in maximization algorithm.
+
+ \item\makelink{param:easyeq_tolerance_max}{}
+ {\tt tolerance\_max} ({\tt Float64}, default: \refname{param:easyeq_tolerance}{{\tt tolerance}}): same as \refname{param:easyeq_tolerance}{{\tt tolerance}}, used for the Newton algorithm underlying the maximization algorithm.
+ \end{itemize}
+ \underline{Output}: [$|x_{\mathrm{max}}|$] [$C_2(|x_{\mathrm{max}}|)$]
+
+ \item\makelink{command:anyeq_2pt_max_rho}{}
+ {\tt 2pt\_max\_rho}: compute the maximum of the spherically averaged two-point correlation function $C_2(|x|)$ for a range of $\rho$.\par
+ \underline{Extra parameters}: same as \refname{command:anyeq_2pt_max}{{\tt anyeq\_2pt\_max}} plus those of \refname{command:anyeq_energy_rho}{{\tt energy\_rho}}.\par
+ \underline{Output} (one line for each value of $\rho$): [$\rho$] [$|x_{\mathrm{max}}|$] [$C_2(|x_{\mathrm{max}}|)$]\par
+ \underline{Multithread support}: yes, different values of $\rho$ split up among workers.
+
+ \item\makelink{command:anyeq_2pt_fourier}{}
+ {\tt 2pt\_fourier}: compute the spherically averaged Fourier transform of the two-point correlation function $\hat C_2(|k|)$ at a given $\rho$.\par
+ \underline{Extra parameters}:
+ \begin{itemize}
+ \item\makelink{param:anyeq_kmin}{}
+ {\tt kmin} ({\tt Float64}, default: 0): minimum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:anyeq_kmax}{}
+ {\tt kmax} ({\tt Float64}, default: 10): maximum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:anyeq_nk}{}
+ {\tt nk} ({\tt Int64}, default: 100): number of $|k|$'s to be printed.
+
+ \item\makelink{param:anyeq_2pt_fourier_window_L}{}
+ {\tt window\_L} ({\tt Float64}, default: 1000): what is actually computed is $\hat C_2$ convolved with a Gaussian of variance $1/\sqrt L$ where $L=\sqrt{\mathrm{\tt window\_L}}$, see\-~(\ref{anyeq_gaussian}).
+ \end{itemize}
+ \underline{Output} (one line for each value of $|k|$): [$|k|$] [$\hat C_2(|k|)$].\par
+ \underline{Multithread support}: yes, different values of $k$ are split up among workers.
+
+ \item\makelink{command:anyeq_2pt_fourier_max}{}
+ {\tt 2pt\_fourier\_max}: compute the maximum of the spherically averaged Fourier transformed two-point correlation function $\hat C_2(|k|)$.\par
+ \underline{Extra parameters}: \refname{param:anyeq_2pt_fourier_window_L}{{\tt window\_L}}, \refname{param:anyeq_maxstep}{{\tt maxstep}} plus
+ \begin{itemize}
+ \item\makelink{param:anyeq_dk}{}
+ {\tt dk} ({\tt Float64}, default: $10^{-7}$): step used to numerically approximate derivatives.
+
+ \item\makelink{param:anyeq_k0}{}
+ {\tt k0} ({\tt Float64}, default: $1$): initial guess for the maximum is $\rho^{1/3}\mathrm{\tt k0}$.
+ \end{itemize}
+ \underline{Output}: [$|k_{\mathrm{max}}|$] [$\hat C_2(|k_{\mathrm{max}}|)$]\par
+
+ \item\makelink{command:anyeq_2pt_fourier_max_rho}{}
+ {\tt 2pt\_fourier\_max\_rho}: compute the maximum of the spherically averaged Fourier transformed two-point correlation function $\hat C_2(|k|)$ for a range of $\rho$.\par
+ \underline{Extra parameters}: same as those of \refname{command:anyeq_2pt_fourier_max}{{\tt 2pt\_fourier\_max}} plus those of \refname{command:anyeq_energy_rho}{{\tt energy\_rho}}.\par
+ \underline{Output} (one line for each value of $\rho$): [$\rho$] [$|k_{\mathrm{max}}|$] [$\hat C_2(|k_{\mathrm{max}}|)$]\par
+ \underline{Multithread support}: yes, different values of $\rho$ split up among workers.
+
+ \item\makelink{command:anyeq_momentum_distribution}{}
+ {\tt momentum\_distribution}: compute the momentum distribution $\mathcal M(|k|)$ at a given $\rho$. The momentum distribution is computed for $k=k_{l,j}$ (see\-~(\ref{klj})).\par
+ \underline{Extra parameters}:
+ \begin{itemize}
+ \item\makelink{param:anyeq_momentum_kmin}{}
+ {\tt kmin} ({\tt Float64}, default: 0): minimum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:anyeq_momentum_kmax}{}
+ {\tt kmax} ({\tt Float64}, default: 10): maximum of the range of $|k|$ to be printed.
+
+ \item\makelink{param:anyeq_momentum_window_L}{}
+ {\tt window\_L} ({\tt Float64}, default: 1000): what is actually computed is $\mathfrak M_k$ convolved with a Gaussian of variance $1/\sqrt L$ where $L=\sqrt{\mathrm{\tt window\_L}}/k^2$, see\-~(\ref{anyeq_gaussian_momt}).
+ \end{itemize}
+ \underline{Output} (one line for each value of $|k|$): [$|k|$] [$\mathcal M(|k|)$]
+
+ \item\makelink{command:anyeq_compressibility_rho}{}
+ {\tt compressibility\_rho}: compute the compressibility $\chi$ as a function of $\rho$.
+ The Newton algorithm is initialized with the solution of \refname{eq:easyeq_medeq}{{\tt medeq}}.
+ \underline{Disabled parameters}: same as \refname{command:anyeq_energy_rho}{{\tt energy\_rho}}.\par
+ \underline{Extra parameters}: same as \refname{command:anyeq_energy_rho}{{\tt energy\_rho}}.\par
+ \underline{Output} (one line for each value of $\rho$): [$\rho$] [$\chi$].
+
\item \makelink{command:anyeq_save_Abar}{}
{\tt save\_Abar}: compute the matrix $\bar A$. This matrix is used to compute observables for \refname{eq:anyeq_compleq}{{\tt compleq}}. This command is useful to output the value of $\bar A$ to a file once and for all, and use this file to run commands without recomputing $\bar A$.\par
- \underline{Disabled parameters}: \refname{param:anyeq_rho}{{\tt rho}}, \refname{param:anyeq_tolerance}{{\tt tolerance}}, \refname{param:anyeq_maxiter}{{\tt maxiter}}, \refname{param:anyeq_minlrho_init}{{\tt minlrho\_init}}, \refname{param:anyeq_nlrho}{{\tt nlrho}}.\par
+ \underline{Disabled parameters}: \refname{param:anyeq_rho}{{\tt rho}}, \refname{param:anyeq_tolerance}{{\tt tolerance}}, \refname{param:anyeq_maxiter}{{\tt maxiter}}, \refname{param:anyeq_minlrho_init}{{\tt minlrho\_init}}, \refname{param:anyeq_nlrho_init}{{\tt nlrho\_init}}.\par
\underline{Output}: [$\bar A$] (the output is not designed to be human-readable; it is obtained through nested {\tt for} loops; for details, see the code).\par
\underline{Multithread support}: yes, the first indices are split up among workers, which produces $NJ$ jobs.
\end{itemize}
\subsubsection{Description}
-\point{\bf Fourier space formulation.}
+\subsubsubsection{Fourier space formulation}
The computation is carried out in Fourier space.
We take the convention that the Fourier transform of a function $f(|x|)$ is
\begin{equation}
@@ -770,11 +1314,15 @@ with
\end{equation}
Therefore,
\begin{equation}
+ \Omega(u)=0
+\end{equation}
+with
+\begin{equation}
+ \Omega(u):=
\rho^2\hat u(|k|)^2\sigma_{L,1}(|k|)
-\left(\frac{k^2}\rho+2\sigma_K(|k|)+2f_1(|k|)\right)\rho\hat u(|k|)
+\left(\hat S(|k|)+\frac12f_2(|k|)+G(|k|)\right)
- =
- 0
+ \label{Omega}
\end{equation}
with
\begin{equation}
@@ -831,7 +1379,7 @@ with
\end{equation}
\bigskip
-\point{\bf Evaluating integrals.}
+\subsubsubsection{Evaluating integrals}
To evaluate integrals numerically, we will split integration intervals over splines and use Gauss-Legendre quadratures.
More specifically, to compute integrals of the form
\begin{equation}
@@ -861,7 +1409,7 @@ In these terms,
\int \frac{dk}{(2\pi)^3}\ f(U(k),k)
=
\sum_{l=0}^{J-1}
- \int_{\tau_l}^{\tau_{l+1}} d\tau\ \frac{(1-\tau)^2}{(1+\tau^4}g(U({\textstyle\frac{1-\tau}{1+\tau},\frac{1-\tau}{1+\tau}})
+ \int_{\tau_l}^{\tau_{l+1}} d\tau\ \frac{(1-\tau)^2}{(1+\tau)^4}g(U({\textstyle\frac{1-\tau}{1+\tau},\frac{1-\tau}{1+\tau}})
.
\end{equation}
We then change variables to $r$:
@@ -879,6 +1427,7 @@ and find
\sum_{l=0}^{J-1}
\frac{\tau_{l+1}-\tau_l}{16\pi}\int_{-1}^1 dr\ \cos({\textstyle\frac{\pi r}2})(1+\vartheta_l(r))^2\vartheta_l^2(r)f(U(\vartheta_l(r)),\vartheta_l(r))
.
+ \label{anyeq_preintegration}
\end{equation}
We then approximate the integral using a Gauss-Legendre quadrature of order $N$ (see appendix\-~\ref{appGL}):
\begin{equation}
@@ -901,14 +1450,14 @@ The choice of the change of variables\-~(\ref{chebyshevvars}) is made so that $U
In this way, we can compute arbitrary integrals of functions of $U$ by just computing the values of $\mathbb U_{l,j}$.
\bigskip
-\point{\bf Chebyshev polynomial expansion.}
+\subsubsubsection{Chebyshev polynomial expansion}
In the case of \refname{sec:easyeq}{{\tt easyeq}}, we saw that using Gauss quadratures reduced the computation to evaluating $U$ at a fixed set of discrete momenta.
This is not the case here, due to the presence of more complicated convolutions of $U$.
Instead, we will approximate $U$ using polynomial approximations.
We will now discuss this approximation for an arbitrary function $a(|k|)$, as we will need it for other functions than simply $U$.
\bigskip
-\subpoint
+\point
As in the previous paragraph, we compactify $[0,\infty)$ to $(-1,1]$ via the change of variables $r\mapsto\frac{1-r}{1+r}$, and split the interval into splines.
Inside each spline, we use a Chebyshev polynomial expansion.
However, we need to be careful in the first spline, which encapsulates the behavior at $|k|\to\infty$: $U$ decays to 0 as $|k|\to\infty$, and this behavior cannot be reproduced by a polynomial expansion.
@@ -934,7 +1483,7 @@ in which $\mathds 1_{\tau_l<\tau\leqslant\tau_{l+1}}\in\{0,1\}$ is equal to 1 if
(see appendix\-~\ref{appChebyshev} for a discussion of the Chebyshev polynomial expansion and the error of its truncations).
\bigskip
-\subpoint
+\point
In order to compute an approximation for $a$ using\-~(\ref{a_chebyshev_spline}), we will truncate the sum over $n$ to a finite value $P$ (given by the parameter \refname{param:anyeq_P}{{\tt P}}).
In addition, to compute the integral in\-~(\ref{bfF}), we will use a Gauss-Legendre quadrature of order $N$ (given by the parameter \refname{param:anyeq_N}{{\tt N}}), see appendix\-~\ref{appGL}:
\begin{equation}
@@ -952,7 +1501,7 @@ with
and $(x_j,w_j)$ are the abcissa and weights for Gauss-Legendre quadratures.
\bigskip
-\subpoint
+\point
All in all, we approximate
\begin{equation}
a({\textstyle\frac{1-\tau}{1+\tau}})
@@ -964,14 +1513,15 @@ Furthermore, using the Chebyshev polynomial expansion and Gauss-Legendre quadrat
With this in mind, we will represent the function $U$ as a vector of dimension $NJ$ whose components are $\mathbb U_{l,j}$.
\bigskip
-\point{\bf Convolutions.}
+\subsubsubsection{Convolutions}
Using the Chebyshev polynomial approximation, we can compute convolutions as follows.
\medskip
-\subpoint
+\point
First, we rewrite the convolution as a two-dimensional integral, using bipolar coordinates (see lemma\-~\ref{lemma:bipolar}):
\begin{equation}
(a\hat\ast b)(|k|)=\frac1{4\pi^2|k|}\int_0^\infty dt\ ta(t)\int_{||k|-t|}^{|k|+t}ds\ sb(s)
+ \label{conv_approx1}
\end{equation}
We change variables to compactify the integrals $\tau=\frac{1-t}{1+t}$, $\sigma=\frac{1-s}{1+s}$:
\begin{equation}
@@ -990,30 +1540,31 @@ Therefore, using the approximation\-~(\ref{approxchebyshev}), if $\mathfrak a_{l
\begin{equation}
(a\hat\ast b)(|k_{l,j}|)\approx
(\mathfrak a\odot \mathfrak b)_{l,j}:=
- \frac1{4\pi^2|k_{l,j}|}
\sum_{n,m=0}^P
- \sum_{l,l'=0}^{J-1}
- \mathfrak F_{l,n}^{(\nu_a)}(\mathfrak a)\mathfrak F_{l',m}^{(\nu_b)}(\mathfrak b)
- A_{l,n;l',m}^{(\nu_a,\nu_b)}(|k_{l,j}|)
+ \sum_{l',l''=0}^{J-1}
+ \mathfrak F_{l',n}^{(\nu_a)}(\mathfrak a)\mathfrak F_{l'',m}^{(\nu_b)}(\mathfrak b)
+ A_{l',n;l'',m}^{(\nu_a,\nu_b)}(|k_{l,j}|)
\label{odot}
\end{equation}
with
\begin{equation}
\begin{largearray}
- A_{l,n;l',m}^{(\nu_a,\nu_b)}(|k|):=
- \int_{\tau_l}^{\tau_{l+1}} d\tau\ \frac{2(1-\tau)}{(1+\tau)^{3-\nu_a}}T_n({\textstyle\frac{2\tau-(\tau_l+\tau_{l+1})}{\tau_{l+1}-\tau_l}})
+ A_{l',n;l'',m}^{(\nu_a,\nu_b)}(|k|):=
+ \frac1{4\pi^2|k_{l,j}|}
+ \int_{\tau_{l'}}^{\tau_{l'+1}} d\tau\ \frac{2(1-\tau)}{(1+\tau)^{3-\nu_a}}T_n({\textstyle\frac{2\tau-(\tau_{l'}+\tau_{l'+1})}{\tau_{l'+1}-\tau_{l'}}})
\cdot\\[0.5cm]\hfill\cdot
- \mathds 1_{\alpha_-(|\tilde k|,\tau)<\tau_{\zeta'+1}}
- \mathds 1_{\alpha_+(|\tilde k|,\tau)>\tau_{\zeta'}}
- \int_{\max(\tau_{l'},\alpha_-(|k|,\tau))}^{\min(\tau_{l'+1},\alpha_+(|k|,\tau))}d\sigma\ \frac{2(1-\sigma)}{(1+\sigma)^{3-\nu_b}}T_m({\textstyle\frac{2\sigma-(\tau_{l'}+\tau_{l'+1})}{\tau_{l'+1}-\tau_{l'}}})
+ \mathds 1_{\alpha_-(|k|,\tau)<\tau_{l''+1}}
+ \mathds 1_{\alpha_+(|k|,\tau)>\tau_{l''}}
+ \int_{\max(\tau_{l''},\alpha_-(|k|,\tau))}^{\min(\tau_{l''+1},\alpha_+(|k|,\tau))}d\sigma\ \frac{2(1-\sigma)}{(1+\sigma)^{3-\nu_b}}T_m({\textstyle\frac{2\sigma-(\tau_{l''}+\tau_{l''+1})}{\tau_{l''+1}-\tau_{l''}}})
\end{largearray}
+ \label{conv_approx2}
\end{equation}
(we need the indicator functions to ensure that the bounds of the integral are correct).
Note that $A$ is independent of $a$ and $b$, and can be computed once and for all at the beginning of execution for all values of $k_{l,j}$ (\ref{klj}).
We then compute the integrals using Gauss-Legendre quadratures (as is proved in the next paragraph, the integrand is non singular provided $\nu_a,\nu_b\geqslant 2$).
\bigskip
-\subpoint
+\point
Note that these integrals are not singular as long as $\nu_a,\nu_b\geqslant 2$: indeed (since the only possible problems occur at $-1$, it suffices to consider the case with only one spline), $\alpha_-,\alpha_+>-1$ for $\tau>-1$, and
\begin{equation}
\alpha_\pm(k,\tau)=-1+(1+\tau)\pm\frac k2(1+\tau)^2+O(1+\tau)^3
@@ -1047,7 +1598,7 @@ where $c_{2}:=1$ and $c_{\nu_b}:=\nu_b-2$ if $\nu_b>2$.
The integrand is, therefore, not singular as long as $\nu_a,\nu_b\geqslant 2$.
\bigskip
-\subpoint
+\point
Evaluating convolutions at $k=0$ is not immediate, as the formula for $A(0)$ involves a bit of a computation.
To compute $A(0)$, we expand
\begin{equation}
@@ -1077,11 +1628,11 @@ We can then evaluate convolutions at $k=0$:
\bigskip
-\subpoint
+\point
Let us now compute some choices of $\mathfrak a,\mathfrak b$ more explicitly.
\medskip
-\subsubpoint
+\subpoint
Let us start with $\mathds 1_{l,n}\hat\ast a$ where $\mathds 1_{l,n}$ is the vector which has 0's everywhere except at position $(l,n)$.
We have
\begin{equation}
@@ -1095,7 +1646,7 @@ so
\end{equation}
\bigskip
-\subsubpoint
+\subpoint
We now turn to $a\hat\ast\hat v$.
Let
\begin{equation}
@@ -1132,7 +1683,7 @@ The integral in\-~(\ref{Upsilon}) is computed using Gauss-Legendre quadratures,
To maintain a high precision, we set the order of the integration to \refname{param:anyeq_J}{{\tt J}}$\times$\refname{param:anyeq_N}{{\tt N}}.
\bigskip
-\subsubpoint
+\subpoint
Finally,
\begin{equation}
(\mathds 1_{l',n}\odot\mathfrak v)_{l,i}=
@@ -1146,7 +1697,7 @@ and
\end{equation}
\bigskip
-\point{\bf Evaluating $\hat l_3$.}
+\subsubsubsection{Evaluating $\hat l_3$}
The only term in\-~(\ref{anyeq}) that does not involve just convolutions (whose computation was described above) is $\hat l_3$ (\ref{l3}).
To evaluate it, we first change variables, using a generalization of bipolar coordinates (see lemma\-~\ref{lemma:bipolar2}):
\begin{equation}
@@ -1230,12 +1781,12 @@ Since the tensor $\bar A$ is quite large (it contains $(NJ)^5$ entries), and its
Instead, one can use the \refname{command:anyeq_save_Abar}{{\tt save\_Abar}} method to compute $\bar A$ and save it to a file, which can then be recalled via the {\tt -s} option on the command line.
\bigskip
-\point{\bf Main algorithm to compute $U$.}
+\subsubsubsection{Main algorithm to compute $U$}
We are now ready to detail how $U\equiv\rho\hat u$ is computed.
All of the observables we are interested in are approximated from the values $\mathbb U_{l,j}:=U(k_{l,j})$ (\ref{klj}).
\bigskip
-\subpoint
+\point
The equation for $(\mathbb U_{l,j})_{l\in\{0,\cdots,J-1\},j\in\{1,\cdots,N\}}$ is obtained by approximating\-~(\ref{anyeq_hatu}) according to the prescriptions detailed above:
\begin{equation}
\mathbb U_{l,j}:=
@@ -1283,7 +1834,7 @@ The equation for $(\mathbb U_{l,j})_{l\in\{0,\cdots,J-1\},j\in\{1,\cdots,N\}}$ i
(see\-~(\ref{odot}), (\ref{otimes}) and\-~(\ref{avg}) for the definitions of $\odot$, $\otimes$ and $\left<\cdot\right>$).
\bigskip
-\subpoint
+\point
We rewrite\-~(\ref{bbU}) as a root finding problem:
\begin{equation}
\Xi_{l,j}(\mathbb U):=
@@ -1303,14 +1854,14 @@ where $D\Xi$ is the Jacobian of $\Xi$:
\end{equation}
\bigskip
-\subpoint
+\point
We initialize the algorithm with the solution of the \refname{eq:easyeq_medeq}{Medium equation}, which is computed using the \refname{sec:easyeq}{{\tt easyeq}} method.
However, \refname{sec:easyeq}{{\tt easyeq}} only computes $\hat u$ at the momenta given by the Gauss-Legendre quadratures\-~(\ref{easyeq_ki}).
To obtain a value for $\hat u$ at $k_{l,j}$, we use a linear interpolation (code is provided for a polynomial interpolation, which has not performed as well).
-The parameters \refname{param:anyeq_tolerance}{{\tt tolerance}}, \refname{param:anyeq_maxiter}{{\tt maxiter}}, \refname{param:anyeq_minlrho_init}{{\tt minlrho\_init}}, \refname{param:anyeq_nlrho_init}{{\tt nlrho\_init}} are passed on to \refname{sec:easyeq}{easyeq} as is, and the order of the Gauss-Legendre quadratures is set to \refname{param:anyeq_J}{{\tt J}}$\times$\refname{param:anyeq_N}{{\tt N}}.
+The parameters \refname{param:anyeq_tolerance}{{\tt tolerance}}, \refname{param:anyeq_maxiter}{{\tt maxiter}} are passed on to \refname{sec:easyeq}{{\tt easyeq}} as is, and the order of the Gauss-Legendre quadratures is set to \refname{param:anyeq_J}{{\tt J}}$\times$\refname{param:anyeq_N}{{\tt N}}.
\bigskip
-\subpoint
+\point
We are left with computing the Jacobian of $\Xi$:
\begin{equation}
\begin{largearray}
@@ -1444,7 +1995,7 @@ with
\end{equation}
\bigskip
-\subpoint
+\point
We iterate the Newton algorithm until the Newton relative error $\epsilon$ becomes smaller than the \refname{param:easyeq_tolerance}{{\tt tolerance}} parameter.
The Newton error is defined as
\begin{equation}
@@ -1471,8 +2022,8 @@ where $k_{l,j}$ was defined in\-~(\ref{klj}), and the solution $u$ in real space
\end{equation}
\bigskip
-\point{\bf Condensate fraction.}
-To compute the condensate fraction, we solve the modified {\tt anyeq} (see\-~\cite{CJL20b}):
+\subsubsubsection{Condensate fraction}
+To compute the condensate fraction, we solve the modified {\tt anyeq} (see\-~\cite{CJL21}):
\begin{equation}
(-\Delta+2\mu)u_\mu
=
@@ -1519,41 +2070,53 @@ We then approximate
(see\-~(\ref{avg})).
\bigskip
-\point{\bf Correlation function.}
+\subsubsubsection{Correlation function (spherical average)}
The two-point correlation function is
\begin{equation}
- C_2(x):=
+ c_2(x):=
2\rho\frac{\delta e}{\delta v(x)}
+\end{equation}
+and its spherical average is
+\begin{equation}
+ C_2(|x|):=\frac1{4\pi|x|^2}\int dy\ \delta(|x|-|y|)c_2(y)
.
\end{equation}
In Fourier space,
\begin{equation}
- C_2(x)=
- 2\rho\int dk\ e^{ikx}\frac{\delta e}{\delta\hat v(k)}
+ c_2(x)=
+ 2\rho
+ \int dk\ e^{ikx}\frac{\delta e}{\delta\hat v(k)}
+\end{equation}
+so
+\begin{equation}
+ C_2(|x|)=
+ 2\rho\int dk\ \left(\frac1{4\pi|x|^2}\int dy\ \delta(|x|-|y|)e^{iky}\right)\frac{\delta e}{\delta\hat v(k)}
=2\rho\int dk\ \frac{\sin(|k||x|)}{|k||x|}\frac{\delta e}{\delta\hat v(k)}
.
\label{C2fourier}
\end{equation}
\bigskip
-\subpoint
+\point
We can compute this quantity by considering a modified {\tt anyeq} in Fourier space, by formally replacing $\hat v$ with
\begin{equation}
\hat v+\lambda g(|k|)
,\quad
g(|k|):=\frac{\sin(|k||x|)}{|k||x|}
.
+ \label{2pt_addv}
\end{equation}
Indeed, if $e_\lambda$ denotes the energy of this modified equation,
\begin{equation}
\partial_\lambda e_\lambda|_{\lambda=0}
- =\int dk\ \frac{\delta e}{\hat v(k)}\partial_\lambda({\textstyle \hat v(k)+\lambda g(|k|)})
- =\int dk\ g(|k|)\frac{\delta e}{\hat v(k)}
+ =\int dk\ \frac{\delta e}{\delta\hat v(k)}\partial_\lambda({\textstyle \hat v(k)+\lambda g(|k|)})
+ =\int dk\ g(|k|)\frac{\delta e}{\delta\hat v(k)}
+ .
\end{equation}
-so, denoting the solution of the modified equation by $u_\lambda$,
+So, denoting the solution of the modified equation by $u_\lambda$,
\begin{equation}
C_2(x)=2\rho\partial_\lambda e_\lambda|_{\lambda=0}
- =-\rho^2\int dx\ (g(x)u_0(x)+v(x)\partial_\lambda u_\lambda(x)|_{\lambda=0})
+ =\rho^2g(0)-\rho^2\int\frac{dk}{(2\pi)^3}\ (g(k)\hat u(k)+\hat v(k)\partial_\lambda\hat u_\lambda(k)|_{\lambda=0})
.
\end{equation}
We compute $\partial_\lambda u_\lambda|_{\lambda=0}$ in the same way as the uncondensed fraction: we define $\Xi(\mathbb U,\lambda)$ by formally adding $\lambda g(|k|)$ to $\hat v$, solve $\Xi(\mathbb U,\lambda)=0$, and differentiate:
@@ -1563,7 +2126,7 @@ We compute $\partial_\lambda u_\lambda|_{\lambda=0}$ in the same way as the unco
\end{equation}
\bigskip
-\subpoint
+\point
We compute $\partial_\lambda\Xi|_{\lambda=0}$:
\begin{equation}
\begin{largearray}
@@ -1581,6 +2144,7 @@ We compute $\partial_\lambda\Xi|_{\lambda=0}$:
-\partial_\lambda\mathbb Y_{l,j}
\right)\ \partial\Phi\left({\textstyle\frac{1+\mathbb Y_{l,j}}{(\mathbb X_{l,j}+1)^2}}\right)
\end{largearray}
+ \label{2pt_dXi}
\end{equation}
with
\begin{equation}
@@ -1610,7 +2174,7 @@ with
\begin{equation}
\partial_\lambda\mathbb I_{l,j}=
\frac1{\rho}\gamma_{L,2}\left(
- \beta_{L,2}(\mathbb U\odot(\mathbb U\partial_\lambda\mathbb S)_{l,j}
+ \beta_{L,2}(\mathbb U\odot(\mathbb U\partial_\lambda\mathbb S))_{l,j}
+
(1-\beta_{L,2})\partial_\lambda\mathbb E(\mathbb U\odot\mathbb U)_{l,j}
\right)
@@ -1623,7 +2187,7 @@ with
\begin{equation}
\begin{largearray}
\partial_\lambda\mathbb G_{l,j}=
- \frac2{\rho}\gamma_K\alpha_K\beta_K\left(\partial_\lambda\mathbb S\mathbb U\right)_{l,j}
+ \frac2{\rho}\gamma_K\alpha_K\beta_K\left(\mathbb U\odot\left(\partial_\lambda\mathbb S\mathbb U\right)\right)_{l,j}
+\frac2{\rho}\gamma_K\alpha_K(1-\beta_K)\partial_\lambda\mathbb E(\mathbb U\odot\mathbb U)_{l,j}
-
\frac1{\rho}\alpha_{L,1}\beta_{L,1}\left(\mathbb U\odot\partial_\lambda\mathbb S\mathbb U^2\right)_{l,j}
@@ -1641,7 +2205,7 @@ To evaluate $(\mathbb U\odot\mathfrak g)$ and $\left<\mathbb U\mathfrak g\right>
To do so, we replace $\hat v$ with $g$ in the computation of $\Upsilon$.
\bigskip
-\subpoint
+\point
In order to invert the Fourier transform in\-~(\ref{C2fourier}) numerically, we will use a Hann window (see appendix\-~\ref{appendix:hann})
\begin{equation}
H_L(k):=\mathds 1_{|k|<\frac L2}\cos^2({\textstyle\frac{\pi|k|}{L}})
@@ -1652,7 +2216,203 @@ The parameter $L$ is set using \refname{param:anyeq_window_L}{{\tt window\_L}}.
The computation is changed only in that $g$ is changed to $H_L(k)\frac{\sin(|k||x|)}{|k||x|}$.
\bigskip
-\point {\bf Momentum distribution.}
+\point
+To compute the maximum of $C_2$, we use a modified Newton algorithm.
+The initial guess for the maximum is $|x_0|=\rho^{-\frac13}$\refname{param:anyeq_x0}{{\tt x0}}.
+The modified Newton algorithm is an iteration:
+\begin{equation}
+ x_{n+1}=x_n+\frac{\partial C_2(|x_n|)}{|\partial^2C_2(|x_n|)|}
+ \label{anyeq_newton_2pt}
+\end{equation}
+in which the derivatives are approximated using finite differences:
+\begin{equation}
+ \partial C_2(x)\approx \frac{C_2(|x|+dx)-C_2(|x|)}{dx}
+ ,\quad
+ \partial^2 C_2(x)\approx \frac{C_2(|x|+dx)+C_2(|x|-dx)-2C_2(|x|)}{dx^2}
+ .
+ \label{anyeq_dx_2pt}
+\end{equation}
+This is a modification of the usual Newton iteration $x_n+\partial C_2/\partial^2C_2$ which is designed to follow the direction of the gradient, and thus to move toward a local maximum.
+In addition, if $|\partial C_2|/|\partial^2 C_2|$ is larger than \refname{param:anyeq_maxstep}{{\tt maxstep}}, then the step is replaced with $\pm$\refname{param:anyeq_maxstep}{{\tt maxstep}}.
+This prevents the algorithm from stepping over a maximum and land on another, further away.
+This is useful if one has a good idea of where the global maximum is, and does not want to get trapped in a smaller local maximum.
+\bigskip
+
+\indent
+The algorithm is run for a maximum of \refname{param:anyeq_maxiter}{{\tt maxiter}} iterations, or until $|x_{n+1}-x_n|$ is smaller than \refname{param:anyeq_tolerance}{{\tt tolerance}}.
+If the maximal number of iterations is reached, or if the solution found is not a local maximum, then the algorithm fails, and returns $+\infty$.
+The point thus computed is therefore a local maximum, but it is not guaranteed to be the global maximum.
+
+\subsubsubsection{Fourier transform of two-point correlation (spherical average)}
+The Fourier transform of the two-point correlation function is
+\begin{equation}
+ \hat c_2(q):=
+ 2\rho\frac{\delta e}{\delta v(q)}
+\end{equation}
+and its spherical average is
+\begin{equation}
+ \hat C_2(|q|):=\frac1{4\pi|q|^2}\int dk\ \delta(|q|-|k|)c_2(k)
+ =
+ \frac\rho{2\pi|q|^2}\int dk\ \delta(|q|-|k|)\frac{\delta e}{\delta\hat v(k)}
+ .
+\end{equation}
+\bigskip
+
+\point
+To compute $\frac{\delta e}{\delta\hat v(q)}$, one idea would be to proceed in the same way as for the two-point correlation function, by replacing $\hat v$ with
+\begin{equation}
+ \hat v+\lambda g(|k|)
+ ,\quad
+ g(|k|):=\frac1{4\pi|q|^2}\delta(|q|-|k|)
+\end{equation}
+where $\delta$ is the Dirac-delta function distribution (compare this with\-~(\ref{2pt_addv})).
+However, the $\delta$ function causes all sorts of problems with the Chebyshev polynomial exansion and the quadratures.
+\bigskip
+
+\point
+Instead, we approximate $\hat C_2$ by convolving it with a normalized Gaussian: let
+\begin{equation}
+ \Gamma_L(|k|):=\left(\frac{L}{2\pi}\right)^{\frac32}e^{-\frac L2k^2}
+ \label{anyeq_gaussian}
+\end{equation}
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)
+ :=
+ \int dp\ \hat C_2(|q-p|)\Gamma_L(|p|)
+ =\int dk\ \int dp\ \frac\rho{2\pi|q-p|^2}\delta(|q-p|-|k|)\frac{\delta e}{\delta\hat v(k)}\Gamma_L(|p|)
+\end{equation}
+which by lemma\-~\ref{lemma:bipolar} is
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)
+ =\int dk\
+ \frac\rho{|q|}
+ \frac{\delta e}{\delta\hat v(k)}
+ \int_0^\infty dt\ \int_{||q|-t|}^{|q|+t}ds\ s\frac{\delta(t-|k|)}t\Gamma_L(s)
+\end{equation}
+that is
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)
+ =\int dk\
+ \frac{\delta e}{\delta\hat v(k)}
+ \frac{\rho}{|q||k|}
+ \int_{||q|-|k||}^{|q|+|k|}ds\ s\Gamma_L(s)
+\end{equation}
+which is the directional derivative of $e$ with respect to $\hat v$ in the direction of $2\rho g$ with
+\begin{equation}
+ g(|k|):=\frac1{2|q||k|}\int_{||q|-|k||}^{|q|+|k|}ds\ s\Gamma_L(s)
+ =
+ \frac1{2|k|rL}(\Gamma_L(|k|-r)-\Gamma_L(|k|+r))
+ .
+ \label{anyeq_2pt_fourier_g}
+\end{equation}
+Note that
+\begin{equation}
+ g(0):=\Gamma_L(|q|)
+ .
+\end{equation}
+To compute this derivative, we replace $\hat v$ with
+\begin{equation}
+ \hat v+\lambda g(|k|)
+\end{equation}
+so, denoting the solution of the modified equation by $u_\lambda$, for $q\neq 0$,
+\begin{equation}
+ \hat{\mathfrak C}_2(|q|)=2\rho\partial_\lambda e_\lambda|_{\lambda=0}
+ =\rho^2\left(
+ -\int\frac{dk}{(2\pi)^3}\ g(|k|)\hat u(|k|)
+ -\int\frac{dk}{(2\pi)^3}\ \hat v(|k|)\partial_\lambda\hat u_\lambda(|k|)|_{\lambda=0}
+ \right)
+ .
+\end{equation}
+To compute $\partial_\lambda\hat u_\lambda|_{\lambda=0}$, we differentiate $\Xi(\mathbb U,\lambda)=0$:
+\begin{equation}
+ \partial_\lambda\mathbb U|_{\lambda=0}=-(D\Xi)^{-1}\partial_\lambda\Xi|_{\lambda=0}
+ .
+\end{equation}
+The computation of $\partial_\lambda\Xi|_{\lambda=0}$ is identical to\-~(\ref{2pt_dXi}), but taking
+\begin{equation}
+ \mathfrak g_{l,j}=g(|k_{l,j}|)
+ .
+\end{equation}
+with $g$ defined in\-~(\ref{anyeq_2pt_fourier_g}).
+\bigskip
+
+\point
+To compute the maximum of $\hat C_2$, we proceed as for $C_2$, see\-~(\ref{anyeq_newton_2pt})-(\ref{anyeq_dx_2pt}).
+The only difference is that the algorithm is initialized with $|k_0|=\rho^{\frac13}$\refname{param:anyeq_k0}{{\tt k0}}.
+
+\subsubsubsection{Correlation function of uncondensed particles (spherical average)}
+To compute the correlation function among uncondensed particles, denoted by $\gamma_2(|\xi|)$, we solve the modified {\tt anyeq} (see\-~\cite{Ja23}):
+\begin{equation}
+ -\Delta u_\mu
+ =
+ (1-u_\mu)v-2\rho K+\rho^2 L
+ -\frac{\rho\mu}{2\pi|\xi|^2} u(|\xi|)\delta(|\xi|-|x|)
+\end{equation}
+where $K$ and $L$ are defined as in\-~(\ref{anyeq_K})-(\ref{anyeq_e}) in which $u$ is replaced with $u_\mu$.
+In Fourier space,
+\begin{equation}
+ k^2 \hat u_\mu
+ =
+ \hat S-2\rho\hat K+\rho^2\hat L
+ -2\rho\mu u(|\xi|)\frac{\sin(|k||\xi|)}{|k||\xi|}
+ .
+\end{equation}
+The uncondensed correlation function is then
+\begin{equation}
+ \gamma_2(|\xi|)=\partial_\mu e|_{\mu=0}
+ =-\frac\rho2\int dx\ v(x)\partial_\mu u_\mu(x)|_{\mu=0}
+ .
+\end{equation}
+To compute the energy in the presence of the parameter $\mu$, we proceed in the same way as for $\mu=0$, the only difference being that the term
+\begin{equation}
+ \mu g(|k|):=
+ -\mu 2\rho u(|\xi|)\frac{\sin(|k||\xi|)}{|k||\xi|}
+\end{equation}
+should formally be added to the right side of\-~(\ref{Omega}).
+In other words, we consider $\mathbb U_{j,l}=u_\mu(|k_{j,l}|)$ and define $\Xi(\mathbb U,\mu)$ in the same way as in\-~(\ref{root_anyeq}), except that $\mathbb Y_{l,j}$ should be replaced by
+\begin{equation}
+ \mathbb Y_{l,j}=
+ \frac1{\mathbb L_{l,j}}\left(\mathbb S_{l,j}-\mathbb L_{l,j}+\frac12\mathbb J_{l,j}+\mathbb G_{l,j}+\mu g(k_{l,j})\right)
+ .
+\end{equation}
+We then solve
+\begin{equation}
+ \Xi(\mathbb U_\mu,\mu)=0
+\end{equation}
+By differentiating this identity with respect to $\mu$, we find $\partial_\mu u_\mu$:
+\begin{equation}
+ \partial_\mu \mathbb U|_{\mu=0}=-(D\Xi)^{-1}\partial_\mu\Xi|_{\mu=0}
+\end{equation}
+and
+\begin{equation}
+ \partial_\mu\Xi|_{\mu=0}=
+ -\frac{\partial_\mu\mathbb Y_{l,j}}{2(\mathbb X_{l,j}+1)}
+ \Phi\left({\textstyle\frac{1+\mathbb Y_{l,j}}{(\mathbb X_{l,j}+1)^2}}\right)
+ -\frac{(1+\mathbb Y_{l,j})\partial_\mu\mathbb Y_{l,j}}{2(\mathbb X_{l,j}+1)^3}
+ \partial\Phi\left({\textstyle\frac{1+\mathbb Y_{l,j}}{(\mathbb X_{l,j}+1)^2}}\right)
+ ,\quad
+ \partial_\mu\mathbb Y_{l,j}=\frac{g(k_{l,j})}{\mathbb L_{l,j}}
+ .
+\end{equation}
+We then approximate
+\begin{equation}
+ \gamma_2(\xi)\approx
+ -\frac12\left<\mathfrak v\partial_\mu\mathbb U\right>
+\end{equation}
+(see\-~(\ref{avg})).
+\bigskip
+
+\indent
+In order to avoid numerical oscillations due to the $\sin$ function, we will use a Hann window (see appendix\-~\ref{appendix:hann})
+\begin{equation}
+ H_L(k):=\mathds 1_{|k|<\frac L2}\cos^2({\textstyle\frac{\pi|k|}{L}})
+ .
+ \label{hann}
+\end{equation}
+The parameter $L$ is set using \refname{param:anyeq_window_L}{{\tt window\_L}}.
+The computation is changed only in that $g$ is changed to $H_L(k)g(k)$.
+
+\subsubsubsection{Momentum distribution}
To compute the momentum distribution (see\-~\cite{CHe21}), we add a parameter $\lambda$ to {\tt anyeq}:
\begin{equation}
-\Delta u_\lambda(|x|)
@@ -1664,7 +2424,7 @@ To compute the momentum distribution (see\-~\cite{CHe21}), we add a parameter $\
The momentum distribution is then
\begin{equation}
\mathcal M(q)=\partial_\lambda e|_{\lambda=0}
- =-\frac\rho2\int dx\ v(x)\partial_\lambda u_\lambda(x)|_{\lambda=0}
+ =-\frac\rho2\int\frac{dk}{(2\pi)^3}\ \hat v(k)\partial_\lambda\hat u_\lambda(k)|_{\lambda=0}
.
\end{equation}
Note that the Fourier transform of $2\lambda\hat u_0(q)\cos(q\cdot x)$ is
@@ -1673,52 +2433,118 @@ Note that the Fourier transform of $2\lambda\hat u_0(q)\cos(q\cdot x)$ is
.
\label{fouriermomentum}
\end{equation}
-We compute $\partial_\lambda u_\lambda|_{\lambda=0}$ in the same way as the uncondensed fraction.
+The presence of delta functions does not play well with the Chebyshev polynomial expansion and the quadratures.
+\bigskip
+
+\point
+We will consider two different ways of getting around this.
\bigskip
\subpoint
-In order to do so we will discretize momentum space, see\-~(\ref{klj}), and so it is necessary to construct a discrete analog of the delta-functions in\-~(\ref{fouriermomentum}).
-The starting point we take is
+One idea is to compute a regularization of $\mathcal M(q)$ by convolving it with a peaked spherically symmetric function.
+Let $\Gamma_L$ denote the Gaussian with variance $1/\sqrt L$:
\begin{equation}
- \int dk f(k)\delta(k-q)
- =f(q)
+ \Gamma_L(|k|):=\left(\frac{L}{2\pi}\right)^{\frac32}e^{-\frac L2k^2}
+ .
+ \label{anyeq_gaussian_momt}
+\end{equation}
+In fact, we will scale $L$ with $k$, and set $L$ to
+\begin{equation}
+ L=\sqrt{\mathrm{\refname{param:anyeq_momentum_window_L}{{\tt window\_L}}}}/k^2
+ .
+\end{equation}
+To compute
+\begin{equation}
+ \mathfrak M(q):=\mathcal M\ast\Gamma_L(q)
+\end{equation}
+we solve the equation
+\begin{equation}
+ -\Delta u_\lambda(|x|)
+ =
+ (1-u_\lambda(|x|))v(|x|)-2\rho K(|x|)+\rho^2 L(|x|)
+ -2\lambda\int dk\ \hat u_0(k)\cos(k\cdot x)\Gamma_L(q-k)
+ .
+\end{equation}
+Note that the Fourier transform of
+\begin{equation}
+ -2\lambda\int dk\ \hat u_0(k)\cos(k\cdot x)\Gamma_L(q-k)
+\end{equation}
+is
+\begin{equation}
+ -(2\pi)^3\lambda\hat u_0(q)(\Gamma_L(k+q)+\Gamma_L(k-q))
+ .
+\end{equation}
+Since the ground state is unique, $\mathcal M$ is spherically symmetric.
+The term $\Gamma_L(k\pm q)$ is not, so we take its spherical average (which will not change the final result): by lemma\-~\ref{lemma:bipolar},
+\begin{equation}
+ -\frac1{4\pi r^2}\int dq\ \delta(|q|-r)(2\pi)^3\lambda\hat u_0(q)(\Gamma_L(k+q)+\Gamma_L(k-q))
+ =
+ -\frac{(2\pi)^3}{|k|r}\lambda\hat u_0(r)\int_{||k|-r|}^{|k|+r} ds\ s\Gamma_L(s)
+ .
+\end{equation}
+In this setup, the approximation of the delta function is thus
+\begin{equation}
+ \tilde\delta(|k|,r):=
+ \frac1{2|k|r}\int_{||k|-r|}^{|k|+r} ds\ s\Gamma_L(s)
+ =
+ \frac{1}{2|k|rL}(\Gamma_L(|k|-r)-\Gamma_L(|k|+r))
+ .
+\end{equation}
+To choose this method, set \refname{param:anyeq_window_L}{{\tt window\_L}} to a finite value.
+\bigskip
+
+\subpoint
+Another approach is to contruct a discrete analog of the delta-functions in\-~(\ref{fouriermomentum}).
+The starting point we take is, for $q\neq0$,
+\begin{equation}
+ \int dk\ f(|k|)\delta(k-q)
+ \equiv\frac1{4\pi|q|^2}\int dk\ f(|k|)\delta(|k|-|q|)
+ =f(|q|)
\end{equation}
so, when approximating the integral according to\-~(\ref{anyeq_integration}), we find
\begin{equation}
- \frac{\pi^2}2\sum_{l=0}^{J-1}
+ \frac{\pi}{8|q|^2}\sum_{l=0}^{J-1}
(\tau_{l+1}-\tau_l)
\sum_{j=1}^Nw_j
- \cos({\textstyle\frac{\pi x_j}2})(1+\vartheta_l(x_j))^2\vartheta_l^2(x_j)f(\vartheta_l(x_j))\tilde\delta(\vartheta_l(x_j)-k_{l',i})
- \approx
- f(k_{l',i})
+ \cos({\textstyle\frac{\pi x_j}2})(1+\vartheta_l(x_j))^2\vartheta_l^2(x_j)f(\vartheta_l(x_j))\tilde\delta(\vartheta_l(x_j),|q|)
+ =
+ f(|q|)
\end{equation}
where $\tilde\delta$ is the approximation of the delta-function.
Since
\begin{equation}
\vartheta_l(x_j)\equiv k_{l,j}
\end{equation}
-(see\-~(\ref{chebyshevvars})), we find that the definition of $\tilde\delta$ must be
+(see\-~(\ref{chebyshevvars})), we define the approximation of the delta function as
\begin{equation}
- \tilde\delta_{l,j;l',i}
+ \tilde\delta(k_{l,j},k_{l',i})
:=
\delta_{l,l'}\delta_{j,i}
- \frac2{\pi^2}
+ \frac{8}{\pi}
\left(
(\tau_{l+1}-\tau_l)
w_j
\cos({\textstyle\frac{\pi x_j}2})
- (1+k_{l,j})^2k_{l,j}^2
+ (1+k_{l,j})^2
\right)^{-1}
.
\end{equation}
-Note that, due to the invariance under rotation, the approximation for $\delta(q+k)$ is equal to that for $\delta(q-k)$.
+To choose this method, set \refname{param:anyeq_window_L}{{\tt window\_L}} to {\tt Inf}.
+{\color{red}This method seems to yield some fairly poor results!}
\bigskip
-\subpoint
-To compute the momentum distribution at $q=k_{l',i}$, we define $\Xi(\mathbb U,\lambda)$ by formally adding $-2(2\pi)^3\lambda \hat u_0(k_{l',i})\tilde\delta_{l,j;l',i}$ to $\mathbb G_{l,j}$, which corresponds to replacing $\mathbb Y$ with
+\point
+To compute the momentum distribution at $q$, we define $\Xi(\mathbb U,\lambda)$ by formally adding
+\begin{equation}
+ -2(2\pi)^3\lambda \hat u_0(|q|)\tilde\delta(k_{l,j},|q|)
+\end{equation}
+to $\mathbb G_{l,j}$, which corresponds to replacing $\mathbb Y$ with
\begin{equation}
\mathbb Y_{l,j}=
- \frac1{\mathbb L_{l,j}}\left(\mathbb S_{l,j}-\mathbb L_{l,j}+\frac12\mathbb J_{l,j}+\mathbb G_{l,j}-2(2\pi)^3\lambda\frac{\mathbb U_{l',i}}\rho\tilde\delta_{l,j;l',i}\right)
+ \frac1{\mathbb L_{l,j}}\left(\mathbb S_{l,j}-\mathbb L_{l,j}+\frac12\mathbb J_{l,j}+\mathbb G_{l,j}
+ -2(2\pi)^3\lambda \hat u(|q|)\tilde\delta(k_{l,j},|q|)
+ \right)
+ .
\end{equation}
Then we solve $\Xi(\mathbb U,\lambda)=0$, and differentiate:
\begin{equation}
@@ -1739,7 +2565,33 @@ Finally,
with
\begin{equation}
\partial_\lambda\mathbb Y_{l,j}|_{\lambda=0}=
- \frac{2(2\pi)^3\mathbb U_{l',i}\tilde\delta_{l,j;l',i}}{\rho\mathbb L_{l,j}}
+ -\frac{2(2\pi)^3}{\mathbb L_{l,j}} \hat u(|q|)\tilde\delta(k_{l,j},|q|)
+ .
+\end{equation}
+\bigskip
+
+\subsubsubsection{Compressibility}
+The compressibility is defined as
+\begin{equation}
+ \chi:=\frac1{\rho^2\partial_\rho^2(\rho e)}
+ =\frac1{\partial_{\log\rho}^2(\rho e)-\partial_{\log\rho}(\rho e)}
+ .
+\end{equation}
+We approximate these derivatives by finite differences:
+\begin{equation}
+ \partial_{\log\rho}^2 f(\rho)
+ \approx
+ \frac{f(\rho_{j+1})+f(\rho_{j-1})-2f(\rho_j)}{(\log\rho_{j+2}-\log\rho_{j+1})(\log\rho_{j+1}-\log\rho_j)}
+\end{equation}
+and
+\begin{equation}
+ \partial_{\log\rho} f(\rho)
+ \approx
+ \frac12\left(
+ \frac{f(\rho_{j+1})-f(\rho_j)}{\log\rho_{j+1}-\log\rho_{j}}
+ +
+ \frac{f(\rho_{j})-f(\rho_{j-1})}{\log\rho_{j}-\log\rho_{j-1}}
+ \right)
.
\end{equation}
@@ -1755,7 +2607,7 @@ The method is used to compute observables for the simple equation
.
\label{simpleq}
\end{equation}
-One can show\-~\cite[Theorem\-~1.6]{CJL20b} that the condensate fraction is
+One can show\-~\cite[Theorem\-~1.6]{CJL21} that the condensate fraction is
\begin{equation}
\eta=\frac{\rho\int v(x)\mathfrak Ku(x)\ dx}{1-\rho\int v(x)\mathfrak K(2u(x)-\rho u\ast u(x))\ dx}
\label{simpleq-Kv_eta}
@@ -1824,8 +2676,18 @@ The available {\tt commands} are the following.
\item\makelink{param:simpleq-Kv_nlrho}{}
{\tt nlrho} ({\tt Int64}, default: $100$): number of values for $\rho$ (spaced logarithmically).
+ \item\makelink{param:simpleq-Kv_minrho}{}
+ {\tt minrho} ({\tt Float64}, default: $10^{-6}$): minimal value for $\rho$.
+
+ \item\makelink{param:simpleq-Kv_maxrho}{}
+ {\tt maxrho} ({\tt Float64}, default: $10^{2}$): maximal value for $\rho$.
+
+ \item\makelink{param:simpleq-Kv_nrho}{}
+ {\tt nrho} ({\tt Int64}, default: $0$): number of values for $\rho$ (spaced linearly). If {\tt nrho} is $\neq0$, then the linear spacing will be used, and \refname{param:simpleq-Kv_minlrho}{{\tt minlrho}}, \refname{param:simpleq-Kv_maxlrho}{{\tt maxlrho}}, \refname{param:simpleq-Kv_nlrho}{{\tt nlrho}} will be ignored. Otherwise, the logarithmic spacing will be used and \refname{param:simpleq-Kv_minrho}{{\tt minrho}}, \refname{param:simpleq-Kv_maxrho}{{\tt maxrho}} will be ignored.
+
\item\makelink{param:simpleq-Kv_rhos}{}
- {\tt rhos} ({\tt Array\{Float64\}}, default: $(10^{{\tt minlrho}+\frac{{\tt maxlrho}-{\tt minlrho}}{{\tt nlrho}}n})_n$: list of values for $\rho$, specified as a `{\tt,}' separated list.
+ {\tt rhos} ({\tt Array\{Float64\}}): list of values for $\rho$, specified as a `{\tt,}' separated list.
+ This parameter takes precedence over \refname{param:simpleq-Kv_minlrho}{{\tt minlrho}}, \refname{param:simpleq-Kv_maxlrho}{{\tt maxlrho}}, \refname{param:simpleq-Kv_nlrho}{{\tt nlrho}}, \refname{param:simpleq-Kv_minrho}{{\tt minrho}}, \refname{param:simpleq-Kv_maxrho}{{\tt maxrho}}, \refname{param:simpleq-Kv_nrho}{{\tt nrho}}.
\end{itemize}
\underline{Output} (one line for each value of $\rho$): [$\rho$] [$\eta$]
@@ -1980,8 +2842,18 @@ The available {\tt commands} are the following.
\item\makelink{param:simpleq-hardcore_nlrho}{}
{\tt nlrho} ({\tt Int64}, default: $100$): number of values for $\rho$ (spaced logarithmically).
+ \item\makelink{param:simpleq-hardcore_minrho}{}
+ {\tt minrho} ({\tt Float64}, default: $10^{-6}$): minimal value for $\rho$.
+
+ \item\makelink{param:simpleq-hardcore_maxrho}{}
+ {\tt maxrho} ({\tt Float64}, default: $10^{2}$): maximal value for $\rho$.
+
+ \item\makelink{param:simpleq-hardcore_nrho}{}
+ {\tt nrho} ({\tt Int64}, default: $0$): number of values for $\rho$ (spaced linearly). If {\tt nrho} is $\neq0$, then the linear spacing will be used, and \refname{param:simpleq-hardcore_minlrho}{{\tt minlrho}}, \refname{param:simpleq-hardcore_maxlrho}{{\tt maxlrho}}, \refname{param:simpleq-hardcore_nlrho}{{\tt nlrho}} will be ignored. Otherwise, the logarithmic spacing will be used and \refname{param:simpleq-hardcore_minrho}{{\tt minrho}}, \refname{param:simpleq-hardcore_maxrho}{{\tt maxrho}} will be ignored.
+
\item\makelink{param:simpleq-hardcore_rhos}{}
- {\tt rhos} ({\tt Array\{Float64\}}, default: $(10^{{\tt minlrho}+\frac{{\tt maxlrho}-{\tt minlrho}}{{\tt nlrho}}n})_n$: list of values for $\rho$, specified as a `{\tt,}' separated list.
+ {\tt rhos} ({\tt Array\{Float64\}}): list of values for $\rho$, specified as a `{\tt,}' separated list.
+ This parameter takes precedence over \refname{param:simpleq-hardcore_minlrho}{{\tt minlrho}}, \refname{param:simpleq-hardcore_maxlrho}{{\tt maxlrho}}, \refname{param:simpleq-hardcore_nlrho}{{\tt nlrho}}, \refname{param:simpleq-hardcore_minrho}{{\tt minrho}}, \refname{param:simpleq-hardcore_maxrho}{{\tt maxrho}}, \refname{param:simpleq-hardcore_nrho}{{\tt nrho}}.
\end{itemize}
\underline{Output} (one line for each value of $\rho$): [$\rho$] [$e$] [Newton error $\epsilon$].\par
\underline{Multithread support}: yes, different values of $\rho$ split up among workers.
@@ -2023,7 +2895,7 @@ In order to carry out the computation of the solution of\-~(\ref{linearhc}) and
for $|x|>1$.
\bigskip
-\point{\bf Energy.}
+\subsubsubsection{Energy}
To compute the energy $e$ of this equation, with the extra parameter $\mu$, we consider the limit of the soft sphere potential $\lambda\mathds 1_{|x|<1}$ (see\-~(\ref{easyeq}) with $\beta_K=\beta_L=0$):
\begin{equation}
(-\Delta+2\mu+4e)u(x)=s_\lambda(x)+2e\rho u\ast u
@@ -2056,7 +2928,7 @@ Therefore,
\end{equation}
\bigskip
-\point{\bf Integral equation.}
+\subsubsubsection{Integral equation}
We turn the differential equation in\-~(\ref{hardcore_simple}) into an integral equation.
Let
\begin{equation}
@@ -2115,7 +2987,7 @@ We change variables in the last integral:
\end{equation}
\bigskip
-\point{\bf The auto-convolution term.} We split
+\subsubsubsection{The auto-convolution term} We split
\begin{equation}
u(r)=\mathds 1_{r>1}u_+(r-1)+\mathds 1_{r\leqslant 1}
.
@@ -2253,7 +3125,7 @@ where
is the same as is defined for \refname{sec:anyeq}{{\tt anyeq}} (\ref{anyeq_alpha}).
\bigskip
-\point{\bf Chebyshev polynomial expansion.} We use the same interpolation as we used in \refname{sec:anyeq}{{\tt anyeq}}: (\ref{a_chebyshev_spline})
+\subsubsubsection{Chebyshev polynomial expansion} We use the same interpolation as we used in \refname{sec:anyeq}{{\tt anyeq}}: (\ref{a_chebyshev_spline})
\begin{equation}
\frac1{(1+\tau)^{\nu_u}}u_+({\textstyle\frac{1-\tau}{1+\tau}})=\sum_{l=0}^{J-1}\mathds 1_{\tau_l\leqslant\tau<\tau_{l+1}}\sum_{n=0}^\infty \mathbf F_{l,n}^{(\nu_u)}(u_+) T_n({\textstyle\frac{2\tau-(\tau_l+\tau_{l+1})}{\tau_{l+1}-\tau_l}})
\label{a_chebyshev_spline}
@@ -2343,10 +3215,10 @@ and
\end{equation}
\bigskip
-\point{\bf Energy.} We now compute the approximation for the energy, using\-~(\ref{hardcore_energy}).
+\subsubsubsection{Energy} We now compute the approximation for the energy, using\-~(\ref{hardcore_energy}).
\bigskip
-\subpoint We start with $\partial u|_{|x|\searrow 1}$.
+\point We start with $\partial u|_{|x|\searrow 1}$.
By\-~(\ref{uinteq}),
\begin{equation}
\partial u|_{|x|\searrow 1}
@@ -2386,7 +3258,7 @@ and
.
\end{equation}
-\subpoint Let us now turn to $\int_{|x|<1}dx\ u\ast u(x)$.
+\point Let us now turn to $\int_{|x|<1}dx\ u\ast u(x)$.
We have
\begin{equation}
\int_{|x|<1}dx\ u\ast u(x)
@@ -2421,7 +3293,7 @@ and
\end{equation}
\bigskip
-\subpoint Thus,
+\point Thus,
\begin{equation}
\begin{largearray}
e=2\pi\rho
@@ -2452,11 +3324,11 @@ and
\end{equation}
\bigskip
-\point{\bf Newton algorithm.}
+\subsubsubsection{Newton algorithm}
In this paragraph, we set $\epsilon=e$, that is, $\mu=0$.
\bigskip
-\subpoint
+\point
As we did for \refname{sec:anyeq}{{\tt anyeq}}, we discretize the integral in\-~(\ref{bfF}) by using a Gauss-Legendre quadrature, and truncate the sum over Chebyshev polynomials to order \refname{param:simpleq-hardcore_P}{{\tt P}}.
We then reduce the computation to a finite system of equations, whose variables are
\begin{equation}
@@ -2519,7 +3391,7 @@ Gauss-Legendre and Gauss-Laguerre quadratures and their errors are discussed in
The orders of the quadratures are given by the variable \refname{param:simpleq-hardcore_N}{{\tt N}}.
\bigskip
-\subpoint
+\point
We then solve $\Xi=0$ using the Newton algorithm, that is, we define a sequence of $\mathbb U$'s:
\begin{equation}
\mathbb U^{(n+1)}=\mathbb U^{(n)}-(D\Xi(\mathbb U^{(n)}))^{-1}\Xi(\mathbb U^{(n)})
@@ -2538,7 +3410,7 @@ We initialize the algorithm with
\end{equation}
\bigskip
-\subpoint
+\point
We are left with computing the Jacobian of $\Xi$:
\begin{equation}
\begin{largearray}
@@ -2709,7 +3581,7 @@ and
Finally, to get from $D$ to $\mathbb D$ and $\gamma$ to $\mathfrak g$, we approximate the integrate using Gauss-Legendre and Gauss-Laguerre quadratures (see appendix\-~\ref{appGL}), as described above.
\bigskip
-\subpoint
+\point
We iterate the Newton algorithm until the Newton relative error $\epsilon$ becomes smaller than the \refname{param:easyeq_tolerance}{{\tt tolerance}} parameter.
The Newton error is defined as
\begin{equation}
@@ -2723,7 +3595,7 @@ The energy thus obtained is
\end{equation}
\bigskip
-\point{\bf Condensate fraction.}
+\subsubsubsection{Condensate fraction}
To compute the condensate fraction, we use the parameter $\mu$ in\-~(\ref{hardcore_simple}).
The uncondensed fraction is
\begin{equation}
@@ -3213,7 +4085,7 @@ In $x$-space
\frac{12c( x^6b^6(2e-b^2) +b^4x^4(9e-7b^2) +4b^2x^2(3e-2b^2) +(5e+16b^2))}{(1+b^2x^2)^2(4+b^2x^2)^2((1+b^2x^2)^2-c)}
\end{equation}
The constants $a,b,c,e$ can be set using the parameters {\tt v\_a}, {\tt v\_b}, {\tt v\_c}, {\tt v\_e}, and $a,e\in\mathbb R$, $b\neq0$, $c>0$, $c\neq9$.
-Note that $v\geqslant 0$ if and only if\-~\cite{CJL20b}
+Note that $v\geqslant 0$ if and only if\-~\cite{CJL21}
\begin{equation}
b>0
,\quad
diff --git a/src/anyeq.jl b/src/anyeq.jl
index 8459cb0..fee77d8 100644
--- a/src/anyeq.jl
+++ b/src/anyeq.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.
@@ -28,24 +28,26 @@
end
# compute energy for a given rho
-# use minlrho, nlrho to incrementally compute the solution to medeq (to initialize the Newton algorithm)
-function anyeq_energy(rho,minlrho,nlrho,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
+function anyeq_energy(
+ rho::Float64,
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
- end
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- u0=u0s[nlrho]
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
(u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
@@ -53,72 +55,60 @@ function anyeq_energy(rho,minlrho,nlrho,taus,P,N,J,a0,v,maxiter,tolerance,approx
end
# compute energy as a function of rho
-function anyeq_energy_rho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
+function anyeq_energy_rho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
-
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
-
- # save result from each task
- es=Array{Float64,1}(undef,length(rhos))
- err=Array{Float64,1}(undef,length(rhos))
+ u0s=anyeq_init_medeq(rhos,minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
- ## spawn workers
- # number of workers
- nw=nworkers()
- # split jobs among workers
- work=Array{Array{Int64,1},1}(undef,nw)
- # init empty arrays
- for p in 1:nw
- work[p]=zeros(0)
- end
- for j in 1:length(rhos)
- append!(work[(j-1)%nw+1],j)
- end
+ # spawn workers
+ work=spawn_workers(length(rhos))
- count=0
- # for each worker
- @sync for p in 1:nw
- # for each task
- @async for j in work[p]
- count=count+1
- if count>=nw
- progress(count,length(rhos),10000)
- end
- # run the task
- (u,es[j],err[j])=remotecall_fetch(anyeq_hatu,workers()[p],u0s[j],P,N,J,rhos[j],a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
- end
- end
+ # compute u
+ (us,es,errs)=anyeq_hatu_rho_multithread(u0s,P,N,J,rhos,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx,work)
for j in 1:length(rhos)
- @printf("% .15e % .15e % .15e\n",rhos[j],es[j],err[j])
+ @printf("% .15e % .15e % .15e\n",rhos[j],es[j],errs[j])
end
end
# compute energy as a function of rho
# initialize with previous rho
-function anyeq_energy_rho_init_prevrho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
+function anyeq_energy_rho_init_prevrho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
-
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- u0s=anyeq_init_medeq([rhos[1]],N,J,k,a0,v,maxiter,tolerance)
- u=u0s[1]
+ u=anyeq_init_medeq([rhos[1]],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
for j in 1:length(rhos)
progress(j,length(rhos),10000)
@@ -134,20 +124,26 @@ function anyeq_energy_rho_init_prevrho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,ap
end
# compute energy as a function of rho
# initialize with next rho
-function anyeq_energy_rho_init_nextrho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
+function anyeq_energy_rho_init_nextrho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
-
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- u0s=anyeq_init_medeq([rhos[length(rhos)]],N,J,k,a0,v,maxiter,tolerance)
- u=u0s[1]
+ u=anyeq_init_medeq([rhos[length(rhos)]],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
for j in 1:length(rhos)
progress(j,length(rhos),10000)
@@ -163,23 +159,26 @@ function anyeq_energy_rho_init_nextrho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,ap
end
# compute u(k)
-# use minlrho, nlrho to incrementally compute the solution to medeq (to initialize the Newton algorithm)
-function anyeq_uk(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,approx,savefile)
+function anyeq_uk(
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# init vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
- end
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- u0=u0s[nlrho]
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
(u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
@@ -192,58 +191,60 @@ function anyeq_uk(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,approx,sav
end
# compute u(x)
-# use minlrho, nlrho to incrementally compute the solution to medeq (to initialize the Newton algorithm)
-function anyeq_ux(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,xmin,xmax,nx,approx,savefile)
+function anyeq_ux(
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ xmin::Float64,
+ xmax::Float64,
+ nx::Int64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# init vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
- end
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- u0=u0s[nlrho]
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
(u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
for i in 1:nx
x=xmin+(xmax-xmin)*i/nx
- ux=0.
- for zeta in 0:J-1
- for j in 1:N
- ux+=(taus[zeta+2]-taus[zeta+1])/(16*pi*x)*weights[2][j]*cos(pi*weights[1][j]/2)*(1+k[zeta*N+j])^2*k[zeta*N+j]*u[zeta*N+j]*sin(k[zeta*N+j]*x)
- end
- end
- @printf("% .15e % .15e % .15e\n",x,real(ux),imag(ux))
+ ux=anyeq_u_x(x,u,k,N,J,taus,weights)
+ @printf("% .15e % .15e % .15e\n",x,ux,)
end
end
# compute condensate fraction for a given rho
-# use minlrho, nlrho to incrementally compute the solution to medeq (to initialize the Newton algorithm)
-function anyeq_condensate_fraction(rho,minlrho,nlrho,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
+function anyeq_condensate_fraction(
+ rho::Float64,
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
- end
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
- end
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- u0=u0s[nlrho]
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
(u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
@@ -254,161 +255,571 @@ function anyeq_condensate_fraction(rho,minlrho,nlrho,taus,P,N,J,a0,v,maxiter,tol
end
# condensate fraction as a function of rho
-function anyeq_condensate_fraction_rho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
- ## spawn workers
- # number of workers
- nw=nworkers()
- # split jobs among workers
- work=Array{Array{Int64,1},1}(undef,nw)
- # init empty arrays
- for p in 1:nw
- work[p]=zeros(0)
+function anyeq_condensate_fraction_rho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # spawn workers
+ work=spawn_workers(length(rhos))
+
+ # initialize vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0s=anyeq_init_medeq(rhos,minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # compute u
+ (us,es,errs)=anyeq_hatu_rho_multithread(u0s,P,N,J,rhos,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx,work)
+
+ # compute eta
+ etas=Array{Float64,1}(undef,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
+ etas[j]=remotecall_fetch(anyeq_eta,workers()[p],us[j],P,N,J,rhos[j],weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
+ end
end
+
for j in 1:length(rhos)
- append!(work[(j-1)%nw+1],j)
+ @printf("% .15e % .15e % .15e\n",rhos[j],etas[j],errs[j])
end
+end
+# compute the momentum distribution for a given rho
+function anyeq_momentum_distribution(
+ kmin::Float64,
+ kmax::Float64,
+ rho::Float64,
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+
+ # compute M
+ if windowL==Inf
+ # use discrete approximation of delta function
+ M=anyeq_momentum_discrete_delta(kmin,kmax,u,P,N,J,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
+ M=anyeq_momentum_window(kmin,kmax,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
end
+ # order k's in increasing order
+ for zeta in 0:J-1
+ for j in 1:N
+ q=k[(J-1-zeta)*N+j]
+ # drop if not in k interval
+ if q<kmin || q>kmax
+ continue
+ end
+ @printf("% .15e % .15e\n",q,M[(J-1-zeta)*N+j])
+ end
+ end
+end
+
+# 2 point correlation function
+function anyeq_2pt_correlation(
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ xmin::Float64,
+ xmax::Float64,
+ nx::Int64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
# compute initial guess from medeq
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # compute u and some useful integrals
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+
+ for i in 1:nx
+ x=xmin+(xmax-xmin)*i/nx
+ C2=anyeq_2pt(x,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK)
+ @printf("% .15e % .15e\n",x,C2)
+ end
+end
+
+# maximum of 2 point correlation function
+function anyeq_2pt_correlation_max(
+ rho::Float64,
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ dx::Float64,
+ x0::Float64, # initial guess is x0/rho^(1/3)
+ maxstep::Float64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ tolerance_max::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # initial guess
+ x0=1/rho^(1/3)
+
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ (x,f)=anyeq_2pt_max(u,P,N,J,x0/rho^(1/3),dx,maxstep,maxiter,tolerance_max,windowL,rho,weights,T,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,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 anyeq_2pt_correlation_max_rho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ dx::Float64,
+ x0::Float64, # initial guess is x0/rho^(1/3)
+ maxstep::Float64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ tolerance_max::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0s=anyeq_init_medeq(rhos,minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # 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))
# compute u
- us=Array{Array{Float64,1}}(undef,length(rhos))
- errs=Array{Float64,1}(undef,length(rhos))
+ (us,es,errs)=anyeq_hatu_rho_multithread(u0s,P,N,J,rhos,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx,work)
+
count=0
# for each worker
- @sync for p in 1:nw
+ @sync for p in 1:length(work)
# for each task
@async for j in work[p]
count=count+1
- if count>=nw
- progress(count,length(rhos),10000)
+ if count>=length(work)
+ progress(count,length(rhos),10000)
end
# run the task
- (us[j],E,errs[j])=remotecall_fetch(anyeq_hatu,workers()[p],u0s[j],P,N,J,rhos[j],a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ (xs[j],fs[j])=remotecall_fetch(anyeq_2pt_max,workers()[p],us[j],P,N,J,x0/rhos[j]^(1/3),dx,maxstep,maxiter,tolerance_max,windowL,rhos[j],weights,T,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
end
end
- # compute eta
- etas=Array{Float64}(undef,length(rhos))
+ 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
+
+# Correlation function in Fourier space
+function anyeq_2pt_correlation_fourier(
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ kmin::Float64,
+ kmax::Float64,
+ nk::Int64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # compute u and some useful integrals
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+
+ # save result from each task
+ C2s=Array{Float64,1}(undef,nk)
+
+ # spawn workers
+ work=spawn_workers(nk)
+
count=0
# for each worker
- @sync for p in 1:nw
+ @sync for p in 1:length(work)
# for each task
@async for j in work[p]
count=count+1
- if count>=nw
- progress(count,length(rhos),10000)
+ if count>=length(work)
+ progress(count,nk,10000)
end
# run the task
- etas[j]=anyeq_eta(us[j],P,N,J,rhos[j],weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
+ C2s[j]=remotecall_fetch(anyeq_2pt_fourier,workers()[p],kmin+(kmax-kmin)*j/nk,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK)
end
end
- for j in 1:length(rhos)
- @printf("% .15e % .15e % .15e\n",rhos[j],etas[j],errs[j])
+ for j in 1:nk
+ @printf("% .15e % .15e\n",kmin+(kmax-kmin)*j/nk,C2s[j])
end
end
-# compute the momentum distribution for a given rho
-# use minlrho, nlrho to incrementally compute the solution to medeq (to initialize the Newton algorithm)
-function anyeq_momentum_distribution(rho,minlrho,nlrho,taus,P,N,J,a0,v,maxiter,tolerance,approx,savefile)
- # initialize vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
+# maximum of Fourier transform of 2 point correlation function
+function anyeq_2pt_correlation_fourier_max(
+ rho::Float64,
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ dk::Float64,
+ k0::Float64, # initial guess is k0*rho^(1/3)
+ maxstep::Float64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ tolerance_max::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # compute u
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ (ko,f)=anyeq_2pt_fourier_max(u,P,N,J,k0*rho^(1/3),dk,maxstep,maxiter,tolerance_max,windowL,rho,weights,T,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
+
+ if(ko==Inf)
+ @printf(stderr,"max search failed for rho=%e\n",rho)
else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
+ @printf("% .15e % .15e\n",ko,f)
end
+end
+
+# maximum of fourier transform of 2 point correlation function as a function of rho
+function anyeq_2pt_correlation_fourier_max_rho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ dk::Float64,
+ k0::Float64, # initial guess is k0*rho^(1/3)
+ maxstep::Float64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ tolerance_max::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
- end
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- u0=u0s[nlrho]
+ u0s=anyeq_init_medeq(rhos,minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
- (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ # spawn workers
+ work=spawn_workers(length(rhos))
- # compute M
- M=anyeq_momentum(u,P,N,J,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
+ # compute u
+ (us,es,errs)=anyeq_hatu_rho_multithread(u0s,P,N,J,rhos,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx,work)
- for zeta in 0:J-1
- for j in 1:N
- # order k's in increasing order
- @printf("% .15e % .15e\n",k[(J-1-zeta)*N+j],M[(J-1-zeta)*N+j])
+ # save result from each task
+ ks=Array{Float64,1}(undef,length(rhos))
+ fs=Array{Float64,1}(undef,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(anyeq_2pt_fourier_max,workers()[p],us[j],P,N,J,k0*rhos[j]^(1/3),dk,maxstep,maxiter,tolerance_max,windowL,rhos[j],weights,T,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,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
-# 2 point correlation function
-function anyeq_2pt_correlation(minlrho,nlrho,taus,P,N,J,windowL,rho,a0,v,maxiter,tolerance,xmin,xmax,nx,approx,savefile)
+# uncondensed 2 point correlation function
+function anyeq_uncondensed_2pt_correlation(
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ xmin::Float64,
+ xmax::Float64,
+ nx::Int64,
+ approx::Anyeq_approx,
+ savefile::String
+)
# init vectors
- (weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
- # init Abar
- if savefile!=""
- Abar=anyeq_read_Abar(savefile,P,N,J)
- else
- Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # compute u and some useful integrals
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+
+ # compute u(xi)
+ uxis=Array{Float64,1}(undef,nx)
+ for i in 1:nx
+ uxis[i]=anyeq_u_x(xmin+(xmax-xmin)*i/nx,u,k,N,J,taus,weights)
+ end
+
+
+ # spawn workers
+ work=spawn_workers(nx)
+ gamma2s=Array{Float64,1}(undef,nx)
+ 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,nx,10000)
+ end
+ # run the task
+ gamma2s[j]=remotecall_fetch(anyeq_uncondensed_2pt,workers()[p],xmin+(xmax-xmin)*j/nx,uxis[j],u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK)
+ end
end
+ for i in 1:nx
+ @printf("% .15e % .15e\n",xmin+(xmax-xmin)*i/nx,gamma2s[i])
+ end
+end
+
+# compute the compressibility
+function anyeq_compressibility_rho(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # initialize vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
+ u0s=anyeq_init_medeq(rhos,minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
+
+ # save result from each task
+ es=Array{Float64,1}(undef,length(rhos))
+ err=Array{Float64,1}(undef,length(rhos))
+
+ # spawn workers
+ work=spawn_workers(length(rhos))
+
+ # compute u
+ (us,es,errs)=anyeq_hatu_rho_multithread(u0s,P,N,J,rhos,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx,work)
+
+ for j in 1:length(rhos)-2
+ # compute \rho^2\partial^2(\rho e)=\partial^2_{\log\rho}(\rho e)-\partial_{\log\rho}(\rho e) as a function of rho
+ # \partial^2_{\log\rho}(\rho e)
+ p2=(rhos[j+2]*es[j+2]-2*rhos[j+1]*es[j+1]+rhos[j]*es[j])/(log(rhos[j+2])-log(rhos[j+1]))/(log(rhos[j+1])-log(rhos[j]))
+ # \partial_{\log\rho}(\rho e) (take average of front and back)
+ p11=(rhos[j+2]*es[j+2]-rhos[j+1]*es[j+1])/(log(rhos[j+2])-log(rhos[j+1]))
+ p12=(rhos[j+1]*es[j+1]-rhos[j]*es[j])/(log(rhos[j+1])-log(rhos[j]))
+ # compressibility is 1/this
+ @printf("% .15e % .15e\n",rhos[j+1],1/(p2-(p11+p12)/2))
end
- u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- u0=u0s[nlrho]
+end
+
+# Fourier transform 2 point correlation function test: compute by transforming anyeq_2pt
+function anyeq_2pt_correlation_fourier_test(
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ xmax::Float64,
+ kmin::Float64,
+ kmax::Float64,
+ nk::Int64,
+ approx::Anyeq_approx,
+ savefile::String
+)
+ # init vectors
+ (weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v,approx,savefile)
+
+ # compute initial guess from medeq
+ u0=anyeq_init_medeq([rho],minlrho_init,nlrho_init,N,J,k,a0,v,maxiter,tolerance)
# compute u and some useful integrals
(u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
(S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
- for i in 1:nx
- x=xmin+(xmax-xmin)*i/nx
- C2=anyeq_2pt(x,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK,G)
- @printf("% .15e % .15e\n",x,C2)
+ # compute C2 in real space
+ C2=Array{Float64,1}(undef,N*J)
+ for i in 1:N*J
+ if k[i]<xmax
+ C2[i]=anyeq_2pt(k[i],u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK)-rho^2
+ else
+ C2[i]=0.
+ end
+ end
+ # invert Fourier transform
+ for i in 1:nk
+ k0=kmin+(kmax-kmin)*i/nk
+ hatC2=inverse_fourier_chebyshev(C2,k0,k,taus,weights,N,J)
+ @printf("% .15e % .15e\n",k0,hatC2)
end
end
# compute Abar
-function anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
+function anyeq_Abar_multithread(
+ k::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ approx::Anyeq_approx
+)
if approx.bL3==0.
- return []
+ # empty array
+ return Array{Array{Float64,5}}(undef,0)
end
out=Array{Array{Float64,5}}(undef,J*N)
- ## spawn workers
- # number of workers
- nw=nworkers()
- # split jobs among workers
- work=Array{Array{Int64,1},1}(undef,nw)
- # init empty arrays
- for p in 1:nw
- work[p]=zeros(0)
- end
- for j in 1:N*J
- append!(work[(j-1)%nw+1],j)
- end
+ # spawn workers
+ work=spawn_workers(N*J)
count=0
# for each worker
- @sync for p in 1:nw
+ @sync for p in 1:length(work)
# for each task
@async for j in work[p]
count=count+1
- if count>=nw
+ if count>=length(work)
progress(count,N*J,10000)
end
# run the task
@@ -419,14 +830,23 @@ function anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
return out
end
+
# initialize computation
-@everywhere function anyeq_init(taus,P,N,J,v)
+@everywhere function anyeq_init(
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ v::Function,
+ approx::Anyeq_approx,
+ savefile::String
+)
# Gauss-Legendre weights
weights=gausslegendre(N)
# initialize vectors V,k
- V=Array{Float64}(undef,J*N)
- k=Array{Float64}(undef,J*N)
+ V=Array{Float64,1}(undef,J*N)
+ k=Array{Float64,1}(undef,J*N)
for zeta in 0:J-1
for j in 1:N
xj=weights[1][j]
@@ -437,7 +857,7 @@ end
end
end
# potential at 0
- V0=v(0)
+ V0=v(0.)
# initialize matrix A
T=chebyshev_polynomials(P)
@@ -449,39 +869,62 @@ end
Upsilon=Upsilonmat(k,v,weights_plus)
Upsilon0=Upsilon0mat(k,v,weights_plus)
- return(weights,T,k,V,V0,A,Upsilon,Upsilon0)
+ # init Abar
+ if savefile!=""
+ Abar=anyeq_read_Abar(savefile,P,N,J)
+ else
+ Abar=anyeq_Abar_multithread(k,weights,taus,T,P,N,J,approx)
+ end
+
+ return(weights,T,k,V,V0,A,Abar,Upsilon,Upsilon0)
end
# compute initial guess from medeq
-@everywhere function anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
- us_medeq=Array{Array{Float64,1}}(undef,length(rhos))
- u0s=Array{Array{Float64,1}}(undef,length(rhos))
-
+@everywhere function anyeq_init_medeq(
+ rhos::Array{Float64,1},
+ minlrho_init::Float64,
+ nlrho_init::Int64,
+ N::Int64,
+ J::Int64,
+ k::Array{Float64,1},
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64
+)
weights_medeq=gausslegendre(N*J)
+ (u0s_medeq,es,errs)=easyeq_compute_u_prevrho(rhos,minlrho_init,nlrho_init,a0,N*J,v,maxiter,tolerance,weights_medeq,Easyeq_approx(1.,1.))
- (us_medeq[1],E,err)=easyeq_hatu(easyeq_init_u(a0,J*N,weights_medeq),J*N,rhos[1],v,maxiter,tolerance,weights_medeq,Easyeq_approx(1.,1.))
- u0s[1]=easyeq_to_anyeq(us_medeq[1],weights_medeq,k,N,J)
- if err>tolerance
- print(stderr,"warning: computation of initial Ansatz failed for rho=",rhos[1],"\n")
- end
-
- for j in 2:length(rhos)
- (us_medeq[j],E,err)=easyeq_hatu(us_medeq[j-1],J*N,rhos[j],v,maxiter,tolerance,weights_medeq,Easyeq_approx(1.,1.))
- u0s[j]=easyeq_to_anyeq(us_medeq[j],weights_medeq,k,N,J)
-
- if err>tolerance
+ # check errs
+ for j in 1:length(errs)
+ if errs[j]>tolerance
print(stderr,"warning: computation of initial Ansatz failed for rho=",rhos[j],"\n")
end
end
- return u0s
+ # return a single vector if there is a single rho
+ if length(rhos)>1
+ u0s=Array{Array{Float64,1}}(undef,length(rhos))
+ for j in 1:length(u0s_medeq)
+ u0s[j]=easyeq_to_anyeq(u0s_medeq[j],weights_medeq,k,N,J)
+ end
+ return u0s
+ else
+ return easyeq_to_anyeq(u0s_medeq,weights_medeq,k,N,J)
+ end
end
# interpolate the solution of medeq to an input for anyeq
-@everywhere function easyeq_to_anyeq(u_simple,weights,k,N,J)
+@everywhere function easyeq_to_anyeq(
+ u_simple::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ N::Int64,
+ J::Int64
+)
# reorder u_simple, which is evaluated at (1-x_j)/(1+x_j) with x_j\in[-1,1]
u_s=zeros(Float64,length(u_simple))
- k_s=Array{Float64}(undef,length(u_simple))
+ k_s=Array{Float64,1}(undef,length(u_simple))
for j in 1:length(u_simple)
xj=weights[1][j]
k_s[length(u_simple)-j+1]=(1-xj)/(1+xj)
@@ -501,7 +944,27 @@ end
# compute u using chebyshev expansions
-@everywhere function anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+@everywhere function anyeq_hatu(
+ u0::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ a0::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx
+)
# init
# rescale by rho (that's how u is defined)
u=rho*u0
@@ -512,7 +975,7 @@ end
# run Newton algorithm
for i in 1:maxiter-1
(S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
- new=u-inv(anyeq_DXi(u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*anyeq_Xi(u,X,Y)
+ new=u-inv(anyeq_DXi(u,rho,k,taus,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*anyeq_Xi(u,X,Y)
error=norm(new-u)/norm(u)
if(error<tolerance)
@@ -528,8 +991,60 @@ end
end
+# compute u for various rho
+function anyeq_hatu_rho_multithread(
+ u0s::Array{Array{Float64,1},1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rhos::Array{Float64,1},
+ a0::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ approx::Anyeq_approx,
+ work::Array{Array{Int64,1},1}
+)
+ # compute u
+ us=Array{Array{Float64,1}}(undef,length(rhos))
+ es=Array{Float64,1}(undef,length(rhos))
+ errs=Array{Float64,1}(undef,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
+ (us[j],es[j],errs[j])=remotecall_fetch(anyeq_hatu,workers()[p],u0s[j],P,N,J,rhos[j],a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,approx)
+ end
+ end
+
+ return (us,es,errs)
+end
+
+
# save Abar
-function anyeq_save_Abar(taus,P,N,J,v,approx)
+function anyeq_save_Abar(
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ v::Function,
+ approx::Anyeq_approx
+)
# initialize vectors
(weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
@@ -555,7 +1070,12 @@ function anyeq_save_Abar(taus,P,N,J,v,approx)
end
# read Abar
-function anyeq_read_Abar(savefile,P,N,J)
+function anyeq_read_Abar(
+ savefile::String,
+ P::Int64,
+ N::Int64,
+ J::Int64
+)
# open file
ff=open(savefile,"r")
# read all lines
@@ -623,13 +1143,39 @@ end
# Xi
# takes the vector of kj's and xn's as input
-@everywhere function anyeq_Xi(U,X,Y)
+@everywhere function anyeq_Xi(
+ U::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1}
+)
return U-(Y.+1)./(2*(X.+1)).*dotPhi((Y.+1)./((X.+1).^2))
end
# DXi
# takes the vector of kj's as input
-@everywhere function anyeq_DXi(U,rho,k,taus,v,v0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK)
+@everywhere function anyeq_DXi(
+ U::Array{Float64,1},
+ rho::Float64,
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ approx::Anyeq_approx,
+ S::Array{Float64,1},
+ E::Float64,
+ II::Array{Float64,1},
+ JJ::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1},
+ sL1::Array{Float64,1},
+ sK::Array{Float64,1}
+)
out=Array{Float64,2}(undef,N*J,N*J)
for zetapp in 0:J-1
for n in 1:N
@@ -720,7 +1266,23 @@ end
end
# compute S,E,I,J,X and Y
-@everywhere function anyeq_SEIJGXY(U,rho,k,taus,v,v0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+@everywhere function anyeq_SEIJGXY(
+ U::Array{Float64,1},
+ rho::Float64,
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ v::Array{Float64,1},
+ v0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ approx::Anyeq_approx
+)
# Chebyshev expansion of U
FU=chebyshev(U,taus,weights,P,N,J,2)
@@ -798,79 +1360,207 @@ end
return(S,E,II,JJ,X,Y,sL1,sK,G)
end
+
+# u(x)
+@everywhere function anyeq_u_x(
+ x::Float64,
+ u::Array{Float64,1},
+ k::Array{Float64,1},
+ N::Int64,
+ J::Int64,
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
+ ux=0.
+ for zeta in 0:J-1
+ for j in 1:N
+ ux+=(taus[zeta+2]-taus[zeta+1])/(16*pi*x)*weights[2][j]*cos(pi*weights[1][j]/2)*(1+k[zeta*N+j])^2*k[zeta*N+j]*u[zeta*N+j]*sin(k[zeta*N+j]*x)
+ end
+ end
+ return real(ux)
+end
+
# condensate fraction
-@everywhere function anyeq_eta(u,P,N,J,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
+@everywhere function anyeq_eta(
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx
+)
# compute dXi/dmu
(S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
dXidmu=(Y.+1)./(rho*sL1)./(2*(X.+1).^2).*dotPhi((Y.+1)./((X.+1).^2))+(Y.+1).^2 ./((X.+1).^4)./(rho*sL1).*dotdPhi((Y.+1)./(X.+1).^2)
# compute eta
- du=-inv(anyeq_DXi(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*dXidmu
+ du=-inv(anyeq_DXi(rho*u,rho,k,taus,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*dXidmu
eta=-avg_v_chebyshev(du,Upsilon0,k,taus,weights,N,J)/2
return eta
end
-# momentum distribution
-@everywhere function anyeq_momentum(u,P,N,J,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx)
- # compute dXi/dlambda (without delta functions)
- (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
- dXidlambda=-(2*pi)^3*2*u./sL1.*(dotPhi((Y.+1)./((X.+1).^2))./(2*(X.+1))+(Y.+1)./(2*(X.+1).^3).*dotdPhi((Y.+1)./(X.+1).^2))
-
- # approximation for delta function (without Kronecker deltas)
- delta=Array{Float64}(undef,J*N)
- for zeta in 0:J-1
- for n in 1:N
- delta[zeta*N+n]=2/pi^2/((taus[zeta+2]-taus[zeta+1])*weights[2][n]*cos(pi*weights[1][n]/2)*(1+k[zeta*N+n])^2*k[zeta*N+n]^2)
- end
- end
-
- # compute dXidu
- dXidu=inv(anyeq_DXi(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))
- M=Array{Float64}(undef,J*N)
- for i in 1:J*N
- # du/dlambda
- du=dXidu[:,i]*dXidlambda[i]*delta[i]
+# correlation function
+@everywhere function anyeq_2pt(
+ x::Float64,
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx,
+ S::Array{Float64,1},
+ E::Float64,
+ II::Array{Float64,1},
+ JJ::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1},
+ sL1::Array{Float64,1},
+ sK::Array{Float64,1}
+)
+ g=(r,x)->sinc(r*x)*hann(r,windowL)
+ du=anyeq_dudv(g, x, u, P, N, J, rho, weights, k, taus, V, V0, A, Abar, Upsilon, Upsilon0, approx, S, E, II, JJ, X, Y, sL1, sK)
+
+ C2=rho^2*(1-integrate_f_chebyshev(s->g(s,x),u,k,taus,weights,N,J)-integrate_f_chebyshev(s->1.,V.*du,k,taus,weights,N,J))
+end
- # compute M
- M[i]=-avg_v_chebyshev(du,Upsilon0,k,taus,weights,N,J)/2
+# uncondensed correlation function
+@everywhere function anyeq_uncondensed_2pt(
+ xi::Float64,
+ uxi::Float64,
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx,
+ S::Array{Float64,1},
+ E::Float64,
+ II::Array{Float64,1},
+ JJ::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1},
+ sL1::Array{Float64,1},
+ sK::Array{Float64,1}
+)
+ # compute dXi/dmu
+ g=Array{Float64,1}(undef,length(k))
+ for i in 1:length(k)
+ g[i]=-2*rho*uxi*sinc(k[i]*xi)*hann(k[i],windowL)
end
+ dXidmu=-g./sL1./(2*(X.+1)).*dotPhi((Y.+1)./((X.+1).^2))-(Y.+1).*g./sL1./(2(X.+1).^3).*dotdPhi((Y.+1)./(X.+1).^2)
- return M
-end
+ # compute gamma2
+ du=-inv(anyeq_DXi(rho*u,rho,k,taus,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*dXidmu
+ gamma2=-avg_v_chebyshev(du,Upsilon0,k,taus,weights,N,J)/2
+ return gamma2
+end
-# correlation function
-@everywhere function anyeq_2pt(x,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK,G)
+# compute the directional derivative of u with respect to v in direction g
+@everywhere function anyeq_dudv(
+ g::Function,# should be of the form g(k,x) where x is a parameter
+ x::Float64,
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx,
+ S::Array{Float64,1},
+ E::Float64,
+ II::Array{Float64,1},
+ JJ::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1},
+ sL1::Array{Float64,1},
+ sK::Array{Float64,1}
+)
# initialize dV
- dV=Array{Float64}(undef,J*N)
+ dV=Array{Float64,1}(undef,J*N)
for i in 1:J*N
- if x>0
- dV[i]=sin(k[i]*x)/(k[i]*x)*hann(k[i],windowL)
- else
- dV[i]=hann(k[i],windowL)
- end
+ dV[i]=g(k[i],x)
end
- dV0=1.
+ dV0=g(0.,x)
# compute dUpsilon
# Upsilonmat does not use splines, so increase precision
weights_plus=gausslegendre(N*J)
- dUpsilon=Upsilonmat(k,r->sin(r*x)/(r*x)*hann(r,windowL),weights_plus)
- dUpsilon0=Upsilon0mat(k,r->sin(r*x)/(r*x)*hann(r,windowL),weights_plus)
+ dUpsilon=Upsilonmat(k,s->g(s,x),weights_plus)
+ dUpsilon0=Upsilon0mat(k,s->g(s,x),weights_plus)
- du=-inv(anyeq_DXi(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*anyeq_dXidv(x,rho*u,rho,k,taus,dV,dV0,A,Abar,dUpsilon,dUpsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK)
+ du=-inv(anyeq_DXi(rho*u,rho,k,taus,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))*anyeq_dXidv(rho*u,rho,k,taus,dV,dV0,A,Abar,dUpsilon,dUpsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK)
# rescale rho
du=du/rho
- C2=rho^2*(1-integrate_f_chebyshev(s->1.,u.*dV+V.*du,k,taus,weights,N,J))
-
- return C2
+ return du
end
-# derivative of Xi with respect to v in the direction sin(kx)/kx
-@everywhere function anyeq_dXidv(x,U,rho,k,taus,dv,dv0,A,Abar,dUpsilon,dUpsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK)
+# derivative of Xi with respect to v in the specified by dUpsilon and dUpsilon0
+@everywhere function anyeq_dXidv(
+ U::Array{Float64,1},
+ rho::Float64,
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ dv::Array{Float64,1},
+ dv0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ dUpsilon::Array{Array{Float64,1},1},
+ dUpsilon0::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ approx::Anyeq_approx,
+ S::Array{Float64,1},
+ E::Float64,
+ II::Array{Float64,1},
+ JJ::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1},
+ sL1::Array{Float64,1},
+ sK::Array{Float64,1}
+)
# Chebyshev expansion of U
FU=chebyshev(U,taus,weights,P,N,J,2)
@@ -896,7 +1586,7 @@ end
dJJ+=approx.gL3*approx.bL3*double_conv_S_chebyshev(FU,FU,FU,FU,dFS,Abar)
end
if approx.bL3!=1.
- dJJ=approx.gL3*(1-approx.bL3)*dE*(UU/rho).^2
+ dJJ+=approx.gL3*(1-approx.bL3)*dE*(UU/rho).^2
end
end
@@ -947,3 +1637,220 @@ end
out=((Y.+1).*dX./(X.+1)-dY)./(2*(X.+1)).*dotPhi((Y.+1)./((X.+1).^2))+(Y.+1)./(2*(X.+1).^3).*(2*(Y.+1)./(X.+1).*dX-dY).*dotdPhi((Y.+1)./(X.+1).^2)
return out
end
+
+# maximum of 2 point correlation function
+@everywhere function anyeq_2pt_max(
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ x0::Float64,
+ dx::Float64,
+ maxstep::Float64,
+ maxiter::Int64,
+ tolerance::Float64,
+ windowL::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ T::Array{Polynomial,1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx
+)
+ # compute some useful integrals
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+
+ (x,f)=newton_maximum(y->anyeq_2pt(y,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK),x0,dx,maxiter,tolerance,maxstep)
+
+ return(x,f)
+end
+
+
+# Fourier transform of 2pt correlation function at q
+@everywhere function anyeq_2pt_fourier(
+ q::Float64,
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx,
+ S::Array{Float64,1},
+ E::Float64,
+ II::Array{Float64,1},
+ JJ::Array{Float64,1},
+ X::Array{Float64,1},
+ Y::Array{Float64,1},
+ sL1::Array{Float64,1},
+ sK::Array{Float64,1}
+)
+ # direction in which to differentiate u
+ weights_plus=gausslegendre(N*J)
+ #g=(r,x)->(r>0. ? (1.)/(2*x*r)*integrate_legendre(s->s*gaussian(s,(1.)/windowL),abs(x-r),x+r,weights_plus) : gaussian(x,(1.)/windowL))
+ g=(r,x)->(r>0. ? (1.)/(2*x*r*windowL)*(gaussian(x-r,(1.)/windowL)-gaussian(x+r,(1.)/windowL)) : gaussian(x,(1.)/windowL))
+
+ du=anyeq_dudv(g,q,u,P,N,J,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK)
+
+ C2=rho^2*(-integrate_f_chebyshev(s->g(s,q),u,k,taus,weights,N,J)-integrate_f_chebyshev(s->1.,V.*du,k,taus,weights,N,J))
+
+ return C2
+end
+
+# maximum of Fourier transform of 2 point correlation function
+@everywhere function anyeq_2pt_fourier_max(
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ k0::Float64,
+ dk::Float64,
+ maxstep::Float64,
+ maxiter::Int64,
+ tolerance::Float64,
+ windowL::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ T::Array{Polynomial,1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx
+)
+ # compute some useful integrals
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+
+ (ko,f)=newton_maximum(y->anyeq_2pt_fourier(y,u,P,N,J,windowL,rho,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,approx,S,E,II,JJ,X,Y,sL1,sK),k0,dk,maxiter,tolerance,maxstep)
+
+ return(ko,f)
+end
+
+# momentum distribution, computed using a Gaussian window
+@everywhere function anyeq_momentum_window(
+ kmin::Float64,
+ kmax::Float64,
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ windowL::Float64, # L is windowL/k^2
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx
+)
+
+ # compute dXi/dlambda without the delta function of u(q)
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+ dXidlambda=(16*pi^3)*(dotPhi((Y.+1)./((X.+1).^2))./(2*(X.+1))+(Y.+1)./(2*(X.+1).^3).*dotdPhi((Y.+1)./(X.+1).^2))./sL1
+
+ # compute dXidu
+ dXidu=inv(anyeq_DXi(rho*u,rho,k,taus,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))
+
+ M=Array{Float64,1}(undef,N*J)
+ for j in 1:J*N
+ # the Chebyshev polynomial expansion is often not good enough to compute M away from k[i]
+ q=k[j]
+
+ # drop the computation if not in k interval
+ if q<kmin || q>kmax
+ continue
+ end
+
+ # delta function
+ delta=Array{Float64,1}(undef,J*N)
+ L=windowL/q^2
+ for i in 1:J*N
+ delta[i]=(1.)/(2*k[i]*q*L)*(gaussian(k[i]-q,(1.)/L)-gaussian(k[i]+q,(1.)/L))
+ end
+
+ # du/dlambda
+ du=-dXidu*(dXidlambda.*delta*u[j])
+ # rescale u
+ du=du/rho
+
+ # compute M
+ M[j]=-avg_v_chebyshev(du,Upsilon0,k,taus,weights,N,J)*rho/2
+ end
+
+ return M
+end
+
+# momentum distribution, computed using a discrete approximation of the delta function
+@everywhere function anyeq_momentum_discrete_delta(
+ kmin::Float64,
+ kmax::Float64,
+ u::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ V::Array{Float64,1},
+ V0::Float64,
+ A::Array{Array{Float64,2},1},
+ Abar::Array{Array{Float64,5},1},
+ Upsilon::Array{Array{Float64,1},1},
+ Upsilon0::Array{Float64,1},
+ approx::Anyeq_approx
+)
+ # compute dXi/dlambda (without delta functions)
+ (S,E,II,JJ,X,Y,sL1,sK,G)=anyeq_SEIJGXY(rho*u,rho,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx)
+ dXidlambda=(2*pi)^3*2*u./sL1.*(dotPhi((Y.+1)./((X.+1).^2))./(2*(X.+1))+(Y.+1)./(2*(X.+1).^3).*dotdPhi((Y.+1)./(X.+1).^2))
+
+ # approximation for delta function (without Kronecker deltas)
+ delta=Array{Float64,1}(undef,J*N)
+ for zeta in 0:J-1
+ for n in 1:N
+ delta[zeta*N+n]=8/pi/((taus[zeta+2]-taus[zeta+1])*weights[2][n]*cos(pi*weights[1][n]/2)*(1+k[zeta*N+n])^2)
+ end
+ end
+
+ # compute dXidu
+ dXidu=inv(anyeq_DXi(rho*u,rho,k,taus,A,Abar,Upsilon,Upsilon0,weights,P,N,J,approx,S,E,II,JJ,X,Y,sL1,sK))
+
+ M=Array{Float64,1}(undef,J*N)
+ for i in 1:J*N
+ # drop the computation if not in k interval
+ if k[i]<kmin || k[i]>kmax
+ continue
+ end
+
+ # du/dlambda
+ du=-dXidu[:,i]*dXidlambda[i]*delta[i]
+
+ # compute M
+ M[i]=-avg_v_chebyshev(du,Upsilon0,k,taus,weights,N,J)/2
+ end
+
+ return M
+end
diff --git a/src/chebyshev.jl b/src/chebyshev.jl
index 28c8f1f..af4be40 100644
--- a/src/chebyshev.jl
+++ b/src/chebyshev.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.
@@ -13,7 +13,15 @@
## limitations under the License.
# Chebyshev expansion
-@everywhere function chebyshev(a,taus,weights,P,N,J,nu)
+@everywhere function chebyshev(
+ a::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
out=zeros(Float64,J*(P+1))
for zeta in 0:J-1
for n in 0:P
@@ -27,7 +35,15 @@
end
# evaluate function from Chebyshev expansion
-@everywhere function chebyshev_eval(Fa,x,taus,chebyshev,P,J,nu)
+@everywhere function chebyshev_eval(
+ Fa::Array{Float64,1},
+ x::Float64,
+ taus::Array{Float64,1},
+ chebyshev::Array{Polynomial,1},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
# change variable
tau=(1-x)/(1+x)
@@ -48,7 +64,11 @@ end
# convolution
# input the Chebyshev expansion of a and b, as well as the A matrix
-@everywhere function conv_chebyshev(Fa,Fb,A)
+@everywhere function conv_chebyshev(
+ Fa::Array{Float64,1},
+ Fb::Array{Float64,1},
+ A::Array{Array{Float64,2},1}
+)
out=zeros(Float64,length(A))
for i in 1:length(A)
out[i]=dot(Fa,A[i]*Fb)
@@ -57,12 +77,27 @@ end
end
# <ab>
-@everywhere function avg_chebyshev(Fa,Fb,A0)
+@everywhere function avg_chebyshev(
+ Fa::Array{Float64,1},
+ Fb::Array{Float64,1},
+ A0::Float64
+)
return dot(Fa,A0*Fb)
end
# 1_n * a
-@everywhere function conv_one_chebyshev(n,zetapp,Fa,A,taus,weights,P,N,J,nu1)
+@everywhere function conv_one_chebyshev(
+ n::Int64,
+ zetapp::Int64,
+ Fa::Array{Float64,1},
+ A::Array{Array{Float64,2},1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu1::Int64
+)
out=zeros(Float64,N*J)
for m in 1:N*J
for l in 0:P
@@ -74,7 +109,15 @@ end
return out
end
# a * v
-@everywhere function conv_v_chebyshev(a,Upsilon,k,taus,weights,N,J)
+@everywhere function conv_v_chebyshev(
+ a::Array{Float64,1},
+ Upsilon::Array{Array{Float64,1},1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
out=zeros(Float64,J*N)
for i in 1:J*N
for zetap in 0:J-1
@@ -86,7 +129,16 @@ end
end
return out
end
-@everywhere function conv_one_v_chebyshev(n,zetap,Upsilon,k,taus,weights,N,J)
+@everywhere function conv_one_v_chebyshev(
+ n::Int64,
+ zetap::Int64,
+ Upsilon::Array{Array{Float64,1},1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
out=zeros(Float64,J*N)
xj=weights[1][n]
for i in 1:J*N
@@ -96,7 +148,14 @@ end
end
# <av>
-@everywhere function avg_v_chebyshev(a,Upsilon0,k,taus,weights,N,J)
+@everywhere function avg_v_chebyshev(a,
+ Upsilon0::Array{Float64,1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
out=0.
for zetap in 0:J-1
for j in 1:N
@@ -107,13 +166,28 @@ end
return out
end
# <1_nv>
-@everywhere function avg_one_v_chebyshev(n,zetap,Upsilon0,k,taus,weights,N)
+@everywhere function avg_one_v_chebyshev(
+ n::Int64,
+ zetap::Int64,
+ Upsilon0::Array{Float64,1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64
+)
xj=weights[1][n]
return (taus[zetap+2]-taus[zetap+1])/(32*pi)*weights[2][n]*cos(pi*xj/2)*(1+k[zetap*N+n])^2*k[zetap*N+n]*Upsilon0[zetap*N+n]
end
# compute \int dq dxi u1(k-xi)u2(q)u3(xi)u4(k-q)u5(xi-q)
-@everywhere function double_conv_S_chebyshev(FU1,FU2,FU3,FU4,FU5,Abar)
+@everywhere function double_conv_S_chebyshev(
+ FU1::Array{Float64,1},
+ FU2::Array{Float64,1},
+ FU3::Array{Float64,1},
+ FU4::Array{Float64,1},
+ FU5::Array{Float64,1},
+ Abar::Array{Float64,5}
+)
out=zeros(Float64,length(Abar))
for i in 1:length(Abar)
for j1 in 1:length(FU1)
@@ -133,7 +207,17 @@ end
# compute A
-@everywhere function Amat(k,weights,taus,T,P,N,J,nua,nub)
+@everywhere function Amat(
+ k::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nua::Int64,
+ nub::Int64
+)
out=Array{Array{Float64,2},1}(undef,J*N)
for i in 1:J*N
out[i]=zeros(Float64,J*(P+1),J*(P+1))
@@ -152,7 +236,11 @@ end
end
# compute Upsilon
-@everywhere function Upsilonmat(k,v,weights)
+@everywhere function Upsilonmat(
+ k::Array{Float64,1},
+ v::Function,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
out=Array{Array{Float64,1},1}(undef,length(k))
for i in 1:length(k)
out[i]=Array{Float64,1}(undef,length(k))
@@ -162,7 +250,11 @@ end
end
return out
end
-@everywhere function Upsilon0mat(k,v,weights)
+@everywhere function Upsilon0mat(
+ k::Array{Float64,1},
+ v::Function,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
out=Array{Float64,1}(undef,length(k))
for j in 1:length(k)
out[j]=2*k[j]*v(k[j])
@@ -171,17 +263,36 @@ end
end
# alpha_-
-@everywhere function alpham(k,t)
+@everywhere function alpham(
+ k::Float64,
+ t::Float64
+)
return (1-k-(1-t)/(1+t))/(1+k+(1-t)/(1+t))
end
# alpha_+
-@everywhere function alphap(k,t)
+@everywhere function alphap(
+ k::Float64,
+ t::Float64
+)
return (1-abs(k-(1-t)/(1+t)))/(1+abs(k-(1-t)/(1+t)))
end
# compute \bar A
-@everywhere function barAmat(k,weights,taus,T,P,N,J,nu1,nu2,nu3,nu4,nu5)
+@everywhere function barAmat(
+ k::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu1::Int64,
+ nu2::Int64,
+ nu3::Int64,
+ nu4::Int64,
+ nu5::Int64
+)
out=zeros(Float64,J*(P+1),J*(P+1),J*(P+1),J*(P+1),J*(P+1))
for zeta1 in 0:J-1
for n1 in 0:P
@@ -211,27 +322,107 @@ end
return out
end
-@everywhere function barAmat_int1(tau,k,taus,T,weights,nu1,nu2,nu3,nu4,nu5,zeta1,zeta2,zeta3,zeta4,zeta5,n1,n2,n3,n4,n5)
+@everywhere function barAmat_int1(tau,
+ k::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu1::Int64,
+ nu2::Int64,
+ nu3::Int64,
+ nu4::Int64,
+ nu5::Int64,
+ zeta1::Int64,
+ zeta2::Int64,
+ zeta3::Int64,
+ zeta4::Int64,
+ zeta5::Int64,
+ n1::Int64,
+ n2::Int64,
+ n3::Int64,
+ n4::Int64,
+ n5::Int64
+)
if(alpham(k,tau)<taus[zeta2+2] && alphap(k,tau)>taus[zeta2+1])
return 2*(1-tau)/(1+tau)^(3-nu1)*T[n1+1]((2*tau-(taus[zeta1+1]+taus[zeta1+2]))/(taus[zeta1+2]-taus[zeta1+1]))*integrate_legendre(sigma->barAmat_int2(tau,sigma,k,taus,T,weights,nu2,nu3,nu4,nu5,zeta2,zeta3,zeta4,zeta5,n2,n3,n4,n5),max(taus[zeta2+1],alpham(k,tau)),min(taus[zeta2+2],alphap(k,tau)),weights)
else
return 0.
end
end
-@everywhere function barAmat_int2(tau,sigma,k,taus,T,weights,nu2,nu3,nu4,nu5,zeta2,zeta3,zeta4,zeta5,n2,n3,n4,n5)
+@everywhere function barAmat_int2(tau,
+ sigma::Float64,
+ k::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu2::Int64,
+ nu3::Int64,
+ nu4::Int64,
+ nu5::Int64,
+ zeta2::Int64,
+ zeta3::Int64,
+ zeta4::Int64,
+ zeta5::Int64,
+ n2::Int64,
+ n3::Int64,
+ n4::Int64,
+ n5::Int64
+)
return 2*(1-sigma)/(1+sigma)^(3-nu2)*T[n2+1]((2*sigma-(taus[zeta2+1]+taus[zeta2+2]))/(taus[zeta2+2]-taus[zeta2+1]))*integrate_legendre(taup->barAmat_int3(tau,sigma,taup,k,taus,T,weights,nu3,nu4,nu5,zeta3,zeta4,zeta5,n3,n4,n5),taus[zeta3+1],taus[zeta3+2],weights)
end
-@everywhere function barAmat_int3(tau,sigma,taup,k,taus,T,weights,nu3,nu4,nu5,zeta3,zeta4,zeta5,n3,n4,n5)
+@everywhere function barAmat_int3(tau,
+ sigma::Float64,
+ taup::Float64,
+ k::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu3::Int64,
+ nu4::Int64,
+ nu5::Int64,
+ zeta3::Int64,
+ zeta4::Int64,
+ zeta5::Int64,
+ n3::Int64,
+ n4::Int64,
+ n5::Int64
+)
if(alpham(k,taup)<taus[zeta4+2] && alphap(k,taup)>taus[zeta4+1])
return 2*(1-taup)/(1+taup)^(3-nu3)*T[n3+1]((2*taup-(taus[zeta3+1]+taus[zeta3+2]))/(taus[zeta3+2]-taus[zeta3+1]))*integrate_legendre(sigmap->barAmat_int4(tau,sigma,taup,sigmap,k,taus,T,weights,nu4,nu5,zeta4,zeta5,n4,n5),max(taus[zeta4+1],alpham(k,taup)),min(taus[zeta4+2],alphap(k,taup)),weights)
else
return 0.
end
end
-@everywhere function barAmat_int4(tau,sigma,taup,sigmap,k,taus,T,weights,nu4,nu5,zeta4,zeta5,n4,n5)
+@everywhere function barAmat_int4(tau,
+ sigma::Float64,
+ taup::Float64,
+ sigmap::Float64,
+ k::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu4::Int64,
+ nu5::Int64,
+ zeta4::Int64,
+ zeta5::Int64,
+ n4::Int64,
+ n5::Int64
+)
return 2*(1-sigmap)/(1+sigmap)^(3-nu4)*T[n4+1]((2*sigma-(taus[zeta4+1]+taus[zeta4+2]))/(taus[zeta4+2]-taus[zeta4+1]))*integrate_legendre(theta->barAmat_int5(tau,sigma,taup,sigmap,theta,k,taus,T,weights,nu5,zeta5,n5),0.,2*pi,weights)
end
-@everywhere function barAmat_int5(tau,sigma,taup,sigmap,theta,k,taus,T,weights,nu5,zeta5,n5)
+@everywhere function barAmat_int5(tau,
+ sigma::Float64,
+ taup::Float64,
+ sigmap::Float64,
+ theta::Float64,
+ k::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu5::Int64,
+ zeta5::Int64,
+ n5::Int64
+)
R=barAmat_R((1-sigma)/(1+sigma),(1-tau)/(1+tau),(1-sigmap)/(1+sigmap),(1-taup)/(1+taup),theta,k)
if((1-R)/(1+R)<taus[zeta5+2] && (1-R)/(1+R)>taus[zeta5+1])
return (2/(2+R))^nu5*T[n5+1]((2*(1-R)/(1+R)-(taus[zeta5+1]+taus[zeta5+2]))/(taus[zeta5+2]-taus[zeta5+1]))
@@ -240,13 +431,22 @@ end
end
end
# R(s,t,s',t,theta,k)
-@everywhere function barAmat_R(s,t,sp,tp,theta,k)
- return sqrt(k^2*(s^2+t^2+sp^2+tp^2)-k^4-(s^2-t^2)*(sp^2-tp^2)-sqrt((4*k^2*s^2-(k^2+s^2-t^2)^2)*(4*k^2*sp^2-(k^2+sp^2-tp^2)^2))*cos(theta))/(sqrt(2)*k)
+@everywhere function barAmat_R(
+ s::Float64,
+ t::Float64,
+ sp::Float64,
+ tp::Float64,
+ theta::Float64,
+ k::Float64
+)
+ return sqrt(k^2*(s^2+t^2+sp^2+tp^2)-k^4-(s^2-t^2)*(sp^2-tp^2)-sqrt((4*k^2*s^2-(k^2+s^2-t^2)^2)*(4*k^2*sp^2-(k^2+sp^2-tp^2)^2))*cos(theta))/(sqrt(2.)*k)
end
# compute Chebyshev polynomials
-@everywhere function chebyshev_polynomials(P)
- T=Array{Polynomial}(undef,P+1)
+@everywhere function chebyshev_polynomials(
+ P::Int64
+)
+ T=Array{Polynomial,1}(undef,P+1)
T[1]=Polynomial([1])
T[2]=Polynomial([0,1])
for n in 1:P-1
@@ -258,7 +458,15 @@ end
end
# compute \int f*u dk/(2*pi)^3
-@everywhere function integrate_f_chebyshev(f,u,k,taus,weights,N,J)
+@everywhere function integrate_f_chebyshev(
+ f::Function,
+ u::Array{Float64,1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
out=0.
for zeta in 0:J-1
for i in 1:N
@@ -268,7 +476,15 @@ end
return out
end
-@everywhere function inverse_fourier_chebyshev(u,x,k,taus,weights,N,J)
+@everywhere function inverse_fourier_chebyshev(
+ u::Array{Float64,1},
+ x::Float64,
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
out=0.
for zeta in 0:J-1
for j in 1:N
@@ -277,3 +493,54 @@ end
end
return out
end
+
+# compute B (for the computation of the fourier transform of the two-point correlation)
+@everywhere function Bmat(
+ q::Float64,
+ k::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Array{Float64,1},1}(undef,J*N)
+ for i in 1:J*N
+ out[i]=zeros(Float64,J*(P+1))
+ for zeta in 0:J-1
+ for n in 0:P
+ out[i][zeta*(P+1)+n+1]=1/(8*pi^3*k[i]*q)*(betam(k[i],q)>taus[zeta+2] || betap(k[i],q)<taus[zeta+1] ? 0. : integrate_legendre(sigma->(1-sigma)/(1+sigma)^(3-nu)*T[n+1]((2*sigma-(taus[zeta+1]+taus[zeta+2]))/(taus[zeta+2]-taus[zeta+1])),max(taus[zeta+1],betam(k[i],q)),min(taus[zeta+2],betap(k[i],q)),weights))
+ end
+ end
+ end
+
+ return out
+end
+# beta_-
+@everywhere function betam(
+ k::Float64,
+ q::Float64
+)
+ return (1-k-q)/(1+k+q)
+end
+# beta_+
+@everywhere function betap(
+ k::Float64,
+ q::Float64
+)
+ return (1-abs(k-q))/(1+abs(k-q))
+end
+
+# mathfrak S (for the computation of the fourier transform of the two-point correlation)
+@everywhere function chebyshev_frakS(
+ Ff::Array{Float64,1},
+ B::Array{Array{Float64,1},1}
+)
+ out=zeros(Float64,length(B))
+ for i in 1:length(B)
+ out[i]=dot(Ff,B[i])
+ end
+ return out
+end
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 q<kmin || q>kmax
+ 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(err<tolerance)
@@ -176,15 +636,23 @@ end
end
# \Eta
-@everywhere function easyeq_H(x,t,weights,v)
- 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)
+@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
diff --git a/src/integration.jl b/src/integration.jl
index 9be4641..223d6cc 100644
--- a/src/integration.jl
+++ b/src/integration.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.
@@ -13,7 +13,12 @@
## limitations under the License.
# approximate \int_a^b f using Gauss-Legendre quadratures
-@everywhere function integrate_legendre(f,a,b,weights)
+@everywhere function integrate_legendre(
+ f::Function,
+ a::Float64,
+ b::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
out=0
for i in 1:length(weights[1])
out+=(b-a)/2*weights[2][i]*f((b-a)/2*weights[1][i]+(b+a)/2)
@@ -21,7 +26,13 @@
return out
end
# \int f*g where g is sampled at the Legendre nodes
-@everywhere function integrate_legendre_sampled(f,g,a,b,weights)
+@everywhere function integrate_legendre_sampled(
+ f::Function,
+ g::Array{Float64,1},
+ a::Float64,
+ b::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
out=0
for i in 1:length(weights[1])
out+=(b-a)/2*weights[2][i]*f((b-a)/2*weights[1][i]+(b+a)/2)*g[i]
@@ -31,7 +42,12 @@ end
# approximate \int_a^b f/sqrt((b-x)(x-a)) using Gauss-Chebyshev quadratures
-@everywhere function integrate_chebyshev(f,a,b,N)
+@everywhere function integrate_chebyshev(
+ f::Function,
+ a::Float64,
+ b::Float64,
+ N::Int64
+)
out=0
for i in 1:N
out=out+pi/N*f((b-a)/2*cos((2*i-1)/(2*N)*pi)+(b+a)/2)
@@ -40,7 +56,11 @@ end
end
# approximate \int_0^\infty dr f(r)*exp(-a*r) using Gauss-Chebyshev quadratures
-@everywhere function integrate_laguerre(f,a,weights_gL)
+@everywhere function integrate_laguerre(
+ f::Function,
+ a::Float64,
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}}
+)
out=0.
for i in 1:length(weights_gL[1])
out+=1/a*f(weights_gL[1][i]/a)*weights_gL[2][i]
@@ -49,10 +69,28 @@ end
end
# Hann window
-@everywhere function hann(x,L)
+@everywhere function hann(
+ x::Float64,
+ L::Float64
+)
if abs(x)<L/2
return cos(pi*x/L)^2
else
return 0.
end
end
+# Fourier transform (in 3d)
+@everywhere function hann_fourier(
+ k::Float64,
+ L::Float64
+)
+ return L^2*4*pi^3/k*(((k*L)^3-4*k*L*pi^2)*cos(k*L/2)-2*(3*(k*L)^2-4*pi^2)*sin(k*L/2))/((k*L)^3-4*k*L*pi^2)^2
+end
+
+# normalized Gaussian (in 3d)
+@everywhere function gaussian(
+ k::Float64,
+ L::Float64
+)
+ return exp(-k^2/(2*L))/sqrt(8*pi^3*L^3)
+end
diff --git a/src/interpolation.jl b/src/interpolation.jl
index fa3bcdb..066bc20 100644
--- a/src/interpolation.jl
+++ b/src/interpolation.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.
@@ -14,7 +14,11 @@
# linear interpolation: given vectors x,y, compute a linear interpolation for y(x0)
# assume x is ordered
-@everywhere function linear_interpolation(x0,x,y)
+@everywhere function linear_interpolation(
+ x0::Float64,
+ x::Array{Float64,1},
+ y::Array{Float64,1}
+)
# if x0 is beyond all x's, then return the corresponding boundary value.
if x0>x[length(x)]
return y[length(y)]
@@ -28,7 +32,12 @@
# interpolate
return y[i]+(y[i+1]-y[i])*(x0-x[i])/(x[i+1]-x[i])
end
-@everywhere function bracket(x0,x,a,b)
+@everywhere function bracket(
+ x0::Float64,
+ x::Array{Float64,1},
+ a::Int64,
+ b::Int64
+)
i=floor(Int64,(a+b)/2)
if x0<x[i]
return bracket(x0,x,a,i)
@@ -41,15 +50,18 @@ end
# polynomial interpolation of a family of points
-@everywhere function poly_interpolation(x,y)
+@everywhere function poly_interpolation(
+ x::Array{Float64,1},
+ y::Array{Float64,1}
+)
# init for recursion
- rec=Array{Polynomial{Float64}}(undef,length(x))
+ rec=Array{Polynomial{Float64},1}(undef,length(x))
for i in 1:length(x)
rec[i]=Polynomial([1.])
end
# compute \prod (x-x_i)
- poly_interpolation_rec(rec,x,1,length(x))
+ poly_interpolation_rec(rec,x,1.,length(x))
# sum terms together
out=0.
@@ -60,7 +72,12 @@ end
return out
end
# recursive helper function
-@everywhere function poly_interpolation_rec(out,x,a,b)
+@everywhere function poly_interpolation_rec(
+ out::Array{Float64,1},
+ x::Array{Float64,1},
+ a::Float64,
+ b::Float64
+)
if a==b
return
end
@@ -91,7 +108,10 @@ end
return
end
## the following does the same, but has complexity N^2, the function above has N*log(N)
-#@everywhere function poly_interpolation(x,y)
+#@everywhere function poly_interpolation(
+# x::Array{Float64,1},
+# y::Array{Float64,1}
+#)
# out=Polynomial([0.])
# for i in 1:length(x)
# prod=Polynomial([1.])
diff --git a/src/main.jl b/src/main.jl
index 382fe6b..28fc2be 100644
--- a/src/main.jl
+++ b/src/main.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.
@@ -22,6 +22,8 @@ include("chebyshev.jl")
include("integration.jl")
include("interpolation.jl")
include("tools.jl")
+include("multithread.jl")
+include("optimization.jl")
include("potentials.jl")
include("print.jl")
include("easyeq.jl")
@@ -36,9 +38,6 @@ function main()
rho=1e-6
e=1e-4
- # incrementally initialize Newton algorithm
- nlrho_init=1
-
# potential
v=k->v_exp(k,1.)
a0=a0_exp(1.)
@@ -49,19 +48,29 @@ function main()
v_param_e=1.
# plot range when plotting in rho
- minlrho=-6
- maxlrho=2
+ # linear
+ minrho=1e-6
+ maxrho=1e2
+ nrho=0
+ # logarithmic
+ minlrho=-6.
+ maxlrho=2.
nlrho=100
- rhos=Array{Float64}(undef,0)
+ # list
+ rhos=Array{Float64,1}(undef,0)
# plot range when plotting in e
- minle=-6
- maxle=2
+ minle=-6.
+ maxle=2.
nle=100
- es=Array{Float64}(undef,0)
+ es=Array{Float64,1}(undef,0)
# plot range when plotting in x
- xmin=0
- xmax=100
+ xmin=0.
+ xmax=100.
nx=100
+ # plot range when plotting in k
+ kmin=0.
+ kmax=10.
+ nk=100
# cutoffs
tolerance=1e-11
@@ -77,8 +86,8 @@ function main()
J=10
# starting rho from which to incrementally initialize Newton algorithm
- # default must be set after reading rho, if not set explicitly
- minlrho_init=nothing
+ minlrho_init=-6.
+ nlrho_init=0
# Hann window for Fourier transforms
windowL=1e3
@@ -98,6 +107,18 @@ function main()
anyeq_compleq_approx=Anyeq_approx(1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.)
anyeq_approx=anyeq_bigeq_approx
+ # numerical approximations of derivatives
+ dx=1e-7
+ dk=1e-7
+
+ # initial guess for 2pt_max
+ x0=1.
+ k0=1.
+ # maximum step in 2pt_max
+ maxstep=Inf
+ # tolerance for max search
+ tolerance_max=Inf
+
# read cli arguments
(params,potential,method,savefile,command)=read_args(ARGS)
@@ -109,8 +130,8 @@ function main()
print(stderr,"error: could not read parameter '",param,"'.\n")
exit(-1)
end
- lhs=terms[1]
- rhs=terms[2]
+ lhs=string(terms[1])
+ rhs=string(terms[2])
if lhs=="rho"
rho=parse(Float64,rhs)
elseif lhs=="minlrho_init"
@@ -133,6 +154,12 @@ function main()
maxlrho=parse(Float64,rhs)
elseif lhs=="nlrho"
nlrho=parse(Int64,rhs)
+ elseif lhs=="minrho"
+ minrho=parse(Float64,rhs)
+ elseif lhs=="maxrho"
+ maxrho=parse(Float64,rhs)
+ elseif lhs=="nrho"
+ nrho=parse(Int64,rhs)
elseif lhs=="es"
es=parse_list(rhs)
elseif lhs=="minle"
@@ -147,6 +174,12 @@ function main()
xmax=parse(Float64,rhs)
elseif lhs=="nx"
nx=parse(Int64,rhs)
+ elseif lhs=="kmin"
+ kmin=parse(Float64,rhs)
+ elseif lhs=="kmax"
+ kmax=parse(Float64,rhs)
+ elseif lhs=="nk"
+ nk=parse(Int64,rhs)
elseif lhs=="P"
P=parse(Int64,rhs)
elseif lhs=="N"
@@ -155,6 +188,18 @@ function main()
J=parse(Int64,rhs)
elseif lhs=="window_L"
windowL=parse(Float64,rhs)
+ elseif lhs=="dx"
+ dx=parse(Float64,rhs)
+ elseif lhs=="x0"
+ x0=parse(Float64,rhs)
+ elseif lhs=="dk"
+ dk=parse(Float64,rhs)
+ elseif lhs=="k0"
+ k0=parse(Float64,rhs)
+ elseif lhs=="maxstep"
+ maxstep=parse(Float64,rhs)
+ elseif lhs=="tolerance_max"
+ tolerance_max=parse(Float64,rhs)
elseif lhs=="aK"
anyeq_approx.aK=parse(Float64,rhs)
elseif lhs=="bK"
@@ -242,37 +287,48 @@ function main()
## set parameters
# rhos
if length(rhos)==0
- rhos=Array{Float64}(undef,nlrho)
- for j in 0:nlrho-1
- rhos[j+1]=(nlrho==1 ? 10^minlrho : 10^(minlrho+(maxlrho-minlrho)/(nlrho-1)*j))
+ # linear only if nrho is specified
+ if nrho>0
+ rhos=Array{Float64,1}(undef,nrho)
+ for j in 0:nrho-1
+ rhos[j+1]=(nrho==1 ? minrho : minrho+(maxrho-minrho)/(nrho-1)*j)
+ end
+ else
+ rhos=Array{Float64,1}(undef,nlrho)
+ for j in 0:nlrho-1
+ rhos[j+1]=(nlrho==1 ? 10^minlrho : 10^(minlrho+(maxlrho-minlrho)/(nlrho-1)*j))
+ end
end
end
+
# es
if length(es)==0
- es=Array{Float64}(undef,nle)
+ es=Array{Float64,1}(undef,nle)
for j in 0:nle-1
es[j+1]=(nle==1 ? 10^minle : 10^(minle+(maxle-minle)/(nle-1)*j))
end
end
- # default minlrho_init
- if (minlrho_init==nothing)
- minlrho_init=log10(rho)
- end
-
# splines
- taus=Array{Float64}(undef,J+1)
+ taus=Array{Float64,1}(undef,J+1)
for j in 0:J
taus[j+1]=-1+2*j/J
end
+ # tolerance_max
+ if tolerance_max==Inf
+ tolerance_max=tolerance
+ end
+
## run command
- if method=="easyeq"
+ if command=="scattering_length"
+ @printf("% .15e\n",a0)
+ elseif method=="easyeq"
if command=="energy"
easyeq_energy(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,easyeq_approx)
# e(rho)
elseif command=="energy_rho"
- easyeq_energy_rho(rhos,order,a0,v,maxiter,tolerance,easyeq_approx)
+ easyeq_energy_rho(rhos,minlrho_init,nlrho_init,order,a0,v,maxiter,tolerance,easyeq_approx)
# u(k)
elseif command=="uk"
easyeq_uk(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,easyeq_approx)
@@ -285,7 +341,28 @@ function main()
elseif command=="condensate_fraction"
easyeq_condensate_fraction(minlrho_init,nlrho_init,order,rho,a0,v,maxiter,tolerance,easyeq_approx)
elseif command=="condensate_fraction_rho"
- easyeq_condensate_fraction_rho(rhos,order,a0,v,maxiter,tolerance,easyeq_approx)
+ easyeq_condensate_fraction_rho(rhos,minlrho_init,nlrho_init,order,a0,v,maxiter,tolerance,easyeq_approx)
+ # 2pt correlation
+ elseif command=="2pt"
+ easyeq_2pt(xmin,xmax,nx,minlrho_init,nlrho_init,order,windowL,rho,a0,v,maxiter,tolerance,easyeq_approx)
+ # max of 2pt correlation
+ elseif command=="2pt_max"
+ easyeq_2pt_max(dx,x0,minlrho_init,nlrho_init,order,windowL,rho,a0,v,maxstep,maxiter,tolerance,tolerance_max,easyeq_approx)
+ # max of 2pt correlation as a function of rho
+ elseif command=="2pt_max_rho"
+ easyeq_2pt_max_rho(rhos,dx,x0,minlrho_init,nlrho_init,order,windowL,a0,v,maxstep,maxiter,tolerance,tolerance_max,easyeq_approx)
+ # fourier transform of 2pt correlation
+ elseif command=="2pt_fourier"
+ easyeq_2pt_fourier(kmin,kmax,nk,minlrho_init,nlrho_init,order,windowL,rho,a0,v,maxiter,tolerance,easyeq_approx)
+ # max of fourier transform of 2pt correlation
+ elseif command=="2pt_fourier_max"
+ easyeq_2pt_fourier_max(dk,k0,minlrho_init,nlrho_init,order,windowL,rho,a0,v,maxstep,maxiter,tolerance,tolerance_max,easyeq_approx)
+ # max of 2pt correlation as a function of rho
+ elseif command=="2pt_fourier_max_rho"
+ easyeq_2pt_fourier_max_rho(rhos,dk,k0,minlrho_init,nlrho_init,order,windowL,a0,v,maxstep,maxiter,tolerance,tolerance_max,easyeq_approx)
+ # momentum distribution
+ elseif command=="momentum_distribution"
+ easyeq_momentum_distribution(kmin,kmax,minlrho_init,nlrho_init,order,windowL,rho,a0,v,maxiter,tolerance,easyeq_approx)
else
print(stderr,"unrecognized command '",command,"'.\n")
exit(-1)
@@ -316,7 +393,7 @@ function main()
anyeq_energy(rho,minlrho_init,nlrho_init,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
# e(rho)
elseif command=="energy_rho"
- anyeq_energy_rho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
+ anyeq_energy_rho(rhos,minlrho_init,nlrho_init,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
elseif command=="energy_rho_init_prevrho"
anyeq_energy_rho_init_prevrho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
elseif command=="energy_rho_init_nextrho"
@@ -331,12 +408,29 @@ function main()
elseif command=="condensate_fraction"
anyeq_condensate_fraction(rho,minlrho_init,nlrho_init,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
elseif command=="condensate_fraction_rho"
- anyeq_condensate_fraction_rho(rhos,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
+ anyeq_condensate_fraction_rho(rhos,minlrho_init,nlrho_init,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
# momentum distribution
elseif command=="momentum_distribution"
- anyeq_momentum_distribution(rho,minlrho_init,nlrho_init,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
+ anyeq_momentum_distribution(kmin,kmax,rho,minlrho_init,nlrho_init,taus,P,N,J,windowL,a0,v,maxiter,tolerance,anyeq_approx,savefile)
elseif command=="2pt"
anyeq_2pt_correlation(minlrho_init,nlrho_init,taus,P,N,J,windowL,rho,a0,v,maxiter,tolerance,xmin,xmax,nx,anyeq_approx,savefile)
+ elseif command=="2pt_max"
+ anyeq_2pt_correlation_max(rho,minlrho_init,nlrho_init,dx,x0,maxstep,taus,P,N,J,windowL,a0,v,maxiter,tolerance,tolerance_max,anyeq_approx,savefile)
+ elseif command=="2pt_max_rho"
+ anyeq_2pt_correlation_max_rho(rhos,minlrho_init,nlrho_init,dx,x0,maxstep,taus,P,N,J,windowL,a0,v,maxiter,tolerance,tolerance_max,anyeq_approx,savefile)
+ elseif command=="2pt_fourier"
+ anyeq_2pt_correlation_fourier(minlrho_init,nlrho_init,taus,P,N,J,windowL,rho,a0,v,maxiter,tolerance,kmin,kmax,nk,anyeq_approx,savefile)
+ elseif command=="2pt_fourier_test"
+ anyeq_2pt_correlation_fourier_test(minlrho_init,nlrho_init,taus,P,N,J,windowL,rho,a0,v,maxiter,tolerance,xmax,kmin,kmax,nk,anyeq_approx,savefile)
+ elseif command=="2pt_fourier_max"
+ anyeq_2pt_correlation_fourier_max(rho,minlrho_init,nlrho_init,dk,k0,maxstep,taus,P,N,J,windowL,a0,v,maxiter,tolerance,tolerance_max,anyeq_approx,savefile)
+ elseif command=="2pt_fourier_max_rho"
+ anyeq_2pt_correlation_fourier_max_rho(rhos,minlrho_init,nlrho_init,dk,k0,maxstep,taus,P,N,J,windowL,a0,v,maxiter,tolerance,tolerance_max,anyeq_approx,savefile)
+ elseif command=="uncondensed_2pt"
+ anyeq_uncondensed_2pt_correlation(minlrho_init,nlrho_init,taus,P,N,J,windowL,rho,a0,v,maxiter,tolerance,xmin,xmax,nx,anyeq_approx,savefile)
+ # compressibility
+ elseif command=="compressibility_rho"
+ anyeq_compressibility_rho(rhos,minlrho_init,nlrho_init,taus,P,N,J,a0,v,maxiter,tolerance,anyeq_approx,savefile)
else
print(stderr,"unrecognized command: '",command,"'\n")
exit(-1)
@@ -360,9 +454,11 @@ function main()
end
# parse a comma separated list as an array of Float64
-function parse_list(str)
+function parse_list(
+ str::String
+)
elems=split(str,",")
- out=Array{Float64}(undef,length(elems))
+ out=Array{Float64,1}(undef,length(elems))
for i in 1:length(elems)
out[i]=parse(Float64,elems[i])
end
@@ -370,7 +466,9 @@ function parse_list(str)
end
# read cli arguments
-function read_args(ARGS)
+function read_args(
+ ARGS
+)
# flag
flag=""
diff --git a/src/multithread.jl b/src/multithread.jl
new file mode 100644
index 0000000..f61cdd7
--- /dev/null
+++ b/src/multithread.jl
@@ -0,0 +1,16 @@
+# split up 1...n among workers
+function spawn_workers(n::Int64)
+ # number of workers
+ nw=nworkers()
+ # split jobs among workers
+ work=Array{Array{Int64,1},1}(undef,nw)
+ # init empty arrays
+ for p in 1:nw
+ work[p]=Int64[]
+ end
+ for i in 1:n
+ append!(work[(i-1)%nw+1],[i])
+ end
+
+ return work
+end
diff --git a/src/optimization.jl b/src/optimization.jl
new file mode 100644
index 0000000..bacead7
--- /dev/null
+++ b/src/optimization.jl
@@ -0,0 +1,94 @@
+# gradient descent: find local minimum of function of one variable from initial guess
+# numerically estimate the derivative
+@everywhere function gradient_descent(
+ f::Function,
+ x0::Float64,
+ delta::Float64, # shift is delta*df
+ dx::Float64, # finite difference for numerical derivative evaluation
+ maxiter::Int64 # interrupt and fail after maxiter steps
+)
+ counter=0
+
+ # init
+ x=x0
+
+ while counter<maxiter
+ # value at x and around
+ val=f(x)
+ valm=f(x-dx)
+ valp=f(x+dx)
+ # quit if minimum
+ if(val<valm && val<valp)
+ return(x,val)
+ end
+
+ # derivative
+ df=(valp-val)/dx
+ # step
+ x=x-delta*df
+ counter+=1
+ end
+
+ # fail
+ return(Inf,Inf)
+end
+
+# Newton algorithm to compute extrema
+# numerically estimate the derivatives
+@everywhere function newton_maximum(
+ f::Function,
+ x0::Float64,
+ dx::Float64, # finite difference for numerical derivative evaluation
+ maxiter::Int64,
+ tolerance::Float64,
+ maxstep::Float64 # maximal size of step
+)
+ counter=0
+
+ # init
+ x=x0
+
+ while counter<maxiter
+ # value at x and around
+ val=f(x)
+ valm=f(x-dx)
+ valp=f(x+dx)
+
+ # derivative
+ dfp=(valp-val)/dx
+ dfm=(val-valm)/dx
+ # second derivative
+ ddf=(dfp-dfm)/dx
+
+ #@printf(stderr,"% .15e % .15e % .15e % .15e\n",x,val,dfp,ddf)
+
+ if abs(dfp/ddf)<tolerance
+ # check it is a local maximum
+ if ddf<0
+ return(x,val)
+ else
+ return(Inf,Inf)
+ end
+ end
+
+ # step
+ step=dfp/abs(ddf)
+
+ # step too large
+ if abs(step)>maxstep
+ step=maxstep*sign(step)
+ end
+
+ x=x+step
+
+ # fail if off to infinity
+ if x==Inf || x==-Inf
+ return(x,val)
+ end
+ counter+=1
+ end
+
+ # fail
+ return(Inf,Inf)
+end
+
diff --git a/src/potentials.jl b/src/potentials.jl
index 46cafc0..b480db0 100644
--- a/src/potentials.jl
+++ b/src/potentials.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.
@@ -13,10 +13,15 @@
## limitations under the License.
# exponential potential in 3 dimensions
-@everywhere function v_exp(k,a)
+@everywhere function v_exp(
+ k::Float64,
+ a::Float64
+)
return 8*pi/(1+k^2)^2*a
end
-@everywhere function a0_exp(a)
+@everywhere function a0_exp(
+ a::Float64
+)
if a>0.
return log(a)+2*MathConstants.eulergamma+2*besselk(0,2*sqrt(a))/besseli(0,2*sqrt(a))
elseif a<0.
@@ -27,15 +32,24 @@ end
end
# exp(-x)-a*exp(-b*x) in 3 dimensions
-@everywhere function v_expcry(k,a,b)
+@everywhere function v_expcry(
+ k::Float64,
+ a::Float64,
+ b::Float64
+)
return 8*pi*((1+k^2)^(-2)-a*b*(b^2+k^2)^(-2))
end
-@everywhere function a0_expcry(a,b)
+@everywhere function a0_expcry(
+ a::Float64,
+ b::Float64
+)
return 1.21751642717932720441274114683413710125487579284827462 #ish
end
# x^2*exp(-|x|) in 3 dimensions
-@everywhere function v_npt(k)
+@everywhere function v_npt(
+ k::Float64
+)
return 96*pi*(1-k^2)/(1+k^2)^4
end
@everywhere function a0_npt()
@@ -43,7 +57,9 @@ end
end
# 1/(1+x^4/4) potential in 3 dimensions
-@everywhere function v_alg(k)
+@everywhere function v_alg(
+ k::Float64
+)
if(k==0)
return 4*pi^2
else
@@ -53,32 +69,50 @@ end
a0_alg=1. #ish
# (1+a x^4)/(1+x^2)^4 potential in 3 dimensions
-@everywhere function v_algwell(k)
+@everywhere function v_algwell(
+ k::Float64
+)
a=4
return pi^2/24*exp(-k)*(a*(k^2-9*k+15)+k^2+3*k+3)
end
a0_algwell=1. #ish
# potential corresponding to the exact solution c/(1+b^2x^2)^2
-@everywhere function v_exact(k,b,c,e)
+@everywhere function v_exact(
+ k::Float64,
+ b::Float64,
+ c::Float64,
+ e::Float64
+)
if k!=0
return 48*pi^2*((18+3*sqrt(c)-(4-3*e/b^2)*c-(1-2*e/b^2)*c^1.5)/(4*(3+sqrt(c))^2*sqrt(c))*exp(-sqrt(1-sqrt(c))*k/b)+(-18+3*sqrt(c)+(4-3*e/b^2)*c-(1-2*e/b^2)*c^1.5)/(4*(3-sqrt(c))^2*sqrt(c))*exp(-sqrt(1+sqrt(c))*k/b)+(1-k/b)/2*exp(-k/b)-c*e/b^2*(3*(9-c)*k/b+8*c)/(8*(9-c)^2)*exp(-2*k/b))/k
else
return 48*pi^2*(-sqrt(1-sqrt(c))/b*(18+3*sqrt(c)-(4-3*e/b^2)*c-(1-2*e/b^2)*c^1.5)/(4*(3+sqrt(c))^2*sqrt(c))-sqrt(1+sqrt(c))/b*(-18+3*sqrt(c)+(4-3*e/b^2)*c-(1-2*e/b^2)*c^1.5)/(4*(3-sqrt(c))^2*sqrt(c))-1/b-c*e/b^2*(27-19*c)/(8*(9-c)^2))
end
end
-@everywhere function a0_exact(b,c,e)
+@everywhere function a0_exact(
+ b::Float64,
+ c::Float64,
+ e::Float64
+)
return 1. #ish
end
# tent potential (convolution of soft sphere with itself): a*pi/12*(2*|x|/b-2)^2*(2*|x|/b+4) for |x|<b
-@everywhere function v_tent(k,a,b)
+@everywhere function v_tent(
+ k::Float64,
+ a::Float64,
+ b::Float64
+)
if k!=0
return (b/2)^3*a*(4*pi*(sin(k*b/2)-k*b/2*cos(k*b/2))/(k*b/2)^3)^2
else
return (b/2)^3*a*(4*pi/3)^2
end
end
-@everywhere function a0_tent(a,b)
+@everywhere function a0_tent(
+ a::Float64,
+ b::Float64
+)
return b #ish
end
diff --git a/src/print.jl b/src/print.jl
index bef1c4d..3587728 100644
--- a/src/print.jl
+++ b/src/print.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.
diff --git a/src/simpleq-Kv.jl b/src/simpleq-Kv.jl
index 8789656..5a6579c 100644
--- a/src/simpleq-Kv.jl
+++ b/src/simpleq-Kv.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.
@@ -13,12 +13,27 @@
## limitations under the License.
# Compute Kv=(-\Delta+v+4e(1-\rho u*))^{-1}v
-function anyeq_Kv(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,xmin,xmax,nx)
+function anyeq_Kv(
+ minlrho::Float64,
+ nlrho::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ xmin::Float64,
+ xmax::Float64,
+ nx::Int64
+)
# init vectors
(weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
+ rhos=Array{Float64,1}(undef,nlrho)
for j in 0:nlrho-1
rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
end
@@ -44,7 +59,17 @@ function anyeq_Kv(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,xmin,xmax,
end
# Compute the condensate fraction for simpleq using Kv
-function simpleq_Kv_condensate_fraction(rhos,taus,P,N,J,a0,v,maxiter,tolerance)
+function simpleq_Kv_condensate_fraction(
+ rhos::Array{Float64,1},
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64
+)
# init vectors
(weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
@@ -67,19 +92,35 @@ function simpleq_Kv_condensate_fraction(rhos,taus,P,N,J,a0,v,maxiter,tolerance)
end
# Compute the two-point correlation function for simpleq using Kv
-function simpleq_Kv_2pt(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,xmin,xmax,nx)
+function simpleq_Kv_2pt(
+ minlrho::Float64,
+ nlrho::Int64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ rho::Float64,
+ a0::Float64,
+ v::Function,
+ maxiter::Int64,
+ tolerance::Float64,
+ xmin::Float64,
+ xmax::Float64,
+ nx::Int64
+)
# init vectors
(weights,T,k,V,V0,A,Upsilon,Upsilon0)=anyeq_init(taus,P,N,J,v)
# compute initial guess from medeq
- rhos=Array{Float64}(undef,nlrho)
+ rhos=Array{Float64,1}(undef,nlrho)
for j in 0:nlrho-1
rhos[j+1]=(nlrho==1 ? rho : 10^(minlrho+(log10(rho)-minlrho)/(nlrho-1)*j))
end
u0s=anyeq_init_medeq(rhos,N,J,k,a0,v,maxiter,tolerance)
u0=u0s[nlrho]
- (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,nothing,Upsilon,Upsilon0,v,maxiter,tolerance,Anyeq_approx(0.,0.,1.,0.,0.,0.,0.,0.,0.,0.,0.))
+ Abar=Array{Float64,5}(undef,0,0,0,0,0)
+ (u,E,error)=anyeq_hatu(u0,P,N,J,rho,a0,weights,k,taus,V,V0,A,Abar,Upsilon,Upsilon0,v,maxiter,tolerance,Anyeq_approx(0.,0.,1.,0.,0.,0.,0.,0.,0.,0.,0.))
# Kv in Fourier space
Kvk=simpleq_Kv_Kvk(u,V,E,rho,Upsilon,k,taus,weights,N,J)
@@ -103,7 +144,18 @@ function simpleq_Kv_2pt(minlrho,nlrho,taus,P,N,J,rho,a0,v,maxiter,tolerance,xmin
end
# Kv
-function simpleq_Kv_Kvk(u,V,E,rho,Upsilon,k,taus,weights,N,J)
+function simpleq_Kv_Kvk(
+ u::Array{Float64,1},
+ V::Array{Float64,1},
+ E::Float64,
+ rho::Float64,
+ Upsilon::Array{Array{Float64,1},1},
+ k::Array{Float64,1},
+ taus::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
# (-Delta+v+4e(1-\rho u*)) in Fourier space
M=Array{Float64,2}(undef,N*J,N*J)
for zetapp in 0:J-1
diff --git a/src/simpleq-hardcore.jl b/src/simpleq-hardcore.jl
index ca64f78..398ac06 100644
--- a/src/simpleq-hardcore.jl
+++ b/src/simpleq-hardcore.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.
@@ -13,28 +13,26 @@
## limitations under the License.
# compute energy as a function of rho
-function simpleq_hardcore_energy_rho(rhos,taus,P,N,J,maxiter,tolerance)
- ## spawn workers
- # number of workers
- nw=nworkers()
- # split jobs among workers
- work=Array{Array{Int64,1},1}(undef,nw)
- # init empty arrays
- for p in 1:nw
- work[p]=zeros(0)
- end
- for j in 1:length(rhos)
- append!(work[j%nw+1],j)
- end
+function simpleq_hardcore_energy_rho(
+ rhos::Array{Float64,1},
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ maxiter::Int64,
+ tolerance::Float64
+)
+ # spawn workers
+ work=spawn_workers(length(rhos))
# initialize vectors
(weights,weights_gL,r,T)=simpleq_hardcore_init(taus,P,N,J)
# initial guess
- u0s=Array{Array{Float64}}(undef,length(rhos))
- e0s=Array{Float64}(undef,length(rhos))
+ u0s=Array{Array{Float64,1}}(undef,length(rhos))
+ e0s=Array{Float64,1}(undef,length(rhos))
for j in 1:length(rhos)
- u0s[j]=Array{Float64}(undef,N*J)
+ u0s[j]=Array{Float64,1}(undef,N*J)
for i in 1:N*J
u0s[j][i]=1/(1+r[i]^2)^2
end
@@ -43,17 +41,17 @@ function simpleq_hardcore_energy_rho(rhos,taus,P,N,J,maxiter,tolerance)
# save result from each task
- us=Array{Array{Float64}}(undef,length(rhos))
- es=Array{Float64}(undef,length(rhos))
- err=Array{Float64}(undef,length(rhos))
+ us=Array{Array{Float64,1}}(undef,length(rhos))
+ es=Array{Float64,1}(undef,length(rhos))
+ err=Array{Float64,1}(undef,length(rhos))
count=0
# for each worker
- @sync for p in 1:nw
+ @sync for p in 1:length(work)
# for each task
@async for j in work[p]
count=count+1
- if count>=nw
+ if count>=length(work)
progress(count,length(rhos),10000)
end
# run the task
@@ -67,12 +65,20 @@ function simpleq_hardcore_energy_rho(rhos,taus,P,N,J,maxiter,tolerance)
end
# compute u(x)
-function simpleq_hardcore_ux(rho,taus,P,N,J,maxiter,tolerance)
+function simpleq_hardcore_ux(
+ rho::Float64,
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ maxiter::Int64,
+ tolerance::Float64
+)
# initialize vectors
(weights,weights_gL,r,T)=simpleq_hardcore_init(taus,P,N,J)
# initial guess
- u0=Array{Float64}(undef,N*J)
+ u0=Array{Float64,1}(undef,N*J)
for i in 1:N*J
u0[i]=1/(1+r[i]^2)^2
end
@@ -86,28 +92,26 @@ function simpleq_hardcore_ux(rho,taus,P,N,J,maxiter,tolerance)
end
# compute condensate fraction as a function of rho
-function simpleq_hardcore_condensate_fraction_rho(rhos,taus,P,N,J,maxiter,tolerance)
- ## spawn workers
- # number of workers
- nw=nworkers()
- # split jobs among workers
- work=Array{Array{Int64,1},1}(undef,nw)
- # init empty arrays
- for p in 1:nw
- work[p]=zeros(0)
- end
- for j in 1:length(rhos)
- append!(work[j%nw+1],j)
- end
+function simpleq_hardcore_condensate_fraction_rho(
+ rhos::Array{Float64,1},
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ maxiter::Int64,
+ tolerance::Float64
+)
+ # spawn workers
+ work=spawn_workers(length(rhos))
# initialize vectors
(weights,weights_gL,r,T)=simpleq_hardcore_init(taus,P,N,J)
# initial guess
- u0s=Array{Array{Float64}}(undef,length(rhos))
- e0s=Array{Float64}(undef,length(rhos))
+ u0s=Array{Array{Float64,1}}(undef,length(rhos))
+ e0s=Array{Float64,1}(undef,length(rhos))
for j in 1:length(rhos)
- u0s[j]=Array{Float64}(undef,N*J)
+ u0s[j]=Array{Float64,1}(undef,N*J)
for i in 1:N*J
u0s[j][i]=1/(1+r[i]^2)^2
end
@@ -116,17 +120,17 @@ function simpleq_hardcore_condensate_fraction_rho(rhos,taus,P,N,J,maxiter,tolera
# save result from each task
- us=Array{Array{Float64}}(undef,length(rhos))
- es=Array{Float64}(undef,length(rhos))
- err=Array{Float64}(undef,length(rhos))
+ us=Array{Array{Float64,1}}(undef,length(rhos))
+ es=Array{Float64,1}(undef,length(rhos))
+ err=Array{Float64,1}(undef,length(rhos))
count=0
# for each worker
- @sync for p in 1:nw
+ @sync for p in 1:length(work)
# for each task
@async for j in work[p]
count=count+1
- if count>=nw
+ if count>=length(work)
progress(count,length(rhos),10000)
end
# run the task
@@ -142,13 +146,18 @@ end
# initialize computation
-@everywhere function simpleq_hardcore_init(taus,P,N,J)
+@everywhere function simpleq_hardcore_init(
+ taus::Array{Float64,1},
+ P::Int64,
+ N::Int64,
+ J::Int64
+)
# Gauss-Legendre weights
weights=gausslegendre(N)
weights_gL=gausslaguerre(N)
# r
- r=Array{Float64}(undef,J*N)
+ r=Array{Float64,1}(undef,J*N)
for zeta in 0:J-1
for j in 1:N
xj=weights[1][j]
@@ -164,9 +173,23 @@ end
end
# compute u using chebyshev expansions
-@everywhere function simpleq_hardcore_hatu(u0,e0,rho,r,taus,T,weights,weights_gL,P,N,J,maxiter,tolerance)
+@everywhere function simpleq_hardcore_hatu(
+ u0::Array{Float64,1},
+ e0::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ maxiter::Int64,
+ tolerance::Float64
+)
# init
- vec=Array{Float64}(undef,J*N+1)
+ vec=Array{Float64,1}(undef,J*N+1)
for i in 1:J*N
vec[i]=u0[i]
end
@@ -194,8 +217,20 @@ end
end
# Xi
-@everywhere function simpleq_hardcore_Xi(u,e,rho,r,taus,T,weights,weights_gL,P,N,J)
- out=Array{Float64}(undef,J*N+1)
+@everywhere function simpleq_hardcore_Xi(
+ u::Array{Float64,1},
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64
+)
+ out=Array{Float64,1}(undef,J*N+1)
FU=chebyshev(u,taus,weights,P,N,J,4)
#D's
@@ -215,7 +250,19 @@ end
return out
end
# DXi
-@everywhere function simpleq_hardcore_DXi(u,e,rho,r,taus,T,weights,weights_gL,P,N,J)
+@everywhere function simpleq_hardcore_DXi(
+ u::Array{Float64,1},
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64
+)
out=Array{Float64,2}(undef,J*N+1,J*N+1)
FU=chebyshev(u,taus,weights,P,N,J,4)
@@ -232,15 +279,15 @@ end
for zetapp in 0:J-1
for n in 1:N
- one=zeros(Int64,J*N)
- one[zetapp*N+n]=1
+ one=zeros(Float64,J*N)
+ one[zetapp*N+n]=1.
Fone=chebyshev(one,taus,weights,P,N,J,4)
for i in 1:J*N
# du/du
out[i,zetapp*N+n]=dot(Fone,d1[i])+2*dot(FU,d2[i]*Fone)-(zetapp*N+n==i ? 1 : 0)
# du/de
- out[i,J*N+1]=(dsed0[i]+dot(FU,dsed1[i])+dot(FU,dsed2[i]*FU))/(2*sqrt(abs(e)))*(e>=0 ? 1 : -1)
+ out[i,J*N+1]=(dsed0[i]+dot(FU,dsed1[i])+dot(FU,dsed2[i]*FU))/(2*sqrt(abs(e)))*(e>=0. ? 1. : -1.)
end
# de/du
out[J*N+1,zetapp*N+n]=2*pi*rho*
@@ -253,14 +300,26 @@ end
#de/de
out[J*N+1,J*N+1]=-1+2*pi*rho*
(2-dsedgamma0(e,rho,weights)-dot(FU,dsedgamma1(e,rho,taus,T,weights,weights_gL,P,J,4))-dot(FU,dsedgamma2(e,rho,taus,T,weights,weights_gL,P,J,4)*FU))/denom/
- (2*sqrt(abs(e)))*(e>=0 ? 1 : -1)
+ (2*sqrt(abs(e)))*(e>=0. ? 1. : -1.)
return out
end
# dXi/dmu
-@everywhere function simpleq_hardcore_dXidmu(u,e,rho,r,taus,T,weights,weights_gL,P,N,J)
- out=Array{Float64}(undef,J*N+1)
+@everywhere function simpleq_hardcore_dXidmu(
+ u::Array{Float64,1},
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64
+)
+ out=Array{Float64,1}(undef,J*N+1)
FU=chebyshev(u,taus,weights,P,N,J,4)
#D's
@@ -281,17 +340,37 @@ end
end
# B's
-@everywhere function B0(r)
+@everywhere function B0(
+ r::Float64
+)
return pi/12*(r-1)^2*(r+5)
end
-@everywhere function B1(r,zeta,n,taus,T,weights,nu)
+@everywhere function B1(
+ r::Float64,
+ zeta::Int64,
+ n::Int64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu::Int64
+)
return (taus[zeta+1]>=(2-r)/r || taus[zeta+2]<=-r/(r+2) ? 0 :
8*pi/(r+1)*integrate_legendre(tau->
(1-(r-(1-tau)/(1+tau))^2)/(1+tau)^(3-nu)*T[n+1]((2*tau-(taus[zeta+1]+taus[zeta+2]))/(taus[zeta+2]-taus[zeta+1])),max(taus[zeta+1],-r/(r+2))
,min(taus[zeta+2],(2-r)/r),weights)
)
end
-@everywhere function B2(r,zeta,n,zetap,m,taus,T,weights,nu)
+@everywhere function B2(
+ r::Float64,
+ zeta::Int64,
+ n::Int64,
+ zetap::Int64,
+ m::Int64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ nu::Int64
+)
return 32*pi/(r+1)*integrate_legendre(tau->
1/(1+tau)^(3-nu)*T[n+1]((2*tau-(taus[zeta+1]+taus[zeta+2]))/(taus[zeta+2]-taus[zeta+1]))*
(taus[zetap+1]>=alphap(abs(r-(1-tau)/(1+tau))-2*tau/(1+tau),tau) || taus[zetap+2]<=alpham(1+r,tau) ? 0 :
@@ -303,30 +382,49 @@ end
end
# D's
-@everywhere function D0(e,rho,r,weights,N,J)
- out=Array{Float64}(undef,J*N)
+@everywhere function D0(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
+ out=Array{Float64,1}(undef,J*N)
for i in 1:J*N
out[i]=exp(-2*sqrt(abs(e))*r[i])/(r[i]+1)+
rho*sqrt(abs(e))/(r[i]+1)*integrate_legendre(s->
(s+1)*B0(s)*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2
- ,0,min(1,r[i]),weights)+
+ ,0.,min(1.,r[i]),weights)+
(r[i]>=1 ? 0 :
rho*sqrt(abs(e))/(2*(r[i]+1))*(1-exp(-4*sqrt(abs(e))*r[i]))*integrate_legendre(s->
(s+r[i]+1)*B0(s+r[i])*exp(-2*sqrt(abs(e))*s)
- ,0,1-r[i],weights)
+ ,0.,1. -r[i],weights)
)
end
return out
end
-@everywhere function D1(e,rho,r,taus,T,weights,weights_gL,P,N,J,nu)
- out=Array{Array{Float64}}(undef,J*N)
+@everywhere function D1(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Array{Float64,1},1}(undef,J*N)
for i in 1:J*N
- out[i]=Array{Float64}(undef,(P+1)*J)
+ out[i]=Array{Float64,1}(undef,(P+1)*J)
for zeta in 0:J-1
for n in 0:P
out[i][zeta*(P+1)+n+1]=rho*sqrt(abs(e))/(r[i]+1)*integrate_legendre(s->
(s+1)*B1(s,zeta,n,taus,T,weights,nu)*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2
- ,0,r[i],weights)+
+ ,0.,r[i],weights)+
rho*sqrt(abs(e))/(2*(r[i]+1))*(1-exp(-4*sqrt(abs(e))*r[i]))*integrate_laguerre(s->
(s+r[i]+1)*B1(s+r[i],zeta,n,taus,T,weights,nu)
,2*sqrt(abs(e)),weights_gL)
@@ -336,7 +434,19 @@ end
return out
end
-@everywhere function D2(e,rho,r,taus,T,weights,weights_gL,P,N,J,nu)
+@everywhere function D2(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Array{Float64,2}}(undef,J*N)
for i in 1:J*N
out[i]=Array{Float64,2}(undef,(P+1)*J,(P+1)*J)
@@ -346,7 +456,7 @@ end
for m in 0:P
out[i][zeta*(P+1)+n+1,zetap*(P+1)+m+1]=rho*sqrt(abs(e))/(r[i]+1)*integrate_legendre(s->
(s+1)*B2(s,zeta,n,zetap,m,taus,T,weights,nu)*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2
- ,0,r[i],weights)+
+ ,0.,r[i],weights)+
rho*sqrt(abs(e))/(2*(r[i]+1))*(1-exp(-4*sqrt(abs(e))*r[i]))*integrate_laguerre(s->
(s+r[i]+1)*B2(s+r[i],zeta,n,zetap,m,taus,T,weights,nu)
,2*sqrt(abs(e)),weights_gL)
@@ -359,28 +469,47 @@ end
end
# dD/d sqrt(abs(e))'s
-@everywhere function dseD0(e,rho,r,weights,N,J)
- out=Array{Float64}(undef,J*N)
+@everywhere function dseD0(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
+ out=Array{Float64,1}(undef,J*N)
for i in 1:J*N
out[i]=-2*r[i]*exp(-2*sqrt(abs(e))*r[i])/(r[i]+1)+
rho/(r[i]+1)*integrate_legendre(s->
(s+1)*B0(s)*((1-2*sqrt(abs(e))*r[i])*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2+2*sqrt(abs(e))*s*(exp(-2*sqrt(abs(e))*(r[i]-s))+exp(-2*sqrt(abs(e))*(r[i]+s)))/2)
- ,0,min(1,r[i]),weights)+
+ ,0.,min(1.,r[i]),weights)+
(r[i]>=1 ? 0 :
- rho/(2*(r[i]+1))*integrate_legendre(s->(s+r[i]+1)*B0(s+r[i])*((1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))*exp(-2*sqrt(abs(e))*s)+4*sqrt(abs(e))*r[i]*exp(-2*sqrt(abs(e))*(2*r[i]+s))),0,1-r[i],weights)
+ rho/(2*(r[i]+1))*integrate_legendre(s->(s+r[i]+1)*B0(s+r[i])*((1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))*exp(-2*sqrt(abs(e))*s)+4*sqrt(abs(e))*r[i]*exp(-2*sqrt(abs(e))*(2*r[i]+s))),0.,1. -r[i],weights)
)
end
return out
end
-@everywhere function dseD1(e,rho,r,taus,T,weights,weights_gL,P,N,J,nu)
- out=Array{Array{Float64}}(undef,J*N)
+@everywhere function dseD1(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Array{Float64,1},1}(undef,J*N)
for i in 1:J*N
- out[i]=Array{Float64}(undef,(P+1)*J)
+ out[i]=Array{Float64,1}(undef,(P+1)*J)
for zeta in 0:J-1
for n in 0:P
out[i][zeta*(P+1)+n+1]=rho/(r[i]+1)*integrate_legendre(s->
(s+1)*B1(s,zeta,n,taus,T,weights,nu)*((1-2*sqrt(abs(e))*r[i])*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2+2*sqrt(abs(e))*s*(exp(-2*sqrt(abs(e))*(r[i]-s))+exp(-2*sqrt(abs(e))*(r[i]+s)))/2)
- ,0,r[i],weights)+
+ ,0.,r[i],weights)+
rho/(2*(r[i]+1))*integrate_laguerre(s->
(s+r[i]+1)*B1(s+r[i],zeta,n,taus,T,weights,nu)*((1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))+4*sqrt(abs(e))*r[i]*exp(-4*sqrt(abs(e))*r[i]))
,2*sqrt(abs(e)),weights_gL)
@@ -389,7 +518,19 @@ end
end
return out
end
-@everywhere function dseD2(e,rho,r,taus,T,weights,weights_gL,P,N,J,nu)
+@everywhere function dseD2(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Array{Float64,2}}(undef,J*N)
for i in 1:J*N
out[i]=Array{Float64,2}(undef,(P+1)*J,(P+1)*J)
@@ -399,7 +540,7 @@ end
for m in 0:P
out[i][zeta*(P+1)+n+1,zetap*(P+1)+m+1]=rho/(r[i]+1)*integrate_legendre(s->
(s+1)*B2(s,zeta,n,zetap,m,taus,T,weights,nu)*((1-2*sqrt(abs(e))*r[i])*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2+2*sqrt(abs(e))*s*(exp(-2*sqrt(abs(e))*(r[i]-s))+exp(-2*sqrt(abs(e))*(r[i]+s)))/2)
- ,0,r[i],weights)+
+ ,0.,r[i],weights)+
rho/(2*(r[i]+1))*integrate_laguerre(s->
(s+r[i]+1)*B2(s+r[i],zeta,n,zetap,m,taus,T,weights,nu)*((1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))+4*sqrt(abs(e))*r[i]*exp(-4*sqrt(abs(e))*r[i]))
,2*sqrt(abs(e)),weights_gL)
@@ -412,28 +553,47 @@ end
end
# dD/d sqrt(abs(e+mu/2))'s
-@everywhere function dsmuD0(e,rho,r,weights,N,J)
- out=Array{Float64}(undef,J*N)
+@everywhere function dsmuD0(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ N::Int64,
+ J::Int64
+)
+ out=Array{Float64,1}(undef,J*N)
for i in 1:J*N
out[i]=-2*r[i]*exp(-2*sqrt(abs(e))*r[i])/(r[i]+1)+
rho/(r[i]+1)*integrate_legendre(s->
(s+1)*B0(s)*((-1-2*sqrt(abs(e))*r[i])*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2+2*sqrt(abs(e))*s*(exp(-2*sqrt(abs(e))*(r[i]-s))+exp(-2*sqrt(abs(e))*(r[i]+s)))/2)
- ,0,min(1,r[i]),weights)+
+ ,0.,min(1.,r[i]),weights)+
(r[i]>=1 ? 0 :
- rho/(2*(r[i]+1))*integrate_legendre(s->(s+r[i]+1)*B0(s+r[i])*((-1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))*exp(-2*sqrt(abs(e))*s)+4*sqrt(abs(e))*r[i]*exp(-2*sqrt(abs(e))*(2*r[i]+s))),0,1-r[i],weights)
+ rho/(2*(r[i]+1))*integrate_legendre(s->(s+r[i]+1)*B0(s+r[i])*((-1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))*exp(-2*sqrt(abs(e))*s)+4*sqrt(abs(e))*r[i]*exp(-2*sqrt(abs(e))*(2*r[i]+s))),0.,1. -r[i],weights)
)
end
return out
end
-@everywhere function dsmuD1(e,rho,r,taus,T,weights,weights_gL,P,N,J,nu)
- out=Array{Array{Float64}}(undef,J*N)
+@everywhere function dsmuD1(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Array{Float64,1},1}(undef,J*N)
for i in 1:J*N
- out[i]=Array{Float64}(undef,(P+1)*J)
+ out[i]=Array{Float64,1}(undef,(P+1)*J)
for zeta in 0:J-1
for n in 0:P
out[i][zeta*(P+1)+n+1]=rho/(r[i]+1)*integrate_legendre(s->
(s+1)*B1(s,zeta,n,taus,T,weights,nu)*((-1-2*sqrt(abs(e))*r[i])*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2+2*sqrt(abs(e))*s*(exp(-2*sqrt(abs(e))*(r[i]-s))+exp(-2*sqrt(abs(e))*(r[i]+s)))/2)
- ,0,r[i],weights)+
+ ,0.,r[i],weights)+
rho/(2*(r[i]+1))*integrate_laguerre(s->
(s+r[i]+1)*B1(s+r[i],zeta,n,taus,T,weights,nu)*((-1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))+4*sqrt(abs(e))*r[i]*exp(-4*sqrt(abs(e))*r[i]))
,2*sqrt(abs(e)),weights_gL)
@@ -442,7 +602,19 @@ end
end
return out
end
-@everywhere function dsmuD2(e,rho,r,taus,T,weights,weights_gL,P,N,J,nu)
+@everywhere function dsmuD2(
+ e::Float64,
+ rho::Float64,
+ r::Array{Float64,1},
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ N::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Array{Float64,2}}(undef,J*N)
for i in 1:J*N
out[i]=Array{Float64,2}(undef,(P+1)*J,(P+1)*J)
@@ -452,7 +624,7 @@ end
for m in 0:P
out[i][zeta*(P+1)+n+1,zetap*(P+1)+m+1]=rho/(r[i]+1)*integrate_legendre(s->
(s+1)*B2(s,zeta,n,zetap,m,taus,T,weights,nu)*((-1-2*sqrt(abs(e))*r[i])*(exp(-2*sqrt(abs(e))*(r[i]-s))-exp(-2*sqrt(abs(e))*(r[i]+s)))/2+2*sqrt(abs(e))*s*(exp(-2*sqrt(abs(e))*(r[i]-s))+exp(-2*sqrt(abs(e))*(r[i]+s)))/2)
- ,0,r[i],weights)+
+ ,0.,r[i],weights)+
rho/(2*(r[i]+1))*integrate_laguerre(s->
(s+r[i]+1)*B2(s+r[i],zeta,n,zetap,m,taus,T,weights,nu)*((-1-2*sqrt(abs(e))*s)*(1-exp(-4*sqrt(abs(e))*r[i]))+4*sqrt(abs(e))*r[i]*exp(-4*sqrt(abs(e))*r[i]))
,2*sqrt(abs(e)),weights_gL)
@@ -465,11 +637,25 @@ end
end
# gamma's
-@everywhere function gamma0(e,rho,weights)
- return 2*rho*e*integrate_legendre(s->(s+1)*B0(s)*exp(-2*sqrt(abs(e))*s),0,1,weights)
-end
-@everywhere function gamma1(e,rho,taus,T,weights,weights_gL,P,J,nu)
- out=Array{Float64}(undef,J*(P+1))
+@everywhere function gamma0(
+ e::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
+ return 2*rho*e*integrate_legendre(s->(s+1)*B0(s)*exp(-2*sqrt(abs(e))*s),0.,1.,weights)
+end
+@everywhere function gamma1(
+ e::Float64,
+ rho::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Float64,1}(undef,J*(P+1))
for zeta in 0:J-1
for n in 0:P
out[zeta*(P+1)+n+1]=2*rho*e*integrate_laguerre(s->(s+1)*B1(s,zeta,n,taus,T,weights,nu),2*sqrt(abs(e)),weights_gL)
@@ -477,7 +663,17 @@ end
end
return out
end
-@everywhere function gamma2(e,rho,taus,T,weights,weights_gL,P,J,nu)
+@everywhere function gamma2(
+ e::Float64,
+ rho::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Float64,2}(undef,J*(P+1),J*(P+1))
for zeta in 0:J-1
for n in 0:P
@@ -492,11 +688,25 @@ end
end
# dgamma/d sqrt(abs(e))'s
-@everywhere function dsedgamma0(e,rho,weights)
- return 4*rho*sqrt(abs(e))*integrate_legendre(s->(s+1)*B0(s)*(1-sqrt(abs(e))*s)*exp(-2*sqrt(abs(e))*s),0,1,weights)
-end
-@everywhere function dsedgamma1(e,rho,taus,T,weights,weights_gL,P,J,nu)
- out=Array{Float64}(undef,J*(P+1))
+@everywhere function dsedgamma0(
+ e::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
+ return 4*rho*sqrt(abs(e))*integrate_legendre(s->(s+1)*B0(s)*(1-sqrt(abs(e))*s)*exp(-2*sqrt(abs(e))*s),0.,1.,weights)
+end
+@everywhere function dsedgamma1(
+ e::Float64,
+ rho::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Float64,1}(undef,J*(P+1))
for zeta in 0:J-1
for n in 0:P
out[zeta*(P+1)+n+1]=4*rho*e*integrate_laguerre(s->(s+1)*B1(s,zeta,n,taus,T,weights,nu)*(1-sqrt(abs(e))*s),2*sqrt(abs(e)),weights_gL)
@@ -504,7 +714,17 @@ end
end
return out
end
-@everywhere function dsedgamma2(e,rho,taus,T,weights,weights_gL,P,J,nu)
+@everywhere function dsedgamma2(
+ e::Float64,
+ rho::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Float64,2}(undef,J*(P+1),J*(P+1))
for zeta in 0:J-1
for n in 0:P
@@ -519,11 +739,25 @@ end
end
# dgamma/d sqrt(e+mu/2)'s
-@everywhere function dsmudgamma0(e,rho,weights)
- return -4*rho*e*integrate_legendre(s->(s+1)*s*B0(s)*exp(-2*sqrt(abs(e))*s),0,1,weights)
-end
-@everywhere function dsmudgamma1(e,rho,taus,T,weights,weights_gL,P,J,nu)
- out=Array{Float64}(undef,J*(P+1))
+@everywhere function dsmudgamma0(
+ e::Float64,
+ rho::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
+ return -4*rho*e*integrate_legendre(s->(s+1)*s*B0(s)*exp(-2*sqrt(abs(e))*s),0.,1.,weights)
+end
+@everywhere function dsmudgamma1(
+ e::Float64,
+ rho::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Float64,1}(undef,J*(P+1))
for zeta in 0:J-1
for n in 0:P
out[zeta*(P+1)+n+1]=-4*rho*e*integrate_laguerre(s->s*(s+1)*B1(s,zeta,n,taus,T,weights,nu),2*sqrt(abs(e)),weights_gL)
@@ -531,7 +765,17 @@ end
end
return out
end
-@everywhere function dsmudgamma2(e,rho,taus,T,weights,weights_gL,P,J,nu)
+@everywhere function dsmudgamma2(
+ e::Float64,
+ rho::Float64,
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ weights_gL::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Float64,2}(undef,J*(P+1),J*(P+1))
for zeta in 0:J-1
for n in 0:P
@@ -546,25 +790,41 @@ end
end
# \bar gamma's
-@everywhere function gammabar0(weights)
- return 4*pi*integrate_legendre(s->s^2*B0(s-1),0,1,weights)
-end
-@everywhere function gammabar1(taus,T,weights,P,J,nu)
- out=Array{Float64}(undef,J*(P+1))
+@everywhere function gammabar0(
+ weights::Tuple{Array{Float64,1},Array{Float64,1}}
+)
+ return 4*pi*integrate_legendre(s->s^2*B0(s-1),0.,1.,weights)
+end
+@everywhere function gammabar1(
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
+ out=Array{Float64,1}(undef,J*(P+1))
for zeta in 0:J-1
for n in 0:P
- out[zeta*(P+1)+n+1]=4*pi*integrate_legendre(s->s^2*B1(s-1,zeta,n,taus,T,weights,nu),0,1,weights)
+ out[zeta*(P+1)+n+1]=4*pi*integrate_legendre(s->s^2*B1(s-1,zeta,n,taus,T,weights,nu),0.,1.,weights)
end
end
return out
end
-@everywhere function gammabar2(taus,T,weights,P,J,nu)
+@everywhere function gammabar2(
+ taus::Array{Float64,1},
+ T::Array{Polynomial,1},
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ P::Int64,
+ J::Int64,
+ nu::Int64
+)
out=Array{Float64,2}(undef,J*(P+1),J*(P+1))
for zeta in 0:J-1
for n in 0:P
for zetap in 0:J-1
for m in 0:P
- out[zeta*(P+1)+n+1,zetap*(P+1)+m+1]=4*pi*integrate_legendre(s->s^2*B2(s-1,zeta,n,zetap,m,taus,T,weights,nu),0,1,weights)
+ out[zeta*(P+1)+n+1,zetap*(P+1)+m+1]=4*pi*integrate_legendre(s->s^2*B2(s-1,zeta,n,zetap,m,taus,T,weights,nu),0.,1.,weights)
end
end
end
diff --git a/src/simpleq-iteration.jl b/src/simpleq-iteration.jl
index 98977b8..4c4de07 100644
--- a/src/simpleq-iteration.jl
+++ b/src/simpleq-iteration.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.
@@ -13,7 +13,12 @@
## limitations under the License.
# compute rho(e) using the iteration
-function simpleq_iteration_rho_e(es,order,v,maxiter)
+function simpleq_iteration_rho_e(
+ es::Array{Float64,1},
+ order::Int64,
+ v::Function,
+ maxiter::Int64
+)
for j in 1:length(es)
(u,rho)=simpleq_iteration_hatun(es[j],order,v,maxiter)
@printf("% .15e % .15e\n",es[j],real(rho[maxiter+1]))
@@ -21,7 +26,15 @@ function simpleq_iteration_rho_e(es,order,v,maxiter)
end
# compute u(x) using the iteration and print at every step
-function simpleq_iteration_ux(order,e,v,maxiter,xmin,xmax,nx)
+function simpleq_iteration_ux(
+ order::Int64,
+ e::Float64,
+ v::Function,
+ maxiter::Int64,
+ xmin::Float64,
+ xmax::Float64,
+ nx::Int64
+)
(u,rho)=simpleq_iteration_hatun(e,order,v,maxiter)
weights=gausslegendre(order)
@@ -37,7 +50,12 @@ end
# \hat u_n
-function simpleq_iteration_hatun(e,order,v,maxiter)
+function simpleq_iteration_hatun(
+ e::Float64,
+ order::Int64,
+ v::Function,
+ maxiter::Int64
+)
# gauss legendre weights
weights=gausslegendre(order)
@@ -46,7 +64,7 @@ function simpleq_iteration_hatun(e,order,v,maxiter)
(Eta,Eta0)=easyeq_init_H(weights,v)
# init u and rho
- u=Array{Array{Float64}}(undef,maxiter+1)
+ u=Array{Array{Float64,1},1}(undef,maxiter+1)
u[1]=zeros(Float64,order)
rho=zeros(Float64,maxiter+1)
@@ -60,7 +78,11 @@ function simpleq_iteration_hatun(e,order,v,maxiter)
end
# A
-function simpleq_iteration_A(e,weights,Eta)
+function simpleq_iteration_A(
+ e::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ Eta::Array{Float64,1}
+)
N=length(weights[1])
out=zeros(Float64,N,N)
for i in 1:N
@@ -75,7 +97,12 @@ function simpleq_iteration_A(e,weights,Eta)
end
# b
-function simpleq_iteration_b(u,e,rho,V)
+function simpleq_iteration_b(
+ u::Array{Float64,1},
+ e::Float64,
+ rho::Float64,
+ V::Array{Float64,1}
+)
out=zeros(Float64,length(V))
for i in 1:length(V)
out[i]=V[i]+2*e*rho*u[i]^2
@@ -84,7 +111,13 @@ function simpleq_iteration_b(u,e,rho,V)
end
# rho_n
-function simpleq_iteration_rhon(u,e,weights,V0,Eta0)
+function simpleq_iteration_rhon(
+ u::Array{Float64,1},
+ e::Float64,
+ weights::Tuple{Array{Float64,1},Array{Float64,1}},
+ V0::Float64,
+ Eta0::Float64
+)
S=V0
for i in 1:length(weights[1])
y=(weights[1][i]+1)/2
diff --git a/src/tools.jl b/src/tools.jl
index 0d3dc7f..5d1678d 100644
--- a/src/tools.jl
+++ b/src/tools.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.
@@ -13,7 +13,9 @@
## limitations under the License.
# \Phi(x)=2*(1-sqrt(1-x))/x
-@everywhere function Phi(x)
+@everywhere function Phi(
+ x::Float64
+)
if abs(x)>1e-5
return 2*(1-sqrt(abs(1-x)))/x
else
@@ -21,7 +23,9 @@
end
end
# \partial\Phi
-@everywhere function dPhi(x)
+@everywhere function dPhi(
+ x::Float64
+)
#if abs(x-1)<1e-5
# @printf(stderr,"warning: dPhi is singular at 1, and evaluating it at (% .8e+i% .8e)\n",real(x),imag(x))
#end
@@ -33,17 +37,25 @@ end
end
# apply Phi to every element of a vector
-@everywhere function dotPhi(v)
+@everywhere function dotPhi(
+ v::Array{Float64,1}
+)
out=zeros(Float64,length(v))
for i in 1:length(v)
out[i]=Phi(v[i])
end
return out
end
-@everywhere function dotdPhi(v)
+@everywhere function dotdPhi(
+ v::Array{Float64,1}
+)
out=zeros(Float64,length(v))
for i in 1:length(v)
out[i]=dPhi(v[i])
end
return out
end
+
+@everywhere function sinc(x::Float64)
+ return (x == 0 ? 1 : sin(x)/x)
+end