\documentclass[a4paper,12pt,notitlepage]{report}

\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage[dvips]{graphicx}

\newcommand{\Rb}{\mathbf R}
\newcommand{\nb}{\boldsymbol \nabla}

\author{Carlo Sbraccia}

\begin{document}

\title{How to implement new constraints into the Quantum-ESPRESSO package.}
%
\maketitle

The two basic ingredients that are required to implement a new type of
constraint into the Quantum-ESPRESSO package are:
%
\begin{itemize}
\item the analytical expression for the constraint $\sigma(\{\Rb^{3N}\})$ (it
must be a function of the ionic coordinates $\{\Rb^{3N}\}$ only);
\item the analytical expression for the gradients of the constraint
$\nb_{\Rb_i}\sigma(\{\Rb^{3N}\})$ with respect to the ionic coordinates.
\end{itemize}
%
Given these expressions one has simply to follow what has already been done for
the standard constraint types.%
%
\footnote{At present the constraint types implemented in Quantum-ESPRESSO are:
\begin{itemize}
\item coordination numbers;
\item distances;
\item planar angles (linear angles included);
\item torsional angles.
\end{itemize}}
%
No detailed knowledge of the algorithm used to impose the constraints (SHAKE) is
necessary since the implementation is designed to work for any possible kind of
constraint, provided it is defined by an analytical expression. In the
following I describe the three basic steps that are strictly necessary to
implement a new constraint type.

One first has to modify the routine that reads the \texttt{CONSTRAINTS}
input card (this input card contains the parameters specified at run-time by the
user to define the constraint). The name of this routine is
\texttt{card\_constraints()} and it is located in the module
\texttt{Modules/read\_cards.f90}. Note the maximum allowed number of input
parameters used to define a single constraint is 6; if the new constraint type
requires additional input parameters one has to modify the dimension of the
array \texttt{constr\_inp(:,:)} defined in the module
\texttt{Modules/input\_parameters.f90}. All the other arrays are dynamically
allocated.

Then one has to copy the input arrays into the internal ones (this is
automatically done and should not not require any additional tuning) and to
initialise the target value of each constraint (the target corresponds to the
initial value of $\sigma_i(\{\Rb^{3N}_0\}$; this is the quantity that is kept
constant during the simulation).
All this is done in the routine \texttt{init\_constraint()} which is
located in the module \texttt{Modules/constraints\_module.f90}. One has to
define the new variables that are needed to calculate the value of the
constraint (possibly recicling those that are already there) and then implement
the equation defining the constraint (following what is done for the other
constraint types).

The last step consists in the implementation of the constraint's gradient
$\nb\sigma(\{\Rb^{3N}\})$. This is done in the routine
\texttt{constraint\_grad()} located in the module
\texttt{Modules/constraints\_module.f90}. Again one has to define the new
variables and implement the equations that define both the constraint violation
and the constraint gradients (respectively stored in \texttt{g} and
\texttt{dg(:,:)}). This is done for a single constraint $\sigma_i$ (identified
by the input variable \texttt{index}) since the routine is externally called by
other drivers as many times as the number of constraints. Note that for each
constraint the sum of the gradients must be zero: $\sum_{i}
\nb_{\Rb_i}\sigma(\{\Rb^{3N}\}) = 0$. This is usually imposed by defining one of
the gradients to be equal to minus the sum of all the others.

Finally, one should not forget to test the new constraint on both PWscf and CP
by monitoring the energy conservation and, of course, the consrevation of the
constraint itself.

\end{document}
