8 #ifndef SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 9 #define SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ 43 template<
template<
int dim>
class Impl >
45 return { std::make_shared<Impl<1> >(data),
46 std::make_shared<Impl<2> >(data),
47 std::make_shared<Impl<3> >(data) };
100 fe_values_(map_, quad_, fe_rt_,
103 velocity_interpolation_quad_(0),
107 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 arma::umat sp(size(),size());
124 sp.submat(0, 0, nsides, nsides).ones();
126 sp.diag(nsides+1).ones();
127 sp.diag(-nsides-1).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_);
153 mortar_assembly->fix_velocity(ele_ac);
161 set_dofs_and_bc(ele_ac);
164 assemble_element(ele_ac);
167 ad_->lin_sys->set_local_system(loc_system_);
169 assembly_dim_connections(ele_ac);
171 if (ad_->balance !=
nullptr)
172 add_fluxes_in_balance_matrix(ele_ac);
175 mortar_assembly->assembly(ele_ac);
186 ngh_values_.fe_side_values_.reinit(ele_higher, ngh->
side()->
el_idx());
187 nv = ngh_values_.fe_side_values_.normal_vector(0);
189 double value = ad_->sigma.value( ele->centre(), ele->element_accessor()) *
190 2*ad_->conductivity.value( ele->centre(), ele->element_accessor()) *
191 arma::dot(ad_->anisotropy.value( ele->centre(), ele->element_accessor())*nv, nv) *
192 ad_->cross_section.value( ngh->
side()->
centre(), ele_higher->element_accessor() ) *
193 ad_->cross_section.value( ngh->
side()->
centre(), ele_higher->element_accessor() ) /
194 ad_->cross_section.value( ele->centre(), ele->element_accessor() ) *
197 loc_system_vb_.add_value(0,0, -value);
198 loc_system_vb_.add_value(0,1, value);
199 loc_system_vb_.add_value(1,0, value);
200 loc_system_vb_.add_value(1,1, -value);
208 flux_in_center.zeros();
210 velocity_interpolation_fv_.reinit(ele);
211 for (
unsigned int li = 0; li < ele->n_sides(); li++) {
212 flux_in_center += ad_->mh_dh->side_flux( *(ele->side( li ) ) )
213 * velocity_interpolation_fv_.vector_view(0).value(li,0);
216 flux_in_center /= ad_->cross_section.value(ele->centre(), ele->element_accessor() );
217 return flux_in_center;
221 static const unsigned int size()
232 loc_system_.row_dofs[loc_ele_dof] = loc_system_.col_dofs[loc_ele_dof] = ele_ac.
ele_row();
235 const unsigned int nsides = ele_ac.
n_sides();
236 LinSys *ls = ad_->lin_sys;
239 unsigned int side_row, edge_row;
241 dirichlet_edge.resize(nsides);
242 for (
unsigned int i = 0; i < nsides; i++) {
244 side_row = loc_side_dofs[i];
245 edge_row = loc_edge_dofs[i];
246 loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = ele_ac.
side_row(i);
247 loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = ele_ac.
edge_row(i);
250 dirichlet_edge[i] = 0;
260 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
261 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
262 dirichlet_edge[i] = 1;
266 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
267 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
268 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
270 dirichlet_edge[i] = 2;
271 loc_system_.add_value(edge_row, edge_row,
273 (bc_flux - bc_sigma * bc_pressure) * bcd->
element()->
measure() * cross_section);
276 ad_->is_linear=
false;
279 char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
280 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
281 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
282 double side_flux = bc_flux * bcd->
element()->
measure() * cross_section;
285 if (switch_dirichlet) {
293 if ( solution_flux < side_flux) {
295 solution_flux = side_flux;
312 if ( solution_head > bc_pressure) {
314 solution_head = bc_pressure;
321 if (switch_dirichlet || ad_->force_bc_switch ) {
323 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
324 dirichlet_edge[i] = 1;
327 loc_system_.add_value(edge_row, side_flux);
331 ad_->is_linear=
false;
333 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
334 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
335 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
336 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
342 if (solution_head > bc_switch_pressure || ad_->force_bc_switch) {
345 loc_system_.add_value(edge_row, edge_row,
347 bcd->
element()->
measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
351 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
353 loc_system_.add_value(edge_row, bc_total_flux * bcd->
element()->
measure() * cross_section);
360 loc_system_.add_value(side_row, edge_row, 1.0);
361 loc_system_.add_value(edge_row, side_row, 1.0);
375 double scale = 1 / cs /conduct;
377 assemble_sides_scale(ele_ac, scale);
385 fe_values_.reinit(ele);
386 unsigned int ndofs = fe_values_.get_fe()->n_dofs();
387 unsigned int qsize = fe_values_.get_quadrature()->size();
388 auto velocity = fe_values_.vector_view(0);
390 for (
unsigned int k=0; k<qsize; k++)
391 for (
unsigned int i=0; i<ndofs; i++){
393 arma::dot(gravity_vec,velocity.value(i,k))
395 loc_system_.add_value(i, rhs_val);
397 for (
unsigned int j=0; j<ndofs; j++){
399 arma::dot(velocity.value(i,k),
401 * velocity.value(j,k))
402 * scale * fe_values_.JxW(k);
404 loc_system_.add_value(i, j, mat_val);
417 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
418 const arma::mat& local_matrix = loc_system_.get_matrix();
419 for(
unsigned int i=0; i < ndofs; i++) {
420 double val_side = local_matrix(i,i);
421 double val_edge = -1./local_matrix(i,i);
423 unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
424 unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
425 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
426 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
435 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
436 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
437 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
440 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
443 diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
453 if(ele->n_neighs_vb == 0)
return;
455 int ele_row = ele_ac.
ele_row();
459 for (
unsigned int i = 0; i < ele->n_neighs_vb; i++) {
463 loc_system_vb_.reset();
464 loc_system_vb_.row_dofs[0] = loc_system_vb_.col_dofs[0] = ele_row;
465 loc_system_vb_.row_dofs[1] = loc_system_vb_.col_dofs[1] = ad_->mh_dh->row_4_edge[ ngh->
edge_idx() ];
469 ad_->lin_sys->set_local_system(loc_system_vb_);
472 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
473 int ind = loc_system_vb_.row_dofs[1];
475 double new_val = loc_system_vb_.get_matrix()(0,0);
476 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
483 for (
unsigned int i = 0; i < ele_ac.
n_sides(); i++) {
494 ad_->balance->add_flux_matrix_values(ad_->water_balance_idx, ad_->local_boundary_index,
495 {(IdxInt)(ele_ac.side_row(i))}, {1});
496 ++(ad_->local_boundary_index);
523 unsigned int loc_ele_dof;
525 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
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...
virtual void assembly_local_vb(ElementFullIter ele, Neighbour *ngh)=0
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 assembly_local_vb(ElementFullIter ele, Neighbour *ngh) override
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)
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
static MultidimAssembly create(typename Impl< 1 >::AssemblyDataPtr data)
FE_P_disc< dim+1, 3 > fe_p_disc_
void assemble_element(LocalElementAccessorBase< 3 > ele_ac)
MappingP1< dim+1, 3 > side_map_
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.