36 _velocity_param(nullptr),
57 _V_range = std::pair<Real, Real>(0.,0.);
71 unsigned int n_V_divs,
72 std::vector<libMesh::NumericVector<Real> *>& basis) {
88 std::map<Real, MAST::FlutterSolutionBase*>::iterator it =
94 std::multimap<Real, MAST::FlutterRootCrossoverBase*>::iterator cross_it =
98 delete cross_it->second;
110 std::multimap<Real, MAST::FlutterRootCrossoverBase*>::const_iterator
115 for ( ; it!=end; it++)
116 if (it->second->root)
131 std::multimap<Real, MAST::FlutterRootCrossoverBase*>::const_iterator
135 unsigned int root_num = 0;
136 for ( ; it!=end; it++) {
137 if (it->second->root) {
139 return *(it->second->root);
145 libmesh_assert(
false);
152 std::pair<bool, MAST::FlutterRootBase*>
154 const unsigned int n_bisection_iters)
158 std::multimap<Real, MAST::FlutterRootCrossoverBase*>::iterator
166 const unsigned int root_num = cross->
root_num;
167 std::pair<bool, MAST::FlutterSolutionBase*> sol;
176 root_num, g_tol, n_bisection_iters);
178 cross->
root = &(sol.second->get_root(root_num));
183 std::pair<Real, MAST::FlutterRootCrossoverBase*>
184 val(cross->
root->
V, cross);
186 return std::pair<bool, MAST::FlutterRootBase*> (
true, cross->
root);
193 return std::pair<bool, MAST::FlutterRootBase*> (
false,
nullptr);
198 std::pair<bool, MAST::FlutterRootBase*>
200 const unsigned int n_bisection_iters)
204 std::multimap<Real, MAST::FlutterRootCrossoverBase*>::iterator
209 return std::pair<bool, MAST::FlutterRootBase*> (
false,
nullptr);
214 while (!it->second->root)
220 const unsigned int root_num = cross->
root_num;
221 std::pair<bool, MAST::FlutterSolutionBase*> sol;
230 root_num, g_tol, n_bisection_iters);
232 cross->
root = &(sol.second->get_root(root_num));
237 std::pair<Real, MAST::FlutterRootCrossoverBase*>
238 val(cross->
root->
V, cross);
247 return std::pair<bool, MAST::FlutterRootBase*> (
true, it->second->root);
254 std::pair<bool, MAST::FlutterRootBase*>
257 const unsigned int n_bisection_iters) {
279 *lower_root =
nullptr,
280 *upper_root =
nullptr;
282 std::pair<unsigned int, unsigned int>
283 bracket_n_unstable_roots(0, 0);
296 libmesh_assert(!bracket_n_unstable_roots.first);
301 (lower_V, sol)).second;
303 libmesh_assert(if_success);
313 upper_V = lower_V + dV;
315 sol =
_analyze(upper_V, sol).release();
324 (upper_V, sol)).second;
326 libmesh_assert(if_success);
329 if (bracket_n_unstable_roots.second ||
340 bracket_n_unstable_roots.first = bracket_n_unstable_roots.second;
341 bracket_n_unstable_roots.second = 0;
342 lower_root = upper_root;
346 std::pair<bool, MAST::FlutterRootBase*> rval(
false,
nullptr);
349 if (!bracket_n_unstable_roots.second)
353 unsigned int n_iters = 0;
355 while (n_iters < n_bisection_iters) {
358 lower_g = lower_root->
root.real();
359 upper_g = upper_root->root.real();
371 0.5*(upper_V-lower_V)/(upper_g-lower_g)*(1.e-4-upper_g);
373 sol =
_analyze(new_V, sol).release();
383 (new_V, sol)).second;
385 libmesh_assert(if_success);
389 if ((root->
root.real() > 0.) &&
390 (root->
root.real() <= g_tol)) {
398 if (root->
root.real() < 0.) {
401 lower_g = root->
root.real();
407 upper_g = root->
root.real();
434 for (
unsigned int i=0; i<
_n_V_divs+1; i++) {
435 V_vals[i] = current_V;
436 current_V += delta_V;
441 for (
unsigned int i=0; i<_n_V_divs+1; i++) {
442 current_V = V_vals[i];
443 std::unique_ptr<MAST::TimeDomainFlutterSolution>
444 sol =
_analyze(current_V, prev_sol);
446 prev_sol = sol.get();
454 (current_V, sol.release())).second;
456 libmesh_assert(if_success);
474 std::map<Real, MAST::FlutterSolutionBase*>::const_iterator
477 libmesh_assert(sol_it != sol_end);
479 unsigned int nvals = sol_it->second->n_roots();
480 libmesh_assert(nvals);
483 for (
unsigned int i=0; i<nvals; i++)
488 << std::setw(5) << i <<
" **" << std::endl
489 << std::setw(15) <<
"V_ref" 490 << std::setw(15) <<
"Re" 491 << std::setw(15) <<
"Im" << std::endl;
497 for ( ; sol_it != sol_end; sol_it++)
500 sol_it->second->get_root(i);
503 << std::setw(15) << root.
V 504 << std::setw(15) << std::real(root.
root)
505 << std::setw(15) << std::imag(root.
root) << std::endl;
507 *
_output << std::endl << std::endl;
512 std::streamsize prec =
_output->precision();
516 <<
"n critical roots identified: " << nroots << std::endl;
517 for (
unsigned int i=0; i<nroots; i++)
521 <<
"** Root : " << std::setw(5) << i <<
" **" << std::endl
522 <<
"V = " << std::setw(15) << std::setprecision(15) << root.
V << std::endl
523 <<
"g = " << std::setw(15) << std::real(root.
root) << std::endl
524 <<
"omega = " << std::setw(15) << std::imag(root.
root) << std::endl
525 << std::setprecision((
int) prec)
526 <<
"Modal Participation : " << std::endl ;
527 for (
unsigned int j=0; j<nvals; j++)
529 <<
"(" << std::setw(5) << j <<
"): " 531 << std::setw(3) <<
" ";
532 *
_output << std::endl << std::endl;
546 *
_output <<
"n crossover points found: " 549 std::multimap<Real, MAST::FlutterRootCrossoverBase*>::const_iterator
554 for ( ; it != end; it++) {
555 *
_output <<
"** Point : " << std::setw(5) << i <<
" **" << std::endl;
566 std::pair<bool, MAST::FlutterSolutionBase*>
570 const unsigned int root_num,
572 const unsigned int max_iters) {
577 lower_V = ref_sol_range.first->ref_val(),
578 lower_g = ref_sol_range.first->get_root(root_num).root.real(),
579 upper_V = ref_sol_range.second->ref_val(),
580 upper_g = ref_sol_range.second->get_root(root_num).root.real(),
582 unsigned int n_iters = 0;
585 std::pair<bool, MAST::FlutterSolutionBase*> rval(
false,
nullptr);
587 while (n_iters < max_iters) {
590 (upper_V-lower_V)/(upper_g-lower_g)*(0.-lower_g);
592 new_sol =
_analyze(new_V, ref_sol_range.first).release();
600 (new_V, new_sol)).second;
602 libmesh_assert(if_success);
607 if (fabs(root.
root.real()) <= g_tol) {
610 rval.second = new_sol;
615 if (root.
root.real() < 0.) {
618 lower_g = root.
root.real();
623 upper_g = root.
root.real();
631 rval.second = new_sol;
639 std::unique_ptr<MAST::TimeDomainFlutterSolution>
644 <<
" ====================================================" << std::endl
645 <<
"Eigensolution" << std::endl
646 <<
" V_ref = " << std::setw(10) << v_ref << std::endl;
660 root->
init(*
this, v_ref, ges);
662 root->
sort(*prev_sol);
665 <<
"Finished Eigensolution" << std::endl
666 <<
" ====================================================" << std::endl;
669 return std::unique_ptr<MAST::TimeDomainFlutterSolution> (root);
700 (*_velocity_param) = U_inf;
707 <<
"*** Performing Steady State Solve ***" << std::endl;
716 m = RealMatrixX::Zero(n, n),
717 c = RealMatrixX::Zero(n, n),
718 k = RealMatrixX::Zero(n, n);
723 std::map<MAST::StructuralQuantityType, RealMatrixX*> qty_map;
738 B.topLeftCorner(n, n) = RealMatrixX::Identity(n,n );
739 B.bottomRightCorner(n, n) = m;
742 A.topRightCorner(n, n) = RealMatrixX::Identity(n, n);
743 A.bottomLeftCorner(n, n) = -k;
744 A.bottomRightCorner(n, n) = -c;
755 const libMesh::NumericVector<Real>& dXdp,
781 m = RealMatrixX::Zero(n, n),
782 c = RealMatrixX::Zero(n, n),
783 k = RealMatrixX::Zero(n, n);
788 std::map<MAST::StructuralQuantityType, RealMatrixX*> qty_map;
795 (*_velocity_param) = U_inf;
808 B.topLeftCorner(n, n) = RealMatrixX::Identity(n,n );
809 B.bottomRightCorner(n, n) = m;
812 A.topRightCorner(n, n) = RealMatrixX::Identity(n, n);
813 A.bottomLeftCorner(n, n) = -k;
814 A.bottomRightCorner(n, n) = -c;
830 const Real tol = 1.0e-5;
834 libmesh_assert(nvals);
843 std::vector<bool> modes_to_neglect(nvals);
844 std::fill(modes_to_neglect.begin(),
845 modes_to_neglect.end(),
false);
849 for (
unsigned int i=0; i<nvals; i++) {
851 std::map<Real, MAST::FlutterSolutionBase*>::const_iterator
862 for ( ; sol_it!=sol_end; sol_it++) {
864 g_val = fabs(sol_it->second->get_root(i).root.real());
865 w_val = sol_it->second->get_root(i).root.imag();
868 if (g_val > max_g_val)
871 if (w_val > max_w_val)
876 if (max_g_val < tol || max_w_val < 0.)
877 modes_to_neglect[i] =
true;
882 for (
unsigned int i=0; i<nvals; i++) {
884 std::map<Real, MAST::FlutterSolutionBase*>::const_iterator
889 if (sol_it == sol_end)
893 bool if_process =
false;
895 while (sol_itp1 != sol_end) {
899 (fabs(sol_it->second->ref_val()) > tol ||
900 fabs(sol_itp1->second->ref_val()) > tol) &&
906 !modes_to_neglect[i]);
913 *lower = sol_it->second,
914 *upper = sol_itp1->second;
917 (upper->get_root(i).root.real() > 0.)) {
924 std::pair<Real, MAST::FlutterRootCrossoverBase*>
929 (upper->get_root(i).root.real() <= 0.)) {
936 std::pair<Real, MAST::FlutterRootCrossoverBase*>
937 val( upper->get_root(i).V, cross);
955 (fabs(sol_it->second->ref_val()) > tol ||
956 fabs(sol_itp1->second->ref_val()) > tol) &&
962 !modes_to_neglect[i]);
964 Real g_val = sol_it->second->get_root(i).root.real();
979 std::pair<Real, MAST::FlutterRootCrossoverBase*>
980 val( sol_it->second->get_root(i).V, cross);
994 libMesh::NumericVector<Real>* dXdp,
995 libMesh::NumericVector<Real>* dXdV) {
1000 <<
" ====================================================" << std::endl
1001 <<
"Flutter Sensitivity Solution" << std::endl
1002 <<
" V_ref = " << std::setw(10) << root.
V << std::endl;
1024 libMesh::NumericVector<Real>* sol_sens = dXdp;
1025 std::unique_ptr<libMesh::NumericVector<Real> > zero_sol_sens;
1027 zero_sol_sens.reset(
_assembly->
system().solution->zero_clone().release());
1028 sol_sens = zero_sol_sens.get();
1059 sol_sens = zero_sol_sens.get();
1082 root.
V_sens = - deig_dp.real() / deig_dV.real();
1090 <<
"Finished Flutter Sensitivity Solution" << std::endl
1091 <<
" ====================================================" << std::endl;
TimeDomainFlutterSolver()
defalut constructor
virtual std::pair< bool, MAST::FlutterRootBase * > analyze_and_find_critical_root_without_tracking(const Real g_tol, const unsigned int n_iters)
This root starts with the lower velocity and increments the speed till a single unstable root is iden...
const MAST::FlutterRootBase & get_root(const unsigned int i) const
virtual void _identify_crossover_points()
identifies all cross-over and divergence points from analyzed roots
ComplexVectorX eig_vec_left
std::vector< libMesh::NumericVector< Real > * > * _basis_vectors
basis vector used to define the reduced order model
MAST::Parameter * _velocity_param
Parameter that define the velocity.
virtual void print(std::ostream &output)
prints the data and modes from this solution
void clear_base_solution(bool if_sens=false)
Clears the pointer to base solution.
virtual void print(std::ostream &output)=0
prints the data and modes from this solution
unsigned int n_unstable_roots_in_upper_complex_half(Real tol) const
number of unstable roots in this solution.
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 clear()
clears the solution and other data from this solver
virtual void calculate_sensitivity(MAST::FlutterRootBase &root, const MAST::FunctionBase &f, libMesh::NumericVector< Real > *dXdp=nullptr, libMesh::NumericVector< Real > *dXdV=nullptr)
Calculate the sensitivity of the flutter root with respect to the f parameter.
virtual void print_crossover_points()
Prints the crossover points output.
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.
Matrix< Complex, Dynamic, 1 > ComplexVectorX
void initialize(MAST::Parameter &velocity_param, Real V_lower, Real V_upper, unsigned int n_V_divs, std::vector< libMesh::NumericVector< Real > * > &basis)
initializes the data structres for a flutter solution.
This is a scalar function whose value can be changed and one that can be used as a design variable in...
virtual std::unique_ptr< MAST::TimeDomainFlutterSolution > _analyze(const Real v_ref, const MAST::FlutterSolutionBase *prev_sol=nullptr)
performs an eigensolution at the specified reference value, and sort the roots based on the provided ...
MAST::FlutterSolverBase::SteadySolver * _steady_solver
object provides the steady state solution.
void init(const MAST::TimeDomainFlutterSolver &solver, const Real v_ref, const MAST::LAPACK_DGGEV &eig_sol)
initializes the root
std::multimap< Real, MAST::FlutterRootCrossoverBase * > _flutter_crossovers
the map of flutter crossover points versus average velocity of the two bounding roots ...
void _initialize_matrices(Real U_inf, RealMatrixX &A, RealMatrixX &B)
Assembles the reduced order system structural and aerodynmaic matrices for specified flight velocity ...
std::ofstream * _output
file to which the result will be written
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
virtual void print_sorted_roots()
Prints the sorted roots to the output.
Matrix< Real, Dynamic, Dynamic > RealMatrixX
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.
virtual ~TimeDomainFlutterSolver()
MAST::FlutterRootBase * get_critical_root(Real tol)
void set_base_solution(const libMesh::NumericVector< Real > &sol, bool if_sens=false)
if the eigenproblem is defined about a non-zero base solution, then this method provides the object w...
virtual unsigned int n_roots_found() const
finds the number of critical points already identified in the procedure.
void initialize(std::vector< libMesh::NumericVector< Real > * > &basis)
initializes the data structres for a flutter solution.
virtual void sort(const MAST::FlutterSolutionBase &sol)
sort this root with respect to the given solution from a previous eigen solution. ...
std::pair< Real, Real > _V_range
range of reference values within which to find flutter roots
std::pair< MAST::FlutterSolutionBase *, MAST::FlutterSolutionBase * > crossover_solutions
virtual const libMesh::NumericVector< Real > & solve()=0
solves for the steady state solution, and
virtual void scan_for_roots()
Scans for flutter roots in the analyzed points, and identified the divergence (if k_red = 0...
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...
MAST::StructuralFluidInteractionAssembly * _assembly
structural assembly that provides the assembly of the system matrices.
unsigned int _n_V_divs
number of division in the reference value range for initial scanning
RealVectorX modal_participation
virtual void clear_solutions()
clears the solutions stored from a previous analysis.
void compute(const RealMatrixX &A, const RealMatrixX &B, bool computeEigenvectors=true)
computes the eigensolution for .
std::map< Real, MAST::FlutterSolutionBase * > _flutter_solutions
map of velocity sorted flutter solutions
ComplexVectorX eig_vec_right
right and left eigenvevtors
const MAST::NonlinearSystem & system() const
virtual void clear()
clears the solution and other data from this solver
bool has_sensitivity_data
void _initialize_matrix_sensitivity_for_param(const MAST::FunctionBase &f, const libMesh::NumericVector< Real > &dXdp, Real U_inf, RealMatrixX &A, RealMatrixX &B)
Assembles the reduced order system structural and aerodynmaic matrices for specified flight velocity ...
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
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