Nektar++
Loading...
Searching...
No Matches
NekNonlinSysIterNewtonTrustRegion.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: NekNonlinSysIterNewtonTrustRegion.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// License for the specific language governing rights and limitations under
14// Permission is hereby granted, free of charge, to any person obtaining a
15// copy of this software and associated documentation files (the "Software"),
16// to deal in the Software without restriction, including without limitation
17// the rights to use, copy, modify, merge, publish, distribute, sublicense,
18// and/or sell copies of the Software, and to permit persons to whom the
19// Software is furnished to do so, subject to the following conditions:
20//
21// The above copyright notice and this permission notice shall be included
22// in all copies or substantial portions of the Software.
23//
24// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30// DEALINGS IN THE SOFTWARE.
31//
32// Description: NekNonlinSysIterNewtonTrustRegion definition
33//
34///////////////////////////////////////////////////////////////////////////////
35
37#include <algorithm>
38#include <cmath>
39
40/* -- XML Parameter section --
41<SOLVERINFO>
42 <I PROPERTY="NonlinearSolver" VALUE="NewtonTrustRegion" />
43</SOLVERINFO>
44
45<PARAMETERS>
46 <P> TrustRadiusInit = 1.0e-2 </P>
47 <P> TrustRadiusMin = 1.0e-8 </P>
48 <P> TrustRadiusMax = 1.0e0 </P>
49
50 <P> TrustRegionRhoAccept = 1.0e-1 </P>
51 <P> TrustRegionRhoShrink = 2.5e-1 </P>
52 <P> TrustRegionRhoGrow = 7.5e-1 </P>
53 <P> TrustRegionShrinkFactor = 0.5 </P>
54 <P> TrustRegionGrowFactor = 2.0 </P>
55
56 <P> MaxTrustRegionSteps = 4 </P>
57 <P> TrustRegionMaxFallbackResidualGrowth = 10.0 </P>
58</PARAMETERS>
59*/
60
61using namespace std;
63{
64
68 "Newton solver with trust-region clipped step.");
69
72 const LibUtilities::CommSharedPtr &vComm, const int nDimen,
73 const NekSysKey &pKey)
74 : NekNonlinSysIterNewton(pSession, vComm, nDimen, pKey)
75{
76 pSession->LoadParameter("TrustRadiusInit", m_trustRadiusInit, 1.0e-2);
77 pSession->LoadParameter("TrustRadiusMin", m_trustRadiusMin, 1.0e-8);
78 pSession->LoadParameter("TrustRadiusMax", m_trustRadiusMax, 1.0e2);
79
80 pSession->LoadParameter("TrustRegionRhoAccept", m_rhoAccept, 1.0e-1);
81 pSession->LoadParameter("TrustRegionRhoShrink", m_rhoShrink, 2.5e-1);
82 pSession->LoadParameter("TrustRegionRhoGrow", m_rhoGrow, 7.5e-1);
83 pSession->LoadParameter("TrustRegionShrinkFactor", m_shrinkFactor, 0.5);
84 pSession->LoadParameter("TrustRegionGrowFactor", m_growFactor, 2.0);
85
86 pSession->LoadParameter("MaxTrustRegionSteps", m_maxTrustRegionSteps, 4);
87 pSession->LoadParameter("TrustRegionMaxFallbackResidualGrowth",
89}
90
101
103 const int ntotal, const Array<OneD, const NekDouble> &x) const
104{
105 NekDouble nrm2 = Vmath::Dot(ntotal, x, x);
106 m_rowComm->AllReduce(nrm2, LibUtilities::ReduceSum);
107 return sqrt(nrm2);
108}
109
111 const int ntotal, const NekDouble oldResNorm)
112{
113 NekDouble deltaNorm = CalcL2Norm(ntotal, m_DeltSltn);
114 NekDouble trustRadiusTrial = m_trustRadius;
115 if (m_verbose)
116 {
117 cout << " Attempting to apply Newton update Trust Region "
118 << " Trust radius = " << trustRadiusTrial
119 << " deltaNorm = " << deltaNorm << " oldResNorm= " << oldResNorm
120 << endl;
121 }
122 for (int it = 0; it < m_maxTrustRegionSteps; ++it)
123 {
124 if (m_verbose)
125 {
126 cout << " Trust region test " << it << " of "
127 << m_maxTrustRegionSteps << endl;
128 }
129 Vmath::Vcopy(ntotal, m_DeltSltn, 1, m_deltaTrial, 1);
130
131 bool boundaryStep = false;
132 if (deltaNorm > trustRadiusTrial)
133 {
134 NekDouble scale = trustRadiusTrial / deltaNorm;
135 Vmath::Smul(ntotal, scale, m_deltaTrial, 1, m_deltaTrial, 1);
136 boundaryStep = true;
137 if (m_verbose)
138 {
139 cout << " deltaNorm > trustRadiusTrial - Boundary Step" << endl;
140 }
141 }
142 NekDouble trialNorm = CalcL2Norm(ntotal, m_deltaTrial);
143 NekDouble alphaPred =
144 (deltaNorm > 1.0e-14) ? (trialNorm / deltaNorm) : 1.0;
145
147 Vmath::Svtvp(ntotal, -1.0, m_deltaTrial, 1, m_solutionTrial, 1,
148 m_solutionTrial, 1);
149
151
152 NekDouble newResNormSq =
154 m_rowComm->AllReduce(newResNormSq, LibUtilities::ReduceSum);
155 NekDouble newResNorm = sqrt(newResNormSq);
156
157 NekDouble pred =
158 std::max(1.0e-14 * oldResNorm, 0.5 * alphaPred * oldResNorm);
159 NekDouble ared = oldResNorm - newResNorm;
160 NekDouble rho = ared / pred;
161
162 if (m_verbose)
163 {
164 cout << " TrustRadius trial = " << trustRadiusTrial
165 << " stepNorm = " << trialNorm << " oldRes = " << oldResNorm
166 << " newRes = " << newResNorm << " ared = " << ared
167 << " pred = " << pred << " rho = " << rho << endl;
168 }
169
170 if (rho > m_rhoAccept)
171 {
172 cout << " Accepting step with rho = " << rho
173 << "> m_rhoAccept = " << m_rhoAccept << endl;
177
178 m_trustRadius = trustRadiusTrial;
179
180 if (rho < m_rhoShrink)
181 {
182 cout << "Trust radius shrink with m_rhoShrink=" << m_rhoShrink
183 << endl;
186 }
187 else if (rho > m_rhoGrow && boundaryStep)
188 {
189 cout << "Trust radius grow with m_rhoGrow=" << m_rhoGrow
190 << endl;
193 }
194
195 return true;
196 }
197
198 trustRadiusTrial =
199 std::max(m_trustRadiusMin, m_shrinkFactor * trustRadiusTrial);
200
201 if (trustRadiusTrial <= m_trustRadiusMin + 1.0e-16)
202 {
203 break;
204 }
205 }
206
207 cout << "Failed to find a correct step "
208 << " Fallback: force a minimum-radius step and continue." << endl;
209 Vmath::Vcopy(ntotal, m_DeltSltn, 1, m_deltaTrial, 1);
210
211 if (deltaNorm > m_trustRadiusMin)
212 {
213 NekDouble scale = m_trustRadiusMin / deltaNorm;
214 Vmath::Smul(ntotal, scale, m_deltaTrial, 1, m_deltaTrial, 1);
215 }
216
218 Vmath::Svtvp(ntotal, -1.0, m_deltaTrial, 1, m_solutionTrial, 1,
219 m_solutionTrial, 1);
220
222
223 NekDouble fallbackResNormSq =
225 m_rowComm->AllReduce(fallbackResNormSq, LibUtilities::ReduceSum);
226 NekDouble fallbackResNorm = sqrt(fallbackResNormSq);
227
228 cout << " No acceptable trust-region step found."
229 << " Taking fallback TrustRadiusMin = " << m_trustRadiusMin
230 << " residual = " << fallbackResNorm << endl;
231
232 if (!std::isfinite(fallbackResNorm) ||
233 fallbackResNorm > m_maxFallbackResidualGrowth * oldResNorm)
234 {
235 WARNINGL0(false,
236 "Fallback trust-region step caused non-finite or excessive "
237 "residual growth.");
239 return false;
240 }
241
245
247 return true;
248}
249
250} // namespace Nektar::LibUtilities
#define WARNINGL0(condition, msg)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
bool v_ApplyNewtonUpdate(const int ntotal, const NekDouble oldResNorm) override
NekDouble CalcL2Norm(const int ntotal, const Array< OneD, const NekDouble > &x) const
NekNonlinSysIterNewtonTrustRegion(const LibUtilities::SessionReaderSharedPtr &pSession, const LibUtilities::CommSharedPtr &vComm, const int nDimen, const NekSysKey &pKey)
static NekNonlinSysIterSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const LibUtilities::CommSharedPtr &vComm, const int nDimen, const NekSysKey &pKey)
LibUtilities::CommSharedPtr m_rowComm
Definition NekSys.h:299
NekSysOperators m_operator
Definition NekSys.h:306
void DoNekSysResEval(InArrayType &inarray, OutArrayType &outarray, const bool &flag=false) const
Definition NekSys.h:141
NekNonlinSysIterFactory & GetNekNonlinSysIterFactory()
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition Comm.h:55
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
Definition Vmath.hpp:396
T Dot(int n, const T *w, const T *x)
dot product
Definition Vmath.hpp:761
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition Vmath.hpp:100
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
STL namespace.
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290