/* Triangles::BThBoundary(Edge e,Real 8) const { // pointeur of the background must be on // Edge be = e.on; } */ int Triangles::SplitElement(int choice) { Direction NoDirOfSearch; const int withBackground = &BTh != this && &BTh; if (verbosity>2) cout << " -- SplitElement " << (choice? " Q->4Q and T->4T " : " Q->4Q or T->3Q " ) << endl;; if (verbosity>5) cout << endl << " (in) Nb of Quadrilaterals = " << NbOfQuad << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 << " Nb of outside triangles = " << NbOutT << endl; ReNumberingTheTriangleBySubDomain(); #ifdef DRAWING2 Draw(); inquire(); #endif int nswap =0; const Int4 nfortria( choice ? 4 : 6); if(withBackground) { BTh.SetVertexFieldOn(); SetVertexFieldOnBTh(); } else BTh.SetVertexFieldOn(); Int4 newnbt=0,newnbv=0; Int4 * kedge = 0; Int4 newNbOfQuad=NbOfQuad; Int4 * ksplit= 0, * ksplitarray=0; Int4 kkk=0; int ret =0; if (nbvx<nbv+nbe) return 1;// Triangles * OCurrentTh= CurrentTh; CurrentTh = this; // 1) create the new points by spliting the internal edges // set the Int4 nbvold = nbv; Int4 nbtold = nbt; Int4 NbOutTold = NbOutT; Int4 NbEdgeOnGeom=0; Int4 i; nbt = nbt - NbOutT; // remove all the the ouside triangles Int4 nbtsave = nbt; Triangle * lastT = triangles + nbt; for (i=0;i<nbe;i++) if(edges[i].on) NbEdgeOnGeom++; Int4 newnbe=nbe+nbe; // Int4 newNbVerticesOnGeomVertex=NbVerticesOnGeomVertex; Int4 newNbVerticesOnGeomEdge=NbVerticesOnGeomEdge+NbEdgeOnGeom; // Int4 newNbVertexOnBThVertex=NbVertexOnBThVertex; Int4 newNbVertexOnBThEdge=withBackground ? NbVertexOnBThEdge+NbEdgeOnGeom:0; // do allocation for pointeur to the geometry and background VertexOnGeom * newVerticesOnGeomEdge = new VertexOnGeom[newNbVerticesOnGeomEdge]; VertexOnEdge *newVertexOnBThEdge = newNbVertexOnBThEdge ? new VertexOnEdge[newNbVertexOnBThEdge]:0; if (NbVerticesOnGeomEdge) memcpy(newVerticesOnGeomEdge,VerticesOnGeomEdge,sizeof(VertexOnGeom)*NbVerticesOnGeomEdge); if (NbVertexOnBThEdge) memcpy(newVertexOnBThEdge,VertexOnBThEdge,sizeof(VertexOnEdge)*NbVertexOnBThEdge); Edge *newedges = new Edge [newnbe]; // memcpy(newedges,edges,sizeof(Edge)*nbe); SetOfEdges4 * edge4= new SetOfEdges4(nbe,nbv); #ifdef DEBUG for (i=0;i<nbt;i++) triangles[i].check(); #endif #ifdef DRAWING2 reffecran(); #endif Int4 k=nbv; Int4 kk=0; Int4 kvb = NbVertexOnBThEdge; Int4 kvg = NbVerticesOnGeomEdge; Int4 ie =0; Edge ** edgesGtoB=0; if (withBackground) edgesGtoB= BTh.MakeGeometricalEdgeToEdge(); Int4 kerr=0,ferr=0; for (i=0;i<nbe;i++) newedges[ie].on=0; for (i=0;i<nbe;i++) { GeometricalEdge *ong = edges[i].on; newedges[ie]=edges[i]; newedges[ie].adj[0]=newedges+(edges[i].adj[0]-edges) ; newedges[ie].adj[1]=newedges + ie +1; R2 A = edges[i][0],B = edges[i][1]; // cout << " ie = " << ie <<" v0 = " << Number(newedges[ie][0]) << endl; kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1]))); if (ong) // a geometrical edges { if (withBackground) { // walk on back ground mesh // newVertexOnBThEdge[ibe++] = VertexOnEdge(vertices[k],bedge,absicsseonBedge); // a faire -- difficile // the first PB is to now a background edge between the 2 vertices assert(edgesGtoB); // cout << " ie = " << ie <<" v0 = " << Number(newedges[ie][0]) << endl; ong= ProjectOnCurve(*edgesGtoB[Gh.Number(edges[i].on)], edges[i][0],edges[i][1],0.5,vertices[k], newVertexOnBThEdge[kvb], newVerticesOnGeomEdge[kvg++]); vertices[k].ReferenceNumber= edges[i].ref; vertices[k].DirOfSearch = NoDirOfSearch; ; // get the Info on background mesh Real8 s = newVertexOnBThEdge[kvb]; Vertex & bv0 = newVertexOnBThEdge[kvb][0]; Vertex & bv1 = newVertexOnBThEdge[kvb][1]; // compute the metrix of the new points vertices[k].m = Metric(1-s,bv0,s,bv1); kvb++; // cout << " ie = " << ie <<" v0 = " << Number(newedges[ie][0]) << endl; } else { ong=Gh.ProjectOnCurve(edges[i], 0.5,vertices[k],newVerticesOnGeomEdge[kvg++]); // vertices[k].i = toI2( vertices[k].r); vertices[k].ReferenceNumber = edges[i].ref; vertices[k].DirOfSearch = NoDirOfSearch; vertices[k].m = Metric(0.5,edges[i][0],0.5,edges[i][1]); } } else // straigth line edge --- { vertices[k].r = ((R2) edges[i][0] + (R2) edges[i][1] )*0.5; vertices[k].m = Metric(0.5,edges[i][0],0.5,edges[i][1]); vertices[k].on = 0; } //vertices[k].i = toI2( vertices[k].r); R2 AB = vertices[k].r; R2 AA = (A+AB)*0.5; R2 BB = (AB+B)*0.5; vertices[k].ReferenceNumber = edges[i].ref; vertices[k].DirOfSearch = NoDirOfSearch; newedges[ie].on = Gh.Contening(AA,ong); newedges[ie++].v[1]=vertices+k; newedges[ie]=edges[i]; newedges[ie].adj[0]=newedges + ie -1; newedges[ie].adj[1]=newedges+(edges[i].adj[1]-edges) ; newedges[ie].on = Gh.Contening(BB,ong); newedges[ie++].v[0]=vertices+k; // cout << " ie = " << ie-2 << " vm " << k << " v0 = " << Number(newedges[ie-2][0]) // << " v1 = " << Number(newedges[ie-1][1]) // << " ong =" << ong-Gh.edges // << " on 0 =" << newedges[ie-2].on -Gh.edges << AA // << " on 1 =" << newedges[ie-1].on -Gh.edges << BB // << endl; k++; } #ifdef DEBUG assert(kvb == newNbVertexOnBThEdge); // verif edge { Vertex *v0 = vertices, *v1 = vertices+ k; for (Int4 i=0;i<ie;i++) { assert( &newedges[i][0] >= v0 && &newedges[i][0] < v1); assert( &newedges[i][1] >= v0 && &newedges[i][1] < v1); } } #endif if (edgesGtoB) delete [] edgesGtoB; edgesGtoB=0; newnbv=k; newNbVerticesOnGeomEdge=kvg; if (newnbv> nbvx) goto Error;// bug nbv = k; kedge = new Int4[3*nbt+1]; ksplitarray = new Int4[nbt+1]; ksplit = ksplitarray +1; // because ksplit[-1] == ksplitarray[0] for (i=0;i<3*nbt;i++) kedge[i]=-1; // for (i=0;i<nbt;i++) { Triangle & t = triangles[i]; assert(t.link); for(int j=0;j<3;j++) { const TriangleAdjacent ta = t.Adj(j); const Triangle & tt = ta; if (&tt >= lastT) t.SetAdj2(j,0,0);// unset adj const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]]; const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]]; Int4 ke =edge4->findtrie(Number(v0),Number(v1)); if (ke>0) { Int4 ii = Number(tt); int jj = ta; Int4 ks = ke + nbvold; kedge[3*i+j] = ks; if (ii<nbt) // good triangle kedge[3*ii+jj] = ks; Vertex &A=vertices[ks]; Real8 aa,bb,cc,dd; if ((dd=Area2(v0.r,v1.r,A.r)) >=0) { // warning PB roundoff error if (t.link && ( (aa=Area2( A.r , t[1].r , t[2].r )) < 0.0 || (bb=Area2( t[0].r , A.r , t[2].r )) < 0.0 || (cc=Area2( t[0].r , t[1].r , A.r )) < 0.0)) ferr++, cerr << " Error : " << ke + nbvold << " not in triangle " << i << " In=" << !!t.link << " " << aa << " " << bb << " " << cc << " " << dd << endl; } else { if (tt.link && ( (aa=Area2( A.r , tt[1].r , tt[2].r )) < 0 || (bb=Area2( tt[0].r , A.r , tt[2].r )) < 0 || (cc=Area2( tt[0].r , tt[1].r , A.r )) < 0)) ferr++, cerr << " Warning : " << ke + nbvold << " not in triangle " << ii << " In=" << !!tt.link << " " << aa << " " << bb << " " << cc << " " << dd << endl; } } } } if(ferr) { cerr << " Number of triangles with P2 interpolation Probleme " << ferr << endl;; MeshError(9); } for (i=0;i<nbt;i++) { ksplit[i]=1; // no split by default const Triangle & t = triangles[ i]; // cout << " Triangle " << i << " " << t << !!t.link << ":: " ; int nbsplitedge =0; int nbinvisible =0; int invisibleedge=0; int kkk[3]; for (int j=0;j<3;j++) { if (t.Hidden(j)) invisibleedge=j,nbinvisible++; const TriangleAdjacent ta = t.Adj(j); const Triangle & tt = ta; const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]]; const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]]; // cout << " ke = " << kedge[3*i+j] << " " << Number(v0) << " " << Number(v1) << "/ "; if ( kedge[3*i+j] < 0) { Int4 ke =edge4->findtrie(Number(v0),Number(v1)); // cout << ":" << ke << "," << !!t.link << " " << &tt ; if (ke<0) // new { if (&tt) // internal triangles all the boundary { // new internal edges Int4 ii = Number(tt); int jj = ta; kedge[3*i+j]=k;// save the vertex number kedge[3*ii+jj]=k; if (k<nbvx) { vertices[k].r = ((R2) v0+(R2) v1 )/2; //vertices[k].i = toI2( vertices[k].r); vertices[k].ReferenceNumber=0; vertices[k].DirOfSearch =NoDirOfSearch; vertices[k].m = Metric(0.5,v0,0.5,v1); } k++; kkk[nbsplitedge++]=j; } // tt else cerr <<endl << " Bug " <<i<< " " << j << " t=" << t << endl; } // ke<0 else { // ke >=0 kedge[3*i+j]=nbvold+ke; kkk[nbsplitedge++]=j;// previously splited } } else kkk[nbsplitedge++]=j;// previously splited } assert (nbinvisible<2); // cout << " " << nbinvisible << " " << nbsplitedge << endl; switch (nbsplitedge) { case 0: ksplit[i]=10; newnbt++; break; // nosplit case 1: ksplit[i]=20+kkk[0];newnbt += 2; break; // split in 2 case 2: ksplit[i]=30+3-kkk[0]-kkk[1];newnbt += 3; break; // split in 3 case 3: if (nbinvisible) ksplit[i]=40+invisibleedge,newnbt += 4; else ksplit[i]=10*nfortria,newnbt+=nfortria; break; } assert(ksplit[i]>=40); } // now do the element split newNbOfQuad = 4*NbOfQuad; nbv = k; #ifdef DRAWING2 inquire(); #endif // cout << " Nbv = " << nbv << endl; kkk = nbt; ksplit[-1] = nbt; // look on old true triangles for (i=0;i<nbtsave;i++) { // cout << "Triangle " << i << " " << ksplit[i] << ":" << triangles[i] // << " ----------------------------------------------- " <<endl; Triangle * tc=0; int nbmkadj=0; Int4 mkadj [100]; mkadj[0]=i; Int4 kk=ksplit[i]/10; int ke=(int) (ksplit[i]%10); assert(kk<7 && kk >0); // def the numbering k (edge) i vertex int k0 = ke; int k1 = NextEdge[k0]; int k2 = PreviousEdge[k0]; int i0 = OppositeVertex[k0]; int i1 = OppositeVertex[k1]; int i2 = OppositeVertex[k2]; Triangle &t0=triangles[i]; Vertex * v0=t0(i0); Vertex * v1=t0(i1); Vertex * v2=t0(i2); // cout << "nbmkadj " << nbmkadj << " it=" << i <<endl; assert(nbmkadj< 10); // -------------------------- TriangleAdjacent ta0(t0.Adj(i0)),ta1(t0.Adj(i1)),ta2(t0.Adj(i2)); // save the flag Hidden int hid[]={t0.Hidden(0),t0.Hidden(1),t0.Hidden(2)}; // un set all adj -- save Hidden flag -- t0.SetAdj2(0,0,hid[0]); t0.SetAdj2(1,0,hid[1]); t0.SetAdj2(2,0,hid[2]); // -- remake switch (kk) { case 1: break;// nothing case 2: // { Triangle &t1=triangles[kkk++]; t1=t0; assert (kedge[3*i+i0]>=0); Vertex * v3 = vertices + kedge[3*i+k0]; t0(i2) = v3; t1(i1) = v3; t0.SetAllFlag(k2,0); t1.SetAllFlag(k1,0); } break; case 3: // { Triangle &t1=triangles[kkk++]; Triangle &t2=triangles[kkk++]; t2=t1=t0; assert (kedge[3*i+k1]>=0); assert (kedge[3*i+k2]>=0); Vertex * v01 = vertices + kedge[3*i+k2]; Vertex * v02 = vertices + kedge[3*i+k1]; t0(i1) = v01; t0(i2) = v02; t1(i2) = v02; t1(i0) = v01; t2(i0) = v02; t0.SetAllFlag(k0,0); t1.SetAllFlag(k1,0); t1.SetAllFlag(k0,0); t2.SetAllFlag(k2,0); } break; case 4: // case 6: // split in 4 { Triangle &t1=triangles[kkk++]; Triangle &t2=triangles[kkk++]; Triangle &t3=triangles[kkk++]; t3=t2=t1=t0; assert(kedge[3*i+k0] >=0 && kedge[3*i+k1] >=0 && kedge[3*i+k2] >=0); Vertex * v12 = vertices + kedge[3*i+k0]; Vertex * v02 = vertices + kedge[3*i+k1]; Vertex * v01 = vertices + kedge[3*i+k2]; // cout << Number(t0(i0)) << " " << Number(t0(i1)) // << " " << Number(t0(i2)) // << " " << kedge[3*i+k0] // << " " << kedge[3*i+k1] // << " " << kedge[3*i+k2] << endl; t0(i1) = v01; t0(i2) = v02; t0.SetAllFlag(k0,hid[k0]); t1(i0) = v01; t1(i2) = v12; t0.SetAllFlag(k1,hid[k1]); t2(i0) = v02; t2(i1) = v12; t2.SetAllFlag(k2,hid[k2]); t3(i0) = v12; t3(i1) = v02; t3(i2) = v01; t3.SetAllFlag(0,hid[0]); t3.SetAllFlag(1,hid[1]); t3.SetAllFlag(2,hid[2]); if ( kk == 6) { Triangle &t4=triangles[kkk++]; Triangle &t5=triangles[kkk++]; t4 = t3; t5 = t3; t0.SetHidden(k0); t1.SetHidden(k1); t2.SetHidden(k2); t3.SetHidden(0); t4.SetHidden(1); t5.SetHidden(2); if (nbv < nbvx ) { vertices[nbv].r = ((R2) *v01 + (R2) *v12 + (R2) *v02 ) / 3.0; vertices[nbv].ReferenceNumber =0; vertices[nbv].DirOfSearch =NoDirOfSearch; //vertices[nbv].i = toI2(vertices[nbv].r); Real8 a3[]={1./3.,1./3.,1./3.}; vertices[nbv].m = Metric(a3,v0->m,v1->m,v2->m); Vertex * vc = vertices +nbv++; t3(i0) = vc; t4(i1) = vc; t5(i2) = vc; } else goto Error; } } break; } // cout << " -- " << i << " " << nbmkadj << " " << kkk << " " << tc << endl; // t0.SetDetf(); // save all the new triangles mkadj[nbmkadj++]=i; Int4 jj; if (t0.link) for (jj=nbt;jj<kkk;jj++) { triangles[jj].link=t0.link; t0.link= triangles+jj; mkadj[nbmkadj++]=jj; // triangles[jj].SetDet(); } // cout << " -- " << i << " " << nbmkadj << endl; assert(nbmkadj<=13);// 13 = 6 + 4 + 3 if (kk==6) newNbOfQuad+=3; // triangles[i].Draw(); for (jj=ksplit[i-1];jj<kkk;jj++) // triangles[jj].SetDet(); // triangles[jj].Draw(); nbt = kkk; ksplit[i]= nbt; // save last adresse of the new triangles kkk = nbt; } // cout << " nv = " << nbv << " nbt = " << nbt << endl; for (i=0;i<nbv;i++) vertices[i].m = vertices[i].m*2.; // if(withBackground) for (i=0;i<BTh.nbv;i++) BTh.vertices[i].m = BTh.vertices[i].m*2.; #ifdef DRAWING2 Draw(); inquire(); #endif ret = 2; if (nbt>= nbtx) goto Error; // bug if (nbv>= nbvx) goto Error; // bug // generation of the new triangles SetIntCoor("In SplitElement"); ReMakeTriangleContainingTheVertex(); if(withBackground) BTh.ReMakeTriangleContainingTheVertex(); delete [] edges; edges = newedges; nbe = newnbe; NbOfQuad = newNbOfQuad; for (i=0;i<NbSubDomains;i++) { Int4 k = subdomains[i].edge- edges; subdomains[i].edge = edges+2*k; // spilt all edge in 2 } if (ksplitarray) delete [] ksplitarray; if (kedge) delete [] kedge; if (edge4) delete edge4; if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge; VerticesOnGeomEdge= newVerticesOnGeomEdge; if(VertexOnBThEdge) delete [] VertexOnBThEdge; VertexOnBThEdge = newVertexOnBThEdge; NbVerticesOnGeomEdge = newNbVerticesOnGeomEdge; NbVertexOnBThEdge=newNbVertexOnBThEdge; // ReMakeTriangleContainingTheVertex(); FillHoleInMesh(); #ifdef DEBUG for (i=0;i<nbt;i++) triangles[i].check(); #endif if (verbosity>2) cout << " (out) Nb of Quadrilaterals = " << NbOfQuad << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 << " Nb of outside triangles = " << NbOutT << endl; CurrentTh=OCurrentTh; return 0; //ok Error: nbv = nbvold; nbt = nbtold; NbOutT = NbOutTold; // cleaning memory --- delete newedges; if (ksplitarray) delete [] ksplitarray; if (kedge) delete [] kedge; if (newVerticesOnGeomEdge) delete [] newVerticesOnGeomEdge; if (edge4) delete edge4; if(newVertexOnBThEdge) delete [] newVertexOnBThEdge; CurrentTh= OCurrentTh; return ret; // ok }
int main(void) { ArArg *arg; printf("Test0 should have no arguments\nIt should have no description.\n----------------------------------\n"); TestAction0 ta0("Test0"); ta0.log(); printf("Test1 should have one argument.\nA double equal to 1.\nIt should have no description.\n----------------------------------\n"); TestAction1 ta1("Test1"); ta1.log(); printf("Test3 should have 3 arguments.\nA double, an int, and a string equal to 3.\nIt should also have a description.\n----------------------------------\n"); TestAction3 ta3("Test3", "The real test class"); ta3.log(); printf("Okay, now the automated test bit:\n"); arg = ta3.getArg(0); if (arg->getType() == ArArg::DOUBLE && arg->getDouble() == 3 && ta3.myDouble == 3) printf("Double argument type and equality: passed.\n"); else { printf("Double argument type and equality: FAILED.\n"); exit(1); } arg->setDouble(6); printf("Double argument setting: %f %f:", arg->getDouble(), ta3.myDouble); if (arg->getDouble() == 6 && ta3.myDouble == 6) printf(" passed\n"); else { printf(" FAILED\n"); exit(1); } arg = ta3.getArg(1); if (arg->getType() == ArArg::INT && arg->getInt() == 3 && ta3.myInt == 3) printf("Int argument type and equality: passed.\n"); else { printf("Int argument type and equality: FAILED.\n"); exit(1); } arg->setInt(6); printf("Int argument setting: %d %d:", arg->getInt(), ta3.myInt); if (arg->getInt() == 6 && ta3.myInt == 6) printf(" passed\n"); else { printf(" FAILED\n"); exit(1); } arg = ta3.getArg(2); if (arg->getType() == ArArg::STRING && strcmp(arg->getString(), "3") == 0 && strcmp(ta3.myString, "3") == 0) printf("String argument type and equality: passed.\n"); else { printf("String argument type and equality: FAILED.\n"); exit(1); } arg->setString("6"); printf("String argument setting: %s %s:", arg->getString(), ta3.myString); if (strcmp(arg->getString(), "6") == 0 && strcmp(ta3.myString, "6") == 0) printf(" passed\n"); else { printf(" FAILED\n"); exit(1); } printf("\nAll tests PASSED\n"); }