28 #include "petscviewer.h"
29 #include "petscerror.h"
85 .
add_value(
MortarP1,
"P1",
"Mortar space: P1 on intersections, using non-conforming pressures.")
95 "Boundary piezometric head for BC types: dirichlet, robin, and river." )
97 "Boundary switch piezometric head for BC types: seepage, river." )
99 "Initial condition for the pressure given as the piezometric head." )
101 return field_descriptor;
108 "Linear solver for MH problem.")
110 "Residual tolerance.")
112 "Minimum number of iterations (linear solutions) to use.\nThis is usefull if the convergence criteria "
113 "does not characterize your goal well enough so it converges prematurely, possibly even without a single linear solution."
114 "If greater then 'max_it' the value is set to 'max_it'.")
116 "Maximum number of iterations (linear solutions) of the non-linear solver.")
118 "If a stagnation of the nonlinear solver is detected the solver stops. "
119 "A divergence is reported by default, forcing the end of the simulation. By setting this flag to 'true', the solver "
120 "ends with convergence success on stagnation, but it reports warning about it.")
125 return it::Record(
"Flow_Darcy_LMH",
"Lumped Mixed-Hybrid solver for saturated Darcy flow.")
129 "Vector of the gravity force. Dimensionless.")
131 "Input data for Darcy flow model.")
133 "Non-linear solver for MH problem.")
135 "Output stream settings.\n Specify file format, precision etc.")
138 IT::Default(
"{ \"fields\": [ \"pressure_p0\", \"velocity_p0\" ] }"),
139 "Specification of output fields and output times.")
141 "Output settings specific to Darcy flow model.\n"
142 "Includes raw output and some experimental functionality.")
144 "Settings for computing mass balance.")
146 "Method for coupling Darcy flow between dimensions on incompatible meshes. [Experimental]" )
152 Input::register_class< DarcyLMH, Mesh &, const Input::Record >(
"Flow_Darcy_LMH") +
171 auto size = dh_p_->get_local_to_global_map().size();
172 save_local_system_.resize(
size);
173 bc_fluxes_reconstruted.resize(
size);
174 loc_system_.resize(
size);
175 loc_schur_.resize(
size);
176 postprocess_solution_.resize(
size);
182 std::fill(save_local_system_.begin(), save_local_system_.end(),
false);
183 std::fill(bc_fluxes_reconstruted.begin(), bc_fluxes_reconstruted.end(),
false);
224 MessageOut() <<
"Duplicate key 'time', time in flow equation is already initialized from parent class!";
264 return next_t * (1 - 2*std::numeric_limits<double>::epsilon());
285 gravity_array.copy_to(gvec);
291 auto field_algo=std::make_shared<FieldConstant<3, FieldValue<3>::VectorFixed>>();
292 field_algo->set_value(gvalue);
293 eq_fields_->gravity_field.set(field_algo, 0.0);
312 MessageOut() <<
"Missing the key 'time', obligatory for the transient problems." << endl;
323 std::shared_ptr< FiniteElement<1> > fe1_rt = std::make_shared<FE_RT0_disc<1>>();
324 std::shared_ptr< FiniteElement<2> > fe2_rt = std::make_shared<FE_RT0_disc<2>>();
325 std::shared_ptr< FiniteElement<3> > fe3_rt = std::make_shared<FE_RT0_disc<3>>();
326 std::shared_ptr< FiniteElement<0> > fe0_disc = std::make_shared<FE_P_disc<0>>(0);
327 std::shared_ptr< FiniteElement<1> > fe1_disc = std::make_shared<FE_P_disc<1>>(0);
328 std::shared_ptr< FiniteElement<2> > fe2_disc = std::make_shared<FE_P_disc<2>>(0);
329 std::shared_ptr< FiniteElement<3> > fe3_disc = std::make_shared<FE_P_disc<3>>(0);
330 std::shared_ptr< FiniteElement<0> > fe0_cr = std::make_shared<FE_CR<0>>();
331 std::shared_ptr< FiniteElement<1> > fe1_cr = std::make_shared<FE_CR<1>>();
332 std::shared_ptr< FiniteElement<2> > fe2_cr = std::make_shared<FE_CR<2>>();
333 std::shared_ptr< FiniteElement<3> > fe3_cr = std::make_shared<FE_CR<3>>();
335 FESystem<0> fe0_sys( {fe0_disc, fe0_disc, fe0_cr} );
341 std::shared_ptr<DiscreteSpace> ds = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_sys);
342 eq_data_->dh_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
352 uint rt_component = 0;
354 auto ele_flux_ptr = create_field_fe<3, FieldValue<3>::VectorFixed>(
eq_data_->dh_, &
eq_data_->full_solution, rt_component);
359 uint p_ele_component = 1;
360 auto ele_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_ele_component);
361 eq_fields_->field_ele_pressure.set(ele_pressure_ptr, 0.0);
363 uint p_edge_component = 2;
364 auto edge_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_edge_component);
365 eq_fields_->field_edge_pressure.set(edge_pressure_ptr, 0.0);
374 uint p_element_component = 1;
375 eq_data_->dh_p_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_element_component);
379 uint p_edge_component = 2;
380 eq_data_->dh_cr_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_edge_component);
385 std::shared_ptr<DiscreteSpace> ds_cr_disc = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_cr_disc);
386 eq_data_->dh_cr_disc_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
387 eq_data_->dh_cr_disc_->distribute_dofs(ds_cr_disc);
398 eq_data_->p_edge_solution_previous_time =
eq_data_->dh_cr_->create_vector();
407 .val<Input::AbstractRecord>(
"linear_solver");
488 eq_data_->p_edge_solution.zero_entries();
490 if (
eq_data_->use_steady_assembly_) {
491 MessageOut() <<
"Flow zero time step - steady case\n";
495 MessageOut() <<
"Flow zero time step - unsteady case\n";
506 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
508 END_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
527 eq_data_->full_solution.local_to_ghost_begin();
528 eq_data_->full_solution.local_to_ghost_end();
537 bool jump_time =
eq_fields_->storativity.is_jump_time();
538 if (! zero_time_term_from_left) {
539 MessageOut() <<
"Flow time step - unsteady case\n";
544 eq_data_->use_steady_assembly_ =
false;
550 WarningOut() <<
"Output of solution discontinuous in time not supported yet.\n";
559 if (! zero_time_term_from_left && ! jump_time && output)
567 if (zero_time_term_from_right) {
568 MessageOut() <<
"Flow time step - steady case\n";
570 eq_data_->use_steady_assembly_ =
true;
575 }
else if (! zero_time_term_from_left && jump_time) {
576 WarningOut() <<
"Discontinuous time term not supported yet.\n";
587 return (
eq_fields_->storativity.input_list_size() == 0);
600 MessageOut().fmt(
"[nonlinear solver] norm of initial residual: {}\n", residual_norm);
603 int is_linear_common;
608 this->
max_n_it_ = nl_solver_rec.
val<
unsigned int>(
"max_it");
609 this->
min_n_it_ = nl_solver_rec.
val<
unsigned int>(
"min_it");
610 if (this->min_n_it_ > this->max_n_it_) this->min_n_it_ = this->
max_n_it_;
612 if (! is_linear_common) {
618 while (
eq_data_->nonlinear_iteration_ < this->min_n_it_ ||
619 (residual_norm > this->tolerance_ &&
eq_data_->nonlinear_iteration_ < this->max_n_it_ )) {
621 convergence_history.push_back(residual_norm);
625 if (convergence_history.size() >= 5 &&
626 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 2] > 0.9 &&
627 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 5] > 0.8) {
630 WarningOut().fmt(
"Accept solution on stagnation. Its: {} Residual: {}\n",
eq_data_->nonlinear_iteration_, residual_norm);
633 THROW(ExcSolverDiverge() << EI_Reason(
"Stagnation."));
637 if (! is_linear_common){
639 eq_data_->p_edge_solution_previous.local_to_ghost_begin();
640 eq_data_->p_edge_solution_previous.local_to_ghost_end();
644 MessageOut().fmt(
"[schur solver] lin. it: {}, reason: {}, residual: {}\n",
650 if (is_linear_common){
653 MessageOut().fmt(
"[nonlinear solver] lin. it: {}, reason: {}, residual: {}\n",
660 VecAXPBY(
eq_data_->p_edge_solution.petsc_vec(), (1-alpha), alpha,
eq_data_->p_edge_solution_previous.petsc_vec());
667 MessageOut().fmt(
"[nonlinear solver] it: {} lin. it: {}, reason: {}, residual: {}\n",
672 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
674 END_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
679 if (
eq_data_->nonlinear_iteration_ < 3) mult = 1.6;
680 if (
eq_data_->nonlinear_iteration_ > 7) mult = 0.7;
690 eq_data_->p_edge_solution_previous_time.copy_from(
eq_data_->p_edge_solution);
691 eq_data_->p_edge_solution_previous_time.local_to_ghost_begin();
692 eq_data_->p_edge_solution_previous_time.local_to_ghost_end();
757 double zeros[100000];
758 for(
int i=0; i<100000; i++) zeros[i] = 0.0;
761 tmp_rows.reserve(200);
764 dofs.reserve(
eq_data_->dh_cr_->max_elem_dofs());
765 dofs_ngh.reserve(
eq_data_->dh_cr_->max_elem_dofs());
771 const uint ndofs = dh_cell.n_dofs();
772 dofs.resize(dh_cell.n_dofs());
773 dh_cell.get_dof_indices(dofs);
775 int* dofs_ptr = dofs.
data();
782 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
790 const uint ndofs_ngh = dh_neighb_cell.
n_dofs();
791 dofs_ngh.resize(ndofs_ngh);
795 tmp_rows.push_back(dofs_ngh[neighb_side.side().side_idx()]);
805 for(
auto &isec : isec_list ) {
809 const uint ndofs_slave = dh_cell_slave.
n_dofs();
810 dofs_ngh.resize(ndofs_slave);
814 for(
unsigned int i_side=0; i_side < dh_cell_slave.
elm()->n_sides(); i_side++) {
815 tmp_rows.push_back( dofs_ngh[i_side] );
955 eq_data_->lin_sys_schur = std::make_shared<LinSys_PETSC>( &(*
eq_data_->dh_cr_->distr()) );
1028 eq_data_->full_solution.zero_entries();
1029 eq_data_->p_edge_solution.zero_entries();
1033 THROW( ExcUnknownSolver() );
1068 START_TIMER(
"DarcyFlowMH::assembly_linear_system");
1071 eq_data_->p_edge_solution.local_to_ghost_begin();
1072 eq_data_->p_edge_solution.local_to_ghost_end();
1094 START_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
1096 END_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
1109 std::string output_file;
1112 double d_max = std::numeric_limits<double>::max();
1113 double h1 = d_max, h2 = d_max, h3 = d_max;
1114 double he2 = d_max, he3 = d_max;
1117 case 1: h1 = std::min(h1,ele.measure());
break;
1118 case 2: h2 = std::min(h2,ele.measure());
break;
1119 case 3: h3 = std::min(h3,ele.measure());
break;
1122 for (
unsigned int j=0; j<ele->n_sides(); j++) {
1124 case 2: he2 = std::min(he2, ele.side(j)->measure());
break;
1125 case 3: he3 = std::min(he3, ele.side(j)->measure());
break;
1129 if(h1 == d_max) h1 = 0;
1130 if(h2 == d_max) h2 = 0;
1131 if(h3 == d_max) h3 = 0;
1132 if(he2 == d_max) he2 = 0;
1133 if(he3 == d_max) he3 = 0;
1136 file = fopen(output_file.c_str(),
"a");
1138 fprintf(file,
"nB = %d;\n",
eq_data_->dh_->mesh()->get_el_ds()->size());
1140 fprintf(file,
"h1 = %e;\nh2 = %e;\nh3 = %e;\n", h1, h2, h3);
1141 fprintf(file,
"he2 = %e;\nhe3 = %e;\n", he2, he3);
1147 PetscViewerASCIIOpen(PETSC_COMM_WORLD, output_file.c_str(), &viewer);
1148 PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);
1149 MatView( *
const_cast<Mat*
>(
lin_sys_schur().get_matrix()), viewer);
1150 VecView( *
const_cast<Vec*
>(
lin_sys_schur().get_rhs()), viewer);
1151 VecView( *
const_cast<Vec*
>(&(
lin_sys_schur().get_solution())), viewer);
1152 VecView( *
const_cast<Vec*
>(&(
eq_data_->full_solution.petsc_vec())), viewer);
1351 if(
time_ !=
nullptr)
1371 unsigned int i, n_dofs, min, max;
1375 n_dofs = dh_cell.get_dof_indices(dof_indices);
1377 for (i=min; i<max; ++i) dof_vec.push_back(dof_indices[i]);