//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual double FuncDeriv(const Vector & x, const Vector & dir, double & deriv) const
        public override double FuncDeriv(Vector x, Vector dir, ref double deriv)
        {
            // from 2d:

            int       j;
            int       k;
            int       lpi;
            int       gpi;
            Vec <3>   n, vgrad;
            Point <3> pp1;
            Vec2d     g1   = new Vec2d();
            Vec2d     vdir = new Vec2d();
            double    badness;
            double    hbad;
            double    hderiv;

            vgrad   = 0;
            badness = 0;

            ld.meshthis.GetNormalVector(ld.surfi, ld.sp1, ld.gi1, n);

            // pp1 = sp1;
            //    pp1.Add2 (x.Get(1), t1, x.Get(2), t2);
            pp1 = ld.sp1 + x(0) * ld.t1.functorMethod + x(1) * ld.t2.functorMethod;

//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	  static Array<Point2d> pts2d;
            FuncDeriv_pts2d.SetSize(mesh.GetNP());

            deriv = 0;

            for (j = 1; j <= ld.locelements.Size(); j++)
            {
                lpi = ld.locrots.Get(j);
                Element2d bel = mesh[ld.locelements.Get(j)];

                gpi = bel.PNum(lpi);

                for (k = 1; k <= bel.GetNP(); k++)
                {
                    PointIndex pi = bel.PNum(k);
                    FuncDeriv_pts2d.Elem(pi) = new Point2d(ld.t1.functorMethod * (new mesh.Point(pi) - ld.sp1), ld.t2.functorMethod * (new mesh.Point(pi) - ld.sp1));
                }
                FuncDeriv_pts2d.Elem(gpi) = new Point2d(x(0), x(1));


                vdir = new Vec2d(dir(0), dir(1));

                hbad = bel.CalcJacobianBadnessDirDeriv(FuncDeriv_pts2d, lpi, vdir, ref hderiv);

                deriv   += hderiv;
                badness += hbad;
            }


            return(badness);
        }
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual double FuncGrad(const Vector & x, Vector & grad) const
        public override double FuncGrad(Vector x, ref Vector grad)
        {
            // from 2d:

            int       lpi;
            int       gpi;
            Vec <3>   n, vgrad;
            Point <3> pp1;
            Vec2d     g1   = new Vec2d();
            Vec2d     vdir = new Vec2d();
            double    badness;
            double    hbad;
            double    hderiv;

            vgrad   = 0;
            badness = 0;

            ld.meshthis.GetNormalVector(ld.surfi, ld.sp1, ld.gi1, n);

            pp1 = ld.sp1 + x(0) * ld.t1.functorMethod + x(1) * ld.t2.functorMethod;

            //  meshthis -> ProjectPoint (surfi, pp1);
            //  meshthis -> GetNormalVector (surfi, pp1, n);

//C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method:
//	  static Array<Point2d> pts2d;
            FuncGrad_pts2d.SetSize(mesh.GetNP());

            grad = 0;

            for (int j = 1; j <= ld.locelements.Size(); j++)
            {
                lpi = ld.locrots.Get(j);
                Element2d bel = mesh[ld.locelements.Get(j)];

                gpi = bel.PNum(lpi);

                for (int k = 1; k <= bel.GetNP(); k++)
                {
                    PointIndex pi = bel.PNum(k);
                    FuncGrad_pts2d.Elem(pi) = new Point2d(ld.t1.functorMethod * (new mesh.Point(pi) - ld.sp1), ld.t2.functorMethod * (new mesh.Point(pi) - ld.sp1));
                }
                FuncGrad_pts2d.Elem(gpi) = new Point2d(x(0), x(1));


                for (int k = 1; k <= 2; k++)
                {
                    if (k == 1)
                    {
                        vdir = new Vec2d(1, 0);
                    }
                    else
                    {
                        vdir = new Vec2d(0, 1);
                    }

                    hbad = bel.CalcJacobianBadnessDirDeriv(FuncGrad_pts2d, lpi, vdir, ref hderiv);

                    grad(k - 1) += hderiv;
                    if (k == 1)
                    {
                        badness += hbad;
                    }
                }
            }


            /*
             * vgrad.Add (-(vgrad * n), n);
             *
             * grad.Elem(1) = vgrad * t1;
             * grad.Elem(2) = vgrad * t2;
             */
            return(badness);
        }
Beispiel #3
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();
    }