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.");
103 "Number of Schur complements to perform when solving MH sytem.")
105 "Linear solver for MH problem.")
107 "Parameters of output form MH module.")
109 "Method for coupling Darcy flow between dimensions." );
113 =
it::Record(
"Steady_MH",
"Mixed-Hybrid solver for STEADY saturated Darcy flow.")
123 =
it::Record(
"Unsteady_MH",
"Mixed-Hybrid solver for unsteady saturated Darcy flow.")
126 "Time governor setting for the unsteady Darcy flow model.")
127 .
copy_keys(DarcyFlowMH_Steady::input_type);
131 =
it::Record(
"Unsteady_LMH",
"Lumped Mixed-Hybrid solver for unsteady saturated Darcy flow.")
134 "Time governor setting for the unsteady Darcy flow model.")
135 .
copy_keys(DarcyFlowMH_Steady::input_type);
149 ADD_FIELD(
cross_section,
"Complement dimension parameter (cross section for 1D, thickness for 2D).",
"1.0" );
151 ADD_FIELD(
sigma,
"Transition coefficient between dimensions.",
"1.0");
154 ADD_FIELD(
bc_type,
"Boundary condition type, possible values:",
"\"none\"" );
176 main_matrix_fields = this->subset({
"anisotropy",
"conductivity",
"cross_section",
"sigma",
"bc_type",
"bc_robin_sigma"});
177 rhs_fields = this->subset({
"water_source_density",
"bc_pressure",
"bc_flux"});
200 using namespace Input;
277 xprintf(
MsgLog,
"Linear solver ended with reason: %d \n", convergedReason );
278 ASSERT( convergedReason >= 0,
"Linear solver failed to converge. Convergence reason %d \n", convergedReason );
340 schur0 -> get_whole_solution( sol_disordered );
344 for (
int i = 0; i < this->
size; i++ ) {
351 ASSERT(vec != NULL,
"Requested solution is not allocated!\n");
365 ASSERT(vec != NULL,
"Requested solution is not allocated!\n");
411 int el_row, side_row, edge_row;
414 int side_rows[4], edge_rows[4];
419 for(
int i=0; i<1000; i++) zeros[i]=0.0;
421 double minus_ones[4] = { -1.0, -1.0, -1.0, -1.0 };
422 double loc_side_rhs[4];
426 for (
unsigned int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++) {
430 unsigned int nsides = ele->n_sides();
434 for (
unsigned int i = 0; i < nsides; i++) {
436 edge_row = edge_rows[i] =
row_4_edge[ele->side(i)->edge_idx()];
437 bcd=ele->side(i)->cond();
440 loc_side_rhs[i] = (ele->centre()[ 2 ] - ele->side(i)->centre()[ 2 ]);
454 loc_side_rhs[i] -= bc_pressure;
486 double val_side = (fe_values.
local_matrix())[i*nsides+i];
487 double val_edge = -1./ (fe_values.
local_matrix())[i*nsides+i];
489 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( side_row, val_side );
490 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( edge_row, val_edge );
525 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( el_row, val_ele );
530 for (
unsigned int i = 0; i < ele->n_neighs_vb; i++) {
533 ngh= ele->neigh_vb[i];
540 switch (ele_higher->dim()) {
555 double value =
data_.
sigma.
value( ele->centre(), ele->element_accessor()) *
564 local_vb[0] = -value; local_vb[1] = value;
565 local_vb[2] = value; local_vb[3] = -value;
571 int ind = tmp_rows[1];
573 double new_val = - value;
574 static_cast<LinSys_BDDC*
>(ls)->diagonal_weights_set_value( ind, new_val );
585 tmp_rows[2+i] = tmp_rows[1];
594 ASSERT(ele->n_neighs_vb*ele->n_neighs_vb<1000,
"Too many values in E block.");
596 ele->n_neighs_vb, tmp_rows+2, zeros);
634 vector<int> &dofs,
unsigned int &ele_type,
double &delta, arma::vec &dirichlet) {
638 if (i_ele == ml_it_->size() ) {
644 const Intersection &isect=intersections_[ (*ml_it_)[i_ele] ];
651 for(
unsigned int i_side=0; i_side < ele->
n_sides(); i_side++ ) {
652 dofs[i_side]=darcy_.row_4_edge[ele->
side(i_side)->
edge_idx()];
655 dirichlet.resize(ele->
n_sides());
661 dofs[i_side] = -dofs[i_side];
662 double bc_pressure = darcy_.data_.bc_pressure.value(b_ele.
centre(), b_ele);
663 dirichlet[i_side] = bc_pressure;
674 double delta_i, delta_j;
676 arma::vec dirichlet_i, dirichlet_j;
677 unsigned int ele_type_i, ele_type_j;
682 for(ml_it_ = master_list_.begin(); ml_it_ != master_list_.end(); ++ml_it_) {
684 if (ml_it_->size() == 0)
continue;
700 master_ = intersections_[ml_it_->front()].master_iter();
701 delta_0 = master_->measure();
703 double master_sigma=darcy_.data_.sigma.value( master_->centre(), master_->element_accessor());
706 for(i = 0; i <= ml_it_->size(); ++i) {
709 pressure_diff(i, dofs_i, ele_type_i, delta_i, dirichlet_i);
711 for (j = 0; j <= ml_it_->size(); ++j) {
712 pressure_diff(j, dofs_j, ele_type_j, delta_j, dirichlet_j);
714 double scale = -master_sigma * delta_i * delta_j / delta_0;
715 product = scale * tensor_average[ele_type_i][ele_type_j];
721 arma::vec rhs(dofs_i.size());
723 ls.
set_values( dofs_i, dofs_j, product, rhs, dirichlet_i, dirichlet_j);
734 for(
unsigned int i_side=0; i_side < ele->
n_sides(); i_side++ ) {
735 dofs[shift+i_side] = darcy_.row_4_edge[ele->
side(i_side)->
edge_idx()];
744 dofs[shift + i_side] = -dofs[shift + i_side];
745 double bc_pressure = darcy_.data_.bc_pressure.value(b_ele.
centre(), b_ele);
746 dirichlet[shift + i_side] = bc_pressure;
772 const Element * master = intersec.master_iter();
773 const Element * slave = intersec.slave_iter();
775 add_sides(master, 0, dofs, dirichlet);
776 add_sides(slave, 2, dofs, dirichlet);
803 arma::vec point_Y(1);
805 arma::vec point_2D_Y(intersec.map_to_slave(point_Y));
806 arma::vec point_1D_Y(intersec.map_to_master(point_Y));
808 arma::vec point_X(1);
810 arma::vec point_2D_X(intersec.map_to_slave(point_X));
811 arma::vec point_1D_X(intersec.map_to_master(point_X));
813 arma::mat base_2D(3, 3);
816 base_2D << 1.0 << 0.0 << -2.0 << arma::endr
817 << -1.0 << 2.0 << 2.0 << arma::endr
818 << 1.0 << -2.0 << 0.0 << arma::endr;
820 arma::mat base_1D(2, 2);
823 base_1D << 1.0 << -1.0 << arma::endr
824 << 0.0 << 1.0 << arma::endr;
832 arma::vec difference_in_Y(5);
833 arma::vec difference_in_X(5);
836 difference_in_Y.subvec(0, 2) = -base_2D * point_2D_Y;
837 difference_in_X.subvec(0, 2) = -base_2D * point_2D_X;
839 difference_in_Y.subvec(3, 4) = base_1D * point_1D_Y;
840 difference_in_X.subvec(3, 4) = base_1D * point_1D_X;
847 for (
int i = 0; i < 5; ++i) {
848 for (
int j = 0; j < 5; ++j) {
849 A(i, j) = -master_sigma * intersec.intersection_true_size() *
850 ( difference_in_Y[i] * difference_in_Y[j]
851 + difference_in_Y[i] * difference_in_X[j]/2
852 + difference_in_X[i] * difference_in_Y[j]/2
853 + difference_in_X[i] * difference_in_X[j]
862 ls.
set_values( dofs, dofs, A, rhs, dirichlet, dirichlet);
897 xprintf(
Warn,
"For BDDC is using no Schur complements.");
911 xprintf(
Err,
"Flow123d was not build with BDDCML support.\n");
917 xprintf(
Warn,
"Invalid number of Schur Complements. Using 2.");
930 ls->LinSys::set_from_input(in_rec);
938 ASSERT(err == 0,
"Error in ISCreateStride.");
952 ASSERT(err == 0,
"Error in ISCreateStride.");
973 xprintf(
Err,
"Unknown solver type. Internal error.\n");
987 DBGMSG(
"Assembly linear system\n");
989 DBGMSG(
" Data changed\n");
1002 DBGMSG(
" setup time term\n");
1013 xprintf(
PrgErr,
"Planned computation time for steady solver, but data are not changed.\n");
1056 for (
int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++ ) {
1059 int e_idx = el.
index();
1061 int elDim = el->dim();
1062 elDimMax = std::max( elDimMax, elDim );
1063 elDimMin = std::min( elDimMin, elDim );
1065 isegn.push_back( e_idx );
1073 localDofMap.insert( std::make_pair( side_row, coord ) );
1074 inet.push_back( side_row );
1081 localDofMap.insert( std::make_pair( el_row, coord ) );
1082 inet.push_back( el_row );
1086 Edge *edg=el->side(si)->edge();
1089 int edge_row =
row_4_edge[ el->side(si)->edge_idx() ];
1092 localDofMap.insert( std::make_pair( edge_row, coord ) );
1093 inet.push_back( edge_row );
1098 for (
int i_neigh = 0; i_neigh < el->n_neighs_vb; i_neigh++) {
1099 int edge_row =
row_4_edge[ el->neigh_vb[i_neigh]->edge_idx() ];
1100 arma::vec3 coord = el->neigh_vb[i_neigh]->edge()->side(0)->centre();
1102 localDofMap.insert( std::make_pair( edge_row, coord ) );
1103 inet.push_back( edge_row );
1107 nnet.push_back( nne );
1118 for (
int i = 0; i < 3; i++) {
1119 coef = coef + aniso.at(i,i);
1122 coef = conduct*coef / 3;
1125 "Zero coefficient of hydrodynamic resistance %f . \n ", coef );
1126 element_permeability.push_back( 1. / coef );
1130 int numNodeSub = localDofMap.size();
1141 for ( ; itB != localDofMap.end(); ++itB ) {
1142 isngn[ind] = itB -> first;
1145 for (
int j = 0; j < 3; j++ ) {
1146 xyz[ j*numNodeSub + ind ] = coord[j];
1151 localDofMap.clear();
1159 Global2LocalMap_ global2LocalNodeMap;
1160 for (
unsigned ind = 0; ind < isngn.size(); ++ind ) {
1161 global2LocalNodeMap.insert( std::make_pair( static_cast<unsigned>( isngn[ind] ), ind ) );
1177 for (
int iEle = 0; iEle < isegn.size(); iEle++ ) {
1178 int nne = nnet[ iEle ];
1179 for (
unsigned ien = 0; ien < nne; ien++ ) {
1181 int indGlob = inet[indInet];
1183 Global2LocalMap_::iterator pos = global2LocalNodeMap.find( indGlob );
1184 ASSERT( pos != global2LocalNodeMap.end(),
1185 "Cannot remap node index %d to local indices. \n ", indGlob );
1186 int indLoc =
static_cast<int> ( pos -> second );
1189 inet[ indInet++ ] = indLoc;
1193 int numNodes =
size;
1194 int numDofsInt =
size;
1196 int meshDim = elDimMax;
1199 bddc_ls -> load_mesh( spaceDim, numNodes, numDofsInt, inet, nnet, nndf, isegn, isngn, isngn, xyz, element_permeability, meshDim );
1371 int edge_shift[np], el_shift[np], side_shift[np];
1372 unsigned int rows_starts[np];
1380 for (i = 0; i < np; i++) {
1387 rows_starts[i] = shift;
1393 for (i = 0; i < side_n_id; i++) {
1398 for (i = 0; i < el_n_id; i++) {
1404 for (i = 0; i < edge_n_id; i++) {
1410 for (i = np - 1; i > 0; i--)
1411 rows_starts[i] -= rows_starts[i - 1];
1413 rows_ds = boost::make_shared<Distribution>(&(rows_starts[0]), PETSC_COMM_WORLD);
1425 VecCreateSeqWithArray(PETSC_COMM_SELF,1,
size,
solution,
1438 loc_idx[i++] =
row_4_el[ele.index()];
1440 for(
unsigned int i_edg=0; i_edg <
mesh_->
n_edges(); i_edg++) {
1443 ASSERT( i==
size,
"Size of array does not match number of fills.\n");
1445 ISCreateGeneral(PETSC_COMM_SELF,
size, loc_idx, PETSC_COPY_VALUES, &(is_loc));
1449 ISDestroy(&(is_loc));
1494 loc_part =
new int[init_edge_ds.lsize()];
1499 unsigned int i_edg = edg -
mesh_->
edges.begin();
1503 if (init_edge_ds.is_local(i_edg)) {
1505 loc_part[loc_i++] = el_ds->get_proc(
row_4_el[e_idx]);
1508 id_4_old[i_edg] = i_edg;
1519 loc_part =
new int[init_side_ds.lsize()];
1526 if (init_side_ds.is_local(is)) {
1528 loc_part[loc_i++] = el_ds->get_proc(
1567 int side_row, edge_row;
1577 for (
unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++) {
1579 int el_row =
row_4_el[el_4_loc[i_loc]];
1583 unsigned int nsides = el->
n_sides();
1584 for (
unsigned int i = 0; i < nsides; i++) {
1597 for (
unsigned int i_neigh = 0; i_neigh < el->
n_neighs_vb; i_neigh++) {
1605 #endif // HAVE_BDDCML
1618 unsigned int i_edg=0;
1631 const PetscInt *cols;
1637 MatGetOwnershipRange(m, &first, &last);
1638 for (
int row = first; row < last; row++) {
1639 MatGetRow(m, row, &n, &cols, PETSC_NULL);
1640 bool exists_off =
false;
1641 for (
int i = 0; i < n; i++)
1643 n_off++, exists_off =
true;
1648 MatRestoreRow(m, row, &n, &cols, PETSC_NULL);
1709 for (
unsigned int i_loc_el = 0; i_loc_el <
el_ds->
lsize(); i_loc_el++) {
1728 PetscScalar *local_diagonal;
1733 for (
unsigned int i_loc_el = 0; i_loc_el <
el_ds->
lsize(); i_loc_el++) {
1805 for (
unsigned int i_loc_el = 0; i_loc_el <
el_ds->
lsize(); i_loc_el++) {
1811 int edge_row =
row_4_edge[ele->side(i)->edge_idx()];
1837 for (
unsigned int i_loc_el = 0; i_loc_el <
el_ds->
lsize(); i_loc_el++) {
1843 int edge_row =
row_4_edge[ele->side(i)->edge_idx()];
1848 time_->
dt() / ele->n_sides(),ADD_VALUES);
1883 int i_loc, side_row, loc_edge_row, i;
1886 double new_pressure, old_pressure, time_coef;
1888 PetscScalar *loc_prev_sol;
1899 old_pressure = loc_prev_sol[loc_edge_row];
1903 time_coef = - ele->
measure() *
1907 VecSetValue(
schur0->
get_solution(), side_row, time_coef * (new_pressure - old_pressure), ADD_VALUES);
1924 for (
unsigned int i_loc = 0; i_loc <
el_ds->
lsize(); i_loc++) {
1928 values[i] = -1.0 * ele->
measure() *