XLiFE++’s basics#

Basic types#

In front of the various data types in C/C++, the choice was made to have a minimal possible basic data types by respecting one rule: integers and floats are encoded in 32 bits on 32 bits architecture, and encoded in 64 bits on 64 bits architectures, whatever the OS. As a result, XLiFE++ provides its own types for integer and float data.

The same goes for strings.

Caution

If you are not familiar with C++ syntax, we recommend you to see C++ syntax before reading this page.

Integers#

To define integers, XLiFE++ provided three types:

Int: it represents a signed integer (default 32 bits).

Dimen: it represents a :xlifepp:`short unsigned int`( default 16 bits).

Number: it represents an unsigned integer. It is an alias of size_t (default 64bits).

Booleans#

To define booleans, you may use the standard C++ type bool.

Floats and complexes#

To define floats, XLiFE++ provides Real. It is an alias whose default value is double.

Complex is no more than an alias to std::complex<Real>.

Strings#

XLiFE++ provides String, an alias of std::string (the default) for ut8 encoded strings, or std::wstring for utf16 encoded strings (=wide strings).

Points#

XLiFE++ provides Point to manage coordinates in any dimension. Logically, it is used to define geometries (vertices for instance), and on inhomogeneous coefficients (see Functions and kernels below).

Global constants and objects#

Some global constants are available and may be useful to you:

pi_: the pi constant with the Real precision

i_: the imaginary number with the Complex precision

theEulerConst: the Euler-Mascheroni constant

theTolerance: the precision used to convergence in norms (2.22045e-12 in double precision)

theEpsilon: the machine epsilon (2.22045e-16 in double precision)

Some useful objects are also available:

thePrintStream_: the dedicated file stream to the print.txt file generated while executing a program using XLiFE++.

theCout: using this stream object means using either the standard output stream std::cout and the previous file stream thePrintStream_. This is the reason why we recommend you to always use this stream.

eol: an alias to std::endl (end of line).

Collections, vectors and matrices#

Collections#

XLiFE++ provides data types for collections, namely sets of values. The main collection types are:

Ints, for a collection of Int.

Numbers, for a collection of Number.

Strings, for a collection of String.

Points, for a collection of Point.

A collection can be constructed with a set of 1 to 48 values, and provides access operators.

Numbers nv(1, 2, 3, 4, 5); // constructor from 5 values, you can set up to 48 values
theCout << nv[2] << " " << nv(3) << eol; // accessing to third element by both operators

Hint

The purpose of a collection is not to be used in computations. Classes were defined at the time when XLiFE++ default C++ standard was 98, for the definition of geometries. With standard 11, you can use the initializer lists instead.

Vectors#

For real or complex vectors, you can use Reals and Complexes. Both types are aliases of the general Vector<T> class, that you can use for vectors of anything, even for vectors of vectors (RealVectors and ComplexVectors for real or complex vectors of vectors).

Reals u(3);         // u=[0. 0. 0.]
Reals v(3, 2.5);    // v=[2.5 2.5 2.5]
Reals w={1.,2.,3.}; // from initializer list
Complexes cu(3);    // cu=[(0.,0.) (0.,0.) (0.,0.)]
Complex c(2.,1.);   // the complex 2+i
Complexes cc(3, c); // cc=[(2.,1.) (2.,1.) (2.,1.)]
Complex cw(w);      // cw=[(1.,0.) (2.,0.) (3.,0.)], Reals to Complexes

theCout << w[1] << " " << w(2); // printing the second element by both access operators

Every classical operation on vector is available:

  • +, -, *, / with scalars of same type (conversion from real to complex values is implemented)

  • size

  • linspace : produces a vector of n values uniformly distributed over an interval

  • dot, crossProduct, norm1, norm2, norminfty

Matrices#

Next to vectors, you have matrices, with the general Matrix<T> class and its aliases RealMatrix and ComplexMatrix for real or complex matrices, and RealMatrices and ComplexMatrices for real or complex matrix of matrices.

RealMatrix rA;                     // an empty matrix
RealMatrix rB(3, 2);               // a 3x2 zeros matrix
RealMatrix rC(3, 2, 1);            // a 3x2 ones matrix
RealMatrix rE = {11.,12},{21.,22}; // a 2x2 matrix from explicit
ComplexMatrix cA(3, 2, i_);        // a 3x2 i matrix

theCout << rE(2, 1); // printing the element of the 2nd row and 1st column

Every classical operation on vector is available:

  • +, -, *, / with scalars of same type (conversion from real to complex values is implemented)

  • * (matrix-vector product)

  • vsize / numberOfRows

  • hsize / numberOfColumns

  • transpose, adjoint, diag

  • norm2, norminfty

See also

For sparse matrices, you can use SparseMatrix<T>, only for the user purpose.

Functions and kernels#

When dealing with inhomogeneous coefficients in a variational formulation, you will have to define functions. 2 possibilities :

  • a function, depending on a single space variable. The general prototypes follow:

    OUT fs(const Point& P, Parameters& pa = defaultParameters);                  // scalar form
    Vector<OUT> fv(const Vector<Point>& Ps, Parameters& pa = defaultParameters); // vector form
    Matrix<OUT> fm(const Vector<Point>& Ps, Parameters& pa = defaultParameters); // matrix form
    
  • a kernel, namely a function depending on 2 space variables. The general prototypes follow:

    OUT ks(const Point& P, const Point& M, Parameters& pa = defaultParameters); // scalar form
    Vector<OUT> kv(const Vector<Point>& Ps, const Vector<Point>& Ms,
                   Parameters& pa = defaultParameters);                         // vector form
    Matrix<OUT> km(const Vector<Point>& Ps, const Vector<Point>& Ms,
                   Parameters& pa = defaultParameters);                         // matrix form
    

The return type OUT can be one of the following: Real, Complex, Reals, Complexes, RealMatrix or ComplexMatrix.

Hint

For other purpose, you can of course define any other type of function.

In the variational formulation, if your function does not depend on other parameters you can use the C++ function directly. If there are parameters, you will have to define a Function/Kernel object to which these parameters will be associated. First, lets’ talk about parameters.

Parameters#

As we see in the function/kernel prototypes above, there is an argument (the last one) with default value (defaultParameters). It is an object of the Parameters class, that handles a vector of Parameter with name-based indexing.

The Parameter class is provided by XLiFE++ to encapsulate different kind of values: Int, Real, Complex, String, bool, void*; the last type allowing to handle anything by pointer.

A Parameter object is constructed from a value and an identifier name. The name will be the key in a Parameters.

Parameter p(2.5, "k"); // Parameter from a Real value
Parameters pars;       // list of Parameter
pars << p;             // inserting a Parameter into list
Real k=pars("k");      // getting a parameter from list

See also

The Parameter is also used in the context of user options of a main program, of user options defined in files (see Management of custom options (Options class) for more details), and of the key-value system in most of the main user classes.

Let’s now talk about assigning parameters to functions / kernels and how to use them.

Functions and kernels objects#

Functions and kernels may also have parameters, for example, the real \(k\) in the next example. The output argument may be of any type (real, complex, vector, matrix, …), but has to be compatible which the type required in computation.

In the variational formulation, we can not use the standard C++ function/kernel name, but you have to define an object from this C++ function and the parameters object. This is the purpose of classes Function and Kerrnel:

Parameters pars(1, "k");  // function parameters
Function F(f, pars);      // Function object

To use these parameters in the implementation of the function, you will have to use pa, as follows:

Complex f(const Point & P, Parameters& pa = defaultParameters)
{
  Real k=pa("k");    // is available if you have a parameter with name "k"
  Real x=P(1);       // x is the first coordinate of the point P
  return exp(i_*k*x); // return a complex value result,
}

Hint

If your function is defined before your main program (in the same file), you can use a global variable instead the Parameter machinery:

Real k=0.;   // global variable available in any function defined here
...
Complex f(const Point & P, Parameters& pa = defaultParameters)
{ return exp(i_*k*P(1));    // k is available }
...
int main()
{
   k=10.;   // k is available
}