272#define SMALL DBL_EPSILON
273#define EPMACH DBL_MIN
288 template<
class Gr
id,
class Equation,
class VariableSet,
class Spaces>
339 typedef enum {initial=1,intermediate=2,solution=3,
final=4} OutputMode;
342 std::vector<double> *fx, *dx;
343 double normF, normDx, normDxBar, lambda, theta;
347 typedef typename Grid::LeafGridView LeafView;
350 #define THETA_MAX 0.5
351 #define MAX_ITER_DEFAULT 50
352 #define LAMBDA_START_DEFAULT 1.0e-2
353 #define LAMBDA_START_EXTREMELY_DEFAULT 1.0e-4
354 #define LAMBDA_MIN_DEFAULT 1.0e-4
355 #define LAMBDA_MIN_EXTREMELY_DEFAULT 1.0e-8
363 maximumNoIterations = 50;
366 errorStream = &(std::cerr);
367 monitorStream = &(std::cout);
371 outFilePrefix =
"iter_";
372 scale =
new std::vector<double>(0);
473 void setOutFilePrefix(
const std::string& outFilePrefix_ ) { outFilePrefix=outFilePrefix_; }
482 if (scale_) scale=scale_;
508 double lambda, lambdaNew, mue, normFk, normFkPlusOne, normDxkMinusOne,
509 normDxBar, normDx, theta, s;
511 int const nvars = Equation::AnsatzVars::noOfVariables;
512 int const n = variableSet.degreesOfFreedom(0,nvars);
513 int iterationCounter=0, fail=0;
515 std::vector<double> dxdata(n), dxBar(n), xThresh(n), w(n), xData(n);
516 std::vector<double> *fxk =
new std::vector<double>(n);
517 int noRHSComputations=0, noJacobianComputations=0, noLinearSolverIterations=0;
518 struct NleqData *data =
new struct NleqData;
521 std::cerr << std::endl <<
" could not allocate struct data" << std::endl;
525 data->mode = initial;
527 if ( monitorLevel > 0 )
528 *monitorStream << std::endl <<
" nleqErr - Version 2.0" << std::endl;
548 if (data)
delete data;
552 LeafView leafGridView = gridManager.
grid().leafGridView();
553 Dune::InverseOperatorResult res;
555 Assembler assembler(spaces);
559 int const neq = Equation::TestVars::noOfVariables;
560 size_t nnz = assembler.nnz(0,neq,0,nvars,
false);
561 if ( monitorLevel > 0 )
562 *monitorStream <<
" nvars=" << nvars <<
", neq=" << neq <<
", nnz=" << nnz <<
"\n";
563 typedef typename VariableSet::template CoefficientVectorRepresentation<0,neq>::type CoefficientVectors;
564 CoefficientVectors theSolution(VariableSet::template CoefficientVectorRepresentation<0,neq>::init(spaces));
567 x->write(xData.begin());
568 if ( monitorLevel > 1 )
569 *monitorStream << std::endl
570 <<
"| Newton iteration |iterative linear solver|" << std::endl
571 <<
" iter normScl(dx) norm(fk) lambda res niter rate "
572 << std::endl << std::endl;
573 normDx = 0.0; normDxBar = 0.0;
574 w=xData; xThresh=*scale;
579 nleqErrRescale(*scale,xData,w,xThresh);
580 if ( iterationCounter>0 )
583 normDxkMinusOne = nleqScaledNorm2(dxdata,*scale);
584 normDxBar = nleqScaledNorm2(dxBar,*scale);
586 if (statistics) timer.start(
"time for assemble");
587 assembler.assemble(linearization(eq,*x));
588 if (statistics) timer.stop(
"time for assemble");
589 noRHSComputations++; noJacobianComputations++;
590 CoefficientVectors fx(assembler.rhs());
591 fx.write(fxk->begin());
592 normFk = nleqNorm2(*fxk);
596 double iteEps = xtol*1.0e-2;
597 typedef typename VariableSet::template CoefficientVectorRepresentation<0,neq>::type LinearSpace;
598 if (statistics) timer.start(
"time for preconditioner setup");
600 if (statistics) timer.stop(
"time for preconditioner setup");
601 Dune::BiCGSTABSolver<LinearSpace> cg(A,iluk,iteEps,iteSteps,0);
603 if (statistics) timer.start(
"time for linear solver BiCGSTAB");
604 cg.apply(theSolution,fx,res);
605 if (statistics) timer.stop(
"time for linear solver BiCGSTAB");
606 noLinearSolverIterations += res.iterations;
607 if ( !res.converged ) { info.
returnCode=4;
break; };
608 dx.data = theSolution.data;
609 dx.write(dxdata.begin());
610 normDx = nleqScaledNorm2(dxdata,*scale);
611 if ( monitorLevel > 1 )
612 nleqErrMonitor(iterationCounter,normDx,normFk,lambda,
' ',res);
613 if ( normDx <= xtol )
615 data->normF = normFk; data->normDx = normDx;
616 data->normDxBar = normDxBar; data->lambda = lambda;
617 if (statistics) timer.start(
"time for writing output data");
618 nleqDataOut(iterationCounter,leafGridView,*x,data);
619 if (statistics) timer.stop(
"time for writing output data");
620 *x += dx; iterationCounter++;
623 if ( iterationCounter>0 )
625 for (
int i=0;i<n;i++) w[i] = dxBar[i]-dxdata[i];
626 s = nleqScaledNorm2(w,*scale);
627 mue = (normDxkMinusOne*normDxBar)/(s*normDx) * lambda;
632 bool doCorrectorLoop=
true;
635 if ( lambda < lambdaMin ) { info.
returnCode=3;
break; };
638 xkPlusOne=*x; xkPlusOne += tmp;
639 if (statistics) timer.start(
"time for assemble");
640 assembler.assemble(linearization(eq,xkPlusOne),assembler.RHS);
641 if (statistics) timer.stop(
"time for assemble");
643 CoefficientVectors fxq(assembler.rhs());
644 fxq.write(fxk->begin());
646 normFkPlusOne = nleqNorm2(*fxk);
649 if (statistics) timer.start(
"time for linear solver BiCGSTAB");
650 cg.apply(theSolution,fxq,res);
651 if (statistics) timer.stop(
"time for linear solver BiCGSTAB");
652 noLinearSolverIterations += res.iterations;
653 if ( !res.converged ) { info.
returnCode=5;
break; };
654 tmp.data = theSolution.data;
655 tmp.write(dxBar.begin());
656 normDxBar = nleqScaledNorm2(dxBar,*scale);
657 if ( monitorLevel > 1 )
658 nleqErrMonitor(iterationCounter,normDxBar,normFkPlusOne,lambda,
'*',res);
659 theta = normDxBar/normDx;
661 for (
int i=0;i<n;i++) w[i] = dxBar[i]-s*dxdata[i];
662 mue = (0.5*normDx*lambda*lambda) / nleqScaledNorm2(w,*scale);
663 if ( ( !restricted && theta >= 1.0 ) ||
664 ( restricted && theta > 1.0-lambda/4.0) )
666 lambdaNew =
std::min(mue,0.5*lambda);
667 if ( lambda <= lambdaMin ) lambda = lambdaNew;
668 else lambda =
std::max(lambdaNew,lambdaMin);
673 if ( lambda==1.0 && lambdaNew==1.0 )
675 if ( normDxBar <= xtol )
684 if( lambdaNew >= 4.0*lambda && !reducted )
686 lambda=lambdaNew;
continue;
689 doCorrectorLoop=
false;
691 while ( doCorrectorLoop );
693 data->normF = normFk; data->normDx = normDx;
694 data->normDxBar = normDxBar; data->lambda = lambda;
695 if (statistics) timer.start(
"time for writing output data");
696 nleqDataOut(iterationCounter,leafGridView,*x,data);
697 if (statistics) timer.stop(
"time for writing output data");
698 data->mode = intermediate;
700 x->write(w.begin()); *x=xkPlusOne; x->write(xData.begin());
703 normFk = normFkPlusOne;
705 while ( iterationCounter <= maximumNoIterations && info.
returnCode == 2 );
707 data->normF = normFkPlusOne; data->normDx = normDx;
708 data->normDxBar = normDxBar; data->lambda = lambda;
709 data->mode = ( info.
returnCode==0 ? solution : final );
710 if (statistics) timer.start(
"time for writing output data");
711 nleqDataOut(iterationCounter,leafGridView,*x,data);
712 if (statistics) timer.stop(
"time for writing output data");
714 if ( (monitorLevel > 0) && (info.
returnCode==0) )
715 *monitorStream << std::endl <<
716 " solution of nonlinear system obtained within " << iterationCounter <<
" Newton iteration steps" <<
717 std::endl <<
" using " << noJacobianComputations <<
" Jacobian assemblies and " << noRHSComputations <<
718 " function assemblies" << std::endl;
720 if ( (errorLevel > 0) && (info.
returnCode != 0) )
725 *errorStream << std::endl <<
726 " Error - Maximum allowed number of iterations exceeded" << std::endl;
729 *errorStream << std::endl <<
730 " Error - no convergence, damping factor became too small" << std::endl;
733 *errorStream << std::endl <<
734 " Error - no convergence of iterative linear solver for dx computation" <<
738 *errorStream << std::endl <<
739 " Error - no convergence of iterative linear solver for dxq computation" << std::endl;
742 *errorStream << std::endl <<
" Error, code=" << info.
returnCode <<
743 ", subCode=" << fail << std::endl;
758 if (statistics) std::cout << timer << std::endl;
763 void nleqErrRescale(std::vector<double>& scale, std::vector<double>
const & x,
764 std::vector<double>
const& xa, std::vector<double>
const& xThresh)
766 int const n=scale.size();
767 assert ( (x.size()==n) && (xa.size()==n) && (xThresh.size()==n) );
768 for (
int i=0;i<n;i++)
772 void nleqErrMonitor(
int const iterationCounter,
double const normDx,
773 double const normF,
double const lambda,
char const indicator,
774 Dune::InverseOperatorResult res)
776 *monitorStream <<
" " << std::setw(4) << iterationCounter <<
" " << std::setw(1) << indicator <<
" "
777 << std::setw(12) << std::setprecision(5) << std::scientific << normDx <<
" "
778 << std::setw(12) << std::setprecision(5) << normF <<
" ";
779 monitorStream->unsetf(std::ios::fixed | std::ios::scientific);
780 *monitorStream << std::setw(8) << std::fixed << lambda <<
" " << std::setw(4)
781 << (res.converged?
"conv":
"fail") <<
" " << std::setw(5) << res.iterations <<
" "
782 << std::setw(8) << res.conv_rate << std::endl;
783 monitorStream->unsetf(std::ios::fixed | std::ios::scientific);
786 double nleqScaledNorm2(std::vector<double>
const& v, std::vector<double>
const& scale)
788 int const n=v.size();
789 assert ( scale.size()==n );
790 double t, rval = 0.0;
791 for (
int i=0;i<n;i++) {t=v[i]/scale[i]; rval += t*t;};
792 return sqrt( rval / (
double)n );
795 double nleqNorm2(std::vector<double>
const& v)
797 int const n=v.size();
799 for (
int i=0;i<n;i++) rval += v[i]*v[i];
800 return sqrt( rval / (
double)n );
803 void nleqDataOut(
int const iterationCounter, LeafView
const leafGridView, VariableSetRepresentation
const x,
804 struct NleqData
const *data)
806 if ( (dataLevel==
none) || ( (dataLevel==
minimum) && (data->mode==intermediate) ) )
811 std::ostringstream fname;
812 fname << outFilePrefix;
815 fname.setf(std::ios_base::right,std::ios_base::adjustfield);
816 fname << iterationCounter;
818 writeVTKFile(x,fname.str(),IoOptions());
821 int nleqParcheckAndPrint(
int const n)
822 #define TOLMIN EPMACH*1.0e2
823 #define TOLMAX 1.0e-1
825 double large = 1.0/
SMALL, small =
SMALL, defaultScale;
829 *errorStream << std::endl <<
" Error - Number of Equations/unknowns must be >0" << std::endl;
835 *errorStream << std::endl <<
" Error - xtol must be positive" << std::endl;
844 *errorStream << std::endl <<
845 " User prescribed RTOL decreased to reasonable largest value RTOL=" <<
852 *errorStream << std::endl <<
853 "User prescribed RTOL increased to reasonable smallest value RTOL=" <<
862 if ( scale->empty() )
865 for (
int i=0;i<n;i++) (*scale)[i]=defaultScale;
869 for (
int i=0;i<n;i++)
871 if ( (*scale)[i] < 0.0 )
874 *errorStream << std::endl <<
875 " Error - negative value scale[" << i <<
"] supplied" << std::endl;
878 else if ( (*scale)[i] == 0.0 )
879 (*scale)[i] = defaultScale;
880 else if ( (*scale)[i] <
SMALL )
883 *errorStream << std::endl <<
884 " Warning scale[" << i <<
"] too small - increased to " <<
SMALL << std::endl;
887 else if ( (*scale)[i] > large )
890 *errorStream << std::endl <<
891 " Warning scale[" << i <<
"] too large - decreased to " << large << std::endl;
896 if ( monitorLevel==0 )
return 0;
897 *monitorStream << std::endl <<
" Problem dimension: n = " << n << std::endl;
898 *monitorStream << std::endl <<
" Prescribed relative precision: " << xtol
900 *monitorStream <<
" The problem is specified as being ";
901 switch ( nonlinType )
903 case mildlyNonlinear: *monitorStream <<
"mildly nonlinear" << std::endl;
905 case highlyNonlinear: *monitorStream <<
"highly nonlinear" << std::endl;
911 *monitorStream <<
" The restricted monotonicity test will be applied" << std::endl;
913 *monitorStream <<
" The standard monotonicity test will be applied" << std::endl;
915 *monitorStream <<
" The maximum permitted number of iteration steps is: " <<
916 maximumNoIterations << std::endl;
921 int maximumNoIterations, preconFillLevel;
922 bool restricted, statistics;
923 std::ostream *errorStream, *monitorStream;
924 enum {StandardScale=0,StartValueScale=1} scaleopt;
925 PrintLevel errorLevel, monitorLevel, dataLevel;
927 std::vector<double>* scale;
928 std::string outFilePrefix;
929 struct NleqInfo info;
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
Grid const & grid() const
Returns a const reference on the owned grid.
Solution of a nonlinear system of equations by a damped Newton-method.
void setErrorLevel(PrintLevel errorLevel_)
Sets the error-output level. The default error-output level is verbose.
void setScalingVector(std::vector< double > *scale_)
Sets a user-defined scaling-threshold vector.
void setMonitorStream(std::ostream &monitorStream_)
Sets the monitor-output stream. The default monitor-output stream is std::cout.
struct NleqInfo getInfo()
After calling nleqErr, getInfo returns the info structure contents.
void setDataLevel(PrintLevel dataLevel_)
Sets the plot-data-output level. The default plot-data-output level is none.
void setStatistics(bool statistics_)
Sets the Timings statistics flag. The default Timings statistics flag level is off.
void setTolerance(double tol_)
Sets the error tolerance which the final approximate solution must fit. The default value is 1....
void setNonlinProblemType(NonlinProblemType nonlinType_)
Set the classification of the nonlinear problem. The default value is highlyNonlinear.
void setPreconFillLevel(int preconFillLevel_)
Sets the fillin-level of the preconditioner PrecondType::ILUK. The default fillin-level is 0.
void setMonitorLevel(PrintLevel monitorLevel_)
Sets the monitor-output level. The default monitor-output level is none.
void nleqErr(GridManager< Grid > &gridManager, Equation &eq, VariableSet const &variableSet, typename VariableSet::VariableSet *x, Spaces const &spaces, Timings &timer=Timings::instance())
Calls the nleqErr damped Newton-iteration solver.
void setMaximumNoIterations(int maximumIter_)
Sets the maximum allowed number of Newton-iterations. The default value is 50.
void setErrorStream(std::ostream &errorStream_)
Sets the error-output stream. The default error-output stream is std::cerr.
void setRestricted(bool restricted_)
Sets the restricted monotonicity-test flag. The default value depends on the selected NonlinProblemTy...
void setOutFilePrefix(const std::string &outFilePrefix_)
Sets the prefix of the output-files named <prefix>nnn.vtu, where n denotes a decimal digit....
Supports gathering and reporting execution times information for nested program parts.
static Timings & instance()
Returns a reference to a single default instance.
A class for storing a heterogeneous collection of FunctionSpaceElement s.
VariableSet(Self const &vs)
Copy constructor.
A class for assembling Galerkin representation matrices and right hand sides for variational function...
Utility classes for the definition and use of variational functionals.
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
#define LAMBDA_START_EXTREMELY_DEFAULT
#define LAMBDA_MIN_DEFAULT
#define LAMBDA_START_DEFAULT
#define LAMBDA_MIN_EXTREMELY_DEFAULT
std::vector< double > * fx
std::vector< double > * dx
int noJacobianEvaluations
int noFunctionEvaluations
Output of mesh and solution for visualization software.