This example solves for the flutter speed of a semi-infinite (2D) panel with
Initialize libMesh library.
libMesh::LibMeshInit init(argc, argv);
initialize the wrapper to read input parameters. This will check if the executable parameters included a parameter of type input=${filename}
. If included, then the input parameters will be read from this filename. Otherwise, the parameters will be read from the executable arguments. The wrapper uses default values for parameters if none are provided.
MAST::Examples::GetPotWrapper
input(argc, argv, "input");
const unsigned int
dim = 2,
nx_divs = 3,
ny_divs = 1,
panel_bc_id = 4,
symmetry_bc_id = 5,
n_modes = input("n_modes", "number of structural modes to use for creation of reduced order flutter eigenproblem", 8),
n_divs_ff_to_panel = input("n_divs_farfield_to_panel", "number of element divisions from far-field to panel", 30),
n_divs_panel = input("n_divs_panel", "number of element divisions on panel", 10),
n_k_divs = input("n_k_divs", "number of divisions between upper and lower reduced frequencies for search of flutter root", 10),
max_bisection_iters = input("flutter_max_bisection_it", "maximum number of bisection iterations to search flutter root after initial sweep of reduced frequencies", 10);
k_upper = input("k_upper", "upper value of reduced frequency for flutter solver", 0.75),
k_lower = input("k_lower", "lower value of reduced frequency for flutter solver", 0.00),
tol = input( "g_tol", "tolerace for convergence of damping of flutter root", 1e-4),
length = input("panel_l", "length of panel", 0.3),
ff_to_panel_l = input("farfield_to_l_ratio", "Ratio of distance of farfield boundary to panel length", 5.0),
ff_to_panel_e_size = input("farfield_to_panel_elem_size_ratio", "Ratio of element size at far-field to element size at panel", 20.0);
Initialize Fluid Solver
std::string s;
s = input("fe_order", "order of finite element shape basis functions", "first");
libMesh::Order
fe_order = libMesh::Utility::string_to_enum<libMesh::Order>(s);
s = input("fluid_elem_type", "type of geometric element in the fluid mesh", "quad4");
libMesh::ElemType
elem_type = libMesh::Utility::string_to_enum<libMesh::ElemType>(s);
s = input("fe_family", "family of finite element shape functions", "lagrange");
libMesh::FEFamily
fe_family = libMesh::Utility::string_to_enum<libMesh::FEFamily>(s);
setting up fluid mesh
std::vector<Real>
x_div_loc = {-length*ff_to_panel_l, 0., length, length*(1.+ff_to_panel_l)},
x_relative_dx = {ff_to_panel_e_size, 1., 1., ff_to_panel_e_size},
y_div_loc = {0., length*ff_to_panel_l},
y_relative_dx = {1., ff_to_panel_e_size};
std::vector<unsigned int>
x_divs = {n_divs_ff_to_panel, n_divs_panel, n_divs_ff_to_panel},
y_divs = {n_divs_ff_to_panel};
MAST::MeshInitializer::CoordinateDivisions
x_coord_divs,
y_coord_divs;
x_coord_divs.init(nx_divs, x_div_loc, x_relative_dx, x_divs);
y_coord_divs.init(ny_divs, y_div_loc, y_relative_dx, y_divs);
std::vector<MAST::MeshInitializer::CoordinateDivisions*>
divs = {&x_coord_divs, &y_coord_divs};
initialize the fluid mesh
libMesh::ParallelMesh
fluid_mesh(init.comm());
initialize the mesh
MAST::PanelMesh2D().init(0.,
false,
0,
divs,
fluid_mesh,
elem_type);
initialize equation system
libMesh::EquationSystems
fluid_eq_sys(fluid_mesh);
add the system to be used for fluid analysis
fluid properties, boundary conditions
fluid_discipline(fluid_eq_sys);
variables
fluid_sys_init(fluid_sys,
fluid_sys.name(),
libMesh::FEType(fe_order, fe_family), dim);
keep fluid boundary on all partitions
MAST::AugmentGhostElementSendListObj augment_send_list_obj(fluid_sys);
fluid_sys.get_dof_map().attach_extra_send_list_object(augment_send_list_obj);
fluid_eq_sys.init();
print the information
fluid_mesh.print_info();
fluid_eq_sys.print_info();
create the boundary conditions for slip-wall and far-field
tell the physics about boundary conditions
fluid_discipline.add_side_load( panel_bc_id, slip_wall);
fluid_discipline.add_side_load(symmetry_bc_id, symm_wall);
for (unsigned int i=1; i<=3; i++)
fluid_discipline.add_side_load(i, far_field);
set fluid properties
flight_cond.
mach = input(
"fluid_mach",
"fluid Mach number", 0.5);
flight_cond.
gas_property.
cp = input(
"fluid_cp",
"fluid specific heat at constant pressure", 1003.);
flight_cond.
gas_property.
cv = input(
"fluid_cv",
"fluid specific heat at constant volume", 716.);
flight_cond.
gas_property.
T = input(
"fluid_T",
"fluid absolute temperature", 300.);
tell the discipline about the fluid values
fluid_discipline.set_flight_condition(flight_cond);
define parameters
omega ( "omega", 0.),
b_ref ( "b_ref", length);
now define the constant field functions based on this
omega_f ( "omega", omega),
velocity_f ("velocity", velocity),
b_ref_f ( "b_ref", b_ref);
TODO: replace with interpolation
pressure_function(fluid_sys_init, flight_cond);
pressure_function.set_calculate_cp(true);
freq_domain_pressure_function(fluid_sys_init, flight_cond);
freq_domain_pressure_function.set_calculate_cp(true);
Initialize Structural Solver
x_div_loc = {0.0, length};
x_relative_dx = {1., 1.};
x_divs = {n_divs_panel};
MAST::MeshInitializer::CoordinateDivisions
x_coord_divs_struct;
x_coord_divs_struct.init(1, x_div_loc, x_relative_dx, x_divs);
divs = {&x_coord_divs_struct};
create the mesh
libMesh::SerialMesh structural_mesh(init.comm());
if (elem_type == libMesh::QUAD4)
MAST::MeshInitializer().init(divs, structural_mesh, libMesh::EDGE2);
else if (elem_type == libMesh::QUAD8 || elem_type == libMesh::QUAD9)
MAST::MeshInitializer().init(divs, structural_mesh, libMesh::EDGE3);
create the equation system
libMesh::EquationSystems structural_eq_sys(structural_mesh);
create the libmesh system
initialize the system to the right set of variables
structural_discipline(structural_eq_sys);
structural_sys_init(structural_sys,
structural_sys.name(),
libMesh::FEType(fe_order, fe_family));
create and add the boundary condition and loads
dirichlet_left,
dirichlet_right;
std::vector<unsigned int> constrained_vars = {0, 1, 2, 3};
dirichlet_left.
init (0, constrained_vars);
dirichlet_right.
init(1, constrained_vars);
structural_discipline.add_dirichlet_bc(0, dirichlet_left);
structural_discipline.add_dirichlet_bc(1, dirichlet_right);
structural_discipline.init_system_dirichlet_bc(structural_sys);
MAST::ConstrainBeamDofs constraint_beam_dofs(structural_sys);
structural_sys.attach_constraint_object(constraint_beam_dofs);
initialize the equation system
structural_eq_sys.init();
print information
structural_mesh.print_info();
structural_eq_sys.print_info();
TODO: replace this functionality in conservative_fluid_element
displ(structural_sys_init, "frequency_domain_displacement");
normal_rot("frequency_domain_normal_rotation", displ);
slip_wall.add(displ);
slip_wall.add(normal_rot);
set up structural eigenvalue problem
structural_sys.
eigen_solver->set_position_of_spectrum(libMesh::LARGEST_MAGNITUDE);
create the property functions and add them to the material property card
thy ("thy", input("str_thickness", "thickness of beam", 0.0015)),
thz ("thz", 1.00),
rho ("rho", input("str_rho", "structural material density", 2.7e3)),
E ("E", input("str_E", "structural material Young's modulus", 72.e9)),
nu ("nu", input("str_nu", "structural material Poisson's ratio", 0.33)),
kappa ("kappa", 5./6.),
zero ("zero", 0.);
thy_f ("hy", thy),
thz_f ("hz", thz),
rho_f ("rho", rho),
E_f ("E", E),
nu_f ("nu", nu),
kappa_f ("kappa", kappa),
hyoff_f ("hy_off", zero),
hzoff_f ("hz_off", zero);
m_card;
p_card;
tell the card about the orientation
p_card.
y_vector() = RealVectorX::Zero(3);
add the section properties to the card
tell the section property about the material property
structural_discipline.set_property_for_subdomain(0, p_card);
pressure boundary condition for the beam
pressure.add(pressure_function);
pressure.add(freq_domain_pressure_function);
structural_discipline.add_volume_load(0, pressure);
Initialize Flutter Solver
initialize the frequency function
freq_function("freq", omega_f, velocity_f, b_ref_f);
freq_function.if_nondimensional(true);
INITIALIZE FLUID SOLUTION
the modal and flutter problems are solved on rank 0, while the fluid solution is setup on the global communicator
initialize the solution
fluid_ff_vars << flight_cond.
rho(),
create the vector for storing the base solution. we will swap this out with the system solution, initialize and then swap it back.
libMesh::NumericVector<Real>& base_sol =
fluid_sys.add_vector("fluid_base_solution");
fluid_sys.solution->swap(base_sol);
fluid_sys_init.initialize_solution(fluid_ff_vars);
fluid_sys.solution->swap(base_sol);
create the nonlinear assembly object
now set up the assembly objects
pressure_function.init(base_sol);
Solution
Structural Modal Solution
structural_sys.nonlinear_solver->nearnullspace_object = &nsp;
Get the number of converged eigen pairs.
unsigned int
std::vector<libMesh::NumericVector<Real>*> basis(nconv, nullptr);
libMesh::ExodusII_IO writer(structural_mesh);
for (unsigned int i=0; i<nconv; i++) {
create a vector to store the basis
basis[i] = structural_sys.solution->zero_clone().release();
now write the eigenvalue
re = 0.,
im = 0.;
libMesh::out
<< std::setw(35) << std::fixed << std::setprecision(15)
<< re << std::endl;
We write the file in the ExodusII format. copy the solution for output
structural_sys.solution->swap(*basis[i]);
writer.write_timestep("modes.exo",
structural_eq_sys,
i+1, i);
structural_sys.solution->swap(*basis[i]);
}
Flutter Solution
solver for complex solution
fsi_assembly.
init(fsi_elem_ops,
solver,
complex_assembly,
fluid_elem_ops,
pressure_function,
freq_domain_pressure_function,
displ);
b_ref,
k_lower,
k_upper,
n_k_divs,
basis);
std::ostringstream oss;
oss << "flutter_output_" << init.comm().rank() << ".txt";
if (init.comm().rank() == 0)
find the roots for the specified divisions
now ask the flutter solver to return the critical flutter root, which is the flutter cross-over point at the lowest velocity
std::pair<bool, MAST::FlutterRootBase*>
make sure solution was found
libmesh_assert(sol.first);
Plot Flutter Solution
MAST::plot_structural_flutter_solution("structural_flutter_mode.exo",
structural_sys,
sol.second->eig_vec_right,
basis);
MAST::plot_fluid_flutter_solution("fluid_flutter_mode.exo",
structural_sys,
fluid_sys,
displ,
solver,
sol.second->eig_vec_right,
basis);
cleanup the data structures
delete the basis vectors
for (unsigned int i=0; i<basis.size(); i++)
if (basis[i]) delete basis[i];