37 #include "libmesh/numeric_vector.h" 38 #include "libmesh/equation_systems.h" 39 #include "libmesh/sparse_matrix.h" 40 #include "libmesh/dof_map.h" 41 #include "libmesh/nonlinear_solver.h" 42 #include "libmesh/petsc_linear_solver.h" 43 #include "libmesh/xdr_cxx.h" 44 #include "libmesh/mesh_tools.h" 45 #include "libmesh/utility.h" 46 #include "libmesh/libmesh_version.h" 47 #include "libmesh/generic_projector.h" 48 #include "libmesh/wrapped_functor.h" 49 #include "libmesh/fem_context.h" 53 const std::string& name,
54 const unsigned int number):
55 libMesh::NonlinearImplicitSystem(es, name, number),
56 _initialize_B_matrix (false),
59 eigen_solver (nullptr),
60 _condensed_dofs_initialized (false),
61 _exchange_A_and_B (false),
62 _n_requested_eigenpairs (0),
63 _n_converged_eigenpairs (0),
65 _is_generalized_eigenproblem (false),
66 _eigen_problem_type (libMesh::NHEP),
99 libMesh::NonlinearImplicitSystem::clear();
117 libMesh::NonlinearImplicitSystem::init_data();
126 libMesh::DofMap& dof_map = this->get_dof_map();
129 matrix_A = libMesh::SparseMatrix<Real>::build(this->comm()).release();
136 matrix_B = libMesh::SparseMatrix<Real>::build(this->comm()).release();
143 if (libMesh::on_command_line(
"--solver_system_names")) {
146 std::string nm = this->name() +
"_";
147 EPSSetOptionsPrefix(eps, nm.c_str());
152 linear_solver.reset(
new libMesh::PetscLinearSolver<Real>(this->comm()));
153 if (libMesh::on_command_line(
"--solver_system_names")) {
155 std::string nm = this->name() +
"_";
165 libMesh::NonlinearImplicitSystem::reinit();
174 if (libMesh::on_command_line(
"--solver_system_names")) {
177 std::string nm = this->name() +
"_";
178 EPSSetOptionsPrefix(eps, nm.c_str());
183 linear_solver.reset(
new libMesh::PetscLinearSolver<Real>(this->comm()));
184 if (libMesh::on_command_line(
"--solver_system_names")) {
186 std::string nm = this->name() +
"_";
200 std::pair<unsigned int, Real>
203 this->set_solver_parameters();
204 return libMesh::NonlinearImplicitSystem::get_linear_solve_parameters();
217 libMesh::NonlinearImplicitSystem::ComputeResidualandJacobian
218 *old_ptr = this->nonlinear_solver->residual_and_jacobian_object;
220 this->nonlinear_solver->residual_and_jacobian_object = &assembly;
224 libMesh::NonlinearImplicitSystem::solve();
226 this->nonlinear_solver->residual_and_jacobian_object = old_ptr;
242 START_LOG(
"eigensolve()",
"NonlinearSystem");
247 libMesh::EquationSystems& es = this->get_equation_systems();
259 tol = es.parameters.get<
Real>(
"linear solver tolerance");
262 maxits = es.parameters.get<
unsigned int>(
"linear solver maximum iterations"),
263 nev = es.parameters.get<
unsigned int>(
"eigenpairs"),
264 ncv = es.parameters.get<
unsigned int>(
"basis vectors");
266 std::pair<unsigned int, unsigned int> solve_data;
268 libMesh::SparseMatrix<Real>
318 std::unique_ptr<libMesh::SparseMatrix<Real> >
319 condensed_matrix_A(libMesh::SparseMatrix<Real>::build(this->comm()).release()),
320 condensed_matrix_B(libMesh::SparseMatrix<Real>::build(this->comm()).release());
323 matrix_A->create_submatrix(*condensed_matrix_A,
330 matrix_B->create_submatrix(*condensed_matrix_B,
342 eig_A = condensed_matrix_A.get();
343 eig_B = condensed_matrix_B.get();
346 eig_B = condensed_matrix_A.get();
347 eig_A = condensed_matrix_B.get();
362 solve_data =
eigen_solver->solve_standard (*condensed_matrix_A,
375 STOP_LOG(
"eigensolve()",
"NonlinearSystem");
385 std::pair<Real, Real>
393 Complex complex_val (val.first, val.second);
394 complex_val = 1./complex_val;
395 re = complex_val.real();
396 im = complex_val.imag();
406 libMesh::NumericVector<Real>& vec_re,
407 libMesh::NumericVector<Real>* vec_im) {
409 START_LOG(
"get_eigenpair()",
"NonlinearSystem");
410 std::pair<Real, Real>
416 libmesh_assert (vec_im ==
nullptr);
424 val = this->
eigen_solver->get_eigenpair (i, vec_re, vec_im);
431 Complex complex_val (val.first, val.second);
432 complex_val = 1./complex_val;
433 re = complex_val.real();
434 im = complex_val.imag();
442 std::unique_ptr< libMesh::NumericVector<Real> >
443 temp_re(libMesh::NumericVector<Real>::build(this->comm()).release()),
452 temp_re->init (n, n_local,
false, libMesh::PARALLEL);
457 temp_im.reset(libMesh::NumericVector<Real>::build(this->comm()).release());
458 temp_im->init (n, n_local,
false, libMesh::PARALLEL);
463 val = this->
eigen_solver->get_eigenpair (i, *temp_re, temp_im.get());
470 Complex complex_val (val.first, val.second);
471 complex_val = 1./complex_val;
472 re = complex_val.real();
473 im = complex_val.imag();
483 vec_re.set(index,(*temp_re)(temp_re->first_local_index()+j));
495 vec_im->set(index,(*temp_im)(temp_im->first_local_index()+j));
507 v = vec_re.dot(vec_re);
510 libmesh_assert_greater(v, 0.);
511 vec_re.scale(1./std::sqrt(v));
515 case libMesh::GHEP: {
517 std::unique_ptr<libMesh::NumericVector<Real> >
518 tmp(vec_re.zero_clone().release());
521 matrix_B->vector_mult(*tmp, vec_re);
524 v = tmp->dot(vec_re);
527 libmesh_assert_greater(v, 0.);
528 vec_re.scale(1./std::sqrt(v));
542 STOP_LOG(
"get_eigenpair()",
"NonlinearSystem");
554 std::vector<Real>& sens,
555 const std::vector<unsigned int>* indices) {
574 n_calc = indices?(
unsigned int)indices->size():nconv;
576 libmesh_assert_equal_to(n_calc, nconv);
578 std::vector<unsigned int> indices_to_calculate;
580 indices_to_calculate = *indices;
581 for (
unsigned int i=0; i<n_calc; i++) libmesh_assert_less(indices_to_calculate[i], nconv);
585 indices_to_calculate.resize(n_calc);
586 for (
unsigned int i=0; i<n_calc; i++) indices_to_calculate[i] = i;
591 sens.resize(n_calc, 0.);
593 std::vector<libMesh::NumericVector<Real>*>
597 std::unique_ptr<libMesh::NumericVector<Real> >
598 tmp (this->solution->zero_clone().release());
608 for (
unsigned int i=0; i<n_calc; i++) {
610 x_right[i] = (this->solution->zero_clone().release());
618 this->
get_eigenpair(indices_to_calculate[i], re, im, *x_right[i],
nullptr);
619 denom[i] = x_right[i]->dot(*x_right[i]);
624 case libMesh::GHEP: {
626 this->
get_eigenpair(indices_to_calculate[i], re, im, *x_right[i],
nullptr);
627 matrix_B->vector_mult(*tmp, *x_right[i]);
628 denom[i] = x_right[i]->dot(*tmp);
645 for (
unsigned int i=0; i<n_calc; i++) {
651 matrix_A->vector_mult(*tmp, *x_right[i]);
652 sens[i] = x_right[i]->dot(*tmp);
653 sens[i]-= eig[i] * x_right[i]->dot(*x_right[i]);
658 case libMesh::GHEP: {
660 matrix_A->vector_mult(*tmp, *x_right[i]);
661 sens[i] = x_right[i]->dot(*tmp);
662 matrix_B->vector_mult(*tmp, *x_right[i]);
663 sens[i]-= eig[i] * x_right[i]->dot(*tmp);
676 for (
unsigned int i=0; i<x_right.size(); i++)
690 const libMesh::DofMap & dof_map = this->get_dof_map();
692 std::set<unsigned int> global_dirichlet_dofs_set;
698 std::set<unsigned int> local_non_condensed_dofs_set;
699 for(
unsigned int i=this->get_dof_map().first_dof();
700 i<this->get_dof_map().end_dof();
702 if (!dof_map.is_constrained_dof(i))
703 local_non_condensed_dofs_set.insert(i);
706 std::set<unsigned int>::iterator
707 iter = global_dirichlet_dofs_set.begin(),
708 iter_end = global_dirichlet_dofs_set.end();
710 for ( ; iter != iter_end ; ++iter) {
712 unsigned int condensed_dof_index = *iter;
714 if ( (this->get_dof_map().first_dof() <= condensed_dof_index) &&
715 (condensed_dof_index < this->get_dof_map().end_dof()) )
716 local_non_condensed_dofs_set.erase(condensed_dof_index);
721 iter = local_non_condensed_dofs_set.begin();
722 iter_end = local_non_condensed_dofs_set.end();
726 for ( ; iter != iter_end; ++iter)
740 bool if_assemble_jacobian) {
747 LOG_SCOPE(
"sensitivity_solve()",
"NonlinearSystem");
751 libMesh::NumericVector<Real>
752 &dsol = this->add_sensitivity_solution(),
753 &rhs = this->add_sensitivity_rhs();
755 if (if_assemble_jacobian)
764 std::pair<unsigned int, Real>
768 libMesh::SparseMatrix<Real> * pc = this->request_matrix(
"Preconditioner");
770 std::pair<unsigned int, Real> rval =
774 solver_params.second,
775 solver_params.first);
778 #ifdef LIBMESH_ENABLE_CONSTRAINTS 779 this->get_dof_map().enforce_constraints_exactly (*
this, &dsol,
true);
795 bool if_assemble_jacobian) {
803 LOG_SCOPE(
"adjoint_solve()",
"NonlinearSystem");
805 libMesh::NumericVector<Real>
806 &dsol = this->add_adjoint_solution(),
807 &rhs = this->add_adjoint_rhs();
811 if (if_assemble_jacobian)
822 std::pair<unsigned int, Real>
825 const std::pair<unsigned int, Real> rval =
829 solver_params.second,
830 solver_params.first);
833 #ifdef LIBMESH_ENABLE_CONSTRAINTS 834 this->get_dof_map().enforce_adjoint_constraints_exactly(dsol, 0);
846 const std::string & directory_name,
847 const std::string & data_name,
848 const bool write_binary_vectors)
850 LOG_SCOPE(
"write_out_vector()",
"NonlinearSystem");
852 if (this->processor_id() == 0)
855 libMesh::Utility::mkdir(directory_name.c_str());
859 this->comm().barrier();
861 std::ostringstream file_name;
862 const std::string suffix = (write_binary_vectors ?
".xdr" :
".dat");
864 file_name << directory_name <<
"/" << data_name <<
"_data" << suffix;
865 libMesh::Xdr bf_data(file_name.str(),
866 write_binary_vectors ? libMesh::ENCODE : libMesh::WRITE);
868 std::string version(
"libMesh-" + libMesh::get_io_compatibility_version());
869 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 870 version +=
" with infinite elements";
872 bf_data.data(version ,
"# File Format Identifier");
874 this->write_header(bf_data, version,
false);
878 libMesh::MeshTools::Private::globally_renumber_nodes_and_elements(this->get_mesh());
883 std::vector<const libMesh::NumericVector<Real> *> bf_out(1);
885 this->write_serialized_vectors (bf_data, bf_out);
890 bf_data.set_version(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION,
891 LIBMESH_MINOR_VERSION,
892 LIBMESH_MICRO_VERSION));
896 this->get_mesh().fix_broken_node_and_element_numbering();
903 const std::string & directory_name,
904 const std::string & data_name,
905 const bool read_binary_vector) {
907 LOG_SCOPE(
"read_in_vector()",
"NonlinearSystem");
910 this->comm().barrier();
916 libMesh::MeshTools::Private::globally_renumber_nodes_and_elements(this->get_mesh());
918 std::ostringstream file_name;
919 const std::string suffix = (read_binary_vector ?
".xdr" :
".dat");
921 file_name << directory_name
923 <<
"_data" << suffix;
926 if (this->processor_id() == 0)
928 struct stat stat_info;
929 int stat_result = stat(file_name.str().c_str(), &stat_info);
931 if (stat_result != 0)
932 libmesh_error_msg(
"File does not exist: " + file_name.str());
935 if (!std::ifstream(file_name.str()))
936 libmesh_error_msg(
"File missing: " + file_name.str());
938 libMesh::Xdr vector_data(file_name.str(),
939 read_binary_vector ? libMesh::DECODE : libMesh::READ);
944 vector_data.data(version);
946 const std::string libMesh_label =
"libMesh-";
947 std::string::size_type lm_pos = version.find(libMesh_label);
948 if (lm_pos==std::string::npos)
950 libmesh_error_msg(
"version info missing in Xdr header");
953 std::istringstream iss(version.substr(lm_pos + libMesh_label.size()));
954 int ver_major = 0, ver_minor = 0, ver_patch = 0;
956 iss >> ver_major >> dot >> ver_minor >> dot >> ver_patch;
957 vector_data.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch));
962 this->read_header(vector_data, version,
false,
false);
965 std::vector<libMesh::NumericVector<Real> *> bf_in(1);
967 this->read_serialized_vectors (vector_data, bf_in);
970 this->get_mesh().fix_broken_node_and_element_numbering();
978 libMesh::FunctionBase<Real>& f)
const {
980 LOG_SCOPE (
"project_vector_without_dirichlet()",
"NonlinearSystem");
982 libMesh::ConstElemRange active_local_range
983 (this->get_mesh().active_local_elements_begin(),
984 this->get_mesh().active_local_elements_end() );
986 libMesh::VectorSetAction<Real> setter(new_vector);
988 const unsigned int n_variables = this->n_vars();
990 std::vector<unsigned int> vars(n_variables);
991 for (
unsigned int i=0; i != n_variables; ++i)
996 libMesh::GenericProjector<libMesh::FEMFunctionWrapper<Real>, libMesh::FEMFunctionWrapper<libMesh::Gradient>,
997 Real, libMesh::VectorSetAction<Real>> FEMProjector;
999 libMesh::WrappedFunctor<Real> f_fem(f);
1000 libMesh::FEMFunctionWrapper<Real> fw(f_fem);
1002 #if (LIBMESH_MAJOR_VERSION == 1 && LIBMESH_MINOR_VERSION < 5) 1003 libMesh::Threads::parallel_for
1004 (active_local_range,
1005 FEMProjector(*
this, fw,
nullptr, setter, vars));
1007 FEMProjector projector(*
this, fw,
nullptr, setter, vars);
1008 projector.project(active_local_range);
1014 if (this->processor_id() == (this->n_processors()-1))
1017 libMesh::FEMContext context( *
this );
1019 const libMesh::DofMap & dof_map = this->get_dof_map();
1020 for (
unsigned int var=0; var<this->n_vars(); var++)
1021 if (this->variable(var).type().family == libMesh::SCALAR)
1026 libMesh::Elem * el =
const_cast<libMesh::Elem *
>(*(this->get_mesh().active_local_elements_begin()));
1027 context.pre_fe_reinit(*
this, el);
1029 std::vector<libMesh::dof_id_type> SCALAR_indices;
1030 dof_map.SCALAR_dof_indices (SCALAR_indices, var);
1031 const unsigned int n_SCALAR_dofs =
1032 libMesh::cast_int<unsigned int>(SCALAR_indices.size());
1034 for (
unsigned int i=0; i<n_SCALAR_dofs; i++)
1036 const libMesh::dof_id_type global_index = SCALAR_indices[i];
1037 const unsigned int component_index =
1038 this->variable_scalar_number(var,i);
1040 new_vector.set(global_index, f_fem.component(context, component_index, libMesh::Point(), this->time));
unsigned int _n_iterations
The number of iterations of the eigen solver algorithm.
virtual void sensitivity_solve(MAST::AssemblyElemOperations &elem_ops, MAST::AssemblyBase &assembly, const MAST::FunctionBase &p, bool if_assemble_jacobian=true)
Solves the sensitivity problem for the provided parameter.
virtual void eigenproblem_assemble(libMesh::SparseMatrix< Real > *A, libMesh::SparseMatrix< Real > *B)
assembles the matrices for eigenproblem depending on the analysis type
void initialize_condensed_dofs(MAST::PhysicsDisciplineBase &physics)
Loop over the dofs on each processor to initialize the list of non-condensed dofs.
void read_in_vector(libMesh::NumericVector< Real > &vec, const std::string &directory_name, const std::string &data_name, const bool read_binary_vectors)
reads the specified vector with the specified name in a directory.
This class implements a system for solution of nonlinear systems.
void get_system_dirichlet_bc_dofs(libMesh::System &sys, std::set< unsigned int > &dof_ids) const
Prepares a list of the constrained dofs for system sys and returns in dof_ids.
bool _is_generalized_eigenproblem
A boolean flag to indicate whether we are dealing with a generalized eigenvalue problem.
virtual void clear_elem_operation_object()
clears the association of this object with the assembly element operation object. ...
virtual bool sensitivity_assemble(const MAST::FunctionBase &f, libMesh::NumericVector< Real > &sensitivity_rhs)
Assembly function.
virtual void clear() libmesh_override
Clear all the data structures associated with the system.
virtual void calculate_output_derivative(const libMesh::NumericVector< Real > &X, MAST::OutputAssemblyElemOperations &output, libMesh::NumericVector< Real > &dq_dX)
calculates
void write_out_vector(libMesh::NumericVector< Real > &vec, const std::string &directory_name, const std::string &data_name, const bool write_binary_vectors)
writes the specified vector with the specified name in a directory.
unsigned int _n_requested_eigenpairs
The number of requested eigenpairs.
This provides the base class for definitin of element level contribution of output quantity in an ana...
std::unique_ptr< MAST::SlepcEigenSolver > eigen_solver
The EigenSolver, definig which interface, i.e solver package to use.
virtual void set_elem_operation_object(MAST::AssemblyElemOperations &elem_ops)
attaches a element operation to this object, and associated this with the element operation object...
bool _initialize_B_matrix
initialize the B matrix in addition to A, which might be needed for solution of complex system of equ...
This class inherits from libMesh::SlepcEigenSolver<Real> and implements a method for retriving the re...
void set_eigenproblem_type(libMesh::EigenProblemType ept)
Sets the type of the current eigen problem.
virtual void reinit() libmesh_override
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be use...
MAST::NonlinearSystem::Operation _operation
current operation of the system
virtual void eigenproblem_sensitivity_solve(MAST::AssemblyElemOperations &elem_ops, MAST::EigenproblemAssembly &assembly, const MAST::FunctionBase &f, std::vector< Real > &sens, const std::vector< unsigned int > *indices=nullptr)
Solves the sensitivity system, for the provided parameters.
virtual bool eigenproblem_sensitivity_assemble(const MAST::FunctionBase &f, libMesh::SparseMatrix< Real > *sensitivity_A, libMesh::SparseMatrix< Real > *sensitivity_B)
Assembly function.
Assembles the system of equations for an eigenproblem of type .
libMesh::SparseMatrix< Real > * matrix_A
The system matrix for standard eigenvalue problems.
bool _condensed_dofs_initialized
A private flag to indicate whether the condensed dofs have been initialized.
virtual void eigenproblem_solve(MAST::AssemblyElemOperations &elem_ops, MAST::EigenproblemAssembly &assembly)
Assembles & solves the eigen system.
virtual std::pair< unsigned int, Real > get_linear_solve_parameters()
calls NonlinearImplicitSystem::set_solver_parameters() before accessing the values.
virtual void init_data() libmesh_override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used...
libMesh::SparseMatrix< Real > * matrix_B
A second system matrix for generalized eigenvalue problems.
libMesh::EigenProblemType _eigen_problem_type
The type of the eigenvalue problem.
virtual void get_eigenvalue(unsigned int i, Real &re, Real &im)
gets the real and imaginary parts of the ith eigenvalue for the eigenproblem , and the associated eig...
virtual ~NonlinearSystem()
std::unique_ptr< libMesh::LinearSolver< Real > > linear_solver
The LinearSolver for solution of the linear equations.
unsigned int _n_converged_eigenpairs
The number of converged eigenpairs.
std::vector< libMesh::dof_id_type > _local_non_condensed_dofs_vector
Vector storing the local dof indices that will not be condensed.
virtual void get_eigenpair(unsigned int i, Real &re, Real &im, libMesh::NumericVector< Real > &vec_re, libMesh::NumericVector< Real > *vec_im=nullptr)
gets the real and imaginary parts of the ith eigenvalue for the eigenproblem , and the associated eig...
virtual void residual_and_jacobian(const libMesh::NumericVector< Real > &X, libMesh::NumericVector< Real > *R, libMesh::SparseMatrix< Real > *J, libMesh::NonlinearImplicitSystem &S)
function that assembles the matrices and vectors quantities for nonlinear solution ...
bool _exchange_A_and_B
flag to exchange the A and B matrices in the eigenproblem solution
void project_vector_without_dirichlet(libMesh::NumericVector< Real > &new_vector, libMesh::FunctionBase< Real > &f) const
virtual void adjoint_solve(MAST::AssemblyElemOperations &elem_ops, MAST::OutputAssemblyElemOperations &output, MAST::AssemblyBase &assembly, bool if_assemble_jacobian=true)
solves the adjoint problem for the provided output function.
NonlinearSystem(libMesh::EquationSystems &es, const std::string &name, const unsigned int number)
Default constructor.
virtual void solve(MAST::AssemblyElemOperations &elem_ops, MAST::AssemblyBase &assembly)
solves the nonlinear problem with the specified assembly operation object