Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/improve3.cpp
3206 views
#include <mystdlib.h>12#include "meshing.hpp"34#ifdef SOLIDGEOM5#include <csg.hpp>6#endif7#include <opti.hpp>89namespace netgen10{1112/*13Combine two points to one.14Set new point into the center, if both are15inner points.16Connect inner point to boundary point, if one17point is inner point.18*/1920void MeshOptimize3d :: CombineImprove (Mesh & mesh,21OPTIMIZEGOAL goal)22{23int np = mesh.GetNP();24int ne = mesh.GetNE();2526TABLE<ElementIndex, PointIndex::BASE> elementsonnode(np);27ARRAY<ElementIndex> hasonepi, hasbothpi;2829ARRAY<double> oneperr;30ARRAY<double> elerrs (ne);3132PrintMessage (3, "CombineImprove");33(*testout) << "Start CombineImprove" << "\n";3435// mesh.CalcSurfacesOfNode ();36const char * savetask = multithread.task;37multithread.task = "Combine Improve";383940double totalbad = 0;41for (ElementIndex ei = 0; ei < ne; ei++)42{43double elerr = CalcBad (mesh.Points(), mesh[ei], 0);44totalbad += elerr;45elerrs[ei] = elerr;46}4748if (goal == OPT_QUALITY)49{50totalbad = CalcTotalBad (mesh.Points(), mesh.VolumeElements());51(*testout) << "Total badness = " << totalbad << endl;52PrintMessage (5, "Total badness = ", totalbad);53}5455for (ElementIndex ei = 0; ei < ne; ei++)56if (!mesh[ei].IsDeleted())57for (int j = 0; j < mesh[ei].GetNP(); j++)58elementsonnode.Add (mesh[ei][j], ei);5960INDEX_2_HASHTABLE<int> edgetested (np+1);6162int cnt = 0;6364for (ElementIndex ei = 0; ei < ne; ei++)65{66if (multithread.terminate)67break;6869multithread.percent = 100.0 * (ei+1) / ne;7071if (mesh.ElementType(ei) == FIXEDELEMENT)72continue;7374for (int j = 0; j < 6; j++)75{76Element & elemi = mesh[ei];77if (elemi.IsDeleted()) continue;7879static const int tetedges[6][2] =80{ { 0, 1 }, { 0, 2 }, { 0, 3 },81{ 1, 2 }, { 1, 3 }, { 2, 3 } };8283PointIndex pi1 = elemi[tetedges[j][0]];84PointIndex pi2 = elemi[tetedges[j][1]];8586if (pi2 < pi1) Swap (pi1, pi2);8788INDEX_2 si2 (pi1, pi2);89si2.Sort();9091if (edgetested.Used (si2)) continue;92edgetested.Set (si2, 1);939495// hasonepoint.SetSize(0);96// hasbothpoints.SetSize(0);97hasonepi.SetSize(0);98hasbothpi.SetSize(0);99100FlatArray<ElementIndex> row1 = elementsonnode[pi1];101for (int k = 0; k < row1.Size(); k++)102{103Element & elem = mesh[row1[k]];104if (elem.IsDeleted()) continue;105106if (elem[0] == pi2 || elem[1] == pi2 ||107elem[2] == pi2 || elem[3] == pi2)108{109hasbothpi.Append (row1[k]);110}111else112{113hasonepi.Append (row1[k]);114}115}116117FlatArray<ElementIndex> row2 = elementsonnode[pi2];118for (int k = 0; k < row2.Size(); k++)119{120Element & elem = mesh[row2[k]];121if (elem.IsDeleted()) continue;122123if (elem[0] == pi1 || elem[1] == pi1 ||124elem[2] == pi1 || elem[3] == pi1)125;126else127{128hasonepi.Append (row2[k]);129}130}131132double bad1 = 0;133for (int k = 0; k < hasonepi.Size(); k++)134bad1 += elerrs[hasonepi[k]];135for (int k = 0; k < hasbothpi.Size(); k++)136bad1 += elerrs[hasbothpi[k]];137138MeshPoint p1 = mesh[pi1];139MeshPoint p2 = mesh[pi2];140141142// if (mesh.PointType(pi2) != INNERPOINT)143if (p2.Type() != INNERPOINT)144continue;145146MeshPoint pnew;147// if (mesh.PointType(pi1) != INNERPOINT)148if (p1.Type() != INNERPOINT)149pnew = p1;150else151pnew = Center (p1, p2);152153mesh[pi1] = pnew;154mesh[pi2] = pnew;155156oneperr.SetSize (hasonepi.Size());157158double bad2 = 0;159for (int k = 0; k < hasonepi.Size(); k++)160{161const Element & elem = mesh[hasonepi[k]];162double err = CalcTetBadness (mesh[elem[0]], mesh[elem[1]],163mesh[elem[2]], mesh[elem[3]], 0);164bad2 += err;165oneperr[k] = err;166}167168mesh[pi1] = p1;169mesh[pi2] = p2;170171// if (mesh.PointType(pi1) != INNERPOINT)172if (p1.Type() != INNERPOINT)173{174for (int k = 0; k < hasonepi.Size(); k++)175{176Element & elem = mesh[hasonepi[k]];177int l;178for (l = 0; l < 4; l++)179if (elem[l] == pi2)180{181elem[l] = pi1;182break;183}184185elem.flags.illegal_valid = 0;186if (!mesh.LegalTet(elem))187bad2 += 1e4;188189if (l < 4)190{191elem.flags.illegal_valid = 0;192elem[l] = pi2;193}194}195}196197if (bad2 / hasonepi.Size() <198bad1 / (hasonepi.Size()+hasbothpi.Size()))199{200mesh[pi1] = pnew;201cnt++;202203FlatArray<ElementIndex> row = elementsonnode[pi2];204for (int k = 0; k < row.Size(); k++)205{206Element & elem = mesh[row[k]];207if (elem.IsDeleted()) continue;208209elementsonnode.Add (pi1, row[k]);210for (int l = 0; l < elem.GetNP(); l++)211if (elem[l] == pi2)212elem[l] = pi1;213214elem.flags.illegal_valid = 0;215if (!mesh.LegalTet (elem))216(*testout) << "illegal tet " << elementsonnode[pi2][k] << endl;217}218219for (int k = 0; k < hasonepi.Size(); k++)220elerrs[hasonepi[k]] = oneperr[k];221222for (int k = 0; k < hasbothpi.Size(); k++)223{224mesh[hasbothpi[k]].flags.illegal_valid = 0;225mesh[hasbothpi[k]].Delete();226}227}228}229}230231mesh.Compress();232mesh.MarkIllegalElements();233234PrintMessage (5, cnt, " elements combined");235(*testout) << "CombineImprove done" << "\n";236237totalbad = 0;238for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)239totalbad += CalcBad (mesh.Points(), mesh[ei], 0);240241if (goal == OPT_QUALITY)242{243totalbad = CalcTotalBad (mesh.Points(), mesh.VolumeElements());244(*testout) << "Total badness = " << totalbad << endl;245246int cntill = 0;247for (ElementIndex ei = 0; ei < ne; ei++)248if (!mesh.LegalTet (mesh[ei]))249cntill++;250251PrintMessage (5, cntill, " illegal tets");252}253multithread.task = savetask;254}255256257258259260/*261Mesh improvement by edge splitting.262If mesh quality is improved by inserting a node into an inner edge,263the edge is split into two parts.264*/265void MeshOptimize3d :: SplitImprove (Mesh & mesh,266OPTIMIZEGOAL goal)267{268int j, k, l;269Point3d p1, p2, pnew;270271ElementIndex ei;272SurfaceElementIndex sei;273PointIndex pi1, pi2;274275double bad1, bad2, badmax, badlimit;276277278int cnt = 0;279int np = mesh.GetNP();280int ne = mesh.GetNE();281282TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np);283ARRAY<ElementIndex> hasbothpoints;284285BitArray origpoint(np), boundp(np);286origpoint.Set();287288ARRAY<double> elerrs(ne);289BitArray illegaltet(ne);290illegaltet.Clear();291292const char * savetask = multithread.task;293multithread.task = "Split Improve";294295296PrintMessage (3, "SplitImprove");297(*testout) << "start SplitImprove" << "\n";298299ARRAY<INDEX_3> locfaces;300301INDEX_2_HASHTABLE<int> edgetested (np);302303bad1 = 0;304badmax = 0;305for (ei = 0; ei < ne; ei++)306{307elerrs[ei] = CalcBad (mesh.Points(), mesh[ei], 0);308bad1 += elerrs[ei];309if (elerrs[ei] > badmax) badmax = elerrs[ei];310}311312PrintMessage (5, "badmax = ", badmax);313badlimit = 0.5 * badmax;314315316boundp.Clear();317for (sei = 0; sei < mesh.GetNSE(); sei++)318for (j = 0; j < 3; j++)319boundp.Set (mesh[sei][j]);320321if (goal == OPT_QUALITY)322{323bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements());324(*testout) << "Total badness = " << bad1 << endl;325}326327for (ei = 0; ei < ne; ei++)328for (j = 0; j < mesh[ei].GetNP(); j++)329elementsonnode.Add (mesh[ei][j], ei);330331332mesh.MarkIllegalElements();333if (goal == OPT_QUALITY || goal == OPT_LEGAL)334{335int cntill = 0;336for (ei = 0; ei < ne; ei++)337{338// if (!LegalTet (volelements.Get(i)))339if (mesh[ei].flags.illegal)340{341cntill++;342illegaltet.Set (ei+1);343}344}345// (*mycout) << cntill << " illegal tets" << endl;346}347348349for (ei = 0; ei < ne; ei++)350{351if (multithread.terminate)352break;353354multithread.percent = 100.0 * (ei+1) / ne;355356bool ltestmode = 0;357358359if (elerrs[ei] < badlimit && !illegaltet.Test(ei+1)) continue;360361if ((goal == OPT_LEGAL) &&362!illegaltet.Test(ei+1) &&363CalcBad (mesh.Points(), mesh[ei], 0) < 1e3)364continue;365366367Element & elem = mesh[ei];368369if (ltestmode)370{371(*testout) << "test el " << ei << endl;372for (j = 0; j < 4; j++)373(*testout) << elem[j] << " ";374(*testout) << endl;375}376377378for (j = 0; j < 6; j++)379{380381static const int tetedges[6][2] =382{ { 0, 1 }, { 0, 2 }, { 0, 3 },383{ 1, 2 }, { 1, 3 }, { 2, 3 } };384385pi1 = elem[tetedges[j][0]];386pi2 = elem[tetedges[j][1]];387388if (pi2 < pi1) Swap (pi1, pi2);389if (pi2 > elementsonnode.Size()) continue;390391if (!origpoint.Test(pi1) || !origpoint.Test(pi2))392continue;393394395INDEX_2 i2(pi1, pi2);396i2.Sort();397398if (mesh.BoundaryEdge (pi1, pi2)) continue;399400if (edgetested.Used (i2) && !illegaltet.Test(ei+1)) continue;401edgetested.Set (i2, 1);402403hasbothpoints.SetSize (0);404for (k = 1; k <= elementsonnode.EntrySize(pi1); k++)405{406bool has1 = 0, has2 = 0;407408ElementIndex elnr = elementsonnode.Get(pi1, k);409Element & el = mesh[elnr];410411for (l = 0; l < el.GetNP(); l++)412{413if (el[l] == pi1) has1 = 1;414if (el[l] == pi2) has2 = 1;415}416if (has1 && has2)417{ // only once418for (l = 0; l < hasbothpoints.Size(); l++)419if (hasbothpoints[l] == elnr)420has1 = 0;421422if (has1)423hasbothpoints.Append (elnr);424}425}426427bad1 = 0;428for (k = 0; k < hasbothpoints.Size(); k++)429bad1 += CalcBad (mesh.Points(), mesh[hasbothpoints[k]], 0);430431432bool puretet = 1;433for (k = 0; k < hasbothpoints.Size(); k++)434if (mesh[hasbothpoints[k]].GetType() != TET)435puretet = 0;436if (!puretet) continue;437438p1 = mesh[pi1];439p2 = mesh[pi2];440441/*442pnew = Center (p1, p2);443444points.Elem(pi1) = pnew;445bad2 = 0;446for (k = 1; k <= hasbothpoints.Size(); k++)447bad2 += CalcBad (points,448volelements.Get(hasbothpoints.Get(k)), 0);449450points.Elem(pi1) = p1;451points.Elem(pi2) = pnew;452453for (k = 1; k <= hasbothpoints.Size(); k++)454bad2 += CalcBad (points,455volelements.Get(hasbothpoints.Get(k)), 0);456points.Elem(pi2) = p2;457*/458459460locfaces.SetSize (0);461for (k = 0; k < hasbothpoints.Size(); k++)462{463const Element & el = mesh[hasbothpoints[k]];464465for (l = 0; l < 4; l++)466if (el[l] == pi1 || el[l] == pi2)467{468INDEX_3 i3;469Element2d face;470el.GetFace (l+1, face);471for (int kk = 1; kk <= 3; kk++)472i3.I(kk) = face.PNum(kk);473locfaces.Append (i3);474}475}476477PointFunction1 pf (mesh.Points(), locfaces, -1);478OptiParameters par;479par.maxit_linsearch = 50;480par.maxit_bfgs = 20;481482pnew = Center (p1, p2);483Vector px(3);484px.Elem(1) = pnew.X();485px.Elem(2) = pnew.Y();486px.Elem(3) = pnew.Z();487488if (elerrs[ei] > 0.1 * badmax)489BFGS (px, pf, par);490491bad2 = pf.Func (px);492493pnew.X() = px.Get(1);494pnew.Y() = px.Get(2);495pnew.Z() = px.Get(3);496497498int hpinew = mesh.AddPoint (pnew);499// ptyps.Append (INNERPOINT);500501for (k = 0; k < hasbothpoints.Size(); k++)502{503Element & oldel = mesh[hasbothpoints[k]];504Element newel1 = oldel;505Element newel2 = oldel;506507oldel.flags.illegal_valid = 0;508newel1.flags.illegal_valid = 0;509newel2.flags.illegal_valid = 0;510511for (l = 0; l < 4; l++)512{513if (newel1[l] == pi2) newel1[l] = hpinew;514if (newel2[l] == pi1) newel2[l] = hpinew;515}516517if (!mesh.LegalTet (oldel)) bad1 += 1e6;518if (!mesh.LegalTet (newel1)) bad2 += 1e6;519if (!mesh.LegalTet (newel2)) bad2 += 1e6;520}521522// mesh.PointTypes().DeleteLast();523mesh.Points().DeleteLast();524525if (bad2 < bad1)526/* (bad1 > 1e4 && boundp.Test(pi1) && boundp.Test(pi2)) */527{528cnt++;529530PointIndex pinew = mesh.AddPoint (pnew);531532for (k = 0; k < hasbothpoints.Size(); k++)533{534Element & oldel = mesh[hasbothpoints[k]];535Element newel = oldel;536537newel.flags.illegal_valid = 0;538oldel.flags.illegal_valid = 0;539540for (l = 0; l < 4; l++)541{542origpoint.Clear (oldel[l]);543544if (oldel[l] == pi2) oldel[l] = pinew;545if (newel[l] == pi1) newel[l] = pinew;546}547mesh.AddVolumeElement (newel);548}549550j = 10;551}552}553}554555556mesh.Compress();557PrintMessage (5, cnt, " splits performed");558559(*testout) << "Splitt - Improve done" << "\n";560561if (goal == OPT_QUALITY)562{563bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements());564(*testout) << "Total badness = " << bad1 << endl;565566int cntill = 0;567ne = mesh.GetNE();568for (ei = 0; ei < ne; ei++)569{570if (!mesh.LegalTet (mesh[ei]))571cntill++;572}573// cout << cntill << " illegal tets" << endl;574}575576multithread.task = savetask;577}578579580581582583void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,584const BitArray * working_elements)585{586int j, k, l;587588ElementIndex ei;589SurfaceElementIndex sei;590591PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0), pi6(0);592int cnt = 0;593594Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET);595Element el1(TET), el2(TET), el3(TET), el4(TET);596Element el1b(TET), el2b(TET), el3b(TET), el4b(TET);597598double bad1, bad2, bad3;599600int np = mesh.GetNP();601int ne = mesh.GetNE();602//int nse = mesh.GetNSE();603604// contains at least all elements at node605TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np);606607ARRAY<ElementIndex> hasbothpoints;608609PrintMessage (3, "SwapImprove ");610(*testout) << "\n" << "Start SwapImprove" << endl;611612const char * savetask = multithread.task;613multithread.task = "Swap Improve";614615// mesh.CalcSurfacesOfNode ();616/*617for (i = 1; i <= GetNE(); i++)618if (volelements.Get(i).PNum(1))619if (!LegalTet (volelements.Get(i)))620{621cout << "detected illegal tet, 1" << endl;622(*testout) << "detected illegal tet1: " << i << endl;623}624*/625626627INDEX_3_HASHTABLE<int> faces(mesh.GetNOpenElements()/3 + 2);628if (goal == OPT_CONFORM)629{630for (int i = 1; i <= mesh.GetNOpenElements(); i++)631{632const Element2d & hel = mesh.OpenElement(i);633INDEX_3 face(hel[0], hel[1], hel[2]);634face.Sort();635faces.Set (face, 1);636}637}638639// Calculate total badness640if (goal == OPT_QUALITY)641{642bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements());643(*testout) << "Total badness = " << bad1 << endl;644}645646// find elements on node647for (ei = 0; ei < ne; ei++)648for (j = 0; j < mesh[ei].GetNP(); j++)649elementsonnode.Add (mesh[ei][j], ei);650651/*652BitArray illegaltet(GetNE());653MarkIllegalElements();654if (goal == OPT_QUALITY || goal == OPT_LEGAL)655{656int cntill = 0;657for (i = 1; i <= GetNE(); i++)658{659// if (!LegalTet (volelements.Get(i)))660if (VolumeElement(i).flags.illegal)661{662cntill++;663illegaltet.Set (i);664}665}666// (*mycout) << cntill << " illegal tets" << endl;667}668*/669670INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5);671672for (ei = 0; ei < ne; ei++)673{674if (multithread.terminate)675break;676677multithread.percent = 100.0 * (ei+1) / ne;678679if ((mesh.ElementType(ei)) == FIXEDELEMENT)680continue;681682if(working_elements &&683ei < working_elements->Size() &&684!working_elements->Test(ei))685continue;686687if (mesh[ei].IsDeleted())688continue;689690if ((goal == OPT_LEGAL) &&691mesh.LegalTet (mesh[ei]) &&692CalcBad (mesh.Points(), mesh[ei], 0) < 1e3)693continue;694695// int onlybedges = 1;696697for (j = 0; j < 6; j++)698{699// loop over edges700701const Element & elemi = mesh[ei];702if (elemi.IsDeleted()) continue;703704705// (*testout) << "check element " << elemi << endl;706707int mattyp = elemi.GetIndex();708709static const int tetedges[6][2] =710{ { 0, 1 }, { 0, 2 }, { 0, 3 },711{ 1, 2 }, { 1, 3 }, { 2, 3 } };712713pi1 = elemi[tetedges[j][0]];714pi2 = elemi[tetedges[j][1]];715716717if (pi2 < pi1) Swap (pi1, pi2);718719if (mesh.BoundaryEdge (pi1, pi2)) continue;720721722INDEX_2 i2 (pi1, pi2);723i2.Sort();724if (edgeused.Used(i2)) continue;725edgeused.Set (i2, 1);726727hasbothpoints.SetSize (0);728for (k = 0; k < elementsonnode[pi1].Size(); k++)729{730bool has1 = 0, has2 = 0;731ElementIndex elnr = elementsonnode[pi1][k];732const Element & elem = mesh[elnr];733734if (elem.IsDeleted()) continue;735736for (l = 0; l < elem.GetNP(); l++)737{738if (elem[l] == pi1) has1 = 1;739if (elem[l] == pi2) has2 = 1;740}741742if (has1 && has2)743{ // only once744for (l = 0; l < hasbothpoints.Size(); l++)745if (hasbothpoints[l] == elnr)746has1 = 0;747748if (has1)749hasbothpoints.Append (elnr);750}751}752753bool puretet = 1;754for (k = 0; k < hasbothpoints.Size(); k++)755if (mesh[hasbothpoints[k]].GetType () != TET)756puretet = 0;757if (!puretet)758continue;759760int nsuround = hasbothpoints.Size();761762if ( nsuround == 3 )763{764Element & elem = mesh[hasbothpoints[0]];765for (l = 0; l < 4; l++)766if (elem[l] != pi1 && elem[l] != pi2)767{768pi4 = pi3;769pi3 = elem[l];770}771772el31[0] = pi1;773el31[1] = pi2;774el31[2] = pi3;775el31[3] = pi4;776el31.SetIndex (mattyp);777778if (WrongOrientation (mesh.Points(), el31))779{780Swap (pi3, pi4);781el31[2] = pi3;782el31[3] = pi4;783}784785pi5 = 0;786for (k = 1; k < 3; k++)787{788const Element & elemk = mesh[hasbothpoints[k]];789bool has1 = 0;790for (l = 0; l < 4; l++)791if (elemk[l] == pi4)792has1 = 1;793if (has1)794{795for (l = 0; l < 4; l++)796if (elemk[l] != pi1 && elemk[l] != pi2 && elemk[l] != pi4)797pi5 = elemk[l];798}799}800801if(pi5 == 0)802throw NgException("Illegal state observed in SwapImprove");803804805806el32[0] = pi1;807el32[1] = pi2;808el32[2] = pi4;809el32[3] = pi5;810el32.SetIndex (mattyp);811812el33[0] = pi1;813el33[1] = pi2;814el33[2] = pi5;815el33[3] = pi3;816el33.SetIndex (mattyp);817818elementsonnode.Add (pi4, hasbothpoints[1]);819elementsonnode.Add (pi3, hasbothpoints[2]);820821bad1 = CalcBad (mesh.Points(), el31, 0) +822CalcBad (mesh.Points(), el32, 0) +823CalcBad (mesh.Points(), el33, 0);824825el31.flags.illegal_valid = 0;826el32.flags.illegal_valid = 0;827el33.flags.illegal_valid = 0;828829if (!mesh.LegalTet(el31) ||830!mesh.LegalTet(el32) ||831!mesh.LegalTet(el33))832bad1 += 1e4;833834el21[0] = pi3;835el21[1] = pi4;836el21[2] = pi5;837el21[3] = pi2;838el21.SetIndex (mattyp);839840el22[0] = pi5;841el22[1] = pi4;842el22[2] = pi3;843el22[3] = pi1;844el22.SetIndex (mattyp);845846bad2 = CalcBad (mesh.Points(), el21, 0) +847CalcBad (mesh.Points(), el22, 0);848849el21.flags.illegal_valid = 0;850el22.flags.illegal_valid = 0;851852if (!mesh.LegalTet(el21) ||853!mesh.LegalTet(el22))854bad2 += 1e4;855856857if (goal == OPT_CONFORM && bad2 < 1e4)858{859INDEX_3 face(pi3, pi4, pi5);860face.Sort();861if (faces.Used(face))862{863// (*testout) << "3->2 swap, could improve conformity, bad1 = " << bad1864// << ", bad2 = " << bad2 << endl;865if (bad2 < 1e4)866bad1 = 2 * bad2;867}868/*869else870{871INDEX_2 hi1(pi3, pi4);872hi1.Sort();873INDEX_2 hi2(pi3, pi5);874hi2.Sort();875INDEX_2 hi3(pi4, pi5);876hi3.Sort();877878if (boundaryedges->Used (hi1) ||879boundaryedges->Used (hi2) ||880boundaryedges->Used (hi3) )881bad1 = 2 * bad2;882}883*/884}885886if (bad2 < bad1)887{888// (*mycout) << "3->2 " << flush;889// (*testout) << "3->2 conversion" << endl;890cnt++;891892893/*894(*testout) << "3->2 swap, old els = " << endl895<< mesh[hasbothpoints[0]] << endl896<< mesh[hasbothpoints[1]] << endl897<< mesh[hasbothpoints[2]] << endl898<< "new els = " << endl899<< el21 << endl900<< el22 << endl;901*/902903el21.flags.illegal_valid = 0;904el22.flags.illegal_valid = 0;905mesh[hasbothpoints[0]] = el21;906mesh[hasbothpoints[1]] = el22;907for (l = 0; l < 4; l++)908mesh[hasbothpoints[2]][l] = 0;909mesh[hasbothpoints[2]].Delete();910911for (k = 0; k < 2; k++)912for (l = 0; l < 4; l++)913elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]);914}915}916917918if (nsuround == 4)919{920const Element & elem1 = mesh[hasbothpoints[0]];921for (l = 0; l < 4; l++)922if (elem1[l] != pi1 && elem1[l] != pi2)923{924pi4 = pi3;925pi3 = elem1[l];926}927928el1[0] = pi1; el1[1] = pi2;929el1[2] = pi3; el1[3] = pi4;930el1.SetIndex (mattyp);931932if (WrongOrientation (mesh.Points(), el1))933{934Swap (pi3, pi4);935el1[2] = pi3;936el1[3] = pi4;937}938939pi5 = 0;940for (k = 1; k < 4; k++)941{942const Element & elem = mesh[hasbothpoints[k]];943bool has1 = 0;944for (l = 0; l < 4; l++)945if (elem[l] == pi4)946has1 = 1;947if (has1)948{949for (l = 0; l < 4; l++)950if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4)951pi5 = elem[l];952}953}954955pi6 = 0;956for (k = 1; k < 4; k++)957{958const Element & elem = mesh[hasbothpoints[k]];959bool has1 = 0;960for (l = 0; l < 4; l++)961if (elem[l] == pi3)962has1 = 1;963if (has1)964{965for (l = 0; l < 4; l++)966if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi3)967pi6 = elem[l];968}969}970971/*972INDEX_2 i22(pi3, pi5);973i22.Sort();974INDEX_2 i23(pi4, pi6);975i23.Sort();976*/977978el1[0] = pi1; el1[1] = pi2;979el1[2] = pi3; el1[3] = pi4;980el1.SetIndex (mattyp);981982el2[0] = pi1; el2[1] = pi2;983el2[2] = pi4; el2[3] = pi5;984el2.SetIndex (mattyp);985986el3[0] = pi1; el3[1] = pi2;987el3[2] = pi5; el3[3] = pi6;988el3.SetIndex (mattyp);989990el4[0] = pi1; el4[1] = pi2;991el4[2] = pi6; el4[3] = pi3;992el4.SetIndex (mattyp);993994// elementsonnode.Add (pi4, hasbothpoints.Elem(2));995// elementsonnode.Add (pi3, hasbothpoints.Elem(3));996997bad1 = CalcBad (mesh.Points(), el1, 0) +998CalcBad (mesh.Points(), el2, 0) +999CalcBad (mesh.Points(), el3, 0) +1000CalcBad (mesh.Points(), el4, 0);100110021003el1.flags.illegal_valid = 0;1004el2.flags.illegal_valid = 0;1005el3.flags.illegal_valid = 0;1006el4.flags.illegal_valid = 0;100710081009if (goal != OPT_CONFORM)1010{1011if (!mesh.LegalTet(el1) ||1012!mesh.LegalTet(el2) ||1013!mesh.LegalTet(el3) ||1014!mesh.LegalTet(el4))1015bad1 += 1e4;1016}10171018el1[0] = pi3; el1[1] = pi5;1019el1[2] = pi2; el1[3] = pi4;1020el1.SetIndex (mattyp);10211022el2[0] = pi3; el2[1] = pi5;1023el2[2] = pi4; el2[3] = pi1;1024el2.SetIndex (mattyp);10251026el3[0] = pi3; el3[1] = pi5;1027el3[2] = pi1; el3[3] = pi6;1028el3.SetIndex (mattyp);10291030el4[0] = pi3; el4[1] = pi5;1031el4[2] = pi6; el4[3] = pi2;1032el4.SetIndex (mattyp);10331034bad2 = CalcBad (mesh.Points(), el1, 0) +1035CalcBad (mesh.Points(), el2, 0) +1036CalcBad (mesh.Points(), el3, 0) +1037CalcBad (mesh.Points(), el4, 0);10381039el1.flags.illegal_valid = 0;1040el2.flags.illegal_valid = 0;1041el3.flags.illegal_valid = 0;1042el4.flags.illegal_valid = 0;10431044if (goal != OPT_CONFORM)1045{1046if (!mesh.LegalTet(el1) ||1047!mesh.LegalTet(el2) ||1048!mesh.LegalTet(el3) ||1049!mesh.LegalTet(el4))1050bad2 += 1e4;1051}105210531054el1b[0] = pi4; el1b[1] = pi6;1055el1b[2] = pi3; el1b[3] = pi2;1056el1b.SetIndex (mattyp);10571058el2b[0] = pi4; el2b[1] = pi6;1059el2b[2] = pi2; el2b[3] = pi5;1060el2b.SetIndex (mattyp);10611062el3b[0] = pi4; el3b[1] = pi6;1063el3b[2] = pi5; el3b[3] = pi1;1064el3b.SetIndex (mattyp);10651066el4b[0] = pi4; el4b[1] = pi6;1067el4b[2] = pi1; el4b[3] = pi3;1068el4b.SetIndex (mattyp);10691070bad3 = CalcBad (mesh.Points(), el1b, 0) +1071CalcBad (mesh.Points(), el2b, 0) +1072CalcBad (mesh.Points(), el3b, 0) +1073CalcBad (mesh.Points(), el4b, 0);10741075el1b.flags.illegal_valid = 0;1076el2b.flags.illegal_valid = 0;1077el3b.flags.illegal_valid = 0;1078el4b.flags.illegal_valid = 0;10791080if (goal != OPT_CONFORM)1081{1082if (!mesh.LegalTet(el1b) ||1083!mesh.LegalTet(el2b) ||1084!mesh.LegalTet(el3b) ||1085!mesh.LegalTet(el4b))1086bad3 += 1e4;1087}108810891090/*1091int swap2 = (bad2 < bad1) && (bad2 < bad3);1092int swap3 = !swap2 && (bad3 < bad1);10931094if ( ((bad2 < 10 * bad1) ||1095(bad2 < 1e6)) && mesh.BoundaryEdge (pi3, pi5))1096swap2 = 1;1097else if ( ((bad3 < 10 * bad1) ||1098(bad3 < 1e6)) && mesh.BoundaryEdge (pi4, pi6))1099{1100swap3 = 1;1101swap2 = 0;1102}1103*/1104bool swap2, swap3;11051106if (goal != OPT_CONFORM)1107{1108swap2 = (bad2 < bad1) && (bad2 < bad3);1109swap3 = !swap2 && (bad3 < bad1);1110}1111else1112{1113if (mesh.BoundaryEdge (pi3, pi5)) bad2 /= 1e6;1114if (mesh.BoundaryEdge (pi4, pi6)) bad3 /= 1e6;11151116swap2 = (bad2 < bad1) && (bad2 < bad3);1117swap3 = !swap2 && (bad3 < bad1);1118}111911201121if (swap2 || swap3)1122{1123// (*mycout) << "4->4 " << flush;1124cnt++;1125// (*testout) << "4->4 conversion" << "\n";1126/*1127(*testout) << "bad1 = " << bad11128<< " bad2 = " << bad21129<< " bad3 = " << bad3 << "\n";11301131(*testout) << "Points: " << pi1 << " " << pi2 << " " << pi31132<< " " << pi4 << " " << pi5 << " " << pi6 << "\n";1133(*testout) << "Elements: "1134<< hasbothpoints.Get(1) << " "1135<< hasbothpoints.Get(2) << " "1136<< hasbothpoints.Get(3) << " "1137<< hasbothpoints.Get(4) << " " << "\n";1138*/11391140/*1141{1142int i1, j1;1143for (i1 = 1; i1 <= 4; i1++)1144{1145for (j1 = 1; j1 <= 4; j1++)1146(*testout) << volelements.Get(hasbothpoints.Get(i1)).PNum(j1)1147<< " ";1148(*testout) << "\n";1149}1150}1151*/1152}115311541155if (swap2)1156{1157// (*mycout) << "bad1 = " << bad1 << " bad2 = " << bad2 << "\n";115811591160/*1161(*testout) << "4->4 swap A, old els = " << endl1162<< mesh[hasbothpoints[0]] << endl1163<< mesh[hasbothpoints[1]] << endl1164<< mesh[hasbothpoints[2]] << endl1165<< mesh[hasbothpoints[3]] << endl1166<< "new els = " << endl1167<< el1 << endl1168<< el2 << endl1169<< el3 << endl1170<< el4 << endl;1171*/1172117311741175el1.flags.illegal_valid = 0;1176el2.flags.illegal_valid = 0;1177el3.flags.illegal_valid = 0;1178el4.flags.illegal_valid = 0;11791180mesh[hasbothpoints[0]] = el1;1181mesh[hasbothpoints[1]] = el2;1182mesh[hasbothpoints[2]] = el3;1183mesh[hasbothpoints[3]] = el4;11841185for (k = 0; k < 4; k++)1186for (l = 0; l < 4; l++)1187elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]);1188}1189else if (swap3)1190{1191// (*mycout) << "bad1 = " << bad1 << " bad3 = " << bad3 << "\n";1192el1b.flags.illegal_valid = 0;1193el2b.flags.illegal_valid = 0;1194el3b.flags.illegal_valid = 0;1195el4b.flags.illegal_valid = 0;119611971198/*1199(*testout) << "4->4 swap A, old els = " << endl1200<< mesh[hasbothpoints[0]] << endl1201<< mesh[hasbothpoints[1]] << endl1202<< mesh[hasbothpoints[2]] << endl1203<< mesh[hasbothpoints[3]] << endl1204<< "new els = " << endl1205<< el1b << endl1206<< el2b << endl1207<< el3b << endl1208<< el4b << endl;1209*/121012111212mesh[hasbothpoints[0]] = el1b;1213mesh[hasbothpoints[1]] = el2b;1214mesh[hasbothpoints[2]] = el3b;1215mesh[hasbothpoints[3]] = el4b;121612171218for (k = 0; k < 4; k++)1219for (l = 0; l < 4; l++)1220elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]);1221}1222}12231224if (nsuround >= 5)1225{1226Element hel(TET);12271228ArrayMem<PointIndex, 50> suroundpts(nsuround);1229ArrayMem<char, 50> tetused(nsuround);12301231Element & elem = mesh[hasbothpoints[0]];12321233for (l = 0; l < 4; l++)1234if (elem[l] != pi1 && elem[l] != pi2)1235{1236pi4 = pi3;1237pi3 = elem[l];1238}12391240hel[0] = pi1;1241hel[1] = pi2;1242hel[2] = pi3;1243hel[3] = pi4;1244hel.SetIndex (mattyp);12451246if (WrongOrientation (mesh.Points(), hel))1247{1248Swap (pi3, pi4);1249hel[2] = pi3;1250hel[3] = pi4;1251}125212531254// suroundpts.SetSize (nsuround);1255suroundpts[0] = pi3;1256suroundpts[1] = pi4;12571258tetused = 0;1259tetused[0] = 1;12601261for (l = 2; l < nsuround; l++)1262{1263int oldpi = suroundpts[l-1];1264int newpi = 0;12651266for (k = 0; k < nsuround && !newpi; k++)1267if (!tetused[k])1268{1269const Element & nel = mesh[hasbothpoints[k]];12701271for (int k2 = 0; k2 < 4 && !newpi; k2++)1272if (nel[k2] == oldpi)1273{1274newpi =1275nel[0] + nel[1] + nel[2] + nel[3]1276- pi1 - pi2 - oldpi;12771278tetused[k] = 1;1279suroundpts[l] = newpi;1280}1281}1282}128312841285bad1 = 0;1286for (k = 0; k < nsuround; k++)1287{1288hel[0] = pi1;1289hel[1] = pi2;1290hel[2] = suroundpts[k];1291hel[3] = suroundpts[(k+1) % nsuround];1292hel.SetIndex (mattyp);12931294bad1 += CalcBad (mesh.Points(), hel, 0);1295}12961297// (*testout) << "nsuround = " << nsuround << " bad1 = " << bad1 << endl;129812991300int bestl = -1;1301int confface = -1;1302int confedge = -1;1303double badopt = bad1;13041305for (l = 0; l < nsuround; l++)1306{1307bad2 = 0;13081309for (k = l+1; k <= nsuround + l - 2; k++)1310{1311hel[0] = suroundpts[l];1312hel[1] = suroundpts[k % nsuround];1313hel[2] = suroundpts[(k+1) % nsuround];1314hel[3] = pi2;13151316bad2 += CalcBad (mesh.Points(), hel, 0);1317hel.flags.illegal_valid = 0;1318if (!mesh.LegalTet(hel)) bad2 += 1e4;13191320hel[2] = suroundpts[k % nsuround];1321hel[1] = suroundpts[(k+1) % nsuround];1322hel[3] = pi1;13231324bad2 += CalcBad (mesh.Points(), hel, 0);13251326hel.flags.illegal_valid = 0;1327if (!mesh.LegalTet(hel)) bad2 += 1e4;1328}1329// (*testout) << "bad2," << l << " = " << bad2 << endl;13301331if ( bad2 < badopt )1332{1333bestl = l;1334badopt = bad2;1335}133613371338if (goal == OPT_CONFORM)1339// (bad2 <= 100 * bad1 || bad2 <= 1e6))1340{1341bool nottoobad =1342(bad2 <= bad1) ||1343(bad2 <= 100 * bad1 && bad2 <= 1e18) ||1344(bad2 <= 1e8);13451346for (k = l+1; k <= nsuround + l - 2; k++)1347{1348INDEX_3 hi3(suroundpts[l],1349suroundpts[k % nsuround],1350suroundpts[(k+1) % nsuround]);1351hi3.Sort();1352if (faces.Used(hi3))1353{1354// (*testout) << "could improve face conformity, bad1 = " << bad11355// << ", bad 2 = " << bad2 << ", nottoobad = " << nottoobad << endl;1356if (nottoobad)1357confface = l;1358}1359}13601361for (k = l+2; k <= nsuround+l-2; k++)1362{1363if (mesh.BoundaryEdge (suroundpts[l],1364suroundpts[k % nsuround]))1365{1366/*1367*testout << "could improve edge conformity, bad1 = " << bad11368<< ", bad 2 = " << bad2 << ", nottoobad = " << nottoobad << endl;1369*/1370if (nottoobad)1371confedge = l;1372}1373}1374}1375}13761377if (confedge != -1)1378bestl = confedge;1379if (confface != -1)1380bestl = confface;13811382if (bestl != -1)1383{1384// (*mycout) << nsuround << "->" << 2 * (nsuround-2) << " " << flush;1385cnt++;13861387for (k = bestl+1; k <= nsuround + bestl - 2; k++)1388{1389int k1;13901391hel[0] = suroundpts[bestl];1392hel[1] = suroundpts[k % nsuround];1393hel[2] = suroundpts[(k+1) % nsuround];1394hel[3] = pi2;1395hel.flags.illegal_valid = 0;13961397/*1398(*testout) << nsuround << "-swap, new el,top = "1399<< hel << endl;1400*/1401mesh.AddVolumeElement (hel);14021403for (k1 = 0; k1 < 4; k1++)1404elementsonnode.Add (hel[k1], mesh.GetNE()-1);140514061407hel[2] = suroundpts[k % nsuround];1408hel[1] = suroundpts[(k+1) % nsuround];1409hel[3] = pi1;14101411/*1412(*testout) << nsuround << "-swap, new el,bot = "1413<< hel << endl;1414*/14151416mesh.AddVolumeElement (hel);14171418for (k1 = 0; k1 < 4; k1++)1419elementsonnode.Add (hel[k1], mesh.GetNE()-1);1420}14211422for (k = 0; k < nsuround; k++)1423{1424Element & rel = mesh[hasbothpoints[k]];1425/*1426(*testout) << nsuround << "-swap, old el = "1427<< rel << endl;1428*/1429rel.Delete();1430for (int k1 = 0; k1 < 4; k1++)1431rel[k1] = 0;14321433}1434}1435}1436}14371438/*1439if (onlybedges)1440{1441(*testout) << "bad tet: "1442<< volelements.Get(i)[0]1443<< volelements.Get(i)[1]1444<< volelements.Get(i)[2]1445<< volelements.Get(i)[3] << "\n";14461447if (!mesh.LegalTet (volelements.Get(i)))1448cerr << "Illegal tet" << "\n";1449}1450*/1451}1452// (*mycout) << endl;14531454/*1455cout << "edgeused: ";1456edgeused.PrintMemInfo(cout);1457*/1458PrintMessage (5, cnt, " swaps performed");145914601461146214631464mesh.Compress ();14651466/*1467if (goal == OPT_QUALITY)1468{1469bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements());1470// (*testout) << "Total badness = " << bad1 << endl;1471}1472*/14731474/*1475for (i = 1; i <= GetNE(); i++)1476if (volelements.Get(i)[0])1477if (!mesh.LegalTet (volelements.Get(i)))1478{1479cout << "detected illegal tet, 2" << endl;1480(*testout) << "detected illegal tet1: " << i << endl;1481}1482*/14831484multithread.task = savetask;1485}1486148714881489149014911492void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal,1493const BitArray * working_elements,1494const ARRAY< ARRAY<int,PointIndex::BASE>* > * idmaps)1495{1496ARRAY< ARRAY<int,PointIndex::BASE>* > locidmaps;1497const ARRAY< ARRAY<int,PointIndex::BASE>* > * used_idmaps;14981499if(idmaps)1500used_idmaps = idmaps;1501else1502{1503used_idmaps = &locidmaps;15041505for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)1506{1507if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)1508{1509locidmaps.Append(new ARRAY<int,PointIndex::BASE>);1510mesh.GetIdentifications().GetMap(i,*locidmaps.Last(),true);1511}1512}1513}15141515ElementIndex ei;1516SurfaceElementIndex sei;15171518PointIndex pi1, pi2, pi3, pi4, pi5, pi6;1519PointIndex pi1other, pi2other;1520int cnt = 0;15211522//double bad1, bad2, bad3, sbad;1523double bad1, sbad;1524double h;15251526int np = mesh.GetNP();1527int ne = mesh.GetNE();1528int nse = mesh.GetNSE();15291530int mattype, othermattype;153115321533// contains at least all elements at node1534TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np);1535TABLE<SurfaceElementIndex,PointIndex::BASE> surfaceelementsonnode(np);1536TABLE<int,PointIndex::BASE> surfaceindicesonnode(np);15371538ARRAY<ElementIndex> hasbothpoints;1539ARRAY<ElementIndex> hasbothpointsother;15401541PrintMessage (3, "SwapImproveSurface ");1542(*testout) << "\n" << "Start SwapImproveSurface" << endl;15431544const char * savetask = multithread.task;1545multithread.task = "Swap Improve Surface";1546154715481549// find elements on node1550for (ei = 0; ei < ne; ei++)1551for (int j = 0; j < mesh[ei].GetNP(); j++)1552elementsonnode.Add (mesh[ei][j], ei);15531554for (sei = 0; sei < nse; sei++)1555for(int j=0; j<mesh[sei].GetNP(); j++)1556{1557surfaceelementsonnode.Add(mesh[sei][j], sei);1558if(!surfaceindicesonnode[mesh[sei][j]].Contains(mesh[sei].GetIndex()))1559surfaceindicesonnode.Add(mesh[sei][j],mesh[sei].GetIndex());1560}15611562bool periodic;1563int idnum(-1);15641565INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5);15661567for (ei = 0; ei < ne; ei++)1568{1569if (multithread.terminate)1570break;15711572multithread.percent = 100.0 * (ei+1) / ne;15731574if (mesh.ElementType(ei) == FIXEDELEMENT)1575continue;15761577if(working_elements &&1578ei < working_elements->Size() &&1579!working_elements->Test(ei))1580continue;15811582if (mesh[ei].IsDeleted())1583continue;15841585if ((goal == OPT_LEGAL) &&1586mesh.LegalTet (mesh[ei]) &&1587CalcBad (mesh.Points(), mesh[ei], 0) < 1e3)1588continue;15891590const Element & elemi = mesh[ei];1591//Element elemi = mesh[ei];1592if (elemi.IsDeleted()) continue;159315941595mattype = elemi.GetIndex();15961597bool swapped = false;15981599for (int j = 0; !swapped && j < 6; j++)1600{1601// loop over edges160216031604static const int tetedges[6][2] =1605{ { 0, 1 }, { 0, 2 }, { 0, 3 },1606{ 1, 2 }, { 1, 3 }, { 2, 3 } };16071608pi1 = elemi[tetedges[j][0]];1609pi2 = elemi[tetedges[j][1]];161016111612if (pi2 < pi1)1613Swap (pi1, pi2);161416151616bool found = false;1617for(int k=0; !found && k<used_idmaps->Size(); k++)1618{1619if(pi2 < (*used_idmaps)[k]->Size() + PointIndex::BASE)1620{1621pi1other = (*(*used_idmaps)[k])[pi1];1622pi2other = (*(*used_idmaps)[k])[pi2];1623found = (pi1other != 0 && pi2other != 0 && pi1other != pi1 && pi2other != pi2);1624if(found)1625idnum = k;1626}1627}1628if(found)1629periodic = true;1630else1631{1632periodic = false;1633pi1other = pi1; pi2other = pi2;1634}1635163616371638if (!mesh.BoundaryEdge (pi1, pi2) ||1639mesh.IsSegment(pi1, pi2)) continue;16401641othermattype = -1;164216431644INDEX_2 i2 (pi1, pi2);1645i2.Sort();1646if (edgeused.Used(i2)) continue;1647edgeused.Set (i2, 1);1648if(periodic)1649{1650i2.I1() = pi1other;1651i2.I2() = pi2other;1652i2.Sort();1653edgeused.Set(i2,1);1654}165516561657hasbothpoints.SetSize (0);1658hasbothpointsother.SetSize (0);1659for (int k = 0; k < elementsonnode[pi1].Size(); k++)1660{1661bool has1 = false, has2 = false;1662ElementIndex elnr = elementsonnode[pi1][k];1663const Element & elem = mesh[elnr];16641665if (elem.IsDeleted()) continue;16661667for (int l = 0; l < elem.GetNP(); l++)1668{1669if (elem[l] == pi1) has1 = true;1670if (elem[l] == pi2) has2 = true;1671}16721673if (has1 && has2)1674{1675if(othermattype == -1 && elem.GetIndex() != mattype)1676othermattype = elem.GetIndex();16771678if(elem.GetIndex() == mattype)1679{1680// only once1681for (int l = 0; l < hasbothpoints.Size(); l++)1682if (hasbothpoints[l] == elnr)1683has1 = 0;16841685if (has1)1686hasbothpoints.Append (elnr);1687}1688else if(elem.GetIndex() == othermattype)1689{1690// only once1691for (int l = 0; l < hasbothpointsother.Size(); l++)1692if (hasbothpointsother[l] == elnr)1693has1 = 0;16941695if (has1)1696hasbothpointsother.Append (elnr);1697}1698else1699{1700cout << "problem with domain indices" << endl;1701(*testout) << "problem: mattype = " << mattype << ", othermattype = " << othermattype1702<< " elem " << elem << " mt " << elem.GetIndex() << endl1703<< " pi1 " << pi1 << " pi2 " << pi2 << endl;1704(*testout) << "hasbothpoints:" << endl;1705for(int ii=0; ii < hasbothpoints.Size(); ii++)1706(*testout) << mesh[hasbothpoints[ii]] << endl;1707(*testout) << "hasbothpointsother:" << endl;1708for(int ii=0; ii < hasbothpointsother.Size(); ii++)1709(*testout) << mesh[hasbothpointsother[ii]] << endl;1710}1711}1712}17131714if(hasbothpointsother.Size() > 0 && periodic)1715throw NgException("SwapImproveSurface: Assumption about interface/periodicity wrong!");17161717if(periodic)1718{1719for (int k = 0; k < elementsonnode[pi1other].Size(); k++)1720{1721bool has1 = false, has2 = false;1722ElementIndex elnr = elementsonnode[pi1other][k];1723const Element & elem = mesh[elnr];17241725if (elem.IsDeleted()) continue;17261727for (int l = 0; l < elem.GetNP(); l++)1728{1729if (elem[l] == pi1other) has1 = true;1730if (elem[l] == pi2other) has2 = true;1731}17321733if (has1 && has2)1734{1735if(othermattype == -1)1736othermattype = elem.GetIndex();17371738// only once1739for (int l = 0; l < hasbothpointsother.Size(); l++)1740if (hasbothpointsother[l] == elnr)1741has1 = 0;17421743if (has1)1744hasbothpointsother.Append (elnr);1745}1746}1747}174817491750//for(k=0; k<hasbothpoints.Size(); k++)1751// (*testout) << "hasbothpoints["<<k<<"]: " << mesh[hasbothpoints[k]] << endl;175217531754SurfaceElementIndex sel1=-1,sel2=-1;1755SurfaceElementIndex sel1other=-1,sel2other=-1;1756for(int k = 0; k < surfaceelementsonnode[pi1].Size(); k++)1757{1758bool has1 = false, has2 = false;1759SurfaceElementIndex elnr = surfaceelementsonnode[pi1][k];1760const Element2d & elem = mesh[elnr];17611762if (elem.IsDeleted()) continue;17631764for (int l = 0; l < elem.GetNP(); l++)1765{1766if (elem[l] == pi1) has1 = true;1767if (elem[l] == pi2) has2 = true;1768}17691770if(has1 && has2 && elnr != sel2)1771{1772sel1 = sel2;1773sel2 = elnr;1774}1775}17761777if(periodic)1778{1779for(int k = 0; k < surfaceelementsonnode[pi1other].Size(); k++)1780{1781bool has1 = false, has2 = false;1782SurfaceElementIndex elnr = surfaceelementsonnode[pi1other][k];1783const Element2d & elem = mesh[elnr];17841785if (elem.IsDeleted()) continue;17861787for (int l = 0; l < elem.GetNP(); l++)1788{1789if (elem[l] == pi1other) has1 = true;1790if (elem[l] == pi2other) has2 = true;1791}17921793if(has1 && has2 && elnr != sel2other)1794{1795sel1other = sel2other;1796sel2other = elnr;1797}1798}1799}1800else1801{1802sel1other = sel1; sel2other = sel2;1803}18041805//(*testout) << "sel1 " << sel1 << " sel2 " << sel2 << " el " << mesh[sel1] << " resp. " << mesh[sel2] << endl;18061807PointIndex sp1(0), sp2(0);1808PointIndex sp1other, sp2other;1809for(int l=0; l<mesh[sel1].GetNP(); l++)1810if(mesh[sel1][l] != pi1 && mesh[sel1][l] != pi2)1811sp1 = mesh[sel1][l];1812for(int l=0; l<mesh[sel2].GetNP(); l++)1813if(mesh[sel2][l] != pi1 && mesh[sel2][l] != pi2)1814sp2 = mesh[sel2][l];18151816if(periodic)1817{1818sp1other = (*(*used_idmaps)[idnum])[sp1];1819sp2other = (*(*used_idmaps)[idnum])[sp2];18201821bool change = false;1822for(int l=0; !change && l<mesh[sel1other].GetNP(); l++)1823change = (sp2other == mesh[sel1other][l]);18241825if(change)1826{1827SurfaceElementIndex aux = sel1other;1828sel1other = sel2other;1829sel2other = aux;1830}18311832}1833else1834{1835sp1other = sp1; sp2other = sp2;1836}18371838Vec<3> v1 = mesh[sp1]-mesh[pi1],1839v2 = mesh[sp2]-mesh[pi1],1840v3 = mesh[sp1]-mesh[pi2],1841v4 = mesh[sp2]-mesh[pi2];1842double vol = 0.5*(Cross(v1,v2).Length() + Cross(v3,v4).Length());1843h = sqrt(vol);1844h = 0;18451846sbad = CalcTriangleBadness (mesh[pi1],mesh[pi2],mesh[sp1],0,0) +1847CalcTriangleBadness (mesh[pi2],mesh[pi1],mesh[sp2],0,0);1848184918501851bool puretet = true;1852for (int k = 0; puretet && k < hasbothpoints.Size(); k++)1853if (mesh[hasbothpoints[k]].GetType () != TET)1854puretet = false;1855for (int k = 0; puretet && k < hasbothpointsother.Size(); k++)1856if (mesh[hasbothpointsother[k]].GetType () != TET)1857puretet = false;1858if (!puretet)1859continue;18601861int nsuround = hasbothpoints.Size();1862int nsuroundother = hasbothpointsother.Size();18631864ARRAY < int > outerpoints(nsuround+1);1865outerpoints[0] = sp1;18661867for(int i=0; i<nsuround; i++)1868{1869bool done = false;1870for(int jj=i; !done && jj<hasbothpoints.Size(); jj++)1871{1872for(int k=0; !done && k<4; k++)1873if(mesh[hasbothpoints[jj]][k] == outerpoints[i])1874{1875done = true;1876for(int l=0; l<4; l++)1877if(mesh[hasbothpoints[jj]][l] != pi1 &&1878mesh[hasbothpoints[jj]][l] != pi2 &&1879mesh[hasbothpoints[jj]][l] != outerpoints[i])1880outerpoints[i+1] = mesh[hasbothpoints[jj]][l];1881}1882if(done)1883{1884ElementIndex aux = hasbothpoints[i];1885hasbothpoints[i] = hasbothpoints[jj];1886hasbothpoints[jj] = aux;1887}1888}1889}1890if(outerpoints[nsuround] != sp2)1891{1892cerr << "OJE OJE OJE" << endl;1893(*testout) << "OJE OJE OJE" << endl;1894(*testout) << "hasbothpoints: " << endl;1895for(int ii=0; ii < hasbothpoints.Size(); ii++)1896{1897(*testout) << mesh[hasbothpoints[ii]] << endl;1898for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++)1899if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 0)1900(*testout) << mesh[hasbothpoints[ii]][jj] << " between "1901<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and "1902<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl;1903}1904(*testout) << "outerpoints: " << outerpoints << endl;1905(*testout) << "sel1 " << mesh[sel1] << endl1906<< "sel2 " << mesh[sel2] << endl;1907for(int ii=0; ii<3; ii++)1908{1909if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0)1910(*testout) << mesh[sel1][ii] << " between "1911<< mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and "1912<< mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl;1913if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0)1914(*testout) << mesh[sel2][ii] << " between "1915<< mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and "1916<< mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl;1917}1918}191919201921ARRAY < int > outerpointsother;19221923if(nsuroundother > 0)1924{1925outerpointsother.SetSize(nsuroundother+1);1926outerpointsother[0] = sp2other;1927}19281929for(int i=0; i<nsuroundother; i++)1930{1931bool done = false;1932for(int jj=i; !done && jj<hasbothpointsother.Size(); jj++)1933{1934for(int k=0; !done && k<4; k++)1935if(mesh[hasbothpointsother[jj]][k] == outerpointsother[i])1936{1937done = true;1938for(int l=0; l<4; l++)1939if(mesh[hasbothpointsother[jj]][l] != pi1other &&1940mesh[hasbothpointsother[jj]][l] != pi2other &&1941mesh[hasbothpointsother[jj]][l] != outerpointsother[i])1942outerpointsother[i+1] = mesh[hasbothpointsother[jj]][l];1943}1944if(done)1945{1946ElementIndex aux = hasbothpointsother[i];1947hasbothpointsother[i] = hasbothpointsother[jj];1948hasbothpointsother[jj] = aux;1949}1950}1951}1952if(nsuroundother > 0 && outerpointsother[nsuroundother] != sp1other)1953{1954cerr << "OJE OJE OJE (other)" << endl;1955(*testout) << "OJE OJE OJE (other)" << endl;1956(*testout) << "pi1 " << pi1 << " pi2 " << pi2 << " sp1 " << sp1 << " sp2 " << sp2 << endl;1957(*testout) << "hasbothpoints: " << endl;1958for(int ii=0; ii < hasbothpoints.Size(); ii++)1959{1960(*testout) << mesh[hasbothpoints[ii]] << endl;1961for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++)1962if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 0)1963(*testout) << mesh[hasbothpoints[ii]][jj] << " between "1964<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and "1965<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl;1966}1967(*testout) << "outerpoints: " << outerpoints << endl;1968(*testout) << "sel1 " << mesh[sel1] << endl1969<< "sel2 " << mesh[sel2] << endl;1970for(int ii=0; ii<3; ii++)1971{1972if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0)1973(*testout) << mesh[sel1][ii] << " between "1974<< mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and "1975<< mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl;1976if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0)1977(*testout) << mesh[sel2][ii] << " between "1978<< mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and "1979<< mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl;1980}19811982(*testout) << "pi1other " << pi1other << " pi2other " << pi2other << " sp1other " << sp1other << " sp2other " << sp2other << endl;1983(*testout) << "hasbothpointsother: " << endl;1984for(int ii=0; ii < hasbothpointsother.Size(); ii++)1985{1986(*testout) << mesh[hasbothpointsother[ii]] << endl;1987for(int jj=0; jj<mesh[hasbothpointsother[ii]].GetNP(); jj++)1988if(mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] > 0)1989(*testout) << mesh[hasbothpointsother[ii]][jj] << " between "1990<< mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] << " and "1991<< mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][1] << endl;1992}1993(*testout) << "outerpoints: " << outerpointsother << endl;1994(*testout) << "sel1other " << mesh[sel1other] << endl1995<< "sel2other " << mesh[sel2other] << endl;1996for(int ii=0; ii<3; ii++)1997{1998if(mesh.mlbetweennodes[mesh[sel1other][ii]][0] > 0)1999(*testout) << mesh[sel1other][ii] << " between "2000<< mesh.mlbetweennodes[mesh[sel1other][ii]][0] << " and "2001<< mesh.mlbetweennodes[mesh[sel1other][ii]][1] << endl;2002if(mesh.mlbetweennodes[mesh[sel2other][ii]][0] > 0)2003(*testout) << mesh[sel2other][ii] << " between "2004<< mesh.mlbetweennodes[mesh[sel2other][ii]][0] << " and "2005<< mesh.mlbetweennodes[mesh[sel2other][ii]][1] << endl;2006}2007}20082009bad1=0;2010for(int i=0; i<hasbothpoints.Size(); i++)2011bad1 += CalcBad(mesh.Points(), mesh[hasbothpoints[i]],h);2012for(int i=0; i<hasbothpointsother.Size(); i++)2013bad1 += CalcBad(mesh.Points(), mesh[hasbothpointsother[i]],h);2014bad1 /= double(hasbothpoints.Size() + hasbothpointsother.Size());201520162017int startpoints,startpointsother;201820192020if(outerpoints.Size() == 3)2021startpoints = 1;2022else if(outerpoints.Size() == 4)2023startpoints = 2;2024else2025startpoints = outerpoints.Size();20262027if(outerpointsother.Size() == 3)2028startpointsother = 1;2029else if(outerpointsother.Size() == 4)2030startpointsother = 2;2031else2032startpointsother = outerpointsother.Size();203320342035ARRAY < ARRAY < Element* > * > newelts(startpoints);2036ARRAY < ARRAY < Element* > * > neweltsother(startpointsother);20372038double minbad = 1e50, minbadother = 1e50, currbad;2039int minpos = -1, minposother = -1;20402041//(*testout) << "pi1 " << pi1 << " pi2 " << pi2 << " outerpoints " << outerpoints << endl;20422043for(int i=0; i<startpoints; i++)2044{2045newelts[i] = new ARRAY <Element*>(2*(nsuround-1));20462047for(int jj=0; jj<nsuround-1; jj++)2048{2049(*newelts[i])[2*jj] = new Element(TET);2050(*newelts[i])[2*jj+1] = new Element(TET);2051Element & newel1 = *((*newelts[i])[2*jj]);2052Element & newel2 = *((*newelts[i])[2*jj+1]);20532054newel1[0] = pi1;2055newel1[1] = outerpoints[i];2056newel1[2] = outerpoints[(i+jj+1)%outerpoints.Size()];2057newel1[3] = outerpoints[(i+jj+2)%outerpoints.Size()];20582059newel2[0] = pi2;2060newel2[1] = outerpoints[i];2061newel2[2] = outerpoints[(i+jj+2)%outerpoints.Size()];2062newel2[3] = outerpoints[(i+jj+1)%outerpoints.Size()];206320642065//(*testout) << "j " << j << " newel1 " << newel1[0] << " "<< newel1[1] << " "<< newel1[2] << " "<< newel1[3] << endl2066// << " newel2 " << newel2[0] << " "<< newel2[1] << " "<< newel2[2] << " "<< newel2[3] << endl;20672068newel1.SetIndex(mattype);2069newel2.SetIndex(mattype);20702071}20722073bool wrongorientation = true;2074for(int jj = 0; wrongorientation && jj<newelts[i]->Size(); jj++)2075wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*newelts[i])[jj]);20762077currbad = 0;20782079for(int jj=0; jj<newelts[i]->Size(); jj++)2080{2081if(wrongorientation)2082Swap((*(*newelts[i])[jj])[2],(*(*newelts[i])[jj])[3]);208320842085// not two new faces on same surface2086ARRAY<int> face_index;2087for(int k = 0; k<surfaceindicesonnode[(*(*newelts[i])[jj])[0]].Size(); k++)2088face_index.Append(surfaceindicesonnode[(*(*newelts[i])[jj])[0]][k]);20892090for(int k=1; k<4; k++)2091{2092for(int l=0; l<face_index.Size(); l++)2093{2094if(face_index[l] != -1 &&2095!(surfaceindicesonnode[(*(*newelts[i])[jj])[k]].Contains(face_index[l])))2096face_index[l] = -1;2097}20982099}21002101for(int k=0; k<face_index.Size(); k++)2102if(face_index[k] != -1)2103currbad += 1e12;210421052106currbad += CalcBad(mesh.Points(),*(*newelts[i])[jj],h);210721082109}21102111//currbad /= double(newelts[i]->Size());2112211321142115if(currbad < minbad)2116{2117minbad = currbad;2118minpos = i;2119}21202121}21222123if(startpointsother == 0)2124minbadother = 0;21252126for(int i=0; i<startpointsother; i++)2127{2128neweltsother[i] = new ARRAY <Element*>(2*(nsuroundother));21292130for(int jj=0; jj<nsuroundother; jj++)2131{2132(*neweltsother[i])[2*jj] = new Element(TET);2133(*neweltsother[i])[2*jj+1] = new Element(TET);2134Element & newel1 = *((*neweltsother[i])[2*jj]);2135Element & newel2 = *((*neweltsother[i])[2*jj+1]);21362137newel1[0] = pi1other;2138newel1[1] = outerpointsother[i];2139newel1[2] = outerpointsother[(i+jj+1)%outerpointsother.Size()];2140newel1[3] = outerpointsother[(i+jj+2)%outerpointsother.Size()];21412142newel2[0] = pi2other;2143newel2[1] = outerpointsother[i];2144newel2[2] = outerpointsother[(i+jj+2)%outerpointsother.Size()];2145newel2[3] = outerpointsother[(i+jj+1)%outerpointsother.Size()];214621472148//(*testout) << "j " << j << " newel1 " << newel1[0] << " "<< newel1[1] << " "<< newel1[2] << " "<< newel1[3] << endl2149// << " newel2 " << newel2[0] << " "<< newel2[1] << " "<< newel2[2] << " "<< newel2[3] << endl;21502151newel1.SetIndex(othermattype);2152newel2.SetIndex(othermattype);21532154}21552156bool wrongorientation = true;2157for(int jj = 0; wrongorientation && jj<neweltsother[i]->Size(); jj++)2158wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*neweltsother[i])[jj]);21592160currbad = 0;21612162for(int jj=0; jj<neweltsother[i]->Size(); jj++)2163{2164if(wrongorientation)2165Swap((*(*neweltsother[i])[jj])[2],(*(*neweltsother[i])[jj])[3]);21662167currbad += CalcBad(mesh.Points(),*(*neweltsother[i])[jj],h);2168}21692170//currbad /= double(neweltsother[i]->Size());2171217221732174if(currbad < minbadother)2175{2176minbadother = currbad;2177minposother = i;2178}21792180}21812182//(*testout) << "minbad " << minbad << " bad1 " << bad1 << endl;218321842185double sbadnew = CalcTriangleBadness (mesh[pi1],mesh[sp2],mesh[sp1],0,0) +2186CalcTriangleBadness (mesh[pi2],mesh[sp1],mesh[sp2],0,0);218721882189int denom = newelts[minpos]->Size();2190if(minposother >= 0)2191denom += neweltsother[minposother]->Size();219221932194if((minbad+minbadother)/double(denom) < bad1 &&2195sbadnew < sbad)2196{2197cnt++;21982199swapped = true;220022012202int start1 = -1;2203for(int l=0; l<3; l++)2204if(mesh[sel1][l] == pi1)2205start1 = l;2206if(mesh[sel1][(start1+1)%3] == pi2)2207{2208mesh[sel1][0] = pi1;2209mesh[sel1][1] = sp2;2210mesh[sel1][2] = sp1;2211mesh[sel2][0] = pi2;2212mesh[sel2][1] = sp1;2213mesh[sel2][2] = sp2;2214}2215else2216{2217mesh[sel1][0] = pi2;2218mesh[sel1][1] = sp2;2219mesh[sel1][2] = sp1;2220mesh[sel2][0] = pi1;2221mesh[sel2][1] = sp1;2222mesh[sel2][2] = sp2;2223}2224//(*testout) << "changed surface element " << sel1 << " to " << mesh[sel1] << ", " << sel2 << " to " << mesh[sel2] << endl;22252226for(int l=0; l<3; l++)2227{2228surfaceelementsonnode.Add(mesh[sel1][l],sel1);2229surfaceelementsonnode.Add(mesh[sel2][l],sel2);2230}2231223222332234if(periodic)2235{2236start1 = -1;2237for(int l=0; l<3; l++)2238if(mesh[sel1other][l] == pi1other)2239start1 = l;2240224122422243//(*testout) << "changed surface elements " << mesh[sel1other] << " and " << mesh[sel2other] << endl;2244if(mesh[sel1other][(start1+1)%3] == pi2other)2245{2246mesh[sel1other][0] = pi1other;2247mesh[sel1other][1] = sp2other;2248mesh[sel1other][2] = sp1other;2249mesh[sel2other][0] = pi2other;2250mesh[sel2other][1] = sp1other;2251mesh[sel2other][2] = sp2other;2252//(*testout) << " with rule 1" << endl;2253}2254else2255{2256mesh[sel1other][0] = pi2other;2257mesh[sel1other][1] = sp2other;2258mesh[sel1other][2] = sp1other;2259mesh[sel2other][0] = pi1other;2260mesh[sel2other][1] = sp1other;2261mesh[sel2other][2] = sp2other;2262//(*testout) << " with rule 2" << endl;2263}2264//(*testout) << " to " << mesh[sel1other] << " and " << mesh[sel2other] << endl;22652266//(*testout) << " and surface element " << sel1other << " to " << mesh[sel1other] << ", " << sel2other << " to " << mesh[sel2other] << endl;22672268for(int l=0; l<3; l++)2269{2270surfaceelementsonnode.Add(mesh[sel1other][l],sel1other);2271surfaceelementsonnode.Add(mesh[sel2other][l],sel2other);2272}2273}22742275227622772278for(int i=0; i<hasbothpoints.Size(); i++)2279{2280mesh[hasbothpoints[i]] = *(*newelts[minpos])[i];22812282for(int l=0; l<4; l++)2283elementsonnode.Add((*(*newelts[minpos])[i])[l],hasbothpoints[i]);2284}22852286for(int i=hasbothpoints.Size(); i<(*newelts[minpos]).Size(); i++)2287{2288ElementIndex ni = mesh.AddVolumeElement(*(*newelts[minpos])[i]);22892290for(int l=0; l<4; l++)2291elementsonnode.Add((*(*newelts[minpos])[i])[l],ni);2292}22932294if(hasbothpointsother.Size() > 0)2295{2296for(int i=0; i<hasbothpointsother.Size(); i++)2297{2298mesh[hasbothpointsother[i]] = *(*neweltsother[minposother])[i];2299for(int l=0; l<4; l++)2300elementsonnode.Add((*(*neweltsother[minposother])[i])[l],hasbothpointsother[i]);2301}23022303for(int i=hasbothpointsother.Size(); i<(*neweltsother[minposother]).Size(); i++)2304{2305ElementIndex ni = mesh.AddVolumeElement(*(*neweltsother[minposother])[i]);2306for(int l=0; l<4; l++)2307elementsonnode.Add((*(*neweltsother[minposother])[i])[l],ni);2308}2309}2310231123122313}23142315for(int i=0; i<newelts.Size(); i++)2316{2317for(int jj=0; jj<newelts[i]->Size(); jj++)2318delete (*newelts[i])[jj];2319delete newelts[i];2320}23212322for(int i=0; i<neweltsother.Size(); i++)2323{2324for(int jj=0; jj<neweltsother[i]->Size(); jj++)2325delete (*neweltsother[i])[jj];2326delete neweltsother[i];2327}23282329}2330}23312332PrintMessage (5, cnt, " swaps performed");233323342335for(int i=0; i<locidmaps.Size(); i++)2336delete locidmaps[i];233723382339mesh.Compress ();23402341multithread.task = savetask;2342}234323442345234623472348234923502351/*23522 -> 3 conversion2353*/2354235523562357void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)2358{2359int j, k, l;2360ElementIndex ei, eli1, eli2, elnr;2361SurfaceElementIndex sei;2362PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0);23632364int cnt = 0;23652366Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET);23672368double bad1, bad2;23692370int np = mesh.GetNP();2371int ne = mesh.GetNE();2372int nse = mesh.GetNSE();23732374if (goal == OPT_CONFORM) return;23752376// contains at least all elements at node2377TABLE<ElementIndex, PointIndex::BASE> elementsonnode(np);2378TABLE<SurfaceElementIndex, PointIndex::BASE> belementsonnode(np);23792380PrintMessage (3, "SwapImprove2 ");2381(*testout) << "\n" << "Start SwapImprove2" << "\n";2382// TestOk();2383238423852386/*2387CalcSurfacesOfNode ();2388for (i = 1; i <= GetNE(); i++)2389if (volelements.Get(i)[0])2390if (!mesh.LegalTet (volelements.Get(i)))2391{2392cout << "detected illegal tet, 1" << endl;2393(*testout) << "detected illegal tet1: " << i << endl;2394}2395*/239623972398// Calculate total badness23992400bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements());2401(*testout) << "Total badness = " << bad1 << endl;2402// cout << "tot bad = " << bad1 << endl;24032404// find elements on node24052406for (ei = 0; ei < ne; ei++)2407for (j = 0; j < mesh[ei].GetNP(); j++)2408elementsonnode.Add (mesh[ei][j], ei);24092410for (sei = 0; sei < nse; sei++)2411for (j = 0; j < 3; j++)2412belementsonnode.Add (mesh[sei][j], sei);24132414for (eli1 = 0; eli1 < ne; eli1++)2415{2416if (multithread.terminate)2417break;24182419if (mesh.ElementType (eli1) == FIXEDELEMENT)2420continue;24212422if (mesh[eli1].GetType() != TET)2423continue;24242425if ((goal == OPT_LEGAL) &&2426mesh.LegalTet (mesh[eli1]) &&2427CalcBad (mesh.Points(), mesh[eli1], 0) < 1e3)2428continue;24292430// cout << "eli = " << eli1 << endl;2431// (*testout) << "swapimp2, eli = " << eli1 << "; el = " << mesh[eli1] << endl;24322433for (j = 0; j < 4; j++)2434{2435// loop over faces24362437Element & elem = mesh[eli1];2438// if (elem[0] < PointIndex::BASE) continue;2439if (elem.IsDeleted()) continue;24402441int mattyp = elem.GetIndex();24422443switch (j)2444{2445case 0:2446pi1 = elem.PNum(1); pi2 = elem.PNum(2);2447pi3 = elem.PNum(3); pi4 = elem.PNum(4);2448break;2449case 1:2450pi1 = elem.PNum(1); pi2 = elem.PNum(4);2451pi3 = elem.PNum(2); pi4 = elem.PNum(3);2452break;2453case 2:2454pi1 = elem.PNum(1); pi2 = elem.PNum(3);2455pi3 = elem.PNum(4); pi4 = elem.PNum(2);2456break;2457case 3:2458pi1 = elem.PNum(2); pi2 = elem.PNum(4);2459pi3 = elem.PNum(3); pi4 = elem.PNum(1);2460break;2461}246224632464bool bface = 0;2465for (k = 0; k < belementsonnode[pi1].Size(); k++)2466{2467const Element2d & bel =2468mesh[belementsonnode[pi1][k]];24692470bool bface1 = 1;2471for (l = 0; l < 3; l++)2472if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3)2473{2474bface1 = 0;2475break;2476}24772478if (bface1)2479{2480bface = 1;2481break;2482}2483}24842485if (bface) continue;248624872488FlatArray<ElementIndex> row = elementsonnode[pi1];2489for (k = 0; k < row.Size(); k++)2490{2491eli2 = row[k];24922493// cout << "\rei1 = " << eli1 << ", pi1 = " << pi1 << ", k = " << k << ", ei2 = " << eli22494// << ", getne = " << mesh.GetNE();24952496if ( eli1 != eli2 )2497{2498Element & elem2 = mesh[eli2];2499if (elem2.IsDeleted()) continue;2500if (elem2.GetType() != TET)2501continue;25022503int comnodes=0;2504for (l = 1; l <= 4; l++)2505if (elem2.PNum(l) == pi1 || elem2.PNum(l) == pi2 ||2506elem2.PNum(l) == pi3)2507{2508comnodes++;2509}2510else2511{2512pi5 = elem2.PNum(l);2513}25142515if (comnodes == 3)2516{2517bad1 = CalcBad (mesh.Points(), elem, 0) +2518CalcBad (mesh.Points(), elem2, 0);25192520if (!mesh.LegalTet(elem) ||2521!mesh.LegalTet(elem2))2522bad1 += 1e4;252325242525el31.PNum(1) = pi1;2526el31.PNum(2) = pi2;2527el31.PNum(3) = pi5;2528el31.PNum(4) = pi4;2529el31.SetIndex (mattyp);25302531el32.PNum(1) = pi2;2532el32.PNum(2) = pi3;2533el32.PNum(3) = pi5;2534el32.PNum(4) = pi4;2535el32.SetIndex (mattyp);25362537el33.PNum(1) = pi3;2538el33.PNum(2) = pi1;2539el33.PNum(3) = pi5;2540el33.PNum(4) = pi4;2541el33.SetIndex (mattyp);25422543bad2 = CalcBad (mesh.Points(), el31, 0) +2544CalcBad (mesh.Points(), el32, 0) +2545CalcBad (mesh.Points(), el33, 0);254625472548el31.flags.illegal_valid = 0;2549el32.flags.illegal_valid = 0;2550el33.flags.illegal_valid = 0;25512552if (!mesh.LegalTet(el31) ||2553!mesh.LegalTet(el32) ||2554!mesh.LegalTet(el33))2555bad2 += 1e4;255625572558bool do_swap = (bad2 < bad1);25592560if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) &&2561mesh.BoundaryEdge (pi4, pi5))2562do_swap = 1;25632564if (do_swap)2565{2566// cout << "do swap, eli1 = " << eli1 << "; eli2 = " << eli2 << endl;2567// (*mycout) << "2->3 " << flush;2568cnt++;25692570el31.flags.illegal_valid = 0;2571el32.flags.illegal_valid = 0;2572el33.flags.illegal_valid = 0;25732574mesh[eli1] = el31;2575mesh[eli2] = el32;25762577ElementIndex neli =2578mesh.AddVolumeElement (el33);25792580/*2581if (!LegalTet(el31) || !LegalTet(el32) ||2582!LegalTet(el33))2583{2584cout << "Swap to illegal tets !!!" << endl;2585}2586*/2587// cout << "neli = " << neli << endl;2588for (l = 0; l < 4; l++)2589{2590elementsonnode.Add (el31[l], eli1);2591elementsonnode.Add (el32[l], eli2);2592elementsonnode.Add (el33[l], neli);2593}25942595break;2596}2597}2598}2599}2600}2601}260226032604PrintMessage (5, cnt, " swaps performed");2605260626072608/*2609CalcSurfacesOfNode ();2610for (i = 1; i <= GetNE(); i++)2611if (volelements.Get(i).PNum(1))2612if (!LegalTet (volelements.Get(i)))2613{2614cout << "detected illegal tet, 2" << endl;2615(*testout) << "detected illegal tet2: " << i << endl;2616}2617*/261826192620bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements());2621(*testout) << "Total badness = " << bad1 << endl;2622(*testout) << "swapimprove2 done" << "\n";2623// (*mycout) << "Vol = " << CalcVolume (points, volelements) << "\n";2624}262526262627/*2628void Mesh :: SwapImprove2 (OPTIMIZEGOAL goal)2629{2630int i, j;2631int eli1, eli2;2632int mattyp;26332634Element el31(4), el32(4), el33(4);2635double bad1, bad2;263626372638INDEX_3_HASHTABLE<INDEX_2> elsonface (GetNE());26392640(*mycout) << "SwapImprove2 " << endl;2641(*testout) << "\n" << "Start SwapImprove2" << "\n";26422643// Calculate total badness26442645if (goal == OPT_QUALITY)2646{2647double bad1 = CalcTotalBad (points, volelements);2648(*testout) << "Total badness = " << bad1 << endl;2649}26502651// find elements on node265226532654Element2d face;2655for (i = 1; i <= GetNE(); i++)2656if ( (i > eltyps.Size()) || (eltyps.Get(i) != FIXEDELEMENT) )2657{2658const Element & el = VolumeElement(i);2659if (!el.PNum(1)) continue;26602661for (j = 1; j <= 4; j++)2662{2663el.GetFace (j, face);2664INDEX_3 i3 (face.PNum(1), face.PNum(2), face.PNum(3));2665i3.Sort();266626672668int bnr, posnr;2669if (!elsonface.PositionCreate (i3, bnr, posnr))2670{2671INDEX_2 i2;2672elsonface.GetData (bnr, posnr, i3, i2);2673i2.I2() = i;2674elsonface.SetData (bnr, posnr, i3, i2);2675}2676else2677{2678INDEX_2 i2 (i, 0);2679elsonface.SetData (bnr, posnr, i3, i2);2680}26812682// if (elsonface.Used (i3))2683// {2684// INDEX_2 i2 = elsonface.Get(i3);2685// i2.I2() = i;2686// elsonface.Set (i3, i2);2687// }2688// else2689// {2690// INDEX_2 i2 (i, 0);2691// elsonface.Set (i3, i2);2692// }26932694}2695}26962697BitArray original(GetNE());2698original.Set();26992700for (i = 1; i <= GetNSE(); i++)2701{2702const Element2d & sface = SurfaceElement(i);2703INDEX_3 i3 (sface.PNum(1), sface.PNum(2), sface.PNum(3));2704i3.Sort();2705INDEX_2 i2(0,0);2706elsonface.Set (i3, i2);2707}270827092710for (i = 1; i <= elsonface.GetNBags(); i++)2711for (j = 1; j <= elsonface.GetBagSize(i); j++)2712{2713INDEX_3 i3;2714INDEX_2 i2;2715elsonface.GetData (i, j, i3, i2);271627172718int eli1 = i2.I1();2719int eli2 = i2.I2();27202721if (eli1 && eli2 && original.Test(eli1) && original.Test(eli2) )2722{2723Element & elem = volelements.Elem(eli1);2724Element & elem2 = volelements.Elem(eli2);27252726int pi1 = i3.I1();2727int pi2 = i3.I2();2728int pi3 = i3.I3();27292730int pi4 = elem.PNum(1) + elem.PNum(2) + elem.PNum(3) + elem.PNum(4) - pi1 - pi2 - pi3;2731int pi5 = elem2.PNum(1) + elem2.PNum(2) + elem2.PNum(3) + elem2.PNum(4) - pi1 - pi2 - pi3;2732273327342735273627372738el31.PNum(1) = pi1;2739el31.PNum(2) = pi2;2740el31.PNum(3) = pi3;2741el31.PNum(4) = pi4;2742el31.SetIndex (mattyp);27432744if (WrongOrientation (points, el31))2745swap (pi1, pi2);274627472748bad1 = CalcBad (points, elem, 0) +2749CalcBad (points, elem2, 0);27502751// if (!LegalTet(elem) || !LegalTet(elem2))2752// bad1 += 1e4;275327542755el31.PNum(1) = pi1;2756el31.PNum(2) = pi2;2757el31.PNum(3) = pi5;2758el31.PNum(4) = pi4;2759el31.SetIndex (mattyp);27602761el32.PNum(1) = pi2;2762el32.PNum(2) = pi3;2763el32.PNum(3) = pi5;2764el32.PNum(4) = pi4;2765el32.SetIndex (mattyp);27662767el33.PNum(1) = pi3;2768el33.PNum(2) = pi1;2769el33.PNum(3) = pi5;2770el33.PNum(4) = pi4;2771el33.SetIndex (mattyp);27722773bad2 = CalcBad (points, el31, 0) +2774CalcBad (points, el32, 0) +2775CalcBad (points, el33, 0);27762777// if (!LegalTet(el31) || !LegalTet(el32) ||2778// !LegalTet(el33))2779// bad2 += 1e4;278027812782int swap = (bad2 < bad1);27832784INDEX_2 hi2b(pi4, pi5);2785hi2b.Sort();27862787if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) &&2788boundaryedges->Used (hi2b) )2789swap = 1;27902791if (swap)2792{2793(*mycout) << "2->3 " << flush;27942795volelements.Elem(eli1) = el31;2796volelements.Elem(eli2) = el32;2797volelements.Append (el33);27982799original.Clear (eli1);2800original.Clear (eli2);2801}2802}2803}28042805(*mycout) << endl;28062807if (goal == OPT_QUALITY)2808{2809bad1 = CalcTotalBad (points, volelements);2810(*testout) << "Total badness = " << bad1 << endl;2811}28122813// FindOpenElements ();28142815(*testout) << "swapimprove2 done" << "\n";2816}28172818*/2819}282028212822