inline MPI_Request MyMPI_IRecv (FlatArray<T, BASE> s, int dest) { MPI_Request request; MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, 1, MPI_COMM_WORLD, &request); return request; // MPI_Request_free (&request); }
void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, const FlatArray<T> & in3, ARRAY<T> & out) { out.SetSize(0); for(int i=0; i<in1.Size(); i++) if(in2.Contains(in1[i]) && in3.Contains(in1[i])) out.Append(in1[i]); }
void Append (FlatArray<T2, B2> a2) { if (this->size+a2.Size() > allocsize) ReSize (this->size+a2.Size()); for (int i = 0; i < a2.Size(); i++) this->data[this->size+i] = a2[i+B2]; this->size += a2.Size(); }
inline void BubbleSort (const FlatArray<T> & data) { T hv; for (int i = 0; i < data.Size(); i++) for (int j = i+1; j < data.Size(); j++) if (data[i] > data[j]) { hv = data[i]; data[i] = data[j]; data[j] = hv; } }
inline ostream & operator<< (ostream & ost, const TABLE<T,BASE> & table) { for (int i = BASE; i < table.Size()+BASE; i++) { ost << i << ": "; FlatArray<T> row = table[i]; ost << "(" << row.Size() << ") "; for (int j = 0; j < row.Size(); j++) ost << row[j] << " "; ost << endl; } return ost; }
inline void BubbleSort (FlatArray<T> & data, FlatArray<S> & slave) { T hv; S hvs; for (int i = 0; i < data.Size(); i++) for (int j = i+1; j < data.Size(); j++) if (data[i] > data[j]) { hv = data[i]; data[i] = data[j]; data[j] = hv; hvs = slave[i]; slave[i] = slave[j]; slave[j] = hvs; } }
BASE_TABLE :: BASE_TABLE (const FlatArray<int> & entrysizes, int elemsize) : data(entrysizes.Size()) { int i, cnt = 0; int n = entrysizes.Size(); for (i = 0; i < n; i++) cnt += entrysizes[i]; oneblock = new char[elemsize * cnt]; // mem_total_alloc_table += elemsize * cnt; cnt = 0; for (i = 0; i < n; i++) { data[i].maxsize = entrysizes[i]; data[i].size = 0; data[i].col = &oneblock[elemsize * cnt]; cnt += entrysizes[i]; } }
void Add (int blocknr, const FlatArray<int> & dofs) { switch (mode) { case 1: if (blocknr+1 > nd) nd = blocknr+1; break; case 2: cnt[blocknr]+=dofs.Size(); break; case 3: for (int j = 0; j < dofs.Size(); j++) (*table)[blocknr][cnt[blocknr]+j] = dofs[j]; cnt[blocknr]+=dofs.Size(); /* for (int j = 0; j < dofs.Size(); j++) table->Data()[cnt[blocknr]+j] = dofs[j]; cnt[blocknr]+=dofs.Size(); */ break; } }
/// Construct table of variable entrysize INLINE Table (FlatArray<int> entrysize) { size_t cnt = 0; size = entrysize.Size(); index = new size_t[size+1]; for (int i = 0; i < size; i++) { index[i] = cnt; cnt += entrysize[i]; } index[size] = cnt; data = new T[cnt]; }
std::tuple<int,int*> Ngx_Mesh :: GetDistantProcs (int nodetype, int locnum) const { switch (nodetype) { case 0: { FlatArray<int> dn = mesh->GetParallelTopology().GetDistantPNums(locnum); return std::tuple<int,int*>(dn.Size(), &dn[0]); } case 1: { FlatArray<int> dn = mesh->GetParallelTopology().GetDistantEdgeNums(locnum); return std::tuple<int,int*>(dn.Size(), &dn[0]); } case 2: { FlatArray<int> dn = mesh->GetParallelTopology().GetDistantFaceNums(locnum); return std::tuple<int,int*>(dn.Size(), &dn[0]); } default: return std::tuple<int,int*>(0,nullptr); } }
inline void MyMPI_ISend (FlatArray<T, BASE> s, int dest, MPI_Request & request) { MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, 1, MPI_COMM_WORLD, & request); }
inline void MyMPI_Send (FlatArray<T, BASE> s, int dest, int tag) { MPI_Send( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD); }
void WriteDiffPackFormat (const Mesh & mesh, const CSGeometry & /*geom*/, const string & filename) { // double scale = globflags.GetNumFlag ("scale", 1); double scale = 1; ofstream outfile(filename.c_str()); outfile.precision(14); if (mesh.GetDimension() == 3) { // Output compatible to Diffpack grid format // Bartosz Sawicki <*****@*****.**> int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); Array <int> BIname; Array <int> BCsinpoint; int i, j, k, l; outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); const Element & eldummy = mesh.VolumeElement((int)1); outfile << "\n\n" "Finite element mesh (GridFE):\n\n" " Number of space dim. = 3\n" " Number of elements = " << ne << "\n" " Number of nodes = " << np << "\n\n" " All elements are of the same type : dpTRUE\n" " Max number of nodes in an element: "<< eldummy.GetNP() << "\n" " Only one subdomain : dpFALSE\n" " Lattice data ? 0\n\n\n\n"; for (i = 1; i <= nse; i++) { int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty(); int nbi=BIname.Size(); int found=0; for (j = 1; j <= nbi; j++) if(BI == BIname.Get(j)) found = 1; if( ! found ) BIname.Append(BI); } outfile << " " << BIname.Size() << " Boundary indicators: "; for (i =1 ; i <= BIname.Size(); i++) outfile << BIname.Get(i) << " "; outfile << "\n\n\n"; outfile << " Nodal coordinates and nodal boundary indicators,\n" " the columns contain:\n" " - node number\n" " - coordinates\n" " - no of boundary indicators that are set (ON)\n" " - the boundary indicators that are set (ON) if any.\n" "#\n"; // setup point-to-surfaceelement table TABLE<SurfaceElementIndex, PointIndex::BASE> point2sel(np); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = mesh[sei]; for (int j = 0; j < el.GetNP(); j++) point2sel.Add (el[j], sei); } for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(12); outfile << i << " ("; outfile.width(16); outfile << p.X()/scale << ", "; outfile.width(16); outfile << p.Y()/scale << ", "; outfile.width(16); outfile << p.Z()/scale << ") "; if(mesh[PointIndex(i)].Type() != INNERPOINT) { BCsinpoint.DeleteAll(); /* for (j = 1; j <= nse; j++) */ FlatArray<SurfaceElementIndex> sels = point2sel[i]; for (int jj = 0; jj < sels.Size(); jj++) { for (k = 1; k <= mesh[sels[jj]].GetNP(); k++) { if(mesh[sels[jj]].PNum(k)==i) { int BC=mesh.GetFaceDescriptor(mesh[sels[jj]].GetIndex()).BCProperty(); int nbcsp=BCsinpoint.Size(); int found = 0; for (l = 1; l <= nbcsp; l++) if(BC == BCsinpoint.Get(l)) found = 1; if( ! found ) BCsinpoint.Append(BC); } } } int nbcsp = BCsinpoint.Size(); outfile << "[" << nbcsp << "] "; for (j = 1; j <= nbcsp; j++) outfile << BCsinpoint.Get(j) << " "; outfile << "\n"; } else outfile << "[0]\n"; } outfile << "\n" " Element types and connectivity\n" " the columns contain:\n" " - element number\n" " - element type\n" " - subdomain number\n" " - the global node numbers of the nodes in the element.\n" "#\n"; for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); outfile.width(5); if(el.GetNP()==4) outfile << i << " ElmT4n3D "; else outfile << i << " ElmT10n3D "; outfile.width(4); outfile << el.GetIndex() << " "; if(el.GetNP()==10) { outfile.width(8); outfile << el.PNum(1); outfile.width(8); outfile << el.PNum(3); outfile.width(8); outfile << el.PNum(2); outfile.width(8); outfile << el.PNum(4); outfile.width(8); outfile << el.PNum(6); outfile.width(8); outfile << el.PNum(8); outfile.width(8); outfile << el.PNum(5); outfile.width(8); outfile << el.PNum(7); outfile.width(8); outfile << el.PNum(10); outfile.width(8); outfile << el.PNum(9); } else { outfile.width(8); outfile << el.PNum(1); outfile.width(8); outfile << el.PNum(3); outfile.width(8); outfile << el.PNum(2); outfile.width(8); outfile << el.PNum(4); } outfile << "\n"; } } /* Diffpack */ else { // Output compatible to Diffpack grid format 2D int np = mesh.GetNP(); //int ne = mesh.GetNE(); int nse = mesh.GetNSE(); Array <int> BIname; Array <int> BCsinpoint; int i, j, k, l; outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); const Element2d & eldummy = mesh.SurfaceElement((int)1); outfile << "\n\n" "Finite element mesh (GridFE):\n\n" " Number of space dim. = 2\n" " Number of elements = " << nse << "\n" " Number of nodes = " << np << "\n\n" " All elements are of the same type : dpTRUE\n" " Max number of nodes in an element: "<<eldummy.GetNP()<<"\n" " Only one subdomain : dpFALSE\n" " Lattice data ? 0\n\n\n\n"; for (i = 1; i <= nse; i++) { int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty(); int nbi=BIname.Size(); int found=0; for (j = 1; j <= nbi; j++) if(BI == BIname.Get(j)) found = 1; if( ! found ) BIname.Append(BI); } outfile << " " << BIname.Size() << " Boundary indicators: "; for (i =1 ; i <= BIname.Size(); i++) outfile << BIname.Get(i) << " "; outfile << "\n\n\n"; outfile << " Nodal coordinates and nodal boundary indicators,\n" " the columns contain:\n" " - node number\n" " - coordinates\n" " - no of boundary indicators that are set (ON)\n" " - the boundary indicators that are set (ON) if any.\n" "#\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(12); outfile << i << " ("; outfile.width(16); outfile << p.X()/scale << ", "; outfile.width(16); outfile << p.Y()/scale << ", "; if(mesh[PointIndex(i)].Type() != INNERPOINT) { BCsinpoint.DeleteAll(); for (j = 1; j <= nse; j++) { for (k = 1; k <= 2; k++) { if(mesh.SurfaceElement(j).PNum(k)==i) { int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).GetIndex()).BCProperty(); int nbcsp=BCsinpoint.Size(); int found = 0; for (l = 1; l <= nbcsp; l++) if(BC == BCsinpoint.Get(l)) found = 1; if( ! found ) BCsinpoint.Append(BC); } } } int nbcsp = BCsinpoint.Size(); outfile << "[" << nbcsp << "] "; for (j = 1; j <= nbcsp; j++) outfile << BCsinpoint.Get(j) << " "; outfile << "\n"; } else outfile << "[0]\n"; } outfile << "\n" " Element types and connectivity\n" " the columns contain:\n" " - element number\n" " - element type\n" " - subdomain number\n" " - the global node numbers of the nodes in the element.\n" "#\n"; for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); outfile.width(12); if(eldummy.GetNP()==3) outfile << i << " ElmT3n2D "; else outfile << i << " ElmT6n2D "; outfile.width(12); outfile << el.GetIndex() << " "; outfile.width(16); outfile << el.PNum(1); outfile.width(16); outfile << el.PNum(2); outfile.width(16); outfile << el.PNum(3); if(eldummy.GetNP()==6) { outfile.width(16); outfile << el.PNum(6); outfile.width(16); outfile << el.PNum(4); outfile.width(16); outfile << el.PNum(5); } outfile << "\n"; } } }
inline void MyMPI_IRecvTag (FlatArray<T, BASE> s, int dest, int tag, MPI_Request & request) { MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, & request); }
/// Creates fixed element size table inline TABLE (const FlatArray<int,BASE> & entrysizes) : BASE_TABLE (FlatArray<int> (entrysizes.Size(), const_cast<int*>(&entrysizes[BASE])), sizeof(T)) { ; }
inline MPI_Request MyMPI_IRecv (FlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) { MPI_Request request; MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, comm, &request); return request; }
ParallelDofs :: ParallelDofs (MPI_Comm acomm, Table<int> && adist_procs, int dim, bool iscomplex) : comm(acomm), dist_procs(adist_procs) { int ntasks = MyMPI_GetNTasks(comm); int id = MyMPI_GetId(comm); ndof = dist_procs.Size(); if (ntasks == 1) { Array<int> nexdofs(ntasks), ndistprocs(ndof); nexdofs = 0; ndistprocs = 0; exchangedofs = Table<int> (nexdofs); dist_procs = Table<int> (ndistprocs); ismasterdof.SetSize(ndof); ismasterdof.Set(); global_ndof = ndof; return; } // transpose table Array<int> nexdofs(ntasks); nexdofs = 0; for (int i = 0; i < ndof; i++) for (int d : dist_procs[i]) nexdofs[d]++; exchangedofs = Table<int>(nexdofs); nexdofs = 0; for (int i = 0; i < ndof; i++) for (int d : dist_procs[i]) exchangedofs[d][nexdofs[d]++] = i; ismasterdof.SetSize (ndof); ismasterdof.Set(); for (int i = 0; i < id; i++) for (int ex : exchangedofs[i]) ismasterdof.Clear (ex); mpi_t.SetSize (ntasks); MPI_Datatype mpi_type; mpi_type = iscomplex ? MyGetMPIType<Complex>() : MyGetMPIType<double>(); if (dim != 1) { MPI_Datatype htype; MPI_Type_contiguous (dim, mpi_type, &htype); mpi_type = htype; } for (int dest = 0; dest < ntasks; dest++ ) { if ( !IsExchangeProc(dest) ) continue; FlatArray<int> exdofs = GetExchangeDofs(dest); int len_vec = exdofs.Size(); if (len_vec == 0) continue; Array<int> blocklen(len_vec); blocklen = 1; MPI_Type_indexed (len_vec, &blocklen[0], &exdofs[0], mpi_type, &mpi_t[dest]); MPI_Type_commit (&mpi_t[dest]); } for (int i = 0; i < ntasks; i++) if (IsExchangeProc (i)) all_dist_procs.Append (i); size_t nlocal = 0; for (int i = 0; i < ndof; i++) if (ismasterdof.Test(i)) nlocal++; global_ndof = MyMPI_AllReduce (nlocal, MPI_SUM, comm); }
inline void MyMPI_Recv ( FlatArray<T, BASE> s, int src, int tag) { MPI_Status status; MPI_Recv( &s.First(), s.Size(), MyGetMPIType<T>(), src, tag, MPI_COMM_WORLD, &status); }
void MeshOptimize2d :: GenericImprove (Mesh & mesh) { if (!faceindex) { if (writestatus) PrintMessage (3, "Generic Improve"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) GenericImprove (mesh); faceindex = 0; } // int j, k, l, ri; int np = mesh.GetNP(); int ne = mesh.GetNSE(); // SurfaceElementIndex sei; // for (SurfaceElementIndex sei = 0; sei < ne; sei++) // { // const Element2d & el = mesh[sei]; // (*testout) << "element " << sei << ": " <<flush; // for(int j=0; j<el.GetNP(); j++) // (*testout) << el[j] << " " << flush; // (*testout) << "IsDeleted() " << el.IsDeleted()<< endl; // } bool ok; int olddef, newdef; ARRAY<ImprovementRule*> rules; ARRAY<SurfaceElementIndex> elmap; ARRAY<int> elrot; ARRAY<PointIndex> pmap; ARRAY<PointGeomInfo> pgi; int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); ImprovementRule * r1; // 2 triangles to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3)); r1->oldels.Append (Element2d (3, 2, 4)); r1->newels.Append (Element2d (1, 2, 4, 3)); r1->deledges.Append (INDEX_2 (2,3)); r1->onp = 4; r1->bonus = 2; rules.Append (r1); // 2 quad to 1 quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (4, 3, 2, 5)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // swap quads r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 6, 3, 4)); r1->newels.Append (Element2d (1, 2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // three quads to 2 r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (3, 6, 7, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->newels.Append (Element2d (4, 5, 6, 7)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 7; r1->bonus = -1; rules.Append (r1); // quad + 2 connected trigs to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->oldels.Append (Element2d (3, 5, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 5)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // quad + 2 non-connected trigs to quad (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 3, 4, 5)); r1->newels.Append (Element2d (1, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 2, 4, 5)); r1->newels.Append (Element2d (4, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // two quad + trig -> one quad + trig r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (4, 3, 6)); r1->newels.Append (Element2d (1, 2, 6, 4)); r1->newels.Append (Element2d (2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 6; r1->bonus = -1; rules.Append (r1); // swap quad + trig (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (2, 5, 3, 4)); r1->newels.Append (Element2d (1, 2, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (1, 2, 5, 3)); r1->newels.Append (Element2d (1, 3, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // 2 quads to quad + 2 trigs r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 5, 6, 4)); r1->newels.Append (Element2d (1, 2, 5)); r1->newels.Append (Element2d (4, 6, 3)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; // rules.Append (r1); ARRAY<int> mapped(rules.Size()); ARRAY<int> used(rules.Size()); used = 0; mapped = 0; for (int ri = 0; ri < rules.Size(); ri++) { ImprovementRule & rule = *rules[ri]; rule.incelsonnode.SetSize (rule.onp); rule.reused.SetSize (rule.onp); for (int j = 1; j <= rule.onp; j++) { rule.incelsonnode.Elem(j) = 0; rule.reused.Elem(j) = 0; } for (int j = 1; j <= rule.oldels.Size(); j++) { const Element2d & el = rule.oldels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) rule.incelsonnode.Elem(el.PNum(k))--; } for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & el = rule.newels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) { rule.incelsonnode.Elem(el.PNum(k))++; rule.reused.Elem(el.PNum(k)) = 1; } } } TABLE<int,PointIndex::BASE> elonnode(np); ARRAY<int,PointIndex::BASE> nelonnode(np); TABLE<SurfaceElementIndex> nbels(ne); nelonnode = -4; for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) elonnode.Add (el[j], sei); } if(!el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) nelonnode[el[j]]++; } } for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) { for (int k = 0; k < elonnode[el[j]].Size(); k++) { int nbel = elonnode[el[j]] [k]; bool inuse = false; for (int l = 0; l < nbels[sei].Size(); l++) if (nbels[sei][l] == nbel) inuse = true; if (!inuse) nbels.Add (sei, nbel); } } } } for (int ri = 0; ri < rules.Size(); ri++) { const ImprovementRule & rule = *rules[ri]; elmap.SetSize (rule.oldels.Size()); elrot.SetSize (rule.oldels.Size()); pmap.SetSize (rule.onp); pgi.SetSize (rule.onp); for (SurfaceElementIndex sei = 0; sei < ne; sei++) { if (multithread.terminate) break; if (mesh[sei].IsDeleted()) continue; elmap[0] = sei; FlatArray<SurfaceElementIndex> neighbours = nbels[sei]; for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++) { const Element2d & el0 = mesh[sei]; const Element2d & rel0 = rule.oldels[0]; if (el0.GetIndex() != faceindex) continue; if (el0.IsDeleted()) continue; if (el0.GetNP() != rel0.GetNP()) continue; pmap = -1; for (int k = 0; k < el0.GetNP(); k++) { pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1); pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1); } ok = 1; for (int i = 1; i < elmap.Size(); i++) { // try to find a mapping for reference-element i const Element2d & rel = rule.oldels[i]; bool possible = 0; for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++) { const Element2d & el = mesh[neighbours[elmap[i]]]; if (el.IsDeleted()) continue; if (el.GetNP() != rel.GetNP()) continue; for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++) { possible = 1; for (int k = 0; k < rel.GetNP(); k++) if (pmap.Elem(rel[k]) != -1 && pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1)) possible = 0; if (possible) { for (int k = 0; k < el.GetNP(); k++) { pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1); pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1); } break; } } if (possible) break; } if (!possible) { ok = 0; break; } elmap[i] = neighbours[elmap[i]]; } for(int i=0; ok && i<rule.deledges.Size(); i++) { ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()), pmap.Elem(rule.deledges[i].I2())); } if (!ok) continue; mapped[ri]++; olddef = 0; for (int j = 1; j <= pmap.Size(); j++) olddef += sqr (nelonnode[pmap.Get(j)]); olddef += rule.bonus; newdef = 0; for (int j = 1; j <= pmap.Size(); j++) if (rule.reused.Get(j)) newdef += sqr (nelonnode[pmap.Get(j)] + rule.incelsonnode.Get(j)); if (newdef > olddef) continue; // calc metric badness double bad1 = 0, bad2 = 0; Vec<3> n; SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1)); GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n); for (int j = 1; j <= rule.oldels.Size(); j++) bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n); // check new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); for (int k = 1; k <= rnel.GetNP(); k++) nel.PNum(k) = pmap.Get(rnel.PNum(k)); bad2 += nel.CalcJacobianBadness (mesh.Points(), n); } if (bad2 > 1e3) continue; if (newdef == olddef && bad2 > bad1) continue; // generate new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); nel.SetIndex (faceindex); for (int k = 1; k <= rnel.GetNP(); k++) { nel.PNum(k) = pmap.Get(rnel.PNum(k)); nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k)); } mesh.AddSurfaceElement(nel); } for (int j = 0; j < rule.oldels.Size(); j++) mesh.DeleteSurfaceElement ( elmap[j] ); for (int j = 1; j <= pmap.Size(); j++) nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j); used[ri]++; } } } mesh.Compress(); for (int ri = 0; ri < rules.Size(); ri++) { PrintMessage (5, "rule ", ri+1, " ", mapped[ri], "/", used[ri], " mapped/used"); } }