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++) {
502 ad_->balance->add_flux_matrix_values(ad_->water_balance_idx, ele_ac.
side(i),
530 unsigned int loc_ele_dof;
532 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
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.