void MAST::StructuralElement2D:: initialize_von_karman_strain_operator_sensitivity(const unsigned int qp, RealMatrixX &vk_dwdxi_mat_sens) { const std::vector<std::vector<libMesh::RealVectorValue> >& dphi = _fe->get_dphi(); const unsigned int n_phi = (unsigned int)dphi.size(); libmesh_assert_equal_to(vk_dwdxi_mat_sens.rows(), 3); libmesh_assert_equal_to(vk_dwdxi_mat_sens.cols(), 2); Real dw=0.; vk_dwdxi_mat_sens.setConstant(0.); RealVectorX phi_vec = RealVectorX::Zero(n_phi); dw = 0.; for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ ) { phi_vec(i_nd) = dphi[i_nd][qp](0); // dphi/dx dw += phi_vec(i_nd)*_local_sol_sens(2*n_phi+i_nd); // dw/dx } vk_dwdxi_mat_sens(0, 0) = dw; // epsilon-xx : dw/dx vk_dwdxi_mat_sens(2, 1) = dw; // gamma-xy : dw/dx dw = 0.; for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ ) { phi_vec(i_nd) = dphi[i_nd][qp](1); // dphi/dy dw += phi_vec(i_nd)*_local_sol_sens(2*n_phi+i_nd); // dw/dy } vk_dwdxi_mat_sens(1, 1) = dw; // epsilon-yy : dw/dy vk_dwdxi_mat_sens(2, 0) = dw; // gamma-xy : dw/dy }
void MAST::OrthotropicProperty3D:: StiffnessMatrix::operator() (const libMesh::Point& p, const Real t, RealMatrixX& m) const { RealMatrixX A = RealMatrixX::Zero(3, 3), Tinv = RealMatrixX::Zero(6, 6); _material_stiffness (p, t, m); _orient (p, t, A); _orient.stress_strain_transformation_matrix(A.transpose(), Tinv); // vk' = vj ej.ek' = vj Ajk = A^T v // v = A vk' // sij' = skl ek.ei' el.ej' = skl Aki Alj = A^T s A // s' = T s // s = Tinv s' // s' = C' e' // T s = C' Rinv T R s // s = Tinv C Rinv T R e // C = Tinv C Rinv T R // T R scales last three columns by 1/2 // Rinv T scales last three rows by 2 // therefore, Rinv T R scales top right 3x3 block by 1/2, // and bottom left 3x3 block by 2. // Also, Rinv T R = T^{-T} m = Tinv * m * Tinv.transpose(); }
void MAST::TimeDomainFlutterSolver::initialize_matrices(Real ref_val, RealMatrixX& a, // LHS RealMatrixX& b) // RHS { bool has_matrix = false; RealMatrixX mat1, mat2; Real q0 = flight_condition->q0(); // mass matrix forms the LHS of the eigenvalue problem has_matrix = aero_structural_model->get_structural_mass_matrix(mat1); const unsigned int n = (int)mat1.rows(); a.block(n,n,n,n) = mat1; libmesh_assert(has_matrix); // structural and aerodynamic stiffness matrices has_matrix = aero_structural_model->get_structural_stiffness_matrix(mat1); libmesh_assert(has_matrix); has_matrix = aero_structural_model->get_aero_stiffness_matrix(mat2); libmesh_assert(has_matrix); b.block(n, 0, n, n) = (q0*mat2-mat1); // structural and aerodynamic stiffness matrices has_matrix = aero_structural_model->get_structural_damping_matrix(mat1); libmesh_assert(has_matrix); has_matrix = aero_structural_model->get_aero_damping_matrix(mat2); libmesh_assert(has_matrix); b.block(n, 0, n, n) = (q0*mat2-mat1); // finally set the identity blocks in the matrix for (unsigned int i=0; i<n; i++) { a(i, i) = 1.; b(i,i+n) = 1.; } }
void MAST::StructuralElement2D::_convert_prestress_B_mat_to_vector(const RealMatrixX& mat, RealVectorX& vec) const { libmesh_assert_equal_to(mat.rows(), 2); libmesh_assert_equal_to(mat.cols(), 2); vec = RealVectorX::Zero(3); vec(0) = mat(0,0); // sigma x vec(1) = mat(1,1); // sigma y vec(2) = mat(0,1); // tau xy }
void MAST::OrthotropicProperty3D::ThermalConductanceMatrix:: operator() (const libMesh::Point& p, const Real t, RealMatrixX& m) const { RealMatrixX A = RealMatrixX::Zero(3, 3); _mat_cond (p, t, m); _orient (p, t, A); m = A.transpose() * m * A; }
virtual void operator() (const libMesh::Point& p, const Real t, RealMatrixX& m) const { // add the values of each matrix to get the integrated value RealMatrixX mi; for (unsigned int i=0; i<_layer_mats.size(); i++) { (*_layer_mats[i])(p, t, mi); // use the size of the layer matrix to resize the output // all other layers should return the same sized matrices if (i==0) m = RealMatrixX::Zero(mi.rows(), mi.cols()); m += mi; } }
virtual void derivative ( const MAST::FunctionBase& f, const libMesh::Point& p, const Real t, RealMatrixX& m) const { // add the values of each matrix to get the integrated value RealMatrixX mi; m = RealMatrixX::Zero(2,2); for (unsigned int i=0; i<_layer_mats.size(); i++) { _layer_mats[i]->derivative( f, p, t, mi); // use the size of the layer matrix to resize the output // all other layers should return the same sized matrices if (i==0) m = RealMatrixX::Zero(mi.rows(), mi.cols()); m += mi; } }
void MAST::StructuralElement2D:: initialize_von_karman_strain_operator(const unsigned int qp, RealVectorX& vk_strain, RealMatrixX& vk_dwdxi_mat, MAST::FEMOperatorMatrix& Bmat_vk) { const std::vector<std::vector<libMesh::RealVectorValue> >& dphi = _fe->get_dphi(); const unsigned int n_phi = (unsigned int)dphi.size(); libmesh_assert_equal_to(vk_strain.size(), 3); libmesh_assert_equal_to(vk_dwdxi_mat.rows(), 3); libmesh_assert_equal_to(vk_dwdxi_mat.cols(), 2); libmesh_assert_equal_to(Bmat_vk.m(), 2); libmesh_assert_equal_to(Bmat_vk.n(), 6*n_phi); Real dw=0.; vk_strain.setConstant(0.); vk_dwdxi_mat.setConstant(0.); RealVectorX phi_vec = RealVectorX::Zero(n_phi); dw = 0.; for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ ) { phi_vec(i_nd) = dphi[i_nd][qp](0); // dphi/dx dw += phi_vec(i_nd)*_local_sol(2*n_phi+i_nd); // dw/dx } Bmat_vk.set_shape_function(0, 2, phi_vec); // dw/dx vk_dwdxi_mat(0, 0) = dw; // epsilon-xx : dw/dx vk_dwdxi_mat(2, 1) = dw; // gamma-xy : dw/dx vk_strain(0) = 0.5*dw*dw; // 1/2 * (dw/dx)^2 vk_strain(2) = dw; // (dw/dx)*(dw/dy) only dw/dx is provided here dw = 0.; for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ ) { phi_vec(i_nd) = dphi[i_nd][qp](1); // dphi/dy dw += phi_vec(i_nd)*_local_sol(2*n_phi+i_nd); // dw/dy } Bmat_vk.set_shape_function(1, 2, phi_vec); // dw/dy vk_dwdxi_mat(1, 1) = dw; // epsilon-yy : dw/dy vk_dwdxi_mat(2, 0) = dw; // gamma-xy : dw/dy vk_strain(1) = 0.5*dw*dw; // 1/2 * (dw/dy)^2 vk_strain(2) *= dw; // (dw/dx)*(dw/dy) }
void MAST::TimeDomainFlutterRoot::init(const Real ref_val, const Real b_ref, const Complex num, const Complex den, const RealMatrixX& Bmat, const ComplexVectorX& evec_right, const ComplexVectorX& evec_left) { V = ref_val; if (std::abs(den) > 0.) { root = num/den; if (std::real(root) > 0.) { V = sqrt(1./std::real(root)); g = std::imag(root)/std::real(root); omega = k_red*V/b_ref; if_nonphysical_root = false; } else { V = 0.; g = 0.; omega = 0.; if_nonphysical_root = true; } } // calculate the modal participation vector const unsigned int nvals = (int)Bmat.rows(); eig_vec_right = evec_right; eig_vec_left = evec_left; ComplexVectorX k_q; k_q = Bmat * evec_right; modal_participation.resize(nvals, 1); for (unsigned int i=0; i<nvals; i++) modal_participation(i) = std::abs(std::conj(evec_right(i)) * k_q(i)); modal_participation *= (1./modal_participation.sum()); }
void MAST::LevelSetReinitializationTransientAssembly:: residual_and_jacobian (const libMesh::NumericVector<Real>& X, libMesh::NumericVector<Real>* R, libMesh::SparseMatrix<Real>* J, libMesh::NonlinearImplicitSystem& S) { libmesh_assert(_system); libmesh_assert(_discipline); libmesh_assert(_elem_ops); MAST::TransientSolverBase &solver = dynamic_cast<MAST::TransientSolverBase&>(*_elem_ops); MAST::NonlinearSystem &transient_sys = _system->system(); MAST::LevelSetTransientAssemblyElemOperations &level_set_elem_ops = dynamic_cast<MAST::LevelSetTransientAssemblyElemOperations&> (solver.get_elem_operation_object()); // make sure that the system for which this object was created, // and the system passed through the function call are the same libmesh_assert_equal_to(&S, &transient_sys); if (R) R->zero(); if (J) J->zero(); // iterate over each element, initialize it and get the relevant // analysis quantities RealVectorX vec, ref_sol; RealMatrixX mat; std::vector<libMesh::dof_id_type> dof_indices; const libMesh::DofMap& dof_map = transient_sys.get_dof_map(); // stores the localized solution, velocity, acceleration, etc. vectors. // These pointers will have to be deleted std::vector<libMesh::NumericVector<Real>*> local_qtys; std::unique_ptr<libMesh::NumericVector<Real> > localized_solution; localized_solution.reset(build_localized_vector(transient_sys, *_ref_sol).release()); // if a solution function is attached, initialize it if (_sol_function) _sol_function->init( X); // ask the solver to localize the relevant solutions solver.build_local_quantities(X, local_qtys); libMesh::MeshBase::const_element_iterator el = transient_sys.get_mesh().active_local_elements_begin(); const libMesh::MeshBase::const_element_iterator end_el = transient_sys.get_mesh().active_local_elements_end(); for ( ; el != end_el; ++el) { const libMesh::Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); solver.init(*elem); // get the solution unsigned int ndofs = (unsigned int)dof_indices.size(); vec.setZero(ndofs); ref_sol.setZero(ndofs); mat.setZero(ndofs, ndofs); for (unsigned int i=0; i<dof_indices.size(); i++) ref_sol(i) = (*localized_solution)(dof_indices[i]); solver.set_element_data(dof_indices, local_qtys); level_set_elem_ops.set_elem_reference_solution(ref_sol); // if (_sol_function) // physics_elem->attach_active_solution_function(*_sol_function); // perform the element level calculations solver.elem_calculations(J!=nullptr?true:false, vec, mat); solver.clear_elem(); // copy to the libMesh matrix for further processing DenseRealVector v; DenseRealMatrix m; if (R) MAST::copy(v, vec); if (J) MAST::copy(m, mat); // constrain the quantities to account for hanging dofs, // Dirichlet constraints, etc. if (R && J) dof_map.constrain_element_matrix_and_vector(m, v, dof_indices); else if (R) dof_map.constrain_element_vector(v, dof_indices); else dof_map.constrain_element_matrix(m, dof_indices); // add to the global matrices if (R) R->add_vector(v, dof_indices); if (J) J->add_matrix(m, dof_indices); } // delete pointers to the local solutions for (unsigned int i=0; i<local_qtys.size(); i++) delete local_qtys[i]; // if a solution function is attached, clear it if (_sol_function) _sol_function->clear(); if (R) R->close(); if (J) J->close(); }
void MAST::NoniterativeUGFlutterSolver::calculate_sensitivity(MAST::FlutterRootBase& root, const libMesh::ParameterVector& params, const unsigned int i) { // make sure that the aero_structural_model is a valid pointer libmesh_assert(aero_structural_model); libMesh::out << " ====================================================" << std::endl << "UG Sensitivity Solution" << std::endl << " k_red = " << std::setw(10) << root.k_red << std::endl << " V_ref = " << std::setw(10) << root.V << std::endl; Complex eig = root.root, sens = 0., k_sens = 0., vref_sens = 0., den = 0.; // matrix to store the sensitivity of constraint wrt kref and vref // first row is constraint f1(k,v) = g = im(lambda)/re(lambda) = 0 // second row is constraint f2(k,v) = vref*sqrt(re(lambda))-1. = 0 RealMatrixX jac; // residual vector for the sensitivity problem, and total derivative vec // first row is for constraint f1(k,v) // first row is for constraint f2(k,v) RealVectorX res, dsens; jac.setZero(2,2); res.setZero(2); // get the sensitivity of the matrices ComplexMatrixX mat_A, mat_B, mat_A_sens, mat_B_sens; ComplexVectorX v; // initialize the baseline matrices initialize_matrices(root.k_red_ref, root.V_ref, mat_A, mat_B); // calculate the eigenproblem sensitivity initialize_matrix_sensitivity_for_param(params, i, root.k_red_ref, root.V_ref, mat_A_sens, mat_B_sens); // the eigenproblem is A x - lambda B x = 0 // therefore, the denominator is obtained from the inner product of // x^T B x // sensitivity is // -dlambda/dp x^T B x = - x^T (dA/dp - lambda dB/dp) // or // dlambda/dp = [x^T (dA/dp - lambda dB/dp)]/(x^T B x) // now calculate the quotient for sensitivity // numerator = ( dA/dp - lambda dB/dp) mat_B_sens *= -eig; mat_B_sens += mat_A_sens; v = mat_B_sens*root.eig_vec_right; den = root.eig_vec_left.dot(mat_B*root.eig_vec_right); sens = root.eig_vec_left.dot(v)/den; // sensitivity of f1(k,v) = im(lambda)/re(lambda) = 0 res(0) = sens.imag()/eig.real() - eig.imag()/pow(eig.real(),2) * sens.real(); // sensitivity of f2(k,v) = vref*sqrt(real(lambda)) - 1 = 0 res(1) = root.V_ref*0.5*pow(eig.real(),-0.5)*sens.real(); // next we need the sensitivity of k_red before we can calculate // the sensitivity of flutter eigenvalue initialize_matrix_sensitivity_for_reduced_freq(root.k_red_ref, root.V_ref, mat_A_sens, mat_B_sens); // now calculate the quotient for sensitivity wrt k_red // calculate numerator mat_B_sens *= -eig; mat_B_sens += mat_A_sens; v = mat_B_sens*root.eig_vec_right; k_sens = root.eig_vec_left.dot(v) / den; // use this to calculate the partial derivative of f1 wrt k_red jac(0,0) = k_sens.imag()/eig.real() - eig.imag()/pow(eig.real(),2)*k_sens.real(); jac(1,0) = root.V_ref*0.5*pow(eig.real(),-0.5)*k_sens.real(); // next we need the sensitivity of Vref constraint before we can calculate // the sensitivity of flutter eigenvalue initialize_matrix_sensitivity_for_V_ref(root.k_red_ref, root.V_ref, mat_A_sens, mat_B_sens); // now calculate the quotient for sensitivity wrt k_red // calculate numerator mat_B_sens *= -eig; mat_B_sens += mat_A_sens; v = mat_B_sens*root.eig_vec_right; vref_sens = root.eig_vec_left.dot(v) / den; // use this to calculate the partial derivative of f2 wrt vref jac(0,1) = vref_sens.imag()/eig.real() - eig.imag()/pow(eig.real(),2)*vref_sens.real(); jac(1,1) = sqrt(eig.real()) + root.V_ref*0.5*pow(eig.real(),-0.5)*vref_sens.real(); // now invert the Jacobian to calculate the sensitivity dsens = -jac.inverse()*res; // finally add the correction to the flutter sensitivity sens += k_sens * dsens(0) + vref_sens * dsens(1); // set value in the return root root.has_sensitivity_data = true; root.root_sens = sens; root.V_sens = -.5*sens.real()/pow(eig.real(), 1.5); libMesh::out << "Finished UG Sensitivity Solution" << std::endl << " ====================================================" << std::endl; }
std::pair<bool, MAST::FlutterSolutionBase*> MAST::NoniterativeUGFlutterSolver::newton_search(const MAST::FlutterSolutionBase& init_sol, const unsigned int root_num, const Real tol, const unsigned int max_iters) { std::pair<bool, MAST::FlutterSolutionBase*> rval(false, NULL); // assumes that the upper k_val has +ve g val and lower k_val has -ve // k_val Real k_red, v_ref; unsigned int n_iters = 0; std::auto_ptr<MAST::FlutterSolutionBase> new_sol; RealVectorX res, sol, dsol; RealMatrixX jac; ComplexMatrixX mat_A, mat_B, mat_A_sens, mat_B_sens; ComplexVectorX v; res.resize(2); sol.resize(2); dsol.resize(2); jac.resize(2,2); // initialize the solution to the values of init_sol k_red = init_sol.get_root(root_num).k_red_ref; v_ref = init_sol.get_root(root_num).V_ref; sol(0) = k_red; sol(1) = v_ref; const MAST::FlutterSolutionBase* prev_sol = &init_sol; bool if_continue = true; while (if_continue) { // evaluate the residual and Jacobians std::auto_ptr<MAST::FlutterSolutionBase> ug_sol = this->analyze(k_red, v_ref, prev_sol); ug_sol->print(_output); // add the solution to this solver _insert_new_solution(v_ref, ug_sol.release()); // now get a pointer to the previous solution // get the solution from the database for this reduced frequency std::map<Real, MAST::FlutterSolutionBase*>::iterator it = _flutter_solutions.find(k_red); libmesh_assert(it != _flutter_solutions.end()); rval.second = it->second; prev_sol = it->second; // solve the Newton update problem const MAST::FlutterRootBase& root = prev_sol->get_root(root_num); Complex eig = root.root, eig_k_red_sens = 0., den = 0., eig_V_ref_sens = 0.; // initialize the baseline matrices initialize_matrices(k_red, v_ref, mat_A, mat_B); // solve the sensitivity problem // first with respect to k_red // next we need the sensitivity of k_red before we can calculate // the sensitivity of flutter eigenvalue initialize_matrix_sensitivity_for_reduced_freq(k_red, v_ref, mat_A_sens, mat_B_sens); // now calculate the quotient for sensitivity wrt k_red // calculate numerator mat_B_sens *= -eig; mat_B_sens += mat_A_sens; v = mat_B_sens*root.eig_vec_right; den = root.eig_vec_left.dot(mat_B*root.eig_vec_right); eig_k_red_sens = root.eig_vec_left.dot(v) / den; // next, sensitivity wrt V_ref initialize_matrix_sensitivity_for_V_ref(k_red, v_ref, mat_A_sens, mat_B_sens); // now calculate the quotient for sensitivity wrt V_ref // calculate numerator mat_B_sens *= -eig; mat_B_sens += mat_A_sens; v = mat_B_sens*root.eig_vec_right; den = root.eig_vec_left.dot(mat_B*root.eig_vec_right); eig_V_ref_sens = root.eig_vec_left.dot(v) / den; // residual res(0) = eig.imag()/eig.real(); res(1) = v_ref*sqrt(eig.real()) - 1.; // Jacobian jac(0,0) = eig_k_red_sens.imag()/eig.real() - eig.imag()*pow(eig.real(),-2)*eig_k_red_sens.real(); jac(0,1) = eig_V_ref_sens.imag()/eig.real() - eig.imag()*pow(eig.real(),-2)*eig_V_ref_sens.real(); jac(1,0) = 0.5*v_ref*pow(eig.real(),-0.5)*eig_k_red_sens.real(); jac(1,1) = sqrt(eig.real()) + 0.5*v_ref*pow(eig.real(),-0.5)*eig_V_ref_sens.real(); /*std::auto_ptr<MAST::FlutterSolutionBase> ug_dsol = this->analyze(k_red+.001, v_ref, prev_sol); Complex deig = ug_dsol->get_root(root_num).root; deig -= eig; deig /= .001; std::cout << "fd deig/dk: " << deig << std::endl; std::cout << "analytical: " << eig_k_red_sens << std::endl; ug_dsol.reset(this->analyze(k_red, v_ref+.001, prev_sol).release()); deig = ug_dsol->get_root(root_num).root; deig -= eig; deig /= .001; std::cout << "fd deig/dV: " << deig << std::endl; std::cout << "analytical: " << eig_V_ref_sens << std::endl;*/ // now calculate the updates // r0 + J *dx = 0 // => dx = - inv(J) * r0 // => x1 = x0 + dx dsol = -jac.inverse()*res; sol += dsol; // get the updated parameter values k_red = sol(0); v_ref = sol(1); // increment the iteration counter n_iters++; // set the flag if (fabs(root.g) < tol) { rval.first = true; return rval; } if (n_iters >= max_iters) if_continue = false; } // return false, along with the latest sol rval.first = false; return rval; }
void MAST::StructuralElement2D:: _linearized_geometric_stiffness_sensitivity_with_static_solution (const unsigned int n2, const unsigned int qp, const std::vector<Real>& JxW, RealMatrixX& local_jac, FEMOperatorMatrix& Bmat_mem, FEMOperatorMatrix& Bmat_bend, FEMOperatorMatrix& Bmat_vk, RealMatrixX& stress_l, RealMatrixX& vk_dwdxi_mat, RealMatrixX& material_A_mat, RealMatrixX& material_B_mat, RealVectorX& vec1_n1, RealVectorX& vec2_n1, RealMatrixX& mat1_n1n2, RealMatrixX& mat2_n2n2, RealMatrixX& mat3) { this->initialize_direct_strain_operator(qp, Bmat_mem); _bending_operator->initialize_bending_strain_operator(qp, Bmat_bend); // first handle constant throught the thickness stresses: membrane and vonKarman Bmat_mem.vector_mult(vec1_n1, _local_sol_sens); vec2_n1 = material_A_mat * vec1_n1; // linear direct stress // copy the stress values to a matrix stress_l(0,0) = vec2_n1(0); // sigma_xx stress_l(0,1) = vec2_n1(2); // sigma_xy stress_l(1,0) = vec2_n1(2); // sigma_yx stress_l(1,1) = vec2_n1(1); // sigma_yy // get the von Karman operator matrix this->initialize_von_karman_strain_operator(qp, vec2_n1, // epsilon_vk vk_dwdxi_mat, Bmat_vk); // sensitivity of the vk_dwdxi matrix due to solution sensitivity this->initialize_von_karman_strain_operator_sensitivity(qp, vk_dwdxi_mat); // membrane - vk mat3 = RealMatrixX::Zero(vk_dwdxi_mat.rows(), n2); Bmat_vk.left_multiply(mat3, vk_dwdxi_mat); mat3 = material_A_mat * mat3; Bmat_mem.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // vk - membrane Bmat_mem.left_multiply(mat1_n1n2, material_A_mat); mat3 = vk_dwdxi_mat.transpose() * mat1_n1n2; Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // vk - vk: first order term mat3 = RealMatrixX::Zero(2, n2); Bmat_vk.left_multiply(mat3, stress_l); Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // bending - vk mat3 = RealMatrixX::Zero(vk_dwdxi_mat.rows(), n2); Bmat_vk.left_multiply(mat3, vk_dwdxi_mat); mat3 = material_B_mat.transpose() * mat3; Bmat_bend.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // vk - bending Bmat_bend.left_multiply(mat1_n1n2, material_B_mat); mat3 = vk_dwdxi_mat.transpose() * mat1_n1n2; Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; }
void MAST::LAPACK_DGGEV::compute(const RealMatrixX &A, const RealMatrixX &B, bool computeEigenvectors) { libmesh_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows()); _A = A; _B = B; RealMatrixX Amat = A, Bmat = B; int n = (int)A.cols(); char L='N',R='N'; if (computeEigenvectors) { L = 'V'; R = 'V'; VL.setZero(n, n); VR.setZero(n, n); } int lwork=16*n; info_val=-1; alpha.setZero(n); beta.setZero(n); RealVectorX work, aval_r, aval_i, bval; RealMatrixX vecl, vecr; work.setZero(lwork); aval_r.setZero(n); aval_i.setZero(n); bval.setZero(n); vecl.setZero(n,n); vecr.setZero(n,n); Real *a_vals = Amat.data(), *b_vals = Bmat.data(), *alpha_r_v = aval_r.data(), *alpha_i_v = aval_i.data(), *beta_v = bval.data(), *vecl_v = vecl.data(), *vecr_v = vecr.data(), *work_v = work.data(); dggev_(&L, &R, &n, &(a_vals[0]), &n, &(b_vals[0]), &n, &(alpha_r_v[0]), &(alpha_i_v[0]), &(beta_v[0]), &(vecl_v[0]), &n, &(vecr_v[0]), &n, &(work_v[0]), &lwork, &info_val); // now sort the eigenvalues for complex conjugates unsigned int n_located = 0; while (n_located < n) { // if the imaginary part of the eigenvalue is non-zero, it is a // complex conjugate if (aval_i(n_located) != 0.) { // complex conjugate alpha( n_located) = std::complex<double>(aval_r(n_located), aval_i(n_located)); alpha(1+n_located) = std::complex<double>(aval_r(n_located), -aval_i(n_located)); beta ( n_located) = bval(n_located); beta (1+n_located) = bval(n_located); // copy the eigenvectors if they were requested if (computeEigenvectors) { std::complex<double> iota = std::complex<double>(0, 1.); VL.col( n_located) = (vecl.col( n_located).cast<Complex>() + vecl.col(1+n_located).cast<Complex>() * iota); VL.col(1+n_located) = (vecl.col( n_located).cast<Complex>() - vecl.col(1+n_located).cast<Complex>() * iota); VR.col( n_located) = (vecr.col( n_located).cast<Complex>() + vecr.col(1+n_located).cast<Complex>() * iota); VR.col(1+n_located) = (vecr.col( n_located).cast<Complex>() - vecr.col(1+n_located).cast<Complex>() * iota); } // two complex conjugate roots were found n_located +=2; } else { alpha( n_located) = std::complex<double>(aval_r(n_located), 0.); beta ( n_located) = bval(n_located); // copy the eigenvectors if they were requested if (computeEigenvectors) { VL.col(n_located) = vecl.col(n_located).cast<Complex>(); VR.col(n_located) = vecr.col(n_located).cast<Complex>(); } // only one real root was found n_located++; } } if (info_val != 0) libMesh::out << "Warning!! DGGEV returned with nonzero info = " << info_val << std::endl; }
void MAST::NonlinearImplicitAssembly:: residual_and_jacobian (const libMesh::NumericVector<Real>& X, libMesh::NumericVector<Real>* R, libMesh::SparseMatrix<Real>* J, libMesh::NonlinearImplicitSystem& S) { libMesh::NonlinearImplicitSystem& nonlin_sys = dynamic_cast<libMesh::NonlinearImplicitSystem&>(_system->system()); // make sure that the system for which this object was created, // and the system passed through the function call are the same libmesh_assert_equal_to(&S, &(nonlin_sys)); if (R) R->zero(); if (J) J->zero(); // iterate over each element, initialize it and get the relevant // analysis quantities RealVectorX vec, sol; RealMatrixX mat; std::vector<libMesh::dof_id_type> dof_indices; const libMesh::DofMap& dof_map = _system->system().get_dof_map(); std::auto_ptr<MAST::ElementBase> physics_elem; std::auto_ptr<libMesh::NumericVector<Real> > localized_solution; localized_solution.reset(_build_localized_vector(nonlin_sys, X).release()); // if a solution function is attached, initialize it if (_sol_function) _sol_function->init_for_system_and_solution(*_system, X); libMesh::MeshBase::const_element_iterator el = nonlin_sys.get_mesh().active_local_elements_begin(); const libMesh::MeshBase::const_element_iterator end_el = nonlin_sys.get_mesh().active_local_elements_end(); for ( ; el != end_el; ++el) { const libMesh::Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); physics_elem.reset(_build_elem(*elem).release()); // get the solution unsigned int ndofs = (unsigned int)dof_indices.size(); sol.setZero(ndofs); vec.setZero(ndofs); mat.setZero(ndofs, ndofs); for (unsigned int i=0; i<dof_indices.size(); i++) sol(i) = (*localized_solution)(dof_indices[i]); physics_elem->set_solution(sol); if (_sol_function) physics_elem->attach_active_solution_function(*_sol_function); //_check_element_numerical_jacobian(*physics_elem, sol); // perform the element level calculations _elem_calculations(*physics_elem, J!=NULL?true:false, vec, mat); physics_elem->detach_active_solution_function(); // copy to the libMesh matrix for further processing DenseRealVector v; DenseRealMatrix m; if (R) MAST::copy(v, vec); if (J) MAST::copy(m, mat); // constrain the quantities to account for hanging dofs, // Dirichlet constraints, etc. if (R && J) nonlin_sys.get_dof_map().constrain_element_matrix_and_vector(m, v, dof_indices); else if (R) nonlin_sys.get_dof_map().constrain_element_vector(v, dof_indices); else nonlin_sys.get_dof_map().constrain_element_matrix(m, dof_indices); // add to the global matrices if (R) R->add_vector(v, dof_indices); if (J) J->add_matrix(m, dof_indices); } // if a solution function is attached, clear it if (_sol_function) _sol_function->clear(); if (R) R->close(); if (J) J->close(); }
bool MAST::NonlinearImplicitAssembly:: sensitivity_assemble (const libMesh::ParameterVector& parameters, const unsigned int i, libMesh::NumericVector<Real>& sensitivity_rhs) { libMesh::NonlinearImplicitSystem& nonlin_sys = dynamic_cast<libMesh::NonlinearImplicitSystem&>(_system->system()); sensitivity_rhs.zero(); // iterate over each element, initialize it and get the relevant // analysis quantities RealVectorX vec, sol; RealMatrixX mat; std::vector<libMesh::dof_id_type> dof_indices; const libMesh::DofMap& dof_map = nonlin_sys.get_dof_map(); std::auto_ptr<MAST::ElementBase> physics_elem; std::auto_ptr<libMesh::NumericVector<Real> > localized_solution; localized_solution.reset(_build_localized_vector(nonlin_sys, *nonlin_sys.solution).release()); // if a solution function is attached, initialize it if (_sol_function) _sol_function->init_for_system_and_solution(*_system, *nonlin_sys.solution); libMesh::MeshBase::const_element_iterator el = nonlin_sys.get_mesh().active_local_elements_begin(); const libMesh::MeshBase::const_element_iterator end_el = nonlin_sys.get_mesh().active_local_elements_end(); for ( ; el != end_el; ++el) { const libMesh::Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); physics_elem.reset(_build_elem(*elem).release()); // get the solution unsigned int ndofs = (unsigned int)dof_indices.size(); sol.setZero(ndofs); vec.setZero(ndofs); mat.setZero(ndofs, ndofs); for (unsigned int i=0; i<dof_indices.size(); i++) sol(i) = (*localized_solution)(dof_indices[i]); physics_elem->sensitivity_param = _discipline->get_parameter(parameters[i]); physics_elem->set_solution(sol); if (_sol_function) physics_elem->attach_active_solution_function(*_sol_function); // perform the element level calculations _elem_sensitivity_calculations(*physics_elem, vec); physics_elem->detach_active_solution_function(); // copy to the libMesh matrix for further processing DenseRealVector v; MAST::copy(v, vec); // constrain the quantities to account for hanging dofs, // Dirichlet constraints, etc. nonlin_sys.get_dof_map().constrain_element_vector(v, dof_indices); // add to the global matrices sensitivity_rhs.add_vector(v, dof_indices); } // if a solution function is attached, initialize it if (_sol_function) _sol_function->clear(); sensitivity_rhs.close(); return true; }
void MAST::StructuralElement2D::_internal_residual_operation (bool if_bending, bool if_vk, const unsigned int n2, const unsigned int qp, const std::vector<Real>& JxW, bool request_jacobian, bool if_ignore_ho_jac, RealVectorX& local_f, RealMatrixX& local_jac, FEMOperatorMatrix& Bmat_mem, FEMOperatorMatrix& Bmat_bend, FEMOperatorMatrix& Bmat_vk, RealMatrixX& stress, RealMatrixX& stress_l, RealMatrixX& vk_dwdxi_mat, RealMatrixX& material_A_mat, RealMatrixX& material_B_mat, RealMatrixX& material_D_mat, RealVectorX& vec1_n1, RealVectorX& vec2_n1, RealVectorX& vec3_n2, RealVectorX& vec4_2, RealVectorX& vec5_2, RealMatrixX& mat1_n1n2, RealMatrixX& mat2_n2n2, RealMatrixX& mat3, RealMatrixX& mat4_2n2) { this->initialize_direct_strain_operator(qp, Bmat_mem); // first handle constant throught the thickness stresses: membrane and vonKarman Bmat_mem.vector_mult(vec1_n1, _local_sol); vec2_n1 = material_A_mat * vec1_n1; // linear direct stress // copy the stress values to a matrix stress_l(0,0) = vec2_n1(0); // sigma_xx stress_l(0,1) = vec2_n1(2); // sigma_xy stress_l(1,0) = vec2_n1(2); // sigma_yx stress_l(1,1) = vec2_n1(1); // sigma_yy stress = stress_l; // get the bending strain operator vec2_n1.setConstant(0.); // used to store vk strain, if applicable if (if_bending) { _bending_operator->initialize_bending_strain_operator(qp, Bmat_bend); Bmat_bend.vector_mult(vec2_n1, _local_sol); vec1_n1 = material_B_mat * vec2_n1; stress_l(0,0) += vec2_n1(0); // sigma_xx stress_l(0,1) += vec2_n1(2); // sigma_xy stress_l(1,0) += vec2_n1(2); // sigma_yx stress_l(1,1) += vec2_n1(1); // sigma_yy stress(0,0) += vec2_n1(0); // sigma_xx stress(0,1) += vec2_n1(2); // sigma_xy stress(1,0) += vec2_n1(2); // sigma_yx stress(1,1) += vec2_n1(1); // sigma_yy if (if_vk) { // get the vonKarman strain operator if needed this->initialize_von_karman_strain_operator(qp, vec2_n1, // epsilon_vk vk_dwdxi_mat, Bmat_vk); vec1_n1 = material_A_mat * vec2_n1; // stress stress(0,0) += vec1_n1(0); // sigma_xx stress(0,1) += vec1_n1(2); // sigma_xy stress(1,0) += vec1_n1(2); // sigma_yx stress(1,1) += vec1_n1(1); // sigma_yy } } // add the linear and nonlinear direct strains Bmat_mem.vector_mult(vec1_n1, _local_sol); vec2_n1 += vec1_n1; // epsilon_mem + epsilon_vk // copy the total integrated stress to the vector vec1_n1(0) = stress(0,0); vec1_n1(1) = stress(1,1); vec1_n1(2) = stress(0,1); // now the internal force vector // this includes the membrane strain operator with all A and B material operators Bmat_mem.vector_mult_transpose(vec3_n2, vec1_n1); local_f += JxW[qp] * vec3_n2; if (if_bending) { if (if_vk) { // von Karman strain vec4_2 = vk_dwdxi_mat.transpose() * vec1_n1; Bmat_vk.vector_mult_transpose(vec3_n2, vec4_2); local_f += JxW[qp] * vec3_n2; } // now coupling with the bending strain // B_bend^T [B] B_mem vec1_n1 = material_B_mat * vec2_n1; Bmat_bend.vector_mult_transpose(vec3_n2, vec1_n1); local_f += JxW[qp] * vec3_n2; // now bending stress Bmat_bend.vector_mult(vec2_n1, _local_sol); vec1_n1 = material_D_mat * vec2_n1; Bmat_bend.vector_mult_transpose(vec3_n2, vec1_n1); local_f += JxW[qp] * vec3_n2; } if (request_jacobian) { // membrane - membrane Bmat_mem.left_multiply(mat1_n1n2, material_A_mat); Bmat_mem.right_multiply_transpose(mat2_n2n2, mat1_n1n2); local_jac += JxW[qp] * mat2_n2n2; if (if_bending) { if (if_vk) { // membrane - vk mat3 = RealMatrixX::Zero(vk_dwdxi_mat.rows(), n2); Bmat_vk.left_multiply(mat3, vk_dwdxi_mat); mat3 = material_A_mat * mat3; Bmat_mem.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // vk - membrane Bmat_mem.left_multiply(mat1_n1n2, material_A_mat); mat3 = vk_dwdxi_mat.transpose() * mat1_n1n2; Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // if only the first order term of the Jacobian is needed, for // example for linearized buckling analysis, then the linear // stress combined with the variation of the von Karman strain // is included. Otherwise, all terms are included if (if_ignore_ho_jac) { // vk - vk: first order term mat3 = RealMatrixX::Zero(2, n2); Bmat_vk.left_multiply(mat3, stress_l); Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; } else { // vk - vk mat3 = RealMatrixX::Zero(2, n2); Bmat_vk.left_multiply(mat3, stress); Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; mat3 = RealMatrixX::Zero(vk_dwdxi_mat.rows(), n2); Bmat_vk.left_multiply(mat3, vk_dwdxi_mat); mat3 = vk_dwdxi_mat.transpose() * material_A_mat * mat3; Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; } // bending - vk mat3 = RealMatrixX::Zero(vk_dwdxi_mat.rows(), n2); Bmat_vk.left_multiply(mat3, vk_dwdxi_mat); mat3 = material_B_mat.transpose() * mat3; Bmat_bend.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; // vk - bending Bmat_bend.left_multiply(mat1_n1n2, material_B_mat); mat3 = vk_dwdxi_mat.transpose() * mat1_n1n2; Bmat_vk.right_multiply_transpose(mat2_n2n2, mat3); local_jac += JxW[qp] * mat2_n2n2; } // bending - membrane Bmat_mem.left_multiply(mat1_n1n2, material_B_mat); Bmat_bend.right_multiply_transpose(mat2_n2n2, mat1_n1n2); local_jac += JxW[qp] * mat2_n2n2; // membrane - bending Bmat_bend.left_multiply(mat1_n1n2, material_B_mat); Bmat_mem.right_multiply_transpose(mat2_n2n2, mat1_n1n2); local_jac += JxW[qp] * mat2_n2n2; // bending - bending Bmat_bend.left_multiply(mat1_n1n2, material_D_mat); Bmat_bend.right_multiply_transpose(mat2_n2n2, mat1_n1n2); local_jac += JxW[qp] * mat2_n2n2; } } }