35template<
typename TDomain>
38 const std::vector<LFEID> & vLfeID,
45 " The discretization does not support hanging nodes.\n");
48 if (vLfeID.size () != 1)
49 UG_THROW (
"FractPF_FV1: The pressure driven flow requires one coponent in every vertex.");
54 UG_THROW (
"FractPF_FV1: This discretization works with the LagrangeP1-elements only.");
62template<
typename TDomain>
63template<
typename TElem,
typename TBulkFVGeom>
71 if (! m_spFractManager.valid())
75 if (! m_spFractManager->is_closed ())
76 UG_THROW (
"FractPF_FV1: Fracture manager not closed");
77 m_isFracture = m_spFractManager->contains (si);
81 if (!m_imConstGravity.data_given())
82 UG_THROW (
"FractPF_FV1: Missing Import 'gravity'.");
83 if (m_imConstGravity.constant())
86 UG_THROW (
"FractPF_FV1: Gravity must be constant.");
90 this->
template bulk_prepare_element_loop<TElem, TBulkFVGeom> (roid, si);
92 this->
template fract_prepare_element_loop<TElem> (roid, si);
96template<
typename TDomain>
97template<
typename TElem,
typename TBulkFVGeom>
105 m_imAperture.set_data (
SPNULL);
106 m_imFractPermeability.set_data (
SPNULL);
107 m_imOrthoPermeability.set_data (
SPNULL);
110 if (!m_imPermeability.data_given())
111 UG_THROW (
"FractPF_FV1: Missing Import 'full-dim. permeability'.");
115 static const int refDim = TElem::dim;
119 m_imPermeability.template set_local_ips<refDim> (coe_local, 1,
false);
123template<
typename TDomain>
124template<
typename TElem>
135 m_imAperture.set_data (m_spApertureData);
136 m_imFractPermeability.set_data (m_spFractPermeabilityData);
137 m_imOrthoPermeability.set_data (m_spOrthoPermeabilityData);
140 if (!m_imAperture.data_given ())
141 UG_THROW (
"FractPF_FV1: Missing Import 'fracture width (aperture)'.");
142 if (!m_imPermeability.data_given ())
143 UG_THROW (
"FractPF_FV1: Missing Import 'full-dim. permeability' (for the fract.-bulk interface interaction).");
144 if (!m_imFractPermeability.data_given ())
145 UG_THROW (
"FractPF_FV1: Missing Import 'permeability along fracture'.");
150template<
typename TDomain>
151template<
typename TElem,
typename TBulkFVGeom>
157template<
typename TDomain>
158template<
typename TElem,
typename TBulkFVGeom>
167 TElem * pElem =
static_cast<TElem*
> (elem);
171 this->
template bulk_prepare_element<TElem, TBulkFVGeom> (u, pElem, vCornerCoords);
173 this->
template fract_prepare_element<TElem> (u, pElem, vCornerCoords);
177template<
typename TDomain>
178template<
typename TElem,
typename TBulkFVGeom>
192 UG_CATCH_THROW(
"FractPF_FV1: Cannot update the Finite Volume Geometry for a bulk element.");
196 m_imPermeability.set_global_ips (coe_global, 1);
200template<
typename TDomain>
201template<
typename TElem>
215 m_spFractManager->get_layer_sides
217 m_numFractCo, m_innerFractSide, m_innerFractSideIdx, m_innerSideCo,
218 m_outerFractSide, m_outerFractSideIdx, m_outerSideCo,
221 UG_CATCH_THROW(
"FractPF_FV1: Cannot find orientation of a fracture element.");
227 for (
size_t co = 0; co < m_numFractCo; co++)
228 vSideCornerCoords [co] = vCornerCoords [m_innerSideCo [co]];
229 m_pFractGeo->update (m_innerFractSide, vSideCornerCoords, &(this->
subset_handler()));
231 UG_CATCH_THROW(
"FractPF_FV1: Cannot update the Finite Volume Geometry for a fracture element.");
232 size_t numSCVFip = m_pFractGeo->num_scvf_ips ();
239 = ReferenceMappingProvider::get<low_dim, dim> (m_innerFractSide->reference_object_id ());
240 for (
size_t co = 0; co < m_numFractCo; co++)
241 vSideLocCornerCoords [co] = rRefElem.corner (m_innerSideCo [co]);
242 rMapping.
update (vSideLocCornerCoords);
244 rMapping.
local_to_global (m_elem_loc_coe, *(m_pFractGeo->coe_local ()));
245 rMapping.
local_to_global (m_elem_loc_scvf, m_pFractGeo->scvf_local_ips (), numSCVFip);
247 UG_CATCH_THROW(
"FractPF_FV1: Cannot transform local side coordinates to local element coordinates in a fracture element.");
251 loc_center_of_outer_sd = 0.0; glob_center_of_outer_sd = 0.0;
252 for (
size_t co = 0; co < m_numFractCo; co++)
254 loc_center_of_outer_sd += rRefElem.corner (m_outerSideCo [co]);
255 glob_center_of_outer_sd += vCornerCoords [m_outerSideCo [co]];
257 loc_center_of_outer_sd /= m_numFractCo;
258 glob_center_of_outer_sd /= m_numFractCo;
261 m_imAperture.template set_local_ips<dim> (&m_elem_loc_coe, 1);
262 m_imFractPermeability.template set_local_ips<dim> (&m_elem_loc_coe, 1);
263 if (m_imOrthoPermeability.data_given ())
264 m_imOrthoPermeability.template set_local_ips<dim> (&m_elem_loc_coe, 1);
266 m_imPermeability.template set_local_ips<dim> (&m_elem_loc_coe, 1);
270 m_imAperture.set_global_ips (coe_global, 1);
271 m_imFractPermeability.set_global_ips (coe_global, 1);
272 if (m_imOrthoPermeability.data_given ())
273 m_imOrthoPermeability.set_global_ips (coe_global, 1);
275 m_imPermeability.set_global_ips (coe_global, 1);
285 SideNormal<ref_elem_type, dim> (m_unitOuterNormal, m_outerFractSideIdx, vCornerCoords);
287 if (outerNormalNorm < 1e-32)
288 UG_THROW (
"FractPF_FV1: Cannot get the normal to a fracture.")
289 m_unitOuterNormal /= outerNormalNorm;
293template<
typename TDomain>
294template<
typename TFVGeom>
303 const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
307 for (
size_t sh = 0; sh < scvf.num_sh(); sh++)
315template<
typename TDomain>
316template<
typename TElem,
typename TBulkFVGeom>
325 TElem * pElem =
static_cast<TElem*
> (elem);
330 this->
template bulk_ass_dA_elem<TElem, TBulkFVGeom> (d, u, pElem, vCornerCoords);
334 this->
template fract_ass_dA_elem<TElem> (d, u, pElem, vCornerCoords);
335 this->
template fract_bulk_ass_dA_elem<TElem> (d, u, pElem, vCornerCoords);
340template<
typename TDomain>
341template<
typename TElem,
typename TBulkFVGeom>
355 const size_t numSh = bulk_geo.num_sh ();
356 const size_t numScvf = bulk_geo.num_scvf ();
359 number vPressure [ref_elem_type::numCorners];
360 for (
size_t sh = 0; sh < numSh; sh++)
361 vPressure [sh] = u (_P_, sh);
365 for (
size_t ip = 0; ip < numScvf; ip++)
368 this->
template compute_ip_velocity<TBulkFVGeom> (Vel, ip, bulk_geo, vPressure);
369 MatVecMult (DarcyVel, m_imPermeability[0], Vel);
372 const typename TBulkFVGeom::SCVF& scvf = bulk_geo.scvf (ip);
375 const number flux =
VecDot (DarcyVel, scvf.normal ()) * m_density;
378 d (_P_, scvf.from ()) += flux;
379 d (_P_, scvf.to ()) -= flux;
384template<
typename TDomain>
385template<
typename TElem>
394 const number half_fr_width = m_imAperture[0] / 2;
396 const size_t numSh = m_pFractGeo->num_sh ();
397 const size_t numScvf = m_pFractGeo->num_scvf ();
400 number vPressure [maxFractSideCorners];
401 for (
size_t sh = 0; sh < numSh; sh++)
402 vPressure [sh] = u (_P_, m_innerSideCo [sh]);
406 for (
size_t ip = 0; ip < numScvf; ip++)
409 this->
template compute_ip_velocity<TFractFVGeom> (Vel, ip, *m_pFractGeo, vPressure);
412 const typename TFractFVGeom::SCVF& scvf = m_pFractGeo->scvf (ip);
415 number flux =
VecDot (Vel, scvf.normal ()) * m_imFractPermeability[0]
416 * m_density * half_fr_width;
419 d (_P_, m_innerSideCo [scvf.from ()]) += flux;
420 d (_P_, m_innerSideCo [scvf.to ()]) -= flux;
425template<
typename TDomain>
426template<
typename TElem>
435 const number half_fr_width = m_imAperture[0] / 2;
439 if (m_imOrthoPermeability.data_given ())
440 orthPermeability = m_imOrthoPermeability[0];
444 MatVecMult (orthPermeabilityVec, m_imPermeability[0], m_unitOuterNormal);
445 orthPermeability =
VecDot (orthPermeabilityVec, m_unitOuterNormal);
449 for (
size_t ip = 0; ip < m_pFractGeo->num_scv (); ip++)
452 const typename TFractFVGeom::SCV& scv = m_pFractGeo->scv(ip);
455 const int co = m_innerSideCo [scv.node_id ()];
458 const number orthP_f = u (_P_, co);
459 const number orthP_m = u (_P_, m_assCo [co]);
462 const number orthVelocity = - (orthP_m - orthP_f) / half_fr_width
463 * orthPermeability / m_viscosity;
465 const number flux = orthVelocity * m_density * scv.volume();
467 d (_P_, m_assCo [co]) -= flux;
473template<
typename TDomain>
474template<
typename TFVGeom>
482 const typename TFVGeom::SCVF& scvf = geo.scvf (ip);
483 const size_t numSh = geo.num_sh ();
486 for (
size_t sh = 0; sh < numSh; sh++)
487 VecScale (Vel_p [sh], scvf.global_grad (sh), -1 / m_viscosity);
491template<
typename TDomain>
492template<
typename TElem,
typename TBulkFVGeom>
501 TElem * pElem =
static_cast<TElem*
> (elem);
505 this->
template bulk_ass_JA_elem<TElem, TBulkFVGeom> (J, u, pElem, vCornerCoords);
508 this->
template fract_ass_JA_elem<TElem> (J, u, pElem, vCornerCoords);
509 this->
template fract_bulk_ass_JA_elem<TElem> (J, u, pElem, vCornerCoords);
514template<
typename TDomain>
515template<
typename TElem,
typename TBulkFVGeom>
529 const size_t numScvf = bulk_geo.num_scvf();
533 for (
size_t ip = 0; ip < numScvf; ip++)
536 const typename TBulkFVGeom::SCVF& scvf = bulk_geo.scvf (ip);
539 this->
template compute_J_ip_velocity<TBulkFVGeom> (Vel_p, ip, bulk_geo);
542 for (
size_t sh = 0; sh < scvf.num_sh (); sh++)
544 MatVecMult (DarcyVel_p, m_imPermeability[0], Vel_p [sh]);
545 number DFlux_p =
VecDot (DarcyVel_p, scvf.normal ()) * m_density;
547 J (_P_, scvf.from (), _P_, sh) += DFlux_p;
548 J (_P_, scvf.to (), _P_, sh) -= DFlux_p;
554template<
typename TDomain>
555template<
typename TElem>
564 const number half_fr_width = m_imAperture[0] / 2;
566 const size_t numScvf = m_pFractGeo->num_scvf ();
570 for (
size_t ip = 0; ip < numScvf; ip++)
573 const typename TFractFVGeom::SCVF& scvf = m_pFractGeo->scvf(ip);
576 this->
template compute_J_ip_velocity<TFractFVGeom> (Vel_p, ip, *m_pFractGeo);
579 for (
size_t sh = 0; sh < scvf.num_sh(); sh++)
582 number DFlux_p =
VecDot (Vel_p [sh], scvf.normal ()) * m_imFractPermeability[0]
583 * m_density * half_fr_width;
586 size_t co = m_innerSideCo [sh];
587 size_t co_from = m_innerSideCo [scvf.from ()];
588 size_t co_to = m_innerSideCo [scvf.to ()];
591 J (_P_, co_from, _P_, co) += DFlux_p;
592 J (_P_, co_to, _P_, co) -= DFlux_p;
598template<
typename TDomain>
599template<
typename TElem>
608 const number half_fr_width = m_imAperture[0] / 2;
612 if (m_imOrthoPermeability.data_given ())
613 orthPermeability = m_imOrthoPermeability[0];
617 MatVecMult (orthPermeabilityVec, m_imPermeability[0], m_unitOuterNormal);
618 orthPermeability =
VecDot (orthPermeabilityVec, m_unitOuterNormal);
622 for (
size_t ip = 0; ip < m_pFractGeo->num_scv(); ip++)
625 const typename TFractFVGeom::SCV& scv = m_pFractGeo->scv (ip);
626 number s = scv.volume () * m_density;
629 const int co = m_innerSideCo [scv.node_id ()];
632 const number D_orthFlux_fr = orthPermeability / m_viscosity / half_fr_width *
s;
634 J(_P_, m_assCo [co], _P_, m_assCo [co]) += D_orthFlux_fr;
635 J(_P_, co, _P_, m_assCo [co]) -= D_orthFlux_fr;
637 J(_P_, m_assCo [co], _P_, co) -= D_orthFlux_fr;
638 J(_P_, co, _P_, co) += D_orthFlux_fr;
643template<
typename TDomain>
644template<
typename TElem,
typename TBulkFVGeom>
657template<
typename TDomain>
658template<
typename TElem,
typename TBulkFVGeom>
671template<
typename TDomain>
672template<
typename TElem,
typename TBulkFVGeom>
680 TElem * pElem =
static_cast<TElem*
> (elem);
685 this->
template bulk_ass_rhs_elem<TElem, TBulkFVGeom> (b, pElem, vCornerCoords);
689 this->
template fract_ass_rhs_elem<TElem> (b, pElem, vCornerCoords);
694template<
typename TDomain>
695template<
typename TElem,
typename TBulkFVGeom>
706 const size_t numScvf = bulk_geo.num_scvf ();
713 for (
size_t ip = 0; ip < numScvf; ip++)
716 const typename TBulkFVGeom::SCVF& scvf = bulk_geo.scvf (ip);
719 VecScale (Vel, m_Gravity, m_density / m_viscosity);
720 MatVecMult (DarcyVel, m_imPermeability[0], Vel);
723 number flux =
VecDot (DarcyVel, scvf.normal ()) * m_density;
726 b (_P_, scvf.from ()) -= flux;
727 b (_P_, scvf.to ()) += flux;
734template<
typename TDomain>
735template<
typename TElem>
743 const number half_fr_width = m_imAperture[0] / 2;
745 const size_t numScvf = m_pFractGeo->num_scvf ();
752 for (
size_t ip = 0; ip < numScvf; ip++)
755 const typename TFractFVGeom::SCVF& scvf = m_pFractGeo->scvf (ip);
758 VecScale (DarcyVel, m_Gravity, m_density * m_imFractPermeability[0] / m_viscosity);
761 number flux =
VecDot (DarcyVel, scvf.normal ()) * m_density * half_fr_width;
764 b (_P_, m_innerSideCo [scvf.from ()]) -= flux;
765 b (_P_, m_innerSideCo [scvf.to ()]) += flux;
776template<
typename TDomain>
777template<
typename TElem,
typename TBulkFVGeom>
782 this->clear_add_fct(
id);
784 this->set_prep_elem_loop_fct(
id, & this_type::template prepare_element_loop<TElem, TBulkFVGeom>);
785 this->set_prep_elem_fct (
id, & this_type::template prepare_element<TElem, TBulkFVGeom>);
786 this->set_fsh_elem_loop_fct (
id, & this_type::template finish_element_loop<TElem, TBulkFVGeom>);
787 this->set_add_jac_A_elem_fct(
id, & this_type::template ass_JA_elem<TElem, TBulkFVGeom>);
788 this->set_add_jac_M_elem_fct(
id, & this_type::template ass_JM_elem<TElem, TBulkFVGeom>);
789 this->set_add_def_A_elem_fct(
id, & this_type::template ass_dA_elem<TElem, TBulkFVGeom>);
790 this->set_add_def_M_elem_fct(
id, & this_type::template ass_dM_elem<TElem, TBulkFVGeom>);
791 this->set_add_rhs_elem_fct (
id, & this_type::template ass_rhs_elem<TElem, TBulkFVGeom>);
795template<
typename TDomain>
796template<
typename TElem>
799 if (! m_bCondensedFV)
800 this->register_loc_discr_func_with_fvgeom<TElem, FV1Geometry<TElem, dim> > ();
802 this->register_loc_discr_func_with_fvgeom<TElem, FV1CondensedGeometry<TElem, dim> > ();
810template<
typename TDomain>
814 m_bCondensedFV = condensed;
818 this->register_import (m_imPermeability);
820 this->register_import (m_imAperture);
821 this->register_import (m_imFractPermeability);
830template <
typename TDomain>
833 const char* functions,
837:
IElemDisc<TDomain> (functions, subsets),
838 m_imPermeability (false),
839 m_imAperture (false), m_imFractPermeability (false)
843 UG_THROW (
"Wrong number of functions: The ElemDisc 'FractPF_FV1'"
844 " needs exactly 1 symbolic function (for the pressure).");
853template <
typename TDomain>
856 const char* functions,
859:
IElemDisc<TDomain> (functions, subsets),
860 m_imPermeability (false),
861 m_imAperture (false), m_imFractPermeability (false)
865 UG_THROW (
"Wrong number of functions: The ElemDisc 'FractPF_FV1'"
866 " needs exactly 1 symbolic function (for the pressure).");
parameterString s
Definition Biogas.lua:2
virtual void local_to_global(MathVector< worldDim > &globPos, const MathVector< dim > &locPos) const=0
virtual void update(const MathVector< worldDim > *vCornerCoord)=0
void finish_element_loop()
finalizes the loop over the elements
Definition fract_pf_fv1_impl.h:152
void fract_ass_JA_elem(LocalMatrix &J, const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
computes the local stiffness matrix on a fracture element
Definition fract_pf_fv1_impl.h:557
void bulk_ass_dA_elem(LocalVector &d, const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
computes the stiffness part of the local defect on a bulk element
Definition fract_pf_fv1_impl.h:343
void fract_prepare_element_loop(ReferenceObjectID roid, int si)
prepares the loop over the elements: the 'fracture' version
Definition fract_pf_fv1_impl.h:126
void fract_ass_rhs_elem(LocalVector &d, TElem *elem, const position_type vCornerCoords[])
computes the right-hand side due to the gravitation and the mass sources
Definition fract_pf_fv1_impl.h:737
void prepare_element(const LocalVector &u, GridObject *elem, ReferenceObjectID roid, const position_type vCornerCoords[])
prepares a given element for assembling
Definition fract_pf_fv1_impl.h:160
void compute_J_ip_velocity(MathVector< dim > Vel_p[], size_t ip, const TFVGeom &geo)
computes the derivatives of the Darcy velocity (not scaled with the permeability)
Definition fract_pf_fv1_impl.h:476
void register_loc_discr_func_with_fvgeom()
registers the local assembler functions for a given element
Definition fract_pf_fv1_impl.h:778
void fract_prepare_element(const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
prepares a given fracture element for assembling
Definition fract_pf_fv1_impl.h:203
void fract_bulk_ass_JA_elem(LocalMatrix &J, const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
computes the local stiffness matrix of the fracture-bulk interaction terms on a fracture element
Definition fract_pf_fv1_impl.h:601
virtual void prepare_setting(const std::vector< LFEID > &vLfeID, bool bNonRegular)
check type of the grid and the trial space
Definition fract_pf_fv1_impl.h:37
void compute_ip_velocity(MathVector< dim > &Vel, size_t ip, const TFVGeom &bulk_geo, number vPressure[])
computes the pressure part of the Darcy velocity (not scaled with the permeability!...
Definition fract_pf_fv1_impl.h:296
void fract_bulk_ass_dA_elem(LocalVector &d, const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
computes the stiffness fracture-bulk interaction terms of the local defect on a fracture element
Definition fract_pf_fv1_impl.h:428
void ass_JA_elem(LocalMatrix &J, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the local stiffness matrix
Definition fract_pf_fv1_impl.h:494
FractPF_FV1(const char *functions, const char *subsets, bool condensed_FV)
class constructor
Definition fract_pf_fv1_impl.h:832
void prepare_element_loop(ReferenceObjectID roid, int si)
prepares the loop over the elements: checks whether the parameters are set, ...
Definition fract_pf_fv1_impl.h:65
void bulk_ass_JA_elem(LocalMatrix &J, const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
computes the local stiffness matrix on a bulk element
Definition fract_pf_fv1_impl.h:517
void bulk_prepare_element(const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
prepares a given bulk element for assembling
Definition fract_pf_fv1_impl.h:180
void bulk_ass_rhs_elem(LocalVector &d, TElem *elem, const position_type vCornerCoords[])
computes the right-hand side due to the gravitation and the mass sources
Definition fract_pf_fv1_impl.h:697
void register_discr_and_param(bool condensed)
calls functions for registering all the provided discretization functions and parameters
Definition fract_pf_fv1_impl.h:811
void ass_dA_elem(LocalVector &d, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the stiffness part of the local defect
Definition fract_pf_fv1_impl.h:318
void ass_dM_elem(LocalVector &d, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the mass part of the defect of a time-dependent problem
Definition fract_pf_fv1_impl.h:646
void bulk_prepare_element_loop(ReferenceObjectID roid, int si)
prepares the loop over the elements: the 'bulk' version
Definition fract_pf_fv1_impl.h:99
void ass_JM_elem(LocalMatrix &J, const LocalVector &u, GridObject *elem, const position_type vCornerCoords[])
computes the mass matrix of a time-dependent problem
Definition fract_pf_fv1_impl.h:660
void fract_ass_dA_elem(LocalVector &d, const LocalVector &u, TElem *elem, const position_type vCornerCoords[])
computes the stiffness part of the local defect on a fracture element
Definition fract_pf_fv1_impl.h:387
base_type::position_type position_type
position type
Definition fract_pf_fv1.h:72
void ass_rhs_elem(LocalVector &d, GridObject *elem, const position_type vCornerCoords[])
computes the right-hand side due to the gravitation and the mass sources
Definition fract_pf_fv1_impl.h:674
void register_loc_discr_func()
registers the local assembler functions for a given element
Definition fract_pf_fv1_impl.h:797
SmartPtr< TSubsetHandler > subset_handler()
const NullSmartPtr SPNULL
#define UG_CATCH_THROW(msg)
void MatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
vector_t::value_type VecLength(const vector_t &v)
void VecScaleAppend(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1)
void VecScale(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
Definition fract_pf_fv1.h:323