18 #ifndef ASSEMBLY_LMH_HH_
19 #define ASSEMBLY_LMH_HH_
46 template <
unsigned int dim,
class TEqData>
53 static constexpr
const char *
name() {
return "Darcy_ReadInitCond_Assembly"; }
72 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
79 double init_value =
eq_fields_->init_pressure(p);
81 for (
unsigned int i=0; i<cell.
elm()->
n_sides(); i++) {
90 eq_data_->p_edge_solution.ghost_to_local_begin();
91 eq_data_->p_edge_solution.ghost_to_local_end();
92 eq_data_->p_edge_solution.local_to_ghost_begin();
93 eq_data_->p_edge_solution.local_to_ghost_end();
111 template <
template<
IntDim...>
class DimAssembly>
116 template <
unsigned int dim,
class TEqData>
125 static constexpr
const char *
name() {
return "Darcy_MHMatrix_Assembly"; }
185 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
204 ASSERT_EQ(cell_side.
dim(), dim).error(
"Dimension of element mismatch!");
227 if (dim == 3)
return;
228 ASSERT_EQ(cell_lower_dim.
dim(), dim).error(
"Dimension of element mismatch!");
230 unsigned int neigh_idx =
ngh_idx(cell_lower_dim, neighb_side);
231 unsigned int loc_dof_higher = (2*(cell_lower_dim.
dim()+1) + 1) + neigh_idx;
236 auto p_low = p_high.lower_dim(cell_lower_dim);
296 std::sort(
eq_data_->loc_constraint_.begin(),
eq_data_->loc_constraint_.end());
297 eq_data_->loc_constraint_.emplace_back(
uint(-1), 0, 0.0);
298 unsigned int i_constr = 0;
301 while (
eq_data_->loc_constraint_[i_constr].i_element() == dh_cell.local_idx()) {
305 eq_data_->loc_system_[dh_cell.local_idx()].compute_schur_complement(
306 eq_data_->schur_offset_[dh_cell.dim()-1], this->loc_schur_,
true);
309 if (
eq_data_->save_local_system_[dh_cell.local_idx()])
310 eq_data_->seepage_bc_systems[dh_cell.elm_idx()] =
eq_data_->loc_system_[dh_cell.local_idx()];
331 this->
eq_data_->full_solution.zero_entries();
332 this->
eq_data_->p_edge_solution.local_to_ghost_begin();
333 this->
eq_data_->p_edge_solution.local_to_ghost_end();
346 schur_solution, this->reconstructed_solution_);
350 this->
eq_data_->full_solution.set_subvec(this->
eq_data_->loc_system_[this->bulk_local_idx_].row_dofs.head(
351 this->eq_data_->schur_offset_[dh_cell.dim()-1]), this->reconstructed_solution_);
352 this->
eq_data_->full_solution.set_subvec(this->
eq_data_->loc_system_[this->bulk_local_idx_].row_dofs.tail(
353 this->loc_schur_.row_dofs.n_elem), schur_solution);
356 this->
eq_data_->full_solution.local_to_ghost_begin();
357 this->
eq_data_->full_solution.local_to_ghost_end();
365 double scale_sides = 1 /
eq_fields_->cross_section(p) / conductivity;
368 for (
unsigned int i=0; i<
n_dofs_; i++){
373 for (
unsigned int j=0; j<
n_dofs_; j++){
378 * scale_sides *
JxW_(p_rt);
413 for(
unsigned int side = 0; side <
eq_data_->loc_side_dofs[dim-1].size(); side++){
438 if(!
eq_data_->use_steady_assembly_)
446 for (
unsigned int i=0; i<n_sides; i++)
448 if(!
eq_data_->use_steady_assembly_)
468 eq_data_->balance_->add_source_values(
eq_data_->water_balance_idx, cell.elm().region().bulk_idx(),
478 cross_section_ = eq_fields_->cross_section(p_side);
482 side_row_ = eq_data_->loc_side_dofs[dim-1][sidx_];
483 edge_row_ = eq_data_->loc_edge_dofs[dim-1][sidx_];
489 char & switch_dirichlet = eq_data_->bc_switch_dirichlet[b_ele.
idx()];
490 if (switch_dirichlet) {
496 auto reconstr_solution = this->load_local_system(cell_side.
cell());
497 double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.
measure() * cross_section_;
499 if ( reconstr_solution[side_row_] < side_flux) {
501 switch_dirichlet = 0;
516 double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
517 double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
519 if ( solution_head > bc_pressure) {
534 eq_data_->loc_constraint_.emplace_back( bulk_local_idx_, sidx_, eq_fields_->bc_pressure(p_bdr) );
538 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
539 -b_ele.
measure() * eq_fields_->bc_robin_sigma(p_bdr) * cross_section_,
540 (-eq_fields_->bc_flux(p_bdr) - eq_fields_->bc_robin_sigma(p_bdr) * eq_fields_->bc_pressure(p_bdr)) * b_ele.
measure() * cross_section_);
542 eq_data_->is_linear=
false;
544 double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
545 double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.
measure() * cross_section_;
547 eq_data_->save_local_system_[bulk_local_idx_] = (bool) eq_data_->bc_switch_dirichlet[b_ele.
idx()];
551 if (eq_data_->save_local_system_[bulk_local_idx_] || eq_data_->force_no_neumann_bc ) {
553 eq_data_->loc_constraint_.emplace_back(bulk_local_idx_, sidx_, bc_pressure);
556 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, side_flux);
560 eq_data_->is_linear=
false;
562 double bc_pressure = eq_fields_->bc_pressure(p_bdr);
563 double bc_switch_pressure = eq_fields_->bc_switch_pressure(p_bdr);
564 double bc_flux = -eq_fields_->bc_flux(p_bdr);
565 double bc_sigma = eq_fields_->bc_robin_sigma(p_bdr);
569 double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
572 if (solution_head > bc_switch_pressure || eq_data_->force_no_neumann_bc) {
575 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
576 -b_ele.
measure() * bc_sigma * cross_section_,
577 b_ele.
measure() * cross_section_ * (bc_flux - bc_sigma * bc_pressure) );
581 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
583 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, bc_total_flux * b_ele.
measure() * cross_section_);
587 THROW( ExcBCNotSupported() );
590 eq_data_->balance_->add_flux_values(eq_data_->water_balance_idx, cell_side,
591 {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_side_dofs[dim-1][sidx_]]},
597 unsigned int size, loc_size, elm_dim;;
602 size = (elm_dim+1) + 1 + (elm_dim+1);
607 dofs.head(dh_cell.n_dofs()) = dh_cell.get_loc_dof_indices();
614 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
625 const unsigned int p = size+i;
627 const unsigned int t = dh_neighb_cell.
n_dofs() - dh_neighb_cr_cell.
n_dofs() + neighb_side.side().side_idx();
632 eq_data_->loc_system_[dh_cell.local_idx()].reset(dofs, dofs);
635 for (
DHCellSide dh_side : dh_cell.side_range()) {
636 unsigned int sidx = dh_side.side_idx();
638 eq_data_->loc_system_[dh_cell.local_idx()].add_value(eq_data_->loc_side_dofs[elm_dim-1][sidx], eq_data_->loc_edge_dofs[elm_dim-1][sidx], 1.0);
639 eq_data_->loc_system_[dh_cell.local_idx()].add_value(eq_data_->loc_edge_dofs[elm_dim-1][sidx], eq_data_->loc_side_dofs[elm_dim-1][sidx], 1.0);
667 const unsigned int tt = dh_cr_cell.
n_dofs()+i;
674 loc_schur_.reset(dofs_schur, dofs_schur);
680 for (
uint n_i=0; n_i<dh_cell.
elm()->n_neighs_vb(); ++n_i) {
682 if ( (side->elem_idx() == neighb_side.
elem_idx()) && (side->side_idx() == neighb_side.
side_idx()) )
return n_i;
697 auto ls = eq_data_->seepage_bc_systems.find(dh_cell.
elm_idx());
698 if (ls != eq_data_->seepage_bc_systems.end())
702 arma::vec schur_solution = eq_data_->p_edge_solution.get_subvec(loc_dof_vec);
704 ls->second.reconstruct_solution_schur(eq_data_->schur_offset_[dim-1], schur_solution, reconstructed_solution_);
706 unsigned int pos_in_cache = this->asm_internals_->element_cache_map_.position_in_cache(dh_cell.
elm_idx());
707 auto p = *( bulk_integral_->points(pos_in_cache).begin() );
708 postprocess_velocity_darcy(dh_cell, p, reconstructed_solution_);
710 eq_data_->bc_fluxes_reconstruted[bulk_local_idx_] =
true;
713 return reconstructed_solution_;
725 * eq_fields_->cross_section(p)
728 edge_source_term_ = edge_scale_ *
729 ( eq_fields_->water_source_density(p)
730 + eq_fields_->extra_source(p));
737 postprocess_velocity(dh_cell, p);
743 for (
unsigned int i=0; i<dh_cell.
elm()->n_sides(); i++) {
745 if( ! eq_data_->use_steady_assembly_)
747 double new_pressure = eq_data_->p_edge_solution.get(loc_dof_vec[i]);
748 double old_pressure = eq_data_->p_edge_solution_previous_time.get(loc_dof_vec[i]);
749 time_term_ = edge_scale_ * (eq_fields_->storativity(p) + eq_fields_->extra_storativity(p))
750 / eq_data_->time_step_ * (new_pressure - old_pressure);
752 solution[eq_data_->loc_side_dofs[dim-1][i]] += edge_source_term_ - time_term_;
793 template <
template<
IntDim...>
class DimAssembly>
798 template <
unsigned int dim,
class TEqData>
805 static constexpr
const char *
name() {
return "Darcy_ReconstructSchur_Assembly"; }
814 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
817 auto p = *( this->
bulk_integral_->points(element_patch_idx).begin() );
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Quadrature * quad_
Quadrature used in assembling methods.
std::shared_ptr< CouplingIntegralAcc< dim > > create_coupling_integral(Quadrature *quad)
AssemblyInternals * asm_internals_
Holds shared internals data with GeneriAssembly.
std::shared_ptr< BoundaryIntegralAcc< dim > > create_boundary_integral(Quadrature *quad)
std::shared_ptr< BulkIntegralAcc< dim > > create_bulk_integral(Quadrature *quad)
Quadrature * quad_low_
Quadrature used in assembling methods (dim-1).
Point accessor allow iterate over quadrature points of given side defined in local element coordinate...
ElementAccessor< 3 > element_accessor()
Base point accessor class.
Cell accessor allow iterate over DOF handler cells.
unsigned int n_dofs() const
Return number of dofs on given cell.
RangeConvert< DHNeighbSide, DHCellSide > neighb_sides() const
Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension.
bool is_own() const
Return true if accessor represents own element (false for ghost element)
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
DHCellAccessor cell_with_other_dh(const DOFHandlerMultiDim *dh) const
Create new accessor with same local idx and given DOF handler. Actual and given DOF handler must be c...
unsigned int dim() const
Return dimension of element appropriate to cell.
unsigned int elm_idx() const
Return serial idx to element of loc_ele_idx_.
ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
unsigned int local_idx() const
Return local index to element (index of DOF handler).
Side accessor allows to iterate over sides of DOF handler cell.
unsigned int elem_idx() const
Side side() const
Return Side of given cell and side_idx.
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
unsigned int dim() const
Return dimension of element appropriate to the side.
unsigned int side_idx() const
unsigned int n_sides() const
Returns number of sides aligned with the edge.
double measure() const
Computes the measure of the element.
SideIter side(const unsigned int loc_index)
unsigned int idx() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
const Element * element() const
unsigned int n_neighs_vb() const
Return number of neighbours.
unsigned int n_sides() const
Compound finite element on dim dimensional simplex.
std::vector< unsigned int > fe_dofs(unsigned int fe_index)
Return dof indices belonging to given sub-FE.
Container for various descendants of FieldCommonBase.
Generic class of assemblation.
void set_solution(uint loc_dof, double solution, double diag=0.0)
Set the position and value of known solution. E.g. Dirichlet boundary condition.
void eliminate_solution()
double time_term_rhs_
Variables used in compute time term (unsteady)
void asm_sides(BulkPoint &p, double conductivity, unsigned int element_patch_idx)
Part of cell_integral method, common in all descendants.
unsigned int n_dofs_
Number of DOFs of fe_rt component.
arma::vec load_local_system(const DHCellAccessor &dh_cell)
unsigned int edge_row_
Helper indices in boundary assembly.
void begin_mh_matrix()
Common code of begin method of MH matrix assembly (Darcy and Richards)
void end_reconstruct_schur()
Common code of end method of Reconstruct Schur assembly (Darcy and Richards)
void begin_reconstruct_schur()
Common code of begin method of Reconstruct Schur assembly (Darcy and Richards)
virtual ~MHMatrixAssemblyLMH()
Destructor.
FieldSet used_fields_
Sub field set contains fields used in calculation.
TEqData::EqFields EqFields
void set_dofs()
Precompute loc_system and loc_schur data members.
unsigned int bulk_local_idx_
Local idx of bulk element.
void begin() override
Implements AssemblyBase::begin.
ElQ< Vector > normal_join_
void postprocess_velocity_darcy(const DHCellAccessor &dh_cell, BulkPoint &p, arma::vec &solution)
Postprocess velocity during loading of local system and after calculating of cell integral.
void initialize()
Initialize auxiliary vectors and other data members.
arma::vec reconstructed_solution_
Vector for reconstructed solution (velocity and pressure on element) from Schur complement.
static constexpr const char * name()
void set_loc_schur(const DHCellAccessor dh_cr_cell)
Precompute loc_schur data member of given cell.
double cross_section_
Precomputed cross-section value.
EqFields * eq_fields_
Data objects shared with DarcyFlow.
void boundary_side_integral_in(DHCellSide cell_side, const ElementAccessor< 3 > &b_ele, BulkPoint &p_bdr)
QGauss quad_rt_
Assembly volume integrals.
void asm_element()
Part of cell_integral method, common in all descendants.
DarcyLMH::EqFields::BC_Type type_
Type of boundary condition.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
double source_term_
Variables used in compute lumped source.
void end() override
Implements AssemblyBase::end.
std::shared_ptr< CouplingIntegralAcc< dim > > coupling_integral_
Coupling integral of assembly class.
void asm_source_term_darcy(const DHCellAccessor &cell, BulkPoint &p)
Part of cell_integral method, specialized in Darcy equation.
arma::vec3 nv_
Normal vector.
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
void boundary_side_integral(DHCellSide cell_side)
DECLARE_EXCEPTION(ExcBCNotSupported,<< "BC type not supported.\n")
double ngh_value_
Precomputed ngh value.
unsigned int ngh_idx(DHCellAccessor &dh_cell, DHCellSide &neighb_side)
Temporary method find neighbour index in higher-dim cell.
FeQ< Scalar > JxW_
Following data members represent Element quantities and FE quantities.
void end_mh_matrix()
Common code of end method of MH matrix assembly (Darcy and Richards)
std::shared_ptr< BulkIntegralAcc< dim > > bulk_integral_
Bulk integral of assembly class.
void use_dirichlet_switch(DHCellSide &cell_side, const ElementAccessor< 3 > &b_ele, BulkPoint &p_bdr)
Update BC switch dirichlet in MH matrix assembly if BC type is seepage.
MHMatrixAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
std::shared_ptr< BoundaryIntegralAcc< dim > > bdr_integral_
Boundary integral of assembly class.
FeQArray< Vector > velocity_
void precompute_boundary_side(DHCellSide &cell_side, BoundaryPoint &p_side, BulkPoint &p_bdr)
Precompute values used in boundary side integral on given DHCellSide.
void postprocess_velocity(const DHCellAccessor &dh_cell, BulkPoint &p)
std::shared_ptr< BulkIntegralAcc< dim > > asm_sides_integral_
Bulk integral defined on quadrature of higher order.
unsigned int n_dofs() const
Returns the number of shape functions.
Symmetric Gauss-Legendre quadrature formulae on simplices.
static constexpr const char * name()
void initialize()
Initialize auxiliary vectors and other data members.
virtual ~ReadInitCondAssemblyLMH()
Destructor.
FieldSet used_fields_
Sub field set contains fields used in calculation.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
std::shared_ptr< BulkIntegralAcc< dim > > bulk_integral_
Bulk integral of assembly class.
ReadInitCondAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
LocDofVec l_indices_
Vector of pre-computed local DOF indices.
EqFields * eq_fields_
Data objects shared with Flow equation.
void end() override
Implements AssemblyBase::end.
TEqData::EqFields EqFields
ReconstructSchurAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
void dimjoin_intergral(FMT_UNUSED DHCellAccessor cell_lower_dim, FMT_UNUSED DHCellSide neighb_side)
static constexpr const char * name()
void begin() override
Implements AssemblyBase::begin.
void boundary_side_integral(FMT_UNUSED DHCellSide cell_side)
Assembles between boundary element and corresponding side on bulk element.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Integral over element.
void end() override
Implements AssemblyBase::end.
TEqData::EqFields EqFields
Edge edge() const
Returns pointer to the edge connected to the side.
Lumped mixed-hybrid model of linear Darcy flow, possibly unsteady.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Definitions of Raviart-Thomas finite elements.
Class FESystem for compound finite elements.
Class FEValues calculates finite element data on the actual cells such as shape function values,...
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
arma::Col< IntIdx > LocDofVec
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
unsigned int IntDim
A dimension index type.
Store finite element reinit functions.
Definitions of particular quadrature rules on simplices.
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
Holds common data shared between GenericAssemblz and Assembly<dim> classes.
PatchFEValues< 3 > fe_values_
Common FEValues object over all dimensions.