18 #ifndef ASSEMBLY_LMH_HH_
19 #define ASSEMBLY_LMH_HH_
44 template <
unsigned int dim,
class TEqData>
51 static constexpr
const char *
name() {
return "Darcy_ReadInitCond_Assembly"; }
70 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
77 double init_value =
eq_fields_->init_pressure(p);
79 for (
unsigned int i=0; i<cell.
elm()->
n_sides(); i++) {
88 eq_data_->p_edge_solution.ghost_to_local_begin();
89 eq_data_->p_edge_solution.ghost_to_local_end();
90 eq_data_->p_edge_solution.local_to_ghost_begin();
91 eq_data_->p_edge_solution.local_to_ghost_end();
109 template <
template<
IntDim...>
class DimAssembly>
114 template <
unsigned int dim,
class TEqData>
123 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;
369 for (
unsigned int i=0; i<
n_dofs_; i++){
374 for (
unsigned int j=0; j<
n_dofs_; j++){
377 * scale_sides *
JxW_(p_rt);
412 for(
unsigned int side = 0; side <
eq_data_->loc_side_dofs[dim-1].size(); side++){
440 if(!
eq_data_->use_steady_assembly_)
448 for (
unsigned int i=0; i<n_sides; i++)
450 if(!
eq_data_->use_steady_assembly_)
470 eq_data_->balance_->add_source_values(
eq_data_->water_balance_idx, cell.elm().region().bulk_idx(),
480 cross_section_ = eq_fields_->cross_section(p_side);
484 side_row_ = eq_data_->loc_side_dofs[dim-1][sidx_];
485 edge_row_ = eq_data_->loc_edge_dofs[dim-1][sidx_];
491 char & switch_dirichlet = eq_data_->bc_switch_dirichlet[b_ele.
idx()];
492 if (switch_dirichlet) {
498 auto reconstr_solution = this->load_local_system(cell_side.
cell());
499 double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.
measure() * cross_section_;
501 if ( reconstr_solution[side_row_] < side_flux) {
503 switch_dirichlet = 0;
518 double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
519 double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
521 if ( solution_head > bc_pressure) {
536 eq_data_->loc_constraint_.emplace_back( bulk_local_idx_, sidx_, eq_fields_->bc_pressure(p_bdr) );
540 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
541 -b_ele.
measure() * eq_fields_->bc_robin_sigma(p_bdr) * cross_section_,
542 (-eq_fields_->bc_flux(p_bdr) - eq_fields_->bc_robin_sigma(p_bdr) * eq_fields_->bc_pressure(p_bdr)) * b_ele.
measure() * cross_section_);
544 eq_data_->is_linear=
false;
546 double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
547 double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.
measure() * cross_section_;
549 eq_data_->save_local_system_[bulk_local_idx_] = (bool) eq_data_->bc_switch_dirichlet[b_ele.
idx()];
553 if (eq_data_->save_local_system_[bulk_local_idx_] || eq_data_->force_no_neumann_bc ) {
555 eq_data_->loc_constraint_.emplace_back(bulk_local_idx_, sidx_, bc_pressure);
558 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, side_flux);
562 eq_data_->is_linear=
false;
564 double bc_pressure = eq_fields_->bc_pressure(p_bdr);
565 double bc_switch_pressure = eq_fields_->bc_switch_pressure(p_bdr);
566 double bc_flux = -eq_fields_->bc_flux(p_bdr);
567 double bc_sigma = eq_fields_->bc_robin_sigma(p_bdr);
571 double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
574 if (solution_head > bc_switch_pressure || eq_data_->force_no_neumann_bc) {
577 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
578 -b_ele.
measure() * bc_sigma * cross_section_,
579 b_ele.
measure() * cross_section_ * (bc_flux - bc_sigma * bc_pressure) );
583 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
585 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, bc_total_flux * b_ele.
measure() * cross_section_);
589 THROW( ExcBCNotSupported() );
592 eq_data_->balance_->add_flux_values(eq_data_->water_balance_idx, cell_side,
593 {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_side_dofs[dim-1][sidx_]]},
599 unsigned int size, loc_size, elm_dim;;
604 size = (elm_dim+1) + 1 + (elm_dim+1);
609 dofs.head(dh_cell.n_dofs()) = dh_cell.get_loc_dof_indices();
616 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
627 const unsigned int p = size+i;
629 const unsigned int t = dh_neighb_cell.
n_dofs() - dh_neighb_cr_cell.
n_dofs() + neighb_side.side().side_idx();
634 eq_data_->loc_system_[dh_cell.local_idx()].reset(dofs, dofs);
637 for (
DHCellSide dh_side : dh_cell.side_range()) {
638 unsigned int sidx = dh_side.side_idx();
640 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);
641 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);
669 const unsigned int tt = dh_cr_cell.
n_dofs()+i;
676 loc_schur_.reset(dofs_schur, dofs_schur);
682 for (
uint n_i=0; n_i<dh_cell.
elm()->n_neighs_vb(); ++n_i) {
684 if ( (side->elem_idx() == neighb_side.
elem_idx()) && (side->side_idx() == neighb_side.
side_idx()) )
return n_i;
699 auto ls = eq_data_->seepage_bc_systems.find(dh_cell.
elm_idx());
700 if (ls != eq_data_->seepage_bc_systems.end())
704 arma::vec schur_solution = eq_data_->p_edge_solution.get_subvec(loc_dof_vec);
706 ls->second.reconstruct_solution_schur(eq_data_->schur_offset_[dim-1], schur_solution, reconstructed_solution_);
708 unsigned int pos_in_cache = this->patch_internals_->element_cache_map_.position_in_cache(dh_cell.
elm_idx());
709 auto p = *( bulk_integral_->points(pos_in_cache).begin() );
710 postprocess_velocity_darcy(dh_cell, p, reconstructed_solution_);
712 eq_data_->bc_fluxes_reconstruted[bulk_local_idx_] =
true;
715 return reconstructed_solution_;
727 * eq_fields_->cross_section(p)
730 edge_source_term_ = edge_scale_ *
731 ( eq_fields_->water_source_density(p)
732 + eq_fields_->water_source_sigma(p)*eq_fields_->water_source_ref_pressure(p)
733 + eq_fields_->extra_source(p));
740 postprocess_velocity(dh_cell, p);
746 for (
unsigned int i=0; i<dh_cell.
elm()->n_sides(); i++) {
748 double new_pressure = eq_data_->p_edge_solution.get(loc_dof_vec[i]);
749 if( ! eq_data_->use_steady_assembly_)
751 double old_pressure = eq_data_->p_edge_solution_previous_time.get(loc_dof_vec[i]);
752 time_term_ = edge_scale_ * (eq_fields_->storativity(p) + eq_fields_->extra_storativity(p))
753 / eq_data_->time_step_ * (new_pressure - old_pressure);
755 solution[eq_data_->loc_side_dofs[dim-1][i]] += edge_source_term_ - time_term_ - edge_scale_ * eq_fields_->water_source_sigma(p)*new_pressure;
796 template <
template<
IntDim...>
class DimAssembly>
801 template <
unsigned int dim,
class TEqData>
808 static constexpr
const char *
name() {
return "Darcy_ReconstructSchur_Assembly"; }
817 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
820 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.
std::shared_ptr< CouplingIntegralAcc< dim > > create_coupling_integral(Quadrature *quad)
PatchInternals * patch_internals_
Holds shared internals data with GeneriAssembly.
std::shared_ptr< BulkIntegralAcc< dim > > create_bulk_integral(Quadrature *quad)
Quadrature * quad_low_
Quadrature used in assembling methods (dim-1).
Quadrature * quad_
Quadrature used in assembling methods.
std::shared_ptr< BoundaryIntegralAcc< dim > > create_boundary_integral(Quadrature *quad)
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.
MHMatrixAssemblyLMH(EqData *eq_data, PatchInternals *patch_internals)
Constructor.
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.
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.
ReadInitCondAssemblyLMH(EqData *eq_data, PatchInternals *patch_internals)
Constructor.
std::shared_ptr< BulkIntegralAcc< dim > > bulk_integral_
Bulk integral of assembly class.
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, PatchInternals *patch_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.
#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.