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 postprocess_solution_.resize(
size);
181 std::fill(save_local_system_.begin(), save_local_system_.end(),
false);
182 std::fill(bc_fluxes_reconstruted.begin(), bc_fluxes_reconstruted.end(),
false);
223 MessageOut() <<
"Duplicate key 'time', time in flow equation is already initialized from parent class!";
263 return next_t * (1 - 2*std::numeric_limits<double>::epsilon());
284 gravity_array.copy_to(gvec);
290 auto field_algo=std::make_shared<FieldConstant<3, FieldValue<3>::VectorFixed>>();
291 field_algo->set_value(gvalue);
292 eq_fields_->gravity_field.set(field_algo, 0.0);
311 MessageOut() <<
"Missing the key 'time', obligatory for the transient problems." << endl;
322 std::shared_ptr< FiniteElement<1> > fe1_rt = std::make_shared<FE_RT0_disc<1>>();
323 std::shared_ptr< FiniteElement<2> > fe2_rt = std::make_shared<FE_RT0_disc<2>>();
324 std::shared_ptr< FiniteElement<3> > fe3_rt = std::make_shared<FE_RT0_disc<3>>();
325 std::shared_ptr< FiniteElement<0> > fe0_disc = std::make_shared<FE_P_disc<0>>(0);
326 std::shared_ptr< FiniteElement<1> > fe1_disc = std::make_shared<FE_P_disc<1>>(0);
327 std::shared_ptr< FiniteElement<2> > fe2_disc = std::make_shared<FE_P_disc<2>>(0);
328 std::shared_ptr< FiniteElement<3> > fe3_disc = std::make_shared<FE_P_disc<3>>(0);
329 std::shared_ptr< FiniteElement<0> > fe0_cr = std::make_shared<FE_CR<0>>();
330 std::shared_ptr< FiniteElement<1> > fe1_cr = std::make_shared<FE_CR<1>>();
331 std::shared_ptr< FiniteElement<2> > fe2_cr = std::make_shared<FE_CR<2>>();
332 std::shared_ptr< FiniteElement<3> > fe3_cr = std::make_shared<FE_CR<3>>();
334 FESystem<0> fe0_sys( {fe0_disc, fe0_disc, fe0_cr} );
340 std::shared_ptr<DiscreteSpace> ds = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_sys);
341 eq_data_->dh_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
351 uint rt_component = 0;
353 auto ele_flux_ptr = create_field_fe<3, FieldValue<3>::VectorFixed>(
eq_data_->dh_, &
eq_data_->full_solution, rt_component);
358 uint p_ele_component = 1;
359 auto ele_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_ele_component);
360 eq_fields_->field_ele_pressure.set(ele_pressure_ptr, 0.0);
362 uint p_edge_component = 2;
363 auto edge_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_edge_component);
364 eq_fields_->field_edge_pressure.set(edge_pressure_ptr, 0.0);
373 uint p_element_component = 1;
374 eq_data_->dh_p_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_element_component);
378 uint p_edge_component = 2;
379 eq_data_->dh_cr_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_edge_component);
384 std::shared_ptr<DiscreteSpace> ds_cr_disc = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_cr_disc);
385 eq_data_->dh_cr_disc_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
386 eq_data_->dh_cr_disc_->distribute_dofs(ds_cr_disc);
397 eq_data_->p_edge_solution_previous_time =
eq_data_->dh_cr_->create_vector();
406 .val<Input::AbstractRecord>(
"linear_solver");
487 eq_data_->p_edge_solution.zero_entries();
489 if (
eq_data_->use_steady_assembly_) {
490 MessageOut() <<
"Flow zero time step - steady case\n";
494 MessageOut() <<
"Flow zero time step - unsteady case\n";
504 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
506 END_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
525 eq_data_->full_solution.local_to_ghost_begin();
526 eq_data_->full_solution.local_to_ghost_end();
535 bool jump_time =
eq_fields_->storativity.is_jump_time();
536 if (! zero_time_term_from_left) {
537 MessageOut() <<
"Flow time step - unsteady case\n";
542 eq_data_->use_steady_assembly_ =
false;
548 WarningOut() <<
"Output of solution discontinuous in time not supported yet.\n";
557 if (! zero_time_term_from_left && ! jump_time && output)
565 if (zero_time_term_from_right) {
566 MessageOut() <<
"Flow time step - steady case\n";
568 eq_data_->use_steady_assembly_ =
true;
573 }
else if (! zero_time_term_from_left && jump_time) {
574 WarningOut() <<
"Discontinuous time term not supported yet.\n";
585 return (
eq_fields_->storativity.input_list_size() == 0);
598 MessageOut().fmt(
"[nonlinear solver] norm of initial residual: {}\n", residual_norm);
601 int is_linear_common;
606 this->
max_n_it_ = nl_solver_rec.
val<
unsigned int>(
"max_it");
607 this->
min_n_it_ = nl_solver_rec.
val<
unsigned int>(
"min_it");
608 if (this->min_n_it_ > this->max_n_it_) this->min_n_it_ = this->
max_n_it_;
610 if (! is_linear_common) {
616 while (
eq_data_->nonlinear_iteration_ < this->min_n_it_ ||
617 (residual_norm > this->tolerance_ &&
eq_data_->nonlinear_iteration_ < this->max_n_it_ )) {
619 convergence_history.push_back(residual_norm);
623 if (convergence_history.size() >= 5 &&
624 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 2] > 0.9 &&
625 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 5] > 0.8) {
628 WarningOut().fmt(
"Accept solution on stagnation. Its: {} Residual: {}\n",
eq_data_->nonlinear_iteration_, residual_norm);
631 THROW(ExcSolverDiverge() << EI_Reason(
"Stagnation."));
635 if (! is_linear_common){
637 eq_data_->p_edge_solution_previous.local_to_ghost_begin();
638 eq_data_->p_edge_solution_previous.local_to_ghost_end();
642 MessageOut().fmt(
"[schur solver] lin. it: {}, reason: {}, residual: {}\n",
648 if (is_linear_common){
651 MessageOut().fmt(
"[nonlinear solver] lin. it: {}, reason: {}, residual: {}\n",
658 VecAXPBY(
eq_data_->p_edge_solution.petsc_vec(), (1-alpha), alpha,
eq_data_->p_edge_solution_previous.petsc_vec());
665 MessageOut().fmt(
"[nonlinear solver] it: {} lin. it: {}, reason: {}, residual: {}\n",
670 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
672 END_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
677 if (
eq_data_->nonlinear_iteration_ < 3) mult = 1.6;
678 if (
eq_data_->nonlinear_iteration_ > 7) mult = 0.7;
688 eq_data_->p_edge_solution_previous_time.copy_from(
eq_data_->p_edge_solution);
689 eq_data_->p_edge_solution_previous_time.local_to_ghost_begin();
690 eq_data_->p_edge_solution_previous_time.local_to_ghost_end();
755 double zeros[100000];
756 for(
int i=0; i<100000; i++) zeros[i] = 0.0;
759 tmp_rows.reserve(200);
762 dofs.reserve(
eq_data_->dh_cr_->max_elem_dofs());
763 dofs_ngh.reserve(
eq_data_->dh_cr_->max_elem_dofs());
769 const uint ndofs = dh_cell.n_dofs();
770 dofs.resize(dh_cell.n_dofs());
771 dh_cell.get_dof_indices(dofs);
773 int* dofs_ptr = dofs.
data();
780 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
788 const uint ndofs_ngh = dh_neighb_cell.
n_dofs();
789 dofs_ngh.resize(ndofs_ngh);
793 tmp_rows.push_back(dofs_ngh[neighb_side.side().side_idx()]);
803 for(
auto &isec : isec_list ) {
807 const uint ndofs_slave = dh_cell_slave.
n_dofs();
808 dofs_ngh.resize(ndofs_slave);
812 for(
unsigned int i_side=0; i_side < dh_cell_slave.
elm()->n_sides(); i_side++) {
813 tmp_rows.push_back( dofs_ngh[i_side] );
953 eq_data_->lin_sys_schur = std::make_shared<LinSys_PETSC>( &(*
eq_data_->dh_cr_->distr()) );
1026 eq_data_->full_solution.zero_entries();
1027 eq_data_->p_edge_solution.zero_entries();
1031 THROW( ExcUnknownSolver() );
1066 START_TIMER(
"DarcyFlowMH::assembly_linear_system");
1069 eq_data_->p_edge_solution.local_to_ghost_begin();
1070 eq_data_->p_edge_solution.local_to_ghost_end();
1092 START_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
1094 END_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
1107 std::string output_file;
1110 double d_max = std::numeric_limits<double>::max();
1111 double h1 = d_max, h2 = d_max, h3 = d_max;
1112 double he2 = d_max, he3 = d_max;
1115 case 1: h1 = std::min(h1,ele.measure());
break;
1116 case 2: h2 = std::min(h2,ele.measure());
break;
1117 case 3: h3 = std::min(h3,ele.measure());
break;
1120 for (
unsigned int j=0; j<ele->n_sides(); j++) {
1122 case 2: he2 = std::min(he2, ele.side(j)->measure());
break;
1123 case 3: he3 = std::min(he3, ele.side(j)->measure());
break;
1127 if(h1 == d_max) h1 = 0;
1128 if(h2 == d_max) h2 = 0;
1129 if(h3 == d_max) h3 = 0;
1130 if(he2 == d_max) he2 = 0;
1131 if(he3 == d_max) he3 = 0;
1134 file = fopen(output_file.c_str(),
"a");
1136 fprintf(file,
"nB = %d;\n",
eq_data_->dh_->mesh()->get_el_ds()->size());
1138 fprintf(file,
"h1 = %e;\nh2 = %e;\nh3 = %e;\n", h1, h2, h3);
1139 fprintf(file,
"he2 = %e;\nhe3 = %e;\n", he2, he3);
1145 PetscViewerASCIIOpen(PETSC_COMM_WORLD, output_file.c_str(), &viewer);
1146 PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);
1147 MatView( *
const_cast<Mat*
>(
lin_sys_schur().get_matrix()), viewer);
1148 VecView( *
const_cast<Vec*
>(
lin_sys_schur().get_rhs()), viewer);
1149 VecView( *
const_cast<Vec*
>(&(
lin_sys_schur().get_solution())), viewer);
1150 VecView( *
const_cast<Vec*
>(&(
eq_data_->full_solution.petsc_vec())), viewer);
1347 if(
time_ !=
nullptr)
1366 ASSERT_LT(component, 3).error(
"Invalid component!");
1367 unsigned int i, n_dofs, min, max;
1371 n_dofs = dh_cell.get_dof_indices(dof_indices);
1373 for (i=min; i<max; ++i) dof_vec.push_back(dof_indices[i]);