28 #include "petscviewer.h"
29 #include "petscerror.h"
84 .
add_value(
MortarP1,
"P1",
"Mortar space: P1 on intersections, using non-conforming pressures.")
94 "Boundary piezometric head for BC types: dirichlet, robin, and river." )
96 "Boundary switch piezometric head for BC types: seepage, river." )
98 "Initial condition for the pressure given as the piezometric head." )
100 return field_descriptor;
107 "Linear solver for MH problem.")
109 "Residual tolerance.")
111 "Minimum number of iterations (linear solutions) to use.\nThis is usefull if the convergence criteria "
112 "does not characterize your goal well enough so it converges prematurely, possibly even without a single linear solution."
113 "If greater then 'max_it' the value is set to 'max_it'.")
115 "Maximum number of iterations (linear solutions) of the non-linear solver.")
117 "If a stagnation of the nonlinear solver is detected the solver stops. "
118 "A divergence is reported by default, forcing the end of the simulation. By setting this flag to 'true', the solver "
119 "ends with convergence success on stagnation, but it reports warning about it.")
124 return it::Record(
"Flow_Darcy_LMH",
"Lumped Mixed-Hybrid solver for saturated Darcy flow.")
128 "Vector of the gravity force. Dimensionless.")
130 "Input data for Darcy flow model.")
132 "Non-linear solver for MH problem.")
134 "Output stream settings.\n Specify file format, precision etc.")
137 IT::Default(
"{ \"fields\": [ \"pressure_p0\", \"velocity_p0\" ] }"),
138 "Specification of output fields and output times.")
140 "Output settings specific to Darcy flow model.\n"
141 "Includes raw output and some experimental functionality.")
143 "Settings for computing mass balance.")
145 "Method for coupling Darcy flow between dimensions on incompatible meshes. [Experimental]" )
151 Input::register_class< DarcyLMH, Mesh &, const Input::Record >(
"Flow_Darcy_LMH") +
203 MessageOut() <<
"Duplicate key 'time', time in flow equation is already initialized from parent class!";
243 gravity_array.copy_to(gvec);
249 auto field_algo=std::make_shared<FieldConstant<3, FieldValue<3>::VectorFixed>>();
250 field_algo->set_value(gvalue);
251 eq_fields_->gravity_field.set(field_algo, 0.0);
270 MessageOut() <<
"Missing the key 'time', obligatory for the transient problems." << endl;
281 std::shared_ptr< FiniteElement<1> > fe1_rt = std::make_shared<FE_RT0_disc<1>>();
282 std::shared_ptr< FiniteElement<2> > fe2_rt = std::make_shared<FE_RT0_disc<2>>();
283 std::shared_ptr< FiniteElement<3> > fe3_rt = std::make_shared<FE_RT0_disc<3>>();
284 std::shared_ptr< FiniteElement<0> > fe0_disc = std::make_shared<FE_P_disc<0>>(0);
285 std::shared_ptr< FiniteElement<1> > fe1_disc = std::make_shared<FE_P_disc<1>>(0);
286 std::shared_ptr< FiniteElement<2> > fe2_disc = std::make_shared<FE_P_disc<2>>(0);
287 std::shared_ptr< FiniteElement<3> > fe3_disc = std::make_shared<FE_P_disc<3>>(0);
288 std::shared_ptr< FiniteElement<0> > fe0_cr = std::make_shared<FE_CR<0>>();
289 std::shared_ptr< FiniteElement<1> > fe1_cr = std::make_shared<FE_CR<1>>();
290 std::shared_ptr< FiniteElement<2> > fe2_cr = std::make_shared<FE_CR<2>>();
291 std::shared_ptr< FiniteElement<3> > fe3_cr = std::make_shared<FE_CR<3>>();
293 FESystem<0> fe0_sys( {fe0_disc, fe0_disc, fe0_cr} );
299 std::shared_ptr<DiscreteSpace> ds = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_sys);
300 eq_data_->dh_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
310 uint rt_component = 0;
312 auto ele_flux_ptr = create_field_fe<3, FieldValue<3>::VectorFixed>(
eq_data_->dh_, &
eq_data_->full_solution, rt_component);
317 uint p_ele_component = 1;
318 auto ele_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_ele_component);
319 eq_fields_->field_ele_pressure.set(ele_pressure_ptr, 0.0);
321 uint p_edge_component = 2;
322 auto edge_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_edge_component);
323 eq_fields_->field_edge_pressure.set(edge_pressure_ptr, 0.0);
332 uint p_element_component = 1;
333 eq_data_->dh_p_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_element_component);
337 uint p_edge_component = 2;
338 eq_data_->dh_cr_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_edge_component);
343 std::shared_ptr<DiscreteSpace> ds_cr_disc = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_cr_disc);
344 eq_data_->dh_cr_disc_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
345 eq_data_->dh_cr_disc_->distribute_dofs(ds_cr_disc);
354 eq_data_->p_edge_solution_previous_time =
eq_data_->dh_cr_->create_vector();
363 .val<Input::AbstractRecord>(
"linear_solver");
416 DebugOut().fmt(
"Read initial condition\n");
420 LocDofVec p_indices = dh_cell.cell_with_other_dh(
eq_data_->dh_p_.get()).get_loc_dof_indices();
422 LocDofVec l_indices = dh_cell.cell_with_other_dh(
eq_data_->dh_cr_.get()).get_loc_dof_indices();
427 unsigned int p_idx =
eq_data_->dh_p_->parent_indices()[p_indices[0]];
428 eq_data_->full_solution.set(p_idx, init_value);
430 for (
unsigned int i=0; i<ele->
n_sides(); i++) {
432 unsigned int l_idx =
eq_data_->dh_cr_->parent_indices()[l_indices[i]];
433 eq_data_->full_solution.add(l_idx, init_value/n_sides_of_edge);
435 eq_data_->p_edge_solution.add(l_indices[i], init_value/n_sides_of_edge);
439 eq_data_->full_solution.ghost_to_local_begin();
440 eq_data_->full_solution.ghost_to_local_end();
442 eq_data_->p_edge_solution.ghost_to_local_begin();
443 eq_data_->p_edge_solution.ghost_to_local_end();
444 eq_data_->p_edge_solution_previous_time.copy_from(
eq_data_->p_edge_solution);
466 eq_data_->p_edge_solution.zero_entries();
468 if (
eq_data_->use_steady_assembly_) {
487 eq_data_->full_solution.copy_from(temp);
509 eq_data_->full_solution.local_to_ghost_begin();
510 eq_data_->full_solution.local_to_ghost_end();
518 bool jump_time =
eq_fields_->storativity.is_jump_time();
519 if (! zero_time_term_from_left) {
524 eq_data_->use_steady_assembly_ =
false;
530 WarningOut() <<
"Output of solution discontinuous in time not supported yet.\n";
539 if (! zero_time_term_from_left && ! jump_time && output)
546 if (zero_time_term_from_right) {
548 eq_data_->use_steady_assembly_ =
true;
553 }
else if (! zero_time_term_from_left && jump_time) {
554 WarningOut() <<
"Discontinuous time term not supported yet.\n";
565 return (
eq_fields_->storativity.input_list_size() == 0);
578 MessageOut().fmt(
"[nonlinear solver] norm of initial residual: {}\n", residual_norm);
581 int is_linear_common;
586 this->
max_n_it_ = nl_solver_rec.
val<
unsigned int>(
"max_it");
587 this->
min_n_it_ = nl_solver_rec.
val<
unsigned int>(
"min_it");
588 if (this->min_n_it_ > this->max_n_it_) this->min_n_it_ = this->
max_n_it_;
590 if (! is_linear_common) {
596 while (nonlinear_iteration_ < this->
min_n_it_ ||
597 (residual_norm > this->tolerance_ && nonlinear_iteration_ < this->
max_n_it_ )) {
599 convergence_history.push_back(residual_norm);
603 if (convergence_history.size() >= 5 &&
604 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 2] > 0.9 &&
605 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 5] > 0.8) {
611 THROW(ExcSolverDiverge() << EI_Reason(
"Stagnation."));
615 if (! is_linear_common){
617 eq_data_->p_edge_solution_previous.local_to_ghost_begin();
618 eq_data_->p_edge_solution_previous.local_to_ghost_end();
622 MessageOut().fmt(
"[schur solver] lin. it: {}, reason: {}, residual: {}\n",
628 if (is_linear_common){
631 MessageOut().fmt(
"[nonlinear solver] lin. it: {}, reason: {}, residual: {}\n",
638 VecAXPBY(
eq_data_->p_edge_solution.petsc_vec(), (1-alpha), alpha,
eq_data_->p_edge_solution_previous.petsc_vec());
645 MessageOut().fmt(
"[nonlinear solver] it: {} lin. it: {}, reason: {}, residual: {}\n",
665 eq_data_->p_edge_solution_previous_time.copy_from(
eq_data_->p_edge_solution);
666 eq_data_->p_edge_solution_previous_time.local_to_ghost_begin();
667 eq_data_->p_edge_solution_previous_time.local_to_ghost_end();
689 return eq_data_->lin_sys_schur->get_solution_precision();
701 START_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
714 unsigned int dim = dh_cell.dim();
715 assembler[dim-1]->assemble(dh_cell);
731 double zeros[100000];
732 for(
int i=0; i<100000; i++) zeros[i] = 0.0;
735 tmp_rows.reserve(200);
738 dofs.reserve(
eq_data_->dh_cr_->max_elem_dofs());
739 dofs_ngh.reserve(
eq_data_->dh_cr_->max_elem_dofs());
745 const uint ndofs = dh_cell.n_dofs();
746 dofs.resize(dh_cell.n_dofs());
747 dh_cell.get_dof_indices(dofs);
749 int* dofs_ptr = dofs.
data();
756 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
764 const uint ndofs_ngh = dh_neighb_cell.
n_dofs();
765 dofs_ngh.resize(ndofs_ngh);
769 tmp_rows.push_back(dofs_ngh[neighb_side.side().side_idx()]);
779 for(
auto &isec : isec_list ) {
783 const uint ndofs_slave = dh_cell_slave.
n_dofs();
784 dofs_ngh.resize(ndofs_slave);
788 for(
unsigned int i_side=0; i_side < dh_cell_slave.
elm()->n_sides(); i_side++) {
789 tmp_rows.push_back( dofs_ngh[i_side] );
929 eq_data_->lin_sys_schur = std::make_shared<LinSys_PETSC>( &(*
eq_data_->dh_cr_->distr()) );
1002 eq_data_->full_solution.zero_entries();
1003 eq_data_->p_edge_solution.zero_entries();
1007 THROW( ExcUnknownSolver() );
1018 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
1020 eq_data_->full_solution.zero_entries();
1021 eq_data_->p_edge_solution.local_to_ghost_begin();
1022 eq_data_->p_edge_solution.local_to_ghost_end();
1029 unsigned int dim = dh_cell.dim();
1030 assembler[dim-1]->assemble_reconstruct(dh_cell);
1033 eq_data_->full_solution.local_to_ghost_begin();
1034 eq_data_->full_solution.local_to_ghost_end();
1042 START_TIMER(
"DarcyFlowMH::assembly_linear_system");
1045 eq_data_->p_edge_solution.local_to_ghost_begin();
1046 eq_data_->p_edge_solution.local_to_ghost_end();
1080 std::string output_file;
1083 double d_max = std::numeric_limits<double>::max();
1084 double h1 = d_max, h2 = d_max, h3 = d_max;
1085 double he2 = d_max, he3 = d_max;
1088 case 1: h1 = std::min(h1,ele.measure());
break;
1089 case 2: h2 = std::min(h2,ele.measure());
break;
1090 case 3: h3 = std::min(h3,ele.measure());
break;
1093 for (
unsigned int j=0; j<ele->n_sides(); j++) {
1095 case 2: he2 = std::min(he2, ele.side(j)->measure());
break;
1096 case 3: he3 = std::min(he3, ele.side(j)->measure());
break;
1100 if(h1 == d_max) h1 = 0;
1101 if(h2 == d_max) h2 = 0;
1102 if(h3 == d_max) h3 = 0;
1103 if(he2 == d_max) he2 = 0;
1104 if(he3 == d_max) he3 = 0;
1107 file = fopen(output_file.c_str(),
"a");
1109 fprintf(file,
"nB = %d;\n",
eq_data_->dh_->mesh()->get_el_ds()->size());
1111 fprintf(file,
"h1 = %e;\nh2 = %e;\nh3 = %e;\n", h1, h2, h3);
1112 fprintf(file,
"he2 = %e;\nhe3 = %e;\n", he2, he3);
1118 PetscViewerASCIIOpen(PETSC_COMM_WORLD, output_file.c_str(), &viewer);
1119 PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);
1120 MatView( *
const_cast<Mat*
>(
lin_sys_schur().get_matrix()), viewer);
1121 VecView( *
const_cast<Vec*
>(
lin_sys_schur().get_rhs()), viewer);
1122 VecView( *
const_cast<Vec*
>(&(
lin_sys_schur().get_solution())), viewer);
1123 VecView( *
const_cast<Vec*
>(&(
eq_data_->full_solution.petsc_vec())), viewer);
1322 if(
time_ !=
nullptr)
1330 unsigned int i, n_dofs, min, max;
1334 n_dofs = dh_cell.get_dof_indices(dof_indices);
1336 for (i=min; i<max; ++i) dof_vec.push_back(dof_indices[i]);