8 #ifndef SRC_ASSEMBLY_LMH_HH_
9 #define SRC_ASSEMBLY_LMH_HH_
46 velocity_interpolation_quad_(dim, 0),
55 auto fe = ad_->dh_->ds()->fe()[
Dim<dim>{}];
57 loc_side_dofs = fe_system->
fe_dofs(0);
58 loc_ele_dof = fe_system->
fe_dofs(1)[0];
59 loc_edge_dofs = fe_system->
fe_dofs(2);
62 .error(
"Mortar methods are not supported in Lumped Mixed-Hybrid Method.");
71 schur_offset_ = loc_edge_dofs[0];
72 reconstructed_solution_.zeros(schur_offset_);
97 arma::vec schur_solution = ad_->p_edge_solution.get_subvec(loc_schur_.row_dofs);
99 loc_system_.reconstruct_solution_schur(schur_offset_, schur_solution, reconstructed_solution_);
104 ad_->full_solution.set_subvec(loc_system_.row_dofs.head(schur_offset_), reconstructed_solution_);
105 ad_->full_solution.set_subvec(loc_system_.row_dofs.tail(loc_schur_.row_dofs.n_elem), schur_solution);
111 save_local_system_ =
false;
112 bc_fluxes_reconstruted =
false;
116 loc_system_.compute_schur_complement(schur_offset_, loc_schur_,
true);
120 loc_schur_.eliminate_solution();
121 ad_->lin_sys_schur->set_local_system(loc_schur_, ad_->dh_cr_->get_local_to_global_map());
157 if(bc_fluxes_reconstruted)
161 auto ls = ad_->seepage_bc_systems.find(dh_cell.
elm_idx());
162 if (ls != ad_->seepage_bc_systems.end())
164 arma::vec schur_solution = ad_->p_edge_solution.get_subvec(loc_schur_.row_dofs);
166 ls->second.reconstruct_solution_schur(schur_offset_, schur_solution, reconstructed_solution_);
170 bc_fluxes_reconstruted =
true;
180 if(save_local_system_)
181 ad_->seepage_bc_systems[dh_cell.
elm_idx()] = loc_system_;
215 const unsigned int p =
size()+i;
217 const unsigned int t = dh_neighb_cell.
n_dofs() - dh_neighb_cr_cell.
n_dofs() + neighb_side.side().side_idx();
221 const unsigned int tt = dh_cr_cell.
n_dofs()+i;
223 [neighb_side.side().side_idx()];
227 loc_system_.reset(dofs, dofs);
228 loc_schur_.reset(dofs_schur, dofs_schur);
235 dirichlet_edge.resize(ele->
n_sides());
237 unsigned int sidx = dh_side.side_idx();
238 dirichlet_edge[sidx] = 0;
241 if (dh_side.side().is_boundary()) {
242 double cross_section = ad_->cross_section.value(ele.
centre(), ele);
245 ad_->balance->add_flux_values(ad_->water_balance_idx, dh_side,
246 {loc_system_.row_dofs[loc_side_dofs[sidx]]},
251 loc_system_.add_value(loc_side_dofs[sidx], loc_edge_dofs[sidx], 1.0);
252 loc_system_.add_value(loc_edge_dofs[sidx], loc_side_dofs[sidx], 1.0);
259 const unsigned int sidx = side.
side_idx();
260 const unsigned int side_row = loc_side_dofs[sidx];
261 const unsigned int edge_row = loc_edge_dofs[sidx];
269 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
270 loc_schur_.set_solution(sidx, bc_pressure);
271 dirichlet_edge[sidx] = 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[sidx] = 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;
287 char & switch_dirichlet = ad_->bc_switch_dirichlet[b_ele.
idx()];
288 double bc_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
289 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
290 double side_flux = bc_flux * b_ele.
measure() * cross_section;
293 if(use_dirichlet_switch){
294 if (switch_dirichlet) {
301 double solution_flux = reconstructed_solution_[side_row];
303 if ( solution_flux < side_flux) {
318 double solution_head = ad_->p_edge_solution.get(loc_schur_.row_dofs[sidx]);
320 if ( solution_head > bc_pressure) {
327 save_local_system_ = (bool) switch_dirichlet;
331 if (switch_dirichlet || ad_->force_no_neumann_bc ) {
333 loc_schur_.set_solution(sidx, bc_pressure);
334 dirichlet_edge[sidx] = 1;
337 loc_system_.add_value(edge_row, side_flux);
341 ad_->is_linear=
false;
343 double bc_pressure = ad_->bc_pressure.value(b_ele.
centre(), b_ele);
344 double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.
centre(), b_ele);
345 double bc_flux = -ad_->bc_flux.value(b_ele.
centre(), b_ele);
346 double bc_sigma = ad_->bc_robin_sigma.value(b_ele.
centre(), b_ele);
348 double solution_head = ad_->p_edge_solution.get(loc_schur_.row_dofs[sidx]);
351 if (solution_head > bc_switch_pressure || ad_->force_no_neumann_bc) {
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);
366 THROW( ExcBCNotSupported() );
374 double cs = ad_->cross_section.value(ele.
centre(), ele);
375 double conduct = ad_->conductivity.value(ele.
centre(), ele);
376 double scale = 1 / cs /conduct;
384 auto ele = dh_cell.
elm();
391 for (
unsigned int k=0; k<qsize; k++)
392 for (
unsigned int i=0; i<ndofs; i++){
394 arma::dot(gravity_vec,velocity.value(i,k))
396 loc_system_.add_value(i, rhs_val);
398 for (
unsigned int j=0; j<ndofs; j++){
400 arma::dot(velocity.value(i,k),
401 (ad_->anisotropy.value(ele.centre(), ele)).i()
402 * velocity.value(j,k))
405 loc_system_.add_value(i, j, mat_val);
436 for(
unsigned int side = 0; side < loc_side_dofs.size(); side++){
437 loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
438 loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
453 double alpha = 1.0 / ele->
n_sides();
454 double cross_section = ad_->cross_section.value(ele.
centre(), ele);
455 double coef = alpha * ele.
measure() * cross_section;
457 double source = ad_->water_source_density.value(ele.
centre(), ele)
458 + ad_->extra_source.value(ele.
centre(), ele);
459 double source_term = coef * source;
462 double storativity = 0.0;
463 double time_term_diag = 0.0, time_term = 0.0, time_term_rhs = 0.0;
465 if(! ad_->use_steady_assembly_)
467 storativity = ad_->storativity.value(ele.
centre(), ele)
468 + ad_->extra_storativity.value(ele.
centre(), ele);
469 time_term = coef * storativity;
472 for (
unsigned int i=0; i<ele->
n_sides(); i++)
474 if(! ad_->use_steady_assembly_)
476 time_term_diag = time_term / ad_->time_step_;
477 time_term_rhs = time_term_diag * ad_->p_edge_solution_previous_time.get(loc_schur_.row_dofs[i]);
479 ad_->balance->add_mass_values(ad_->water_balance_idx, dh_cell,
480 {loc_system_.row_dofs[loc_edge_dofs[i]]}, {time_term}, 0);
486 ad_->balance->add_mass_values(ad_->water_balance_idx, dh_cell,
487 {loc_system_.row_dofs[loc_edge_dofs[i]]}, {0}, 0);
490 this->loc_system_.add_value(loc_edge_dofs[i], loc_edge_dofs[i],
492 -source_term - time_term_rhs);
494 ad_->balance->add_source_values(ad_->water_balance_idx, ele.
region().
bulk_idx(),
495 {loc_system_.row_dofs[loc_edge_dofs[i]]}, {0},{source_term});
513 unsigned int p =
size()+i;
516 ngh_values_.fe_side_values_.reinit(neighb_side.side());
517 nv = ngh_values_.fe_side_values_.normal_vector(0);
519 double value = ad_->sigma.value( ele.
centre(), ele) *
520 2*ad_->conductivity.value( ele.
centre(), ele) *
521 arma::dot(ad_->anisotropy.value( ele.
centre(), ele)*nv, nv) *
522 ad_->cross_section.value( neighb_side.centre(), ele_higher ) *
523 ad_->cross_section.value( neighb_side.centre(), ele_higher ) /
524 ad_->cross_section.value( ele.
centre(), ele ) *
525 neighb_side.measure();
527 loc_system_.add_value(loc_ele_dof, loc_ele_dof, -
value);
528 loc_system_.add_value(loc_ele_dof, p,
value);
529 loc_system_.add_value(p,loc_ele_dof,
value);
530 loc_system_.add_value(p,p, -
value);
547 double edge_scale = ele.
measure()
548 * ad_->cross_section.value(ele.
centre(), ele)
551 double edge_source_term = edge_scale *
552 ( ad_->water_source_density.value(ele.
centre(), ele)
553 + ad_->extra_source.value(ele.
centre(), ele));
559 double edge_scale,
double edge_source_term)
563 double storativity = ad_->storativity.value(ele.
centre(), ele)
564 + ad_->extra_storativity.value(ele.
centre(), ele);
565 double new_pressure, old_pressure, time_term = 0.0;
567 for (
unsigned int i=0; i<ele->
n_sides(); i++) {
569 if( ! ad_->use_steady_assembly_)
571 new_pressure = ad_->p_edge_solution.get(loc_schur_.row_dofs[i]);
572 old_pressure = ad_->p_edge_solution_previous_time.get(loc_schur_.row_dofs[i]);
573 time_term = edge_scale * storativity / ad_->time_step_ * (new_pressure - old_pressure);
575 solution[loc_side_dofs[i]] += edge_source_term - time_term;
587 QGauss velocity_interpolation_quad_;
603 unsigned int loc_ele_dof;
608 unsigned int schur_offset_;
615 bool save_local_system_;
618 bool bc_fluxes_reconstruted;