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_(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) *
200 arma::dot(ad_->anisotropy.value( ele.
centre(), ele)*nv, nv) *
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;
230 static const unsigned int size()
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;
248 unsigned int side_row, edge_row;
250 dirichlet_edge.resize(nsides);
251 for (
unsigned int i = 0; i < nsides; i++) {
253 side_row = loc_side_dofs[i];
254 edge_row = loc_edge_dofs[i];
255 loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = ele_ac.
side_row(i);
256 loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = ele_ac.
edge_row(i);
259 dirichlet_edge[i] = 0;
269 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
270 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
271 dirichlet_edge[i] = 1;
275 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
276 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
277 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
279 dirichlet_edge[i] = 2;
280 loc_system_.add_value(edge_row, edge_row,
281 -b_ele.
measure() * bc_sigma * cross_section,
282 (bc_flux - bc_sigma * bc_pressure) * b_ele.
measure() * cross_section);
285 ad_->is_linear=
false;
288 char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
289 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
290 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
291 double side_flux = bc_flux * b_ele.
measure() * cross_section;
294 if (switch_dirichlet) {
302 if ( solution_flux < side_flux) {
304 solution_flux = side_flux;
321 if ( solution_head > bc_pressure) {
323 solution_head = bc_pressure;
330 if (switch_dirichlet || ad_->force_bc_switch ) {
332 loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
333 dirichlet_edge[i] = 1;
336 loc_system_.add_value(edge_row, side_flux);
340 ad_->is_linear=
false;
342 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
343 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
344 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
345 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
351 if (solution_head > bc_switch_pressure || ad_->force_bc_switch) {
354 loc_system_.add_value(edge_row, edge_row,
355 -b_ele.
measure() * bc_sigma * cross_section,
356 b_ele.
measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
360 double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
362 loc_system_.add_value(edge_row, bc_total_flux * b_ele.
measure() * cross_section);
369 loc_system_.add_value(side_row, edge_row, 1.0);
370 loc_system_.add_value(edge_row, side_row, 1.0);
384 double scale = 1 / cs /conduct;
386 assemble_sides_scale(ele_ac, scale);
394 fe_values_.reinit(ele);
395 unsigned int ndofs = fe_values_.get_fe()->n_dofs();
396 unsigned int qsize = fe_values_.get_quadrature()->size();
397 auto velocity = fe_values_.vector_view(0);
399 for (
unsigned int k=0; k<qsize; k++)
400 for (
unsigned int i=0; i<ndofs; i++){
402 arma::dot(gravity_vec,velocity.value(i,k))
404 loc_system_.add_value(i, rhs_val);
406 for (
unsigned int j=0; j<ndofs; j++){
408 arma::dot(velocity.value(i,k),
410 * velocity.value(j,k))
411 * scale * fe_values_.JxW(k);
413 loc_system_.add_value(i, j, mat_val);
426 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
427 const arma::mat& local_matrix = loc_system_.get_matrix();
428 for(
unsigned int i=0; i < ndofs; i++) {
429 double val_side = local_matrix(i,i);
430 double val_edge = -1./local_matrix(i,i);
432 unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
433 unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
434 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
435 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
444 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
445 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
446 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
449 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
452 diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
464 int ele_row = ele_ac.
ele_row();
468 for (
unsigned int i = 0; i < ele->
n_neighs_vb(); i++) {
472 loc_system_vb_.reset();
473 loc_system_vb_.row_dofs[0] = loc_system_vb_.col_dofs[0] = ele_row;
474 loc_system_vb_.row_dofs[1] = loc_system_vb_.col_dofs[1] = ad_->mh_dh->row_4_edge[ ngh->
edge_idx() ];
478 ad_->lin_sys->set_local_system(loc_system_vb_);
481 if (
typeid(*ad_->lin_sys) ==
typeid(
LinSys_BDDC) ) {
482 int ind = loc_system_vb_.row_dofs[1];
484 double new_val = loc_system_vb_.get_matrix()(0,0);
485 static_cast<LinSys_BDDC*
>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
492 for (
unsigned int i = 0; i < ele_ac.
n_sides(); i++) {
503 ad_->balance->add_flux_matrix_values(ad_->water_balance_idx, ad_->local_boundary_index,
504 {(LongIdx)(ele_ac.side_row(i))}, {1});
505 ++(ad_->local_boundary_index);
532 unsigned int loc_ele_dof;
534 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...
#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
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
static const unsigned int size()
void assemble(LocalElementAccessorBase< 3 > ele_ac) 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(ElementAccessor< 3 > ele, Neighbour *ngh)=0
SideIter side(const unsigned int loc_index)
ElementAccessor< 3 > element() const
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...
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.
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
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)
virtual void update_water_content(LocalElementAccessorBase< 3 > ele)
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
void fix_velocity(LocalElementAccessorBase< 3 > ele_ac) override
static MultidimAssembly create(typename Impl< 1 >::AssemblyDataPtr data)
void assemble_element(LocalElementAccessorBase< 3 > ele_ac)
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.