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::ComplexAssemblyBase:: residual_and_jacobian_field_split (const libMesh::NumericVector<Real>& X_R, const libMesh::NumericVector<Real>& X_I, libMesh::NumericVector<Real>& R_R, libMesh::NumericVector<Real>& R_I, libMesh::SparseMatrix<Real>& J_R, libMesh::SparseMatrix<Real>& J_I) { libmesh_assert(_system); libmesh_assert(_discipline); libmesh_assert(_elem_ops); MAST::NonlinearSystem& nonlin_sys = _system->system(); R_R.zero(); R_I.zero(); J_R.zero(); J_I.zero(); // iterate over each element, initialize it and get the relevant // analysis quantities RealVectorX sol, vec_re; RealMatrixX mat_re; ComplexVectorX delta_sol, vec; ComplexMatrixX mat; std::vector<libMesh::dof_id_type> dof_indices; const libMesh::DofMap& dof_map = _system->system().get_dof_map(); std::unique_ptr<libMesh::NumericVector<Real> > localized_base_solution, localized_real_solution, localized_imag_solution; // localize the base solution, if it was provided if (_base_sol) localized_base_solution.reset(build_localized_vector(nonlin_sys, *_base_sol).release()); // localize sol to real vector localized_real_solution.reset(build_localized_vector(nonlin_sys, X_R).release()); // localize sol to imag vector localized_imag_solution.reset(build_localized_vector(nonlin_sys, X_I).release()); // if a solution function is attached, initialize it //if (_sol_function) // _sol_function->init( 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(); MAST::ComplexAssemblyElemOperations& ops = dynamic_cast<MAST::ComplexAssemblyElemOperations&>(*_elem_ops); for ( ; el != end_el; ++el) { const libMesh::Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); ops.init(*elem); // get the solution unsigned int ndofs = (unsigned int)dof_indices.size(); sol.setZero(ndofs); delta_sol.setZero(ndofs); vec.setZero(ndofs); mat.setZero(ndofs, ndofs); // first set the velocity to be zero ops.set_elem_velocity(sol); // next, set the base solution, if provided if (_base_sol) for (unsigned int i=0; i<dof_indices.size(); i++) sol(i) = (*localized_base_solution)(dof_indices[i]); ops.set_elem_solution(sol); // set the value of the small-disturbance solution for (unsigned int i=0; i<dof_indices.size(); i++) delta_sol(i) = Complex((*localized_real_solution)(dof_indices[i]), (*localized_imag_solution)(dof_indices[i])); ops.set_elem_complex_solution(delta_sol); // if (_sol_function) // physics_elem->attach_active_solution_function(*_sol_function); // perform the element level calculations ops.elem_calculations(true, vec, mat); ops.clear_elem(); vec *= -1.; //physics_elem->detach_active_solution_function(); // extract the real or the imaginary part of the matrix/vector // The complex system of equations // (J_R + i J_I) (x_R + i x_I) + (r_R + i r_I) = 0 // is rewritten as // [ J_R -J_I] {x_R} + {r_R} = {0} // [ J_I J_R] {x_I} + {r_I} = {0} // DenseRealVector v; DenseRealMatrix m; // copy the real part of the residual and Jacobian MAST::copy(v, vec.real()); MAST::copy(m, mat.real()); dof_map.constrain_element_matrix_and_vector(m, v, dof_indices); R_R.add_vector(v, dof_indices); J_R.add_matrix(m, dof_indices); // copy the imag part of the residual and Jacobian v.zero(); m.zero(); MAST::copy(v, vec.imag()); MAST::copy(m, mat.imag()); dof_map.constrain_element_matrix_and_vector(m, v, dof_indices); R_I.add_vector(v, dof_indices); J_I.add_matrix(m, dof_indices); } // if a solution function is attached, clear it //if (_sol_function) // _sol_function->clear(); R_R.close(); R_I.close(); J_R.close(); J_I.close(); libMesh::out << "R_R: " << R_R.l2_norm() << " R_I: " << R_I.l2_norm() << std::endl; }