8 #ifndef SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 9 #define SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 53 template<
template<
int dim>
class Impl,
class Data>
55 return { std::make_shared<Impl<1> >(data),
56 std::make_shared<Impl<2> >(data),
57 std::make_shared<Impl<3> >(data) };
94 velocity_interpolation_quad_(dim, 0),
96 loc_system_(size(), size()),
100 fe_values_.initialize(
quad_, fe_rt_,
105 unsigned int nsides = dim+1;
106 loc_side_dofs.
resize(nsides);
107 loc_ele_dof = nsides;
108 loc_edge_dofs.resize(nsides);
109 for(
unsigned int i = 0; i < nsides; i++){
110 loc_side_dofs[i] = i;
111 loc_edge_dofs[i] = nsides + i + 1;
116 arma::umat sp(size(),size());
118 sp.submat(0, 0, nsides, nsides).ones();
125 sp.submat(0, nsides+1, nsides-1, size()-1).diag().ones();
126 sp.submat(nsides+1, 0, size()-1, nsides-1).diag().ones();
128 loc_system_.set_sparsity(sp);
133 loc_system_vb_.set_sparsity(sp);
136 mortar_assembly = std::make_shared<P0_CouplingAssembler>(ad_);
138 mortar_assembly = std::make_shared<P1_CouplingAssembler>(ad_);
157 mortar_assembly->fix_velocity(dh_cell);
165 set_dofs_and_bc(dh_cell);
167 assemble_sides(dh_cell);
168 assemble_element(dh_cell);
170 loc_system_.eliminate_solution();
171 ad_->lin_sys->set_local_system(loc_system_);
173 assembly_dim_connections(dh_cell);
175 if (ad_->balance !=
nullptr)
176 add_fluxes_in_balance_matrix(dh_cell);
179 mortar_assembly->assembly(dh_cell);
190 ngh_values_.fe_side_values_.reinit(neighb_side.
side());
191 nv = ngh_values_.fe_side_values_.normal_vector(0);
193 double value = ad_->sigma.value( ele.
centre(), ele) *
194 2*ad_->conductivity.value( ele.
centre(), ele) *
195 arma::dot(ad_->anisotropy.value( ele.
centre(), ele)*nv, nv) *
196 ad_->cross_section.value( neighb_side.
centre(), ele_higher ) *
197 ad_->cross_section.value( neighb_side.
centre(), ele_higher ) /
198 ad_->cross_section.value( ele.
centre(), ele ) *
201 loc_system_vb_.add_value(0,0, -value);
202 loc_system_vb_.add_value(0,1, value);
203 loc_system_vb_.add_value(1,0, value);
204 loc_system_vb_.add_value(1,1, -value);
217 global_dofs_.resize(dh_cell.
n_dofs());
223 loc_system_.row_dofs[loc_ele_dof] = loc_system_.col_dofs[loc_ele_dof] = global_dofs_[loc_ele_dof];
226 const unsigned int nsides = ele->
n_sides();
227 LinSys *ls = ad_->lin_sys;
229 unsigned int side_row, edge_row;
231 dirichlet_edge.resize(nsides);
232 for (
unsigned int i = 0; i < nsides; i++) {
234 side_row = loc_side_dofs[i];
235 edge_row = loc_edge_dofs[i];
236 loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = global_dofs_[side_row];
237 loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = global_dofs_[edge_row];
239 dirichlet_edge[i] = 0;
246 double cross_section = ad_->cross_section.value(ele.
centre(), ele);
251 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
252 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
253 dirichlet_edge[i] = 1;
257 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
258 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
259 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
261 dirichlet_edge[i] = 2;
262 loc_system_.add_value(edge_row, edge_row,
263 -b_ele.
measure() * bc_sigma * cross_section,
264 (bc_flux - bc_sigma * bc_pressure) * b_ele.
measure() * cross_section);
267 ad_->is_linear=
false;
270 char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
271 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
272 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
273 double side_flux = bc_flux * b_ele.
measure() * cross_section;
276 if (switch_dirichlet) {
280 ASSERT_DBG(ad_->dh_->distr()->is_local(global_dofs_[side_row]))(global_dofs_[side_row]);
281 unsigned int loc_side_row = local_dofs_[side_row];
284 if ( solution_flux < side_flux) {
286 solution_flux = side_flux;
299 ASSERT_DBG(ad_->dh_->distr()->is_local(global_dofs_[edge_row]))(global_dofs_[edge_row]);
300 unsigned int loc_edge_row = local_dofs_[edge_row];
303 if ( solution_head > bc_pressure) {
305 solution_head = bc_pressure;
312 if (switch_dirichlet || ad_->force_no_neumann_bc ) {
314 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
315 dirichlet_edge[i] = 1;
318 loc_system_.add_value(edge_row, side_flux);
322 ad_->is_linear=
false;
324 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
325 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
326 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
327 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
328 ASSERT_DBG(ad_->dh_->distr()->is_local(global_dofs_[edge_row]))(global_dofs_[edge_row]);
329 unsigned int loc_edge_row = local_dofs_[edge_row];
333 if (solution_head > bc_switch_pressure || ad_->force_no_neumann_bc) {
336 loc_system_.add_value(edge_row, edge_row,
337 -b_ele.
measure() * bc_sigma * cross_section,
338 b_ele.
measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
342 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
344 loc_system_.add_value(edge_row, bc_total_flux * b_ele.
measure() * cross_section);
348 THROW( ExcBCNotSupported() );
351 loc_system_.add_value(side_row, edge_row, 1.0);
352 loc_system_.add_value(edge_row, side_row, 1.0);
359 double cs = ad_->cross_section.value(ele.
centre(), ele);
360 double conduct = ad_->conductivity.value(ele.
centre(), ele);
361 double scale = 1 / cs /conduct;
363 assemble_sides_scale(dh_cell, scale);
371 fe_values_.reinit(ele);
372 unsigned int ndofs = fe_values_.n_dofs();
373 unsigned int qsize = fe_values_.n_points();
374 auto velocity = fe_values_.vector_view(0);
376 for (
unsigned int k=0; k<qsize; k++)
377 for (
unsigned int i=0; i<ndofs; i++){
379 arma::dot(gravity_vec,velocity.value(i,k))
381 loc_system_.add_value(i, rhs_val);
383 for (
unsigned int j=0; j<ndofs; j++){
385 arma::dot(velocity.value(i,k),
386 (ad_->anisotropy.value(ele.
centre(), ele )).i()
387 * velocity.value(j,k))
388 * scale * fe_values_.JxW(k);
390 loc_system_.add_value(i, j, mat_val);
403 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
404 const arma::mat& local_matrix = loc_system_.get_matrix();
405 for(
unsigned int i=0; i < ndofs; i++) {
406 double val_side = local_matrix(i,i);
407 double val_edge = -1./local_matrix(i,i);
409 unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
410 unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
411 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
412 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
421 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
422 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
423 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
426 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
429 diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
436 auto ele = dh_cell.
elm();
448 loc_system_vb_.reset();
449 loc_system_vb_.row_dofs[0] = loc_system_vb_.col_dofs[0] = global_dofs_[loc_ele_dof];
455 higher_dim_dofs.resize(dh_neighb_cell.
n_dofs());
461 const unsigned int t = dh_neighb_cell.
n_dofs() - (dim+2) + neighb_side.side().side_idx();
462 loc_system_vb_.row_dofs[1] = loc_system_vb_.col_dofs[1] = higher_dim_dofs[t];
464 assembly_local_vb(ele, neighb_side);
466 loc_system_vb_.eliminate_solution();
467 ad_->lin_sys->set_local_system(loc_system_vb_);
470 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
471 int ind = loc_system_vb_.row_dofs[1];
473 double new_val = loc_system_vb_.get_matrix()(0,0);
474 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
483 unsigned int sidx = dh_side.side_idx();
484 if (dh_side.side().is_boundary()) {
485 ad_->balance->add_flux_values(ad_->water_balance_idx, dh_side,
486 {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
arma::Col< IntIdx > LocDofVec
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
DECLARE_EXCEPTION(ExcBCNotSupported,<< "BC type not supported.\n")
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.
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.
void fix_velocity(const DHCellAccessor &dh_cell) override
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
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.