8 #ifndef SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 9 #define SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 42 template<
template<
int dim>
class Impl >
44 return { std::make_shared<Impl<1> >(data),
45 std::make_shared<Impl<2> >(data),
46 std::make_shared<Impl<3> >(data) };
100 fe_values_(map_, quad_, fe_rt_,
104 velocity_interpolation_quad_(0),
108 loc_system_(size(), size())
111 unsigned int nsides = dim+1;
112 loc_side_dofs.resize(nsides);
113 loc_ele_dof = nsides;
114 loc_edge_dofs.resize(nsides);
115 for(
unsigned int i = 0; i < nsides; i++){
116 loc_side_dofs[i] = i;
117 loc_edge_dofs[i] = nsides + i + 1;
122 mortar_assembly = std::make_shared<P0_CouplingAssembler>(ad_);
124 mortar_assembly = std::make_shared<P1_CouplingAssembler>(ad_);
139 mortar_assembly->fix_velocity(ele_ac);
147 set_dofs_and_bc(ele_ac);
150 assemble_element(ele_ac);
155 ad_->lin_sys->set_local_system(loc_system_);
157 assembly_dim_connections(ele_ac);
159 if (ad_->balance !=
nullptr)
160 add_fluxes_in_balance_matrix(ele_ac);
163 mortar_assembly->assembly(ele_ac);
174 ngh_values_.fe_side_values_.reinit(ele_higher, ngh->
side()->
el_idx());
175 nv = ngh_values_.fe_side_values_.normal_vector(0);
177 double value = ad_->sigma.value( ele->centre(), ele->element_accessor()) *
178 2*ad_->conductivity.value( ele->centre(), ele->element_accessor()) *
179 arma::dot(ad_->anisotropy.value( ele->centre(), ele->element_accessor())*nv, nv) *
180 ad_->cross_section.value( ngh->
side()->
centre(), ele_higher->element_accessor() ) *
181 ad_->cross_section.value( ngh->
side()->
centre(), ele_higher->element_accessor() ) /
182 ad_->cross_section.value( ele->centre(), ele->element_accessor() ) *
194 flux_in_center.zeros();
196 velocity_interpolation_fv_.reinit(ele);
197 for (
unsigned int li = 0; li < ele->n_sides(); li++) {
198 flux_in_center += ad_->mh_dh->side_flux( *(ele->side( li ) ) )
199 * velocity_interpolation_fv_.shape_vector(li,0);
202 flux_in_center /= ad_->cross_section.value(ele->centre(), ele->element_accessor() );
203 return flux_in_center;
207 static const unsigned int size()
218 loc_system_.row_dofs[loc_ele_dof] = loc_system_.col_dofs[loc_ele_dof] = ele_ac.
ele_row();
221 const unsigned int nsides = ele_ac.
n_sides();
222 LinSys *ls = ad_->lin_sys;
225 unsigned int side_row, edge_row;
227 dirichlet_edge.resize(nsides);
228 for (
unsigned int i = 0; i < nsides; i++) {
230 side_row = loc_side_dofs[i];
231 edge_row = loc_edge_dofs[i];
232 loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = ele_ac.
side_row(i);
233 loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = ele_ac.
edge_row(i);
236 dirichlet_edge[i] = 0;
246 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
247 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
248 dirichlet_edge[i] = 1;
252 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
253 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
254 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
256 dirichlet_edge[i] = 2;
257 loc_system_.add_value(edge_row, edge_row,
259 (bc_flux - bc_sigma * bc_pressure) * bcd->
element()->
measure() * cross_section);
262 ad_->is_linear=
false;
265 char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
266 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
267 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
268 double side_flux = bc_flux * bcd->
element()->
measure() * cross_section;
271 if (switch_dirichlet) {
279 if ( solution_flux < side_flux) {
281 solution_flux = side_flux;
298 if ( solution_head > bc_pressure) {
300 solution_head = bc_pressure;
307 if (switch_dirichlet || ad_->force_bc_switch ) {
309 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
310 dirichlet_edge[i] = 1;
313 loc_system_.add_value(edge_row, side_flux);
317 ad_->is_linear=
false;
319 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
320 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
321 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
322 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
328 if (solution_head > bc_switch_pressure || ad_->force_bc_switch) {
331 loc_system_.add_value(edge_row, edge_row,
333 bcd->
element()->
measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
337 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
339 loc_system_.add_value(edge_row, bc_total_flux * bcd->
element()->
measure() * cross_section);
346 loc_system_.add_value(side_row, edge_row, 1.0);
347 loc_system_.add_value(edge_row, side_row, 1.0);
361 double scale = 1 / cs /conduct;
363 assemble_sides_scale(ele_ac, scale);
371 fe_values_.reinit(ele);
372 unsigned int ndofs = fe_values_.get_fe()->n_dofs();
373 unsigned int qsize = fe_values_.get_quadrature()->size();
375 for (
unsigned int k=0; k<qsize; k++)
376 for (
unsigned int i=0; i<ndofs; i++){
378 arma::dot(gravity_vec,fe_values_.shape_vector(i,k))
380 loc_system_.add_value(i, rhs_val);
382 for (
unsigned int j=0; j<ndofs; j++){
384 arma::dot(fe_values_.shape_vector(i,k),
386 * fe_values_.shape_vector(j,k))
387 * scale * fe_values_.JxW(k);
389 loc_system_.add_value(i, j, mat_val);
402 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
403 const arma::mat& local_matrix = loc_system_.get_matrix();
404 for(
unsigned int i=0; i < ndofs; i++) {
405 double val_side = local_matrix(i,i);
406 double val_edge = -1./local_matrix(i,i);
408 unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
409 unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
410 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
411 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
420 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
421 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
422 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
425 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
428 diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
435 int ele_row = ele_ac.
ele_row();
442 for (
unsigned int i = 0; i < ele_ac.
full_iter()->n_neighs_vb; i++) {
447 rows[1]=ad_->mh_dh->row_4_edge[ ngh->
edge_idx() ];
452 ad_->lin_sys->mat_set_values(2, rows, 2, rows, local_vb);
455 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
458 double new_val = local_vb[0];
459 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
466 for (
unsigned int i = 0; i < ele_ac.
n_sides(); i++) {
477 ad_->balance->add_flux_matrix_values(ad_->water_balance_idx, ad_->local_boundary_index,
478 {ele_ac.side_row(i)}, {1});
479 ++(ad_->local_boundary_index);
505 unsigned int loc_ele_dof;
507 std::shared_ptr<MortarAssemblyBase> mortar_assembly;
const arma::vec3 centre() const
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
double measure() const
Computes the measure of the element.
#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 assemble_sides(LocalElementAccessorBase< 3 > ele_ac) override
ElementAccessor< 3 > element_accessor()
virtual arma::vec3 make_element_vector(ElementFullIter ele)=0
void add_fluxes_in_balance_matrix(LocalElementAccessorBase< 3 > ele_ac)
static const unsigned int size()
void assemble(LocalElementAccessorBase< 3 > ele_ac) override
arma::vec3 make_element_vector(ElementFullIter ele) override
Wrappers for linear systems based on MPIAIJ and MATIS format.
arma::vec3 centre() const
uint side_local_row(uint i)
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtr
FE_P_disc< 0, dim+1, 3 > fe_p_disc_
virtual void assemble_source_term(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...
static constexpr bool value
Symmetric Gauss-Legendre quadrature formulae on simplices.
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtr
virtual void fix_velocity(LocalElementAccessorBase< 3 > ele_ac)=0
Transformed quadrature points.
double * get_solution_array()
void set_dofs_and_bc(LocalElementAccessorBase< 3 > ele_ac)
Definitions of basic Lagrangean finite elements with polynomial shape functions.
void assemble_sides_scale(LocalElementAccessorBase< 3 > ele_ac, double scale)
Shape function gradients.
uint edge_local_row(uint i)
virtual void update_water_content(LocalElementAccessorBase< 3 > ele)
ElementFullIter element() const
FEValues< dim, 3 > fe_values_
void assembly_dim_connections(LocalElementAccessorBase< 3 > ele_ac)
Abstract linear system class.
Definitions of particular quadrature rules on simplices.
virtual void assemble_sides(LocalElementAccessorBase< 3 > ele)=0
arma::vec::fixed< spacedim > centre() const
void fix_velocity(LocalElementAccessorBase< 3 > ele_ac) override
unsigned int el_idx() const
void assembly_local_vb(double *local_vb, ElementFullIter ele, Neighbour *ngh) override
static MultidimAssembly create(typename Impl< 1 >::AssemblyDataPtr data)
void assemble_element(LocalElementAccessorBase< 3 > ele_ac)
MappingP1< dim+1, 3 > side_map_
virtual void assembly_local_vb(double *local_vb, ElementFullIter ele, Neighbour *ngh)=0
ElementFullIter full_iter()
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.