rsvs3D  0.0.0
Codes for the c++ implementation of the 3D RSVS
SQPstep.hpp
Go to the documentation of this file.
1 
7 #ifndef SQPSTEP_H_INCLUDED
8 #define SQPSTEP_H_INCLUDED
9 
10 //=================================
11 // forward declared dependencies
12 // class foo; //when you only need a pointer not the actual object
13 // and to avoid circular dependencies
14 #include <Eigen>
15 #include <fstream>
16 #include <iostream>
17 #include <vector>
18 
19 #include "RSVScalc.hpp"
20 #include "arraystructures.hpp"
21 #include "mesh.hpp"
22 #include "snake.hpp"
23 #include "triangulate.hpp"
24 #include "warning.hpp"
25 
26 //=================================
27 // included dependencies
28 //==================================
29 // Code
30 // NOTE: function in a class definition are IMPLICITELY INLINED
31 // ie replaced by their code at compile time
32 
44 void ResizeLagrangianMultiplier(const RSVScalc &calcobj, Eigen::VectorXd &lagMultAct, bool &isLarge, bool &isNan);
45 
76 template <class T>
77 bool SQPstep(const RSVScalc &calcobj, const Eigen::MatrixXd &dConstrAct, const Eigen::RowVectorXd &dObjAct,
78  const Eigen::VectorXd &constrAct, Eigen::VectorXd &lagMultAct, Eigen::VectorXd &deltaDVAct, bool &isNan,
79  bool &isLarge, bool attemptConstrOnly = true);
80 
112 template <template <typename> class T>
113 bool SQPstep(const RSVScalc &calcobj, const Eigen::MatrixXd &dConstrAct, const Eigen::RowVectorXd &dObjAct,
114  const Eigen::VectorXd &constrAct, Eigen::VectorXd &lagMultAct, Eigen::VectorXd &deltaDVAct, bool &isNan,
115  bool &isLarge, bool attemptConstrOnly = true);
116 
130 template <class T>
131 bool SQPsens_sparse(const Eigen::MatrixXd &sensMult, const MatrixXd_sparse &sensInv, Eigen::MatrixXd &sensRes);
132 
133 template <class T>
134 bool SQPsens(const Eigen::MatrixXd &sensMult, const Eigen::MatrixXd &sensInv, Eigen::MatrixXd &sensRes);
135 
136 template <template <typename> class T>
137 bool SQPsens(const Eigen::MatrixXd &sensMult, const Eigen::MatrixXd &sensInv, Eigen::MatrixXd &sensRes);
138 
139 // Code to be included as templated functions
140 
141 template <template <typename> class T>
142 bool SQPstep(const RSVScalc &calcobj, const Eigen::MatrixXd &dConstrAct, const Eigen::RowVectorXd &dObjAct,
143  const Eigen::VectorXd &constrAct, Eigen::VectorXd &lagMultAct, Eigen::VectorXd &deltaDVAct, bool &isNan,
144  bool &isLarge, bool attemptConstrOnly)
145 {
146  return (SQPstep<T<Eigen::MatrixXd>>(calcobj, dConstrAct, dObjAct, constrAct, lagMultAct, deltaDVAct, isNan, isLarge,
147  attemptConstrOnly));
148 }
149 
150 template <class T>
151 bool SQPstep(const RSVScalc &calcobj, const Eigen::MatrixXd &dConstrAct, const Eigen::RowVectorXd &dObjAct,
152  const Eigen::VectorXd &constrAct, Eigen::VectorXd &lagMultAct, Eigen::VectorXd &deltaDVAct, bool &isNan,
153  bool &isLarge, bool attemptConstrOnly)
154 {
155  Eigen::LDLT<Eigen::MatrixXd> condsys(calcobj.HLag);
156  Eigen::MatrixXd temp1, temp2;
157  T HLagSystem(calcobj.HLag);
158 
159  std::cout << " (rcond) " << condsys.rcond();
160 
161  temp1 = HLagSystem.solve(dConstrAct.transpose());
162  temp2 = HLagSystem.solve(dObjAct.transpose());
163 
164  T LagMultSystem(dConstrAct * (temp1));
165 
166  lagMultAct = LagMultSystem.solve(constrAct - (dConstrAct * (temp2)));
167 
168  ResizeLagrangianMultiplier(calcobj, lagMultAct, isLarge, isNan);
169  isLarge = false;
170  if (!attemptConstrOnly && (isLarge || isNan))
171  {
172  std::cout << "(early sqp return) ";
173  return (isLarge || isNan);
174  }
175  if (isLarge || isNan)
176  {
177  // Use a least squared solver if only using the constraint
178  std::cout << "(constrmov) ";
179  deltaDVAct = -dConstrAct.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(constrAct);
180  }
181  else
182  {
183  deltaDVAct = -(HLagSystem.solve(dObjAct.transpose() + dConstrAct.transpose() * lagMultAct));
184  }
185  return (isLarge || isNan);
186 }
187 
188 template <class T>
189 bool SQPstep_sparse(const RSVScalc &calcobj, const MatrixXd_sparse &dConstrAct, const Eigen::RowVectorXd &dObjAct,
190  const Eigen::VectorXd &constrAct, Eigen::VectorXd &lagMultAct, Eigen::VectorXd &deltaDVAct,
191  bool &isNan, bool &isLarge, bool attemptConstrOnly)
192 {
193  // Eigen::LDLT<MatrixXd_sparse> condsys(calcobj.HLag_sparse);
194  T HLagSystem;
195  HLagSystem.compute(calcobj.HLag_sparse);
196  // std::cout << " (rcond) " << condsys.rcond();
197  if (HLagSystem.info() != Eigen::Success)
198  {
199  // decomposition failed
200  RSVS3D_ERROR_NOTHROW("Failed to decompose Hessian of lagrangian.");
201  isNan = true;
202  return (isLarge || isNan);
203  }
204  T LagMultSystem;
205  MatrixXd_sparse temp1 = dConstrAct.transpose();
206  temp1.makeCompressed();
207  MatrixXd_sparse temp2 = dConstrAct * HLagSystem.solve(temp1);
208  temp2.makeCompressed();
209  LagMultSystem.compute(temp2);
210  if (LagMultSystem.info() != Eigen::Success)
211  {
212  // decomposition failed
213  RSVS3D_ERROR_NOTHROW("Failed to decompose Lagrangian multiplier system.");
214  isNan = true;
215  return (isLarge || isNan);
216  }
217  lagMultAct = LagMultSystem.solve(constrAct - (dConstrAct * HLagSystem.solve(dObjAct.transpose())));
218 
219  ResizeLagrangianMultiplier(calcobj, lagMultAct, isLarge, isNan);
220  isLarge = false;
221  if (!attemptConstrOnly && (isLarge || isNan))
222  {
223  std::cout << "(early sqp return) ";
224  return (isLarge || isNan);
225  }
226  if (isLarge || isNan)
227  {
228  // Use a least squared solver if only using the constraint
229  std::cout << "(constrmov) ";
230  Eigen::SparseQR<MatrixXd_sparse, Eigen::COLAMDOrdering<int>> gradOnlySolver;
231  gradOnlySolver.compute(dConstrAct);
232  deltaDVAct = -gradOnlySolver.solve(constrAct);
233  }
234  else
235  {
236  deltaDVAct = -(HLagSystem.solve(dObjAct.transpose() + dConstrAct.transpose() * lagMultAct));
237  }
238  return (isLarge || isNan);
239 }
240 
241 template <template <typename> class T>
242 bool SQPsens(const Eigen::MatrixXd &sensMult, const Eigen::MatrixXd &sensInv, Eigen::MatrixXd &sensRes)
243 {
244  return SQPsens<T<Eigen::MatrixXd>>(sensMult, sensInv, sensRes);
245 }
246 
247 template <class T>
248 bool SQPsens(const Eigen::MatrixXd &sensMult, const Eigen::MatrixXd &sensInv, Eigen::MatrixXd &sensRes)
249 {
250  T HLagSystem(sensInv);
251 
252  sensRes = -HLagSystem.solve(sensMult);
253  return (true);
254 }
255 
256 template <class T>
257 bool SQPsens_sparse(const Eigen::MatrixXd &sensMult, const MatrixXd_sparse &sensInv, Eigen::MatrixXd &sensRes)
258 {
259  T HLagSystem;
260  HLagSystem.compute(sensInv);
261  if (HLagSystem.info() != Eigen::Success)
262  {
263  // decomposition failed
264  RSVS3D_ERROR_NOTHROW("Failed to decompose sensitivity system.");
265  return (false);
266  }
267  sensRes = -(HLagSystem.solve(sensMult));
268  return (true);
269 }
270 
271 #endif
Provides the infrastructure for calculation of the RSVS equations.
void ResizeLagrangianMultiplier(const RSVScalc &calcobj, Eigen::VectorXd &lagMultAct, bool &isLarge, bool &isNan)
Resizes the lagrangian multiplier LagMultAct based on whether any of its values are nan or too large.
bool SQPsens_sparse(const Eigen::MatrixXd &sensMult, const MatrixXd_sparse &sensInv, Eigen::MatrixXd &sensRes)
Calculation for the sparse SQP sensitivity.
Definition: SQPstep.hpp:257
bool SQPstep(const RSVScalc &calcobj, const Eigen::MatrixXd &dConstrAct, const Eigen::RowVectorXd &dObjAct, const Eigen::VectorXd &constrAct, Eigen::VectorXd &lagMultAct, Eigen::VectorXd &deltaDVAct, bool &isNan, bool &isLarge, bool attemptConstrOnly=true)
Template for calculation of an SQP step.
Definition: SQPstep.hpp:142
Provide std::vector container with hashed index mapping.
Class to handle the RSVS calculation.
Definition: RSVScalc.hpp:130
Eigen::MatrixXd HLag
Lagrangian Hessian, size: [nDv, nDv].
Definition: RSVScalc.hpp:171
Provides all the mesh tools used for the generation of 3D grids and geometries.
Provides the core restricted surface snake container.
Provides a triangulation for snake and meshes.
Provides the error and warning system used by the RSVS3D project.
#define RSVS3D_ERROR_NOTHROW(M)
Generic rsvs warning.
Definition: warning.hpp:120