MAST
pseudo_arclength_continuation_solver.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 
21 // MAST includes
23 #include "base/assembly_base.h"
24 #include "base/nonlinear_system.h"
25 #include "base/parameter.h"
26 
27 // libMesh includes
28 #include "libmesh/linear_solver.h"
29 
30 
33 _t0_p (0.),
34 _t0_p_orig (0.) {
35 
36 }
37 
38 
40 
41 }
42 
43 
44 void
46 
47  libmesh_assert(!_initialized);
48  libmesh_assert(_elem_ops);
49 
50  (*_p)() += dp;
51 
53  system = _assembly->system();
54 
55  _t0_X.reset(system.solution->clone().release());
56  _t0_X_orig.reset(system.solution->zero_clone().release());
57 
59 
60  _t0_X->add(-1., *system.solution);
61  _t0_X->scale(-1.);
62  _t0_X->close();
63 
64  // initialize scaling factors
65  _X_scale = 1./_t0_X->l2_norm();
66  _p_scale = 1./std::fabs(dp);
67 
68  arc_length = std::sqrt(std::pow(_p_scale, 2) * dp*dp +
69  std::pow(_X_scale, 2) * std::pow(_t0_X->l2_norm(), 2));
70 
71  libmesh_assert_greater(arc_length, 0.);
72 
73  // scale _t0_X such that {t0_X, t0_p} is a unit vector
74  _t0_X->scale(_X_scale/arc_length);
75  _t0_X->close();
77 
79 
80  _initialized = true;
81 }
82 
83 
84 void
86 _solve_NR_iterate(libMesh::NumericVector<Real> &X,
87  MAST::Parameter &p) {
88 
89  libmesh_assert(_initialized);
90 
91  std::unique_ptr<libMesh::NumericVector<Real>>
92  f(X.zero_clone().release()),
93  dfdp(X.zero_clone().release()),
94  dXdp(X.zero_clone().release()),
95  t1_X(X.zero_clone().release()),
96  dX(X.zero_clone().release());
97 
98  libMesh::SparseMatrix<Real>
99  &jac = *_assembly->system().matrix;
100 
101  Real
102  t1_p = 0.,
103  g = 0.,
104  dp = 0.;
105 
107  jac,
108  *t1_X,
109  t1_p);
110 
111 
112  _g(X, p, *t1_X, t1_p, g);
113 
114  // scale the values so that they are in the scaled coordinates
115  t1_X->scale(_X_scale);
116  t1_X->close();
117  t1_p *= _p_scale;
118 
119  if (!schur_factorization)
120  _solve(X, p,
121  *f, true, // update f
122  *dfdp, true, // update dfdp
123  *t1_X, t1_p, g, // dgdX = X_scale * t1^X, dgdp = p_scale *t1^p
124  *dX, dp);
125  else
127  jac, false, // do not update jac
128  *f, true, // update f
129  *dfdp, true, // update dfdp
130  *dXdp, true, // update dXdp
131  *t1_X, t1_p, g, // dgdX = X_scale * t1^X, dgdp = p_scale *t1^p
132  *dX, dp);
133 
134  // update the solution and load parameter
135  p() += dp;
136  X.add(1., *dX);
137  X.close();
138 
139 }
140 
141 
142 void
144 _update_search_direction(const libMesh::NumericVector<Real> &X,
145  const MAST::Parameter &p,
146  libMesh::SparseMatrix<Real> &jac,
147  libMesh::NumericVector<Real> &t1_X,
148  Real &t1_p) {
149 
150  libmesh_assert(_initialized);
151 
152  std::unique_ptr<libMesh::NumericVector<Real>>
153  f(X.zero_clone().release()),
154  dfdp(X.zero_clone().release()),
155  dXdp(X.zero_clone().release());
156 
158  &system = _assembly->system();
159 
162 
163  _assembly->sensitivity_assemble(p, *dfdp);
164  dfdp->scale(_X_scale/_p_scale);
165  dfdp->close();
166 
168  system.set_operation(MAST::NonlinearSystem::NONE);
169 
170 
171  // first update the search direction
172  if (!schur_factorization)
173  _solve(X, p,
174  *f, false, // do not update f
175  *dfdp, false, // do not update dfdp
176  *_t0_X, _t0_p, -1., // dgdX = t0^X, dgdp = t0^p, g = -1
177  t1_X, t1_p);
178  else
180  jac, true, // update jac
181  *f, false, // do not update f
182  *dfdp, false, // do not update dfdp
183  *dXdp, true, // update dXdp
184  *_t0_X, _t0_p, -1., // dgdX = t0^X, dgdp = t0^p, g = -1
185  t1_X, t1_p);
186 
187  // now scale the vector for unit magnitude
188  Real
189  val = std::sqrt(t1_p*t1_p + std::pow(t1_X.l2_norm(), 2));
190 
191  t1_X.scale(1./val);
192  t1_X.close();
193  t1_p /= val;
194 
195  // store values for next iterate
196  _t0_X->zero();
197  _t0_X->add(1., t1_X);
198  _t0_X->close();
199 
200  _t0_p = t1_p;
201 }
202 
203 
204 Real
205 MAST::PseudoArclengthContinuationSolver::_g(const libMesh::NumericVector<Real> &X,
206  const MAST::Parameter &p) {
207 
208  std::unique_ptr<libMesh::NumericVector<Real>>
209  f(X.zero_clone().release()),
210  t1_X(X.zero_clone().release());
211 
212  Real
213  g = 0.,
214  t1_p = 0.;
215 
217  *_assembly->system().matrix,
218  *t1_X,
219  t1_p);
220 
221  _g(X, p, *t1_X, t1_p, g);
222 
223  return g;
224 }
225 
226 
227 void
228 MAST::PseudoArclengthContinuationSolver::_g(const libMesh::NumericVector<Real> &X,
229  const MAST::Parameter &p,
230  libMesh::NumericVector<Real> &t1_X,
231  Real &t1_p,
232  Real &g) {
233 
234  libmesh_assert(_initialized);
235 
236  std::unique_ptr<libMesh::NumericVector<Real>>
237  dX(X.clone().release());
238 
239  dX->add(-1., *_X0);
240  dX->close();
241 
242  g = (_X_scale * dX->dot(t1_X) +
243  _p_scale * (p() - _p0) * t1_p) - arc_length;
244 }
245 
246 
247 void
249 
250  // copy for possible reuse in resetting step
251  _t0_X_orig->zero();
252  _t0_X_orig->add(1., *_t0_X);
253  _t0_X_orig->close();
254  _t0_p_orig = _t0_p;
255 }
256 
257 
258 void
260 
261  libmesh_assert(_initialized);
262 
263  _t0_X->zero();
264  _t0_X->add(1., *_t0_X_orig);
265  _t0_X->close();
266  _t0_p = _t0_p_orig;
267 }
virtual Real _g(const libMesh::NumericVector< Real > &X, const MAST::Parameter &p)
where, and .
void _update_search_direction(const libMesh::NumericVector< Real > &X, const MAST::Parameter &p, libMesh::SparseMatrix< Real > &jac, libMesh::NumericVector< Real > &t1_X, Real &t1_p)
updates for the current iterate X and p, and stores these values to _t0_X and _t0_p for next computa...
This class implements a system for solution of nonlinear systems.
virtual void clear_elem_operation_object()
clears the association of this object with the assembly element operation object. ...
virtual bool sensitivity_assemble(const MAST::FunctionBase &f, libMesh::NumericVector< Real > &sensitivity_rhs)
Assembly function.
virtual void _save_iteration_data()
method saves any data for possible resuse if the solution step is restarted
This is a scalar function whose value can be changed and one that can be used as a design variable in...
Definition: parameter.h:35
virtual void set_elem_operation_object(MAST::AssemblyElemOperations &elem_ops)
attaches a element operation to this object, and associated this with the element operation object...
libMesh::Real Real
void _solve_schur_factorization(const libMesh::NumericVector< Real > &X, const MAST::Parameter &p, libMesh::SparseMatrix< Real > &jac, bool update_jac, libMesh::NumericVector< Real > &f, bool update_f, libMesh::NumericVector< Real > &dfdp, bool update_dfdp, libMesh::NumericVector< Real > &dXdp, bool update_dXdp, const libMesh::NumericVector< Real > &dgdX, const Real dgdp, const Real g, libMesh::NumericVector< Real > &dX, Real &dp)
solves for the linear system of equation using Schur factorization.
virtual void initialize(Real dp)
initializes the search direction using the specified load step dp.
void _solve(const libMesh::NumericVector< Real > &X, const MAST::Parameter &p, libMesh::NumericVector< Real > &f, bool update_f, libMesh::NumericVector< Real > &dfdp, bool update_dfdp, const libMesh::NumericVector< Real > &dgdX, const Real dgdp, const Real g, libMesh::NumericVector< Real > &dX, Real &dp)
solves for the linear system of equation as a monolithic system dX and dp are returned from the solu...
the equation set is: the N-R updates are calculated such that This equation is solved using Schur-f...
Real arc_length
arc length that the solver is required to satisfy for the update.
std::unique_ptr< libMesh::NumericVector< Real > > _t0_X_orig
std::unique_ptr< libMesh::NumericVector< Real > > _X0
void set_operation(MAST::NonlinearSystem::Operation op)
sets the current operation of the system
std::unique_ptr< libMesh::NumericVector< Real > > _t0_X
virtual void _solve_NR_iterate(libMesh::NumericVector< Real > &X, MAST::Parameter &p)
MAST::AssemblyElemOperations * _elem_ops
virtual void _reset_iterations()
method resets any data if a solution step is restarted
const MAST::NonlinearSystem & system() const
bool schur_factorization
flag to use Schur-factorizaiton (default) or monolithic solver
virtual void solve(MAST::AssemblyElemOperations &elem_ops, MAST::AssemblyBase &assembly)
solves the nonlinear problem with the specified assembly operation object