//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public void LoadRule(istream ist)
        {
            string      buf = new string(new char[256]);
            char        ch;
            Point2d     p   = new Point2d();
            INDEX_2     lin = new INDEX_2();
            int         i;
            int         j;
            DenseMatrix tempoldutonewu          = new DenseMatrix(20, 20);
            DenseMatrix tempoldutofreearea      = new DenseMatrix(20, 20);
            DenseMatrix tempoldutofreearealimit = new DenseMatrix(20, 20);

            tempoldutonewu          = 0;
            tempoldutofreearea      = 0;
            tempoldutofreearealimit = 0;

            noldp = 0;
            noldl = 0;

            ist.get(buf, sizeof(char), '"');
            ist.get(ch);
            ist.get(buf, sizeof(char), '"');
            ist.get(ch);

            // if(name != NULL)
            name = null;
            name = new char[buf.Length + 1];
            name = buf;
            //(*testout) << "name " << name << endl;
            //  (*mycout) << "Rule " << name << " found." << endl;

            do
            {
                ist >> buf;

                //(*testout) << "buf " << buf << endl;

                if (string.Compare(buf, "quality") == 0)

                {
                    ist >> quality;
                }

                else if (string.Compare(buf, "mappoints") == 0)
                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        ist >> p.X();
                        ist >> ch;           // ','
                        ist >> p.Y();
                        ist >> ch;           // ')'

                        points.Append(p);
                        noldp++;

                        tolerances.SetSize(noldp);
                        tolerances.Elem(noldp).f1 = 1.0;
                        tolerances.Elem(noldp).f2 = 0;
                        tolerances.Elem(noldp).f3 = 1.0;

                        ist >> ch;
                        while (ch != ';')
                        {
                            if (ch == '{')
                            {
                                ist >> tolerances.Elem(noldp).f1;
                                ist >> ch;           // ','
                                ist >> tolerances.Elem(noldp).f2;
                                ist >> ch;           // ','
                                ist >> tolerances.Elem(noldp).f3;
                                ist >> ch;           // '}'
                            }
                            else if (ch == 'd')
                            {
                                //            delpoints.Append (noldp);
                                ist >> ch;           // 'e'
                                ist >> ch;           // 'l'
                            }

                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    ist.putback(ch);
                }


                else if (string.Compare(buf, "maplines") == 0)
                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        ist >> lin.I1();
                        ist >> ch;           // ','
                        ist >> lin.I2();
                        ist >> ch;           // ')'


                        //(*testout) << "read line " << lin.I1() << " " << lin.I2() << endl;
                        lines.Append(lin);
                        linevecs.Append(points.Get(lin.I2()) - points.Get(lin.I1()));
                        noldl++;
                        linetolerances.SetSize(noldl);
                        linetolerances.Elem(noldl).f1 = 0;
                        linetolerances.Elem(noldl).f2 = 0;
                        linetolerances.Elem(noldl).f3 = 0;

                        //(*testout) << "mapl1" << endl;
                        ist >> ch;
                        while (ch != ';')
                        {
                            //(*testout) << "working on character \""<<ch<<"\""<< endl;
                            if (ch == '{')
                            {
                                ist >> linetolerances.Elem(noldl).f1;
                                ist >> ch;           // ','
                                ist >> linetolerances.Elem(noldl).f2;
                                ist >> ch;           // ','
                                ist >> linetolerances.Elem(noldl).f3;
                                ist >> ch;           // '}'
                            }
                            else if (ch == 'd')
                            {
                                dellines.Append(noldl);
                                ist >> ch;           // 'e'
                                ist >> ch;           // 'l'
                                //(*testout) << "read del" << endl;
                            }

                            ist >> ch;
                            //(*testout) << "read character \""<<ch<<"\""<< endl;
                        }

                        ist >> ch;
                        //(*testout) << "read next character \""<<ch<<"\""<< endl;
                    }


                    ist.putback(ch);
                }

                else if (string.Compare(buf, "newpoints") == 0)
                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        ist >> p.X();
                        ist >> ch;           // ','
                        ist >> p.Y();
                        ist >> ch;           // ')'

                        points.Append(p);

                        ist >> ch;
                        while (ch != ';')
                        {
                            if (ch == '{')
                            {
                                LoadMatrixLine(ist, tempoldutonewu.functorMethod, 2 * (points.Size() - noldp) - 1);

                                ist >> ch;           // '{'
                                LoadMatrixLine(ist, tempoldutonewu.functorMethod, 2 * (points.Size() - noldp));
                            }

                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    ist.putback(ch);
                }

                else if (string.Compare(buf, "newlines") == 0)
                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        ist >> lin.I1();
                        ist >> ch;           // ','
                        ist >> lin.I2();
                        ist >> ch;           // ')'

                        lines.Append(lin);
                        linevecs.Append(points.Get(lin.I2()) - points.Get(lin.I1()));

                        ist >> ch;
                        while (ch != ';')
                        {
                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    ist.putback(ch);
                }

                else if (string.Compare(buf, "freearea") == 0)
                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        ist >> p.X();
                        ist >> ch;           // ','
                        ist >> p.Y();
                        ist >> ch;           // ')'

                        freezone.Append(p);
                        freezonelimit.Append(p);

                        ist >> ch;
                        while (ch != ';')
                        {
                            if (ch == '{')
                            {
                                LoadMatrixLine(ist, tempoldutofreearea.functorMethod, 2 * freezone.Size() - 1);

                                ist >> ch;           // '{'
                                LoadMatrixLine(ist, tempoldutofreearea.functorMethod, 2 * freezone.Size());
                            }

                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    for (i = 1; i <= tempoldutofreearealimit.Height(); i++)
                    {
                        for (j = 1; j <= tempoldutofreearealimit.Width(); j++)
                        {
                            tempoldutofreearealimit.Elem(i, j) = tempoldutofreearea.Elem(i, j);
                        }
                    }


                    ist.putback(ch);
                }
                else if (string.Compare(buf, "freearea2") == 0)
                {
                    ist >> ch;
                    int freepi = 0;
                    tempoldutofreearealimit = 0;

                    while (ch == '(')
                    {
                        freepi++;

                        ist >> p.X();
                        ist >> ch;           // ','
                        ist >> p.Y();
                        ist >> ch;           // ')'

                        freezonelimit.Elem(freepi) = p;

                        ist >> ch;
                        while (ch != ';')
                        {
                            if (ch == '{')
                            {
                                LoadMatrixLine(ist, tempoldutofreearealimit.functorMethod, 2 * freepi - 1);

                                ist >> ch;           // '{'
                                LoadMatrixLine(ist, tempoldutofreearealimit.functorMethod, 2 * freepi);
                            }

                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    ist.putback(ch);
                }

                else if (string.Compare(buf, "elements") == 0)
                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        elements.Append(new Element2d(ELEMENT_TYPE.TRIG));

                        ist >> elements.Last().PNum(1);
                        ist >> ch;           // ','

                        if (ch == DefineConstants.COMMASIGN)
                        {
                            ist >> elements.Last().PNum(2);
                            ist >> ch;       // ','
                        }
                        if (ch == DefineConstants.COMMASIGN)
                        {
                            ist >> elements.Last().PNum(3);
                            ist >> ch;       // ','
                        }
                        if (ch == DefineConstants.COMMASIGN)
                        {
                            elements.Last().SetType(ELEMENT_TYPE.QUAD);
                            ist >> elements.Last().PNum(4);
                            ist >> ch;       // ','

                            // const Element2d & el = elements.Last();

                            /*
                             * orientations.Append (threeint(el.PNum(1), el.PNum(2), el.PNum(3)));
                             * orientations.Append (threeint(el.PNum(2), el.PNum(3), el.PNum(4)));
                             * orientations.Append (threeint(el.PNum(3), el.PNum(4), el.PNum(1)));
                             * orientations.Append (threeint(el.PNum(4), el.PNum(1), el.PNum(2)));
                             */
                        }

                        ist >> ch;
                        while (ch != ';')
                        {
                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    ist.putback(ch);
                }

                else if (string.Compare(buf, "orientations") == 0)

                {
                    ist >> ch;

                    while (ch == '(')
                    {
                        //        threeint a = threeint();
                        orientations.Append(new threeint());

                        ist >> orientations.Last().i1;
                        ist >> ch;           // ','
                        ist >> orientations.Last().i2;
                        ist >> ch;           // ','
                        ist >> orientations.Last().i3;
                        ist >> ch;           // ','

                        ist >> ch;
                        while (ch != ';')
                        {
                            ist >> ch;
                        }

                        ist >> ch;
                    }

                    ist.putback(ch);
                }

                else if (string.Compare(buf, "endrule") != 0)
                {
                    PrintSysError("Parser error, unknown token ", buf);
                }
            } while (!ist.eof() && string.Compare(buf, "endrule") != 0);

            oldutonewu.SetSize(2 * (points.Size() - noldp), 2 * noldp);
            oldutofreearea.SetSize(2 * freezone.Size(), 2 * noldp);
            oldutofreearealimit.SetSize(2 * freezone.Size(), 2 * noldp);

            for (i = 1; i <= oldutonewu.Height(); i++)
            {
                for (j = 1; j <= oldutonewu.Width(); j++)
                {
                    oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j);
                }
            }

            for (i = 1; i <= oldutofreearea.Height(); i++)
            {
                for (j = 1; j <= oldutofreearea.Width(); j++)
                {
                    oldutofreearea.Elem(i, j) = tempoldutofreearea.Elem(i, j);
                }
            }

            for (i = 1; i <= oldutofreearea.Height(); i++)
            {
                for (j = 1; j <= oldutofreearea.Width(); j++)
                {
                    oldutofreearealimit.Elem(i, j) = tempoldutofreearealimit.Elem(i, j);
                }
            }

            freesetinequ.SetSize(freezone.Size());


            {
                char        ok;
                int         minn;
                Array <int> pnearness = new Array <int>(noldp);

                for (i = 1; i <= pnearness.Size(); i++)
                {
                    pnearness.Elem(i) = 1000;
                }

                for (j = 1; j <= 2; j++)
                {
                    pnearness.Elem(GetPointNr(1, j)) = 0;
                }

                do
                {
                    ok = 1;

                    for (i = 1; i <= noldl; i++)
                    {
                        minn = 1000;
                        for (j = 1; j <= 2; j++)
                        {
                            minn = min2(minn, pnearness.Get(GetPointNr(i, j)));
                        }

                        for (j = 1; j <= 2; j++)
                        {
                            if (pnearness.Get(GetPointNr(i, j)) > minn + 1)
                            {
                                ok = 0;
                                pnearness.Elem(GetPointNr(i, j)) = minn + 1;
                            }
                        }
                    }
                } while (!ok);

                lnearness.SetSize(noldl);

                for (i = 1; i <= noldl; i++)
                {
                    lnearness.Elem(i) = 0;
                    for (j = 1; j <= 2; j++)
                    {
                        lnearness.Elem(i) += pnearness.Get(GetPointNr(i, j));
                    }
                }
            }

            oldutofreearea_i.SetSize(10);
            freezone_i.SetSize(10);

            for (i = 0; i < oldutofreearea_i.Size(); i++)
            {
                double lam1 = 1.0 / (i + 1);

                oldutofreearea_i[i] = new DenseMatrix(oldutofreearea.Height(), oldutofreearea.Width());
                DenseMatrix mati = *oldutofreearea_i[i];
                for (j = 0; j < oldutofreearea.Height(); j++)
                {
                    for (int k = 0; k < oldutofreearea.Width(); k++)
                    {
                        mati.functorMethod(j, k) = lam1 * oldutofreearea(j, k) + (1 - lam1) * oldutofreearealimit(j, k);
                    }
                }

                freezone_i[i] = new Array <Point2d> (freezone.Size());
                Array <Point2d> fzi = *freezone_i[i];
                for (int j = 0; j < freezone.Size(); j++)
                {
                    fzi[j] = freezonelimit[j] + lam1 * (freezone[j] - freezonelimit[j]);
                }
            }
        }
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public int ApplyRules(Array <Point2d> lpoints, Array <int> legalpoints, int maxlegalpoint, Array <INDEX_2> llines1, int maxlegalline, Array <Element2d> elements, Array <int> dellines, int tolerance, MeshingParameters mp)
        {
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer = NgProfiler::CreateTimer("meshing2::ApplyRules");
            NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(ApplyRules_timer);



            double maxerr   = 0.5 + 0.3 * tolerance;
            double minelerr = 2 + 0.5 * tolerance * tolerance;

            int noldlp = lpoints.Size();
            int noldll = llines1.Size();


            ArrayMem <int, 100> pused     = new ArrayMem <int, 100>((uint)maxlegalpoint);
            ArrayMem <int, 100> lused     = new ArrayMem <int, 100>((uint)maxlegalline);
            ArrayMem <int, 100> pnearness = new ArrayMem <int, 100>((uint)noldlp);
            ArrayMem <int, 100> lnearness = new ArrayMem <int, 100>(llines1.Size());

            ArrayMem <int, 20> pmap   = new ArrayMem <int, 20>();
            ArrayMem <int, 20> pfixed = new ArrayMem <int, 20>();
            ArrayMem <int, 20> lmap   = new ArrayMem <int, 20>();

            ArrayMem <Point2d, 100>   tempnewpoints = new ArrayMem <Point2d, 100>();
            ArrayMem <INDEX_2, 100>   tempnewlines  = new ArrayMem <INDEX_2, 100>();
            ArrayMem <int, 100>       tempdellines  = new ArrayMem <int, 100>();
            ArrayMem <Element2d, 100> tempelements  = new ArrayMem <Element2d, 100>();


            elements.SetSize(0);
            dellines.SetSize(0);

            testmode = debugparam.debugoutput;

                #if LOCDEBUG
            int loctestmode = testmode;

            if (loctestmode != 0)
            {
                (*testout) << "\n" << "\n" << "Check new environment" << "\n";
                (*testout) << "tolerance = " << tolerance << "\n";
                for (int i = 1; i <= lpoints.Size(); i++)
                {
                    (*testout) << "P" << i << " = " << lpoints.Get(i) << "\n";
                }
                (*testout) << "\n";
                for (int i = 1; i <= llines1.Size(); i++)
                {
                    (*testout) << "(" << llines1.Get(i).I1() << "-" << llines1.Get(i).I2() << ")" << "\n";
                }
            }
                #endif

            // check every rule

            int found = 0;             // rule number

            pnearness = 1000;

            for (int j = 0; j < 2; j++)
            {
                pnearness.Set(llines1[0][j], 0);
            }



            for (int cnt = 0; cnt < MAX_NEARNESS; cnt++)
            {
                bool ok = true;
                for (int i = 0; i < maxlegalline; i++)
                {
                    INDEX_2 hline = llines1[i];

                    int minn = min2(pnearness.Get(hline[0]), pnearness.Get(hline[1]));

                    for (int j = 0; j < 2; j++)
                    {
                        if (pnearness.Get(hline[j]) > minn + 1)
                        {
                            ok = false;
                            pnearness.Set(hline[j], minn + 1);
                        }
                    }
                }
                if (!ok)
                {
                    break;
                }
            }


            for (int i = 0; i < maxlegalline; i++)
            {
                lnearness[i] = pnearness.Get(llines1[i][0]) + pnearness.Get(llines1[i][1]);
            }


            // resort lines after lnearness
            Array <INDEX_2> llines          = new Array <INDEX_2>(llines1.Size());
            Array <int>     sortlines       = new Array <int>(llines1.Size());
            int[]           lnearness_class = new int[MAX_NEARNESS];

            for (int j = 0; j < MAX_NEARNESS; j++)
            {
                lnearness_class[j] = 0;
            }
            for (int i = 0; i < maxlegalline; i++)
            {
                if (lnearness[i] < MAX_NEARNESS)
                {
                    lnearness_class[lnearness[i]]++;
                }
            }

            int cumm = 0;
            for (int j = 0; j < MAX_NEARNESS; j++)
            {
                int hcnt = lnearness_class[j];
                lnearness_class[j] = cumm;
                cumm += hcnt;
            }

            for (int i = 0; i < maxlegalline; i++)
            {
                if (lnearness[i] < MAX_NEARNESS)
                {
                    llines[lnearness_class[lnearness[i]]]    = llines1[i];
                    sortlines[lnearness_class[lnearness[i]]] = i + 1;
                    lnearness_class[lnearness[i]]++;
                }
                else
                {
                    llines[cumm]    = llines1[i];
                    sortlines[cumm] = i + 1;
                    cumm++;
                }
            }

            for (int i = maxlegalline; i < llines1.Size(); i++)
            {
                llines[cumm]    = llines1[i];
                sortlines[cumm] = i + 1;
                cumm++;
            }

            for (int i = 0; i < maxlegalline; i++)
            {
                lnearness[i] = pnearness.Get(llines[i][0]) + pnearness.Get(llines[i][1]);
            }



            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static bool firsttime = true;
            // static int timers[100];
            // static int timers2[100];
            // static int timers3[100];
            if (ApplyRules_firsttime)
            {
                /*
                 * for (int ri = 0; ri < rules.Size(); ri++)
                 * timers[ri] = NgProfiler::CreateTimer (string("netrule ")+rules[ri]->Name());
                 * for (int ri = 0; ri < rules.Size(); ri++)
                 * timers2[ri] = NgProfiler::CreateTimer (string("netrule,mapped ")+rules[ri]->Name());
                 * for (int ri = 0; ri < rules.Size(); ri++)
                 * timers3[ri] = NgProfiler::CreateTimer (string("netrule,lines mapped ")+rules[ri]->Name());
                 */
                ApplyRules_firsttime = false;
            }

            lused = 0;
            pused = 0;


            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1 = NgProfiler::CreateTimer("meshing2::ApplyRules 1");
            NgProfiler.RegionTimer reg1 = new NgProfiler.RegionTimer(ApplyRules_timer1);


            for (int ri = 1; ri <= rules.Size(); ri++)
            {
                // NgProfiler::RegionTimer reg(timers[ri-1]);
                netrule rule = rules.Get(ri);

                #if LOCDEBUG
                if (loctestmode != 0)
                {
                    (*testout) << "Rule " << rule.Name() << "\n";
                }
                #endif

                if (rule.GetQuality() > tolerance)
                {
                    continue;
                }

                pmap.SetSize(rule.GetNP());
                lmap.SetSize(rule.GetNL());

                pmap = 0;
                lmap = 0;

                lused[0] = 1;
                lmap[0]  = 1;

                for (int j = 0; j < 2; j++)
                {
                    pmap.Elem(rule.GetLine 1[j]) = llines[0][j];
                    pused.Elem(llines[0][j])++;
                }



                int nlok = 2;


                bool ok = false;

                while (nlok >= 2)
                {
                    if (nlok <= rule.GetNOldL())

                    {
                        ok = false;

                        int maxline = (rule.GetLNearness(nlok) < MAX_NEARNESS) ? lnearness_class[rule.GetLNearness(nlok)] : maxlegalline;
                        // int maxline = maxlegalline;

                        while (!ok && lmap.Get(nlok) < maxline)
                        {
                            lmap.Elem(nlok)++;
                            int locli = lmap.Get(nlok);

                            if (lnearness.Get(locli) > rule.GetLNearness(nlok))
                            {
                                continue;
                            }
                            if (lused.Get(locli))
                            {
                                continue;
                            }


                            ok = true;

                            INDEX_2 loclin  = llines.Get(locli);
                            Vec2d   linevec = lpoints.Get(loclin.I2()) - lpoints.Get(loclin.I1());

                            if (rule.CalcLineError(nlok, linevec) > maxerr)
                            {
                                ok = false;
                #if LOCDEBUG
                                if (loctestmode != 0)
                                {
                                    (*testout) << "not ok pos1" << "\n";
                                }
                #endif
                                continue;
                            }

                            for (int j = 0; j < 2; j++)
                            {
                                int refpi = rule.GetLine(nlok)[j];

                                if (pmap.Get(refpi) != 0)
                                {
                                    if (pmap.Get(refpi) != loclin[j])
                                    {
                                        ok = false;
                #if LOCDEBUG
                                        if (loctestmode != 0)
                                        {
                                            (*testout) << "not ok pos2" << "\n";
                                        }
                #endif
                                        break;
                                    }
                                }
                                else
                                {
                                    if (rule.CalcPointDist(refpi, lpoints.Get(loclin[j])) > maxerr || !legalpoints.Get(loclin[j]) || pused.Get(loclin[j]))
                                    {
                                        ok = false;
                #if LOCDEBUG
                                        if (loctestmode != 0)
                                        {
                                            (*testout) << "nok pos3" << "\n";
                                            //if(rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr)
                                            //(*testout) << "r1" << endl;
                                            //if(!legalpoints.Get(loclin[j]))
                                            //(*testout) << "r2 legalpoints " << legalpoints << " loclin " << loclin << " j " << j << endl;
                                            //if(pused.Get(loclin[j]))
                                            //(*testout) << "r3" << endl;
                                        }
                #endif
                                        break;
                                    }
                                }
                            }
                        }

                        if (ok)
                        {
                            int     locli  = lmap.Get(nlok);
                            INDEX_2 loclin = llines.Get(locli);

                            lused.Elem(locli) = 1;
                            for (int j = 0; j < 2; j++)
                            {
                                pmap.Set(rule.GetLine nlok[j], loclin[j]);
Example #3
0
 ///
 public FrontLine(INDEX_2 al)
 {
     l         = al;
     lineclass = 1;
 }
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public void Delaunay(Mesh mesh, int domainnr, MeshingParameters mp)
        {
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer = NgProfiler::CreateTimer("Meshing2::Delaunay - total");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timerstart = NgProfiler::CreateTimer("Meshing2::Delaunay - start");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timerfinish = NgProfiler::CreateTimer("Meshing2::Delaunay - finish");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1 = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1a = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental a");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1b = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental b");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1c = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental c");
            //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
            //	static int timer1d = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental d");
            NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(Delaunay_timer);



            Console.Write("2D Delaunay meshing (in progress)");
            Console.Write("\n");


            BlockFillLocalH(mesh, mp);

            NgProfiler.StartTimer(Delaunay_timerstart);

            // do the delaunay


            // face bounding box:
            Box <3> bbox(Box <3> .EMPTY_BOX);

            for (int i = 0; i < adfront.GetNFL(); i++)
            {
                FrontLine line = adfront.GetLine(i);
                bbox.Add(Point <3> (adfront.GetPoint(line.L [0])));
                bbox.Add(Point <3> (adfront.GetPoint(line.L [1])));
            }

            for (int i = 0; i < mesh.LockedPoints().Size(); i++)
            {
                bbox.Add(new mesh.Point(mesh.LockedPoints [i]));
            }

            Console.Write("bbox = ");
            Console.Write(bbox);
            Console.Write("\n");

            // external point
            Vec <3> vdiag = bbox.PMax() - bbox.PMin();

            var          old_points = mesh.Points().Range();
            DelaunayTrig startel    = new DelaunayTrig();

            startel[0] = mesh.AddPoint(bbox.PMin() + Vec <3> (-8 * vdiag(0), -8 * vdiag(1), 0));
            startel[1] = mesh.AddPoint(bbox.PMin() + Vec <3> (+8 * vdiag(0), -8 * vdiag(1), 0));
            startel[2] = mesh.AddPoint(bbox.PMin() + Vec <3> (0, 8 * vdiag(1), 0));

            Box <3> hbox;

            hbox.Set(mesh[startel[0]]);
            hbox.Add(mesh[startel[1]]);
            hbox.Add(mesh[startel[2]]);
            Point <3> hp = mesh[startel[0]];

            hp(2) = 1;
            hbox.Add(hp);
            hp(2) = -1;
            hbox.Add(hp);
            BoxTree <3> searchtree(hbox);

            Array <DelaunayTrig> tempels = new Array <DelaunayTrig>();

            startel.CalcCenter(mesh);

            tempels.Append(startel);
            searchtree.Insert(startel.BoundingBox(), 0);

            Array <int>     closeels     = new Array <int>();
            Array <int>     intersecting = new Array <int>();
            Array <INDEX_2> edges        = new Array <INDEX_2>();



            // reorder points
            Array <PointIndex, PointIndex.BASE, PointIndex> mixed = new Array <PointIndex, PointIndex.BASE, PointIndex>(old_points.Size());

            int[] prims = { 11, 13, 17, 19, 23, 29, 31, 37 };
            int   prim;

            {
                int i = 0;
                while (old_points.Size() % prims[i] == 0)
                {
                    i++;
                }
                prim = prims[i];
            }

            foreach (PointIndex pi in old_points)
            {
                mixed[pi] = new PointIndex((prim * pi) % old_points.Size() + PointIndex.BASE);
            }

            NgProfiler.StopTimer(Delaunay_timerstart);
            NgProfiler.StartTimer(Delaunay_timer1);


            foreach (PointIndex i1 in old_points)
            {
                PointIndex i = mixed[i1];

                NgProfiler.StartTimer(Delaunay_timer1a);
                Point <3> newp = mesh[i];
                intersecting.SetSize(0);
                edges.SetSize(0);

                searchtree.GetIntersecting(newp, newp, closeels);
                // for (int jj = 0; jj < closeels.Size(); jj++)
                // for (int j = 0; j < tempels.Size(); j++)
                foreach (int j in closeels)
                {
                    if (tempels[j][0] < 0)
                    {
                        continue;
                    }
                    Point <3> c  = tempels[j].Center();
                    double    r2 = tempels[j].Radius2();

                    bool inside = Dist2(mesh[i], c) < r2;
                    if (inside)
                    {
                        intersecting.Append(j);
                    }
                }

                NgProfiler.StopTimer(Delaunay_timer1a);
                NgProfiler.StartTimer(Delaunay_timer1b);

                // find outer edges
                foreach (var j in intersecting)
                {
                    DelaunayTrig trig = tempels[j];
                    for (int k = 0; k < 3; k++)
                    {
                        int     p1   = trig[k];
                        int     p2   = trig[(k + 1) % 3];
                        INDEX_2 edge = new INDEX_2(p1, p2);
                        edge.Sort();
                        bool found = false;
                        for (int l = 0; l < edges.Size(); l++)
                        {
                            if (edges[l] == edge)
                            {
                                edges.Delete(l);
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            edges.Append(edge);
                        }
                    }
                }

                NgProfiler.StopTimer(Delaunay_timer1b);
                NgProfiler.StartTimer(Delaunay_timer1c);

                /*
                 * for (int j = intersecting.Size()-1; j >= 0; j--)
                 * tempels.Delete (intersecting[j]);
                 */
                foreach (int j in intersecting)
                {
                    searchtree.DeleteElement(j);
                    tempels[j][0] = -1;
                    tempels[j][1] = -1;
                    tempels[j][2] = -1;
                }

                NgProfiler.StopTimer(Delaunay_timer1c);
                NgProfiler.StartTimer(Delaunay_timer1d);

                foreach (var edge in edges)
                {
                    DelaunayTrig trig = new DelaunayTrig(edge[0], edge[1], i);
                    trig.CalcCenter(mesh);
                    tempels.Append(trig);
                    searchtree.Insert(trig.BoundingBox(), tempels.Size() - 1);
                }

                NgProfiler.StopTimer(Delaunay_timer1d);
            }

            NgProfiler.StopTimer(Delaunay_timer1);
            NgProfiler.StartTimer(Delaunay_timerfinish);

            foreach (DelaunayTrig trig in tempels)
            {
                if (trig[0] < 0)
                {
                    continue;
                }

                Point <3> c = Center(mesh[trig[0]], mesh[trig[1]], mesh[trig[2]]);
                if (!adfront.Inside(Point <2> (c(0), c(1))))
                {
                    continue;
                }

                Vec <3> n = Cross(mesh[trig[1]] - mesh[trig[0]], mesh[trig[2]] - mesh[trig[0]]);
                if (n(2) < 0)
                {
                    Swap(ref trig[1], ref trig[2]);
                }

                Element2d el = new Element2d(trig[0], trig[1], trig[2]);
                el.SetIndex(domainnr);
                mesh.AddSurfaceElement(el);
            }

            foreach (PointIndex pi in mesh.Points().Range())
            {
                *testout << pi << ": " << mesh[pi].Type() << "\n";
            }

            NgProfiler.StopTimer(Delaunay_timerfinish);
        }
Example #5
0
        public void UpdateCoarseGrid()
        {
            // cout << "UpdateCoarseGrid" << endl;
            // if (is_updated) return;

            NgMPI_Comm comm   = mesh.GetCommunicator();
            int        id     = comm.Rank();
            int        ntasks = comm.Size();

            if (ntasks == 1)
            {
                return;
            }

            Reset();
//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	  static int timer = NgProfiler::CreateTimer("UpdateCoarseGrid");
            NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(UpdateCoarseGrid_timer);


            (*testout) << "UPDATE COARSE GRID PARALLEL TOPOLOGY " << "\n";
            if (id == 0)
            {
                PrintMessage(1, "update parallel topology");
            }


            // UpdateCoarseGridGlobal();



            // MPI_Barrier (MPI_COMM_WORLD);

            MPI_Group MPI_GROUP_comm = new MPI_Group();
            MPI_Group MPI_LocalGroup = new MPI_Group();
            MPI_Comm  MPI_LocalComm  = new MPI_Comm();

            int[] process_ranks = { 0 };
            MPI_Comm_group(comm, MPI_GROUP_comm);
            MPI_Group_excl(MPI_GROUP_comm, 1, process_ranks, MPI_LocalGroup);
            MPI_Comm_create(comm, MPI_LocalGroup, MPI_LocalComm);

            if (id == 0)
            {
                return;
            }

            MeshTopology topology = mesh.GetTopology();

            Array <int> cnt_send = new Array <int>(ntasks - 1);


            // update new vertices after mesh-refinement
            if (mesh.mlbetweennodes.Size() > 0)
            {
                // cout << "UpdateCoarseGrid - vertices" << endl;
                int newnv = mesh.mlbetweennodes.Size();
                loc2distvert.ChangeSize(mesh.mlbetweennodes.Size());

                /*
                 *      for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++)
                 *            {
                 *              PointIndex v1 = mesh.mlbetweennodes[pi][0];
                 *              PointIndex v2 = mesh.mlbetweennodes[pi][1];
                 *              if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1)
                 *                    for (int dest = 1; dest < ntasks; dest++)
                 *                      if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2))
                 *                            SetDistantPNum(dest, pi);
                 *            }
                 */

                bool changed = true;
                while (changed)
                {
                    changed = false;

                    // build exchange vertices
                    cnt_send = 0;
                    foreach (PointIndex pi in mesh.Points().Range())
                    {
                        foreach (int dist in GetDistantPNums(pi - PointIndex.BASE))
                        {
                            cnt_send[dist - 1]++;
                        }
                    }
                    TABLE <int> dest2vert = new TABLE <int>(cnt_send);
                    foreach (PointIndex pi in mesh.Points().Range())
                    {
                        foreach (int dist in GetDistantPNums(pi - PointIndex.BASE))
                        {
                            dest2vert.Add(dist - 1, pi);
                        }
                    }


                    for (PointIndex pi = PointIndex.BASE; pi < newnv + PointIndex.BASE; pi++)
                    {
                        PointIndex v1 = mesh.mlbetweennodes[pi][0];
                        PointIndex v2 = mesh.mlbetweennodes[pi][1];
                        if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1)
                        {
                            // for (int dest = 1; dest < ntasks; dest++)
                            foreach (int dest in GetDistantPNums(v1 - PointIndex.BASE))
                            {
                                if (IsExchangeVert(dest, new netgen.PointIndex(v1)) && IsExchangeVert(dest, new netgen.PointIndex(v2)))
                                {
                                    cnt_send[dest - 1]++;
                                }
                            }
                        }
                    }

                    TABLE <int> dest2pair = new TABLE <int>(cnt_send);
                    // for (int dest = 1; dest < ntasks; dest++)
                    for (PointIndex pi = PointIndex.BASE; pi < newnv + PointIndex.BASE; pi++)
                    {
                        PointIndex v1 = mesh.mlbetweennodes[pi][0];
                        PointIndex v2 = mesh.mlbetweennodes[pi][1];
                        if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1)
                        {
                            foreach (int dest in GetDistantPNums(v1 - PointIndex.BASE))
                            {
                                if (IsExchangeVert(dest, new netgen.PointIndex(v1)) && IsExchangeVert(dest, new netgen.PointIndex(v2)))
                                {
                                    dest2pair.Add(dest - 1, pi);
                                }
                            }
                        }
                    }

                    cnt_send = 0;
                    int v1;
                    int v2;
                    for (PointIndex pi = PointIndex.BASE; pi < newnv + PointIndex.BASE; pi++)
                    {
                        PointIndex v1 = mesh.mlbetweennodes[pi][0];
                        PointIndex v2 = mesh.mlbetweennodes[pi][1];
                        if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1)
                        {
                            foreach (int dest in GetDistantPNums(v1 - PointIndex.BASE))
                            {
                                if (IsExchangeVert(dest, new netgen.PointIndex(v2)))
                                {
                                    cnt_send[dest - 1] += 2;
                                }
                            }
                        }
                    }

                    TABLE <int> send_verts = new TABLE <int>(cnt_send);

                    Array <int, PointIndex.BASE> loc2exchange = new Array <int, PointIndex.BASE>(mesh.GetNV());
                    for (int dest = 1; dest < ntasks; dest++)
                    {
                        if (dest != id)
                        {
                            loc2exchange = -1;
                            int cnt = 0;

                            /*
                             * for (PointIndex pi : mesh.Points().Range())
                             * if (IsExchangeVert(dest, pi))
                             *  loc2exchange[pi] = cnt++;
                             */
                            foreach (PointIndex pi in dest2vert[dest - 1])
                            {
                                loc2exchange[pi] = cnt++;
                            }

                            // for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++)
                            foreach (PointIndex pi in dest2pair[dest - 1])
                            {
                                PointIndex v1 = mesh.mlbetweennodes[pi][0];
                                PointIndex v2 = mesh.mlbetweennodes[pi][1];
                                if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1)
                                {
                                    if (IsExchangeVert(dest, new netgen.PointIndex(v1)) && IsExchangeVert(dest, new netgen.PointIndex(v2)))
                                    {
                                        send_verts.Add(dest - 1, loc2exchange[v1]);
                                        send_verts.Add(dest - 1, loc2exchange[v2]);
                                    }
                                }
                            }
                        }
                    }

                    TABLE <int> recv_verts = new TABLE <int>(ntasks - 1);
                    netgen.GlobalMembers.MyMPI_ExchangeTable(send_verts, recv_verts, MPI_TAG_MESH + 9, MPI_LocalComm);

                    for (int dest = 1; dest < ntasks; dest++)
                    {
                        if (dest != id)
                        {
                            loc2exchange = -1;
                            int cnt = 0;

                            /*
                             * for (PointIndex pi : mesh.Points().Range())
                             * if (IsExchangeVert(dest, pi))
                             *  loc2exchange[pi] = cnt++;
                             */
                            foreach (PointIndex pi in dest2vert[dest - 1])
                            {
                                loc2exchange[pi] = cnt++;
                            }

                            FlatArray <int> recvarray = recv_verts[dest - 1];
                            for (int ii = 0; ii < recvarray.Size(); ii += 2)
                            {
                                foreach (PointIndex pi in dest2pair[dest - 1])
                                {
                                    // for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++)
                                    PointIndex v1 = mesh.mlbetweennodes[pi][0];
                                    PointIndex v2 = mesh.mlbetweennodes[pi][1];
                                    if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1)
                                    {
                                        INDEX_2 re = new INDEX_2(recvarray[ii], recvarray[ii + 1]);
                                        INDEX_2 es = new INDEX_2(loc2exchange[v1], loc2exchange[v2]);
                                        if (es == re && !IsExchangeVert(dest, new netgen.PointIndex(pi)))
                                        {
                                            SetDistantPNum(dest, new netgen.PointIndex(pi));
                                            changed = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            Array <int> sendarray = new Array <int>();
            Array <int> recvarray = new Array <int>();

            // cout << "UpdateCoarseGrid - edges" << endl;

            // static int timerv = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex vertices");
//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	  static int timere = NgProfiler::CreateTimer("UpdateCoarseGrid - ex edges");
//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	  static int timerf = NgProfiler::CreateTimer("UpdateCoarseGrid - ex faces");


            NgProfiler.StartTimer(UpdateCoarseGrid_timere);


            int nfa = topology.GetNFaces();
            int ned = topology.GetNEdges();

            // build exchange vertices
            cnt_send = 0;
            foreach (PointIndex pi in mesh.Points().Range())
            {
                foreach (int dist in GetDistantPNums(pi - PointIndex.BASE))
                {
                    cnt_send[dist - 1]++;
                }
            }
            TABLE <int> dest2vert = new TABLE <int>(cnt_send);

            foreach (PointIndex pi in mesh.Points().Range())
            {
                foreach (int dist in GetDistantPNums(pi - PointIndex.BASE))
                {
                    dest2vert.Add(dist - 1, pi);
                }
            }

            // exchange edges
            cnt_send = 0;
            int v1;
            int v2;

            for (int edge = 1; edge <= ned; edge++)
            {
                topology.GetEdgeVertices(edge, ref v1, ref v2);
                for (int dest = 1; dest < ntasks; dest++)
                {
                    if (IsExchangeVert(dest, v1) && IsExchangeVert(dest, v2))
                    {
                        cnt_send[dest - 1] += 1;
                    }
                }
            }

            TABLE <int> dest2edge = new TABLE <int>(cnt_send);

            foreach (int v in cnt_send)
            {
                v *= 2;
            }
            TABLE <int> send_edges = new TABLE <int>(cnt_send);

            for (int edge = 1; edge <= ned; edge++)
            {
                topology.GetEdgeVertices(edge, ref v1, ref v2);
                for (int dest = 1; dest < ntasks; dest++)
                {
                    if (IsExchangeVert(dest, v1) && IsExchangeVert(dest, v2))
                    {
                        dest2edge.Add(dest - 1, edge);
                    }
                }
            }


            Array <int, PointIndex.BASE> loc2exchange = new Array <int, PointIndex.BASE>(mesh.GetNV());

            for (int dest = 1; dest < ntasks; dest++)
            {
                loc2exchange = -1;
                int cnt = 0;
                foreach (PointIndex pi in dest2vert[dest - 1])
                {
                    loc2exchange[pi] = cnt++;
                }

                foreach (int edge in dest2edge[dest - 1])
                {
                    topology.GetEdgeVertices(edge, ref v1, ref v2);
                    if (IsExchangeVert(dest, v1) && IsExchangeVert(dest, v2))
                    {
                        send_edges.Add(dest - 1, loc2exchange[v1]);
                        send_edges.Add(dest - 1, loc2exchange[v2]);
                    }
                }
            }

            // cout << "UpdateCoarseGrid - edges mpi-exchange" << endl;
            TABLE <int> recv_edges = new TABLE <int>(ntasks - 1);

            netgen.GlobalMembers.MyMPI_ExchangeTable(send_edges, recv_edges, MPI_TAG_MESH + 9, MPI_LocalComm);
            // cout << "UpdateCoarseGrid - edges mpi-exchange done" << endl;

            /*
             * for (int dest = 1; dest < ntasks; dest++)
             * {
             * auto ex2loc = dest2vert[dest-1];
             * FlatArray<int> recvarray = recv_edges[dest-1];
             *  for (int ii = 0; ii < recvarray.Size(); ii+=2)
             *    for (int edge : dest2edge[dest-1])
             *      {
             *            topology.GetEdgeVertices (edge, v1, v2);
             *            INDEX_2 re(ex2loc[recvarray[ii]],
             *               ex2loc[recvarray[ii+1]]);
             *            INDEX_2 es(v1, v2);
             *            if (es == re)
             *      SetDistantEdgeNum(dest, edge);
             *      }
             * }
             */

            for (int dest = 1; dest < ntasks; dest++)
            {
                var ex2loc = dest2vert[dest - 1];
                if (ex2loc.Size() == 0)
                {
                    continue;
                }

                INDEX_2_CLOSED_HASHTABLE <int> vert2edge = new INDEX_2_CLOSED_HASHTABLE <int>((uint)(2 * dest2edge[dest - 1].Size() + 10));
                foreach (int edge in dest2edge[dest - 1])
                {
                    topology.GetEdgeVertices(edge, ref v1, ref v2);
                    vert2edge.Set(new INDEX_2(v1, v2), edge);
                }

                FlatArray <int> recvarray = recv_edges[dest - 1];
                for (int ii = 0; ii < recvarray.Size(); ii += 2)
                {
                    INDEX_2 re = new INDEX_2(ex2loc[recvarray[ii]], ex2loc[recvarray[ii + 1]]);
                    if (vert2edge.Used(re))
                    {
                        SetDistantEdgeNum(dest, vert2edge.Get(re));
                    }
                }
            }



            NgProfiler.StopTimer(UpdateCoarseGrid_timere);

            // MPI_Barrier (MPI_LocalComm);

            // cout << "UpdateCoarseGrid - faces" << endl;
            if (mesh.GetDimension() == 3)
            {
                NgProfiler.StartTimer(UpdateCoarseGrid_timerf);
                Array <int> verts = new Array <int>();

                // exchange faces
                cnt_send = 0;
                for (int face = 1; face <= nfa; face++)
                {
                    topology.GetFaceVertices(face, verts);
                    for (int dest = 1; dest < ntasks; dest++)
                    {
                        if (dest != id)
                        {
                            if (IsExchangeVert(dest, verts[0]) && IsExchangeVert(dest, verts[1]) && IsExchangeVert(dest, verts[2]))
                            {
                                cnt_send[dest - 1]++;
                            }
                        }
                    }
                }

                TABLE <int> dest2face = new TABLE <int>(cnt_send);
                for (int face = 1; face <= nfa; face++)
                {
                    topology.GetFaceVertices(face, verts);
                    for (int dest = 1; dest < ntasks; dest++)
                    {
                        if (dest != id)
                        {
                            if (IsExchangeVert(dest, verts[0]) && IsExchangeVert(dest, verts[1]) && IsExchangeVert(dest, verts[2]))
                            {
                                dest2face.Add(dest - 1, face);
                            }
                        }
                    }
                }

                foreach (int c in cnt_send)
                {
                    c *= 3;
                }
                TABLE <int> send_faces = new TABLE <int>(cnt_send);
                Array <int, PointIndex.BASE> loc2exchange = new Array <int, PointIndex.BASE>(mesh.GetNV());
                for (int dest = 1; dest < ntasks; dest++)
                {
                    if (dest != id)
                    {
                        /*
                         * loc2exchange = -1;
                         * int cnt = 0;
                         * for (PointIndex pi : mesh.Points().Range())
                         * if (IsExchangeVert(dest, pi))
                         * loc2exchange[pi] = cnt++;
                         */
                        if (dest2vert[dest - 1].Size() == 0)
                        {
                            continue;
                        }

                        loc2exchange = -1;
                        int cnt = 0;
                        foreach (PointIndex pi in dest2vert[dest - 1])
                        {
                            loc2exchange[pi] = cnt++;
                        }

                        foreach (int face in dest2face[dest - 1])
                        {
                            topology.GetFaceVertices(face, verts);
                            if (IsExchangeVert(dest, verts[0]) && IsExchangeVert(dest, verts[1]) && IsExchangeVert(dest, verts[2]))
                            {
                                send_faces.Add(dest - 1, loc2exchange[verts[0]]);
                                send_faces.Add(dest - 1, loc2exchange[verts[1]]);
                                send_faces.Add(dest - 1, loc2exchange[verts[2]]);
                            }
                        }
                    }
                }

                // cout << "UpdateCoarseGrid - faces mpi-exchange" << endl;
                TABLE <int> recv_faces = new TABLE <int>(ntasks - 1);
                netgen.GlobalMembers.MyMPI_ExchangeTable(send_faces, recv_faces, MPI_TAG_MESH + 9, MPI_LocalComm);
                // cout << "UpdateCoarseGrid - faces mpi-exchange done" << endl;

                /*
                 * for (int dest = 1; dest < ntasks; dest++)
                 * if (dest != id)
                 *  {
                 *    loc2exchange = -1;
                 *    int cnt = 0;
                 *    for (PointIndex pi : dest2vert[dest-1])
                 *    loc2exchange[pi] = cnt++;
                 *
                 *    FlatArray<int> recvarray = recv_faces[dest-1];
                 *    for (int ii = 0; ii < recvarray.Size(); ii+=3)
                 *    for (int face : dest2face[dest-1])
                 *      {
                 *        topology.GetFaceVertices (face, verts);
                 *        INDEX_3 re(recvarray[ii], recvarray[ii+1], recvarray[ii+2]);
                 *        INDEX_3 es(loc2exchange[verts[0]], loc2exchange[verts[1]], loc2exchange[verts[2]]);
                 *        if (es == re)
                 *          SetDistantFaceNum(dest, face);
                 *      }
                 *  }
                 */


                for (int dest = 1; dest < ntasks; dest++)
                {
                    var ex2loc = dest2vert[dest - 1];
                    if (ex2loc.Size() == 0)
                    {
                        continue;
                    }

                    INDEX_3_CLOSED_HASHTABLE <int> vert2face = new INDEX_3_CLOSED_HASHTABLE <int>(2 * dest2face[dest - 1].Size() + 10);
                    foreach (int face in dest2face[dest - 1])
                    {
                        topology.GetFaceVertices(face, verts);
                        vert2face.Set(new INDEX_3(verts[0], verts[1], verts[2]), face);
                    }

                    FlatArray <int> recvarray = recv_faces[dest - 1];
                    for (int ii = 0; ii < recvarray.Size(); ii += 3)
                    {
                        INDEX_3 re = new INDEX_3(ex2loc[recvarray[ii]], ex2loc[recvarray[ii + 1]], ex2loc[recvarray[ii + 2]]);
                        if (vert2face.Used(re))
                        {
                            SetDistantFaceNum(dest, vert2face.Get(re));
                        }
                    }
                }



                /*
                 * Array<int,1> glob2loc;
                 *
                 * int maxface = 0;
                 * for (int face = 1; face <= nfa; face++)
                 * maxface = max (maxface, GetGlobalFaceNum (face));
                 *
                 * // glob2loc.SetSize (nfaglob);
                 * glob2loc.SetSize (maxface);
                 * glob2loc = -1;
                 *
                 * for (int loc = 1; loc <= nfa; loc++)
                 * glob2loc[GetGlobalFaceNum(loc)] = loc;
                 *
                 * cnt_send = 0;
                 * Array<int> verts;
                 * for (int face = 1; face <= nfa; face++)
                 * {
                 *  topology.GetFaceVertices (face, verts);
                 *  for (int dest = 1; dest < ntasks; dest++)
                 *    if (IsExchangeVert (dest, verts[0]) &&
                 *      IsExchangeVert (dest, verts[1]) &&
                 *      IsExchangeVert (dest, verts[2]))
                 *    {
                 *      cnt_send[dest-1]+=2;
                 *    }
                 * }
                 *
                 * TABLE<int> send_faces(cnt_send);
                 * for (int face = 1; face <= nfa; face++)
                 * {
                 *  topology.GetFaceVertices (face, verts);
                 *  for (int dest = 1; dest < ntasks; dest++)
                 *    {
                 *    if (IsExchangeVert (dest, verts[0]) &&
                 *        IsExchangeVert (dest, verts[1]) &&
                 *        IsExchangeVert (dest, verts[2]))
                 *      {
                 *        send_faces.Add (dest-1, GetGlobalFaceNum(face));
                 *        send_faces.Add (dest-1, face);
                 *      }
                 *    }
                 * }
                 * TABLE<int> recv_faces(ntasks-1);
                 * MyMPI_ExchangeTable (send_faces, recv_faces, MPI_TAG_MESH+8, MPI_LocalComm);
                 *
                 * for (int sender = 1; sender < ntasks; sender ++)
                 * if (id != sender)
                 *  {
                 *    FlatArray<int> recvarray = recv_faces[sender-1];
                 *
                 *    for (int ii = 0; ii < recvarray.Size(); )
                 *    {
                 *      int globf = recvarray[ii++];
                 *      int distf = recvarray[ii++];
                 *
                 *      if (globf <= maxface)
                 *        {
                 *          int locf = glob2loc[globf];
                 *          if (locf != -1)
                 *            SetDistantFaceNum (sender, locf);
                 *        }
                 *    }
                 *  }
                 */

                NgProfiler.StopTimer(UpdateCoarseGrid_timerf);
            }
            // cout << "UpdateCoarseGrid - done" << endl;

            is_updated = true;
        }
Example #6
0
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found:
        public int GetLocals(int fstind, Array <Point3d, PointIndex.BASE> locpoints, Array <MiniElement2d> locfaces, Array <PointIndex, PointIndex.BASE> pindex, Array <int> findex, INDEX_2_HASHTABLE <int> getconnectedpairs, float xh, float relh, ref int facesplit)
        {
            // static int timer = NgProfiler::CreateTimer ("AdFront3::GetLocals");
            // NgProfiler::RegionTimer reg (timer);


            if (hashon && faces.Size() < 500)
            {
                hashon = 0;
            }
            if (hashon && !hashcreated)
            {
                hashtable.Create();
                hashcreated = 1;
            }

            int        i;
            int        j;
            PointIndex pstind = new PointIndex();
            Point3d    midp   = new Point3d();
            Point3d    p0     = new Point3d();

            //  static Array<int, PointIndex::BASE> invpindex;

            Array <MiniElement2d> locfaces2 = new Array <MiniElement2d>(); //all local faces in radius xh
            Array <int>           locfaces3 = new Array <int>();           // all faces in outer radius relh
            Array <int>           findex2   = new Array <int>();

            locfaces2.SetSize(0);
            locfaces3.SetSize(0);
            findex2.SetSize(0);

            int cluster = faces.Get(fstind).cluster;

            pstind = faces.Get(fstind).Face().PNum(1);
            p0     = points[pstind].P();

            locfaces2.Append(faces.Get(fstind).Face());
            findex2.Append(fstind);


            Box3d b1 = new Box3d(p0 - new Vec3d(xh, xh, xh), p0 + new Vec3d(xh, xh, xh));

            if (hashon)
            {
                hashtable.GetLocals(locfaces2, findex2, fstind, p0, xh);
            }
            else
            {
                for (i = 1; i <= faces.Size(); i++)
                {
                    MiniElement2d face = faces.Get(i).Face();
                    if (faces.Get(i).cluster == cluster && faces.Get(i).Valid() && i != fstind)
                    {
                        Box3d b2 = new Box3d();
                        b2.SetPoint(points[face[0]].P());
                        b2.AddPoint(points[face[1]].P());
                        b2.AddPoint(points[face[2]].P());

                        if (b1.Intersect(b2) != 0)
                        {
                            locfaces2.Append(faces.Get(i).Face());
                            findex2.Append(i);
                        }
                    }
                }
            }

            //local faces for inner radius:
            for (i = 1; i <= locfaces2.Size(); i++)
            {
                MiniElement2d face = locfaces2.Get(i);
                Point3d       p1   = points[face[0]].P();
                Point3d       p2   = points[face[1]].P();
                Point3d       p3   = points[face[2]].P();

                midp = Center(p1, p2, p3);

                if (Dist2(midp, p0) <= relh * relh || i == 1)
                {
                    locfaces.Append(locfaces2.Get(i));
                    findex.Append(findex2.Get(i));
                }
                else
                {
                    locfaces3.Append(i);
                }
            }

            facesplit = locfaces.Size();


            //local faces for outer radius:
            for (i = 1; i <= locfaces3.Size(); i++)
            {
                locfaces.Append(locfaces2.Get(locfaces3.Get(i)));
                findex.Append(findex2.Get(locfaces3.Get(i)));
            }


            invpindex.SetSize(points.Size());
            for (i = 1; i <= locfaces.Size(); i++)
            {
                for (j = 1; j <= locfaces.Get(i).GetNP(); j++)
                {
                    PointIndex pi = locfaces.Get(i).PNum(j);
                    invpindex[pi] = -1;
                }
            }

            for (i = 1; i <= locfaces.Size(); i++)
            {
                for (j = 1; j <= locfaces.Get(i).GetNP(); j++)
                {
                    PointIndex pi = locfaces.Get(i).PNum(j);
                    if (invpindex[pi] == -1)
                    {
                        pindex.Append(pi);
                        locpoints.Append(points[pi].P());
                        invpindex[pi] = pindex.Size() - 1 + PointIndex.BASE;
                    }
                    // locfaces.Elem(i).PNum(j) = locpoints.Append (points[pi].P());
                    // }
                    // else
                    locfaces.Elem(i).PNum(j) = invpindex[pi];
                }
            }



            if (connectedpairs)
            {
                for (i = 1; i <= locpoints.Size(); i++)
                {
                    int pind = pindex.Get(i);
                    if (pind >= 1 && pind <= connectedpairs.Size())
                    {
                        for (j = 1; j <= connectedpairs.EntrySize(pind); j++)
                        {
                            int oi    = connectedpairs.Get(pind, j);
                            int other = invpindex.Get(oi);
                            if (other >= 1 && other <= pindex.Size() && pindex.Get(other) == oi)
                            {
                                // INDEX_2 coned(i, other);
                                // coned.Sort();
                                // (*testout) << "connected: " << locpoints.Get(i) << "-" << locpoints.Get(other) << endl;
                                getconnectedpairs.Set(INDEX_2.Sort(i, other), 1);
                            }
                        }
                    }
                }
            }


            /*
             * // add isolated points
             * for (i = 1; i <= points.Size(); i++)
             * if (points.Elem(i).Valid() && Dist (points.Elem(i).P(), p0) <= xh)
             *  {
             *    if (!invpindex.Get(i))
             *      {
             *            locpoints.Append (points.Get(i).P());
             *            pindex.Append (i);
             *            invpindex.Elem(i) = pindex.Size();
             *      }
             *  }
             */
            return(faces.Get(fstind).QualClass());
        }
Example #7
0
    public void EdgeSwapping(Mesh mesh, int usemetric)
    {
        if (!faceindex)
        {
            if (usemetric != 0)
            {
                PrintMessage(3, "Edgeswapping, metric");
            }
            else
            {
                PrintMessage(3, "Edgeswapping, topological");
            }

            for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)
            {
                EdgeSwapping(mesh, usemetric);

                if (multithread.terminate)
                {
                    throw new Exception("Meshing stopped");
                }
            }

            faceindex = 0;
            mesh.CalcSurfacesOfNode();
            return;
        }


//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	static int timer = NgProfiler::CreateTimer("EdgeSwapping 2D");
        NgProfiler.RegionTimer reg1 = new NgProfiler.RegionTimer(EdgeSwapping_timer);

//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	static int timerstart = NgProfiler::CreateTimer("EdgeSwapping 2D start");
        NgProfiler.StartTimer(EdgeSwapping_timerstart);


        Array <SurfaceElementIndex> seia = new Array <SurfaceElementIndex>();

        mesh.GetSurfaceElementsOfFace(faceindex, seia);

        for (int i = 0; i < seia.Size(); i++)
        {
            if (mesh[seia[i]].GetNP() != 3)
            {
                GenericImprove(mesh);
                return;
            }
        }

        int surfnr = mesh.GetFaceDescriptor(faceindex).SurfNr();

        Array <Neighbour>             neighbors = new Array <Neighbour>(mesh.GetNSE());
        INDEX_2_HASHTABLE <trionedge> other     = new INDEX_2_HASHTABLE <trionedge>(seia.Size() + 2);


        Array <char> swapped = new Array <char>(mesh.GetNSE());
        Array <int, PointIndex.BASE>    pdef   = new Array <int, PointIndex.BASE>(mesh.GetNP());
        Array <double, PointIndex.BASE> pangle = new Array <double, PointIndex.BASE>(mesh.GetNP());


        // int e;
        // double d;
        // Vec3d nv1, nv2;

        // double loch(-1);
        double[] minangle = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 };


        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d sel = mesh[seia[i]];
            for (int j = 0; j < 3; j++)
            {
                pangle[sel[j]] = 0.0;
            }
        }
        // pangle = 0;

        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d sel = mesh[seia[i]];
            for (int j = 0; j < 3; j++)
            {
                POINTTYPE typ = mesh[sel[j]].Type();
                if (typ == FIXEDPOINT || typ == EDGEPOINT)
                {
                    pangle[sel[j]] += Angle(mesh[sel[(j + 1) % 3]] - mesh[sel[j]], mesh[sel[(j + 2) % 3]] - mesh[sel[j]]);
                }
            }
        }

        // for (PointIndex pi = PointIndex::BASE;
        // pi < mesh.GetNP()+PointIndex::BASE; pi++)

        // pdef = 0;
        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d sel = mesh[seia[i]];
            for (int j = 0; j < 3; j++)
            {
                PointIndex pi = sel[j];
                if (mesh[pi].Type() == INNERPOINT || mesh[pi].Type() == SURFACEPOINT)
                {
                    pdef[pi] = -6;
                }
                else
                {
                    for (int j = 0; j < 8; j++)
                    {
                        if (pangle[pi] >= minangle[j])
                        {
                            pdef[pi] = -1 - j;
                        }
                    }
                }
            }
        }

        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d sel = mesh[seia[i]];
            for (int j = 0; j < 3; j++)
            {
                pdef[sel[j]]++;
            }
        }

        for (int i = 0; i < seia.Size(); i++)
        {
            for (int j = 0; j < 3; j++)
            {
                neighbors[seia[i]].SetNr(j, -1);
                neighbors[seia[i]].SetOrientation(j, 0);
            }
        }

        /*
         * Array<Vec3d> normals(mesh.GetNP());
         * for (i = 1; i <= mesh.GetNSE(); i++)
         * {
         * Element2d & hel = mesh.SurfaceElement(i);
         * if (hel.GetIndex() == faceindex)
         * for (k = 1; k <= 3; k++)
         * {
         * int pi = hel.PNum(k);
         * SelectSurfaceOfPoint (mesh.Point(pi), hel.GeomInfoPi(k));
         * int surfi = mesh.GetFaceDescriptor(faceindex).SurfNr();
         * GetNormalVector (surfi, mesh.Point(pi), normals.Elem(pi));
         * normals.Elem(pi) /= normals.Elem(pi).Length();
         * }
         * }
         */

        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d sel = mesh[seia[i]];

            for (int j = 0; j < 3; j++)
            {
                PointIndex pi1 = sel.PNumMod(j + 2);
                PointIndex pi2 = sel.PNumMod(j + 3);

                //	    double loch = mesh.GetH(mesh[pi1]);

                INDEX_2 edge = new INDEX_2(pi1, pi2);
                edge.Sort();

                if (mesh.IsSegment(pi1, pi2))
                {
                    continue;
                }

                /*
                 * if (segments.Used (edge))
                 * continue;
                 */
                INDEX_2 ii2 = new INDEX_2(pi1, pi2);
                if (other.Used(ii2))
                {
                    // INDEX_2 i2s(ii2);
                    // i2s.Sort();

                    int i2 = other.Get(ii2).tnr;
                    int j2 = other.Get(ii2).sidenr;

                    neighbors[seia[i]].SetNr(j, i2);
                    neighbors[seia[i]].SetOrientation(j, j2);
                    neighbors[i2].SetNr(j2, seia[i]);
                    neighbors[i2].SetOrientation(j2, j);
                }
                else
                {
                    other.Set(new INDEX_2(pi2, pi1), new trionedge(seia[i], j));
                }
            }
        }

        for (int i = 0; i < seia.Size(); i++)
        {
            swapped[seia[i]] = 0;
        }

        NgProfiler.StopTimer(EdgeSwapping_timerstart);



        int t    = 4;
        int done = 0;

        while (done == 0 && t >= 2)
        {
            for (int i = 0; i < seia.Size(); i++)
            {
                SurfaceElementIndex t1 = seia[i];

                if (mesh[t1].IsDeleted())
                {
                    continue;
                }

                if (mesh[t1].GetIndex() != faceindex)
                {
                    continue;
                }

                if (multithread.terminate)
                {
                    throw new Exception("Meshing stopped");
                }

                for (int o1 = 0; o1 < 3; o1++)
                {
                    bool should;


                    SurfaceElementIndex t2 = neighbors[t1].GetNr(o1);
                    int o2 = neighbors[t1].GetOrientation(o1);

                    if (t2 == -1)
                    {
                        continue;
                    }
                    if (swapped[t1] || swapped[t2])
                    {
                        continue;
                    }


                    PointIndex pi1 = mesh[t1].PNumMod(o1 + 1 + 1);
                    PointIndex pi2 = mesh[t1].PNumMod(o1 + 1 + 2);
                    PointIndex pi3 = mesh[t1].PNumMod(o1 + 1);
                    PointIndex pi4 = mesh[t2].PNumMod(o2 + 1);

                    PointGeomInfo gi1 = mesh[t1].GeomInfoPiMod(o1 + 1 + 1);
                    PointGeomInfo gi2 = mesh[t1].GeomInfoPiMod(o1 + 1 + 2);
                    PointGeomInfo gi3 = mesh[t1].GeomInfoPiMod(o1 + 1);
                    PointGeomInfo gi4 = mesh[t2].GeomInfoPiMod(o2 + 1);

                    bool allowswap = true;

                    Vec <3> auxvec1 = mesh[pi3] - mesh[pi4];
                    Vec <3> auxvec2 = mesh[pi1] - mesh[pi4];

                    allowswap = allowswap && ngsimd.GlobalMembers.fabs(1.0 - (auxvec1 * auxvec2) / (auxvec1.Length() * auxvec2.Length())) > 1e-4;

                    if (!allowswap)
                    {
                        continue;
                    }

                    // normal of new
                    Vec <3> nv1 = netgen.GlobalMembers.Cross(auxvec1, auxvec2);

                    auxvec1   = new mesh.Point(pi4) - new mesh.Point(pi3);
                    auxvec2   = new mesh.Point(pi2) - new mesh.Point(pi3);
                    allowswap = allowswap && ngsimd.GlobalMembers.fabs(1.0 - (auxvec1 * auxvec2) / (auxvec1.Length() * auxvec2.Length())) > 1e-4;


                    if (!allowswap)
                    {
                        continue;
                    }

                    Vec <3> nv2 = netgen.GlobalMembers.Cross(auxvec1, auxvec2);


                    // normals of original
                    Vec <3> nv3 = netgen.GlobalMembers.Cross(mesh[pi1] - mesh[pi4], mesh[pi2] - mesh[pi4]);
                    Vec <3> nv4 = netgen.GlobalMembers.Cross(mesh[pi2] - mesh[pi3], mesh[pi1] - mesh[pi3]);

                    nv3 *= -1;
                    nv4 *= -1;
                    nv3.Normalize();
                    nv4.Normalize();

                    nv1.Normalize();
                    nv2.Normalize();

                    Vec <3> nvp3, nvp4;
                    SelectSurfaceOfPoint(new mesh.Point(pi3), gi3);
                    GetNormalVector(surfnr, new mesh.Point(pi3), gi3, nvp3);

                    nvp3.Normalize();

                    SelectSurfaceOfPoint(new mesh.Point(pi4), gi4);
                    GetNormalVector(surfnr, new mesh.Point(pi4), gi4, nvp4);

                    nvp4.Normalize();



                    double critval = ngsimd.GlobalMembers.cos(DefineConstants.M_PI / 6); // 30 degree
                    allowswap = allowswap && (nv1 * nvp3 > critval) && (nv1 * nvp4 > critval) && (nv2 * nvp3 > critval) && (nv2 * nvp4 > critval) && (nvp3 * nv3 > critval) && (nvp4 * nv4 > critval);


                    double horder = netgen.GlobalMembers.Dist(new mesh.Point(pi1), new mesh.Point(pi2));

                    if (nv1.Length() > 1e-3 * horder * horder && nv2.Length() > 1e-3 * horder * horder && allowswap)
                    {
                        if (usemetric == 0)
                        {
                            int    e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4];
                            double d = netgen.GlobalMembers.Dist2(new mesh.Point(pi1), new mesh.Point(pi2)) - netgen.GlobalMembers.Dist2(new mesh.Point(pi3), new mesh.Point(pi4));

                            should = e >= t && (e > 2 || d > 0);
                        }
                        else
                        {
                            double loch = mesh.GetH(mesh[pi1]);
                            should = CalcTriangleBadness(new mesh.Point(pi4), new mesh.Point(pi3), new mesh.Point(pi1), metricweight, loch) + CalcTriangleBadness(new mesh.Point(pi3), new mesh.Point(pi4), new mesh.Point(pi2), metricweight, loch) < CalcTriangleBadness(new mesh.Point(pi1), new mesh.Point(pi2), new mesh.Point(pi3), metricweight, loch) + CalcTriangleBadness(new mesh.Point(pi2), new mesh.Point(pi1), new mesh.Point(pi4), metricweight, loch);
                        }

                        if (allowswap)
                        {
                            Element2d sw1 = new Element2d(pi4, pi3, pi1);
                            Element2d sw2 = new Element2d(pi3, pi4, pi2);

                            int legal1 = mesh.LegalTrig(mesh.SurfaceElement(t1)) + mesh.LegalTrig(mesh.SurfaceElement(t2));
                            int legal2 = mesh.LegalTrig(sw1) + mesh.LegalTrig(sw2);

                            if (legal1 < legal2)
                            {
                                should = true;
                            }
                            if (legal2 < legal1)
                            {
                                should = false;
                            }
                        }

                        if (should)
                        {
                            // do swapping !

                            done = 1;

                            mesh[t1].PNum(1) = pi1;
                            mesh[t1].PNum(2) = pi4;
                            mesh[t1].PNum(3) = pi3;

                            mesh[t2].PNum(1) = pi2;
                            mesh[t2].PNum(2) = pi3;
                            mesh[t2].PNum(3) = pi4;

                            mesh[t1].GeomInfoPi(1) = gi1;
                            mesh[t1].GeomInfoPi(2) = gi4;
                            mesh[t1].GeomInfoPi(3) = gi3;

                            mesh[t2].GeomInfoPi(1) = gi2;
                            mesh[t2].GeomInfoPi(2) = gi3;
                            mesh[t2].GeomInfoPi(3) = gi4;

                            pdef[pi1]--;
                            pdef[pi2]--;
                            pdef[pi3]++;
                            pdef[pi4]++;

                            swapped[t1] = 1;
                            swapped[t2] = 1;
                        }
                    }
                }
            }
            t--;
        }

        mesh.SetNextTimeStamp();
    }
Example #8
0
    public void CombineImprove(Mesh mesh)
    {
        if (!faceindex)
        {
            PrintMessage(3, "Combine improve");

            for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)
            {
                CombineImprove(mesh);

                if (multithread.terminate)
                {
                    throw new Exception("Meshing stopped");
                }
            }
            faceindex = 0;
            return;
        }


//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	static int timer = NgProfiler::CreateTimer("Combineimprove 2D");
        NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(CombineImprove_timer);

//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	static int timerstart = NgProfiler::CreateTimer("Combineimprove 2D start");
        NgProfiler.StartTimer(CombineImprove_timerstart);


//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	static int timerstart1 = NgProfiler::CreateTimer("Combineimprove 2D start1");
        NgProfiler.StartTimer(CombineImprove_timerstart1);



        // int i, j, k, l;
        // PointIndex pi;
        // SurfaceElementIndex sei;


        Array <SurfaceElementIndex> seia = new Array <SurfaceElementIndex>();

        mesh.GetSurfaceElementsOfFace(faceindex, seia);


        for (int i = 0; i < seia.Size(); i++)
        {
            if (mesh[seia[i]].GetNP() != 3)
            {
                return;
            }
        }



        int surfnr = 0;

        if (faceindex)
        {
            surfnr = mesh.GetFaceDescriptor(faceindex).SurfNr();
        }


        // PointIndex pi1, pi2;
        // MeshPoint p1, p2, pnew;
        double  bad1;
        double  bad2;
        Vec <3> nv;

        int np = mesh.GetNP();
        //int nse = mesh.GetNSE();

        TABLE <SurfaceElementIndex, PointIndex.BASE> elementsonnode = new TABLE <SurfaceElementIndex, PointIndex.BASE>(np);
        Array <SurfaceElementIndex> hasonepi  = new Array <SurfaceElementIndex>();
        Array <SurfaceElementIndex> hasbothpi = new Array <SurfaceElementIndex>();

        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d el = mesh[seia[i]];
            for (int j = 0; j < el.GetNP(); j++)
            {
                elementsonnode.Add(el[j], seia[i]);
            }
        }

        Array <bool, PointIndex.BASE> @fixed = new Array <bool, PointIndex.BASE>(np);

        @fixed = false;

        NgProfiler.StopTimer(CombineImprove_timerstart1);

        /*
         * for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)
         * {
         * INDEX_2 i2(mesh[si][0], mesh[si][1]);
         * fixed[i2.I1()] = true;
         * fixed[i2.I2()] = true;
         * }
         */

        for (int i = 0; i < seia.Size(); i++)
        {
            Element2d sel = mesh[seia[i]];
            for (int j = 0; j < sel.GetNP(); j++)
            {
                PointIndex pi1 = sel.PNumMod(j + 2);
                PointIndex pi2 = sel.PNumMod(j + 3);
                if (mesh.IsSegment(pi1, pi2))
                {
                    @fixed[pi1] = true;
                    @fixed[pi2] = true;
                }
            }
        }



        for (int i = 0; i < mesh.LockedPoints().Size(); i++)
        {
            @fixed[mesh.LockedPoints()[i]] = true;
        }



        Array <Vec <3>, PointIndex.BASE> normals = new Array <Vec <3>, PointIndex.BASE>(np);

        for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++)
        {
            if (elementsonnode[pi].Size())
            {
                Element2d hel = mesh[elementsonnode[pi][0]];
                for (int k = 0; k < 3; k++)
                {
                    if (hel[k] == pi)
                    {
                        SelectSurfaceOfPoint(mesh[pi], hel.GeomInfoPi(k + 1));
                        GetNormalVector(surfnr, mesh[pi], hel.GeomInfoPi(k + 1), normals[pi]);
                        break;
                    }
                }
            }
        }

        NgProfiler.StopTimer(CombineImprove_timerstart);

        for (int i = 0; i < seia.Size(); i++)
        {
            SurfaceElementIndex sei  = seia[i];
            Element2d           elem = mesh[sei];
            if (elem.IsDeleted())
            {
                continue;
            }

            for (int j = 0; j < 3; j++)
            {
                PointIndex pi1 = elem[j];
                PointIndex pi2 = elem[(j + 1) % 3];

                if (pi1 < PointIndex.BASE || pi2 < PointIndex.BASE)
                {
                    continue;
                }

                /*
                 * INDEX_2 i2(pi1, pi2);
                 * i2.Sort();
                 * if (segmentht.Used(i2))
                 * continue;
                 */

                bool debugflag = false;

                if (debugflag)
                {
                    (*testout) << "Combineimprove, face = " << faceindex << "pi1 = " << pi1 << " pi2 = " << pi2 << "\n";
                }

                /*
                 * // save version:
                 * if (fixed.Get(pi1) || fixed.Get(pi2))
                 * continue;
                 * if (pi2 < pi1) swap (pi1, pi2);
                 */

                // more general
                if (@fixed[pi2])
                {
                    netgen.GlobalMembers.Swap(ref pi1, ref pi2);
                }

                if (@fixed[pi2])
                {
                    continue;
                }

                double loch = mesh.GetH(mesh[pi1]);

                INDEX_2 si2 = new INDEX_2(pi1, pi2);
                si2.Sort();

                /*
                 * if (edgetested.Used (si2))
                 * continue;
                 * edgetested.Set (si2, 1);
                 */

                hasonepi.SetSize(0);
                hasbothpi.SetSize(0);

                for (int k = 0; k < elementsonnode[pi1].Size(); k++)
                {
                    Element2d el2 = mesh[elementsonnode[pi1][k]];

                    if (el2.IsDeleted())
                    {
                        continue;
                    }

                    if (el2[0] == pi2 || el2[1] == pi2 || el2[2] == pi2)
                    {
                        hasbothpi.Append(elementsonnode[pi1][k]);
                        nv = netgen.GlobalMembers.Cross(new Vec3d(mesh[el2[0]], mesh[el2[1]]), new Vec3d(mesh[el2[0]], mesh[el2[2]]));
                    }
                    else
                    {
                        hasonepi.Append(elementsonnode[pi1][k]);
                    }
                }


                Element2d hel = mesh[hasbothpi[0]];
                for (int k = 0; k < 3; k++)
                {
                    if (hel[k] == pi1)
                    {
                        SelectSurfaceOfPoint(mesh[pi1], hel.GeomInfoPi(k + 1));
                        GetNormalVector(surfnr, mesh[pi1], hel.GeomInfoPi(k + 1), nv);
                        break;
                    }
                }

                //	  nv = normals.Get(pi1);



                for (int k = 0; k < elementsonnode[pi2].Size(); k++)
                {
                    Element2d el2 = mesh[elementsonnode[pi2][k]];
                    if (el2.IsDeleted())
                    {
                        continue;
                    }

                    if (el2[0] == pi1 || el2[1] == pi1 || el2[2] == pi1)
                    {
                        ;
                    }
                    else
                    {
                        hasonepi.Append(elementsonnode[pi2][k]);
                    }
                }

                bad1 = 0;
                int illegal1 = 0;
                int illegal2 = 0;
                for (int k = 0; k < hasonepi.Size(); k++)
                {
                    Element2d el = mesh[hasonepi[k]];
                    bad1     += CalcTriangleBadness(mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch);
                    illegal1 += 1 - mesh.LegalTrig(el);
                }

                for (int k = 0; k < hasbothpi.Size(); k++)
                {
                    Element2d el = mesh[hasbothpi[k]];
                    bad1     += CalcTriangleBadness(mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch);
                    illegal1 += 1 - mesh.LegalTrig(el);
                }
                bad1 /= (hasonepi.Size() + hasbothpi.Size());

                MeshPoint p1 = mesh[pi1];
                MeshPoint p2 = mesh[pi2];

                MeshPoint pnew = new MeshPoint(p1);
                mesh[pi1] = pnew;
                mesh[pi2] = pnew;

                bad2 = 0;
                for (int k = 0; k < hasonepi.Size(); k++)
                {
                    Element2d el  = mesh[hasonepi[k]];
                    double    err = CalcTriangleBadness(mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch);
                    bad2 += err;

                    Vec <3> hnv = netgen.GlobalMembers.Cross(new Vec3d(mesh[el[0]], mesh[el[1]]), new Vec3d(mesh[el[0]], mesh[el[2]]));
                    if (hnv * nv < 0)
                    {
                        bad2 += 1e10;
                    }

                    for (int l = 0; l < 3; l++)
                    {
                        if ((normals[el[l]] * nv) < 0.5)
                        {
                            bad2 += 1e10;
                        }
                    }

                    illegal2 += 1 - mesh.LegalTrig(el);
                }
                bad2 /= hasonepi.Size();

                mesh[pi1] = p1;
                mesh[pi2] = p2;


                if (debugflag)
                {
                    (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << "\n";
                }


                bool should = (bad2 < bad1 && bad2 < 1e4);
                if (bad2 < 1e4)
                {
                    if (illegal1 > illegal2)
                    {
                        should = true;
                    }
                    if (illegal2 > illegal1)
                    {
                        should = false;
                    }
                }


                if (should)
                {
                    /*
                     * (*testout) << "combine !" << endl;
                     * (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl;
                     * (*testout) << "illegal1 = " << illegal1 << ", illegal2 = " << illegal2 << endl;
                     * (*testout) << "loch = " << loch << endl;
                     */

                    mesh[pi1] = pnew;
                    PointGeomInfo gi = new PointGeomInfo();
                    // bool gi_set(false);


                    Element2d el1p = new Element2d(null);
                    int       l    = 0;
                    while (mesh[elementsonnode[pi1][l]].IsDeleted() && l < elementsonnode.EntrySize(pi1))
                    {
                        l++;
                    }
                    if (l < elementsonnode.EntrySize(pi1))
                    {
                        el1p = mesh[elementsonnode[pi1][l]];
                    }
                    else
                    {
                        cerr << "OOPS!" << "\n";
                    }

                    for (l = 0; l < el1p.GetNP(); l++)
                    {
                        if (el1p[l] == pi1)
                        {
                            gi = el1p.GeomInfoPi(l + 1);
                            // gi_set = true;
                        }
                    }

                    // (*testout) << "Connect point " << pi2 << " to " << pi1 << "\n";
                    for (int k = 0; k < elementsonnode[pi2].Size(); k++)
                    {
                        Element2d el = mesh[elementsonnode[pi2][k]];
                        if (el.IsDeleted())
                        {
                            continue;
                        }
                        elementsonnode.Add(pi1, elementsonnode[pi2][k]);

                        bool haspi1 = false;
                        for (l = 0; l < el.GetNP(); l++)
                        {
                            if (el[l] == pi1)
                            {
                                haspi1 = true;
                            }
                        }
                        if (haspi1)
                        {
                            continue;
                        }

                        for (int l = 0; l < el.GetNP(); l++)
                        {
                            if (el[l] == pi2)
                            {
                                el[l] = pi1;
                                el.GeomInfoPi(l + 1) = gi;
                            }

                            @fixed[el[l]] = true;
                        }
                    }

                    /*
                     * for (k = 0; k < hasbothpi.Size(); k++)
                     * {
                     * cout << mesh[hasbothpi[k]] << endl;
                     * for (l = 0; l < 3; l++)
                     * cout << mesh[mesh[hasbothpi[k]][l]] << " ";
                     * cout << endl;
                     * }
                     */

                    for (int k = 0; k < hasbothpi.Size(); k++)
                    {
                        mesh[hasbothpi[k]].Delete();

                        /*
                         * for (l = 0; l < 4; l++)
                         * mesh[hasbothpi[k]][l] = PointIndex::BASE-1;
                         */
                    }
                }
            }
        }

        //  mesh.Compress();
        mesh.SetNextTimeStamp();
    }