28 #include "petscviewer.h"
29 #include "petscerror.h"
87 .
add_value(
MortarP1,
"P1",
"Mortar space: P1 on intersections, using non-conforming pressures.")
97 "Boundary piezometric head for BC types: dirichlet, robin, and river." )
99 "Boundary switch piezometric head for BC types: seepage, river." )
101 "Initial condition for the pressure given as the piezometric head." )
103 return field_descriptor;
109 "Linear solver for MH problem.")
111 "Residual tolerance.")
113 "Minimum number of iterations (linear solutions) to use.\nThis is usefull if the convergence criteria "
114 "does not characterize your goal well enough so it converges prematurely, possibly even without a single linear solution."
115 "If greater then 'max_it' the value is set to 'max_it'.")
117 "Maximum number of iterations (linear solutions) of the non-linear solver.")
119 "If a stagnation of the nonlinear solver is detected the solver stops. "
120 "A divergence is reported by default, forcing the end of the simulation. By setting this flag to 'true', the solver "
121 "ends with convergence success on stagnation, but it reports warning about it.")
130 "Vector of the gravity force. Dimensionless.")
133 "Input fields of the equation defined by user.")
135 "Input data for Darcy flow model.")
137 "Non-linear solver for MH problem.")
139 "Output stream settings.\n Specify file format, precision etc.")
142 IT::Default(
"{ \"fields\": [ \"pressure_p0\", \"velocity_p0\" ] }"),
143 "Specification of output fields and output times.")
145 "Output settings specific to Darcy flow model.\n"
146 "Includes raw output and some experimental functionality.")
148 "Settings for computing mass balance.")
150 "Method for coupling Darcy flow between dimensions on incompatible meshes. [Experimental]" )
156 Input::register_class< DarcyLMH, Mesh &, const Input::Record >(equation_name_) +
175 auto size = dh_p_->get_local_to_global_map().size();
176 save_local_system_.resize(
size);
177 bc_fluxes_reconstruted.resize(
size);
178 loc_system_.resize(
size);
179 postprocess_solution_.resize(
size);
185 std::fill(save_local_system_.begin(), save_local_system_.end(),
false);
186 std::fill(bc_fluxes_reconstruted.begin(), bc_fluxes_reconstruted.end(),
false);
227 MessageOut() <<
"Duplicate key 'time', time in flow equation is already initialized from parent class!";
267 return next_t * (1 - 2*std::numeric_limits<double>::epsilon());
288 gravity_array.copy_to(gvec);
294 auto field_algo=std::make_shared<FieldConstant<3, FieldValue<3>::VectorFixed>>();
295 field_algo->set_value(gvalue);
296 eq_fields_->gravity_field.set(field_algo, 0.0);
314 eq_fields_->set_user_fields_map(user_fields_arr);
321 MessageOut() <<
"Missing the key 'time', obligatory for the transient problems." << endl;
332 std::shared_ptr< FiniteElement<1> > fe1_rt = std::make_shared<FE_RT0_disc<1>>();
333 std::shared_ptr< FiniteElement<2> > fe2_rt = std::make_shared<FE_RT0_disc<2>>();
334 std::shared_ptr< FiniteElement<3> > fe3_rt = std::make_shared<FE_RT0_disc<3>>();
335 std::shared_ptr< FiniteElement<0> > fe0_disc = std::make_shared<FE_P_disc<0>>(0);
336 std::shared_ptr< FiniteElement<1> > fe1_disc = std::make_shared<FE_P_disc<1>>(0);
337 std::shared_ptr< FiniteElement<2> > fe2_disc = std::make_shared<FE_P_disc<2>>(0);
338 std::shared_ptr< FiniteElement<3> > fe3_disc = std::make_shared<FE_P_disc<3>>(0);
339 std::shared_ptr< FiniteElement<0> > fe0_cr = std::make_shared<FE_CR<0>>();
340 std::shared_ptr< FiniteElement<1> > fe1_cr = std::make_shared<FE_CR<1>>();
341 std::shared_ptr< FiniteElement<2> > fe2_cr = std::make_shared<FE_CR<2>>();
342 std::shared_ptr< FiniteElement<3> > fe3_cr = std::make_shared<FE_CR<3>>();
344 FESystem<0> fe0_sys( {fe0_disc, fe0_disc, fe0_cr} );
350 std::shared_ptr<DiscreteSpace> ds = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_sys);
351 eq_data_->dh_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
361 uint rt_component = 0;
363 auto ele_flux_ptr = create_field_fe<3, FieldValue<3>::VectorFixed>(
eq_data_->dh_, &
eq_data_->full_solution, rt_component);
368 uint p_ele_component = 1;
369 auto ele_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_ele_component);
370 eq_fields_->field_ele_pressure.set(ele_pressure_ptr, 0.0);
372 uint p_edge_component = 2;
373 auto edge_pressure_ptr = create_field_fe<3, FieldValue<3>::Scalar>(
eq_data_->dh_, &
eq_data_->full_solution, p_edge_component);
374 eq_fields_->field_edge_pressure.set(edge_pressure_ptr, 0.0);
383 uint p_element_component = 1;
384 eq_data_->dh_p_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_element_component);
388 uint p_edge_component = 2;
389 eq_data_->dh_cr_ = std::make_shared<SubDOFHandlerMultiDim>(
eq_data_->dh_,p_edge_component);
394 std::shared_ptr<DiscreteSpace> ds_cr_disc = std::make_shared<EqualOrderDiscreteSpace>(
mesh_, fe_cr_disc);
395 eq_data_->dh_cr_disc_ = std::make_shared<DOFHandlerMultiDim>(*
mesh_);
396 eq_data_->dh_cr_disc_->distribute_dofs(ds_cr_disc);
407 eq_data_->p_edge_solution_previous_time =
eq_data_->dh_cr_->create_vector();
416 .val<Input::AbstractRecord>(
"linear_solver");
495 eq_data_->p_edge_solution.zero_entries();
497 if (
eq_data_->use_steady_assembly_) {
498 MessageOut() <<
"Flow zero time step - steady case\n";
502 MessageOut() <<
"Flow zero time step - unsteady case\n";
512 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
514 END_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
533 eq_data_->full_solution.local_to_ghost_begin();
534 eq_data_->full_solution.local_to_ghost_end();
542 bool jump_time =
eq_fields_->storativity.is_jump_time();
543 if (! zero_time_term_from_left) {
544 MessageOut() <<
"Flow time step - unsteady case\n";
549 eq_data_->use_steady_assembly_ =
false;
555 WarningOut() <<
"Output of solution discontinuous in time not supported yet.\n";
564 if (! zero_time_term_from_left && ! jump_time && output)
571 if (zero_time_term_from_right) {
572 MessageOut() <<
"Flow time step - steady case\n";
574 eq_data_->use_steady_assembly_ =
true;
579 }
else if (! zero_time_term_from_left && jump_time) {
580 WarningOut() <<
"Discontinuous time term not supported yet.\n";
591 return (
eq_fields_->storativity.input_list_size() == 0);
604 MessageOut().fmt(
"[nonlinear solver] norm of initial residual: {}\n", residual_norm);
607 int is_linear_common;
612 this->
max_n_it_ = nl_solver_rec.
val<
unsigned int>(
"max_it");
613 this->
min_n_it_ = nl_solver_rec.
val<
unsigned int>(
"min_it");
614 if (this->min_n_it_ > this->max_n_it_) this->min_n_it_ = this->
max_n_it_;
616 if (! is_linear_common) {
622 while (
eq_data_->nonlinear_iteration_ < this->min_n_it_ ||
623 (residual_norm > this->tolerance_ &&
eq_data_->nonlinear_iteration_ < this->max_n_it_ )) {
625 convergence_history.push_back(residual_norm);
629 if (convergence_history.size() >= 5 &&
630 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 2] > 0.9 &&
631 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 5] > 0.8) {
634 WarningOut().fmt(
"Accept solution on stagnation. Its: {} Residual: {}\n",
eq_data_->nonlinear_iteration_, residual_norm);
637 THROW(ExcSolverDiverge() << EI_Reason(
"Stagnation."));
641 if (! is_linear_common){
643 eq_data_->p_edge_solution_previous.local_to_ghost_begin();
644 eq_data_->p_edge_solution_previous.local_to_ghost_end();
648 MessageOut().fmt(
"[schur solver] lin. it: {}, reason: {}, residual: {}\n",
654 if (is_linear_common){
657 MessageOut().fmt(
"[nonlinear solver] lin. it: {}, reason: {}, residual: {}\n",
664 VecAXPBY(
eq_data_->p_edge_solution.petsc_vec(), (1-alpha), alpha,
eq_data_->p_edge_solution_previous.petsc_vec());
671 MessageOut().fmt(
"[nonlinear solver] it: {} lin. it: {}, reason: {}, residual: {}\n",
676 START_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
678 END_TIMER(
"DarcyFlowMH::reconstruct_solution_from_schur");
683 if (
eq_data_->nonlinear_iteration_ < 3) mult = 1.6;
684 if (
eq_data_->nonlinear_iteration_ > 7) mult = 0.7;
694 eq_data_->p_edge_solution_previous_time.copy_from(
eq_data_->p_edge_solution);
695 eq_data_->p_edge_solution_previous_time.local_to_ghost_begin();
696 eq_data_->p_edge_solution_previous_time.local_to_ghost_end();
761 double zeros[100000];
762 for(
int i=0; i<100000; i++) zeros[i] = 0.0;
765 tmp_rows.reserve(200);
768 dofs.reserve(
eq_data_->dh_cr_->max_elem_dofs());
769 dofs_ngh.reserve(
eq_data_->dh_cr_->max_elem_dofs());
775 const uint ndofs = dh_cell.n_dofs();
776 dofs.resize(dh_cell.n_dofs());
777 dh_cell.get_dof_indices(dofs);
779 int* dofs_ptr = dofs.
data();
786 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
794 const uint ndofs_ngh = dh_neighb_cell.
n_dofs();
795 dofs_ngh.resize(ndofs_ngh);
799 tmp_rows.push_back(dofs_ngh[neighb_side.side().side_idx()]);
809 for(
auto &isec : isec_list ) {
813 const uint ndofs_slave = dh_cell_slave.
n_dofs();
814 dofs_ngh.resize(ndofs_slave);
818 for(
unsigned int i_side=0; i_side < dh_cell_slave.
elm()->n_sides(); i_side++) {
819 tmp_rows.push_back( dofs_ngh[i_side] );
959 eq_data_->lin_sys_schur = std::make_shared<LinSys_PETSC>( &(*
eq_data_->dh_cr_->distr()) );
1032 eq_data_->full_solution.zero_entries();
1033 eq_data_->p_edge_solution.zero_entries();
1037 THROW( ExcUnknownSolver() );
1072 START_TIMER(
"DarcyFlowMH::assembly_linear_system");
1075 eq_data_->p_edge_solution.local_to_ghost_begin();
1076 eq_data_->p_edge_solution.local_to_ghost_end();
1098 START_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
1100 END_TIMER(
"DarcyLMH::assembly_steady_mh_matrix");
1113 std::string output_file;
1116 double d_max = std::numeric_limits<double>::max();
1117 double h1 = d_max, h2 = d_max, h3 = d_max;
1118 double he2 = d_max, he3 = d_max;
1121 case 1: h1 = std::min(h1,ele.measure());
break;
1122 case 2: h2 = std::min(h2,ele.measure());
break;
1123 case 3: h3 = std::min(h3,ele.measure());
break;
1126 for (
unsigned int j=0; j<ele->n_sides(); j++) {
1128 case 2: he2 = std::min(he2, ele.side(j)->measure());
break;
1129 case 3: he3 = std::min(he3, ele.side(j)->measure());
break;
1133 if(h1 == d_max) h1 = 0;
1134 if(h2 == d_max) h2 = 0;
1135 if(h3 == d_max) h3 = 0;
1136 if(he2 == d_max) he2 = 0;
1137 if(he3 == d_max) he3 = 0;
1140 file = fopen(output_file.c_str(),
"a");
1142 fprintf(file,
"nB = %d;\n",
eq_data_->dh_->mesh()->get_el_ds()->size());
1144 fprintf(file,
"h1 = %e;\nh2 = %e;\nh3 = %e;\n", h1, h2, h3);
1145 fprintf(file,
"he2 = %e;\nhe3 = %e;\n", he2, he3);
1151 PetscViewerASCIIOpen(PETSC_COMM_WORLD, output_file.c_str(), &viewer);
1152 PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);
1153 MatView( *
const_cast<Mat*
>(
lin_sys_schur().get_matrix()), viewer);
1154 VecView( *
const_cast<Vec*
>(
lin_sys_schur().get_rhs()), viewer);
1155 VecView( *
const_cast<Vec*
>(&(
lin_sys_schur().get_solution())), viewer);
1156 VecView( *
const_cast<Vec*
>(&(
eq_data_->full_solution.petsc_vec())), viewer);
1353 if(
time_ !=
nullptr)
1372 ASSERT_LT(component, 3).error(
"Invalid component!");
1373 unsigned int i, n_dofs, min, max;
1377 n_dofs = dh_cell.get_dof_indices(dof_indices);
1379 for (i=min; i<max; ++i) dof_vec.push_back(dof_indices[i]);