1 #include <cmath>
2 #include <cstdlib>
3 #include "error.hpp"
4 #include <iostream>
5 #include <fstream>
6 #include <map>
7 #include "rgraph.hpp"
8 using namespace std;
9 
10 #include "RNM.hpp"
11 #include "fem.hpp"
12 #include "FESpace.hpp"
13 
14 namespace  Fem2D {
15 
Make(const TypeOfFE ** t,int k,KN<R2> & P,KN<int> & I)16  int  Make(const TypeOfFE ** t,int k,KN<R2> & P,KN<int> & I)
17  {
18    typedef  TypeOfFE::IPJ IPJ;
19 
20    int n=0,nn=0;
21 
22    for (int i=0;i<k;i++)
23     {
24      const KN<R2> p(t[i]->P_Pi_h);
25      for (int j=0;j<p.N();j++,nn++)
26      {
27        P[n]=p[j]; // par defaut un nouveau => ajout
28        I[nn]=n++;
29        for (int l=0;l<n-1;l++)
30         {
31           R2 QP(p[j],P[l]);
32           if ( (QP,QP) < 1.0e-12 ) {
33             I[nn]=l;
34             n--; // on a retrouver =>  detruit
35             break;}
36         }
37 
38      }
39     }
40    return n; // nombre de point commun
41  }
42 
Makepij_alpha(const TypeOfFE ** t,int k)43  KN<TypeOfFE::IPJ > Makepij_alpha(const TypeOfFE ** t,int k)
44  {
45  // Attention les df est numerote de facon croissant
46  // en faisant une boucle sur les TypeOfFE
47  // comme dans la class TypeOfFESum
48   typedef TypeOfFE::IPJ IPJ;
49   int n=0,m=0;
50   for (int i=0;i< k;i++) {
51     n += t[i]->pij_alpha.N();
52     m += t[i]->P_Pi_h.N();
53     }
54   KN<TypeOfFE::IPJ > ij(n);
55   KN<int> I(m);
56   KN<R2> P(m);
57   Make(t,k,P,I);
58   int p0=0,i0=0,N0=0,nn=0;
59   for (int i=0;i< k;i++) {
60     const KN<IPJ > p(t[i]->pij_alpha);
61      for (int j=0;j<p.N();j++,nn++)
62       {
63         ij[nn].i= p[j].i+i0; //  comme dans TypeOfFESum
64         ij[nn].j= N0+ p[j].j;
65         ij[nn].p= I[p[j].p+p0];
66 
67       //   cout << nn << "Makepij_alpha: " << ij[nn].i << " " << ij[nn].p << " " << ij[nn].j << endl;
68 
69       }
70     i0+=t[i]->NbDoF;
71     p0+=t[i]->P_Pi_h.N();
72     N0+=t[i]->N;}
73   return ij;
74  }
MakeP_Pi_h(const TypeOfFE ** t,int k)75  KN<R2 > MakeP_Pi_h(const TypeOfFE **t,int k)
76  {
77   int np=0;
78   for (int i=0;i< k;i++)
79     np += t[i]->P_Pi_h.N();
80 
81   KN< R2 >  yy(np);
82   KN<int> zz(np);
83   int kk=Make(t,k,yy,zz);
84  // cout << " MakeP_Pi_h: " << kk << " from " << np << endl;
85   return yy(SubArray(kk));
86 
87  }
88 
89 ListOfTFE * ListOfTFE::all ; // list of all object of this type
90 
ListOfTFE(const char * n,TypeOfFE * t)91 ListOfTFE::ListOfTFE (const char * n,TypeOfFE *t) : name(n),tfe(t)
92 {
93   if(!t)
94   assert(t);
95   static int count=0;
96   if (count++==0)
97     all=0; // init of all in dependant of the ordre of the objet file
98   next=all;
99   all=this;
100 }
101 
Make(const FESpace ** l,int k)102 const TypeOfFE ** Make(const FESpace **l,int k) {
103   const TypeOfFE** p=new const TypeOfFE*[k];
104   for (int i=0;i<k;i++)
105     p[i]=l[i]->TFE[0];
106   return p;
107 }
Make(const TypeOfFE ** l,int k)108 const TypeOfFE ** Make(const TypeOfFE **l,int k) {
109   const TypeOfFE** p=new const TypeOfFE*[k];
110   for (int i=0;i<k;i++)
111     p[i]=l[i];
112   return p;
113 }
114 
115 
Same(const FESpace ** l,int k)116 bool Same(const FESpace **l,int k)
117 {
118    for (int i=1;i<k;i++)
119     if (l[0] != l[i] ) return false;
120    return true;
121 }
122 
123 class FESumConstruct { protected:
124    const TypeOfFE ** teb;
125    const int k;
126    int nbn; // nb of node
127    int  *  data;
128    int  * const NN; //  NN[ i:i+1[ dimension de l'element i
129    int  * const DF; // DF[i:i+1[  df associe a l'element i
130    int  * const comp; //
131    FESumConstruct(int kk,const TypeOfFE **t);
~FESumConstruct()132    virtual ~FESumConstruct(){
133      delete [] DF;
134      delete [] NN;
135      delete [] comp;
136      delete [] data;}
137 };
138 
Pi_h(RN_ val,InterpolFunction f,R * v,void * arg=0) const139   void FElement::Pi_h(RN_ val,InterpolFunction f,R *v, void * arg=0) const {
140    // routine: a  tester FH.
141     FElement::aIPJ ipj(Pi_h_ipj());
142     FElement::aR2  PtHat(Pi_h_R2());
143     KN<R>   Aipj(ipj.N());
144     KNM<R>  Vp(N,PtHat.N());
145 
146      Pi_h(Aipj);
147      for (int p=0;p<PtHat.N();p++)
148           {
149             f(v,T(PtHat[p]),*this,T.lab,PtHat[p],arg);
150             KN_<double> Vpp(Vp('.',p));
151             for (int j=0;j<N;j++)
152                Vpp[j]=v[j];
153            }
154 
155          for (int i=0;i<Aipj.N();i++)
156           {
157            const FElement::IPJ &ipj_i(ipj[i]);
158            val[ipj_i.i] += Aipj[i]*Vp(ipj_i.j,ipj_i.p);
159           }
160  }
161 
162 class TypeOfFESum: public FESumConstruct, public  TypeOfFE { public:
TypeOfFESum(const FESpace ** t,int kk)163    TypeOfFESum(const FESpace **t,int kk):
164      FESumConstruct(kk,Make(t,kk)),TypeOfFE(teb,kk,data) {}
TypeOfFESum(const TypeOfFE ** t,int kk)165        TypeOfFESum(const TypeOfFE **t,int kk):
166      FESumConstruct(kk,Make(t,kk)),TypeOfFE(teb,kk,data) {}
167 
168   // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
169    void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
170 //   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
171 //  void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void * arg ) const;
Pi_h_alpha(const baseFElement & K,KN_<double> & v) const172    virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
173     {
174       for (int i=0,k0=0;i<k;i++) {
175           int n=teb[i]->NbDoF;
176           KN_<R> sv(v(SubArray(n,k0)));
177           teb[i]->Pi_h_alpha(K,sv);
178           k0+= n;}
179     }
~TypeOfFESum()180    ~TypeOfFESum(){  delete []  teb;}
181 } ;
182 
183 class FEProduitConstruct { protected:
184    const TypeOfFE & teb;
185    int k;
186    int * data;
187    FEProduitConstruct(int kk,const TypeOfFE &t)  ;
~FEProduitConstruct()188    ~FEProduitConstruct(){delete [] data;}
189 };
190 
191 class TypeOfFEProduit: protected FEProduitConstruct, public  TypeOfFE { public:
TypeOfFEProduit(int kk,const TypeOfFE & t)192    TypeOfFEProduit(int kk,const TypeOfFE &t):
193      FEProduitConstruct(kk,t),TypeOfFE(t,kk,data)  {}
194 
195   // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
196    void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
197 //   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
198 //   void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void * arg ) const;
Pi_h_alpha(const baseFElement & K,KN_<double> & v) const199    virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
200     { int nbof=teb.NbDoF;
201       for (int i=0,k0=0;i<k;i++,k0+=nbof)
202         {
203           KN_<R> sv(v(SubArray(nbof,k0)));
204           teb.Pi_h_alpha(K,sv);
205         }
206     }
207 
~TypeOfFEProduit()208    ~TypeOfFEProduit(){}
209 } ;
210 
FEProduitConstruct(int kk,const TypeOfFE & t)211 FEProduitConstruct::FEProduitConstruct(int kk,const TypeOfFE &t)
212  :k(kk),teb(t)
213 {
214   int m= teb.NbDoF;
215   KN<int> nn(teb.NbNode);
216   nn=0; // nb de dl par noeud
217   for (int i=0;i<m;i++)
218     nn[teb.NodeOfDF[i]]++;
219 
220   int n= m*kk;
221   int N= teb.N*kk;
222   data = new int [n*5+N];
223   int c=0;
224 
225   for (int i=0;i<m;i++)
226    for (int j=0;j<kk;j++)
227     data[c++] = teb.DFOnWhat[i];
228 
229   for (int i=0;i<m;i++)
230    for (int j=0;j<kk;j++) // num of df on node  for the df = j
231       data[c++] = teb.DFOfNode[i]+j*nn[teb.NodeOfDF[i]];
232 
233   for (int i=0;i<m;i++)
234    for (int j=0;j<kk;j++)
235     data[c++] = teb.NodeOfDF[i]; //  node of df
236 
237   for (int i=0;i<m;i++)
238    for (int j=0;j<kk;j++)
239     data[c++] = j; //  node from of FE
240 
241   for (int i=0;i<m;i++)
242    for (int j=0;j<kk;j++)
243     data[c++] = i; //  node from of df in FE
244 
245    for (int j=0;j<kk;j++)
246     for (int i=0;i<teb.N;i++)
247       data[c++]= teb.dim_which_sub_fem[i] + teb.nb_sub_fem*j ;
248 }
249 
FESumConstruct(int kk,const TypeOfFE ** t)250 FESumConstruct::FESumConstruct(int kk,const TypeOfFE **t)
251  :k(kk),teb(t),NN(new int[kk+1]),DF(new int[kk+1]) , comp(new int[kk])
252 {
253    map<const TypeOfFE *,int> m;
254    int i=k,j;
255    while(i--) // on va a l'envert pour avoir comp[i] <=i
256       m[teb[i]]=i;
257     // l'ordre comp est important comp est croissant  mais pas de pb.
258    i=k;
259    while(i--)
260      comp[i]=m[teb[i]]; //  comp[i] <=i
261 
262   // reservatition des intervalles en espaces
263   int n=0,N=0;
264    for ( j=0;j<kk;j++)
265      {NN[j]=N;N+=teb[j]->N;}
266    NN[kk] = N;
267  //  reservation des interval en df
268    n=0;
269    for ( j=0;j<kk;j++)
270     { DF[j]=n;n+=teb[j]->NbDoF;}
271    DF[kk] = n;
272 //  n = nb de DF total
273 //  N the fem is in R^N
274 
275   data = new int [n*5 + N];
276   int c=0;
277   int ki= 0;
278 // recherche des noeuds
279    KN<int> w(7),nn(7);
280    w=0;
281    nn=0;
282 
283 
284    for ( j=0;j<kk;j++)
285      for ( i=0;i<teb[j]->NbDoF;i++)
286          nn[teb[j]->DFOnWhat[i]]++;
287    nbn=0;
288    for( j=0;j<7;j++)
289      if (nn[j]) nn[j]=nbn++;
290      else nn[j]=-1;
291    KN<int> dln(7);
292    dln=0;
293   // nn donne numero de noeud sur what
294    for ( j=0;j<kk;j++)
295      for ( i=0;i<teb[j]->NbDoF;i++)
296        data[c++] = teb[j]->DFOnWhat[i];
297 
298    for ( j=0;j<kk;j++)
299     {
300      int  cc=c;
301      for ( i=0;i<teb[j]->NbDoF;i++)
302        data[c++] = teb[j]->DFOfNode[i]+dln[teb[j]->DFOnWhat[i]];
303      for ( i=0;i<teb[j]->NbDoF;i++)
304        dln[teb[j]->DFOnWhat[i]]=Max(dln[teb[j]->DFOnWhat[i]],data[cc++]+1);
305     }
306 
307 
308    for ( j=0;j<kk;j++)
309     {
310      //  w renumerotation des noeuds
311      //  Ok si un noeud par what
312      for ( i=0;i<teb[j]->NbDoF;i++)
313        data[c++] = nn[teb[j]->DFOnWhat[i]];
314     }
315 
316    for ( j=0;j<kk;j++)
317      for ( i=0;i<teb[j]->NbDoF;i++)
318        data[c++] = j; //  node from of FE
319 
320 
321    for ( j=0;j<kk;j++)
322      for ( i=0;i<teb[j]->NbDoF;i++)
323        data[c++] = i; //  node from of df in FE
324 
325    int xx=0;
326    for (j=0;j<kk;j++)
327      {
328       int xxx=xx;
329       for (i=0;i<teb[j]->N;i++)
330        {
331          data[c] = teb[j]->dim_which_sub_fem[i]+xx;
332          xxx=Max(xxx,data[c]+1);
333          c++;
334        }
335        xx=xxx;
336      }
337 
338   throwassert(c== 5*n+N);
339 /*  int cc=0;
340    cout << " Data : " << endl;
341   for ( i=0;i<5;i++)    {
342     for (j=0;j<n;j++)
343       cout << " " << data[cc++];
344      cout << endl;}
345  cout << " which " ;
346  for (i=0;i<N;i++)
347    cout << " " << data[cc++];
348   cout << endl;*/
349 }
350 
351 class TypeOfFE_P1Lagrange : public  TypeOfFE { public:
352   static int Data[];
353   static double Pi_h_coef[];
TypeOfFE_P1Lagrange()354    TypeOfFE_P1Lagrange(): TypeOfFE(1,0,0,1,Data,1,1,3,3,Pi_h_coef)
355     { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) };
356       for (int i=0;i<NbDoF;i++) {
357        pij_alpha[i]= IPJ(i,i,0);
358        P_Pi_h[i]=Pt[i]; }
359      }
360   // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
361    void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
362 
363 //   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
364   // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
365 virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
366 
367 } ;
368 
369 ///////////////////////////////////////////////////////////////////////////////
370 ////////////////////////////////// NEW ////////////////////////////////////////
371 ///////////////////////////////////////////////////////////////////////////////
372 
373 class TypeOfFE_P1Bubble : public  TypeOfFE { public:
374   static int Data[];
375   static double Pi_h_coef[];
TypeOfFE_P1Bubble()376    TypeOfFE_P1Bubble(): TypeOfFE(1,0,1,1,Data,1,1,4,4,Pi_h_coef)
377     { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1), R2(1./3.,1./3.) };
378       for (int i=0;i<NbDoF;i++) {
379        pij_alpha[i]= IPJ(i,i,0);
380        P_Pi_h[i]=Pt[i]; }
381      }
382   // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
383    void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
384 
385 //   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
386  //  void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
387   //virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
388 
389 } ;
390 ///////////////////////////////////////////////////////////////////////////////
391 ///////////////////////////////////////////////////////////////////////////////
392 
393 class TypeOfFE_P2Lagrange : public  TypeOfFE { public:
394   static int Data[];
395   static double Pi_h_coef[];
396 
TypeOfFE_P2Lagrange()397    TypeOfFE_P2Lagrange(): TypeOfFE(1,1,0,1,Data,3,1,6,6,Pi_h_coef)
398     { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0) };
399       for (int i=0;i<NbDoF;i++) {
400        pij_alpha[i]= IPJ(i,i,0);
401        P_Pi_h[i]=Pt[i]; }
402      }
403 
404   // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
405    void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
406  //  void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
407   // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
408 } ;
409 
410 int TypeOfFE_P1Lagrange::Data[]={0,1,2,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0};
411 int TypeOfFE_P1Bubble::Data[]={0,1,2,6,     0,0,0,0,     0,1,2,3,     0,0,0,0,        0,1,2,3,     0};
412 int TypeOfFE_P2Lagrange::Data[]={0,1,2,3,4,5, 0,0,0,0,0,0, 0,1,2,3,4,5, 0,0,0,0,0,0,  0,1,2,3,4,5, 0};
413 double TypeOfFE_P1Lagrange::Pi_h_coef[]={1.,1.,1.};
414 double TypeOfFE_P1Bubble::Pi_h_coef[]={1.,1.,1.,1.};
415 double TypeOfFE_P2Lagrange::Pi_h_coef[]={1.,1.,1.,1.,1.,1.};
416 
dump(char * m,int n,int * p)417 inline void dump(char *m,int n,int * p)
418 {
419   cout << m ;
420   for (int i=0;i<n;i++) cout << " " << p[i] ;
421   cout << endl;
422 }
423 
424 
425 
~ConstructDataFElement()426 ConstructDataFElement::~ConstructDataFElement()
427 {
428   if(*counter==0)
429    {
430     delete [] NodesOfElement;
431     delete []  FirstNodeOfElement;
432     delete [] FirstDfOfNode;
433   }
434  else counter--;
435 }
436 
ConstructDataFElement(const ConstructDataFElement * t,int k)437  ConstructDataFElement::ConstructDataFElement(const ConstructDataFElement * t,int k)
438   :thecounter(0),
439    counter(t->counter),
440    MaxNbNodePerElement(t->MaxNbNodePerElement),
441    MaxNbDFPerElement(t->MaxNbDFPerElement*k),
442    NodesOfElement(t->NodesOfElement),
443    FirstNodeOfElement(t->FirstNodeOfElement),
444    FirstDfOfNode(0),
445    NbOfElements(t->NbOfElements),
446    NbOfDF(t->NbOfDF*k),
447    NbOfNode(t->NbOfNode),
448    Nproduit(t->Nproduit*k)
449  {
450    throwassert(t==0 || t->FirstDfOfNode==0);
451    *counter++;
452  }
453 
ConstructDataFElement(const Mesh & Th,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,const TypeOfMortar * tm,int nbdfv,const int * ndfv,int nbdfe,const int * ndfe)454 ConstructDataFElement::ConstructDataFElement (const Mesh &Th,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,const TypeOfMortar *tm,
455 int nbdfv,const int *ndfv,int nbdfe,const int *ndfe)
456 : counter(&thecounter),thecounter(0)
457 {
458  Make(Th,NbDfOnSommet,NbDfOnEdge,NbDfOnElement, tm,nbdfv,ndfv,nbdfe,ndfe);
459 }
460 
ConstructDataFElement(const FESpace ** l,int k)461 ConstructDataFElement::ConstructDataFElement(const FESpace ** l,int k)
462 : thecounter(0),counter(&thecounter)
463 {
464  int NbDfOnSommet=0;
465  int NbDfOnEdge=0;
466  int NbDfOnElement=0;
467  const Mesh & Th(l[0]->Th);
468  for  (int i=0;i<k;i++)
469    {
470      NbDfOnSommet += l[i]->TFE[0]->NbDfOnVertex;
471      NbDfOnEdge += l[i]->TFE[0]->NbDfOnEdge;
472      NbDfOnElement += l[i]->TFE[0]->NbDfOnElement;
473      throwassert( &Th== &l[i]->Th);
474      throwassert( l[i]->TFE.constant());
475    }
476 
477  Make(Th,NbDfOnSommet,NbDfOnEdge,NbDfOnElement,0);
478 }
479 
480 
Make(const Mesh & Th,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,const TypeOfMortar * tm,int nb_dfv,const int * ndfv,int nb_dfe,const int * ndfe)481 void ConstructDataFElement::Make(const Mesh &Th,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,const TypeOfMortar *tm,
482 int nb_dfv,const int *ndfv,int nb_dfe,const int *ndfe)
483 {
484   *counter=0;
485   Nproduit =1;
486   int ndf=0,samendf=1;
487 
488   int nbdfe=3*NbDfOnSommet+3*NbDfOnEdge+NbDfOnElement;
489   int nbne = 0;
490   int nn=0;
491   int firstmul=0;
492   throwassert( tm || Th.NbMortars==0);
493   NbOfElements = Th.nt; //  by default
494   // if mortars
495   //
496   int NbOfNodeL=0;
497   NbOfElements += Th.NbMortars;
498   FirstDfOfNode =0;
499   FirstNodeOfElement=0;
500   MaxNbDFPerElement=3*NbDfOnSommet+3*NbDfOnEdge+NbDfOnElement;
501 
502   int ks=0,ke=0,kt=0;
503   if(NbDfOnSommet) { nbne+=3;
504      ks=1;
505      ndf=NbDfOnSommet;}
506 
507   if(NbDfOnEdge) {  nbne+=3;
508      ke=1;
509      samendf &= !ndf || ndf == NbDfOnEdge;
510      ndf=NbDfOnEdge;}
511 
512   if(NbDfOnElement) {  nbne+=1;
513      kt=1;
514      samendf &= !ndf || ndf == NbDfOnElement;
515      ndf=NbDfOnElement;}
516 
517   int NbDFonNode[7],NodeIsOn[7];
518    {
519      int j=0,k=0;
520      if(ks) { NbDFonNode[j++]=NbDfOnSommet; NbDFonNode[j++]=NbDfOnSommet; NbDFonNode[j++]=NbDfOnSommet;}
521      if(ke) { NbDFonNode[j++]=NbDfOnEdge; NbDFonNode[j++]=NbDfOnEdge; NbDFonNode[j++]=NbDfOnEdge;}
522      if(kt) { NbDFonNode[j++]=NbDfOnElement;}
523 
524      if (ks) {NodeIsOn[k++]=0;NodeIsOn[k++]=1;NodeIsOn[k++]=2;}
525      if (ke) {NodeIsOn[k++]=3;NodeIsOn[k++]=4;NodeIsOn[k++]=5;}
526      if (kt) {NodeIsOn[k++]=6;}
527 
528      throwassert(j == nbne);
529   }
530 
531     MaxNbNodePerElement=nbne;
532 
533 //
534    if ( ks && (!ke && ! kt) && (ndfv==0 && ndfe==0))
535      {nn=Th.nv;
536       NodesOfElement=0;
537       }
538    else {
539 //    constuction du tableau  NodesOfElement  bofbof
540 
541 //     computation of the length lne of array NodesOfElement
542        int lne=  Th.nt*nbne;
543        if (Th.NbMortars)
544         {
545           samendf= false;
546           NbOfNodeL=Th.NbMortars;
547           throwassert(tm);
548           FirstNodeOfElement = new int[NbOfElements+1];
549           int k=0,kk=0;
550           for (k=0;k<Th.nt;k++,kk+=nbne)
551             FirstNodeOfElement[k] = kk;
552 
553           for (int im=0;im<Th.NbMortars;im++) // (www) code
554             {
555              FirstNodeOfElement[k++]=lne;
556              lne += tm->NbOfNodes(Th,Th.mortars[im]);
557             }
558           FirstNodeOfElement[k++]=lne;
559         }
560 
561        NodesOfElement = new int[lne];
562 
563        for (int i=0;i<lne;i++)
564          NodesOfElement[i]=-1;
565        int i=0;
566        int oe=0;
567        if(ks) { oe=3;nn=ndfv ? nb_dfv : Th.nv;}
568 
569        if (ke && ndfe) {
570         for (int be=0;be<Th.neb;be++)
571          {
572           int j,k=Th.BoundaryElement(be,j);
573           int jj=j;
574           int kk=Th.ElementAdj(k,jj);
575           if ( kk >=0 && jj>=0)
576             NodesOfElement[kk*nbne+oe+jj] = nn + ndfe[be]   ; // adj
577           NodesOfElement[k*nbne+oe+j]   = nn + ndfe[be]   ; // new
578          }
579          nn += nb_dfe;
580         }
581        for (int k=0;k<Th.nt;k++)
582         {
583           int iold=i;
584           if(ks) {
585             for (int j=0;j<3;j++)
586              NodesOfElement[i++]= ndfv ?  ndfv[Th(k,j)] : Th(k,j) ;
587           }
588           if(ke) {
589             for (int j=0;j<3;j++)
590              if (NodesOfElement[i]<0) {
591                int jj=j;
592                int kk=Th.ElementAdj(k,jj);
593 
594                NodesOfElement[kk*nbne+oe+jj] = nn   ; // adj
595                NodesOfElement[i++]           = nn++ ; // new
596              }  else i++;
597           }
598           if(kt)
599              NodesOfElement[i++]= nn++;
600          // cout << k ;
601          // dump(" ",i-iold, NodesOfElement+iold);
602         }
603        // cout << i << " " << Th.nt*nbne << endl;
604         firstmul=nn;
605         if (Th.NbMortars)
606           {
607             //  construction of the mortars element
608            int * color= new int [firstmul];
609            //
610            int thecolor=0;
611            for (int j=0;j<firstmul;j++)
612              color[j]=thecolor;
613 
614            for (int im=0;im<Th.NbMortars;im++)
615             {
616              int iold=i;
617              thecolor++; // get a new color
618              // tm->ConstructionOfNode(Th,im,NodesOfElement,FirstNodeOfElement,nn);
619              Mortar & M(Th.mortars[im]);
620               NodesOfElement[i++] = nn++; // the first node is the lag. mul.
621              int n=M.NbT();
622              for (int kk=0;kk<n;kk++)
623              {
624               int K,e;
625                K=M.T_e(kk,e);
626                int kb=FirstNodeOfElement[K];
627                int ke=FirstNodeOfElement[K+1];
628                for (int j=kb,jj=0;j<ke;j++,jj++)
629                 if (onWhatIsEdge[e][NodeIsOn[jj]])
630                  { // the node jj is on edge e
631                     int node=NodesOfElement[j];
632                    // cout << "." << jj << " K=" << K <<" "<<e << " n=" << node ;
633                     throwassert(node<firstmul);
634                     if (color[node] != thecolor) //  new node => adding
635                      {
636                     //   cout << "a, ";
637                        color[node] = thecolor;
638                        NodesOfElement[i++] = node;
639                      }
640                    // else cout << ", ";
641                  }
642                }
643                //cout << endl;
644 
645                //cout << im ;
646                //dump(": ",i-iold, NodesOfElement+iold);
647                throwassert(i==FirstNodeOfElement[im+Th.nt+1]);
648               }
649              delete [] color;
650           }
651         else
652           throwassert(i==Th.nt*nbne);
653         NbOfNode=nn;
654 
655 
656    }
657   NbOfNode=nn;
658   int NbOfDFL=0;
659    if (! samendf)
660        { throwassert(NodesOfElement);
661          FirstDfOfNode= new int [nn+1];
662          for (int i=0;i<=nn;i++) FirstDfOfNode[i]=-1;
663          int i=0;
664          //  the classical part (FEM)
665          for (int k=0;k<Th.nt;k++)
666            for (int j=0;j<nbne;j++) // thanks to student
667              FirstDfOfNode[ NodesOfElement[i++]+1]=NbDFonNode[j];
668          //  the mortars parts juste the mulplicator
669 
670          for (int km=0,k=Th.nt;km<Th.NbMortars;km++,k++)
671             {  //  the lag. mult. is the first node of the mortar --
672               throwassert(FirstNodeOfElement);
673               //  hack
674               int fk=FirstNodeOfElement[k];
675               int lk=FirstNodeOfElement[k+1];
676               int ndlmul = tm->NbLagrangeMult(Th,Th.mortars[km]);  //  On node par
677               int nodemul = NodesOfElement[fk]; // the first node is the lagr. mul.
678               throwassert(FirstDfOfNode[nodemul+1]==-1);
679               FirstDfOfNode[nodemul+1]= ndlmul;
680               NbOfDFL += ndlmul;
681               int nbdle=0;
682               int nbnm=lk-fk;
683               for (int j=fk;j<lk;j++)
684                nbdle+=FirstDfOfNode[NodesOfElement[j]+1];
685               MaxNbDFPerElement = Max(MaxNbDFPerElement,nbdle);
686             }
687 
688          FirstDfOfNode[0]=0;
689          for (int i=0;i<=nn;i++) throwassert(FirstDfOfNode[i]!=-1);
690 
691          for (int i=0;i<nn;i++)
692               FirstDfOfNode[i+1] += FirstDfOfNode[i] ;
693            NbOfDF=  FirstDfOfNode[nn];
694         }
695     else
696        {
697          NbOfDF = nn*ndf;
698          Nproduit = ndf;
699        }
700    MaxNbNodePerElement=nbne;
701 
702    cout << " Nb Of Nodes = " << nn << endl;
703    if(NbOfNodeL)
704      cout << " Nb of Lagrange Mul Node = " << NbOfNodeL << endl;
705    cout << " Nb of DF = " << NbOfDF << endl;
706    if(NbOfDFL) {
707      cout << " Nb of Lagrange Mul DF = "   << NbOfDFL << endl;
708      cout << " MaxNbDFPerElement     =   " << MaxNbDFPerElement << endl;
709    };
710 
711 }
712 
FESpace(const FESpace & Vh,int k)713 FESpace::FESpace(const FESpace & Vh,int k )
714  :
715      ptrTFE(new TypeOfFEProduit(k,*Vh.TFE[0])),
716      TFE(1,0,ptrTFE),
717      cmesh(Vh.Th),
718      cdef(Vh.cdef?new ConstructDataFElement(Vh.cdef,k):0),
719      N(Vh.N*k),
720      Nproduit(Vh.Nproduit*k),
721      nb_sub_fem(TFE[0]->nb_sub_fem),
722      dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
723 
724      Th(Vh.Th),
725      NbOfDF(Vh.NbOfDF*k),
726      NbOfElements(Vh.NbOfElements),
727      NbOfNodes(Vh.NbOfNodes),
728      MaxNbNodePerElement(Vh.MaxNbNodePerElement),
729      MaxNbDFPerElement(Vh.MaxNbDFPerElement*k),
730      NodesOfElement(Vh.NodesOfElement),
731      FirstDfOfNodeData(cdef?cdef->FirstDfOfNode:0),
732      FirstNodeOfElement(Vh.FirstNodeOfElement),
733      tom(0) {
734      if(cdef) renum();}
735 
FESpace(const FESpace ** Vh,int k)736 FESpace::FESpace(const FESpace ** Vh,int k )
737  :
738      ptrTFE(new TypeOfFESum(Vh,k)),
739      TFE(1,0,ptrTFE),
740      cmesh((**Vh).Th),
741      cdef(new ConstructDataFElement(Vh,k)),
742      N(sum(Vh,&FESpace::N,k)),
743      Nproduit(cdef->Nproduit),
744      nb_sub_fem(TFE[0]->nb_sub_fem),
745      dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
746 
747      Th((**Vh).Th),
748      NbOfDF(cdef->NbOfDF),
749      NbOfElements(cdef->NbOfElements),
750      NbOfNodes(cdef->NbOfNode),
751      MaxNbNodePerElement(cdef->MaxNbNodePerElement),
752      MaxNbDFPerElement(cdef->MaxNbDFPerElement),
753      NodesOfElement(cdef->NodesOfElement),
754      FirstDfOfNodeData(cdef->FirstDfOfNode),
755      FirstNodeOfElement(cdef->FirstNodeOfElement),
756      tom(0) {
757      if(cdef) renum(); }
758 
FESpace(const Mesh & TTh,const TypeOfFE ** tef,int k,int nbdfv,const int * ndfv,int nbdfe,const int * ndfe)759 FESpace::FESpace(const Mesh & TTh,const TypeOfFE ** tef,int k,int nbdfv,const int *ndfv,int nbdfe,const int *ndfe )
760  :
761      ptrTFE(new TypeOfFESum(tef,k)),
762      TFE(1,0,ptrTFE),
763      cmesh(TTh),
764      cdef(new ConstructDataFElement(TTh,sum(tef,&TypeOfFE::NbDfOnVertex,k),
765                                         sum(tef,&TypeOfFE::NbDfOnEdge,k),
766                                         sum(tef,&TypeOfFE::NbDfOnElement,k),
767                                         0,nbdfv,ndfv,nbdfe,ndfe)),
768      N(sum(tef,&TypeOfFE::N,k)),
769      Nproduit(cdef->Nproduit),
770      nb_sub_fem(TFE[0]->nb_sub_fem),
771      dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
772 
773      Th(TTh),
774      NbOfDF(cdef->NbOfDF),
775      NbOfElements(cdef->NbOfElements),
776      NbOfNodes(cdef->NbOfNode),
777      MaxNbNodePerElement(cdef->MaxNbNodePerElement),
778      MaxNbDFPerElement(cdef->MaxNbDFPerElement),
779      NodesOfElement(cdef->NodesOfElement),
780      FirstDfOfNodeData(cdef->FirstDfOfNode),
781      FirstNodeOfElement(cdef->FirstNodeOfElement),
782      tom(0) {
783      if(cdef) renum(); }
784 
785 
FESpace(const Mesh & TTh,const TypeOfFE & tef,int nbdfv,const int * ndfv,int nbdfe,const int * ndfe)786  FESpace::FESpace(const Mesh & TTh,const TypeOfFE & tef,int nbdfv,const int *ndfv,int nbdfe,const int *ndfe)
787    :
788      ptrTFE(0),
789      TFE(1,0,&tef),
790      cmesh(TTh),
791      cdef(new ConstructDataFElement(TTh,tef.NbDfOnVertex,tef.NbDfOnEdge,tef.NbDfOnElement,0,nbdfv,ndfv,nbdfe,ndfe)),
792      N(tef.N),
793      Nproduit(cdef->Nproduit),
794      nb_sub_fem(TFE[0]->nb_sub_fem),
795      dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
796      Th(TTh),
797      NbOfDF(cdef->NbOfDF),
798      NbOfElements(cdef->NbOfElements),
799      NbOfNodes(cdef->NbOfNode),
800      MaxNbNodePerElement(cdef->MaxNbNodePerElement),
801      MaxNbDFPerElement(cdef->MaxNbDFPerElement),
802      NodesOfElement(cdef->NodesOfElement),
803      FirstDfOfNodeData(cdef->FirstDfOfNode),
804      FirstNodeOfElement(cdef->FirstNodeOfElement),
805      tom(0) {
806      if(tef.NbDfOnVertex || tef.NbDfOnEdge) renum();
807      }
808 
~FESpace()809  FESpace::~FESpace()
810    {
811      SHOWVERB(cout << " FESpace::~FESpace() " << endl);
812       delete  cdef;
813       if(ptrTFE)
814         delete  ptrTFE;
815    }
816 
FESpace(const Mesh & TTh,const TypeOfFE & tef,const TypeOfMortar & tm)817  FESpace::FESpace(const Mesh & TTh,const TypeOfFE & tef,const TypeOfMortar & tm)
818    :
819      ptrTFE(0),
820      TFE(1,0,&tef),
821      cmesh(TTh),
822      cdef(new ConstructDataFElement(TTh,tef.NbDfOnVertex,tef.NbDfOnEdge,tef.NbDfOnElement,&tm)),
823      N(tef.N),
824      Nproduit(1),
825      nb_sub_fem(TFE[0]->nb_sub_fem),
826      dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
827      Th(TTh),
828      NbOfDF(cdef->NbOfDF),
829      NbOfElements(cdef->NbOfElements),
830      NbOfNodes(cdef->NbOfNode),
831      MaxNbNodePerElement(cdef->MaxNbNodePerElement),
832      MaxNbDFPerElement(cdef->MaxNbDFPerElement),
833      NodesOfElement(cdef->NodesOfElement),
834      FirstDfOfNodeData(cdef->FirstDfOfNode),
835      FirstNodeOfElement(cdef->FirstNodeOfElement),
836      tom(&tm) {
837      // cout << "avant renum ="<< *this <<endl;
838        renum();
839      // cout << "apres renum ="<< *this <<endl;
840      }
841 
renum(const long * r,int l)842 void ConstructDataFElement::renum(const long *r,int l)
843  {
844 /*   cout << "renu=" << l << ":" << endl;
845    for (int i=0;i<NbOfNode;i++)
846       if (i%10) cout << r[i] << "\t";
847       else cout << "\n " << i << ":\t" << r[i] << "\t";
848       cout << endl;
849 */
850    throwassert(this);
851    if (NodesOfElement)
852      for (int i=0;i< l ; i++)
853        NodesOfElement[i]=r[NodesOfElement[i]];
854    if(FirstDfOfNode)
855     { int k,i,*n=new int[NbOfNode];
856       for ( i=0;i<NbOfNode;i++)
857          n[r[i]]=FirstDfOfNode[i+1]-FirstDfOfNode[i];
858       FirstDfOfNode[0]=k=0;
859       for(i=0;i< NbOfNode;)
860         {k+=n[i];
861          FirstDfOfNode[++i]=k;}
862        delete [] n;
863     }
864  }
865 
866 
867 /*
868  void TypeOfFEProduit::D2_FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
869  {
870    int n=teb.NbDoF;
871    int m=teb.N;
872    val=0.0;
873    SubArray t(3);
874    RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
875    teb.D2_FB(Th,K,P,v);
876    for (int i=1;i<k;i++)
877      val(SubArray(n,i,k),SubArray(m,m*i),t)=v;
878  }
879 */
880 /*
881  void TypeOfFEProduit::FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
882  {
883    int n=teb.NbDoF;
884    int m=teb.N;
885    val=0.0;
886    SubArray t(3);
887    RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
888    teb.FB(Th,K,P,v);
889    for (int i=1;i<k;i++)
890      val(SubArray(n,i,k),SubArray(m,m*i),t)=v;
891  }
892  */
FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const893  void TypeOfFEProduit::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
894  {
895    int n=teb.NbDoF;
896    int m=teb.N;
897    val=0.0;
898    SubArray t(val.K());
899    RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
900    teb.FB(whatd,Th,K,P,v);
901    for (int i=1;i<k;i++)
902      val(SubArray(n,i,k),SubArray(m,m*i),t)=v;
903  }
904 
905 /*
906  void TypeOfFEProduit::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j, void * arg) const
907  {
908    const baseFElement  KK(K,teb);
909    int m=teb.N;
910     for(int i=0;i<k;i++)
911      { RN_  vv(val(SubArray(m,m*i)));
912      teb.Pi_h(KK,vv,f,v,j+i*m,arg);}
913  }
914 
915 /*
916  void TypeOfFESum::D2_FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
917  {
918    val=0.0;
919    SubArray t(3);
920    for (int i=0;i<k;i++)
921     {
922      int j=comp[i];
923      int ni=NN[i];
924      int di=DF[i];
925      int i1=i+1;
926      int nii=NN[i1];
927      int dii=DF[i1];
928      throwassert(ni<nii && di < dii);
929      RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));
930      if (j<=i)
931        teb[i]->D2_FB(Th,K,P,v);
932      else
933        v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);
934     } }
935 */
936 /*
937  void TypeOfFESum::FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
938  {
939    val=0.0;
940    SubArray t(3);
941    for (int i=0;i<k;i++)
942     {
943      int j=comp[i];
944      int ni=NN[i];
945      int di=DF[i];
946      int i1=i+1;
947      int nii=NN[i1];
948      int dii=DF[i1];
949      throwassert(ni<nii && di < dii);
950      RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));
951      if (j<=i)
952        teb[i]->FB(Th,K,P,v);
953      else
954        v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);
955     }
956  }
957 */
FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const958   void TypeOfFESum::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
959  {
960    val=0.0;
961    SubArray t(val.K());
962    for (int i=0;i<k;i++)
963     {
964      int j=comp[i];
965      int ni=NN[i];
966      int di=DF[i];
967      int i1=i+1;
968      int nii=NN[i1];
969      int dii=DF[i1];
970      throwassert(ni<nii && di < dii);
971      RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));
972      if (j<=i)
973        teb[i]->FB(whatd,Th,K,P,v);
974      else
975        v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);
976     }
977  }
978 /*
979  void TypeOfFESum::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int jjj, void * arg) const
980  {
981     for(int i=0;i<k;i++)
982      {
983        const baseFElement  KK(K,*teb[i]);
984        int dfii=DF[i+1],dfi=DF[i];
985        RN_  vv(val(SubArray(dfii-dfi,dfi)));
986        teb[i]->Pi_h(KK,vv,f,v,jjj+NN[i],arg);
987      }
988     // cout << val(SubArray(NbDoF)) << endl;
989 
990  }
991  /*
992  void TypeOfFE_P1Lagrange::D2_FB(const Mesh & ,const Triangle & ,const R2 & ,RNMK_ & val) const
993 { //
994   val=0;
995 }
996 */
997 /*
998  void TypeOfFE_P2Lagrange::D2_FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
999 { // 2 times derivatives  for error indicator
1000 //  const Triangle & K(FE.T);
1001   R2 A(K[0]), B(K[1]),C(K[2]);
1002   R l0=1-P.x-P.y,l1=P.x,l2=P.y;
1003   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
1004   R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1);
1005 
1006   throwassert(val.N() >=6);
1007   throwassert(val.M()==1 );
1008   throwassert(val.K()==3 );
1009 
1010   val=0;
1011   RN_ fxx(val('.',0,0));
1012   RN_ fxy(val('.',0,1));
1013   RN_ fyy(val('.',0,2));
1014 
1015   fxx[0] = 4*Dl0.x*Dl0.x;
1016   fxx[1] = 4*Dl1.x*Dl1.x;
1017   fxx[2] = 4*Dl2.x*Dl2.x;
1018   fxx[3] =  8*Dl1.x*Dl2.x;
1019   fxx[4] =  8*Dl0.x*Dl2.x;
1020   fxx[5] =  8*Dl0.x*Dl1.x;
1021 
1022   fyy[0] = 4*Dl0.y*Dl0.y;
1023   fyy[1] = 4*Dl1.y*Dl1.y;
1024   fyy[2] = 4*Dl2.y*Dl2.y;
1025   fyy[3] =  8*Dl1.y*Dl2.y;
1026   fyy[4] =  8*Dl0.y*Dl2.y;
1027   fyy[5] =  8*Dl0.y*Dl1.y;
1028 
1029   fxy[0] = 4*Dl0.y*Dl0.y;
1030   fxy[1] = 4*Dl1.y*Dl1.y;
1031   fxy[2] = 4*Dl2.y*Dl2.y;
1032   fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
1033   fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
1034   fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
1035 
1036 }
1037 */
operator ()(const FElement & K,const R2 & PHat,const KN_<R> & u,int componante,int op) const1038  R TypeOfFE_P1Lagrange::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const
1039 {
1040    R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
1041    R r=0;
1042    if (op==0)
1043     {
1044       R l0=1-PHat.x-PHat.y,l1=PHat.x,l2=PHat.y;
1045       r = u0*l0+u1*l1+l2*u2;
1046     }
1047    else
1048     {
1049        const Triangle & T=K.T;
1050        R2 D0 = T.H(0) , D1 = T.H(1)  , D2 = T.H(2) ;
1051        if (op==1)
1052          r =  D0.x*u0 + D1.x*u1 + D2.x*u2 ;
1053         else
1054          r =  D0.y*u0 + D1.y*u1 + D2.y*u2 ;
1055     }
1056  //  cout << r << "\t";
1057    return r;
1058 }
1059 
1060 
FB(const bool * whatd,const Mesh &,const Triangle & K,const R2 & P,RNMK_ & val) const1061 void TypeOfFE_P1Lagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
1062 {
1063 //  const Triangle & K(FE.T);
1064   R2 A(K[0]), B(K[1]),C(K[2]);
1065   R l0=1-P.x-P.y,l1=P.x,l2=P.y;
1066 
1067   if (val.N() <3)
1068    throwassert(val.N() >=3);
1069   throwassert(val.M()==1 );
1070 //  throwassert(val.K()==3 );
1071 
1072   val=0;
1073   RN_ f0(val('.',0,op_id));
1074 
1075   if (whatd[op_id])
1076    {
1077     f0[0] = l0;
1078     f0[1] = l1;
1079     f0[2] = l2;}
1080  if (whatd[op_dx] || whatd[op_dy])
1081   {
1082   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
1083 
1084   if (whatd[op_dx])
1085    {
1086     RN_ f0x(val('.',0,op_dx));
1087    f0x[0] = Dl0.x;
1088    f0x[1] = Dl1.x;
1089    f0x[2] = Dl2.x;
1090   }
1091 
1092   if (whatd[op_dy]) {
1093     RN_ f0y(val('.',0,op_dy));
1094    f0y[0] = Dl0.y;
1095    f0y[1] = Dl1.y;
1096    f0y[2] = Dl2.y;
1097   }
1098   }
1099 }
1100 
1101 ///////////////////////////////////////////////////////////////////////////////
1102 ///////////////////////////////// NEW /////////////////////////////////////////
1103 ///////////////////////////////////////////////////////////////////////////////
1104 /*
1105 void TypeOfFE_P1Bubble::FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const
1106 {
1107   assert(0);
1108 }
1109 
1110 
1111 void TypeOfFE_P1Bubble::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const
1112 {
1113   assert(0);
1114 }
1115 
1116 /*
1117 R TypeOfFE_P1Bubble::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const
1118 {
1119   assert(0);
1120 }
1121 */
1122 
FB(const bool * whatd,const Mesh &,const Triangle & K,const R2 & P,RNMK_ & val) const1123 void TypeOfFE_P1Bubble::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
1124 {
1125 //  const Triangle & K(FE.T);
1126   R2 A(K[0]), B(K[1]),C(K[2]);
1127   R l0=1-P.x-P.y, l1=P.x, l2=P.y, lb=l0*l1*l2*9.;
1128 
1129   if (val.N() <4)
1130    throwassert(val.N() >=4);
1131   throwassert(val.M()==1 );
1132 //  throwassert(val.K()==3 );
1133 
1134   val=0;
1135   RN_ f0(val('.',0,op_id));
1136 
1137   if (whatd[op_id])
1138    {
1139     f0[0] = l0-lb;
1140     f0[1] = l1-lb;
1141     f0[2] = l2-lb;
1142     f0[3] = 3.*lb;
1143    }
1144   if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
1145  {
1146   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2)),
1147      Dlb((Dl0*l1*l2+Dl1*l0*l2+Dl2*l0*l1)*9.);
1148 
1149   if (whatd[op_dx])
1150    {
1151     RN_ f0x(val('.',0,op_dx));
1152    f0x[0] = Dl0.x-Dlb.x;
1153    f0x[1] = Dl1.x-Dlb.x;
1154    f0x[2] = Dl2.x-Dlb.x;
1155    f0x[3] = 3.*Dlb.x;
1156   }
1157 
1158   if (whatd[op_dy]) {
1159     RN_ f0y(val('.',0,op_dy));
1160    f0y[0] = Dl0.y-Dlb.y;
1161    f0y[1] = Dl1.y-Dlb.y;
1162    f0y[2] = Dl2.y-Dlb.y;
1163    f0y[3] = 3.*Dlb.y;
1164   }
1165  if (whatd[op_dxx])
1166   {
1167     RN_ fxx(val('.',0,op_dxx));
1168     R lbdxx= 2*((Dl0.x*Dl1.x)*l2+(Dl1.x*Dl2.x)*l0+(Dl2.x*Dl0.x)*l1);
1169     fxx[0] = -lbdxx;
1170     fxx[1] = -lbdxx;
1171     fxx[2] = -lbdxx;
1172     fxx[3] = 3*lbdxx;
1173   }
1174 
1175  if (whatd[op_dyy])
1176   {
1177     RN_ fyy(val('.',0,op_dyy));
1178     R lbdyy= 2*((Dl0.y*Dl1.y)*l2+(Dl1.y*Dl2.y)*l0+(Dl2.y*Dl0.y)*l1);
1179 
1180     fyy[0] =  -lbdyy;
1181     fyy[1] =  -lbdyy;
1182     fyy[2] =  -lbdyy;
1183     fyy[3] =  3*lbdyy;
1184   }
1185  if (whatd[op_dxy])
1186   {
1187     assert(val.K()>op_dxy);
1188     RN_ fxy(val('.',0,op_dxy));
1189     R lbdxy= (Dl0.x*Dl1.y+ Dl0.y*Dl1.x)*l2+(Dl1.x*Dl2.y+Dl1.y*Dl2.x)*l0+(Dl2.x*Dl0.y+Dl2.y*Dl0.x)*l1;
1190     fxy[0] = 4*Dl0.x*Dl0.y-9.*(l0-l1-l2);
1191     fxy[1] = 4*Dl1.x*Dl1.y-9.*(l0-l1-l2);
1192     fxy[2] = 4*Dl2.x*Dl2.y-9.*(l0-l1-l2);
1193     fxy[3] = 27.*(l0-l1-l2);
1194   }
1195   }
1196 
1197 }
1198 ///////////////////////////////////////////////////////////////////////////////
1199 ///////////////////////////////////////////////////////////////////////////////
1200 
1201 /* void TypeOfFE_P1Lagrange::FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
1202 {
1203 //  const Triangle & K(FE.T);
1204   R2 A(K[0]), B(K[1]),C(K[2]);
1205   R l0=1-P.x-P.y,l1=P.x,l2=P.y;
1206   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
1207 
1208   if (val.N() <3)
1209    throwassert(val.N() >=3);
1210   throwassert(val.M()==1 );
1211   throwassert(val.K()==3 );
1212 
1213   val=0;
1214   RN_ f0(val('.',0,0));
1215   RN_ f0x(val('.',0,1));
1216   RN_ f0y(val('.',0,2));
1217 
1218   f0[0] = l0;
1219   f0[1] = l1;
1220   f0[2] = l2;
1221 
1222   f0x[0] = Dl0.x;
1223   f0x[1] = Dl1.x;
1224   f0x[2] = Dl2.x;
1225 
1226   f0y[0] = Dl0.y;
1227   f0y[1] = Dl1.y;
1228   f0y[2] = Dl2.y;
1229 }
1230 
1231  void TypeOfFE_P2Lagrange::FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
1232 {
1233 //  const Triangle & K(FE.T);
1234   R2 A(K[0]), B(K[1]),C(K[2]);
1235   R l0=1-P.x-P.y,l1=P.x,l2=P.y;
1236   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
1237   R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1);
1238 
1239 //  throwassert(FE.N == 1);
1240   throwassert( val.N()>=6);
1241   throwassert(val.M()==1);
1242   throwassert(val.K()==3 );
1243 
1244   val=0;
1245   RN_ f0(val('.',0,0));
1246   RN_ f0x(val('.',0,1));
1247   RN_ f0y(val('.',0,2));
1248 // --
1249   f0[0] = l0*(2*l0-1);
1250   f0[1] = l1*(2*l1-1);
1251   f0[2] = l2*(2*l2-1);
1252   f0[3] = 4*l1*l2; // oppose au sommet 0
1253   f0[4] = 4*l0*l2; // oppose au sommet 1
1254   f0[5] = 4*l1*l0; // oppose au sommet 3
1255 
1256 
1257   f0x[0] = Dl0.x*l4_0;
1258   f0x[1] = Dl1.x*l4_1;
1259   f0x[2] = Dl2.x*l4_2;
1260   f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
1261   f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
1262   f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
1263 
1264 
1265   f0y[0] = Dl0.y*l4_0;
1266   f0y[1] = Dl1.y*l4_1;
1267   f0y[2] = Dl2.y*l4_2;
1268   f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
1269   f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
1270   f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
1271 
1272 }
1273 */
FB(const bool * whatd,const Mesh &,const Triangle & K,const R2 & P,RNMK_ & val) const1274 void TypeOfFE_P2Lagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
1275 {
1276 //  const Triangle & K(FE.T);
1277   R2 A(K[0]), B(K[1]),C(K[2]);
1278   R l0=1-P.x-P.y,l1=P.x,l2=P.y;
1279   R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1);
1280 
1281 //  throwassert(FE.N == 1);
1282   throwassert( val.N()>=6);
1283   throwassert(val.M()==1);
1284 //  throwassert(val.K()==3 );
1285 
1286   val=0;
1287 // --
1288  if (whatd[op_id])
1289   {
1290    RN_ f0(val('.',0,op_id));
1291   f0[0] = l0*(2*l0-1);
1292   f0[1] = l1*(2*l1-1);
1293   f0[2] = l2*(2*l2-1);
1294   f0[3] = 4*l1*l2; // oppose au sommet 0
1295   f0[4] = 4*l0*l2; // oppose au sommet 1
1296   f0[5] = 4*l1*l0; // oppose au sommet 3
1297   }
1298  if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
1299  {
1300    R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
1301   if (whatd[op_dx])
1302   {
1303     RN_ f0x(val('.',0,op_dx));
1304   f0x[0] = Dl0.x*l4_0;
1305   f0x[1] = Dl1.x*l4_1;
1306   f0x[2] = Dl2.x*l4_2;
1307   f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
1308   f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
1309   f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
1310   }
1311 
1312  if (whatd[op_dy])
1313   {
1314     RN_ f0y(val('.',0,op_dy));
1315   f0y[0] = Dl0.y*l4_0;
1316   f0y[1] = Dl1.y*l4_1;
1317   f0y[2] = Dl2.y*l4_2;
1318   f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
1319   f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
1320   f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
1321   }
1322 
1323  if (whatd[op_dxx])
1324   {
1325     RN_ fxx(val('.',0,op_dxx));
1326 
1327     fxx[0] = 4*Dl0.x*Dl0.x;
1328     fxx[1] = 4*Dl1.x*Dl1.x;
1329     fxx[2] = 4*Dl2.x*Dl2.x;
1330     fxx[3] =  8*Dl1.x*Dl2.x;
1331     fxx[4] =  8*Dl0.x*Dl2.x;
1332     fxx[5] =  8*Dl0.x*Dl1.x;
1333   }
1334 
1335  if (whatd[op_dyy])
1336   {
1337     RN_ fyy(val('.',0,op_dyy));
1338     fyy[0] = 4*Dl0.y*Dl0.y;
1339     fyy[1] = 4*Dl1.y*Dl1.y;
1340     fyy[2] = 4*Dl2.y*Dl2.y;
1341     fyy[3] =  8*Dl1.y*Dl2.y;
1342     fyy[4] =  8*Dl0.y*Dl2.y;
1343     fyy[5] =  8*Dl0.y*Dl1.y;
1344   }
1345  if (whatd[op_dxy])
1346   {
1347     assert(val.K()>op_dxy);
1348     RN_ fxy(val('.',0,op_dxy));
1349 
1350     fxy[0] = 4*Dl0.x*Dl0.y;
1351     fxy[1] = 4*Dl1.x*Dl1.y;
1352     fxy[2] = 4*Dl2.x*Dl2.y;
1353     fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
1354     fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
1355     fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
1356   }
1357 
1358  }
1359 
1360 }
1361 /*
1362  void TypeOfFE_P1Lagrange::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j,  void * arg) const
1363 {
1364   const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) };
1365    for (int i=0;i<3;i++)
1366      {
1367      f(v,K.T(Pt[i]),K,i,Pt[i],arg),val[i]=*(v+j);}
1368 
1369 }
1370  void TypeOfFE_P2Lagrange::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j, void * arg) const
1371 {
1372   const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0) };
1373    for (int i=0;i<6;i++)
1374      {
1375      f(v,K.T(Pt[i]),K,i,Pt[i],arg),val[i]=*(v+j);}
1376 
1377 }
1378 */
1379 
1380 
1381 //TypeOfFE  P1Lagrange(1,0,0,P1Functions,D2_P1Functions,P1Interpolant,DataP1Lagrange);
1382 //TypeOfFE  P2Lagrange(1,1,0,P2Functions,D2_P2Functions,P2Interpolant,DataP2Lagrange,3);
1383 
1384 //  case of   fine mesh
1385 class TypeOfMortarCas1: public TypeOfMortar {
1386   friend class FESpace;
1387   friend class FMortar;
1388   friend class ConstructDataFElement;
1389   protected:
1390   int NbLagrangeMult(const Mesh &,const Mortar &M) const ;
1391 
NbDoF(const Mesh &,const Mortar & M,int i) const1392    int NbDoF(const Mesh &,const Mortar &M,int i) const
1393      { int l(M.NbLeft()),r(M.NbRight());
1394        int n =Max(l,r);
1395        int mn=Min(l,r);
1396        return (l+r)*(NbDfOnVertex + NbDfOnEdge) + (n+1)*NbDfOnVertex + n*NbDfOnEdge -mn-1;
1397       }
NbOfNodes(const Mesh &,const Mortar & M) const1398   int NbOfNodes(const Mesh &,const Mortar &M) const // call one time
1399      {int l(M.NbLeft()),r(M.NbRight()); return (l+r)*(vertex_is_node+edge_is_node)+1;}
NbDoF(const Mesh &,const Mortar & M) const1400   int NbDoF(const Mesh &,const Mortar &M) const
1401      { int l(M.NbLeft()),r(M.NbRight());
1402        int n =Max(l,r);
1403        int mn=Min(l,r);
1404        return (l+r)*(NbDfOnVertex + NbDfOnEdge) + (n+1)*NbDfOnVertex + n*NbDfOnEdge -mn-1;
1405       }
1406 
NodeOfDF(const FESpace & Vh,const Mortar & M,int i) const1407    int NodeOfDF(const FESpace &Vh,const Mortar &M,int i) const
1408      {throwassert(0);return 0;}
DFOfNode(const FESpace & Vh,const Mortar & M,int i) const1409    int DFOfNode(const FESpace &Vh,const Mortar &M,int i) const
1410      {throwassert(0);return 0;}
1411    void ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const;
1412    void ConsTheSubMortar(FMortar & ) const;
1413 
1414    const int vertex_is_node,edge_is_node;
1415   public:
TypeOfMortarCas1(int i,int j)1416     TypeOfMortarCas1 (int i,int j): TypeOfMortar(i,j),
1417       vertex_is_node(i?1:0),edge_is_node(j?1:0) {};
1418 
1419 }  MortarCas1P2(1,1) ;
1420 
1421  const TypeOfMortar & TheMortarCas1P2(MortarCas1P2);
1422 
1423 
ConstructionOfNode(const Mesh & Th,int im,int * NodesOfElement,int * FirstNodeOfElement,int & lastnodenumber) const1424 void TypeOfMortarCas1::ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const
1425 {
1426   // im   mortar number
1427  // trop complique on change
1428              const Mortar &M(Th.mortars[im]);
1429              int k = Th.nt+im;
1430              int  kk=FirstNodeOfElement[k]; //  begin
1431              // lagrange  multiplicator one new node
1432               NodesOfElement[kk++] = lastnodenumber++;
1433 /*
1434              int il = M.NbLeft();
1435              int ir = M.NbRight();
1436              int ir1 = ir-1;
1437              //  left
1438 
1439              for( int j=0;j<il;j++)  //  numbering vertex0 edge vertex1
1440               {
1441                 int K = M.TLeft(j);  // triangle
1442                 int e = M.ELeft(j);  //  edge
1443                 int nbneK = FirstNodeOfElement[K];
1444                 int oe = vertex_is_node ? 3 : 0;
1445                 int i0 = VerticesOfTriangularEdge[e][0];
1446                 int i1 = VerticesOfTriangularEdge[e][1];
1447                 if (vertex_is_node && !j)   //  just the first time
1448                    NodesOfElement[kk++]=NodesOfElement[nbneK +i0];
1449                 if (edge_is_node)
1450                    NodesOfElement[kk++]=NodesOfElement[nbneK+oe+e];
1451                 if (vertex_is_node )
1452                    NodesOfElement[kk++]=NodesOfElement[nbneK +i1];
1453               }
1454 
1455              //  right
1456              for( int j=0;j<ir;j++)  //  numbering vertex0 edge vertex1
1457               {
1458                 int K = M.TRight(j);  // triangle
1459                 int e = M.ERight(j);  //  edge
1460                 int nbneK = FirstNodeOfElement[K];
1461                 int oe = vertex_is_node ? 3 : 0;
1462 
1463                 int i0 = VerticesOfTriangularEdge[e][1]; //  change the sens because right side
1464                 int i1 = VerticesOfTriangularEdge[e][0];
1465               //  if (vertex_is_node &&  !j)   // never
1466                //    NodesOfElement[kk++]=NodesOfElement[nbneK +i0];
1467                 if (edge_is_node)
1468                    NodesOfElement[kk++]=NodesOfElement[nbneK+oe+e];
1469                 if (vertex_is_node  && (j != ir1) )  //  skip the last
1470                    NodesOfElement[kk++]=NodesOfElement[nbneK +i1];
1471               } */
1472 
1473               throwassert(FirstNodeOfElement[k+1]==kk);
1474 }
1475 
d1P1F0(const FESpace *,const aSubFMortar *,R x)1476  R  d1P1F0(const FESpace *,const aSubFMortar *,R x) {return 1-x;}// 1 on 0
d1P1F1(const FESpace *,const aSubFMortar *,R x)1477  R  d1P1F1 (const FESpace *,const aSubFMortar *,R x) {return x;}//  1 on 1
1478 
d1P2F0(const FESpace *,const aSubFMortar *,R x)1479  R  d1P2F0 (const FESpace *,const aSubFMortar *,R x) {return (1-x)*(1-2*x);}// 1 on x=0
d1P2F1(const FESpace *,const aSubFMortar *,R x)1480  R  d1P2F1(const FESpace *,const aSubFMortar *,R x) {return (1-x)*x*4;} // 1 on x=1/2
d1P2F2(const FESpace *,const aSubFMortar *,R x)1481  R  d1P2F2(const FESpace *,const aSubFMortar *,R x) {return x*(2*x-1);} // 1 on x=1
1482 
ConsTheSubMortar(FMortar & sm) const1483  void  TypeOfMortarCas1::ConsTheSubMortar(FMortar & sm) const
1484    { //  constuction of
1485    /*
1486      int nbsm; // nb of submortar
1487   aSubFMortar * sm;
1488   ~FMortar() { delete [] dataDfNumberOFmul; delete [] dataf;}
1489   private:
1490 
1491   int *dataDfNumberOFmul;
1492    R (**dataf)(const FESpace *,const aSubFMortar *,R);
1493 
1494    */
1495    //  typedef
1496      const Mesh &Th(sm.Vh.Th);
1497      const Mortar & M(sm.M);
1498      int nl=M.NbLeft();
1499      int nr=M.NbRight();
1500      int nbsm= nl+nr-1;
1501      sm.nbsm = nbsm;
1502      int ldata = 6*nbsm;// 3 gauche+ 3 droite
1503      sm.sm = new aSubFMortar[nbsm];
1504      sm.datai = new int [ldata];
1505      sm.dataf = new (R (*[ldata])(const FESpace *,const aSubFMortar *,R))  ;
1506      int *dataDfNumberOFmul=sm.datai;
1507 
1508      R (**dataf)(const FESpace *,const aSubFMortar *,R) ;
1509      dataf=sm.dataf;
1510      for (int i=0;i<ldata;i++) sm.dataf[i]=0;
1511    //  int * data0=sm.data+ldata;
1512    //  int * data1=data0+ldata;
1513 
1514      //  now the construction
1515      int l=0,g=0;
1516      R2 A(M.VLeft(0));
1517      R2 B(M.VLeft(nl));
1518      throwassert(&M.VLeft(0) == &M.VRight(0));
1519      throwassert(&M.VLeft(nl) == &M.VRight(nr));
1520 
1521      R2 AB(A,B);
1522      R lg=Norme2(AB);
1523     // cout << " Mortar from " << A << " to " << B << " = " <<lg << endl;
1524      R2 AB1(AB/lg);
1525      int il=0,ir=0;
1526      int k=0;
1527      R la=0.0;
1528      R lb=0.0;
1529      R2 AA(A),BB(A);
1530    //  cout << "lg : " <<lg ;
1531      do {
1532        sm.sm[k].left  = M.left[il];
1533        sm.sm[k].right =  M.right[ir];
1534        R2 Bl(M.VLeft(il+1));
1535        R2 Br(M.VRight(ir+1));
1536        R ll=(AB1,Bl-A), lr=(AB1,Br-A);
1537      //  throwassert ( ll >=0 && lr >= 0);
1538      //  throwassert ( ll <=lg  && lr <= lg);
1539 
1540    //    cout << "AA , BB = " << AA << "," << BB << endl;
1541     //   cout << " " << ll << " " << lr << " ll=" << sm.sm[k].left << ", ";
1542        if (ll<lr) {BB=Bl,lb=ll,il++;} else {BB=Br, lb=lr,ir++;}
1543   //     cout << k << " " << k << " " << la/lg << " " << lb/lg << endl;
1544        sm.sm[k].a = la/lg;
1545        sm.sm[k].b = lb/lg;
1546        sm.sm[k].A=AA;
1547        sm.sm[k].B=BB;
1548        la=lb;
1549        AA=BB;
1550        k++;
1551        throwassert(k<=nbsm);
1552      } while (il<nl && ir < nr);
1553 
1554   //   cout << "k=" << k <<endl;
1555      throwassert(nbsm==Max(nl,nr));
1556      //throwassert(nbsm<=k);
1557     nbsm=k;
1558     sm.nbsm=k;
1559 //   construction of interpolation
1560 //  1) on a P1 on P2
1561 //   P2  si les longueurs des aSubMortar precedende et suivant  sont les meme
1562 //   sinon P1
1563    //  calcul de leps
1564      R leps=1.0/(1048576.0) ; // 1/2^20
1565      R lgp=0;
1566      R lgc=0;
1567      R lgs=sm.sm[0].lg1();
1568     // cout << lgp << " " << lgc << " " << lgs << endl;
1569 
1570      int nmul=0;
1571      for (int k=0;k<nbsm;k++)
1572        {
1573 
1574          lgp=lgc;
1575          lgc=lgs;
1576          lgs=  k+1 == nbsm  ? 0 : sm.sm[k+1].lg1();
1577          sm.sm[k].DfNumberOFmul= dataDfNumberOFmul;
1578          sm.sm[k].f=dataf;
1579         // cout << lgp << " " << lgc << " " << lgs << " ";
1580          if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
1581           { // P2
1582            sm.sm[k].Nbmul=3;
1583            *dataDfNumberOFmul++=nmul++;
1584            *dataDfNumberOFmul++=nmul++;
1585            *dataDfNumberOFmul++=nmul;
1586            *dataf++ = d1P2F0;
1587            *dataf++ = d1P2F1;
1588            *dataf++ = d1P2F2;
1589           // cout << "P2 " << nmul << " " ;
1590 
1591           }
1592          else
1593           { // P1
1594                    sm.sm[k].Nbmul=2;
1595            *dataDfNumberOFmul++=nmul++;
1596            *dataDfNumberOFmul++=nmul;
1597            *dataf++ = d1P1F0;
1598            *dataf++ = d1P1F1;
1599           // cout << "P1 " << nmul << " " ;
1600 
1601 
1602           }
1603        }
1604       nmul++;
1605      // cout << " " << nmul << " " <<  sm.NbDoF(0) << endl;
1606       throwassert(nmul==sm.NbDoF(0));
1607 
1608    }
1609 
NbLagrangeMult(const Mesh &,const Mortar & M) const1610   int TypeOfMortarCas1::NbLagrangeMult(const Mesh &,const Mortar &M) const
1611      {
1612        int nl = M.NbLeft();
1613        int nr = M.NbRight();
1614        R2 A(M.VLeft(0));
1615        R2 B(M.VLeft(nl));
1616        R2 AB(A,B);
1617        R lg=Norme2(AB);
1618        R leps = lg/1048576.0;
1619        throwassert(nl==1 || nr==1);
1620        R lgp=0,lgc=0,lgs=0;
1621        int nbmul=3;
1622        if (nr==1)
1623         {
1624         R2 AA(M.VLeft(0)),BB(M.VLeft(1));
1625         lgp= Norme2(BB-AA); // preced
1626         AA=BB;
1627         BB=M.VLeft(2);
1628         lgc= Norme2(BB-AA); // courant
1629 
1630         for (int i=1;i<nl-1;i++)
1631          {
1632             AA=BB;
1633             BB=M.VLeft(i+2);
1634             lgs=Norme2(AA-BB); // le suivant
1635             if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
1636               nbmul+=2; // P2
1637             else
1638               nbmul+=1;// P1;
1639             lgp=lgc;
1640             lgc=lgs;
1641 
1642          }
1643         }
1644         else
1645         {
1646         R2 AA(M.VRight(0)),BB(M.VRight(1));
1647         lgp= Norme2(BB-AA); // preced
1648         AA=BB;
1649         BB=M.VRight(2);
1650         lgc= Norme2(BB-AA); // courant
1651 
1652         for (int i=1;i<nr-1;i++)
1653          {
1654             AA=BB;
1655             BB=M.VRight(i+2);
1656             lgs=Norme2(AA-BB); // le suivant
1657             if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
1658               nbmul+=2; // P2
1659             else
1660               nbmul+=1;// P1;
1661             lgp=lgc;
1662             lgc=lgs;
1663 
1664          }
1665         }
1666        throwassert(nbmul>2);
1667        return nbmul;
1668       }
1669 
1670 
1671 // ---
FMortar(const FESpace * VVh,int k)1672  FMortar::FMortar(const FESpace * VVh,int k)
1673   :
1674     Vh(*VVh),
1675     M(Vh.Th.mortars[k-Vh.Th.nt]),
1676     N(VVh->N),
1677     p(Vh.PtrFirstNodeOfElement(k)),
1678     nbn(Vh.NbOfNodesInElement(k)),
1679     tom(Vh.tom)
1680 
1681  { throwassert(k>=Vh.Th.nt && k <Vh.Th.nt + Vh.Th.NbMortars);
1682    VVh->tom->ConsTheSubMortar(*this);}
1683 
operator ()(const FElement & K,const R2 & PHat,const KN_<R> & u,int componante,int op) const1684  R TypeOfFE::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const
1685   {
1686    R v[1000],vf[100];
1687    assert(N*3*NbDoF<=1000 && NbDoF <100 );
1688    KNMK_<R> fb(v,NbDoF,N,op+1); //  the value for basic fonction
1689    KN_<R> fk(vf,NbDoF);
1690    for (int i=0;i<NbDoF;i++) // get the local value
1691     fk[i] = u[K(i)];
1692     //  get value of basic function
1693    bool whatd[last_operatortype];
1694    for (int i=0;i<last_operatortype;i++)
1695      whatd[i]=false;
1696    whatd[op]=true;
1697    FB(whatd,K.Vh.Th,K.T,PHat,fb);
1698    R r = (fb('.',componante,op),fk);
1699    return r;
1700   }
1701 
1702 static TypeOfFE_P1Lagrange P1LagrangeP1;
1703 static TypeOfFE_P1Bubble P1BubbleP1;
1704 static TypeOfFE_P2Lagrange P2LagrangeP2;
1705 
1706 TypeOfFE  & P2Lagrange(P2LagrangeP2);
1707 TypeOfFE  & P1Bubble(P1BubbleP1);
1708 TypeOfFE  & P1Lagrange(P1LagrangeP1);
1709 
1710 static ListOfTFE typefemP1("P1", &P1LagrangeP1);
1711 static ListOfTFE typefemP1b("P1b", &P1BubbleP1);
1712 static ListOfTFE typefemP2("P2", &P2LagrangeP2);
1713 static  ListOfTFE typefemRT("RT0", &RTLagrange);
1714 static  ListOfTFE typefemRTOrtho("RT0Ortho", &RTLagrangeOrtho);
1715 
1716  extern  TypeOfFE & RTmodifLagrange, & P1ttdc, & P2ttdc;
1717  static  ListOfTFE typefemRTmodif("RTmodif", &RTmodifLagrange);
1718  static ListOfTFE typefemP0("P0", &P0Lagrange);
1719  static ListOfTFE typefemP1nc("P1nc", &P1ncLagrange);
1720  static ListOfTFE typefemP1ttdc("P1dc", &P1ttdc);
1721  static ListOfTFE typefemP2ttdc("P2dc", &P2ttdc);
1722 
1723 } // fin de namespace Fem2D
1724