LifeV
darcy/examples/twophase_impes/user_fun.cpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*-
2 
3  This file is part of the LifeV Applications.
4 
5  Author(s): A. Fumagalli <alessio.fumagalli@mail.polimi.it>
6  Date: 2010-07-29
7 
8  Copyright (C) 2010 EPFL, Politecnico di Milano
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2.1 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful, but
16  WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23  USA
24 */
25 
26 /**
27  @file user_fun.cpp
28  @author A. Fumagalli <alessio.fumagalli@mail.polimi.it>
29  @date 2010-07-29
30 */
31 
32 #include "user_fun.hpp"
33 
34 // ===================================================
35 //! User functions for the pressure equation
36 // ===================================================
37 namespace dataProblem
38 {
39 
40 namespace dataPhysical
41 {
42 
43 // Porosity
44 Real Phi ( const Real& /* x */, const Real& /* y */, const Real& /* z */ )
45 {
46  return 0.4;
47 }
48 
49 // Relative permeability for the wetting phase
50 Real k_rw ( const Real& S_w )
51 {
52  // Define the effective saturation
53  const Real barS_w = (S_w - S_wr) / (1. - S_wr - S_nr);
54 
55  return std::pow ( barS_w, (2. + 3.*lambda) / lambda );
56 }
57 
58 // First derivative of the relative permeability for the wetting phase
59 Real Dk_rw ( const Real& S_w )
60 {
61  // Define the effective saturation
62  const Real barS_w = (S_w - S_wr) / (1. - S_wr - S_nr);
63 
64  return (2. + 3.*lambda) / lambda * std::pow (barS_w, (2. + 3.*lambda) / lambda - 1.) / (1. - S_wr - S_nr);
65 }
66 
67 // Relative permeability for the non-wetting phase
68 Real k_rn ( const Real& S_n )
69 {
70  // Define the effective saturation
71  const Real barS_n = (S_n - S_nr) / (1. - S_wr - S_nr);
72 
73  return std::pow ( barS_n, 2.) * (1 - std::pow ( 1 - barS_n, (2. + lambda) / lambda) );
74 }
75 
76 // First derivative of the relative permeability for the non-wetting phase
77 Real Dk_rn ( const Real& S_n )
78 {
79  // Define the effective saturation
80  const Real barS_n = (S_n - S_nr) / (1. - S_wr - S_nr);
81 
82  return ( 2.*barS_n * (1 - std::pow ( 1 - barS_n, (2. + lambda) / lambda) ) -
83  std::pow ( barS_n, 2.) * (2. + lambda) / lambda * std::pow (1 - barS_n, (2. + lambda) / lambda - 1.) ) /
84  (1. - S_wr - S_nr);
85 }
86 
87 // Capillary pressure
88 Real pc ( const Real& S_w ) // [Pa]
89 {
90  // Define the effective saturation
91  const Real barS_w = (S_w - S_wr) / (1. - S_wr - S_nr);
92 
93  return pd * std::pow (barS_w, -1. / lambda);
94 }
95 
96 // First derivative of the capillary pressure
97 Real Dpc ( const Real& S_w ) // [Pa]
98 {
99  // Define the effective saturation
100  const Real barS_w = (S_w - S_wr) / (1. - S_wr - S_nr);
101 
102  return pd / lambda * std::pow (barS_w, -1. / lambda - 1.) / (1. - S_wr - S_nr);
103 }
104 
105 // Absolute inverse permeability
106 const Matrix invK ( const Real& /* t */, const Real& x, const Real& y, const Real& /* z */ ) // [m^2]
107 {
108  Matrix inversePermeabilityMatrix ( static_cast<UInt> (3), static_cast<UInt> (3) );
109 
110  const Real highInvPermeability = 1e5;
111  const Real lowInvPermeability = 1.;
112 
113  Real Entry00, Entry01, Entry02, Entry11, Entry12, Entry22;
114 
115  if ( ( (x > 1000) && (x < 1250) && (y > 0) && (y < 1250) )
116  || ( (x > 2250) && (x < 2500) && (y > 1000) && (y < 3000) )
117  || ( (x > 3500) && (x < 3750) && (y > 500) && (y < 3000) ) )
118  {
119  // First row
120  Entry00 = highInvPermeability;
121  Entry01 = 0.;
122  Entry02 = 0.;
123 
124  // Second row
125  Entry11 = highInvPermeability;
126  Entry12 = 0.;
127 
128  // Third row
129  Entry22 = highInvPermeability;
130 
131  }
132  else
133  {
134  // First row
135  Entry00 = lowInvPermeability;
136  Entry01 = 0.;
137  Entry02 = 0.;
138 
139  // Second row
140  Entry11 = lowInvPermeability;
141  Entry12 = 0.;
142 
143  // Third row
144  Entry22 = lowInvPermeability;
145  }
146 
147  // Fill in of the inversePermeabilityMatrix
148  inversePermeabilityMatrix ( static_cast<UInt> (0), static_cast<UInt> (0) ) = Entry00;
149  inversePermeabilityMatrix ( static_cast<UInt> (0), static_cast<UInt> (1) ) = Entry01;
150  inversePermeabilityMatrix ( static_cast<UInt> (0), static_cast<UInt> (2) ) = Entry02;
151  inversePermeabilityMatrix ( static_cast<UInt> (1), static_cast<UInt> (0) ) = Entry01;
152  inversePermeabilityMatrix ( static_cast<UInt> (1), static_cast<UInt> (1) ) = Entry11;
153  inversePermeabilityMatrix ( static_cast<UInt> (1), static_cast<UInt> (2) ) = Entry12;
154  inversePermeabilityMatrix ( static_cast<UInt> (2), static_cast<UInt> (0) ) = Entry02;
155  inversePermeabilityMatrix ( static_cast<UInt> (2), static_cast<UInt> (1) ) = Entry12;
156  inversePermeabilityMatrix ( static_cast<UInt> (2), static_cast<UInt> (2) ) = Entry22;
157 
158  return inversePermeabilityMatrix;
159 
160 }
161 
162 
163 }
164 
165 
166 // Inverse of permeability matrix
167 /* In this case the permeability matrix is
168  K = [2 1 0
169  1 1 0
170  0 0 1]
171 */
172 Matrix pressurePermeability ( const Real& t,
173  const Real& x,
174  const Real& y,
175  const Real& z,
176  const std::vector<Real>& u )
177 {
178 
179  // Alias for the non-wetting phase saturation
180  const Real& S_n = u[0];
181 
182  // Compute the phase mobility
183  const Real lambda_w = dataPhysical::k_rw ( 1. - S_n ) / dataPhysical::mu_w;
184  const Real lambda_n = dataPhysical::k_rn ( S_n ) / dataPhysical::mu_n;
185 
186  return - dataPhysical::invK (t, x, y, z) / ( lambda_n + lambda_w );
187 }
188 
189 // Source term
190 Real pressureSource ( const Real& /* t */,
191  const Real& /* x */,
192  const Real& /* y */,
193  const Real& /* z */,
194  const ID& /* icomp */)
195 {
196  return 0.;
197 }
198 
199 // Boundary condition of Dirichlet
200 Real pressureDirichlet1 ( const Real& /* t */,
201  const Real& /* x */,
202  const Real& /* y */,
203  const Real& /* z */,
204  const ID& /* icomp */)
205 {
206  return 11000000.;
207 }
208 
209 // Boundary condition of Dirichlet
210 Real pressureDirichlet2 ( const Real& /* t */,
211  const Real& /* x */,
212  const Real& /* y */,
213  const Real& /* z */,
214  const ID& /* icomp */)
215 {
216  return 10000000.;
217 }
218 
219 // Boundary conditisaturationDirichletBDfunon of Dirichlet
220 Real pressureDirichlet3 ( const Real& /* t */,
221  const Real& /* x */,
222  const Real& /* y */,
223  const Real& /* z */,
224  const ID& /* icomp */)
225 {
226  return 10500000.;
227 }
228 
229 // Boundary condition of Neumann
230 Real pressureNeumann ( const Real& /* t */,
231  const Real& x,
232  const Real& y,
233  const Real& /* z */,
234  const ID& icomp)
235 {
236  return 0.;
237 
238  switch (icomp)
239  {
240  case 0: //! Dx
241  return -1.* (4.*x * y * y + 2.*x * x * y + 12.);
242  break;
243  case 1: //! Dy
244  return 0.;
245  break;
246  case 2: //! Dz
247  return 0.;
248  break;
249  }
250  return 0.;
251 }
252 
253 // Boundary condition of Robin
254 Real pressureRobin ( const Real& /* t */,
255  const Real& /* x */,
256  const Real& /* y */,
257  const Real& /* z */,
258  const ID& /* icomp */)
259 {
260  return 0.;
261 }
262 
263 
264 
265 // ===================================================
266 //! User functions for the saturation equation
267 // ===================================================
268 
269 // Inverse of permeability matrix
270 /* In this case the permeability matrix is
271 K = [p^2+2 1 0
272  1 1 0
273  0 0 2]
274 */
275 Matrix saturationPermeability ( const Real& t,
276  const Real& x,
277  const Real& y,
278  const Real& z,
279  const std::vector<Real>& u )
280 {
281  // Alias for the non-wetting phase saturation
282  const Real& S_n = u[0];
283 
284  // Compute the phase mobility
285  const Real lambda_w = dataPhysical::k_rw ( 1. - S_n ) / dataPhysical::mu_w;
286  const Real lambda_n = dataPhysical::k_rn ( S_n ) / dataPhysical::mu_n;
287 
288  // Compute the fractional flow
289  const Real f_n = lambda_n / ( lambda_w + lambda_n );
290 
291  return - dataPhysical::invK (t, x, y, z) / ( lambda_w * f_n * dataPhysical::Dpc ( 1. - S_n ) ) ;
292 }
293 
294 // Physical flux function
295 Vector saturationPhysicalFlux ( const Real& t,
296  const Real& x,
297  const Real& y,
298  const Real& z,
299  const std::vector<Real>& u )
300 {
301  Vector physicalFluxVector ( static_cast<UInt> (3) );
302 
303  // Alias for the non-wetting phase saturation
304  const Real& S_n = u[0];
305 
306  // Compute the phase mobility
307  const Real lambda_w = dataPhysical::k_rw ( 1. - S_n ) / dataPhysical::mu_w;
308  const Real lambda_n = dataPhysical::k_rn ( S_n ) / dataPhysical::mu_n;
309 
310  // Compute the fractional flow
311  const Real f_n = lambda_n / ( lambda_w + lambda_n );
312 
313  // Compute the last column of the inverse of the inverse permeability
314  const Matrix invK = dataPhysical::invK ( t, x, y, z );
315 
316  // Compute the denominator of the last column of the inverse of the inverse permeability
317  const Real denominator = invK (0, 0) * invK (1, 1) * invK (2, 2)
318  - invK (0, 0) * invK (1, 2) * invK (1, 2)
319  - invK (0, 1) * invK (0, 1) * invK (2, 2)
320  + 2. * invK (0, 1) * invK (0, 2) * invK (1, 2)
321  - invK (0, 2) * invK (0, 2) * invK (1, 1);
322 
323  // Compute the first component of the last column of the inverse of the inverse permeability
324  const Real K02 = ( invK (0, 1) * invK (1, 2) - invK (0, 2) * invK (1, 1) ) / denominator;
325 
326  // Compute the second component of the last column of the inverse of the inverse permeability
327  const Real K12 = ( invK (0, 0) * invK (1, 2) - invK (0, 1) * invK (0, 2) ) / denominator;
328 
329  // Compute the third component of the last column of the inverse of the inverse permeability
330  const Real K22 = ( invK (0, 0) * invK (1, 1) - invK (0, 1) * invK (0, 1) ) / denominator;
331 
332  // Compute a common constant
333  const Real lfrg = lambda_w * f_n * (dataPhysical::rho_w - dataPhysical::rho_n) * dataPhysical::g;
334 
335  // First row
336  const Real Entry0 = f_n * u[1] - lfrg * K02;
337 
338  // Second row
339  const Real Entry1 = f_n * u[2] - lfrg * K12;
340 
341  // Third row
342  const Real Entry2 = f_n * u[3] - lfrg * K22;
343 
344  physicalFluxVector ( static_cast<UInt> (0) ) = Entry0;
345  physicalFluxVector ( static_cast<UInt> (1) ) = Entry1;
346  physicalFluxVector ( static_cast<UInt> (2) ) = Entry2;
347 
348  return physicalFluxVector;
349 }
350 
351 // First derivative in u of the physical flux function
352 Vector saturationFirstDerivativePhysicalFlux ( const Real& t,
353  const Real& x,
354  const Real& y,
355  const Real& z,
356  const std::vector<Real>& u )
357 {
358  Vector firstDerivativePhysicalFluxVector ( static_cast<UInt> (3) );
359 
360  // Alias for the non-wetting phase saturation
361  const Real& S_n = u[0];
362 
363  // Compute the phase mobility
364  const Real lambda_w = dataPhysical::k_rw ( 1. - S_n ) / dataPhysical::mu_w;
365  const Real lambda_n = dataPhysical::k_rn ( S_n ) / dataPhysical::mu_n;
366 
367  // Compute the first derivative of the phase mobility
368  const Real Dlambda_w = dataPhysical::Dk_rw ( 1. - S_n ) / dataPhysical::mu_w;
369  const Real Dlambda_n = dataPhysical::Dk_rn ( S_n ) / dataPhysical::mu_n;
370 
371  // Compute the fractional flow
372  const Real f_n = lambda_n / ( lambda_w + lambda_n );
373 
374  // Compute the first derivative of the fractional flow
375  const Real Df_n = (Dlambda_w * (lambda_w + lambda_n) - lambda_w * (Dlambda_w + Dlambda_n) ) /
376  std::pow (lambda_w + lambda_n, 2);
377 
378  // Compute the last column of the inverse of the inverse permeability
379  const Matrix invK = dataPhysical::invK ( t, x, y, z );
380 
381  // Compute the denominator of the last column of the inverse of the inverse permeability
382  const Real denominator = invK (0, 0) * invK (1, 1) * invK (2, 2)
383  - invK (0, 0) * invK (1, 2) * invK (1, 2)
384  - invK (0, 1) * invK (0, 1) * invK (2, 2)
385  + 2. * invK (0, 1) * invK (0, 2) * invK (1, 2)
386  - invK (0, 2) * invK (0, 2) * invK (1, 1);
387 
388  // Compute the first component of the last column of the inverse of the inverse permeability
389  const Real K02 = ( invK (0, 1) * invK (1, 2) - invK (0, 2) * invK (1, 1) ) / denominator;
390 
391  // Compute the second component of the last column of the inverse of the inverse permeability
392  const Real K12 = ( invK (0, 0) * invK (1, 2) - invK (0, 1) * invK (0, 2) ) / denominator;
393 
394  // Compute the third component of the last column of the inverse of the inverse permeability
395  const Real K22 = ( invK (0, 0) * invK (1, 1) - invK (0, 1) * invK (0, 1) ) / denominator;
396 
397  // Compute a common constant
398  const Real lfrg = (Dlambda_w * f_n + lambda_w * Df_n) * (dataPhysical::rho_w - dataPhysical::rho_n) * dataPhysical::g;
399 
400  // First row
401  Real Entry0 = u[1] * Df_n - lfrg * K02;
402 
403  // Second row
404  Real Entry1 = u[2] * Df_n - lfrg * K12;
405 
406  // Third row
407  Real Entry2 = u[3] * Df_n - lfrg * K22;
408 
409  firstDerivativePhysicalFluxVector ( static_cast<UInt> (0) ) = Entry0;
410  firstDerivativePhysicalFluxVector ( static_cast<UInt> (1) ) = Entry1;
411  firstDerivativePhysicalFluxVector ( static_cast<UInt> (2) ) = Entry2;
412 
413  return firstDerivativePhysicalFluxVector;
414 }
415 
416 // Source term
417 Real saturationSource ( const Real& /* t */,
418  const Real& /* x */,
419  const Real& /* y */,
420  const Real& /* z */,
421  const ID& /* icomp */)
422 {
423  return 0.;
424 }
425 
426 // Initial condition
427 Real saturationInitialCondition ( const Real& /* t */,
428  const Real& /* x */,
429  const Real& /* y */,
430  const Real& /* z */,
431  const ID& /* icomp */ )
432 {
433  return 0.1;
434 }
435 
436 // Mass function
437 Real saturationMass ( const Real& /* t */,
438  const Real& x,
439  const Real& y,
440  const Real& z,
441  const ID& /* icomp */ )
442 {
443  return dataPhysical::Phi ( x, y, z );
444 }
445 
446 // Boundary condition of Dirichlet
447 Real saturationDirichlet1 ( const Real& t,
448  const Real& /* x */,
449  const Real& /* y */,
450  const Real& /* z */,
451  const ID& /* icomp */)
452 {
453  if ( t < 5.)
454  {
455  return 0.8;
456  }
457  else
458  {
459  return 0.1;
460  }
461 }
462 
463 // Boundary condition of Dirichlet
464 Real saturationDirichlet2 ( const Real& /* t */,
465  const Real& /* x */,
466  const Real& /* y */,
467  const Real& /* z */,
468  const ID& /* icomp */)
469 {
470  return 0.5;
471 }
472 
473 // Boundary condition of Dirichlet
474 Real saturationDirichlet3 ( const Real& /* t */,
475  const Real& /* x */,
476  const Real& /* y */,
477  const Real& /* z */,
478  const ID& /* icomp */)
479 {
480  return 0.01;
481 }
482 
483 // Boundary condition of Neumann
484 Real saturationNeumann ( const Real& /* t */,
485  const Real& /* x */,
486  const Real& /* y */,
487  const Real& /* z */,
488  const ID& icomp)
489 {
490  return 0.;
491 
492  switch (icomp)
493  {
494  case 0: //! Dx
495  return 0.;
496  break;
497  case 1: //! Dy
498  return 0.;
499  break;
500  case 2: //! Dz
501  return 0.;
502  break;
503  }
504  return 0.;
505 }
506 
507 // Boundary condition of Robin
508 Real saturationRobin ( const Real& /* t */,
509  const Real& /* x */,
510  const Real& /* y */,
511  const Real& /* z */,
512  const ID& /* icomp */)
513 {
514  return 0.;
515 }
516 
517 }
uint32_type ID
IDs.
Definition: LifeV.hpp:194
double Real
Generic real data.
Definition: LifeV.hpp:175
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191