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{Space management} 18 19\subsection{The {\classtitle Space} and {\classtitle SpaceInfo} classes} 20 21The {\class Space} class manages different kind of spaces using inherited classes: finite element 22space ({\class FeSpace}), spectral space ({\class SpSpace}), sub space (({\class SubSpace}) 23and product space ({\class ProdSpace}). To avoid the user to deal explicitly with this space 24hierarchy, we use the following programming paradigm: {\class Space} class has a pointer 25to a Space as attribute, which contains either its own address or the address of a child. In 26a sense, the {\class Space} class is not an abstract class but has a the behaviour of an abstract 27one. When an end user declares a Space object, he induces the construction of a child Space. 28With this trick, an end user instantiates only {\class Space} object, never the child spaces. 29As a consequence, it requires a little more memory because member attributes are duplicated. 30In order to limit this effect, the common characteristics of a space are collected in the {\class 31SpaceInfo} class: 32\vspace{.1cm} 33\begin{lstlisting}[deletekeywords={[3] dimCom}] 34class SpaceInfo 35 {public : 36 String name_; // name of space 37 Domain * domain_p; // geometric domain supporting the space 38 SobolevType spaceConforming_; // conforming space (L2,H1,Hdiv,Hcurl,H2,Hinf) 39 dimen_t dimFun_; // number of components of the basis functions 40 Dimen dimCom; // number of components of the unknowns 41 SpaceType spaceType_; // space type (FESpace,SPSpace,SubSpace,ProductSpace) 42 SpaceInfo(){}; 43 SpaceInfo(const String &,SobolevType,Domain *,dimen_t , SpaceType) 44 }; 45\end{lstlisting} 46\vspace{.2cm} 47The general characteristics of a space are the geometric domain supporting the basis functions, 48the space conformity which "tells" the regularity of the basis functions and the dimension 49of the basis functions. The space conformity property is a way to distinguish discontinuous 50finite element approximation from continuous one. The space conformity is given by the SobolevType 51enumeration declared in the \textit{config.hpp} header file: 52\vspace{.1cm} 53\begin{lstlisting}[] 54enum SobolevType {L2=0, L2=_L2,H1, H1=_H1,_Hdiv, Hdiv=_Hdiv,_Hcurl, Hcurl=_Hcurl, 55 _Hrot=_Hcurl, Hrot=_Hrot,_H2, H2=_H2,_Hinf, Hinf=_Hinf} 56\end{lstlisting} 57\vspace{.1cm} 58To be user friendly, several names are available for the same space.\\ 59 60The parent class {\class Space} has only two pointers and a static vector managing the list 61of all defined spaces: 62\vspace{.1cm} 63\begin{lstlisting} 64class Space 65{protected : 66 Space * space_p; //pointer to the "true" space (child) 67 SpaceInfo * spaceInfo_p; //pointer to the space information structure 68public : 69 static std::vector<Space*> theSpaces; //unique list of defined spaces 70\end{lstlisting} 71\vspace{.2cm} 72Regarding the type of spaces, the {\class Space} provides several constructors to construct child spaces: 73\vspace{.1cm} 74\begin{lstlisting} 75//constructors of trivial space of dim n, say Rn 76Space(number_t, const string_t& ="Rn"); 77Space(const GeomDomain&, number_t, const string_t& ="Rn"); 78 79//constructors addressing spectral space 80Space(const SpectralBasis&, const string_t&); //from spectral basis 81Space(const GeomDomain&, const Function&, number_t, dimen_t, const string_t&); 82Space(const GeomDomain&, const Function&, number_t, dimen_t); 83Space(const GeomDomain&, const Function&, number_t, const string_t&); 84Space(const TermVectors&, const string_t&); //from interpolated functions 85 86//constructors addressing FeSpace type from Interpolation or FE types 87Space(const GeomDomain&, const Interpolation&, const string_t&, bool opt = true); 88Space(const GeomDomain&, PolynomType, const string_t&, bool opt = true); 89Space(const GeomDomain&, QolynomType, const string_t&, bool opt = true); 90Space(const GeomDomain&, FeFaceType, const string_t&, bool opt = true); 91Space(const GeomDomain&, FeEdgeType, const string_t&, bool opt = true); 92 93//constructors addressing SubSpace type 94Space(const GeomDomain&, Space&, const string_t& na = ""); 95Space(const GeomDomain&, const vector<number_t>&, Space&, const string_t& na = ""); 96Space(const std::vector<number_t>&, Space&, const string_t& na = ""); 97 98//tools related to construtors 99void buildSpFun(const GeomDomain&, const Function&, number_t, 100 dimen_t, const string_t&); 101SubSpace* createSubSpace(const GeomDomain&, Space&, const string_t& na); 102void createSubSpaces(const vector<const GeomDomain*>&,vector<Space*>&); 103Space* buildSubspaces(const vector<const GeomDomain*>&, vector<Space*>&); 104\end{lstlisting} 105\vspace{.1cm} 106These constructors work as follows (\textit{(child)Space} denotes any inherited space class): 107\vspace{.1cm} 108\begin{lstlisting}[] 109 (child)Space* csp_p=new (child)Space(...); //create the (child)Space 110 space_p=static_cast<Space *>(csp_p); //cast (child)Space* to Space* 111 spaceInfo_p=csp_p->spaceInfo_p; //copy the SpaceInfo pointer 112 theSpaces.push_back(this); //store space in list of spaces 113\end{lstlisting} 114\vspace{.1cm} 115Note that it is the child constructors that set all the attributes (general ones and specific 116ones).\\ 117 118The {\class Space} class provides some accessors, some being virtual: 119\vspace{.1cm} 120\begin{lstlisting}[] 121string_t name() const; //space name 122SobolevType conformingSpace() const; //space conformity 123const GeomDomain* domain(); //related domain 124dimen_t dimDomain() const; //dimension of related domain 125dimen_t dimPoint() const ; //dimension of points 126dimen_t dimFun() const; //dimension of basis functions 127SpaceType typeOfSpace() const; //type of space 128SpaceType typeOfSubSpace() const; //type of sub-space 129virtual bool isSpectral() const; //true if spectral space 130virtual bool isFE() const; //true if FE space or FeSubspace 131const Space* space() const; //pointer to true space object 132virtual number_t dimSpace() const; //space dimension 133virtual number_t nbDofs()const; //number of dofs 134virtual const FeSpace* feSpace() const; //pointer to child fespace 135virtual FeSpace* feSpace(); //pointer to child fespace 136virtual const FeSubSpace* feSubSpace() const;//pointer to child fesubspace 137virtual const SpSpace* spSpace() const; //pointer to child fesubspace 138virtual const SubSpace* subSpace() const; //pointer to child subspace 139virtual SubSpace* subSpace(); //pointer to child subspace 140virtual const Space* rootSpace() const; //pointer to root space 141virtual Space* rootSpace(); //pointer to root space 142virtual ValueType valueType() const; //value type of basis function 143virtual StrucType strucType() const; //structure type of basis function 144virtual bool include(const Space*) const; //inclusion test 145\end{lstlisting} 146\vspace{.1cm} 147To understand how works the non abstract/abstract class paradigm, here is the implementation 148of the access function \textit{feSpace}: 149\vspace{.1cm} 150\begin{lstlisting}[] 151FeSpace* Space::feSpace() const 152{if(space_p!=this) return space_p->feSpace(); //call the true feSpace 153 error("is_not_fespace",name()); 154 return 0; 155} 156FeSpace* FeSpace::feSpace() const {return *this;} 157\end{lstlisting} 158\vspace{.1cm} 159The test \verb?space_p!=this? means that the current space is a user space (it has a child), 160the {\cmd fespace()} function is called by its child. By polymorphic behaviour, if \verb?space_p? 161is a {\class FeSpace} the {\cmd FeSpace::fespace()} is called else {\cmd Space::fespace()} is 162again called, but with \verb?space_p=this? and an error is thrown because the current space 163is not a {\class FeSpace}. \\ 164 165As you will see in section \ref{s.dof}, the dof number is relative to the parent space. To get the global number of a dof or the dof itself and to manage dofs, Space provides the following functions : 166\vspace{0.1cm} 167\begin{lstlisting}[] 168virtual number_t dofId(number_t) const; //n-th DoF id of space 169virtual std::vector<number_t> dofIds() const; //DoF ids on space 170virtual const Dof& dof(number_t) const; //n-th dof (n=1,...) 171virtual std::pair<number_t, number_t> renumberDofs();//optimize dofs numbering 172virtual void shiftDofs(number_t n); //shift dofs numbering from n (SpSpace) 173\end{lstlisting} 174\vspace{0.2cm} 175When space is a FE space or a FE subspace, tools to access to finite element informations are provided: 176\vspace{0.1cm} 177\begin{lstlisting}[] 178virtual const Interpolation* interpolation() const; 179virtual number_t nbOfElements() const; 180virtual const Element* element_p(number_t k) const: 181virtual const Element* element_p(GeomElement* gelt) const; 182virtual number_t numElement(GeomElement* gelt) const; 183virtual vector<number_t> elementDofs(number_t k) const; 184virtual vector<number_t> elementParentDofs(number_t k) const; 185virtual const set<RefElement*>& refElements() const; 186virtual void buildgelt2elt() const; 187\end{lstlisting} 188\vspace{0.2cm} 189Finally, the {\class Space} provides some printing facilities: 190\vspace{.1cm} 191\begin{lstlisting}[] 192void printSpaceInfo(std::ostream &) const; 193virtual void print(std::ostream &) const; 194friend std::ostream& operator<<(std::ostream&,const Space &); 195\end{lstlisting} 196\vspace{.2cm} 197Some functions managing subspaces (comparison, merging) are also available: 198\begin{lstlisting}[] 199bool compareSpaceUsingSize(const Space*, const Space*); 200vector<number_t> renumber(const Space*, const Space*); 201Space& subSpace(Space&, const GeomDomain&); 202inline Space& operator |(Space&, const GeomDomain&); 203Space* mergeSubspaces(Space*&, Space*&, bool newSubspaces=false); 204Space* mergeSubspaces(std::vector<Space*>&, bool newSubspaces=false); 205Space* unionOf(std::vector<Space*>&); 206vector<Point> dofCoords(Space&, const GeomDomain&); 207\end{lstlisting} 208\vspace{.2cm} 209Linked to the {\class Space} class, the {\class DoF} class stores characteristics of degree 210of freedom. Degree of freedom is like a key index of components of element of space. Generally, 211it handles a numeric index and carries some additionnal informations. From {\class DoF} class 212inherit the classes {\class FeDoF} and {\class SpDoF} (see section DoF).\\ 213\displayInfos{library=space, header=Space.hpp, implementation=Space.cpp, test=test\_Space.cpp, 214header dep={config.h, geometry.h, Df.hpp}} 215 216Now, let's have a look at the child space classes. 217 218\subsection{The {\classtitle FeSpace} class} 219 220A finite elements space is defined is by a finite set of functions given by interpolated form on a mesh. 221The inherited {\class FeSpace} class is defined as follows : 222\vspace{.1cm} 223\begin{lstlisting}[deletekeywords={[3] elements}] 224class FeSpace : public Space 225{ 226 protected : 227 const Interpolation* interpolation_p; //!< pointer to finite element interpolation description 228 bool optimizedNumbering_; //!< true if dof numbering is bandwidth optimized 229 230 public: 231 std::vector<Element> elements; //!< list of finite elements 232 std::vector<FeDof> dofs; //!< list of global degrees of freedom 233 234 static Number lastEltIndex; //!< to manage a unique index for elements 235}; 236\end{lstlisting} 237\vspace{.1cm} 238This class provides one constructor, using two member functions: 239\vspace{.1cm} 240\begin{lstlisting}[] 241FeSpace(const Domain&, const Interpolation&, Dimen, const String&, bool opt=true); 242void buildElements(); //!< construct the list of elements 243void buildFeDofs(); //!< construct the list of FeDofs 244\end{lstlisting} 245\vspace{.1cm} 246The {\cmd buildElements()} member functions create the list of elements ({\class Element} objects) from the list of geometric elements belonging to the domain supporting the space. The {\cmd buildFeDofs()} function is the most important one. It constructs from reference dofs the list of global dofs using a general algorithm. It works as follows: 247\vspace{.1cm} 248$$ 249\left| 250\begin{array}{l} 251\bullet \ \text{case of no shared dof (L2 conforming space), concatenate all local dofs and exit}\\ 252\bullet \ \text{case of shared dofs }\\ 253 \ \ \ \ \bullet \ \text{construct a string index of dofs by traveling elements with the convention }\\ 254 \ \ \ \ \ \ \ \text{"V i" for a dof on vertex i}\\ 255 \ \ \ \ \ \ \ \text{"E i j l" for the l-th dof on edge [Vi, Vj], i<j, not a vertex dof}\\ 256 \ \ \ \ \ \ \ \text{"F i j k l" for the l-th dof on face [Vi, Vj, Vk], i<j<k, not an edge dof}\\ 257 \ \ \ \ \ \ \ \text{"N i l" for the l-th dof on element i (non shared dof)}\\ 258 \ \ \ \ \bullet \ \text{construct the list of global dofs from this index and update elements} 259\end{array} 260\right. 261$$ 262To insure the right matching between shared dofs on edge or face, this algorithm uses the {\cmd sideDofsMap} and {\cmd sideOfSideDofsMap} member functions of finite element classes. These functions relates dof numbering to one edge/face to an other edge/face.\\ 263\vspace{.2cm} 264The {\class FeSpace} class provides also some specific accessors: 265\vspace{.1cm} 266\begin{lstlisting}[] 267virtual Number nbDofs() const; //!< number of dofs (a dof may be a vector dof) 268Dimen dimElements() const; //!< return the dimension of FE elements 269const Interpolation* interpolation() const; //!< return pointer to interpolation 270Number nbOfElements() const; //!< number of elements 271\end{lstlisting} 272\vspace{.1cm} 273The {\class FeSpace} class provides also some specific renumbering functions: 274\vspace{.1cm} 275\begin{lstlisting}[] 276Graph graphOfDofs(); //!< create dof connection graph 277const Element* element_p(Number k) const; //!< access to k-th (k>=0) element (pointer) 278std::vector<Number> elementDofs(Number k) const; //!< access to dofs ranks (local numbering) of k-th (>=0) element 279std::vector<Number> elementParentDofs(Number k) const; //!< access to dofs ranks (parent numbering, same as local) of k-th (>=0) element 280\end{lstlisting} 281\vspace{.1cm} 282\displayInfos{library=space, header=FeSpace.hpp, implementation=FeSpace.cpp, test=test\_Space.cpp, 283header dep={config.h, Elements.hpp, Space.hpp, dof.hpp, finiteElement.h}} 284 285 286\subsection{The {\classtitle SpSpace} class} 287 288A spectral space is defined by a finite set of functions given by analytic expression or by 289interpolated form. These global basis functions defined over a geometric domain are collected 290in the {\class SpectralBasis} class declared in the \textit{SpectralBasis.hpp} header file 291(see the section SpectralBasis). The inherited {\class SpSpace} class is defined as follows: 292\vspace{.1cm} 293\begin{lstlisting} 294class SpSpace : public Space 295{ 296 protected : 297 SpectralBasis* spectralBasis_; //! object function encapsulating the spectral functions 298 //either defined in an analytical form or by interpolated functions (TermVector) 299 public : 300 std::vector<SpDof> dofs; //! list of global degrees of freedom 301}; 302\end{lstlisting} 303\vspace{.1cm} 304This class provides one constructor, a destructor, several accessors and a printing function: 305\vspace{.1cm} 306\begin{lstlisting}[] 307SpSpace(const String&, Domain&, number_t, dimen_t, SpectralBasis*); 308~SpSpace(); 309SpectralBasis* spectralBasis() const; 310virtual Number nbDofs() const; //!< number of dofs (a dof may be a vector dof) 311\end{lstlisting} 312\vspace{.1cm} 313 314\displayInfos{library=space, header=SpSpace.hpp, implementation=SpSpace.cpp, test=test\_Space.cpp, 315header dep={config.h, Elements.hpp, Space.hpp, dof.hpp}} 316 317 318\subsection{The {\classtitle SubSpace} and {\classtitle FeSubSpace} classes} 319 320A subspace is part of a space. Its dofs are a subset of the parent dofs. The inherited {\class SubSpace} class is defined as follows: 321\vspace{.1cm} 322\begin{lstlisting} 323class SubSpace : public Space 324{ 325 protected : 326 Space* parent_p; //!< the parent space 327 std::vector<Number> dofNumbers_; //!< global numbers of D.o.Fs in parent D.o.Fs numbering 328}; 329\end{lstlisting} 330\vspace{.1cm} 331This class provides two constructor, a destructor, and several specific accessors about the {\tt dofNumbers\_} attribute or about the type of subspace : 332\vspace{.1cm} 333\begin{lstlisting}[] 334SubSpace() //!< default constructor 335SubSpace(const Domain&, Space&, const String& na = ""); //!< constructor specifying geom domain, parent space and name 336~SubSpace(); //! destructor 337 338std::vector<Number>& dofNumbers() //!< access to dofNumbers list 339const std::vector<Number>& dofNumbers() const //!< access to dofNumbers list (const) 340std::vector<Number> dofRootNumbers() const; //!< access to dofNumbers list in root space numbering 341Number dofRootNumber(Number k) const; //!< access to dof number in root space numbering 342virtual Number nbDofs() const //! number of dofs (a dof may be a vector dof) 343virtual bool isFeSubspace(); 344virtual const FeSubSpace* fesubspace() const; 345\end{lstlisting} 346\vspace{.1cm} 347It also provides functions for numbering management: 348\vspace{.1cm} 349\begin{lstlisting}[] 350void createNumbering(); //!< create numbering of subspace DoFs 351void dofsOfFeSubspace(); //!< build dofs numbering of Fe SubSpace 352void dofsOfSpSubspace(); //!< build dofs numbering of Sp SubSpace 353void dofsOfSubSubspace(); //!< build dofs numbering of Subspace of SubSpace 354\end{lstlisting} 355\vspace{.1cm} 356\displayInfos{library=space, header=SubSpace.hpp, implementation=SubSpace.cpp, test=test\_Space.cpp, 357header dep={config.h, Elements.hpp, Space.hpp, Dof.hpp}} 358 359 360The {\class FeSubSpace} class concerns subspaces of finite element spaces. It is defined as follows: 361\vspace{.1cm} 362\begin{lstlisting}[deletekeywords={[3] elements}] 363class FeSubSpace : public SubSpace 364{ 365 public : 366 std::vector<Element*> elements; //!< list of finite elements (or subelements) 367 std::vector<std::vector<Number> > dofRanks; //!< numbering of D.o.Fs of domain elements in domain D.o.Fs 368}; 369\end{lstlisting} 370\vspace{.1cm} 371This class provides one constructor, a destructor, and several specific functions, also provided by the {\class FeSpace} class : 372\vspace{.1cm} 373\begin{lstlisting} 374FeSubSpace(const Domain&, Space&, const String& na = ""); //!< constructor specifying geom domain, parent space and name 375~FeSubSpace(); //!< destructor 376Number nbOfElements() const; //!< number of elements 377const Element* element_p(Number k) const; //!< access to k-th (k>=0) element (pointer) 378std::vector<Number> elementDofs(Number k) const; //!< access to dofs ranks (local numbering) of k-th (>=0) element 379std::vector<Number> elementParentDofs(Number k) const; //!< access to dofs ranks (parent numbering) of k-th (>=0) element 380\end{lstlisting} 381\vspace{.1cm} 382\displayInfos{library=space, header=FeSubSpace.hpp, implementation=FeSubSpace.cpp, test=test\_Space.cpp, 383header dep={config.h, Elements.hpp, SubSpace.hpp, dof.hpp}} 384 385\subsection{The {\classtitle ProdSpace} class} 386 387The {\class ProdSpace} class manages product of spaces using a vector of space pointers : 388\vspace{.1cm} 389\begin{lstlisting} 390class ProdSpace : public Space 391{ 392 protected : 393 std::vector<Space*> spaces_; 394 public : 395 virtual Number dimSpace()const; 396 virtual Number nbdofs() const; 397 virtual const Space* rootSpace() const 398 {return static_cast<const Space*>(this);} 399 virtual Space* rootSpace() 400 {return static_cast<Space*>(this);} 401 virtual Number dofId(Number n) const 402 {error("no_dof_numbering", name()); 403 return 0;} 404}; 405\end{lstlisting} 406\vspace{.1cm} 407It is currently not used. 408\subsection{The {\classtitle Spaces} class} 409{\class Spaces} is an alias of {\class PCollection<Space>} class that manages a collection of {\class Space} objects, in fact a {\var std::vector<Space*>}. Be cautious when using it because the Space pointers are shared; in particular when using temporary instance of Space! It is the reason why the {\class PCollectionItem} class is overloaded to protect pointer in assign syntax {\cmd sp(i)=Space(...)}: 410\vspace{.1cm} 411\begin{lstlisting}[] 412template<> class PCollectionItem<Space> 413{public: 414 typename std::vector<Space*>::iterator itp; 415 PCollectionItem(typename std::vector<Space*>::iterator it) : itp(it){} 416 Space& operator = (const Space& sp); //protected assignment 417 operator Space&(){return **itp;} //autocast PCollectionItem->Space& 418}; 419\end{lstlisting} 420\vspace{.2cm} 421Main usages of this class are the following: 422\vspace{.1cm} 423\begin{lstlisting}[] 424Space V1(omega,_P1,"V1"), V2(omega,_P2,"V2"), V3(omega,_P3,"V3"); 425Spaces Vs2(V1,V2); 426Spaces Vs3(V1,V2,V3); 427Spaces Vs4; Vs4<<V1<<V2<<V3<<V1; 428Spaces Vs5(5); 429for(Number i=1;i<=5;i++) 430 Vs5(i)=Space(omega,interpolation(Lagrange,_standard,i,H1),"V_"+tostring(i)); 431\end{lstlisting} 432\vspace{.2cm} 433\begin{cpp11} 434If C++11 is available (the library has to be compiled in C++11), the following syntax is also working: 435\vspace{.1cm} 436\begin{lstlisting}[] 437Spaces vs={V1,V2,V3}; 438\end{lstlisting} 439\end{cpp11} 440 441\vspace{.2cm} 442Collection of spaces can also be set by the following functions from one or several domains and one or several interpolations: 443\vspace{.1cm} 444\begin{lstlisting}[] 445Spaces spaces(const Domains&,const Interpolations&,bool=true); 446Spaces spaces(const Domains&,const Interpolation&,bool=true); 447Spaces spaces(const GeomDomain&,const Interpolations&,bool=true); 448\end{lstlisting} 449\vspace{.2cm} 450 451\displayInfos{library=space, header=ProdSpace.hpp, implementation=ProdSpace.cpp, test=test\_space.cpp, 452header dep={config.h, Space.hpp}} 453