28 #include "petscviewer.h" 29 #include "petscerror.h" 79 .
add_value(
MortarP1,
"P1",
"Mortar space: P1 on intersections, using non-conforming pressures.")
87 "Homogeneous Neumann boundary condition. Zero flux")
89 "Dirichlet boundary condition. " 90 "Specify the pressure head through the 'bc_pressure' field " 91 "or the piezometric head through the 'bc_piezo_head' field.")
92 .
add_value(total_flux,
"total_flux",
"Flux boundary condition (combines Neumann and Robin type). " 93 "Water inflow equal to (($q^N + \\sigma (h^R - h)$)). " 94 "Specify the water inflow by the 'bc_flux' field, the transition coefficient by 'bc_robin_sigma' " 95 "and the reference pressure head or pieozmetric head through 'bc_pressure' or 'bc_piezo_head' respectively.")
97 "Seepage face boundary condition. Pressure and inflow bounded from above. Boundary with potential seepage flow " 98 "is described by the pair of inequalities:" 99 "(($h \\le h_d^D$)) and (($ q \\le q_d^N$)), where the equality holds in at least one of them. Caution! Setting $q_d^N$ strictly negative" 100 "may lead to an ill posed problem since a positive outflow is enforced." 101 "Parameters (($h_d^D$)) and (($q_d^N$)) are given by fields ``bc_pressure`` (or ``bc_piezo_head``) and ``bc_flux`` respectively." 104 "River boundary condition. For the water level above the bedrock, (($H > H^S$)), the Robin boundary condition is used with the inflow given by: " 105 "(( $q^N + \\sigma(H^D - H)$)). For the water level under the bedrock, constant infiltration is used " 106 "(( $q^N + \\sigma(H^D - H^S)$)). Parameters: ``bc_pressure``, ``bc_switch_pressure``," 107 " ``bc_sigma, ``bc_flux``." 118 "Boundary piezometric head for BC types: dirichlet, robin, and river." )
120 "Boundary switch piezometric head for BC types: seepage, river." )
122 "Initial condition for the pressure given as the piezometric head." )
127 "Linear solver for MH problem.")
129 "Residual tolerance.")
131 "Maximal number of iterations (linear solves) of the non-linear solver.")
133 "If a stagnation of the nonlinear solver is detected the solver stops. " 134 "A divergence is reported by default forcing the end of the simulation. Setting this flag to 'true', the solver" 135 "ends with convergence success on stagnation, but report warning about it.")
138 return it::Record(
"SteadyDarcy_MH",
"Mixed-Hybrid solver for STEADY saturated Darcy flow.")
141 "Input data for Darcy flow model.")
143 "Non-linear solver for MH problem.")
146 "Parameters of output form MH module.")
148 "Settings for computing mass balance.")
150 "Time governor setting for the unsteady Darcy flow model.")
152 "Number of Schur complements to perform when solving MH system.")
154 "Method for coupling Darcy flow between dimensions." )
160 Input::register_class< DarcyFlowMH_Steady, Mesh &, const Input::Record >(
"SteadyDarcy_MH") +
167 ADD_FIELD(anisotropy,
"Anisotropy of the conductivity tensor.",
"1.0" );
170 ADD_FIELD(cross_section,
"Complement dimension parameter (cross section for 1D, thickness for 2D).",
"1.0" );
171 cross_section.units(
UnitSI().m(3).md() );
173 ADD_FIELD(conductivity,
"Isotropic conductivity scalar.",
"1.0" );
174 conductivity.units(
UnitSI().m().s(-1) );
176 ADD_FIELD(sigma,
"Transition coefficient between dimensions.",
"1.0");
179 ADD_FIELD(water_source_density,
"Water source density.",
"0.0");
180 water_source_density.units(
UnitSI().s(-1) );
182 ADD_FIELD(bc_type,
"Boundary condition type, possible values:",
"\"none\"" );
184 bc_type.input_selection( &get_bc_type_selection() );
187 ADD_FIELD(bc_pressure,
"Prescribed pressure value on the boundary. Used for all values of 'bc_type' save the bc_type='none'." 188 "See documentation of 'bc_type' for exact meaning of 'bc_pressure' in individual boundary condition types.",
"0.0");
189 bc_pressure.disable_where(bc_type, {
none} );
190 bc_pressure.units(
UnitSI().m() );
192 ADD_FIELD(bc_flux,
"Incoming water boundary flux. Used for bc_types : 'none', 'total_flux', 'seepage', 'river'.",
"0.0");
193 bc_flux.disable_where(bc_type, {
none, dirichlet} );
194 bc_flux.units(
UnitSI().m(4).s(-1).md() );
196 ADD_FIELD(bc_robin_sigma,
"Conductivity coefficient in the 'total_flux' or the 'river' boundary condition type.",
"0.0");
197 bc_robin_sigma.disable_where(bc_type, {
none, dirichlet, seepage} );
198 bc_robin_sigma.units(
UnitSI().m(3).s(-1).md() );
201 "Critical switch pressure for 'seepage' and 'river' boundary conditions.",
"0.0");
202 bc_switch_pressure.disable_where(bc_type, {
none, dirichlet, total_flux} );
203 bc_switch_pressure.units(
UnitSI().m() );
206 ADD_FIELD(init_pressure,
"Initial condition as pressure",
"0.0" );
207 init_pressure.units(
UnitSI().m() );
209 ADD_FIELD(storativity,
"Storativity.",
"0.0" );
210 storativity.units(
UnitSI().m(-1) );
219 template<
unsigned int dim>
222 fe_values_(map_, quad_, fe_rt_,
228 velocity_interpolation_quad_(0),
235 template<
unsigned int dim>
269 if ( in_rec.
opt_val(
"time", time_record) )
324 bool zero_time_term_from_right
330 .val<Input::AbstractRecord>(
"linear_solver");
336 if (it->val<
bool>(
"balance_on"))
351 if (zero_time_term_from_right) {
376 bool zero_time_term_from_left
379 if (! zero_time_term_from_left) {
387 xprintf(
Warn,
"Output of solution discontinuous in time not supported yet.\n");
396 if (! zero_time_term_from_left && ! jump_time)
output_data();
401 bool zero_time_term_from_right
403 if (zero_time_term_from_right) {
408 }
else if (! zero_time_term_from_left && jump_time) {
409 xprintf(
Warn,
"Discontinuous time term not supported yet.\n");
429 int is_linear_common;
434 this->
max_n_it_ = nl_solver_rec.
val<
unsigned int>(
"max_it");
436 if (! is_linear_common) {
443 while (residual_norm > this->tolerance_ && nonlinear_iteration_ < this->max_n_it_) {
445 convergence_history.push_back(residual_norm);
446 if (convergence_history.size() >= 5 &&
447 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 2] > 0.9 &&
448 convergence_history[ convergence_history.size() - 1]/convergence_history[ convergence_history.size() - 5] > 0.8) {
454 THROW(ExcSolverDiverge() << EI_Reason(
"Stagnation."));
464 if (is_linear_common)
break;
550 vec_size = this->
size;
551 OLD_ASSERT(vec != NULL,
"Requested solution is not allocated!\n");
557 OLD_ASSERT(vec != NULL,
"Requested solution is not allocated!\n");
561 template<
unsigned int dim>
565 fe_values_.reinit(ele);
566 const unsigned int ndofs = fe_values_.get_fe()->n_dofs(), qsize = fe_values_.get_quadrature()->size();
567 local_matrix.zeros(ndofs, ndofs);
570 / ad_.data->conductivity.value( ele->centre(), ele->element_accessor() )
571 / ad_.data->cross_section.value( ele->centre(), ele->element_accessor() );
573 for (
unsigned int k=0; k<qsize; k++)
575 for (
unsigned int i=0; i<ndofs; i++)
577 for (
unsigned int j=0; j<ndofs; j++)
578 local_matrix[i*ndofs+j] +=
580 * arma::dot(fe_values_.shape_vector(i,k),
581 (ad_.data->anisotropy.value(ele->centre(), ele->element_accessor() )).i()
582 * fe_values_.shape_vector(j,k)
589 template<
unsigned int dim>
596 fe_side_values_.reinit(ele_higher, ngh->
side()->
el_idx());
597 nv = fe_side_values_.normal_vector(0);
599 double value = ad_.data->sigma.value( ele->centre(), ele->element_accessor()) *
600 2*ad_.data->conductivity.value( ele->centre(), ele->element_accessor()) *
601 arma::dot(ad_.data->anisotropy.value( ele->centre(), ele->element_accessor())*nv, nv) *
602 ad_.data->cross_section.value( ngh->
side()->
centre(), ele_higher->element_accessor() ) *
603 ad_.data->cross_section.value( ngh->
side()->
centre(), ele_higher->element_accessor() ) /
604 ad_.data->cross_section.value( ele->centre(), ele->element_accessor() ) *
607 local_vb[0] = -value; local_vb[1] = value;
608 local_vb[2] = value; local_vb[3] = -value;
613 template<
unsigned int dim>
618 flux_in_center.zeros();
620 velocity_interpolation_fv_.reinit(ele);
621 for (
unsigned int li = 0; li < ele->n_sides(); li++) {
622 flux_in_center += ad_.mh_dh->side_flux( *(ele->side( li ) ) )
623 * velocity_interpolation_fv_.shape_vector(li,0);
626 flux_in_center /= ad_.data->cross_section.value(ele->centre(), ele->element_accessor() );
627 return flux_in_center;
640 START_TIMER(
"DarcyFlowMH_Steady::assembly_steady_mh_matrix");
650 int el_row, side_row, edge_row, loc_b = 0;
652 int side_rows[4], edge_rows[4];
657 for(
int i=0; i<1000; i++) zeros[i]=0.0;
659 double minus_ones[4] = { -1.0, -1.0, -1.0, -1.0 };
660 double loc_side_rhs[4];
665 for (
unsigned int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++) {
666 arma::mat local_matrix;
669 unsigned int nsides = ele->n_sides();
672 assembly_[ele->dim()-1]->assembly_local_matrix(local_matrix, ele);
676 for (
unsigned int i = 0; i < nsides; i++) {
683 unsigned int idx_edge= ele->side(i)->edge_idx();
685 edge_row = edge_rows[i] =
row_4_edge[idx_edge];
686 bcd=ele->side(i)->cond();
689 loc_side_rhs[i] = (ele->centre()[ 2 ] - ele->side(i)->centre()[ 2 ]);
703 loc_side_rhs[i] -= bc_pressure;
722 double side_flux=bc_flux * bcd->
element()->
measure() * cross_section;
725 if (switch_dirichlet) {
730 unsigned int loc_side_row = side_row -
rows_ds->begin();
733 if ( solution_flux < side_flux) {
735 solution_flux = side_flux;
750 unsigned int loc_edge_row = edge_row -
rows_ds->begin();
753 if ( solution_head > bc_pressure) {
755 solution_head = bc_pressure;
765 loc_side_rhs[i] -= bc_pressure;
784 unsigned int loc_edge_row = edge_row -
rows_ds->begin();
797 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
823 double val_side = local_matrix(i,i);
824 double val_edge = -1./local_matrix(i,i);
826 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( side_row, val_side );
827 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( edge_row, val_edge );
835 ls->
mat_set_values(nsides, side_rows, nsides, side_rows, local_matrix.memptr());
847 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( el_row, val_ele );
852 for (
unsigned int i = 0; i < ele->n_neighs_vb; i++) {
855 ngh= ele->neigh_vb[i];
865 int ind = tmp_rows[1];
867 double new_val = local_vb[0];
868 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( ind, new_val );
879 tmp_rows[2+i] = tmp_rows[1];
888 OLD_ASSERT(ele->n_neighs_vb*ele->n_neighs_vb<1000,
"Too many values in E block.");
890 ele->n_neighs_vb, tmp_rows+2, zeros);
921 for (
unsigned int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++) {
927 double source = ele->measure() *
942 vector<int> &dofs,
unsigned int &ele_type,
double &delta, arma::vec &dirichlet) {
946 if (i_ele == (
int)(ml_it_->size()) ) {
952 const Intersection &isect=intersections_[ (*ml_it_)[i_ele] ];
958 dirichlet.resize(ele->
n_sides());
961 for(
unsigned int i_side=0; i_side < ele->
n_sides(); i_side++ ) {
962 dofs[i_side]=darcy_.row_4_edge[ele->
side(i_side)->
edge_idx()];
970 dofs[i_side] = -dofs[i_side];
971 double bc_pressure = darcy_.data_.bc_pressure.value(b_ele.
centre(), b_ele);
972 dirichlet[i_side] = bc_pressure;
983 double delta_i, delta_j;
985 arma::vec dirichlet_i, dirichlet_j;
986 unsigned int ele_type_i, ele_type_j;
991 for(ml_it_ = master_list_.begin(); ml_it_ != master_list_.end(); ++ml_it_) {
993 if (ml_it_->size() == 0)
continue;
1009 master_ = intersections_[ml_it_->front()].master_iter();
1010 delta_0 = master_->measure();
1012 double master_sigma=darcy_.data_.sigma.value( master_->centre(), master_->element_accessor());
1015 double check_delta_sum=0;
1016 for(i = 0; i <= ml_it_->size(); ++i) {
1017 pressure_diff(i, dofs_i, ele_type_i, delta_i, dirichlet_i);
1018 check_delta_sum+=delta_i;
1020 for (j = 0; j <= ml_it_->size(); ++j) {
1021 pressure_diff(j, dofs_j, ele_type_j, delta_j, dirichlet_j);
1023 double scale = -master_sigma * delta_i * delta_j / delta_0;
1024 product = scale * tensor_average[ele_type_i][ele_type_j];
1026 arma::vec rhs(dofs_i.size());
1028 ls.
set_values( dofs_i, dofs_j, product, rhs, dirichlet_i, dirichlet_j);
1029 auto dofs_i_cp=dofs_i;
1030 auto dofs_j_cp=dofs_j;
1031 ls.
set_values( dofs_i_cp, dofs_j_cp, product, rhs, dirichlet_i, dirichlet_j);
1034 OLD_ASSERT(check_delta_sum < 1E-5*delta_0, "sum err %f > 0\n
", check_delta_sum/delta_0); 1035 } // loop over master elements 1040 void P1_CouplingAssembler::add_sides(const Element * ele, unsigned int shift, vector<int> &dofs, vector<double> &dirichlet) 1043 for(unsigned int i_side=0; i_side < ele->n_sides(); i_side++ ) { 1044 dofs[shift+i_side] = darcy_.row_4_edge[ele->side(i_side)->edge_idx()]; 1045 Boundary * bcd = ele->side(i_side)->cond(); 1048 ElementAccessor<3> b_ele = bcd->element_accessor(); 1049 auto type = (DarcyFlowMH_Steady::EqData::BC_Type)darcy_.data_.bc_type.value(b_ele.centre(), b_ele); 1050 //DBGMSG("bcd
id: %d sidx: %d type: %d\n
", ele->id(), i_side, type); 1051 if (type == DarcyFlowMH_Steady::EqData::dirichlet) { 1052 //DBGMSG("Dirichlet: %d\n
", ele->index()); 1053 dofs[shift + i_side] = -dofs[shift + i_side]; 1054 double bc_pressure = darcy_.data_.bc_pressure.value(b_ele.centre(), b_ele); 1055 dirichlet[shift + i_side] = bc_pressure; 1068 void P1_CouplingAssembler::assembly(LinSys &ls) {
1070 for (const Intersection &intersec : intersections_) {
1071 const Element * master = intersec.master_iter();
1072 const Element * slave = intersec.slave_iter();
1074 add_sides(slave, 0, dofs, dirichlet);
1075 add_sides(master, 3, dofs, dirichlet);
1077 double master_sigma=darcy_.data_.sigma.value( master->centre(), master->element_accessor());
1080 * Local coordinates on 1D
1086 * t0 = 0.0 on side 0 node 0
1087 * t0 = 1.0 on side 1 node 1
1089 * Local coordinates on 2D
1096 * t0=0.5, t1=0.0 on side 0 nodes (0,1)
1097 * t0=0.5, t1=0.5 on side 1 nodes (1,2)
1098 * t0=0.0, t1=0.5 on side 2 nodes (2,0)
1103 arma::vec point_Y(1);
1105 arma::vec point_2D_Y(intersec.map_to_slave(point_Y)); // local coordinates of Y on slave (1, t0, t1)
1106 arma::vec point_1D_Y(intersec.map_to_master(point_Y)); // local coordinates of Y on master (1, t0)
1108 arma::vec point_X(1);
1110 arma::vec point_2D_X(intersec.map_to_slave(point_X)); // local coordinates of X on slave (1, t0, t1)
1111 arma::vec point_1D_X(intersec.map_to_master(point_X)); // local coordinates of X on master (1, t0)
1113 arma::mat base_2D(3, 3);
1114 // basis functions are numbered as sides
1116 // Use RT finite element to evaluate following matrices.
1118 // Ravirat - Thomas base functions evaluated in points (0,0), (1,0), (0,1)
1119 // 2D RT_i(t0, t1) = a0 + a1*t0 + a2*t1
1121 base_2D << 1.0 << 0.0 << -2.0 << arma::endr // RT for side 0
1122 << 1.0 << -2.0 << 0.0 << arma::endr // RT for side 1
1123 << -1.0 << 2.0 << 2.0 << arma::endr;// RT for side 2
1126 arma::mat base_1D(2, 2);
1127 // Ravirat - Thomas base functions evaluated in points (0,0), (1,0), (0,1)
1128 // 1D RT_i(t0) = a0 + a1 * t0
1130 base_1D << 1.0 << -1.0 << arma::endr // RT for side 0,
1131 << 0.0 << 1.0 << arma::endr; // RT for side 1,
1135 // Consider both 2D and 1D value are defined for the test function
1136 // related to the each of 5 DOFs involved in the intersection.
1137 // One of these values is always zero.
1138 // Compute difference of the 2D and 1D value for every DOF.
1139 // Compute value of this difference in both endpoints X,Y of the intersection.
1141 arma::vec difference_in_Y(5);
1142 arma::vec difference_in_X(5);
1143 // slave sides 0,1,2
1144 difference_in_Y.subvec(0, 2) = -base_2D * point_2D_Y;
1145 difference_in_X.subvec(0, 2) = -base_2D * point_2D_X;
1147 difference_in_Y.subvec(3, 4) = base_1D * point_1D_Y;
1148 difference_in_X.subvec(3, 4) = base_1D * point_1D_X;
1150 // applying the Simpson's rule
1151 // to the product of two linear functions f, g we get
1152 // (b-a)/6 * ( 3*f(a)*g(a) + 3*f(b)*g(b) + 2*f(a)*g(b) + 2*f(b)*g(a) )
1154 for (int i = 0; i < 5; ++i) {
1155 for (int j = 0; j < 5; ++j) {
1156 A(i, j) = -master_sigma * intersec.intersection_true_size() *
1157 ( difference_in_Y[i] * difference_in_Y[j]
1158 + difference_in_Y[i] * difference_in_X[j]/2
1159 + difference_in_X[i] * difference_in_Y[j]/2
1160 + difference_in_X[i] * difference_in_X[j]
1166 ls.set_values( dofs_cp, dofs_cp, A, rhs, dirichlet, dirichlet);
1173 /*******************************************************************************
1174 * COMPOSE WATER MH MATRIX WITHOUT SCHUR COMPLEMENT
1175 ******************************************************************************/
1177 void DarcyFlowMH_Steady::create_linear_system(Input::AbstractRecord in_rec) {
1179 START_TIMER("preallocation
"); 1181 if (schur0 == NULL) { // create Linear System for MH matrix 1183 if (in_rec.type() == LinSys_BDDC::get_input_type()) { 1184 #ifdef FLOW123D_HAVE_BDDCML 1185 xprintf(Warn, "For BDDC no Schur complements are used.
"); 1186 prepare_parallel_bddc(); 1188 LinSys_BDDC *ls = new LinSys_BDDC(global_row_4_sub_row->size(), &(*rows_ds), 1189 3, // 3 == la::BddcmlWrapper::SPD_VIA_SYMMETRICGENERAL 1190 1, // 1 == number of subdomains per process 1191 true); // swap signs of matrix and rhs to make the matrix SPD 1192 ls->set_from_input(in_rec); 1193 ls->set_solution( NULL ); 1194 // possible initialization particular to BDDC 1196 set_mesh_data_for_bddc(ls); 1200 xprintf(Err, "Flow123d was not build with BDDCML support.\n
"); 1201 #endif // FLOW123D_HAVE_BDDCML 1203 else if (in_rec.type() == LinSys_PETSC::get_input_type()) { 1204 // use PETSC for serial case even when user wants BDDC 1205 if (n_schur_compls > 2) { 1206 xprintf(Warn, "Invalid number of Schur Complements. Using 2.
"); 1210 LinSys_PETSC *schur1, *schur2; 1212 if (n_schur_compls == 0) { 1213 LinSys_PETSC *ls = new LinSys_PETSC( &(*rows_ds) ); 1215 // temporary solution; we have to set precision also for sequantial case of BDDC 1216 // final solution should be probably call of direct solver for oneproc case 1217 if (in_rec.type() != LinSys_BDDC::get_input_type()) ls->set_from_input(in_rec); 1219 ls->LinSys::set_from_input(in_rec); // get only common options 1222 ls->set_solution( NULL ); 1226 ISCreateStride(PETSC_COMM_WORLD, side_ds->lsize(), rows_ds->begin(), 1, &is); 1227 //OLD_ASSERT(err == 0,"Error in ISCreateStride.
"); 1229 SchurComplement *ls = new SchurComplement(is, &(*rows_ds)); 1230 ls->set_from_input(in_rec); 1231 ls->set_solution( NULL ); 1234 Distribution *ds = ls->make_complement_distribution(); 1235 if (n_schur_compls==1) { 1236 schur1 = new LinSys_PETSC(ds); 1237 schur1->set_positive_definite(); 1240 ISCreateStride(PETSC_COMM_WORLD, el_ds->lsize(), ls->get_distribution()->begin(), 1, &is); 1241 //OLD_ASSERT(err == 0,"Error in ISCreateStride.
"); 1242 SchurComplement *ls1 = new SchurComplement(is, ds); // is is deallocated by SchurComplement 1243 ls1->set_negative_definite(); 1246 schur2 = new LinSys_PETSC( ls1->make_complement_distribution() ); 1247 schur2->set_positive_definite(); 1248 schur2->set_from_input(in_rec); 1249 ls1->set_complement( schur2 ); 1252 ls->set_complement( schur1 ); 1256 START_TIMER("PETSC PREALLOCATION
"); 1257 schur0->set_symmetric(); 1258 schur0->start_allocation(); 1259 assembly_steady_mh_matrix(); // preallocation 1260 VecZeroEntries(schur0->get_solution()); 1261 END_TIMER("PETSC PREALLOCATION
"); 1264 xprintf(Err, "Unknown solver type. Internal error.\n
"); 1268 END_TIMER("preallocation
"); 1269 make_serial_scatter(); 1275 void DarcyFlowMH_Steady::assembly_linear_system() { 1278 bool is_steady = data_.storativity.field_result(mesh_->region_db().get_region_set("BULK
")) == result_zeros; 1279 //DBGMSG("Assembly linear system\n
"); 1280 if (data_.changed()) { 1281 //DBGMSG(" Data changed\n
"); 1282 // currently we have no optimization for cases when just time term data or RHS data are changed 1283 START_TIMER("full assembly
"); 1284 if (typeid(*schur0) != typeid(LinSys_BDDC)) { 1285 schur0->start_add_assembly(); // finish allocation and create matrix 1287 schur0->mat_zero_entries(); 1288 schur0->rhs_zero_entries(); 1289 assembly_steady_mh_matrix(); // fill matrix 1290 schur0->finish_assembly(); 1291 schur0->set_matrix_changed(); 1292 //MatView( *const_cast<Mat*>(schur0->get_matrix()), PETSC_VIEWER_STDOUT_WORLD ); 1293 //VecView( *const_cast<Vec*>(schur0->get_rhs()), PETSC_VIEWER_STDOUT_WORLD); 1297 START_TIMER("fix
time term
"); 1298 //DBGMSG(" setup
time term\n
"); 1299 // assembly time term and rhs 1303 else if (balance_ != nullptr) 1305 balance_->start_mass_assembly(water_balance_idx_); 1306 balance_->finish_mass_assembly(water_balance_idx_); 1308 END_TIMER("full assembly
"); 1310 START_TIMER("modify system
"); 1314 //xprintf(PrgErr, "Planned computation
time for steady solver, but
data are not changed.\n
"); 1316 END_TIMER("modiffy system
"); 1323 void DarcyFlowMH_Steady::set_mesh_data_for_bddc(LinSys_BDDC * bddc_ls) { 1325 // prepare mesh for BDDCML 1326 // initialize arrays 1327 // auxiliary map for creating coordinates of local dofs and global-to-local numbering 1328 std::map<int,arma::vec3> localDofMap; 1329 // connectivity for the subdomain, i.e. global dof numbers on element, stored element-by-element 1330 // Indices of Nodes on Elements 1331 std::vector<int> inet; 1332 // number of degrees of freedom on elements - determines elementwise chunks of INET array 1333 // Number of Nodes on Elements 1334 std::vector<int> nnet; 1335 // Indices of Subdomain Elements in Global Numbering - for local elements, their global indices 1336 std::vector<int> isegn; 1338 // This array is currently not used in BDDCML, it was used as an interface scaling alternative to scaling 1339 // by diagonal. It corresponds to the rho-scaling. 1340 std::vector<double> element_permeability; 1342 // maximal and minimal dimension of elements 1345 for ( unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++ ) { 1346 // for each element, create local numbering of dofs as fluxes (sides), pressure (element centre), Lagrange multipliers (edges), compatible connections 1347 ElementFullIter el = mesh_->element(el_4_loc[i_loc]); 1348 int e_idx = el.index(); 1350 int elDim = el->dim(); 1351 elDimMax = std::max( elDimMax, elDim ); 1352 elDimMin = std::min( elDimMin, elDim ); 1354 isegn.push_back( e_idx ); 1357 FOR_ELEMENT_SIDES(el,si) { 1358 // insert local side dof 1359 int side_row = side_row_4_id[ mh_dh.side_dof( el->side(si) ) ]; 1360 arma::vec3 coord = el->side(si)->centre(); 1362 localDofMap.insert( std::make_pair( side_row, coord ) ); 1363 inet.push_back( side_row ); 1367 // insert local pressure dof 1368 int el_row = row_4_el[ el_4_loc[i_loc] ]; 1369 arma::vec3 coord = el->centre(); 1370 localDofMap.insert( std::make_pair( el_row, coord ) ); 1371 inet.push_back( el_row ); 1374 FOR_ELEMENT_SIDES(el,si) { 1375 // insert local edge dof 1376 int edge_row = row_4_edge[ el->side(si)->edge_idx() ]; 1377 arma::vec3 coord = el->side(si)->centre(); 1379 localDofMap.insert( std::make_pair( edge_row, coord ) ); 1380 inet.push_back( edge_row ); 1384 // insert dofs related to compatible connections 1385 for ( unsigned int i_neigh = 0; i_neigh < el->n_neighs_vb; i_neigh++) { 1386 int edge_row = row_4_edge[ el->neigh_vb[i_neigh]->edge_idx() ]; 1387 arma::vec3 coord = el->neigh_vb[i_neigh]->edge()->side(0)->centre(); 1389 localDofMap.insert( std::make_pair( edge_row, coord ) ); 1390 inet.push_back( edge_row ); 1394 nnet.push_back( nne ); 1396 // version for rho scaling 1397 // trace computation 1398 arma::vec3 centre = el->centre(); 1399 double conduct = data_.conductivity.value( centre , el->element_accessor() ); 1400 arma::mat33 aniso = data_.anisotropy.value( centre, el->element_accessor() ); 1402 // compute mean on the diagonal 1404 for ( int i = 0; i < 3; i++) { 1405 coef = coef + aniso.at(i,i); 1407 // Maybe divide by cs 1408 coef = conduct*coef / 3; 1410 OLD_ASSERT( coef > 0., 1411 "Zero coefficient of hydrodynamic resistance %f . \n
", coef ); 1412 element_permeability.push_back( 1. / coef ); 1414 //convert set of dofs to vectors 1415 // number of nodes (= dofs) on the subdomain 1416 int numNodeSub = localDofMap.size(); 1417 OLD_ASSERT_EQUAL( (unsigned int)numNodeSub, global_row_4_sub_row->size() ); 1418 // Indices of Subdomain Nodes in Global Numbering - for local nodes, their global indices 1419 std::vector<int> isngn( numNodeSub ); 1420 // pseudo-coordinates of local nodes (i.e. dofs) 1421 // they need not be exact, they are used just for some geometrical considerations in BDDCML, 1422 // such as selection of corners maximizing area of a triangle, bounding boxes fro subdomains to 1423 // find candidate neighbours etc. 1424 std::vector<double> xyz( numNodeSub * 3 ) ; 1426 std::map<int,arma::vec3>::iterator itB = localDofMap.begin(); 1427 for ( ; itB != localDofMap.end(); ++itB ) { 1428 isngn[ind] = itB -> first; 1430 arma::vec3 coord = itB -> second; 1431 for ( int j = 0; j < 3; j++ ) { 1432 xyz[ j*numNodeSub + ind ] = coord[j]; 1437 localDofMap.clear(); 1439 // Number of Nodal Degrees of Freedom 1440 // nndf is trivially one - dofs coincide with nodes 1441 std::vector<int> nndf( numNodeSub, 1 ); 1443 // prepare auxiliary map for renumbering nodes 1444 typedef std::map<int,int> Global2LocalMap_; //! type for storage of global to local map 1445 Global2LocalMap_ global2LocalNodeMap; 1446 for ( unsigned ind = 0; ind < isngn.size(); ++ind ) { 1447 global2LocalNodeMap.insert( std::make_pair( static_cast<unsigned>( isngn[ind] ), ind ) ); 1450 // renumber nodes in the inet array to locals 1452 for ( unsigned int iEle = 0; iEle < isegn.size(); iEle++ ) { 1453 int nne = nnet[ iEle ]; 1454 for ( int ien = 0; ien < nne; ien++ ) { 1456 int indGlob = inet[indInet]; 1457 // map it to local node 1458 Global2LocalMap_::iterator pos = global2LocalNodeMap.find( indGlob ); 1459 OLD_ASSERT( pos != global2LocalNodeMap.end(), 1460 "Cannot remap node index %d to local indices. \n
", indGlob ); 1461 int indLoc = static_cast<int> ( pos -> second ); 1464 inet[ indInet++ ] = indLoc; 1468 int numNodes = size; 1469 int numDofsInt = size; 1470 int spaceDim = 3; // TODO: what is the proper value here? 1471 int meshDim = elDimMax; 1473 bddc_ls -> load_mesh( spaceDim, numNodes, numDofsInt, inet, nnet, nndf, isegn, isngn, isngn, xyz, element_permeability, meshDim ); 1479 //============================================================================= 1480 // DESTROY WATER MH SYSTEM STRUCTURE 1481 //============================================================================= 1482 DarcyFlowMH_Steady::~DarcyFlowMH_Steady() { 1483 if (schur0 != NULL) delete schur0; 1491 xfree(side_id_4_loc); 1492 xfree(side_row_4_id); 1496 if (solution != NULL) { 1497 VecDestroy(&sol_vec); 1501 delete output_object; 1503 VecScatterDestroy(&par_to_all); 1508 // ================================================ 1512 // ======================================================================== 1513 // to finish row_4_id arrays we have to convert individual numberings of 1514 // sides/els/edges to whole numbering of rows. To this end we count shifts 1515 // for sides/els/edges on each proc and then we apply them on row_4_id 1517 // we employ macros to avoid code redundancy 1518 // ======================================================================= 1519 void DarcyFlowMH_Steady::make_row_numberings() { 1521 int np = edge_ds->np(); 1522 int edge_shift[np], el_shift[np], side_shift[np]; 1523 unsigned int rows_starts[np]; 1525 int edge_n_id = mesh_->n_edges(), 1526 el_n_id = mesh_->element.size(), 1527 side_n_id = mesh_->n_sides(); 1529 // compute shifts on every proc 1530 shift = 0; // in this var. we count new starts of arrays chunks 1531 for (i = 0; i < np; i++) { 1532 side_shift[i] = shift - (side_ds->begin(i)); // subtract actual start of the chunk 1533 shift += side_ds->lsize(i); 1534 el_shift[i] = shift - (el_ds->begin(i)); 1535 shift += el_ds->lsize(i); 1536 edge_shift[i] = shift - (edge_ds->begin(i)); 1537 shift += edge_ds->lsize(i); 1538 rows_starts[i] = shift; 1541 for (i = 0; i < side_n_id; i++) { 1542 int &what = side_row_4_id[i]; 1544 what += side_shift[side_ds->get_proc(what)]; 1546 for (i = 0; i < el_n_id; i++) { 1547 int &what = row_4_el[i]; 1549 what += el_shift[el_ds->get_proc(what)]; 1552 for (i = 0; i < edge_n_id; i++) { 1553 int &what = row_4_edge[i]; 1555 what += edge_shift[edge_ds->get_proc(what)]; 1557 // make distribution of rows 1558 for (i = np - 1; i > 0; i--) 1559 rows_starts[i] -= rows_starts[i - 1]; 1561 rows_ds = boost::make_shared<Distribution>(&(rows_starts[0]), PETSC_COMM_WORLD); 1564 void DarcyFlowMH_Steady::make_serial_scatter() { 1565 START_TIMER("prepare scatter
"); 1566 // prepare Scatter form parallel to sequantial in original numbering 1569 int i, *loc_idx; //, si; 1571 // create local solution vector 1572 solution = (double *) xmalloc(size * sizeof(double)); 1573 VecCreateSeqWithArray(PETSC_COMM_SELF,1, size, solution, 1576 // create seq. IS to scatter par solutin to seq. vec. in original order 1577 // use essentialy row_4_id arrays 1578 loc_idx = (int *) xmalloc(size * sizeof(int)); 1580 FOR_ELEMENTS(mesh_, ele) { 1581 FOR_ELEMENT_SIDES(ele,si) { 1582 loc_idx[i++] = side_row_4_id[ mh_dh.side_dof( ele->side(si) ) ]; 1585 FOR_ELEMENTS(mesh_, ele) { 1586 loc_idx[i++] = row_4_el[ele.index()]; 1588 for(unsigned int i_edg=0; i_edg < mesh_->n_edges(); i_edg++) { 1589 loc_idx[i++] = row_4_edge[i_edg]; 1591 OLD_ASSERT( i==size,"Size of array does not match number of fills.\n
"); 1592 //DBGPRINT_INT("loc_idx
",size,loc_idx); 1593 ISCreateGeneral(PETSC_COMM_SELF, size, loc_idx, PETSC_COPY_VALUES, &(is_loc)); 1595 VecScatterCreate(schur0->get_solution(), is_loc, sol_vec, 1596 PETSC_NULL, &par_to_all); 1597 ISDestroy(&(is_loc)); 1599 solution_changed_for_scatter=true; 1601 END_TIMER("prepare scatter
"); 1605 // ==================================================================================== 1606 // - compute optimal edge partitioning 1607 // - compute appropriate partitioning of elements and sides 1608 // - make arrays: *_id_4_loc and *_row_4_id to allow parallel assembly of the MH matrix 1609 // ==================================================================================== 1610 void DarcyFlowMH_Steady::prepare_parallel() { 1614 int *loc_part; // optimal (edge,el) partitioning (local chunk) 1615 int *id_4_old; // map from old idx to ids (edge,el) 1621 //ierr = MPI_Barrier(PETSC_COMM_WORLD); 1624 // row_4_el will be modified so we make a copy of the array from mesh 1625 row_4_el = new int[mesh_->n_elements()]; 1626 std::copy(mesh_->get_row_4_el(), mesh_->get_row_4_el()+mesh_->n_elements(), row_4_el); 1627 el_4_loc = mesh_->get_el_4_loc(); 1628 el_ds = mesh_->get_el_ds(); 1630 //optimal element part; loc. els. id-> new el. numbering 1631 Distribution init_edge_ds(DistributionLocalized(), mesh_->n_edges(), PETSC_COMM_WORLD); 1632 // partitioning of edges, edge belongs to the proc of his first element 1633 // this is not optimal but simple 1634 loc_part = new int[init_edge_ds.lsize()]; 1635 id_4_old = new int[mesh_->n_edges()]; 1638 FOR_EDGES(mesh_, edg ) { 1639 unsigned int i_edg = edg - mesh_->edges.begin(); 1641 e_idx = mesh_->element.index(edg->side(0)->element()); 1642 if (init_edge_ds.is_local(i_edg)) { 1643 // find (new) proc of the first element of the edge 1644 loc_part[loc_i++] = el_ds->get_proc(row_4_el[e_idx]); 1647 id_4_old[i_edg] = i_edg; 1651 Partitioning::id_maps(mesh_->n_edges(), id_4_old, init_edge_ds, loc_part, edge_ds, edge_4_loc, row_4_edge); 1655 //optimal side part; loc. sides; id-> new side numbering 1656 Distribution init_side_ds(DistributionBlock(), mesh_->n_sides(), PETSC_COMM_WORLD); 1657 // partitioning of sides follows elements 1658 loc_part = new int[init_side_ds.lsize()]; 1659 id_4_old = new int[mesh_->n_sides()]; 1663 FOR_SIDES(mesh_, side ) { 1665 if (init_side_ds.is_local(is)) { 1666 // find (new) proc of the element of the side 1667 loc_part[loc_i++] = el_ds->get_proc( 1668 row_4_el[mesh_->element.index(side->element())]); 1671 id_4_old[is++] = mh_dh.side_dof( side ); 1675 Partitioning::id_maps(mesh_->n_sides(), id_4_old, init_side_ds, loc_part, side_ds, 1676 side_id_4_loc, side_row_4_id); 1680 // convert row_4_id arrays from separate numberings to global numbering of rows 1681 make_row_numberings(); 1683 // Initialize bc_switch_dirichlet to size of global boundary. 1684 bc_switch_dirichlet.resize(mesh_->bc_elements.size(), 1); 1687 void DarcyFlowMH_Steady::prepare_parallel_bddc() { 1688 #ifdef FLOW123D_HAVE_BDDCML 1691 int side_row, edge_row; 1693 global_row_4_sub_row = boost::make_shared<LocalToGlobalMap>(rows_ds); 1697 // for each subdomain: 1698 // | velocities (at sides) | pressures (at elements) | L. mult. (at edges) | 1699 for (unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++) { 1700 el = mesh_->element(el_4_loc[i_loc]); 1701 int el_row = row_4_el[el_4_loc[i_loc]]; 1703 global_row_4_sub_row->insert( el_row ); 1705 unsigned int nsides = el->n_sides(); 1706 for (unsigned int i = 0; i < nsides; i++) { 1707 side_row = side_row_4_id[ mh_dh.side_dof( el->side(i) ) ]; 1708 edge_row = row_4_edge[el->side(i)->edge_idx()]; 1710 global_row_4_sub_row->insert( side_row ); 1711 global_row_4_sub_row->insert( edge_row ); 1714 for (unsigned int i_neigh = 0; i_neigh < el->n_neighs_vb; i_neigh++) { 1716 edge_row = row_4_edge[el->neigh_vb[i_neigh]->edge_idx() ]; 1717 global_row_4_sub_row->insert( edge_row ); 1720 global_row_4_sub_row->finalize(); 1721 #endif // FLOW123D_HAVE_BDDCML 1725 void mat_count_off_proc_values(Mat m, Vec v) { 1727 const PetscInt *cols; 1728 Distribution distr(v); 1733 MatGetOwnershipRange(m, &first, &last); 1734 for (int row = first; row < last; row++) { 1735 MatGetRow(m, row, &n, &cols, PETSC_NULL); 1736 bool exists_off = false; 1737 for (int i = 0; i < n; i++) 1738 if (distr.get_proc(cols[i]) != distr.myp()) 1739 n_off++, exists_off = true; 1744 MatRestoreRow(m, row, &n, &cols, PETSC_NULL); 1759 // ======================== 1762 DarcyFlowMH_Steady::DarcyFlowMH_Unsteady(Mesh &mesh_in, const Input::Record in_rec) 1763 : DarcyFlowMH_Steady(mesh_in, in_rec) 1766 time_ = new TimeGovernor(in_rec.val<Input::Record>("time
")); 1767 data_.mark_input_times(this->mark_type()); 1768 data_.set_time(time_->step(), LimitSide::right); 1770 output_object = new DarcyFlowMHOutput(this, in_rec.val<Input::Record>("output
")); 1771 //balance_->units(output_object->get_output_fields().field_ele_pressure.units()*data_.cross_section.units()*data_.storativity.units()); 1773 //time_->fix_dt_until_mark(); 1774 create_linear_system(); 1778 assembly_linear_system(); 1779 read_init_condition(); 1785 void DarcyFlowMH_Steady::read_initial_condition() 1788 VecDuplicate(schur0->get_solution(), &previous_solution); 1789 VecCreateMPI(PETSC_COMM_WORLD,rows_ds->lsize(),PETSC_DETERMINE,&(steady_diagonal)); 1790 VecDuplicate(steady_diagonal,& new_diagonal); 1791 VecZeroEntries(new_diagonal); 1792 VecDuplicate(*( schur0->get_rhs()), &steady_rhs); 1794 // read inital condition 1795 VecZeroEntries(schur0->get_solution()); 1797 double *local_sol = schur0->get_solution_array(); 1799 // cycle over local element rows 1800 ElementFullIter ele = ELEMENT_FULL_ITER(mesh_, NULL); 1802 DBGMSG("Setup with dt: %f\n
",time_->dt()); 1803 for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) { 1804 ele = mesh_->element(el_4_loc[i_loc_el]); 1805 int i_loc_row = i_loc_el + side_ds->lsize(); 1807 // set initial condition 1808 local_sol[i_loc_row] = data_.init_pressure.value(ele->centre(),ele->element_accessor()); 1811 solution_changed_for_scatter=true; 1815 void DarcyFlowMH_Steady::setup_time_term() { 1816 // save diagonal of steady matrix 1817 MatGetDiagonal(*( schur0->get_matrix() ), steady_diagonal); 1819 VecCopy(*( schur0->get_rhs()), steady_rhs); 1822 PetscScalar *local_diagonal; 1823 VecGetArray(new_diagonal,& local_diagonal); 1825 ElementFullIter ele = ELEMENT_FULL_ITER(mesh_, NULL); 1826 DBGMSG("Setup with dt: %f\n
",time_->dt()); 1828 if (balance_ != nullptr) 1829 balance_->start_mass_assembly(water_balance_idx_); 1831 for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) { 1832 ele = mesh_->element(el_4_loc[i_loc_el]); 1833 int i_loc_row = i_loc_el + side_ds->lsize(); 1836 double diagonal_coeff = data_.cross_section.value(ele->centre(), ele->element_accessor()) 1837 * data_.storativity.value(ele->centre(), ele->element_accessor()) 1839 local_diagonal[i_loc_row]= - diagonal_coeff / time_->dt(); 1841 if (balance_ != nullptr) 1842 balance_->add_mass_matrix_values(water_balance_idx_, ele->region().bulk_idx(), {i_loc_row}, {diagonal_coeff}); 1844 VecRestoreArray(new_diagonal,& local_diagonal); 1845 MatDiagonalSet(*( schur0->get_matrix() ), new_diagonal, ADD_VALUES); 1847 solution_changed_for_scatter=true; 1848 schur0->set_matrix_changed(); 1850 if (balance_ != nullptr) 1851 balance_->finish_mass_assembly(water_balance_idx_); 1854 void DarcyFlowMH_Steady::modify_system() { 1855 START_TIMER("modify system
"); 1856 if (time_->is_changed_dt() && time_->step().index()>0) { 1857 double scale_factor=time_->step(-2).length()/time_->step().length(); 1858 if (scale_factor != 1.0) { 1859 // if time step has changed and setup_time_term not called 1860 MatDiagonalSet(*( schur0->get_matrix() ),steady_diagonal, INSERT_VALUES); 1862 VecScale(new_diagonal, time_->last_dt()/time_->dt()); 1863 MatDiagonalSet(*( schur0->get_matrix() ),new_diagonal, ADD_VALUES); 1864 schur0->set_matrix_changed(); 1868 // modify RHS - add previous solution 1869 VecPointwiseMult(*( schur0->get_rhs()), new_diagonal, schur0->get_solution()); 1870 VecAXPY(*( schur0->get_rhs()), 1.0, steady_rhs); 1871 schur0->set_rhs_changed(); 1874 VecSwap(previous_solution, schur0->get_solution()); 1878 //----------------------------------------------------------------------------- 1879 // vim: set cindent:
void set_input_list(Input::Array input_list)
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
static const Input::Type::Record & get_input_type()
Main balance input record type.
BCField< 3, FieldValue< 3 >::Scalar > bc_robin_sigma
#define ADD_FIELD(name,...)
Assembly(AssemblyData ad)
Output class for darcy_flow_mh model.
Field< 3, FieldValue< 3 >::Scalar > water_source_density
static const int registrar
Registrar of class to factory.
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
void make_intersec_elements()
void get_parallel_solution_vector(Vec &vector) override
unsigned int edge_idx() const
Field< 3, FieldValue< 3 >::Scalar > cross_section
bool solution_changed_for_scatter
void set_time(const TimeStep &time, LimitSide limit_side)
Wrappers for linear systems based on MPIAIJ and MATIS format.
static const Input::Type::Selection & get_bc_type_selection()
Return a Selection corresponding to enum BC_Type.
virtual void rhs_set_values(int nrow, int *rows, double *vals)=0
friend class P1_CouplingAssembler
bool is_end() const
Returns true if the actual time is greater than or equal to the end time.
void assembly(LinSys &ls)
void next_time()
Proceed to the next time according to current estimated time step.
FieldResult field_result(RegionSet region_set) const
Indicates special field states.
arma::vec3 centre() const
TimeMark::Type type_output()
void zero_time_step() override
friend class P0_CouplingAssembler
RegionSet get_region_set(const string &set_name) const
#define ELEMENT_FULL_ITER(_mesh_, i)
Class FEValues calculates finite element data on the actual cells such as shape function values...
virtual void read_initial_condition()
boost::shared_ptr< Distribution > rows_ds
bool is_current(const TimeMark::Type &mask) const
virtual double get_solution_precision()=0
const RegionDB & region_db() const
void pressure_diff(int i_ele, vector< int > &dofs, unsigned int &ele_type, double &delta, arma::vec &dirichlet)
const TimeStep & step(int index=-1) const
static const std::string field_descriptor_record_description(const string &record_name)
unsigned int water_balance_idx_
index of water balance within the Balance object.
void solve_nonlinear()
Solve method common to zero_time_step and update solution.
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static TimeMarks & marks()
Basic time management class.
virtual void set_tolerances(double r_tol, double a_tol, unsigned int max_it)=0
static const Input::Type::Record & get_input_type()
void view(const char *name="") const
static const Input::Type::Record & get_input_type()
BCField< 3, FieldValue< 3 >::Scalar > bc_pressure
bool use_steady_assembly_
void assembly_local_vb(double *local_vb, ElementFullIter ele, Neighbour *ngh) override
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
void mat_set_value(int row, int col, double val)
MortarMethod mortar_method_
Transformed quadrature points.
unsigned int n_elements() const
virtual void assembly_source_term()
Source term is implemented differently in LMH version.
double * get_solution_array()
FLOW123D_FORCE_LINK_IN_CHILD(darcy_flow_mh)
const Vec & get_solution()
BCField< 3, FieldValue< 3 >::Enum > bc_type
Definitions of basic Lagrangean finite elements with polynomial shape functions.
void assembly_linear_system()
unsigned int n_sides() const
const Element * slave_iter() const
#define START_TIMER(tag)
Starts a timer with specified tag.
void assembly_local_matrix(arma::mat &local_matrix, ElementFullIter ele) override
MortarMethod
Type of experimental Mortar-like method for non-compatible 1d-2d interaction.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
unsigned int side_dof(const SideIter side) const
arma::vec3 make_element_vector(ElementFullIter ele) override
static Input::Type::Abstract & get_input_type()
unsigned int nonlinear_iteration_
SideIter side(const unsigned int loc_index)
Shape function gradients.
virtual double solution_precision() const
DarcyFlowMH_Steady(Mesh &mesh, const Input::Record in_rec)
CREATE AND FILL GLOBAL MH MATRIX OF THE WATER MODEL.
void create_linear_system(Input::AbstractRecord rec)
void mark_input_times(const TimeGovernor &tg)
std::vector< char > bc_switch_dirichlet
Idicator of dirichlet or neumann type of switch boundary conditions.
Support classes for parallel programing.
#define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm)
std::vector< AssemblyBase * > assembly_
void set_values(int nrow, int *rows, int ncol, int *cols, PetscScalar *mat_vals, PetscScalar *rhs_vals)
Set values in the system matrix and values in the right-hand side vector on corresponding rows...
double intersection_true_size() const
virtual void postprocess()
postprocess velocity field (add sources)
Input::Record input_record_
ElementFullIter element() const
boost::shared_ptr< Balance > balance_
object for calculation and writing the water balance to file.
EqData()
Creation of all fields.
void assembly_steady_mh_matrix()
void add_factory(std::shared_ptr< FactoryBase > factory)
friend class DarcyFlowMHOutput
Distributed sparse graphs, partitioning.
static const Input::Type::Selection & get_mh_mortar_selection()
Selection for enum MortarMethod.
Abstract linear system class.
static const Input::Type::Record & get_input_type()
Definitions of particular quadrature rules on simplices.
arma::vec::fixed< spacedim > centre() const
#define OLD_ASSERT_EQUAL(a, b)
void set_mesh_data_for_bddc(LinSys_BDDC *bddc_ls)
mixed-hybrid model of linear Darcy flow, possibly unsteady.
unsigned int el_idx() const
void set_mesh(const Mesh &mesh)
void update_solution() override
virtual void output_data() override
Write computed fields.
static Input::Type::Abstract & get_input_type()
virtual void mat_set_values(int nrow, int *rows, int ncol, int *cols, double *vals)=0
unsigned int n_edges() const
Class for representation SI units of Fields.
#define MPI_Barrier(comm)
DarcyFlowMHOutput * output_object
static UnitSI & dimensionless()
Returns dimensionless unit.
virtual double compute_residual()=0
Field< 3, FieldValue< 3 >::Scalar > storativity
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
BCField< 3, FieldValue< 3 >::Scalar > bc_flux
BCField< 3, FieldValue< 3 >::Scalar > bc_switch_pressure
Definitions of Raviart-Thomas finite elements.
ElementAccessor< 3 > element_accessor()
void rhs_set_value(int row, double val)
Solver based on Multilevel BDDC - using corresponding class of OpenFTL package.
ElementVector element
Vector of elements of the mesh.
void output()
Calculate values for output.
Transformed quadrature weights.
void get_solution_vector(double *&vec, unsigned int &vec_size) override
unsigned int lsize(int proc) const
get local size