8 #ifndef SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 9 #define SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 51 template<
template<
int dim>
class Impl,
class Data>
53 return { std::make_shared<Impl<1> >(data),
54 std::make_shared<Impl<2> >(data),
55 std::make_shared<Impl<3> >(data) };
92 velocity_interpolation_quad_(dim, 0),
94 loc_system_(size(), size()),
98 fe_values_.initialize(
quad_, fe_rt_,
103 unsigned int nsides = dim+1;
104 loc_side_dofs.
resize(nsides);
105 loc_ele_dof = nsides;
106 loc_edge_dofs.resize(nsides);
107 for(
unsigned int i = 0; i < nsides; i++){
108 loc_side_dofs[i] = i;
109 loc_edge_dofs[i] = nsides + i + 1;
114 arma::umat sp(size(),size());
116 sp.submat(0, 0, nsides, nsides).ones();
123 sp.submat(0, nsides+1, nsides-1, size()-1).diag().ones();
124 sp.submat(nsides+1, 0, size()-1, nsides-1).diag().ones();
126 loc_system_.set_sparsity(sp);
131 loc_system_vb_.set_sparsity(sp);
134 mortar_assembly = std::make_shared<P0_CouplingAssembler>(ad_);
136 mortar_assembly = std::make_shared<P1_CouplingAssembler>(ad_);
155 mortar_assembly->fix_velocity(dh_cell);
163 set_dofs_and_bc(dh_cell);
165 assemble_sides(dh_cell);
166 assemble_element(dh_cell);
168 loc_system_.eliminate_solution();
169 ad_->lin_sys->set_local_system(loc_system_);
171 assembly_dim_connections(dh_cell);
173 if (ad_->balance !=
nullptr)
174 add_fluxes_in_balance_matrix(dh_cell);
177 mortar_assembly->assembly(dh_cell);
188 ngh_values_.fe_side_values_.reinit(neighb_side.
side());
189 nv = ngh_values_.fe_side_values_.normal_vector(0);
191 double value = ad_->sigma.value( ele.
centre(), ele) *
192 2*ad_->conductivity.value( ele.
centre(), ele) *
193 arma::dot(ad_->anisotropy.value( ele.
centre(), ele)*nv, nv) *
194 ad_->cross_section.value( neighb_side.
centre(), ele_higher ) *
195 ad_->cross_section.value( neighb_side.
centre(), ele_higher ) /
196 ad_->cross_section.value( ele.
centre(), ele ) *
199 loc_system_vb_.add_value(0,0, -value);
200 loc_system_vb_.add_value(0,1, value);
201 loc_system_vb_.add_value(1,0, value);
202 loc_system_vb_.add_value(1,1, -value);
215 global_dofs_.resize(dh_cell.
n_dofs());
221 loc_system_.row_dofs[loc_ele_dof] = loc_system_.col_dofs[loc_ele_dof] = global_dofs_[loc_ele_dof];
224 const unsigned int nsides = ele->
n_sides();
225 LinSys *ls = ad_->lin_sys;
227 unsigned int side_row, edge_row;
229 dirichlet_edge.resize(nsides);
230 for (
unsigned int i = 0; i < nsides; i++) {
232 side_row = loc_side_dofs[i];
233 edge_row = loc_edge_dofs[i];
234 loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = global_dofs_[side_row];
235 loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = global_dofs_[edge_row];
237 dirichlet_edge[i] = 0;
244 double cross_section = ad_->cross_section.value(ele.
centre(), ele);
249 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
250 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
251 dirichlet_edge[i] = 1;
255 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
256 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
257 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
259 dirichlet_edge[i] = 2;
260 loc_system_.add_value(edge_row, edge_row,
261 -b_ele.
measure() * bc_sigma * cross_section,
262 (bc_flux - bc_sigma * bc_pressure) * b_ele.
measure() * cross_section);
265 ad_->is_linear=
false;
268 char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
269 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
270 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
271 double side_flux = bc_flux * b_ele.
measure() * cross_section;
274 if (switch_dirichlet) {
278 ASSERT_DBG(ad_->dh_->distr()->is_local(global_dofs_[side_row]))(global_dofs_[side_row]);
279 unsigned int loc_side_row = local_dofs_[side_row];
282 if ( solution_flux < side_flux) {
284 solution_flux = side_flux;
297 ASSERT_DBG(ad_->dh_->distr()->is_local(global_dofs_[edge_row]))(global_dofs_[edge_row]);
298 unsigned int loc_edge_row = local_dofs_[edge_row];
301 if ( solution_head > bc_pressure) {
303 solution_head = bc_pressure;
310 if (switch_dirichlet || ad_->force_no_neumann_bc ) {
312 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
313 dirichlet_edge[i] = 1;
316 loc_system_.add_value(edge_row, side_flux);
320 ad_->is_linear=
false;
322 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
323 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
324 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
325 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
326 ASSERT_DBG(ad_->dh_->distr()->is_local(global_dofs_[edge_row]))(global_dofs_[edge_row]);
327 unsigned int loc_edge_row = local_dofs_[edge_row];
331 if (solution_head > bc_switch_pressure || ad_->force_no_neumann_bc) {
334 loc_system_.add_value(edge_row, edge_row,
335 -b_ele.
measure() * bc_sigma * cross_section,
336 b_ele.
measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
340 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
342 loc_system_.add_value(edge_row, bc_total_flux * b_ele.
measure() * cross_section);
349 loc_system_.add_value(side_row, edge_row, 1.0);
350 loc_system_.add_value(edge_row, side_row, 1.0);
357 double cs = ad_->cross_section.value(ele.
centre(), ele);
358 double conduct = ad_->conductivity.value(ele.
centre(), ele);
359 double scale = 1 / cs /conduct;
361 assemble_sides_scale(dh_cell, scale);
369 fe_values_.reinit(ele);
370 unsigned int ndofs = fe_values_.n_dofs();
371 unsigned int qsize = fe_values_.n_points();
372 auto velocity = fe_values_.vector_view(0);
374 for (
unsigned int k=0; k<qsize; k++)
375 for (
unsigned int i=0; i<ndofs; i++){
377 arma::dot(gravity_vec,velocity.value(i,k))
379 loc_system_.add_value(i, rhs_val);
381 for (
unsigned int j=0; j<ndofs; j++){
383 arma::dot(velocity.value(i,k),
384 (ad_->anisotropy.value(ele.
centre(), ele )).i()
385 * velocity.value(j,k))
386 * scale * fe_values_.JxW(k);
388 loc_system_.add_value(i, j, mat_val);
401 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
402 const arma::mat& local_matrix = loc_system_.get_matrix();
403 for(
unsigned int i=0; i < ndofs; i++) {
404 double val_side = local_matrix(i,i);
405 double val_edge = -1./local_matrix(i,i);
407 unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
408 unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
409 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
410 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
419 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
420 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
421 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
424 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
427 diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
434 auto ele = dh_cell.
elm();
446 loc_system_vb_.reset();
447 loc_system_vb_.row_dofs[0] = loc_system_vb_.col_dofs[0] = global_dofs_[loc_ele_dof];
453 higher_dim_dofs.resize(dh_neighb_cell.
n_dofs());
459 const unsigned int t = dh_neighb_cell.
n_dofs() - (dim+2) + neighb_side.side().side_idx();
460 loc_system_vb_.row_dofs[1] = loc_system_vb_.col_dofs[1] = higher_dim_dofs[t];
462 assembly_local_vb(ele, neighb_side);
464 loc_system_vb_.eliminate_solution();
465 ad_->lin_sys->set_local_system(loc_system_vb_);
468 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
469 int ind = loc_system_vb_.row_dofs[1];
471 double new_val = loc_system_vb_.get_matrix()(0,0);
472 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
481 unsigned int sidx = dh_side.side_idx();
482 if (dh_side.side().is_boundary()) {
483 ad_->balance->add_flux_values(ad_->water_balance_idx, dh_side,
484 {local_dofs_[loc_side_dofs[sidx]]},
Range< DHCellSide > side_range() const
Returns range of cell sides.
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
virtual void assemble(const DHCellAccessor &dh_cell)=0
std::vector< LongIdx > global_dofs_
QGauss velocity_interpolation_quad_
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
virtual void fix_velocity(const DHCellAccessor &dh_cell)=0
void assembly_dim_connections(const DHCellAccessor &dh_cell)
void assemble_sides_scale(const DHCellAccessor &dh_cell, double scale)
void assemble(const DHCellAccessor &dh_cell) override
unsigned int get_dof_indices(std::vector< LongIdx > &indices) const
Fill vector of the global indices of dofs associated to the cell.
Wrappers for linear systems based on MPIAIJ and MATIS format.
static unsigned int size()
unsigned int dim() const
Return dimension of element appropriate to cell.
Cell accessor allow iterate over DOF handler cells.
void set_dofs_and_bc(const DHCellAccessor &dh_cell)
Class FEValues calculates finite element data on the actual cells such as shape function values...
LocalSystem loc_system_vb_
virtual void assemble_reconstruct(const DHCellAccessor &dh_cell)=0
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
void resize(unsigned int n_q_points)
Modify the number of quadrature points.
SideIter side(const unsigned int loc_index)
std::vector< unsigned int > loc_edge_dofs
std::vector< unsigned int > dirichlet_edge
unsigned int n_dofs() const
Return number of dofs on given cell.
Side side() const
Return Side of given cell and side_idx.
FEValues< 3 > velocity_interpolation_fv_
static constexpr bool value
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtrMH
Symmetric Gauss-Legendre quadrature formulae on simplices.
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
arma::vec::fixed< spacedim > centre() const
Computes the barycenter.
Transformed quadrature points.
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
void assemble_sides(const DHCellAccessor &dh_cell)
ArmaMat< double, N, M > mat
virtual void update_water_content(const DHCellAccessor &dh_cell)=0
Updates water content in Richards.
bool is_boundary() const
Returns true for side on the boundary.
double * get_solution_array()
Raviart-Thomas element of order 0.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
ElementAccessor< 3 > element() const
unsigned int n_sides() const
RangeConvert< DHNeighbSide, DHCellSide > neighb_sides() const
Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension...
FEValues< 3 > fe_side_values_
double measure() const
Computes the measure of the element.
Shape function gradients.
void update_water_content(const DHCellAccessor &) override
Updates water content in Richards.
std::shared_ptr< MortarAssemblyBase > mortar_assembly
NeighSideValues< (dim< 3)?dim:2 > ngh_values_
Definitions of particular quadrature rules on simplices.
void assemble_reconstruct(const DHCellAccessor &) override
std::vector< unsigned int > loc_side_dofs
void add_fluxes_in_balance_matrix(const DHCellAccessor &dh_cell)
mixed-hybrid model of linear Darcy flow, possibly unsteady.
static MultidimAssembly create(Data data)
void assemble_element(const DHCellAccessor &)
void assembly_local_vb(ElementAccessor< 3 > ele, DHCellSide neighb_side)
FE_P_disc< dim+1 > fe_p_disc_
unsigned int n_neighs_vb() const
Return number of neighbours.
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
arma::Col< Idx > LocDofVec
void fix_velocity(const DHCellAccessor &dh_cell) override
Quadrature * quad_
Quadrature used in assembling methods.
Definitions of Raviart-Thomas finite elements.
Side accessor allows to iterate over sides of DOF handler cell.
ElementAccessor< 3 > element_accessor()
Solver based on Multilevel BDDC - using corresponding class of OpenFTL package.
Transformed quadrature weights.
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
arma::vec3 centre() const
Side centre.