^n)&(!n59$%mqN}fX4>ZD4dFmTfDGx_!p_w|CgnO%eeY{`EL
ziNPvNtGLU$Q<1mGpC)}QFNm82X9$C@-b(i@XFT9WyUl9bxpPj_B-PKgGwO4CgzuUy
z>1&tcgB>bTRW$xl;6EVB7@EDJ_So@K|Jpdwl9}NWg;7_((0Y+O!NKL|^G5~uTPN9qdSDG;DCXg)=3&A6g3Z(JdGytfHpitIKIw%)3m7*2Vqsy)_;nc_ZpK$yT
zG=qS?!hO8FcR4R{VNBkdBh3{lM49-}=~9~^We4_c(5{cIPa&=)Bzz|=CE^vC5UHW~
zS`|B1U7`QvS=$No?yiNIZm93B&(hQ5#bG&yR!5Z>eB%@@Lp>aNl%0&0f66
zN$sD5r>!%;>;haL$v!q$VQ~`=C6Tkali!TfJz7b0;$G(Bv4NMOBnti1o#oxY|`VF7u<<7wZl1#JMu|N$Q>GP
zYM@>?E?J#m?Vny~58%Q{3Aof0fPl`bM3eVG0Qj$x*`&U|1hgE;x0I=0Z$rRe+}tKc=oqyztp$@QUPF$
z@78*Uww!45FZiP9vKqU&rh?C2l(7?O@6
z(Hs3KVVR6p5C)-`z(siBmW8^s03LqAJw#k(+!Kh1T
zELkv_(`*Xf1Ri`aT5X4O&*i%c!#y{J(`zg?topC
zN58a$+vh+Ts-pMi@&C&mn*W0G|LexhY<{8`WI^?b9{Cx6{!3FITY>`
o=;Q%Xbo91&5)c)Hv8w1AsQ!obQ8P0mgweRJ0%0DcL^%4`~P ...
+\newenvironment{DoxyPre}{%
+ \small%
+ \begin{alltt}%
+}{%
+ \end{alltt}%
+ \normalsize%
+}
+
+% Used by @code ... @endcode
+\newenvironment{DoxyCode}{%
+
+
+\begin{scriptsize}\begin{alltt}%
+}{%
+\end{alltt}\end{scriptsize}%
+}
+
+% Used by @example, @include, @includelineno and @dontinclude
+\newenvironment{DoxyCodeInclude}{%
+ \DoxyCode%
+}{%
+ \endDoxyCode%
+}
+
+% Used by @verbatim ... @endverbatim
+\newenvironment{DoxyVerb}{%
+ \footnotesize%
+ \verbatim%
+}{%
+ \endverbatim%
+ \normalsize%
+}
+
+% Used by @verbinclude
+\newenvironment{DoxyVerbInclude}{%
+ \DoxyVerb%
+}{%
+ \endDoxyVerb%
+}
+
+% Used by numbered lists (using '-#' or ...
)
+\newenvironment{DoxyEnumerate}{%
+ \enumerate%
+}{%
+ \endenumerate%
+}
+
+% Used by bullet lists (using '-', @li, @arg, or )
+\newenvironment{DoxyItemize}{%
+ \itemize%
+}{%
+ \enditemize%
+}
+
+% Used by description lists (using ...
)
+\newenvironment{DoxyDescription}{%
+ \description%
+}{%
+ \enddescription%
+}
+
+% Used by @image, @dotfile, and @dot ... @enddot
+% (only if caption is specified)
+\newenvironment{DoxyImage}{%
+ \begin{figure}[H]%
+ \begin{center}%
+}{%
+ \end{center}%
+ \end{figure}%
+}
+
+% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc
+% (only if no caption is specified)
+\newenvironment{DoxyImageNoCaption}{%
+}{%
+}
+
+% Used by @attention
+\newenvironment{DoxyAttention}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @author and @authors
+\newenvironment{DoxyAuthor}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @date
+\newenvironment{DoxyDate}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @invariant
+\newenvironment{DoxyInvariant}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @note
+\newenvironment{DoxyNote}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @post
+\newenvironment{DoxyPostcond}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @pre
+\newenvironment{DoxyPrecond}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @copyright
+\newenvironment{DoxyCopyright}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @remark
+\newenvironment{DoxyRemark}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @return
+\newenvironment{DoxyReturn}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @since
+\newenvironment{DoxySince}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @see
+\newenvironment{DoxySeeAlso}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @version
+\newenvironment{DoxyVersion}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @warning
+\newenvironment{DoxyWarning}[1]{%
+ \begin{DoxyDesc}{#1}%
+}{%
+ \end{DoxyDesc}%
+}
+
+% Used by @internal
+\newenvironment{DoxyInternal}[1]{%
+ \paragraph*{#1}%
+}{%
+}
+
+% Used by @par and @paragraph
+\newenvironment{DoxyParagraph}[1]{%
+ \begin{list}{}%
+ {%
+ \settowidth{\labelwidth}{40pt}%
+ \setlength{\leftmargin}{\labelwidth}%
+ \setlength{\parsep}{0pt}%
+ \setlength{\itemsep}{-4pt}%
+ \renewcommand{\makelabel}{\entrylabel}%
+ }%
+ \item[#1]%
+}{%
+ \end{list}%
+}
+
+% Used by parameter lists
+\newenvironment{DoxyParams}[2][]{%
+ \begin{DoxyDesc}{#2}%
+ \item[] \hspace{\fill} \vspace{-40pt}%
+ \settowidth{\labelwidth}{40pt}%
+ \setlength{\LTleft}{0pt}%
+ \setlength{\tabcolsep}{0.01\textwidth}%
+ \ifthenelse{\equal{#1}{}}%
+ {\begin{longtable}{|>{\raggedleft\hspace{0pt}}p{0.15\textwidth}|%
+ p{0.815\textwidth}|}}%
+ {\ifthenelse{\equal{#1}{1}}%
+ {\begin{longtable}{|>{\centering}p{0.10\textwidth}|%
+ >{\raggedleft\hspace{0pt}}p{0.15\textwidth}|%
+ p{0.685\textwidth}|}}%
+ {\begin{longtable}{|>{\centering}p{0.10\textwidth}|%
+ >{\centering\hspace{0pt}}p{0.15\textwidth}|%
+ >{\raggedleft\hspace{0pt}}p{0.15\textwidth}|%
+ p{0.515\textwidth}|}}%
+ }\hline%
+}{%
+ \end{longtable}%
+ \end{DoxyDesc}%
+}
+
+% Used for fields of simple structs
+\newenvironment{DoxyFields}[1]{%
+ \begin{DoxyDesc}{#1}%
+ \item[] \hspace{\fill} \vspace{-40pt}%
+ \settowidth{\labelwidth}{40pt}%
+ \setlength{\LTleft}{0pt}%
+ \setlength{\tabcolsep}{0.01\textwidth}%
+ \begin{longtable}{|>{\raggedleft\hspace{0pt}}p{0.15\textwidth}|%
+ p{0.15\textwidth}|%
+ p{0.635\textwidth}|}%
+ \hline%
+}{%
+ \end{longtable}%
+ \end{DoxyDesc}%
+}
+
+% is used for parameters within a detailed function description
+\newenvironment{DoxyParamCaption}{%
+ \renewcommand{\item}[2][]{##1 {\em ##2}}%
+ }{%
+}
+
+% Used by return value lists
+\newenvironment{DoxyRetVals}[1]{%
+ \begin{DoxyDesc}{#1}%
+ \begin{description}%
+ \item[] \hspace{\fill} \vspace{-25pt}%
+ \setlength{\tabcolsep}{0.01\textwidth}%
+ \begin{longtable}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|%
+ p{0.77\textwidth}|}%
+ \hline%
+}{%
+ \end{longtable}%
+ \end{description}%
+ \end{DoxyDesc}%
+}
+
+% Used by exception lists
+\newenvironment{DoxyExceptions}[1]{%
+ \begin{DoxyDesc}{#1}%
+ \begin{description}%
+ \item[] \hspace{\fill} \vspace{-25pt}%
+ \definecolor{tableShade}{HTML}{F8F8F8}%
+ \rowcolors{1}{white}{tableShade}%
+ \arrayrulecolor{gray}%
+ \setlength{\tabcolsep}{0.01\textwidth}%
+ \begin{longtable}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|%
+ p{0.77\textwidth}|}%
+ \hline%
+}{%
+ \end{longtable}%
+ \end{description}%
+ \end{DoxyDesc}%
+}
+
+% Used by template parameter lists
+\newenvironment{DoxyTemplParams}[1]{%
+ \begin{DoxyDesc}{#1}%
+ \begin{description}%
+ \item[] \hspace{\fill} \vspace{-25pt}%
+ \definecolor{tableShade}{HTML}{F8F8F8}%
+ \rowcolors{1}{white}{tableShade}%
+ \arrayrulecolor{gray}%
+ \setlength{\tabcolsep}{0.01\textwidth}%
+ \begin{longtable}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|%
+ p{0.77\textwidth}|}%
+ \hline%
+}{%
+ \end{longtable}%
+ \end{description}%
+ \end{DoxyDesc}%
+}
+
+\newcommand{\doxyref}[3]{\textbf{#1} (\textnormal{#2}\,\pageref{#3})}
+\newenvironment{DoxyCompactList}
+{\begin{list}{}{
+ \setlength{\leftmargin}{0.5cm}
+ \setlength{\itemsep}{0pt}
+ \setlength{\parsep}{0pt}
+ \setlength{\topsep}{0pt}
+ \renewcommand{\makelabel}{\hfill}}}
+{\end{list}}
+\newenvironment{DoxyCompactItemize}
+{
+ \begin{itemize}
+ \setlength{\itemsep}{-3pt}
+ \setlength{\parsep}{0pt}
+ \setlength{\topsep}{0pt}
+ \setlength{\partopsep}{0pt}
+}
+{\end{itemize}}
+\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}
+\newlength{\tmplength}
+\newenvironment{TabularC}[1]
+{
+\setlength{\tmplength}
+ {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)}
+ \par\begin{xtabular*}{\linewidth}
+ {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|}
+}
+{\end{xtabular*}\par}
+\newcommand{\entrylabel}[1]{
+ {\parbox[b]{\labelwidth-4pt}{\makebox[0pt][l]{%
+ \usefont{OT1}{phv}{bc}{n}\color{darkgray}#1}\vspace{1.5\baselineskip}}}}
+\newenvironment{Desc}
+{\begin{list}{}
+ {
+ \settowidth{\labelwidth}{40pt}
+ \setlength{\leftmargin}{\labelwidth}
+ \setlength{\parsep}{0pt}
+ \setlength{\itemsep}{-4pt}
+ \renewcommand{\makelabel}{\entrylabel}
+ }
+}
+{\end{list}}
+\newsavebox{\xrefbox}
+\newlength{\xreflength}
+\newcommand{\xreflabel}[1]{%
+ \sbox{\xrefbox}{#1}%
+ \setlength{\xreflength}{\wd\xrefbox}%
+ \ifthenelse{\xreflength>\labelwidth}{%
+ \begin{minipage}{\textwidth}%
+ \setlength{\parindent}{0pt}%
+ \hangindent=15pt\bfseries #1\vspace{1.2\itemsep}%
+ \end{minipage}%
+ }{%
+ \parbox[b]{\labelwidth}{\makebox[0pt][l]{\textbf{#1}}}%
+ }}%
+\newenvironment{DoxyRefList}{%
+ \begin{list}{}{%
+ \setlength{\labelwidth}{10pt}%
+ \setlength{\leftmargin}{\labelwidth}%
+ \addtolength{\leftmargin}{\labelsep}%
+ \renewcommand{\makelabel}{\xreflabel}%
+ }%
+ }%
+{\end{list}}
+\newenvironment{DoxyRefDesc}[1]
+{\begin{list}{}{%
+ \renewcommand\makelabel[1]{\textbf{##1}}
+ \settowidth\labelwidth{\makelabel{#1}}
+ \setlength\leftmargin{\labelwidth+\labelsep}}}
+{\end{list}}
+\newenvironment{Indent}
+ {\begin{list}{}{\setlength{\leftmargin}{0.5cm}}
+ \item[]\ignorespaces}
+ {\unskip\end{list}}
+\setlength{\parindent}{0cm}
+\setlength{\parskip}{0.2cm}
+\addtocounter{secnumdepth}{2}
+\usepackage[T1]{fontenc}
+\makeatletter
+\renewcommand{\paragraph}{\@startsection{paragraph}{4}{0ex}%
+ {-1.0ex}%
+ {1.0ex}%
+ {\usefont{OT1}{phv}{bc}{n}\color{darkgray}}}
+\renewcommand{\subparagraph}{\@startsection{subparagraph}{5}{0ex}%
+ {-1.0ex}%
+ {1.0ex}%
+ {\usefont{OT1}{phv}{bc}{n}\color{darkgray}}}
+\makeatother
+\allsectionsfont{\usefont{OT1}{phv}{bc}{n}\selectfont\color{darkgray}}
+\stepcounter{secnumdepth}
+\stepcounter{tocdepth}
+\definecolor{comment}{rgb}{0.5,0.0,0.0}
+\definecolor{keyword}{rgb}{0.0,0.5,0.0}
+\definecolor{keywordtype}{rgb}{0.38,0.25,0.125}
+\definecolor{keywordflow}{rgb}{0.88,0.5,0.0}
+\definecolor{preprocessor}{rgb}{0.5,0.38,0.125}
+\definecolor{stringliteral}{rgb}{0.0,0.125,0.25}
+\definecolor{charliteral}{rgb}{0.0,0.5,0.5}
+\definecolor{vhdldigit}{rgb}{1.0,0.0,1.0}
+\definecolor{vhdlkeyword}{rgb}{0.43,0.0,0.43}
+\definecolor{vhdllogic}{rgb}{1.0,0.0,0.0}
+\definecolor{vhdlchar}{rgb}{0.0,0.0,0.0}
diff --git a/doc/latex_sty/sectsty.sty b/doc/latex_sty/sectsty.sty
new file mode 100644
index 0000000000000000000000000000000000000000..9f7ecab2660a2546c8b38abe877a9133c31015af
--- /dev/null
+++ b/doc/latex_sty/sectsty.sty
@@ -0,0 +1,601 @@
+
+%%
+%% This is file `sectsty.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% sectsty.dtx (with options: `package')
+%%
+%% IMPORTANT NOTICE:
+%%
+%% For the copyright see the source file.
+%%
+%% You are *not* allowed to modify this file.
+%%
+%% You are *not* allowed to distribute this file.
+%% For distribution of the original source see the terms
+%% for copying and modification in the file sectsty.dtx.
+%%
+%%
+%% \CheckSum{1463}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+\ProvidesPackage{sectsty}[1999/04/12 v2.0.1 Commands to change all
+sectional heading styles]
+\NeedsTeXFormat{LaTeX2e}[1998/06/01]
+\long\def\SS@ocl#1#2#3{\ifnum #1>\SS@chatlevel #2\else #3\fi}
+\def\SS@oclto#1#2{\SS@ocl{#1}{\typeout{#2}}{}}
+\def\SS@chatlevel{3}
+\DeclareOption{garrulous}{\def\SS@chatlevel{0}}
+\DeclareOption{chatty}{\def\SS@chatlevel{1}}
+\DeclareOption{taciturn}{\def\SS@chatlevel{2}}
+\DeclareOption{yorkshire}{\def\SS@chatlevel{3}}
+\ProcessOptions
+\let\@svsec\relax
+\newcommand{\nohang}{\let\@hangfrom\@empty}
+\let\SS@origunderline\underline
+\CheckCommand*{\underbar}[1]%
+ {\underline{\sbox\tw@{#1}\dp\tw@\z@\box\tw@}}
+\newcommand*{\SS@ulemsectuline}[2]{%
+ \ifhmode% run-in head
+ \begingroup%
+ \def\hskip##1\relax##2\@@par{\endgroup\@@hskip##1\relax#1{##2}}%
+ \else% stand alone head
+ % \ifx\\\@centercr\let\@hangfrom\@empty\fi% deal with \@hangfrom prob
+ \protected@edef\@svsec{\noexpand#1{\@svsec\strut}}% added strut
+ \def\interlinepenalty##1##2\@@par{\@@interlinepenalty##1#1{##2}\@@par}%
+ \fi%
+ #2\@@par}% added strut here then removed it (stupid boy)
+\let\@@hskip\hskip
+\let\@@interlinepenalty\interlinepenalty
+\CheckCommand*{\underline}[1]{%
+ \relax
+ \ifmmode\@@underline{#1}%
+ \else $\@@underline{\hbox{#1}}\m@th$\relax\fi}
+\def\SS@underline#1{%
+ \relax
+ \ifmmode\@@underline{\strut#1}%
+ \else $\@@underline{\hbox{\strut#1}}\m@th$\relax\fi}
+
+\def\SS@ulemheadingchapfudge#1#2{%
+ \ifSS@komascript%
+ \ifnum\SSsectlevel=1% chapter level
+ \ifx\SS@headingpart\SS@nopartid%
+ \SS@oclto{1}{Koma-script chapter number part}%
+ \let\SS@savechapterformat\chapterformat%
+ \def\chapterformat{#1{\SS@savechapterformat}}%
+ \def\@tempcmda{#2}%
+ \else%
+ \SS@oclto{1}{Koma-script chapter title part}%
+ \def\@tempcmda{#1{#2}}%
+ \fi%
+ \else%
+ \SS@oclto{1}{Koma-script not chapter}%
+ \def\@tempcmda{#1{#2}}%
+ \fi%
+ \else%
+ \SS@oclto{1}{Not Koma-script}%
+ \def\@tempcmda{#1{#2}}%
+ \fi%
+ \@tempcmda
+}%
+
+\AtBeginDocument{%
+ \@ifundefined{UL@box}%
+ {% if ulem has not been loaded
+ \SS@oclto{1}{ulem not loaded; underlining setup}%
+ \def\SS@makeulinesect{%
+ \def\underbar##1{\SS@origunderline{\sbox\tw@{##1}\dp\tw@\z@\box\tw@}}%
+ \def\underline{\SS@ulemsectuline{\SS@underline}}%
+ \def\ulemheading##1{\SS@ulemsectuline{\SS@underline}}}%
+ \def\SS@makeulinepartchap{%
+ \def\underbar##1{\SS@origunderline{\sbox\tw@{##1}\dp\tw@\z@\box\tw@}}%
+ \def\underline##1{\SS@ulemheadingchapfudge{\SS@underline}{##1}}%
+ \def\ulemheading##1##2{\SS@ulemheadingchapfudge{\SS@underline}{##2}}}%
+ }% endif ulem has not been loaded
+ {% If ulem has been loaded
+ \SS@oclto{1}{ulem loaded; underlining setup}%
+ \def\SS@makeulinesect{%
+ \def\underbar##1{\SS@origunderline{\sbox\tw@{##1}\dp\tw@\z@\box\tw@}}%
+ \def\underline{\SS@ulemsectuline{\uline}}%
+ \def\ulemheading##1##2{\SS@ulemsectuline{##1}{##2}}}%
+ \def\SS@makeulinepartchap{%
+ \def\underbar##1{\SS@origunderline{\sbox\tw@{##1}\dp\tw@\z@\box\tw@}}%
+ \def\underline##1{\SS@ulemheadingchapfudge{\uline}{##1}}%
+ \let\ulemheading\SS@ulemheadingchapfudge}
+ }% endif ulem has been loaded
+}% end \AtBeginDocument
+\def\SS@rr{\def\raggedright{%
+ \let\\\@centercr\@rightskip\@flushglue \rightskip\@rightskip}}
+\newif\ifSS@komascript
+\SS@komascriptfalse
+\@ifclassloaded{scrartcl}{\SS@komascripttrue}{}
+\@ifclassloaded{scrreprt}{\SS@komascripttrue}{}
+\@ifclassloaded{scrbook} {\SS@komascripttrue}{}
+
+\newcommand{\SS@sectid}[1]{\gdef\SSsectlevel{#1}}
+\newcommand{\SS@nopart}{\global\let\SS@headingpart\SS@nopartid}
+\newcommand{\SS@titlepart}{\global\let\SS@headingpart\SS@titlepartid}
+\newcommand{\SS@nopartid}{number part}
+\newcommand{\SS@titlepartid}{title part}
+\newcommand{\SSifnumberpart}{%
+ \ifx\SS@headingpart\SS@nopartid
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi}
+\newcommand{\SSiftitlepart}{%
+ \ifx\SS@headingpart\SS@titlepartid
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi}
+\def\ifraggedleft#1#2{%
+ \edef\@tempcmda{\the\rightskip}%
+ \edef\@tempcmdb{\the\z@skip}%
+ \ifx\@tempcmda\@tempcmdb\@tempswatrue\else\@tempswafalse\fi
+ \edef\@tempcmda{\the\leftskip}%
+ \edef\@tempcmdb{\the\@flushglue}%
+ \if@tempswa
+ \ifx\@tempcmda\@tempcmdb\@tempswatrue\else\@tempswafalse\fi
+ \fi
+ \if@tempswa#1\else#2\fi}
+\def\ifcentering{%
+ \edef\@tempcmda{\the\rightskip}%
+ \edef\@tempcmdb{\the\@flushglue}%
+ \ifx\@tempcmda\@tempcmdb\@tempswatrue\else\@tempswafalse\fi
+ \edef\@tempcmda{\the\leftskip}%
+ \edef\@tempcmdb{\the\@flushglue}%
+ \if@tempswa
+ \ifx\@tempcmda\@tempcmdb\@tempswatrue\else\@tempswafalse\fi
+ \fi
+ \if@tempswa\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
+\newcommand{\sectionrule}[5]{%
+ \ifcentering{%
+ \PackageError{sectsty}%
+ {Can't use \protect\sectionrule\space with \protect\centering}%
+ {The \protect\sectionrule\space command doesn't work properly
+ with sectional headings that\MessageBreak are centred, so I'll
+ carry on as if you'd not used the \protect\sectionrule\space
+ command.}#5}%
+ {\ifSS@komascript
+ \ifnum\SSsectlevel>1
+ \SS@oclto{1}{KOMA-script; normal section rule}%
+ \SS@sectionrule{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \SS@oclto{1}{KOMA-script; part/chap section rule}%
+ \SS@komapartchaprule{#1}{#2}{#3}{#4}{#5}%
+ \fi
+ \else
+ \SS@oclto{1}{No KOMA-script; normal section rule}%
+ \SS@sectionrule{#1}{#2}{#3}{#4}{#5}%
+ \fi}}
+\def\SS@sectionrule#1#2#3#4#5{%
+ \ifraggedleft
+ {\SS@rlsectionrule{#1}{#2}{#3}{#4}{#5}}%
+ {\SS@normsectionrule{#1}{#2}{#3}{#4}{#5}}}
+\def\SS@normsectionrule#1#2#3#4#5{%
+ \let\SS@@par\@@par\let\@@par\relax% very dodgy
+ \noindent\makebox[0pt][l]{\rule[#1]{\hsize}{#2}}%
+ #5\hfill\makebox[0pt][r]{\rule[#3]{\hsize}{#4}}%
+ \let\@@par\SS@@par\@@par}
+\def\SS@rlsectionrule#1#2#3#4#5{%
+ \let\SS@@par\@@par\let\@@par\relax% very dodgy
+ \noindent\makebox[0pt][l]{\rule[#1]{\hsize}{#2}}\hfill%
+ #5\makebox[0pt][r]{\rule[#3]{\hsize}{#4}}%
+ \let\@@par\SS@@par\@@par}
+\newif\ifSS@starform
+\def\secdef#1#2{\@ifstar{\SS@starformtrue#2}{\SS@starformfalse\@dblarg{#1}}}
+\def\SS@komapartchaprule#1#2#3#4#5{%
+ \ifraggedleft
+ {\SS@rlkomapartchaprule{#1}{#2}{#3}{#4}{#5}}%
+ {\SS@normkomapartchaprule{#1}{#2}{#3}{#4}{#5}}%
+}
+\def\SS@normkomapartchaprule#1#2#3#4#5{%
+ \SS@oclto{1}{SS@normkomapartchaprule}%
+ \ifSS@starform
+ \SS@normsectionrule{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \SSifnumberpart
+ {\noindent\makebox[0pt][l]{\rule[#1]{\hsize}{#2}}#5}%
+ {#5\hfill\makebox[0pt][r]{\rule[#3]{\hsize}{#4}}}%
+ \fi
+}
+\def\SS@rlkomapartchaprule#1#2#3#4#5{%
+ \SS@oclto{1}{SS@rlkomapartchaprule}%
+ \ifSS@starform
+ \SS@rlsectionrule{#1}{#2}{#3}{#4}{#5}%
+ \else
+ \SSifnumberpart
+ {\noindent\makebox[0pt][l]{\rule[#1]{\hsize}{#2}}\hfill#5}%
+ {#5\makebox[0pt][r]{\rule[#3]{\hsize}{#4}}}%
+ \fi
+}
+\newcommand*{\partfont} [1]
+ {\gdef\SS@partnumberfont{\SS@sectid{0}\SS@nopart\SS@makeulinepartchap#1}
+ \gdef\SS@parttitlefont{\SS@sectid{0}\SS@titlepart\SS@makeulinepartchap#1}}
+\newcommand*{\partnumberfont} [1]
+ {\gdef\SS@partnumberfont{\SS@sectid{0}\SS@nopart\SS@makeulinepartchap#1}}
+\newcommand*{\parttitlefont} [1]
+ {\gdef\SS@parttitlefont{\SS@sectid{0}\SS@titlepart\SS@makeulinepartchap#1}}
+\newcommand*{\chapterfont} [1]
+ {\gdef\SS@chapnumfont{\SS@sectid{1}\SS@nopart\SS@makeulinepartchap#1}
+ \gdef\SS@chaptitlefont{\SS@sectid{1}\SS@titlepart\SS@makeulinepartchap#1}}
+\newcommand*{\chapternumberfont} [1]
+ {\gdef\SS@chapnumfont{\SS@sectid{1}\SS@nopart\SS@makeulinepartchap#1}}
+\newcommand*{\chaptertitlefont} [1]
+ {\gdef\SS@chaptitlefont{\SS@sectid{1}\SS@titlepart\SS@makeulinepartchap#1}}
+\newcommand*{\sectionfont} [1]
+ {\gdef\SS@sectfont{\SS@sectid{2}\SS@rr\SS@makeulinesect#1}}
+\newcommand*{\subsectionfont} [1]
+ {\gdef\SS@subsectfont{\SS@sectid{3}\SS@rr\SS@makeulinesect#1}}
+\newcommand*{\subsubsectionfont} [1]
+ {\gdef\SS@subsubsectfont{\SS@sectid{4}\SS@rr\SS@makeulinesect#1}}
+\newcommand*{\paragraphfont} [1]
+ {\gdef\SS@parafont{\SS@sectid{5}\SS@rr\SS@makeulinesect#1}}
+\newcommand*{\subparagraphfont} [1]
+ {\gdef\SS@subparafont{\SS@sectid{6}\SS@rr\SS@makeulinesect#1}}
+\newcommand*{\minisecfont} [1]
+ {\gdef\SS@minisecfont{\SS@sectid{7}\SS@rr\SS@makeulinepartchap#1}}
+\newcommand*{\allsectionsfont} [1] {\partfont{#1}
+ \chapterfont{#1}
+ \sectionfont{#1}
+ \subsectionfont{#1}
+ \subsubsectionfont{#1}
+ \paragraphfont{#1}
+ \subparagraphfont{#1}
+ \minisecfont{#1}}
+\allsectionsfont{\relax}
+\@tempswafalse
+\@ifclassloaded{article} {\@tempswatrue\SS@oclto{1}{article detected}} {}
+\@ifclassloaded{report} {\@tempswatrue\SS@oclto{1}{report detected}} {}
+\@ifclassloaded{book} {\@tempswatrue\SS@oclto{1}{book detected}} {}
+\@ifclassloaded{letter} {} {}
+\@ifclassloaded{slides} {} {}
+\@ifclassloaded{scrartcl}{\@tempswatrue\SS@oclto{1}{scrartcl detected}} {}
+\@ifclassloaded{scrreprt}{\@tempswatrue\SS@oclto{1}{scrreprt detected}} {}
+\@ifclassloaded{scrbook} {\@tempswatrue\SS@oclto{1}{scrbook detected}} {}
+
+\if@tempswa\else
+ \PackageError{sectsty}%
+ {The sectsty package doesn't work with\MessageBreak
+ this document class}%
+ {The sectsty package only works with the following classes:
+ \MessageBreak
+ the standard LaTeX document classes\MessageBreak
+ article, report, and book; and\MessageBreak
+ the KOMA-Script classes\MessageBreak
+ scrartcl, scrbook, and scrreprt.}
+\fi
+\@tempswafalse
+\@ifclassloaded{article} {\@tempswatrue\SS@oclto{1}{article detected}} {}
+\@ifclassloaded{report} {\@tempswatrue\SS@oclto{1}{report detected}} {}
+\@ifclassloaded{book} {\@tempswatrue\SS@oclto{1}{book detected}} {}
+\@ifclassloaded{letter} {} {}
+\@ifclassloaded{slides} {} {}
+\@ifclassloaded{scrartcl}{} {}
+\@ifclassloaded{scrreprt}{} {}
+\@ifclassloaded{scrbook} {} {}
+\if@tempswa
+\SS@oclto{1}{section->subparagraph modifications for article, report,
+and book classes}%
+\renewcommand\section{\@startsection {section}{1}{\z@}%
+ {-3.5ex \@plus -1ex \@minus -.2ex}%
+ {2.3ex \@plus.2ex}%
+ {\normalfont\Large\bfseries\SS@sectfont}}
+\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
+ {-3.25ex\@plus -1ex \@minus -.2ex}%
+ {1.5ex \@plus .2ex}%
+ {\normalfont\large\bfseries\SS@subsectfont}}
+\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+ {-3.25ex\@plus -1ex \@minus -.2ex}%
+ {1.5ex \@plus .2ex}%
+ {\normalfont\normalsize\bfseries\SS@subsubsectfont}}
+\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
+ {3.25ex \@plus1ex \@minus.2ex}%
+ {-1em}%
+ {\normalfont\normalsize\bfseries\SS@parafont}}
+\renewcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}%
+ {3.25ex \@plus1ex \@minus .2ex}%
+ {-1em}%
+ {\normalfont\normalsize\bfseries\SS@subparafont}}
+\fi
+\@tempswafalse
+\@ifclassloaded{article} {} {}
+\@ifclassloaded{report} {} {}
+\@ifclassloaded{book} {} {}
+\@ifclassloaded{letter} {} {}
+\@ifclassloaded{slides} {} {}
+\@ifclassloaded{scrartcl}{\@tempswatrue\SS@oclto{1}{scrartcl detected}} {}
+\@ifclassloaded{scrreprt}{\@tempswatrue\SS@oclto{1}{scrreprt detected}} {}
+\@ifclassloaded{scrbook} {\@tempswatrue\SS@oclto{1}{scrbook detected}} {}
+\if@tempswa
+\SS@oclto{1}{section->minisec modifications for scrartcl, scrreprt,
+and scrbook classes}%
+\renewcommand\section{\@startsection{section}{1}{\z@}%
+ {-3.5ex \@plus -1ex \@minus -.2ex}%
+ {2.3ex \@plus.2ex}%
+ {\raggedsection\normalfont\size@section\sectfont\SS@sectfont}}
+\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
+ {-3.25ex\@plus -1ex \@minus -.2ex}%
+ {1.5ex \@plus .2ex}%
+ {\raggedsection\normalfont\size@subsection\sectfont\SS@subsectfont}}
+\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+ {-3.25ex\@plus -1ex \@minus -.2ex}%
+ {1.5ex \@plus .2ex}%
+ {\raggedsection\normalfont\size@subsubsection\sectfont\SS@subsubsectfont}}
+\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
+ {3.25ex \@plus1ex \@minus.2ex}%
+ {-1em}%
+ {\raggedsection\normalfont\size@paragraph\sectfont\SS@parafont}}
+\renewcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}%
+ {3.25ex \@plus1ex \@minus .2ex}%
+ {-1em}%
+ {\raggedsection\normalfont\size@subparagraph\sectfont\SS@subparafont}}
+\renewcommand\minisec[1]{\@afterindentfalse \vskip 1.5ex
+ {\parindent \z@ \raggedsection\sectfont\SS@minisecfont {#1}\par\nobreak}%
+ \@afterheading}%
+ \fi
+%% Code from |report.cls| June 1996
+\@ifclassloaded{report}{%
+\SS@oclto{1}{chapter modifications for report class}%
+\def\@makechapterhead#1{%
+ \vspace*{50\p@}%
+ {\parindent \z@ \raggedright \normalfont
+ \ifnum \c@secnumdepth >\m@ne
+ \huge\bfseries\SS@chapnumfont{\@chapapp\space \thechapter}%
+ \par\nobreak
+ \vskip 20\p@
+ \fi
+ \interlinepenalty\@M
+ \raggedright \normalfont
+ \Huge \bfseries \SS@chaptitlefont {#1}\par\nobreak
+ \vskip 40\p@
+ }}
+\def\@makeschapterhead#1{%
+ \vspace*{50\p@}%
+ {\parindent \z@ \raggedright
+ \normalfont
+ \interlinepenalty\@M
+ \Huge \bfseries \SS@chaptitlefont {#1}\par\nobreak
+ \vskip 40\p@
+ }}%
+}{}
+%% End code re-defining chapter stuff for report class
+%% Chapter code from |book.cls| 1997/10/10 v1.3x
+\@ifclassloaded{book}{%
+\SS@oclto{1}{chapter modifications for book class}%
+\def\@makechapterhead#1{%
+ \vspace*{50\p@}%
+ {\parindent \z@ \raggedright \normalfont
+ \ifnum \c@secnumdepth >\m@ne
+ \if@mainmatter
+ \huge\bfseries\SS@chapnumfont {\@chapapp\space \thechapter}%
+ \par\nobreak
+ \vskip 20\p@
+ \fi
+ \fi
+ \interlinepenalty\@M
+ \raggedright \normalfont
+ \Huge \bfseries \SS@chaptitlefont {#1}\par\nobreak
+ \vskip 40\p@
+ }}
+\def\@makeschapterhead#1{%
+ \vspace*{50\p@}%
+ {\parindent \z@ \raggedright
+ \normalfont
+ \interlinepenalty\@M
+ \Huge \bfseries \SS@chaptitlefont {#1}\par\nobreak
+ \vskip 40\p@
+ }}%
+}{}
+%% End code redefining chapter stuff from book.cls
+%% Begin code redefining chapter stuff from scrreprt.cls
+\@ifclassloaded{scrreprt}{%
+\SS@oclto{1}{chapter modifications for scrreprt class}%
+\def\@makechapterhead#1{\chapterheadstartvskip%
+ {\size@chapter{\sectfont\SS@chapnumfont
+ \@hangfrom{\ifnum \c@secnumdepth >\m@ne%
+ \chapterformat\fi}%
+ {\raggedsection \interlinepenalty \@M \SS@chaptitlefont {#1}\par}}%
+ \nobreak\chapterheadendvskip
+ }}
+\def\@makeschapterhead#1{\chapterheadstartvskip%
+ {\parindent \z@ \raggedsection
+ \normalfont
+ \size@chapter\sectfont\SS@chaptitlefont {#1}\par
+ \nobreak\chapterheadendvskip
+ }}
+}{}
+%% End code redefining chapter stuff from scrreprt.cls
+%% Begin code redefining chapter stuff from scrbook.cls
+\@ifclassloaded{scrbook}{%
+\SS@oclto{1}{chapter modifications for scrbook class}%
+\def\@makechapterhead#1{\chapterheadstartvskip%
+ {\size@chapter{\sectfont\SS@chapnumfont
+ \@hangfrom{\ifnum \c@secnumdepth >\m@ne%
+ \if@mainmatter \chapterformat\fi\fi}%
+ {\raggedsection \interlinepenalty \@M \SS@chaptitlefont {#1}\par}}%
+ \nobreak\chapterheadendvskip
+ }}
+\def\@makeschapterhead#1{\chapterheadstartvskip%
+ {\parindent \z@ \raggedsection
+ \normalfont
+ \size@chapter\sectfont\SS@chaptitlefont {#1}\par
+ \nobreak\chapterheadendvskip
+ }}%
+ }{}
+ % \end{macrocode}
+%% End code redefining chapter stuff from scrbook.cls
+%% Part code from book.cls 1997/10/10 v1.3x
+\@ifclassloaded{book}{%
+\SS@oclto{1}{part modifications for book class}%
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >-2\relax
+ \refstepcounter{part}%
+ \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ \markboth{}{}%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >-2\relax
+ \huge\bfseries\SS@partnumberfont {\partname~\thepart}%
+ \par
+ \vskip 20\p@
+ \fi
+ \centering \normalfont
+ \Huge \bfseries \SS@parttitlefont {#2}\par}%
+ \@endpart}
+\def\@spart#1{%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont \Huge \bfseries \SS@parttitlefont {#1}\par}%
+ \@endpart}
+}{}
+%% End code redefining part stuff from |book.cls|
+%% Part code from |article.cls| 1997/10/10 v1.3x
+\@ifclassloaded{article}{%
+\SS@oclto{1}{part modifications for article class}%
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >\m@ne
+ \refstepcounter{part}%
+ \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ {\parindent \z@ \raggedright
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >\m@ne
+ \Large\bfseries\SS@partnumberfont {\partname~\thepart}%
+ \par\nobreak
+ \fi
+ \raggedright \normalfont
+ \huge \bfseries \SS@parttitlefont {#2}%
+ \markboth{}{}\par}%
+ \nobreak
+ \vskip 3ex
+ \@afterheading}
+\def\@spart#1{%
+ {\parindent \z@ \raggedright
+ \interlinepenalty \@M
+ \normalfont
+ \huge \bfseries \SS@parttitlefont {#1}\par}%
+ \nobreak
+ \vskip 3ex
+ \@afterheading}
+}{}
+%% End code redefining part stuff from |article.cls|
+%% Part code from |report.cls| 1997/10/10 v1.3x
+\@ifclassloaded{report}{%
+\SS@oclto{1}{part modifications for report class}%
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >-2\relax
+ \refstepcounter{part}%
+ \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ \markboth{}{}%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >-2\relax
+ \huge\bfseries\SS@partnumberfont {\partname~\thepart}%
+ \par
+ \vskip 20\p@
+ \fi
+ \centering \normalfont
+ \Huge \bfseries \SS@parttitlefont {#2}\par}%
+ \@endpart}
+\def\@spart#1{%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \Huge \bfseries \SS@parttitlefont {#1}\par}%
+ \@endpart}
+}{}
+%% End code redefining part stuff from report.cls
+\@tempswafalse
+\@ifclassloaded{scrreprt}{\@tempswatrue}{}
+\@ifclassloaded{scrbook} {\@tempswatrue}{}
+%% Part code from |scrbook.cls| 1998/07/17 v2.5e
+\if@tempswa%
+\SS@oclto{1}{part modifications for scrreprt and scrbook classes}%
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >-2\relax
+ \refstepcounter{part}\@maybeasf%
+ \addcontentsline{toc}{part}{\protect\numberline{\thepart}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ \chaptermark{}
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >-2\relax
+ \size@partnumber\sectfont\SS@partnumberfont\partformat
+ \par
+ \vskip 20\p@
+ \fi
+ \size@part\sectfont\SS@parttitlefont {#2}\par}%
+ \@endpart}
+\def\@spart#1{%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \size@part\sectfont\SS@parttitlefont {#1}\chaptermark{}\par}%
+ \@endpart}%
+ \fi
+%% End part code from |scrbook.cls| 1998/07/17 v2.5e
+%% Part code from |scrartcl.cls| 1998/07/17 v2.5e
+\@ifclassloaded{scrartcl}{%
+\SS@oclto{1}{part modifications for scrartcl classes}%
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >\m@ne
+ \refstepcounter{part}\@maybeasf%
+ \addcontentsline{toc}{part}{\protect\numberline{\thepart}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ {\parindent \z@ \raggedright
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >\m@ne
+ \size@partnumber\sectfont\SS@partnumberfont\partformat
+ \par\nobreak
+ \fi
+ \size@part\sectfont\SS@parttitlefont {#2}%
+ \sectionmark{}\par}%
+ \nobreak
+ \vskip 3ex
+ \@afterheading}
+\def\@spart#1{%
+ {\parindent \z@ \raggedright
+ \interlinepenalty \@M
+ \normalfont
+ \size@part\sectfont\SS@parttitlefont {#1}\sectionmark{}\par}%
+ \nobreak
+ \vskip 3ex
+ \@afterheading}%
+ }{}
+\endinput
+%%
+%% End of file `sectsty.sty'.
diff --git a/doc/latex_sty/stdclsdv.sty b/doc/latex_sty/stdclsdv.sty
new file mode 100644
index 0000000000000000000000000000000000000000..9eb86645028600a37705ebf03aa913172c728394
--- /dev/null
+++ b/doc/latex_sty/stdclsdv.sty
@@ -0,0 +1,75 @@
+%%
+%% This is file `stdclsdv.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% stdclsdv.dtx (with options: `usc')
+%%
+%% Copyright 1999 Peter R. Wilson
+%%
+%% This program is provided under the terms of the
+%% LaTeX Project Public License distributed from CTAN
+%% archives in directory macros/latex/base/lppl.txt.
+%%
+%% Author: Peter Wilson (CUA and NIST)
+%% now at: peter.r.wilson@boeing.com
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{stdclsdv}[1999/01/18 v1.0 Sectional divisions]
+\newif\ifSCDknownclass\SCDknownclassfalse
+\newif\ifSCDpart\SCDparttrue
+\newif\ifSCDchapter\SCDchapterfalse
+\newif\ifSCDsection\SCDsectiontrue
+\newif\ifSCDnodivs\SCDnodivsfalse
+\@ifclassloaded{book}{\SCDknownclasstrue\SCDchaptertrue}{}
+\@ifclassloaded{report}{\SCDknownclasstrue\SCDchaptertrue}{}
+\@ifclassloaded{article}{\SCDknownclasstrue}{}
+\@ifclassloaded{proc}{\SCDknownclasstrue}{}
+\@ifclassloaded{ltxdoc}{\SCDknownclasstrue}{}
+\@ifclassloaded{slides}{\SCDknownclasstrue
+ \SCDnodivstrue\SCDpartfalse\SCDsectionfalse}{}
+\@ifclassloaded{letter}{\SCDknownclasstrue
+ \SCDnodivstrue\SCDpartfalse\SCDsectionfalse}{}
+\ifSCDknownclass\else
+ \SCDnodivstrue
+ \ifx\part\undefined
+ \SCDpartfalse
+ \else
+ \SCDnodivsfalse
+ \fi
+ \ifx\chapter\undefined\else
+ \SCDchaptertrue \SCDnodivsfalse
+ \fi
+ \ifx\section\undefined
+ \SCDsectionfalse
+ \else
+ \SCDnodivsfalse
+ \fi
+\fi
+\newcommand{\SCDquit}{}
+\newif\ifSCDSameDefinition
+\def\SCDCheckCommand{\@star@or@long%
+ \SCDSameDefinitiontrue% changed from CheckCommand
+ \@SCD@check@command}
+ \@onlypreamble\SCDCheckCommand
+\def\@SCD@check@command#1#2#{\@SCD@check@c#1{#2}}
+ \@onlypreamble\@SCD@check@command
+\long\def\@SCD@check@c#1#2#3{%
+ \expandafter\let\csname\string\reserved@a\endcsname\relax
+ \renew@command\reserved@a#2{#3}%
+ \@ifundefined{\string\reserved@a}%
+ {\@SCD@check@eq#1\reserved@a}%
+ {\expandafter\@SCD@check@eq
+ \csname\string#1\expandafter\endcsname
+ \csname\string\reserved@a\endcsname}}
+ \@onlypreamble\@SCD@check@c
+\def\@SCD@check@eq#1#2{%
+ \ifx#1#2\else
+ \SCDSameDefinitionfalse % changed from CheckCommand
+ \fi}
+ \@onlypreamble\@SCD@check@eq
+\endinput
+%%
+%% End of file `stdclsdv.sty'.
+
diff --git a/doc/latex_sty/tocloft.sty b/doc/latex_sty/tocloft.sty
new file mode 100644
index 0000000000000000000000000000000000000000..d3978f433061321478ecc1ab37b1a313695fd6af
--- /dev/null
+++ b/doc/latex_sty/tocloft.sty
@@ -0,0 +1,737 @@
+
+%%
+%% This is file `tocloft.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% tocloft.dtx (with options: `usc')
+%%
+%% Copyright 1998, 1999 Peter R. Wilson
+%%
+%% This program is provided under the terms of the
+%% LaTeX Project Public License distributed from CTAN
+%% archives in directory macros/latex/base/lppl.txt.
+%%
+%% Author: Peter Wilson (CUA and NIST)
+%% now at: peter.r.wilson@boeing.com
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{tocloft}[2000/02/11 v1.1 parameterised ToC, etc., typesetting]
+\RequirePackage{stdclsdv}
+\providecommand{\PRWPackageNote}[2]{%
+ \GenericWarning{%
+ (#1)\@spaces\@spaces\@spaces\@spaces
+ }{%
+ Package #1 Note: #2%
+ }%
+}
+\providecommand{\PRWPackageNoteNoLine}[2]{%
+ \PRWPackageNote{#1}{#2\@gobble}%
+}
+\ifSCDnodivs
+ \PackageWarning{tocloft}%
+ {I don't recognize any sectional divisions so I'll do nothing}
+ \renewcommand{\SCDquit}{\endinput}
+\fi
+\SCDquit
+\ifSCDknownclass\else
+ \PackageWarning{tocloft}%
+ {I don't recognize the class but I'll do my best}
+ \ifSCDnodivs
+ \PackageWarning{tocloft}%
+ {I don't recognize any sectional divisions so I'll do nothing}
+ \renewcommand{\SCDquit}{\endinput}
+ \else
+ \ifSCDchapter
+ \PRWPackageNoteNoLine{tocloft}{The document class has chapter divisions}
+ \else
+ \ifSCDsection
+ \PRWPackageNoteNoLine{tocloft}{The document class has section divisions}
+ \else
+ \PackageWarning{tocloft}%
+ {The class has neither chapters nor sections, so I'll do nothing}
+ \renewcommand{\SCDquit}{\endinput}
+ \fi
+ \fi
+ \fi
+\fi
+\SCDquit
+\newif\if@cfttocbibind
+\AtBeginDocument{%
+ \@ifpackageloaded{tocbibind}{\@cfttocbibindtrue}{\@cfttocbibindfalse}
+ \if@cfttocbibind
+ \@ifpackagelater{tocbibind}{1998/11/16}{}{%
+ \PackageWarning{tocloft}{%
+You are using a version of the tocbibind package\MessageBreak
+that is not compatible with tocloft.\MessageBreak
+The results may be surprising.\MessageBreak
+Consider installing the current version of tocbibind.}}
+ \fi
+}
+\newif\if@cftnctoc\@cftnctocfalse
+\DeclareOption{titles}{\@cftnctoctrue}
+ %% \ProcessOptions\relax
+\newcommand{\cftmarktoc}{%
+ \@mkboth{\MakeUppercase\contentsname}{\MakeUppercase\contentsname}}
+\newcommand{\cftmarklof}{%
+ \@mkboth{\MakeUppercase\listfigurename}{\MakeUppercase\listfigurename}}
+\newcommand{\cftmarklot}{%
+ \@mkboth{\MakeUppercase\listtablename}{\MakeUppercase\listtablename}}
+\newcommand{\@cfttocstart}{%
+ \ifSCDchapter
+ \if@twocolumn
+ \@restonecoltrue\onecolumn
+ \else
+ \@restonecolfalse
+ \fi
+ \fi}
+\newcommand{\@cfttocfinish}{%
+ \ifSCDchapter
+ \if@restonecol\twocolumn\fi
+ \fi}
+\newcommand{\@cftdobibtoc}{%
+ \if@dotoctoc
+ \if@bibchapter
+ \addcontentsline{toc}{chapter}{\contentsname}
+ \else
+ \addcontentsline{toc}{\@tocextra}{\contentsname}
+ \fi
+ \fi}
+\AtBeginDocument{%
+\if@cftnctoc\else
+ \renewcommand{\tableofcontents}{%
+ \@cfttocstart
+ \par
+ \begingroup
+ \parindent\z@ \parskip\z@
+ \@cftmaketoctitle
+ \if@cfttocbibind
+ \@cftdobibtoc
+ \fi
+ \@starttoc{toc}%
+ \endgroup
+ \@cfttocfinish}
+\fi
+}
+\newcommand{\@cftmaketoctitle}{%
+ \vspace*{\cftbeforetoctitleskip}
+ \interlinepenalty\@M
+ {\cfttoctitlefont\contentsname}{\cftaftertoctitle}
+ \cftmarktoc
+ \par\nobreak
+ \vskip \cftaftertoctitleskip
+ \@afterheading}
+\newlength{\cftbeforetoctitleskip}
+\newlength{\cftaftertoctitleskip}
+\ifSCDchapter
+ \setlength{\cftbeforetoctitleskip}{50pt}
+ \setlength{\cftaftertoctitleskip}{40pt}
+\else
+ \setlength{\cftbeforetoctitleskip}{3.5ex \@plus 1ex \@minus .2ex}
+ \setlength{\cftaftertoctitleskip}{2.3ex \@plus.2ex}
+\fi
+\ifSCDchapter
+ \newcommand{\cfttoctitlefont}{\normalfont\Huge\bfseries}
+\else
+ \newcommand{\cfttoctitlefont}{\normalfont\Large\bfseries}
+\fi
+\newcommand{\cftaftertoctitle}{}
+\newcommand{\cftsetpnumwidth}[1]{\renewcommand{\@pnumwidth}{#1}}
+\newcommand{\cftsetrmarg}[1]{\renewcommand{\@tocrmarg}{#1}}
+\newcommand{\cftdot}{.}
+\newcommand{\cftdotfill}[1]{%
+ \leaders\hbox{$\m@th\mkern #1 mu\hbox{\cftdot}\mkern #1 mu$}\hfill}
+\newcommand{\cftdotsep}{4.5}
+\newcommand{\cftnodots}{10000}
+\newcommand{\cftparfillskip}{\parfillskip=0pt plus1fil}
+\renewcommand{\numberline}[1]{%
+ \hb@xt@\@tempdima{\@cftbsnum #1\@cftasnum\hfil}\@cftasnumb}
+\newcommand{\@cftbsnum}{}
+\newcommand{\@cftasnum}{}
+\newcommand{\@cftasnumb}{}
+\newif\if@cftdopart
+\ifSCDpart
+\renewcommand*{\l@part}[2]{%
+ \@cftdopartfalse
+ \ifnum \c@tocdepth >-2\relax
+ \ifSCDchapter
+ \@cftdoparttrue
+ \fi
+ \ifnum \c@tocdepth >\m@ne
+ \ifSCDchapter\else
+ \@cftdoparttrue
+ \fi
+ \fi
+ \fi
+ \if@cftdopart
+ \ifSCDchapter
+ \addpenalty{-\@highpenalty}%
+ \else
+ \addpenalty\@secpenalty
+ \fi
+ \addvspace{\cftbeforepartskip}%
+ \@tempdima \cftpartnumwidth\relax
+ \let\@cftbsnum \cftpartpresnum
+ \let\@cftasnum \cftpartaftersnum
+ \let\@cftasnumb \cftpartaftersnumb
+ \begingroup
+ \parindent \z@ \rightskip \@pnumwidth
+ \parfillskip -\@pnumwidth
+ {\leavevmode
+ {\cftpartfont #1}{\cftpartleader}
+ {\hb@xt@\@pnumwidth{\hss {\cftpartpagefont #2}}}\cftpartafterpnum}\par
+ \nobreak
+ \ifSCDchapter
+ \global\@nobreaktrue
+ \everypar{\global\@nobreakfalse\everypar{}}%
+ \else
+ \if@compatibility
+ \global\@nobreaktrue
+ \everypar{\global\@nobreakfalse\everypar{}}%
+ \fi
+ \fi
+ \endgroup
+ \fi}
+\fi
+\newlength{\cftbeforepartskip}
+ \setlength{\cftbeforepartskip}{2.25em \@plus\p@}
+\newlength{\cftpartnumwidth}
+ \setlength{\cftpartnumwidth}{3em}
+\newcommand{\cftpartfont}{\large\bfseries}
+\newcommand{\cftpartpresnum}{}
+\newcommand{\cftpartaftersnum}{}
+\newcommand{\cftpartaftersnumb}{}
+\newcommand{\cftpartleader}{\large\bfseries\cftdotfill{\cftpartdotsep}}
+\newcommand{\cftpartdotsep}{\cftnodots}
+\newcommand{\cftpartpagefont}{\large\bfseries}
+\newcommand{\cftpartafterpnum}{}
+\ifSCDchapter
+\renewcommand*{\l@chapter}[2]{%
+ \ifnum \c@tocdepth >\m@ne
+ \addpenalty{-\@highpenalty}%
+ \vskip \cftbeforechapskip
+ {\leftskip \cftchapindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftchapindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftchapnumwidth\relax
+ \let\@cftbsnum \cftchappresnum
+ \let\@cftasnum \cftchapaftersnum
+ \let\@cftasnumb \cftchapaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftchapfont #1}\nobreak
+ {\cftchapleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftchappagefont #2}\cftchapafterpnum\par}%
+ \fi}
+\fi
+\newlength{\cftbeforechapskip}
+ \setlength{\cftbeforechapskip}{1.0em \@plus\p@}
+\newlength{\cftchapindent}
+ \setlength{\cftchapindent}{0em}
+\newlength{\cftchapnumwidth}
+ \setlength{\cftchapnumwidth}{1.5em}
+\newcommand{\cftchapfont}{\bfseries}
+\newcommand{\cftchappresnum}{}
+\newcommand{\cftchapaftersnum}{}
+\newcommand{\cftchapaftersnumb}{}
+\newcommand{\cftchapleader}{\bfseries\cftdotfill{\cftchapdotsep}}
+\newcommand{\cftchapdotsep}{\cftnodots}
+\newcommand{\cftchappagefont}{\bfseries}
+\newcommand{\cftchapafterpnum}{}
+\renewcommand*{\l@section}[2]{%
+ \ifnum \c@tocdepth >\z@
+ \ifSCDchapter
+ \vskip \cftbeforesecskip
+ \else
+ \addpenalty\@secpenalty
+ \addvspace{\cftbeforesecskip}
+ \fi
+ {\leftskip \cftsecindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftsecindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftsecnumwidth\relax
+ \let\@cftbsnum \cftsecpresnum
+ \let\@cftasnum \cftsecaftersnum
+ \let\@cftasnumb \cftsecaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftsecfont #1}\nobreak
+ {\cftsecleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftsecpagefont #2}\cftsecafterpnum\par}%
+ \fi}
+\newlength{\cftbeforesecskip}
+\ifSCDchapter
+ \setlength{\cftbeforesecskip}{\z@ \@plus.2\p@}
+\else
+ \setlength{\cftbeforesecskip}{1.0em \@plus\p@}
+\fi
+\newlength{\cftsecindent}
+\ifSCDchapter
+ \setlength{\cftsecindent}{1.5em}
+\else
+ \setlength{\cftsecindent}{0em}
+\fi
+\newlength{\cftsecnumwidth}
+\ifSCDchapter
+ \setlength{\cftsecnumwidth}{2.3em}
+\else
+ \setlength{\cftsecnumwidth}{1.5em}
+\fi
+\ifSCDchapter
+ \newcommand{\cftsecfont}{\normalfont}
+\else
+ \newcommand{\cftsecfont}{\bfseries}
+\fi
+\newcommand{\cftsecpresnum}{}
+\newcommand{\cftsecaftersnum}{}
+\newcommand{\cftsecaftersnumb}{}
+\ifSCDchapter
+ \newcommand{\cftsecleader}{\normalfont\cftdotfill{\cftsecdotsep}}
+\else
+ \newcommand{\cftsecleader}{\bfseries\cftdotfill{\cftsecdotsep}}
+\fi
+\ifSCDchapter
+ \newcommand{\cftsecdotsep}{\cftdotsep}
+\else
+ \newcommand{\cftsecdotsep}{\cftnodots}
+\fi
+\ifSCDchapter
+ \newcommand{\cftsecpagefont}{\normalfont}
+\else
+ \newcommand{\cftsecpagefont}{\bfseries}
+\fi
+\newcommand{\cftsecafterpnum}{}
+\renewcommand*{\l@subsection}[2]{%
+ \ifnum \c@tocdepth >\@ne
+ \vskip \cftbeforesubsecskip
+ {\leftskip \cftsubsecindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftsubsecindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftsubsecnumwidth\relax
+ \let\@cftbsnum \cftsubsecpresnum
+ \let\@cftasnum \cftsubsecaftersnum
+ \let\@cftasnumb \cftsubsecaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftsubsecfont #1}\nobreak
+ {\cftsubsecleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftsubsecpagefont #2}\cftsubsecafterpnum\par}%
+ \fi}
+\newlength{\cftbeforesubsecskip}
+ \setlength{\cftbeforesubsecskip}{\z@ \@plus.2\p@}
+\newlength{\cftsubsecindent}
+\ifSCDchapter
+ \setlength{\cftsubsecindent}{3.8em}
+\else
+ \setlength{\cftsubsecindent}{1.5em}
+\fi
+\newlength{\cftsubsecnumwidth}
+\ifSCDchapter
+ \setlength{\cftsubsecnumwidth}{3.2em}
+\else
+ \setlength{\cftsubsecnumwidth}{2.3em}
+\fi
+\newcommand{\cftsubsecfont}{\normalfont}
+\newcommand{\cftsubsecpresnum}{}
+\newcommand{\cftsubsecaftersnum}{}
+\newcommand{\cftsubsecaftersnumb}{}
+\newcommand{\cftsubsecleader}{\normalfont\cftdotfill{\cftsubsecdotsep}}
+\newcommand{\cftsubsecdotsep}{\cftdotsep}
+\newcommand{\cftsubsecpagefont}{\normalfont}
+\newcommand{\cftsubsecafterpnum}{}
+\renewcommand*{\l@subsubsection}[2]{%
+ \ifnum \c@tocdepth >\tw@
+ \vskip \cftbeforesubsubsecskip
+ {\leftskip \cftsubsubsecindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftsubsubsecindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftsubsubsecnumwidth\relax
+ \let\@cftbsnum \cftsubsubsecpresnum
+ \let\@cftasnum \cftsubsubsecaftersnum
+ \let\@cftasnumb \cftsubsubsecaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftsubsubsecfont #1}\nobreak
+ {\cftsubsubsecleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftsubsubsecpagefont #2}\cftsubsubsecafterpnum\par}%
+ \fi}
+\newlength{\cftbeforesubsubsecskip}
+ \setlength{\cftbeforesubsubsecskip}{\z@ \@plus.2\p@}
+\newlength{\cftsubsubsecindent}
+\ifSCDchapter
+ \setlength{\cftsubsubsecindent}{7.0em}
+\else
+ \setlength{\cftsubsubsecindent}{3.8em}
+\fi
+\newlength{\cftsubsubsecnumwidth}
+\ifSCDchapter
+ \setlength{\cftsubsubsecnumwidth}{4.1em}
+\else
+ \setlength{\cftsubsubsecnumwidth}{3.2em}
+\fi
+\newcommand{\cftsubsubsecfont}{\normalfont}
+\newcommand{\cftsubsubsecpresnum}{}
+\newcommand{\cftsubsubsecaftersnum}{}
+\newcommand{\cftsubsubsecaftersnumb}{}
+\newcommand{\cftsubsubsecleader}{\normalfont\cftdotfill{\cftsubsubsecdotsep}}
+\newcommand{\cftsubsubsecdotsep}{\cftdotsep}
+\newcommand{\cftsubsubsecpagefont}{\normalfont}
+\newcommand{\cftsubsubsecafterpnum}{}
+\renewcommand*{\l@paragraph}[2]{%
+ \ifnum \c@tocdepth >3\relax
+ \vskip \cftbeforeparaskip
+ {\leftskip \cftparaindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftparaindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftparanumwidth\relax
+ \let\@cftbsnum \cftparapresnum
+ \let\@cftasnum \cftparaaftersnum
+ \let\@cftasnumb \cftparaaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftparafont #1}\nobreak
+ {\cftparaleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftparapagefont #2}\cftparaafterpnum\par}%
+ \fi}
+\newlength{\cftbeforeparaskip}
+ \setlength{\cftbeforeparaskip}{\z@ \@plus.2\p@}
+\newlength{\cftparaindent}
+\ifSCDchapter
+ \setlength{\cftparaindent}{10em}
+\else
+ \setlength{\cftparaindent}{7.0em}
+\fi
+\newlength{\cftparanumwidth}
+\ifSCDchapter
+ \setlength{\cftparanumwidth}{5em}
+\else
+ \setlength{\cftparanumwidth}{4.1em}
+\fi
+\newcommand{\cftparafont}{\normalfont}
+\newcommand{\cftparapresnum}{}
+\newcommand{\cftparaaftersnum}{}
+\newcommand{\cftparaaftersnumb}{}
+\newcommand{\cftparaleader}{\normalfont\cftdotfill{\cftparadotsep}}
+\newcommand{\cftparadotsep}{\cftdotsep}
+\newcommand{\cftparapagefont}{\normalfont}
+\newcommand{\cftparaafterpnum}{}
+\renewcommand*{\l@subparagraph}[2]{%
+ \ifnum \c@tocdepth >4\relax
+ \vskip \cftbeforesubparaskip
+ {\leftskip \cftsubparaindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftsubparaindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftsubparanumwidth\relax
+ \let\@cftbsnum \cftsubparapresnum
+ \let\@cftasnum \cftsubparaaftersnum
+ \let\@cftasnumb \cftsubparaaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftsubparafont #1}\nobreak
+ {\cftsubparaleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftsubparapagefont #2}\cftsubparaafterpnum\par}%
+ \fi}
+\newlength{\cftbeforesubparaskip}
+ \setlength{\cftbeforesubparaskip}{\z@ \@plus.2\p@}
+\newlength{\cftsubparaindent}
+\ifSCDchapter
+ \setlength{\cftsubparaindent}{12em}
+\else
+ \setlength{\cftsubparaindent}{10em}
+\fi
+\newlength{\cftsubparanumwidth}
+\ifSCDchapter
+ \setlength{\cftsubparanumwidth}{6em}
+\else
+ \setlength{\cftsubparanumwidth}{5em}
+\fi
+\newcommand{\cftsubparafont}{\normalfont}
+\newcommand{\cftsubparapresnum}{}
+\newcommand{\cftsubparaaftersnum}{}
+\newcommand{\cftsubparaaftersnumb}{}
+\newcommand{\cftsubparaleader}{\normalfont\cftdotfill{\cftsubparadotsep}}
+\newcommand{\cftsubparadotsep}{\cftdotsep}
+\newcommand{\cftsubparapagefont}{\normalfont}
+\newcommand{\cftsubparaafterpnum}{}
+\newcommand{\@cftdobiblof}{%
+ \if@dotoclof
+ \if@bibchapter
+ \addcontentsline{toc}{chapter}{\listfigurename}
+ \else
+ \addcontentsline{toc}{\@tocextra}{\listfigurename}
+ \fi
+ \fi}
+\AtBeginDocument{
+\if@cftnctoc\else
+\renewcommand{\listoffigures}{%
+ \@cfttocstart
+ \par
+ \begingroup
+ \parindent\z@ \parskip\z@
+ \@cftmakeloftitle
+ \if@cfttocbibind
+ \@cftdobiblof
+ \fi
+ \@starttoc{lof}%
+ \endgroup
+ \@cfttocfinish}
+\fi
+}
+\newcommand{\@cftmakeloftitle}{%
+ \vspace*{\cftbeforeloftitleskip}
+ \interlinepenalty\@M
+ {\cftloftitlefont\listfigurename}{\cftafterloftitle}
+ \cftmarklof
+ \par\nobreak
+ \vskip \cftafterloftitleskip
+ \@afterheading}
+\newlength{\cftbeforeloftitleskip}
+\newlength{\cftafterloftitleskip}
+\ifSCDchapter
+ \setlength{\cftbeforeloftitleskip}{50pt}
+ \setlength{\cftafterloftitleskip}{40pt}
+\else
+ \setlength{\cftbeforeloftitleskip}{3.5ex \@plus 1ex \@minus .2ex}
+ \setlength{\cftafterloftitleskip}{2.3ex \@plus.2ex}
+\fi
+\ifSCDchapter
+ \newcommand{\cftloftitlefont}{\normalfont\Huge\bfseries}
+\else
+ \newcommand{\cftloftitlefont}{\normalfont\Large\bfseries}
+\fi
+\newcommand{\cftafterloftitle}{}
+\renewcommand*{\l@figure}[2]{%
+ \vskip \cftbeforefigskip
+ {\leftskip \cftfigindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftfigindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftfignumwidth\relax
+ \let\@cftbsnum \cftfigpresnum
+ \let\@cftasnum \cftfigaftersnum
+ \let\@cftasnumb \cftfigaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftfigfont #1}\nobreak
+ {\cftfigleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftfigpagefont #2}\cftfigafterpnum\par}%
+ }
+\newlength{\cftbeforefigskip}
+ \setlength{\cftbeforefigskip}{\z@ \@plus.2\p@}
+\newlength{\cftfigindent}
+ \setlength{\cftfigindent}{1.5em}
+\newlength{\cftfignumwidth}
+ \setlength{\cftfignumwidth}{2.3em}
+\newcommand{\cftfigfont}{\normalfont}
+\newcommand{\cftfigpresnum}{}
+\newcommand{\cftfigaftersnum}{}
+\newcommand{\cftfigaftersnumb}{}
+\newcommand{\cftfigleader}{\normalfont\cftdotfill{\cftfigdotsep}}
+\newcommand{\cftfigdotsep}{\cftdotsep}
+\newcommand{\cftfigpagefont}{\normalfont}
+\newcommand{\cftfigafterpnum}{}
+\newcommand{\@cftdobiblot}{%
+ \if@dotoclot
+ \if@bibchapter
+ \addcontentsline{toc}{chapter}{\listtablename}
+ \else
+ \addcontentsline{toc}{\@tocextra}{\listtablename}
+ \fi
+ \fi}
+\AtBeginDocument{
+\if@cftnctoc\else
+\renewcommand{\listoftables}{%
+ \@cfttocstart
+ \par
+ \begingroup
+ \parindent\z@ \parskip\z@
+ \@cftmakelottitle
+ \if@cfttocbibind
+ \@cftdobiblot
+ \fi
+ \@starttoc{lot}%
+ \endgroup
+ \@cfttocfinish}
+\fi
+}
+\newcommand{\@cftmakelottitle}{%
+ \vspace*{\cftbeforelottitleskip}
+ \interlinepenalty\@M
+ {\cftlottitlefont\listtablename}{\cftafterlottitle}
+ \cftmarklot
+ \par\nobreak
+ \vskip \cftafterlottitleskip
+ \@afterheading}
+\newlength{\cftbeforelottitleskip}
+\newlength{\cftafterlottitleskip}
+\ifSCDchapter
+ \setlength{\cftbeforelottitleskip}{50pt}
+ \setlength{\cftafterlottitleskip}{40pt}
+\else
+ \setlength{\cftbeforelottitleskip}{3.5ex \@plus 1ex \@minus .2ex}
+ \setlength{\cftafterlottitleskip}{2.3ex \@plus.2ex}
+\fi
+\ifSCDchapter
+ \newcommand{\cftlottitlefont}{\normalfont\Huge\bfseries}
+\else
+ \newcommand{\cftlottitlefont}{\normalfont\Large\bfseries}
+\fi
+\newcommand{\cftafterlottitle}{}
+\renewcommand*{\l@table}[2]{%
+ \vskip \cftbeforetabskip
+ {\leftskip \cfttabindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cfttabindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cfttabnumwidth\relax
+ \let\@cftbsnum \cfttabpresnum
+ \let\@cftasnum \cfttabaftersnum
+ \let\@cftasnumb \cfttabaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cfttabfont #1}\nobreak
+ {\cfttableader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cfttabpagefont #2}\cfttabafterpnum\par}%
+ }
+\newlength{\cftbeforetabskip}
+ \setlength{\cftbeforetabskip}{\z@ \@plus.2\p@}
+\newlength{\cfttabindent}
+ \setlength{\cfttabindent}{1.5em}
+\newlength{\cfttabnumwidth}
+ \setlength{\cfttabnumwidth}{2.3em}
+\newcommand{\cfttabfont}{\normalfont}
+\newcommand{\cfttabpresnum}{}
+\newcommand{\cfttabaftersnum}{}
+\newcommand{\cfttabaftersnumb}{}
+\newcommand{\cfttableader}{\normalfont\cftdotfill{\cfttabdotsep}}
+\newcommand{\cfttabdotsep}{\cftdotsep}
+\newcommand{\cfttabpagefont}{\normalfont}
+\newcommand{\cfttabafterpnum}{}
+\newcommand{\@cftl@subfig}{
+\renewcommand*{\l@subfigure}[2]{%
+ \ifnum \c@lofdepth > 1\relax
+ \vskip \cftbeforesubfigskip
+ {\leftskip \cftsubfigindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftsubfigindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftsubfignumwidth\relax
+ \let\@cftbsnum \cftsubfigpresnum
+ \let\@cftasnum \cftsubfigaftersnum
+ \let\@cftasnumb \cftsubfigaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftsubfigfont ##1}\nobreak
+ {\cftsubfigleader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftsubfigpagefont ##2}\cftsubfigafterpnum\par}%
+ \fi
+ }
+}
+\newcommand{\@cftsetsubfig}{
+\newlength{\cftbeforesubfigskip}
+ \setlength{\cftbeforesubfigskip}{\z@ \@plus.2\p@}
+\newlength{\cftsubfigindent}
+ \setlength{\cftsubfigindent}{3.8em}
+\newlength{\cftsubfignumwidth}
+ \setlength{\cftsubfignumwidth}{2.5em}
+\newcommand{\cftsubfigfont}{\normalfont}
+\newcommand{\cftsubfigpresnum}{}
+\newcommand{\cftsubfigaftersnum}{}
+\newcommand{\cftsubfigaftersnumb}{}
+\newcommand{\cftsubfigleader}{\normalfont\cftdotfill{\cftsubfigdotsep}}
+\newcommand{\cftsubfigdotsep}{\cftdotsep}
+\newcommand{\cftsubfigpagefont}{\normalfont}
+\newcommand{\cftsubfigafterpnum}{}
+}
+
+\newcommand{\@cftl@subtab}{
+\renewcommand*{\l@subtable}[2]{%
+ \ifnum \c@lotdepth > 1\relax
+ \vskip \cftbeforesubtabskip
+ {\leftskip \cftsubtabindent\relax
+ \rightskip \@tocrmarg
+ \parfillskip -\rightskip
+ \parindent \cftsubtabindent\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima \cftsubtabnumwidth\relax
+ \let\@cftbsnum \cftsubtabpresnum
+ \let\@cftasnum \cftsubtabaftersnum
+ \let\@cftasnumb \cftsubtabaftersnumb
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {\cftsubtabfont ##1}\nobreak
+ {\cftsubtableader}
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\cftsubtabpagefont ##2}\cftsubtabafterpnum\par}%
+ \fi
+ }
+}
+\newcommand{\@cftsetsubtab}{
+\newlength{\cftbeforesubtabskip}
+ \setlength{\cftbeforesubtabskip}{\z@ \@plus.2\p@}
+\newlength{\cftsubtabindent}
+ \setlength{\cftsubtabindent}{3.8em}
+\newlength{\cftsubtabnumwidth}
+ \setlength{\cftsubtabnumwidth}{2.5em}
+\newcommand{\cftsubtabfont}{\normalfont}
+\newcommand{\cftsubtabpresnum}{}
+\newcommand{\cftsubtabaftersnum}{}
+\newcommand{\cftsubtabaftersnumb}{}
+\newcommand{\cftsubtableader}{\normalfont\cftdotfill{\cftsubtabdotsep}}
+\newcommand{\cftsubtabdotsep}{\cftdotsep}
+\newcommand{\cftsubtabpagefont}{\normalfont}
+\newcommand{\cftsubtabafterpnum}{}
+}
+
+\DeclareOption{subfigure}{%
+ \@cftsetsubfig\@cftsetsubtab
+ \AtBeginDocument{\@cftl@subfig\@cftl@subtab}
+}
+\ProcessOptions\relax
+
+\newcommand{\cftchapterprecis}[1]{%
+ \cftchapterprecishere{#1}
+ \cftchapterprecistoc{#1}}
+\newcommand{\cftchapterprecishere}[1]{%
+ \vspace*{-2\baselineskip}
+ \begin{quote}\textit{#1}\end{quote}}
+\newcommand{\cftchapterprecistoc}[1]{\addtocontents{toc}{%
+ {\leftskip \cftchapindent\relax
+ \advance\leftskip \cftchapnumwidth\relax
+ \rightskip \@tocrmarg\relax
+ \textit{#1}\protect\par}}}
+\newcommand{\cftlocalchange}[3]{%
+ \addtocontents{#1}{\protect\cftsetpnumwidth{#2} \protect\cftsetrmarg{#3}}}
+\newcommand{\cftaddtitleline}[4]{%
+ \addtocontents{#1}{\protect\contentsline{#2}{#3}{#4}}}
+\newcommand{\cftaddnumtitleline}[5]{%
+ \addtocontents{#1}%
+ {\protect\contentsline{#2}{\protect\numberline{#3}{\protect\ignorespaces #4}}{#5}}}
+\endinput
+%%
+%% End of file `tocloft.sty'.
diff --git a/doc/latex_sty/xtab.sty b/doc/latex_sty/xtab.sty
new file mode 100644
index 0000000000000000000000000000000000000000..9eb86645028600a37705ebf03aa913172c728394
--- /dev/null
+++ b/doc/latex_sty/xtab.sty
@@ -0,0 +1,75 @@
+%%
+%% This is file `stdclsdv.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% stdclsdv.dtx (with options: `usc')
+%%
+%% Copyright 1999 Peter R. Wilson
+%%
+%% This program is provided under the terms of the
+%% LaTeX Project Public License distributed from CTAN
+%% archives in directory macros/latex/base/lppl.txt.
+%%
+%% Author: Peter Wilson (CUA and NIST)
+%% now at: peter.r.wilson@boeing.com
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{stdclsdv}[1999/01/18 v1.0 Sectional divisions]
+\newif\ifSCDknownclass\SCDknownclassfalse
+\newif\ifSCDpart\SCDparttrue
+\newif\ifSCDchapter\SCDchapterfalse
+\newif\ifSCDsection\SCDsectiontrue
+\newif\ifSCDnodivs\SCDnodivsfalse
+\@ifclassloaded{book}{\SCDknownclasstrue\SCDchaptertrue}{}
+\@ifclassloaded{report}{\SCDknownclasstrue\SCDchaptertrue}{}
+\@ifclassloaded{article}{\SCDknownclasstrue}{}
+\@ifclassloaded{proc}{\SCDknownclasstrue}{}
+\@ifclassloaded{ltxdoc}{\SCDknownclasstrue}{}
+\@ifclassloaded{slides}{\SCDknownclasstrue
+ \SCDnodivstrue\SCDpartfalse\SCDsectionfalse}{}
+\@ifclassloaded{letter}{\SCDknownclasstrue
+ \SCDnodivstrue\SCDpartfalse\SCDsectionfalse}{}
+\ifSCDknownclass\else
+ \SCDnodivstrue
+ \ifx\part\undefined
+ \SCDpartfalse
+ \else
+ \SCDnodivsfalse
+ \fi
+ \ifx\chapter\undefined\else
+ \SCDchaptertrue \SCDnodivsfalse
+ \fi
+ \ifx\section\undefined
+ \SCDsectionfalse
+ \else
+ \SCDnodivsfalse
+ \fi
+\fi
+\newcommand{\SCDquit}{}
+\newif\ifSCDSameDefinition
+\def\SCDCheckCommand{\@star@or@long%
+ \SCDSameDefinitiontrue% changed from CheckCommand
+ \@SCD@check@command}
+ \@onlypreamble\SCDCheckCommand
+\def\@SCD@check@command#1#2#{\@SCD@check@c#1{#2}}
+ \@onlypreamble\@SCD@check@command
+\long\def\@SCD@check@c#1#2#3{%
+ \expandafter\let\csname\string\reserved@a\endcsname\relax
+ \renew@command\reserved@a#2{#3}%
+ \@ifundefined{\string\reserved@a}%
+ {\@SCD@check@eq#1\reserved@a}%
+ {\expandafter\@SCD@check@eq
+ \csname\string#1\expandafter\endcsname
+ \csname\string\reserved@a\endcsname}}
+ \@onlypreamble\@SCD@check@c
+\def\@SCD@check@eq#1#2{%
+ \ifx#1#2\else
+ \SCDSameDefinitionfalse % changed from CheckCommand
+ \fi}
+ \@onlypreamble\@SCD@check@eq
+\endinput
+%%
+%% End of file `stdclsdv.sty'.
+
diff --git a/doc/markdown/MANUAL.md b/doc/markdown/MANUAL.md
new file mode 100644
index 0000000000000000000000000000000000000000..d6cf4bb8e20884ba425b1a3c919db9bd91433622
--- /dev/null
+++ b/doc/markdown/MANUAL.md
@@ -0,0 +1,897 @@
+\section Contents
+
+ -
+ \ref sect_fluid_eq
+
+ -
+ \ref sect_physical
+
+ - \ref sect_ddr
+ - \ref sect_elecpotfield
+ - \ref sect_rescaling
+
+
+ - \ref sect_bic
+ -
+ \ref sect_numeric
+
+ - \ref sect_dde
+ - \ref sect_dpe
+
+
+ - \ref sect_timestepping
+
+
+ -
+ \ref sect_refinement
+
+ - \ref sect_overview
+ - \ref sect_size_refinement
+ - \ref sect_criterion
+ - \ref sect_curvature
+ - \ref sect_fishpack
+ - \ref sect_Conclusions
+
+
+ -
+ \ref sect_software
+
+ - \ref sect_ARCoS_overview
+ -
+ \ref sect_IO
+
+ - \ref sect_sim
+ - \ref sect_input
+ - \ref sect_parameter
+ - \ref sect_needle
+ - \ref sect_output
+ - \ref sect_structure
+ - \ref sect_source
+
+
+
+
+
+
+\section sect_fluid_eq Fluid model
+
+\subsection sect_physical Physical model
+
+\subsubsection sect_ddr Drift-diffusion-reaction equations
+
+[1]: http://homepages.cwi.nl/~ebert/CaroJCP06.pdf "Montijn et al."
+[2]: http://homepages.cwi.nl/~ebert/LuqueAPL07.pdf "Luque et al."
+[3]: http://homepages.cwi.nl/~ebert/StrBranchLuque2011.pdf "Luque et al.(2011)"
+[4]: http://homepages.cwi.nl/~ebert/JCP-Li-12.pdf "Li et al."
+[5]: http://arxiv.org/abs/1301.1552 "Teunissen et al.".
+[6]: http:// "PhD Thesis Wormeester(to appear in 2013)"
+[7]: http://alexandria.tue.nl/repository/books/598717.pdf "PhD Thesis Montijn"
+[8]: http://homepages.cwi.nl/~willem/ "Monograph by Hundsdorfer and Verwer"
+[9]: http://www2.cisl.ucar.edu/resources/legacy/fishpack "Fishpack"
+[10]: http://www2.cisl.ucar.edu/resources/legacy/fishpack90 "Fish90"
+[11]: http://www.amazon.com/books/dp/3540194622 "Y. P. Raizer, Gas Discharge Physics"
+[12]: http://www.stack.nl/~dimitri/doxygen/manual/index.html "Doxygen"
+
+
+In a fluid model of a streamer, we replace the individual particles in the
+system by a density function \f${n}(\mathbf{r},t)\f$.
+The temporal evolution of this density function is governed by the physical
+processes of the system and this model takes the form of a set of partial
+differential equations (PDEs).
+The derivation of this so-called classical streamer model starts from the
+continuity equation. For particle species \f$i\f$, we have:
+\f[
+ \frac{\partial n_i(\mathbf{r},t)}{\partial t} + \nabla \cdot \mathbf{j}_i(\mathbf{r},t) = S_i(\mathbf{r},t).
+\f]
+
+Here \f$S_i(\mathbf{r},t)\f$ represents the total of all sources and sinks of
+species \f$i\f$. \f$\mathbf{j}_i(\mathbf{r},t)\f$ is the term for the particle
+current density of species \f$i\f$.
+Particles can drift and diffuse as described by the following
+expression for the particle current density
+\f$\mathbf{j}_i\f$:
+\f[
+ \mathbf{j}_i(\mathbf{r},t) = \mu_i n_i(\mathbf{r},t) \mathbf{E}(\mathbf{r},t) - D_i \nabla n_i (\mathbf{r},t).
+
+\f]
+In the above equation, the first term represents the particle drift due
+to the electric field, with \f$\mu_i\f$ the mobility coefficient of species \f$i\f$.
+The second term represents the diffusion of particles due to the spatial gradient in particle densities with diffusion coefficient \f$D_i\f$. These equations can be derived from the Boltzmann equation
+
+On the timescales involved, we consider only electrons to be mobile, while ions and neutrals remain stationary, which means that for heavy species, the [continuity equation](#continuity) is reduced to
+\f[
+ \frac{\partial n_i(\mathbf{r},t)}{\partial t} = S_i(\mathbf{r},t).
+\f]
+
+The sources and sinks in the first equation play a very important role in the dynamics of the streamer. In this model, the sources and sinks correspond to reactions between the different charged and neutral species present in the gas. The source term due to a single reaction is the product of the densities of the species involved in the reaction and the field-dependent rate coefficient for that reaction.
+
+As an example, the impact ionization reaction
+\f[
+ e^- + \mathbf{N}_2 \rightarrow 2 e^- + \mathbf{N}_2^+
+\f]
+is modeled by
+\f[
+ S_{ionization} = k_{ion}(|\mathbf{E}|) n_e [\mathbf{N}_2].
+\f]
+Here \f$n_e\f$ is the local electron density, \f$[\mbox{N}_2]\f$ the density of
+\f$\mbox{N}_2\f$ and \f$k_{ion}\f$ the reaction coefficient for impact ionization
+depending on the magnitude of the local electric field.
+The value of \f$k\f$ can be determined in different ways, from experiments,
+theoretical calculations or simulations.
+The traditional approximation suggested by Townsend
+uses an empirical expression for the impact ionization term, see the
+[book by Y. P. Raizer, "Gas Discharge Physics"][11]:
+\f[
+ \frac{dn_e}{dt} = n_e \mu_e |\mathbf{E}| \alpha_0 e^{-E_0 / |\mathbf{E}|},
+\f]
+where \f$\mu_e\f$ is the electron mobility coefficient,
+\f$\mathbf{E}\f$ is the local electric field and \f$\alpha_0\f$ and \f$E_0\f$ are
+parameters that can be determined by fitting experimental data.
+In gases that contain an electronegative admixture, such as \f$\mathbf{O}_2\f$, the process of
+attachment can provide a sink for the electron density through the following
+reactions:
+\f[
+ e^- + \mathbf{O}_2 \rightarrow \mathbf{O} + \mathbf{O}^-
+\f]
+\f[
+ e^- + \mathbf{O}_2 + \mathbf{O}_2 \rightarrow \mathbf{O}_2^- + \mathbf{O}_2
+\f]
+The first attachment process is dissociative attachment, the second an example
+of a 3-body attachment (a 3-body attachment can also occur with an oxygen and nitrogen
+molecule).
+In the case of the 3-body attachment, the reaction rate scales with the square of the oxygen density:
+\f[
+ S_{3-body-att} = k_{3-body-att}(|\mathbf{E}|) n_e [\mathbf{O}_2]^2.
+\f]
+Further ionization losses can occur via one or more recombination processes,
+but these typically have a timescale that is much longer than the timescale of
+streamer development and propagation and are therefore primarily interesting for
+the evolution of the charge density after a streamer discharge,
+as discussed in [PhD Thesis Wormeester(to appear in 2013)][6], Chapter 5.
+
+
+
+In gases with attachment, detachment may occur, resulting in an additional
+source of electrons.
+In gases that contain both nitrogen and oxygen, the photoionization process
+provides a non-local source of electrons.
+Since photoionization is non-local, it can not be modelled by simple reaction
+equations such as the ones for impact ionization.
+Instead, the local contribution of photoionization is calculated by spatially
+integrating contributions from the entire domain.
+The commonly used model for photoionization and the approximations made to make
+this model suitable for simulation are discussed in
+[PhD Thesis Wormeester(to appear in 2013)][6], Chapter 3, section Photoionization.
+
+The reaction model for streamer simulations can be very minimal or very extended,
+with many species and reactions, including metastables and various excited states.
+The complexity of the reaction model depends on the purpose of the simulations.
+For negative streamers in nitrogen, a model containing no more than three species
+(\f$\mbox{e}^-\f$, \f$\mbox{N}_2\f$ and \f$\mbox{N}_2^+\f$) and one reaction
+(impact ionization)
+is sufficient to simulate the dynamics of the streamer head, see [Montijn et al][1].
+For more detailed studies of the streamer chemistry, the reaction model should be
+as complete as possible.
+
+
+\subsubsection sect_elecpotfield Electric potential and field
+
+The streamer evolves under the influence of an electric field, which consists
+of an externally applied electric field and the electric field generated by
+space charges.
+These space charges are present at the head of the streamer as well as on the edge of the streamer channel.
+For the further propagation of the streamer, the enhanced electric field in front of the streamer, generated by the space charge in the streamer head is essential.
+We compute the net charge density
+\f$q(\mathbf{r},t)\f$:
+\f[
+ q(\mathbf{r},t) = e \sum_i q_i n_i(\mathbf{r},t),
+\f]
+where for species \f$i\f$, \f$n_i\f$
+denotes the density function of these species and \f$q_i\f$ the charge of
+a particle in units of the electron charge \f$e\f$.
+From this we compute the potential by solving the Poisson equation
+\f[
+ \nabla^2 \phi(\mathbf{r},t) = \frac{q(\mathbf{r},t)}{\epsilon_0}
+\f]
+and the electric field
+\f[
+ \mathbf{E}(\mathbf{r},t) = -\nabla \phi(\mathbf{r},t).
+\f]
+
+\subsubsection sect_rescaling Rescaling to dimensionless units
+
+The classical fluid model for streamers can be rescaled to dimensionless units and
+it is with these units that the code used in this documentation works.
+We refer the interested reader to the
+[PhD thesis of Gideon Wormeester (to appear in 2013)][6].
+From the [Townsend](#townsend_ionization) approximation for ionization,
+a characteristic field and length scale
+emerges: \f$E_0\f$ and \f$l_0 = \alpha_0^{-1}\f$, respectively.
+The characteristic velocity follows from the drift velocity of electrons
+in the characteristic field,
+\f[
+ E_0: v_0 = \mu_e E_0.
+\f]
+
+The characteristic number density follows from the [Poisson](#Poisson) equation.
+Values for \f$\alpha_0\f$, \f$E_0\f$ and \f$\mu_e\f$ were obtained from
+[PhD Thesis Montijn][7]
+and are at standard temperature and pressure:
+\f{eqnarray*}
+ \alpha_0 & \simeq & 4332 \quad \mbox{cm}^{-1}\\
+ E_0 & \simeq & 2 \times 10^5 \quad \mbox{V} \mbox{cm}^{-1}\\
+ \mu_e & \simeq & 380 \quad \mbox{~cm}^2 \mbox{V}^{-1} \mbox{s}^{-1}.
+\f}
+
+When we insert these values in the characteristic scales, we obtain the values with which to rescale the equations:
+\f{eqnarray*}
+ l_0 & \simeq & 2.3 \times 10^{-4} \quad \mbox{~cm}\\
+ t_0 & \simeq & 3.0 \times 10^{-12} \quad \mbox{~s}\\
+ n_0 & \simeq & 4.7 \times 10^{14} \quad \mbox{~cm}^{-3}\\
+ D_0 & \simeq & 1.8 \times 10^{4} \quad \mbox{~cm}^2 \mbox{s}^{-1}.
+\f}
+We can now make the appropriate substitutions
+(\f$t^d = t / t_0\f$ and similarly for the other variables;
+the superscript \f${\;}^d\f$ will be used to indicate that a variable is
+in dimensionless form, where this is not clear from the context.
+For clarity of reading, the superscript \f${\;}^d\f$ will be omitted where it is clear that variables are
+dimensionless) to obtain the classical fluid equations in
+dimensionless continuity form:
+\f[
+ \partial_{t} + \nabla \cdot \mathbf{j}_i = S_i,
+\f]
+where \f$t\f$ is the dimensionless time, \f$\mathbf{j}_i\f$ the dimensionless
+particle density current for species \f$i\f$ and \f$S_i\f$ the dimensionless source term
+for species \f$i\f$.
+\f$S_i\f$ is obtained by rewriting reaction equations such as the
+[impact ionization reaction](#reaction_imp_ion) equation in dimensionless form,
+where we remark that all rate-coefficients should also be rescaled.
+The particle density current \f$\mathbf{j}_i\f$ is obtained by rescaling
+[expression](#current_dens) into
+equation
+\f[
+ \mathbf{j}_i = -\mu_i n_i \mathbf{E} - D_i \nabla n_i,
+\f]
+where \f$\mathbf{E}\f$ is the dimensionless electric field and \f$n_i\f$,
+\f$D_i\f$ and \f$\mu_i\f$ are the dimensionless particle density,
+diffusion coefficient and mobility respectively of species \f$i\f$.
+We find that in dimensionless units \f$\mu_i\f$ is equal to 1 while for heavy particles
+\f$\mu_i\f$ is taken as 0, since heavy particles are assumed to be stationary in
+this model.
+The [dimensionless current density equation](#current_dens_dimless) can therefore be simplified to
+\f[
+ \mathbf{j}_e = -n_e \mathbf{E} - D_e \nabla n_e
+\f]
+for electrons and \f$ \mathbf{j}_i = 0 \f$ for heavy particles.
+The expression for the [charge density equation](#charge_dens) \f$q\f$, is rescaled to
+\f[
+ q(\mathbf{r},t) = \sum_i q_i n_i(\mathbf{r},t).
+\f]
+The [Poisson](#Poisson) equation is rescaled to
+\f[
+ \nabla^2 \phi = q.
+\f]
+We remark that although the code
+described here internally
+works with the dimensionless equations and variables described in this section,
+all results are presented in regular units unless otherwise noted.
+Input parameters for the simulation code are expected to be in dimensionless units.
+Finally we note that the rescaling to dimensionless units does not change
+the structure of the equations, it is merely a rescaling to a different
+set of units, where the dimensionless units yield a set of equations where some
+constants (such as \f$e\f$, \f$\epsilon_0\f$, \f$\mu_e\f$) become unity.
+
+\subsection sect_bic Boundary and initial conditions
+
+
+We consider a cylindrical computational domain with coordinates:
+\f[
+(r,z,\theta) \in (0,L_r) \times (0,L_z) \times (0,2\pi).
+\f]
+Although the code described here is capable of performing full 3D calculations,
+we assume cylindrical symmetry to greatly simplify the computations.
+For any spatially dependent function \f$f(r,z,\theta)\f$, we assume:
+\f$\partial_{\theta} f(r,z,\theta) = 0\f$.
+Consequently, the coordinate system for our computations is limited to
+\f$(0,L_r) \times (0,L_z)\f$.
+We consider a setup with a powered electrode at \f$z = L_z\f$ and a grounded
+electrode at \f$z = 0\f$.
+If the powered electrode is a plate, the following boundary conditions are used for
+the electric potential \f$\phi(r,z,t)\f$:
+
+\f[
+ \begin{array}{llll}
+ \forall z \; & \partial_r \phi(0,z,t) & = & 0\\
+ \forall r \; & \phi(L_r,z,t) & = & 0\\
+ \forall z \; & \phi(r,0,t) & = & 0\\
+ \forall r \; & \phi(r,L_z,t) & = & \phi_0
+ \end{array}
+\f]
+
+with \f$\phi_0\f$ the potential applied to the powered electrode.
+If the powered electrode is a needle protruding from a plate, the needle has the
+same potential \f$\phi_0\f$ as the plate.
+
+
+\par Figure 1. Schematic of the computational setup.
+
+In Figure 1., the shaded rectangle represents the computational domain for
+the fluid equations, the thick horizontal lines the two planar electrodes
+with the needle and its parameters depicted at the anode.
+The area between the two planar electrodes is the computational domain
+for the Poisson equation.
+The needle is simulated by a single point charge, \f$Q\f$, chosen such
+that \f$\phi =\phi_0\f$ in the point \f$P\f$, which is the tip of the needle.
+The calculation assumes cylindrical symmetry around the needle axis
+represented by the dashed-dotted line.
+
+For the density equations, we use homogeneous Neumann conditions on all edges:
+\f[
+ \partial_r n(0,z,t) = \partial_r n(L_r,z,t) = \partial_z n(r,0,t) = \partial_z n(r,L_z,t) = 0,
+\f]
+where we remark that if the powered electrode is a needle, the computational domain
+for the density equations is smaller than the computational domain for the Poisson
+equation and the \f$L_z\f$ values for both domains are not equal.
+This difference is a requirement of the numerical implementation of the needle
+electrode and is further detailed in section \ref sect_needle.
+
+While the boundary conditions mentioned above are the ones used by Wormeester,
+the code that was used can also handle different choices of boundary conditions:
+both homogeneous Neumann and homogeneous Dirichlet boundary conditions are available
+for the top (\f$z = L_z\f$), bottom (\f$z = 0\f$) and right (\f$r = L_r\f$)
+edges of the domain for both the densities and the potential.
+The Neumann condition on the central axis of the cylindrical domain is required
+for symmetry reasons.
+
+As initial conditions for particle densities, two types of seeds are implemented in
+the code. A homogeneous seed, with a constant density over the entire domain and a
+Gaussian seed of the form
+\f[
+ n(r,z,0) = n_{max} \mbox{exp}(-\frac{r^2 + (z - z_0)^2}{\sigma^2}).
+\f]
+Here \f$z_0\f$ specifies the \f$z\f$-coordinate of the maximum of the seed
+(which is located on the symmetry axis with \f$r = 0\f$), where the density is
+\f$n_{max}\f$. \f$\sigma\f$ is a measure of the radius of the seed, it is the distance
+at which the density drops to \f$e^{-1}\f$ of the maximum value.
+
+In typical streamer simulations, a seed of electrons and positive ions is placed at the tip of the needle to initiate the discharge. Other than these Gaussian seeds and the neutral background gas, initial particle densities are zero with the possible exception of added background ionization, a homogeneous density of negative and positive ions. The initial distribution of electrons and ions is charge neutral at every point of the domain.
+
+\subsection sect_numeric Numerical method
+
+The physical equations in section \ref sect_fluid_eq are to be solved numerically.
+The computational code we have applied for this uses finite volume methods to solve
+a discretized version of the physical equations.
+Here we give a basic summary of the numerical technique used.
+For more details, the reader is referred to the work of [Montijn et al.][1],
+upon which the current code is based.
+
+\subsubsection sect_dde Discretization of density equations
+
+The [dimensionless continuity ](#continuity_dimless) and the [dimensionless current density](#current_dens_dimless) equations
+are discretized using finite volume methods and solved on a uniform rectangular grid with cells:
+\f[
+ C_{ij} = [(i - 1) \Delta r, i \Delta r] \times [(j - 1) \Delta z, j \Delta z]\left(i = 1 , \cdots , \frac{L_r}{\Delta r}, j = 1 , \cdots , \frac{L_z}{\Delta z}\right),
+\f]
+where \f$L_r\f$ and \f$L_z\f$ are the \f$r\f$- and \f$z\f$-dimensions of the grid and \f$\Delta r\f$ and \f$\Delta z\f$ the size of a cell in \f$r\f$- and \f$z\f$-direction, respectively. Particle density distributions are represented by their value in the cell center, which can be seen as an average over the cell. For some species \f$n\f$, we use \f$n_{i,j}\f$ to denote the density at the cell center \f$C_{ij}\f$. For sake of clarity of notation we omit the superscript \f$^d\f$ indicating that variables are in dimensionless units.
+
+The discretized continuity equations in cylindrical coordinates, with cylindrical symmetry (\f$\partial_{\theta} f = 0\f$) assumed, have the following form:
+\f[
+ \begin{array}{ll}
+ \frac{d n_{i,j}}{d t} = & \frac{1}{r_i \Delta r} \Big(r_{i - \frac{1}{2}} F^a_{i - \frac{1}{2},j} - r_{i + \frac{1}{2}} F^a_{i + \frac{1}{2},j} + r_{i - \frac{1}{2}} F^d_{i - \frac{1}{2},j} - r_{i + \frac{1}{2}} F^d_{i + \frac{1}{2},j}\Big) + \\
+ & \frac{1}{\Delta z} \Big(F^a_{i,j - \frac{1}{2}} - F^a_{i,j + \frac{1}{2}} + F^d_{i,j - \frac{1}{2}} - F^d_{i,j + \frac{1}{2}}\Big) + S_{i,j}.
+\end{array}
+\f]
+Here \f$F^a\f$ and \f$F^d\f$ represent the advective and diffusive fluxes across the cell boundaries. Since we assume ions and neutral particles to be stationary, these terms are nonzero only for electrons. For heavy particles, only the source term \f$S_{ij}\f$ remains.
+
+The advective flux, \f$F^a\f$ uses an upwind scheme with flux limiting and is defined as follows:
+\f[
+ \begin{array}{ll}
+F^a_{i + \frac{1}{2},j} = & E^+_{r; ~ i + \frac{1}{2},j} \Big[ n_{i,j} + \psi(P_{i,j})(n_{i+1,j} - n_{i,j}) \Big] \\
+& E^-_{r; ~ i + \frac{1}{2},j} \Big[ n_{i + 1,j} + \psi(\frac{1}{P_{i+1,j}})(n_{i,j} - n_{i+1,j}) \Big]
+\end{array}
+\f]
+
+\f[
+ \begin{array}{ll}
+ F^a_{i,j + \frac{1}{2}} = & E^+_{z; ~ i,j + \frac{1}{2}} \Big[ n_{i,j} + \psi(Q_{i,j})(n_{i,j+1} - n_{i,j}) \Big] \\
+ & E^-_{z; ~ i,j + \frac{1}{2}} \Big[ n_{i,j + 1} + \psi(\frac{1}{Q_{i,j+1}})(n_{i,j} - n_{i,j+1}) \Big],
+\end{array}
+\f]
+where \f$E^+ = max(-E,0)\f$ and \f$E^- = min(-E,0)\f$ are used to distinguish the upwind directions for the components of the electric field, \f$E_r\f$ and \f$E_z\f$, and we have
+\f[
+\begin{array}{lll}
+ P_{i,j} & = & \frac{n_{i,j} - n_{i-1,j}}{n_{i+1,j} - n_{i,j}}\\
+ Q_{i,j} & = & \frac{n_{i,j} - n_{i,j-1}}{n_{i,j+1} - n_{i,j}}.
+\end{array}
+\f]
+\f$\psi\f$ is the Koren limiter function:
+\f[
+ \psi(x) = max(0, min(1, \frac{1}{3} + \frac{x}{6}, x)).
+\f]
+The diffusive flux \f$F^d\f$ is calculated using a second-order central differences scheme:
+\f[
+\begin{array}{lll}
+ F^d_{i + \frac{1}{2},j} & = & \frac{D}{\Delta r}(n_{i,j} - n_{i+1,j})\\
+ F^d_{i,j + \frac{1}{2}} & = & \frac{D}{\Delta z}(n_{i,j} - n_{i,j+1})
+\end{array}
+\f]
+and the reaction term \f$S_{i,j}\f$ is computed as
+\f[
+ S_{i,j} = \sum_{A~\in~{reactions}} \Big[ k_A(|\mathbf{E}|_{i,j}) \prod_{s~\in~{Spec(A)}} n_{s; i,j} \Big]
+\f]
+where \f$k_A\f$ denotes the field-dependent reaction rate coefficient of
+reaction \f$A\f$, and \f$Spec(A)\f$ the set of species that appear as an input
+for reaction \f$A\f$.
+
+\subsubsection sect_dpe Discretization of the Poisson equation
+
+We compute the net charge \f$q_{i,j}\f$ in a cell center by adding up the contributions from the individual charged species:
+\f[
+ q_{i,j} = \sum_{s~\in~{species}} n_{s; i,j} q_s.
+\f]
+With this net charge, the electric potential \f$\phi\f$ can be computed in the cell centers through a second-order central approximation of the dimensionless Poisson equation:
+\f[
+ q_{i,j} = \frac{\phi_{i+1,j} - 2 \phi_{i,j} + \phi_{i-1,j}}{\Delta r^2} + \frac{\phi_{i+1,j} - \phi_{i-1,j}}{2r_{i,j} \Delta r} + \frac{\phi_{i,j+1} - 2 \phi_{i,j} + \phi_{i,j-1}}{\Delta z^2}.
+\f]
+From the potential we can compute the components of the electric field from \f$\mathbf{E} = - \nabla \phi\f$ in the cell boundaries:
+\f[
+\begin{array}{lll}
+ E_{r; ~ i + \frac{1}{2},j} & = & \frac{\phi_{i,j} - \phi_{i+1,j}}{\Delta r}\\
+ E_{z; ~ i,j + \frac{1}{2}} & = & \frac{\phi_{i,j} - \phi_{i,j+1}}{\Delta r}.
+\end{array}
+\f]
+The electric field strength is determined at the cell center, so we have to compute the field components in the center by averaging the values on the boundaries after which we can compute the field strength:
+\f[
+ |\mathbf{E}|_{i,j} = \sqrt{\left(\frac{E_{r;i - \frac{1}{2},j} + E_{r;i + \frac{1}{2},j}}{2}\right)^2 + \left(\frac{E_{z;i,j - \frac{1}{2}} + E_{z;i,j + \frac{1}{2}}}{2}\right)^2}.
+\f]
+
+\subsection sect_timestepping Time stepping
+
+The code uses the explicit trapezoidal rule, a second order Runge-Kutta method,
+for the temporal discretization with time step \f$\Delta t\f$.
+Given some time step \f$t_i = i \Delta t\f$, density distributions
+\f$\mathbf{n}_i(r,z) = \mathbf{n}(r,z,t_i)\f$ and electric field
+\f$\mathbf{E}_i(r,z) = \mathbf{E}(r,z,t_i)\f$, the densities and field at the next
+time step, \f$t_{i+1}\f$ are calculated by first computing an intermediate result
+for the densities:
+\f[
+ \overline{\mathbf{n}}_{i+1} = \mathbf{n}_i + \Delta t F(\mathbf{n}_i, \mathbf{E}_i).
+\f]
+Using these intermediate densities, the potential can be computed by solving the
+Poisson equation, after which we obtain the intermediate electric field
+\f$\overline{\mathbf{E}}_{i+1}\f$.
+With this, we compute the final values of the densities at \f$t_{i+1}\f$:
+\f[
+ \mathbf{n}_{i+1} = \mathbf{n}_i + \frac{\Delta t}{2} F(\mathbf{n}_i, \mathbf{E}_i) + \frac{\Delta t}{2} F(\overline{\mathbf{n}}_{i+1}, \overline{\mathbf{E}}_{i+1}).
+\f]
+Finally, we again compute the potential and electric field, now using the final
+values of the densities.
+
+The size of the time step \f$\Delta t\f$ is determined by using a Courant-Friederichs-Levy (CFL) restriction for stability of the advection part of the equations:
+\f[
+ \texttt{max} E_r \frac{\Delta t}{\Delta r} + \texttt{max} E_z \frac{\Delta_t}{\Delta_z} < \nu_a.
+\f]
+There are additional restrictions from other diffusion and reaction parts of the
+equations, but they are dominated by the CFL criterior for the advection part, see
+[Montijn et al.][1].
+The value of \f$\nu_a\f$ is typically set to 0.25, which is well below the maximum
+required for stability.
+We refer the interested reader to the [Monograph by Hundsdorfer and Verwer][8].
+
+\section sect_refinement Overview of refinement strategies and criteria
+
+\subsection sect_overview Overview
+
+The \c ARCoS simulation code contains functions for adaptive grid refinement (also known as adaptive mesh refinement or AMR). Since streamers span different length scales, there is a need to simulate relatively large physical domains while still having high spatial resolution in areas such as the streamer head. To ensure that such large domains can be simulated without giving up resolution and accuracy, the numerical grid is refined adaptively at each time step. The equations are solved on a coarse grid, after which the solution is analyzed using refinement criteria to determine the areas where refinement is needed. The equations are then solved on the refined subgrids after which the process is iterated. Grid generation and grid refinement are performed separately for the density equations and for the Poisson equation.
+
+There are three main refinement criteria. The first two concern refinement of the density grids: Refinement based on the absolute value of \f$\mathbf{E}\f$ and refinement based on the curvature of densities (both charge density and particle density). The grids used by the [FISHPACK][9] solver use their own refinement scheme where the decision to refine is made if the difference between the solution on a grid and the solution on a finer grid exceeds a threshold. The [FISHPACK][9] solver is used for both the Poisson equation that determines the electric potential of the system and the Helmholtz equations for the photoionization reactions.
+
+\subsection sect_size_refinement Size of the refined areas of the density grids
+
+All CDR (Convection-Diffusion-Reaction, CDR is the shorthand term for the density part of the code) refinement criteria are on a per-point basis, which means that the question whether to refine or not is initially answered for every grid cell. This is inconvenient for several reasons, primarily due to the computational cost of such a scheme. The regions containing the streamer head will almost always need to be refined, it is not necessary to evaluate this point-by-point in these regions.
+
+To ease this problem, a minimal refinement area is defined by two parameters:\n
+\c cdr\_brick\_dr and \c cdr\_brick\_dz, see e.g., file default.cfg . The refinement module divides the grid it receives (this can be the coarsest grid covering the entire domain or a refined grid covering only part of the domain, the code and grid structure are recursive) into "bricks" of these dimensions and searches each brick for cells that match the refinement criteria. Once such a cell is found, the entire brick containing that cell is refined.
+
+For the [FISHPACK][9] module, a different approach is used. The refinement routine scans its input grid, starting at the top (\f$z = z_{min}\f$), going down per "line" (a set of cells with equal \f$z\f$d-coordinate). Once it finds a line with points that meet the refinement criterion it searches for the first line that does not contain any points that meet the criterion. It then refines the smallest rectangular area that contains all the points that meet the criterion. This process is repeated until the bottom (\f$z = z_{max}\f$) of the grid is reached.
+
+
+\par Figure 2. The nested structure of refined density grids
+
+In Figure 2.,
+the black squares represent grid cells at the coarsest level (level 0),
+the dark gray cells are the first refined sublevel (level 1). Two rectangular
+grids are included at this level, their shared border is indicated by the
+red line.
+The light gray cells show grids at a further refined level (level 2).
+
+
+\par Figure 3. The nested structure of refined Poisson grids
+
+The black grid, as shown in Figure 3. is the coarsest level, the dark gray cells are the first
+refined sublevel, the light gray cells show grids at a further refined level.
+Each grid has at most one subgrid.
+
+The tree of grids for the density equations may contain refined grids that are adjacent to each other. A schematic showing the nested structure of refined density grids is shown in [Figure 2.](#refinement_cdr). The red line in this figure indicates the shared border between two subgrids. For the Poisson-grids, such a structure is not possible and a grid can have at most one refined child-grid as depicted in [Figure 3.](#refinement_poisson).
+
+\subsection sect_criterion The |E| criterion
+
+The electric field criterion is the most simple of the three refinement criteria. It is an empirical criterion that is not directly motivated by the underlying numerics. A cell with coordinates \f$(r,z)\f$ qualifies for refinement if:
+\f[
+|\mathbf{E}(r,z)| > E_c
+\f]
+where \f$E_c\f$ is the threshold electric field strength for refinement. \f$E_c\f$ is a user-determined parameter that is provided in the input file for a run. Since this criterion is independent of the grid level or the cell size, once a cell meets the criterion at the coarsest level, it will also do so at every refined level. Because of this property, the user can limit the refinement depth that is reached through this criterion with the \c ref\_level\_eabs input parameter, see e.g., file default.cfg. Setting \c ref\_level\_eabs to 1, for example, restricts the refinement from the coarsest level to the first refined level due to the \f$|\mathbf{E}|\f$ criterion.
+
+The \f$|\mathbf{E}|\f$ criterion is inflexible in the sense that it requires the user to have advance knowledge of what the field strengths will be. A possible alternative would be to replace the fixed threshold value \f$E_c\f$ by a dimensionless fraction \f$c\f$ and refine if
+\f[
+|\mathbf{E}(r,z)| > c E_{max}
+\f]
+with \f$E_{max}\f$ the maximum electric field strength in the computational domain. Since the electric field criterion is mostly empirical, picking the right value for the refinement threshold may be a trial-and-error process.
+
+\subsection sect_curvature The curvature criteria
+
+There are two criteria that use the curvature of density functions in order to determine which areas to refine. If the curvature is large compared to the cell size, the numerics may become unreliable and it is desirable to work with a finer grid. For a density function \f$u(r,z)\f$ and a cell size \f$\triangle r \times \triangle z\f$ the curvature function \f$C_u(r,z)\f$ is a discretization of the second derivative of \f$u\f$ in cylindrical coordinates \f$(r,z)\f$:
+\f[
+ \begin{array}{ll}
+ C_u(r,z) = & \frac{1}{r + \frac{\triangle r}{2}}\Big[(r + \triangle r)\big(u(r + \triangle r, z) - u(r,z)\big) - r\big(u(r,z) - u(r - \triangle r,z)\big)\Big] + \\
+ & \big[u(r, z + \triangle z) - 2 u(r,z) + u(r, z - \triangle z)\big].
+ \end{array}
+\f]
+Rather than the absolute value of the curvature, the refinement module looks at the curvature relative to the global maximum, \f$Max(u)\f$. The final criterion then reads:\n
+\n
+\b Refine \f$(r,z)\f$ \b if \f$\frac{C_u(r,z)}{Max(u)} > C_t\f$\n
+\n
+with \f$C_t\f$ the threshold curvature. This refinement criterion is checked for two density functions \f$u\f$. The first is the (absolute) charge density function. Here an extra condition applies: the absolute value of the charge needs to exceed a certain threshold value (which is hard-coded) before a cell can qualify for refinement based on this criterion. Secondly, the curvature criterion is applied to the particle density functions. Since only mobile particles require a high spatial resolution, any immobile species are not considered in these criteria (which currently excludes all species other than electrons). The computational grids for these immobile species are simply the same as the grids used to solve the density equations for electrons.
+
+\subsection sect_fishpack FISHPACK refinement
+
+The [FISHPACK][9] module, for the Poisson equation and the photoionization equations, uses a different set of grids than the CDR module and with it a different refinement scheme. Initially, two grids are set up, one coarse and one fine grid (with the fine grid having twice the spatial resolution in each dimension, so 4 times the number of cells). The Poisson/Helmholtz equation is then solved on both grids and the solution of the coarse grid is interpolated onto the fine grid. A grid cell then qualifies for refinement if the absolute difference between the interpolated coarse solution and the fine solution (this difference is called the error) is more than some user-defined threshold. When refinement is needed, a new set of grids is determined using the strategy mentioned earlier and the process is repeated until either the desired accuracy is reached or the maximum number of allowed refinement levels is reached. Since the [FISHPACK][9] module was originally only used to solve the Poisson equation for the electrostatic problem and the value of the electric field
+is defined on the edge of a cell, a cell that does not meet the error-criterion still qualifies for refinement if its neighbor does meet the error-criterion.
+
+One limitation to this scheme is the limited number of grid cells that the [FISHPACK][9] routine can handle. Since [FISHPACK][9] applies a cyclic reduction scheme, the round-off error increases with the number of grid cells. This places a limit on the size of grids that [FISHPACK][9] can solve. Once the refinement module wants to create a grid that is larger than the so-called [FISHPACK][9] limit, the refinement attempt is rejected and the code relaxes the error threshold by a factor of 2 and again determines the area to refine, using the new threshold.
+
+To solve the photoionization problem, two Helmholtz equations need to be solved (For details on the implementation of photoionization, the reader is referred to [PhD Thesis Wormeester(to appear in 2013)][6], Chapter 3, section Photoionization
+and references therein). Each of the so-called "photo-terms" has its own characteristic absorption length, which depends on the gas density and oxygen ratio. The term with the short absorption length is often dominated by impact ionization in the head of the streamer, while the term with the long absorption length is the main contributor of electrons in front of the streamer head that are required for a positive streamer to propagate.
+
+The default behavior of the \c ARCoS code is to treat these two photoionization terms in the same manner as the Poisson problem when it comes to refinement: all user-definable parameters were equal. Since the term with the short absorption length gives rise to a solution that benefits strongly from high spatial resolution (due to the steep gradients) it will easily trigger the refinement criterion. However, it is this term that is dominated by impact ionization, see [Luque et al.][2],
+which reduces the relevance of accurate computation of this term. The user can therefore specify the refinement criteria for each of the two photoionization terms separately, providing the user with the means to allow the important, long absorption length term to benefit from high spatial resolution, while reducing the computational cost incurred by the less important term. However, in tests it was found that tuning the refinement criteria for the photoionization terms has very little effect on
+computational cost or results.
+
+\subsection sect_Conclusions Conclusion
+The adaptive refinement scheme of \c ARCoS allows for the simulation of large domains while maintaining high spatial resolution in regions that require this. A number of refinement parameters influence both the computational performance and the accuracy of the results, which means that the user has to monitor the results carefully. Since the refinement criteria were setup by
+[Montijn et al.][1].
+and
+[Luque et al.][2].
+for simulations of air and pure nitrogen, application of the code to other gases may require changes to the values of the various thresholds used in the refinement criteria. An example is high-purity oxygen, with a small nitrogen admixture. In such a gas, ionizing photons will have a very short characteristic absorption length and the calculation of the photoionization terms should be done with high accuracy close to the photon source, primarily the streamer head. However, the limitation of the [FISHPACK][9] refinement method does not permit several smaller, adjacent
+refined sub-grids, which makes it difficult to properly focus on the streamer head without including too much of the channel.
+
+\section sect_software ARCoS software
+
+\subsection sect_ARCoS_overview Basic overview and functionality
+
+The \c ARCoS simulation software was originally developed by Alejendro Luque as a more flexible version of the adaptive refinement code developed by Carolynne Montijn as described in [PhD Thesis Montijn][7].
+The original code by Montijn has been written in Fortran90, while \c ARCoS has been written in C.
+The original [FISHPACK][9] package used for solving the Poisson and Helmholtz equations is written
+in Fortran77 and was developed by Adams, Swarztrauber and Sweet. The \c ARCoS code is now compiled
+with [FISH90][10], a modernization of the original [FISHPACK][9], employing Fortran90 to slightly
+simplify and standardize the interface to some of the routines.
+
+\c ARCoS solves the fluid equations for streamers, described in section \ref sect_fluid_eq,
+on nested Cartesian grids using an adaptive mesh refinement technique.
+\c ARCoS allows for the simulation of both positive and negative streamers in the
+electrode configurations plate-plate and needle-plate.
+The needle-plate electrode geometry is included using a charge simulation method
+[Luque et al.][2].
+This method replaces the electrode needle by a single point charge, with the
+location and the size of the charge being updated at every time step to ensure the
+potential at needle tip remains fixed at the predetermined value.
+The limitation of this method is that the potential on the rest of the surface
+of the simulated needle will not be accurate.
+Consequently, the [continuity](#continuity) equation is only solved on
+a smaller grid, not containing the simulated needle.
+
+The effect of this is that \c ARCoS is not well suited for the study of the
+inception of streamers, as the area around the tip of the needle is not
+accurately modelled.
+However, since inception is often affected by the behavior
+of individual particles, the use of a particle code such as described in
+[Teunissen et al.][5] and [Li et al.][4].
+is recommended for studying streamer inception.
+The purpose of the \c ARCoS code is to study streamer propagation in the phase
+after the streamer has formed.
+Studies performed by [Luque et al.][2] show that the dynamics of
+streamers in later stages hardly depends on initial conditions.
+
+\c ARCoS allows the user full control over the numerical parameters of the
+simulation: grid size, refinement criteria and CFL numbers can be set by the user.
+The kinetic model, i.e., the list of particle species, their reactions and
+initial densities as well as the diffusion and mobility coefficients can be
+specified via a series of input files, allowing the user to fine-tune the properties
+of the gas in which the streamer is simulated, see configuration file input/kinetic_example.cfg.
+
+The \c ARCoS code can be downloaded from the website
+\c http://md-wiki.project.cwi.nl/
+
+\subsection sect_IO Handling the software, input and output
+
+\subsubsection sect_sim Starting a simulation
+
+Two input parameter files governs all details of the simulation:
+
+\li \b Physical \b parameters such as voltage, electrode configuration, size of the gap, etc.
+\li \b Numerical \b parameters such as grid size, refinement criteria, etc.
+\li \b Practical \b details like the directory name, where the output files should be stored and the interval at which output should be generated.
+
+[libconfig](http://www.hyperrealm.com/libconfig/), a free library for processing
+structured configuration files, is used for reading, manipulating and writing these files.
+The first file, stored as input/default.cfg, must contain the default values for the global variables.
+This file is a part of the streamer package distribution.
+The second file, say input/user_init.cfg, an example is given by input/example_user_init.cfg,
+has a structure analogously to input/default.cfg, and should contain the parameters which differ
+from the default values.
+The program delivers a configuration file, say input/example_user_continue.cfg with the updated parameters
+from input/user_init.cfg completed with the default values of input/default.cfg.
+
+Since the execution time of a single run will take on the order of several days, it is recommended to
+split the time period into smaller pieces, and restart the execution several times from the point
+where the previous run stopped.
+The easiest way to restart the simulation is
+ \li to copy the file input/user_continue.cfg into input/default.cfg, to be sure that equal values for the parameters are used,
+ \li to edit the file input/user_init.cfg, and change the \b \c t_end value, the \b \c restart value and the name of the \b \c load_file. See the end of of this section.
+
+The use of the configuration files construction has the following advantages:
+ \li recompilation of the code is not necessary in case of a restart
+ \li the user always has a clear overview of the parameter values used
+ \li results of different or continuing runs can be stored in different output directories,
+ as listed in the configuration file.
+ \li besides the parameter value also comment coupled to a parameter can be changed in the configuration files written by the user. The length of the comment must be restricted by 100 characters
+ \li the order of the parameters in the configuration file is free
+ \li the user has the possibility to control the simulation, many parameter values can be changed.
+
+It is easy to resume a simulation by using a set of output data as initial conditions.
+One has to adapt the parameter file with modified start and end times for the simulation.
+To start a \c ARCoS simulation use the following command from
+the directory containing the executables:
+\n
+\code
+ ./arcos > out.example 2> err.example
+\endcode
+\n
+
+The \c ARCoS program starts and it will print out the parameter values used:
+ \li in \c out.example
+ \li in input/user_continue.cfg.
+
+The program will print some extra information to file \c out.example, e.g., the step size and
+when a new set of output data has been written, and to which set of file names.
+Warnings and errors will be printed in file \c err.example. The program can terminate in three different ways:
+
+ \li The preset end-time is reached.
+ \li The program is terminated by the user.
+ \li The time-step (as determined by the Courant criterion for stability, more details to come) has dropped below a preset threshold. This usually points to some form of instability.
+
+In case the simulation runs on a PC or desktop machine, a convenient approach is to set a very
+large value for the end time and, rather than having the program determine when to terminate,
+keeping track of the progress of the streamer by checking the output files and manually terminating
+the program when the desired output is reached, e.g., the streamer has reached the electrode, or,
+ it has started to branch.
+In other cases, it may be necessary for the program to be able to run for a fixed amount of time.
+For example when it needs to exit gracefully, which is required for profiling software to work.
+Also in case of batch jobbing with a limited CPU wall clock time, like on most supercomputers,
+the end time must be chosen corresponding to the wall clock time.
+
+Data files with periodical data controlled by \c $output_dt, stored in directory \c $output\_dir,
+have names using the format \c variable.C123abc.tsv:
+ \tparam is a particle species or electric field, e.g. \c charge, \c d_dummyminus, \c d_electrons \n
+ \tparam <123> is the sequence number of that particular output dataset and \n
+ \tparam specified the subgrid the output belongs to.
+
+These files can be used to plot the solution or to restart the simulation. More details on this in the section on output files. To resume the example simulation from output set \c 123, call:
+\n
+\code
+./arcos example C123
+\endcode
+\n
+
+\subsubsection sect_input The input files
+
+
+File and directory handling:
+ \li \b \c kin\_input - The filename of the [libconfig](http://www.hyperrealm.com/libconfig/)
+ input file containing the species, seeds and reactions.
+ By convention, these files have the extension \b .cfg.
+ \li \b \c output\_dir - The directory where the output files will be stored.
+ This can be a relative path to the directory with the executable or an absolute
+ path. When the execution starts, the directory $output_dir must be present and writable.
+ \li \b \c output\_dt - The interval (in dimensionless units) with which an output dataset is to be saved.
+ Lower values mean more frequent output, which gives finer grained time-dependent
+ data at the cost of more disk space.
+
+Physical parameters:
+ \li \b \c L\_r - Radius of the physical domain in dimensionless units.
+ \li \b \c L\_z - Length of the physical domain. Does not include the needle.
+ \li \b \c has\_photoionization - Whether to enable the photoionization module.\n
+ So, if \b \c has\_photoionization = 1, photoionization is present,\n
+ if \b \c has\_photoionization = 0, execution without photoionization.\n
+ \li \b \c photoionization\_file - Filename of the file containing the photoionization parameters.\n These parameters are further explained in appendix~ref{app:photoionization_parameters}.
+
+\todo: WRITE APPENDIX
+
+ \li \b \c E0\_z, \b \c E0\_y, \b \c E0\_x - Components of the external electric field in dimensionless units. Since the electrodes are located at the top and bottom of the domain \f$(z = L_z\f$ and \f$z = 0)\f$, only \c E0\_z should be nonzero. Positive values of \c E0\_z will generate an electric field in the \f$^z\f$ direction, with the top electrode (at \f$z = L_z\f$) having a negative charge, generating negative streamers and vice verse.
+ \li \b \c pois\_inhom - Whether to use a needle-plane geometry or not.\n
+ If \b \c pois\_inhom = 1 then we have \b \c needle-plane case, \n
+ otherwise if \b \c pois\_inhom = 0 gives the plane-plane case. \n
+ See below for additional remarks regarding the needle-plane geometry.
+ \li \b \c needle\_length and \b \c needle\_radius - The length and radius of the needle in dimensionless units. Only applies when \b \c pois\_inhom = 1.
+ \li \b \c end\_t - Time at which the simulation will stop, in dimensionless units.
+ \li \b \c max\_ntheta - Number of azimuthal grid cells. Default \b \c max\_ntheta = 1. \n
+ \b \c max\_ntheta > 1 will activate the full 3D simulation (without cylindrical symmetry) using a pseudo-spectral method described in more detail in [Luque et al.(2011)][3].
+
+Numerical parameters:
+ \li \b \c gridpoints\_r, \b \c gridpoints\_z - Number of gridpoints in \f$r\f$ and \f$z\f$ direction for the density equations at the coarsest level.
+ \li \b \c cdr\_max\_level - Maximum number of refinement levels of the grid for the fluid equations. \n
+ \b \c cdr\_max\_level = 0 means no refinement.
+ \li \b \c cdr\_bnd\_bottom, \b \c cdr\_bnd\_top, \b \c cdr\_bnd\_right - Boundary condition for the density equations at the bottom \f$(z = 0)\f$, top \f$(z = L_z)\f$ and right \f$(r = L_r)\f$ of the domain. \n
+ \b \c cdr\_bnd\_xxx = 1 gives homogeneous Neumann boundary conditions, \n
+ \b \c cdr\_bnd\_xxx = -1 gives homogeneous Dirichlet boundary conditions.
+ \li \b \c pois\_max\_level - Maximum number of refinement levels of the grid for the Poisson equation.
+\b \c pois\_max\_level = 0 means no refinement.
+ \li \b \c pois\_bnd\_bottom, \b \c pois\_bnd\_top, \b \c pois\_bnd\_right - Boundary condition for the Poisson equation at the bottom \f$(z = 0)\f$, top \f$(z = L_z)\f$ and right \f$(r = L_r)\f$ of the domain. \n
+\b \c pois\_bnd\_xxx = 1 gives homogeneous Neumann boundary conditions, \n
+\b \c pois\_bnd\_xxx = -1 gives homogeneous Dirichlet.
+
+\subsubsection sect_parameter The parameter file
+
+In the parameter file input/default.cfg variables and their values are assigned with the following syntax
+\verbatim
+{
+ type = "type"; /* type can be a "string", a "double", an "int" */
+ name = "name"; /* variable name as defined in file include/parameters.h */
+ comment = "comment"; /* description of the variable, maximum of 100 characters */
+ value = "value"; /* value of type string, double or integer, related to "type" */
+},
+
+ # <-- this starts a comment-line, which is ignored.
+
+ # White lines are also ignored.
+ # String-values should be between quotes, numeric values should not
+ pi=3.14
+ # (Note: The above is an approximation)
+ # Scientific notation can be used:
+ pi_times_thousand=3.14E3
+\endverbatim
+
+Non-existent or misspelled parameters are ignored.
+Parameters are not required, every parameter has a default value, which can be found
+in function \b \c init_parameters of src/cstream.c.
+
+The following overview lists the parameters generally meant for testing purposes and changing them is not required for streamer simulations. Therefore they are best left at their default value.
+
+File and directory handling:
+ \li \b \c cdr\_output\_margin - Number of margin-cells to be added to the output of the density grids. 2 layers of ghost cells are added on the edge of the computational domain for the purpose of enforcing boundary conditions. With this parameter, these can be included in the output. Value must be smaller than or equal to 2. Default \b \c cdr\_output\_margin = 0.
+ \li \b \c pois\_output - Output the grids used in solving the Poisson equation? The grids used for the Poisson equation are different than those used for the density equations as detailed in section \ref sect_refinement. \b \c pois\_output = 0. Note that the absolute electric field is already saved as a density grid, so it is not required to set this parameter to 1 to obtain this data.
+ \li \b \c pois\_output\_margin - Number of margin-cells to be added to the output of the Poisson grids. Default \b \c pois\_output\_margin = 0. Note : \b \c pois\_output\_margin <= 2.
+
+Physical parameters:
+ \li \b \c start\_t - Initial time. This parameter is used when resuming simulations and is automatically updated in that case.
+
+Numerical parameters: \n
+
+The adaptive mesh refinement criteria and the parameters related to them are discussed in more detail in section \ref sect_refinement.
+
+ \li \b \c ref\_threshold\_eabs - Refine grid if \f$|\mathbf{E}|\f$ exceeds this value.
+ \li \b \c ref\_level\_eabs - Maximum number of refinement levels of the grid for the fluid equation due to the \f$|\mathbf{E}|\f$ criterion.
+ \li \b \c ref\_threshold\_charge - Refinement threshold for the curvature of the charge density.
+ \li \b \c ref\_threshold\_dens - Refinement threshold for the curvature of the particle densities.
+ \li \b \c cdr\_brick\_r, \b \c cdr\_brick\_z - Size \f$(r\f$ and \f$z)\f$ of the minimal refinement area. See Section \ref sect_size_refinement.
+ \li \b \c pois\_max\_error - An area of the Poisson grid is further refined if the relative error between two consecutive refined levels exceeds this value.
+ \li \b \c nu\_a - Courant number based on advection to determine the time step. Note, that \b \c nu\_a < 1 to satisfy CFL stability. In streamer simulations, this time step restriction will dominate over other parameters (\b \c nu\_d (diffusion) and \b \c nu\_rt (reaction)). More details on the time stepping can be found in \ref sect_timestepping.
+
+\subsubsection sect_needle Implementation of the needle-plane configuration
+
+As mentioned in section \ref sect_overview , the needle-plane electrode geometry is
+implemented using a charge simulation technique, which means that the entire needle is
+represented by a single point charge located on the axis.
+The position and strength of this charge is updated each time step to ensure that the
+potential at the point that would be the tip of the needle remains fixed.
+A schematic depiction of this setup can be seen in [Figure 1.](#setup).
+This provides a reasonable approximation of the potential in the area below
+the needle (the needle is always located at the top of the domain), but the potential
+will be wrong in the areas to the sides of the needle.
+Consequently, the density equations are only solved from the tip of the needle and downwards.
+This means that the computational domain for the density equations is smaller than
+that for the Poisson equation.
+
+In the specification of the external electric field, \c E0\_z is interpreted as the electric field between the two planar electrodes, far away from the needle. The applied potential is computed as follows:
+\f[
+ V = E_{0,z} * (L_z + L_{needle})
+\f]
+
+\subsubsection sect_output Output
+
+The code generates a large amount of output files at every \c \b output\_dt units
+of simulated time.
+These output files combined are sufficient to resume the simulation
+from that time step and can also be used for data analysis.
+Output files are named \c variable.C123abc.tsv, where 'tsv' stands for 'Tab-Separated Values'.
+\c variable is a particle species or electric field.
+Examples include \c electrons, \c n2plus and \c eabs
+(the latter being \f$|\mathbf{E}|\f$). \c 123 is the sequence number or
+output time step (which is unrelated to the time step of the numerical scheme) of that
+output set, it starts at \c 000 for the first set.
+This is the initial condition of the system before the simulation starts at \f$t = 0\f$.
+The alphabetic part of the filename after the output time step, \c abc denotes the
+subgrid contained in that file and this extension is defined recursively.
+The coarsest grid covering the entire domain has no such alphabetical extension
+(example: \c electrons.C123.tsv).
+At every next level, the subgrids at that level are named \c a, \c b, \c c, ...
+and this letter is appended to the alphabetical extension.
+The file \c electrons.C123ba.tsv contains electron densities at the
+123-th time step (so at \f$t = 123 * output\_dt\f$ ) for the first
+subgrid of the second subgrid of the main grid.
+Beware that since the grid refinement is adaptive, each time step has different subgrids.
+
+
+\par Figure 4. Schematic depiction of the naming convention for output files. Each next letter corresponds to a new refined level.
+
+Data, as shown in Figure 4., is stored as plain text,
+with each line containing a single number.
+Data is ordered in columns (with fixed \f$r\f$ coordinate).
+So to read the data, use the following pseudo-code:
+\verbatim
+for (i = 0, i < rmax*zmax; i++)
+{
+ r = floor(i / zmax);
+ z = i % zmax;
+ data[r,z] = read_line_from_file();
+}
+\endverbatim
+
+The dimensions of the grid are not contained in the data files.
+Instead, for each subgrid and output-step, two additional files are created:
+
+1. _r.C123abc.tsv_\n
+2. _z.C123abc.tsv_\n
+\n
+
+corresponding to subgrid _abc_ of output step _123_. The structure of these files is identical to that of the regular data files, but instead of particle densities or electric field strengths, these files contain the \f$r\f$ and \f$z\f$ coordinates of the center of the cell corresponding to that line-number. So to determine the coordinates of the \f$n^{th}\f$ line in a regular data file, simply read the \f$n^{th}\f$ line of the corresponding \b r and \b z files.
+
+\subsubsection sect_structure File structure
+
+
+\par Figure 5. File structure of of ARCoS package.
+
+The distribution of the ARCoS package contains several directories:
+
+\li \b \c FISH90 - the directory where FISH90 or FISHPACK should be downloaded
+
+\li \b \c output - this directory may be empty. Its name must correspond to the value of \b \c output_dir in file input/default.cfg. Or, the value in input/user_init.cfg if present.
+\li \b \c python - contains plot files. By means of \b \c plotvar pictures can be made of the output files. Not yet implemented.
+\li \b \c doc - directory with files for [Doxygen][12] to generate documentation from source code and this \b \c MANUAL. The source of this manual (in MANUAL.md) can be found in its directory \b \c markdown. See also the \b \c doxygen_config_file.
+\li \b \c arcos_f90 - a part of the \b \c functions in file cdr.c have been replaced by a piece of \b \c FORTRAN90 code in order to accelerate the simulation.
+\li \b \c src - this directory contains the source files written in \b \c c.
+\li \b \c include - this directory contains the include files
+\li \b \c input - this directory contains all input files. Most of them are libconfig configuration files.
+
+
+\subsubsection sect_source Source files
+
+The \c ARCoS simulation software was mostly written in \c C and its source code is split up in several files, each dealing with a separate part of the program. Most source files have an associated header file (the source file \b \c example.c has header file \b \c example.h ) containing the type-definitions and preprocessor macros. The function prototypes are aggregated in the header file \c proto.h. Below is a short summary of the important source files and the functionality that is contained within them.
+
+ \li cdr.c - Functions for solving the convection-diffusion-reaction (CDR) equations, creation, manipulation and refinement of CDR grids and time stepping.
+ \li configuration.c - Module for input/output of parameters. The code uses the library
+[libconfig](http://www.hyperrealm.com/libconfig/)
+ \li cstream.c - Contains some general initialization and termination functions.
+ \li dft.c - Functions related with discrete fourier transformations.
+ \li grid.c - Low-level functions for handling of grids, both CDR and Poisson grids.
+ \li interpol2.c - Interpolation functions for the mapping of one grid to another (for example during refinement).
+ \li main.c - Functions for reading input parameters, starting of the code and the main loop.
+ \li mapper.c - Mapping of one grid tree onto another.
+ \li misc.c - Miscellaneous utilities for allocating memory.
+ \li photo.c - Photoionization functions.
+ \li poisson.c - Functions for solving the Poisson equation, including manipulation of Poisson grids and calling the external [FISPACK][9] solver.
+ \li reaction.c - Functions for computation of reactions between species as part of the density equations.
+ \li react_table.c - Performs initialization of reaction coefficient tables as well as table lookups.
+ \li rt.c - Functions for handling the loading of the input file containing the kinetic model (species, reactions, seeds).
+ \li rz_array.c - Low-level functions for handling Fortran-compatible arrays.
+ \li sprites.c - Routines for the sprites module.
diff --git a/doc/markdown/MANUAL.md_cp01 b/doc/markdown/MANUAL.md_cp01
new file mode 100644
index 0000000000000000000000000000000000000000..d6cf4bb8e20884ba425b1a3c919db9bd91433622
--- /dev/null
+++ b/doc/markdown/MANUAL.md_cp01
@@ -0,0 +1,897 @@
+\section Contents
+
+ -
+ \ref sect_fluid_eq
+
+ -
+ \ref sect_physical
+
+ - \ref sect_ddr
+ - \ref sect_elecpotfield
+ - \ref sect_rescaling
+
+
+ - \ref sect_bic
+ -
+ \ref sect_numeric
+
+ - \ref sect_dde
+ - \ref sect_dpe
+
+
+ - \ref sect_timestepping
+
+
+ -
+ \ref sect_refinement
+
+ - \ref sect_overview
+ - \ref sect_size_refinement
+ - \ref sect_criterion
+ - \ref sect_curvature
+ - \ref sect_fishpack
+ - \ref sect_Conclusions
+
+
+ -
+ \ref sect_software
+
+ - \ref sect_ARCoS_overview
+ -
+ \ref sect_IO
+
+ - \ref sect_sim
+ - \ref sect_input
+ - \ref sect_parameter
+ - \ref sect_needle
+ - \ref sect_output
+ - \ref sect_structure
+ - \ref sect_source
+
+
+
+
+
+
+\section sect_fluid_eq Fluid model
+
+\subsection sect_physical Physical model
+
+\subsubsection sect_ddr Drift-diffusion-reaction equations
+
+[1]: http://homepages.cwi.nl/~ebert/CaroJCP06.pdf "Montijn et al."
+[2]: http://homepages.cwi.nl/~ebert/LuqueAPL07.pdf "Luque et al."
+[3]: http://homepages.cwi.nl/~ebert/StrBranchLuque2011.pdf "Luque et al.(2011)"
+[4]: http://homepages.cwi.nl/~ebert/JCP-Li-12.pdf "Li et al."
+[5]: http://arxiv.org/abs/1301.1552 "Teunissen et al.".
+[6]: http:// "PhD Thesis Wormeester(to appear in 2013)"
+[7]: http://alexandria.tue.nl/repository/books/598717.pdf "PhD Thesis Montijn"
+[8]: http://homepages.cwi.nl/~willem/ "Monograph by Hundsdorfer and Verwer"
+[9]: http://www2.cisl.ucar.edu/resources/legacy/fishpack "Fishpack"
+[10]: http://www2.cisl.ucar.edu/resources/legacy/fishpack90 "Fish90"
+[11]: http://www.amazon.com/books/dp/3540194622 "Y. P. Raizer, Gas Discharge Physics"
+[12]: http://www.stack.nl/~dimitri/doxygen/manual/index.html "Doxygen"
+
+
+In a fluid model of a streamer, we replace the individual particles in the
+system by a density function \f${n}(\mathbf{r},t)\f$.
+The temporal evolution of this density function is governed by the physical
+processes of the system and this model takes the form of a set of partial
+differential equations (PDEs).
+The derivation of this so-called classical streamer model starts from the
+continuity equation. For particle species \f$i\f$, we have:
+\f[
+ \frac{\partial n_i(\mathbf{r},t)}{\partial t} + \nabla \cdot \mathbf{j}_i(\mathbf{r},t) = S_i(\mathbf{r},t).
+\f]
+
+Here \f$S_i(\mathbf{r},t)\f$ represents the total of all sources and sinks of
+species \f$i\f$. \f$\mathbf{j}_i(\mathbf{r},t)\f$ is the term for the particle
+current density of species \f$i\f$.
+Particles can drift and diffuse as described by the following
+expression for the particle current density
+\f$\mathbf{j}_i\f$:
+\f[
+ \mathbf{j}_i(\mathbf{r},t) = \mu_i n_i(\mathbf{r},t) \mathbf{E}(\mathbf{r},t) - D_i \nabla n_i (\mathbf{r},t).
+
+\f]
+In the above equation, the first term represents the particle drift due
+to the electric field, with \f$\mu_i\f$ the mobility coefficient of species \f$i\f$.
+The second term represents the diffusion of particles due to the spatial gradient in particle densities with diffusion coefficient \f$D_i\f$. These equations can be derived from the Boltzmann equation
+
+On the timescales involved, we consider only electrons to be mobile, while ions and neutrals remain stationary, which means that for heavy species, the [continuity equation](#continuity) is reduced to
+\f[
+ \frac{\partial n_i(\mathbf{r},t)}{\partial t} = S_i(\mathbf{r},t).
+\f]
+
+The sources and sinks in the first equation play a very important role in the dynamics of the streamer. In this model, the sources and sinks correspond to reactions between the different charged and neutral species present in the gas. The source term due to a single reaction is the product of the densities of the species involved in the reaction and the field-dependent rate coefficient for that reaction.
+
+As an example, the impact ionization reaction
+\f[
+ e^- + \mathbf{N}_2 \rightarrow 2 e^- + \mathbf{N}_2^+
+\f]
+is modeled by
+\f[
+ S_{ionization} = k_{ion}(|\mathbf{E}|) n_e [\mathbf{N}_2].
+\f]
+Here \f$n_e\f$ is the local electron density, \f$[\mbox{N}_2]\f$ the density of
+\f$\mbox{N}_2\f$ and \f$k_{ion}\f$ the reaction coefficient for impact ionization
+depending on the magnitude of the local electric field.
+The value of \f$k\f$ can be determined in different ways, from experiments,
+theoretical calculations or simulations.
+The traditional approximation suggested by Townsend
+uses an empirical expression for the impact ionization term, see the
+[book by Y. P. Raizer, "Gas Discharge Physics"][11]:
+\f[
+ \frac{dn_e}{dt} = n_e \mu_e |\mathbf{E}| \alpha_0 e^{-E_0 / |\mathbf{E}|},
+\f]
+where \f$\mu_e\f$ is the electron mobility coefficient,
+\f$\mathbf{E}\f$ is the local electric field and \f$\alpha_0\f$ and \f$E_0\f$ are
+parameters that can be determined by fitting experimental data.
+In gases that contain an electronegative admixture, such as \f$\mathbf{O}_2\f$, the process of
+attachment can provide a sink for the electron density through the following
+reactions:
+\f[
+ e^- + \mathbf{O}_2 \rightarrow \mathbf{O} + \mathbf{O}^-
+\f]
+\f[
+ e^- + \mathbf{O}_2 + \mathbf{O}_2 \rightarrow \mathbf{O}_2^- + \mathbf{O}_2
+\f]
+The first attachment process is dissociative attachment, the second an example
+of a 3-body attachment (a 3-body attachment can also occur with an oxygen and nitrogen
+molecule).
+In the case of the 3-body attachment, the reaction rate scales with the square of the oxygen density:
+\f[
+ S_{3-body-att} = k_{3-body-att}(|\mathbf{E}|) n_e [\mathbf{O}_2]^2.
+\f]
+Further ionization losses can occur via one or more recombination processes,
+but these typically have a timescale that is much longer than the timescale of
+streamer development and propagation and are therefore primarily interesting for
+the evolution of the charge density after a streamer discharge,
+as discussed in [PhD Thesis Wormeester(to appear in 2013)][6], Chapter 5.
+
+
+
+In gases with attachment, detachment may occur, resulting in an additional
+source of electrons.
+In gases that contain both nitrogen and oxygen, the photoionization process
+provides a non-local source of electrons.
+Since photoionization is non-local, it can not be modelled by simple reaction
+equations such as the ones for impact ionization.
+Instead, the local contribution of photoionization is calculated by spatially
+integrating contributions from the entire domain.
+The commonly used model for photoionization and the approximations made to make
+this model suitable for simulation are discussed in
+[PhD Thesis Wormeester(to appear in 2013)][6], Chapter 3, section Photoionization.
+
+The reaction model for streamer simulations can be very minimal or very extended,
+with many species and reactions, including metastables and various excited states.
+The complexity of the reaction model depends on the purpose of the simulations.
+For negative streamers in nitrogen, a model containing no more than three species
+(\f$\mbox{e}^-\f$, \f$\mbox{N}_2\f$ and \f$\mbox{N}_2^+\f$) and one reaction
+(impact ionization)
+is sufficient to simulate the dynamics of the streamer head, see [Montijn et al][1].
+For more detailed studies of the streamer chemistry, the reaction model should be
+as complete as possible.
+
+
+\subsubsection sect_elecpotfield Electric potential and field
+
+The streamer evolves under the influence of an electric field, which consists
+of an externally applied electric field and the electric field generated by
+space charges.
+These space charges are present at the head of the streamer as well as on the edge of the streamer channel.
+For the further propagation of the streamer, the enhanced electric field in front of the streamer, generated by the space charge in the streamer head is essential.
+We compute the net charge density
+\f$q(\mathbf{r},t)\f$:
+\f[
+ q(\mathbf{r},t) = e \sum_i q_i n_i(\mathbf{r},t),
+\f]
+where for species \f$i\f$, \f$n_i\f$
+denotes the density function of these species and \f$q_i\f$ the charge of
+a particle in units of the electron charge \f$e\f$.
+From this we compute the potential by solving the Poisson equation
+\f[
+ \nabla^2 \phi(\mathbf{r},t) = \frac{q(\mathbf{r},t)}{\epsilon_0}
+\f]
+and the electric field
+\f[
+ \mathbf{E}(\mathbf{r},t) = -\nabla \phi(\mathbf{r},t).
+\f]
+
+\subsubsection sect_rescaling Rescaling to dimensionless units
+
+The classical fluid model for streamers can be rescaled to dimensionless units and
+it is with these units that the code used in this documentation works.
+We refer the interested reader to the
+[PhD thesis of Gideon Wormeester (to appear in 2013)][6].
+From the [Townsend](#townsend_ionization) approximation for ionization,
+a characteristic field and length scale
+emerges: \f$E_0\f$ and \f$l_0 = \alpha_0^{-1}\f$, respectively.
+The characteristic velocity follows from the drift velocity of electrons
+in the characteristic field,
+\f[
+ E_0: v_0 = \mu_e E_0.
+\f]
+
+The characteristic number density follows from the [Poisson](#Poisson) equation.
+Values for \f$\alpha_0\f$, \f$E_0\f$ and \f$\mu_e\f$ were obtained from
+[PhD Thesis Montijn][7]
+and are at standard temperature and pressure:
+\f{eqnarray*}
+ \alpha_0 & \simeq & 4332 \quad \mbox{cm}^{-1}\\
+ E_0 & \simeq & 2 \times 10^5 \quad \mbox{V} \mbox{cm}^{-1}\\
+ \mu_e & \simeq & 380 \quad \mbox{~cm}^2 \mbox{V}^{-1} \mbox{s}^{-1}.
+\f}
+
+When we insert these values in the characteristic scales, we obtain the values with which to rescale the equations:
+\f{eqnarray*}
+ l_0 & \simeq & 2.3 \times 10^{-4} \quad \mbox{~cm}\\
+ t_0 & \simeq & 3.0 \times 10^{-12} \quad \mbox{~s}\\
+ n_0 & \simeq & 4.7 \times 10^{14} \quad \mbox{~cm}^{-3}\\
+ D_0 & \simeq & 1.8 \times 10^{4} \quad \mbox{~cm}^2 \mbox{s}^{-1}.
+\f}
+We can now make the appropriate substitutions
+(\f$t^d = t / t_0\f$ and similarly for the other variables;
+the superscript \f${\;}^d\f$ will be used to indicate that a variable is
+in dimensionless form, where this is not clear from the context.
+For clarity of reading, the superscript \f${\;}^d\f$ will be omitted where it is clear that variables are
+dimensionless) to obtain the classical fluid equations in
+dimensionless continuity form:
+\f[
+ \partial_{t} + \nabla \cdot \mathbf{j}_i = S_i,
+\f]
+where \f$t\f$ is the dimensionless time, \f$\mathbf{j}_i\f$ the dimensionless
+particle density current for species \f$i\f$ and \f$S_i\f$ the dimensionless source term
+for species \f$i\f$.
+\f$S_i\f$ is obtained by rewriting reaction equations such as the
+[impact ionization reaction](#reaction_imp_ion) equation in dimensionless form,
+where we remark that all rate-coefficients should also be rescaled.
+The particle density current \f$\mathbf{j}_i\f$ is obtained by rescaling
+[expression](#current_dens) into
+equation
+\f[
+ \mathbf{j}_i = -\mu_i n_i \mathbf{E} - D_i \nabla n_i,
+\f]
+where \f$\mathbf{E}\f$ is the dimensionless electric field and \f$n_i\f$,
+\f$D_i\f$ and \f$\mu_i\f$ are the dimensionless particle density,
+diffusion coefficient and mobility respectively of species \f$i\f$.
+We find that in dimensionless units \f$\mu_i\f$ is equal to 1 while for heavy particles
+\f$\mu_i\f$ is taken as 0, since heavy particles are assumed to be stationary in
+this model.
+The [dimensionless current density equation](#current_dens_dimless) can therefore be simplified to
+\f[
+ \mathbf{j}_e = -n_e \mathbf{E} - D_e \nabla n_e
+\f]
+for electrons and \f$ \mathbf{j}_i = 0 \f$ for heavy particles.
+The expression for the [charge density equation](#charge_dens) \f$q\f$, is rescaled to
+\f[
+ q(\mathbf{r},t) = \sum_i q_i n_i(\mathbf{r},t).
+\f]
+The [Poisson](#Poisson) equation is rescaled to
+\f[
+ \nabla^2 \phi = q.
+\f]
+We remark that although the code
+described here internally
+works with the dimensionless equations and variables described in this section,
+all results are presented in regular units unless otherwise noted.
+Input parameters for the simulation code are expected to be in dimensionless units.
+Finally we note that the rescaling to dimensionless units does not change
+the structure of the equations, it is merely a rescaling to a different
+set of units, where the dimensionless units yield a set of equations where some
+constants (such as \f$e\f$, \f$\epsilon_0\f$, \f$\mu_e\f$) become unity.
+
+\subsection sect_bic Boundary and initial conditions
+
+
+We consider a cylindrical computational domain with coordinates:
+\f[
+(r,z,\theta) \in (0,L_r) \times (0,L_z) \times (0,2\pi).
+\f]
+Although the code described here is capable of performing full 3D calculations,
+we assume cylindrical symmetry to greatly simplify the computations.
+For any spatially dependent function \f$f(r,z,\theta)\f$, we assume:
+\f$\partial_{\theta} f(r,z,\theta) = 0\f$.
+Consequently, the coordinate system for our computations is limited to
+\f$(0,L_r) \times (0,L_z)\f$.
+We consider a setup with a powered electrode at \f$z = L_z\f$ and a grounded
+electrode at \f$z = 0\f$.
+If the powered electrode is a plate, the following boundary conditions are used for
+the electric potential \f$\phi(r,z,t)\f$:
+
+\f[
+ \begin{array}{llll}
+ \forall z \; & \partial_r \phi(0,z,t) & = & 0\\
+ \forall r \; & \phi(L_r,z,t) & = & 0\\
+ \forall z \; & \phi(r,0,t) & = & 0\\
+ \forall r \; & \phi(r,L_z,t) & = & \phi_0
+ \end{array}
+\f]
+
+with \f$\phi_0\f$ the potential applied to the powered electrode.
+If the powered electrode is a needle protruding from a plate, the needle has the
+same potential \f$\phi_0\f$ as the plate.
+
+
+\par Figure 1. Schematic of the computational setup.
+
+In Figure 1., the shaded rectangle represents the computational domain for
+the fluid equations, the thick horizontal lines the two planar electrodes
+with the needle and its parameters depicted at the anode.
+The area between the two planar electrodes is the computational domain
+for the Poisson equation.
+The needle is simulated by a single point charge, \f$Q\f$, chosen such
+that \f$\phi =\phi_0\f$ in the point \f$P\f$, which is the tip of the needle.
+The calculation assumes cylindrical symmetry around the needle axis
+represented by the dashed-dotted line.
+
+For the density equations, we use homogeneous Neumann conditions on all edges:
+\f[
+ \partial_r n(0,z,t) = \partial_r n(L_r,z,t) = \partial_z n(r,0,t) = \partial_z n(r,L_z,t) = 0,
+\f]
+where we remark that if the powered electrode is a needle, the computational domain
+for the density equations is smaller than the computational domain for the Poisson
+equation and the \f$L_z\f$ values for both domains are not equal.
+This difference is a requirement of the numerical implementation of the needle
+electrode and is further detailed in section \ref sect_needle.
+
+While the boundary conditions mentioned above are the ones used by Wormeester,
+the code that was used can also handle different choices of boundary conditions:
+both homogeneous Neumann and homogeneous Dirichlet boundary conditions are available
+for the top (\f$z = L_z\f$), bottom (\f$z = 0\f$) and right (\f$r = L_r\f$)
+edges of the domain for both the densities and the potential.
+The Neumann condition on the central axis of the cylindrical domain is required
+for symmetry reasons.
+
+As initial conditions for particle densities, two types of seeds are implemented in
+the code. A homogeneous seed, with a constant density over the entire domain and a
+Gaussian seed of the form
+\f[
+ n(r,z,0) = n_{max} \mbox{exp}(-\frac{r^2 + (z - z_0)^2}{\sigma^2}).
+\f]
+Here \f$z_0\f$ specifies the \f$z\f$-coordinate of the maximum of the seed
+(which is located on the symmetry axis with \f$r = 0\f$), where the density is
+\f$n_{max}\f$. \f$\sigma\f$ is a measure of the radius of the seed, it is the distance
+at which the density drops to \f$e^{-1}\f$ of the maximum value.
+
+In typical streamer simulations, a seed of electrons and positive ions is placed at the tip of the needle to initiate the discharge. Other than these Gaussian seeds and the neutral background gas, initial particle densities are zero with the possible exception of added background ionization, a homogeneous density of negative and positive ions. The initial distribution of electrons and ions is charge neutral at every point of the domain.
+
+\subsection sect_numeric Numerical method
+
+The physical equations in section \ref sect_fluid_eq are to be solved numerically.
+The computational code we have applied for this uses finite volume methods to solve
+a discretized version of the physical equations.
+Here we give a basic summary of the numerical technique used.
+For more details, the reader is referred to the work of [Montijn et al.][1],
+upon which the current code is based.
+
+\subsubsection sect_dde Discretization of density equations
+
+The [dimensionless continuity ](#continuity_dimless) and the [dimensionless current density](#current_dens_dimless) equations
+are discretized using finite volume methods and solved on a uniform rectangular grid with cells:
+\f[
+ C_{ij} = [(i - 1) \Delta r, i \Delta r] \times [(j - 1) \Delta z, j \Delta z]\left(i = 1 , \cdots , \frac{L_r}{\Delta r}, j = 1 , \cdots , \frac{L_z}{\Delta z}\right),
+\f]
+where \f$L_r\f$ and \f$L_z\f$ are the \f$r\f$- and \f$z\f$-dimensions of the grid and \f$\Delta r\f$ and \f$\Delta z\f$ the size of a cell in \f$r\f$- and \f$z\f$-direction, respectively. Particle density distributions are represented by their value in the cell center, which can be seen as an average over the cell. For some species \f$n\f$, we use \f$n_{i,j}\f$ to denote the density at the cell center \f$C_{ij}\f$. For sake of clarity of notation we omit the superscript \f$^d\f$ indicating that variables are in dimensionless units.
+
+The discretized continuity equations in cylindrical coordinates, with cylindrical symmetry (\f$\partial_{\theta} f = 0\f$) assumed, have the following form:
+\f[
+ \begin{array}{ll}
+ \frac{d n_{i,j}}{d t} = & \frac{1}{r_i \Delta r} \Big(r_{i - \frac{1}{2}} F^a_{i - \frac{1}{2},j} - r_{i + \frac{1}{2}} F^a_{i + \frac{1}{2},j} + r_{i - \frac{1}{2}} F^d_{i - \frac{1}{2},j} - r_{i + \frac{1}{2}} F^d_{i + \frac{1}{2},j}\Big) + \\
+ & \frac{1}{\Delta z} \Big(F^a_{i,j - \frac{1}{2}} - F^a_{i,j + \frac{1}{2}} + F^d_{i,j - \frac{1}{2}} - F^d_{i,j + \frac{1}{2}}\Big) + S_{i,j}.
+\end{array}
+\f]
+Here \f$F^a\f$ and \f$F^d\f$ represent the advective and diffusive fluxes across the cell boundaries. Since we assume ions and neutral particles to be stationary, these terms are nonzero only for electrons. For heavy particles, only the source term \f$S_{ij}\f$ remains.
+
+The advective flux, \f$F^a\f$ uses an upwind scheme with flux limiting and is defined as follows:
+\f[
+ \begin{array}{ll}
+F^a_{i + \frac{1}{2},j} = & E^+_{r; ~ i + \frac{1}{2},j} \Big[ n_{i,j} + \psi(P_{i,j})(n_{i+1,j} - n_{i,j}) \Big] \\
+& E^-_{r; ~ i + \frac{1}{2},j} \Big[ n_{i + 1,j} + \psi(\frac{1}{P_{i+1,j}})(n_{i,j} - n_{i+1,j}) \Big]
+\end{array}
+\f]
+
+\f[
+ \begin{array}{ll}
+ F^a_{i,j + \frac{1}{2}} = & E^+_{z; ~ i,j + \frac{1}{2}} \Big[ n_{i,j} + \psi(Q_{i,j})(n_{i,j+1} - n_{i,j}) \Big] \\
+ & E^-_{z; ~ i,j + \frac{1}{2}} \Big[ n_{i,j + 1} + \psi(\frac{1}{Q_{i,j+1}})(n_{i,j} - n_{i,j+1}) \Big],
+\end{array}
+\f]
+where \f$E^+ = max(-E,0)\f$ and \f$E^- = min(-E,0)\f$ are used to distinguish the upwind directions for the components of the electric field, \f$E_r\f$ and \f$E_z\f$, and we have
+\f[
+\begin{array}{lll}
+ P_{i,j} & = & \frac{n_{i,j} - n_{i-1,j}}{n_{i+1,j} - n_{i,j}}\\
+ Q_{i,j} & = & \frac{n_{i,j} - n_{i,j-1}}{n_{i,j+1} - n_{i,j}}.
+\end{array}
+\f]
+\f$\psi\f$ is the Koren limiter function:
+\f[
+ \psi(x) = max(0, min(1, \frac{1}{3} + \frac{x}{6}, x)).
+\f]
+The diffusive flux \f$F^d\f$ is calculated using a second-order central differences scheme:
+\f[
+\begin{array}{lll}
+ F^d_{i + \frac{1}{2},j} & = & \frac{D}{\Delta r}(n_{i,j} - n_{i+1,j})\\
+ F^d_{i,j + \frac{1}{2}} & = & \frac{D}{\Delta z}(n_{i,j} - n_{i,j+1})
+\end{array}
+\f]
+and the reaction term \f$S_{i,j}\f$ is computed as
+\f[
+ S_{i,j} = \sum_{A~\in~{reactions}} \Big[ k_A(|\mathbf{E}|_{i,j}) \prod_{s~\in~{Spec(A)}} n_{s; i,j} \Big]
+\f]
+where \f$k_A\f$ denotes the field-dependent reaction rate coefficient of
+reaction \f$A\f$, and \f$Spec(A)\f$ the set of species that appear as an input
+for reaction \f$A\f$.
+
+\subsubsection sect_dpe Discretization of the Poisson equation
+
+We compute the net charge \f$q_{i,j}\f$ in a cell center by adding up the contributions from the individual charged species:
+\f[
+ q_{i,j} = \sum_{s~\in~{species}} n_{s; i,j} q_s.
+\f]
+With this net charge, the electric potential \f$\phi\f$ can be computed in the cell centers through a second-order central approximation of the dimensionless Poisson equation:
+\f[
+ q_{i,j} = \frac{\phi_{i+1,j} - 2 \phi_{i,j} + \phi_{i-1,j}}{\Delta r^2} + \frac{\phi_{i+1,j} - \phi_{i-1,j}}{2r_{i,j} \Delta r} + \frac{\phi_{i,j+1} - 2 \phi_{i,j} + \phi_{i,j-1}}{\Delta z^2}.
+\f]
+From the potential we can compute the components of the electric field from \f$\mathbf{E} = - \nabla \phi\f$ in the cell boundaries:
+\f[
+\begin{array}{lll}
+ E_{r; ~ i + \frac{1}{2},j} & = & \frac{\phi_{i,j} - \phi_{i+1,j}}{\Delta r}\\
+ E_{z; ~ i,j + \frac{1}{2}} & = & \frac{\phi_{i,j} - \phi_{i,j+1}}{\Delta r}.
+\end{array}
+\f]
+The electric field strength is determined at the cell center, so we have to compute the field components in the center by averaging the values on the boundaries after which we can compute the field strength:
+\f[
+ |\mathbf{E}|_{i,j} = \sqrt{\left(\frac{E_{r;i - \frac{1}{2},j} + E_{r;i + \frac{1}{2},j}}{2}\right)^2 + \left(\frac{E_{z;i,j - \frac{1}{2}} + E_{z;i,j + \frac{1}{2}}}{2}\right)^2}.
+\f]
+
+\subsection sect_timestepping Time stepping
+
+The code uses the explicit trapezoidal rule, a second order Runge-Kutta method,
+for the temporal discretization with time step \f$\Delta t\f$.
+Given some time step \f$t_i = i \Delta t\f$, density distributions
+\f$\mathbf{n}_i(r,z) = \mathbf{n}(r,z,t_i)\f$ and electric field
+\f$\mathbf{E}_i(r,z) = \mathbf{E}(r,z,t_i)\f$, the densities and field at the next
+time step, \f$t_{i+1}\f$ are calculated by first computing an intermediate result
+for the densities:
+\f[
+ \overline{\mathbf{n}}_{i+1} = \mathbf{n}_i + \Delta t F(\mathbf{n}_i, \mathbf{E}_i).
+\f]
+Using these intermediate densities, the potential can be computed by solving the
+Poisson equation, after which we obtain the intermediate electric field
+\f$\overline{\mathbf{E}}_{i+1}\f$.
+With this, we compute the final values of the densities at \f$t_{i+1}\f$:
+\f[
+ \mathbf{n}_{i+1} = \mathbf{n}_i + \frac{\Delta t}{2} F(\mathbf{n}_i, \mathbf{E}_i) + \frac{\Delta t}{2} F(\overline{\mathbf{n}}_{i+1}, \overline{\mathbf{E}}_{i+1}).
+\f]
+Finally, we again compute the potential and electric field, now using the final
+values of the densities.
+
+The size of the time step \f$\Delta t\f$ is determined by using a Courant-Friederichs-Levy (CFL) restriction for stability of the advection part of the equations:
+\f[
+ \texttt{max} E_r \frac{\Delta t}{\Delta r} + \texttt{max} E_z \frac{\Delta_t}{\Delta_z} < \nu_a.
+\f]
+There are additional restrictions from other diffusion and reaction parts of the
+equations, but they are dominated by the CFL criterior for the advection part, see
+[Montijn et al.][1].
+The value of \f$\nu_a\f$ is typically set to 0.25, which is well below the maximum
+required for stability.
+We refer the interested reader to the [Monograph by Hundsdorfer and Verwer][8].
+
+\section sect_refinement Overview of refinement strategies and criteria
+
+\subsection sect_overview Overview
+
+The \c ARCoS simulation code contains functions for adaptive grid refinement (also known as adaptive mesh refinement or AMR). Since streamers span different length scales, there is a need to simulate relatively large physical domains while still having high spatial resolution in areas such as the streamer head. To ensure that such large domains can be simulated without giving up resolution and accuracy, the numerical grid is refined adaptively at each time step. The equations are solved on a coarse grid, after which the solution is analyzed using refinement criteria to determine the areas where refinement is needed. The equations are then solved on the refined subgrids after which the process is iterated. Grid generation and grid refinement are performed separately for the density equations and for the Poisson equation.
+
+There are three main refinement criteria. The first two concern refinement of the density grids: Refinement based on the absolute value of \f$\mathbf{E}\f$ and refinement based on the curvature of densities (both charge density and particle density). The grids used by the [FISHPACK][9] solver use their own refinement scheme where the decision to refine is made if the difference between the solution on a grid and the solution on a finer grid exceeds a threshold. The [FISHPACK][9] solver is used for both the Poisson equation that determines the electric potential of the system and the Helmholtz equations for the photoionization reactions.
+
+\subsection sect_size_refinement Size of the refined areas of the density grids
+
+All CDR (Convection-Diffusion-Reaction, CDR is the shorthand term for the density part of the code) refinement criteria are on a per-point basis, which means that the question whether to refine or not is initially answered for every grid cell. This is inconvenient for several reasons, primarily due to the computational cost of such a scheme. The regions containing the streamer head will almost always need to be refined, it is not necessary to evaluate this point-by-point in these regions.
+
+To ease this problem, a minimal refinement area is defined by two parameters:\n
+\c cdr\_brick\_dr and \c cdr\_brick\_dz, see e.g., file default.cfg . The refinement module divides the grid it receives (this can be the coarsest grid covering the entire domain or a refined grid covering only part of the domain, the code and grid structure are recursive) into "bricks" of these dimensions and searches each brick for cells that match the refinement criteria. Once such a cell is found, the entire brick containing that cell is refined.
+
+For the [FISHPACK][9] module, a different approach is used. The refinement routine scans its input grid, starting at the top (\f$z = z_{min}\f$), going down per "line" (a set of cells with equal \f$z\f$d-coordinate). Once it finds a line with points that meet the refinement criterion it searches for the first line that does not contain any points that meet the criterion. It then refines the smallest rectangular area that contains all the points that meet the criterion. This process is repeated until the bottom (\f$z = z_{max}\f$) of the grid is reached.
+
+
+\par Figure 2. The nested structure of refined density grids
+
+In Figure 2.,
+the black squares represent grid cells at the coarsest level (level 0),
+the dark gray cells are the first refined sublevel (level 1). Two rectangular
+grids are included at this level, their shared border is indicated by the
+red line.
+The light gray cells show grids at a further refined level (level 2).
+
+
+\par Figure 3. The nested structure of refined Poisson grids
+
+The black grid, as shown in Figure 3. is the coarsest level, the dark gray cells are the first
+refined sublevel, the light gray cells show grids at a further refined level.
+Each grid has at most one subgrid.
+
+The tree of grids for the density equations may contain refined grids that are adjacent to each other. A schematic showing the nested structure of refined density grids is shown in [Figure 2.](#refinement_cdr). The red line in this figure indicates the shared border between two subgrids. For the Poisson-grids, such a structure is not possible and a grid can have at most one refined child-grid as depicted in [Figure 3.](#refinement_poisson).
+
+\subsection sect_criterion The |E| criterion
+
+The electric field criterion is the most simple of the three refinement criteria. It is an empirical criterion that is not directly motivated by the underlying numerics. A cell with coordinates \f$(r,z)\f$ qualifies for refinement if:
+\f[
+|\mathbf{E}(r,z)| > E_c
+\f]
+where \f$E_c\f$ is the threshold electric field strength for refinement. \f$E_c\f$ is a user-determined parameter that is provided in the input file for a run. Since this criterion is independent of the grid level or the cell size, once a cell meets the criterion at the coarsest level, it will also do so at every refined level. Because of this property, the user can limit the refinement depth that is reached through this criterion with the \c ref\_level\_eabs input parameter, see e.g., file default.cfg. Setting \c ref\_level\_eabs to 1, for example, restricts the refinement from the coarsest level to the first refined level due to the \f$|\mathbf{E}|\f$ criterion.
+
+The \f$|\mathbf{E}|\f$ criterion is inflexible in the sense that it requires the user to have advance knowledge of what the field strengths will be. A possible alternative would be to replace the fixed threshold value \f$E_c\f$ by a dimensionless fraction \f$c\f$ and refine if
+\f[
+|\mathbf{E}(r,z)| > c E_{max}
+\f]
+with \f$E_{max}\f$ the maximum electric field strength in the computational domain. Since the electric field criterion is mostly empirical, picking the right value for the refinement threshold may be a trial-and-error process.
+
+\subsection sect_curvature The curvature criteria
+
+There are two criteria that use the curvature of density functions in order to determine which areas to refine. If the curvature is large compared to the cell size, the numerics may become unreliable and it is desirable to work with a finer grid. For a density function \f$u(r,z)\f$ and a cell size \f$\triangle r \times \triangle z\f$ the curvature function \f$C_u(r,z)\f$ is a discretization of the second derivative of \f$u\f$ in cylindrical coordinates \f$(r,z)\f$:
+\f[
+ \begin{array}{ll}
+ C_u(r,z) = & \frac{1}{r + \frac{\triangle r}{2}}\Big[(r + \triangle r)\big(u(r + \triangle r, z) - u(r,z)\big) - r\big(u(r,z) - u(r - \triangle r,z)\big)\Big] + \\
+ & \big[u(r, z + \triangle z) - 2 u(r,z) + u(r, z - \triangle z)\big].
+ \end{array}
+\f]
+Rather than the absolute value of the curvature, the refinement module looks at the curvature relative to the global maximum, \f$Max(u)\f$. The final criterion then reads:\n
+\n
+\b Refine \f$(r,z)\f$ \b if \f$\frac{C_u(r,z)}{Max(u)} > C_t\f$\n
+\n
+with \f$C_t\f$ the threshold curvature. This refinement criterion is checked for two density functions \f$u\f$. The first is the (absolute) charge density function. Here an extra condition applies: the absolute value of the charge needs to exceed a certain threshold value (which is hard-coded) before a cell can qualify for refinement based on this criterion. Secondly, the curvature criterion is applied to the particle density functions. Since only mobile particles require a high spatial resolution, any immobile species are not considered in these criteria (which currently excludes all species other than electrons). The computational grids for these immobile species are simply the same as the grids used to solve the density equations for electrons.
+
+\subsection sect_fishpack FISHPACK refinement
+
+The [FISHPACK][9] module, for the Poisson equation and the photoionization equations, uses a different set of grids than the CDR module and with it a different refinement scheme. Initially, two grids are set up, one coarse and one fine grid (with the fine grid having twice the spatial resolution in each dimension, so 4 times the number of cells). The Poisson/Helmholtz equation is then solved on both grids and the solution of the coarse grid is interpolated onto the fine grid. A grid cell then qualifies for refinement if the absolute difference between the interpolated coarse solution and the fine solution (this difference is called the error) is more than some user-defined threshold. When refinement is needed, a new set of grids is determined using the strategy mentioned earlier and the process is repeated until either the desired accuracy is reached or the maximum number of allowed refinement levels is reached. Since the [FISHPACK][9] module was originally only used to solve the Poisson equation for the electrostatic problem and the value of the electric field
+is defined on the edge of a cell, a cell that does not meet the error-criterion still qualifies for refinement if its neighbor does meet the error-criterion.
+
+One limitation to this scheme is the limited number of grid cells that the [FISHPACK][9] routine can handle. Since [FISHPACK][9] applies a cyclic reduction scheme, the round-off error increases with the number of grid cells. This places a limit on the size of grids that [FISHPACK][9] can solve. Once the refinement module wants to create a grid that is larger than the so-called [FISHPACK][9] limit, the refinement attempt is rejected and the code relaxes the error threshold by a factor of 2 and again determines the area to refine, using the new threshold.
+
+To solve the photoionization problem, two Helmholtz equations need to be solved (For details on the implementation of photoionization, the reader is referred to [PhD Thesis Wormeester(to appear in 2013)][6], Chapter 3, section Photoionization
+and references therein). Each of the so-called "photo-terms" has its own characteristic absorption length, which depends on the gas density and oxygen ratio. The term with the short absorption length is often dominated by impact ionization in the head of the streamer, while the term with the long absorption length is the main contributor of electrons in front of the streamer head that are required for a positive streamer to propagate.
+
+The default behavior of the \c ARCoS code is to treat these two photoionization terms in the same manner as the Poisson problem when it comes to refinement: all user-definable parameters were equal. Since the term with the short absorption length gives rise to a solution that benefits strongly from high spatial resolution (due to the steep gradients) it will easily trigger the refinement criterion. However, it is this term that is dominated by impact ionization, see [Luque et al.][2],
+which reduces the relevance of accurate computation of this term. The user can therefore specify the refinement criteria for each of the two photoionization terms separately, providing the user with the means to allow the important, long absorption length term to benefit from high spatial resolution, while reducing the computational cost incurred by the less important term. However, in tests it was found that tuning the refinement criteria for the photoionization terms has very little effect on
+computational cost or results.
+
+\subsection sect_Conclusions Conclusion
+The adaptive refinement scheme of \c ARCoS allows for the simulation of large domains while maintaining high spatial resolution in regions that require this. A number of refinement parameters influence both the computational performance and the accuracy of the results, which means that the user has to monitor the results carefully. Since the refinement criteria were setup by
+[Montijn et al.][1].
+and
+[Luque et al.][2].
+for simulations of air and pure nitrogen, application of the code to other gases may require changes to the values of the various thresholds used in the refinement criteria. An example is high-purity oxygen, with a small nitrogen admixture. In such a gas, ionizing photons will have a very short characteristic absorption length and the calculation of the photoionization terms should be done with high accuracy close to the photon source, primarily the streamer head. However, the limitation of the [FISHPACK][9] refinement method does not permit several smaller, adjacent
+refined sub-grids, which makes it difficult to properly focus on the streamer head without including too much of the channel.
+
+\section sect_software ARCoS software
+
+\subsection sect_ARCoS_overview Basic overview and functionality
+
+The \c ARCoS simulation software was originally developed by Alejendro Luque as a more flexible version of the adaptive refinement code developed by Carolynne Montijn as described in [PhD Thesis Montijn][7].
+The original code by Montijn has been written in Fortran90, while \c ARCoS has been written in C.
+The original [FISHPACK][9] package used for solving the Poisson and Helmholtz equations is written
+in Fortran77 and was developed by Adams, Swarztrauber and Sweet. The \c ARCoS code is now compiled
+with [FISH90][10], a modernization of the original [FISHPACK][9], employing Fortran90 to slightly
+simplify and standardize the interface to some of the routines.
+
+\c ARCoS solves the fluid equations for streamers, described in section \ref sect_fluid_eq,
+on nested Cartesian grids using an adaptive mesh refinement technique.
+\c ARCoS allows for the simulation of both positive and negative streamers in the
+electrode configurations plate-plate and needle-plate.
+The needle-plate electrode geometry is included using a charge simulation method
+[Luque et al.][2].
+This method replaces the electrode needle by a single point charge, with the
+location and the size of the charge being updated at every time step to ensure the
+potential at needle tip remains fixed at the predetermined value.
+The limitation of this method is that the potential on the rest of the surface
+of the simulated needle will not be accurate.
+Consequently, the [continuity](#continuity) equation is only solved on
+a smaller grid, not containing the simulated needle.
+
+The effect of this is that \c ARCoS is not well suited for the study of the
+inception of streamers, as the area around the tip of the needle is not
+accurately modelled.
+However, since inception is often affected by the behavior
+of individual particles, the use of a particle code such as described in
+[Teunissen et al.][5] and [Li et al.][4].
+is recommended for studying streamer inception.
+The purpose of the \c ARCoS code is to study streamer propagation in the phase
+after the streamer has formed.
+Studies performed by [Luque et al.][2] show that the dynamics of
+streamers in later stages hardly depends on initial conditions.
+
+\c ARCoS allows the user full control over the numerical parameters of the
+simulation: grid size, refinement criteria and CFL numbers can be set by the user.
+The kinetic model, i.e., the list of particle species, their reactions and
+initial densities as well as the diffusion and mobility coefficients can be
+specified via a series of input files, allowing the user to fine-tune the properties
+of the gas in which the streamer is simulated, see configuration file input/kinetic_example.cfg.
+
+The \c ARCoS code can be downloaded from the website
+\c http://md-wiki.project.cwi.nl/
+
+\subsection sect_IO Handling the software, input and output
+
+\subsubsection sect_sim Starting a simulation
+
+Two input parameter files governs all details of the simulation:
+
+\li \b Physical \b parameters such as voltage, electrode configuration, size of the gap, etc.
+\li \b Numerical \b parameters such as grid size, refinement criteria, etc.
+\li \b Practical \b details like the directory name, where the output files should be stored and the interval at which output should be generated.
+
+[libconfig](http://www.hyperrealm.com/libconfig/), a free library for processing
+structured configuration files, is used for reading, manipulating and writing these files.
+The first file, stored as input/default.cfg, must contain the default values for the global variables.
+This file is a part of the streamer package distribution.
+The second file, say input/user_init.cfg, an example is given by input/example_user_init.cfg,
+has a structure analogously to input/default.cfg, and should contain the parameters which differ
+from the default values.
+The program delivers a configuration file, say input/example_user_continue.cfg with the updated parameters
+from input/user_init.cfg completed with the default values of input/default.cfg.
+
+Since the execution time of a single run will take on the order of several days, it is recommended to
+split the time period into smaller pieces, and restart the execution several times from the point
+where the previous run stopped.
+The easiest way to restart the simulation is
+ \li to copy the file input/user_continue.cfg into input/default.cfg, to be sure that equal values for the parameters are used,
+ \li to edit the file input/user_init.cfg, and change the \b \c t_end value, the \b \c restart value and the name of the \b \c load_file. See the end of of this section.
+
+The use of the configuration files construction has the following advantages:
+ \li recompilation of the code is not necessary in case of a restart
+ \li the user always has a clear overview of the parameter values used
+ \li results of different or continuing runs can be stored in different output directories,
+ as listed in the configuration file.
+ \li besides the parameter value also comment coupled to a parameter can be changed in the configuration files written by the user. The length of the comment must be restricted by 100 characters
+ \li the order of the parameters in the configuration file is free
+ \li the user has the possibility to control the simulation, many parameter values can be changed.
+
+It is easy to resume a simulation by using a set of output data as initial conditions.
+One has to adapt the parameter file with modified start and end times for the simulation.
+To start a \c ARCoS simulation use the following command from
+the directory containing the executables:
+\n
+\code
+ ./arcos > out.example 2> err.example
+\endcode
+\n
+
+The \c ARCoS program starts and it will print out the parameter values used:
+ \li in \c out.example
+ \li in input/user_continue.cfg.
+
+The program will print some extra information to file \c out.example, e.g., the step size and
+when a new set of output data has been written, and to which set of file names.
+Warnings and errors will be printed in file \c err.example. The program can terminate in three different ways:
+
+ \li The preset end-time is reached.
+ \li The program is terminated by the user.
+ \li The time-step (as determined by the Courant criterion for stability, more details to come) has dropped below a preset threshold. This usually points to some form of instability.
+
+In case the simulation runs on a PC or desktop machine, a convenient approach is to set a very
+large value for the end time and, rather than having the program determine when to terminate,
+keeping track of the progress of the streamer by checking the output files and manually terminating
+the program when the desired output is reached, e.g., the streamer has reached the electrode, or,
+ it has started to branch.
+In other cases, it may be necessary for the program to be able to run for a fixed amount of time.
+For example when it needs to exit gracefully, which is required for profiling software to work.
+Also in case of batch jobbing with a limited CPU wall clock time, like on most supercomputers,
+the end time must be chosen corresponding to the wall clock time.
+
+Data files with periodical data controlled by \c $output_dt, stored in directory \c $output\_dir,
+have names using the format \c variable.C123abc.tsv:
+ \tparam is a particle species or electric field, e.g. \c charge, \c d_dummyminus, \c d_electrons \n
+ \tparam <123> is the sequence number of that particular output dataset and \n
+ \tparam specified the subgrid the output belongs to.
+
+These files can be used to plot the solution or to restart the simulation. More details on this in the section on output files. To resume the example simulation from output set \c 123, call:
+\n
+\code
+./arcos example C123
+\endcode
+\n
+
+\subsubsection sect_input The input files
+
+
+File and directory handling:
+ \li \b \c kin\_input - The filename of the [libconfig](http://www.hyperrealm.com/libconfig/)
+ input file containing the species, seeds and reactions.
+ By convention, these files have the extension \b .cfg.
+ \li \b \c output\_dir - The directory where the output files will be stored.
+ This can be a relative path to the directory with the executable or an absolute
+ path. When the execution starts, the directory $output_dir must be present and writable.
+ \li \b \c output\_dt - The interval (in dimensionless units) with which an output dataset is to be saved.
+ Lower values mean more frequent output, which gives finer grained time-dependent
+ data at the cost of more disk space.
+
+Physical parameters:
+ \li \b \c L\_r - Radius of the physical domain in dimensionless units.
+ \li \b \c L\_z - Length of the physical domain. Does not include the needle.
+ \li \b \c has\_photoionization - Whether to enable the photoionization module.\n
+ So, if \b \c has\_photoionization = 1, photoionization is present,\n
+ if \b \c has\_photoionization = 0, execution without photoionization.\n
+ \li \b \c photoionization\_file - Filename of the file containing the photoionization parameters.\n These parameters are further explained in appendix~ref{app:photoionization_parameters}.
+
+\todo: WRITE APPENDIX
+
+ \li \b \c E0\_z, \b \c E0\_y, \b \c E0\_x - Components of the external electric field in dimensionless units. Since the electrodes are located at the top and bottom of the domain \f$(z = L_z\f$ and \f$z = 0)\f$, only \c E0\_z should be nonzero. Positive values of \c E0\_z will generate an electric field in the \f$^z\f$ direction, with the top electrode (at \f$z = L_z\f$) having a negative charge, generating negative streamers and vice verse.
+ \li \b \c pois\_inhom - Whether to use a needle-plane geometry or not.\n
+ If \b \c pois\_inhom = 1 then we have \b \c needle-plane case, \n
+ otherwise if \b \c pois\_inhom = 0 gives the plane-plane case. \n
+ See below for additional remarks regarding the needle-plane geometry.
+ \li \b \c needle\_length and \b \c needle\_radius - The length and radius of the needle in dimensionless units. Only applies when \b \c pois\_inhom = 1.
+ \li \b \c end\_t - Time at which the simulation will stop, in dimensionless units.
+ \li \b \c max\_ntheta - Number of azimuthal grid cells. Default \b \c max\_ntheta = 1. \n
+ \b \c max\_ntheta > 1 will activate the full 3D simulation (without cylindrical symmetry) using a pseudo-spectral method described in more detail in [Luque et al.(2011)][3].
+
+Numerical parameters:
+ \li \b \c gridpoints\_r, \b \c gridpoints\_z - Number of gridpoints in \f$r\f$ and \f$z\f$ direction for the density equations at the coarsest level.
+ \li \b \c cdr\_max\_level - Maximum number of refinement levels of the grid for the fluid equations. \n
+ \b \c cdr\_max\_level = 0 means no refinement.
+ \li \b \c cdr\_bnd\_bottom, \b \c cdr\_bnd\_top, \b \c cdr\_bnd\_right - Boundary condition for the density equations at the bottom \f$(z = 0)\f$, top \f$(z = L_z)\f$ and right \f$(r = L_r)\f$ of the domain. \n
+ \b \c cdr\_bnd\_xxx = 1 gives homogeneous Neumann boundary conditions, \n
+ \b \c cdr\_bnd\_xxx = -1 gives homogeneous Dirichlet boundary conditions.
+ \li \b \c pois\_max\_level - Maximum number of refinement levels of the grid for the Poisson equation.
+\b \c pois\_max\_level = 0 means no refinement.
+ \li \b \c pois\_bnd\_bottom, \b \c pois\_bnd\_top, \b \c pois\_bnd\_right - Boundary condition for the Poisson equation at the bottom \f$(z = 0)\f$, top \f$(z = L_z)\f$ and right \f$(r = L_r)\f$ of the domain. \n
+\b \c pois\_bnd\_xxx = 1 gives homogeneous Neumann boundary conditions, \n
+\b \c pois\_bnd\_xxx = -1 gives homogeneous Dirichlet.
+
+\subsubsection sect_parameter The parameter file
+
+In the parameter file input/default.cfg variables and their values are assigned with the following syntax
+\verbatim
+{
+ type = "type"; /* type can be a "string", a "double", an "int" */
+ name = "name"; /* variable name as defined in file include/parameters.h */
+ comment = "comment"; /* description of the variable, maximum of 100 characters */
+ value = "value"; /* value of type string, double or integer, related to "type" */
+},
+
+ # <-- this starts a comment-line, which is ignored.
+
+ # White lines are also ignored.
+ # String-values should be between quotes, numeric values should not
+ pi=3.14
+ # (Note: The above is an approximation)
+ # Scientific notation can be used:
+ pi_times_thousand=3.14E3
+\endverbatim
+
+Non-existent or misspelled parameters are ignored.
+Parameters are not required, every parameter has a default value, which can be found
+in function \b \c init_parameters of src/cstream.c.
+
+The following overview lists the parameters generally meant for testing purposes and changing them is not required for streamer simulations. Therefore they are best left at their default value.
+
+File and directory handling:
+ \li \b \c cdr\_output\_margin - Number of margin-cells to be added to the output of the density grids. 2 layers of ghost cells are added on the edge of the computational domain for the purpose of enforcing boundary conditions. With this parameter, these can be included in the output. Value must be smaller than or equal to 2. Default \b \c cdr\_output\_margin = 0.
+ \li \b \c pois\_output - Output the grids used in solving the Poisson equation? The grids used for the Poisson equation are different than those used for the density equations as detailed in section \ref sect_refinement. \b \c pois\_output = 0. Note that the absolute electric field is already saved as a density grid, so it is not required to set this parameter to 1 to obtain this data.
+ \li \b \c pois\_output\_margin - Number of margin-cells to be added to the output of the Poisson grids. Default \b \c pois\_output\_margin = 0. Note : \b \c pois\_output\_margin <= 2.
+
+Physical parameters:
+ \li \b \c start\_t - Initial time. This parameter is used when resuming simulations and is automatically updated in that case.
+
+Numerical parameters: \n
+
+The adaptive mesh refinement criteria and the parameters related to them are discussed in more detail in section \ref sect_refinement.
+
+ \li \b \c ref\_threshold\_eabs - Refine grid if \f$|\mathbf{E}|\f$ exceeds this value.
+ \li \b \c ref\_level\_eabs - Maximum number of refinement levels of the grid for the fluid equation due to the \f$|\mathbf{E}|\f$ criterion.
+ \li \b \c ref\_threshold\_charge - Refinement threshold for the curvature of the charge density.
+ \li \b \c ref\_threshold\_dens - Refinement threshold for the curvature of the particle densities.
+ \li \b \c cdr\_brick\_r, \b \c cdr\_brick\_z - Size \f$(r\f$ and \f$z)\f$ of the minimal refinement area. See Section \ref sect_size_refinement.
+ \li \b \c pois\_max\_error - An area of the Poisson grid is further refined if the relative error between two consecutive refined levels exceeds this value.
+ \li \b \c nu\_a - Courant number based on advection to determine the time step. Note, that \b \c nu\_a < 1 to satisfy CFL stability. In streamer simulations, this time step restriction will dominate over other parameters (\b \c nu\_d (diffusion) and \b \c nu\_rt (reaction)). More details on the time stepping can be found in \ref sect_timestepping.
+
+\subsubsection sect_needle Implementation of the needle-plane configuration
+
+As mentioned in section \ref sect_overview , the needle-plane electrode geometry is
+implemented using a charge simulation technique, which means that the entire needle is
+represented by a single point charge located on the axis.
+The position and strength of this charge is updated each time step to ensure that the
+potential at the point that would be the tip of the needle remains fixed.
+A schematic depiction of this setup can be seen in [Figure 1.](#setup).
+This provides a reasonable approximation of the potential in the area below
+the needle (the needle is always located at the top of the domain), but the potential
+will be wrong in the areas to the sides of the needle.
+Consequently, the density equations are only solved from the tip of the needle and downwards.
+This means that the computational domain for the density equations is smaller than
+that for the Poisson equation.
+
+In the specification of the external electric field, \c E0\_z is interpreted as the electric field between the two planar electrodes, far away from the needle. The applied potential is computed as follows:
+\f[
+ V = E_{0,z} * (L_z + L_{needle})
+\f]
+
+\subsubsection sect_output Output
+
+The code generates a large amount of output files at every \c \b output\_dt units
+of simulated time.
+These output files combined are sufficient to resume the simulation
+from that time step and can also be used for data analysis.
+Output files are named \c variable.C123abc.tsv, where 'tsv' stands for 'Tab-Separated Values'.
+\c variable is a particle species or electric field.
+Examples include \c electrons, \c n2plus and \c eabs
+(the latter being \f$|\mathbf{E}|\f$). \c 123 is the sequence number or
+output time step (which is unrelated to the time step of the numerical scheme) of that
+output set, it starts at \c 000 for the first set.
+This is the initial condition of the system before the simulation starts at \f$t = 0\f$.
+The alphabetic part of the filename after the output time step, \c abc denotes the
+subgrid contained in that file and this extension is defined recursively.
+The coarsest grid covering the entire domain has no such alphabetical extension
+(example: \c electrons.C123.tsv).
+At every next level, the subgrids at that level are named \c a, \c b, \c c, ...
+and this letter is appended to the alphabetical extension.
+The file \c electrons.C123ba.tsv contains electron densities at the
+123-th time step (so at \f$t = 123 * output\_dt\f$ ) for the first
+subgrid of the second subgrid of the main grid.
+Beware that since the grid refinement is adaptive, each time step has different subgrids.
+
+
+\par Figure 4. Schematic depiction of the naming convention for output files. Each next letter corresponds to a new refined level.
+
+Data, as shown in Figure 4., is stored as plain text,
+with each line containing a single number.
+Data is ordered in columns (with fixed \f$r\f$ coordinate).
+So to read the data, use the following pseudo-code:
+\verbatim
+for (i = 0, i < rmax*zmax; i++)
+{
+ r = floor(i / zmax);
+ z = i % zmax;
+ data[r,z] = read_line_from_file();
+}
+\endverbatim
+
+The dimensions of the grid are not contained in the data files.
+Instead, for each subgrid and output-step, two additional files are created:
+
+1. _r.C123abc.tsv_\n
+2. _z.C123abc.tsv_\n
+\n
+
+corresponding to subgrid _abc_ of output step _123_. The structure of these files is identical to that of the regular data files, but instead of particle densities or electric field strengths, these files contain the \f$r\f$ and \f$z\f$ coordinates of the center of the cell corresponding to that line-number. So to determine the coordinates of the \f$n^{th}\f$ line in a regular data file, simply read the \f$n^{th}\f$ line of the corresponding \b r and \b z files.
+
+\subsubsection sect_structure File structure
+
+
+\par Figure 5. File structure of of ARCoS package.
+
+The distribution of the ARCoS package contains several directories:
+
+\li \b \c FISH90 - the directory where FISH90 or FISHPACK should be downloaded
+
+\li \b \c output - this directory may be empty. Its name must correspond to the value of \b \c output_dir in file input/default.cfg. Or, the value in input/user_init.cfg if present.
+\li \b \c python - contains plot files. By means of \b \c plotvar pictures can be made of the output files. Not yet implemented.
+\li \b \c doc - directory with files for [Doxygen][12] to generate documentation from source code and this \b \c MANUAL. The source of this manual (in MANUAL.md) can be found in its directory \b \c markdown. See also the \b \c doxygen_config_file.
+\li \b \c arcos_f90 - a part of the \b \c functions in file cdr.c have been replaced by a piece of \b \c FORTRAN90 code in order to accelerate the simulation.
+\li \b \c src - this directory contains the source files written in \b \c c.
+\li \b \c include - this directory contains the include files
+\li \b \c input - this directory contains all input files. Most of them are libconfig configuration files.
+
+
+\subsubsection sect_source Source files
+
+The \c ARCoS simulation software was mostly written in \c C and its source code is split up in several files, each dealing with a separate part of the program. Most source files have an associated header file (the source file \b \c example.c has header file \b \c example.h ) containing the type-definitions and preprocessor macros. The function prototypes are aggregated in the header file \c proto.h. Below is a short summary of the important source files and the functionality that is contained within them.
+
+ \li cdr.c - Functions for solving the convection-diffusion-reaction (CDR) equations, creation, manipulation and refinement of CDR grids and time stepping.
+ \li configuration.c - Module for input/output of parameters. The code uses the library
+[libconfig](http://www.hyperrealm.com/libconfig/)
+ \li cstream.c - Contains some general initialization and termination functions.
+ \li dft.c - Functions related with discrete fourier transformations.
+ \li grid.c - Low-level functions for handling of grids, both CDR and Poisson grids.
+ \li interpol2.c - Interpolation functions for the mapping of one grid to another (for example during refinement).
+ \li main.c - Functions for reading input parameters, starting of the code and the main loop.
+ \li mapper.c - Mapping of one grid tree onto another.
+ \li misc.c - Miscellaneous utilities for allocating memory.
+ \li photo.c - Photoionization functions.
+ \li poisson.c - Functions for solving the Poisson equation, including manipulation of Poisson grids and calling the external [FISPACK][9] solver.
+ \li reaction.c - Functions for computation of reactions between species as part of the density equations.
+ \li react_table.c - Performs initialization of reaction coefficient tables as well as table lookups.
+ \li rt.c - Functions for handling the loading of the input file containing the kinetic model (species, reactions, seeds).
+ \li rz_array.c - Low-level functions for handling Fortran-compatible arrays.
+ \li sprites.c - Routines for the sprites module.
diff --git a/fish90/README b/fish90/README
new file mode 100644
index 0000000000000000000000000000000000000000..b8240054f60c5825623b333505a5343de070129b
--- /dev/null
+++ b/fish90/README
@@ -0,0 +1,24 @@
+
+SCD released version 1.1 of FISHPACK90 on December 19, 2005. It is an
+improvement over Version 1.0 in that it uses Fortran90 intrinsic function
+ASSOCIATED to check on pointer association. Also, version 1.1 offers
+an integated Makefile for use with gmake.
+
+Here is some history for version 1.0:
+
+SCD released FISHPACK90 1.0 in September 30 2004. It is an improvement
+of the original Fortran77 FISHPACK insofar as it has removed workspace
+arguments in the solvers, replacing them with FORTRAN90 derived data
+types that are pointers to real and complex allocatable arrays and are
+opaque to user level interface. And also this version replaced many
+internal interfaces in conformance with strict prototype
+matching of Fortran90.
+
+Neither version FISHPACK90 1.0 nor 1.1 are full-blown Fortran90
+implementation of FISHPACK. User calls to the old FISHPACK solvers are
+not compatible with calls to FISHPACK90 solvers.
+
+IMPORTANT NOTE: FISHPACK90 has dependencies in the FFTPACK library; the
+present version of FFTPACK has not been updated in the same manner as
+FISHPACK90. That is, FFTPACK may not strictly conform to the Fortran90
+interface specification.
diff --git a/fish90/include/fishpack.h b/fish90/include/fishpack.h
new file mode 100644
index 0000000000000000000000000000000000000000..18513055b11fa3e6a5b9ce39fa39a550ba1fccb9
--- /dev/null
+++ b/fish90/include/fishpack.h
@@ -0,0 +1,50 @@
+#ifndef _FISPHACK_H_
+
+/* Arguments for the boundary conditions in fishpack:
+ The first name is the b.c. at the lowest value of the variable,
+ the second one is the b.c. at the highest value.
+ DIR = Dirichlet,
+ NEU = Neumann,
+ UNS = Unspecified (when r = 0 for cylindrical calculations).
+*/
+#define FISH_PERIODIC 0
+#define FISH_DIR_DIR 1
+#define FISH_DIR_NEU 2
+#define FISH_NEU_NEU 3
+#define FISH_NEU_DIR 4
+
+#define FISH_UNS_DIR 5
+#define FISH_UNS_NEU 6
+
+
+/* This is the maximum number of grid cells that fishpack can handle
+ without accumulating larger and larger roundoff errors
+ (it's only an approximation: not checked throughly so if you notice
+ that you are getting strange things such as artificial lines in
+ the electric field, this is the first thing you should check). */
+#define FISH_MAX_GRIDPOINTS 1700
+
+#define LOG2 0.69314718055994530941723212145818
+
+#define FISH_WORK(M_, N_) (13 * (M_) + 4 * (N_) \
+ + (M_) * (int) (log(N_) / LOG2))
+
+#define FISH_ERROR_MAX 13
+const char *hstcyl_error_str[FISH_ERROR_MAX];
+
+void
+fish_hstcyl (double r0, double r1, int nr,
+ int rbndcnd, double *bcr0, double *bcr1,
+ double z0, double z1, int nz,
+ int zbndcnd, double *bcz0, double *bcz1,
+ double lambda, double s, double *f, int idimf);
+void
+fish_hstcrt (double r0, double r1, int nr,
+ int rbndcnd, double *bcr0, double *bcr1,
+ double z0, double z1, int nz,
+ int zbndcnd, double *bcz0, double *bcz1,
+ double lambda, double *f, int idimf);
+
+#define _FISHPACK_H_
+#endif /* _FISHPACK_H_ */
+
diff --git a/fish90/src/Makefile b/fish90/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8b56cb940710d031bf8038a5b1f0223c18546fc1
--- /dev/null
+++ b/fish90/src/Makefile
@@ -0,0 +1,39 @@
+# This Makefile builds the FISH90 library.
+# FISH90 is a modified F90 version of FISHPACK
+
+TOPDIR := ../..
+
+include $(TOPDIR)/Makefile.config
+include $(TOPDIR)/Makefile.inc
+
+LIBFISH = ../lib/libfish90.a
+
+.PHONY: all
+
+all:
+ @echo
+ @echo "###############################"
+ @echo "### BUILDING FISH90 library ###"
+ @echo "###############################"
+ @echo
+ make lib
+
+SRCF = genbunal.f90 gnbnaux.f90 hst_procs.f90 poisson.f90
+SRCC = hstcrt_wrap.c hstcyl_wrap.c
+
+OBJF = $(subst .f90,.o,$(SRCF))
+OBJC = $(subst .c,.o,$(SRCC))
+OBJ := fish.o $(OBJF) $(OBJC)
+
+hst_procs.o : fish.o genbunal.o poisson.o
+genbunal.o : gnbnaux.o poisson.o
+poisson.o : gnbnaux.o
+
+lib : $(LIBFISH)
+
+$(LIBFISH) : $(OBJ)
+ $(AR) $@ $?
+ mv fish.mod ../lib
+
+clean:
+ rm -f $(LIBFISH) $(OBJ) *~ ../lib/fish.mod ../lib/FISH.mod fish.f
diff --git a/fish90/src/fish.F b/fish90/src/fish.F
new file mode 100644
index 0000000000000000000000000000000000000000..616b5166bcd7a446db9104debea75b92a06783b4
--- /dev/null
+++ b/fish90/src/fish.F
@@ -0,0 +1,166 @@
+!
+! file fish.f
+!
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+! . .
+! . copyright (c) 2004 by UCAR .
+! . .
+! . UNIVERSITY CORPORATION for ATMOSPHERIC RESEARCH .
+! . .
+! . all rights reserved .
+! . .
+! . .
+! . FISHPACK version 5.0 .
+! . .
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+!
+!
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+! * *
+! * F I S H P A C K *
+! * *
+! * *
+! * A PACKAGE OF FORTRAN SUBPROGRAMS FOR THE SOLUTION OF *
+! * *
+! * SEPARABLE ELLIPTIC PARTIAL DIFFERENTIAL EQUATIONS *
+! * *
+! * (Version 5.0 , JUNE 2004) *
+! * *
+! * BY *
+! * *
+! * JOHN ADAMS, PAUL SWARZTRAUBER AND ROLAND SWEET *
+! * *
+! * OF *
+! * *
+! * THE NATIONAL CENTER FOR ATMOSPHERIC RESEARCH *
+! * *
+! * BOULDER, COLORADO (80307) U.S.A. *
+! * *
+! * WHICH IS SPONSORED BY *
+! * *
+! * THE NATIONAL SCIENCE FOUNDATION *
+! * *
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+!
+!
+
+! this module is used by all fishpack solvers to allocate
+! real and complex work space
+ MODULE fish
+
+ TYPE fishworkspace
+ DOUBLE PRECISION,DIMENSION(:),ALLOCATABLE :: rew
+ COMPLEX,DIMENSION(:),ALLOCATABLE :: cxw
+ END TYPE fishworkspace
+
+ CONTAINS
+ SUBROUTINE allocatfish(irwk,icwk,wsave,ierror)
+ IMPLICIT NONE
+ TYPE (fishworkspace) :: wsave
+! irwk is the required real work space length
+! icwk is the required integer work space length
+ INTEGER, INTENT(IN) :: irwk,icwk
+! ierror is set to 20 if the dynamic allocation is unsuccessful
+! (e.g., this would happen if m,n are too large for the computers memory
+ INTEGER, INTENT(INOUT) :: ierror
+ INTEGER :: istatus
+! first deallocate to avoid memory leakage
+ write(*,*) 'fish.F: allocatfish'
+ if(allocated(wsave%rew)) then
+ write(*,*) 'allocated wsave%rew, size= ',size(wsave%rew)
+ DEALLOCATE(wsave%rew,STAT=istatus)
+ write(*,*) 'deallocate wsave%rew, istatus=',istatus
+ end if
+! allocate irwk words of real work space
+ if (irwk > 0) then
+ ALLOCATE(wsave%rew(irwk),STAT = istatus)
+ write(*,*) 'fish.F: allocatfish, irwk:',irwk
+ end if
+!
+ if(allocated(wsave%cxw)) then
+ write(*,*) 'allocated wsave%cxw, size=',size(wsave%cxw)
+ DEALLOCATE(wsave%cxw,STAT=istatus)
+ write(*,*) 'deallocate wsave%cxw, istatus=',istatus
+ end if
+! allocate icwk words of complex work space
+ if (icwk > 0) then
+ ALLOCATE(wsave%cxw(icwk),STAT = istatus)
+ write(*,*) 'fish.F: allocatfish, icrk:',icwk
+ end if
+ ierror = 0
+! flag fatal error if allocation fails
+ if (istatus .ne. 0 ) then
+ ierror = 20
+ END IF
+ RETURN
+ END SUBROUTINE allocatfish
+
+ SUBROUTINE BLK_space(N,M,irwk,icwk)
+! this subroutine computes the real and complex work space
+! requirements (generous estimate) of blktri for N,M values
+ IMPLICIT NONE
+ INTEGER,INTENT(IN) :: N,M
+ INTEGER,INTENT(OUT) :: irwk,icwk
+ INTEGER :: L,log2n
+! compute nearest integer greater than or equal to
+! log base 2 of n+1, i.e., log2n is smallest integer
+! such that 2**log2n >= n+1
+ log2n = 1
+ do
+ log2n = log2n+1
+ if (n+1 <= 2**log2n) EXIT
+ end do
+ L = 2**(log2n+1)
+ irwk = (log2n-2)*L+5+MAX0(2*N,6*M)+log2n+2*n
+ icwk = ((log2n-2)*L+5+log2n)/2+3*M+N
+ RETURN
+ END SUBROUTINE BLK_space
+
+ SUBROUTINE GEN_space(N,M,irwk)
+! this subroutine computes the real work space
+! requirement (generously) of genbun for the current N,M
+ IMPLICIT NONE
+ INTEGER,INTENT(IN) :: N,M
+ INTEGER,INTENT(OUT) :: irwk
+ INTEGER :: log2n
+! compute nearest integer greater than or equal to
+! log base 2 of n+1, i.e., log2n is smallest integer
+! such that 2**log2n >= n+1
+ log2n = 1
+ do
+ log2n = log2n+1
+ if (n+1 <= 2**log2n) EXIT
+ end do
+ irwk = 4*N + (10 + log2n)*M
+ RETURN
+ END SUBROUTINE GEN_space
+
+ SUBROUTINE fishfin(wsave,ierror)
+! this subroutine releases allocated work space
+! fishfin should be called after a fishpack solver has finished
+! TYPE (fishworkspace) variable wsave.
+ IMPLICIT NONE
+ TYPE (fishworkspace) :: wsave
+ INTEGER,intent(out) :: ierror
+ INTEGER :: istatus
+!
+ write(*,*) 'fish.F: fishfin'
+ if(allocated(wsave%rew)) then
+ write(*,*) 'deallocated wsave%rew, size= ',size(wsave%rew)
+ DEALLOCATE(wsave%rew,STAT=istatus)
+ end if
+ if(allocated(wsave%cxw)) then
+ write(*,*) 'deallocated wsave%cxw, size=',size(wsave%cxw)
+ DEALLOCATE(wsave%cxw,STAT=istatus)
+ end if
+! #ifndef G95
+ ! if(associated(wsave%rew))DEALLOCATE(wsave%rew)
+ ! if(associated(wsave%cxw))DEALLOCATE(wsave%cxw)
+! #endif
+ if (istatus .ne. 0 ) then
+ ierror = 20
+ END IF
+
+ END SUBROUTINE fishfin
+
+ END MODULE fish
diff --git a/fish90/src/genbunal.f90 b/fish90/src/genbunal.f90
new file mode 100644
index 0000000000000000000000000000000000000000..c4d025d8c880227ef1b1b6bbc5f3c28ac9d6d4ac
--- /dev/null
+++ b/fish90/src/genbunal.f90
@@ -0,0 +1,1325 @@
+!
+! file genbun.f
+!
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+! . .
+! . copyright (c) 2004 by UCAR .
+! . .
+! . UNIVERSITY CORPORATION for ATMOSPHERIC RESEARCH .
+! . .
+! . all rights reserved .
+! . .
+! . .
+! . FISHPACK version 5.0 .
+! . .
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+!
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+! * *
+! * F I S H P A C K *
+! * *
+! * *
+! * A PACKAGE OF FORTRAN SUBPROGRAMS FOR THE SOLUTION OF *
+! * *
+! * SEPARABLE ELLIPTIC PARTIAL DIFFERENTIAL EQUATIONS *
+! * *
+! * (Version 5.0 , JUNE 2004) *
+! * *
+! * BY *
+! * *
+! * JOHN ADAMS, PAUL SWARZTRAUBER AND ROLAND SWEET *
+! * *
+! * OF *
+! * *
+! * THE NATIONAL CENTER FOR ATMOSPHERIC RESEARCH *
+! * *
+! * BOULDER, COLORADO (80307) U.S.A. *
+! * *
+! * WHICH IS SPONSORED BY *
+! * *
+! * THE NATIONAL SCIENCE FOUNDATION *
+! * *
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+!
+! SUBROUTINE GENBUN (NPEROD,N,MPEROD,M,A,B,C,IDIMY,Y,IERROR)
+!
+!
+! DIMENSION OF A(M),B(M),C(M),Y(IDIMY,N)
+! ARGUMENTS
+!
+! LATEST REVISION JUNE 2004
+!
+! PURPOSE THE NAME OF THIS PACKAGE IS A MNEMONIC FOR THE
+! GENERALIZED BUNEMAN ALGORITHM.
+!
+! IT SOLVES THE REAL LINEAR SYSTEM OF EQUATIONS
+!
+! A(I)*X(I-1,J) + B(I)*X(I,J) + C(I)*X(I+1,J)
+! + X(I,J-1) - 2.*X(I,J) + X(I,J+1) = Y(I,J)
+!
+! FOR I = 1,2,...,M AND J = 1,2,...,N.
+!
+! INDICES I+1 AND I-1 ARE EVALUATED MODULO M,
+! I.E., X(0,J) = X(M,J) AND X(M+1,J) = X(1,J),
+! AND X(I,0) MAY EQUAL 0, X(I,2), OR X(I,N),
+! AND X(I,N+1) MAY EQUAL 0, X(I,N-1), OR X(I,1)
+! DEPENDING ON AN INPUT PARAMETER.
+!
+! USAGE CALL GENBUN (NPEROD,N,MPEROD,M,A,B,C,IDIMY,Y,
+! IERROR)
+!
+! ARGUMENTS
+!
+! ON INPUT NPEROD
+!
+! INDICATES THE VALUES THAT X(I,0) AND
+! X(I,N+1) ARE ASSUMED TO HAVE.
+!
+! = 0 IF X(I,0) = X(I,N) AND X(I,N+1) =
+! X(I,1).
+! = 1 IF X(I,0) = X(I,N+1) = 0 .
+! = 2 IF X(I,0) = 0 AND X(I,N+1) = X(I,N-1).
+! = 3 IF X(I,0) = X(I,2) AND X(I,N+1) =
+! X(I,N-1).
+! = 4 IF X(I,0) = X(I,2) AND X(I,N+1) = 0.
+!
+! N
+! THE NUMBER OF UNKNOWNS IN THE J-DIRECTION.
+! N MUST BE GREATER THAN 2.
+!
+! MPEROD
+! = 0 IF A(1) AND C(M) ARE NOT ZERO
+! = 1 IF A(1) = C(M) = 0
+!
+! M
+! THE NUMBER OF UNKNOWNS IN THE I-DIRECTION.
+! N MUST BE GREATER THAN 2.
+!
+! A,B,C
+! ONE-DIMENSIONAL ARRAYS OF LENGTH M THAT
+! SPECIFY THE COEFFICIENTS IN THE LINEAR
+! EQUATIONS GIVEN ABOVE. IF MPEROD = 0
+! THE ARRAY ELEMENTS MUST NOT DEPEND UPON
+! THE INDEX I, BUT MUST BE CONSTANT.
+! SPECIFICALLY, THE SUBROUTINE CHECKS THE
+! FOLLOWING CONDITION .
+!
+! A(I) = C(1)
+! C(I) = C(1)
+! B(I) = B(1)
+!
+! FOR I=1,2,...,M.
+!
+! IDIMY
+! THE ROW (OR FIRST) DIMENSION OF THE
+! TWO-DIMENSIONAL ARRAY Y AS IT APPEARS
+! IN THE PROGRAM CALLING GENBUN.
+! THIS PARAMETER IS USED TO SPECIFY THE
+! VARIABLE DIMENSION OF Y.
+! IDIMY MUST BE AT LEAST M.
+!
+! Y
+! A TWO-DIMENSIONAL COMPLEX ARRAY THAT
+! SPECIFIES THE VALUES OF THE RIGHT SIDE
+! OF THE LINEAR SYSTEM OF EQUATIONS GIVEN
+! ABOVE.
+! Y MUST BE DIMENSIONED AT LEAST M*N.
+!
+!
+! ON OUTPUT Y
+!
+! CONTAINS THE SOLUTION X.
+!
+! IERROR
+! AN ERROR FLAG WHICH INDICATES INVALID
+! INPUT PARAMETERS EXCEPT FOR NUMBER
+! ZERO, A SOLUTION IS NOT ATTEMPTED.
+!
+! = 0 NO ERROR.
+! = 1 M .LE. 2 .
+! = 2 N .LE. 2
+! = 3 IDIMY .LT. M
+! = 4 NPEROD .LT. 0 OR NPEROD .GT. 4
+! = 5 MPEROD .LT. 0 OR MPEROD .GT. 1
+! = 6 A(I) .NE. C(1) OR C(I) .NE. C(1) OR
+! B(I) .NE. B(1) FOR
+! SOME I=1,2,...,M.
+! = 7 A(1) .NE. 0 OR C(M) .NE. 0 AND
+! MPEROD = 1
+! = 20 If the dynamic allocation of real and
+! complex work space required for solution
+! fails (for example if N,M are too large
+! for your computer)
+!
+!
+! SPECIAL CONDITONS NONE
+!
+! I/O NONE
+!
+! PRECISION SINGLE
+!
+! REQUIRED FILES comf.f,gnbnaux.f,fish.f
+! FILES
+!
+! LANGUAGE FORTRAN 90
+!
+! HISTORY WRITTEN IN 1979 BY ROLAND SWEET OF NCAR'S
+! SCIENTIFIC COMPUTING DIVISION. MADE AVAILABLE
+! ON NCAR'S PUBLIC LIBRARIES IN JANUARY, 1980.
+! Revised in June 2004 by John Adams using
+! Fortran 90 dynamically allocated work space.
+!
+! ALGORITHM THE LINEAR SYSTEM IS SOLVED BY A CYCLIC
+! REDUCTION ALGORITHM DESCRIBED IN THE
+! REFERENCE.
+!
+! PORTABILITY FORTRAN 90 --
+! THE MACHINE DEPENDENT CONSTANT PI IS
+! DEFINED IN FUNCTION PIMACH.
+!
+! REFERENCES SWEET, R., "A CYCLIC REDUCTION ALGORITHM FOR
+! SOLVING BLOCK TRIDIAGONAL SYSTEMS OF ARBITRARY
+! DIMENSIONS," SIAM J. ON NUMER. ANAL., 14 (1977)
+! PP. 706-720.
+!
+! ACCURACY THIS TEST WAS PERFORMED ON a platform with
+! 64 bit floating point arithmetic.
+! A UNIFORM RANDOM NUMBER GENERATOR WAS USED
+! TO CREATE A SOLUTION ARRAY X FOR THE SYSTEM
+! GIVEN IN THE 'PURPOSE' DESCRIPTION ABOVE
+! WITH
+! A(I) = C(I) = -0.5*B(I) = 1, I=1,2,...,M
+!
+! AND, WHEN MPEROD = 1
+!
+! A(1) = C(M) = 0
+! A(M) = C(1) = 2.
+!
+! THE SOLUTION X WAS SUBSTITUTED INTO THE
+! GIVEN SYSTEM AND, USING DOUBLE PRECISION
+! A RIGHT SIDE Y WAS COMPUTED.
+! USING THIS ARRAY Y, SUBROUTINE GENBUN
+! WAS CALLED TO PRODUCE APPROXIMATE
+! SOLUTION Z. THEN RELATIVE ERROR
+! E = MAX(ABS(Z(I,J)-X(I,J)))/
+! MAX(ABS(X(I,J)))
+! WAS COMPUTED, WHERE THE TWO MAXIMA ARE TAKEN
+! OVER I=1,2,...,M AND J=1,...,N.
+!
+! THE VALUE OF E IS GIVEN IN THE TABLE
+! BELOW FOR SOME TYPICAL VALUES OF M AND N.
+!
+! M (=N) MPEROD NPEROD E
+! ------ ------ ------ ------
+!
+! 31 0 0 6.E-14
+! 31 1 1 4.E-13
+! 31 1 3 3.E-13
+! 32 0 0 9.E-14
+! 32 1 1 3.E-13
+! 32 1 3 1.E-13
+! 33 0 0 9.E-14
+! 33 1 1 4.E-13
+! 33 1 3 1.E-13
+! 63 0 0 1.E-13
+! 63 1 1 1.E-12
+! 63 1 3 2.E-13
+! 64 0 0 1.E-13
+! 64 1 1 1.E-12
+! 64 1 3 6.E-13
+! 65 0 0 2.E-13
+! 65 1 1 1.E-12
+! 65 1 3 4.E-13
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ SUBROUTINE GENBUN(NPEROD, N, MPEROD, M, A, B, C, IDIMY, Y, IERROR)
+ USE fish
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+ TYPE(fishworkspace) :: w
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: NPEROD, N, MPEROD, M, IDIMY
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, DIMENSION(:) :: A, B, C
+ DOUBLE PRECISION, INTENT(INOUT) :: Y(IDIMY,*)
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: IRWK, ICWK
+!-----------------------------------------------
+
+ write(*,*) 'fish90: genbun'
+ IERROR = 0
+! check input arguments
+ IF (M <= 2) then
+ ierror = 1
+ return
+ end if
+ IF (N <= 2) then
+ ierror = 2
+ return
+ end if
+ IF (IDIMY < M) then
+ ierror = 3
+ return
+ end if
+ IF (NPEROD<0 .OR. NPEROD>4) then
+ ierror = 4
+ return
+ end if
+ IF (MPEROD<0 .OR. MPEROD>1) then
+ ierror = 5
+ return
+ end if
+! compute and allocate real work space for genbun
+ CALL GEN_SPACE (N, M, IRWK)
+ ICWK = 0
+ CALL ALLOCATFISH (IRWK, ICWK, W, IERROR)
+! return if allocation failed (e.g., if n,m are too large)
+ IF (IERROR == 20) THEN
+ write(*,*) 'error call ALLOCATFISH'
+ RETURN
+ END IF
+ call genbunn(NPEROD,N,MPEROD,M,A,B,C,IDIMY,Y,IERROR,w%rew,IRWK)
+! release allocated work space
+ CALL FISHFIN (W,IERROR)
+ IF (IERROR == 20) THEN
+ write(*,*) 'error call FISHFIN'
+ RETURN
+ END IF
+!
+ END SUBROUTINE GENBUN
+
+
+ SUBROUTINE GENBUNN(NPEROD,N,MPEROD,M,vecA,vecB,vecC,IDIMY,matY, &
+ IERROR,vecW,IW)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: NPEROD, N, MPEROD, M, IDIMY,IW
+ INTEGER, INTENT(INOUT) :: IERROR
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA, vecB, vecC
+ DOUBLE PRECISION, DIMENSION(IW), INTENT(OUT) :: vecW
+ DOUBLE PRECISION, DIMENSION(IDIMY,N),INTENT(INOUT) :: matY
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: I, MP1, IWBA, IWBB, IWBC, IWB2, IWB3, IWW1, IWW2, IWW3, &
+ IWD, IWTCOS, IWP, IW2, K, J, MP, NP, &
+ IPSTOR, IREV, MH, MHM1, MODD, NBY2, MSKIP
+ DOUBLE PRECISION :: A1
+!-----------------------------------------------
+ IF (MPEROD /= 1) THEN
+ DO I = 2, M
+ IF (vecA(I) /= vecC(1)) GO TO 103
+ IF (vecC(I) /= vecC(1)) GO TO 103
+ IF (vecB(I) /= vecB(1)) GO TO 103
+ END DO
+ GO TO 104
+ ENDIF
+ IF (vecA(1)/=ZERO .OR. vecC(M)/=ZERO) IERROR = 7
+ GO TO 104
+ 103 CONTINUE
+ IERROR = 6
+ 104 CONTINUE
+ IF (IERROR /= 0) RETURN
+ MP1 = M + 1
+ IWBA = MP1
+ IWBB = IWBA + M
+ IWBC = IWBB + M
+ IWB2 = IWBC + M
+ IWB3 = IWB2 + M
+ IWW1 = IWB3 + M
+ IWW2 = IWW1 + M
+ IWW3 = IWW2 + M
+ IWD = IWW3 + M
+ IWTCOS = IWD + M
+ IWP = IWTCOS + 4*N
+ vecW(IWBA:M-1+IWBA) = -vecA(:M)
+ vecW(IWBC:M-1+IWBC) = -vecC(:M)
+ vecW(IWBB:M-1+IWBB) = TWO - vecB(:M)
+ matY(:M,:N) = -matY(:M,:N)
+ MP = MPEROD + 1
+ NP = NPEROD + 1
+ GO TO (114,107) MP
+ 107 CONTINUE
+ GO TO (108,109,110,111,123) NP
+ 108 CONTINUE
+ IW2 = IW - IWP + 1
+ CALL POISP2 (M, N, vecW(IWBA:IWBA+M-1), vecW(IWBB:IWBB+M-1), &
+ vecW(IWBC:IWBC+M-1), matY, IDIMY, &
+ vecW(1:M), vecW(IWB2:IWB2+M-1), vecW(IWB3:IWB3+M-1), &
+ vecW(IWW1:IWW1+M-1), vecW(IWW2:IWW2+M-1), &
+ vecW(IWW3:IWW3+M-1), vecW(IWD:IWD+M-1), &
+ vecW(IWTCOS:IWTCOS+4*N-1), vecW(IWP:),IW2)
+ GO TO 112
+ 109 CONTINUE
+ IW2 = IW - IWP + 1
+ CALL POISD2 (M, N, 1, vecW(IWBA:IWBA+M-1), vecW(IWBB:IWBB+M-1), &
+ vecW(IWBC::IWBC+M-1), matY, IDIMY, &
+ vecW(1:M), vecW(IWW1:IWW1+M-1), vecW(IWD:IWD+M-1), &
+ vecW(IWTCOS:IWTCOS+4*N-1), vecW(IWP:), IW2)
+ GO TO 112
+ 110 CONTINUE
+ IW2 = IW - IWP + 1
+ CALL POISN2 (M, N, 1, 2, vecW(IWBA:IWBA+M-1), vecW(IWBB:IWBB+M-1), &
+ vecW(IWBC:IWBC+M-1), matY, IDIMY, vecW(1:M), &
+ vecW(IWB2:IWB2+M-1), vecW(IWB3:IWB3+M-1), &
+ vecW(IWW1:IWW1+M-1), vecW(IWW2:IWW2+M-1), &
+ vecW(IWW3::IWW3+M-1), vecW(IWD:IWD+M-1), &
+ vecW(IWTCOS:IWTCOS+4*N-1),vecW(IWP:),IW2)
+ GO TO 112
+ 111 CONTINUE
+ IW2 = IW - IWP + 1
+ CALL POISN2 (M, N, 1, 1, vecW(IWBA:IWBA+M-1), vecW(IWBB:IWBB+M-1), &
+ vecW(IWBC::IWBC+M-1), matY, IDIMY, vecW(1:M), &
+ vecW(IWB2:IWW1+M-1), vecW(IWB3:IWB3+M-1), &
+ vecW(IWW1:IWW1+M-1), vecW(IWW2:IWW2+M-1), &
+ vecW(IWW3::IWW3+M-1), vecW(IWD:IWD+M-1), &
+ vecW(IWTCOS:IWTCOS+4*N-1),vecW(IWP:),IW2)
+ 112 CONTINUE
+ IPSTOR = vecW(IWW1)
+ IREV = 2
+ IF (NPEROD == 4) GO TO 124
+ 113 CONTINUE
+ GO TO (127,133) MP
+ 114 CONTINUE
+ MH = (M + 1)/2
+ MHM1 = MH - 1
+ MODD = 1
+ IF (MH*2 == M) MODD = 2
+ DO J = 1, N
+ vecW(:MHM1) = matY(MH-1:MH-MHM1:(-1),J) - matY(MH+1:MHM1+MH,J)
+ vecW(MH+1:MHM1+MH) = matY(MH-1:MH-MHM1:(-1),J) + matY(MH+1:MHM1+MH,J)
+ vecW(MH) = TWO*matY(MH,J)
+ GO TO (117,116) MODD
+ 116 CONTINUE
+ vecW(M) = TWO*matY(M,J)
+ 117 CONTINUE
+ matY(:M,J) = vecW(:M)
+ END DO
+ K = IWBC + MHM1 - 1
+ I = IWBA + MHM1
+ vecW(K) = ZERO
+ vecW(I) = ZERO
+ vecW(K+1) = TWO*vecW(K+1)
+ SELECT CASE (MODD)
+ CASE DEFAULT
+ K = IWBB + MHM1 - 1
+ vecW(K) = vecW(K) - vecW(I-1)
+ vecW(IWBC-1) = vecW(IWBC-1) + vecW(IWBB-1)
+ CASE (2)
+ vecW(IWBB-1) = vecW(K+1)
+ END SELECT
+ GO TO 107
+!
+! REVERSE COLUMNS WHEN NPEROD = 4.
+!
+ 123 CONTINUE
+ IREV = 1
+ NBY2 = N/2
+ 124 CONTINUE
+ DO J = 1, NBY2
+ MSKIP = N + 1 - J
+ DO I = 1, M
+ A1 = matY(I,J)
+ matY(I,J) = matY(I,MSKIP)
+ matY(I,MSKIP) = A1
+ END DO
+ END DO
+ GO TO (110,113) IREV
+ 127 CONTINUE
+ DO J = 1, N
+ vecW(MH-1:MH-MHM1:(-1)) = HALF*(matY(MH+1:MHM1+MH,J)+matY(:MHM1,J))
+ vecW(MH+1:MHM1+MH) = HALF*(matY(MH+1:MHM1+MH,J)-matY(:MHM1,J))
+ vecW(MH) = HALF*matY(MH,J)
+ GO TO (130,129) MODD
+ 129 CONTINUE
+ vecW(M) = HALF*matY(M,J)
+ 130 CONTINUE
+ matY(:M,J) = vecW(:M)
+ END DO
+ 133 CONTINUE
+ vecW(1) = IPSTOR + IWP - 1
+ RETURN
+ END SUBROUTINE GENBUNN
+
+
+ SUBROUTINE POISD2(MR,NR,ISTAG,vecBA,vecBB,vecBC,matY,IDIMY, &
+ vecB,vecW,vecD,TCOS,vecP,IDIMP)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: MR, NR, ISTAG, IDIMY,IDIMP
+ DOUBLE PRECISION, DIMENSION(MR), INTENT(IN) :: vecBA, vecBB, &
+ vecBC
+ DOUBLE PRECISION, DIMENSION(IDIMY,NR),INTENT(INOUT) :: matY
+ DOUBLE PRECISION, DIMENSION(MR), INTENT(INOUT) :: vecB, vecD, vecW
+ DOUBLE PRECISION, DIMENSION(4*NR), INTENT(INOUT) :: TCOS
+ DOUBLE PRECISION, DIMENSION(IDIMP), INTENT(INOUT) :: vecP
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: M, N, JSH, IP, IPSTOR, KR, IRREG, JSTSAV, I, LR, NUN, &
+ JST, JSP, L, NODD, J, JM1, JP1, JM2, JP2, JM3, JP3, &
+ NODDPR, KRPI, IDEG, JDEG
+ DOUBLE PRECISION :: FI, T
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE POISSON'S EQUATION FOR DIRICHLET BOUNDARY
+! CONDITIONS.
+!
+! ISTAG = 1 IF THE LAST DIAGONAL BLOCK IS THE MATRIX A.
+! ISTAG = 2 IF THE LAST DIAGONAL BLOCK IS THE MATRIX A+I.
+!
+ M = MR
+ N = NR
+ JSH = 0
+ FI = ONE/FLOAT(ISTAG)
+ IP = -M
+ IPSTOR = 0
+ SELECT CASE (ISTAG)
+ CASE DEFAULT
+ KR = 0
+ IRREG = 1
+ IF (N > 1) GO TO 106
+ TCOS(1) = ZERO
+ CASE (2)
+ KR = 1
+ JSTSAV = 1
+ IRREG = 2
+ IF (N > 1) GO TO 106
+ TCOS(1) = -ONE
+ END SELECT
+ vecB(:M) = matY(:M,1)
+ CALL TRIX (1, 0, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ matY(:M,1) = vecB(:M)
+ GO TO 183
+ 106 CONTINUE
+ LR = 0
+ vecP(:M) = ZERO
+ NUN = N
+ JST = 1
+ JSP = N
+!
+! IRREG = 1 WHEN NO IRREGULARITIES HAVE OCCURRED, OTHERWISE IT IS 2.
+!
+ 108 CONTINUE
+ L = 2*JST
+ NODD = 2 - 2*((NUN + 1)/2) + NUN
+!
+! NODD = 1 WHEN NUN IS ODD, OTHERWISE IT IS 2.
+!
+ SELECT CASE (NODD)
+ CASE DEFAULT
+ JSP = JSP - L
+ CASE (1)
+ JSP = JSP - JST
+ IF (IRREG /= 1) JSP = JSP - L
+ END SELECT
+ CALL COSGEN (JST, 1, HALF, ZERO, TCOS, 4*NR)
+ IF (L <= JSP) THEN
+ DO J = L, JSP, L
+ JM1 = J - JSH
+ JP1 = J + JSH
+ JM2 = J - JST
+ JP2 = J + JST
+ JM3 = JM2 - JSH
+ JP3 = JP2 + JSH
+ IF (JST == 1) THEN
+ vecB(:M) = TWO*matY(:M,J)
+ matY(:M,J) = matY(:M,JM2) + matY(:M,JP2)
+ ELSE
+ DO I = 1, M
+ T = matY(I,J) - matY(I,JM1) - matY(I,JP1) + matY(I,JM2) + &
+ matY(I,JP2)
+ vecB(I) = T + matY(I,J) - matY(I,JM3) - matY(I,JP3)
+ matY(I,J) = T
+ END DO
+ ENDIF
+ CALL TRIX (JST, 0, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ matY(:M,J) = matY(:M,J) + vecB(:M)
+ END DO
+ ENDIF
+!
+! REDUCTION FOR LAST UNKNOWN
+!
+ SELECT CASE (NODD)
+ CASE DEFAULT
+ GO TO (152,120) IRREG
+!
+! ODD NUMBER OF UNKNOWNS
+!
+ 120 CONTINUE
+ JSP = JSP + L
+ J = JSP
+ JM1 = J - JSH
+ JP1 = J + JSH
+ JM2 = J - JST
+ JP2 = J + JST
+ JM3 = JM2 - JSH
+ GO TO (123,121) ISTAG
+ 121 CONTINUE
+ IF (JST /= 1) GO TO 123
+ vecB(:M) = matY(:M,J)
+ matY(:M,J) = ZERO
+ GO TO 130
+ 123 CONTINUE
+ SELECT CASE (NODDPR)
+ CASE DEFAULT
+ vecB(:M) = HALF*(matY(:M,JM2)-matY(:M,JM1)-matY(:M,JM3)) + &
+ vecP(IP+1:M+IP)+ matY(:M,J)
+ CASE (2)
+ vecB(:M) = HALF*(matY(:M,JM2)-matY(:M,JM1)-matY(:M,JM3)) + &
+ matY(:M,JP2) - matY(:M,JP1) + matY(:M,J)
+ END SELECT
+ matY(:M,J) = HALF*(matY(:M,J)-matY(:M,JM1)-matY(:M,JP1))
+ 130 CONTINUE
+ CALL TRIX (JST, 0, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ IP = IP + M
+ IPSTOR = MAX0(IPSTOR,IP + M)
+ vecP(IP+1:M+IP) = matY(:M,J) + vecB(:M)
+ vecB(:M) = matY(:M,JP2) + vecP(IP+1:M+IP)
+ IF (LR == 0) THEN
+ DO I = 1, JST
+ KRPI = KR + I
+ TCOS(KRPI) = TCOS(I)
+ END DO
+ ELSE
+ CALL COSGEN (LR, JSTSAV, ZERO, FI, TCOS(JST+1), 4*NR-JST)
+ CALL MERGE (TCOS, 0, JST, JST, LR, KR, 4*NR)
+ ENDIF
+ CALL COSGEN (KR, JSTSAV, ZERO, FI, TCOS, 4*NR)
+ CALL TRIX (KR, KR, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ matY(:M,J) = matY(:M,JM2) + vecB(:M) + vecP(IP+1:M+IP)
+ LR = KR
+ KR = KR + L
+!
+! EVEN NUMBER OF UNKNOWNS
+!
+ CASE (2)
+ JSP = JSP + L
+ J = JSP
+ JM1 = J - JSH
+ JP1 = J + JSH
+ JM2 = J - JST
+ JP2 = J + JST
+ JM3 = JM2 - JSH
+ SELECT CASE (IRREG)
+ CASE DEFAULT
+ JSTSAV = JST
+ IDEG = JST
+ KR = L
+ CASE (2)
+ CALL COSGEN (KR, JSTSAV, ZERO, FI, TCOS, 4*NR)
+ CALL COSGEN (LR, JSTSAV, ZERO, FI, TCOS(KR+1), 4*NR-KR)
+ IDEG = KR
+ KR = KR + JST
+ END SELECT
+ IF (JST == 1) THEN
+ IRREG = 2
+ vecB(:M) = matY(:M,J)
+ matY(:M,J) = matY(:M,JM2)
+ ELSE
+ vecB(:M) = matY(:M,J) + HALF*(matY(:M,JM2)-matY(:M,JM1)- &
+ matY(:M,JM3))
+ SELECT CASE (IRREG)
+ CASE DEFAULT
+ matY(:M,J) = matY(:M,JM2) + HALF*(matY(:M,J)- &
+ matY(:M,JM1)-matY(:M,JP1))
+ IRREG = 2
+ CASE (2)
+ SELECT CASE (NODDPR)
+ CASE DEFAULT
+ matY(:M,J) = matY(:M,JM2) + vecP(IP+1:M+IP)
+ IP = IP - M
+ CASE (2)
+ matY(:M,J) = matY(:M,JM2) + matY(:M,J) - matY(:M,JM1)
+ END SELECT
+ END SELECT
+ ENDIF
+ CALL TRIX (IDEG, LR, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ matY(:M,J) = matY(:M,J) + vecB(:M)
+ END SELECT
+ 152 CONTINUE
+ NUN = NUN/2
+ NODDPR = NODD
+ JSH = JST
+ JST = 2*JST
+ IF (NUN >= 2) GO TO 108
+!
+! START SOLUTION.
+!
+ J = JSP
+ vecB(:M) = matY(:M,J)
+ SELECT CASE (IRREG)
+ CASE DEFAULT
+ CALL COSGEN (JST, 1, HALF, ZERO, TCOS, 4*NR)
+ IDEG = JST
+ CASE (2)
+ KR = LR + JST
+ CALL COSGEN (KR, JSTSAV, ZERO, FI, TCOS, 4*NR)
+ CALL COSGEN (LR, JSTSAV, ZERO, FI, TCOS(KR+1), 4*NR-KR)
+ IDEG = KR
+ END SELECT
+ CALL TRIX (IDEG, LR, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ JM1 = J - JSH
+ JP1 = J + JSH
+ SELECT CASE (IRREG)
+ CASE DEFAULT
+ matY(:M,J) = HALF*(matY(:M,J)-matY(:M,JM1)-matY(:M,JP1)) + vecB(:M)
+ CASE (2)
+ SELECT CASE (NODDPR)
+ CASE DEFAULT
+ matY(:M,J) = vecP(IP+1:M+IP) + vecB(:M)
+ IP = IP - M
+ CASE (2)
+ matY(:M,J) = matY(:M,J) - matY(:M,JM1) + vecB(:M)
+ END SELECT
+ END SELECT
+ 164 CONTINUE
+ JST = JST/2
+ JSH = JST/2
+ NUN = 2*NUN
+ IF (NUN > N) GO TO 183
+ DO J = JST, N, L
+ JM1 = J - JSH
+ JP1 = J + JSH
+ JM2 = J - JST
+ JP2 = J + JST
+ IF (J <= JST) THEN
+ vecB(:M) = matY(:M,J) + matY(:M,JP2)
+ ELSE
+ IF (JP2 <= N) GO TO 168
+ vecB(:M) = matY(:M,J) + matY(:M,JM2)
+ IF (JST < JSTSAV) IRREG = 1
+ GO TO (170,171) IRREG
+ 168 CONTINUE
+ vecB(:M) = matY(:M,J) + matY(:M,JM2) + matY(:M,JP2)
+ ENDIF
+ 170 CONTINUE
+ CALL COSGEN (JST, 1, HALF, ZERO, TCOS, 4*NR)
+ IDEG = JST
+ JDEG = 0
+ GO TO 172
+ 171 CONTINUE
+ IF (J + L > N) LR = LR - JST
+ KR = JST + LR
+ CALL COSGEN (KR, JSTSAV, ZERO, FI, TCOS, 4*NR)
+ CALL COSGEN (LR, JSTSAV, ZERO, FI, TCOS(KR+1), 4*NR-KR)
+ IDEG = KR
+ JDEG = LR
+ 172 CONTINUE
+ CALL TRIX (IDEG, JDEG, M, vecBA, vecBB, vecBC, vecB, TCOS, 4*NR, vecD, vecW)
+ IF (JST <= 1) THEN
+ matY(:M,J) = vecB(:M)
+ ELSE
+ IF (JP2 > N) GO TO 177
+ 175 CONTINUE
+ matY(:M,J) = HALF*(matY(:M,J)-matY(:M,JM1)-matY(:M,JP1)) + vecB(:M)
+ CYCLE
+ 177 CONTINUE
+ GO TO (175,178) IRREG
+ 178 CONTINUE
+ IF (J + JSH <= N) THEN
+ matY(:M,J) = vecB(:M) + vecP(IP+1:M+IP)
+ IP = IP - M
+ ELSE
+ matY(:M,J) = vecB(:M) + matY(:M,J) - matY(:M,JM1)
+ ENDIF
+ ENDIF
+ END DO
+ L = L/2
+ GO TO 164
+ 183 CONTINUE
+ vecW(1) = IPSTOR
+ RETURN
+ END SUBROUTINE POISD2
+
+
+ SUBROUTINE POISN2(M, N, ISTAG, MIXBND, vecA, vecBB, vecC, &
+ matQ, IDIMQ, vecB, vecB2,vecB3, &
+ vecW, vecW2, vecW3, vecD, TCOS, vecP, IDIMP)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M, N, ISTAG, MIXBND, IDIMQ,IDIMP
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA, vecBB, vecC
+ DOUBLE PRECISION, DIMENSION(IDIMQ,N), INTENT(INOUT) :: matQ
+ DOUBLE PRECISION, DIMENSION(M),INTENT(INOUT) :: vecB, vecB2, vecB3, &
+ vecD, vecW, vecW2, vecW3
+ DOUBLE PRECISION, DIMENSION(IDIMP),INTENT(INOUT) :: vecP
+ DOUBLE PRECISION, DIMENSION(4*N),INTENT(INOUT) :: TCOS
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER, DIMENSION(4) :: K
+ INTEGER :: K1, K2, K3, K4, MR, IP, IPSTOR, I2R, JR, NR, NLAST, &
+ KR, LR, I, NROD, JSTART, JSTOP, I2RBY2, &
+ J, JP1, JP2, JP3, JM1,JM2, JM3, NRODPR, II, I1, I2, &
+ JR2, NLASTP, JSTEP
+ DOUBLE PRECISION :: FISTAG, FNUM, FDEN, FI, T
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE POISSON'S EQUATION WITH NEUMANN BOUNDARY
+! CONDITIONS.
+!
+! ISTAG = 1 IF THE LAST DIAGONAL BLOCK IS A.
+! ISTAG = 2 IF THE LAST DIAGONAL BLOCK IS A-I.
+! MIXBND = 1 IF HAVE NEUMANN BOUNDARY CONDITIONS AT BOTH BOUNDARIES.
+! MIXBND = 2 IF HAVE NEUMANN BOUNDARY CONDITIONS AT BOTTOM AND
+! DIRICHLET CONDITION AT TOP. (FOR THIS CASE, MUST HAVE ISTAG = 1.)
+!
+ EQUIVALENCE (K(1), K1), (K(2), K2), (K(3), K3), (K(4), K4)
+ FISTAG = 3 - ISTAG
+ FNUM = ONE/FLOAT(ISTAG)
+ FDEN = HALF*FLOAT(ISTAG - 1)
+ MR = M
+ IP = -MR
+ IPSTOR = 0
+ I2R = 1
+ JR = 2
+ NR = N
+ NLAST = N
+ KR = 1
+ LR = 0
+ GO TO (101,103) ISTAG
+ 101 CONTINUE
+ matQ(:MR,N) = HALF*matQ(:MR,N)
+ GO TO (103,104) MIXBND
+ 103 CONTINUE
+ IF (N <= 3) GO TO 155
+ 104 CONTINUE
+ JR = 2*I2R
+ NROD = 1
+ IF ((NR/2)*2 == NR) NROD = 0
+ SELECT CASE (MIXBND)
+ CASE DEFAULT
+ JSTART = 1
+ CASE (2)
+ JSTART = JR
+ NROD = 1 - NROD
+ END SELECT
+ JSTOP = NLAST - JR
+ IF (NROD == 0) JSTOP = JSTOP - I2R
+ CALL COSGEN (I2R, 1, HALF, ZERO, TCOS, 4*NR)
+ I2RBY2 = I2R/2
+ IF (JSTOP < JSTART) THEN
+ J = JR
+ ELSE
+ DO J = JSTART, JSTOP, JR
+ JP1 = J + I2RBY2
+ JP2 = J + I2R
+ JP3 = JP2 + I2RBY2
+ JM1 = J - I2RBY2
+ JM2 = J - I2R
+ JM3 = JM2 - I2RBY2
+ IF (J == 1) THEN
+ JM1 = JP1
+ JM2 = JP2
+ JM3 = JP3
+ ENDIF
+ IF (I2R == 1) THEN
+ IF (J == 1) JM2 = JP2
+ vecB(:MR) = TWO*matQ(:MR,J)
+ matQ(:MR,J) = matQ(:MR,JM2) + matQ(:MR,JP2)
+ ELSE
+ DO I = 1, MR
+ FI = matQ(I,J)
+ matQ(I,J)=matQ(I,J)-matQ(I,JM1)-matQ(I,JP1)+ &
+ matQ(I,JM2)+matQ(I,JP2)
+ vecB(I) = FI + matQ(I,J) - matQ(I,JM3) - matQ(I,JP3)
+ END DO
+ ENDIF
+ CALL TRIX (I2R, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+!
+! END OF REDUCTION FOR REGULAR UNKNOWNS.
+!
+ END DO
+!
+! BEGIN SPECIAL REDUCTION FOR LAST UNKNOWN.
+!
+ J = JSTOP + JR
+ ENDIF
+ NLAST = J
+ JM1 = J - I2RBY2
+ JM2 = J - I2R
+ JM3 = JM2 - I2RBY2
+ IF (NROD /= 0) THEN
+!
+! ODD NUMBER OF UNKNOWNS
+!
+ IF (I2R == 1) THEN
+ vecB(:MR) = FISTAG*matQ(:MR,J)
+ matQ(:MR,J) = matQ(:MR,JM2)
+ ELSE
+ vecB(:MR) = matQ(:MR,J) + HALF*(matQ(:MR,JM2)- &
+ matQ(:MR,JM1)-matQ(:MR,JM3))
+ IF (NRODPR == 0) THEN
+ matQ(:MR,J) = matQ(:MR,JM2) + vecP(IP+1:MR+IP)
+ IP = IP - MR
+ ELSE
+ matQ(:MR,J) = matQ(:MR,J) - matQ(:MR,JM1) + matQ(:MR,JM2)
+ ENDIF
+ IF (LR /= 0) THEN
+ CALL COSGEN (LR, 1, HALF, FDEN, TCOS(KR+1), 4*NR-KR)
+ ELSE
+ vecB(:MR) = FISTAG*vecB(:MR)
+ ENDIF
+ ENDIF
+ CALL COSGEN (KR, 1, HALF, FDEN, TCOS, 4*NR)
+ CALL TRIX (KR, LR, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ KR = KR + I2R
+ ELSE
+ JP1 = J + I2RBY2
+ JP2 = J + I2R
+ IF (I2R == 1) THEN
+ vecB(:MR) = matQ(:MR,J)
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ IP = 0
+ IPSTOR = MR
+ SELECT CASE (ISTAG)
+ CASE DEFAULT
+ vecP(:MR) = vecB(:MR)
+ vecB(:MR) = vecB(:MR) + matQ(:MR,N)
+ TCOS(1) = ONE
+ TCOS(2) = ZERO
+ CALL TRIX (1, 1, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,JM2) + vecP(:MR) + vecB(:MR)
+ GO TO 150
+ CASE (1)
+ vecP(:MR) = vecB(:MR)
+ matQ(:MR,J) = matQ(:MR,JM2) + TWO*matQ(:MR,JP2) + 3.*vecB(:MR)
+ GO TO 150
+ END SELECT
+ ENDIF
+ vecB(:MR) = matQ(:MR,J) + HALF*(matQ(:MR,JM2)- &
+ matQ(:MR,JM1)-matQ(:MR,JM3))
+ IF (NRODPR == 0) THEN
+ vecB(:MR) = vecB(:MR) + vecP(IP+1:MR+IP)
+ ELSE
+ vecB(:MR) = vecB(:MR) + matQ(:MR,JP2) - matQ(:MR,JP1)
+ ENDIF
+ CALL TRIX (I2R, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ IP = IP + MR
+ IPSTOR = MAX0(IPSTOR,IP + MR)
+ vecP(IP+1:MR+IP) = vecB(:MR) + HALF*(matQ(:MR,J)- &
+ matQ(:MR,JM1)-matQ(:MR,JP1))
+ vecB(:MR) = vecP(IP+1:MR+IP) + matQ(:MR,JP2)
+ IF (LR /= 0) THEN
+ CALL COSGEN (LR, 1, HALF, FDEN, TCOS(I2R+1), 4*NR-I2R)
+ CALL MERGE (TCOS, 0, I2R, I2R, LR, KR, 4*NR)
+ ELSE
+ DO I = 1, I2R
+ II = KR + I
+ TCOS(II) = TCOS(I)
+ END DO
+ ENDIF
+ CALL COSGEN (KR, 1, HALF, FDEN, TCOS, 4*NR)
+ IF (LR == 0) THEN
+ GO TO (146,145) ISTAG
+ ENDIF
+ 145 CONTINUE
+ CALL TRIX (KR, KR, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ GO TO 148
+ 146 CONTINUE
+ vecB(:MR) = FISTAG*vecB(:MR)
+ 148 CONTINUE
+ matQ(:MR,J) = matQ(:MR,JM2) + vecP(IP+1:MR+IP) + vecB(:MR)
+ 150 CONTINUE
+ LR = KR
+ KR = KR + JR
+ ENDIF
+ SELECT CASE (MIXBND)
+ CASE DEFAULT
+ NR = (NLAST - 1)/JR + 1
+ IF (NR <= 3) GO TO 155
+ CASE (2)
+ NR = NLAST/JR
+ IF (NR <= 1) GO TO 192
+ END SELECT
+ I2R = JR
+ NRODPR = NROD
+ GO TO 104
+ 155 CONTINUE
+ J = 1 + JR
+ JM1 = J - I2R
+ JP1 = J + I2R
+ JM2 = NLAST - I2R
+ IF (NR /= 2) THEN
+ IF (LR /= 0) GO TO 170
+ IF (N == 3) THEN
+!
+! CASE N = 3.
+!
+ GO TO (156,168) ISTAG
+ 156 CONTINUE
+ vecB(:MR) = matQ(:MR,2)
+ TCOS(1) = ZERO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,2) = vecB(:MR)
+ vecB(:MR) = 4.*vecB(:MR) + matQ(:MR,1) + TWO*matQ(:MR,3)
+ TCOS(1) = -TWO
+ TCOS(2) = TWO
+ I1 = 2
+ I2 = 0
+ CALL TRIX (I1, I2, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,2) = matQ(:MR,2) + vecB(:MR)
+ vecB(:MR) = matQ(:MR,1) + TWO*matQ(:MR,2)
+ TCOS(1) = ZERO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,1) = vecB(:MR)
+ JR = 1
+ I2R = 0
+ GO TO 194
+ ENDIF
+!
+! CASE N = 2**P+1
+!
+ GO TO (162,170) ISTAG
+ 162 CONTINUE
+ vecB(:MR) = matQ(:MR,J) + HALF*matQ(:MR,1) - &
+ matQ(:MR,JM1) + matQ(:MR,NLAST) - matQ(:MR,JM2)
+ CALL COSGEN (JR, 1, HALF, ZERO, TCOS, 4*NR)
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = HALF*(matQ(:MR,J)-matQ(:MR,JM1)-matQ(:MR,JP1)) + vecB(:MR)
+ vecB(:MR) = matQ(:MR,1) + TWO*matQ(:MR,NLAST) + 4.*matQ(:MR,J)
+ JR2 = 2*JR
+ CALL COSGEN (JR, 1, ZERO, ZERO, TCOS, 4*NR)
+ TCOS(JR+1:JR*2) = -TCOS(JR:1:(-1))
+ CALL TRIX (JR2, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ vecB(:MR) = matQ(:MR,1) + TWO*matQ(:MR,J)
+ CALL COSGEN (JR, 1, HALF, ZERO, TCOS, 4*NR)
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,1) = HALF*matQ(:MR,1) - matQ(:MR,JM1) + vecB(:MR)
+ GO TO 194
+!
+! CASE OF GENERAL N WITH NR = 3 .
+!
+ 168 CONTINUE
+ vecB(:MR) = matQ(:MR,2)
+ matQ(:MR,2) = ZERO
+ vecB2(:MR) = matQ(:MR,3)
+ vecB3(:MR) = matQ(:MR,1)
+ JR = 1
+ I2R = 0
+ J = 2
+ GO TO 177
+ 170 CONTINUE
+ vecB(:MR) = HALF*matQ(:MR,1) - matQ(:MR,JM1) + matQ(:MR,J)
+ IF (NROD == 0) THEN
+ vecB(:MR) = vecB(:MR) + vecP(IP+1:MR+IP)
+ ELSE
+ vecB(:MR) = vecB(:MR) + matQ(:MR,NLAST) - matQ(:MR,JM2)
+ ENDIF
+ DO I = 1, MR
+ T = HALF*(matQ(I,J)-matQ(I,JM1)-matQ(I,JP1))
+ matQ(I,J) = T
+ vecB2(I) = matQ(I,NLAST) + T
+ vecB3(I) = matQ(I,1) + TWO*T
+ END DO
+ 177 CONTINUE
+ K1 = KR + 2*JR - 1
+ K2 = KR + JR
+ TCOS(K1+1) = -TWO
+ K4 = K1 + 3 - ISTAG
+ CALL COSGEN (K2 + ISTAG - 2, 1, ZERO, FNUM, TCOS(K4), 4*NR-K4+1)
+ K4 = K1 + K2 + 1
+ CALL COSGEN (JR - 1, 1, ZERO, ONE, TCOS(K4), 4*NR-K4+1)
+ CALL MERGE (TCOS, K1, K2, K1 + K2, JR - 1, 0, 4*NR)
+ K3 = K1 + K2 + LR
+ CALL COSGEN (JR, 1, HALF, ZERO, TCOS(K3+1), 4*NR-K3)
+ K4 = K3 + JR + 1
+ CALL COSGEN (KR, 1, HALF, FDEN, TCOS(K4), 4*NR-K4+1)
+ CALL MERGE (TCOS, K3, JR, K3 + JR, KR, K1, 4*NR)
+ IF (LR /= 0) THEN
+ CALL COSGEN (LR, 1, HALF, FDEN, TCOS(K4), 4*NR-K4+1)
+ CALL MERGE (TCOS, K3, JR, K3 + JR, LR, K3 - LR, 4*NR)
+ CALL COSGEN (KR, 1, HALF, FDEN, TCOS(K4), 4*NR-K4+1)
+ ENDIF
+ K3 = KR
+ K4 = KR
+ CALL TRI3 (MR, vecA, vecBB, vecC, K, vecB, vecB2, vecB3, &
+ TCOS, 4*NR, vecD, vecW, vecW2, vecW3)
+ vecB(:MR) = vecB(:MR) + vecB2(:MR) + vecB3(:MR)
+ TCOS(1) = TWO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ vecB(:MR) = matQ(:MR,1) + TWO*matQ(:MR,J)
+ CALL COSGEN (JR, 1, HALF, ZERO, TCOS, 4*NR)
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ IF (JR == 1) THEN
+ matQ(:MR,1) = vecB(:MR)
+ GO TO 194
+ ENDIF
+ matQ(:MR,1) = HALF*matQ(:MR,1) - matQ(:MR,JM1) + vecB(:MR)
+ GO TO 194
+ ENDIF
+ IF (N == 2) THEN
+!
+! CASE N = 2
+!
+ vecB(:MR) = matQ(:MR,1)
+ TCOS(1) = ZERO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,1) = vecB(:MR)
+ vecB(:MR) = TWO*(matQ(:MR,2)+vecB(:MR))*FISTAG
+ TCOS(1) = -FISTAG
+ TCOS(2) = TWO
+ CALL TRIX (2, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,1) = matQ(:MR,1) + vecB(:MR)
+ JR = 1
+ I2R = 0
+ GO TO 194
+ ENDIF
+ vecB3(:MR) = ZERO
+ vecB(:MR) = matQ(:MR,1) + TWO*vecP(IP+1:MR+IP)
+ matQ(:MR,1) = HALF*matQ(:MR,1) - matQ(:MR,JM1)
+ vecB2(:MR) = TWO*(matQ(:MR,1)+matQ(:MR,NLAST))
+ K1 = KR + JR - 1
+ TCOS(K1+1) = -TWO
+ K4 = K1 + 3 - ISTAG
+ CALL COSGEN (KR + ISTAG - 2, 1, ZERO, FNUM, TCOS(K4), 4*NR-K4+1)
+ K4 = K1 + KR + 1
+ CALL COSGEN (JR - 1, 1, ZERO, ONE, TCOS(K4), 4*NR-K4+1)
+ CALL MERGE (TCOS, K1, KR, K1 + KR, JR - 1, 0, 4*NR)
+ CALL COSGEN (KR, 1, HALF, FDEN, TCOS(K1+1), 4*NR-K1)
+ K2 = KR
+ K4 = K1 + K2 + 1
+ CALL COSGEN (LR, 1, HALF, FDEN, TCOS(K4), 4*NR-K4+1)
+ K3 = LR
+ K4 = 0
+ CALL TRI3 (MR, vecA, vecBB, vecC, K, vecB, vecB2, vecB3, TCOS, &
+ 4*NR, vecD, vecW, vecW2, vecW3)
+ vecB(:MR) = vecB(:MR) + vecB2(:MR)
+ TCOS(1) = TWO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,1) = matQ(:MR,1) + vecB(:MR)
+ GO TO 194
+ 192 CONTINUE
+ vecB(:MR) = matQ(:MR,NLAST)
+ GO TO 196
+ 194 CONTINUE
+ J = NLAST - JR
+ vecB(:MR) = matQ(:MR,NLAST) + matQ(:MR,J)
+ 196 CONTINUE
+ JM2 = NLAST - I2R
+ IF (JR == 1) THEN
+ matQ(:MR,NLAST) = ZERO
+ ELSE
+ IF (NROD == 0) THEN
+ matQ(:MR,NLAST) = vecP(IP+1:MR+IP)
+ IP = IP - MR
+ ELSE
+ matQ(:MR,NLAST) = matQ(:MR,NLAST) - matQ(:MR,JM2)
+ ENDIF
+ ENDIF
+ CALL COSGEN (KR, 1, HALF, FDEN, TCOS, 4*NR)
+ CALL COSGEN (LR, 1, HALF, FDEN, TCOS(KR+1), 4*NR-KR)
+ IF (LR == 0) THEN
+ vecB(:MR) = FISTAG*vecB(:MR)
+ ENDIF
+ CALL TRIX (KR, LR, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,NLAST) = matQ(:MR,NLAST) + vecB(:MR)
+ NLASTP = NLAST
+ 206 CONTINUE
+ JSTEP = JR
+ JR = I2R
+ I2R = I2R/2
+ IF (JR == 0) GO TO 222
+ SELECT CASE (MIXBND)
+ CASE DEFAULT
+ JSTART = 1 + JR
+ CASE (2)
+ JSTART = JR
+ END SELECT
+ KR = KR - JR
+ IF (NLAST + JR <= N) THEN
+ KR = KR - JR
+ NLAST = NLAST + JR
+ JSTOP = NLAST - JSTEP
+ ELSE
+ JSTOP = NLAST - JR
+ ENDIF
+ LR = KR - JR
+ CALL COSGEN (JR, 1, HALF, ZERO, TCOS, 4*NR)
+ DO J = JSTART, JSTOP, JSTEP
+ JM2 = J - JR
+ JP2 = J + JR
+ IF (J == JR) THEN
+ vecB(:MR) = matQ(:MR,J) + matQ(:MR,JP2)
+ ELSE
+ vecB(:MR) = matQ(:MR,J) + matQ(:MR,JM2) + matQ(:MR,JP2)
+ ENDIF
+ IF (JR == 1) THEN
+ matQ(:MR,J) = ZERO
+ ELSE
+ JM1 = J - I2R
+ JP1 = J + I2R
+ matQ(:MR,J) = HALF*(matQ(:MR,J)-matQ(:MR,JM1)-matQ(:MR,JP1))
+ ENDIF
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, 4*NR, vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ END DO
+ NROD = 1
+ IF (NLAST + I2R <= N) NROD = 0
+ IF (NLASTP /= NLAST) GO TO 194
+ GO TO 206
+ 222 CONTINUE
+ vecW(1) = IPSTOR
+ RETURN
+ END SUBROUTINE POISN2
+
+
+ SUBROUTINE POISP2(M, N, vecA, vecBB, vecC, matQ, IDIMQ, &
+ vecB, vecB2, vecB3, vecW, vecW2, vecW3, &
+ vecD, TCOS, vecP, IP)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M, N, IDIMQ, IP
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA, vecBB, vecC
+ DOUBLE PRECISION, DIMENSION(4*N), INTENT(INOUT) :: TCOS
+ DOUBLE PRECISION, DIMENSION(IDIMQ,N), INTENT(INOUT) :: matQ
+ DOUBLE PRECISION, DIMENSION(IP),INTENT(INOUT) :: vecP
+ DOUBLE PRECISION, DIMENSION(M),INTENT(INOUT) :: vecB, vecB2, vecB3, &
+ vecD, vecW, vecW2, vecW3
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: MR, NR, NRM1, J, NRMJ, NRPJ, I, IPSTOR, LH
+ DOUBLE PRECISION :: S, T
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE POISSON EQUATION WITH PERIODIC BOUNDARY
+! CONDITIONS.
+!
+ MR = M
+ NR = (N + 1)/2
+ NRM1 = NR - 1
+ IF (2*NR == N) THEN
+!
+! EVEN NUMBER OF UNKNOWNS
+!
+ DO J = 1, NRM1
+ NRMJ = NR - J
+ NRPJ = NR + J
+ DO I = 1, MR
+ S = matQ(I,NRMJ) - matQ(I,NRPJ)
+ T = matQ(I,NRMJ) + matQ(I,NRPJ)
+ matQ(I,NRMJ) = S
+ matQ(I,NRPJ) = T
+ END DO
+ END DO
+ matQ(:MR,NR) = TWO*matQ(:MR,NR)
+ matQ(:MR,N) = TWO*matQ(:MR,N)
+ CALL POISD2 (MR, NRM1, 1, vecA, vecBB, vecC, matQ, IDIMQ, &
+ vecB, vecW, vecD, TCOS, vecP, IP)
+ IPSTOR = vecW(1)
+ CALL POISN2 (MR, NR + 1, 1, 1, vecA, vecBB, vecC, matQ(:,NR:), &
+ IDIMQ, vecB, vecB2, vecB3, vecW, vecW2, vecW3, vecD, &
+ TCOS, vecP, IP)
+ IPSTOR = MAX0(IPSTOR,INT(vecW(1)))
+ DO J = 1, NRM1
+ NRMJ = NR - J
+ NRPJ = NR + J
+ DO I = 1, MR
+ S = HALF*(matQ(I,NRPJ)+matQ(I,NRMJ))
+ T = HALF*(matQ(I,NRPJ)-matQ(I,NRMJ))
+ matQ(I,NRMJ) = S
+ matQ(I,NRPJ) = T
+ END DO
+ END DO
+ matQ(:MR,NR) = HALF*matQ(:MR,NR)
+ matQ(:MR,N) = HALF*matQ(:MR,N)
+ ELSE
+ DO J = 1, NRM1
+ NRPJ = N + 1 - J
+ DO I = 1, MR
+ S = matQ(I,J) - matQ(I,NRPJ)
+ T = matQ(I,J) + matQ(I,NRPJ)
+ matQ(I,J) = S
+ matQ(I,NRPJ) = T
+ END DO
+ END DO
+ matQ(:MR,NR) = TWO*matQ(:MR,NR)
+ LH = NRM1/2
+ DO J = 1, LH
+ NRMJ = NR - J
+ DO I = 1, MR
+ S = matQ(I,J)
+ matQ(I,J) = matQ(I,NRMJ)
+ matQ(I,NRMJ) = S
+ END DO
+ END DO
+ CALL POISD2 (MR, NRM1, 2, vecA, vecBB, vecC, matQ, IDIMQ, &
+ vecB, vecW, vecD, TCOS, vecP, IP)
+ IPSTOR = vecW(1)
+ CALL POISN2 (MR, NR, 2, 1, vecA, vecBB, vecC, matQ(:,NR:), IDIMQ, &
+ vecB, vecB2, vecB3, vecW, vecW2, vecW3, vecD, TCOS, &
+ vecP, IP)
+ IPSTOR = MAX0(IPSTOR,INT(vecW(1)))
+ DO J = 1, NRM1
+ NRPJ = NR + J
+ DO I = 1, MR
+ S = HALF*(matQ(I,NRPJ)+matQ(I,J))
+ T = HALF*(matQ(I,NRPJ)-matQ(I,J))
+ matQ(I,NRPJ) = T
+ matQ(I,J) = S
+ END DO
+ END DO
+ matQ(:MR,NR) = HALF*matQ(:MR,NR)
+ DO J = 1, LH
+ NRMJ = NR - J
+ DO I = 1, MR
+ S = matQ(I,J)
+ matQ(I,J) = matQ(I,NRMJ)
+ matQ(I,NRMJ) = S
+ END DO
+ END DO
+ ENDIF
+ vecW(1) = IPSTOR
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+! June 2004 Version 5.0, Fortran 90 changes
+!-----------------------------------------------------------------------
+ END SUBROUTINE POISP2
diff --git a/fish90/src/gnbnaux.f90 b/fish90/src/gnbnaux.f90
new file mode 100644
index 0000000000000000000000000000000000000000..4640121ecf744e48588a3222b58c153710f7eb37
--- /dev/null
+++ b/fish90/src/gnbnaux.f90
@@ -0,0 +1,399 @@
+!
+! file gnbnaux.f
+!
+!
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+! . .
+! . copyright (c) 2004 by UCAR .
+! . .
+! . UNIVERSITY CORPORATION for ATMOSPHERIC RESEARCH .
+! . .
+! . all rights reserved .
+! . .
+! . .
+! . FISHPACK version 5.0 .
+! . .
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+!
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+! * *
+! * F I S H P A C K *
+! * *
+! * *
+! * A PACKAGE OF FORTRAN SUBPROGRAMS FOR THE SOLUTION OF *
+! * *
+! * SEPARABLE ELLIPTIC PARTIAL DIFFERENTIAL EQUATIONS *
+! * *
+! * (Version 5.0 , JUNE 2004) *
+! * *
+! * BY *
+! * *
+! * JOHN ADAMS, PAUL SWARZTRAUBER AND ROLAND SWEET *
+! * *
+! * OF *
+! * *
+! * THE NATIONAL CENTER FOR ATMOSPHERIC RESEARCH *
+! * *
+! * BOULDER, COLORADO (80307) U.S.A. *
+! * *
+! * WHICH IS SPONSORED BY *
+! * *
+! * THE NATIONAL SCIENCE FOUNDATION *
+! * *
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+!
+!
+! PACKAGE GNBNAUX
+!
+! LATEST REVISION June 2004
+!
+! PURPOSE TO PROVIDE AUXILIARY ROUTINES FOR FISHPACK
+! ENTRIES GENBUN AND POISTG.
+!
+! USAGE THERE ARE NO USER ENTRIES IN THIS PACKAGE.
+! THE ROUTINES IN THIS PACKAGE ARE NOT INTENDED
+! TO BE CALLED BY USERS, BUT RATHER BY ROUTINES
+! IN PACKAGES GENBUN AND POISTG.
+!
+! SPECIAL CONDITIONS NONE
+!
+! I/O NONE
+!
+! PRECISION SINGLE
+!
+!
+! LANGUAGE FORTRAN 90
+!
+! HISTORY WRITTEN IN 1979 BY ROLAND SWEET OF NCAR'S
+! SCIENTIFIC COMPUTING DIVISION. MADE AVAILABLE
+! ON NCAR'S PUBLIC LIBRARIES IN JANUARY, 1980.
+! Revised by John Adams in June 2004 incorporating
+! Fortran 90 features
+!
+! PORTABILITY FORTRAN 90
+! ********************************************************************
+ SUBROUTINE COSGEN(N, IJUMP, FNUM, FDEN, vecA, IA)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: N, IJUMP, IA
+ DOUBLE PRECISION, INTENT(IN) :: FNUM, FDEN
+ DOUBLE PRECISION, DIMENSION(IA),INTENT(OUT) :: vecA
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: K3, K4, K, K1, K5, I, K2, NP1
+ DOUBLE PRECISION :: PI, PIBYN, X, Y
+!-----------------------------------------------
+!
+!
+! THIS SUBROUTINE COMPUTES REQUIRED COSINE VALUES IN ASCENDING
+! ORDER. WHEN IJUMP .GT. 1 THE ROUTINE COMPUTES VALUES
+!
+! 2*COS(J*PI/L) , J=1,2,...,L AND J .NE. 0(MOD N/IJUMP+1)
+!
+! WHERE L = IJUMP*(N/IJUMP+1).
+!
+!
+! WHEN IJUMP = 1 IT COMPUTES
+!
+! 2*COS((J-FNUM)*PI/(N+FDEN)) , J=1, 2, ... ,N
+!
+! WHERE
+! FNUM = 0.5, FDEN = 0.0, FOR REGULAR REDUCTION VALUES
+! FNUM = 0.0, FDEN = 1.0, FOR B-R AND C-R WHEN ISTAG = 1
+! FNUM = 0.0, FDEN = 0.5, FOR B-R AND C-R WHEN ISTAG = 2
+! FNUM = 0.5, FDEN = 0.5, FOR B-R AND C-R WHEN ISTAG = 2
+! IN POISN2 ONLY.
+!
+!
+ PI = 4.0*ATAN(1.0)
+ IF (N /= 0) THEN
+ IF (IJUMP /= 1) THEN
+ K3 = N/IJUMP + 1
+ K4 = K3 - 1
+ PIBYN = PI/FLOAT(N + IJUMP)
+ DO K = 1, IJUMP
+ K1 = (K - 1)*K3
+ K5 = (K - 1)*K4
+ DO I = 1, K4
+ X = K1 + I
+ K2 = K5 + I
+ vecA(K2) = -2.*COS(X*PIBYN)
+ END DO
+ END DO
+ ELSE
+ NP1 = N + 1
+ Y = PI/(FLOAT(N) + FDEN)
+ DO I = 1, N
+ X = FLOAT(NP1 - I) - FNUM
+ vecA(I) = 2.*COS(X*Y)
+ END DO
+ ENDIF
+ ENDIF
+!
+ END SUBROUTINE COSGEN
+
+ SUBROUTINE MERGE(TCOS, I1, M1, I2, M2, I3, itcos)
+ implicit none
+
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: I1, M1, I2, M2, I3, ITCOS
+ DOUBLE PRECISION, DIMENSION(ITCOS), INTENT(INOUT) :: TCOS
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: J11, J3, J1, J2, J, L, K, M
+ DOUBLE PRECISION :: X, Y
+!-----------------------------------------------
+!
+! THIS SUBROUTINE MERGES TWO ASCENDING STRINGS OF NUMBERS IN THE
+! ARRAY TCOS. THE FIRST STRING IS OF LENGTH M1 AND STARTS AT
+! TCOS(I1+1). THE SECOND STRING IS OF LENGTH M2 AND STARTS AT
+! TCOS(I2+1). THE MERGED STRING GOES INTO TCOS(I3+1).
+!
+!
+ J1 = 1
+ J2 = 1
+ J = I3
+ IF (M1 == 0) GO TO 107
+ IF (M2 == 0) GO TO 104
+ 101 CONTINUE
+ J11 = J1
+ J3 = MAX(M1,J11)
+ DO J1 = J11, J3
+ J = J + 1
+ L = J1 + I1
+ X = TCOS(L)
+ L = J2 + I2
+ Y = TCOS(L)
+ IF (X - Y > 0.) GO TO 103
+ TCOS(J) = X
+ END DO
+ GO TO 106
+ 103 CONTINUE
+ TCOS(J) = Y
+ J2 = J2 + 1
+ IF (J2 <= M2) GO TO 101
+ IF (J1 > M1) GO TO 109
+ 104 CONTINUE
+ K = J - J1 + 1
+ DO J = J1, M1
+ M = K + J
+ L = J + I1
+ TCOS(M) = TCOS(L)
+ END DO
+ GO TO 109
+ 106 CONTINUE
+ IF (J2 > M2) GO TO 109
+ 107 CONTINUE
+ K = J - J2 + 1
+ DO J = J2, M2
+ M = K + J
+ L = J + I2
+ TCOS(M) = TCOS(L)
+ END DO
+ 109 CONTINUE
+!
+ END SUBROUTINE MERGE
+
+
+ SUBROUTINE TRIX(IDEGBR, IDEGCR, M, vecA, vecB, vecC, vecY, TCOS, ITCOS, &
+ vecD, vecW)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: IDEGBR, IDEGCR, M, ITCOS
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA, vecB, vecC
+ DOUBLE PRECISION, DIMENSION(ITCOS), INTENT(IN) :: TCOS
+ DOUBLE PRECISION, DIMENSION(M), INTENT(INOUT) :: vecY, vecD, vecW
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: MM1, IFB, IFC, L, LINT, K, I, IP
+ DOUBLE PRECISION :: X, XX, Z
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE A SYSTEM OF LINEAR EQUATIONS WHERE THE
+! COEFFICIENT MATRIX IS A RATIONAL FUNCTION IN THE MATRIX GIVEN BY
+! TRIDIAGONAL ( . . . , vecA(I), vecB(I), vecC(I), . . . ).
+!
+ MM1 = M - 1
+ IFB = IDEGBR + 1
+ IFC = IDEGCR + 1
+ L = IFB/IFC
+ LINT = 1
+ DO K = 1, IDEGBR
+ X = TCOS(K)
+ IF (K == L) THEN
+ I = IDEGBR + LINT
+ XX = X - TCOS(I)
+ vecW(:M) = vecY(:M)
+ vecY(:M) = XX*vecY(:M)
+ ENDIF
+ Z = 1./(vecB(1)-X)
+ vecD(1) = vecC(1)*Z
+ vecY(1) = vecY(1)*Z
+ DO I = 2, MM1
+ Z = 1./(vecB(I)-X-vecA(I)*vecD(I-1))
+ vecD(I) = vecC(I)*Z
+ vecY(I) = (vecY(I)-vecA(I)*vecY(I-1))*Z
+ END DO
+ Z = vecB(M) - X - vecA(M)*vecD(MM1)
+ IF (Z == 0.) THEN
+ vecY(M) = 0.
+ ELSE
+ vecY(M) = (vecY(M)-vecA(M)*vecY(MM1))/Z
+ ENDIF
+ DO IP = 1, MM1
+ vecY(M-IP) = vecY(M-IP) - vecD(M-IP)*vecY(M+1-IP)
+ END DO
+ IF (K /= L) CYCLE
+ vecY(:M) = vecY(:M) + vecW(:M)
+ LINT = LINT + 1
+ L = (LINT*IFB)/IFC
+ END DO
+!
+ END SUBROUTINE TRIX
+
+
+ SUBROUTINE TRI3(M, vecA, vecB, vecC, ivecK, vecY1, vecY2, vecY3, TCOS, &
+ ITCOS, vecD, vecW1, vecW2, vecW3)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M,ITCOS
+ INTEGER, DIMENSION(4),INTENT(IN) :: ivecK
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA, vecB, vecC
+ DOUBLE PRECISION, DIMENSION(ITCOS), INTENT(IN) :: TCOS
+ DOUBLE PRECISION, DIMENSION(M), INTENT(INOUT) :: vecY1, vecY2, vecY3, &
+ vecD, vecW1, vecW2, vecW3
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: MM1, K1, K2, K3, K4, IF1, IF2, IF3, IF4, K2K3K4, &
+ L1, L2, L3, LINT1, LINT2, LINT3, KINT1, KINT2, KINT3, &
+ N, I, IP
+ DOUBLE PRECISION :: X, Z, XX
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE THREE LINEAR SYSTEMS WHOSE COMMON COEFFICIENT
+! MATRIX IS A RATIONAL FUNCTION IN THE MATRIX GIVEN BY
+!
+! TRIDIAGONAL (...,vecA(I),vecB(I),vecC(I),...)
+!
+ MM1 = M - 1
+ K1 = ivecK(1)
+ K2 = ivecK(2)
+ K3 = ivecK(3)
+ K4 = ivecK(4)
+ IF1 = K1 + 1
+ IF2 = K2 + 1
+ IF3 = K3 + 1
+ IF4 = K4 + 1
+ K2K3K4 = K2 + K3 + K4
+ IF (K2K3K4 /= 0) THEN
+ L1 = IF1/IF2
+ L2 = IF1/IF3
+ L3 = IF1/IF4
+ LINT1 = 1
+ LINT2 = 1
+ LINT3 = 1
+ KINT1 = K1
+ KINT2 = KINT1 + K2
+ KINT3 = KINT2 + K3
+ ELSE
+ write(*,*) 'warning tri3: l1,l2,l3,kint1,kint2,kint3 uninitialized'
+ stop 'stop in tri3: l1,l2,l3,kint1,kint2,kint3 uninitialized'
+ ENDIF
+ DO N = 1, K1
+ X = TCOS(N)
+ IF (K2K3K4 /= 0) THEN
+ IF (N == L1) THEN
+ vecW1(:M) = vecY1(:M)
+ ENDIF
+ IF (N == L2) THEN
+ vecW2(:M) = vecY2(:M)
+ ENDIF
+ IF (N == L3) THEN
+ vecW3(:M) = vecY3(:M)
+ ENDIF
+ ENDIF
+ Z = 1./(vecB(1)-X)
+ vecD(1) = vecC(1)*Z
+ vecY1(1) = vecY1(1)*Z
+ vecY2(1) = vecY2(1)*Z
+ vecY3(1) = vecY3(1)*Z
+ DO I = 2, M
+ Z = 1./(vecB(I)-X-vecA(I)*vecD(I-1))
+ vecD(I) = vecC(I)*Z
+ vecY1(I) = (vecY1(I)-vecA(I)*vecY1(I-1))*Z
+ vecY2(I) = (vecY2(I)-vecA(I)*vecY2(I-1))*Z
+ vecY3(I) = (vecY3(I)-vecA(I)*vecY3(I-1))*Z
+ END DO
+ DO IP = 1, MM1
+ vecY1(M-IP) = vecY1(M-IP) - vecD(M-IP)*vecY1(M+1-IP)
+ vecY2(M-IP) = vecY2(M-IP) - vecD(M-IP)*vecY2(M+1-IP)
+ vecY3(M-IP) = vecY3(M-IP) - vecD(M-IP)*vecY3(M+1-IP)
+ END DO
+ IF (K2K3K4 == 0) CYCLE
+ IF (N == L1) THEN
+ I = LINT1 + KINT1
+ XX = X - TCOS(I)
+ vecY1(:M) = XX*vecY1(:M) + vecW1(:M)
+ LINT1 = LINT1 + 1
+ L1 = (LINT1*IF1)/IF2
+ ENDIF
+ IF (N == L2) THEN
+ I = LINT2 + KINT2
+ XX = X - TCOS(I)
+ vecY2(:M) = XX*vecY2(:M) + vecW2(:M)
+ LINT2 = LINT2 + 1
+ L2 = (LINT2*IF1)/IF3
+ ENDIF
+ IF (N /= L3) CYCLE
+ I = LINT3 + KINT3
+ XX = X - TCOS(I)
+ vecY3(:M) = XX*vecY3(:M) + vecW3(:M)
+ LINT3 = LINT3 + 1
+ L3 = (LINT3*IF1)/IF4
+ END DO
+ RETURN
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! OCTOBER 1980 CHANGED SEVERAL DIVIDES OF FLOATING INTEGERS
+! TO INTEGER DIVIDES TO ACCOMODATE CRAY-1 ARITHMETIC.
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+!-----------------------------------------------------------------------
+ END SUBROUTINE TRI3
diff --git a/fish90/src/hst_procs.f90 b/fish90/src/hst_procs.f90
new file mode 100644
index 0000000000000000000000000000000000000000..f438ec0416c8da45c55da0e5911711327e42946b
--- /dev/null
+++ b/fish90/src/hst_procs.f90
@@ -0,0 +1,1650 @@
+!
+! file hstcrt.f
+!
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+! . .
+! . copyright (c) 2004 by UCAR .
+! . .
+! . UNIVERSITY CORPORATION for ATMOSPHERIC RESEARCH .
+! . .
+! . all rights reserved .
+! . .
+! . .
+! . FISHPACK version 5.0 .
+! . .
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+!
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+! * *
+! * F I S H P A C K *
+! * *
+! * *
+! * A PACKAGE OF FORTRAN SUBPROGRAMS FOR THE SOLUTION OF *
+! * *
+! * SEPARABLE ELLIPTIC PARTIAL DIFFERENTIAL EQUATIONS *
+! * *
+! * (Version 5.0 , JUNE 2004) *
+! * *
+! * BY *
+! * *
+! * JOHN ADAMS, PAUL SWARZTRAUBER AND ROLAND SWEET *
+! * *
+! * OF *
+! * *
+! * THE NATIONAL CENTER FOR ATMOSPHERIC RESEARCH *
+! * *
+! * BOULDER, COLORADO (80307) U.S.A. *
+! * *
+! * WHICH IS SPONSORED BY *
+! * *
+! * THE NATIONAL SCIENCE FOUNDATION *
+! * *
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+!
+! SUBROUTINE HSTCRT (A,B,M,MBDCND,BDA,BDB,C,D,N,NBDCND,BDC,BDD,
+! + ELMBDA,F,IDIMF,PERTRB,IERROR)
+!
+! DIMENSION OF BDA(N),BDB(N),BDC(M),BDD(M),F(IDIMF,N)
+! ARGUMENTS
+!
+! LATEST REVISION June 2004
+!
+! PURPOSE SOLVES THE STANDARD FIVE-POINT FINITE
+! DIFFERENCE APPROXIMATION TO THE HELMHOLTZ
+! EQUATION
+! (D/DX)(DU/DX) + (D/DY)(DU/DY) + LAMBDA*U
+! = F(X,Y)
+! ON A STAGGERED GRID IN CARTESIAN COORDINATES.
+!
+! USAGE CALL HSTCRT (A,B,M,MBDCND,BDA,BDB,C,D
+! N,NBDCND,BDC,BDD,ELMBDA,
+! F,IDIMF,PERTRB,IERROR)
+!
+! ARGUMENTS
+! ON INPUT
+!
+! A,B
+! THE RANGE OF X, I.E. A .LE. X .LE. B.
+! A MUST BE LESS THAN B.
+!
+! M
+! THE NUMBER OF GRID POINTS IN THE
+! INTERVAL (A,B). THE GRID POINTS
+! IN THE X-DIRECTION ARE GIVEN BY
+! X(I) = A + (I-0.5)DX FOR I=1,2,...,M
+! WHERE DX =(B-A)/M. M MUST BE GREATER
+! THAN 2.
+!
+! MBDCND
+! INDICATES THE TYPE OF BOUNDARY CONDITIONS
+! AT X = A AND X = B.
+!
+! = 0 IF THE SOLUTION IS PERIODIC IN X,
+! U(M+I,J) = U(I,J).
+!
+! = 1 IF THE SOLUTION IS SPECIFIED AT
+! X = A AND X = B.
+!
+! = 2 IF THE SOLUTION IS SPECIFIED AT
+! X = A AND THE DERIVATIVE
+! OF THE SOLUTION WITH RESPECT TO X
+! IS SPECIFIED AT X = B.
+!
+! = 3 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO X IS SPECIFIED
+! AT X = A AND X = B.
+!
+! = 4 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO X IS SPECIFIED
+! AT X = A AND THE SOLUTION IS
+! SPECIFIED AT X = B.
+!
+! BDA
+! A ONE-DIMENSIONAL ARRAY OF LENGTH N
+! THAT SPECIFIES THE BOUNDARY VALUES
+! (IF ANY) OF THE SOLUTION AT X = A.
+!
+! WHEN MBDCND = 1 OR 2,
+! BDA(J) = U(A,Y(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 3 OR 4,
+! BDA(J) = (D/DX)U(A,Y(J)) , J=1,2,...,N.
+!
+! BDB
+! A ONE-DIMENSIONAL ARRAY OF LENGTH N
+! THAT SPECIFIES THE BOUNDARY VALUES
+! OF THE SOLUTION AT X = B.
+!
+! WHEN MBDCND = 1 OR 4
+! BDB(J) = U(B,Y(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 2 OR 3
+! BDB(J) = (D/DX)U(B,Y(J)) , J=1,2,...,N.
+!
+! C,D
+! THE RANGE OF Y, I.E. C .LE. Y .LE. D.
+! C MUST BE LESS THAN D.
+!
+!
+! N
+! THE NUMBER OF UNKNOWNS IN THE INTERVAL
+! (C,D). THE UNKNOWNS IN THE Y-DIRECTION
+! ARE GIVEN BY Y(J) = C + (J-0.5)DY,
+! J=1,2,...,N, WHERE DY = (D-C)/N.
+! N MUST BE GREATER THAN 2.
+!
+! NBDCND
+! INDICATES THE TYPE OF BOUNDARY CONDITIONS
+! AT Y = C AND Y = D.
+!
+!
+! = 0 IF THE SOLUTION IS PERIODIC IN Y, I.E.
+! U(I,J) = U(I,N+J).
+!
+! = 1 IF THE SOLUTION IS SPECIFIED AT Y = C
+! AND Y = D.
+!
+! = 2 IF THE SOLUTION IS SPECIFIED AT Y = C
+! AND THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO Y IS SPECIFIED AT
+! Y = D.
+!
+! = 3 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO Y IS SPECIFIED AT
+! Y = C AND Y = D.
+!
+! = 4 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO Y IS SPECIFIED AT
+! Y = C AND THE SOLUTION IS SPECIFIED
+! AT Y = D.
+!
+! BDC
+! A ONE DIMENSIONAL ARRAY OF LENGTH M THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT Y = C.
+!
+! WHEN NBDCND = 1 OR 2,
+! BDC(I) = U(X(I),C) , I=1,2,...,M.
+!
+! WHEN NBDCND = 3 OR 4,
+! BDC(I) = (D/DY)U(X(I),C), I=1,2,...,M.
+!
+! WHEN NBDCND = 0, BDC IS A DUMMY VARIABLE.
+!
+! BDD
+! A ONE-DIMENSIONAL ARRAY OF LENGTH M THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT Y = D.
+!
+! WHEN NBDCND = 1 OR 4,
+! BDD(I) = U(X(I),D) , I=1,2,...,M.
+!
+! WHEN NBDCND = 2 OR 3,
+! BDD(I) = (D/DY)U(X(I),D) , I=1,2,...,M.
+!
+! WHEN NBDCND = 0, BDD IS A DUMMY VARIABLE.
+!
+! ELMBDA
+! THE CONSTANT LAMBDA IN THE HELMHOLTZ
+! EQUATION. IF LAMBDA IS GREATER THAN 0,
+! A SOLUTION MAY NOT EXIST. HOWEVER,
+! HSTCRT WILL ATTEMPT TO FIND A SOLUTION.
+!
+! F
+! A TWO-DIMENSIONAL ARRAY THAT SPECIFIES
+! THE VALUES OF THE RIGHT SIDE OF THE
+! HELMHOLTZ EQUATION. FOR I=1,2,...,M
+! AND J=1,2,...,N
+!
+! F(I,J) = F(X(I),Y(J)) .
+!
+! F MUST BE DIMENSIONED AT LEAST M X N.
+!
+! IDIMF
+! THE ROW (OR FIRST) DIMENSION OF THE ARRAY
+! F AS IT APPEARS IN THE PROGRAM CALLING
+! HSTCRT. THIS PARAMETER IS USED TO SPECIFY
+! THE VARIABLE DIMENSION OF F.
+! IDIMF MUST BE AT LEAST M.
+!
+!
+! ON OUTPUT F
+! CONTAINS THE SOLUTION U(I,J) OF THE FINITE
+! DIFFERENCE APPROXIMATION FOR THE GRID POINT
+! (X(I),Y(J)) FOR I=1,2,...,M, J=1,2,...,N.
+!
+! PERTRB
+! IF A COMBINATION OF PERIODIC OR DERIVATIVE
+! BOUNDARY CONDITIONS IS SPECIFIED FOR A
+! POISSON EQUATION (LAMBDA = 0), A SOLUTION
+! MAY NOT EXIST. PERTRB IS A CONSTANT,
+! CALCULATED AND SUBTRACTED FROM F, WHICH
+! ENSURES THAT A SOLUTION EXISTS. HSTCRT
+! THEN COMPUTES THIS SOLUTION, WHICH IS A
+! LEAST SQUARES SOLUTION TO THE ORIGINAL
+! APPROXIMATION. THIS SOLUTION PLUS ANY
+! CONSTANT IS ALSO A SOLUTION; HENCE, THE
+! SOLUTION IS NOT UNIQUE. THE VALUE OF
+! PERTRB SHOULD BE SMALL COMPARED TO THE
+! RIGHT SIDE F. OTHERWISE, A SOLUTION IS
+! OBTAINED TO AN ESSENTIALLY DIFFERENT PROBLEM.
+! THIS COMPARISON SHOULD ALWAYS BE MADE TO
+! INSURE THAT A MEANINGFUL SOLUTION HAS BEEN
+! OBTAINED.
+!
+! IERROR
+! AN ERROR FLAG THAT INDICATES INVALID INPUT
+! PARAMETERS. EXCEPT TO NUMBERS 0 AND 6,
+! A SOLUTION IS NOT ATTEMPTED.
+!
+! = 0 NO ERROR
+!
+! = 1 A .GE. B
+!
+! = 2 MBDCND .LT. 0 OR MBDCND .GT. 4
+!
+! = 3 C .GE. D
+!
+! = 4 N .LE. 2
+!
+! = 5 NBDCND .LT. 0 OR NBDCND .GT. 4
+!
+! = 6 LAMBDA .GT. 0
+!
+! = 7 IDIMF .LT. M
+!
+! = 8 M .LE. 2
+!
+! SINCE THIS IS THE ONLY MEANS OF INDICATING
+! A POSSIBLY INCORRECT CALL TO HSTCRT, THE
+! USER SHOULD TEST IERROR AFTER THE CALL.
+!
+! = 20 If the dynamic allocation of real and
+! complex work space required for solution
+! fails (for example if N,M are too large
+! for your computer)
+!
+!
+! I/O NONE
+!
+! PRECISION SINGLE
+!
+! REQUIRED LIBRARY fish.f,comf.f,genbun.f,gnbnaux.f,poistg.f
+! FILES
+!
+! LANGUAGE FORTRAN 90
+!
+! HISTORY WRITTEN BY ROLAND SWEET AT NCAR IN 1977.
+! RELEASED ON NCAR'S PUBLIC SOFTWARE LIBRARIES
+! IN JANUARY 1980.
+! Revised in June 2004 by John Adams using
+! Fortran 90 dynamically allocated work space.
+!
+! PORTABILITY FORTRAN 90
+!
+! ALGORITHM THIS SUBROUTINE DEFINES THE FINITE-DIFFERENCE
+! EQUATIONS, INCORPORATES BOUNDARY DATA, ADJUSTS
+! THE RIGHT SIDE WHEN THE SYSTEM IS SINGULAR
+! AND CALLS EITHER POISTG OR GENBUN WHICH SOLVES
+! THE LINEAR SYSTEM OF EQUATIONS.
+!
+! TIMING FOR LARGE M AND N, THE OPERATION COUNT
+! IS ROUGHLY PROPORTIONAL TO M*N*LOG2(N).
+!
+! ACCURACY THE SOLUTION PROCESS EMPLOYED RESULTS IN A
+! LOSS OF NO MORE THAN FOUR SIGNIFICANT DIGITS
+! FOR N AND M AS LARGE AS 64. MORE DETAILED
+! INFORMATION ABOUT ACCURACY CAN BE FOUND IN
+! THE DOCUMENTATION FOR PACKAGE POISTG WHICH
+! SOLVES THE FINITE DIFFERENCE EQUATIONS.
+!
+! REFERENCES U. SCHUMANN AND R. SWEET,"A DIRECT METHOD
+! FOR THE SOLUTION OF POISSON'S EQUATION WITH
+! BOUNDARY CONDITIONS ON A STAGGERED GRID OF
+! ARBITRARY SIZE," J. COMP. PHYS. 20(1976),
+! PP. 171-182.
+!***********************************************************************
+ SUBROUTINE HSTCRT(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, matF, IDIMF, PERTRB, IERROR)
+ USE fish
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER,INTENT(IN) :: M,MBDCND,N,NBDCND,IDIMF
+ INTEGER,INTENT(OUT) :: IERROR
+ DOUBLE PRECISION,INTENT(IN) :: A,B,C,D,ELMBDA
+ DOUBLE PRECISION,INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION,DIMENSION(N),INTENT(IN) :: vecBDA,vecBDB
+ DOUBLE PRECISION,DIMENSION(M),INTENT(IN) :: vecBDC,vecBDD
+ DOUBLE PRECISION,DIMENSION(IDIMF,N),INTENT(INOUT) :: matF
+!-----------------------------------------------
+! Allocatable arrays
+!-----------------------------------------------
+ DOUBLE PRECISION,DIMENSION(:),ALLOCATABLE :: work
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: irwk, istatus
+
+ ! JANNIS: add interface
+ interface
+ SUBROUTINE HSTCRTT(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, matF, IDIMF, PERTRB, IERROR, vecW, IW)
+ INTEGER,INTENT(IN) :: M,MBDCND,N,NBDCND,IDIMF,IW
+ INTEGER,INTENT(OUT) :: IERROR
+ DOUBLE PRECISION,INTENT(IN) :: A,B,C,D,ELMBDA
+ DOUBLE PRECISION,INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION,DIMENSION(N),INTENT(IN) :: vecBDA,vecBDB
+ DOUBLE PRECISION,DIMENSION(M),INTENT(IN) :: vecBDC,vecBDD
+ DOUBLE PRECISION,DIMENSION(IDIMF,N),INTENT(INOUT) :: matF
+ DOUBLE PRECISION,DIMENSION(IW),INTENT(INOUT) :: vecW
+ end subroutine HSTCRTT
+ end interface
+!-----------------------------------------------
+!
+! CHECK FOR INVALID PARAMETERS.
+!
+ IERROR = 0
+
+ IF (A >= B) IERROR = 1
+ IF (MBDCND<0 .OR. MBDCND>4) IERROR = 2
+ IF (C >= D) IERROR = 3
+ IF (N <= 2) IERROR = 4
+ IF (NBDCND<0 .OR. NBDCND>4) IERROR = 5
+ IF (IDIMF < M) IERROR = 7
+ IF (M <= 2) IERROR = 8
+ IF (IERROR /= 0) RETURN
+!C! write(*,*) 'hstcrt: vecBDC:',vecBDC(1:size(vecBDC))
+!C! write(*,*) 'hstcrt: BDD:',BDD(:)
+!C! write(*,*) 'hstcrt: ELMBDA:',ELMBDA
+!C! write(*,*) 'hstcrt: matF:',matF(1:IDIMF,:)
+!C! write(*,*) 'hstcrt: IDIMF:',IDIMF
+! compute and allocate required real work space
+ CALL GEN_SPACE (N, M, IRWK)
+ irwk = irwk + 3*M
+ allocate(work(irwK),STAT=istatus)
+!@! write(*,*) 'HSTCRT: allocate work(irwk); irwk=',irwk
+! return if allocation failed (e.g., if n,m are too large)
+ IF (istatus > 0) THEN
+ write(*,*) 'HSTCRT: error allocate work(irwk); irwk=',irwk
+ RETURN
+ END IF
+
+! check that allocation was successful
+ call hstcrtt(a,b,m,mbdcnd,vecbda,vecbdb,c,d,n,nbdcnd, &
+ vecbdc,vecbdd,elmbda,matf,idimf,pertrb,ierror, &
+ work,size(work))
+!
+!@! write(*,*) 'HSTCRT: deallocate work(irwk); irwk=',irwk
+ deallocate(work,STAT=istatus)
+ IF (istatus > 0) THEN
+ write(*,*) 'HSTCRT: error deallocate work'
+ RETURN
+ END IF
+!
+ END SUBROUTINE HSTCRT
+
+ SUBROUTINE HSTCRTT(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, matF, IDIMF, PERTRB, &
+ IERROR, vecW, IW)
+
+! USE genbunal
+! USE poisson
+
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER,INTENT(IN) :: M,MBDCND,N,NBDCND,IDIMF,IW
+ INTEGER,INTENT(OUT) :: IERROR
+ DOUBLE PRECISION,INTENT(IN) :: A,B,C,D,ELMBDA
+ DOUBLE PRECISION,INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION,DIMENSION(N),INTENT(IN) :: vecBDA,vecBDB
+ DOUBLE PRECISION,DIMENSION(M),INTENT(IN) :: vecBDC,vecBDD
+ DOUBLE PRECISION,DIMENSION(IDIMF,N),INTENT(INOUT) :: matF
+ DOUBLE PRECISION,DIMENSION(IW),INTENT(INOUT) :: vecW
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: NPEROD, MPEROD, NP, MP, ID2, ID3, ID4, &
+ J, IERR1, IW2
+ DOUBLE PRECISION :: DELTAX,TWDELX,DELXSQ,DELTAY,TWDELY,DELYSQ,TWDYSQ,S,ST2
+!-----------------------------------------------
+
+ NPEROD = NBDCND
+ MPEROD = 0
+ IF (MBDCND > 0) MPEROD = 1
+ DELTAX = (B - A)/DBLE(M)
+ TWDELX = ONE/DELTAX
+ DELXSQ = TWO/DELTAX**2
+ DELTAY = (D - C)/DBLE(N)
+ TWDELY = ONE/DELTAY
+ DELYSQ = DELTAY**2
+ TWDYSQ = TWO/DELYSQ
+ NP = NBDCND + 1
+ MP = MBDCND + 1
+!
+! DEFINE THE A,B,C COEFFICIENTS IN W-ARRAY.
+!
+ ID2 = M
+ ID3 = ID2 + M
+ ID4 = ID3 + M
+ S = (DELTAY/DELTAX)**2
+ ST2 = TWO*S
+ vecW(:M) = S
+ vecW(ID2+1:M+ID2) = (-ST2) + ELMBDA*DELYSQ
+ vecW(ID3+1:M+ID3) = S
+!
+! ENTER BOUNDARY DATA FOR X-BOUNDARIES.
+!
+ GO TO (111,102,102,104,104) MP
+ 102 CONTINUE
+ matF(1,:N) = matF(1,:N) - vecBDA(:N)*DELXSQ
+ vecW(ID2+1) = vecW(ID2+1) - vecW(1)
+ GO TO 106
+ 104 CONTINUE
+ matF(1,:N) = matF(1,:N) + vecBDA(:N)*TWDELX
+ vecW(ID2+1) = vecW(ID2+1) + vecW(1)
+ 106 CONTINUE
+ GO TO (111,107,109,109,107) MP
+ 107 CONTINUE
+ matF(M,:N) = matF(M,:N) - vecBDB(:N)*DELXSQ
+ vecW(ID3) = vecW(ID3) - vecW(1)
+ GO TO 111
+ 109 CONTINUE
+ matF(M,:N) = matF(M,:N) - vecBDB(:N)*TWDELX
+ vecW(ID3) = vecW(ID3) + vecW(1)
+ 111 CONTINUE
+ GO TO (121,112,112,114,114) NP
+ 112 CONTINUE
+ matF(:M,1) = matF(:M,1) - vecBDC(:M)*TWDYSQ
+ GO TO 116
+ 114 CONTINUE
+ matF(:M,1) = matF(:M,1) + vecBDC(:M)*TWDELY
+ 116 CONTINUE
+ GO TO (121,117,119,119,117) NP
+ 117 CONTINUE
+ matF(:M,N) = matF(:M,N) - vecBDD(:M)*TWDYSQ
+ GO TO 121
+ 119 CONTINUE
+ matF(:M,N) = matF(:M,N) - vecBDD(:M)*TWDELY
+ 121 CONTINUE
+ matF(:M,:N) = matF(:M,:N)*DELYSQ
+ IF (MPEROD /= 0) THEN
+ vecW(1) = ZERO
+ vecW(ID4) = ZERO
+ ENDIF
+ PERTRB = ZERO
+ IF (ELMBDA >= ZERO) THEN
+ IF (ELMBDA /= ZERO) THEN
+ IERROR = 6
+ ELSE
+ GO TO (127,133,133,127,133) MP
+ 127 CONTINUE
+ GO TO (128,133,133,128,133) NP
+!
+! FOR SINGULAR PROBLEMS MUST ADJUST DATA TO INSURE THAT A SOLUTION
+! WILL EXIST.
+!
+ 128 CONTINUE
+ S = ZERO
+ DO J = 1, N
+ S = S + SUM(matF(:M,J))
+ END DO
+ PERTRB = S/DBLE(M*N)
+ matF(:M,:N) = matF(:M,:N) - PERTRB
+ PERTRB = PERTRB/DELYSQ
+!
+! SOLVE THE EQUATION.
+!
+ ENDIF
+ ENDIF
+ 133 CONTINUE
+ IERR1 = 0
+! Workarray splitted into parts of length M and IW
+ IW2 = size(vecW)-ID4
+ IF (NPEROD /= 0) THEN
+ CALL POISTGG (NPEROD, N, MPEROD, M, vecW(1:M), vecW(ID2+1:ID2+M), &
+ vecW(ID3+1:ID3+M),IDIMF, matF, IERR1, vecW(ID4+1:),IW2)
+ ELSE
+ CALL GENBUNN (NPEROD, N, MPEROD, M, vecW(1:M), vecW(ID2+1:ID2+M), &
+ vecW(ID3+1:ID3+M), IDIMF, matF, IERR1, vecW(ID4+1:),IW2)
+ ENDIF
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+! June 2004 Version 5.0, Fortran 90 changes
+!-----------------------------------------------------------------------
+ END SUBROUTINE HSTCRTT
+
+
+! file hstcyl.f
+!
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+! . .
+! . copyright (c) 2004 by UCAR .
+! . .
+! . UNIVERSITY CORPORATION for ATMOSPHERIC RESEARCH .
+! . .
+! . all rights reserved .
+! . .
+! . .
+! . FISHPACK version 5.0 .
+! . .
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+!
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+! * *
+! * F I S H P A C K *
+! * *
+! * *
+! * A PACKAGE OF FORTRAN SUBPROGRAMS FOR THE SOLUTION OF *
+! * *
+! * SEPARABLE ELLIPTIC PARTIAL DIFFERENTIAL EQUATIONS *
+! * *
+! * (Version 5.0 , JUNE 2004) *
+! * *
+! * BY *
+! * *
+! * JOHN ADAMS, PAUL SWARZTRAUBER AND ROLAND SWEET *
+! * *
+! * OF *
+! * *
+! * THE NATIONAL CENTER FOR ATMOSPHERIC RESEARCH *
+! * *
+! * BOULDER, COLORADO (80307) U.S.A. *
+! * *
+! * WHICH IS SPONSORED BY *
+! * *
+! * THE NATIONAL SCIENCE FOUNDATION *
+! * *
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+!
+! SUBROUTINE HSTCYL (A,B,M,MBDCND,BDA,BDB,C,D,N,NBDCND,BDC,BDD,
+! + ELMBDA,F,IDIMF,PERTRB,IERROR)
+!
+! DIMENSION OF BDA(N),BDB(N),BDC(M),BDD(M),F(IDIMF,N)
+! ARGUMENTS
+!
+! LATEST REVISION June 2004
+!
+! PURPOSE SOLVES THE STANDARD FIVE-POINT FINITE
+! DIFFERENCE APPROXIMATION ON A STAGGERED
+! GRID TO THE MODIFIED HELMHOLTZ EQUATION
+! IN CYLINDRICAL COORDINATES. THIS EQUATION
+!
+! (1/R)(D/DR)(R(DU/DR)) + (D/DZ)(DU/DZ)
+!
+! + LAMBDA*(1/R**2)*U = F(R,Z)
+!
+! IS A TWO-DIMENSIONAL MODIFIED HELMHOLTZ
+! EQUATION RESULTING FROM THE FOURIER TRANSFORM
+! OF A THREE-DIMENSIONAL POISSON EQUATION.
+!
+! USAGE CALL HSTCYL (A,B,M,MBDCND,BDA,BDB,C,D,N,
+! NBDCND,BDC,BDD,ELMBDA,F,IDIMF,
+! PERTRB,IERROR)
+!
+! ARGUMENTS
+! ON INPUT A,B
+!
+! THE RANGE OF R, I.E. A .LE. R .LE. B.
+! A MUST BE LESS THAN B AND A MUST BE
+! BE NON-NEGATIVE.
+!
+! M
+! THE NUMBER OF GRID POINTS IN THE INTERVAL
+! (A,B). THE GRID POINTS IN THE R-DIRECTION
+! R-DIRECTION ARE GIVEN BY
+! R(I) = A + (I-0.5)DR FOR I=1,2,...,M
+! WHERE DR =(B-A)/M.
+! M MUST BE GREATER THAN 2.
+!
+! MBDCND
+! INDICATES THE TYPE OF BOUNDARY CONDITIONS
+! AT R = A AND R = B.
+!
+! = 1 IF THE SOLUTION IS SPECIFIED AT R = A
+! (SEE NOTE BELOW) AND R = B.
+!
+! = 2 IF THE SOLUTION IS SPECIFIED AT R = A
+! (SEE NOTE BELOW) AND THE DERIVATIVE
+! OF THE SOLUTION WITH RESPECT TO R IS
+! SPECIFIED AT R = B.
+!
+! = 3 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO R IS SPECIFIED AT
+! R = A (SEE NOTE BELOW) AND R = B.
+!
+! = 4 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO R IS SPECIFIED AT
+! R = A (SEE NOTE BELOW) AND THE
+! SOLUTION IS SPECIFIED AT R = B.
+!
+! = 5 IF THE SOLUTION IS UNSPECIFIED AT
+! R = A = 0 AND THE SOLUTION IS
+! SPECIFIED AT R = B.
+!
+! = 6 IF THE SOLUTION IS UNSPECIFIED AT
+! R = A = 0 AND THE DERIVATIVE OF THE
+! SOLUTION WITH RESPECT TO R IS SPECIFIED
+! AT R = B.
+!
+! NOTE:
+! IF A = 0, DO NOT USE MBDCND = 1,2,3, OR 4,
+! BUT INSTEAD USE MBDCND = 5 OR 6.
+! THE RESULTING APPROXIMATION GIVES THE ONLY
+! MEANINGFUL BOUNDARY CONDITION,
+! I.E. DU/DR = 0.
+! (SEE D. GREENSPAN, 'INTRODUCTORY NUMERICAL
+! ANALYSIS OF ELLIPTIC BOUNDARY VALUE
+! PROBLEMS,' HARPER AND ROW, 1965, CHAPTER 5.)
+!
+! BDA
+! A ONE-DIMENSIONAL ARRAY OF LENGTH N THAT
+! SPECIFIES THE BOUNDARY VALUES (IF ANY)
+! OF THE SOLUTION AT R = A.
+!
+! WHEN MBDCND = 1 OR 2,
+! BDA(J) = U(A,Z(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 3 OR 4,
+! BDA(J) = (D/DR)U(A,Z(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 5 OR 6, BDA IS A DUMMY
+! VARIABLE.
+!
+! BDB
+! A ONE-DIMENSIONAL ARRAY OF LENGTH N THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT R = B.
+!
+! WHEN MBDCND = 1,4,OR 5,
+! BDB(J) = U(B,Z(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 2,3, OR 6,
+! BDB(J) = (D/DR)U(B,Z(J)) , J=1,2,...,N.
+!
+! C,D
+! THE RANGE OF Z, I.E. C .LE. Z .LE. D.
+! C MUST BE LESS THAN D.
+!
+! N
+! THE NUMBER OF UNKNOWNS IN THE INTERVAL
+! (C,D). THE UNKNOWNS IN THE Z-DIRECTION
+! ARE GIVEN BY Z(J) = C + (J-0.5)DZ,
+! J=1,2,...,N, WHERE DZ = (D-C)/N.
+! N MUST BE GREATER THAN 2.
+!
+! NBDCND
+! INDICATES THE TYPE OF BOUNDARY CONDITIONS
+! AT Z = C AND Z = D.
+!
+! = 0 IF THE SOLUTION IS PERIODIC IN Z, I.E.
+! U(I,J) = U(I,N+J).
+!
+! = 1 IF THE SOLUTION IS SPECIFIED AT Z = C
+! AND Z = D.
+!
+! = 2 IF THE SOLUTION IS SPECIFIED AT Z = C
+! AND THE DERIVATIVE OF THE SOLUTION WITH
+! RESPECT TO Z IS SPECIFIED AT Z = D.
+!
+! = 3 IF THE DERIVATIVE OF THE SOLUTION WITH
+! RESPECT TO Z IS SPECIFIED AT Z = C
+! AND Z = D.
+!
+! = 4 IF THE DERIVATIVE OF THE SOLUTION WITH
+! RESPECT TO Z IS SPECIFIED AT Z = C AND
+! THE SOLUTION IS SPECIFIED AT Z = D.
+!
+! BDC
+! A ONE DIMENSIONAL ARRAY OF LENGTH M THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT Z = C.
+!
+! WHEN NBDCND = 1 OR 2,
+! BDC(I) = U(R(I),C) , I=1,2,...,M.
+!
+! WHEN NBDCND = 3 OR 4,
+! BDC(I) = (D/DZ)U(R(I),C), I=1,2,...,M.
+!
+! WHEN NBDCND = 0, BDC IS A DUMMY VARIABLE.
+!
+! BDD
+! A ONE-DIMENSIONAL ARRAY OF LENGTH M THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT Z = D.
+!
+! WHEN NBDCND = 1 OR 4,
+! BDD(I) = U(R(I),D) , I=1,2,...,M.
+!
+! WHEN NBDCND = 2 OR 3,
+! BDD(I) = (D/DZ)U(R(I),D) , I=1,2,...,M.
+!
+! WHEN NBDCND = 0, BDD IS A DUMMY VARIABLE.
+!
+! ELMBDA
+! THE CONSTANT LAMBDA IN THE MODIFIED
+! HELMHOLTZ EQUATION. IF LAMBDA IS GREATER
+! THAN 0, A SOLUTION MAY NOT EXIST.
+! HOWEVER, HSTCYL WILL ATTEMPT TO FIND A
+! SOLUTION. LAMBDA MUST BE ZERO WHEN
+! MBDCND = 5 OR 6.
+!
+! F
+! A TWO-DIMENSIONAL ARRAY THAT SPECIFIES
+! THE VALUES OF THE RIGHT SIDE OF THE
+! MODIFIED HELMHOLTZ EQUATION.
+! FOR I=1,2,...,M AND J=1,2,...,N
+! F(I,J) = F(R(I),Z(J)) .
+! F MUST BE DIMENSIONED AT LEAST M X N.
+!
+! IDIMF
+! THE ROW (OR FIRST) DIMENSION OF THE ARRAY
+! F AS IT APPEARS IN THE PROGRAM CALLING
+! HSTCYL. THIS PARAMETER IS USED TO SPECIFY
+! THE VARIABLE DIMENSION OF F. IDIMF MUST
+! BE AT LEAST M.
+!
+! ON OUTPUT
+!
+! F
+! CONTAINS THE SOLUTION U(I,J) OF THE FINITE
+! DIFFERENCE APPROXIMATION FOR THE GRID POINT
+! (R(I),Z(J)) FOR I=1,2,...,M, J=1,2,...,N.
+!
+! PERTRB
+! IF A COMBINATION OF PERIODIC, DERIVATIVE,
+! OR UNSPECIFIED BOUNDARY CONDITIONS IS
+! SPECIFIED FOR A POISSON EQUATION
+! (LAMBDA = 0), A SOLUTION MAY NOT EXIST.
+! PERTRB IS A CONSTANT, CALCULATED AND
+! SUBTRACTED FROM F, WHICH ENSURES THAT A
+! SOLUTION EXISTS. HSTCYL THEN COMPUTES
+! THIS SOLUTION, WHICH IS A LEAST SQUARES
+! SOLUTION TO THE ORIGINAL APPROXIMATION.
+! THIS SOLUTION PLUS ANY CONSTANT IS ALSO
+! A SOLUTION; HENCE, THE SOLUTION IS NOT
+! UNIQUE. THE VALUE OF PERTRB SHOULD BE
+! SMALL COMPARED TO THE RIGHT SIDE F.
+! OTHERWISE, A SOLUTION IS OBTAINED TO AN
+! ESSENTIALLY DIFFERENT PROBLEM.
+! THIS COMPARISON SHOULD ALWAYS BE MADE TO
+! INSURE THAT A MEANINGFUL SOLUTION HAS BEEN
+! OBTAINED.
+!
+! IERROR
+! AN ERROR FLAG THAT INDICATES INVALID INPUT
+! PARAMETERS. EXCEPT TO NUMBERS 0 AND 11,
+! A SOLUTION IS NOT ATTEMPTED.
+!
+! = 0 NO ERROR
+!
+! = 1 A .LT. 0
+!
+! = 2 A .GE. B
+!
+! = 3 MBDCND .LT. 1 OR MBDCND .GT. 6
+!
+! = 4 C .GE. D
+!
+! = 5 N .LE. 2
+!
+! = 6 NBDCND .LT. 0 OR NBDCND .GT. 4
+!
+! = 7 A = 0 AND MBDCND = 1,2,3, OR 4
+!
+! = 8 A .GT. 0 AND MBDCND .GE. 5
+!
+! = 9 M .LE. 2
+!
+! = 10 IDIMF .LT. M
+!
+! = 11 LAMBDA .GT. 0
+!
+! = 12 A=0, MBDCND .GE. 5, ELMBDA .NE. 0
+!
+! SINCE THIS IS THE ONLY MEANS OF INDICATING
+! A POSSIBLY INCORRECT CALL TO HSTCYL, THE
+! USER SHOULD TEST IERROR AFTER THE CALL.
+!
+! = 20 If the dynamic allocation of real and
+! complex work space required for solution
+! fails (for example if N,M are too large
+! for your computer)
+! I/O NONE
+!
+! PRECISION SINGLE
+!
+! REQUIRED LIBRARY fish.f,comf.f,genbun.f,gnbnaux.f,poistg.f
+! FILES
+!
+! LANGUAGE FORTRAN 90
+!
+! HISTORY WRITTEN BY ROLAND SWEET AT NCAR IN 1977.
+! RELEASED ON NCAR'S PUBLIC SOFTWARE LIBRARIES
+! IN JANUARY 1980.
+! Revised in June 2004 by John Adams using
+! Fortran 90 dynamically allocated work space.
+!
+! PORTABILITY FORTRAN 90
+!
+! ALGORITHM THIS SUBROUTINE DEFINES THE FINITE-DIFFERENCE
+! EQUATIONS, INCORPORATES BOUNDARY DATA, ADJUSTS
+! THE RIGHT SIDE WHEN THE SYSTEM IS SINGULAR AND
+! CALLS EITHER POISTG OR GENBUN WHICH SOLVES THE
+! LINEAR SYSTEM OF EQUATIONS.
+!
+! TIMING FOR LARGE M AND N, THE OPERATION COUNT
+! IS ROUGHLY PROPORTIONAL TO M*N*LOG2(N).
+!
+! ACCURACY THE SOLUTION PROCESS RESULTS IN A LOSS
+! OF NO MORE THAN FOUR SIGNIFICANT DIGITS
+! FOR N AND M AS LARGE AS 64.
+! MORE DETAILED INFORMATION ABOUT ACCURACY
+! CAN BE FOUND IN THE DOCUMENTATION FOR
+! SUBROUTINE POISTG WHICH IS THE ROUTINE THAT
+! ACTUALLY SOLVES THE FINITE DIFFERENCE
+! EQUATIONS.
+!
+! REFERENCES U. SCHUMANN AND R. SWEET, "A DIRECT METHOD FOR
+! THE SOLUTION OF POISSON'S EQUATION WITH NEUMANN
+! BOUNDARY CONDITIONS ON A STAGGERED GRID OF
+! ARBITRARY SIZE," J. COMP. PHYS. 20(1976),
+! PP. 171-182.
+!***********************************************************************
+ SUBROUTINE HSTCYL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, &
+ NBDCND, vecBDC, vecBDD, ELMBDA, matF, IDIMF, &
+ PERTRB, IERROR)
+ USE fish
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M, MBDCND, N, NBDCND, IDIMF
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, INTENT(IN) :: A, B, C, D, ELMBDA
+ DOUBLE PRECISION, INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION, DIMENSION(:), INTENT(IN) :: vecBDA, vecBDB, vecBDC, &
+ vecBDD
+ DOUBLE PRECISION, DIMENSION(IDIMF,N), INTENT(INOUT) :: matF
+!-----------------------------------------------
+! Allocatable arrays
+!-----------------------------------------------
+ DOUBLE PRECISION,DIMENSION(:),ALLOCATABLE :: work
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: irwk, istatus
+!-----------------------------------------------
+ ! JANNIS: add interface
+ interface
+ SUBROUTINE HSTCYLL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, matF, IDIMF, PERTRB, IERROR, W)
+ INTEGER, INTENT(IN) :: M, MBDCND, N, NBDCND, IDIMF
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, INTENT(IN) :: A, B, C, D, ELMBDA
+ DOUBLE PRECISION, INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecBDA, vecBDB,vecBDC, &
+ vecBDD
+ DOUBLE PRECISION, DIMENSION(IDIMF,N), INTENT(INOUT) :: matF
+ DOUBLE PRECISION, DIMENSION(:), INTENT(OUT) :: W
+ end subroutine hstcyll
+ end interface
+
+ IERROR = 0
+ IF (A < ZERO) IERROR = 1
+ IF (A >= B) IERROR = 2
+ IF (MBDCND<=0 .OR. MBDCND>=7) IERROR = 3
+ IF (C >= D) IERROR = 4
+ IF (N <= 2) IERROR = 5
+ IF (NBDCND<0 .OR. NBDCND>=5) IERROR = 6
+ IF (A==ZERO .AND. MBDCND/=5 .AND. MBDCND/=6) IERROR = 7
+ IF (A>ZERO .AND. MBDCND>=5) IERROR = 8
+ IF (IDIMF < M) IERROR = 10
+ IF (M <= 2) IERROR = 9
+ IF (A==ZERO .AND. MBDCND>=5 .AND. ELMBDA/=ZERO) IERROR = 12
+ IF (IERROR /= 0) RETURN
+! allocate real work space
+! compute and allocate required real work space
+ CALL GEN_SPACE (N, M, IRWK)
+ IRWK = IRWK + 3*M
+ allocate(work(irwK),STAT=istatus)
+!@! write(*,*) 'HSTCYL: allocate work(irwk); irwk=',irwk
+! return if allocation failed (e.g., if n,m are too large)
+ IF (istatus > 0) THEN
+ write(*,*) 'HSTCYL: error allocate work(irwk); irwk=',irwk
+ RETURN
+ END IF
+! check that allocation was successful
+ call HSTCYLL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, matF, IDIMF, PERTRB, IERROR, work)
+! release allocated work space
+!@! write(*,*) 'HSTCYL: deallocate work(irwk); irwk=',irwk
+ deallocate(work,STAT=istatus)
+ IF (istatus > 0) THEN
+ write(*,*) 'HSTCYL: error deallocate work'
+ RETURN
+ END IF
+!
+! RETURN
+ END SUBROUTINE HSTCYL
+
+ SUBROUTINE HSTCYLL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, matF, IDIMF, PERTRB, IERROR, W)
+
+! USE poisson
+! USE genbunal
+
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M, MBDCND, N, NBDCND, IDIMF
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, INTENT(IN) :: A, B, C, D, ELMBDA
+ DOUBLE PRECISION, INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecBDA, vecBDB,vecBDC, &
+ vecBDD
+ DOUBLE PRECISION, DIMENSION(IDIMF,N), INTENT(INOUT) :: matF
+ DOUBLE PRECISION, DIMENSION(:), INTENT(OUT) :: W
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: NP, IWB, IWC, IWR, I, J, K, LP, IERR1
+ DOUBLE PRECISION :: DELTAR, DLRSQ, DELTHT, DLTHSQ, A1
+!-----------------------------------------------
+ DELTAR = (B - A)/DBLE(M)
+ DLRSQ = DELTAR**2
+ DELTHT = (D - C)/DBLE(N)
+ DLTHSQ = DELTHT**2
+ NP = NBDCND + 1
+!
+! DEFINE A,B,C COEFFICIENTS IN W-ARRAY.
+!
+ IWB = M
+ IWC = IWB + M
+ IWR = IWC + M
+ DO I = 1, M
+ J = IWR + I
+ W(J) = A + (DBLE(I) - HALF)*DELTAR
+ W(I) = (A + DBLE(I - 1)*DELTAR)/(DLRSQ*W(J))
+ K = IWC + I
+ W(K) = (A + DBLE(I)*DELTAR)/(DLRSQ*W(J))
+ K = IWB + I
+ W(K) = ELMBDA/W(J)**2 - TWO/DLRSQ
+ END DO
+!
+! ENTER BOUNDARY DATA FOR R-BOUNDARIES.
+!
+ GO TO (102,102,104,104,106,106) MBDCND
+ 102 CONTINUE
+ A1 = TWO*W(1)
+ W(IWB+1) = W(IWB+1) - W(1)
+ matF(1,:N) = matF(1,:N) - A1*vecBDA(:N)
+ GO TO 106
+ 104 CONTINUE
+ A1 = DELTAR*W(1)
+ W(IWB+1) = W(IWB+1) + W(1)
+ matF(1,:N) = matF(1,:N) + A1*vecBDA(:N)
+ 106 CONTINUE
+ GO TO (107,109,109,107,107,109) MBDCND
+ 107 CONTINUE
+ W(IWC) = W(IWC) - W(IWR)
+ A1 = TWO*W(IWR)
+ matF(M,:N) = matF(M,:N) - A1*vecBDB(:N)
+ GO TO 111
+ 109 CONTINUE
+ W(IWC) = W(IWC) + W(IWR)
+ A1 = DELTAR*W(IWR)
+ matF(M,:N) = matF(M,:N) - A1*vecBDB(:N)
+!
+! ENTER BOUNDARY DATA FOR THETA-BOUNDARIES.
+!
+ 111 CONTINUE
+ A1 = TWO/DLTHSQ
+ GO TO (121,112,112,114,114) NP
+ 112 CONTINUE
+ matF(:M,1) = matF(:M,1) - A1*vecBDC(:M)
+ GO TO 116
+ 114 CONTINUE
+ A1 = ONE/DELTHT
+ matF(:M,1) = matF(:M,1) + A1*vecBDC(:M)
+ 116 CONTINUE
+ A1 = TWO/DLTHSQ
+ GO TO (121,117,119,119,117) NP
+ 117 CONTINUE
+ matF(:M,N) = matF(:M,N) - A1*vecBDD(:M)
+ GO TO 121
+ 119 CONTINUE
+ A1 = ONE/DELTHT
+ matF(:M,N) = matF(:M,N) - A1*vecBDD(:M)
+ 121 CONTINUE
+ PERTRB = ZERO
+ IF (ELMBDA >= ZERO) THEN
+ IF (ELMBDA /= ZERO) THEN
+ IERROR = 11
+ ELSE
+ GO TO (130,130,124,130,130,124) MBDCND
+ 124 CONTINUE
+ GO TO (125,130,130,125,130) NP
+ 125 CONTINUE
+ DO I = 1, M
+ A1 = ZERO
+ A1 = SUM(matF(I,:N))
+ J = IWR + I
+ PERTRB = PERTRB + A1*W(J)
+ END DO
+ PERTRB = PERTRB/(DBLE(M*N)*HALF*(A + B))
+ matF(:M,:N) = matF(:M,:N) - PERTRB
+ ENDIF
+ ENDIF
+ 130 CONTINUE
+ W(:M) = W(:M)*DLTHSQ
+ W(IWC+1:M+IWC) = W(IWC+1:M+IWC)*DLTHSQ
+ W(IWB+1:M+IWB) = W(IWB+1:M+IWB)*DLTHSQ
+ matF(:M,:N) = matF(:M,:N)*DLTHSQ
+ LP = NBDCND
+ W(1) = ZERO
+ W(IWR) = ZERO
+!
+! SOLVE THE SYSTEM OF EQUATIONS.
+!
+ IERR1 = 0
+ IF (NBDCND /= 0) THEN
+ CALL POISTGG (LP, N, 1, M, W(1:M), W(IWB+1:IWB+M), W(IWC+1:IWC+M), &
+ IDIMF, matF, IERR1, W(IWR+1:), SIZE(W)-IWR)
+ ELSE
+ CALL GENBUNN (LP, N, 1, M, W(1:M), W(IWB+1:IWB+M), W(IWC+1:IWC+M), &
+ IDIMF, matF, IERR1, W(IWR+1:), SIZE(W)-IWR)
+ ENDIF
+! RETURN
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+! June 2004 Version 5.0, Fortran 90 changes
+!-----------------------------------------------------------------------
+ END SUBROUTINE HSTCYLL
+!
+! file mhstcyl.f
+!
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+! . .
+! . copyright (c) 2004 by UCAR .
+! . .
+! . UNIVERSITY CORPORATION for ATMOSPHERIC RESEARCH .
+! . .
+! . all rights reserved .
+! . .
+! . .
+! . FISHPACK version 5.0 .
+! . .
+! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+!
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+! * *
+! * F I S H P A C K *
+! * *
+! * *
+! * A PACKAGE OF FORTRAN SUBPROGRAMS FOR THE SOLUTION OF *
+! * *
+! * SEPARABLE ELLIPTIC PARTIAL DIFFERENTIAL EQUATIONS *
+! * *
+! * (Version 5.0 , JUNE 2004) *
+! * *
+! * BY *
+! * *
+! * JOHN ADAMS, PAUL SWARZTRAUBER AND ROLAND SWEET *
+! * *
+! * OF *
+! * *
+! * THE NATIONAL CENTER FOR ATMOSPHERIC RESEARCH *
+! * *
+! * BOULDER, COLORADO (80307) U.S.A. *
+! * *
+! * WHICH IS SPONSORED BY *
+! * *
+! * THE NATIONAL SCIENCE FOUNDATION *
+! * *
+! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+!
+! SUBROUTINE MHSTCYL (A,B,M,MBDCND,BDA,BDB,C,D,N,NBDCND,BDC,BDD,
+! + ELMBDA,ES,F,IDIMF,PERTRB,IERROR)
+!
+! DIMENSION OF BDA(N),BDB(N),BDC(M),BDD(M),F(IDIMF,N)
+! ARGUMENTS
+!
+! LATEST REVISION June 2004
+!
+! PURPOSE SOLVES THE STANDARD FIVE-POINT FINITE
+! DIFFERENCE APPROXIMATION ON A STAGGERED
+! GRID TO THE MODIFIED HELMHOLTZ EQUATION
+! IN CYLINDRICAL COORDINATES. THIS EQUATION
+!
+! (D2U/DR2) + (D/DZ)(DU/DZ)
+!
+! + LAMBDA*(1/R**2)*U + ES * U = F(R,Z)
+!
+! IS A TWO-DIMENSIONAL MODIFIED HELMHOLTZ
+! EQUATION RESULTING FROM THE FOURIER TRANSFORM
+! OF A THREE-DIMENSIONAL POISSON EQUATION.
+!
+! USAGE CALL MHSTCYL (A,B,M,MBDCND,BDA,BDB,C,D,N,
+! NBDCND,BDC,BDD,ELMBDA,ES,F,IDIMF,
+! PERTRB,IERROR)
+!
+! ARGUMENTS
+! ON INPUT A,B
+!
+! THE RANGE OF R, I.E. A .LE. R .LE. B.
+! A MUST BE LESS THAN B AND A MUST BE
+! BE NON-NEGATIVE.
+!
+! M
+! THE NUMBER OF GRID POINTS IN THE INTERVAL
+! (A,B). THE GRID POINTS IN THE R-DIRECTION
+! R-DIRECTION ARE GIVEN BY
+! R(I) = A + (I-0.5)DR FOR I=1,2,...,M
+! WHERE DR =(B-A)/M.
+! M MUST BE GREATER THAN 2.
+!
+! MBDCND
+! INDICATES THE TYPE OF BOUNDARY CONDITIONS
+! AT R = A AND R = B.
+!
+! = 1 IF THE SOLUTION IS SPECIFIED AT R = A
+! (SEE NOTE BELOW) AND R = B.
+!
+! = 2 IF THE SOLUTION IS SPECIFIED AT R = A
+! (SEE NOTE BELOW) AND THE DERIVATIVE
+! OF THE SOLUTION WITH RESPECT TO R IS
+! SPECIFIED AT R = B.
+!
+! = 3 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO R IS SPECIFIED AT
+! R = A (SEE NOTE BELOW) AND R = B.
+!
+! = 4 IF THE DERIVATIVE OF THE SOLUTION
+! WITH RESPECT TO R IS SPECIFIED AT
+! R = A (SEE NOTE BELOW) AND THE
+! SOLUTION IS SPECIFIED AT R = B.
+!
+! = 5 IF THE SOLUTION IS UNSPECIFIED AT
+! R = A = 0 AND THE SOLUTION IS
+! SPECIFIED AT R = B.
+!
+! = 6 IF THE SOLUTION IS UNSPECIFIED AT
+! R = A = 0 AND THE DERIVATIVE OF THE
+! SOLUTION WITH RESPECT TO R IS SPECIFIED
+! AT R = B.
+!
+! NOTE:
+! IF A = 0, DO NOT USE MBDCND = 1,2,3, OR 4,
+! BUT INSTEAD USE MBDCND = 5 OR 6.
+! THE RESULTING APPROXIMATION GIVES THE ONLY
+! MEANINGFUL BOUNDARY CONDITION,
+! I.E. DU/DR = 0.
+! (SEE D. GREENSPAN, 'INTRODUCTORY NUMERICAL
+! ANALYSIS OF ELLIPTIC BOUNDARY VALUE
+! PROBLEMS,' HARPER AND ROW, 1965, CHAPTER 5.)
+!
+! BDA
+! A ONE-DIMENSIONAL ARRAY OF LENGTH N THAT
+! SPECIFIES THE BOUNDARY VALUES (IF ANY)
+! OF THE SOLUTION AT R = A.
+!
+! WHEN MBDCND = 1 OR 2,
+! BDA(J) = U(A,Z(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 3 OR 4,
+! BDA(J) = (D/DR)U(A,Z(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 5 OR 6, BDA IS A DUMMY
+! VARIABLE.
+!
+! BDB
+! A ONE-DIMENSIONAL ARRAY OF LENGTH N THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT R = B.
+!
+! WHEN MBDCND = 1,4,OR 5,
+! BDB(J) = U(B,Z(J)) , J=1,2,...,N.
+!
+! WHEN MBDCND = 2,3, OR 6,
+! BDB(J) = (D/DR)U(B,Z(J)) , J=1,2,...,N.
+!
+! C,D
+! THE RANGE OF Z, I.E. C .LE. Z .LE. D.
+! C MUST BE LESS THAN D.
+!
+! N
+! THE NUMBER OF UNKNOWNS IN THE INTERVAL
+! (C,D). THE UNKNOWNS IN THE Z-DIRECTION
+! ARE GIVEN BY Z(J) = C + (J-0.5)DZ,
+! J=1,2,...,N, WHERE DZ = (D-C)/N.
+! N MUST BE GREATER THAN 2.
+!
+! NBDCND
+! INDICATES THE TYPE OF BOUNDARY CONDITIONS
+! AT Z = C AND Z = D.
+!
+! = 0 IF THE SOLUTION IS PERIODIC IN Z, I.E.
+! U(I,J) = U(I,N+J).
+!
+! = 1 IF THE SOLUTION IS SPECIFIED AT Z = C
+! AND Z = D.
+!
+! = 2 IF THE SOLUTION IS SPECIFIED AT Z = C
+! AND THE DERIVATIVE OF THE SOLUTION WITH
+! RESPECT TO Z IS SPECIFIED AT Z = D.
+!
+! = 3 IF THE DERIVATIVE OF THE SOLUTION WITH
+! RESPECT TO Z IS SPECIFIED AT Z = C
+! AND Z = D.
+!
+! = 4 IF THE DERIVATIVE OF THE SOLUTION WITH
+! RESPECT TO Z IS SPECIFIED AT Z = C AND
+! THE SOLUTION IS SPECIFIED AT Z = D.
+!
+! BDC
+! A ONE DIMENSIONAL ARRAY OF LENGTH M THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT Z = C.
+!
+! WHEN NBDCND = 1 OR 2,
+! BDC(I) = U(R(I),C) , I=1,2,...,M.
+!
+! WHEN NBDCND = 3 OR 4,
+! BDC(I) = (D/DZ)U(R(I),C), I=1,2,...,M.
+!
+! WHEN NBDCND = 0, BDC IS A DUMMY VARIABLE.
+!
+! BDD
+! A ONE-DIMENSIONAL ARRAY OF LENGTH M THAT
+! SPECIFIES THE BOUNDARY VALUES OF THE
+! SOLUTION AT Z = D.
+!
+! WHEN NBDCND = 1 OR 4,
+! BDD(I) = U(R(I),D) , I=1,2,...,M.
+!
+! WHEN NBDCND = 2 OR 3,
+! BDD(I) = (D/DZ)U(R(I),D) , I=1,2,...,M.
+!
+! WHEN NBDCND = 0, BDD IS A DUMMY VARIABLE.
+!
+! ELMBDA
+! THE CONSTANT LAMBDA IN THE MODIFIED
+! HELMHOLTZ EQUATION. IF LAMBDA IS GREATER
+! THAN 0, A SOLUTION MAY NOT EXIST.
+! HOWEVER, MHSTCYL WILL ATTEMPT TO FIND A
+! SOLUTION. LAMBDA MUST BE ZERO WHEN
+! MBDCND = 5 OR 6.
+!
+! F
+! A TWO-DIMENSIONAL ARRAY THAT SPECIFIES
+! THE VALUES OF THE RIGHT SIDE OF THE
+! MODIFIED HELMHOLTZ EQUATION.
+! FOR I=1,2,...,M AND J=1,2,...,N
+! F(I,J) = F(R(I),Z(J)) .
+! F MUST BE DIMENSIONED AT LEAST M X N.
+!
+! IDIMF
+! THE ROW (OR FIRST) DIMENSION OF THE ARRAY
+! F AS IT APPEARS IN THE PROGRAM CALLING
+! MHSTCYL. THIS PARAMETER IS USED TO SPECIFY
+! THE VARIABLE DIMENSION OF F. IDIMF MUST
+! BE AT LEAST M.
+!
+! ON OUTPUT
+!
+! F
+! CONTAINS THE SOLUTION U(I,J) OF THE FINITE
+! DIFFERENCE APPROXIMATION FOR THE GRID POINT
+! (R(I),Z(J)) FOR I=1,2,...,M, J=1,2,...,N.
+!
+! PERTRB
+! IF A COMBINATION OF PERIODIC, DERIVATIVE,
+! OR UNSPECIFIED BOUNDARY CONDITIONS IS
+! SPECIFIED FOR A POISSON EQUATION
+! (LAMBDA = 0), A SOLUTION MAY NOT EXIST.
+! PERTRB IS A CONSTANT, CALCULATED AND
+! SUBTRACTED FROM F, WHICH ENSURES THAT A
+! SOLUTION EXISTS. MHSTCYL THEN COMPUTES
+! THIS SOLUTION, WHICH IS A LEAST SQUARES
+! SOLUTION TO THE ORIGINAL APPROXIMATION.
+! THIS SOLUTION PLUS ANY CONSTANT IS ALSO
+! A SOLUTION; HENCE, THE SOLUTION IS NOT
+! UNIQUE. THE VALUE OF PERTRB SHOULD BE
+! SMALL COMPARED TO THE RIGHT SIDE F.
+! OTHERWISE, A SOLUTION IS OBTAINED TO AN
+! ESSENTIALLY DIFFERENT PROBLEM.
+! THIS COMPARISON SHOULD ALWAYS BE MADE TO
+! INSURE THAT A MEANINGFUL SOLUTION HAS BEEN
+! OBTAINED.
+!
+! IERROR
+! AN ERROR FLAG THAT INDICATES INVALID INPUT
+! PARAMETERS. EXCEPT TO NUMBERS 0 AND 11,
+! A SOLUTION IS NOT ATTEMPTED.
+!
+! = 0 NO ERROR
+!
+! = 1 A .LT. 0
+!
+! = 2 A .GE. B
+!
+! = 3 MBDCND .LT. 1 OR MBDCND .GT. 6
+!
+! = 4 C .GE. D
+!
+! = 5 N .LE. 2
+!
+! = 6 NBDCND .LT. 0 OR NBDCND .GT. 4
+!
+! = 7 A = 0 AND MBDCND = 1,2,3, OR 4
+!
+! = 8 A .GT. 0 AND MBDCND .GE. 5
+!
+! = 9 M .LE. 2
+!
+! = 10 IDIMF .LT. M
+!
+! = 11 LAMBDA .GT. 0
+!
+! = 12 A=0, MBDCND .GE. 5, ELMBDA .NE. 0
+!
+! SINCE THIS IS THE ONLY MEANS OF INDICATING
+! A POSSIBLY INCORRECT CALL TO MHSTCYL, THE
+! USER SHOULD TEST IERROR AFTER THE CALL.
+!
+! = 20 If the dynamic allocation of real and
+! complex work space required for solution
+! fails (for example if N,M are too large
+! for your computer)
+! I/O NONE
+!
+! PRECISION SINGLE
+!
+! REQUIRED LIBRARY fish.f,comf.f,genbun.f,gnbnaux.f,poistg.f
+! FILES
+!
+! LANGUAGE FORTRAN 90
+!
+! HISTORY WRITTEN BY ROLAND SWEET AT NCAR IN 1977.
+! RELEASED ON NCAR'S PUBLIC SOFTWARE LIBRARIES
+! IN JANUARY 1980.
+! Revised in June 2004 by John Adams using
+! Fortran 90 dynamically allocated work space.
+!
+! PORTABILITY FORTRAN 90
+!
+! ALGORITHM THIS SUBROUTINE DEFINES THE FINITE-DIFFERENCE
+! EQUATIONS, INCORPORATES BOUNDARY DATA, ADJUSTS
+! THE RIGHT SIDE WHEN THE SYSTEM IS SINGULAR AND
+! CALLS EITHER POISTG OR GENBUN WHICH SOLVES THE
+! LINEAR SYSTEM OF EQUATIONS.
+!
+! TIMING FOR LARGE M AND N, THE OPERATION COUNT
+! IS ROUGHLY PROPORTIONAL TO M*N*LOG2(N).
+!
+! ACCURACY THE SOLUTION PROCESS RESULTS IN A LOSS
+! OF NO MORE THAN FOUR SIGNIFICANT DIGITS
+! FOR N AND M AS LARGE AS 64.
+! MORE DETAILED INFORMATION ABOUT ACCURACY
+! CAN BE FOUND IN THE DOCUMENTATION FOR
+! SUBROUTINE POISTG WHICH IS THE ROUTINE THAT
+! ACTUALLY SOLVES THE FINITE DIFFERENCE
+! EQUATIONS.
+!
+! REFERENCES U. SCHUMANN AND R. SWEET, "A DIRECT METHOD FOR
+! THE SOLUTION OF POISSON'S EQUATION WITH NEUMANN
+! BOUNDARY CONDITIONS ON A STAGGERED GRID OF
+! ARBITRARY SIZE," J. COMP. PHYS. 20(1976),
+! PP. 171-182.
+!***********************************************************************
+ SUBROUTINE MHSTCYL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, &
+ N, NBDCND, vecBDC, vecBDD, ELMBDA, ES, &
+ matF, IDIMF, PERTRB, IERROR)
+ USE fish
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M, MBDCND, N, NBDCND, IDIMF
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, INTENT(IN) :: A, B, C, D, ELMBDA, ES
+ DOUBLE PRECISION, INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION, DIMENSION(N), INTENT(IN) :: vecBDA, vecBDB
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecBDC, vecBDD
+ DOUBLE PRECISION, DIMENSION(IDIMF,N), INTENT(OUT) :: matF
+!-----------------------------------------------
+! Allocatable arrays
+!-----------------------------------------------
+ DOUBLE PRECISION,DIMENSION(:),ALLOCATABLE :: work
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: irwk, istatus
+!-----------------------------------------------
+ IERROR = 0
+ IF (A < ZERO) IERROR = 1
+ IF (A >= B) IERROR = 2
+ IF (MBDCND<=0 .OR. MBDCND>=7) IERROR = 3
+ IF (C >= D) IERROR = 4
+ IF (N <= 2) IERROR = 5
+ IF (NBDCND<0 .OR. NBDCND>=5) IERROR = 6
+!Mod IF (A==ZERO .AND. MBDCND/=5 .AND. MBDCND/=6) IERROR = 7
+ IF (A>ZERO .AND. MBDCND>=5) IERROR = 8
+ IF (IDIMF < M) IERROR = 10
+ IF (M <= 2) IERROR = 9
+!Mod IF (A==ZERO .AND. MBDCND>=5 .AND. ELMBDA/=ZERO) IERROR = 12
+ IF (IERROR /= 0) RETURN
+! allocate real work space
+! compute and allocate required real work space
+ CALL GEN_SPACE (N, M, IRWK)
+ IRWK = IRWK + 3*M
+!@! write(*,*) 'MHSTCYL: allocate work(irwk); irwk=',irwk
+ allocate(work(irwk),STAT=istatus)
+! return if allocation failed (e.g., if n,m are too large)
+ IF (istatus > 0) THEN
+ write(*,*) 'HSTCRT: error allocate work(irwk); irwk=',irwk
+ RETURN
+ END IF
+ call MHSTCYLL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, ES, matF, IDIMF, PERTRB, &
+ IERROR, work, IRWK )
+! release allocated work space
+!@! write(*,*) 'MHSTCYL: deallocate work(irwk); irwk=',irwk
+ deallocate(work,STAT=istatus)
+ IF (istatus > 0) THEN
+ write(*,*) 'MHSTCYL: error deallocate work'
+ RETURN
+ END IF
+!
+ END SUBROUTINE MHSTCYL
+
+ SUBROUTINE MHSTCYLL(A, B, M, MBDCND, vecBDA, vecBDB, C, D, N, NBDCND, &
+ vecBDC, vecBDD, ELMBDA, ES, matF, IDIMF, &
+ PERTRB, IERROR, W, IW)
+! USE genbunal
+! USE poisson
+
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M, MBDCND, N, NBDCND, IDIMF, IW
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, INTENT(IN) :: A, B, C, D, ELMBDA, ES
+ DOUBLE PRECISION, INTENT(OUT) :: PERTRB
+ DOUBLE PRECISION, DIMENSION(N), INTENT(IN) :: vecBDA, vecBDB
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecBDC, vecBDD
+ DOUBLE PRECISION, DIMENSION(IDIMF,N), INTENT(OUT) :: matF
+ DOUBLE PRECISION, DIMENSION(IW), INTENT(INOUT) :: W
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: NP, IWB, IWC, IWR, I, J, K, LP, IERR1
+ DOUBLE PRECISION :: DELTAR, DLRSQ, DELTHT, DLTHSQ, A1
+!-----------------------------------------------
+ DELTAR = (B - A)/DBLE(M)
+ DLRSQ = DELTAR**2
+ DELTHT = (D - C)/DBLE(N)
+ DLTHSQ = DELTHT**2
+ NP = NBDCND + 1
+!
+! DEFINE A,B,C COEFFICIENTS IN W-ARRAY.
+!
+ IWB = M
+ IWC = IWB + M
+ IWR = IWC + M
+ DO I = 1, M
+ J = IWR + I
+ W(J) = A + (DBLE(I) - HALF)*DELTAR
+ W(I) = (W(J) - HALF * DELTAR)/(DLRSQ*W(J))
+ K = IWC + I
+ W(K) = (W(J) + HALF * DELTAR)/(DLRSQ*W(J))
+ K = IWB + I
+ W(K) = ELMBDA/W(J)**2 + ES - TWO/DLRSQ
+ END DO
+!
+! ENTER BOUNDARY DATA FOR R-BOUNDARIES.
+!
+ GO TO (102,102,104,104,106,106) MBDCND
+ 102 CONTINUE
+ A1 = TWO*W(1)
+ W(IWB+1) = W(IWB+1) - W(1)
+ matF(1,:N) = matF(1,:N) - A1*vecBDA(:N)
+ GO TO 106
+ 104 CONTINUE
+ A1 = DELTAR*W(1)
+ W(IWB+1) = W(IWB+1) + W(1)
+ matF(1,:N) = matF(1,:N) + A1*vecBDA(:N)
+ 106 CONTINUE
+ GO TO (107,109,109,107,107,109) MBDCND
+ 107 CONTINUE
+ W(IWC) = W(IWC) - W(IWR)
+ A1 = TWO*W(IWR)
+ matF(M,:N) = matF(M,:N) - A1*vecBDB(:N)
+ GO TO 111
+ 109 CONTINUE
+ W(IWC) = W(IWC) + W(IWR)
+ A1 = DELTAR*W(IWR)
+ matF(M,:N) = matF(M,:N) - A1*vecBDB(:N)
+!
+! ENTER BOUNDARY DATA FOR THETA-BOUNDARIES.
+!
+ 111 CONTINUE
+ A1 = TWO/DLTHSQ
+ GO TO (121,112,112,114,114) NP
+ 112 CONTINUE
+ matF(:M,1) = matF(:M,1) - A1*vecBDC(:M)
+ GO TO 116
+ 114 CONTINUE
+ A1 = ONE/DELTHT
+ matF(:M,1) = matF(:M,1) + A1*vecBDC(:M)
+ 116 CONTINUE
+ A1 = TWO/DLTHSQ
+ GO TO (121,117,119,119,117) NP
+ 117 CONTINUE
+ matF(:M,N) = matF(:M,N) - A1*vecBDD(:M)
+ GO TO 121
+ 119 CONTINUE
+ A1 = ONE/DELTHT
+ matF(:M,N) = matF(:M,N) - A1*vecBDD(:M)
+ 121 CONTINUE
+ PERTRB = ZERO
+ IF (ELMBDA >= ZERO) THEN
+ IF (ELMBDA /= ZERO) THEN
+ IERROR = 11
+ ELSE
+ GO TO (130,130,124,130,130,124) MBDCND
+ 124 CONTINUE
+ GO TO (125,130,130,125,130) NP
+ 125 CONTINUE
+ DO I = 1, M
+ A1 = ZERO
+ A1 = SUM(matF(I,:N))
+ J = IWR + I
+ PERTRB = PERTRB + A1*W(J)
+ END DO
+ PERTRB = PERTRB/(DBLE(M*N)*HALF*(A + B))
+ matF(:M,:N) = matF(:M,:N) - PERTRB
+ ENDIF
+ ENDIF
+ 130 CONTINUE
+ W(:M) = W(:M)*DLTHSQ
+ W(IWC+1:M+IWC) = W(IWC+1:M+IWC)*DLTHSQ
+ W(IWB+1:M+IWB) = W(IWB+1:M+IWB)*DLTHSQ
+ matF(:M,:N) = matF(:M,:N)*DLTHSQ
+ LP = NBDCND
+ W(1) = ZERO
+ W(IWR) = ZERO
+!
+! SOLVE THE SYSTEM OF EQUATIONS.
+!
+ IERR1 = 0
+ IF (NBDCND /= 0) THEN
+ CALL POISTGG (LP, N, 1, M, W, W(IWB+1:IWB+M), W(IWC+1:IWC+M), &
+ IDIMF, matF,IERR1, W(IWR+1:), size(W)-IWR)
+ ELSE
+ CALL GENBUNN (LP, N, 1, M, W, W(IWB+1:IWB+M), W(IWC+1:IWC+M), &
+ IDIMF, matF,IERR1, W(IWR+1:), size(W)-IWR)
+ ENDIF
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+! June 2004 Version 5.0, Fortran 90 changes
+! February 2009 Modified version of HSTCYL
+!-----------------------------------------------------------------------
+ END SUBROUTINE MHSTCYLL
diff --git a/fish90/src/hstcrt_wrap.c b/fish90/src/hstcrt_wrap.c
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/fish90/src/hstcyl_wrap.c b/fish90/src/hstcyl_wrap.c
new file mode 100644
index 0000000000000000000000000000000000000000..7caf2fb6776ff0a6212385e8cc2e40298913c73d
--- /dev/null
+++ b/fish90/src/hstcyl_wrap.c
@@ -0,0 +1,78 @@
+/* Wrapper for the HSTCYL function.
+ Alejandro Luque Estepa - 2006
+*/
+
+#include "stdlib.h"
+#include "stdio.h"
+#include "../include/fishpack.h"
+#include "math.h"
+#include "assert.h"
+
+const char *hstcyl_error_str[FISH_ERROR_MAX] =
+ {"No error",
+ "A .LT. 0",
+ "A .GE. B",
+ "MBDCND .LT. 1 OR MBDCND .GT. 6",
+ "C .GE. D",
+ "N .LE. 2",
+ "NBDCND .LT. 0 OR NBDCND .GT. 4",
+ "A = 0 AND MBDCND = 1,2,3, OR 4",
+ "A .GT. 0 AND MBDCND .GE. 5",
+ "M .LE. 2",
+ "IDIMF .LT. M",
+ "LAMBDA .GT. 0",
+ "A=0, MBDCND .GE. 5, ELMBDA .NE. 0"};
+
+int number=0;
+
+void mhstcyl_(double *r0, double *r1, int *nr, int *rbndcnd,
+ double *bcr0, double *bcr1,
+ double *z0, double *z1, int *nz, int *zbndcnd,
+ double *bcz0, double *bcz1,
+ double *lambda, double *s, double *f,
+ int *idimf, double *pertrb, int *ierror);
+
+/* Calls hstcyl and checks for errors. If an error occurs, prints the
+ corresponding message and exists. */
+void
+fish_hstcyl (double r0, double r1, int nr,
+ int rbndcnd, double *bcr0, double *bcr1,
+ double z0, double z1, int nz,
+ int zbndcnd, double *bcz0, double *bcz1,
+ double lambda, double s, double *f, int idimf)
+{
+ double pertrb;
+ int ierror;
+
+ mhstcyl_(&r0, &r1, &nr, &rbndcnd, bcr0, bcr1,
+ &z0, &z1, &nz, &zbndcnd, bcz0, bcz1,
+ &lambda, &s, f, &idimf, &pertrb, &ierror);
+ number+=1;
+
+/* fprintf(stderr, "# calls mhstcyl =%d\n",number); */
+ if (pertrb != 0.0) {
+ fprintf (stderr, "%s: ERROR: Undefined solution to the Poisson equation.",
+ __func__);
+ fprintf (stderr, "\nTry to change your boundary conditions.\n");
+ exit(-1);
+ }
+
+ if (0 != ierror) {
+ if (ierror <= FISH_ERROR_MAX) {
+ fprintf (stderr, "%s: ERROR: %s\n", __func__, hstcyl_error_str[ierror]);
+ fprintf (stderr, "The call to fishpack was\n");
+ fprintf (stderr, "mhstcyl_ (A = %f, B = %f, M = %d,\n", r0, r1, nr);
+ fprintf (stderr, " MBDCND = %d, ...\n", rbndcnd);
+ fprintf (stderr, " C = %f, D = %f, N = %d,\n", z0, z1, nz);
+ fprintf (stderr, " NBDCND = %d, ...\n", zbndcnd);
+ fprintf (stderr, " ELMBDA = %f, ...\n", lambda);
+ fprintf (stderr, " ES = %f, ...\n", s);
+ fprintf (stderr, " IDIMF = %d, ...)\n", idimf);
+ } else {
+ fprintf (stderr, "%s: Unknown error #%d\n", __func__, ierror);
+ }
+
+ exit(-1);
+ }
+}
+
diff --git a/fish90/src/poisson.f90 b/fish90/src/poisson.f90
new file mode 100644
index 0000000000000000000000000000000000000000..57f8b42e6808d4819133a77e11a3325dec07701c
--- /dev/null
+++ b/fish90/src/poisson.f90
@@ -0,0 +1,608 @@
+ SUBROUTINE POISTGG(NPEROD,N,MPEROD,M,vecA,vecB,vecC,IDIMY,matY, &
+ IERROR,W,IW)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: NPEROD, N, MPEROD, M, IDIMY,IW
+ INTEGER, INTENT(OUT) :: IERROR
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA,vecB,vecC
+ DOUBLE PRECISION, DIMENSION(IDIMY,N),INTENT(INOUT) :: matY
+ DOUBLE PRECISION, DIMENSION(IW) :: W
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: IWBA, IWBB, IWBC, IWB2, IWB3, IWW1, IWW2, IWW3, &
+ IWD,IWTCOS, IWP, I, K, J, NP, MP, IPSTOR, &
+ IREV, MH, MHM1, MODD, NBY2, MSKIP
+ DOUBLE PRECISION :: A1
+!-----------------------------------------------
+ IERROR = 0
+
+ IWBA = M + 1
+ IWBB = IWBA + M
+ IWBC = IWBB + M
+ IWB2 = IWBC + M
+ IWB3 = IWB2 + M
+ IWW1 = IWB3 + M
+ IWW2 = IWW1 + M
+ IWW3 = IWW2 + M
+ IWD = IWW3 + M
+ IWTCOS = IWD + M
+ IWP = IWTCOS + 4*N
+ DO I = 1, M
+ K = IWBA + I - 1
+ ! write(*,*) '0: i,k:',i,k
+ ! write(*,*) '0: vecA(I):',vecA(I)
+ W(K) = -vecA(I)
+ ! write(*,*) 'A: i,k,w(k):',i,k,w(k)
+ K = IWBC + I - 1
+ W(K) = -vecC(I)
+ ! write(*,*) 'B: i,k,w(k):',i,k,w(k)
+ K = IWBB + I - 1
+ W(K) = TWO - vecB(I)
+ ! write(*,*) 'C: i,k,w(k):',i,k,w(k)
+ matY(I,:N) = -matY(I,:N)
+ ! write(*,*) 'D: Y(i,:N):',Y(I,:N)
+ END DO
+ NP = NPEROD
+ MP = MPEROD + 1
+ GO TO (110,107) MP
+ 107 CONTINUE
+ GO TO (108,108,108,119) NPEROD
+ 108 CONTINUE
+ CALL POSTG2 (NP, N, M, W(IWBA:IWBA+M-1), W(IWBB:IWBB+M-1), &
+ W(IWBC:IWBC+M-1), IDIMY, matY, W(1:M), W(IWB2:IWB2+M-1), &
+ W(IWB3:IWB3+M-1), W(IWW1:IWW1+M-1), W(IWW2:IWW2+M-1), &
+ W(IWW3:IWW3+M-1), W(IWD:IWD+M-1), W(IWTCOS:IWTCOS+4*N-1), &
+ W(IWP:),IW-IWP)
+ IPSTOR = W(IWW1)
+ IREV = 2
+ IF (NPEROD == 4) GO TO 120
+ 109 CONTINUE
+ GO TO (123,129) MP
+ 110 CONTINUE
+ MH = (M + 1)/2
+ MHM1 = MH - 1
+ MODD = 1
+ IF (MH*2 == M) MODD = 2
+ DO J = 1, N
+ DO I = 1, MHM1
+ W(I) = matY(MH-I,J) - matY(I+MH,J)
+ W(I+MH) = matY(MH-I,J) + matY(I+MH,J)
+ END DO
+ W(MH) = TWO*matY(MH,J)
+ GO TO (113,112) MODD
+ 112 CONTINUE
+ W(M) = TWO*matY(M,J)
+ 113 CONTINUE
+ matY(:M,J) = W(:M)
+ END DO
+ K = IWBC + MHM1 - 1
+ I = IWBA + MHM1
+ W(K) = 0.
+ W(I) = 0.
+ W(K+1) = TWO*W(K+1)
+ SELECT CASE (MODD)
+ CASE DEFAULT
+ K = IWBB + MHM1 - 1
+ W(K) = W(K) - W(I-1)
+ W(IWBC-1) = W(IWBC-1) + W(IWBB-1)
+ CASE (2)
+ W(IWBB-1) = W(K+1)
+ END SELECT
+ GO TO 107
+ 119 CONTINUE
+ IREV = 1
+ NBY2 = N/2
+ NP = 2
+ 120 CONTINUE
+ DO J = 1, NBY2
+ MSKIP = N + 1 - J
+ DO I = 1, M
+ A1 = matY(I,J)
+ matY(I,J) = matY(I,MSKIP)
+ matY(I,MSKIP) = A1
+ END DO
+ END DO
+ GO TO (108,109) IREV
+ 123 CONTINUE
+ DO J = 1, N
+ W(MH-1:MH-MHM1:(-1)) = HALF*(matY(MH+1:MHM1+MH,J)+matY(:MHM1,J))
+ W(MH+1:MHM1+MH) = HALF*(matY(MH+1:MHM1+MH,J)-matY(:MHM1,J))
+ W(MH) = HALF*matY(MH,J)
+ GO TO (126,125) MODD
+ 125 CONTINUE
+ W(M) = HALF*matY(M,J)
+ 126 CONTINUE
+ matY(:M,J) = W(:M)
+ END DO
+ 129 CONTINUE
+ W(1) = IPSTOR + IWP - 1
+!
+ END SUBROUTINE POISTGG
+
+ SUBROUTINE POSTG2(NPEROD, N, M, vecA, vecBB, vecC, IDIMQ, matQ, &
+ vecB, vecB2, vecB3, vecW,vecW2, vecW3, vecD, &
+ TCOS, vecP,IvecP)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER , INTENT(IN) :: NPEROD,N,M,IDIMQ,IvecP
+ DOUBLE PRECISION, DIMENSION(M),INTENT(IN) :: vecA,vecBB,vecC
+ DOUBLE PRECISION, DIMENSION(M),INTENT(OUT) :: vecB
+ DOUBLE PRECISION, DIMENSION(IDIMQ,N),INTENT(INOUT) :: matQ
+ DOUBLE PRECISION, DIMENSION(M),INTENT(INOUT) :: vecB2,vecB3,vecD, &
+ vecW2,vecW3, vecW
+ DOUBLE PRECISION, DIMENSION(IvecP),INTENT(INOUT) :: vecP
+ DOUBLE PRECISION, DIMENSION(4*N),INTENT(INOUT) :: TCOS
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER, DIMENSION(4) :: K
+ INTEGER :: K1, K2, K3, K4, NP, MR, IP, IPSTOR, I2R, JR, NR, NLAST, &
+ KR, LR, NROD, JSTART, JSTOP, I2RBY2, &
+ J, IJUMP, JP1, JP2, JP3, JM1, JM2, JM3, I, NRODPR, II, &
+ NLASTP, JSTEP
+ DOUBLE PRECISION :: FNUM, FNUM2, FI, T
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE POISSON'S EQUATION ON A STAGGERED GRID.
+!
+ EQUIVALENCE (K(1), K1), (K(2), K2), (K(3), K3), (K(4), K4)
+ NP = NPEROD
+ FNUM = HALF*DBLE(NP/3)
+ FNUM2 = HALF*DBLE(NP/2)
+ MR = M
+ IP = -MR
+ IPSTOR = 0
+ I2R = 1
+ JR = 2
+ NR = N
+ NLAST = N
+ KR = 1
+ LR = 0
+ IF (NR > 3) THEN
+ 101 CONTINUE
+ JR = 2*I2R
+ NROD = 1
+ IF ((NR/2)*2 == NR) NROD = 0
+ JSTART = 1
+ JSTOP = NLAST - JR
+ IF (NROD == 0) JSTOP = JSTOP - I2R
+ I2RBY2 = I2R/2
+ IF (JSTOP < JSTART) THEN
+ J = JR
+ ELSE
+ IJUMP = 1
+ DO J = JSTART, JSTOP, JR
+ JP1 = J + I2RBY2
+ JP2 = J + I2R
+ JP3 = JP2 + I2RBY2
+ JM1 = J - I2RBY2
+ JM2 = J - I2R
+ JM3 = JM2 - I2RBY2
+ IF (J == 1) THEN
+ CALL COSGEN (I2R, 1, FNUM, HALF, TCOS, size(TCOS) )
+ IF (I2R == 1) THEN
+ vecB(:MR) = matQ(:MR,1)
+ matQ(:MR,1) = matQ(:MR,2)
+ GO TO 112
+ ENDIF
+ vecB(:MR) = matQ(:MR,1) + &
+ HALF*(matQ(:MR,JP2)-matQ(:MR,JP1)-matQ(:MR,JP3))
+ matQ(:MR,1) = matQ(:MR,JP2) + matQ(:MR,1) - matQ(:MR,JP1)
+ GO TO 112
+ ENDIF
+ GO TO (107,108) IJUMP
+ 107 CONTINUE
+ IJUMP = 2
+ CALL COSGEN (I2R, 1, HALF, ZERO, TCOS, size(TCOS) )
+ 108 CONTINUE
+ IF (I2R == 1) THEN
+ vecB(:MR) = TWO*matQ(:MR,J)
+ matQ(:MR,J) = matQ(:MR,JM2) + matQ(:MR,JP2)
+ ELSE
+ DO I = 1, MR
+ FI = matQ(I,J)
+ matQ(I,J)=matQ(I,J)-matQ(I,JM1)-matQ(I,JP1)+ &
+ matQ(I,JM2)+matQ(I,JP2)
+ vecB(I) =FI + matQ(I,J) - matQ(I,JM3) - matQ(I,JP3)
+ END DO
+ ENDIF
+ 112 CONTINUE
+ CALL TRIX (I2R, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+!
+! END OF REDUCTION FOR REGULAR UNKNOWNS.
+!
+ END DO
+!
+! BEGIN SPECIAL REDUCTION FOR LAST UNKNOWN.
+!
+ J = JSTOP + JR
+ ENDIF
+ NLAST = J
+ JM1 = J - I2RBY2
+ JM2 = J - I2R
+ JM3 = JM2 - I2RBY2
+ IF (NROD /= 0) THEN
+!
+! ODD NUMBER OF UNKNOWNS
+!
+ IF (I2R == 1) THEN
+ vecB(:MR) = matQ(:MR,J)
+ matQ(:MR,J) = matQ(:MR,JM2)
+ ELSE
+ vecB(:MR)=matQ(:MR,J)+ &
+ HALF*(matQ(:MR,JM2)-matQ(:MR,JM1)-matQ(:MR,JM3))
+ IF (NRODPR == 0) THEN
+ matQ(:MR,J) = matQ(:MR,JM2) + vecP(IP+1:MR+IP)
+ IP = IP - MR
+ ELSE
+ matQ(:MR,J) = matQ(:MR,J) - matQ(:MR,JM1) + matQ(:MR,JM2)
+ ENDIF
+ IF (LR /= 0) CALL COSGEN (LR, 1, FNUM2, HALF, TCOS(KR+1), &
+ size(tcos)-KR)
+ ENDIF
+ CALL COSGEN (KR, 1, FNUM2, HALF, TCOS, size(tcos))
+ CALL TRIX (KR, LR, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ KR = KR + I2R
+ ELSE
+ JP1 = J + I2RBY2
+ JP2 = J + I2R
+ IF (I2R == 1) THEN
+ vecB(:MR) = matQ(:MR,J)
+ TCOS(1) = 0.
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ IP = 0
+ IPSTOR = MR
+ vecP(:MR) = vecB(:MR)
+ vecB(:MR) = vecB(:MR) + matQ(:MR,N)
+ TCOS(1) = -ONE + TWO*DBLE(NP/2)
+ TCOS(2) = 0.
+ CALL TRIX (1, 1, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,JM2) + vecP(:MR) + vecB(:MR)
+ ELSE
+ vecB(:MR)=matQ(:MR,J)+ &
+ HALF*(matQ(:MR,JM2)-matQ(:MR,JM1)-matQ(:MR,JM3))
+ IF (NRODPR == 0) THEN
+ vecB(:MR) = vecB(:MR) + vecP(IP+1:MR+IP)
+ ELSE
+ vecB(:MR) = vecB(:MR) + matQ(:MR,JP2) - matQ(:MR,JP1)
+ ENDIF
+ CALL COSGEN (I2R, 1, HALF, ZERO, TCOS, size(tcos))
+ CALL TRIX (I2R, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ IP = IP + MR
+ IPSTOR = MAX0(IPSTOR,IP + MR)
+ vecP(IP+1:MR+IP) = vecB(:MR) + &
+ HALF*(matQ(:MR,J)-matQ(:MR,JM1)-matQ(:MR,JP1))
+ vecB(:MR) = vecP(IP+1:MR+IP) + matQ(:MR,JP2)
+ IF (LR /= 0) THEN
+ CALL COSGEN (LR, 1, FNUM2, HALF, TCOS(I2R+1), size(tcos)-I2R)
+ CALL MERGE (TCOS, 0, I2R, I2R, LR, KR, size(TCOS))
+ ELSE
+ DO I = 1, I2R
+ II = KR + I
+ TCOS(II) = TCOS(I)
+ END DO
+ ENDIF
+ CALL COSGEN (KR, 1, FNUM2, HALF, TCOS, size(TCOS))
+ CALL TRIX (KR, KR, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,JM2) + vecP(IP+1:MR+IP) + vecB(:MR)
+ ENDIF
+ LR = KR
+ KR = KR + JR
+ ENDIF
+ NR = (NLAST - 1)/JR + 1
+ IF (NR <= 3) GO TO 142
+ I2R = JR
+ NRODPR = NROD
+ GO TO 101
+ ENDIF ! IF (NR > 3)
+ 142 CONTINUE
+ J = 1 + JR
+ JM1 = J - I2R
+ JP1 = J + I2R
+ JM2 = NLAST - I2R
+ IF (NR /= 2) THEN
+ IF (LR == 0) THEN
+ IF (N == 3) THEN
+!
+! CASE N = 3.
+!
+ GO TO (143,148,143) NP
+ 143 CONTINUE
+ vecB(:MR) = matQ(:MR,2)
+ vecB2(:MR) = matQ(:MR,1) + matQ(:MR,3)
+ vecB3(:MR) = 0.
+ SELECT CASE (NP)
+ CASE DEFAULT
+ TCOS(1) = -ONE
+ TCOS(2) = ONE
+ K1 = 1
+ CASE (1:2)
+ TCOS(1) = -TWO
+ TCOS(2) = ONE
+ TCOS(3) = -ONE
+ K1 = 2
+ END SELECT
+ K2 = 1
+ K3 = 0
+ K4 = 0
+ GO TO 150
+ 148 CONTINUE
+ vecB(:MR) = matQ(:MR,2)
+ vecB2(:MR) = matQ(:MR,3)
+ vecB3(:MR) = matQ(:MR,1)
+ CALL COSGEN (3, 1, HALF, ZERO, TCOS, size(TCOS))
+ TCOS(4) = -ONE
+ TCOS(5) = ONE
+ TCOS(6) = -ONE
+ TCOS(7) = ONE
+ K1 = 3
+ K2 = 2
+ K3 = 1
+ K4 = 1
+ 150 CONTINUE
+ CALL TRI3(MR,vecA,vecBB,vecC,K,vecB,vecB2,vecB3,TCOS, &
+ size(TCOS),vecD,vecW,vecW2,vecW3)
+ vecB(:MR) = vecB(:MR) + vecB2(:MR) + vecB3(:MR)
+ GO TO (153,153,152) NP
+ 152 CONTINUE
+ TCOS(1) = TWO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ 153 CONTINUE
+ matQ(:MR,2) = vecB(:MR)
+ vecB(:MR) = matQ(:MR,1) + vecB(:MR)
+ TCOS(1) = -ONE + FOUR*FNUM
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,1) = vecB(:MR)
+ JR = 1
+ I2R = 0
+ GO TO 188
+ ENDIF
+!
+! CASE N = 2**P+1
+!
+ vecB(:MR)=matQ(:MR,J)+matQ(:MR,1)-matQ(:MR,JM1)+ &
+ matQ(:MR,NLAST)-matQ(:MR,JM2)
+ GO TO (158,160,158) NP
+ 158 CONTINUE
+ vecB2(:MR) = matQ(:MR,1) + matQ(:MR,NLAST) + &
+ matQ(:MR,J) - matQ(:MR,JM1) -matQ(:MR,JP1)
+ vecB3(:MR) = 0.
+ K1 = NLAST - 1
+ K2 = NLAST + JR - 1
+ CALL COSGEN (JR - 1, 1, ZERO, ONE, TCOS(NLAST), size(TCOS)-NLAST+1)
+ TCOS(K2) = TWO*DBLE(NP - 2)
+ CALL COSGEN (JR, 1, HALF - FNUM, HALF, TCOS(K2+1),size(TCOS)-K2)
+ K3 = (3 - NP)/2
+ CALL MERGE (TCOS, K1, JR - K3, K2 - K3, JR + K3, 0, size(TCOS))
+ K1 = K1 - 1 + K3
+ CALL COSGEN (JR, 1, FNUM, HALF, TCOS(K1+1),size(TCOS)-K1)
+ K2 = JR
+ K3 = 0
+ K4 = 0
+ GO TO 162
+ 160 CONTINUE
+ DO I = 1, MR
+ FI = HALF*(matQ(I,J)-matQ(I,JM1)-matQ(I,JP1))
+ vecB2(I) = matQ(I,1) + FI
+ vecB3(I) = matQ(I,NLAST) + FI
+ END DO
+ K1 = NLAST + JR - 1
+ K2 = K1 + JR - 1
+ CALL COSGEN (JR - 1, 1, ZERO, ONE, TCOS(K1+1), size(TCOS)-K1)
+ CALL COSGEN (NLAST, 1, HALF, ZERO, TCOS(K2+1), size(TCOS)-K2)
+ CALL MERGE (TCOS, K1, JR - 1, K2, NLAST, 0, size(TCOS))
+ K3 = K1 + NLAST - 1
+ K4 = K3 + JR
+ CALL COSGEN (JR, 1, HALF, HALF, TCOS(K3+1),SIZE(TCOS)-K3)
+ CALL COSGEN (JR, 1, ZERO, HALF, TCOS(K4+1),SIZE(TCOS)-K4)
+ CALL MERGE (TCOS, K3, JR, K4, JR, K1, size(TCOS) )
+ K2 = NLAST - 1
+ K3 = JR
+ K4 = JR
+ 162 CONTINUE
+ CALL TRI3 (MR, vecA, vecBB, vecC, K, vecB, vecB2, vecB3, &
+ TCOS, size(TCOS), vecD, vecW, vecW2, vecW3)
+ vecB(:MR) = vecB(:MR) + vecB2(:MR) + vecB3(:MR)
+ IF (NP == 3) THEN
+ TCOS(1) = TWO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ ENDIF
+ matQ(:MR,J) = vecB(:MR) + &
+ HALF*(matQ(:MR,J)-matQ(:MR,JM1)-matQ(:MR,JP1))
+ vecB(:MR) = matQ(:MR,J) + matQ(:MR,1)
+ CALL COSGEN (JR, 1, FNUM, HALF, TCOS,size(TCOS))
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,1) = matQ(:MR,1) - matQ(:MR,JM1) + vecB(:MR)
+ GO TO 188
+ ENDIF
+!
+! CASE OF GENERAL N WITH NR = 3 .
+!
+ vecB(:MR) = matQ(:MR,1) - matQ(:MR,JM1) + matQ(:MR,J)
+ IF (NROD == 0) THEN
+ vecB(:MR) = vecB(:MR) + vecP(IP+1:MR+IP)
+ ELSE
+ vecB(:MR) = vecB(:MR) + matQ(:MR,NLAST) - matQ(:MR,JM2)
+ ENDIF
+ DO I = 1, MR
+ T = HALF*(matQ(I,J)-matQ(I,JM1)-matQ(I,JP1))
+ matQ(I,J) = T
+ vecB2(I) = matQ(I,NLAST) + T
+ vecB3(I) = matQ(I,1) + T
+ END DO
+ K1 = KR + 2*JR
+ CALL COSGEN (JR - 1, 1, ZERO, ONE, TCOS(K1+1),size(TCOS)-K1)
+ K2 = K1 + JR
+ TCOS(K2) = TWO*DBLE(NP - 2)
+ K4 = (NP - 1)*(3 - NP)
+ K3 = K2 + 1 - K4
+ CALL COSGEN(KR+JR+K4,1,HALF*DBLE(K4),ONE-DBLE(K4),TCOS(K3), &
+ size(TCOS)-K3+1 )
+ K4 = 1 - NP/3
+ CALL MERGE (TCOS, K1, JR - K4, K2 - K4, KR + JR + K4, 0, size(TCOS) )
+ IF (NP == 3) K1 = K1 - 1
+ K2 = KR + JR
+ K4 = K1 + K2
+ CALL COSGEN (KR, 1, FNUM2, HALF, TCOS(K4+1),size(TCOS)-K4)
+ K3 = K4 + KR
+ CALL COSGEN (JR, 1, FNUM, HALF, TCOS(K3+1),size(TCOS)-K3)
+ CALL MERGE (TCOS, K4, KR, K3, JR, K1, size(TCOS) )
+ K4 = K3 + JR
+ CALL COSGEN (LR, 1, FNUM2, HALF, TCOS(K4+1),size(TCOS)-K4)
+ CALL MERGE (TCOS, K3, JR, K4, LR, K1 + K2, size(TCOS) )
+ CALL COSGEN (KR, 1, FNUM2, HALF, TCOS(K3+1),size(TCOS)-K3)
+ K3 = KR
+ K4 = KR
+ CALL TRI3 (MR, vecA, vecBB, vecC, K, vecB, vecB2, vecB3, &
+ TCOS, SIZE(TCOS), vecD, vecW, vecW2, vecW3)
+ vecB(:MR) = vecB(:MR) + vecB2(:MR) + vecB3(:MR)
+ IF (NP == 3) THEN
+ TCOS(1) = TWO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ ENDIF
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ vecB(:MR) = matQ(:MR,1) + matQ(:MR,J)
+ CALL COSGEN (JR, 1, FNUM, HALF, TCOS,size(TCOS))
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ IF (JR == 1) THEN
+ matQ(:MR,1) = vecB(:MR)
+ GO TO 188
+ ENDIF
+ matQ(:MR,1) = matQ(:MR,1) - matQ(:MR,JM1) + vecB(:MR)
+ GO TO 188
+ ENDIF
+ vecB3(:MR) = 0.
+ vecB (:MR) = matQ(:MR,1) + vecP(IP+1:MR+IP)
+ matQ (:MR,1) = matQ(:MR,1) - matQ(:MR,JM1)
+ vecB2(:MR) = matQ(:MR,1) + matQ(:MR,NLAST)
+ K1 = KR + JR
+ K2 = K1 + JR
+ CALL COSGEN (JR - 1, 1, ZERO, ONE, TCOS(K1+1),SIZE(TCOS)-K1)
+ GO TO (182,183,182) NP
+ 182 CONTINUE
+ TCOS(K2) = TWO*DBLE(NP - 2)
+ CALL COSGEN (KR, 1, ZERO, ONE, TCOS(K2+1),SIZE(TCOS)-K2)
+ GO TO 184
+ 183 CONTINUE
+ CALL COSGEN (KR + 1, 1, HALF, ZERO, TCOS(K2),SIZE(TCOS)-K2)
+ 184 CONTINUE
+ K4 = 1 - NP/3
+ CALL MERGE (TCOS, K1, JR - K4, K2 - K4, KR + K4, 0, size(TCOS) )
+ IF (NP == 3) K1 = K1 - 1
+ K2 = KR
+ CALL COSGEN (KR, 1, FNUM2, HALF, TCOS(K1+1),SIZE(TCOS)-K1)
+ K4 = K1 + KR
+ CALL COSGEN (LR, 1, FNUM2, HALF, TCOS(K4+1),SIZE(TCOS)-K4)
+ K3 = LR
+ K4 = 0
+ CALL TRI3 (MR, vecA, vecBB, vecC, K, vecB, vecB2, vecB3, &
+ TCOS, SIZE(TCOS), vecD, vecW, vecW2, vecW3)
+ vecB(:MR) = vecB(:MR) + vecB2(:MR)
+ IF (NP == 3) THEN
+ TCOS(1) = TWO
+ CALL TRIX (1, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ ENDIF
+ matQ(:MR,1) = matQ(:MR,1) + vecB(:MR)
+ 188 CONTINUE
+ J = NLAST - JR
+ vecB(:MR) = matQ(:MR,NLAST) + matQ(:MR,J)
+ JM2 = NLAST - I2R
+ IF (JR == 1) THEN
+ matQ(:MR,NLAST) = 0.
+ ELSE
+ IF (NROD == 0) THEN
+ matQ(:MR,NLAST) = vecP(IP+1:MR+IP)
+ IP = IP - MR
+ ELSE
+ matQ(:MR,NLAST) = matQ(:MR,NLAST) - matQ(:MR,JM2)
+ ENDIF
+ ENDIF
+ CALL COSGEN (KR, 1, FNUM2, HALF, TCOS,SIZE(TCOS))
+ CALL COSGEN (LR, 1, FNUM2, HALF, TCOS(KR+1),SIZE(TCOS)-KR)
+ CALL TRIX (KR, LR, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,NLAST) = matQ(:MR,NLAST) + vecB(:MR)
+ NLASTP = NLAST
+ 197 CONTINUE
+ JSTEP = JR
+ JR = I2R
+ I2R = I2R/2
+ IF (JR == 0) GO TO 210
+ JSTART = 1 + JR
+ KR = KR - JR
+ IF (NLAST + JR <= N) THEN
+ KR = KR - JR
+ NLAST = NLAST + JR
+ JSTOP = NLAST - JSTEP
+ ELSE
+ JSTOP = NLAST - JR
+ ENDIF
+ LR = KR - JR
+ CALL COSGEN (JR, 1, HALF, ZERO, TCOS,SIZE(TCOS))
+ DO J = JSTART, JSTOP, JSTEP
+ JM2 = J - JR
+ JP2 = J + JR
+ IF (J == JR) THEN
+ vecB(:MR) = matQ(:MR,J) + matQ(:MR,JP2)
+ ELSE
+ vecB(:MR) = matQ(:MR,J) + matQ(:MR,JM2) + matQ(:MR,JP2)
+ ENDIF
+ IF (JR == 1) THEN
+ matQ(:MR,J) = 0.
+ ELSE
+ JM1 = J - I2R
+ JP1 = J + I2R
+ matQ(:MR,J) = HALF*(matQ(:MR,J)-matQ(:MR,JM1)-matQ(:MR,JP1))
+ ENDIF
+ CALL TRIX (JR, 0, MR, vecA, vecBB, vecC, vecB, TCOS, &
+ size(TCOS), vecD, vecW)
+ matQ(:MR,J) = matQ(:MR,J) + vecB(:MR)
+ END DO
+ NROD = 1
+ IF (NLAST + I2R <= N) NROD = 0
+ IF (NLASTP /= NLAST) GO TO 188
+ GO TO 197
+ 210 CONTINUE
+ vecW(1) = IPSTOR
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+! June 2004 Version 5.0, Fortran 90 Changes
+!-----------------------------------------------------------------------
+ END SUBROUTINE POSTG2
diff --git a/fish90/src/test.c b/fish90/src/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce96079a380e06ec2d50e09a8035d38df47a13bc
--- /dev/null
+++ b/fish90/src/test.c
@@ -0,0 +1,13 @@
+#include "stdlib.h"
+#include "stdio.h"
+#include "fishpack.h"
+
+
+int main()
+{
+ fish_hstcyl (0.0, 1.0, 256,
+ 1, NULL, NULL,
+ 0.0, 1.0, 256,
+ 1, NULL, NULL,
+ 0.0, 0.0, NULL, 0);
+}
diff --git a/fish90/src/tri3.f90 b/fish90/src/tri3.f90
new file mode 100644
index 0000000000000000000000000000000000000000..48fc20008bf7695426bd1de321dc084f6812a2b6
--- /dev/null
+++ b/fish90/src/tri3.f90
@@ -0,0 +1,122 @@
+ SUBROUTINE TRI3(M, vecA, vecB, vecC, ivecK, vecY1, vecY2, vecY3, TCOS, &
+ ITCOS, vecD, vecW1, vecW2, vecW3)
+ implicit none
+
+ DOUBLE PRECISION, PARAMETER :: ZERO = 0.0D0, HALF = 0.5D0, &
+ ONE = 1.0D0, TWO = 2.0D0, &
+ FOUR = 4.0D0
+
+!-----------------------------------------------
+! D u m m y A r g u m e n t s
+!-----------------------------------------------
+ INTEGER, INTENT(IN) :: M,ITCOS
+ INTEGER, DIMENSION(4),INTENT(IN) :: ivecK
+ DOUBLE PRECISION, DIMENSION(M), INTENT(IN) :: vecA, vecB, vecC
+ DOUBLE PRECISION, DIMENSION(ITCOS), INTENT(IN) :: TCOS
+ DOUBLE PRECISION, DIMENSION(M), INTENT(INOUT) :: vecY1, vecY2, vecY3, &
+ vecD, vecW1, vecW2, vecW3
+!-----------------------------------------------
+! L o c a l V a r i a b l e s
+!-----------------------------------------------
+ INTEGER :: MM1, K1, K2, K3, K4, IF1, IF2, IF3, IF4, K2K3K4, &
+ L1, L2, L3, LINT1, LINT2, LINT3, KINT1, KINT2, KINT3, &
+ N, I, IP
+ DOUBLE PRECISION :: X, Z, XX
+!-----------------------------------------------
+!
+! SUBROUTINE TO SOLVE THREE LINEAR SYSTEMS WHOSE COMMON COEFFICIENT
+! MATRIX IS A RATIONAL FUNCTION IN THE MATRIX GIVEN BY
+!
+! TRIDIAGONAL (...,vecA(I),vecB(I),vecC(I),...)
+!
+ MM1 = M - 1
+ K1 = ivecK(1)
+ K2 = ivecK(2)
+ K3 = ivecK(3)
+ K4 = ivecK(4)
+ IF1 = K1 + 1
+ IF2 = K2 + 1
+ IF3 = K3 + 1
+ IF4 = K4 + 1
+ K2K3K4 = K2 + K3 + K4
+ IF (K2K3K4 /= 0) THEN
+ L1 = IF1/IF2
+ L2 = IF1/IF3
+ L3 = IF1/IF4
+ LINT1 = 1
+ LINT2 = 1
+ LINT3 = 1
+ KINT1 = K1
+ KINT2 = KINT1 + K2
+ KINT3 = KINT2 + K3
+ ELSE
+ write(*,*) 'warning', &
+ 'tri3: l1,l2,l3,kint1,kint2,kint3 uninitialized'
+ stop 'stop in tri3: l1,l2,l3,kint1,kint2,kint3 uninitialized'
+ ENDIF
+ DO N = 1, K1
+ X = TCOS(N)
+ IF (K2K3K4 /= 0) THEN
+ IF (N == L1) THEN
+ vecW1(:M) = vecY1(:M)
+ ENDIF
+ IF (N == L2) THEN
+ vecW2(:M) = vecY2(:M)
+ ENDIF
+ IF (N == L3) THEN
+ vecW3(:M) = vecY3(:M)
+ ENDIF
+ ENDIF
+ Z = 1./(vecB(1)-X)
+ vecD(1) = vecC(1)*Z
+ vecY1(1) = vecY1(1)*Z
+ vecY2(1) = vecY2(1)*Z
+ vecY3(1) = vecY3(1)*Z
+ DO I = 2, M
+ Z = 1./(vecB(I)-X-vecA(I)*vecD(I-1))
+ vecD(I) = vecC(I)*Z
+ vecY1(I) = (vecY1(I)-vecA(I)*vecY1(I-1))*Z
+ vecY2(I) = (vecY2(I)-vecA(I)*vecY2(I-1))*Z
+ vecY3(I) = (vecY3(I)-vecA(I)*vecY3(I-1))*Z
+ END DO
+ DO IP = 1, MM1
+ vecY1(M-IP) = vecY1(M-IP) - vecD(M-IP)*vecY1(M+1-IP)
+ vecY2(M-IP) = vecY2(M-IP) - vecD(M-IP)*vecY2(M+1-IP)
+ vecY3(M-IP) = vecY3(M-IP) - vecD(M-IP)*vecY3(M+1-IP)
+ END DO
+ IF (K2K3K4 == 0) CYCLE
+ IF (N == L1) THEN
+ I = LINT1 + KINT1
+ XX = X - TCOS(I)
+ vecY1(:M) = XX*vecY1(:M) + vecW1(:M)
+ LINT1 = LINT1 + 1
+ L1 = (LINT1*IF1)/IF2
+ ENDIF
+ IF (N == L2) THEN
+ I = LINT2 + KINT2
+ XX = X - TCOS(I)
+ vecY2(:M) = XX*vecY2(:M) + vecW2(:M)
+ LINT2 = LINT2 + 1
+ L2 = (LINT2*IF1)/IF3
+ ENDIF
+ IF (N /= L3) CYCLE
+ I = LINT3 + KINT3
+ XX = X - TCOS(I)
+ vecY3(:M) = XX*vecY3(:M) + vecW3(:M)
+ LINT3 = LINT3 + 1
+ L3 = (LINT3*IF1)/IF4
+ END DO
+ RETURN
+!
+! REVISION HISTORY---
+!
+! SEPTEMBER 1973 VERSION 1
+! APRIL 1976 VERSION 2
+! JANUARY 1978 VERSION 3
+! DECEMBER 1979 VERSION 3.1
+! OCTOBER 1980 CHANGED SEVERAL DIVIDES OF FLOATING INTEGERS
+! TO INTEGER DIVIDES TO ACCOMODATE CRAY-1 ARITHMETIC.
+! FEBRUARY 1985 DOCUMENTATION UPGRADE
+! NOVEMBER 1988 VERSION 3.2, FORTRAN 77 CHANGES
+!-----------------------------------------------------------------------
+ END SUBROUTINE TRI3
diff --git a/include/cdr.h b/include/cdr.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5d22137833b963ca80a9369fd873a84960518fe
--- /dev/null
+++ b/include/cdr.h
@@ -0,0 +1,49 @@
+/** @file cdr.h
+ * @brief Header file for cdr grids. */
+
+#include "cstream.h"
+#include "tree.h"
+
+#ifndef _GRID_H_
+#include "grid.h"
+#endif
+
+#ifndef _RZ_ARRAY_H_
+#include "rz_array.h"
+#endif
+
+#ifndef _TREE_H_
+#include "tree.h"
+#endif
+
+#ifndef _CDR_H_
+typedef struct cdr_grid_t cdr_grid_t;
+
+struct cdr_grid_t {
+ RECT_COORDS;
+ LEAF_FIELDS(cdr_grid_t);
+ int ext_bound;
+
+ /* Pointer to each of the species. And their time derivatives */
+ rz_array_t **dens;
+ rz_array_t **d_dens;
+
+ /* Components and magnitude of the electric field */
+ rz_array_t *er, *ez, *etheta, *eabs;
+ rz_array_t *charge;
+
+ rz_array_t *photo;
+
+ REAL *max_dens;
+ REAL max_charge;
+ REAL max_eabs;
+
+ int contains_edge;
+};
+
+#define SET_DENS_OVERWRITE 1
+#define SET_DENS_ADD 2
+#define SET_DENS_SUB 3
+
+#define _CDR_H_
+#endif
diff --git a/include/configuration.h b/include/configuration.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2ed41ac92c912fc2c0fb9b9473285595a08495a
--- /dev/null
+++ b/include/configuration.h
@@ -0,0 +1,90 @@
+/** @file configuration.h
+ * @brief Function prototypes for configuration functions.
+ */
+/* ----------------------------------------------------------------------------
+ libconfig - A library for processing structured configuration files
+ Copyright (C) 2005-2010 Mark A Lindner
+
+ This file is part of libconfig.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, see
+ .
+ ----------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+#ifndef _CSTREAM_H
+# include "cstream.h"
+#endif
+
+#ifndef _PARAMETERS_H_
+# include "parameters.h"
+#endif
+
+#ifndef _SPECIES_H
+# include "species.h"
+#endif
+
+#ifndef _REACTION_H
+# include "reaction.h"
+#endif
+
+#define COMPARE_LIMIT 100
+#define NO_PARAMETERS 100
+
+typedef struct array_name {
+ const char *name;
+} ARRAY_NAME ;
+
+ARRAY_NAME parameter_names[NO_PARAMETERS];
+
+bool
+change_cfg_integer(const char* name,const char *type,const char *comment,
+ const char *sstring, int *par,int value,int count,
+ bool *change, config_setting_t *setting_default,int i);
+bool
+change_cfg_double(const char* name,const char *type,const char *comment,
+ const char *sstring,double *par,double value,int count,
+ bool *change, config_setting_t *setting_default,int i);
+//bool
+//change_cfg_bool(const char* name,const char *type,const char *comment,
+// const char *sstring, bool *par,bool value,int count,
+// bool *change, config_setting_t *setting_default,int i);
+bool
+change_cfg_string(const char *name,const char *type,const char *comment,
+ const char *sstring,char** par,char* value,int count,
+ bool *change, config_setting_t *setting_default,int i);
+void
+change_cfg_parameters (const char *name,const char *type,const char *comment,
+ int ii,int ivalue, double dvalue, bool bbool,
+ const char* astring, config_setting_t *setting,
+ int count,bool *change);
+bool
+read_parameter(config_setting_t *setting1,config_setting_t *setting2,
+ int ii,int count,bool *change);
+
+bool
+read_specie(config_setting_t *setting,int ii,species_t *temp_s);
+
+bool
+read_seed(config_setting_t *setting,int ii,seed_t *temp_se);
+
+bool
+read_reaction(config_setting_t *setting,int ii,reaction_t *temp_r);
+
diff --git a/include/cstream.h b/include/cstream.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a27ba27278957b9d0074d879d0611c9326b061b
--- /dev/null
+++ b/include/cstream.h
@@ -0,0 +1,143 @@
+/** @file cstream.h
+ * @brief Global header file
+ */
+
+#ifndef _CSTREAM_H_
+
+#include "tree.h"
+#include "assert.h"
+#include "stdlib.h"
+
+#ifdef _OPENMP
+# include "omp.h"
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+
+#ifdef DEBUG_LEVEL
+# ifdef _OPENMP
+# define debug(level, ...) if (DEBUG_LEVEL >= level) { \
+ fprintf (stderr,"[%d] %s:%d: ", omp_get_thread_num(), \
+ __FILE__, __LINE__); \
+ fprintf (stderr,__VA_ARGS__); \
+ }
+# else /*_OPENMP*/
+# define debug(level, ...) if (DEBUG_LEVEL >= level) { \
+ fprintf (stderr,"%s:%d: ", __FILE__, __LINE__); \
+ fprintf (stderr,__VA_ARGS__); \
+ }
+# endif
+#else
+# define debug(level, ...)
+# define NDEBUG /* To supress the asserts */
+#endif
+
+#define warning(...) do{ \
+ fprintf (stderr, "%s: Warning: ", invok_name); \
+ fprintf (stderr, ## __VA_ARGS__); \
+ } while(0)
+
+#define fatal(...) do{ \
+ fprintf (stderr, "%s: Fatal error: ", invok_name); \
+ fprintf (stderr, ## __VA_ARGS__); \
+ exit(-1); \
+ } while(0)
+
+/* Useful to debug. */
+#define show_double(VAR_) printf (#VAR_ " = %g\n", VAR_)
+#define show_int(VAR_) printf (#VAR_ " = %d\n", VAR_)
+
+/* Beware of side-effects! */
+#define MYMAX(X_, Y_) ((X_) > (Y_)? (X_): (Y_))
+#define MYMIN(X_, Y_) ((X_) < (Y_)? (X_): (Y_))
+#define MAX_AT_LEVEL(X_, Y_, L_) MYMAX(X_, (Y_) << (L_))
+#define MIN_AT_LEVEL(X_, Y_, L_) MYMIN(X_, (Y_) << (L_))
+#define MAX_AT_LEVEL_WITH_SHIFT(X_, Y_, L_, S_) \
+ MYMAX(X_, ((Y_) << (L_)) + ((L_) > 0? ((S_) << (L_ - 1)): 0))
+#define MIN_AT_LEVEL_WITH_SHIFT(X_, Y_, L_, S_) \
+ MYMIN(X_, ((Y_) << (L_)) + ((L_) > 0? ((S_) << (L_ - 1)): 0))
+
+#define XCHG(X1_, X2_) do { \
+ typeof(X1_) TMP_; \
+ TMP_ = X1_; \
+ X1_ = X2_; \
+ X2_ = TMP_; \
+ } while(0)
+
+
+#define SQ(X_) ((X_) * (X_))
+
+///** @brief Information about each program parameter. */
+//typedef struct param_t param_t;
+//struct param_t {
+ //char *name;
+ //char *desc;
+ //char *type;
+ //void *value;
+//};
+
+/** @brief These are the types for the global parameters. */
+typedef char* string;
+typedef double* doublep;
+
+//#ifdef ALLOC_PARAMS
+//# define decl_param(TYPE, NAME, DESC, DEFAULT) \
+ //TYPE NAME = DEFAULT; \
+ //param_t NAME ## _st = { \
+ //#NAME, \
+ //DESC, \
+ //#TYPE, \
+ //(void *) &NAME};
+//# define decl_deprec_param(TYPE, NAME, DESC, DEFAULT) \
+ //TYPE NAME; \
+ //param_t NAME ## _st = { \
+ //#NAME, \
+ //DESC, \
+ //"deprecated", \
+ //NULL};
+//#else
+//# define decl_param(TYPE, NAME, DESC, DEFAULT) \
+ //extern TYPE NAME; \
+ //extern param_t NAME ## _st;
+//# define decl_deprec_param(TYPE, NAME, DESC, DEFAULT) \
+ //decl_param(TYPE, NAME, DESC, DEFAULT)
+//#endif
+
+typedef double REAL;
+
+extern double *dr, *dz, dtheta;
+/*!< The grid sizes */
+extern double *w2k, *wk;
+/*!< See cstream.c */
+
+#define decl_field_comp(_DIR) \
+ double (*ext_e_ ## _DIR) (double r, double z, double theta)
+/*!< The three components of the external field: ext_e_r, ext_e_z and
+ * ext_e_theta. */
+
+extern decl_field_comp(r);
+extern decl_field_comp(z);
+extern decl_field_comp(theta);
+
+extern char *invok_name;
+
+extern const double twopi;
+extern const double invfourpi;
+extern const double invpi32;
+
+/**********
+ * misc.c *
+ **********/
+void *xmalloc (size_t size);
+void *xrealloc (void *ptr, size_t size);
+void *xcalloc (size_t count, size_t size);
+
+#define _CSTREAM_H_
+#endif
diff --git a/include/grid.h b/include/grid.h
new file mode 100644
index 0000000000000000000000000000000000000000..576499613c6134134a6eb13f58227bb4a901c547
--- /dev/null
+++ b/include/grid.h
@@ -0,0 +1,159 @@
+/** @file grid.h
+ * @brief Definitions for working with general grids.
+ */
+#ifndef _GRID_H_
+
+#ifndef _TREE_H_
+# include "tree.h"
+#endif
+
+#define RECT_COORDS int r0, r1, z0, z1, ntheta
+/*!< Coordinate names for the grids */
+
+#define BND_AT_R 0
+#define BND_AT_Z 2
+#define BND_MIN 0
+#define BND_MAX 1
+
+#define BND_LEFT (BND_AT_R | BND_MIN)
+#define BND_RIGHT (BND_AT_R | BND_MAX)
+#define BND_BOTTOM (BND_AT_Z | BND_MIN)
+#define BND_TOP (BND_AT_Z | BND_MAX)
+
+#define BND_MASK(B_) (1 << (B_))
+#define BND_NONE 0
+#define BND_MASK_LEFT BND_MASK(BND_LEFT)
+#define BND_MASK_RIGHT BND_MASK(BND_RIGHT)
+#define BND_MASK_BOTTOM BND_MASK(BND_BOTTOM)
+#define BND_MASK_TOP BND_MASK(BND_TOP)
+#define BND_MASK_ALL (BND_MASK_LEFT | BND_MASK_RIGHT\
+ | BND_MASK_BOTTOM | BND_MASK_TOP)
+
+#define GRID_INSIDE (1 << (BND_TOP + 1))
+
+/* Locations of the cell centers. */
+#define r_at(r_, level_) (((double) (r_) + 0.5) * dr[level_])
+#define z_at(z_, level_) (((double) (z_) + 0.5) * dz[level_])
+#define theta_at(theta_) ((double) (theta_) * dtheta)
+
+/* Locations of the electric field. */
+#define er_r_at(i_, level_) ((i_ + 1) * dr[level_])
+#define er_z_at(j_, level_) (((double) (j_) + 0.5) * dz[level_])
+#define ez_r_at(i_, level_) (((double) (i_) + 0.5) * dr[level_])
+#define ez_z_at(j_, level_) ((j_ + 1) * dz[level_])
+#define etheta_theta_at(i_) (((double) (i_) + 0.5) * dtheta)
+
+
+/** We can produce easily a true 2d code by replacing r when it appears
+ * due to the cylindrical coordinates by this macros. This has a rather
+ * large performance penalty, so it is better to do that in compile time
+ */
+
+/* Locations of the electric field. */
+#ifdef TRUE2D
+# define cyl_q(X_) 1
+# define cyl_er_r_at(i_, level_) 1
+# define cyl_r_at(r_, level_) 1
+#else
+# define cyl_q(X_) (X_)
+# define cyl_er_r_at(i_, level_) er_r_at(i_, level_)
+# define cyl_r_at(r_, level_) r_at(r_, level_)
+#endif
+
+/* These are shortcuts to make the iteration over grid cells easier.
+ * Note that it is important that the inner loop has the smallest
+ * stride to minimize the cache faults.
+ */
+#define iter_grid_z(grid_, iz_) \
+ for(iz_ = grid_->z0; iz_ < grid_->z1; iz_++)
+
+#define iter_grid_r(grid_, ir_) \
+ for(ir_ = grid_->r0; ir_ < grid_->r1; ir_++)
+
+#define iter_grid_theta(grid_, it_) \
+ for(it_ = 0; it_ < grid_->ntheta; it_++)
+
+#define iter_grid(grid_, ir_, iz_) \
+ iter_grid_z(grid_, iz_) \
+ iter_grid_r(grid_, ir_)
+
+#define iter_grid_3d(grid_, ir_, iz_, it_) \
+ iter_grid_theta(grid_, it_) \
+ iter_grid_z(grid_, iz_) \
+ iter_grid_r(grid_, ir_)
+
+
+/* Functions to iterate over the grids _including_ 1 extra boundary */
+#define iter_grid_z_1(grid_, iz_) \
+ for(iz_ = grid_->z0 - 1; iz_ < grid_->z1 + 1; iz_++)
+
+#define iter_grid_r_1(grid_, ir_) \
+ for(ir_ = grid_->r0 - 1; ir_ < grid_->r1 + 1; ir_++)
+
+#define iter_grid_1(grid_, ir_, iz_) \
+ iter_grid_z_1(grid_, iz_) \
+ iter_grid_r(grid_, ir_)
+
+#define iter_grid_3d_1(grid_, ir_, iz_, it_) \
+ iter_grid_theta(grid_, it_) \
+ iter_grid_z_1(grid_, iz_) \
+ iter_grid_r_1(grid_, ir_)
+
+
+/* These include n extra cells in the boundary. We avoid that when
+ * ntheta == 1 because we are in the 2D case and there are no boundaries
+ * in theta*/
+#define iter_grid_theta_n(grid_, it_, n_) \
+ for(it_ = (grid_->ntheta == 1? 0: -n_); it_ < grid_->ntheta \
+ + (grid_->ntheta == 1? 0: n_); it_++)
+
+#define iter_grid_z_n(grid_, iz_, n_) \
+ for(iz_ = grid_->z0 - n_; iz_ < grid_->z1 + n_; iz_++)
+
+#define iter_grid_r_n(grid_, ir_, n_) \
+ for(ir_ = grid_->r0 - n_; ir_ < grid_->r1 + n_; ir_++)
+
+#define iter_grid_n(grid_, ir_, iz_, n_) \
+ iter_grid_z_n(grid_, iz_, n_) \
+ iter_grid_r_n(grid_, ir_, n_)
+
+#define iter_grid_3d_n(grid_, ir_, iz_, it_, n_) \
+ iter_grid_theta_n(grid_, it_, n_) \
+ iter_grid_z_n(grid_, iz_, n_) \
+ iter_grid_r_n(grid_, ir_, n_)
+
+
+/* Iter through the parent indices that fill one grid. */
+#define iter_grid_parent(grid_, ir_, iz_) \
+ for(ir_ = (grid_->r0 >> 1) + (grid_->r0 % 2); \
+ ir_ < (grid_->r1 >> 1); ir_++) \
+ for(iz_ = (grid_->z0 >> 1) + (grid_->z0 % 2); \
+ iz_ < (grid_->z1 >> 1); iz_++)
+
+
+/** @brief The cdr grids and poisson grids types are cdr_grid_t and
+ * pois_grid_t, defined in cdr.h and poisson.h.
+ *
+ * This structure contains the common parts of both structures and
+ * thus can be used in general routines that accept any kind of grid.
+ * The C standard promises that we can du this.
+ */
+typedef struct grid_t grid_t;
+struct grid_t {
+ RECT_COORDS;
+ LEAF_FIELDS(grid_t);
+ /* ext_bound indicates which boundaries are external boundaries.
+ e.g. ext_bound & BND_LEFT_TOP tells us whether the left-top boundary
+ is an external one. */
+ int ext_bound;
+};
+
+/** @brief To ease typing, you can write e.g.
+ * printf ("Solving grid (" grid_printf_str ")\n", grid_printf_args(grid));
+ */
+#define grid_printf_str "{r0 = %d, z0 = %d, r1 = %d, z1 = %d, level = %d}"
+#define grid_printf_args(G_) (G_)->r0, (G_)->z0, (G_)->r1, (G_)->z1, \
+ (G_)->level
+
+#define _GRID_H_
+#endif
diff --git a/include/interpol2.h b/include/interpol2.h
new file mode 100644
index 0000000000000000000000000000000000000000..283035d293a23846a75f0f69ff8506c64143502f
--- /dev/null
+++ b/include/interpol2.h
@@ -0,0 +1,65 @@
+/** @file interpol2.h
+ * @brief Header file for interpol2.c.
+ */
+#ifndef _INTERPOL2_H_
+
+/* We will certainly never use a 16th order scheme,
+ * but in case we do, remember to change it here
+ */
+#define MAX_ORDER 16
+
+#define MAX_INTERPOL_METHODS 9
+
+typedef struct interpol_t interpol_t;
+typedef struct interpol_method_t interpol_method_t;
+
+struct interpol_t
+{
+ double *coeffs;
+ double *stencil;
+
+ /* The separation between stencil points. */
+ double Lr, Lz;
+
+ /* The interpolation method to use. */
+ interpol_method_t *method;
+
+ /* Origin of the interpolation polynomial, which is thus written in
+ powers of (r - r0) and (z - z0). */
+ double r0, z0;
+};
+
+struct interpol_method_t
+{
+ double *matrix;
+
+ /* p is the order of the polynomial plus one.
+ * q is the number of stencil points in one direction (the total
+ * number is, of course, q^2. */
+ int p, q;
+
+ /* Location of the origin with respect to the stencil in units of L. */
+ int ir0, iz0;
+
+ int masses;
+
+ void (*set_coeffs) (interpol_t *this);
+ double (*apply) (interpol_t *this, double r, double z);
+};
+
+extern interpol_method_t interpol_zero;
+extern interpol_method_t interpol_wackers;
+extern interpol_method_t interpol_luque;
+extern interpol_method_t interpol_quadratic;
+extern interpol_method_t interpol_bilin;
+extern interpol_method_t interpol_quadlog;
+extern interpol_method_t interpol_zero_masses;
+extern interpol_method_t interpol_wackers_masses;
+extern interpol_method_t interpol_luque_masses;
+extern interpol_method_t interpol_quadratic_masses;
+extern interpol_method_t interpol_bilin_masses;
+
+extern interpol_method_t *interpol_methods_index[MAX_INTERPOL_METHODS];
+
+#define _INTERPOL2_H_
+#endif
diff --git a/include/libconfig.h b/include/libconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..77962046fdfb452055f95cfaf2231bac93bd8ab7
--- /dev/null
+++ b/include/libconfig.h
@@ -0,0 +1,325 @@
+/** @file libconfig.h
+ * @brief Header file of library libconfig. */
+
+
+/* ----------------------------------------------------------------------------
+ libconfig - A library for processing structured configuration files
+ Copyright (C) 2005-2010 Mark A Lindner
+
+ This file is part of libconfig.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, see
+ .
+ ----------------------------------------------------------------------------
+*/
+
+#ifndef __libconfig_h
+#define __libconfig_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#if defined(LIBCONFIG_STATIC)
+#define LIBCONFIG_API
+#elif defined(LIBCONFIG_EXPORTS)
+#define LIBCONFIG_API __declspec(dllexport)
+#else /* ! LIBCONFIG_EXPORTS */
+#define LIBCONFIG_API __declspec(dllimport)
+#endif /* LIBCONFIG_STATIC */
+#else /* ! WIN32 */
+#define LIBCONFIG_API
+#endif /* WIN32 */
+
+#define LIBCONFIG_VER_MAJOR 1
+#define LIBCONFIG_VER_MINOR 4
+#define LIBCONFIG_VER_REVISION 9
+
+#include
+
+#define CONFIG_TYPE_NONE 0
+#define CONFIG_TYPE_GROUP 1
+#define CONFIG_TYPE_INT 2
+#define CONFIG_TYPE_INT64 3
+#define CONFIG_TYPE_FLOAT 4
+#define CONFIG_TYPE_STRING 5
+#define CONFIG_TYPE_BOOL 6
+#define CONFIG_TYPE_ARRAY 7
+#define CONFIG_TYPE_LIST 8
+
+#define CONFIG_FORMAT_DEFAULT 0
+#define CONFIG_FORMAT_HEX 1
+
+#define CONFIG_OPTION_AUTOCONVERT 0x01
+
+#define CONFIG_TRUE (1)
+#define CONFIG_FALSE (0)
+
+typedef union config_value_t
+{
+ int ival;
+ long long llval;
+ double fval;
+ char *sval;
+ struct config_list_t *list;
+} config_value_t;
+
+typedef struct config_setting_t
+{
+ char *name;
+ short type;
+ short format;
+ config_value_t value;
+ struct config_setting_t *parent;
+ struct config_t *config;
+ void *hook;
+ unsigned int line;
+ const char *file;
+} config_setting_t;
+
+typedef enum
+{
+ CONFIG_ERR_NONE = 0,
+ CONFIG_ERR_FILE_IO = 1,
+ CONFIG_ERR_PARSE = 2
+} config_error_t;
+
+typedef struct config_list_t
+{
+ unsigned int length;
+ config_setting_t **elements;
+} config_list_t;
+
+typedef struct config_t
+{
+ config_setting_t *root;
+ void (*destructor)(void *);
+ unsigned short flags;
+ unsigned short tab_width;
+ short default_format;
+ const char *include_dir;
+ const char *error_text;
+ const char *error_file;
+ int error_line;
+ config_error_t error_type;
+ const char **filenames;
+ unsigned int num_filenames;
+} config_t;
+
+extern LIBCONFIG_API int config_read(config_t *config, FILE *stream);
+extern LIBCONFIG_API void config_write(const config_t *config, FILE *stream);
+
+extern LIBCONFIG_API void config_set_default_format(config_t *config,
+ short format);
+
+extern LIBCONFIG_API void config_set_auto_convert(config_t *config, int flag);
+extern LIBCONFIG_API int config_get_auto_convert(const config_t *config);
+
+extern LIBCONFIG_API int config_read_string(config_t *config, const char *str);
+
+extern LIBCONFIG_API int config_read_file(config_t *config,
+ const char *filename);
+extern LIBCONFIG_API int config_write_file(config_t *config,
+ const char *filename);
+
+extern LIBCONFIG_API void config_set_destructor(config_t *config,
+ void (*destructor)(void *));
+extern LIBCONFIG_API void config_set_include_dir(config_t *config,
+ const char *include_dir);
+
+extern LIBCONFIG_API void config_init(config_t *config);
+extern LIBCONFIG_API void config_destroy(config_t *config);
+
+extern LIBCONFIG_API int config_setting_get_int(
+ const config_setting_t *setting);
+extern LIBCONFIG_API long long config_setting_get_int64(
+ const config_setting_t *setting);
+extern LIBCONFIG_API double config_setting_get_float(
+ const config_setting_t *setting);
+extern LIBCONFIG_API int config_setting_get_bool(
+ const config_setting_t *setting);
+extern LIBCONFIG_API const char *config_setting_get_string(
+ const config_setting_t *setting);
+
+extern LIBCONFIG_API int config_setting_lookup_int(
+ const config_setting_t *setting, const char *name, int *value);
+extern LIBCONFIG_API int config_setting_lookup_int64(
+ const config_setting_t *setting, const char *name, long long *value);
+extern LIBCONFIG_API int config_setting_lookup_float(
+ const config_setting_t *setting, const char *name, double *value);
+extern LIBCONFIG_API int config_setting_lookup_bool(
+ const config_setting_t *setting, const char *name, int *value);
+extern LIBCONFIG_API int config_setting_lookup_string(
+ const config_setting_t *setting, const char *name, const char **value);
+
+extern LIBCONFIG_API int config_setting_set_int(config_setting_t *setting,
+ int value);
+extern LIBCONFIG_API int config_setting_set_int64(config_setting_t *setting,
+ long long value);
+extern LIBCONFIG_API int config_setting_set_float(config_setting_t *setting,
+ double value);
+extern LIBCONFIG_API int config_setting_set_bool(config_setting_t *setting,
+ int value);
+extern LIBCONFIG_API int config_setting_set_string(config_setting_t *setting,
+ const char *value);
+
+extern LIBCONFIG_API int config_setting_set_format(config_setting_t *setting,
+ short format);
+extern LIBCONFIG_API short config_setting_get_format(
+ const config_setting_t *setting);
+
+extern LIBCONFIG_API int config_setting_get_int_elem(
+ const config_setting_t *setting, int idx);
+extern LIBCONFIG_API long long config_setting_get_int64_elem(
+ const config_setting_t *setting, int idx);
+extern LIBCONFIG_API double config_setting_get_float_elem(
+ const config_setting_t *setting, int idx);
+extern LIBCONFIG_API int config_setting_get_bool_elem(
+ const config_setting_t *setting, int idx);
+extern LIBCONFIG_API const char *config_setting_get_string_elem(
+ const config_setting_t *setting, int idx);
+
+extern LIBCONFIG_API config_setting_t *config_setting_set_int_elem(
+ config_setting_t *setting, int idx, int value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_int64_elem(
+ config_setting_t *setting, int idx, long long value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_float_elem(
+ config_setting_t *setting, int idx, double value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_bool_elem(
+ config_setting_t *setting, int idx, int value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_string_elem(
+ config_setting_t *setting, int idx, const char *value);
+
+#define /* const char * */ config_get_include_dir(/* const config_t * */ C) \
+ ((C)->include_dir)
+
+#define /* int */ config_setting_type(/* const config_setting_t * */ S) \
+ ((S)->type)
+
+#define /* int */ config_setting_is_group(/* const config_setting_t * */ S) \
+ ((S)->type == CONFIG_TYPE_GROUP)
+#define /* int */ config_setting_is_array(/* const config_setting_t * */ S) \
+ ((S)->type == CONFIG_TYPE_ARRAY)
+#define /* int */ config_setting_is_list(/* const config_setting_t * */ S) \
+ ((S)->type == CONFIG_TYPE_LIST)
+
+#define /* int */ config_setting_is_aggregate( \
+ /* const config_setting_t * */ S) \
+ (((S)->type == CONFIG_TYPE_GROUP) || ((S)->type == CONFIG_TYPE_LIST) \
+ || ((S)->type == CONFIG_TYPE_ARRAY))
+
+#define /* int */ config_setting_is_number(/* const config_setting_t * */ S) \
+ (((S)->type == CONFIG_TYPE_INT) \
+ || ((S)->type == CONFIG_TYPE_INT64) \
+ || ((S)->type == CONFIG_TYPE_FLOAT))
+
+#define /* int */ config_setting_is_scalar(/* const config_setting_t * */ S) \
+ (((S)->type == CONFIG_TYPE_BOOL) || ((S)->type == CONFIG_TYPE_STRING) \
+ || config_setting_is_number(S))
+
+#define /* const char * */ config_setting_name( \
+ /* const config_setting_t * */ S) \
+ ((S)->name)
+
+#define /* config_setting_t * */ config_setting_parent( \
+ /* const config_setting_t * */ S) \
+ ((S)->parent)
+
+#define /* int */ config_setting_is_root( \
+ /* const config_setting_t * */ S) \
+ ((S)->parent ? CONFIG_FALSE : CONFIG_TRUE)
+
+extern LIBCONFIG_API int config_setting_index(const config_setting_t *setting);
+
+extern LIBCONFIG_API int config_setting_length(
+ const config_setting_t *setting);
+extern LIBCONFIG_API config_setting_t *config_setting_get_elem(
+ const config_setting_t *setting, unsigned int idx);
+
+extern LIBCONFIG_API config_setting_t *config_setting_get_member(
+ const config_setting_t *setting, const char *name);
+
+extern LIBCONFIG_API config_setting_t *config_setting_add(
+ config_setting_t *parent, const char *name, int type);
+extern LIBCONFIG_API int config_setting_remove(config_setting_t *parent,
+ const char *name);
+extern LIBCONFIG_API int config_setting_remove_elem(config_setting_t *parent,
+ unsigned int idx);
+extern LIBCONFIG_API void config_setting_set_hook(config_setting_t *setting,
+ void *hook);
+
+#define config_setting_get_hook(S) ((S)->hook)
+
+extern LIBCONFIG_API config_setting_t *config_lookup(const config_t *config,
+ const char *path);
+extern LIBCONFIG_API config_setting_t *config_lookup_from(
+ config_setting_t *setting, const char *path);
+
+extern LIBCONFIG_API int config_lookup_int(const config_t *config,
+ const char *path, int *value);
+extern LIBCONFIG_API int config_lookup_int64(const config_t *config,
+ const char *path,
+ long long *value);
+extern LIBCONFIG_API int config_lookup_float(const config_t *config,
+ const char *path, double *value);
+extern LIBCONFIG_API int config_lookup_bool(const config_t *config,
+ const char *path, int *value);
+extern LIBCONFIG_API int config_lookup_string(const config_t *config,
+ const char *path,
+ const char **value);
+
+#define /* config_setting_t * */ config_root_setting( \
+ /* const config_t * */ C) \
+ ((C)->root)
+
+#define /* void */ config_set_default_format(/* config_t * */ C, \
+ /* short */ F) \
+ (C)->default_format = (F)
+
+#define /* short */ config_get_default_format(/* config_t * */ C) \
+ ((C)->default_format)
+
+#define /* void */ config_set_tab_width(/* config_t * */ C, \
+ /* unsigned short */ W) \
+ (C)->tab_width = ((W) & 0x0F)
+
+#define /* unsigned char */ config_get_tab_width(/* const config_t * */ C) \
+ ((C)->tab_width)
+
+#define /* unsigned short */ config_setting_source_line( \
+ /* const config_setting_t * */ S) \
+ ((S)->line)
+
+#define /* const char */ config_setting_source_file( \
+ /* const config_setting_t * */ S) \
+ ((S)->file)
+
+#define /* const char * */ config_error_text(/* const config_t * */ C) \
+ ((C)->error_text)
+
+#define /* const char * */ config_error_file(/* const config_t * */ C) \
+ ((C)->error_file)
+
+#define /* int */ config_error_line(/* const config_t * */ C) \
+ ((C)->error_line)
+
+#define /* config_error_t */ config_error_type(/* const config_t * */ C) \
+ ((C)->error_type)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __libconfig_h */
diff --git a/include/mapper.h b/include/mapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4fb31819e225f0dbcd65df45818fb3c9de84b84
--- /dev/null
+++ b/include/mapper.h
@@ -0,0 +1,92 @@
+/** @file mapper.h
+ * @brief Definitions for mapper objects.
+ *
+ * A mapper objects defines how and what to map between two grid families.
+ * For example, a mapper object can be used to map the charge from
+ * a @a cdr grid to a @a Poisson grid, or to map the @a potential of a Poisson
+ * grid into one of the components of the @a electric field in a @a cdr grid.
+ * For that, a mapper object has to implement some methods that tell us
+ * how to map things in the cases\n
+ * a) the source grid is coarser than the target grid (interpolation),\n
+ * b) the source and the target are at the same level (copy),\n
+ * c) the target grid is coarser (coarsening).
+ */
+
+#ifndef _MAPPER_H_
+
+typedef struct mapper_t mapper_t;
+
+#ifndef _INTERPOL2_H_
+# include "interpol2.h"
+#endif
+
+#define _coarsen_params_ (mapper_t *mapper, grid_t *source, grid_t *target, \
+ int ir, int iz, int itheta)
+#define _copy_params_ (mapper_t *mapper, grid_t *source, grid_t *target, \
+ int ir, int iz, int itheta)
+#define _interpol_set_params_ (mapper_t *mapper, grid_t *source, \
+ interpol_t *interpol, int ir, \
+ int iz, int itheta)
+#define _interpol_params_ (mapper_t *mapper, grid_t *source, grid_t *target, \
+ interpol_t *interpol, int ir, int iz, int itheta)
+
+
+struct mapper_t {
+ interpol_method_t *interpol_method;
+
+ void (*coarsen) _coarsen_params_;
+ void (*copy) _copy_params_;
+ /* may return false if we are outside the source grid. */
+ int (*interpol_set) _interpol_set_params_;
+
+ void (*interpol) _interpol_params_;
+
+ /* This is used for the interpolation of electric fields and indicates
+ * the staggering of the cells. When we call the interpolator to set
+ * the stencil at coordinates pr, pz, the fine-grid cells whose value will
+ * later be calculated ir, iz with
+ * pr << level_diff + shift_r << (level_diff - 1) <= ir
+ * < pr << level_diff + shift_r << (level_diff - 1)
+ *
+ * (and the equivalent for iz).
+ * Hence note that for interpolation in not-staggered grids,
+ * (i.e. charge, densities, ...)
+ * shift_r = shift_z = 0.
+ */
+ int shift_r, shift_z;
+
+ /* We provide this extra member to allow the easy creation of different
+ * mappers that share the same functions but have a slightly different
+ * behaviour. In particular this is used in cdr.c to define
+ * different interpolators for each species. In that case, extra is the
+ * species index.
+ */
+ int extra;
+};
+
+
+/** Usually, we will define functions called xxxx_coarsen, xxxx_copy, etc
+ to implement the above interface. We define these macros to facilitate
+ the declaration of such functions. */
+#define decl_mapper_funcs(_VAR) \
+ void _VAR ## _coarsen _coarsen_params_; \
+ void _VAR ## _copy _copy_params_; \
+ int _VAR ## _interpol_set _interpol_set_params_; \
+ void _VAR ## _interpol _interpol_params_
+
+/** Useful to init a staggered mapper object */
+#define mk_mapper_staggered(_C, _INTERPOL_METHOD, _SHIFT_R, _SHIFT_Z) \
+ {_INTERPOL_METHOD, _C ## _coarsen, _C ## _copy, \
+ _C ## _interpol_set, _C ##_interpol, _SHIFT_R, _SHIFT_Z, 0}
+
+/** Useful to init a mapper object */
+#define mk_mapper(_C, _INTERPOL_METHOD) \
+ mk_mapper_staggered (_C, _INTERPOL_METHOD, 0, 0)
+
+/** Mappers that only copy or interpolate. */
+#define mk_mapper_down(_C, _INTERPOL_METHOD) \
+ {_INTERPOL_METHOD, NULL, _C ## _copy, \
+ _C ## _interpol_set, _C ##_interpol, 0, 0, 0}
+
+#define _MAPPER_H_
+#endif
diff --git a/include/parameters.h b/include/parameters.h
new file mode 100644
index 0000000000000000000000000000000000000000..f90741aba7dc3e0f56d081a0fe70505f474413fd
--- /dev/null
+++ b/include/parameters.h
@@ -0,0 +1,64 @@
+/** @file parameters.h
+ * @brief The declarations of all global parameters, i.e. those
+ * that the user should be able to set.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifndef _CSTREAM_H_
+# include "cstream.h"
+#endif
+
+#ifndef _RZ_ARRAY_H_
+# include "rz_array.h"
+#endif
+
+#ifndef _PARAMETERS_H_
+
+/** @brief These are the global parameters. */
+char* prog_id;
+char* output_dir;
+char* kin_input;
+char* load_file;
+char* photoionization_file;
+
+int cdr_bnd_bottom,cdr_bnd_right,cdr_bnd_top,
+ cdr_brick_dr,cdr_brick_dz,cdr_max_level,cdr_interp_bnd,cdr_interp_in,
+ extra_photo_levels,extra_pois_levels,extra_photo_levels_2,
+ gridpoints_r,gridpoints_z,
+ has_photoionization,
+ max_disk_space,max_disk_space_mb,max_levels,max_ntheta,
+ perturb_max_k,photo_bnd_bottom,photo_bnd_bottom_2,
+ photo_bnd_right,photo_bnd_right_2,
+ photo_bnd_top,photo_bnd_top_2,photo_bnd_top_2_st,
+ photo_max_level,photo_max_level_2,
+ pois_bnd_bottom,pois_bnd_top,pois_bnd_right,
+ pois_inhom,pois_inhom_reflections,pois_max_level,
+ cdr_output_margin,pois_output_margin,
+ restart,ref_level_eabs,spec_total,sprite_module,sprite_sign;
+
+double attachment_rate,attachment_E0,
+ attempt_dt,diffusion_coeff,
+ background_ionization,background_increase_length,
+ constant_source,dens_decay_len,
+ end_t,E0_x,E0_y,E0_z,L_r,L_z,
+ needle_length,needle_radius,nu_a,nu_d,nu_f,nu_rt,
+ off_time,output_dt,
+ perturb_epsilon,
+ photo_max_error,photo_max_error_2,
+ pois_inhom_fixed_q,pois_max_error,
+ ref_threshold_charge,ref_threshold_dens,ref_threshold_eabs,
+ ref_threshold_edge,
+ rise_time,start_t,
+ seed_sigma_x,seed_sigma_y,seed_sigma_z,seed_N,
+ sprite_dens_0,sprite_dens_q,
+ warn_min_timestep;
+int pois_output;
+
+#define _PARAMETERS_H_
+#endif
diff --git a/include/photo.h b/include/photo.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7dbb90756e28733c9e93565db120c40ec541c2a
--- /dev/null
+++ b/include/photo.h
@@ -0,0 +1,24 @@
+/** @file photo.h
+ * @brief Auxiliary header file for photo.c.
+ */
+#ifndef _PHOTO_H_
+
+typedef struct photo_term_t photo_term_t;
+
+struct photo_term_t
+{
+ double A;
+ double lambda;
+
+ /* We store the photoionization terms in a linked list. */
+ photo_term_t *next;
+};
+
+/* Photoionization terms. */
+extern photo_term_t *photo_terms;
+
+#define photo_printf_str "{A = %g, lambda = %g}"
+#define photo_printf_args(_T) (_T)->A, (_T)->lambda
+
+#define _PHOTO_H_
+#endif
diff --git a/include/poisson.h b/include/poisson.h
new file mode 100644
index 0000000000000000000000000000000000000000..f19c2ac75e24d475d55b4491034625ead869b79e
--- /dev/null
+++ b/include/poisson.h
@@ -0,0 +1,76 @@
+/** @file poisson.h
+ * @brief Structures and functions for the Poisson solver
+ */
+
+#ifndef _POISSON_H_
+
+#include "cstream.h"
+#include "rz_array.h"
+
+#ifndef _GRID_H_
+#include "grid.h"
+#endif
+
+typedef struct pois_grid_t pois_grid_t;
+
+struct pois_grid_t {
+ RECT_COORDS;
+ LEAF_FIELDS(pois_grid_t);
+ int ext_bound;
+
+ rz_array_t *phi;
+ rz_array_t *charge;
+ rz_array_t *error;
+};
+
+/*!< With this structure we define a "problem" for the Poisson/Helmholtz solver.
+ * Thus we differentiate between the electrostatic (Poisson) or the
+ * photo-ionization (Helmholtz) uses.
+ */
+typedef struct pois_problem_t pois_problem_t;
+
+struct pois_problem_t {
+ int max_level;
+ int extra_levels;
+ double max_error;
+
+ int bnd_right;
+ int bnd_top;
+ int bnd_bottom;
+};
+
+typedef struct pois_boundaries_t {
+ REAL *left, *right, *top, *bottom;
+ int r, z;
+} pois_boundaries_t;
+
+/*!< Note that the electric fields are computed here as the derivatives
+ * of \f$\phi\f$, and not _minus_ the derivatives.
+ *
+ * This is because our \f$\phi\f$ is not actually the electrostatic potential
+ * in its standard definition but its opposite. This simplifies the computations
+ * since we can use the charge as the source of the Poisson equation.
+ */
+#define UNCHECK_ER_RZ(grid_, ir_, iz_) \
+ (((RZ(grid_->phi, (ir_) + 1, iz_) - RZ(grid_->phi, ir_, iz_)) \
+ / dr[grid_->level]))
+
+#define UNCHECK_EZ_RZ(grid_, ir_, iz_) \
+ (((RZ(grid_->phi, ir_, (iz_) + 1) - RZ(grid_->phi, ir_, iz_)) \
+ / dz[grid_->level]))
+
+/*!< The easiest way (and not too performance costly) is to check the
+ * boundaries where the field can be calculated.
+ *
+ * Note that, if everything is OK, the 0 there that we set should never be
+ * used again (and hence any number would be ok (use NaN for debugging) */
+#define ER_RZ(grid_, ir_, iz_) \
+ (((ir_) < ((grid_)->r1 + 1) && ((ir_) > ((grid_)->r0 - 2)))? \
+ UNCHECK_ER_RZ(grid_, ir_, iz_): 0)
+
+#define EZ_RZ(grid_, ir_, iz_) \
+ (((iz_) < ((grid_)->z1 + 1) && ((iz_) > ((grid_)->z0 - 2)))? \
+ UNCHECK_EZ_RZ(grid_, ir_, iz_): 0)
+
+#define _POISSON_H_
+#endif
diff --git a/include/proto.h b/include/proto.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ed54ad968fd3c9aa610ae55264bc39c51ac64f7
--- /dev/null
+++ b/include/proto.h
@@ -0,0 +1,263 @@
+/** @file proto.h
+ * @brief Function prototypes for exported functions.
+ */
+
+#ifndef _RZ_ARRAY_H_
+# include "rz_array.h"
+#endif
+
+/* rz_array.c */
+rz_array_t *rz_new_3d_a (int r0, int z0, int r1, int z1, int ntheta);
+rz_array_t *rz_guest (rz_array_t *host, int r0, int z0, int r1, int z1);
+void rz_set_zero (rz_array_t *array);
+void rz_set_periodic (rz_array_t *array);
+void rz_copy_bnd (rz_array_t *from, rz_array_t *to,
+ int sign, REAL *start_from, REAL *start_to,
+ int dim0, int inout_from, int inout_to,
+ int dim1, int dim1_0, int dim1_1,
+ int dim2, int dim2_0, int dim2_1);
+void rz_set_bnd (rz_array_t *array, int sign, REAL *start, int dim0, int inout,
+ int dim1, int dim1_from, int dim1_to,
+ int dim2, int dim2_from, int dim2_to);
+void rz_free (rz_array_t *array);
+void rz_copy (rz_array_t *fro, int rfro, int zfro,
+ rz_array_t *to, int rto, int zto,
+ int rn, int zn);
+void rz_copy_modes (rz_array_t *fro, int rfro, int zfro,
+ rz_array_t *to, int rto, int zto,
+ int rn, int zn, int nmode_fro, int nmode_to);
+void rz_dump (rz_array_t *rz_array, const char *fname, const char *mode,
+ int r0, int z0, int r1, int z1);
+void rz_dump_3d (rz_array_t *rz_array, const char *fname, const char *mode,
+ int r0, int z0, int r1, int z1, int ntheta);
+void rz_axis_dump (const char *fname, int x0, int x1, double delta);
+
+
+#ifndef _GRID_H_
+# include "grid.h"
+#endif
+
+/* grid.c */
+int grid_max_depth_r (grid_t *grid);
+double grid_rmin_r (grid_t *grid);
+void grid_print_r (grid_t *grid, int indent);
+int grid_contains (grid_t *grid, int i, int j, int check);
+int grid_overlap (grid_t *grid1, grid_t *grid2, int buff1, int buff2,
+ int *left, int *bottom, int *right, int *top,
+ int *level_diff);
+int grid_overlap_with_shifts (grid_t *grid1, grid_t *grid2,
+ int buff1, int buff2,
+ int *left, int *bottom, int *right, int *top,
+ int *level_diff, int shift_r, int shift_z);
+void grid_inherit_ext_bound (grid_t *grid);
+grid_t *grid_finest_containing_r (grid_t *grid, double r, double z);
+int grid_howmany_children (grid_t *grid);
+grid_t *grid_get_child (grid_t *grid, int n);
+
+
+#ifndef _INTERPOL2_H_
+# include "interpol2.h"
+#endif
+
+interpol_t *interpol_new_a (double Lr, double Lz, interpol_method_t *method);
+void interpol_free (interpol_t *this);
+void interpol_set_stencil (interpol_t *this, double r0, double z0, ...);
+void interpol_set_stencil_at (grid_t *grid,
+ interpol_t *this, double r0, double z0,
+ rz_array_t *ar,
+ int ir, int iz, int itheta);
+void interpol_set_coeffs (interpol_t *this);
+double interpol_apply (interpol_t *this, double r, double z);
+
+#ifndef _MAPPER_H_
+# include "mapper.h"
+#endif
+
+void map_grid (mapper_t **mappers, grid_t *source, grid_t *target, int ntheta,
+ int copy, int interpol, int coarsen, int s_buff, int t_buff);
+void map_grid_r (mapper_t **mappers, grid_t *source, grid_t *target,
+ int ntheta, int copy, int interpol, int coarsen,
+ int s_buff, int t_buff);
+void map_trees_r (mapper_t **mappers, grid_t *source, grid_t *target,
+ int ntheta, int copy, int interpol, int coarsen,
+ int s_buff, int t_buff);
+
+#ifndef _CDR_H_
+# include "cdr.h"
+#endif
+
+#ifndef _POISSON_H_
+# include "poisson.h"
+#endif
+
+/* cdr.c */
+void cdr_init (void);
+void cdr_end (void);
+
+cdr_grid_t *cdr_new_3d_a (int r0, int z0, int r1, int z1, int ntheta);
+cdr_grid_t *cdr_like_a (cdr_grid_t *grid);
+cdr_grid_t *cdr_clone_a (cdr_grid_t *grid);
+void cdr_set_periodic (cdr_grid_t *grid);
+void cdr_free (cdr_grid_t *grid);
+void cdr_free_r (cdr_grid_t *grid);
+void cdr_calc_charge (cdr_grid_t *grid);
+void cdr_calc_charge_r (cdr_grid_t *root);
+void cdr_dft_charge_r (cdr_grid_t *grid, int sign);
+cdr_grid_t *cdr_create_coarser_a (cdr_grid_t *grid);
+cdr_grid_t *cdr_add_coarser_grids_a (cdr_grid_t *prev_root, int n);
+void cdr_free_coarser_grids (cdr_grid_t *prev_root, int n);
+void cdr_add_ext_field (cdr_grid_t *grid);
+void cdr_add_ext_field_r (cdr_grid_t *grid);
+void cdr_add_inhom_field_r (cdr_grid_t *cdr, double q);
+void cdr_calc_eabs (cdr_grid_t *grid);
+void cdr_calc_eabs_r (cdr_grid_t *grid);
+void cdr_nonegative (cdr_grid_t *grid);
+void cdr_nonegative_r (cdr_grid_t *grid);
+pois_grid_t **cdr_calc_field_r (cdr_grid_t *grid, int return_pois);
+void cdr_set_ext_bnd (cdr_grid_t *grid);
+void cdr_set_ext_bnd_r (cdr_grid_t *grid);
+void cdr_calc_d_dens (cdr_grid_t *grid);
+void cdr_calc_d_dens_r (cdr_grid_t *grid);
+void cdr_advect_diffu (cdr_grid_t *grid);
+void cdr_advect_diffu_r (cdr_grid_t *grid);
+
+double cdr_courant (cdr_grid_t *grid);
+void cdr_update (cdr_grid_t *orig, cdr_grid_t *dest, double h);
+void cdr_rk2_update (cdr_grid_t *dens_0, cdr_grid_t *d_dens_1,
+ cdr_grid_t *d_dens_2, cdr_grid_t *dest,
+ double h);
+void cdr_rk2_update_r (cdr_grid_t *dens_0, cdr_grid_t *d_dens_1,
+ cdr_grid_t *d_dens_2, cdr_grid_t *dest,
+ double h);
+void cdr_self_update_r (cdr_grid_t *grid, double h);
+void cdr_like_update_ar (cdr_grid_t *grid, cdr_grid_t *new_grid, double h);
+double cdr_rk2 (cdr_grid_t *grid, double h, double t);
+
+void cdr_update_refined (cdr_grid_t **ptree);
+void cdr_calc_maxs (cdr_grid_t *grid);
+void cdr_refine (cdr_grid_t *grid);
+void cdr_refine_r (cdr_grid_t *grid, cdr_grid_t *source);
+void cdr_match_r (cdr_grid_t *grid1, cdr_grid_t *grid2);
+void cdr_set_bnd (cdr_grid_t *grid);
+void cdr_set_bnd_r (cdr_grid_t *grid);
+
+void cdr_restrict (cdr_grid_t *grid);
+void cdr_restrict_r (cdr_grid_t *grid);
+
+void cdr_set_dens (cdr_grid_t *cdr, int species, int mode, double factor,
+ double (*f) (double, double, double));
+void cdr_init_dens (cdr_grid_t *cdr);
+cdr_grid_t *cdr_scratch_init (void);
+
+mapper_t **cdr_mappers_a (interpol_method_t *interp_method);
+void cdr_free_mappers (mapper_t **mappers);
+
+void cdr_dump (cdr_grid_t *grid, const char *prefix, const char *name);
+void cdr_dump_r (cdr_grid_t *grid, const char *prefix, const char *name,
+ FILE *infp, double sim_time);
+cdr_grid_t *cdr_load_tree_r (const char *prefix, const char *name, FILE *infp);
+void cdr_dump_frames (cdr_grid_t *grid, const char *prefix, const char *name);
+
+/* poisson.c */
+void pois_init (void);
+pois_grid_t *pois_new_a (int r0, int z0, int r1, int z1);
+pois_grid_t *pois_new_3d_a (int r0, int z0, int r1, int z1, int ntheta);
+void pois_free (pois_grid_t *grid);
+void pois_free_r (pois_grid_t *grid);
+pois_grid_t *pois_new_glob_a (int r0, int z0, int r1, int z1, int level);
+pois_grid_t *pois_init_tree_a (int r0, int z0, int r1, int z1);
+REAL *pois_boundary_a (pois_grid_t *grid, int boundary);
+void pois_solve_grid (pois_grid_t *grid, pois_problem_t *prob,
+ double lambda, double s);
+void pois_set_phi_boundaries (pois_grid_t *grid, REAL *boundaries[],
+ int left_uns, int right_neu, int bottom_neu,
+ int top_neu);
+int pois_map_charge (pois_grid_t *pois, cdr_grid_t *cdr, int mode);
+void pois_set_error (pois_grid_t *grid);
+int pois_refine (pois_grid_t *grid, double threshold);
+pois_grid_t **pois_solve_a (cdr_grid_t *cdr, pois_problem_t *prob);
+pois_grid_t **pois_gen_solve_a (cdr_grid_t *cdr, pois_problem_t *prob,
+ mapper_t **mappers, double es);
+pois_grid_t *pois_solve_mode (cdr_grid_t *tree, cdr_grid_t *cdr,
+ pois_problem_t *prob, int mode, double es);
+void pois_solve_r (pois_grid_t *pois, cdr_grid_t *cdr, pois_problem_t *prob,
+ int mode, double es, double threshold);
+double pois_phi_at (pois_grid_t *grid, double r, double z, double theta);
+void pois_dump (pois_grid_t *grid, const char *prefix, const char *name);
+void pois_dump_r (pois_grid_t *grid, const char *prefix, const char *name);
+void pois_write_error_r (pois_grid_t *grid, FILE *fp);
+void pois_error_measures (pois_grid_t *grid, double *L1, double *L2,
+ double *Lmax);
+void pois_inhom_init (void);
+double pois_inhom_phi (double r, double z);
+double pois_inhom_er (double r, double z);
+double pois_inhom_ez (double r, double z);
+double pois_inhom_q_factor (pois_grid_t *pois);
+void pois_add_inhom_phi_r (pois_grid_t *grid, double q);
+
+#ifndef _PHOTO_H_
+# include "photo.h"
+#endif
+
+/* photo.c */
+void photo_init ();
+void photo_register (double A, double lambda);
+void photo_copy_list (photo_term_t *src, photo_term_t **dest);
+void photo_unregister_all (void);
+void photo_dft_r (cdr_grid_t *grid, int sign);
+void photo_copy_source (cdr_grid_t *grid);
+void photo_add_term (photo_term_t *term, cdr_grid_t *cdr);
+void photo_add_term_r (photo_term_t *term, cdr_grid_t *cdr);
+pois_grid_t **photo_calc_term (photo_term_t *term, cdr_grid_t *cdr, int i);
+void photo_calc (photo_term_t *terms, cdr_grid_t *cdr);
+void photo_load_file (char *fname);
+
+/* cstream.c */
+void init_parameters(void);
+void cstream_init (void);
+void cstream_end (void);
+void cstream_set_field_at_time (double t);
+
+/* dft.c */
+void dft_transform (rz_array_t *in, rz_array_t *out, int sign);
+void dft_diff (grid_t *grid, rz_array_t *f);
+void dft_weight (cdr_grid_t *cdr, rz_array_t *var, double weights[],
+ double power);
+void dft_out_weights (cdr_grid_t *grid, const char *prefix, double t);
+void dft_perturb (cdr_grid_t *cdr, rz_array_t *var, double *epsilon_k);
+void dft_dens_perturb_r (cdr_grid_t *grid, int species, double *epsilon_k);
+
+
+#ifndef _REACTION_H_
+# include "reaction.h"
+#endif
+
+/* reaction.c */
+int find_species_by_name(const char *spec_name);
+void react_add (reaction_t *react);
+void react_init ();
+void react_apply_r (reaction_t *react, cdr_grid_t *grid, int overwrite);
+void react_apply_all (cdr_grid_t *grid);
+
+#ifndef _REACT_TABLE_H_
+# include "react_table.h"
+#endif
+
+/* kinetic module (usually minimal.c) */
+void kinetic_init (void);
+
+/* sprites module */
+double spr_density_at (double altitude);
+void spr_init ();
+void spr_hook (cdr_grid_t *grid);
+void spr_update (double altitude);
+double spr_head_altitude (cdr_grid_t *grid, int sign);
+
+/* rt.c */
+void kinetic_init (void);
+void read_input_file(const char *f_kinetic_name, const char *filename);
+
+
+
+
+
diff --git a/include/react_table.h b/include/react_table.h
new file mode 100644
index 0000000000000000000000000000000000000000..b897485d5d1f51956329cbc4ac70fcb9a25fd595
--- /dev/null
+++ b/include/react_table.h
@@ -0,0 +1,23 @@
+/** @file react_table.h
+ * @brief Maximum size of lookup tables.
+ */
+#ifndef _REACT_TABLE_H_
+#define MAX_TABLE_SIZE 500
+
+typedef struct react_table react_table;
+
+struct react_table
+{
+ double e_min;
+ double e_step;
+
+ double underflow;
+ double overflow;
+
+ int steps;
+
+ double values[MAX_TABLE_SIZE];
+};
+
+#define _REACT_TABLE_H_
+#endif
diff --git a/include/reaction.h b/include/reaction.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd2b9f3e6a666a7a99dcf165f673674142fcc2a6
--- /dev/null
+++ b/include/reaction.h
@@ -0,0 +1,53 @@
+/** @file reaction.c
+ * @brief Header file to define reactions.
+ */
+#ifndef _REACTION_H_
+#include "react_table.h"
+
+typedef struct reaction_t reaction_t;
+
+/* Maximum number of reactants that can enter into a reaction. */
+#define REACTION_MAX_IN 4
+#define REACTION_MAX_OUT 6
+
+struct reaction_t {
+ /* Photoionization is an special reaction where all the other parameters
+ * are ignored. Be careful to put photoionization in the correct position
+ * of the reaction list.
+ */
+ int is_photo;
+
+ /* Number of species in and out. */
+ int nin, nout;
+
+ int input[REACTION_MAX_IN];
+ int output[REACTION_MAX_OUT];
+
+ const char *inname[REACTION_MAX_IN];
+ const char *outname[REACTION_MAX_OUT];
+
+
+ void (*f) (double *in, int nin, double *out, int nout, double k, double dens, react_table *rt);
+
+ /* For reactions where k(E) is given by a reaction table. Such reactions
+ * require 'f' to be f_react_table. 'k' is ignored for these reactions.
+ * 'rt' is initialized with 'NULL', while 'tablefile' contains the filename
+ * with the reaction table.
+ *
+ * This file is read in react_add().
+ */
+ react_table *rt;
+
+ char *tablefile;
+
+ double k;
+
+ /* This allows us to define many simultaneous reactions. */
+ reaction_t *next;
+};
+
+extern reaction_t *reactions_list;
+extern reaction_t *reaction_index[];
+
+#define _REACTION_H_
+#endif
diff --git a/include/rz_array.h b/include/rz_array.h
new file mode 100644
index 0000000000000000000000000000000000000000..5cd4b08809e2566805fedd09cb3c0e7a349334ba
--- /dev/null
+++ b/include/rz_array.h
@@ -0,0 +1,86 @@
+/** @file rz_array.h
+ * @brief Definitions for 2D/3D arrays
+ */
+
+#ifndef _RZ_ARRAY_H_
+
+#include "cstream.h"
+
+typedef struct rz_array_t rz_array_t;
+
+struct rz_array_t {
+ REAL *data;
+
+ int strides[3];
+ int r0, z0, theta0, nr, nz;
+ int ntheta;
+ int dim;
+
+ int len;
+
+ rz_array_t *host;
+};
+
+#define R_INDX 0
+#define Z_INDX 1
+#define THETA_INDX 2
+
+/* The 3D macros */
+#define RZTP_OK(_A, _R, _Z, _T) \
+ ((_R) >= (_A)->r0 && (_R) < (_A)->nr + (_A)->r0 + 4 \
+ && (_Z) >= (_A)->z0 && (_Z) < (_A)->nz + (_A)->z0 + 4 \
+ && (_T) >= (_A)->theta0 && (_T) < (_A)->ntheta + (_A)->theta0 + 4) \
+
+#define __RZTP(_A, _R, _Z, _T) ((_A)->data \
+ + ((_R) - (_A)->r0) * (_A)->strides[R_INDX] \
+ + ((_Z) - (_A)->z0) * (_A)->strides[Z_INDX] \
+ + (((_T) - (_A)->theta0) * (_A)->strides[THETA_INDX]))
+
+#if defined (DEBUG_LEVEL) && DEBUG_LEVEL > 4
+/* Look, mum! I am also doing array bound checking.
+ * But, alas, since in some parts of the code we perform direct pointer
+ * arithmetic, this check will not detect all possible out-of-indexes
+ * (but we catch most of them).
+ */
+# define RZTP(_A, _R, _Z, _T) (RZTP_OK (_A, _R, _Z, _T)? \
+ __RZTP (_A, _R, _Z, _T): \
+ (fprintf (stderr, \
+ "%s:%d: Out of bounds ir = %d, iz = %d, itheta = %d\n", \
+ __FILE__, __LINE__, _R, _Z, _T), \
+ fprintf (stderr, \
+ "->r0 = %d ->z0 = %d ->theta0 = %d ->nr = %d ->nz = %d ->ntheta = %d\n", \
+ (_A)->r0, (_A)->z0, (_A)->theta0, \
+ (_A)->nr, (_A)->nz, (_A)->ntheta), \
+ exit(-1), (double*) NULL))
+#else
+# define RZTP(_A, _R, _Z, _T) __RZTP(_A, _R, _Z, _T)
+#endif
+
+#define RZT(_A,_R,_Z,_T) (*RZTP(_A, _R, _Z, _T))
+#define RZTm(_A,_R,_Z,_T) ((fprintf (stderr, \
+ "%s:%d: CHECK ir = %d, iz = %d, itheta = %d\n", \
+ __FILE__, __LINE__, _R, _Z, _T), \
+ fprintf (stderr, \
+ "->r0 = %d ->z0 = %d ->theta0 = %d ->nr = %d ->nz = %d ->ntheta = %d\n", \
+ (_A)->r0, (_A)->z0, (_A)->theta0, \
+ (_A)->nr, (_A)->nz, (_A)->ntheta), \
+ fprintf (stderr, \
+ "->data = %g\n", \
+ (_A)->data), \
+ exit(-1), (double*) NULL))
+
+
+/* These are valid for 2D arrays. When applied to a 3D array, they
+ * return the value with theta=0.
+ */
+#define RZP(_A,_R,_Z) RZTP(_A, _R, _Z, (_A)->theta0)
+#define RZ(_A,_R,_Z) RZT(_A, _R, _Z, (_A)->theta0)
+
+#define BND_CND_HNEUMANN 1
+#define BND_CND_HDIRICHLET -1
+
+#define BND_INWARD -1
+#define BND_OUTWARD 1
+
+#define _RZ_ARRAY_H_
+#endif
diff --git a/include/species.h b/include/species.h
new file mode 100644
index 0000000000000000000000000000000000000000..5587641dd44fa25dc2dafd73ffa26aadd2d48f36
--- /dev/null
+++ b/include/species.h
@@ -0,0 +1,62 @@
+/** @file species.h
+/* @brief include file describing the structs specie_t and seed_t
+ */
+
+#ifndef _SPECIES_H_
+
+#include "cstream.h"
+
+/*!< Number of virtual species. */
+#define N_VIRTUAL_SPECIES 1
+
+/*!< Information about each of the species. */
+typedef struct species_t {
+ double charge;
+ double mass; /* Zero or negative mass means immobile particles. */
+
+ const char *name;
+} species_t;
+
+/*!< Initial seeds for species. Only used at start-up */
+typedef struct seed_t {
+ int species;
+ const char *kind_species;
+ double value;
+ int type;
+ const char *kind_type;
+ double x0;
+ double y0;
+ double z0;
+ double sigma_x;
+ double sigma_y;
+ double sigma_z;
+} seed_t;
+
+extern species_t spec_electrons;
+extern species_t spec_ions;
+
+/*!< species[i] points to a species_t structure for species number I */
+extern species_t *spec_index[];
+
+extern seed_t *seed_index[];
+
+int no_seed, no_reactions, no_species;
+
+/*!< These are the index of two @a special species (that sounds strange, uh?)
+ *
+ * For example, electrons and ions are the species that are initialized
+ * with a gaussian seed, and photo_ions those that are affected by photo-
+ * ionization. Their values are set in the kinetic model file (usually
+ * minimal.c, but more complex models are possible).
+ */
+int electrons, ions, photo_ions;
+
+/*!< There is also a @a virtual species: Just to make it easy to create
+ * reaction functions that depend on variables other than species densities.
+ * Now this trick is only used for @a eabs absolute value of the electric
+ * field.
+ */
+extern const int virt_eabs;
+
+#define _SPECIES_H_
+#endif
diff --git a/include/tree.h b/include/tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b11ebe0ea8c24a8eee8a24dfc311196328f75ec
--- /dev/null
+++ b/include/tree.h
@@ -0,0 +1,94 @@
+/** @file tree.h
+ * @brief Structures and function definitions to handle a tree structure.
+ */
+
+/*!< These fields are included as the first fields of any structure that
+ * we want to convert into leaves of a tree. For people familiar with object
+ * orientation, this is equivalent to defining a class @a leaf and make
+ * other structures derive from it.
+ * The idea here is that we can share the code for the management of
+ * the tree structure of the grids both for the poisson and the cdr parts.
+ */
+
+#ifndef _TREE_H_
+
+#define LEAF_FIELDS(X) \
+ X *parent; \
+ X *next; \
+ X *first_child; \
+ int level; \
+
+#define LEAF_ROOT 0
+
+/*!< Iterate over all childs of a node. Simply write
+ *
+ * leaf_t leaf;
+ *
+ * iter_childs (node, leaf) {
+ * do_something (leaf);
+ * }
+ */
+#define iter_childs(ROOT, LEAF) for (LEAF = ROOT->first_child; LEAF; \
+ LEAF = LEAF->next)
+
+/*!< iter_child may not work if in the loop body we make free(LEAF)
+ * (though this will go unnoticed most of the time). So when
+ * freeing grids, the following macro has to be used instead:
+ */
+#define free_childs(ROOT, LEAF, FREE) do { \
+ grid_t *next__; \
+ for (LEAF = ROOT->first_child; LEAF; LEAF = (typeof(LEAF)) next__) { \
+ next__ = ((grid_t *) LEAF)->next; \
+ FREE (LEAF); \
+ } \
+ } while(0)
+
+/*!< This is used to put into a leaf any set of values. */
+#define set_leaf(LEAF, PARENT, NEXT, FIRST_CHILD, LEVEL) do { \
+ LEAF->parent = PARENT; \
+ LEAF->next = NEXT; \
+ LEAF->first_child = FIRST_CHILD; \
+ LEAF->level = LEVEL; \
+ } while(0)
+
+#define init_leaf(LEAF) set_leaf(LEAF, NULL, NULL, NULL, -1)
+
+/*!< Sometimes we have to remove all of a leaf's children. After freeing
+ * them with free_childs, call this one.
+ */
+#define set_childless(LEAF) (LEAF)->first_child = NULL
+
+/*!< Adds a child to a given leaf. */
+#define add_child(PARENT, CHILD) do { \
+ set_leaf(CHILD, PARENT, PARENT->first_child, CHILD->first_child, \
+ PARENT->level + 1); \
+ PARENT->first_child = CHILD; \
+ } while(0)
+
+/*!< Given a function name, creates a function with the same name plus `_r'
+ * that (tail- in the second case) recursively calls the first.
+ * Can only be applied on functions that receive as single parameter a
+ * grid of type `type'.
+ */
+#define mk_recursive(func, type) \
+ void func ## _r (type *grid_) \
+ { \
+ type *child_; \
+ func (grid_); \
+ iter_childs (grid_, child_) { \
+ func ## _r (child_); \
+ } \
+ }
+
+#define mk_tail_recursive(func, type) \
+ void func ## _r (type *grid_) \
+ { \
+ type *child_; \
+ iter_childs (grid_, child_) { \
+ func ## _r (child_); \
+ } \
+ func (grid_); \
+ }
+
+#define _TREE_H_
+#endif
diff --git a/input/.default.cfg.swp b/input/.default.cfg.swp
new file mode 100644
index 0000000000000000000000000000000000000000..9ac7b0dad19c9ba20b19952ee9a86eb819794299
GIT binary patch
literal 16384
zcmeI3dx#xZ9mi*DAGS$sjG)x#>GqE#baVG^o?@-0Xr!U0t=puEio>~g&b{|!=W#QS
zeWj1of)+%uVxOW_h_C)pDu$x}R7(-5Py-dKqP1WJOIuP5*1v-FbLNrVow>W4o5VlF
zx$xmGb7s!@&G-DyZ_e*GcU#R{_wEzB8rv;C>n-cm*(Yv!;qv#5yt2)*x}l1tIljs#
z)?N@cBIP&QGrHls%bk8l+Tr+o;HhxD-;-fGh{mXFDM`#%i2M|-!laO-v1Z*|B1^j>m_&*ehtUqPUt}k
zz5sin32Whvw^`Qf@G3kHPr^gchl9|8{qPa^%R0+C4$r_Z;c<8nCg4hV54;O5fLGR9
z)}!zM+zVfY!yw_^um&!I5qNzK{leW4gAWJcGq4N(ewk(c0iJ{3z|Y_zxCS=CD7+um
z!fTh(4oBhJ@G#s19()Kk!&UGBSO+KHYFR&r$KZ!>6uu5~up1`eYS;)H;M67P0MEj&
z;Awaa9)=^}Lk}Fd33kGXi!JNV@H{*Rzku(+6nq|Tg-O^A8{wskEbF)MEIb3p-~qTE
zcEC7X4OhUa3oYvj_yK$uz6D=_gD?i~g?GXRu;8y0bnb&M!4bF(y091ifiJxXe}vz`
z(_sATD4f+t@bRUm#I<6y-wWcvZuyQK>TWL{y~Z-F@mxP`)qZy5Fh_466KUJDbQ9Cq
zY&0jbv)h5^DL*#d?Fqvm6mc(9Q7>>E{*tk9m2@Hz2O?A*?W^=$?bD`2I{X$L_S+@}`D35Gf%=OLv8zcr6u*o(eNpU08vqRT^f}
zwpJ!>&mi|HbXdu2j2uHd%?{?NV#0NCth|1#SoYdeQLOq6A@;M%Wjju!d-|yG0-EvWuqkXx2?jBq`!_
zs+#e%wwpLiT&`El?utP3(UL`rlp02>9Z7zTfy6%Bqn4UAq0qCk=NeRL_K(xXf$@
z!nk?KkbJg=4cVi4H;eXmZ3lnD}ENz|F!L&BNC`kLF6&x`A|T(@9CRC=QFYa(K{ww-O|lGd3bryV-VjM!PP1
zTBgru(_AuIE-|}gWiCU>#+7`3H2dxM6kF_Aw{0~my}ql=Z@}|T7U_ILc9L14W@Ro?
zqj-qWjh!}@ELcUQ(aaadt3&1<@90pq;~<=Ci2R&l#KMboIe@P=WPYdBA+PfV@d)ud
zx}D8OI##y1#=mfuk_{$;+S{v7knB%0lVSDun{hWr^xLehezT2@C}%SQCJU`!Nu@T@_Lj1
z-w$7gyWn={!42>xdHe}@8U6;x;U{n}9D#Y51_^s$6y6SN;1YNP4gUnUfeS`c2kK9)
zK&?QnK&?Qn!2hKJ)MCZvY&TjIV+Yg|Z_!;+vMl9_`t08o)hC&kWM?SKkWO|2*9~S&
zqOmE>)6Bk^T`GH4KZwn~KUA)kMR|3hW|j44M+{NgDy_6Z9aJ;=RHFQL&se}lEz*_E
zdOnhAv=5cWS|v{%G~CCtK}-o_-qf)39*d3K;?at>ViR~4qkU5O)YQ!+sM&ttXIUIK
z+NS=M&rE*TVrHDAJ`mE4b(}awYEsyh-hO%=rMj}@s~J|wTPB2F;uh495>hHQ#1!iE
zw4{PJCYlRb)L@aat4dR{()3R>w^qxiH>)sC!j=epcP=YtiKK6o=w}US5qU~%N^6Bh
z6?LH*!Q9Oy`<7fegnfhjr6}>`eP&4n!<*H@YlLWyHy@;pZIk15bT(1_j?>Yz
z#%WB{=#XEN?h;ZK<-vG+cCsVdZjewK;*0z|mr{}N_e7M09V%^=`7{L~?e_wYtes(o
zjRV`8gJyP8I+}Vxz6^b(oYMt?V%22_?JzyFGaK9HVNs=xM~qIttVwd^QO)vO~=2A;&S0OE3WWLs4*`<%vzyqKi<-JrLRO+
z@gM7PI5)7Il@4FJ?UjZcG_?yVFAlpD)j}n)Cs&`6(c%}6n@m+e#$FKhc?eQ3aMN()
YMrC(w$@Ww?3=-ZU6kVF2oXysM0HUev6#xJL
literal 0
HcmV?d00001
diff --git a/input/air760torr.photo b/input/air760torr.photo
new file mode 100644
index 0000000000000000000000000000000000000000..2cf889a844050b2200a7188afa46524e866e6899
--- /dev/null
+++ b/input/air760torr.photo
@@ -0,0 +1,2 @@
+-8.28556e-10 -4.04047e-06
+-1.2328e-07 -0.000149679
diff --git a/input/default.cfg b/input/default.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..bce23673b06426b1b0762454aced6046d7228c5d
--- /dev/null
+++ b/input/default.cfg
@@ -0,0 +1,506 @@
+name = "default";
+param = (
+ {
+ type = "string";
+ name = "prog_id";
+ comment = "An identification name for this run";
+ value = "example";
+ },
+ {
+ type = "string";
+ name = "output_dir";
+ comment = "Output directory. ";
+ value = "output/";
+ },
+ {
+ type = "string";
+ name = "kin_input";
+ comment = "Kinetics input file";
+ value = "input/kinetic_example.cfg";
+ },
+ {
+ type = "int";
+ name = "restart";
+ comment = "If restart is TRUE, the simulation will continue with data from a previous run";
+ value = 0;
+ },
+ {
+ type = "string";
+ name = "load_file";
+ comment = "If restart is TRUE, the name of the file with data from previous run, otherwise empty";
+ value = "";
+ },
+ {
+ type = "double";
+ name = "output_dt";
+ comment = "Time interval for output to be written to disk";
+ value = 0.100;
+ },
+ {
+ type = "int";
+ name = "pois_output";
+ comment = "Output of the Poisson grids, including the potential?";
+ value = 0;
+ },
+ {
+ type = "int";
+ name = "cdr_output_margin";
+ comment = "Margin outside the grids in the output of the cdr equation";
+ value = 0;
+ },
+ {
+ type = "int";
+ name = "pois_output_margin";
+ comment = "Margin outside the grids in the output of the poisson equation";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "warn_min_timestep";
+ comment = "If the time steps are smaller than this number, the program issues a warning";
+ value = 1e-06;
+ },
+ {
+ type = "int";
+ name = "max_disk_space_mb";
+ comment = "Maximum disk space, in Mb, to use";
+ value = 1048576;
+ },
+ {
+ type = "int";
+ name = "gridpoints_r";
+ comment = "Number of R gridpoints at level 0";
+ value = 600;
+ },
+ {
+ type = "int";
+ name = "gridpoints_z";
+ comment = "Number of Z gridpoints at level 0";
+ value = 600;
+ },
+ {
+ type = "int";
+ name = "max_ntheta";
+ comment = "Number of azimuthal gridcells and modes";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "start_t";
+ comment = "Initial time";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "end_t";
+ comment = "End time";
+ value = 0.12;
+ },
+ {
+ type = "double";
+ name = "attempt_dt";
+ comment = "Attempted timestep. The actual timestep may be larger";
+ value = 50.0;
+ },
+ {
+ type = "int";
+ name = "extra_pois_levels";
+ comment = "Extra levels for the Poisson solver";
+ value = 2;
+ },
+ {
+ type = "int";
+ name = "max_levels";
+ comment = "Maximum level of refinement. Use a big number here";
+ value = 64;
+ },
+ {
+ type = "double";
+ name = "pois_max_error";
+ comment = "Error threshold that leads to refinement in the Poisson code.";
+ value = 0.001;
+ },
+ {
+ type = "int";
+ name = "pois_max_level";
+ comment = "Maximum level of refinement in the Poisson equation.";
+ value = 3;
+ },
+ {
+ type = "int";
+ name = "extra_photo_levels";
+ comment = "Extra levels for the photo-ionization solver";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_max_level";
+ comment = "Maximum level of refinement in the photo-ionization solver.";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "photo_max_error";
+ comment = "Error threshold that leads to refinement in the photo-ionization code.";
+ value = 0.01;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_right";
+ comment = "Photo-ionization boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_bottom";
+ comment = "Photo-ionization boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_top";
+ comment = "Photo-ionization boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "extra_photo_levels_2";
+ comment = "Extra levels for the photo-ionization solver";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_max_level_2";
+ comment = "Maximum level of refinement in the photo-ionization solver.";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "photo_max_error_2";
+ comment = "Error threshold that leads to refinement in the photo-ionization code.";
+ value = 0.01;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_right_2";
+ comment = "Photo-ionization boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_bottom_2";
+ comment = "Photo-ionization boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_top_2";
+ comment = "Photo-ionization boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_bottom";
+ comment = "Particles boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_top";
+ comment = "Particles boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_right";
+ comment = "Particles boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_right";
+ comment = "Potential boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_bottom";
+ comment = "Potential boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_top";
+ comment = "Potential boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "double";
+ name = "nu_a";
+ comment = "Maximum advection Courant number";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_d";
+ comment = "Maximum diffusion Courant number";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_rt";
+ comment = "Maximum ratio of dt/relaxation time";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_f";
+ comment = "Maximum ratio of change of the densities (set to a very large number to ignore)";
+ value = 1e+20;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_eabs";
+ comment = "Refinement threshold for the electric field";
+ value = 0.2;
+ },
+ {
+ type = "int";
+ name = "ref_level_eabs";
+ comment = "Maximum refinement level reached through ref_threshold_eabs";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_charge";
+ comment = "Refinement threshold for the curvature of the charge";
+ value = 0.004;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_dens";
+ comment = "Refinement threshold for the curvature of the densities";
+ value = 0.004;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_edge";
+ comment = "Refinement threshold for the densities in the leading edge";
+ value = 10000.0;
+ },
+ {
+ type = "int";
+ name = "cdr_brick_dr";
+ comment = "r-length of the minimal refinement area in the cdr equation";
+ value = 8;
+ },
+ {
+ type = "int";
+ name = "cdr_brick_dz";
+ comment = "z-length of the minimal refinement area in the cdr equation";
+ value = 8;
+ },
+ {
+ type = "int";
+ name = "cdr_max_level";
+ comment = "Maximum level of refinement in the Fluid equation.";
+ value = 3;
+ },
+ {
+ type = "int";
+ name = "cdr_interp_in";
+ comment = "Interpolation method for the grid interior (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_interp_bnd";
+ comment = "Interpolation method for the grid boundaries (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "L_r";
+ comment = "Length in r of the complete domain";
+ value = 13044.0;
+ },
+ {
+ type = "double";
+ name = "L_z";
+ comment = "Length in z of the complete domain";
+ value = 13044.0;
+ },
+ {
+ type = "double";
+ name = "diffusion_coeff";
+ comment = "Isotropic difussion coefficient";
+ value = 0.1;
+ },
+ {
+ type = "int";
+ name = "has_photoionization";
+ comment = "Whether the code includes photoionization or not";
+ value = 1;
+ },
+ {
+ type = "string";
+ name = "photoionization_file";
+ comment = "The name of a file from which we can read the photoionization parameters";
+ value = "input/air760torr.photo";
+ },
+ {
+ type = "double";
+ name = "attachment_rate";
+ comment = "Rate of dissociative attachment";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "attachment_E0";
+ comment = "E0 in the exp(-E0/E) factor in the attachment expression.";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_x";
+ comment = "x component of the external electric field";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_y";
+ comment = "y component of the external electric field";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_z";
+ comment = "z component of the external electric field";
+ value = -0.06;
+ },
+ {
+ type = "double";
+ name = "rise_time";
+ comment = "Rise time of the electric field (0 for instantaneous rise)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "off_time";
+ comment = "Time to switch off the electric field (0.0 means never)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_x";
+ comment = "x width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_y";
+ comment = "y width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_z";
+ comment = "z width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_N";
+ comment = "Number of electrons in the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "background_ionization";
+ comment = "Initial at z=0 densities of electrons and ions";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "background_increase_length";
+ comment = "Length of exponential increase of the pre-ionization (for atmospherical models)";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "pois_inhom";
+ comment = "Use the point-plane geometry?";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "pois_inhom_reflections";
+ comment = "Number of mirror charges to use";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "needle_length";
+ comment = "Length of the needle";
+ value = 2500.0;
+ },
+ {
+ type = "double";
+ name = "needle_radius";
+ comment = "Radius of the needle";
+ value = 400.0;
+ },
+ {
+ type = "double";
+ name = "pois_inhom_fixed_q";
+ comment = "If nonzero, the charge is fixed, not floating (simulation of charged clouds close to the earth surface)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "constant_source";
+ comment = "Constant ionization rate";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "perturb_epsilon";
+ comment = "Initial perturbation to the axisymmetric configuration";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "perturb_max_k";
+ comment = "Perturb only modes up to perturb_max_k (large number to perturb all)";
+ value = 1024;
+ },
+ {
+ type = "int";
+ name = "sprite_module";
+ comment = "1 if the sprite module is activated, 0 otherwise";
+ value = 0;
+ },
+ {
+ type = "double";
+ name = "dens_decay_len";
+ comment = "Lenght of exponential decay of the density w/r to altitude";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "sprite_dens_0";
+ comment = "Density at z = 0";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "sprite_dens_q";
+ comment = "Quenching density";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "sprite_sign";
+ comment = "Sign of the sprite head that we are following (the other will not be reliable";
+ value = -1;
+ } );
diff --git a/input/default.diffusion b/input/default.diffusion
new file mode 100644
index 0000000000000000000000000000000000000000..cf861a89b8c63c2371642f10b02ef6e817891253
--- /dev/null
+++ b/input/default.diffusion
@@ -0,0 +1,33 @@
+START
+-2.91222e+00
+0.113943e+00
+27
+0.015
+0.13
+0.0152226306
+0.01566884
+0.0163744
+0.0164662
+0.0166058
+0.0169752
+0.0173472
+0.0176621
+0.0175883
+0.0172749
+0.0168534
+0.016438
+0.0159813
+0.0157487
+0.015716
+0.017053
+0.0214515
+0.0300934
+0.0415054
+0.0527951
+0.0619993
+0.0700603
+0.0774594
+0.0852778
+0.0944876
+0.104969
+0.117301
diff --git a/input/default.mobility b/input/default.mobility
new file mode 100644
index 0000000000000000000000000000000000000000..3a563e7b4f3bd48465f4ed3d2e16ed1ff05b5fc1
--- /dev/null
+++ b/input/default.mobility
@@ -0,0 +1,33 @@
+START
+-2.91222e+00
+0.113943e+00
+27
+7.0
+0.7
+6.5615252895
+5.9332719211
+5.35874
+4.75762
+4.14641
+3.56977
+3.06845
+2.66783
+2.36204
+2.12783
+1.95148
+1.81282
+1.70094
+1.60616
+1.51537
+1.43021
+1.34845
+1.27194
+1.20157
+1.13616
+1.07396
+1.013
+0.953511
+0.893685
+0.835274
+0.777726
+0.721898
diff --git a/input/elecionrecomb.reaction b/input/elecionrecomb.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..ad219b3474a6eb9837cdff4f54283ae085188b8c
--- /dev/null
+++ b/input/elecionrecomb.reaction
@@ -0,0 +1,107 @@
+Reaction table for e-/ion recomb
+START
+-1.875061e+00
+2.477121e-02
+100
+2.832513e-04
+4.165086e-05
+2.832513e-04
+2.820940e-04
+2.809796e-04
+2.799495e-04
+2.789446e-04
+2.779923e-04
+2.771048e-04
+2.762805e-04
+2.753281e-04
+2.745195e-04
+2.738511e-04
+2.730554e-04
+2.723976e-04
+2.716144e-04
+2.709670e-04
+2.703241e-04
+2.696858e-04
+2.689257e-04
+2.682973e-04
+2.676732e-04
+2.669300e-04
+2.661929e-04
+2.653407e-04
+2.644967e-04
+2.635418e-04
+2.623626e-04
+2.609683e-04
+2.592563e-04
+2.572456e-04
+2.546361e-04
+2.515865e-04
+2.476529e-04
+2.430556e-04
+2.374798e-04
+2.310614e-04
+2.246205e-04
+2.165509e-04
+2.088780e-04
+2.009593e-04
+1.922445e-04
+1.847366e-04
+1.769207e-04
+1.699879e-04
+1.633851e-04
+1.567167e-04
+1.515880e-04
+1.465017e-04
+1.413611e-04
+1.374446e-04
+1.336814e-04
+1.296988e-04
+1.267332e-04
+1.237526e-04
+1.207668e-04
+1.182972e-04
+1.158218e-04
+1.133347e-04
+1.111256e-04
+1.090409e-04
+1.069977e-04
+1.048627e-04
+1.028859e-04
+1.010168e-04
+9.910057e-05
+9.718801e-05
+9.535394e-05
+9.359334e-05
+9.173594e-05
+8.992826e-05
+8.815666e-05
+8.638947e-05
+8.464569e-05
+8.289237e-05
+8.120892e-05
+7.946084e-05
+7.779045e-05
+7.610653e-05
+7.442029e-05
+7.274132e-05
+7.112438e-05
+6.950156e-05
+6.788331e-05
+6.627846e-05
+6.467677e-05
+6.312051e-05
+6.158037e-05
+6.003515e-05
+5.852255e-05
+5.702236e-05
+5.554281e-05
+5.406994e-05
+5.261364e-05
+5.119053e-05
+4.978070e-05
+4.837814e-05
+4.700004e-05
+4.564061e-05
+4.428529e-05
+4.296657e-05
+4.165086e-05
diff --git a/input/example_user_continue.cfg b/input/example_user_continue.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..4fe7cceb32cb0514da3a88600c1969b8ddc4ccd7
--- /dev/null
+++ b/input/example_user_continue.cfg
@@ -0,0 +1,506 @@
+name = "default";
+param = (
+ {
+ type = "string";
+ name = "prog_id";
+ comment = "An identification name for this run";
+ value = "example";
+ },
+ {
+ type = "string";
+ name = "output_dir";
+ comment = "Output directory";
+ value = "output";
+ },
+ {
+ type = "string";
+ name = "kin_input";
+ comment = "Kinetics input file";
+ value = "input/kinetic_example.cfg";
+ },
+ {
+ type = "int";
+ name = "restart";
+ comment = "If restart is 1 (TRUE), the simulation will continue with data from a previous run";
+ value = 0;
+ },
+ {
+ type = "string";
+ name = "load_file";
+ comment = "If restart is TRUE, the name of the file with data from previous run, otherwise empty";
+ value = "";
+ },
+ {
+ type = "double";
+ name = "output_dt";
+ comment = "Time interval for output to be written to disk";
+ value = 0.1;
+ },
+ {
+ type = "int";
+ name = "pois_output";
+ comment = "Output of the Poisson grids, including the potential?";
+ value = 0;
+ },
+ {
+ type = "int";
+ name = "cdr_output_margin";
+ comment = "Margin outside the grids in the output of the cdr equation";
+ value = 0;
+ },
+ {
+ type = "int";
+ name = "pois_output_margin";
+ comment = "Margin outside the grids in the output of the poisson equation";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "warn_min_timestep";
+ comment = "If the time steps are smaller than this number, the program issues a warning";
+ value = 1e-06;
+ },
+ {
+ type = "int";
+ name = "max_disk_space_mb";
+ comment = "Maximum disk space, in Mb, to use";
+ value = 1048576;
+ },
+ {
+ type = "int";
+ name = "gridpoints_r";
+ comment = "Number of R gridpoints at level 0";
+ value = 600;
+ },
+ {
+ type = "int";
+ name = "gridpoints_z";
+ comment = "Number of Z gridpoints at level 0";
+ value = 600;
+ },
+ {
+ type = "int";
+ name = "max_ntheta";
+ comment = "Number of azimuthal gridcells and modes";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "start_t";
+ comment = "Initial time";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "end_t";
+ comment = "End time";
+ value = 0.6;
+ },
+ {
+ type = "double";
+ name = "attempt_dt";
+ comment = "Attempted timestep. The actual timestep may be larger";
+ value = 50.0;
+ },
+ {
+ type = "int";
+ name = "extra_pois_levels";
+ comment = "Extra levels for the Poisson solver";
+ value = 2;
+ },
+ {
+ type = "int";
+ name = "max_levels";
+ comment = "Maximum level of refinement. Use a big number here";
+ value = 64;
+ },
+ {
+ type = "double";
+ name = "pois_max_error";
+ comment = "Error threshold that leads to refinement in the Poisson code.";
+ value = 0.001;
+ },
+ {
+ type = "int";
+ name = "pois_max_level";
+ comment = "Maximum level of refinement in the Poisson equation.";
+ value = 3;
+ },
+ {
+ type = "int";
+ name = "extra_photo_levels";
+ comment = "Extra levels for the photo-ionization solver";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_max_level";
+ comment = "Maximum level of refinement in the photo-ionization solver.";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "photo_max_error";
+ comment = "Error threshold that leads to refinement in the photo-ionization code.";
+ value = 0.01;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_right";
+ comment = "Photo-ionization boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_bottom";
+ comment = "Photo-ionization boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_top";
+ comment = "Photo-ionization boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "extra_photo_levels_2";
+ comment = "Extra levels for the photo-ionization solver";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_max_level_2";
+ comment = "Maximum level of refinement in the photo-ionization solver.";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "photo_max_error_2";
+ comment = "Error threshold that leads to refinement in the photo-ionization code.";
+ value = 0.01;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_right_2";
+ comment = "Photo-ionization boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_bottom_2";
+ comment = "Photo-ionization boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_top_2";
+ comment = "Photo-ionization boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_bottom";
+ comment = "Particles boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_top";
+ comment = "Particles boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_right";
+ comment = "Particles boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_right";
+ comment = "Potential boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_bottom";
+ comment = "Potential boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_top";
+ comment = "Potential boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "double";
+ name = "nu_a";
+ comment = "Maximum advection Courant number";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_d";
+ comment = "Maximum diffusion Courant number";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_rt";
+ comment = "Maximum ratio of dt/relaxation time";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_f";
+ comment = "Maximum ratio of change of the densities (set to a very large number to ignore)";
+ value = 1e+20;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_eabs";
+ comment = "Refinement threshold for the electric field";
+ value = 0.2;
+ },
+ {
+ type = "int";
+ name = "ref_level_eabs";
+ comment = "Maximum refinement level reached through ref_threshold_eabs";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_charge";
+ comment = "Refinement threshold for the curvature of the charge";
+ value = 0.004;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_dens";
+ comment = "Refinement threshold for the curvature of the densities";
+ value = 0.004;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_edge";
+ comment = "Refinement threshold for the densities in the leading edge";
+ value = 10000.0;
+ },
+ {
+ type = "int";
+ name = "cdr_brick_dr";
+ comment = "r-length of the minimal refinement area in the cdr equation";
+ value = 8;
+ },
+ {
+ type = "int";
+ name = "cdr_brick_dz";
+ comment = "z-length of the minimal refinement area in the cdr equation";
+ value = 8;
+ },
+ {
+ type = "int";
+ name = "cdr_max_level";
+ comment = "Maximum level of refinement in the Fluid equation.";
+ value = 3;
+ },
+ {
+ type = "int";
+ name = "cdr_interp_in";
+ comment = "Interpolation method for the grid interior (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_interp_bnd";
+ comment = "Interpolation method for the grid boundaries (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "L_r";
+ comment = "Length in r of the complete domain";
+ value = 13044.0;
+ },
+ {
+ type = "double";
+ name = "L_z";
+ comment = "Length in z of the complete domain";
+ value = 13044.0;
+ },
+ {
+ type = "double";
+ name = "diffusion_coeff";
+ comment = "Isotropic difussion coefficient";
+ value = 0.1;
+ },
+ {
+ type = "int";
+ name = "has_photoionization";
+ comment = "Whether the code includes photoionization or not";
+ value = 1;
+ },
+ {
+ type = "string";
+ name = "photoionization_file";
+ comment = "The name of a file from which we can read the photoionization parameters";
+ value = "input/air760torr.photo";
+ },
+ {
+ type = "double";
+ name = "attachment_rate";
+ comment = "Rate of dissociative attachment";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "attachment_E0";
+ comment = "E0 in the exp(-E0/E) factor in the attachment expression.";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_x";
+ comment = "x component of the external electric field";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_y";
+ comment = "y component of the external electric field";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_z";
+ comment = "z component of the external electric field";
+ value = -0.06;
+ },
+ {
+ type = "double";
+ name = "rise_time";
+ comment = "Rise time of the electric field (0 for instantaneous rise)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "off_time";
+ comment = "Time to switch off the electric field (0.0 means never)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_x";
+ comment = "x width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_y";
+ comment = "y width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_z";
+ comment = "z width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_N";
+ comment = "Number of electrons in the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "background_ionization";
+ comment = "Initial at z=0 densities of electrons and ions";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "background_increase_length";
+ comment = "Length of exponential increase of the pre-ionization (for atmospherical models)";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "pois_inhom";
+ comment = "Use the point-plane geometry?";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "pois_inhom_reflections";
+ comment = "Number of mirror charges to use";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "needle_length";
+ comment = "Length of the needle";
+ value = 2500.0;
+ },
+ {
+ type = "double";
+ name = "needle_radius";
+ comment = "Radius of the needle";
+ value = 400.0;
+ },
+ {
+ type = "double";
+ name = "pois_inhom_fixed_q";
+ comment = "If nonzero, the charge is fixed, not floating (simulation of charged clouds close to the earth surface)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "constant_source";
+ comment = "Constant ionization rate";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "perturb_epsilon";
+ comment = "Initial perturbation to the axisymmetric configuration";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "perturb_max_k";
+ comment = "Perturb only modes up to perturb_max_k (large number to perturb all)";
+ value = 1024;
+ },
+ {
+ type = "int";
+ name = "sprite_module";
+ comment = "1 if the sprite module is activated, 0 otherwise";
+ value = 0;
+ },
+ {
+ type = "double";
+ name = "dens_decay_len";
+ comment = "Lenght of exponential decay of the density w/r to altitude";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "sprite_dens_0";
+ comment = "Density at z = 0";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "sprite_dens_q";
+ comment = "Quenching density";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "sprite_sign";
+ comment = "Sign of the sprite head that we are following (the other will not be reliable";
+ value = -1;
+ } );
diff --git a/input/example_user_init.cfg b/input/example_user_init.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..bd88d47f8051368fda0f206c6b91fcc6866f02f1
--- /dev/null
+++ b/input/example_user_init.cfg
@@ -0,0 +1,27 @@
+name = "user_init";
+param = (
+ {
+ type = "string";
+ name = "output_dir";
+ comment = "Output directory";
+ value = "output";
+ },
+ {
+ type = "int";
+ name = "restart";
+ comment = "If restart is 1 (TRUE), the simulation will continue with data from a previous run";
+ value = 0;
+ },
+ {
+ type = "string";
+ name = "load_file";
+ comment = "If restart is TRUE, the name of the file with data from previous run, otherwise empty";
+ value = "";
+ },
+ {
+ type = "double";
+ name = "end_t";
+ comment = "End time";
+ value = 0.600;
+ }
+);
diff --git a/input/extra_photo_files/10ppbO2.photo b/input/extra_photo_files/10ppbO2.photo
new file mode 100644
index 0000000000000000000000000000000000000000..86905a2a13601b8d68eb0715ec62d57ae46cf5ff
--- /dev/null
+++ b/input/extra_photo_files/10ppbO2.photo
@@ -0,0 +1,2 @@
+-4.14278e-17 -1.01012e-20
+-6.16399e-15 -3.74197e-19
diff --git a/input/extra_photo_files/1ppbO2.photo b/input/extra_photo_files/1ppbO2.photo
new file mode 100644
index 0000000000000000000000000000000000000000..df4be88f544bd32c06b9290926f3664cb29d4aa7
--- /dev/null
+++ b/input/extra_photo_files/1ppbO2.photo
@@ -0,0 +1,2 @@
+-4.14278e-18 -1.01012e-22
+-6.16399e-16 -3.74197e-21
diff --git a/input/extra_photo_files/1ppmN2.photo b/input/extra_photo_files/1ppmN2.photo
new file mode 100644
index 0000000000000000000000000000000000000000..1d1964ec1f31544e678b38cb5b855ce6e9932056
--- /dev/null
+++ b/input/extra_photo_files/1ppmN2.photo
@@ -0,0 +1,2 @@
+-4.14278e-09 -0.000101011
+-6.16398e-07 -0.00374197
diff --git a/input/extra_photo_files/1ppmO2.photo b/input/extra_photo_files/1ppmO2.photo
new file mode 100644
index 0000000000000000000000000000000000000000..f4f538bd8aab334d649627cf7f8425aa0fc502d1
--- /dev/null
+++ b/input/extra_photo_files/1ppmO2.photo
@@ -0,0 +1,2 @@
+-4.14278e-15 -1.01012e-16
+-6.16399e-13 -3.74197e-15
diff --git a/input/extra_photo_files/air760torr-ml-60.photo b/input/extra_photo_files/air760torr-ml-60.photo
new file mode 100644
index 0000000000000000000000000000000000000000..2cf889a844050b2200a7188afa46524e866e6899
--- /dev/null
+++ b/input/extra_photo_files/air760torr-ml-60.photo
@@ -0,0 +1,2 @@
+-8.28556e-10 -4.04047e-06
+-1.2328e-07 -0.000149679
diff --git a/input/extra_photo_files/air_1atm_3term.photo b/input/extra_photo_files/air_1atm_3term.photo
new file mode 100644
index 0000000000000000000000000000000000000000..106c5d43c779a0ac18238f449bb5b079412c1b12
--- /dev/null
+++ b/input/extra_photo_files/air_1atm_3term.photo
@@ -0,0 +1,3 @@
+-3.064258211257769079e-09 -2.029823458382051625e-05
+-1.676017200059491931e-08 -2.080524917212339816e-04
+-1.680217549583392655e-08 -2.025357858924288772e-04
diff --git a/input/kinetic_example.cfg b/input/kinetic_example.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..5109262450b59728429fded9e074a7ead7c57ef8
--- /dev/null
+++ b/input/kinetic_example.cfg
@@ -0,0 +1,266 @@
+filename="kinetic_example.cfg";
+
+#########################
+## Species definitions ##
+#########################
+
+species = (
+ {
+ name="o2";
+ mass=0.0;
+ charge=0.0;
+ },
+ {
+ name="n2";
+ mass=0.0;
+ charge=0.0;
+ },
+ {
+ ## This is the generic neutral species used for compound reactions that take ##
+ ## any neutral as input. Make sure to set its density as the sum of the ##
+ ## densities of all actual neutral species in the seed section ##
+ name="neutral";
+ mass=0.0;
+ charge=0.0;
+ },
+ {
+ name="electrons";
+ mass=1.0;
+ charge=-1.0;
+ },
+ {
+ ## We don't distinguish between different positive ions, so one ##
+ ## generic ion, X+, is used ##
+ name="xplus";
+ mass=0.0;
+ charge=1.0;
+ },
+ {
+ name="o2minus";
+ mass=0.0;
+ charge=-1.0;
+ },
+ {
+ name="ominus";
+ mass=0.0;
+ charge=-1.0;
+ },
+ ## These dummy species are used for the photo-ionization code. ##
+ ## D+ represents N2+, D- is just to preserve the charge-balance. ##
+ {
+ name="dummyminus";
+ mass=0.0;
+ charge=-1.0;
+ },
+ {
+ name="dummyplus";
+ mass=0.0;
+ charge=1.0;
+ }
+ );
+
+######################
+## Seed definitions ##
+######################
+
+seed = (
+ {
+ species="electrons";
+ type="gaussian";
+ value=1.0e6;
+ x0=0.;
+ y0=0.;
+ z0=13044.;
+ sigma_x=32.0;
+ sigma_y=32.0;
+ sigma_z=32.0;
+ },
+ {
+ species="xplus";
+ type="gaussian";
+ value=1.0e6;
+ x0=0.;
+ y0=0.;
+ z0=13044.;
+ sigma_x=32.0;
+ sigma_y=32.0;
+ sigma_z=32.0;
+ },
+ {
+ species="xplus";
+ type="constant";
+ value=0.0e-8;
+ },
+ {
+ species="o2minus";
+ type="constant";
+ value=0.0e-8;
+ },
+ {
+ species="n2";
+ type="constant";
+ value=4.16e4;
+ },
+ {
+ species="o2";
+ type="constant";
+ value=1.04e4;
+ },
+ {
+ species="dummyminus";
+ type="constant";
+ value=0.0;
+ },
+ {
+ species="dummyplus";
+ type="constant";
+ value=0.0;
+ },
+ {
+ ## The value for this seed should be the sum of the values for all ##
+ ## normal neutral seeds. ##
+ species="neutral";
+ type="constant";
+ value=5.2e4;
+ }
+ );
+ ##########################
+ ## Reaction definitions ##
+ ##########################
+
+ ## Impact ionization of N2: e + N2 -> 2 e + X+ + D+ + D- ##
+ ## Since the rate of N2-impact-ionization is a source-term for the ##
+ ## photoionization-equation, we use the dummy species to track this ##
+ ## reaction ##
+
+reactions = (
+ {
+ nin=2;
+ nout=5;
+ specin0="n2";
+ specin1="electrons";
+ specout0="electrons";
+ specout1="electrons";
+ specout2="xplus";
+ specout3="dummyminus";
+ specout4="dummyplus";
+ reacttable="input/n2ion.reaction";
+ },
+ {
+ ## Impact ionization of O2: e + O2 -> 2 e + X+ ##
+ nin=2;
+ nout=3;
+ specin0="o2";
+ specin1="electrons";
+ specout0="electrons";
+ specout1="electrons";
+ specout2="xplus";
+ reacttable="input/o2ion.reaction";
+ },
+ {
+ ## Attachment to O2: e + O2 -> O- + neutral ##
+ nin=2;
+ nout=2;
+ specin0="o2";
+ specin1="electrons";
+ specout0="o2";
+ specout1="neutral";
+ reacttable="input/o2attach2.reaction";
+ },
+ {
+ ## Attachment to O2: e + O2 + O2 -> O2- + O2 ##
+ nin=3;
+ nout=2;
+ specin0="o2";
+ specin1="o2";
+ specin2="electrons";
+ specout0="o2";
+ specout1="o2minus";
+ reacttable="input/o2attach3.reaction";
+ },
+ {
+ ## Attachment to O2: e + O2 + N2 -> O2- + N2 ##
+ nin=3;
+ nout=2;
+ specin0="o2";
+ specin1="n2";
+ specin2="electrons";
+ specout0="o2minus";
+ specout1="n2";
+ reacttable="input/n2o2attach.reaction";
+ },
+ {
+ ## Detachment from O2-: O2- + O2 -> e + 2 O2 ##
+ nin=2;
+ nout=3;
+ specin0="o2";
+ specin1="o2minus";
+ specout0="o2";
+ specout1="o2";
+ specout2="electrons";
+ reacttable="input/o2detach.reaction";
+ },
+ {
+ ## Detachment from O2-: O2- + N2 -> e + O2 + N2 ##
+ nin=2;
+ nout=3;
+ specin0="n2";
+ specin1="o2minus";
+ specout0="n2";
+ specout1="electrons";
+ specout2="o2";
+ reacttable="input/o2n2detach.reaction";
+ },
+ {
+ ## Electron/ion recombination: e + X+ -> X ##
+ nin=2;
+ nout=1;
+ specin0="xplus";
+ specin1="electrons";
+ specout0="neutral";
+ reacttable="input/elecionrecomb.reaction";
+ },
+ {
+ ## Ion/ion recombination: O- + X+ -> X ##
+ nin=2;
+ nout=1;
+ specin0="xplus";
+ specin1="ominus";
+ specout0="neutral";
+ reacttable="input/ominusrecomb.reaction";
+ },
+ {
+ ## Ion/ion recombination: O- + X+ + X -> 2 X + O ##
+ nin=3;
+ nout=3;
+ specin0="xplus";
+ specin1="ominus";
+ specin2="neutral";
+ specout0="neutral";
+ specout1="neutral";
+ specout2="neutral";
+ reacttable="input/ominusneutralrecomb.reaction";
+ },
+ {
+ ## Ion/ion recombination: O2- + X+ -> O2 + X ##
+ nin=2;
+ nout=2;
+ specin0="xplus";
+ specin1="o2minus";
+ specout0="o2";
+ specout1="neutral";
+ reacttable="input/o2minusrecomb.reaction";
+ },
+ {
+ ## Ion/ion recombination: O2- + X+ + X -> O2 + X + X ##
+ nin=3;
+ nout=3;
+ specin0="xplus";
+ specin1="o2minus";
+ specin2="xplus";
+ specout0="o2";
+ specout1="neutral";
+ specout2="neutral";
+ reacttable="input/o2minusneutralrecomb.reaction";
+ }
+ );
diff --git a/input/n2ion.reaction b/input/n2ion.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..5a01393906a32823361a0ba73f3d2fecaae037a3
--- /dev/null
+++ b/input/n2ion.reaction
@@ -0,0 +1,107 @@
+Reaction table automatically generated from BOLSIG+ output file.
+START
+-1.875061e+00
+2.477121e-02
+100
+0.000000e+00
+7.962270e-05
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+0.000000e+00
+2.509800e-20
+1.986690e-18
+1.522800e-17
+6.590340e-17
+2.569020e-16
+9.314460e-16
+3.142890e-15
+9.964470e-15
+2.975100e-14
+8.352840e-14
+2.268690e-13
+5.754210e-13
+1.406616e-12
+3.272610e-12
+7.346100e-12
+1.591890e-11
+3.200700e-11
+6.488820e-11
+1.230648e-10
+2.260230e-10
+4.108740e-10
+7.047180e-10
+1.191591e-09
+1.937340e-09
+3.080850e-09
+4.846170e-09
+7.257270e-09
+1.077240e-08
+1.583430e-08
+2.243310e-08
+3.142890e-08
+4.386510e-08
+5.936100e-08
+7.982010e-08
+1.064127e-07
+1.393362e-07
+1.810440e-07
+2.336370e-07
+2.977920e-07
+3.759060e-07
+4.709400e-07
+5.876880e-07
+7.260090e-07
+8.898510e-07
+1.084713e-06
+1.316235e-06
+1.583430e-06
+1.893630e-06
+2.258820e-06
+2.676180e-06
+3.152760e-06
+3.695610e-06
+4.314600e-06
+5.013960e-06
+5.799330e-06
+6.680580e-06
+7.663350e-06
+8.754690e-06
+9.968700e-06
+1.130679e-05
+1.277601e-05
+1.438200e-05
+1.614450e-05
+1.806210e-05
+2.014890e-05
+2.239080e-05
+2.481600e-05
+2.742450e-05
+3.023040e-05
+3.321960e-05
+3.642030e-05
+3.980430e-05
+4.341390e-05
+4.722090e-05
+5.121120e-05
+5.545530e-05
+5.986860e-05
+6.450750e-05
+6.937200e-05
+7.437750e-05
+7.962270e-05
diff --git a/input/n2o2attach.reaction b/input/n2o2attach.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..d11d2e8330cb5c91669361a2af37ef3e453539f2
--- /dev/null
+++ b/input/n2o2attach.reaction
@@ -0,0 +1,107 @@
+Reaction table for n2o2attach
+START
+-1.875061e+00
+2.477121e-02
+100
+1.140319e-14
+6.494882e-18
+1.140319e-14
+1.123645e-14
+1.107741e-14
+1.093172e-14
+1.079084e-14
+1.065844e-14
+1.053603e-14
+1.042318e-14
+1.029378e-14
+1.018477e-14
+1.009523e-14
+9.989342e-15
+9.902361e-15
+9.799470e-15
+9.714943e-15
+9.631502e-15
+9.549128e-15
+9.451661e-15
+9.371571e-15
+9.292491e-15
+9.198905e-15
+9.106721e-15
+9.000908e-15
+8.896923e-15
+8.780268e-15
+8.637639e-15
+8.471010e-15
+8.269400e-15
+8.036802e-15
+7.741594e-15
+7.406034e-15
+6.988029e-15
+6.520309e-15
+5.982445e-15
+5.402142e-15
+4.860259e-15
+4.236341e-15
+3.697318e-15
+3.193690e-15
+2.697856e-15
+2.316895e-15
+1.962896e-15
+1.682989e-15
+1.444318e-15
+1.229153e-15
+1.080266e-15
+9.460174e-16
+8.231209e-16
+7.376452e-16
+6.618123e-16
+5.879509e-16
+5.370181e-16
+4.891707e-16
+4.444573e-16
+4.098110e-16
+3.771202e-16
+3.462523e-16
+3.204347e-16
+2.974004e-16
+2.760346e-16
+2.549434e-16
+2.365003e-16
+2.199883e-16
+2.039614e-16
+1.888445e-16
+1.751434e-16
+1.626981e-16
+1.502923e-16
+1.389063e-16
+1.283815e-16
+1.184846e-16
+1.092858e-16
+1.005828e-16
+9.272182e-17
+8.505237e-17
+7.817462e-17
+7.166904e-17
+6.556717e-17
+5.988467e-17
+5.476700e-17
+4.996574e-17
+4.549766e-17
+4.136775e-17
+3.753138e-17
+3.406438e-17
+3.087433e-17
+2.790332e-17
+2.520707e-17
+2.273001e-17
+2.046973e-17
+1.839080e-17
+1.649454e-17
+1.478654e-17
+1.322840e-17
+1.180350e-17
+1.051842e-17
+9.356227e-18
+8.295947e-18
+7.353206e-18
+6.494882e-18
diff --git a/input/o2attach2.reaction b/input/o2attach2.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..fbe7ed8157d802378abc196f9d16635f01f22793
--- /dev/null
+++ b/input/o2attach2.reaction
@@ -0,0 +1,107 @@
+Reaction table automatically generated from BOLSIG+ output file.
+START
+-1.875061e+00
+2.477121e-02
+100
+8.103270e-10
+4.960380e-08
+8.103270e-10
+1.097544e-09
+1.453710e-09
+1.886580e-09
+2.406870e-09
+3.021630e-09
+3.733680e-09
+4.548660e-09
+5.455290e-09
+6.478950e-09
+7.619640e-09
+8.851980e-09
+1.018584e-08
+1.161840e-08
+1.314402e-08
+1.474860e-08
+1.642650e-08
+1.820310e-08
+2.000790e-08
+2.186910e-08
+2.375850e-08
+2.570430e-08
+2.766420e-08
+2.959590e-08
+3.155580e-08
+3.351570e-08
+3.547560e-08
+3.740730e-08
+3.931080e-08
+4.118610e-08
+4.303320e-08
+4.483800e-08
+4.661460e-08
+4.836300e-08
+5.006910e-08
+5.171880e-08
+5.332620e-08
+5.489130e-08
+5.642820e-08
+5.786640e-08
+5.924820e-08
+6.057360e-08
+6.181440e-08
+6.298470e-08
+6.405630e-08
+6.505740e-08
+6.595980e-08
+6.676350e-08
+6.746850e-08
+6.804660e-08
+6.854010e-08
+6.892080e-08
+6.918870e-08
+6.934380e-08
+6.940020e-08
+6.932970e-08
+6.917460e-08
+6.892080e-08
+6.858240e-08
+6.814530e-08
+6.763770e-08
+6.704550e-08
+6.641100e-08
+6.570600e-08
+6.495870e-08
+6.415500e-08
+6.333720e-08
+6.247710e-08
+6.160290e-08
+6.071460e-08
+5.982630e-08
+5.893800e-08
+5.804970e-08
+5.717550e-08
+5.632950e-08
+5.549760e-08
+5.467980e-08
+5.390430e-08
+5.317110e-08
+5.246610e-08
+5.178930e-08
+5.118300e-08
+5.059080e-08
+5.006910e-08
+4.958970e-08
+4.916670e-08
+4.880010e-08
+4.847580e-08
+4.822200e-08
+4.802460e-08
+4.788360e-08
+4.779900e-08
+4.778490e-08
+4.782720e-08
+4.795410e-08
+4.813740e-08
+4.837710e-08
+4.870140e-08
+4.912440e-08
+4.960380e-08
diff --git a/input/o2attach3.reaction b/input/o2attach3.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..c797b6c3fd4189a3043e5b05201f727c546c6921
--- /dev/null
+++ b/input/o2attach3.reaction
@@ -0,0 +1,107 @@
+Reaction table automatically generated from BOLSIG+ output file.
+START
+-1.875061e+00
+2.477121e-02
+100
+2.647486e-13
+2.074914e-15
+2.647486e-13
+2.433434e-13
+2.244565e-13
+2.085517e-13
+1.945025e-13
+1.815798e-13
+1.705790e-13
+1.607710e-13
+1.529512e-13
+1.451313e-13
+1.379741e-13
+1.318773e-13
+1.261781e-13
+1.210753e-13
+1.168340e-13
+1.127915e-13
+1.088153e-13
+1.047729e-13
+1.017907e-13
+9.894111e-14
+9.622404e-14
+9.317562e-14
+9.025974e-14
+8.840418e-14
+8.628354e-14
+8.409663e-14
+8.177718e-14
+7.952400e-14
+7.760217e-14
+7.581288e-14
+7.402359e-14
+7.210176e-14
+7.011366e-14
+6.825810e-14
+6.633627e-14
+6.453373e-14
+6.269805e-14
+6.088888e-14
+5.894717e-14
+5.715125e-14
+5.534208e-14
+5.349314e-14
+5.171711e-14
+4.992782e-14
+4.815841e-14
+4.638237e-14
+4.461959e-14
+4.285018e-14
+4.114042e-14
+3.945716e-14
+3.777390e-14
+3.613040e-14
+3.452004e-14
+3.292294e-14
+3.137222e-14
+2.986789e-14
+2.839669e-14
+2.697852e-14
+2.558685e-14
+2.425482e-14
+2.298244e-14
+2.176969e-14
+2.060334e-14
+1.947675e-14
+1.840318e-14
+1.737599e-14
+1.640845e-14
+1.549393e-14
+1.460591e-14
+1.377753e-14
+1.299555e-14
+1.225995e-14
+1.155749e-14
+1.090142e-14
+1.026522e-14
+9.675420e-15
+9.112125e-15
+8.581965e-15
+8.084940e-15
+7.607796e-15
+7.157160e-15
+6.739659e-15
+6.340051e-15
+5.965625e-15
+5.607105e-15
+5.269790e-15
+4.953020e-15
+4.652154e-15
+4.367193e-15
+4.096811e-15
+3.835708e-15
+3.598461e-15
+3.369830e-15
+3.154452e-15
+2.951666e-15
+2.759483e-15
+2.561335e-15
+2.389696e-15
+2.228660e-15
+2.074914e-15
diff --git a/input/o2detach.reaction b/input/o2detach.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..3b51bcd083d7407a41ebe4cf79942ddf46311ac0
--- /dev/null
+++ b/input/o2detach.reaction
@@ -0,0 +1,107 @@
+Reaction table for electron detachment: O2- + O2 -> e- + O2 + O2.
+START
+-1.875061e+00
+2.477121e-02
+100
+3.674894e-15
+1.081081e-05
+3.674894e-15
+3.754518e-15
+3.845705e-15
+3.950385e-15
+4.070882e-15
+4.210005e-15
+4.371175e-15
+4.558584e-15
+4.777414e-15
+5.034119e-15
+5.336803e-15
+5.695737e-15
+6.124063e-15
+6.638761e-15
+7.262007e-15
+8.023084e-15
+8.961114e-15
+1.012901e-14
+1.159926e-14
+1.347252e-14
+1.589057e-14
+1.905601e-14
+2.326289e-14
+2.894472e-14
+3.675117e-14
+4.767221e-14
+6.324223e-14
+8.588049e-14
+1.194673e-13
+1.703321e-13
+2.489705e-13
+3.730597e-13
+5.728112e-13
+9.005403e-13
+1.447876e-12
+2.376796e-12
+3.975561e-12
+6.759153e-12
+1.164819e-11
+2.028384e-11
+3.557277e-11
+6.261033e-11
+1.102028e-10
+1.932990e-10
+3.367295e-10
+5.807146e-10
+9.885782e-10
+1.656952e-09
+2.728403e-09
+4.405870e-09
+6.967599e-09
+1.078058e-08
+1.631002e-08
+2.412231e-08
+3.487954e-08
+4.932461e-08
+6.825740e-08
+9.250414e-08
+1.228830e-07
+1.601698e-07
+2.050673e-07
+2.581817e-07
+3.200074e-07
+3.909211e-07
+4.711856e-07
+5.609604e-07
+6.603179e-07
+7.692639e-07
+8.877590e-07
+1.015740e-06
+1.153142e-06
+1.299911e-06
+1.456027e-06
+1.621509e-06
+1.796428e-06
+1.980916e-06
+2.175164e-06
+2.379434e-06
+2.594054e-06
+2.819422e-06
+3.056005e-06
+3.304338e-06
+3.565025e-06
+3.838740e-06
+4.126222e-06
+4.428279e-06
+4.745787e-06
+5.079691e-06
+5.431004e-06
+5.800813e-06
+6.190275e-06
+6.600625e-06
+7.033173e-06
+7.489313e-06
+7.970524e-06
+8.478370e-06
+9.014512e-06
+9.580708e-06
+1.017882e-05
+1.081081e-05
diff --git a/input/o2ion.reaction b/input/o2ion.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..a9caf58addbe8c6d50c906a96e513f5927d1fc5c
--- /dev/null
+++ b/input/o2ion.reaction
@@ -0,0 +1,107 @@
+Reaction table automatically generated from BOLSIG+ output file.
+START
+-1.875061e+00
+2.477121e-02
+100
+2.351880e-24
+9.382140e-05
+2.351880e-24
+5.592060e-22
+3.932490e-21
+9.133980e-21
+2.670540e-20
+9.533010e-20
+4.277940e-19
+1.880940e-18
+7.905870e-18
+3.079440e-17
+1.115310e-16
+3.766110e-16
+1.189335e-15
+3.532050e-15
+9.917940e-15
+2.629650e-14
+6.625590e-14
+1.591890e-13
+3.650490e-13
+8.022900e-13
+1.693410e-12
+3.444630e-12
+6.765180e-12
+1.284651e-11
+2.364570e-11
+4.227180e-11
+7.353150e-11
+1.246863e-10
+2.062830e-10
+3.337470e-10
+5.287500e-10
+8.213250e-10
+1.252503e-09
+1.876710e-09
+2.769240e-09
+4.024140e-09
+5.764080e-09
+8.148390e-09
+1.138152e-08
+1.570740e-08
+2.144610e-08
+2.897550e-08
+3.876090e-08
+5.139450e-08
+6.755310e-08
+8.802630e-08
+1.138011e-07
+1.459350e-07
+1.859790e-07
+2.350470e-07
+2.951130e-07
+3.680100e-07
+4.557120e-07
+5.607570e-07
+6.856830e-07
+8.330280e-07
+1.005894e-06
+1.207242e-06
+1.441020e-06
+1.710330e-06
+2.017710e-06
+2.367390e-06
+2.765010e-06
+3.211980e-06
+3.715350e-06
+4.276530e-06
+4.902570e-06
+5.594880e-06
+6.360510e-06
+7.203690e-06
+8.128650e-06
+9.139620e-06
+1.024647e-05
+1.144638e-05
+1.275204e-05
+1.417050e-05
+1.569330e-05
+1.734300e-05
+1.910550e-05
+2.100900e-05
+2.303940e-05
+2.522490e-05
+2.753730e-05
+3.001890e-05
+3.264150e-05
+3.543330e-05
+3.839430e-05
+4.153860e-05
+4.483800e-05
+4.832070e-05
+5.198670e-05
+5.586420e-05
+5.991090e-05
+6.416910e-05
+6.859650e-05
+7.326360e-05
+7.808580e-05
+8.313360e-05
+8.837880e-05
+9.382140e-05
diff --git a/input/o2minusneutralrecomb.reaction b/input/o2minusneutralrecomb.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..669092c42ec901f23bc34ad0039735e337d6c421
--- /dev/null
+++ b/input/o2minusneutralrecomb.reaction
@@ -0,0 +1,107 @@
+Reaction table for O2minus-neutral-ion recombination: O2- + X+ + X -> X.
+START
+-1.875061e+00
+2.477121e-02
+100
+1.257124e-07
+8.149557e-16
+1.257124e-07
+1.249125e-07
+1.240234e-07
+1.230362e-07
+1.219415e-07
+1.207293e-07
+1.193890e-07
+1.179097e-07
+1.162801e-07
+1.144888e-07
+1.125244e-07
+1.103758e-07
+1.080325e-07
+1.054852e-07
+1.027258e-07
+9.974824e-08
+9.654895e-08
+9.312742e-08
+8.948680e-08
+8.563446e-08
+8.158255e-08
+7.734835e-08
+7.295453e-08
+6.842922e-08
+6.380575e-08
+5.912213e-08
+5.442026e-08
+4.974474e-08
+4.514149e-08
+4.065615e-08
+3.633234e-08
+3.221001e-08
+2.832388e-08
+2.470216e-08
+2.136568e-08
+1.832742e-08
+1.559249e-08
+1.315858e-08
+1.101674e-08
+9.152495e-09
+7.547049e-09
+6.178604e-09
+5.023610e-09
+4.057890e-09
+3.257592e-09
+2.599938e-09
+2.063757e-09
+1.629830e-09
+1.281066e-09
+1.002533e-09
+7.813966e-10
+6.067805e-10
+4.695841e-10
+3.622795e-10
+2.787031e-10
+2.138546e-10
+1.637109e-10
+1.250588e-10
+9.534902e-11
+7.257123e-11
+5.514839e-11
+4.184934e-11
+3.171708e-11
+2.401056e-11
+1.815793e-11
+1.371927e-11
+1.035709e-11
+7.813096e-12
+5.890082e-12
+4.437744e-12
+3.341742e-12
+2.515230e-12
+1.892337e-12
+1.423164e-12
+1.069952e-12
+8.041597e-13
+6.042313e-13
+4.538993e-13
+3.408964e-13
+2.559776e-13
+1.921795e-13
+1.442600e-13
+1.082743e-13
+8.125542e-14
+6.097223e-14
+4.574776e-14
+3.432181e-14
+2.574762e-14
+1.931409e-14
+1.448721e-14
+1.086605e-14
+8.149626e-15
+6.112020e-15
+4.583688e-15
+3.437402e-15
+2.577700e-15
+1.932959e-15
+1.449446e-15
+1.086857e-15
+8.149557e-16
diff --git a/input/o2minusrecomb.reaction b/input/o2minusrecomb.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..96dd6fd79d0961c0ab2335d41c5e054e46671ef7
--- /dev/null
+++ b/input/o2minusrecomb.reaction
@@ -0,0 +1,107 @@
+Reaction table for O2minus-ion recombination: O2- + X+ -> X.
+START
+-1.875061e+00
+2.477121e-02
+100
+1.380485e-04
+7.323757e-08
+1.380485e-04
+1.376964e-04
+1.373036e-04
+1.368653e-04
+1.363769e-04
+1.358330e-04
+1.352278e-04
+1.345551e-04
+1.338081e-04
+1.329797e-04
+1.320623e-04
+1.310478e-04
+1.299278e-04
+1.286936e-04
+1.273363e-04
+1.258469e-04
+1.242165e-04
+1.224366e-04
+1.204991e-04
+1.183967e-04
+1.161233e-04
+1.136739e-04
+1.110456e-04
+1.082373e-04
+1.052505e-04
+1.020893e-04
+9.876079e-05
+9.527505e-05
+9.164540e-05
+8.788825e-05
+8.402290e-05
+8.007126e-05
+7.605739e-05
+7.200693e-05
+6.794649e-05
+6.390295e-05
+5.990272e-05
+5.597111e-05
+5.213166e-05
+4.840566e-05
+4.481168e-05
+4.136533e-05
+3.807910e-05
+3.496233e-05
+3.202130e-05
+2.925941e-05
+2.667741e-05
+2.427377e-05
+2.204494e-05
+1.998572e-05
+1.808960e-05
+1.634907e-05
+1.475590e-05
+1.330141e-05
+1.197670e-05
+1.077278e-05
+9.680803e-06
+8.692126e-06
+7.798424e-06
+6.991754e-06
+6.264602e-06
+5.609909e-06
+5.021085e-06
+4.492016e-06
+4.017047e-06
+3.590978e-06
+3.209042e-06
+2.866881e-06
+2.560524e-06
+2.286363e-06
+2.041125e-06
+1.821845e-06
+1.625847e-06
+1.450716e-06
+1.294273e-06
+1.154562e-06
+1.029821e-06
+9.184682e-07
+8.190856e-07
+7.304006e-07
+6.512731e-07
+5.806824e-07
+5.177147e-07
+4.615527e-07
+4.114653e-07
+3.667991e-07
+3.269704e-07
+2.914575e-07
+2.597945e-07
+2.315657e-07
+2.063997e-07
+1.839651e-07
+1.639662e-07
+1.461391e-07
+1.302484e-07
+1.160842e-07
+1.034593e-07
+9.220643e-08
+8.217680e-08
+7.323757e-08
diff --git a/input/o2n2detach.reaction b/input/o2n2detach.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..abbb4a315036f8e0ff30a4036cb921d61f25837b
--- /dev/null
+++ b/input/o2n2detach.reaction
@@ -0,0 +1,107 @@
+Reaction table for electron detachment: O2- + N2 -> e- + O2 + N2.
+START
+-1.875061e+00
+2.477121e-02
+100
+1.875746e-16
+7.625682e-08
+1.875746e-16
+1.912100e-16
+1.953635e-16
+2.001189e-16
+2.055766e-16
+2.118570e-16
+2.191057e-16
+2.274997e-16
+2.372556e-16
+2.486409e-16
+2.619881e-16
+2.777140e-16
+2.963459e-16
+3.185566e-16
+3.452133e-16
+3.774448e-16
+4.167368e-16
+4.650658e-16
+5.250927e-16
+6.004437e-16
+6.961236e-16
+8.191316e-16
+9.793910e-16
+1.191170e-15
+1.475283e-15
+1.862544e-15
+2.399260e-15
+3.156063e-15
+4.242307e-15
+5.829773e-15
+8.192122e-15
+1.177113e-14
+1.728870e-14
+2.593732e-14
+3.970489e-14
+6.192883e-14
+9.823887e-14
+1.581513e-13
+2.577380e-13
+4.240328e-13
+7.021711e-13
+1.166694e-12
+1.938941e-12
+3.212929e-12
+5.292353e-12
+8.641115e-12
+1.394873e-11
+2.220980e-11
+3.481356e-11
+5.363536e-11
+8.111804e-11
+1.203285e-10
+1.749741e-10
+2.493674e-10
+3.483329e-10
+4.770585e-10
+6.409042e-10
+8.451856e-10
+1.094957e-09
+1.394817e-09
+1.748752e-09
+2.160038e-09
+2.631200e-09
+3.164024e-09
+3.759630e-09
+4.418568e-09
+5.140947e-09
+5.926575e-09
+6.775100e-09
+7.686138e-09
+8.659392e-09
+9.694755e-09
+1.079239e-08
+1.195279e-08
+1.317684e-08
+1.446583e-08
+1.582149e-08
+1.724601e-08
+1.874203e-08
+2.031264e-08
+2.196140e-08
+2.369231e-08
+2.550985e-08
+2.741891e-08
+2.942486e-08
+3.153351e-08
+3.375113e-08
+3.608445e-08
+3.854068e-08
+4.112751e-08
+4.385312e-08
+4.672624e-08
+4.975611e-08
+5.295254e-08
+5.632594e-08
+5.988734e-08
+6.364839e-08
+6.762148e-08
+7.181967e-08
+7.625682e-08
diff --git a/input/ominusneutralrecomb.reaction b/input/ominusneutralrecomb.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..13a18c78bd052da29bf4bfafc502ed1947037c31
--- /dev/null
+++ b/input/ominusneutralrecomb.reaction
@@ -0,0 +1,107 @@
+Reaction table for Ominus-neutral-ion recombination: O- + X+ + X -> X.
+START
+-1.875061e+00
+2.477121e-02
+100
+1.257124e-07
+8.149557e-16
+1.257124e-07
+1.249125e-07
+1.240234e-07
+1.230362e-07
+1.219415e-07
+1.207293e-07
+1.193890e-07
+1.179097e-07
+1.162801e-07
+1.144888e-07
+1.125244e-07
+1.103758e-07
+1.080325e-07
+1.054852e-07
+1.027258e-07
+9.974824e-08
+9.654895e-08
+9.312742e-08
+8.948680e-08
+8.563446e-08
+8.158255e-08
+7.734835e-08
+7.295453e-08
+6.842922e-08
+6.380575e-08
+5.912213e-08
+5.442026e-08
+4.974474e-08
+4.514149e-08
+4.065615e-08
+3.633234e-08
+3.221001e-08
+2.832388e-08
+2.470216e-08
+2.136568e-08
+1.832742e-08
+1.559249e-08
+1.315858e-08
+1.101674e-08
+9.152495e-09
+7.547049e-09
+6.178604e-09
+5.023610e-09
+4.057890e-09
+3.257592e-09
+2.599938e-09
+2.063757e-09
+1.629830e-09
+1.281066e-09
+1.002533e-09
+7.813966e-10
+6.067805e-10
+4.695841e-10
+3.622795e-10
+2.787031e-10
+2.138546e-10
+1.637109e-10
+1.250588e-10
+9.534902e-11
+7.257123e-11
+5.514839e-11
+4.184934e-11
+3.171708e-11
+2.401056e-11
+1.815793e-11
+1.371927e-11
+1.035709e-11
+7.813096e-12
+5.890082e-12
+4.437744e-12
+3.341742e-12
+2.515230e-12
+1.892337e-12
+1.423164e-12
+1.069952e-12
+8.041597e-13
+6.042313e-13
+4.538993e-13
+3.408964e-13
+2.559776e-13
+1.921795e-13
+1.442600e-13
+1.082743e-13
+8.125542e-14
+6.097223e-14
+4.574776e-14
+3.432181e-14
+2.574762e-14
+1.931409e-14
+1.448721e-14
+1.086605e-14
+8.149626e-15
+6.112020e-15
+4.583688e-15
+3.437402e-15
+2.577700e-15
+1.932959e-15
+1.449446e-15
+1.086857e-15
+8.149557e-16
diff --git a/input/ominusrecomb.reaction b/input/ominusrecomb.reaction
new file mode 100644
index 0000000000000000000000000000000000000000..23fecba4ec2489081fde05f6c4b783afe1b025c4
--- /dev/null
+++ b/input/ominusrecomb.reaction
@@ -0,0 +1,107 @@
+Reaction table for Ominus-ion recombination: O- + X+ -> X.
+START
+-1.875061e+00
+2.477121e-02
+100
+1.380485e-04
+7.323757e-08
+1.380485e-04
+1.376964e-04
+1.373036e-04
+1.368653e-04
+1.363769e-04
+1.358330e-04
+1.352278e-04
+1.345551e-04
+1.338081e-04
+1.329797e-04
+1.320623e-04
+1.310478e-04
+1.299278e-04
+1.286936e-04
+1.273363e-04
+1.258469e-04
+1.242165e-04
+1.224366e-04
+1.204991e-04
+1.183967e-04
+1.161233e-04
+1.136739e-04
+1.110456e-04
+1.082373e-04
+1.052505e-04
+1.020893e-04
+9.876079e-05
+9.527505e-05
+9.164540e-05
+8.788825e-05
+8.402290e-05
+8.007126e-05
+7.605739e-05
+7.200693e-05
+6.794649e-05
+6.390295e-05
+5.990272e-05
+5.597111e-05
+5.213166e-05
+4.840566e-05
+4.481168e-05
+4.136533e-05
+3.807910e-05
+3.496233e-05
+3.202130e-05
+2.925941e-05
+2.667741e-05
+2.427377e-05
+2.204494e-05
+1.998572e-05
+1.808960e-05
+1.634907e-05
+1.475590e-05
+1.330141e-05
+1.197670e-05
+1.077278e-05
+9.680803e-06
+8.692126e-06
+7.798424e-06
+6.991754e-06
+6.264602e-06
+5.609909e-06
+5.021085e-06
+4.492016e-06
+4.017047e-06
+3.590978e-06
+3.209042e-06
+2.866881e-06
+2.560524e-06
+2.286363e-06
+2.041125e-06
+1.821845e-06
+1.625847e-06
+1.450716e-06
+1.294273e-06
+1.154562e-06
+1.029821e-06
+9.184682e-07
+8.190856e-07
+7.304006e-07
+6.512731e-07
+5.806824e-07
+5.177147e-07
+4.615527e-07
+4.114653e-07
+3.667991e-07
+3.269704e-07
+2.914575e-07
+2.597945e-07
+2.315657e-07
+2.063997e-07
+1.839651e-07
+1.639662e-07
+1.461391e-07
+1.302484e-07
+1.160842e-07
+1.034593e-07
+9.220643e-08
+8.217680e-08
+7.323757e-08
diff --git a/input/photo_values.cfg b/input/photo_values.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..575fab77fb3445115472025175606b34678691e9
--- /dev/null
+++ b/input/photo_values.cfg
@@ -0,0 +1,62 @@
+filename="photo_values.cfg";
+
+events =
+ {
+ ## 10ppb02.photo ##
+ nin=2;
+ A0=-4.14278e-17;
+ A1=-6.16399e-15;
+ lambda0=-1.01012e-20;
+ lambda1=-3.74197e-19;
+ },
+ {
+ ## 1ppbO2.photo
+ nin= 2;
+ A0=-4.14278e-18;
+ A1=-6.16399e-16;
+ lambda0=1.01012e-22;
+ lambda1=-3.74197e-21;
+ },
+ {
+ ## 1ppmN2.photo
+ nin= 2;
+ A0=-4.14278e-09;
+ A1=-6.16398e-07;
+ lambda0=-0.000101011;
+ lambda1=-0.00374197;
+ },
+ {
+ ## 1ppmO2.photo
+ nin= 2;
+ A0=-4.14278e-15;
+ A1=-6.16399e-13;
+ lambda0=-1.01012e-16;
+ lambda1=-3.74197e-15;
+ },
+ {
+ ## air_1atm_3term
+ nin=3;
+ A0=-3.064258211257769079e-09;
+ A1=-1.676017200059491931e-08;
+ A2=-1.680217549583392655e-08;
+ lambda0=-2.029823458382051625e-05;
+ lambda1=-2.080524917212339816e-04;
+ lambda2=-2.025357858924288772e-04;
+ },
+ {
+ ## air760torr-ml-60; equal to air760torr !!
+ nin=2;
+ A0=-8.28556e-10;
+ A1=-1.2328e-07;
+ lambda0=-4.04047e-06;
+ lambda1=-0.000149679;
+ },
+ {
+ ## air760torr
+ nin=2;
+ A0=-8.28556e-10;
+ A1=-1.2328e-07;
+ lambda0=-4.04047e-06;
+ lambda1=-0.000149679;
+ }
+ )
diff --git a/input/user_continue.cfg b/input/user_continue.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..1e68f3bc28e419d0b0239758fc03ae514575fc51
--- /dev/null
+++ b/input/user_continue.cfg
@@ -0,0 +1,506 @@
+name = "default";
+param = (
+ {
+ type = "string";
+ name = "prog_id";
+ comment = "An identification name for this run";
+ value = "example";
+ },
+ {
+ type = "string";
+ name = "output_dir";
+ comment = "Output directory";
+ value = "output";
+ },
+ {
+ type = "string";
+ name = "kin_input";
+ comment = "Kinetics input file";
+ value = "input/kinetic_example.cfg";
+ },
+ {
+ type = "int";
+ name = "restart";
+ comment = "If restart is 1 (TRUE), the simulation will continue with data from a previous run";
+ value = 0;
+ },
+ {
+ type = "string";
+ name = "load_file";
+ comment = "If restart is TRUE, the name of the file with data from previous run, otherwise empty";
+ value = "";
+ },
+ {
+ type = "double";
+ name = "output_dt";
+ comment = "Time interval for output to be written to disk";
+ value = 0.1;
+ },
+ {
+ type = "int";
+ name = "pois_output";
+ comment = "Output of the Poisson grids, including the potential?";
+ value = 0;
+ },
+ {
+ type = "int";
+ name = "cdr_output_margin";
+ comment = "Margin outside the grids in the output of the cdr equation";
+ value = 0;
+ },
+ {
+ type = "int";
+ name = "pois_output_margin";
+ comment = "Margin outside the grids in the output of the poisson equation";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "warn_min_timestep";
+ comment = "If the time steps are smaller than this number, the program issues a warning";
+ value = 1e-06;
+ },
+ {
+ type = "int";
+ name = "max_disk_space_mb";
+ comment = "Maximum disk space, in Mb, to use";
+ value = 1048576;
+ },
+ {
+ type = "int";
+ name = "gridpoints_r";
+ comment = "Number of R gridpoints at level 0";
+ value = 600;
+ },
+ {
+ type = "int";
+ name = "gridpoints_z";
+ comment = "Number of Z gridpoints at level 0";
+ value = 600;
+ },
+ {
+ type = "int";
+ name = "max_ntheta";
+ comment = "Number of azimuthal gridcells and modes";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "start_t";
+ comment = "Initial time";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "end_t";
+ comment = "End time";
+ value = 0.45;
+ },
+ {
+ type = "double";
+ name = "attempt_dt";
+ comment = "Attempted timestep. The actual timestep may be larger";
+ value = 50.0;
+ },
+ {
+ type = "int";
+ name = "extra_pois_levels";
+ comment = "Extra levels for the Poisson solver";
+ value = 2;
+ },
+ {
+ type = "int";
+ name = "max_levels";
+ comment = "Maximum level of refinement. Use a big number here";
+ value = 64;
+ },
+ {
+ type = "double";
+ name = "pois_max_error";
+ comment = "Error threshold that leads to refinement in the Poisson code.";
+ value = 0.001;
+ },
+ {
+ type = "int";
+ name = "pois_max_level";
+ comment = "Maximum level of refinement in the Poisson equation.";
+ value = 3;
+ },
+ {
+ type = "int";
+ name = "extra_photo_levels";
+ comment = "Extra levels for the photo-ionization solver";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_max_level";
+ comment = "Maximum level of refinement in the photo-ionization solver.";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "photo_max_error";
+ comment = "Error threshold that leads to refinement in the photo-ionization code.";
+ value = 0.01;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_right";
+ comment = "Photo-ionization boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_bottom";
+ comment = "Photo-ionization boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_top";
+ comment = "Photo-ionization boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "extra_photo_levels_2";
+ comment = "Extra levels for the photo-ionization solver";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_max_level_2";
+ comment = "Maximum level of refinement in the photo-ionization solver.";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "photo_max_error_2";
+ comment = "Error threshold that leads to refinement in the photo-ionization code.";
+ value = 0.01;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_right_2";
+ comment = "Photo-ionization boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_bottom_2";
+ comment = "Photo-ionization boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "photo_bnd_top_2";
+ comment = "Photo-ionization boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_bottom";
+ comment = "Particles boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_top";
+ comment = "Particles boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_bnd_right";
+ comment = "Particles boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_right";
+ comment = "Potential boundary condition at r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_bottom";
+ comment = "Potential boundary condition at z = 0. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "int";
+ name = "pois_bnd_top";
+ comment = "Potential boundary condition at z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet";
+ value = -1;
+ },
+ {
+ type = "double";
+ name = "nu_a";
+ comment = "Maximum advection Courant number";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_d";
+ comment = "Maximum diffusion Courant number";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_rt";
+ comment = "Maximum ratio of dt/relaxation time";
+ value = 0.2;
+ },
+ {
+ type = "double";
+ name = "nu_f";
+ comment = "Maximum ratio of change of the densities (set to a very large number to ignore)";
+ value = 1e+20;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_eabs";
+ comment = "Refinement threshold for the electric field";
+ value = 0.2;
+ },
+ {
+ type = "int";
+ name = "ref_level_eabs";
+ comment = "Maximum refinement level reached through ref_threshold_eabs";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_charge";
+ comment = "Refinement threshold for the curvature of the charge";
+ value = 0.004;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_dens";
+ comment = "Refinement threshold for the curvature of the densities";
+ value = 0.004;
+ },
+ {
+ type = "double";
+ name = "ref_threshold_edge";
+ comment = "Refinement threshold for the densities in the leading edge";
+ value = 10000.0;
+ },
+ {
+ type = "int";
+ name = "cdr_brick_dr";
+ comment = "r-length of the minimal refinement area in the cdr equation";
+ value = 8;
+ },
+ {
+ type = "int";
+ name = "cdr_brick_dz";
+ comment = "z-length of the minimal refinement area in the cdr equation";
+ value = 8;
+ },
+ {
+ type = "int";
+ name = "cdr_max_level";
+ comment = "Maximum level of refinement in the Fluid equation.";
+ value = 3;
+ },
+ {
+ type = "int";
+ name = "cdr_interp_in";
+ comment = "Interpolation method for the grid interior (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "cdr_interp_bnd";
+ comment = "Interpolation method for the grid boundaries (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog";
+ value = 1;
+ },
+ {
+ type = "double";
+ name = "L_r";
+ comment = "Length in r of the complete domain";
+ value = 13044.0;
+ },
+ {
+ type = "double";
+ name = "L_z";
+ comment = "Length in z of the complete domain";
+ value = 13044.0;
+ },
+ {
+ type = "double";
+ name = "diffusion_coeff";
+ comment = "Isotropic difussion coefficient";
+ value = 0.1;
+ },
+ {
+ type = "int";
+ name = "has_photoionization";
+ comment = "Whether the code includes photoionization or not";
+ value = 1;
+ },
+ {
+ type = "string";
+ name = "photoionization_file";
+ comment = "The name of a file from which we can read the photoionization parameters";
+ value = "input/air760torr.photo";
+ },
+ {
+ type = "double";
+ name = "attachment_rate";
+ comment = "Rate of dissociative attachment";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "attachment_E0";
+ comment = "E0 in the exp(-E0/E) factor in the attachment expression.";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_x";
+ comment = "x component of the external electric field";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_y";
+ comment = "y component of the external electric field";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "E0_z";
+ comment = "z component of the external electric field";
+ value = -0.06;
+ },
+ {
+ type = "double";
+ name = "rise_time";
+ comment = "Rise time of the electric field (0 for instantaneous rise)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "off_time";
+ comment = "Time to switch off the electric field (0.0 means never)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_x";
+ comment = "x width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_y";
+ comment = "y width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_sigma_z";
+ comment = "z width of the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "seed_N";
+ comment = "Number of electrons in the initial seed";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "background_ionization";
+ comment = "Initial at z=0 densities of electrons and ions";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "background_increase_length";
+ comment = "Length of exponential increase of the pre-ionization (for atmospherical models)";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "pois_inhom";
+ comment = "Use the point-plane geometry?";
+ value = 1;
+ },
+ {
+ type = "int";
+ name = "pois_inhom_reflections";
+ comment = "Number of mirror charges to use";
+ value = 4;
+ },
+ {
+ type = "double";
+ name = "needle_length";
+ comment = "Length of the needle";
+ value = 2500.0;
+ },
+ {
+ type = "double";
+ name = "needle_radius";
+ comment = "Radius of the needle";
+ value = 400.0;
+ },
+ {
+ type = "double";
+ name = "pois_inhom_fixed_q";
+ comment = "If nonzero, the charge is fixed, not floating (simulation of charged clouds close to the earth surface)";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "constant_source";
+ comment = "Constant ionization rate";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "perturb_epsilon";
+ comment = "Initial perturbation to the axisymmetric configuration";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "perturb_max_k";
+ comment = "Perturb only modes up to perturb_max_k (large number to perturb all)";
+ value = 1024;
+ },
+ {
+ type = "int";
+ name = "sprite_module";
+ comment = "1 if the sprite module is activated, 0 otherwise";
+ value = 0;
+ },
+ {
+ type = "double";
+ name = "dens_decay_len";
+ comment = "Lenght of exponential decay of the density w/r to altitude";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "sprite_dens_0";
+ comment = "Density at z = 0";
+ value = 0.0;
+ },
+ {
+ type = "double";
+ name = "sprite_dens_q";
+ comment = "Quenching density";
+ value = 0.0;
+ },
+ {
+ type = "int";
+ name = "sprite_sign";
+ comment = "Sign of the sprite head that we are following (the other will not be reliable";
+ value = -1;
+ } );
diff --git a/input/user_init.cfg b/input/user_init.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..e4b8d1b7f7c506d16b1141f8348393058546edee
--- /dev/null
+++ b/input/user_init.cfg
@@ -0,0 +1,27 @@
+name = "user_init";
+param = (
+ {
+ type = "string";
+ name = "output_dir";
+ comment = "Output directory";
+ value = "output";
+ },
+ {
+ type = "int";
+ name = "restart";
+ comment = "If restart is 1 (TRUE), the simulation will continue with data from a previous run";
+ value = 0;
+ },
+ {
+ type = "string";
+ name = "load_file";
+ comment = "If restart is TRUE, the name of the file with data from previous run, otherwise empty";
+ value = "";
+ },
+ {
+ type = "double";
+ name = "end_t";
+ comment = "End time";
+ value = 0.450;
+ }
+);
diff --git a/libconfig-1.4.9/AUTHORS b/libconfig-1.4.9/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..f3f746557ebf09490b9268e09e772652964e5153
--- /dev/null
+++ b/libconfig-1.4.9/AUTHORS
@@ -0,0 +1,5 @@
+
+Mark Lindner - Lead developer & maintainer.
+Daniel Marjamäki - Enhancements & bugfixes.
+Andrew Tytula - Windows port.
+Glenn Herteg - Enhancements, bugfixes, documentation corrections.
diff --git a/libconfig-1.4.9/COPYING.LIB b/libconfig-1.4.9/COPYING.LIB
new file mode 100644
index 0000000000000000000000000000000000000000..b124cf581250c210960185e8fbf6c967a0538721
--- /dev/null
+++ b/libconfig-1.4.9/COPYING.LIB
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/libconfig-1.4.9/ChangeLog b/libconfig-1.4.9/ChangeLog
new file mode 100644
index 0000000000000000000000000000000000000000..52125e9fbe9e0e1c8a86bf5a5d4c3a357baeabfc
--- /dev/null
+++ b/libconfig-1.4.9/ChangeLog
@@ -0,0 +1,623 @@
+ ----- version 1.4.9 ------
+
+2012-09-28 Mark Lindner
+
+ * lib/libconfigcpp.c++ - Fixed compiler warnings in constructor
+ initializers
+ * tinytest/tiytest.c, tinytest/tinytest.h - added tt_file_exists();
+ added alternate implementations of some test macros since MSVC does
+ not support C99 fully; added comparators for text files (ignoring
+ line endings)
+ * tests/tests.c - use tt_file_exists() rather than access(); alias
+ snprintf to _snprintf for MSVC; compare files as text files rather
+ than as binary files
+ * lib/scanner.l - fixed parsing issue when backslash in string is
+ followed by invalid escape character; reported by Jimmy Scott
+ * lib/scanner.c - regenerated
+ * lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am,
+ doc/libconfig.texi, configure.ac - bump version numbers
+ * aclocal.m4, ac_config.h - regenerated
+ * m4/*, aux-build/*, libtool - updated to newer
+
+2011-12-30 Mark Lindner
+
+ * debian/control - updates from Jonathan McCrohan
+
+ ----- version 1.4.8 ------
+
+2011-08-04 Mark Lindner
+
+ * tests/Makefile.am - marked 'libconfig_tests' as non-installable
+ * lib/scanner.l, lib/grammar.y - grammar changes to make trailing
+ semicolons optional (and to allow commas as an alternative)
+ * lib/libconfig.c - bugfixes for lack of auto-conversion handling in
+ the config_lookup*() functions (reported by Feng Yu), and some
+ fixes for compiler warnings
+ * lib/Makefile.am - bump .so version
+ * configure.ac - bump version, add '-Wno-unused-parameter' compiler
+ switch to disable "unused parameter" warnings
+ * doc/libconfig.texi - documentation updates; added a chapter that
+ calls attention to the bundled example programs
+ * lib/libconfig.h, lib/libconfig.h++ - bump versions
+
+ ----- version 1.4.7 ------
+
+2011-03-11 Mark Lindner
+
+ * doc/libconfig.texi - fixed typo; updated docs
+ * TODO - updated list
+ * lib/libconfig.c, lib/libconfig.h, lib/libconfigcpp.c++,
+ lib/libconfig.h++ - added config{get,set}_default_format(),
+ Config::{get,set}DefaultFormat()
+
+2011-03-10 Mark Lindner
+
+ * lib/libconfig.c - fixed memory leak when encountering a parse error
+ in an @include'd file
+ * lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am, configure.ac,
+ doc/libconfig.texi - bump versions
+
+ ----- version 1.4.6 ------
+
+2010-09-10 Mark Lindner
+
+ * doc/libconfig.texi - documentation updates
+ * lib/libconfig.c, lib/libconfigcpp.c++, lib/libconfig.h,
+ lib/libconfig.h++, lib/wincompat.h, lib/scanctx.c - added support
+ for specifying an include directory
+ * m4/* - added local m4 directory
+ * contrib/* - added user-contributed files
+
+2010-09-07 Mark Lindner
+
+ * lib/scanner.l - bugfix for parse error when there is a missing
+ newline at the end of the file
+ * lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am - bump version
+ * tinytest/* - added a simple unit testing framework
+ * tests/* - added preliminary unit tests
+ * configure.ac, ac_config.h, ac_config.h.in, Makefile.am,
+ lib/Makefile.am, libtool, doc/libconfig.texi - bump versions/dates
+ * lib/grammar.h, lib/grammar.c - regenerated with newer version of
+ Bison
+ * lib/libconfig.c - bugfix: explicitly set starting line number to 1
+ when parsing from strings; otherwise line numbers reported in parse
+ errors are undefined
+
+ ----- version 1.4.5 ------
+
+2010-05-04 Mark Lindner
+
+ * lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am - bumped version
+ numbers; removed #include for