34 #include "petscviewer.h"
35 #include "petscerror.h"
37 #include <boost/foreach.hpp>
82 namespace it = Input::Type;
86 .
add_value(NoMortar,
"None",
"Mortar space: P0 on elements of lower dimension.")
87 .
add_value(MortarP0,
"P0",
"Mortar space: P0 on elements of lower dimension.")
88 .
add_value(MortarP1,
"P1",
"Mortar space: P1 on intersections, using non-conforming pressures.");
93 .
add_value(
none,
"none",
"Homogeneous Neumann boundary condition. Zero flux")
95 "Dirichlet boundary condition. "
96 "Specify the pressure head through the 'bc_pressure' field "
97 "or the piezometric head through the 'bc_piezo_head' field.")
98 .
add_value(neumann,
"neumann",
"Neumann boundary condition. Prescribe water outflow by the 'bc_flux' field.")
99 .
add_value(robin,
"robin",
"Robin boundary condition. Water outflow equal to $\\sigma (h - h^R)$. "
100 "Specify the transition coefficient by 'bc_sigma' and the reference pressure head or pieaozmetric head "
101 "through 'bc_pressure' and 'bc_piezo_head' respectively.");
108 "Number of Schur complements to perform when solving MH sytem.")
110 "Linear solver for MH problem.")
112 "Parameters of output form MH module.")
114 "Method for coupling Darcy flow between dimensions." )
116 "Settings for computing mass balance.");
123 =
it::Record(
"Steady_MH",
"Mixed-Hybrid solver for STEADY saturated Darcy flow.")
133 =
it::Record(
"Unsteady_MH",
"Mixed-Hybrid solver for unsteady saturated Darcy flow.")
136 "Time governor setting for the unsteady Darcy flow model.")
137 .
copy_keys(DarcyFlowMH_Steady::input_type);
141 =
it::Record(
"Unsteady_LMH",
"Lumped Mixed-Hybrid solver for unsteady saturated Darcy flow.")
144 "Time governor setting for the unsteady Darcy flow model.")
145 .
copy_keys(DarcyFlowMH_Steady::input_type);
155 ADD_FIELD(
cross_section,
"Complement dimension parameter (cross section for 1D, thickness for 2D).",
"1.0" );
161 ADD_FIELD(
sigma,
"Transition coefficient between dimensions.",
"1.0");
167 ADD_FIELD(
bc_type,
"Boundary condition type, possible values:",
"\"none\"" );
194 main_matrix_fields = this->subset({
"anisotropy",
"conductivity",
"cross_section",
"sigma",
"bc_type",
"bc_robin_sigma"});
195 rhs_fields = this->subset({
"water_source_density",
"bc_pressure",
"bc_flux"});
218 using namespace Input;
264 if (it->val<
bool>(
"balance_on"))
306 xprintf(
MsgLog,
"Linear solver ended with reason: %d \n", convergedReason );
307 ASSERT( convergedReason >= 0,
"Linear solver failed to converge. Convergence reason %d \n", convergedReason );
384 vec_size = this->
size;
385 ASSERT(vec != NULL,
"Requested solution is not allocated!\n");
391 ASSERT(vec != NULL,
"Requested solution is not allocated!\n");
436 int el_row, side_row, edge_row, loc_b = 0;
438 int side_rows[4], edge_rows[4];
443 for(
int i=0; i<1000; i++) zeros[i]=0.0;
445 double minus_ones[4] = { -1.0, -1.0, -1.0, -1.0 };
446 double loc_side_rhs[4];
451 for (
unsigned int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++) {
455 unsigned int nsides = ele->n_sides();
459 for (
unsigned int i = 0; i < nsides; i++) {
461 edge_row = edge_rows[i] =
row_4_edge[ele->side(i)->edge_idx()];
462 bcd=ele->side(i)->cond();
465 loc_side_rhs[i] = (ele->centre()[ 2 ] - ele->side(i)->centre()[ 2 ]);
478 loc_side_rhs[i] -= bc_pressure;
515 double val_side = (fe_values.
local_matrix())[i*nsides+i];
516 double val_edge = -1./ (fe_values.
local_matrix())[i*nsides+i];
518 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( side_row, val_side );
519 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( edge_row, val_edge );
539 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( el_row, val_ele );
544 for (
unsigned int i = 0; i < ele->n_neighs_vb; i++) {
547 ngh= ele->neigh_vb[i];
554 switch (ele_higher->dim()) {
569 double value =
data_.
sigma.
value( ele->centre(), ele->element_accessor()) *
578 local_vb[0] = -value; local_vb[1] = value;
579 local_vb[2] = value; local_vb[3] = -value;
585 int ind = tmp_rows[1];
587 double new_val = - value;
588 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( ind, new_val );
599 tmp_rows[2+i] = tmp_rows[1];
608 ASSERT(ele->n_neighs_vb*ele->n_neighs_vb<1000,
"Too many values in E block.");
610 ele->n_neighs_vb, tmp_rows+2, zeros);
640 for (
unsigned int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++) {
646 double source = ele->measure() *
661 vector<int> &dofs,
unsigned int &ele_type,
double &delta, arma::vec &dirichlet) {
665 if (i_ele == (
int)(ml_it_->size()) ) {
671 const Intersection &isect=intersections_[ (*ml_it_)[i_ele] ];
677 dirichlet.resize(ele->
n_sides());
680 for(
unsigned int i_side=0; i_side < ele->
n_sides(); i_side++ ) {
681 dofs[i_side]=darcy_.row_4_edge[ele->
side(i_side)->
edge_idx()];
689 dofs[i_side] = -dofs[i_side];
690 double bc_pressure = darcy_.data_.bc_pressure.value(b_ele.
centre(), b_ele);
691 dirichlet[i_side] = bc_pressure;
702 double delta_i, delta_j;
704 arma::vec dirichlet_i, dirichlet_j;
705 unsigned int ele_type_i, ele_type_j;
710 for(ml_it_ = master_list_.begin(); ml_it_ != master_list_.end(); ++ml_it_) {
712 if (ml_it_->size() == 0)
continue;
728 master_ = intersections_[ml_it_->front()].master_iter();
729 delta_0 = master_->measure();
731 double master_sigma=darcy_.data_.sigma.value( master_->centre(), master_->element_accessor());
734 double check_delta_sum=0;
735 for(i = 0; i <= ml_it_->size(); ++i) {
736 pressure_diff(i, dofs_i, ele_type_i, delta_i, dirichlet_i);
737 check_delta_sum+=delta_i;
739 for (j = 0; j <= ml_it_->size(); ++j) {
740 pressure_diff(j, dofs_j, ele_type_j, delta_j, dirichlet_j);
742 double scale = -master_sigma * delta_i * delta_j / delta_0;
743 product = scale * tensor_average[ele_type_i][ele_type_j];
745 arma::vec rhs(dofs_i.size());
747 ls.
set_values( dofs_i, dofs_j, product, rhs, dirichlet_i, dirichlet_j);
748 auto dofs_i_cp=dofs_i;
749 auto dofs_j_cp=dofs_j;
750 ls.
set_values( dofs_i_cp, dofs_j_cp, product, rhs, dirichlet_i, dirichlet_j);
753 ASSERT(check_delta_sum < 1E-5*delta_0, "sum err %f > 0\n
", check_delta_sum/delta_0);
754 } // loop over master elements
759 void P1_CouplingAssembler::add_sides(const Element * ele, unsigned int shift, vector<int> &dofs, vector<double> &dirichlet)
762 for(unsigned int i_side=0; i_side < ele->n_sides(); i_side++ ) {
763 dofs[shift+i_side] = darcy_.row_4_edge[ele->side(i_side)->edge_idx()];
764 Boundary * bcd = ele->side(i_side)->cond();
767 ElementAccessor<3> b_ele = bcd->element_accessor();
768 DarcyFlowMH::EqData::BC_Type type = (DarcyFlowMH::EqData::BC_Type)darcy_.data_.bc_type.value(b_ele.centre(), b_ele);
769 //DBGMSG("bcd
id: %d sidx: %d type: %d\n
", ele->id(), i_side, type);
770 if (type == DarcyFlowMH::EqData::dirichlet) {
771 //DBGMSG("Dirichlet: %d\n
", ele->index());
772 dofs[shift + i_side] = -dofs[shift + i_side];
773 double bc_pressure = darcy_.data_.bc_pressure.value(b_ele.centre(), b_ele);
774 dirichlet[shift + i_side] = bc_pressure;
787 void P1_CouplingAssembler::assembly(LinSys &ls) {
789 for (const Intersection &intersec : intersections_) {
790 const Element * master = intersec.master_iter();
791 const Element * slave = intersec.slave_iter();
793 add_sides(slave, 0, dofs, dirichlet);
794 add_sides(master, 3, dofs, dirichlet);
796 double master_sigma=darcy_.data_.sigma.value( master->centre(), master->element_accessor());
799 * Local coordinates on 1D
805 * t0 = 0.0 on side 0 node 0
806 * t0 = 1.0 on side 1 node 1
808 * Local coordinates on 2D
815 * t0=0.5, t1=0.0 on side 0 nodes (0,1)
816 * t0=0.5, t1=0.5 on side 1 nodes (1,2)
817 * t0=0.0, t1=0.5 on side 2 nodes (2,0)
822 arma::vec point_Y(1);
824 arma::vec point_2D_Y(intersec.map_to_slave(point_Y)); // local coordinates of Y on slave
825 arma::vec point_1D_Y(intersec.map_to_master(point_Y)); // local coordinates of Y on master
827 arma::vec point_X(1);
829 arma::vec point_2D_X(intersec.map_to_slave(point_X)); // local coordinates of X on slave
830 arma::vec point_1D_X(intersec.map_to_master(point_X)); // local coordinates of X on master
832 arma::mat base_2D(3, 3);
833 // base fce = a0 + a1*t0 + a2*t1
835 base_2D << 1.0 << 0.0 << -2.0 << arma::endr //point on side 0
836 << -1.0 << 2.0 << 2.0 << arma::endr // point on side 1
837 << 1.0 << -2.0 << 0.0 << arma::endr;// point on side 2
839 arma::mat base_1D(2, 2);
840 // base fce = a0 + a1 * t0
842 base_1D << 1.0 << -1.0 << arma::endr // point on side 0,
843 << 0.0 << 1.0 << arma::endr; // point on side 1,
846 arma::vec difference_in_Y(5);
847 arma::vec difference_in_X(5);
850 difference_in_Y.subvec(0, 2) = -base_2D * point_2D_Y;
851 difference_in_X.subvec(0, 2) = -base_2D * point_2D_X;
853 difference_in_Y.subvec(3, 4) = base_1D * point_1D_Y;
854 difference_in_X.subvec(3, 4) = base_1D * point_1D_X;
856 //prvky matice A[i,j]
858 for (int i = 0; i < 5; ++i) {
859 for (int j = 0; j < 5; ++j) {
860 A(i, j) = -master_sigma * intersec.intersection_true_size() *
861 ( difference_in_Y[i] * difference_in_Y[j]
862 + difference_in_Y[i] * difference_in_X[j]/2
863 + difference_in_X[i] * difference_in_Y[j]/2
864 + difference_in_X[i] * difference_in_X[j]
870 ls.set_values( dofs_cp, dofs_cp, A, rhs, dirichlet, dirichlet);
877 /*******************************************************************************
878 * COMPOSE WATER MH MATRIX WITHOUT SCHUR COMPLEMENT
879 ******************************************************************************/
881 void DarcyFlowMH_Steady::create_linear_system() {
883 START_TIMER("preallocation
");
885 auto in_rec = this->input_record_.val<Input::AbstractRecord>("solver
");
887 if (schur0 == NULL) { // create Linear System for MH matrix
889 if (in_rec.type() == LinSys_BDDC::input_type) {
891 xprintf(Warn, "For BDDC is
using no Schur complements.
");
893 LinSys_BDDC *ls = new LinSys_BDDC(global_row_4_sub_row->size(), &(*rows_ds),
894 3, // 3 == la::BddcmlWrapper::SPD_VIA_SYMMETRICGENERAL
895 1, // 1 == number of subdomains per process
896 true); // swap signs of matrix and rhs to make the matrix SPD
897 ls->set_from_input(in_rec);
898 ls->set_solution( NULL );
899 // possible initialization particular to BDDC
901 set_mesh_data_for_bddc(ls);
905 xprintf(Err, "Flow123d was not build with BDDCML support.\n
");
908 else if (in_rec.type() == LinSys_PETSC::input_type) {
909 // use PETSC for serial case even when user wants BDDC
910 if (n_schur_compls > 2) {
911 xprintf(Warn, "Invalid number of Schur Complements. Using 2.
");
915 LinSys_PETSC *schur1, *schur2;
917 if (n_schur_compls == 0) {
918 LinSys_PETSC *ls = new LinSys_PETSC( &(*rows_ds) );
920 // temporary solution; we have to set precision also for sequantial case of BDDC
921 // final solution should be probably call of direct solver for oneproc case
922 if (in_rec.type() != LinSys_BDDC::input_type) ls->set_from_input(in_rec);
924 ls->LinSys::set_from_input(in_rec); // get only common options
927 ls->set_solution( NULL );
931 ISCreateStride(PETSC_COMM_WORLD, side_ds->lsize(), rows_ds->begin(), 1, &is);
932 //ASSERT(err == 0,"Error in ISCreateStride.
");
934 SchurComplement *ls = new SchurComplement(is, &(*rows_ds));
935 ls->set_from_input(in_rec);
936 ls->set_solution( NULL );
939 Distribution *ds = ls->make_complement_distribution();
940 if (n_schur_compls==1) {
941 schur1 = new LinSys_PETSC(ds);
942 schur1->set_positive_definite();
945 ISCreateStride(PETSC_COMM_WORLD, el_ds->lsize(), ls->get_distribution()->begin(), 1, &is);
946 //ASSERT(err == 0,"Error in ISCreateStride.
");
947 SchurComplement *ls1 = new SchurComplement(is, ds); // is is deallocated by SchurComplement
948 ls1->set_negative_definite();
951 schur2 = new LinSys_PETSC( ls1->make_complement_distribution() );
952 schur2->set_positive_definite();
953 ls1->set_complement( schur2 );
956 ls->set_complement( schur1 );
960 START_TIMER("PETSC PREALLOCATION
");
961 schur0->set_symmetric();
962 schur0->start_allocation();
963 assembly_steady_mh_matrix(); // preallocation
964 VecZeroEntries(schur0->get_solution());
965 END_TIMER("PETSC PREALLOCATION
");
968 xprintf(Err, "Unknown solver type. Internal error.\n
");
973 END_TIMER("preallocation
");
975 make_serial_scatter();
982 void DarcyFlowMH_Steady::assembly_linear_system() {
984 data_.set_time(time_->step());
985 //DBGMSG("Assembly linear system\n
");
986 if (data_.changed()) {
987 //DBGMSG(" Data changed\n
");
988 // currently we have no optimization for cases when just time term data or RHS data are changed
989 START_TIMER("full assembly
");
990 if (typeid(*schur0) != typeid(LinSys_BDDC)) {
991 schur0->start_add_assembly(); // finish allocation and create matrix
993 schur0->mat_zero_entries();
994 schur0->rhs_zero_entries();
995 assembly_steady_mh_matrix(); // fill matrix
996 schur0->finish_assembly();
997 schur0->set_matrix_changed();
998 //MatView( *const_cast<Mat*>(schur0->get_matrix()), PETSC_VIEWER_STDOUT_WORLD );
999 //VecView( *const_cast<Vec*>(schur0->get_rhs()), PETSC_VIEWER_STDOUT_WORLD);
1001 if (!time_->is_steady()) {
1002 //DBGMSG(" setup
time term\n
");
1003 // assembly time term and rhs
1007 else if (balance_ != nullptr)
1009 balance_->start_mass_assembly(water_balance_idx_);
1010 balance_->finish_mass_assembly(water_balance_idx_);
1012 END_TIMER("full assembly
");
1014 START_TIMER("modify system
");
1015 if (!time_->is_steady()) {
1018 xprintf(PrgErr, "Planned computation
time for steady solver, but
data are not changed.\n
");
1020 END_TIMER("modiffy system
");
1027 void DarcyFlowMH_Steady::set_mesh_data_for_bddc(LinSys_BDDC * bddc_ls) {
1028 // prepare mesh for BDDCML
1029 // initialize arrays
1030 // auxiliary map for creating coordinates of local dofs and global-to-local numbering
1031 std::map<int,arma::vec3> localDofMap;
1032 // connectivity for the subdomain, i.e. global dof numbers on element, stored element-by-element
1033 // Indices of Nodes on Elements
1034 std::vector<int> inet;
1035 // number of degrees of freedom on elements - determines elementwise chunks of INET array
1036 // Number of Nodes on Elements
1037 std::vector<int> nnet;
1038 // Indices of Subdomain Elements in Global Numbering - for local elements, their global indices
1039 std::vector<int> isegn;
1041 // This array is currently not used in BDDCML, it was used as an interface scaling alternative to scaling
1042 // by diagonal. It corresponds to the rho-scaling.
1043 std::vector<double> element_permeability;
1045 // maximal and minimal dimension of elements
1048 for ( unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++ ) {
1049 // for each element, create local numbering of dofs as fluxes (sides), pressure (element centre), Lagrange multipliers (edges), compatible connections
1050 ElementFullIter el = mesh_->element(el_4_loc[i_loc]);
1051 int e_idx = el.index();
1053 int elDim = el->dim();
1054 elDimMax = std::max( elDimMax, elDim );
1055 elDimMin = std::min( elDimMin, elDim );
1057 isegn.push_back( e_idx );
1060 FOR_ELEMENT_SIDES(el,si) {
1061 // insert local side dof
1062 int side_row = side_row_4_id[ mh_dh.side_dof( el->side(si) ) ];
1063 arma::vec3 coord = el->side(si)->centre();
1065 localDofMap.insert( std::make_pair( side_row, coord ) );
1066 inet.push_back( side_row );
1070 // insert local pressure dof
1071 int el_row = row_4_el[ el_4_loc[i_loc] ];
1072 arma::vec3 coord = el->centre();
1073 localDofMap.insert( std::make_pair( el_row, coord ) );
1074 inet.push_back( el_row );
1077 FOR_ELEMENT_SIDES(el,si) {
1078 // insert local edge dof
1079 int edge_row = row_4_edge[ el->side(si)->edge_idx() ];
1080 arma::vec3 coord = el->side(si)->centre();
1082 localDofMap.insert( std::make_pair( edge_row, coord ) );
1083 inet.push_back( edge_row );
1087 // insert dofs related to compatible connections
1088 for ( unsigned int i_neigh = 0; i_neigh < el->n_neighs_vb; i_neigh++) {
1089 int edge_row = row_4_edge[ el->neigh_vb[i_neigh]->edge_idx() ];
1090 arma::vec3 coord = el->neigh_vb[i_neigh]->edge()->side(0)->centre();
1092 localDofMap.insert( std::make_pair( edge_row, coord ) );
1093 inet.push_back( edge_row );
1097 nnet.push_back( nne );
1099 // version for rho scaling
1100 // trace computation
1101 arma::vec3 centre = el->centre();
1102 double conduct = data_.conductivity.value( centre , el->element_accessor() );
1103 arma::mat33 aniso = data_.anisotropy.value( centre, el->element_accessor() );
1105 // compute mean on the diagonal
1107 for ( int i = 0; i < 3; i++) {
1108 coef = coef + aniso.at(i,i);
1110 // Maybe divide by cs
1111 coef = conduct*coef / 3;
1114 "Zero coefficient of hydrodynamic resistance %f . \n
", coef );
1115 element_permeability.push_back( 1. / coef );
1117 //convert set of dofs to vectors
1118 // number of nodes (= dofs) on the subdomain
1119 int numNodeSub = localDofMap.size();
1120 ASSERT_EQUAL( (unsigned int)numNodeSub, global_row_4_sub_row->size() );
1121 // Indices of Subdomain Nodes in Global Numbering - for local nodes, their global indices
1122 std::vector<int> isngn( numNodeSub );
1123 // pseudo-coordinates of local nodes (i.e. dofs)
1124 // they need not be exact, they are used just for some geometrical considerations in BDDCML,
1125 // such as selection of corners maximizing area of a triangle, bounding boxes fro subdomains to
1126 // find candidate neighbours etc.
1127 std::vector<double> xyz( numNodeSub * 3 ) ;
1129 std::map<int,arma::vec3>::iterator itB = localDofMap.begin();
1130 for ( ; itB != localDofMap.end(); ++itB ) {
1131 isngn[ind] = itB -> first;
1133 arma::vec3 coord = itB -> second;
1134 for ( int j = 0; j < 3; j++ ) {
1135 xyz[ j*numNodeSub + ind ] = coord[j];
1140 localDofMap.clear();
1142 // Number of Nodal Degrees of Freedom
1143 // nndf is trivially one - dofs coincide with nodes
1144 std::vector<int> nndf( numNodeSub, 1 );
1146 // prepare auxiliary map for renumbering nodes
1147 typedef std::map<int,int> Global2LocalMap_; //! type for storage of global to local map
1148 Global2LocalMap_ global2LocalNodeMap;
1149 for ( unsigned ind = 0; ind < isngn.size(); ++ind ) {
1150 global2LocalNodeMap.insert( std::make_pair( static_cast<unsigned>( isngn[ind] ), ind ) );
1153 // renumber nodes in the inet array to locals
1155 for ( unsigned int iEle = 0; iEle < isegn.size(); iEle++ ) {
1156 int nne = nnet[ iEle ];
1157 for ( int ien = 0; ien < nne; ien++ ) {
1159 int indGlob = inet[indInet];
1160 // map it to local node
1161 Global2LocalMap_::iterator pos = global2LocalNodeMap.find( indGlob );
1162 ASSERT( pos != global2LocalNodeMap.end(),
1163 "Cannot remap node index %d to local indices. \n
", indGlob );
1164 int indLoc = static_cast<int> ( pos -> second );
1167 inet[ indInet++ ] = indLoc;
1171 int numNodes = size;
1172 int numDofsInt = size;
1173 int spaceDim = 3; // TODO: what is the proper value here?
1174 int meshDim = elDimMax;
1176 bddc_ls -> load_mesh( spaceDim, numNodes, numDofsInt, inet, nnet, nndf, isegn, isngn, isngn, xyz, element_permeability, meshDim );
1182 //=============================================================================
1183 // DESTROY WATER MH SYSTEM STRUCTURE
1184 //=============================================================================
1185 DarcyFlowMH_Steady::~DarcyFlowMH_Steady() {
1186 if (schur0 != NULL) delete schur0;
1194 xfree(side_id_4_loc);
1195 xfree(side_row_4_id);
1199 if (solution != NULL) {
1200 VecDestroy(&sol_vec);
1204 delete output_object;
1206 VecScatterDestroy(&par_to_all);
1210 // ================================================
1214 // ========================================================================
1215 // to finish row_4_id arrays we have to convert individual numberings of
1216 // sides/els/edges to whole numbering of rows. To this end we count shifts
1217 // for sides/els/edges on each proc and then we apply them on row_4_id
1219 // we employ macros to avoid code redundancy
1220 // =======================================================================
1221 void DarcyFlowMH_Steady::make_row_numberings() {
1223 int np = edge_ds->np();
1224 int edge_shift[np], el_shift[np], side_shift[np];
1225 unsigned int rows_starts[np];
1227 int edge_n_id = mesh_->n_edges(),
1228 el_n_id = mesh_->element.size(),
1229 side_n_id = mesh_->n_sides();
1231 // compute shifts on every proc
1232 shift = 0; // in this var. we count new starts of arrays chunks
1233 for (i = 0; i < np; i++) {
1234 side_shift[i] = shift - (side_ds->begin(i)); // subtract actual start of the chunk
1235 shift += side_ds->lsize(i);
1236 el_shift[i] = shift - (el_ds->begin(i));
1237 shift += el_ds->lsize(i);
1238 edge_shift[i] = shift - (edge_ds->begin(i));
1239 shift += edge_ds->lsize(i);
1240 rows_starts[i] = shift;
1243 for (i = 0; i < side_n_id; i++) {
1244 int &what = side_row_4_id[i];
1246 what += side_shift[side_ds->get_proc(what)];
1248 for (i = 0; i < el_n_id; i++) {
1249 int &what = row_4_el[i];
1251 what += el_shift[el_ds->get_proc(what)];
1254 for (i = 0; i < edge_n_id; i++) {
1255 int &what = row_4_edge[i];
1257 what += edge_shift[edge_ds->get_proc(what)];
1259 // make distribution of rows
1260 for (i = np - 1; i > 0; i--)
1261 rows_starts[i] -= rows_starts[i - 1];
1263 rows_ds = boost::make_shared<Distribution>(&(rows_starts[0]), PETSC_COMM_WORLD);
1266 void DarcyFlowMH_Steady::make_serial_scatter() {
1267 START_TIMER("prepare scatter
");
1268 // prepare Scatter form parallel to sequantial in original numbering
1271 int i, *loc_idx; //, si;
1273 // create local solution vector
1274 solution = (double *) xmalloc(size * sizeof(double));
1275 VecCreateSeqWithArray(PETSC_COMM_SELF,1, size, solution,
1278 // create seq. IS to scatter par solutin to seq. vec. in original order
1279 // use essentialy row_4_id arrays
1280 loc_idx = (int *) xmalloc(size * sizeof(int));
1282 FOR_ELEMENTS(mesh_, ele) {
1283 FOR_ELEMENT_SIDES(ele,si) {
1284 loc_idx[i++] = side_row_4_id[ mh_dh.side_dof( ele->side(si) ) ];
1287 FOR_ELEMENTS(mesh_, ele) {
1288 loc_idx[i++] = row_4_el[ele.index()];
1290 for(unsigned int i_edg=0; i_edg < mesh_->n_edges(); i_edg++) {
1291 loc_idx[i++] = row_4_edge[i_edg];
1293 ASSERT( i==size,"Size of array does not match number of fills.\n
");
1294 //DBGPRINT_INT("loc_idx
",size,loc_idx);
1295 ISCreateGeneral(PETSC_COMM_SELF, size, loc_idx, PETSC_COPY_VALUES, &(is_loc));
1297 VecScatterCreate(schur0->get_solution(), is_loc, sol_vec,
1298 PETSC_NULL, &par_to_all);
1299 ISDestroy(&(is_loc));
1301 solution_changed_for_scatter=true;
1303 END_TIMER("prepare scatter
");
1307 // ====================================================================================
1308 // - compute optimal edge partitioning
1309 // - compute appropriate partitioning of elements and sides
1310 // - make arrays: *_id_4_loc and *_row_4_id to allow parallel assembly of the MH matrix
1311 // ====================================================================================
1312 void DarcyFlowMH_Steady::prepare_parallel( const Input::AbstractRecord in_rec) {
1316 int *loc_part; // optimal (edge,el) partitioning (local chunk)
1317 int *id_4_old; // map from old idx to ids (edge,el)
1323 //ierr = MPI_Barrier(PETSC_COMM_WORLD);
1326 id_4_old = new int[mesh_->n_elements()];
1328 FOR_ELEMENTS(mesh_, el) id_4_old[i++] = el.index();
1330 mesh_->get_part()->id_maps(mesh_->element.size(), id_4_old, el_ds, el_4_loc, row_4_el);
1333 //optimal element part; loc. els. id-> new el. numbering
1334 Distribution init_edge_ds(DistributionLocalized(), mesh_->n_edges(), PETSC_COMM_WORLD);
1335 // partitioning of edges, edge belongs to the proc of his first element
1336 // this is not optimal but simple
1337 loc_part = new int[init_edge_ds.lsize()];
1338 id_4_old = new int[mesh_->n_edges()];
1341 FOR_EDGES(mesh_, edg ) {
1342 unsigned int i_edg = edg - mesh_->edges.begin();
1344 e_idx = mesh_->element.index(edg->side(0)->element());
1345 if (init_edge_ds.is_local(i_edg)) {
1346 // find (new) proc of the first element of the edge
1347 loc_part[loc_i++] = el_ds->get_proc(row_4_el[e_idx]);
1350 id_4_old[i_edg] = i_edg;
1354 Partitioning::id_maps(mesh_->n_edges(), id_4_old, init_edge_ds, loc_part, edge_ds, edge_4_loc, row_4_edge);
1358 //optimal side part; loc. sides; id-> new side numbering
1359 Distribution init_side_ds(DistributionBlock(), mesh_->n_sides(), PETSC_COMM_WORLD);
1360 // partitioning of sides follows elements
1361 loc_part = new int[init_side_ds.lsize()];
1362 id_4_old = new int[mesh_->n_sides()];
1366 FOR_SIDES(mesh_, side ) {
1368 if (init_side_ds.is_local(is)) {
1369 // find (new) proc of the element of the side
1370 loc_part[loc_i++] = el_ds->get_proc(
1371 row_4_el[mesh_->element.index(side->element())]);
1374 id_4_old[is++] = mh_dh.side_dof( side );
1378 Partitioning::id_maps(mesh_->n_sides(), id_4_old, init_side_ds, loc_part, side_ds,
1379 side_id_4_loc, side_row_4_id);
1383 // convert row_4_id arrays from separate numberings to global numbering of rows
1384 make_row_numberings();
1386 // prepare global_row_4_sub_row
1389 if (in_rec.type() == LinSys_BDDC::input_type) {
1392 int side_row, edge_row;
1394 global_row_4_sub_row = boost::make_shared<LocalToGlobalMap>(rows_ds);
1398 // for each subdomain:
1399 // | velocities (at sides) | pressures (at elements) | L. mult. (at edges) |
1400 for (unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++) {
1401 el = mesh_->element(el_4_loc[i_loc]);
1402 int el_row = row_4_el[el_4_loc[i_loc]];
1404 global_row_4_sub_row->insert( el_row );
1406 unsigned int nsides = el->n_sides();
1407 for (unsigned int i = 0; i < nsides; i++) {
1408 side_row = side_row_4_id[ mh_dh.side_dof( el->side(i) ) ];
1409 edge_row = row_4_edge[el->side(i)->edge_idx()];
1411 global_row_4_sub_row->insert( side_row );
1412 global_row_4_sub_row->insert( edge_row );
1415 for (unsigned int i_neigh = 0; i_neigh < el->n_neighs_vb; i_neigh++) {
1417 edge_row = row_4_edge[el->neigh_vb[i_neigh]->edge_idx() ];
1418 global_row_4_sub_row->insert( edge_row );
1421 global_row_4_sub_row->finalize();
1423 #endif // HAVE_BDDCML
1429 void mat_count_off_proc_values(Mat m, Vec v) {
1431 const PetscInt *cols;
1432 Distribution distr(v);
1437 MatGetOwnershipRange(m, &first, &last);
1438 for (int row = first; row < last; row++) {
1439 MatGetRow(m, row, &n, &cols, PETSC_NULL);
1440 bool exists_off = false;
1441 for (int i = 0; i < n; i++)
1442 if (distr.get_proc(cols[i]) != distr.myp())
1443 n_off++, exists_off = true;
1448 MatRestoreRow(m, row, &n, &cols, PETSC_NULL);
1463 // ========================
1466 DarcyFlowMH_Unsteady::DarcyFlowMH_Unsteady(Mesh &mesh_in, const Input::Record in_rec)
1467 : DarcyFlowMH_Steady(mesh_in, in_rec, false)
1469 time_ = new TimeGovernor(in_rec.val<Input::Record>("time
"));
1470 data_.mark_input_times(this->mark_type());
1471 data_.set_limit_side(LimitSide::right);
1472 data_.set_time(time_->step());
1474 output_object = new DarcyFlowMHOutput(this, in_rec.val<Input::Record>("output
"));
1475 //balance_->units(output_object->get_output_fields().field_ele_pressure.units()*data_.cross_section.units()*data_.storativity.units());
1477 //time_->fix_dt_until_mark();
1478 create_linear_system();
1480 VecDuplicate(schur0->get_solution(), &previous_solution);
1481 VecCreateMPI(PETSC_COMM_WORLD,rows_ds->lsize(),PETSC_DETERMINE,&(steady_diagonal));
1482 VecDuplicate(steady_diagonal,& new_diagonal);
1483 VecZeroEntries(new_diagonal);
1484 VecDuplicate(*( schur0->get_rhs()), &steady_rhs);
1486 assembly_linear_system();
1487 read_init_condition();
1492 void DarcyFlowMH_Unsteady::read_init_condition()
1495 // read inital condition
1496 VecZeroEntries(schur0->get_solution());
1498 double *local_sol = schur0->get_solution_array();
1500 // cycle over local element rows
1501 ElementFullIter ele = ELEMENT_FULL_ITER(mesh_, NULL);
1503 DBGMSG("Setup with dt: %f\n
",time_->dt());
1504 for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) {
1505 ele = mesh_->element(el_4_loc[i_loc_el]);
1506 int i_loc_row = i_loc_el + side_ds->lsize();
1508 // set initial condition
1509 local_sol[i_loc_row] = data_.init_pressure.value(ele->centre(),ele->element_accessor());
1512 solution_changed_for_scatter=true;
1516 void DarcyFlowMH_Unsteady::setup_time_term() {
1517 // save diagonal of steady matrix
1518 MatGetDiagonal(*( schur0->get_matrix() ), steady_diagonal);
1520 VecCopy(*( schur0->get_rhs()), steady_rhs);
1523 PetscScalar *local_diagonal;
1524 VecGetArray(new_diagonal,& local_diagonal);
1526 ElementFullIter ele = ELEMENT_FULL_ITER(mesh_, NULL);
1527 DBGMSG("Setup with dt: %f\n
",time_->dt());
1529 if (balance_ != nullptr)
1530 balance_->start_mass_assembly(water_balance_idx_);
1532 for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) {
1533 ele = mesh_->element(el_4_loc[i_loc_el]);
1534 int i_loc_row = i_loc_el + side_ds->lsize();
1537 double diagonal_coeff = data_.cross_section.value(ele->centre(), ele->element_accessor())
1538 * data_.storativity.value(ele->centre(), ele->element_accessor())
1540 local_diagonal[i_loc_row]= - diagonal_coeff / time_->dt();
1542 if (balance_ != nullptr)
1543 balance_->add_mass_matrix_values(water_balance_idx_, ele->region().bulk_idx(), {i_loc_row}, {diagonal_coeff});
1545 VecRestoreArray(new_diagonal,& local_diagonal);
1546 MatDiagonalSet(*( schur0->get_matrix() ), new_diagonal, ADD_VALUES);
1548 solution_changed_for_scatter=true;
1549 schur0->set_matrix_changed();
1551 if (balance_ != nullptr)
1552 balance_->finish_mass_assembly(water_balance_idx_);
1555 void DarcyFlowMH_Unsteady::modify_system() {
1556 START_TIMER("modify system
");
1557 if (time_->is_changed_dt() && time_->step().index()>0) {
1558 double scale_factor=time_->step(-2).length()/time_->step().length();
1559 if (scale_factor != 1.0) {
1560 // if time step has changed and setup_time_term not called
1561 MatDiagonalSet(*( schur0->get_matrix() ),steady_diagonal, INSERT_VALUES);
1563 VecScale(new_diagonal, time_->last_dt()/time_->dt());
1564 MatDiagonalSet(*( schur0->get_matrix() ),new_diagonal, ADD_VALUES);
1565 schur0->set_matrix_changed();
1569 // modify RHS - add previous solution
1570 VecPointwiseMult(*( schur0->get_rhs()), new_diagonal, schur0->get_solution());
1571 VecAXPY(*( schur0->get_rhs()), 1.0, steady_rhs);
1572 schur0->set_rhs_changed();
1575 VecSwap(previous_solution, schur0->get_solution());
1578 // ========================
1581 DarcyFlowLMH_Unsteady::DarcyFlowLMH_Unsteady(Mesh &mesh_in, const Input::Record in_rec)
1582 : DarcyFlowMH_Steady(mesh_in, in_rec,false)
1584 time_ = new TimeGovernor(in_rec.val<Input::Record>("time"));
1585 data_.mark_input_times(this->mark_type());
1588 data_.set_limit_side(LimitSide::right);
1589 data_.set_time(time_->step());
1591 output_object = new DarcyFlowMHOutput(this, in_rec.val<Input::Record>("output
"));
1592 //balance_->units(output_object->get_output_fields().field_ele_pressure.units()*data_.cross_section.units()*data_.storativity.units());
1594 //time_->fix_dt_until_mark();
1595 create_linear_system();
1596 VecDuplicate(schur0->get_solution(), &previous_solution);
1597 VecCreateMPI(PETSC_COMM_WORLD,rows_ds->lsize(),PETSC_DETERMINE,&(steady_diagonal));
1598 VecDuplicate(steady_diagonal,& new_diagonal);
1599 VecDuplicate(*( schur0->get_rhs()), &steady_rhs);
1601 assembly_linear_system();
1602 read_init_condition();
1606 void DarcyFlowLMH_Unsteady::read_init_condition()
1608 VecZeroEntries(schur0->get_solution());
1610 // apply initial condition
1611 // cycle over local element rows
1613 ElementFullIter ele = ELEMENT_FULL_ITER(mesh_, NULL);
1616 for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) {
1617 ele = mesh_->element(el_4_loc[i_loc_el]);
1619 init_value = data_.init_pressure.value(ele->centre(), ele->element_accessor());
1621 FOR_ELEMENT_SIDES(ele,i) {
1622 int edge_row = row_4_edge[ele->side(i)->edge_idx()];
1623 VecSetValue(schur0->get_solution(),edge_row,init_value/ele->n_sides(),ADD_VALUES);
1626 VecAssemblyBegin(schur0->get_solution());
1627 VecAssemblyEnd(schur0->get_solution());
1629 solution_changed_for_scatter=true;
1634 void DarcyFlowLMH_Unsteady::setup_time_term()
1636 // save diagonal of steady matrix
1637 MatGetDiagonal(*( schur0->get_matrix() ), steady_diagonal);
1639 VecCopy(*( schur0->get_rhs()),steady_rhs);
1641 VecZeroEntries(new_diagonal);
1643 // modify matrix diagonal
1644 // cycle over local element rows
1645 ElementFullIter ele = ELEMENT_FULL_ITER(mesh_, NULL);
1646 DBGMSG("setup
time term with dt: %f\n
", time_->dt());
1648 if (balance_ != nullptr)
1649 balance_->start_mass_assembly(water_balance_idx_);
1651 for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) {
1652 ele = mesh_->element(el_4_loc[i_loc_el]);
1654 data_.init_pressure.value(ele->centre(), ele->element_accessor());
1656 FOR_ELEMENT_SIDES(ele,i) {
1657 int edge_row = row_4_edge[ele->side(i)->edge_idx()];
1659 double diagonal_coef = ele->measure() *
1660 data_.storativity.value(ele->centre(), ele->element_accessor()) *
1661 data_.cross_section.value(ele->centre(), ele->element_accessor())
1663 VecSetValue(new_diagonal, edge_row, -diagonal_coef / time_->dt(), ADD_VALUES);
1665 if (balance_ != nullptr)
1666 balance_->add_mass_matrix_values(water_balance_idx_, ele->region().bulk_idx(), {edge_row}, {diagonal_coef});
1671 VecAssemblyBegin(new_diagonal);
1672 VecAssemblyEnd(new_diagonal);
1674 MatDiagonalSet(*( schur0->get_matrix() ),new_diagonal, ADD_VALUES);
1676 solution_changed_for_scatter=true;
1677 schur0->set_matrix_changed();
1679 if (balance_ != nullptr)
1680 balance_->finish_mass_assembly(water_balance_idx_);
1683 void DarcyFlowLMH_Unsteady::modify_system() {
1684 START_TIMER("modify system
");
1685 //if (time_->step().index()>0)
1686 // DBGMSG("dt: %f dt-1: %f indexchanged: %d matrix: %d\n
", time_->step().length(), time_->step(-1).length(), time_->is_changed_dt(), schur0->is_matrix_changed() );
1688 if (time_->is_changed_dt() && time_->step().index()>0) {
1689 // if time step has changed and setup_time_term not called
1691 double scale_factor=time_->step(-2).length()/time_->step().length();
1692 if (scale_factor != 1.0) {
1693 MatDiagonalSet(*( schur0->get_matrix() ),steady_diagonal, INSERT_VALUES);
1695 //DBGMSG("Scale factor: %f\n
",scale_factor);
1696 VecScale(new_diagonal, scale_factor);
1697 MatDiagonalSet(*( schur0->get_matrix() ),new_diagonal, ADD_VALUES);
1698 schur0->set_matrix_changed();
1702 // modify RHS - add previous solution
1703 VecPointwiseMult(*( schur0->get_rhs()), new_diagonal, schur0->get_solution());
1704 VecAXPY(*( schur0->get_rhs()), 1.0, steady_rhs);
1705 schur0->set_rhs_changed();
1708 VecSwap(previous_solution, schur0->get_solution());
1712 void DarcyFlowLMH_Unsteady::assembly_source_term()
1714 if (balance_ != nullptr)
1715 balance_->start_source_assembly(water_balance_idx_);
1717 for (unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++)
1719 ElementFullIter ele = mesh_->element(el_4_loc[i_loc]);
1721 // set lumped source
1722 double diagonal_coef = ele->measure()
1723 * data_.cross_section.value(ele->centre(), ele->element_accessor())
1724 * data_.water_source_density.value(ele->centre(), ele->element_accessor())
1727 FOR_ELEMENT_SIDES(ele,i)
1729 int edge_row = row_4_edge[ele->side(i)->edge_idx()];
1731 schur0->rhs_set_value(edge_row, -diagonal_coef);
1733 if (balance_ != nullptr)
1734 balance_->add_source_rhs_values(water_balance_idx_, ele->region().bulk_idx(), {edge_row}, {diagonal_coef});
1738 if (balance_ != nullptr)
1739 balance_->finish_source_assembly(water_balance_idx_);
1743 void DarcyFlowLMH_Unsteady::postprocess() {
1744 int side_row, loc_edge_row, i;
1747 double new_pressure, old_pressure, time_coef;
1749 PetscScalar *loc_prev_sol;
1750 VecGetArray(previous_solution, &loc_prev_sol);
1752 // modify side fluxes in parallel
1753 // for every local edge take time term on diagonal and add it to the corresponding flux
1754 for (unsigned int i_loc = 0; i_loc < edge_ds->lsize(); i_loc++) {
1756 edg = &( mesh_->edges[ edge_4_loc[i_loc] ] );
1757 loc_edge_row = side_ds->lsize() + el_ds->lsize() + i_loc;
1759 new_pressure = (schur0->get_solution_array())[loc_edge_row];
1760 old_pressure = loc_prev_sol[loc_edge_row];
1761 FOR_EDGE_SIDES(edg,i) {
1762 ele = edg->side(i)->element();
1763 side_row = side_row_4_id[ mh_dh.side_dof( edg->side(i) ) ];
1764 time_coef = - ele->measure() *
1765 data_.cross_section.value(ele->centre(), ele->element_accessor()) *
1766 data_.storativity.value(ele->centre(), ele->element_accessor()) /
1767 time_->dt() / ele->n_sides();
1768 VecSetValue(schur0->get_solution(), side_row, time_coef * (new_pressure - old_pressure), ADD_VALUES);
1771 VecRestoreArray(previous_solution, &loc_prev_sol);
1773 VecAssemblyBegin(schur0->get_solution());
1774 VecAssemblyEnd(schur0->get_solution());
1779 // modify side fluxes in parallel
1780 // for every local edge take time term on digonal and add it to the corresponding flux
1782 for (unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++) {
1783 ele = mesh_->element(el_4_loc[i_loc]);
1784 FOR_ELEMENT_SIDES(ele,i) {
1785 side_rows[i] = side_row_4_id[ mh_dh.side_dof( ele->side(i) ) ];
1786 values[i] = 1.0 * ele->measure() *
1787 data_.cross_section.value(ele->centre(), ele->element_accessor()) *
1788 data_.water_source_density.value(ele->centre(), ele->element_accessor()) /
1791 VecSetValues(schur0->get_solution(), ele->n_sides(), side_rows, values, ADD_VALUES);
1793 VecAssemblyBegin(schur0->get_solution());
1794 VecAssemblyEnd(schur0->get_solution());
1797 //-----------------------------------------------------------------------------
1798 // 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...
void set_limit_side(LimitSide side)
Output class for darcy_flow_mh model.
virtual void get_solution_vector(double *&vec, unsigned int &vec_size)
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
void make_intersec_elements()
static Input::Type::Record input_type
unsigned int edge_idx() const
MortarMethod mortar_method_
Wrappers for linear systems based on MPIAIJ and MATIS format.
virtual void rhs_set_values(int nrow, int *rows, double *vals)=0
static Input::Type::Record input_type
Main balance input record type.
friend class P1_CouplingAssembler
bool is_end() const
Returns true if the actual time is greater than or equal to the end time.
static Input::Type::Selection mh_mortar_selection
void assembly(LinSys &ls)
void next_time()
Proceed to the next time according to current estimated time step.
bool solution_changed_for_scatter
const arma::vec::fixed< spacedim > normal_vector(unsigned int point_no)
Returns the normal vector to a side at given quadrature point.
arma::vec3 centre() const
TimeMark::Type type_output()
void set_time(const TimeStep &time)
friend class P0_CouplingAssembler
#define ELEMENT_FULL_ITER(_mesh_, i)
static Input::Type::Record input_type
Class FEValues calculates finite element data on the actual cells such as shape function values...
boost::shared_ptr< Distribution > rows_ds
bool is_current(const TimeMark::Type &mask) const
virtual double get_solution_precision()=0
BCField< 3, FieldValue< 3 >::Scalar > bc_flux
void pressure_diff(int i_ele, vector< int > &dofs, unsigned int &ele_type, double &delta, arma::vec &dirichlet)
static Input::Type::Record input_type
BCField< 3, FieldValue< 3 >::Enum > bc_type
const TimeStep & step(int index=-1) const
Field< 3, FieldValue< 3 >::Scalar > storativity
#define ADD_FIELD(name,...)
Basic time management functionality for unsteady (and steady) solvers (class Equation).
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
static TimeMarks & marks()
Basic time management class.
void view(const char *name="") const
Symmetric Gauss-Legendre quadrature formulae on simplices.
BCField< 3, FieldValue< 3 >::Scalar > bc_pressure
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)
virtual void update_solution()
unsigned int n_elements() const
virtual void get_parallel_solution_vector(Vec &vector)
virtual void assembly_source_term()
Source term is implemented differently in LMH version.
boost::shared_ptr< Balance > balance_
object for calculation and writing the water balance to file.
static Input::Type::AbstractRecord input_type
void update(ElementFullIter ele, FieldType &cond_anisothropy, FieldType_Scalar &cross_section, FieldType_Scalar &conductivity)
const Vec & get_solution()
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Field< 3, FieldValue< 3 >::TensorFixed > anisotropy
void assembly_linear_system()
FieldCommon & input_selection(const Input::Type::Selection *element_selection)
unsigned int n_sides() const
const Element * slave_iter() const
#define START_TIMER(tag)
Starts a timer with specified tag.
unsigned int water_balance_idx_
index of water balance within the Balance object.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
unsigned int side_dof(const SideIter side) const
SideIter side(const unsigned int loc_index)
Mixed-hybrid model of linear Darcy flow, possibly unsteady.
void mark_input_times(TimeMark::Type mark_type)
static Input::Type::Record input_type
double solution_precision() const
bool is_steady() const
Returns true if the time governor is used for steady problem.
Support classes for parallel programing.
Field< 3, FieldValue< 3 >::Scalar > conductivity
FieldSet main_matrix_fields
static Input::Type::AbstractRecord input_type
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...
Field< 3, FieldValue< 3 >::Scalar > sigma
double intersection_true_size() const
virtual void postprocess()
postprocess velocity field (add sources)
auto disable_where(const Field< spacedim, typename FieldValue< spacedim >::Enum > &control_field, const vector< FieldEnum > &value_list) -> Field &
ElementFullIter element() const
void reinit(ElementFullIter &cell, unsigned int sid)
Update cell-dependent data (gradients, Jacobians etc.)
TimeGovernor const & time()
void assembly_steady_mh_matrix()
void add_factory(std::shared_ptr< FactoryBase > factory)
friend class DarcyFlowMHOutput
Distributed sparse graphs, partitioning.
FullIter full_iter(Iter it)
Abstract linear system class.
Definitions of particular quadrature rules on simplices.
BCField< 3, FieldValue< 3 >::Scalar > bc_robin_sigma
#define END_TIMER(tag)
Ends a timer with specified tag.
static Input::Type::Record input_type
TimeMark::Type mark_type()
arma::vec::fixed< spacedim > centre() const
mixed-hybrid model of linear Darcy flow, possibly unsteady.
unsigned int el_idx() const
void set_mesh(const Mesh &mesh)
virtual void output_data() override
Write computed fields.
Field< 3, FieldValue< 3 >::Scalar > cross_section
virtual void mat_set_values(int nrow, int *rows, int ncol, int *cols, double *vals)=0
unsigned int n_edges() const
static Input::Type::Selection bc_type_selection
Class for representation SI units of Fields.
Field< 3, FieldValue< 3 >::Scalar > init_pressure
#define MPI_Barrier(comm)
DarcyFlowMHOutput * output_object
DarcyFlowMH_Steady(Mesh &mesh, const Input::Record in_rec, bool make_tg=true)
CREATE AND FILL GLOBAL MH MATRIX OF THE WATER MODEL.
static UnitSI & dimensionless()
Returns dimensionless unit.
EqData()
Collect all fields.
Field< 3, FieldValue< 3 >::Scalar > water_source_density
FieldSet time_term_fields
void prepare_parallel(const Input::AbstractRecord in_rec)
ElementAccessor< 3 > element_accessor()
void rhs_set_value(int row, double val)
void create_linear_system()
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.
Calculates finite element data on a side.
unsigned int lsize(int proc) const
get local size