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