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"; }
183 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
202 ASSERT_EQ(cell_side.
dim(), dim).error(
"Dimension of element mismatch!");
225 if (dim == 3)
return;
226 ASSERT_EQ(cell_lower_dim.
dim(), dim).error(
"Dimension of element mismatch!");
228 unsigned int neigh_idx =
ngh_idx(cell_lower_dim, neighb_side);
229 unsigned int loc_dof_higher = (2*(cell_lower_dim.
dim()+1) + 1) + neigh_idx;
234 auto p_low = p_high.lower_dim(cell_lower_dim);
294 std::sort(
eq_data_->loc_constraint_.begin(),
eq_data_->loc_constraint_.end());
295 eq_data_->loc_constraint_.emplace_back(
uint(-1), 0, 0.0);
296 unsigned int i_constr = 0;
299 while (
eq_data_->loc_constraint_[i_constr].i_element() == dh_cell.local_idx()) {
303 eq_data_->loc_system_[dh_cell.local_idx()].compute_schur_complement(
304 eq_data_->schur_offset_[dh_cell.dim()-1], this->loc_schur_,
true);
307 if (
eq_data_->save_local_system_[dh_cell.local_idx()])
308 eq_data_->seepage_bc_systems[dh_cell.elm_idx()] =
eq_data_->loc_system_[dh_cell.local_idx()];
329 this->
eq_data_->full_solution.zero_entries();
330 this->
eq_data_->p_edge_solution.local_to_ghost_begin();
331 this->
eq_data_->p_edge_solution.local_to_ghost_end();
344 schur_solution, this->reconstructed_solution_);
348 this->
eq_data_->full_solution.set_subvec(this->
eq_data_->loc_system_[this->bulk_local_idx_].row_dofs.head(
349 this->eq_data_->schur_offset_[dh_cell.dim()-1]), this->reconstructed_solution_);
350 this->
eq_data_->full_solution.set_subvec(this->
eq_data_->loc_system_[this->bulk_local_idx_].row_dofs.tail(
351 this->loc_schur_.row_dofs.n_elem), schur_solution);
354 this->
eq_data_->full_solution.local_to_ghost_begin();
355 this->
eq_data_->full_solution.local_to_ghost_end();
363 double scale_sides = 1 /
eq_fields_->cross_section(p) / conductivity;
367 for (
unsigned int i=0; i<
n_dofs_; i++){
372 for (
unsigned int j=0; j<
n_dofs_; j++){
375 * scale_sides *
JxW_(p_rt);
410 for(
unsigned int side = 0; side <
eq_data_->loc_side_dofs[dim-1].size(); side++){
435 if(!
eq_data_->use_steady_assembly_)
443 for (
unsigned int i=0; i<n_sides; i++)
445 if(!
eq_data_->use_steady_assembly_)
465 eq_data_->balance_->add_source_values(
eq_data_->water_balance_idx, cell.elm().region().bulk_idx(),
475 cross_section_ = eq_fields_->cross_section(p_side);
479 side_row_ = eq_data_->loc_side_dofs[dim-1][sidx_];
480 edge_row_ = eq_data_->loc_edge_dofs[dim-1][sidx_];
486 char & switch_dirichlet = eq_data_->bc_switch_dirichlet[b_ele.
idx()];
487 if (switch_dirichlet) {
493 auto reconstr_solution = this->load_local_system(cell_side.
cell());
494 double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.
measure() * cross_section_;
496 if ( reconstr_solution[side_row_] < side_flux) {
498 switch_dirichlet = 0;
513 double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
514 double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
516 if ( solution_head > bc_pressure) {
531 eq_data_->loc_constraint_.emplace_back( bulk_local_idx_, sidx_, eq_fields_->bc_pressure(p_bdr) );
535 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
536 -b_ele.
measure() * eq_fields_->bc_robin_sigma(p_bdr) * cross_section_,
537 (-eq_fields_->bc_flux(p_bdr) - eq_fields_->bc_robin_sigma(p_bdr) * eq_fields_->bc_pressure(p_bdr)) * b_ele.
measure() * cross_section_);
539 eq_data_->is_linear=
false;
541 double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
542 double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.
measure() * cross_section_;
544 eq_data_->save_local_system_[bulk_local_idx_] = (bool) eq_data_->bc_switch_dirichlet[b_ele.
idx()];
548 if (eq_data_->save_local_system_[bulk_local_idx_] || eq_data_->force_no_neumann_bc ) {
550 eq_data_->loc_constraint_.emplace_back(bulk_local_idx_, sidx_, bc_pressure);
553 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, side_flux);
557 eq_data_->is_linear=
false;
559 double bc_pressure = eq_fields_->bc_pressure(p_bdr);
560 double bc_switch_pressure = eq_fields_->bc_switch_pressure(p_bdr);
561 double bc_flux = -eq_fields_->bc_flux(p_bdr);
562 double bc_sigma = eq_fields_->bc_robin_sigma(p_bdr);
566 double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
569 if (solution_head > bc_switch_pressure || eq_data_->force_no_neumann_bc) {
572 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
573 -b_ele.
measure() * bc_sigma * cross_section_,
574 b_ele.
measure() * cross_section_ * (bc_flux - bc_sigma * bc_pressure) );
578 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
580 eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, bc_total_flux * b_ele.
measure() * cross_section_);
584 THROW( ExcBCNotSupported() );
587 eq_data_->balance_->add_flux_values(eq_data_->water_balance_idx, cell_side,
588 {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_side_dofs[dim-1][sidx_]]},
594 unsigned int size, loc_size, elm_dim;;
599 size = (elm_dim+1) + 1 + (elm_dim+1);
604 dofs.head(dh_cell.n_dofs()) = dh_cell.get_loc_dof_indices();
611 for (
DHCellSide neighb_side : dh_cell.neighb_sides() ) {
622 const unsigned int p = size+i;
624 const unsigned int t = dh_neighb_cell.
n_dofs() - dh_neighb_cr_cell.
n_dofs() + neighb_side.side().side_idx();
629 eq_data_->loc_system_[dh_cell.local_idx()].reset(dofs, dofs);
632 for (
DHCellSide dh_side : dh_cell.side_range()) {
633 unsigned int sidx = dh_side.side_idx();
635 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);
636 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);
664 const unsigned int tt = dh_cr_cell.
n_dofs()+i;
671 loc_schur_.reset(dofs_schur, dofs_schur);
677 for (
uint n_i=0; n_i<dh_cell.
elm()->n_neighs_vb(); ++n_i) {
679 if ( (side->elem_idx() == neighb_side.
elem_idx()) && (side->side_idx() == neighb_side.
side_idx()) )
return n_i;
694 auto ls = eq_data_->seepage_bc_systems.find(dh_cell.
elm_idx());
695 if (ls != eq_data_->seepage_bc_systems.end())
699 arma::vec schur_solution = eq_data_->p_edge_solution.get_subvec(loc_dof_vec);
701 ls->second.reconstruct_solution_schur(eq_data_->schur_offset_[dim-1], schur_solution, reconstructed_solution_);
703 unsigned int pos_in_cache = this->asm_internals_->element_cache_map_.position_in_cache(dh_cell.
elm_idx());
704 auto p = *( bulk_integral_->points(pos_in_cache).begin() );
705 postprocess_velocity_darcy(dh_cell, p, reconstructed_solution_);
707 eq_data_->bc_fluxes_reconstruted[bulk_local_idx_] =
true;
710 return reconstructed_solution_;
722 * eq_fields_->cross_section(p)
725 edge_source_term_ = edge_scale_ *
726 ( eq_fields_->water_source_density(p)
727 + eq_fields_->extra_source(p));
734 postprocess_velocity(dh_cell, p);
740 for (
unsigned int i=0; i<dh_cell.
elm()->n_sides(); i++) {
742 if( ! eq_data_->use_steady_assembly_)
744 double new_pressure = eq_data_->p_edge_solution.get(loc_dof_vec[i]);
745 double old_pressure = eq_data_->p_edge_solution_previous_time.get(loc_dof_vec[i]);
746 time_term_ = edge_scale_ * (eq_fields_->storativity(p) + eq_fields_->extra_storativity(p))
747 / eq_data_->time_step_ * (new_pressure - old_pressure);
749 solution[eq_data_->loc_side_dofs[dim-1][i]] += edge_source_term_ - time_term_;
790 template <
template<
IntDim...>
class DimAssembly>
795 template <
unsigned int dim,
class TEqData>
802 static constexpr
const char *
name() {
return "Darcy_ReconstructSchur_Assembly"; }
811 ASSERT_EQ(cell.
dim(), dim).error(
"Dimension of element mismatch!");
814 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)
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.
AssemblyInternals * asm_internals_
Holds shared internals data with GeneriAssembly.
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.
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.
#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.