28 #include "libmesh/libmesh_logging.h" 29 #include "libmesh/dof_map.h" 30 #include "libmesh/petsc_matrix.h" 31 #include "libmesh/petsc_vector.h" 48 LOG_SCOPE(
"mat_mult()",
"PetscNonlinearSolver");
50 PetscErrorCode ierr=0;
57 void * ctx = PETSC_NULL;
61 ierr = MatShellGetContext(mat, &ctx);
73 ierr = SNESGetSolution(mat_ctx->
snes, &x); CHKERRABORT(solver->comm().get(), ierr);
82 std::vector<libMesh::NumericVector<Real>*>
83 sys_sols (nd,
nullptr),
84 sys_dsols(nd,
nullptr);
90 for (
unsigned int i=0; i< nd; i++) {
99 ierr = VecGetSubVector( x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
103 sys_sols[i] =
new libMesh::PetscVector<Real>( sol[i], sys.comm());
104 if (i == mat_ctx->
j) {
105 sys_dsols[i] =
new libMesh::PetscVector<Real>(dx, sys.comm());
111 sys.get_dof_map().enforce_constraints_exactly(sys, sys_dsols[i],
115 sys_dsols[i] = sys_sols[i]->zero_clone().release();
129 std::unique_ptr<libMesh::NumericVector<Real> >
130 res(
new libMesh::PetscVector<Real>(y, solver->comm()));
136 (*sys_sols [mat_ctx->
i],
137 *sys_dsols[mat_ctx->
i],
146 for (
unsigned int i=0; i< nd; i++) {
159 ierr = VecRestoreSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
171 LOG_SCOPE(
"residual()",
"PetscMultiphysicsNonlinearSolver");
173 PetscErrorCode ierr=0;
189 std::vector<libMesh::NumericVector<Real>*>
190 sys_sols(nd,
nullptr),
191 sys_res (nd,
nullptr);
197 for (
unsigned int i=0; i< nd; i++) {
206 ierr = VecGetSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
207 ierr = VecGetSubVector(r, sys_is, &res[i]); CHKERRABORT(solver->comm().get(), ierr);
209 sys_sols[i] =
new libMesh::PetscVector<Real>(sol[i], sys.comm()),
210 sys_res[i] =
new libMesh::PetscVector<Real>(res[i], sys.comm());
216 sys.get_dof_map().enforce_constraints_exactly(sys, sys_sols[i]);
234 for (
unsigned int i=0; i< nd; i++) {
247 l2_norms[i] = sys_res[i]->l2_norm();
248 global_l2 += pow(l2_norms[i], 2);
251 global_l2 = pow(global_l2, 0.5);
255 <<
"|| R ||_2 = " << global_l2 <<
" : || R_i ||_2 = ( ";
256 for (
unsigned int i=0; i<nd; i++) {
257 libMesh::out << l2_norms[i];
259 libMesh::out <<
" , ";
261 libMesh::out <<
" )" << std::endl;
266 for (
unsigned int i=0; i< nd; i++) {
276 ierr = VecRestoreSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
277 ierr = VecRestoreSubVector(r, sys_is, &res[i]); CHKERRABORT(solver->comm().get(), ierr);
290 LOG_SCOPE(
"jacobian()",
"PetscMultiphysicsNonlinearSolver");
292 PetscErrorCode ierr=0;
309 std::vector<libMesh::NumericVector<Real>*>
310 sys_sols(nd,
nullptr);
316 for (
unsigned int i=0; i< nd; i++) {
325 ierr = VecGetSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
327 sys_sols[i] =
new libMesh::PetscVector<Real>(sol[i], sys.comm());
334 sys.get_dof_map().enforce_constraints_exactly(sys, sys_sols[i]);
347 for (
unsigned int i=0; i< nd; i++) {
367 for (
unsigned int i=0; i< nd; i++) {
376 ierr = VecRestoreSubVector(x, sys_is, &sol[i]); CHKERRABORT(solver->comm().get(), ierr);
381 ierr = MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY); CHKERRABORT(solver->comm().get(), ierr);
382 ierr = MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY); CHKERRABORT(solver->comm().get(), ierr);
394 const std::string& nm,
396 libMesh::ParallelObject (comm_in),
400 _discipline_assembly (n, nullptr),
401 _is (_n_disciplines, PETSC_NULL),
402 _sub_mats (_n_disciplines*_n_disciplines, PETSC_NULL),
468 ierr = SNESCreate(this->comm().
get(), &snes); CHKERRABORT(this->comm().
get(), ierr);
473 const bool sys_name = libMesh::on_command_line(
"--solver_system_names");
475 unsigned int n_local_dofs = 0;
476 std::vector<__mast_multiphysics_petsc_shell_context>
477 mat_ctx(_n_disciplines*_n_disciplines);
489 n_local_dofs += sys.n_local_dofs();
497 dynamic_cast<libMesh::PetscMatrix<Real>*
>(sys.matrix)->
mat();
504 mat_i_m = sys.get_dof_map().n_dofs(),
505 mat_i_n_l = sys.get_dof_map().n_dofs_on_processor(sys.processor_id()),
506 mat_j_m = sys_j.get_dof_map().n_dofs(),
507 mat_j_n_l = sys_j.get_dof_map().n_dofs_on_processor(sys.processor_id());
510 ierr = MatCreateShell(this->comm().
get(),
517 CHKERRABORT(this->comm().
get(), ierr);
520 mat_ctx[i*_n_disciplines+j].i = i;
521 mat_ctx[i*_n_disciplines+j].j = j;
522 mat_ctx[i*_n_disciplines+j].snes = snes;
523 mat_ctx[i*_n_disciplines+j].solver =
this;
525 ierr = MatShellSetContext(
_sub_mats[i*_n_disciplines+j],
526 &mat_ctx[i*_n_disciplines+j]);
527 CHKERRABORT(this->comm().
get(), ierr);
531 ierr = MatShellSetOperation(
_sub_mats[i*_n_disciplines+j],
534 CHKERRABORT(this->comm().
get(), ierr);
540 ierr = MatCreateNest(this->comm().
get(),
541 _n_disciplines, PETSC_NULL,
542 _n_disciplines, PETSC_NULL,
545 CHKERRABORT(this->comm().
get(), ierr);
550 ierr = MatShellSetOperation(
_mat,
551 MATOP_MULT_TRANSPOSE,
553 CHKERRABORT(this->comm().
get(), ierr);
557 nm = this->
name() +
"_";
558 MatSetOptionsPrefix(
_mat, nm.c_str());
560 ierr = MatSetFromOptions(
_mat);
561 CHKERRABORT(this->comm().
get(), ierr);
564 ierr = MatNestGetISs(
_mat, &
_is[0], PETSC_NULL);
565 CHKERRABORT(this->comm().
get(), ierr);
570 ierr = VecCreate(this->comm().
get(), &
_sol); CHKERRABORT(this->comm().
get(), ierr);
571 ierr = VecSetSizes(
_sol, n_local_dofs,
_n_dofs); CHKERRABORT(this->comm().
get(), ierr);
572 ierr = VecSetType(
_sol, VECMPI); CHKERRABORT(this->comm().
get(), ierr);
573 ierr = VecDuplicate(
_sol, &
_res); CHKERRABORT(this->comm().
get(), ierr);
575 ierr = MatShellSetOperation(
_mat,
576 MATOP_MULT_TRANSPOSE_ADD,
578 CHKERRABORT(this->comm().
get(), ierr);
579 ierr = MatShellSetOperation(
_mat,
582 CHKERRABORT(this->comm().
get(), ierr);
591 libMesh::NumericVector<Real>
597 multiphysics_first = 0,
598 multiphysics_last = 0,
599 first = sys_sol.first_local_index(),
600 last = sys_sol.last_local_index();
605 ierr = VecGetSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
606 ierr = VecGetOwnershipRange(sub_vec,
608 &multiphysics_last); CHKERRABORT(this->comm().
get(), ierr);
611 libmesh_assert_equal_to(multiphysics_first, first);
612 libmesh_assert_equal_to( multiphysics_last, last);
614 std::unique_ptr<libMesh::NumericVector<Real> >
615 multiphysics_sol(
new libMesh::PetscVector<Real>(sub_vec, this->comm()));
617 for (
unsigned int i=first; i<last; i++)
618 multiphysics_sol->set(i, sys_sol(i));
620 multiphysics_sol->close();
622 ierr = VecRestoreSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
637 ierr = SNESSetFunction (snes,
641 ierr = SNESSetJacobian(snes,
650 nm = this->
name() +
"_";
651 SNESSetOptionsPrefix(snes, nm.c_str());
657 ierr = SNESGetKSP (snes, &ksp); CHKERRABORT(this->comm().
get(), ierr);
658 ierr = SNESSetFromOptions(snes); CHKERRABORT(this->comm().
get(), ierr);
663 ierr = KSPGetPC(ksp, &pc); CHKERRABORT(this->comm().
get(), ierr);
670 ierr = PCFieldSplitSetIS(pc, nm.c_str(),
_is[i]); CHKERRABORT(this->comm().
get(), ierr);
673 ierr = PCFieldSplitSetIS(pc,
nullptr,
_is[i]);CHKERRABORT(this->comm().
get(), ierr);
683 START_LOG(
"SNESSolve", this->
name()+
"_MultiphysicsSolve");
686 ierr = SNESSolve(snes, PETSC_NULL,
_sol);
688 STOP_LOG(
"SNESSolve", this->
name()+
"_MultiphysicsSolve");
697 libMesh::NumericVector<Real>
703 multiphysics_first = 0,
704 multiphysics_last = 0,
705 first = sys_sol.first_local_index(),
706 last = sys_sol.last_local_index();
711 ierr = VecGetSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
712 ierr = VecGetOwnershipRange(sub_vec,
714 &multiphysics_last); CHKERRABORT(this->comm().
get(), ierr);
717 libmesh_assert_equal_to(multiphysics_first, first);
718 libmesh_assert_equal_to( multiphysics_last, last);
720 std::unique_ptr<libMesh::NumericVector<Real> >
721 multiphysics_sol(
new libMesh::PetscVector<Real>(sub_vec, this->comm()));
723 for (
unsigned int i=first; i<last; i++)
724 sys_sol.set(i, (*multiphysics_sol)(i));
726 ierr = VecRestoreSubVector(
_sol,
_is[i], &sub_vec); CHKERRABORT(this->comm().
get(), ierr);
732 ierr = SNESDestroy(&snes); CHKERRABORT(this->comm().
get(), ierr);
736 ierr = MatDestroy(&
_sub_mats[i*_n_disciplines+j]);
737 CHKERRABORT(this->comm().
get(), ierr);
740 ierr = MatDestroy(&
_mat); CHKERRABORT(this->comm().
get(), ierr);
741 ierr = VecDestroy(&
_sol); CHKERRABORT(this->comm().
get(), ierr);
742 ierr = VecDestroy(&
_res); CHKERRABORT(this->comm().
get(), ierr);
752 PetscErrorCode ierr=0;
756 std::unique_ptr<libMesh::NumericVector<Real> >
757 global_sol (
new libMesh::PetscVector<Real>(
_sol, this->comm())),
758 global_res (
new libMesh::PetscVector<Real>(
_res, this->comm())),
759 global_res0 (global_sol->zero_clone().release());
764 dynamic_cast<libMesh::PetscVector<Real>*
>(global_res0.get())->vec(),
791 std::unique_ptr<libMesh::NumericVector<Real> >
792 dsol_j (sys_j.solution->zero_clone().release()),
793 dJac_ij_dXj(sys_i.solution->zero_clone().release());
795 for (
unsigned int k=0; k<sys_j.n_dofs(); k++) {
798 dsol_j->add(k, delta);
802 vecx =
dynamic_cast<libMesh::PetscVector<Real>*
>(dsol_j.get())->vec(),
803 vecy =
dynamic_cast<libMesh::PetscVector<Real>*
>(dJac_ij_dXj.get())->vec();
813 ierr = VecGetSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
820 libMesh::PetscVector<Real> v(sol_j, this->comm());
828 ierr = VecRestoreSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
837 ierr = VecGetSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
841 libMesh::PetscVector<Real> v(sol_j, this->comm());
848 ierr = VecRestoreSubVector(
_sol, sys_is_j, &sol_j); CHKERRABORT(this->comm().
get(), ierr);
851 global_res->add(-1., *global_res0);
856 ierr = VecGetSubVector(
_res, sys_is_i, &res_i); CHKERRABORT(this->comm().
get(), ierr);
860 libMesh::PetscVector<Real> v(res_i, this->comm());
861 for (
unsigned int l=0; l<sys_i.n_dofs(); l++) {
863 if (dJac_ij_dXj->el(l) != v.el(l))
867 << dJac_ij_dXj->el(l) <<
" " 868 << v.el(l) << std::endl;
871 libMesh::out << std::endl;
874 ierr = VecRestoreSubVector(
_res, sys_is_i, &res_i); CHKERRABORT(this->comm().
get(), ierr);
const MAST::NonlinearSystem & system() const
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()
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 ...
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...
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
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
const std::string name() const
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
void solve()
solves the system using the nested matrices that uses the discipline specific solver options ...
void set_system_assembly(unsigned int i, MAST::TransientAssembly &assembly)
method to set the n^th discipline of this multiphysics system assembly.