1%%%%%%%%%%%%%%%%%%%
2% XLiFE++ is an extended library of finite elements written in C++
3%     Copyright (C) 2014  Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin
4%
5%     This program is free software: you can redistribute it and/or modify
6%     it under the terms of the GNU General Public License as published by
7%     the Free Software Foundation, either version 3 of the License, or
8%     (at your option) any later version.
9%     This program is distributed in the hope that it will be useful,
10%     but WITHOUT ANY WARRANTY; without even the implied warranty of
11%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12%     GNU General Public License for more details.
13%     You should have received a copy of the GNU General Public License
14%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
15%%%%%%%%%%%%%%%%%%%
16
17\section{The {\classtitle Kernel} class}
18The {\class Kernel} class is intended to deal with kernel, say function $G(x,y)$ where $x,y$ are two points. Basically, it manages the function itself using {\class Function} object that is able to deal with such function but it manages other functions such as $\nabla_xG$, $\nabla_yG$, $\nabla_{xy}G$, $\frac{\partial G}{\partial n_x}$, $\frac{\partial G}{\partial n_y}$:
19\begin{lstlisting}[]{}
20public:
21Function kernel;
22Function gradx;
23Function grady;
24Function gradxy;
25Function ndotgradx;
26Function ndotgrady;
27Parameters userData;
28\end{lstlisting}
29All functions defined in {\class Kernel} class share the same parameters given by \textbf{userData}. Besides, the class provides some additional properties:
30\begin{lstlisting}[]{}
31SingularityType singularType;   // singularity type
32real_t singularOrder;           // singularity order
33complex_t singularCoefficient;  // singularity coefficient
34SymType symmetry;               // kernel symmetry
35string_t name;                  // kernel name
36dimen_t dimPoint;               // dim of points x,y
37//temporary data
38mutable bool checkType_;       // to activate checking mode
39mutable bool conjugate_;       // flag for conjugate operation
40mutable bool transpose_;       // flag for transpose operation
41mutable bool xpar;             // true if x is consider as a parameter
42mutable Point xory;            // x/y as parameter of the kernel
43 //to manage data requirements
44bool requireNx;              // true if requires normal or x-normal vector
45bool requireNy;              // true if requires y-normal vector
46bool requireElt;             // true if requires element
47bool requireDom;             // true if requires domain
48bool requireDof;             // true if requires dof
49\end{lstlisting}
50The following singularity types are currently available:
51\begin{lstlisting}[]{}
52enum SingularityType {_notsingular, _r, _logr,_loglogr};
53\end{lstlisting}
54\vspace{.2cm}
55It is also possible to specify the singular and regular part using {\class Kernel} pointer (0 by default):
56\begin{lstlisting}[]{}
57Kernel* singPart;
58Kernel* regPart;
59\end{lstlisting}
60There are simple constructors from {\class Function} objects or from explicit C++ functions having a kernel form (see {\class Function} class):
61\begin{lstlisting}[]{}
62Kernel();                            // default constructor
63Kernel(const Kernel&);               // copy constructor
64Kernel& operator=(const Kernel&);    // assign operator
65//from Function object
66Kernel(const Function& ker, SingularityType st=_notsingular,
67       real_t so=0, SymType sy=_noSymmetry);
68Kernel(const Function& ker, const string_t& na, SingularityType st=_notsingular,
69       real_t so=0, SymType sy=_noSymmetry);
70//from explicit function having a kernel form
71template <typename T>
72Kernel(T(fun)(const Point&, const Point&, Parameters&),
73       SingularityType st=_notsingular, real_t so=0, SymType sy=_noSymmetry);
74template <typename T>
75Kernel(T(fun)(const Point&, const Point&, Parameters&), const string_t& na,
76       SingularityType st=_notsingular, real_t so=0, SymType sy=_noSymmetry);
77...
78virtual void initParameters();  //to share user parameters
79\end{lstlisting}
80Note that these simple constructors do not allow to set other functions (gradx, grady, ...).\\
81
82This class provides some accessors:
83\begin{lstlisting}[]{}
84bool conjugate() const;
85bool& conjugate();
86void conjugate(bool v) const;
87bool transpose() const;
88bool& transpose();
89void transpose(bool v) const;
90virtual bool isSymbolic() const;
91virtual ValueType valueType() const;
92virtual StrucType structType() const;
93virtual dimPair dims() const;
94\end{lstlisting}
95\vspace{.2cm}
96It provides also some tools to manage parameters:
97\begin{lstlisting}[]{}
98void setParameters(const Parameters& par);
99void setParameter(Parameter& par);
100template<typename T>
101 void setParameter(const string_t& name, T value);
102template<typename T>
103 T getParameter(const string_t& name, T value) const;
104void setX(const Point& P) const;
105void setY(const Point& P) const;
106\end{lstlisting}
107\vspace{.2cm}
108and some functions to manage the kernel data required during computation:
109\begin{lstlisting}[]{}
110bool normalRequired() const;
111bool xnormalRequired() const;
112bool ynormalRequired() const;
113void require(UnitaryVector uv, bool tf=true);
114void require(const string_t& s, bool tf=true);
115\end{lstlisting}
116\vspace{.2cm}
117In some computations, a {\class Kernel} object has to be viewed as a {\class Function} object, x or y being considered as a parameter. the following member functions do the job:
118\begin{lstlisting}[]{}
119//move to y->k(x,y) or  x->k(x,y)
120const Function& operator()(const Point& x, variableName vn ) const;
121const Function& operator()(variableName vn, const Point& y) const;
122const Function& operator()(variableName vn) const;
123\end{lstlisting}
124\vspace{.1cm}
125\textbf{variableName} is defined by the following enumeration:
126\begin{lstlisting}[]{}
127enum VariableName {_x, _x1=_x, _y, _x2=_y, _z, _x3=_z, _t};
128\end{lstlisting}
129\vspace{.2cm}
130The class provides function to evaluate kernel:
131\begin{lstlisting}[]{}
132template<typename T>
133 T& operator()(const Point&, const Point&, T&) const;//compute at (x,y)
134template<typename T>
135 T& operator()(const Point&, T&) const;  //compute at (x,P) or (P,y) with P=xory
136template<typename T>
137 Vector<T>& operator()(const Vector<Point>&,const Vector<Point>&,
138                           Vector<T>&) const; //compute at a list of points
139\end{lstlisting}
140As the {\class Kernel} class is the base class of {\class TensorKernel} class which deals with particular kernel, there are some virtual functions:
141\begin{lstlisting}[]{}
142virtual KernelType type() const;                 //_generalKernel, _tensorKernel
143virtual const TensorKernel* tensorKernel() const;//downcast to tensorkernel
144virtual TensorKernel* tensorKernel();            //downcast to tensorkernel*
145\end{lstlisting}
146\vspace{.2cm}
147To deal with some data that are available during FE computation such as normal vectors, current element, current dof or current domain, there is two things to do : tell to \xlifepp that the Kernel will use such data
148\begin{lstlisting}[]{}
149Kernel K(ker);     //link a C++ function(kernel) to a Kernel object
150K.require(_nx);    //tell that function ker will use normal vector
151\end{lstlisting}
152and get data in the C++ function related to the Kernel object:
153\begin{lstlisting}[]{}
154Real ker(const Point& x, const Point&y, Parameters& pars=theDefaultParameters)
155{...
156Vector<Real>& n = getN();      //get the normal vector
157...
158}
159\end{lstlisting}
160This machinery is based on the {\class ThreadData} class that manages one instance of data by thread.
161
162\vspace{.2cm}
163As an example, we give the sketch of the program constructing the Laplace kernel in 3d:
164\begin{lstlisting}[]{}
165Kernel Laplace3dKernel(Parameters& pars)
166{
167    Kernel K;
168    K.name="Laplace 3D kernel";
169    K.singularType =_r;
170    K.singularOrder = -1;
171    K.singularCoefficient = over4pi;
172    K.symmetry=_symmetric;
173    K.userData.push(pars);
174    K.kernel = Function(Laplace3d, K.userData);
175    K.gradx = Function(Laplace3dGradx, K.userData);
176    K.grady = Function(Laplace3dGrady, K.userData);
177    K.ndotgradx = Function(Laplace3dNxdotGradx, K.userData);
178    K.ndotgrady = Function(Laplace3dNydotGrady, K.userData);
179    return K;
180}
181
182real_t Laplace3d(const Point& x, const Point& y, Parameters& pars)
183{
184  real_t r = x.distance(y);
185  return over4pi / r;
186}
187
188//derivatives
189Vector<real_t> Laplace3dGradx(const Point& x, const Point& y,Parameters& pars)
190{
191  real_t r2 = x.squareDistance(y);
192  real_t r = std::sqrt(r2);
193  Vector<real_t> g1(3);
194  scaledVectorTpl(over4pi / (r*r2), x.begin(), x.end(), y.begin(), g1.begin());
195  return g1;
196}
197
198Vector<real_t> Laplace3dGrady(const Point& x, const Point& y,Parameters& pars)
199{
200  real_t r2 = x.squareDistance(y);
201  real_t r = std::sqrt(r2);
202  Vector<real_t> g1(3);
203  scaledVectorTpl(-over4pi / (r*r2), x.begin(), x.end(), y.begin(), g1.begin());
204  return g1;
205}
206
207real_t Laplace3dNxdotGradx(const Point& x, const Point& y, Parameters& pars)
208{
209 Vector<real_t>& nxp = getNx(); //get normal at x point
210 std::vector<real_t>::const_iterator itx=x.begin(),ity=y.begin(), itn=nxp.begin();
211 real_t d1=(*itx++ - *ity++), d2=(*itx++ - *ity++), d3=(*itx - *ity);
212 real_t r = d1* *itn++; r+= d2* *itn++; r+=d3* *itn;
213 real_t r3= d1*d1+d2*d2+d3*d3; r3*=std::sqrt(r3);
214 return -r*over4pi_/r3;
215}
216...
217\end{lstlisting}
218See in the \textit{mathRessources} directory, the kernels that are avalaible.\\
219
220\displayInfos{library=utils, header=Kernel.hpp, implementation=Kernel.cpp, test=test\_Function.cpp,
221header dep={config.h, Parameters.hpp, Point.hpp, String.hpp, Vector.hpp, Function.hpp}}
222
223\section{The {\classtitle TensorKernel} class}
224
225The {\class TensorKernel} class, inherited from the {\class Kernel} class, deals with kernels of the form:
226$$K(x,y)=\sum_{1\le m\le M}\sum_{1\le n\le N} \psi_m(x)\mathbb{A}_{mn}\phi_n(y)$$
227with $\mathbb{A}$ a $M\times N$ matrix. Such kernel is involved, for instance, in Dirichlet to Neumann method using spectral expansion. In many cases, this matrix is a diagonal one:
228$$K(x,y)=\sum_{1\le n\le N} \psi_n(x)\lambda_n\phi_n(y).$$
229In the meaning of \xlifepp, the families $(\psi_m)_{1\le m\le M}$ and  $(\psi_n)_{1\le n\le N}$ may be considered as some basis of spectral space, say {\class SpectralBasis} object. So, the  {\class TensorKernel} class is defined as follow:
230\begin{lstlisting}[]{}
231protected :
232 const SpectralBasis* phi_p;
233 const SpectralBasis* psi_p;
234 VectorEntry* matrix_p;
235public :
236 bool isDiag;       // true if matrix is a diagonal one
237 Function xmap;     // geometric transformation applied to x
238 Function ymap;     // geometric transformation applied to y
239 bool isConjugate;  // conjugate phi_p in computation (default=false)
240\end{lstlisting}
241\vspace{.1cm}
242The \textbf{xmap} and \textbf{ymap} functions allow to map the basis functions from a reference space to an other one. For instance, suppose  the basis $\cos(n\pi x)$ on the segment $]0,1[$ is given:
243\begin{lstlisting}[]{}
244Real cosn(const Point& P, Parameters& pars)
245{ Real x=P(1);
246  Int n=pa("basis index")-1;  //get the index of function to compute
247  return cos(n*pi*x);
248}
249\end{lstlisting}
250and has to be used on the boundary $\Sigma=\{(0,y), 0<y<h\}$. The basis will be map onto using the function:
251\begin{lstlisting}[]{}
252Point sigmaTo(const Point& P, Parameters& pars)
253{
254  return Point(P(2)/h);
255}
256\end{lstlisting}
257\vspace{.1cm}
258The {\class SpectralBasis} class manages either a basis given by an explicit C++ function (analytic form) or a basis given by a set of \textbf{TermVector} objects (numerical form). So the constructors provided by the {\class TensorKernel} class manages these different cases too:
259\begin{lstlisting}[]{}
260TensorKernel();    //default constructor
261template<typename T>
262 //from one or two SpectralBasis objects
263 TensorKernel(const SpectralBasis&, const vector<T>&, bool conj=false);
264 TensorKernel(const SpectralBasis&, const vector<T>&, const SpectralBasis&);
265 //from one or two Unknown objects belonging to spectral spaces
266 TensorKernel(const Unknown&, const vector<T>&, bool conj=false);
267 TensorKernel(const Unknown&, const vector<T>&, const Unknown&);
268 //from one or two Function objects
269 TensorKernel(Function, const vector<T>&, bool conj=false);
270 TensorKernel(Function, const vector<T>&, Function);
271 //from one or two set of TermVector objects
272 TensorKernel(const vector<TermVector>&, const vector<T>&, bool conj =false);
273 TensorKernel(const vector<TermVector>&, const vector<T>&,
274              const vector<TermVector>&);
275\end{lstlisting}
276Note that these constructors does not allow to set maps! They have to be set after construction. When the user defines {\class TensorKernel} from an explicit function, it has to get the index from the parameters related to the function. This index is automatically set by the computation functions and its name in parameters is "basis index".\\
277
278The {\class TensorKernel} class provides some accessors ans properties:
279\begin{lstlisting}[]{}
280const VectorEntry& vectorEntry() const;
281const SpectralBasis* phip() const;
282const SpectralBasis* psip() const;
283const SpectralBasis& phi()  const;
284const SpectralBasis& psi()  const;
285dimen_t dimOfPhi() const;
286dimen_t dimOfPsi() const;
287number_t nbOfPhi() cons;
288number_t nbOfPsi() cons;
289bool phiIsAnalytic() const;
290bool psiIsAnalytic() const;
291virtual KernelType type() const;
292virtual bool isSymbolic() const;
293virtual ValueType valueType() const;;
294virtual StrucType structType() const;;
295bool sameBasis() const;
296virtual const TensorKernel* tensorKernel() const;
297virtual TensorKernel* tensorKernel();
298\end{lstlisting}
299\vspace{.1cm}
300It implements the computation of kernel:
301\begin{lstlisting}[]{}
302template<typename T>
303 T kernelProduct(number_t, const T&) const;
304template<typename T>
305 T kernelProduct(number_t, number_t, const T&) const;
306\end{lstlisting}
307\displayInfos{library=terms, header=TensorKernel.hpp, implementation=TensorKernel.cpp, test=test\_Function.cpp,
308header dep={config.h, Parameters.hpp, Point.hpp, String.hpp, Vector.hpp, Function.hpp, TermVector.hpp, SpectralBasis.hpp}}
309