19 #ifdef gsHLBFGS_ENABLED
20 #include <gsHLBFGS/gsHLBFGS.h>
42 this->jacobian_into( u, result );
50 deriv_into(u, result);
54 result.resize(d, result.size()/d);
63 deriv_into(u, result);
67 const index_t numPts = u.cols();
74 for (
index_t p = 0; p < numPts; p++ ) {
75 resCol = result.col(p);
76 for (
index_t i = 0; i < d; i++ ) { tmp_div(p) += resCol(i * d + i); }
79 result.resize(1, numPts);
80 result = tmp_div.transpose();
91 const index_t parDim = u.rows();
92 const index_t tarDim = targetDim();
93 const index_t numPts = u.cols();
99 result.resize( parDim * tarDim, numPts );
101 for (
index_t p = 0; p < numPts; p++ )
103 for (
index_t j = 0; j<parDim; j++ )
106 delta(j) = (T)(0.00001);
107 uc.col(0) = u.col(p)+delta;
108 uc.col(1) = u.col(p)-delta;
109 delta(j) = (T)(0.00002);
110 uc.col(2) = u.col(p)+delta;
111 uc.col(3) = u.col(p)-delta;
113 this->eval_into(uc, ev );
114 tmp=(8*( ev.col(0)- ev.col(1)) + ev.col(3) - ev.col(2) ) / (T)(0.00012);
116 for (
index_t c=0; c<tarDim; ++c)
117 result(c*parDim+j,p)=tmp(c);
127 const int d = u.rows();
128 const int n = targetDim();
129 const int numPts = u.cols();
132 const int stride = d + d * ( d - 1 ) / 2;
133 result.resize( n * stride , numPts );
134 for (
int thisPt = 0; thisPt < numPts; thisPt++ )
137 for (
int j = 0; j < d; j++ )
141 tmp( j ) = (T)( 0.00001 );
142 uc.col( 0 ) = u.col( thisPt ) + tmp;
143 uc.col( 1 ) = u.col( thisPt ) ;
144 uc.col( 2 ) = u.col( thisPt ) - tmp;
145 this->eval_into( uc, ev );
146 for (
int k = 0; k < n; k++ )
147 result( k * stride + j, thisPt ) =
148 ( ev( k, 0 ) - (T)(2) * ev( k, 1 ) + ev( k, 2 ) ) / (T)( 0.0000000001 ) ;
150 for (
int l = j + 1; l < d; l++ )
152 tmp( l ) = (T)( 0.00001 );
153 ucm.col( 0 ) = u.col( thisPt ) + tmp;
154 ucm.col( 3 ) = u.col( thisPt ) - tmp;
155 tmp( l ) = (T)( -0.00001 );
156 ucm.col( 1 ) = u.col( thisPt ) + tmp;
157 ucm.col( 2 ) = u.col( thisPt ) - tmp;
159 this->eval_into( ucm, ev );
160 for (
int k = 0; k < n; k++ )
161 result( k * stride + r, thisPt ) =
162 ( ev( k, 0 ) - ev( k, 1 ) - ev( k, 2 ) + ev( k, 3 ) ) / (T)( 0.0000000004 ) ;
177 for (
int j = 0; j < d; j++ )
180 tmp( j, 0 ) = (T)( 0.0000000001 );
181 res.row( j ) = 16 * ( this->eval(u.colwise() + tmp ) +
182 this->eval(u.colwise() - tmp ) ) -
183 30 * ( this->eval( u ) );
184 tmp( j, 0 ) = (T)( 0.0000000002 );
185 res.row( j ) -= ( this->eval( u.colwise() - tmp ) +
186 this->eval( u.colwise() + tmp ) ) ;
187 res.row( j ) /= (T)( 0.0000000012 ) ;
195 const T accuracy,
const bool useInitialPoint)
const
197 result.resize(this->domainDim(), points.cols() );
199 for (
index_t i = 0; i!= points.cols(); ++i)
204 arg = this->parameterCenter();
207 const int iter = this->newtonRaphson(points.col(i), arg,
true, accuracy, 250);
210 gsWarn<<
"Inversion took "<<iter<<
" steps for "<< points.col(i).transpose() <<
" (result="<< arg.transpose()<<
")\n";
214 gsWarn<<
"Inversion failed for: "<< points.col(i).transpose() <<
" (result="<< arg.transpose()<<
")\n";
215 result.col(i).setConstant( std::numeric_limits<T>::infinity() );
244 const bool useInitialPoint)
const
247 result.resize(this->domainDim(), git.numPoints() );
249 auto cw = git.numPointsCwise();
257 arg = this->parameterCenter();
259 arg = (i%cw[0]==0 ? result.col(i-cw[0]) : result.col(i-1) );
261 iter = this->newtonRaphson(*git, arg,
true, accuracy, 500);
262 if (100 < iter)
gsInfo <<
" "<< iter;
265 gsWarn<<
"--- "<<i<<
" Inversion failed for: "<< git->transpose() <<
" ("
266 << (i%cw[0]==0 ? result.col(i-cw[0]) : result.col(i-1) ).transpose() <<
" -> " << arg.transpose()<<
" )\n";
271 result.col(i++) = arg;
277 template <
int mode,
int _Dim>
278 int gsFunction<T>::newtonRaphson_impl(
279 const gsVector<T> & value,
284 T damping_factor, T scale)
const
286 const index_t n = value.rows();
287 const bool squareJac = (n == domainDim());
290 "Input argument has wrong dimensions: "<< arg.transpose() );
293 gsMatrix<T,_Dim,(_Dim==-1?-1:1)> delta , residual;
294 gsMatrix<T,_Dim,_Dim>
jac;
299 GISMO_ASSERT( (arg.array()>=supp.col(0).array()).all() &&
300 (arg.array()<=supp.col(1).array()).all(),
301 "Initial point is outside the domain.\n point = "<<arg<<
"\n domain = "<<supp);
304 T rnorm[2]; rnorm[0]=1e100;
309 this->compute(arg,fd);
310 residual = (0==mode?fd.values[0]:fd.values[1]);
312 residual.noalias() = value - scale*residual;
313 rnorm[iter%2] = residual.norm();
315 if(rnorm[iter%2] <= accuracy)
323 jac = scale * fd.jacobian(0);
325 jac = scale * fd.hessian(0);
335 delta.noalias() = jac.partialPivLu().solve( residual );
337 delta.noalias() = jac.inverse() * residual;
340 delta.noalias() = jac.colPivHouseholderQr().solve(
341 gsMatrix<T>::Identity(n,n)) * residual;
343 const T rr = ( 1==iter ? (T)1.51 : rnorm[(iter-1)%2]/rnorm[iter%2] );
344 damping_factor = rr<1.5 ? math::max((T)0.1 + (rr/99),(rr-(T)0.5)*damping_factor) : math::min((T)1,rr*damping_factor);
361 arg += damping_factor * delta;
365 if ( delta.norm()<accuracy )
370 arg = arg.cwiseMax( supp.col(0) ).cwiseMin( supp.col(1) );
373 }
while (++iter <= max_loop);
375 gsWarn <<
"--- Newton method did not converge after "<< max_loop
376 <<
" iterations. Residual norm: "<< rnorm[max_loop%2]<<
".\n";
382 gsVector<T> gsFunction<T>::_argMinOnGrid(
index_t numpts)
const
385 gsMatrix<T> supp = this->support();
388 result = this->parameterCenter();
389 gsGridIterator<T,CUBE> pt(supp, numpts);
390 T val, mval = this->eval(result).value();
393 val = this->eval(*pt).value();
404 result.setZero( domainDim() );
410 gsVector<T> gsFunction<T>::_argMinNormOnGrid(
index_t numpts)
const
413 gsMatrix<T> supp = this->support();
416 result = this->parameterCenter();
417 gsGridIterator<T,CUBE> pt(supp, numpts);
418 T val, mval = this->eval(result).squaredNorm();
421 if ( (val = this->eval(*pt).squaredNorm())<mval )
431 result.setZero( domainDim() );
442 T damping_factor)
const
445 "Invalid input values:"<< value.rows()<<
"!="<<targetDim());
446 return newtonRaphson_impl<0>(value,arg,withSupport,accuracy,
447 max_loop,damping_factor);
454 T damping_factor)
const
456 GISMO_ASSERT(1==targetDim(),
"Currently argMin works for scalar functions");
460 if ( 0 != init.size() )
464 result = _argMinOnGrid(20);
467 #ifdef gsHLBFGS_ENABLED
468 gsFunctionAdaptor<T> fmin(*
this);
471 gsHLBFGS<T> solver( &fmin );
472 solver.options().setInt(
"MaxIterations",100);
473 solver.options().setInt(
"Verbose",0);
475 solver.solve(result);
476 result = solver.currentDesign();
484 newtonRaphson_impl<1,2>(gsVector<T>::Zero(dd), result,
true,
485 accuracy,max_loop,damping_factor,(T)1);
488 newtonRaphson_impl<1>(gsVector<T>::Zero(dd), result,
true,
489 accuracy,max_loop,damping_factor,(T)1);
510 const T accuracy)
const
513 for (
index_t i = 0; i!= xyz.rows(); ++i)
515 else if (i>k) ind[i-1]=i;
529 xyz = this->eval(uv);
536 index_t k,
const T accuracy)
const
539 for (
index_t i = 0; i!= xyz.rows(); ++i)
541 else if (i>k) ind[i-1]=i;
546 fc.invertPointGrid(git,uv,accuracy,
false);
547 xyz = this->eval(uv);
560 const index_t dim = supp.rows();
566 coordinates(d,0) = supp(d,1);
568 coordinates(d,0) = supp(d,0);
577 const index_t dim = supp.rows();
583 coordinates(d,0) = ( supp(d,1) + supp(d,0) ) / (T)(2);
585 coordinates(d,0) = supp(d,1);
587 coordinates(d,0) = supp(d,0);
592 template <
class T>
void
597 this->deriv2_into(u, secDers);
598 const index_t dim = this->domainDim();
599 const index_t nd = dim*(dim+1)/2;
600 result = util::secDerToHessian(secDers.middleCols(coord*nd,nd), dim);
603 template <
typename T,
short_t domDim,
short_t tarDim>
604 inline void computeAuxiliaryData(
const gsFunction<T> &src, gsMapData<T> & InOut,
int d,
int n)
607 const index_t numPts = InOut.points.cols();
615 if (InOut.side==boundary::none)
616 gsWarn<<
"Computing boundary normal without a valid side.\n";
620 const int dir = InOut.side.direction();
621 InOut.outNormals.resize(n,numPts);
623 if (tarDim!=-1 ? tarDim == domDim : n==d)
625 if ( 1==n ) { InOut.outNormals.setConstant(sgn);
return; }
628 typename gsMatrix<T,domDim,tarDim>::FirstMinorMatrixType minor;
632 for (
index_t p=0; p!=numPts; ++p)
634 const gsAsConstMatrix<T,domDim,tarDim> jacT(InOut.values[1].col(p).data(), d, n);
635 T detJacTcurr = jacT.determinant();
638 det_sgn = detJacTcurr < 0 ? -1 : 1;
644 gsMatrix<T> parameterCenter = src.parameterCenter(InOut.side);
645 T detJacTcurr = src.jacobian(parameterCenter).determinant();
646 det_sgn = detJacTcurr < 0 ? -1 : 1;
649 for (
index_t p=0; p!=numPts; ++p)
651 const gsAsConstMatrix<T,domDim,tarDim> jacT(InOut.values[1].col(p).data(), d, n);
657 T detJacTcurr = jacT.determinant();
658 det_sgn =
math::abs(detJacTcurr) < 1e-7 ? 0 :
659 ( detJacTcurr < 0 ? -1 : 1 );
662 gsMatrix<T> parameterCenter = src.parameterCenter(InOut.side);
663 detJacTcurr = src.jacobian(parameterCenter).determinant();
664 det_sgn = detJacTcurr < 0 ? -1 : 1;
667 GISMO_ENSURE(det_sgn!=0,
"Cannot find a non-zero Jacobian determinant.\n" << InOut.points);
669 T alt_sgn = sgn * det_sgn;
670 for (
int i = 0; i != n; ++i)
672 jacT.firstMinor(dir, i, minor);
673 InOut.outNormals(i,p) = alt_sgn * minor.determinant();
680 gsMatrix<T,domDim,domDim> metric(d,d);
681 gsVector<T,domDim> param(d);
682 typename gsMatrix<T,domDim,domDim>::FirstMinorMatrixType minor;
683 for (
index_t p=0; p!=numPts; ++p)
685 const gsAsConstMatrix<T,domDim,tarDim> jacT(InOut.values[1].col(p).data(), d, n);
686 metric= (jacT*jacT.transpose());
688 for (
int i = 0; i != (domDim!=-1?domDim:d); ++i)
690 metric.firstMinor(dir, i, minor);
691 param(i) = alt_sgn * minor.determinant();
694 InOut.outNormals.col(p)=jacT.transpose()*param/metric.determinant();
704 InOut.measures.resize(1,numPts);
705 if (InOut.side==boundary::none)
707 for (
index_t p = 0; p < numPts; ++p)
709 typename gsAsConstMatrix<T,domDim,tarDim>::Tr jac =
710 gsAsConstMatrix<T,domDim,tarDim>(InOut.values[1].col(p).data(),d, n).transpose();
711 if ( tarDim!=-1 ? tarDim == domDim : n==d )
712 InOut.measures(0,p) =
math::abs(jac.determinant());
714 InOut.measures(0,p) = math::sqrt( ( jac.transpose()*
jac )
721 const int dir = InOut.side.direction();
722 typename gsMatrix<T,domDim,tarDim>::ColMinorMatrixType minor;
723 InOut.measures.resize(1, numPts);
724 for (
index_t p = 0; p != numPts; ++p)
726 const gsAsConstMatrix<T,domDim,tarDim> jacT(InOut.values[1].col(p).data(), d, n);
727 InOut.measures.at(p) = jacT.row(!dir).norm();
737 InOut.jacInvTr.resize(d*n, numPts);
738 for (
index_t p=0; p!=numPts; ++p)
740 const gsAsConstMatrix<T,domDim,tarDim> jacT(InOut.values[1].col(p).data(), d, n);
742 if ( tarDim!=-1 ? tarDim == domDim : n==d )
743 gsAsMatrix<T,tarDim,domDim>(InOut.jacInvTr.col(p).data(), n, d)
744 = jacT.cramerInverse();
747 gsAsMatrix<T,tarDim,domDim>(InOut.jacInvTr.col(p).data(), n, d)
754 if ( (InOut.flags &
NEED_NORMAL) && (tarDim!=-1 ? tarDim == domDim+1 : n==d+1) )
756 typename gsMatrix<T,domDim,tarDim>::ColMinorMatrixType minor;
757 InOut.normals.resize(n, numPts);
759 for (
index_t p = 0; p != numPts; ++p)
761 const gsAsConstMatrix<T,domDim,tarDim> jacT(InOut.values[1].col(p).data(), d, n);
763 for (
int i = 0; i != tarDim; ++i)
765 jacT.colMinor(i, minor);
766 InOut.normals(i,p) = alt_sgn * minor.determinant();
781 InOut.fundForms.resize(d*d, numPts);
783 for (
index_t p=0; p!=numPts; ++p)
785 const gsAsConstMatrix<T,-1,tarDim> ddT(InOut.values[2].col(p).data(), sz, n);
786 const T nrm = InOut.normals.col(p).norm();
789 InOut.fundForms(0,p) = ddT.row(0).dot(InOut.normals.col(p)) / nrm;
790 InOut.fundForms(3,p) = ddT.row(1).dot(InOut.normals.col(p)) / nrm;
791 InOut.fundForms(1,p) = InOut.fundForms(2,p) =
792 ddT.row(2).dot(InOut.normals.col(p)) / nrm;
830 this->compute(InOut.
points, InOut);
833 std::pair<short_t, short_t> Dim = this->dimensions();
835 GISMO_ASSERT(Dim.first<10,
"Domain dimension is too big");
836 GISMO_ASSERT(Dim.first<=Dim.second,
"Singular map: target dimension is lower then the domain dimension");
837 switch (10 * Dim.second + Dim.first)
840 case 11: computeAuxiliaryData<T,1,1>(*
this, InOut, Dim.first, Dim.second);
break;
841 case 21: computeAuxiliaryData<T,1,2>(*
this, InOut, Dim.first, Dim.second);
break;
846 case 22: computeAuxiliaryData<T,2,2>(*
this, InOut, Dim.first, Dim.second);
break;
847 case 32: computeAuxiliaryData<T,2,3>(*
this, InOut, Dim.first, Dim.second);
break;
852 case 33: computeAuxiliaryData<T,3,3>(*
this, InOut, Dim.first, Dim.second);
break;
858 case 44: computeAuxiliaryData<T,4,4>(*
this, InOut, Dim.first, Dim.second);
break;
859 default: computeAuxiliaryData<T,-1,-1>(*
this, InOut, Dim.first, Dim.second);
break;
virtual void eval_component_into(const gsMatrix< T > &u, const index_t comp, gsMatrix< T > &result) const
Evaluate the function for component comp in the target dimension at points u into result...
Definition: gsFunction.hpp:551
Class defining an adaptor for using a gsFunction in an optimization problem.
#define GISMO_NO_IMPLEMENTATION
Definition: gsDebug.h:129
virtual void invertPoints(const gsMatrix< T > &points, gsMatrix< T > &result, const T accuracy=1e-6, const bool useInitialPoint=false) const
Definition: gsFunction.hpp:193
Gradient of the object.
Definition: gsForwardDeclarations.h:73
virtual void computeMap(gsMapData< T > &InOut) const
Computes map function data.
Definition: gsFunction.hpp:822
Matrix< Scalar, Dynamic, Dynamic > cramerInverse() const
Inversion for small matrices using Cramer's Rule.
Definition: gsMatrixAddons.h:55
virtual gsMatrix< T > parameterCenter() const
Returns a "central" point inside inside the parameter domain.
Definition: gsFunction.h:261
#define short_t
Definition: gsConfig.h:35
int newtonRaphson(const gsVector< T > &value, gsVector< T > &arg, bool withSupport=true, const T accuracy=1e-6, int max_loop=100, T damping_factor=1) const
Definition: gsFunction.hpp:437
bool parameter() const
Returns the parameter value (false=0=start, true=1=end) that corresponds to this side.
Definition: gsBoundary.h:128
Outward normal on the boundary.
Definition: gsForwardDeclarations.h:86
the gsMapData is a cache of pre-computed function (map) values.
Definition: gsFuncData.h:324
S give(S &x)
Definition: gsMemory.h:266
Second derivatives.
Definition: gsForwardDeclarations.h:80
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
void recoverPoints(gsMatrix< T > &xyz, gsMatrix< T > &uv, index_t k, const T accuracy=1e-6) const
Definition: gsFunction.hpp:509
A function from a n-dimensional domain to an m-dimensional image.
Definition: gsFunction.h:59
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
#define gsWarn
Definition: gsDebug.h:50
Normal vector of the object.
Definition: gsForwardDeclarations.h:85
Hessian matrix.
Definition: gsForwardDeclarations.h:82
#define gsInfo
Definition: gsDebug.h:43
void blockTransposeInPlace(const index_t colBlock)
Transposes in place the matrix block-wise. The matrix is.
Definition: gsMatrix.h:428
virtual void deriv_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluate derivatives of the function at points u into result.
Definition: gsFunction.hpp:87
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
gsFuncCoordinate< T > coord(const index_t c) const
Returns the scalar function giving the i-th coordinate of this function.
Definition: gsFunction.hpp:32
Second fundamental form.
Definition: gsForwardDeclarations.h:87
int sideOrientation(short_t s)
Definition: gsBoundary.h:1029
The density of the measure pull back.
Definition: gsForwardDeclarations.h:76
Enable optimizations based on the assumption that all evaluation points are in the same bezier domain...
Definition: gsForwardDeclarations.h:89
void div_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Computes for each point u a block of result containing the divergence matrix.
Definition: gsFunction.hpp:59
Provides definition of the FuncCoordinate class.
Value of the object.
Definition: gsForwardDeclarations.h:72
#define GISMO_UNUSED(x)
Definition: gsDebug.h:112
virtual gsMatrix< T > laplacian(const gsMatrix< T > &u) const
Evaluate the Laplacian at points u.
Definition: gsFunction.hpp:171
This is the main header file that collects wrappers of Eigen for linear algebra.
EIGEN_STRONG_INLINE abs_expr< E > abs(const E &u)
Absolute value.
Definition: gsExpressions.h:4488
gsMatrix< T > points
input (parametric) points
Definition: gsFuncData.h:348
virtual void deriv2_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluate second derivatives of the function at points u into result.
Definition: gsFunction.hpp:124
Gradient transformation matrix.
Definition: gsForwardDeclarations.h:77
Represents a certain component of a vector-valued function.
Definition: gsFuncCoordinate.h:34
Provides iteration over integer or numeric points in a (hyper-)cube.
This object is a cache for computed values from an evaluator.
Struct which represents a certain corner of a hyper-cube.
Definition: gsBoundary.h:291
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition: gsBoundary.h:113
virtual void jacobian_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Computes for each point u a block of result containing the Jacobian matrix.
Definition: gsFunction.hpp:47
EIGEN_STRONG_INLINE jac_expr< E > jac(const symbol_expr< E > &u)
The Jacobian matrix of a FE variable.
Definition: gsExpressions.h:4530