Пример #1
0
void MeshOptimize2d :: ImproveVolumeMesh (Mesh & mesh)
{

    if (!faceindex)
    {
        PrintMessage (3, "Smoothing");

        for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)
        {
            ImproveVolumeMesh (mesh);
            if (multithread.terminate)
                throw NgException ("Meshing stopped");
        }
        faceindex = 0;
        return;
    }



    static int timer = NgProfiler::CreateTimer ("MeshSmoothing 2D");
    NgProfiler::RegionTimer reg (timer);



    CheckMeshApproximation (mesh);

    int i, j, k;
    SurfaceElementIndex sei;

    Array<SurfaceElementIndex> seia;
    mesh.GetSurfaceElementsOfFace (faceindex, seia);

    bool mixed = 0;
    for (i = 0; i < seia.Size(); i++)
        if (mesh[seia[i]].GetNP() != 3)
        {
            mixed = 1;
            break;
        }


    int loci;
    double fact;
    bool moveisok;

    PointGeomInfo ngi;
    Point<3> origp;

    Vector x(3);

    Array<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP());

    Array<int, PointIndex::BASE> nelementsonpoint(mesh.GetNP());
    nelementsonpoint = 0;

    for (i = 0; i < seia.Size(); i++)
    {
        const Element2d & el = mesh[seia[i]];
        for (j = 0; j < el.GetNP(); j++)
            nelementsonpoint[el[j]]++;
    }


    TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonpoint(nelementsonpoint);
    for (i = 0; i < seia.Size(); i++)
    {
        const Element2d & el = mesh[seia[i]];
        for (j = 0; j < el.GetNP(); j++)
            elementsonpoint.Add (el[j], seia[i]);
    }


    JacobianPointFunction pf(mesh.Points(),mesh.VolumeElements());



//     Opti2SurfaceMinFunction surfminf(mesh);
//     Opti2EdgeMinFunction edgeminf(mesh);
//     Opti2SurfaceMinFunctionJacobian surfminfj(mesh);

    OptiParameters par;
    par.maxit_linsearch = 8;
    par.maxit_bfgs = 5;

    int np = mesh.GetNP();
    int ne = mesh.GetNE();

    BitArray badnodes(np);
    badnodes.Clear();

    for (i = 1; i <= ne; i++)
    {
        const Element & el = mesh.VolumeElement(i);
        double bad = el.CalcJacobianBadness (mesh.Points());
        if (bad > 1)
            for (j = 1; j <= el.GetNP(); j++)
                badnodes.Set (el.PNum(j));
    }


    bool printeddot = 0;
    char plotchar = '.';
    int modplot = 1;
    if (mesh.GetNP() > 1000)
    {
        plotchar = '+';
        modplot = 10;
    }
    if (mesh.GetNP() > 10000)
    {
        plotchar = 'o';
        modplot = 100;
    }
    int cnt = 0;


    Array<SurfaceElementIndex> locelements(0);
    Array<int> locrots(0);

    for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++)
    {
        if (mesh[pi].Type() != SURFACEPOINT)
            continue;

        if (multithread.terminate)
            throw NgException ("Meshing stopped");

        int surfi(-1);

        if(elementsonpoint[pi].Size() == 0)
            continue;

        Element2d & hel = mesh[elementsonpoint[pi][0]];

        if(hel.GetIndex() != faceindex)
            continue;

        cnt++;
        if (cnt % modplot == 0 && writestatus)
        {
            printeddot = 1;
            PrintDot (plotchar);
        }


        int hpi = 0;
        for (j = 1; j <= hel.GetNP(); j++)
            if (hel.PNum(j) == pi)
            {
                hpi = j;
                break;
            }
        PointGeomInfo gi1 = hel.GeomInfoPi(hpi);

        locelements.SetSize(0);
        locrots.SetSize (0);

        for (j = 0; j < elementsonpoint[pi].Size(); j++)
        {
            sei = elementsonpoint[pi][j];
            const Element2d & bel = mesh[sei];
            surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr();

            locelements.Append (sei);

            for (k = 1; k <= bel.GetNP(); k++)
                if (bel.PNum(k) == pi)
                {
                    locrots.Append (k);
                    break;
                }
        }


        double lh = mesh.GetH(mesh.Point(pi));
        par.typx = lh;

        pf.SetPointIndex(pi);

        x = 0;
        bool pok = (pf.Func (x) < 1e10);

        if (pok)
        {
            BFGS (x, pf, par);

            origp = mesh[pi];
            loci = 1;
            fact = 1;
            moveisok = false;


            //optimizer loop (if whole distance is not possible, move only a bit!!!!)
            while (loci <= 5 && !moveisok)
            {
                loci ++;
                mesh[pi](0) = origp(0) + x(0)*fact;
                mesh[pi](1) = origp(1) + x(1)*fact;
                mesh[pi](2) = origp(2) + x(2)*fact;
                fact = fact/2.;


                //cout << "origp " << origp << " newp " << mesh[pi];

                ngi = gi1;
                moveisok = (ProjectPointGI (surfi, mesh[pi], ngi) != 0);

                //cout << " projected " << mesh[pi] << endl;

                // point lies on same chart in stlsurface

                if (moveisok)
                {
                    for (j = 0; j < locelements.Size(); j++)
                        mesh[locelements[j]].GeomInfoPi(locrots[j]) = ngi;

                    //cout << "moved " << origp << " to " << mesh[pi] << endl;
                }
                else
                {
                    mesh[pi] = origp;
                }

            }
        }
        else
        {
            cout << "el not ok (point " << pi << ": " << mesh[pi] << ")" << endl;
        }
    }

    if (printeddot)
        PrintDot ('\n');

    CheckMeshApproximation (mesh);
    mesh.SetNextTimeStamp();
}
Пример #2
0
static real FindMinimum(This *t, cBounds *b, real *xmin, real fmin)
{
  Vector(real, hessian, NDIM*NDIM);
  Vector(real, gfree, NDIM);
  Vector(real, p, NDIM);
  Vector(real, tmp, NDIM);
  Vector(count, ifree, NDIM);
  Vector(count, ifix, NDIM);
  real ftmp, fini = fmin;
  ccount maxeval = t->neval + 50*t->ndim;
  count nfree, nfix;
  count dim, local;

  Clear(hessian, t->ndim*t->ndim);
  for( dim = 0; dim < t->ndim; ++dim )
    Hessian(dim, dim) = 1;

  /* Step 1: - classify the variables as "fixed" (sufficiently close
               to a border) and "free",
             - if the integrand is flat in the direction of the gradient
               w.r.t. the free dimensions, perform a local search. */

  for( local = 0; local < 2; ++local ) {
    bool resample = false;
    nfree = nfix = 0;
    for( dim = 0; dim < t->ndim; ++dim ) {
      if( xmin[dim] < b[dim].lower + (1 + fabsx(b[dim].lower))*QEPS ) {
        xmin[dim] = b[dim].lower;
        ifix[nfix++] = dim;
        resample = true;
      }
      else if( xmin[dim] > b[dim].upper - (1 + fabsx(b[dim].upper))*QEPS ) {
        xmin[dim] = b[dim].upper;
        ifix[nfix++] = Tag(dim);
        resample = true;
      }
      else ifree[nfree++] = dim;
    }

    if( resample ) fini = fmin = Sample(t, xmin);

    if( nfree == 0 ) goto releasebounds;

    Gradient(t, nfree, ifree, b, xmin, fmin, gfree);
    if( local || Length(nfree, gfree) > GTOL ) break;

    ftmp = LocalSearch(t, nfree, ifree, b, xmin, fmin, tmp);
    if( ftmp > fmin - (1 + fabsx(fmin))*RTEPS )
      goto releasebounds;
    fmin = ftmp;
    XCopy(xmin, tmp);
  }

  while( t->neval <= maxeval ) {

    /* Step 2a: perform a quasi-Newton iteration on the free
                variables only. */

    if( nfree > 0 ) {
      real plen, pleneps;
      real minstep;
      count i, mini = 0, minfix = 0;
      Point low;

      LinearSolve(t, nfree, hessian, gfree, p);
      plen = Length(nfree, p);
      pleneps = plen + RTEPS;

      minstep = INFTY;
      for( i = 0; i < nfree; ++i ) {
        count dim = Untag(ifree[i]);
        if( fabsx(p[i]) > EPS ) {
          real step;
          count fix;
          if( p[i] < 0 ) {
            step = (b[dim].lower - xmin[dim])/p[i];
            fix = dim;
          }
          else {
            step = (b[dim].upper - xmin[dim])/p[i];
            fix = Tag(dim);
          }
          if( step < minstep ) {
            minstep = step;
            mini = i;
            minfix = fix;
          }
        }
      }

      if( minstep*pleneps <= DELTA ) {
fixbound:
        ifix[nfix++] = minfix;

        if( mini < --nfree ) {
          creal diag = Hessian(mini, mini);

          Clear(tmp, mini);
          for( i = mini; i < nfree; ++i )
            tmp[i] = Hessian(i + 1, mini);

          for( i = mini; i < nfree; ++i ) {
            Move(&Hessian(i, 0), &Hessian(i + 1, 0), i);
            Hessian(i, i) = Hessian(i + 1, i + 1);
          }
          RenormalizeCholesky(t, nfree, hessian, tmp, diag);

          Move(&ifree[mini], &ifree[mini + 1], nfree - mini);
          Move(&gfree[mini], &gfree[mini + 1], nfree - mini);
        }
        continue;
      }

      low = LineSearch(t, nfree, ifree, p, xmin, fmin, tmp,
        Min(minstep, 1.), Min(minstep, 100.), Dot(nfree, gfree, p),
        RTEPS/pleneps, DELTA/pleneps, .2);

      if( low.dx > 0 ) {
        real fdiff;

        fmin = low.f;
        XCopy(xmin, tmp);

        Gradient(t, nfree, ifree, b, xmin, fmin, tmp);
        BFGS(t, nfree, hessian, tmp, gfree, p, low.dx);
        XCopy(gfree, tmp);

        if( fabsx(low.dx - minstep) < QEPS*minstep ) goto fixbound;

        fdiff = fini - fmin;
        fini = fmin;
        if( fdiff > (1 + fabsx(fmin))*FTOL ||
            low.dx*plen > (1 + Length(t->ndim, xmin))*FTOL ) continue;
      }
    }

    /* Step 2b: check whether freeing any fixed variable will lead
                to a reduction in f. */

releasebounds:
    if( nfix > 0 ) {
      real mingrad = INFTY;
      count i, mini = 0;
      bool repeat = false;

      Gradient(t, nfix, ifix, b, xmin, fmin, tmp);

      for( i = 0; i < nfix; ++i ) {
        creal grad = Sign(ifix[i])*tmp[i];
        if( grad < -RTEPS ) {
          repeat = true;
          if( grad < mingrad ) {
            mingrad = grad;
            mini = i;
          }
        }
      }

      if( repeat ) {
        gfree[nfree] = tmp[mini];
        ifree[nfree] = Untag(ifix[mini]);
        Clear(&Hessian(nfree, 0), nfree);
        Hessian(nfree, nfree) = 1;
        ++nfree;

        --nfix;
        Move(&ifix[mini], &ifix[mini + 1], nfix - mini);
        continue;
      }
    }

    break;
  }

  return fmin;
}