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) };
106 velocity_interpolation_quad_(0),
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;
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);
176 ad_->lin_sys->set_local_system(loc_system_);
180 if (ad_->balance !=
nullptr)
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;
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))
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),
503 {(LongIdx)(ele_ac.side_row(i))}, {1});
530 unsigned int loc_ele_dof;
532 std::shared_ptr<MortarAssemblyBase> mortar_assembly;