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