8 #ifndef SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 9 #define SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 46 template<
template<
int dim>
class Impl >
48 return { std::make_shared<Impl<1> >(data),
49 std::make_shared<Impl<2> >(data),
50 std::make_shared<Impl<3> >(data) };
103 fe_values_(map_, quad_, fe_rt_,
106 velocity_interpolation_quad_(dim, 0),
110 loc_system_(size(), size()),
114 unsigned int nsides = dim+1;
115 loc_side_dofs.resize(nsides);
116 loc_ele_dof = nsides;
117 loc_edge_dofs.resize(nsides);
118 for(
unsigned int i = 0; i < nsides; i++){
119 loc_side_dofs[i] = i;
120 loc_edge_dofs[i] = nsides + i + 1;
125 arma::umat sp(size(),size());
127 sp.submat(0, 0, nsides, nsides).ones();
134 sp.submat(0, nsides+1, nsides-1, size()-1).diag().ones();
135 sp.submat(nsides+1, 0, size()-1, nsides-1).diag().ones();
137 loc_system_.set_sparsity(sp);
142 loc_system_vb_.set_sparsity(sp);
145 mortar_assembly = std::make_shared<P0_CouplingAssembler>(ad_);
147 mortar_assembly = std::make_shared<P1_CouplingAssembler>(ad_);
162 mortar_assembly->fix_velocity(ele_ac);
170 set_dofs_and_bc(ele_ac);
173 assemble_element(ele_ac);
176 ad_->lin_sys->set_local_system(loc_system_);
178 assembly_dim_connections(ele_ac);
180 if (ad_->balance !=
nullptr)
181 add_fluxes_in_balance_matrix(ele_ac);
184 mortar_assembly->assembly(ele_ac);
195 ngh_values_.fe_side_values_.reinit(ele_higher, ngh->
side()->
side_idx());
196 nv = ngh_values_.fe_side_values_.normal_vector(0);
198 double value = ad_->sigma.value( ele.
centre(), ele) *
199 2*ad_->conductivity.value( ele.
centre(), ele) *
201 ad_->cross_section.value( ngh->
side()->
centre(), ele_higher ) *
202 ad_->cross_section.value( ngh->
side()->
centre(), ele_higher ) /
203 ad_->cross_section.value( ele.
centre(), ele ) *
206 loc_system_vb_.add_value(0,0, -value);
207 loc_system_vb_.add_value(0,1, value);
208 loc_system_vb_.add_value(1,0, value);
209 loc_system_vb_.add_value(1,1, -value);
217 flux_in_center.zeros();
219 velocity_interpolation_fv_.reinit(ele);
220 for (
unsigned int li = 0; li < ele->
n_sides(); li++) {
221 flux_in_center += ad_->mh_dh->side_flux( *(ele.
side( li ) ) )
222 * velocity_interpolation_fv_.vector_view(0).value(li,0);
225 flux_in_center /= ad_->cross_section.value(ele.
centre(), ele );
226 return flux_in_center;
241 loc_system_.row_dofs[loc_ele_dof] = loc_system_.col_dofs[loc_ele_dof] = ele_ac.
ele_row();
244 const unsigned int nsides = ele_ac.
n_sides();
245 LinSys *ls = ad_->lin_sys;
247 unsigned int side_row, edge_row;
249 dirichlet_edge.resize(nsides);
250 for (
unsigned int i = 0; i < nsides; i++) {
252 side_row = loc_side_dofs[i];
253 edge_row = loc_edge_dofs[i];
254 loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = ele_ac.
side_row(i);
255 loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = ele_ac.
edge_row(i);
257 dirichlet_edge[i] = 0;
268 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
269 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
270 dirichlet_edge[i] = 1;
274 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
275 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
276 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
278 dirichlet_edge[i] = 2;
279 loc_system_.add_value(edge_row, edge_row,
280 -b_ele.
measure() * bc_sigma * cross_section,
281 (bc_flux - bc_sigma * bc_pressure) * b_ele.
measure() * cross_section);
284 ad_->is_linear=
false;
287 char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
288 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
289 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
290 double side_flux = bc_flux * b_ele.
measure() * cross_section;
293 if (switch_dirichlet) {
301 if ( solution_flux < side_flux) {
303 solution_flux = side_flux;
320 if ( solution_head > bc_pressure) {
322 solution_head = bc_pressure;
329 if (switch_dirichlet || ad_->force_bc_switch ) {
331 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
332 dirichlet_edge[i] = 1;
335 loc_system_.add_value(edge_row, side_flux);
339 ad_->is_linear=
false;
341 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
342 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
343 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
344 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
350 if (solution_head > bc_switch_pressure || ad_->force_bc_switch) {
353 loc_system_.add_value(edge_row, edge_row,
354 -b_ele.
measure() * bc_sigma * cross_section,
355 b_ele.
measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
359 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
361 loc_system_.add_value(edge_row, bc_total_flux * b_ele.
measure() * cross_section);
368 loc_system_.add_value(side_row, edge_row, 1.0);
369 loc_system_.add_value(edge_row, side_row, 1.0);
383 double scale = 1 / cs /conduct;
385 assemble_sides_scale(ele_ac, scale);
393 fe_values_.reinit(ele);
394 unsigned int ndofs = fe_values_.get_fe()->n_dofs();
395 unsigned int qsize = fe_values_.get_quadrature()->size();
396 auto velocity = fe_values_.vector_view(0);
398 for (
unsigned int k=0; k<qsize; k++)
399 for (
unsigned int i=0; i<ndofs; i++){
401 arma::dot(gravity_vec,velocity.value(i,k))
403 loc_system_.add_value(i, rhs_val);
405 for (
unsigned int j=0; j<ndofs; j++){
409 * velocity.value(j,k))
410 * scale * fe_values_.JxW(k);
412 loc_system_.add_value(i, j, mat_val);
425 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
426 const arma::mat& local_matrix = loc_system_.get_matrix();
427 for(
unsigned int i=0; i < ndofs; i++) {
428 double val_side = local_matrix(i,i);
429 double val_edge = -1./local_matrix(i,i);
431 unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
432 unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
433 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
434 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
443 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
444 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
445 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
448 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
451 diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
463 int ele_row = ele_ac.
ele_row();
467 for (
unsigned int i = 0; i < ele->
n_neighs_vb(); i++) {
471 loc_system_vb_.reset();
472 loc_system_vb_.row_dofs[0] = loc_system_vb_.col_dofs[0] = ele_row;
473 loc_system_vb_.row_dofs[1] = loc_system_vb_.col_dofs[1] = ad_->mh_dh->row_4_edge[ ngh->
edge_idx() ];
477 ad_->lin_sys->set_local_system(loc_system_vb_);
480 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
481 int ind = loc_system_vb_.row_dofs[1];
483 double new_val = loc_system_vb_.get_matrix()(0,0);
484 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
491 for (
unsigned int i = 0; i < ele_ac.
n_sides(); i++) {
499 ad_->balance->add_flux_matrix_values(ad_->water_balance_idx, ele_ac.
side(i),
516 QGauss velocity_interpolation_quad_;
527 unsigned int loc_ele_dof;
529 std::shared_ptr<MortarAssemblyBase> mortar_assembly;
const arma::vec3 centre() const
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
FESideValues< dim+1, 3 > fe_side_values_
std::vector< std::shared_ptr< AssemblyBase > > MultidimAssembly
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
void assembly_local_vb(ElementAccessor< 3 > ele, Neighbour *ngh) override
unsigned int side_idx() const
Returns local index of the side on the element.
void assemble_sides(LocalElementAccessorBase< 3 > ele_ac) override
ElementAccessor< 3 > element_accessor()
void add_fluxes_in_balance_matrix(LocalElementAccessorBase< 3 > ele_ac)
arma::vec3 make_element_vector(ElementAccessor< 3 > ele) override
void assemble(LocalElementAccessorBase< 3 > ele_ac) override
Wrappers for linear systems based on MPIAIJ and MATIS format.
static unsigned int size()
arma::vec3 centre() const
Centre of side.
uint side_local_row(uint i)
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtr
virtual void update_water_content(FMT_UNUSED LocalElementAccessorBase< 3 > ele)
virtual void assemble(LocalElementAccessorBase< 3 > ele_ac)=0
Class FEValues calculates finite element data on the actual cells such as shape function values...
virtual void assembly_local_vb(ElementAccessor< 3 > ele, Neighbour *ngh)=0
SideIter side(const unsigned int loc_index)
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
static constexpr bool value
Symmetric Gauss-Legendre quadrature formulae on simplices.
virtual void assemble_source_term(FMT_UNUSED LocalElementAccessorBase< 3 > ele)
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
arma::vec::fixed< spacedim > centre() const
Computes the barycenter.
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtr
virtual void fix_velocity(LocalElementAccessorBase< 3 > ele_ac)=0
Transformed quadrature points.
bool is_boundary() const
Returns true for side on the boundary.
double * get_solution_array()
void set_dofs_and_bc(LocalElementAccessorBase< 3 > ele_ac)
virtual arma::vec3 make_element_vector(ElementAccessor< 3 > ele)=0
Raviart-Thomas element of order 0.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
unsigned int n_sides() const
Type dot(const Mat< Type, nRows, nCols > &a, const Mat< Type, nRows, nCols > &b)
void assemble_sides_scale(LocalElementAccessorBase< 3 > ele_ac, double scale)
double measure() const
Computes the measure of the element.
Shape function gradients.
uint edge_local_row(uint i)
double measure() const
Calculate metrics of the side.
FEValues< dim, 3 > fe_values_
void assembly_dim_connections(LocalElementAccessorBase< 3 > ele_ac)
void assemble_element(LocalElementAccessorBase< 3 >)
Definitions of particular quadrature rules on simplices.
virtual void assemble_sides(LocalElementAccessorBase< 3 > ele)=0
void fix_velocity(LocalElementAccessorBase< 3 > ele_ac) override
static MultidimAssembly create(typename Impl< 1 >::AssemblyDataPtr data)
MappingP1< dim+1, 3 > side_map_
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.
Definitions of Raviart-Thomas finite elements.
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.