41 _include_highest_kr_unstable(false) {
    78            unsigned int                                 n_kr_divs,
    79            std::vector<libMesh::NumericVector<Real> *>& basis) {
    98     std::map<Real, MAST::FlutterSolutionBase*>::iterator it =
   104     std::multimap<Real, MAST::FlutterRootCrossoverBase*>::iterator cross_it =
   108         delete cross_it->second;
   120     std::multimap<Real, MAST::FlutterRootCrossoverBase*>::const_iterator
   125     for ( ; it!=end; it++)
   126         if (it->second->root) 
   141     std::multimap<Real, MAST::FlutterRootCrossoverBase*>::const_iterator
   145     unsigned int root_num = 0;
   146     for ( ; it!=end; it++) {
   147         if (it->second->root) { 
   149                 return *(it->second->root);
   155     libmesh_assert(
false); 
   162 std::pair<bool, MAST::FlutterRootBase*>
   164                                               const unsigned int n_bisection_iters)
   168     std::multimap<Real, MAST::FlutterRootCrossoverBase*>::iterator
   175             const unsigned int root_num = cross->
root_num;
   176             std::pair<bool, MAST::FlutterSolutionBase*> sol;
   185                                       root_num, g_tol, n_bisection_iters);
   187             cross->
root = &(sol.second->get_root(root_num));
   192             std::pair<Real, MAST::FlutterRootCrossoverBase*>
   193             val(cross->
root->
V, cross);
   195             return std::pair<bool, MAST::FlutterRootBase*> (
true, cross->
root);
   202     return std::pair<bool, MAST::FlutterRootBase*> (
false, 
nullptr);
   207 std::pair<bool,  MAST::FlutterRootBase*>
   209                                                   const unsigned int n_bisection_iters)
   213     std::multimap<Real, MAST::FlutterRootCrossoverBase*>::iterator
   217         return std::pair<bool, MAST::FlutterRootBase*> (
false, 
nullptr);
   222     while (!it->second->root)
   228             const unsigned int root_num = cross->
root_num;
   229             std::pair<bool, MAST::FlutterSolutionBase*> sol;
   238                                       root_num, g_tol, n_bisection_iters);
   240             cross->
root = &(sol.second->get_root(root_num));
   245             std::pair<Real, MAST::FlutterRootCrossoverBase*>
   246             val(cross->
root->
V, cross);
   255     return std::pair<bool, MAST::FlutterRootBase*> (
true, it->second->root);
   273             k_vals[i]      = current_kr;
   274             current_kr    -= delta_kr;
   279         for (
unsigned int i=0; i< _n_kr_divs+1; i++) {
   281             current_kr = k_vals[i];
   282             std::unique_ptr<MAST::FlutterSolutionBase> sol =
   285             prev_sol = sol.get();
   293                                       (current_kr, sol.release())).second;
   295             libmesh_assert(if_success);
   314     std::map<Real, MAST::FlutterSolutionBase*>::const_iterator
   317     libmesh_assert(sol_it != sol_end); 
   319     unsigned int nvals = sol_it->second->n_roots();
   320     libmesh_assert(nvals); 
   323     for (
unsigned int i=0; i<nvals; i++)
   328         << std::setw(5) << i << 
" **" << std::endl
   329         << std::setw(15) << 
"kr"   330         << std::setw(15) << 
"g"   331         << std::setw(15) << 
"V" << std::endl;
   337         for ( ; sol_it != sol_end; sol_it++)
   340             sol_it->second->get_root(i);
   343             << std::setw(15) << root.
kr   344             << std::setw(15) << root.
g   345             << std::setw(15) << root.
V << std::endl;
   347         *
_output << std::endl << std::endl;
   352     std::streamsize prec = 
_output->precision();
   356     << 
"n critical roots identified: " << nroots << std::endl;
   357     for (
unsigned int i=0; i<nroots; i++)
   361         << 
"** Root : " << std::setw(5) << i << 
" **" << std::endl
   362         << 
"kr     = " << std::setw(15) << std::setprecision(15) << root.
kr << std::endl
   363         << 
"V      = " << std::setw(15) << std::setprecision(15) << root.
V << std::endl
   364         << 
"g      = " << std::setw(15) << root.
g << std::endl
   365         << 
"omega  = " << std::setw(15) << root.
omega << std::endl
   366         << std::setprecision((
int) prec) 
   367         << 
"Modal Participation : " << std::endl ;
   368         for (
unsigned int j=0; j<nvals; j++)
   370             << 
"(" << std::setw(5) << j << 
"): "   372             << std::setw(3)  << 
" ";
   373         *
_output << std::endl << std::endl;
   385     *
_output << 
"n crossover points found: "   388     std::multimap<Real, MAST::FlutterRootCrossoverBase*>::const_iterator
   393     for ( ; it != end; it++) {
   394         *
_output << 
"** Point : " << std::setw(5) << i << 
" **" << std::endl;
   405 std::pair<bool, MAST::FlutterSolutionBase*>
   409                   const unsigned int root_num,
   411                   const unsigned int max_iters) {
   416     lower_kr = ref_sol_range.first->get_root(root_num).kr,
   417     lower_g  = ref_sol_range.first->get_root(root_num).g,
   418     upper_kr = ref_sol_range.second->get_root(root_num).kr,
   419     upper_g  = ref_sol_range.second->get_root(root_num).g,
   421     unsigned int n_iters = 0;
   424     std::pair<bool, MAST::FlutterSolutionBase*> rval(
false, 
nullptr);
   426     while (n_iters < max_iters) {
   430         << upper_g << 
"  " << std::endl
   432         << lower_g << 
"  " << std::endl;
   435         (upper_kr-lower_kr)/(upper_g-lower_g)*(0.-lower_g); 
   437         new_sol  = 
_analyze(new_kr, ref_sol_range.first).release();
   445                                   (new_kr, new_sol)).second;
   447         libmesh_assert(if_success);
   453         if (fabs(root.
g) <= g_tol) {
   456             rval.second = new_sol;
   477     rval.second = new_sol;
   485 std::unique_ptr<MAST::FlutterSolutionBase>
   490     << 
" ====================================================" << std::endl
   491     << 
"Eigensolution" << std::endl
   492     << 
"   kr_ref = " << std::setw(10) << kr_ref << std::endl;
   508         root->
sort(*prev_sol);
   511     << 
"Finished Eigensolution" << std::endl
   512     << 
" ====================================================" << std::endl;
   515     return std::unique_ptr<MAST::FlutterSolutionBase> (root);
   536     m      =  RealMatrixX::Zero(n, n),
   537     k      =  RealMatrixX::Zero(n, n);
   540     a      =  ComplexMatrixX::Zero(n, n);
   544     std::map<MAST::StructuralQuantityType, RealMatrixX*> qty_map;
   555     assemble_generalized_aerodynamic_force_matrix(*
_basis_vectors, a);
   579                                          const libMesh::NumericVector<Real>& dXdp,
   594     m      =  RealMatrixX::Zero(n, n),
   595     k      =  RealMatrixX::Zero(n, n);
   598     a      =  ComplexMatrixX::Zero(n, n);
   602     std::map<MAST::StructuralQuantityType, RealMatrixX*> qty_map;
   654     m      =  RealMatrixX::Zero(n, n);
   657     a      =  ComplexMatrixX::Zero(n, n);
   661     std::map<MAST::StructuralQuantityType, RealMatrixX*> qty_map;
   684     B    = ComplexMatrixX::Zero(n, n);
   695     const Real tol = 1.0e-5, max_allowable_g = 0.75;
   699     libmesh_assert(nvals);
   708     std::vector<bool> modes_to_neglect(nvals);
   709     std::fill(modes_to_neglect.begin(),
   710               modes_to_neglect.end(), 
false);
   714     for (
unsigned int i=0; i<nvals; i++) {
   715         std::map<Real, MAST::FlutterSolutionBase*>::const_iterator
   718         Real max_g_val = 0., val = 0.;
   719         for ( ; sol_it!=sol_end; sol_it++) {
   720             val = fabs(sol_it->second->get_root(i).g);
   726             modes_to_neglect[i] = 
true;
   732         std::map<Real, MAST::FlutterSolutionBase*>::const_iterator
   735         if (sol_it == sol_end)
   739         if (fabs(sol_it->second->ref_val()) < tol) { 
   744             for (
unsigned int i=0; i<nvals; i++) {
   745                 if (!sol_it->second->get_root(i).if_nonphysical_root &&
   746                     fabs(sol_it->second->get_root(i).g) < tol) {
   751                     cross->
root = &sol_it->second->get_root(i);
   753                     std::pair<Real, MAST::FlutterRootCrossoverBase*>
   754                     val( cross->
root->
V, cross);
   763     for (
unsigned int i=0; i<nvals; i++) {
   764         std::map<Real, MAST::FlutterSolutionBase*>::const_reverse_iterator
   768         if (sol_rit == sol_rend)
   772         bool if_process = 
false;
   774         while (sol_ritp1 != sol_rend) {
   777              (!sol_rit->second->get_root(i).if_nonphysical_root &&
   778               !sol_ritp1->second->get_root(i).if_nonphysical_root) &&
   780              (fabs(sol_rit->second->ref_val()) > tol ||
   781               fabs(sol_ritp1->second->ref_val()) > tol) &&
   783              (fabs(sol_rit->second->get_root(i).g) < max_allowable_g &&
   784               fabs(sol_ritp1->second->get_root(i).g) < max_allowable_g) &&
   787              !modes_to_neglect[i]);
   792                 *upper = sol_ritp1->second;
   795                     (upper->get_root(i).g > 0.)) {
   801                     std::pair<Real, MAST::FlutterRootCrossoverBase*>
   806                          (upper->get_root(i).g <= 0.)) {
   812                     std::pair<Real, MAST::FlutterRootCrossoverBase*>
   813                     val( upper->get_root(i).V, cross);
   831          (!sol_rit->second->get_root(i).if_nonphysical_root &&
   832           !sol_ritp1->second->get_root(i).if_nonphysical_root) &&
   834          (fabs(sol_rit->second->ref_val()) > tol ||
   835           fabs(sol_ritp1->second->ref_val()) > tol) &&
   837          (fabs(sol_rit->second->get_root(i).g) < max_allowable_g &&
   838           fabs(sol_ritp1->second->get_root(i).g) < max_allowable_g) &&
   841          !modes_to_neglect[i]);
   843         Real g_val = sol_rit->second->get_root(i).g;
   846             g_val < max_allowable_g &&
   858             std::pair<Real, MAST::FlutterRootCrossoverBase*>
   859             val( sol_rit->second->get_root(i).V, cross);
   873                       libMesh::NumericVector<Real>* dXdp,
   874                       libMesh::NumericVector<Real>* dXdkr) {
   879     << 
" ====================================================" << std::endl
   880     << 
"UG Sensitivity Solution" << std::endl
   881     << 
"   k_red = " << std::setw(10) << root.
kr << std::endl
   882     << 
"   V_ref = " << std::setw(10) << root.
V << std::endl;
   910     libMesh::NumericVector<Real>* sol_sens = dXdp;
   911     std::unique_ptr<libMesh::NumericVector<Real> > zero_sol_sens;
   913         zero_sol_sens.reset(
_assembly->
system().solution->zero_clone().release());
   914         sol_sens = zero_sol_sens.get();
   944     sol_sens = zero_sol_sens.get();
   965     deig_dp.imag()/eig.real()  - eig.imag()/pow(eig.real(),2) * deig_dp.real();
   967     deig_dkr.imag()/eig.real() - eig.imag()/pow(eig.real(),2) * deig_dkr.real();
   975     dkr_dp       = -dg_dp / dg_dkr;
   980     root.
root_sens            = deig_dp + deig_dkr * dkr_dp;
   985     << 
"Finished Flutter Sensitivity Solution" << std::endl
   986     << 
" ====================================================" << std::endl;
 
unsigned int _n_kr_divs
number of division in the reference value range for initial scanning 
const MAST::NonlinearSystem & system() const
virtual ~UGFlutterSolver()
ComplexVectorX eig_vec_left
std::vector< libMesh::NumericVector< Real > * > * _basis_vectors
basis vector used to define the reduced order model 
virtual void compute(const ComplexMatrixX &A, const ComplexMatrixX &B, bool computeEigenvectors=true)
computes the eigensolution for . 
virtual void print(std::ostream &output)=0
prints the data and modes from this solution 
virtual void print_sorted_roots()
Prints the sorted roots to the output. 
virtual std::pair< bool, MAST::FlutterSolutionBase * > _bisection_search(const std::pair< MAST::FlutterSolutionBase *, MAST::FlutterSolutionBase *> &ref_sol_range, const unsigned int root_num, const Real g_tol, const unsigned int max_iters)
bisection method search 
Matrix< Complex, Dynamic, 1 > ComplexVectorX
This is a scalar function whose value can be changed and one that can be used as a design variable in...
virtual unsigned int n_roots_found() const
finds the number of critical points already identified in the procedure. 
std::ofstream * _output
file to which the result will be written 
virtual std::pair< bool, MAST::FlutterRootBase * > find_critical_root(const Real g_tol, const unsigned int n_bisection_iters)
This method checks if the flutter root corresponding to the lowest velocity crossover has been calcul...
virtual void assemble_reduced_order_quantity(std::vector< libMesh::NumericVector< Real > *> &basis, std::map< MAST::StructuralQuantityType, RealMatrixX *> &mat_qty_map)
calculates the reduced order matrix given the basis provided in basis. 
void scale_eigenvectors_to_identity_innerproduct()
Scales the right eigenvector so that the inner product with respect to the B matrix is equal to an Id...
virtual void print_crossover_points()
Prints the crossover points output. 
Matrix< Real, Dynamic, Dynamic > RealMatrixX
Matrix< Complex, Dynamic, Dynamic > ComplexMatrixX
bool _include_highest_kr_unstable
flag allows check to see if the root started out as critical at the highest k value. 
const MAST::FlutterRootBase & get_root(const unsigned int i) const
virtual void calculate_sensitivity(MAST::FlutterRootBase &root, const MAST::FunctionBase &f, libMesh::NumericVector< Real > *dXdp=nullptr, libMesh::NumericVector< Real > *dXdkr=nullptr)
Calculate the sensitivity of the flutter root with respect to the f parameter. 
std::pair< Real, Real > _kr_range
range of reference values within which to find flutter roots 
void _initialize_matrix_sensitivity_for_param(const MAST::FunctionBase &f, const libMesh::NumericVector< Real > &dXdp, Real kr, ComplexMatrixX &A, ComplexMatrixX &B)
Assembles the reduced order system structural and aerodynmaic matrices for specified flight velocity ...
void _initialize_matrices(Real kr, ComplexMatrixX &A, ComplexMatrixX &B)
Assembles the reduced order system structural and aerodynmaic matrices for specified reduced freq kr...
void init(const MAST::UGFlutterSolver &solver, const Real v_ref, const Real b_ref, const MAST::LAPACK_ZGGEV_Base &eig_sol)
initializes the root 
virtual void scan_for_roots()
Scans for flutter roots in the analyzed points, and identified the divergence (if k_red = 0...
std::multimap< Real, MAST::FlutterRootCrossoverBase * > _flutter_crossovers
the map of flutter crossover points versus average kr of the two bounding roots 
const MAST::FlutterRootBase & get_root(const unsigned int n) const
returns the n th root in terms of ascending velocity that is found by the solver 
void _initialize_matrix_sensitivity_for_kr(Real kr, ComplexMatrixX &A, ComplexMatrixX &B)
Assembles the sensitivity of matrices wrt kr. 
MAST::Parameter * _bref_param
reference chord 
MAST::Parameter * _kr_param
Parameter that define the reduced frequency. 
std::pair< MAST::FlutterSolutionBase *, MAST::FlutterSolutionBase * > crossover_solutions
virtual void _identify_crossover_points()
identifies all cross-over and divergence points from analyzed roots 
virtual void assemble_reduced_order_quantity_sensitivity(const MAST::FunctionBase &f, std::vector< libMesh::NumericVector< Real > *> &basis, std::map< MAST::StructuralQuantityType, RealMatrixX *> &mat_qty_map)
calculates the sensitivity of reduced order matrix given the basis provided in basis. 
virtual void sort(const MAST::FlutterSolutionBase &sol)
sort this root with respect to the given solution from a previous eigen solution. ...
std::map< Real, MAST::FlutterSolutionBase * > _flutter_solutions
map of kr sorted flutter solutions 
virtual std::unique_ptr< MAST::FlutterSolutionBase > _analyze(const Real kr_ref, const MAST::FlutterSolutionBase *prev_sol=nullptr)
performs an eigensolution at the specified reference value, and sort the roots based on the provided ...
void initialize(MAST::Parameter &kr_param, MAST::Parameter &bref_param, Real rho, Real kr_lower, Real kr_upper, unsigned int n_kr_divs, std::vector< libMesh::NumericVector< Real > *> &basis)
initializes the data structres for a flutter solution. 
MAST::StructuralFluidInteractionAssembly * _assembly
structural assembly that provides the assembly of the system matrices. 
RealVectorX modal_participation
ComplexVectorX eig_vec_right
right and left eigenvevtors 
UGFlutterSolver()
defalut constructor 
void clear()
clears the solution and other data from this solver 
virtual void clear()
clears the solution and other data from this solver 
virtual void clear_solutions()
clears the solutions stored from a previous analysis. 
bool has_sensitivity_data
void initialize(std::vector< libMesh::NumericVector< Real > *> &basis)
initializes the data structres for a flutter solution. 
virtual std::pair< bool, MAST::FlutterRootBase * > find_next_root(const Real g_tol, const unsigned int n_bisection_iters)
Looks through the list of flutter cross-over points and iteratively zooms in to find the cross-over p...
MAST::FlutterRootBase * root