Plugins
Loading...
Searching...
No Matches
fract_pf_fv1_impl.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 Gesellschaft fuer Anlagen- und Reaktorsicherheit gGmbH
3 * SPDX-License-Identifier: EUPL-1.2
4 * SPDX-FileContributor: Dmitry Logashenko
5 * SPDX-FileContributor: Goethe Universität Frankfurt
6 * SPDX-FileType: SOURCE
7 *
8 * This file is part of d3f++.
9 * d3f++ is an extension for UG4. Licensing information and citation requirements of UG4 are provided in LICENSES/UG4-LGPL_2.1
10 */
11
12
13
14/*
15 * fract_pf_fv1_impl.h - class member implementation of the discretization of
16 * the FV-discretization of the pressure-driven flow in fractured porous media.
17 */
18/* UG4 headers: */
23#ifdef UG_FOR_LUA
25#endif
26
27namespace ug{
28namespace d3f{
29
31// Local discretization interface
33
35template<typename TDomain>
37(
38 const std::vector<LFEID> & vLfeID,
39 bool bNonRegular
40)
41{
42// check the grid
43 if (bNonRegular)
44 UG_THROW ("ERROR in FractPF_FV1:"
45 " The discretization does not support hanging nodes.\n");
46
47// check number of the components
48 if (vLfeID.size () != 1)
49 UG_THROW ("FractPF_FV1: The pressure driven flow requires one coponent in every vertex.");
50 /* one component for the real part and one for the imaginary part */
51
52// check whether these are the LagrangeP1 elements
53 if (vLfeID[0] != LFEID(LFEID::LAGRANGE, dim, 1))
54 UG_THROW ("FractPF_FV1: This discretization works with the LagrangeP1-elements only.");
55}
56
58// assembling
60
62template<typename TDomain>
63template<typename TElem, typename TBulkFVGeom>
65(
67 int si
68)
69{
70// check whether we are in a degenerated fracture
71 if (! m_spFractManager.valid())
72 m_isFracture = false;
73 else
74 {
75 if (! m_spFractManager->is_closed ())
76 UG_THROW ("FractPF_FV1: Fracture manager not closed");
77 m_isFracture = m_spFractManager->contains (si);
78 }
79
80// get the gravity
81 if (!m_imConstGravity.data_given())
82 UG_THROW ("FractPF_FV1: Missing Import 'gravity'.");
83 if (m_imConstGravity.constant())
84 (*m_imConstGravity.user_data()) (m_Gravity, MathVector<dim>(), 0.0, 0);
85 else
86 UG_THROW ("FractPF_FV1: Gravity must be constant.");
87
88// call the specific routine:
89 if (! m_isFracture)
90 this->template bulk_prepare_element_loop<TElem, TBulkFVGeom> (roid, si);
91 else
92 this->template fract_prepare_element_loop<TElem> (roid, si);
93}
94
96template<typename TDomain>
97template<typename TElem, typename TBulkFVGeom>
99(
100 ReferenceObjectID roid,
101 int si
102)
103{
104// invalidate the fracture subset imports for this (full-dim.) subset
105 m_imAperture.set_data (SPNULL);
106 m_imFractPermeability.set_data (SPNULL);
107 m_imOrthoPermeability.set_data (SPNULL);
108
109// check the imports
110 if (!m_imPermeability.data_given())
111 UG_THROW ("FractPF_FV1: Missing Import 'full-dim. permeability'.");
112
113// get the FV geometry
114 TBulkFVGeom& bulk_geo = GeomProvider<TBulkFVGeom>::get ();
115 static const int refDim = TElem::dim;
116
117// set local IP coordinates
118 const MathVector<refDim>* coe_local = bulk_geo.coe_local ();
119 m_imPermeability.template set_local_ips<refDim> (coe_local, 1, false);
120}
121
123template<typename TDomain>
124template<typename TElem>
126(
127 ReferenceObjectID roid,
128 int si
129)
130{
131// initialize the pointer to the FV geometry for fracture elements
132 m_pFractGeo = &GeomProvider<TFractFVGeom>::get (LFEID (LFEID::LAGRANGE, low_dim, 1), 1);
133
134// enable the fracture parameters for this subset
135 m_imAperture.set_data (m_spApertureData);
136 m_imFractPermeability.set_data (m_spFractPermeabilityData);
137 m_imOrthoPermeability.set_data (m_spOrthoPermeabilityData);
138
139// check the imports
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'.");
146 /* If m_imOrthoPermeability is not given, we use m_imPermeability. */
147}
148
150template<typename TDomain>
151template<typename TElem, typename TBulkFVGeom>
155
157template<typename TDomain>
158template<typename TElem, typename TBulkFVGeom>
160(
161 const LocalVector & u,
162 GridObject * elem,
163 ReferenceObjectID roid, // id of reference element used for assembling
164 const position_type vCornerCoords[]
165)
166{
167 TElem * pElem = static_cast<TElem*> (elem);
168
169// call the specific routine:
170 if (! m_isFracture)
171 this->template bulk_prepare_element<TElem, TBulkFVGeom> (u, pElem, vCornerCoords);
172 else
173 this->template fract_prepare_element<TElem> (u, pElem, vCornerCoords);
174}
175
177template<typename TDomain>
178template<typename TElem, typename TBulkFVGeom>
180(
181 const LocalVector & u,
182 TElem * elem,
183 const position_type vCornerCoords[]
184)
185{
186// update the FV geometry for this element
187 TBulkFVGeom& bulk_geo = GeomProvider<TBulkFVGeom>::get();
188 try
189 {
190 bulk_geo.update (elem, vCornerCoords, &(this->subset_handler()));
191 }
192 UG_CATCH_THROW("FractPF_FV1: Cannot update the Finite Volume Geometry for a bulk element.");
193
194// set global positions for user data
195 const MathVector<dim>* coe_global = bulk_geo.coe_global ();
196 m_imPermeability.set_global_ips (coe_global, 1);
197}
198
200template<typename TDomain>
201template<typename TElem>
203(
204 const LocalVector & u,
205 TElem * elem,
206 const position_type vCornerCoords[]
207)
208{
209 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
210 ref_elem_type& rRefElem = Provider<ref_elem_type>::get ();
211
212// get the non-degenerated sides of the fracture element
213 try
214 {
215 m_spFractManager->get_layer_sides
216 (elem,
217 m_numFractCo, m_innerFractSide, m_innerFractSideIdx, m_innerSideCo,
218 m_outerFractSide, m_outerFractSideIdx, m_outerSideCo,
219 m_assCo);
220 }
221 UG_CATCH_THROW("FractPF_FV1: Cannot find orientation of a fracture element.");
222
223// compute the FV geometry of the inner side
224 MathVector<dim> vSideCornerCoords [maxFractSideCorners];
225 try
226 {
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()));
230 }
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 ();
233
234// convert local coordinates of the side into the local coordinates of the element (for the input parameters)
235 MathVector<dim> vSideLocCornerCoords [maxFractSideCorners];
236 try
237 {
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);
243
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);
246 }
247 UG_CATCH_THROW("FractPF_FV1: Cannot transform local side coordinates to local element coordinates in a fracture element.");
248
249// get the geometric data of the outer side
250 MathVector<dim> loc_center_of_outer_sd, glob_center_of_outer_sd;
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++)
253 {
254 loc_center_of_outer_sd += rRefElem.corner (m_outerSideCo [co]);
255 glob_center_of_outer_sd += vCornerCoords [m_outerSideCo [co]];
256 }
257 loc_center_of_outer_sd /= m_numFractCo;
258 glob_center_of_outer_sd /= m_numFractCo;
259
260// set local IP coordinates
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);
265 else
266 m_imPermeability.template set_local_ips<dim> (&m_elem_loc_coe, 1);
267
268// set global positions for user data
269 const MathVector<dim>* coe_global = m_pFractGeo->coe_global ();
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);
274 else
275 m_imPermeability.set_global_ips (coe_global, 1);
276
277// set the correct subdomain for the bulk-fracture permeability interface
278//TODO: This would be a good idea to get the permeability from the interface
279// if (! m_imPermeability.data()->constant ()) // constant data are the same everywhere!
280// m_imPermeability.data()->set_subset
281// (this->subset_handler().get_subset_index (m_outerFractSide));
282//END TODO
283
284// compute the outer normal for the fracture side
285 SideNormal<ref_elem_type, dim> (m_unitOuterNormal, m_outerFractSideIdx, vCornerCoords);
286 const number outerNormalNorm = VecLength (m_unitOuterNormal);
287 if (outerNormalNorm < 1e-32)
288 UG_THROW ("FractPF_FV1: Cannot get the normal to a fracture.")
289 m_unitOuterNormal /= outerNormalNorm;
290}
291
293template<typename TDomain>
294template<typename TFVGeom>
296(
297 MathVector<dim>& Vel,
298 size_t ip,
299 const TFVGeom& geo,
300 number vPressure[]
301)
302{
303 const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
304
305// The pressure-gradient part:
306 Vel = 0.0;
307 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
308 VecScaleAppend (Vel, - vPressure[sh], scvf.global_grad(sh));
309
310// The viscosity factor:
311 Vel /= m_viscosity;
312}
313
315template<typename TDomain>
316template<typename TElem, typename TBulkFVGeom>
318(
319 LocalVector & d,
320 const LocalVector & u,
321 GridObject * elem,
322 const position_type vCornerCoords[]
323)
324{
325 TElem * pElem = static_cast<TElem*> (elem);
326
327// call the specific routine:
328 if (! m_isFracture)
329 {
330 this->template bulk_ass_dA_elem<TElem, TBulkFVGeom> (d, u, pElem, vCornerCoords);
331 }
332 else
333 {
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);
336 }
337}
338
340template<typename TDomain>
341template<typename TElem, typename TBulkFVGeom>
343(
344 LocalVector & d,
345 const LocalVector & u,
346 TElem * pElem,
347 const position_type vCornerCoords[]
348)
349{
350 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
351
352// Get finite volume geometry
353 const TBulkFVGeom& bulk_geo = GeomProvider<TBulkFVGeom>::get ();
354
355 const size_t numSh = bulk_geo.num_sh ();
356 const size_t numScvf = bulk_geo.num_scvf ();
357
358// Get the corner pressure
359 number vPressure [ref_elem_type::numCorners];
360 for (size_t sh = 0; sh < numSh; sh++)
361 vPressure [sh] = u (_P_, sh);
362
363// Loop Sub Control Volume Faces (SCVF)
364 MathVector<dim> Vel, DarcyVel;
365 for (size_t ip = 0; ip < numScvf; ip++)
366 {
367 // Compute the Darcy velocity at the ips and the convection shapes
368 this->template compute_ip_velocity<TBulkFVGeom> (Vel, ip, bulk_geo, vPressure);
369 MatVecMult (DarcyVel, m_imPermeability[0], Vel);
370
371 // Get current SCVF
372 const typename TBulkFVGeom::SCVF& scvf = bulk_geo.scvf (ip);
373
374 // Compute flux
375 const number flux = VecDot (DarcyVel, scvf.normal ()) * m_density;
376
377 // Add contribution to flow equation
378 d (_P_, scvf.from ()) += flux;
379 d (_P_, scvf.to ()) -= flux;
380 }
381}
382
384template<typename TDomain>
385template<typename TElem>
387(
388 LocalVector & d,
389 const LocalVector & u,
390 TElem * pElem,
391 const position_type vCornerCoords[]
392)
393{
394 const number half_fr_width = m_imAperture[0] / 2;
395
396 const size_t numSh = m_pFractGeo->num_sh ();
397 const size_t numScvf = m_pFractGeo->num_scvf ();
398
399// Get the corner values
400 number vPressure [maxFractSideCorners];
401 for (size_t sh = 0; sh < numSh; sh++)
402 vPressure [sh] = u (_P_, m_innerSideCo [sh]);
403
404// Loop Sub Control Volume Faces (SCVF)
405 MathVector<dim> Vel;
406 for (size_t ip = 0; ip < numScvf; ip++)
407 {
408 // Compute the Darcy velocity at the ips and the convection shapes
409 this->template compute_ip_velocity<TFractFVGeom> (Vel, ip, *m_pFractGeo, vPressure);
410
411 // Get current SCVF
412 const typename TFractFVGeom::SCVF& scvf = m_pFractGeo->scvf (ip);
413
414 // Compute flux
415 number flux = VecDot (Vel, scvf.normal ()) * m_imFractPermeability[0]
416 * m_density * half_fr_width;
417
418 // Add contribution to flow equation
419 d (_P_, m_innerSideCo [scvf.from ()]) += flux;
420 d (_P_, m_innerSideCo [scvf.to ()]) -= flux;
421 }
422}
423
425template<typename TDomain>
426template<typename TElem>
428(
429 LocalVector & d,
430 const LocalVector & u,
431 TElem * pElem,
432 const position_type vCornerCoords[]
433)
434{
435 const number half_fr_width = m_imAperture[0] / 2;
436
437// the permeability of the fracture-bulk interface
438 number orthPermeability;
439 if (m_imOrthoPermeability.data_given ())
440 orthPermeability = m_imOrthoPermeability[0];
441 else
442 {
443 MathVector<dim> orthPermeabilityVec;
444 MatVecMult (orthPermeabilityVec, m_imPermeability[0], m_unitOuterNormal);
445 orthPermeability = VecDot (orthPermeabilityVec, m_unitOuterNormal);
446 }
447
448// loop over the corners of the inner side
449 for (size_t ip = 0; ip < m_pFractGeo->num_scv (); ip++)
450 {
451 // Get current SCV
452 const typename TFractFVGeom::SCV& scv = m_pFractGeo->scv(ip);
453
454 // Get associated node of the element (not side!)
455 const int co = m_innerSideCo [scv.node_id ()];
456
457 // Get the corner values
458 const number orthP_f = u (_P_, co);
459 const number orthP_m = u (_P_, m_assCo [co]);
460
461 // Flux velocity between the fracture and the bulk medium
462 const number orthVelocity = - (orthP_m - orthP_f) / half_fr_width
463 * orthPermeability / m_viscosity;
464
465 const number flux = orthVelocity * m_density * scv.volume();
466
467 d (_P_, m_assCo [co]) -= flux;
468 d (_P_, co) += flux;
469 }
470}
471
473template<typename TDomain>
474template<typename TFVGeom>
476(
477 MathVector<dim> Vel_p[],
478 size_t ip,
479 const TFVGeom& geo
480)
481{
482 const typename TFVGeom::SCVF& scvf = geo.scvf (ip);
483 const size_t numSh = geo.num_sh ();
484
485// Compute the derivatives of rho g - grad p, multiplied by the viscosity
486 for (size_t sh = 0; sh < numSh; sh++)
487 VecScale (Vel_p [sh], scvf.global_grad (sh), -1 / m_viscosity);
488}
489
491template<typename TDomain>
492template<typename TElem, typename TBulkFVGeom>
494(
495 LocalMatrix & J,
496 const LocalVector & u,
497 GridObject * elem,
498 const position_type vCornerCoords []
499)
500{
501 TElem * pElem = static_cast<TElem*> (elem);
502
503// call the specific routine:
504 if (! m_isFracture)
505 this->template bulk_ass_JA_elem<TElem, TBulkFVGeom> (J, u, pElem, vCornerCoords);
506 else
507 {
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);
510 }
511}
512
514template<typename TDomain>
515template<typename TElem, typename TBulkFVGeom>
517(
518 LocalMatrix & J,
519 const LocalVector & u,
520 TElem * pElem,
521 const position_type vCornerCoords[]
522)
523{
524 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
525
526 // get finite volume geometry
527 const TBulkFVGeom& bulk_geo = GeomProvider<TBulkFVGeom>::get();
528
529 const size_t numScvf = bulk_geo.num_scvf();
530
531// Loop Sub Control Volume Faces (SCVF)
532 MathVector<dim> Vel_p [ref_elem_type::numCorners], DarcyVel_p;
533 for (size_t ip = 0; ip < numScvf; ip++)
534 {
535 // Get current SCVF
536 const typename TBulkFVGeom::SCVF& scvf = bulk_geo.scvf (ip);
537
538 // compute derivatives of the Darcy velocity
539 this->template compute_J_ip_velocity<TBulkFVGeom> (Vel_p, ip, bulk_geo);
540
541 // add the flux contribution to the stiffness matrix
542 for (size_t sh = 0; sh < scvf.num_sh (); sh++)
543 {
544 MatVecMult (DarcyVel_p, m_imPermeability[0], Vel_p [sh]);
545 number DFlux_p = VecDot (DarcyVel_p, scvf.normal ()) * m_density;
546
547 J (_P_, scvf.from (), _P_, sh) += DFlux_p;
548 J (_P_, scvf.to (), _P_, sh) -= DFlux_p;
549 }
550 }
551}
552
554template<typename TDomain>
555template<typename TElem>
557(
558 LocalMatrix & J,
559 const LocalVector & u,
560 TElem * pElem,
561 const position_type vCornerCoords[]
562)
563{
564 const number half_fr_width = m_imAperture[0] / 2;
565
566 const size_t numScvf = m_pFractGeo->num_scvf ();
567
568// Loop Sub Control Volume Faces (SCVF)
569 MathVector<dim> Vel_p [maxFractSideCorners];
570 for (size_t ip = 0; ip < numScvf; ip++)
571 {
572 // get current SCVF
573 const typename TFractFVGeom::SCVF& scvf = m_pFractGeo->scvf(ip);
574
575 // compute the Jacobian of the Darcy velocity
576 this->template compute_J_ip_velocity<TFractFVGeom> (Vel_p, ip, *m_pFractGeo);
577
578 // add the flux contribution to the stiffness matrix
579 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
580 {
581 // get the derivative of the flux
582 number DFlux_p = VecDot (Vel_p [sh], scvf.normal ()) * m_imFractPermeability[0]
583 * m_density * half_fr_width;
584
585 // get the connection indices
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 ()];
589
590 // add to the matrix
591 J (_P_, co_from, _P_, co) += DFlux_p;
592 J (_P_, co_to, _P_, co) -= DFlux_p;
593 }
594 }
595}
596
598template<typename TDomain>
599template<typename TElem>
601(
602 LocalMatrix & J,
603 const LocalVector & u,
604 TElem * pElem,
605 const position_type vCornerCoords[]
606)
607{
608 const number half_fr_width = m_imAperture[0] / 2;
609
610// the permeability of the fracture-bulk interface
611 number orthPermeability;
612 if (m_imOrthoPermeability.data_given ())
613 orthPermeability = m_imOrthoPermeability[0];
614 else
615 {
616 MathVector<dim> orthPermeabilityVec;
617 MatVecMult (orthPermeabilityVec, m_imPermeability[0], m_unitOuterNormal);
618 orthPermeability = VecDot (orthPermeabilityVec, m_unitOuterNormal);
619 }
620
621// loop over the corners of the inner side
622 for (size_t ip = 0; ip < m_pFractGeo->num_scv(); ip++)
623 {
624 // get current SCV
625 const typename TFractFVGeom::SCV& scv = m_pFractGeo->scv (ip);
626 number s = scv.volume () * m_density;
627
628 // get associated node of the element (not side!)
629 const int co = m_innerSideCo [scv.node_id ()];
630
631 // Flux velocity between the fracture and the bulk medium
632 const number D_orthFlux_fr = orthPermeability / m_viscosity / half_fr_width * s;
633
634 J(_P_, m_assCo [co], _P_, m_assCo [co]) += D_orthFlux_fr;
635 J(_P_, co, _P_, m_assCo [co]) -= D_orthFlux_fr;
636
637 J(_P_, m_assCo [co], _P_, co) -= D_orthFlux_fr;
638 J(_P_, co, _P_, co) += D_orthFlux_fr;
639 }
640}
641
643template<typename TDomain>
644template<typename TElem, typename TBulkFVGeom>
646(
647 LocalVector & d,
648 const LocalVector & u,
649 GridObject * elem,
650 const position_type vCornerCoords[]
651)
652{
653 // Nothing to do: FractPF_FV1 discretizes a stationary equation. No mass matrix!
654}
655
657template<typename TDomain>
658template<typename TElem, typename TBulkFVGeom>
660(
661 LocalMatrix & J,
662 const LocalVector & u,
663 GridObject * elem,
664 const position_type vCornerCoords[]
665)
666{
667 // Nothing to do: FractPF_FV1 discretizes a stationary equation. No mass matrix!
668}
669
671template<typename TDomain>
672template<typename TElem, typename TBulkFVGeom>
674(
675 LocalVector & b,
676 GridObject * elem,
677 const position_type vCornerCoords[]
678)
679{
680 TElem * pElem = static_cast<TElem*> (elem);
681
682// call the specific routine:
683 if (! m_isFracture)
684 {
685 this->template bulk_ass_rhs_elem<TElem, TBulkFVGeom> (b, pElem, vCornerCoords);
686 }
687 else
688 {
689 this->template fract_ass_rhs_elem<TElem> (b, pElem, vCornerCoords);
690 }
691}
692
694template<typename TDomain>
695template<typename TElem, typename TBulkFVGeom>
697(
698 LocalVector & b,
699 TElem * elem,
700 const position_type vCornerCoords[]
701)
702{
703// Get finite volume geometry
704 const TBulkFVGeom& bulk_geo = GeomProvider<TBulkFVGeom>::get ();
705
706 const size_t numScvf = bulk_geo.num_scvf ();
707
708// the gravity part
709// REMARK: Note that for for inner nodes, these contributions shoul sum up
710// to 0 (because the density is constant). The only non-zero gravity
711// right-hand sides may remain at the Neumann (or similar) boundaries:
712 MathVector<dim> Vel, DarcyVel;
713 for (size_t ip = 0; ip < numScvf; ip++)
714 {
715 // Get current SCVF
716 const typename TBulkFVGeom::SCVF& scvf = bulk_geo.scvf (ip);
717
718 // Compute K (rho * g) / mu
719 VecScale (Vel, m_Gravity, m_density / m_viscosity);
720 MatVecMult (DarcyVel, m_imPermeability[0], Vel);
721
722 // Compute flux
723 number flux = VecDot (DarcyVel, scvf.normal ()) * m_density;
724
725 // Add contribution to the rhs of the flow equation
726 b (_P_, scvf.from ()) -= flux;
727 b (_P_, scvf.to ()) += flux;
728 }
729
730// mass sources
731}
732
734template<typename TDomain>
735template<typename TElem>
737(
738 LocalVector & b,
739 TElem * elem,
740 const position_type vCornerCoords[]
741)
742{
743 const number half_fr_width = m_imAperture[0] / 2;
744
745 const size_t numScvf = m_pFractGeo->num_scvf ();
746
747// the gravity part
748// REMARK: Note that for for inner nodes, these contributions shoul sum up
749// to 0 (because the density is constant). The only non-zero gravity
750// right-hand sides may remain at the Neumann (or similar) boundaries:
751 MathVector<dim> DarcyVel;
752 for (size_t ip = 0; ip < numScvf; ip++)
753 {
754 // Get current SCVF
755 const typename TFractFVGeom::SCVF& scvf = m_pFractGeo->scvf (ip);
756
757 // Compute K (rho * g) / mu
758 VecScale (DarcyVel, m_Gravity, m_density * m_imFractPermeability[0] / m_viscosity);
759
760 // Compute flux
761 number flux = VecDot (DarcyVel, scvf.normal ()) * m_density * half_fr_width;
762
763 // Add contribution to flow equation
764 b (_P_, m_innerSideCo [scvf.from ()]) -= flux;
765 b (_P_, m_innerSideCo [scvf.to ()]) += flux;
766 }
767
768// mass sources
769}
770
772// register assembling functions
774
776template<typename TDomain>
777template<typename TElem, typename TBulkFVGeom> // the element to register for and its full-dim. FV geometry
779{
781
782 this->clear_add_fct(id);
783
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>);
792}
793
795template<typename TDomain>
796template<typename TElem> // the element to register for
798{
799 if (! m_bCondensedFV)
800 this->register_loc_discr_func_with_fvgeom<TElem, FV1Geometry<TElem, dim> > ();
801 else
802 this->register_loc_discr_func_with_fvgeom<TElem, FV1CondensedGeometry<TElem, dim> > ();
803}
804
806// register assembling functions & parameters
808
810template<typename TDomain>
812{
813// initilize the 'condensed scvf ip' flag
814 m_bCondensedFV = condensed;
815
816// register imports
817
818 this->register_import (m_imPermeability);
819
820 this->register_import (m_imAperture);
821 this->register_import (m_imFractPermeability);
822
823// register the local assembling functions
824 boost::mpl::for_each<AssembleElemList> (RegisterLocalDiscr (this));
825}
826
830template <typename TDomain>
832(
833 const char* functions,
834 const char* subsets,
835 bool condensed_FV
836)
837: IElemDisc<TDomain> (functions, subsets),
838 m_imPermeability (false),
839 m_imAperture (false), m_imFractPermeability (false)
840{
841// check number of functions
842 if (this->num_fct () != 1)
843 UG_THROW ("Wrong number of functions: The ElemDisc 'FractPF_FV1'"
844 " needs exactly 1 symbolic function (for the pressure).");
845
846// register functions and data
847 this->register_discr_and_param (condensed_FV);
848};
849
853template <typename TDomain>
855(
856 const char* functions,
857 const char* subsets
858)
859: IElemDisc<TDomain> (functions, subsets),
860 m_imPermeability (false),
861 m_imAperture (false), m_imFractPermeability (false)
862{
863// check number of functions
864 if (this->num_fct () != 1)
865 UG_THROW ("Wrong number of functions: The ElemDisc 'FractPF_FV1'"
866 " needs exactly 1 symbolic function (for the pressure).");
867
868// register functions and data
869 this->register_discr_and_param (false);
870};
871
872} // namespace d3f
873} // end namespace ug
874
875/* End of File */
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
static TGeom & get()
size_t num_fct() const
static TClass & get()
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)
#define UG_THROW(msg)
double number
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)
ReferenceObjectID
Definition fract_pf_fv1.h:323