MAST
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 #include "libmesh/dof_map.h"
30 
33 _dpds_sign (1.) {
34 
35 }
36 
37 
39 
40 }
41 
42 
43 void
45 
46  libmesh_assert(!_initialized);
47  libmesh_assert(_elem_ops);
48 
49  (*_p)() += dp;
50  if (dp < 0.) _dpds_sign = -1.;
51 
53  system = _assembly->system();
54 
55  std::unique_ptr<libMesh::NumericVector<Real>>
56  dX(system.solution->clone().release());
57 
59 
60  dX->add(-1., *system.solution);
61  dX->scale(-1.);
62  dX->close();
63 
64  // initialize scaling factors
65  _X_scale = 1./dX->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(dX->l2_norm(), 2));
70 
71  libmesh_assert_greater(arc_length, 0.);
72 
73  _initialized = true;
74 }
75 
76 
77 void
79 _solve_NR_iterate(libMesh::NumericVector<Real> &X,
80  MAST::Parameter &p) {
81 
82  libmesh_assert(_initialized);
83 
84  std::unique_ptr<libMesh::NumericVector<Real>>
85  f(X.zero_clone().release()),
86  dgdX(X.zero_clone().release()),
87  dfdp(X.zero_clone().release()),
88  dXdp(X.zero_clone().release()),
89  dX(X.zero_clone().release());
90 
91  libMesh::SparseMatrix<Real>
92  &jac = *_assembly->system().matrix;
93 
94  Real
95  g = 0.,
96  dgdp = 0.,
97  dp = 0.;
98 
99  _g(X, p, *dfdp, *dXdp, g, dgdp, dgdX.get());
100 
101  if (!schur_factorization)
102  _solve(X, p,
103  *f, true, // update f
104  *dfdp, false, // update dfdp
105  *dgdX, dgdp, g,
106  *dX, dp);
107  else
109  jac, true, // update jac
110  *f, true, // update f
111  *dfdp, false, // update dfdp
112  *dXdp, false, // update dXdp
113  *dgdX, dgdp, g,
114  *dX, dp);
115 
116  // update the solution and load parameter
117  p() += dp;
118  X.add(1., *dX);
119  X.close();
120 }
121 
122 
123 void
125 _dXdp(const libMesh::NumericVector<Real> &X,
126  const MAST::Parameter &p,
127  libMesh::NumericVector<Real> &dfdp,
128  libMesh::NumericVector<Real> &dXdp) {
129 
130  libmesh_assert(_elem_ops);
131 
133  &system = _assembly->system();
134 
135  libmesh_assert(system.operation() == MAST::NonlinearSystem::NONE);
136 
138 
140 
142 
143  libMesh::SparseMatrix<Real>
144  *pc = system.request_matrix("Preconditioner");
145 
146  std::pair<unsigned int, Real>
147  solver_params = system.get_linear_solve_parameters(),
148  rval;
149 
150  dXdp.zero();
151 
152  rval = system.linear_solver->solve (*system.matrix, pc,
153  dXdp,
154  dfdp,
155  solver_params.second,
156  solver_params.first);
157 
158  dXdp.scale(-1.);
159  dXdp.close();
160 
161  // The linear solver may not have fit our constraints exactly
162 #ifdef LIBMESH_ENABLE_CONSTRAINTS
163  system.get_dof_map().enforce_constraints_exactly (system,
164  &dXdp,
165  /* homogeneous = */ true);
166 #endif
167 
170 }
171 
172 
173 
174 
175 Real
176 MAST::ArclengthContinuationSolver::_g(const libMesh::NumericVector<Real> &X,
177  const MAST::Parameter &p) {
178 
179  std::unique_ptr<libMesh::NumericVector<Real>>
180  dfdp(X.zero_clone().release()),
181  dXdp(X.zero_clone().release());
182 
183  Real
184  g = 0.,
185  dgdp = 0.;
186 
187  _g(X, p, *dfdp, *dXdp, g, dgdp, nullptr);
188 
189  return g;
190 }
191 
192 
193 void
194 MAST::ArclengthContinuationSolver::_g(const libMesh::NumericVector<Real> &X,
195  const MAST::Parameter &p,
196  libMesh::NumericVector<Real> &dfdp,
197  libMesh::NumericVector<Real> &dXdp,
198  Real &g,
199  Real &dgdp,
200  libMesh::NumericVector<Real> *dgdX) {
201 
202  libmesh_assert(_initialized);
203 
204  // update the constraint data
205  _dXdp(X, p, dfdp, dXdp);
206 
207  // this includes scaling of X and p
208  Real
209  dpds = _dpds_sign * std::sqrt(1./ ( std::pow(_X_scale/_p_scale,2) * dXdp.dot(dXdp) + 1.));
210 
211  std::unique_ptr<libMesh::NumericVector<Real>>
212  dX(X.clone().release());
213 
214  dX->add(-1., *_X0);
215  dX->close();
216 
217  // (dX/ds)_scaled = (dX/dp)_scaled * (dp/ds)_scaled
218  // = (dX_scaled/dX) * dX/dp * (dp/dp_scaled) * (dp/ds)_scaled
219  // = X_scale/p_scale * dX/dp * (dp/ds)_scaled
220  g = (_X_scale * (dX->dot(dXdp) * dpds * _X_scale/_p_scale) +
221  _p_scale * (p() - _p0) * dpds) - arc_length;
222  dgdp = _p_scale * dpds;
223 
224  if (dgdX) {
225 
226  dgdX->zero();
227  dgdX->add(_X_scale * (dpds * _X_scale/_p_scale), dXdp);
228  dgdX->close();
229  }
230 }
231 
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 _solve_NR_iterate(libMesh::NumericVector< Real > &X, MAST::Parameter &p)
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.
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...
virtual std::pair< unsigned int, Real > get_linear_solve_parameters()
calls NonlinearImplicitSystem::set_solver_parameters() before accessing the values.
Real arc_length
arc length that the solver is required to satisfy for the update.
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::LinearSolver< Real > > linear_solver
The LinearSolver for solution of the linear equations.
virtual Real _g(const libMesh::NumericVector< Real > &X, const MAST::Parameter &p)
MAST::NonlinearSystem::Operation operation()
MAST::AssemblyElemOperations * _elem_ops
const MAST::NonlinearSystem & system() const
virtual void initialize(Real dp)
sets the arc length using a nonlinear solution using a step dp.
bool schur_factorization
flag to use Schur-factorizaiton (default) or monolithic solver
virtual void _dXdp(const libMesh::NumericVector< Real > &X, const MAST::Parameter &p, libMesh::NumericVector< Real > &dfdp, libMesh::NumericVector< Real > &dXdp)
virtual void solve(MAST::AssemblyElemOperations &elem_ops, MAST::AssemblyBase &assembly)
solves the nonlinear problem with the specified assembly operation object