28 #include "libmesh/dof_map.h" 29 #include "libmesh/petsc_matrix.h" 30 #include "libmesh/petsc_vector.h" 47 LOG_SCOPE(
"mat_mult()",
"PetscNonlinearSolver");
49 PetscErrorCode ierr=0;
56 void * ctx = PETSC_NULL;
60 ierr = MatShellGetContext(mat, &ctx);
72 ierr = SNESGetSolution(mat_ctx->
snes, &x); CHKERRABORT(solver->comm().get(), ierr);
81 std::vector<libMesh::NumericVector<Real>*>
82 sys_sols (nd,
nullptr),
83 sys_dsols(nd,
nullptr);
89 for (
unsigned int i=0; i< nd; i++) {
98 ierr = VecGetSubVector( x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
102 sys_sols[i] =
new libMesh::PetscVector<Real>( sol[i], sys.comm());
103 if (i == mat_ctx->
j) {
104 sys_dsols[i] =
new libMesh::PetscVector<Real>(dx, sys.comm());
110 sys.get_dof_map().enforce_constraints_exactly(sys, sys_dsols[i],
114 sys_dsols[i] = sys_sols[i]->zero_clone().release();
128 std::unique_ptr<libMesh::NumericVector<Real> >
129 res(
new libMesh::PetscVector<Real>(y, solver->comm()));
135 (*sys_sols [mat_ctx->
i],
136 *sys_dsols[mat_ctx->
i],
145 for (
unsigned int i=0; i< nd; i++) {
158 ierr = VecRestoreSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
170 LOG_SCOPE(
"residual()",
"PetscMultiphysicsNonlinearSolver");
172 PetscErrorCode ierr=0;
188 std::vector<libMesh::NumericVector<Real>*>
189 sys_sols(nd,
nullptr),
190 sys_res (nd,
nullptr);
196 for (
unsigned int i=0; i< nd; i++) {
205 ierr = VecGetSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
206 ierr = VecGetSubVector(r, sys_is, &res[i]); CHKERRABORT(solver->comm().get(), ierr);
208 sys_sols[i] =
new libMesh::PetscVector<Real>(sol[i], sys.comm()),
209 sys_res[i] =
new libMesh::PetscVector<Real>(res[i], sys.comm());
215 sys.get_dof_map().enforce_constraints_exactly(sys, sys_sols[i]);
233 for (
unsigned int i=0; i< nd; i++) {
246 l2_norms[i] = sys_res[i]->l2_norm();
247 global_l2 += pow(l2_norms[i], 2);
250 global_l2 = pow(global_l2, 0.5);
254 <<
"|| R ||_2 = " << global_l2 <<
" : || R_i ||_2 = ( ";
255 for (
unsigned int i=0; i<nd; i++) {
256 libMesh::out << l2_norms[i];
258 libMesh::out <<
" , ";
260 libMesh::out <<
" )" << std::endl;
265 for (
unsigned int i=0; i< nd; i++) {
275 ierr = VecRestoreSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
276 ierr = VecRestoreSubVector(r, sys_is, &res[i]); CHKERRABORT(solver->comm().get(), ierr);
289 LOG_SCOPE(
"jacobian()",
"PetscMultiphysicsNonlinearSolver");
291 PetscErrorCode ierr=0;
308 std::vector<libMesh::NumericVector<Real>*>
309 sys_sols(nd,
nullptr);
315 for (
unsigned int i=0; i< nd; i++) {
324 ierr = VecGetSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
326 sys_sols[i] =
new libMesh::PetscVector<Real>(sol[i], sys.comm());
333 sys.get_dof_map().enforce_constraints_exactly(sys, sys_sols[i]);
346 for (
unsigned int i=0; i< nd; i++) {
366 for (
unsigned int i=0; i< nd; i++) {
375 ierr = VecRestoreSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
380 ierr = MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY); CHKERRABORT(solver->comm().get(), ierr);
381 ierr = MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY); CHKERRABORT(solver->comm().get(), ierr);
393 const std::string& nm,
395 libMesh::ParallelObject (comm_in),
399 _discipline_assembly (n, nullptr),
400 _is (_n_disciplines, PETSC_NULL),
401 _sub_mats (_n_disciplines*_n_disciplines, PETSC_NULL),
467 ierr = SNESCreate(this->comm().
get(), &snes); CHKERRABORT(this->comm().
get(), ierr);
472 const bool sys_name = libMesh::on_command_line(
"--solver_system_names");
474 unsigned int n_local_dofs = 0;
475 std::vector<__mast_multiphysics_petsc_shell_context>
476 mat_ctx(_n_disciplines*_n_disciplines);
488 n_local_dofs += sys.n_local_dofs();
496 dynamic_cast<libMesh::PetscMatrix<Real>*
>(sys.matrix)->
mat();
503 mat_i_m = sys.get_dof_map().n_dofs(),
504 mat_i_n_l = sys.get_dof_map().n_dofs_on_processor(sys.processor_id()),
505 mat_j_m = sys_j.get_dof_map().n_dofs(),
506 mat_j_n_l = sys_j.get_dof_map().n_dofs_on_processor(sys.processor_id());
509 ierr = MatCreateShell(this->comm().
get(),
516 CHKERRABORT(this->comm().
get(), ierr);
519 mat_ctx[i*_n_disciplines+j].i = i;
520 mat_ctx[i*_n_disciplines+j].j = j;
521 mat_ctx[i*_n_disciplines+j].snes = snes;
522 mat_ctx[i*_n_disciplines+j].solver =
this;
524 ierr = MatShellSetContext(
_sub_mats[i*_n_disciplines+j],
525 &mat_ctx[i*_n_disciplines+j]);
526 CHKERRABORT(this->comm().
get(), ierr);
530 ierr = MatShellSetOperation(
_sub_mats[i*_n_disciplines+j],
533 CHKERRABORT(this->comm().
get(), ierr);
539 ierr = MatCreateNest(this->comm().
get(),
540 _n_disciplines, PETSC_NULL,
541 _n_disciplines, PETSC_NULL,
544 CHKERRABORT(this->comm().
get(), ierr);
549 ierr = MatShellSetOperation(
_mat,
550 MATOP_MULT_TRANSPOSE,
552 CHKERRABORT(this->comm().
get(), ierr);
556 nm = this->
name() +
"_";
557 MatSetOptionsPrefix(
_mat, nm.c_str());
559 ierr = MatSetFromOptions(
_mat);
560 CHKERRABORT(this->comm().
get(), ierr);
563 ierr = MatNestGetISs(
_mat, &
_is[0], PETSC_NULL);
564 CHKERRABORT(this->comm().
get(), ierr);
569 ierr = VecCreate(this->comm().
get(), &
_sol); CHKERRABORT(this->comm().
get(), ierr);
570 ierr = VecSetSizes(
_sol, n_local_dofs,
_n_dofs); CHKERRABORT(this->comm().
get(), ierr);
571 ierr = VecSetType(
_sol, VECMPI); CHKERRABORT(this->comm().
get(), ierr);
572 ierr = VecDuplicate(
_sol, &
_res); CHKERRABORT(this->comm().
get(), ierr);
574 ierr = MatShellSetOperation(
_mat,
575 MATOP_MULT_TRANSPOSE_ADD,
577 CHKERRABORT(this->comm().
get(), ierr);
578 ierr = MatShellSetOperation(
_mat,
581 CHKERRABORT(this->comm().
get(), ierr);
590 libMesh::NumericVector<Real>
596 multiphysics_first = 0,
597 multiphysics_last = 0,
598 first = sys_sol.first_local_index(),
599 last = sys_sol.last_local_index();
604 ierr = VecGetSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
605 ierr = VecGetOwnershipRange(sub_vec,
607 &multiphysics_last); CHKERRABORT(this->comm().
get(), ierr);
610 libmesh_assert_equal_to(multiphysics_first, first);
611 libmesh_assert_equal_to( multiphysics_last, last);
613 std::unique_ptr<libMesh::NumericVector<Real> >
614 multiphysics_sol(
new libMesh::PetscVector<Real>(sub_vec, this->comm()));
616 for (
unsigned int i=first; i<last; i++)
617 multiphysics_sol->set(i, sys_sol(i));
619 multiphysics_sol->close();
621 ierr = VecRestoreSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
636 ierr = SNESSetFunction (snes,
640 ierr = SNESSetJacobian(snes,
649 nm = this->
name() +
"_";
650 SNESSetOptionsPrefix(snes, nm.c_str());
656 ierr = SNESGetKSP (snes, &ksp); CHKERRABORT(this->comm().
get(), ierr);
657 ierr = SNESSetFromOptions(snes); CHKERRABORT(this->comm().
get(), ierr);
662 ierr = KSPGetPC(ksp, &pc); CHKERRABORT(this->comm().
get(), ierr);
669 ierr = PCFieldSplitSetIS(pc, nm.c_str(),
_is[i]); CHKERRABORT(this->comm().
get(), ierr);
672 ierr = PCFieldSplitSetIS(pc,
nullptr,
_is[i]);CHKERRABORT(this->comm().
get(), ierr);
682 START_LOG(
"SNESSolve", this->
name()+
"_MultiphysicsSolve");
685 ierr = SNESSolve(snes, PETSC_NULL,
_sol);
687 STOP_LOG(
"SNESSolve", this->
name()+
"_MultiphysicsSolve");
696 libMesh::NumericVector<Real>
702 multiphysics_first = 0,
703 multiphysics_last = 0,
704 first = sys_sol.first_local_index(),
705 last = sys_sol.last_local_index();
710 ierr = VecGetSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
711 ierr = VecGetOwnershipRange(sub_vec,
713 &multiphysics_last); CHKERRABORT(this->comm().
get(), ierr);
716 libmesh_assert_equal_to(multiphysics_first, first);
717 libmesh_assert_equal_to( multiphysics_last, last);
719 std::unique_ptr<libMesh::NumericVector<Real> >
720 multiphysics_sol(
new libMesh::PetscVector<Real>(sub_vec, this->comm()));
722 for (
unsigned int i=first; i<last; i++)
723 sys_sol.set(i, (*multiphysics_sol)(i));
725 ierr = VecRestoreSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
731 ierr = SNESDestroy(&snes); CHKERRABORT(this->comm().
get(), ierr);
735 ierr = MatDestroy(&
_sub_mats[i*_n_disciplines+j]);
736 CHKERRABORT(this->comm().
get(), ierr);
739 ierr = MatDestroy(&
_mat); CHKERRABORT(this->comm().
get(), ierr);
740 ierr = VecDestroy(&
_sol); CHKERRABORT(this->comm().
get(), ierr);
741 ierr = VecDestroy(&
_res); CHKERRABORT(this->comm().
get(), ierr);
751 PetscErrorCode ierr=0;
755 std::unique_ptr<libMesh::NumericVector<Real> >
756 global_sol (
new libMesh::PetscVector<Real>(
_sol, this->comm())),
757 global_res (
new libMesh::PetscVector<Real>(
_res, this->comm())),
758 global_res0 (global_sol->zero_clone().release());
763 dynamic_cast<libMesh::PetscVector<Real>*
>(global_res0.get())->vec(),
790 std::unique_ptr<libMesh::NumericVector<Real> >
791 dsol_j (sys_j.solution->zero_clone().release()),
792 dJac_ij_dXj(sys_i.solution->zero_clone().release());
794 for (
unsigned int k=0; k<sys_j.n_dofs(); k++) {
797 dsol_j->add(k, delta);
801 vecx =
dynamic_cast<libMesh::PetscVector<Real>*
>(dsol_j.get())->vec(),
802 vecy =
dynamic_cast<libMesh::PetscVector<Real>*
>(dJac_ij_dXj.get())->vec();
812 ierr = VecGetSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
819 libMesh::PetscVector<Real> v(sol_j, this->comm());
827 ierr = VecRestoreSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
836 ierr = VecGetSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
840 libMesh::PetscVector<Real> v(sol_j, this->comm());
847 ierr = VecRestoreSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
850 global_res->add(-1., *global_res0);
855 ierr = VecGetSubVector(
_res, sys_is_i, &res_i); CHKERRABORT(this->comm().
get(), ierr);
859 libMesh::PetscVector<Real> v(res_i, this->comm());
860 for (
unsigned int l=0; l<sys_i.n_dofs(); l++) {
862 if (dJac_ij_dXj->el(l) != v.el(l))
866 << dJac_ij_dXj->el(l) <<
" " 867 << v.el(l) << std::endl;
870 libMesh::out << std::endl;
873 ierr = VecRestoreSubVector(
_res, sys_is_i, &res_i); CHKERRABORT(this->comm().
get(), ierr);
MultiphysicsNonlinearSolverBase(const libMesh::Parallel::Communicator &comm_in, const std::string &nm, unsigned int n)
default constructor
MAST::MultiphysicsNonlinearSolverBase * solver
This class implements a system for solution of nonlinear systems.
virtual ~MultiphysicsNonlinearSolverBase()
destructor
std::vector< IS > & index_sets()
PetscErrorCode __mast_multiphysics_petsc_snes_residual(SNES snes, Vec x, Vec r, void *ctx)
void verify_gateaux_derivatives(SNES snes)
PetscErrorCode __mast_multiphysics_petsc_snes_jacobian(SNES snes, Vec x, Mat jac, Mat pc, void *ctx)
virtual void linearized_jacobian_solution_product(const libMesh::NumericVector< Real > &X, const libMesh::NumericVector< Real > &dX, libMesh::NumericVector< Real > &JdX, libMesh::NonlinearImplicitSystem &S)
calculates the product of the Jacobian and a perturbation in solution vector .
std::vector< MAST::TransientAssembly * > _discipline_assembly
vector of assembly objects for each discipline in this multiphysics system
const unsigned int _n_disciplines
number of disciplines
const std::string name() const
PetscErrorCode __mast_multiphysics_petsc_mat_mult(Mat mat, Vec dx, Vec y)
MAST::TransientAssembly & get_system_assembly(unsigned int i)
MAST::MultiphysicsNonlinearSolverBase::PreResidualUpdate * get_pre_residual_update_object()
returns a pointer to the update object
std::vector< Mat > _sub_mats
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 ...
unsigned int n_disciplines() const
virtual void update_at_perturbed_solution(std::vector< libMesh::NumericVector< Real > * > &sol_vecs, std::vector< libMesh::NumericVector< Real > * > &dsol_vecs)=0
sol_vecs is the vector containing the solution for each discipline in this multiphysics solution...
void solve()
solves the system using the nested matrices that uses the discipline specific solver options ...
const MAST::NonlinearSystem & system() const
virtual void update_at_solution(std::vector< libMesh::NumericVector< Real > * > &sol_vecs)=0
sol_vecs is the vector containing the solution for each discipline in this multiphysics solution ...
void set_system_assembly(unsigned int i, MAST::TransientAssembly &assembly)
method to set the n^th discipline of this multiphysics system assembly.