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(); }
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; }