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 /*!
18   \file BilinearForm.hpp
19   \author E. Lunéville
20   \since 23 mar 2012
21   \date 9 may 2012
22 
23   \brief Definition of the xlifepp::BilinearForm classes
24 
25   This file declares all the classes related to bilinear forms management.
26   The more general bilinear form under consideration is a list of linear combinations of basic bilinear forms.
27   The list is indexed by the unknowns of the linear combination.
28 
29   Basic bilinear forms are, for the moment, integral or double integral type.
30   The bilinear form may have multiple unknowns but a linear combination is related to a unique unknown
31 
32   - xlifepp::BiLinearForm is the end user class, it is a map of <Unknown*,LCBilinearForm>
33   - xlifepp::SuBilinearForm deals with linear combination of basic bilinear forms, it is a vector of pairs of <BasicBilinearForm*,complex>
34   - xlifepp::BasicBilinearForm is the mother class (abstract) of classes
35     - xlifepp::IntgBilinearForm for single integral bilinear form (generally in FEM method)
36     - xlifepp::DoubleIngBilinearForm for double integral bilinear form (generally in BEM method)
37     - xlifepp::ComposedBilinearForm for composition of bilinear forms (generally DtN operator)
38     - xlifepp::MatrixBilinearForm for explicit bilinear form given by a TermMatrix
39 
40   As example :
41   \code
42   BilinearForm l=intg(Omega,f*u*v);                               //a single unknown (u) linear form
43   BilinearForm l=intg(Omega,f*u*v)+2*intg(Omega,grad(u)|grad(w)); //a multiple unknowns (u,v), (u,w) bilinear form
44   \endcode
45 
46   All linear algebraic operations are allowed on xlifepp::BilinearForm objects
47 
48   It is possible to impose the quadrature rule to an integral linear form by specifying a quadrature rule type and its order
49   \code
50   BilinearForm l=intg(Omega,f*u*v,Gauss_Legendre,5);                     //a single unknown (u) linear form
51   \endcode
52   see Quadrature class for the list of quadrature rules available
53 */
54 
55 #ifndef BILINEAR_FORM_HPP
56 #define BILINEAR_FORM_HPP
57 
58 #include "config.h"
59 #include "space.h"
60 #include "operator.h"
61 #include "finiteElements.h"
62 #include "largeMatrix.h"
63 
64 #include <utility>
65 
66 namespace xlifepp
67 {
68 
69 class IntgBilinearForm;
70 class DoubleIntgBilinearForm;
71 class ComposedBilinearForm;
72 class MatrixBilinearForm;
73 
74 //=========================================================================================
75 /*!
76   \class BasicBilinearForm
77   describes the base class of bilinear form on a space.
78   It is an abstract class
79 */
80 //=========================================================================================
81 class BasicBilinearForm
82 {
83 protected:
84   const Unknown* u_p;              //!< pointer to unknown u
85   const Unknown* v_p;              //!< pointer to unknown v (test function)
86   const GeomDomain* domainu_p;     //!< geometric domain of unknown u
87   const GeomDomain* domainv_p;     //!< geometric domain of unknown v (test function)
88   ComputationType compuType;       //!< computation type (_FEComputation, _IEComputation, _SPComputation, ...)
89 public:
90   SymType symmetry;                //!< symmetry of the bilinear form ((_noSymmetry , _symmetric, _skewSymmetric, _selfAdjoint, _skewAdjoint)
91 
92 public:
93   //constructor/destructor
BasicBilinearForm(const Unknown * up=0,const GeomDomain * dup=0,const Unknown * vp=0,const GeomDomain * dvp=0)94   BasicBilinearForm(const Unknown* up=0, const GeomDomain* dup=0,
95                     const Unknown* vp=0, const GeomDomain* dvp=0) //! basic and default constructor
96   :u_p(up), v_p(vp), domainu_p(dup), domainv_p(dvp), compuType(_undefComputation), symmetry(_undefSymmetry) {}
~BasicBilinearForm()97   virtual ~BasicBilinearForm() {}  //!< virtual destructor
98 
99   //accessors
up() const100   const Unknown& up() const        //! return the unknown
101   {return *u_p;}
vp() const102   const Unknown& vp() const        //! return the test function
103   {return *v_p;}
dom_up() const104   const GeomDomain& dom_up() const //! return the unknown domain
105   {return *domainu_p;}
dom_vp() const106   const GeomDomain& dom_vp() const //! return the test function domain
107   {return *domainv_p;}
computationType() const108   ComputationType computationType() const    //! return the computation type
109   {return compuType;}
110 
111   Space* subSpace_up();   //!< return the u subspace of the bilinear form, construct it if does not exist
112   Space* subSpace_vp();   //!< return the v subspace of the bilinear form, construct it if does not exist
113 
114   void checkUnknowns() const;   //!< check the Unknown/TestFunction status of u_p and v_p
115 
116   // virtual member functions
117   virtual BasicBilinearForm* clone() const = 0; //!< clone of the bilinear form
118   virtual LinearFormType type() const = 0;      //!< return the type of the bilinear form
119   virtual ValueType valueType() const = 0;      //!< return the value type of the bilinear form
120   IntgBilinearForm* asIntgForm();               //!< downcast as IntgBilinearForm*
121   const IntgBilinearForm* asIntgForm() const;   //!< downcast as const IntgBilinearForm*
122   DoubleIntgBilinearForm* asDoubleIntgForm();   //!< downcast as DoubleIntgBilinearForm*
123   const DoubleIntgBilinearForm* asDoubleIntgForm() const; //!< downcast as const DoubleIntgBilinearForm*
124   //virtual SymType symType() const =0;           //!< find symmetry property
125   virtual void print(std::ostream&) const = 0;   //!< print utility
126   virtual void print(PrintStream&) const = 0;
127   virtual string_t asString() const = 0;         //!< interpret as string for print purpose
setUnknowns(const Unknown & u,const Unknown & v)128   virtual void setUnknowns(const Unknown&u, const Unknown&v) //! set (change) the unknowns
129   {u_p=&u; v_p=&v;}
130 };
131 
132 /*!
133   \class IntgBilinearForm
134   describes a bilinear form based on a single integral
135 
136        intg_domain opu aopu opv
137 
138      with opu, opv   : operator on u and v
139           aopu, aopv : algebraic operation (*,|,%,^)
140 */
141 class IntgBilinearForm : public BasicBilinearForm
142 {
143 protected :
144   const OperatorOnUnknowns* opus_p;           //!< pointer to the operator on unknowns
145   const IntegrationMethod* intgMethod_p;      //!< pointer to integration method
146 
147 public :
148   IntgBilinearForm(const GeomDomain&, const OperatorOnUnknowns&, const IntegrationMethod&, SymType);  //!< constructor from OperatorOnUnknowns
149   IntgBilinearForm(const GeomDomain&, const OperatorOnUnknowns&, QuadRule, number_t, SymType );       //!< constructor from OperatorOnUnknowns
150   IntgBilinearForm(const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
151                    const OperatorOnUnknown&, const IntegrationMethod&, SymType);                      //!< constructor from explicit operators
152   IntgBilinearForm(const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
153                    const OperatorOnUnknown&, QuadRule, number_t, SymType);                            //!< constructor from explicit operators
154   IntgBilinearForm(const IntgBilinearForm&);                                                          //!< copy constructor
155   ~IntgBilinearForm();                                                                                //!< destructor
156   IntgBilinearForm& operator=(const IntgBilinearForm&);                                               //!< assign operator
157 
158   void setIntegrationMethod(const GeomDomain&, const OperatorOnUnknowns&, QuadRule , number_t);       //!< set integration method
159   void setComputationType();                //!< set computation type (_FEComputation,_SPComputation, _FESPComputation)
160 
opu() const161   const OperatorOnUnknown& opu() const      //! return the reference to the operator on unknown
162   {return opus_p->opu();}
opv() const163   const OperatorOnUnknown& opv() const      //! return the reference to the operator on unknown
164   {return opus_p->opv();}
opu_p() const165   const OperatorOnUnknown* opu_p() const    //! return the pointer to the operator on unknown
166   {return opus_p->opu_p();}
opv_p() const167   const OperatorOnUnknown* opv_p() const    //! return the pointer to the operator on unknown
168   {return opus_p->opv_p();}
algop() const169   AlgebraicOperator algop()const            //! return the algebraic operator
170   {return opus_p->algop();}
domain() const171   const GeomDomain* domain() const          //! return the pointer to the domain
172   {return domainu_p;}
type() const173   virtual LinearFormType type() const       //! return the type of the linear form
174   {return _intg;}
valueType() const175   virtual ValueType valueType() const       //! return the value type of the linear form
176   {return opus_p->valueType();}
intgMethod() const177   const IntegrationMethod* intgMethod() const //! pointer to integration method object
178   {return intgMethod_p;}
179   SymType symType() const;                    //!< find symmetry property (used to set symmetry)
180   virtual BasicBilinearForm* clone() const;   //!< clone of the linear form
181   virtual void setUnknowns(const Unknown&, const Unknown&); //!< set (change) the unknowns
182 
183   //print stuff
184   virtual void print(std::ostream&) const;   //!< print utility
print(PrintStream & os) const185   virtual void print(PrintStream& os) const {print(os.currentStream());}
186   virtual string_t asString() const;         //!< interpret as string for print purpose
187 };
188 
189 /*!
190   \class DoubleIntgBilinearForm
191   describes a bilinear form based on a double integral
192 
193      intg_domain_v  intg_domain_u  opu(y) aopu opker(x,y) aopv opv(x) dy dx
194 
195      with opu, opv   : operator on u and v
196           aopu, aopv : algebraic operation (*,|,%,^)
197           opker : operator on a kernel function
198 
199     note : when kernel = 1 the pointer to kernel function in opker is ker_p=0 !
200     Be cautious with order of domain, first if for v-domain, second for u-domain
201 
202     Actually, two ways to handle some integration methods :
203       by pointer to an IntegrationMethod object, so only one integration method (old way, should disappear in futur)
204       by an IntegrationMethods object that handles some IntegrationMethod (new way)
205 */
206 class DoubleIntgBilinearForm : public BasicBilinearForm
207 {
208 protected:
209   const KernelOperatorOnUnknowns* kopus_p; //!< pointer to the operator on unknowns with kernel
210   const IntegrationMethod* intgMethod_p;   //!< pointer to an integration method
211 
212 public:
213   IntegrationMethods intgMethods;          //!< list of integration methods
214 
215 public:
216   //copy constructor
217   DoubleIntgBilinearForm(const DoubleIntgBilinearForm&);            //!< copy constructor
218   DoubleIntgBilinearForm& operator=(const DoubleIntgBilinearForm&); //!< assign operator
219   ~DoubleIntgBilinearForm();                                        //!< destructor
220 
221   //constructors from IntegrationMethod
222   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
223                          const IntegrationMethod&, SymType);      //!< basic constructor
224 
225   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
226                          const IntegrationMethod&, SymType);     //!< constructor from unknown operators (no kernel)
227 
228   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,const OperatorOnKernel&,
229                          AlgebraicOperator, const OperatorOnUnknown&,
230                          const IntegrationMethod&, SymType);     //!< constructor from unknown operators and operator on kernel
231 
232   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,const Kernel&,
233                          AlgebraicOperator, const OperatorOnUnknown&,
234                          const IntegrationMethod&, SymType);    //!< constructor from unknown operators and kernel
235 
236   //constructors from IntegrationMethods
237   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
238                          const IntegrationMethods&, SymType);      //!< basic constructor
239 
240   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
241                          const IntegrationMethods&, SymType);     //!< constructor from unknown operators (no kernel)
242 
243   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,const OperatorOnKernel&,
244                          AlgebraicOperator, const OperatorOnUnknown&,
245                          const IntegrationMethods&, SymType);     //!< constructor from unknown operators and operator on kernel
246 
247   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,const Kernel&,
248                          AlgebraicOperator, const OperatorOnUnknown&,
249                          const IntegrationMethods&, SymType);    //!< constructor from unknown operators and kernel
250 
251   //constructors from Quadrule's
252   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
253                          QuadRule, number_t, QuadRule, number_t, SymType);   //!< basic constructor
254 
255   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
256                          QuadRule, number_t, QuadRule, number_t, SymType);   //!< constructor from unknown operators (no kernel)
257 
258   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,const OperatorOnKernel&,
259                          AlgebraicOperator, const OperatorOnUnknown&,
260                          QuadRule, number_t, QuadRule, number_t, SymType);   //!< constructor from unknown operators and operator on kernel
261 
262   DoubleIntgBilinearForm(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,const Kernel&,
263                          AlgebraicOperator, const OperatorOnUnknown&,
264                          QuadRule, number_t, QuadRule, number_t, SymType);   //!< constructor from unknown operators and kernel//accessors
265 
266   void setIntegrationMethod(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
267                             QuadRule, number_t, QuadRule, number_t);   //!< set IntegrationMethod for quadrature product rule
268   void setComputationType();      //!< set computation type (_IEComputation,_IEExtComputation,IEHMatrixComputation, ..)
269   void setIntegrationMethods();   //!< check and update quadrature pointers of IntegrationsMethods
270   void setHMIntegrationMethods(); //!< check and update quadrature pointers of IntegrationsMethods when a HMatrixIM
271 
272   //accessors
kopus() const273   const KernelOperatorOnUnknowns& kopus()const //! return KernelOperatorOnUnknowns reference (const)
274     {return *kopus_p;}
kopusp() const275   const KernelOperatorOnUnknowns* kopusp()const //! return KernelOperatorOnUnknowns pointer (const)
276     {return kopus_p;}
opu() const277   const OperatorOnUnknown& opu() const      //! return the pointer to the operator on unknown
278     {return kopus_p->opu();}
opv() const279   const OperatorOnUnknown& opv() const      //! return the pointer to the operator on unknown
280     {return kopus_p->opv();}
opker() const281   const OperatorOnKernel& opker() const     //! return the pointer to the operator on kernel
282     {return kopus_p->opker();}
algopu() const283   AlgebraicOperator algopu()const           //! return the algebraic operator on u
284     {return kopus_p->algopu();}
algopv() const285   AlgebraicOperator algopv()const           //! return the algebraic operator on v
286     {return kopus_p->algopv();}
intgMethod() const287   const IntegrationMethod* intgMethod() const //! return the pointer to the integration method
288     {return intgMethod_p;}
domainx() const289   const GeomDomain* domainx() const         //! return the pointer to the x domain, say u-domain
290     {return domainv_p;}
domainy() const291   const GeomDomain* domainy() const         //! return the pointer to the y domain, say v-domain
292     {return domainu_p;}
domains() const293   DomainPair domains() const                //! return the pair of domain pointers
294     {return DomainPair(domainu_p,domainv_p);}
type() const295   virtual LinearFormType type() const       //! return the type of the linear form
296     {return _doubleIntg;}
valueType() const297   virtual ValueType valueType() const       //! return the value type of the bilinear form
298     {return kopus_p->valueType();}
299   SymType symType() const;                  //!< return symmetry property (_noSymmetry , _symmetric, _skewSymmetric, _selfAdjoint, _skewAdjoint)
300   virtual BasicBilinearForm* clone() const; //!< clone of the linear form
301   virtual void setUnknowns(const Unknown&, const Unknown&); //!< set (change) the unknowns
302 
303   //print tools
304   string_t asString() const;                //!< interpret as string for print purpose
305   virtual void print(std::ostream&) const;  //!< print utility
print(PrintStream & os) const306   virtual void print(PrintStream& os) const {print(os.currentStream());}
operator <<(std::ostream & os,const DoubleIntgBilinearForm & dibf)307   friend std::ostream& operator<<(std::ostream& os,const DoubleIntgBilinearForm& dibf)
308   {dibf.print(os);return os;} //!< print operator
309 };
310 
311 //@{
312 //! useful typedefs to MatrixBilinearForm class
313 typedef std::pair<BasicBilinearForm*, complex_t> blfPair;
314 typedef std::vector<blfPair>::iterator it_vblfp;
315 typedef std::vector<blfPair>::const_iterator cit_vblfp;
316 //@}
317 
318 /*!
319   \class MatrixBilinearForm
320   describes a bilinear forms given by an explicit matrix
321   explicit matrix is handled by a MatrixEntry object
322   MatrixEntry pointer may be assigned from :
323     - MatrixEntry pointer or reference : no hard copy to save memory
324     - Matrix : matrix is copied as a dense matrix MatrixEntry
325     - Vector : vector is copied as a diagonal MatrixEntry
326   when hard copy is involved, newMatrixEntry flag is set to true in order to free memory when deleting MatrixBilinearForm
327 */
328 class MatrixBilinearForm : public BasicBilinearForm
329 {
330   protected :
331     const MatrixEntry* matrix_p;  //!< pointer to a MatrixEntry
332     bool newMatrixEntry_;         //!< useful flag to clean memory
333 
334   public :
335     //constructors/destructor
MatrixBilinearForm()336     MatrixBilinearForm()                                                           //! default constructor
337     : BasicBilinearForm(0,0), matrix_p(0), newMatrixEntry_(false) {}
MatrixBilinearForm(const Unknown & u,const GeomDomain & du,const Unknown & v,const GeomDomain & dv,const MatrixEntry * mp)338     MatrixBilinearForm(const Unknown& u, const GeomDomain& du,
339                        const Unknown& v, const GeomDomain& dv, const MatrixEntry* mp)  //! basic constructor
340     : BasicBilinearForm(&u, &du, &v, &dv), matrix_p(mp), newMatrixEntry_(false) {}
MatrixBilinearForm(const Unknown & u,const GeomDomain & du,const Unknown & v,const GeomDomain & dv,const MatrixEntry & m)341     MatrixBilinearForm(const Unknown& u, const GeomDomain& du,
342                        const Unknown& v, const GeomDomain& dv, const MatrixEntry & m)  //! basic constructor
343     : BasicBilinearForm(&u, &du, &v, &dv), matrix_p(&m), newMatrixEntry_(false) {}
344     template <typename T>
345     MatrixBilinearForm(const Unknown&, const GeomDomain&,
346                        const Unknown&, const GeomDomain&,
347                        const Matrix<T>& , SymType=_noSymmetry);                    //!< constructor from a Matrix<T>
348     template <typename T>
349     MatrixBilinearForm(const Unknown&, const GeomDomain&,
350                        const Matrix<T>& , SymType=_noSymmetry);                    //!< constructor from a Matrix<T>
351     template <typename T>
352     MatrixBilinearForm(const Unknown&, const GeomDomain&,const std::vector<T>&);   //!< constructor from a diagonal matrix(vector)
353     ~MatrixBilinearForm();                                                         //!< destructor
354 
type() const355     virtual LinearFormType type() const       //! return the type of the linear form
356     {return _explicitLf;}
357 };
358 
359 //-------------------------------------------------------------------------------
360 // External functions of MatrixBiLinearForm class
361 //-------------------------------------------------------------------------------
362 //constructor from a Matrix<T>
363 template <typename T>
MatrixBilinearForm(const Unknown & u,const GeomDomain & du,const Matrix<T> & m,SymType sy)364 MatrixBilinearForm::MatrixBilinearForm(const Unknown& u, const GeomDomain& du, const Matrix<T>& m, SymType sy)
365 : BasicBilinearForm(&u, &du, &u, &du)
366 {
367   //create dense storage
368   MatrixStorage* sto= new RowDenseStorage(m.numberOfRows(), m.numberOfColumns(),"");
369   matrix_p= new MatrixEntry(m.valueType(), m.strucType(), sto, m.elementSize(), sy);
370   newMatrixEntry_=true;
371 }
372 
373 //constructor from a Matrix<T>
374 template <typename T>
MatrixBilinearForm(const Unknown & u,const GeomDomain & du,const Unknown & v,const GeomDomain & dv,const Matrix<T> & m,SymType sy)375 MatrixBilinearForm::MatrixBilinearForm(const Unknown& u, const GeomDomain& du,
376                          const Unknown& v, const GeomDomain& dv, const Matrix<T>& m, SymType sy)
377 : BasicBilinearForm(&u, &du, &v, &dv)
378 {
379   //create dense storage
380   MatrixStorage* sto= new RowDenseStorage(m.numberOfRows(), m.numberOfColumns(),"");
381   matrix_p= new MatrixEntry(m.valueType(), m.strucType(), sto, m.elementSize(), sy);
382   matrix_p->add(m.begin(),m.end()); //fill matrix
383   newMatrixEntry_=true;
384 }
385 
386 template <typename T>
MatrixBilinearForm(const Unknown & u,const GeomDomain & d,const std::vector<T> & v)387 MatrixBilinearForm::MatrixBilinearForm(const Unknown& u, const GeomDomain& d, const std::vector<T>& v)
388 {
389   //create csr storage
390   MatrixStorage* sto= new RowCsStorage(v.size(), v.size(),"");
391   matrix_p= new MatrixEntry(v.valueType(), v.strucType(), sto, v.elementSize());
392   matrix_p->add(v.begin(),v.end()); //fill matrix
393   newMatrixEntry_=true;
394 }
395 
396 /*!
397   \class SuBilinearForm
398   describes a linear combination of bilinear forms
399   with the same pair of Unknowns.
400 */
401 class SuBilinearForm
402 {
403 protected:
404   std::vector<blfPair> blfs_;                       //!< list of pairs of bilinear form and coefficient
405 public:
SuBilinearForm()406   SuBilinearForm() {}                               //!< default constructor
407   SuBilinearForm(const SuBilinearForm&);            //!< copy constructor
408   SuBilinearForm(const std::vector<blfPair>&);      //!< full constructor from a list of BasicBilinearForms
409   ~SuBilinearForm();                                //!< destructor
410   SuBilinearForm& operator=(const SuBilinearForm&); //!< assignment operator
411 
size() const412   number_t size() const                       //! number of elements of the linear combination
413     {return blfs_.size();}
blfs()414   std::vector<blfPair>& blfs()              //! access to the list of linear forms
415     {return blfs_;}
blfs() const416   const std::vector<blfPair>& blfs() const  //! access to the list of linear forms
417     {return blfs_;}
operator ()(number_t n)418   blfPair& operator()(number_t n)             //! access to n-th pair
419     {return blfs_[n - 1];}
operator ()(number_t n) const420   const blfPair& operator()(number_t n) const //! access to n-th pair
421     {return blfs_[n - 1];}
begin()422   it_vblfp begin()                          //! iterator to the first element of vector of basic bilinear forms
423     {return blfs_.begin();}
begin() const424   cit_vblfp begin() const                   //! const iterator to the first element of vector of basic bilinear forms
425     {return blfs_.begin();}
end()426   it_vblfp end()                            //! iterator to the last+1 element of vector of basic bilinear forms
427     {return blfs_.end();}
end() const428   cit_vblfp end() const                     //! const iterator to the last+1 element of vector of basic bilinear forms
429     {return blfs_.end();}
430   const Unknown* up() const;                //!< return the first unknown of the bilinear form
431   const Unknown* vp() const;                //!< return the second unknown of the bilinear form
432   const GeomDomain* dom_up() const;         //!< return the u-domain of the FIRST basic bilinear form
433   const GeomDomain* dom_vp() const;         //!< return the v-domain of the FIRST basic bilinear form
434   const Space* uSpace() const;              //!< return the u space of the bilinear form
435   const Space* vSpace() const;              //!< return the v space of the bilinear form
436   LinearFormType type() const;              //!< return the type of the bilinear form (intg,doubleIntg,linearCombination)
437   ValueType valueType() const;              //!< return the value type of the bilinear form
438   SymType symType() const;                  //!< return the symmetry of bilinear form
439   void setUnknowns(const Unknown&, const Unknown&); //!< set unknowns of SuBilinearForm
440 
441   bool checkConsistancy(const SuBilinearForm&) const; //!< check consitancy of Unknown
442   SuBilinearForm& operator +=(const SuBilinearForm&); //!< sum of bilinear forms
443   SuBilinearForm& operator -=(const SuBilinearForm&); //!< difference of linear forms
444   SuBilinearForm& operator *=(const complex_t&);      //!< multiply by a complex
445   SuBilinearForm& operator /=(const complex_t&);      //!< divide by a complex
446 
447   void print(std::ostream&) const;                    //!< print utility
448   string_t asString() const;                          //!< as symbolic string
449 
450 }; // end of BilinearForm class
451 
452 //-------------------------------------------------------------------------------
453 // External functions of SuBilinearForm class
454 //-------------------------------------------------------------------------------
455 std::ostream& operator<<(std::ostream&, const SuBilinearForm&); //!< output SuBilinearForm
456 
457 // operations on bilinear form to construct linear combination of forms
458 SuBilinearForm operator-(const SuBilinearForm&);                        //!< opposite of bilinear form
459 SuBilinearForm operator+(const SuBilinearForm&, const SuBilinearForm&); //!< sum of bilinear forms
460 SuBilinearForm operator-(const SuBilinearForm&, const SuBilinearForm&); //!< difference of bilinear forms
461 SuBilinearForm operator*(const complex_t&, const SuBilinearForm&);        //!< multiply(left) by a scalar
462 SuBilinearForm operator*(const SuBilinearForm&, const complex_t&);        //!< multiply(right) by a scalar
463 SuBilinearForm operator/(const SuBilinearForm&, const complex_t&);        //!< divide by a scalar
464 
465 //@{
466 //! useful typedefs to BilinearForm class
467 typedef std::pair<const Unknown*, const Unknown*> uvPair;
468 typedef std::map<uvPair, SuBilinearForm>::iterator it_mublc;
469 typedef std::map<uvPair, SuBilinearForm>::const_iterator cit_mublc;
470 //@}
471 
472 /*!
473   \class BilinearForm
474   describes a general bilinear form, that is a list of linear combinations of basic bilinear forms.
475   It is intend to collect linear forms with different unknowns, using a map<uvPair,SuBilinearForm>.
476   It is the enduser's class
477 */
478 class BilinearForm
479 {
480 protected:
481   std::map<uvPair, SuBilinearForm> mlcblf_;              //!< list of linear combinations of basic bilinear forms
482 
483 public:
484   SuBilinearForm& operator[](const uvPair&);             //!< access to the bilinear form associated to an unknown
485   const SuBilinearForm& operator[](const uvPair&) const; //!< access to the bilinear form associated to a pair of unknowns
BilinearForm()486   BilinearForm() {}                                                                  //!< default constructor
487   BilinearForm(const SuBilinearForm& lc);                                            //!< constructor from a linear combination
clear()488   void clear()                                                                       //! clear the map of bilinear form
489     {mlcblf_.clear();}
490   bool isEmpty() const;                                                              //!< true if no bilinear form
begin()491   it_mublc begin()                                                                   //! iterator to the first element of map
492     {return mlcblf_.begin();}
begin() const493   cit_mublc begin() const                                                            //! const iterator to the first element of map
494     {return mlcblf_.begin();}
end()495   it_mublc end()                                                                     //! iterator to the last+1 element of map
496     {return mlcblf_.end();}
end() const497   cit_mublc end() const                                                              //! const iterator to the last+1 element of map
498     {return mlcblf_.end();}
499   bool singleUnknown() const;                                                        //!< true if only one unknown
500   const SuBilinearForm& first() const;                                               //!< return first linear combination
501   BilinearForm operator()(const Unknown&, const Unknown&) const;                     //!< access to the bilinear form associated to a pair of unknowns
502   BasicBilinearForm& operator()(const Unknown&, const Unknown&, number_t);             //!< access to the n-th basic bilinear form associated to a pair of unknowns
503   const BasicBilinearForm& operator()(const Unknown&, const Unknown&, number_t) const; //!< access to the n-th basic bilinear form associated to a pair of unknowns
504   const SuBilinearForm* subLfp(const uvPair& uv) const;                              //!< access to SuBiLinearForm pointers related to unknown
505   SuBilinearForm* subLfp(const uvPair& uv);                                          //!< access to SuBiLinearForm pointers related to unknown (non const)
506   void setUnknowns(const Unknown&, const Unknown&);                                  //!< set the unknowns of bilinear forms (only for single unknown bf)
507 
508   void print(std::ostream&) const;                                                   //!< print utility
print(PrintStream & os) const509   void print(PrintStream& os) const {print(os.currentStream());}
510 
511   BilinearForm& operator+=(const BilinearForm&); //!< sum of linear forms
512   BilinearForm& operator-=(const BilinearForm&); //!< difference of linear forms
513   BilinearForm& operator*=(const complex_t&);      //!< multiply by a complex
514   BilinearForm& operator/=(const complex_t&);      //!< divide by a complex
515 };
516 
517 //-------------------------------------------------------------------------------
518 // External functions of BiLinearForm class
519 //-------------------------------------------------------------------------------
520 
521 // Single integral user functions like constructors
522 // ------------------------------------------------
523 // using IntegrationMethod object
524 BilinearForm intg(const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
525                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a simple intg bilinear form
526 BilinearForm intg(const GeomDomain&, const OperatorOnUnknowns&,
527                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a simple intg bilinear form
528 // using explicit quadrature rule as IntegrationMethod
529 BilinearForm intg(const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
530                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a simple intg bilinear form
531 BilinearForm intg(const GeomDomain&, const OperatorOnUnknowns&,
532                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a simple intg bilinear form
533 // using default quadrature rule as IntegrationMethod
534 BilinearForm intg(const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
535                   SymType = _undefSymmetry); //!< construct a simple intg bilinear form
536 BilinearForm intg(const GeomDomain&, const OperatorOnUnknowns&,
537                   SymType = _undefSymmetry); //!< construct a simple intg bilinear form
538 
539 // Double integral user functions like constructors
540 // ------------------------------------------------
541 // using IntegrationMethod object
542 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
543                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form (kernel=1)
544 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknowns&,
545                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form (kernel=1)
546 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
547                   const Kernel&, AlgebraicOperator, const OperatorOnUnknown&,
548                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form from kernel
549 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
550                   const OperatorOnKernel&, AlgebraicOperator, const OperatorOnUnknown&,
551                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form from operator on kernel
552 BilinearForm intg(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
553                   const IntegrationMethod&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form from kernel operator
554 // using IntegrationMethods object
555 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
556                   const IntegrationMethods&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form (kernel=1)
557 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknowns&,
558                   const IntegrationMethods&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form (kernel=1)
559 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
560                   const Kernel&, AlgebraicOperator, const OperatorOnUnknown&,
561                   const IntegrationMethods&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form from kernel
562 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
563                   const OperatorOnKernel&, AlgebraicOperator, const OperatorOnUnknown&,
564                   const IntegrationMethods&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form from operator on kernel
565 BilinearForm intg(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
566                   const IntegrationMethods&, SymType = _undefSymmetry);     //!< construct a double intg bilinear form from kernel operator
567 // using an explicit quadrature rule
568 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
569                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a double intg bilinear form (kernel=1)
570 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknowns&,
571                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a double intg bilinear form (kernel=1)
572 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
573                   const Kernel&, AlgebraicOperator, const OperatorOnUnknown&,
574                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a double intg bilinear form from kernel
575 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
576                   const OperatorOnKernel&, AlgebraicOperator, const OperatorOnUnknown&,
577                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a double intg bilinear form from operator on kernel
578 BilinearForm intg(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
579                   QuadRule, number_t =0, SymType = _undefSymmetry); //!< construct a double intg bilinear form from kernel operator
580 // using default quadrature rule
581 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator, const OperatorOnUnknown&,
582                   SymType = _undefSymmetry); //!< construct a double intg bilinear form (kernel=1)
583 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknowns&,
584                   SymType = _undefSymmetry); //!< construct a double intg bilinear form (kernel=1)
585 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
586                   const Kernel&, AlgebraicOperator, const OperatorOnUnknown&,
587                   SymType = _undefSymmetry); //!< construct a double intg bilinear form from kernel
588 BilinearForm intg(const GeomDomain&, const GeomDomain&, const OperatorOnUnknown&, AlgebraicOperator,
589                   const OperatorOnKernel&, AlgebraicOperator, const OperatorOnUnknown&,
590                   SymType = _undefSymmetry); //!< construct a double intg bilinear form from operator on kernel
591 BilinearForm intg(const GeomDomain&, const GeomDomain&, const KernelOperatorOnUnknowns&,
592                   SymType = _undefSymmetry); //!< construct a double intg bilinear form from kernel operator
593 
594 // -------------------------------------------------------------
595 // algebraic operations on BilinearForms
596 // -------------------------------------------------------------
597 const BilinearForm& operator+(const BilinearForm&);               //!< same bilinear form
598 BilinearForm operator-(const BilinearForm&);                      //!< opposite of a bilinear form
599 BilinearForm operator+(const BilinearForm&, const BilinearForm&); //!< sum of bilinear forms
600 BilinearForm operator-(const BilinearForm&, const BilinearForm&); //!< difference of bilinear forms
601 BilinearForm operator*(const int_t&, const BilinearForm&);        //!< product(left) by an integer scalar
602 BilinearForm operator*(const int&, const BilinearForm&);          //!< product(left) by an integer scalar
603 BilinearForm operator*(const number_t&, const BilinearForm&);     //!< product(left) by an integer scalar
604 BilinearForm operator*(const real_t&, const BilinearForm&);       //!< product(left) by a real scalar
605 BilinearForm operator*(const complex_t&, const BilinearForm&);    //!< product(left) by a complex scalar
606 BilinearForm operator*(const BilinearForm&, const int_t&);        //!< product(right) by an integer scalar
607 BilinearForm operator*(const BilinearForm&, const int&);          //!< product(right) by an integer scalar
608 BilinearForm operator*(const BilinearForm&, const number_t&);     //!< product(right) by an integer scalar
609 BilinearForm operator*(const BilinearForm&, const real_t&);       //!< product(right) by a real scalar
610 BilinearForm operator*(const BilinearForm&, const complex_t&);    //!< product(right) by a complex scalar
611 BilinearForm operator/(const BilinearForm&, const int_t&);        //!< division by an integer scalar
612 BilinearForm operator/(const BilinearForm&, const int&);          //!< division by an integer scalar
613 BilinearForm operator/(const BilinearForm&, const number_t&);     //!< division by an integer scalar
614 BilinearForm operator/(const BilinearForm&, const real_t&);       //!< division by a real scalar
615 BilinearForm operator/(const BilinearForm&, const complex_t&);    //!< division by a complex scalar
616 
617 //composition of bilinear forms
618 BasicBilinearForm& operator*(const BasicBilinearForm&, const BasicBilinearForm&); //!< compose two basic bilinear forms
619 BilinearForm operator*(const BilinearForm&, const BilinearForm&); //!< compose two bilinear forms, have to be basic linear forms
620 
621 // print utility
622 std::ostream& operator<<(std::ostream&, const BilinearForm&);     //!< output BilinearForm
623 
624 } // end of namespace xlifepp
625 
626 #endif /* BILINEAR_FORM_HPP */
627