https://mooseframework.inl.gov
PorousFlowVanGenuchtenTest.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "gtest/gtest.h"
11 
12 #include "PorousFlowVanGenuchten.h"
13 
14 const double eps = 1.0E-8;
15 
18 const Real low_ext_Pc = 1.5;
24  low_ext_S,
25  low_ext_Pc,
26  low_ext_dPc);
29  low_ext_S,
30  low_ext_Pc,
31  low_ext_dPc);
34  low_ext_S,
35  low_ext_Pc,
36  low_ext_dPc);
39 const Real high_ext_S = 0.9 * (1.0 - 0.3); // here 0.9 is the so-called ratio
46  high_ext_S,
48  high_ext_dPc);
53  high_ext_S,
55  high_ext_dPc);
56 
57 TEST(PorousFlowVanGenuchtenTest, sat)
58 {
59  EXPECT_NEAR(1.0, PorousFlowVanGenuchten::effectiveSaturation(1.0E30, 0.7, 0.5), 1.0E-5);
60  EXPECT_NEAR(1.0, PorousFlowVanGenuchten::effectiveSaturation(1.0, 0.7, 0.5), 1.0E-5);
61  EXPECT_NEAR(1.0, PorousFlowVanGenuchten::effectiveSaturation(0.0, 0.7, 0.5), 1.0E-5);
62  EXPECT_NEAR(1.0, PorousFlowVanGenuchten::effectiveSaturation(1.0E-10, 0.7, 0.5), 1.0E-5);
63  EXPECT_NEAR(
64  0.486841442435055, PorousFlowVanGenuchten::effectiveSaturation(-2.0, 0.7, 0.6), 1.0E-5);
65  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::effectiveSaturation(-1.0E30, 0.7, 0.5), 1.0E-5);
66 }
67 
68 TEST(PorousFlowVanGenuchtenTest, dsat)
69 {
70  Real fd;
71  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dEffectiveSaturation(1.0E30, 0.7, 0.5), 1.0E-5);
72  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dEffectiveSaturation(1.0, 0.7, 0.5), 1.0E-5);
73  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dEffectiveSaturation(0.0, 0.7, 0.5), 1.0E-5);
74  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dEffectiveSaturation(1.0E-10, 0.7, 0.5), 1.0E-5);
75  fd = (PorousFlowVanGenuchten::effectiveSaturation(-2.0 + eps, 0.7, 0.6) -
77  eps;
78  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dEffectiveSaturation(-2.0, 0.7, 0.6), 1.0E-5);
79  fd = (PorousFlowVanGenuchten::effectiveSaturation(-1.1 + eps, 0.9, 0.66) -
81  eps;
82  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dEffectiveSaturation(-1.1, 0.9, 0.66), 1.0E-5);
83  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dEffectiveSaturation(-1.0E30, 0.7, 0.5), 1.0E-5);
84 }
85 
86 TEST(PorousFlowVanGenuchtenTest, d2sat)
87 {
88  Real fd;
89  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2EffectiveSaturation(1.0E30, 0.7, 0.5), 1.0E-5);
90  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2EffectiveSaturation(1.0, 0.7, 0.5), 1.0E-5);
91  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2EffectiveSaturation(0.0, 0.7, 0.5), 1.0E-5);
92  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2EffectiveSaturation(1.0E-10, 0.7, 0.5), 1.0E-5);
93  fd = (PorousFlowVanGenuchten::dEffectiveSaturation(-2.0 + eps, 0.7, 0.6) -
95  eps;
96  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2EffectiveSaturation(-2.0, 0.7, 0.6), 1.0E-5);
97  fd = (PorousFlowVanGenuchten::dEffectiveSaturation(-1.1 + eps, 2.3, 0.67) -
99  eps;
100  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2EffectiveSaturation(-1.1, 2.3, 0.67), 1.0E-5);
101  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2EffectiveSaturation(-1.0E30, 0.7, 0.5), 1.0E-5);
102 }
103 
104 TEST(PorousFlowVanGenuchtenTest, cap)
105 {
106  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::capillaryPressure(1.1, 1.0, 0.55, 1.0E30), 1.0E-5);
107  EXPECT_NEAR(4.06172392297447,
108  PorousFlowVanGenuchten::capillaryPressure(0.3, 0.625, 0.55, 1.0E30),
109  1.0E-5);
110  EXPECT_NEAR(2.9, PorousFlowVanGenuchten::capillaryPressure(0.001, 0.625, 0.55, 2.9), 1.0E-5);
111  EXPECT_NEAR(1000.0, PorousFlowVanGenuchten::capillaryPressure(0.0, 0.625, 0.55, 1000.0), 1.0E-5);
112 }
113 
114 TEST(PorousFlowVanGenuchtenTest, dcap)
115 {
116  Real fd;
117  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dCapillaryPressure(0.0, 1.0, 0.55, 1.0E30), 1.0E-5);
118  fd = (PorousFlowVanGenuchten::capillaryPressure(0.3 + eps, 0.625, 0.55, 1.0E30) -
119  PorousFlowVanGenuchten::capillaryPressure(0.3, 0.625, 0.55, 1.0E30)) /
120  eps;
121  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dCapillaryPressure(0.3, 0.625, 0.55, 1.0E30), 1.0E-5);
122  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dCapillaryPressure(1.0, 1.0, 0.55, 1.0E30), 1.0E-5);
123 }
124 
125 TEST(PorousFlowVanGenuchtenTest, d2cap)
126 {
127  Real fd;
128  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2CapillaryPressure(0.0, 1.0, 0.55, 1.0E30), 1.0E-5);
129  fd = (PorousFlowVanGenuchten::dCapillaryPressure(0.3 + eps, 0.625, 0.55, 1.0E30) -
130  PorousFlowVanGenuchten::dCapillaryPressure(0.3, 0.625, 0.55, 1.0E30)) /
131  eps;
132  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2CapillaryPressure(0.3, 0.625, 0.55, 1.0E30), 1.0E-5);
133  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2CapillaryPressure(1.0, 0.625, 0.55, 1.0E30), 1.0E-5);
134 }
135 
136 TEST(PorousFlowVanGenuchtenTest, relperm)
137 {
138  EXPECT_NEAR(1.0, PorousFlowVanGenuchten::relativePermeability(1.0E30, 0.7), 1.0E-5);
139  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::relativePermeability(-1.0, 0.7), 1.0E-5);
140  EXPECT_NEAR(0.0091160727, PorousFlowVanGenuchten::relativePermeability(0.3, 0.7), 1.0E-5);
141 }
142 
143 TEST(PorousFlowVanGenuchtenTest, drelperm)
144 {
145  Real fd;
146  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dRelativePermeability(1.0E30, 0.7), 1.0E-5);
147  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dRelativePermeability(-1.0, 0.7), 1.0E-5);
150  eps;
151  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dRelativePermeability(0.3, 0.7), 1.0E-5);
154  eps;
155  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dRelativePermeability(0.8, 0.65), 1.0E-5);
156 }
157 
158 TEST(PorousFlowVanGenuchtenTest, d2relperm)
159 {
160  Real fd;
161  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2RelativePermeability(1.0E30, 0.7), 1.0E-5);
162  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2RelativePermeability(-1.0, 0.7), 1.0E-5);
165  eps;
166  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2RelativePermeability(0.3, 0.7), 1.0E-5);
169  eps;
170  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2RelativePermeability(0.8, 0.65), 1.0E-5);
171 }
172 
173 TEST(PorousFlowVanGenuchtenTest, adrelperm)
174 {
175  ADReal sat = 0.3;
176  Moose::derivInsert(sat.derivatives(), 0, 1.0);
177 
178  const auto adrelperm = PorousFlowVanGenuchten::relativePermeability(sat, 0.7);
179 
180  const auto relperm = PorousFlowVanGenuchten::relativePermeability(sat.value(), 0.7);
181  const auto drelperm = PorousFlowVanGenuchten::dRelativePermeability(sat.value(), 0.7);
182 
183  EXPECT_NEAR(adrelperm.value(), relperm, 1.0E-5);
184  EXPECT_NEAR(adrelperm.derivatives()[0], drelperm, 1.0E-5);
185 }
186 
187 TEST(PorousFlowVanGenuchtenTest, relpermNW)
188 {
189  EXPECT_NEAR(1.0, PorousFlowVanGenuchten::relativePermeabilityNW(1.0E30, 0.7), 1.0E-5);
190  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::relativePermeabilityNW(-1.0, 0.7), 1.0E-5);
191  EXPECT_NEAR(0.664138097, PorousFlowVanGenuchten::relativePermeabilityNW(0.5, 0.3), 1.0E-5);
192  EXPECT_NEAR(0.559879012, PorousFlowVanGenuchten::relativePermeabilityNW(0.7, 0.8), 1.0E-5);
193 }
194 
195 TEST(PorousFlowVanGenuchtenTest, drelpermNW)
196 {
197  Real fd;
198  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dRelativePermeabilityNW(1.0E30, 0.7), 1.0E-5);
199  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dRelativePermeabilityNW(-1.0, 0.7), 1.0E-5);
202  eps;
203  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dRelativePermeabilityNW(0.3, 0.7), 1.0E-5);
206  eps;
207  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dRelativePermeabilityNW(0.8, 0.65), 1.0E-5);
208 }
209 
210 TEST(PorousFlowVanGenuchtenTest, d2relpermNW)
211 {
212  Real fd;
213  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2RelativePermeabilityNW(1.0E30, 0.7), 1.0E-5);
214  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2RelativePermeabilityNW(-1.0, 0.7), 1.0E-5);
217  eps;
218  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2RelativePermeabilityNW(0.3, 0.7), 1.0E-5);
221  eps;
222  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2RelativePermeabilityNW(0.8, 0.65), 1.0E-5);
223 }
224 
225 TEST(PorousFlowVanGenuchtenTest, adrelpermnw)
226 {
227  ADReal sat = 0.3;
228  Moose::derivInsert(sat.derivatives(), 0, 1.0);
229 
230  const auto adrelperm = PorousFlowVanGenuchten::relativePermeabilityNW(sat, 0.7);
231 
232  const auto relperm = PorousFlowVanGenuchten::relativePermeabilityNW(sat.value(), 0.7);
233  const auto drelperm = PorousFlowVanGenuchten::dRelativePermeabilityNW(sat.value(), 0.7);
234 
235  EXPECT_NEAR(adrelperm.value(), relperm, 1.0E-5);
236  EXPECT_NEAR(adrelperm.derivatives()[0], drelperm, 1.0E-5);
237 }
238 
240 TEST(PorousFlowVanGenuchtenTest, caphys)
241 {
242  // first define some extensions that do not actually induce any extension, so the non-extended Pc
243  // can be checked
244  const std::vector<Real> no_ext_sats{1.1, 0.75, 0.2, 0.4, 0.6};
245  const std::vector<Real> expected_pcs{
246  0.0, 0.0, 0.7233512030263158, 0.18806139488299345, 0.06716785873826017};
247  for (unsigned i = 0; i < no_ext_sats.size(); ++i)
248  {
249  EXPECT_NEAR(expected_pcs[i],
251  no_ext_sats[i], 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
252  1.0E-5);
253  EXPECT_NEAR(expected_pcs[i],
254  PorousFlowVanGenuchten::capillaryPressureHys(no_ext_sats[i], 0.1, 0.3, 10.0, 1.9),
255  1.0E-5);
256  }
257  EXPECT_NEAR(123.0,
259  -1.0, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
260  1.0E-5);
261  EXPECT_NEAR(123.0,
263  0.05, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
264  1.0E-5);
265  EXPECT_NEAR(std::numeric_limits<Real>::max(),
266  PorousFlowVanGenuchten::capillaryPressureHys(-1.0, 0.1, 0.3, 10.0, 1.9),
267  1.0E-5);
268  EXPECT_NEAR(std::numeric_limits<Real>::max(),
269  PorousFlowVanGenuchten::capillaryPressureHys(0.05, 0.1, 0.3, 10.0, 1.9),
270  1.0E-5);
271 
272  // check the lower extension values
273  EXPECT_NEAR(0.15229665668299805, low_ext_exp.S, 1.0E-5);
274  EXPECT_NEAR(-32.05516428734052, low_ext_exp.dPc, 1.0E-5);
275 
276  // check the high extension
277  EXPECT_NEAR(0.05300654102157442, high_ext_power.Pc, 1.0E-5);
278  EXPECT_NEAR(-0.48230528124844047, high_ext_power.dPc, 1.0E-5);
279 
280  // using low_ext_exp and high_ext_power
281  const std::vector<Real> sats{0.01, 0.1, 0.15, 0.2, 0.5, 0.63, 0.8, 0.99, 1.0};
282  std::vector<Real> pc;
283  pc = {31.385947046636815,
284  4.5861935551774735,
285  1.5754562501536364,
286  0.7233512030263158,
287  0.11727884570711045,
288  0.05300654102157442,
289  0.006681337544884095,
290  2.7847615834816514e-07,
291  0.0};
292  for (unsigned i = 0; i < sats.size(); ++i)
293  EXPECT_NEAR(pc[i],
295  sats[i], 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
296  1.0E-5);
297 
298  // using low_ext_quad and high_ext_power
299  pc = {3.9304232526771696,
300  2.8885549236001244,
301  1.5730646091089062,
302  0.7233512030263158,
303  0.11727884570711045,
304  0.05300654102157442,
305  0.006681337544884095,
306  2.7847615834816514e-07,
307  0.0};
308  for (unsigned i = 0; i < sats.size(); ++i)
309  EXPECT_NEAR(pc[i],
311  sats[i], 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
312  1.0E-5);
313 
314  // using low_ext_none and high_ext_power
315  pc = {1.5,
316  1.5,
317  1.5,
318  0.7233512030263158,
319  0.11727884570711045,
320  0.05300654102157442,
321  0.006681337544884095,
322  2.7847615834816514e-07,
323  0.0};
324  for (unsigned i = 0; i < sats.size(); ++i)
325  EXPECT_NEAR(pc[i],
327  sats[i], 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
328  1.0E-5);
329 
330  // using low_ext_none and high_ext_none
331  pc = {1.5, 1.5, 1.5, 0.7233512030263158, 0.11727884570711045, 0.05300654102157442, 0.0, 0.0, 0.0};
332  for (unsigned i = 0; i < sats.size(); ++i)
333  EXPECT_NEAR(pc[i],
335  sats[i], 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none),
336  1.0E-5);
337 }
338 
340 TEST(PorousFlowVanGenuchtenTest, sathys)
341 {
342  // first define some extensions that do not actually induce any extension, so the non-extended Pc
343  // can be checked
344  const std::vector<Real> expected_sats{1.0, 0.2, 0.4, 0.6};
345  const std::vector<Real> no_ext_pcs{
346  -1.1, 0.7233512030263158, 0.18806139488299345, 0.06716785873826017};
347  for (unsigned i = 0; i < no_ext_pcs.size(); ++i)
348  {
349  EXPECT_NEAR(expected_sats[i],
351  no_ext_pcs[i], 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
352  1.0E-5);
353  EXPECT_NEAR(expected_sats[i],
354  PorousFlowVanGenuchten::saturationHys(no_ext_pcs[i], 0.1, 0.3, 10.0, 1.9),
355  1.0E-5);
356  }
357  EXPECT_NEAR(
358  -1.0,
359  PorousFlowVanGenuchten::saturationHys(1234.0, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
360  1.0E-5);
361  EXPECT_NEAR(
362  0.0,
363  PorousFlowVanGenuchten::saturationHys(std::numeric_limits<Real>::max(), 0.1, 0.3, 10.0, 1.9),
364  1.0E-5);
365 
366  // now with extensions
367  std::vector<Real> sats{0.01, 0.1, 0.15, 0.2, 0.5, 0.63, 0.8, 0.99, 1.0};
368  std::vector<Real> pc;
369  pc = {31.385947046636815,
370  4.5861935551774735,
371  1.5754562501536364,
372  0.7233512030263158,
373  0.11727884570711045,
374  0.05300654102157442,
375  0.006681337544884095,
376  2.7847615834816514e-07,
377  0.0};
378  for (unsigned i = 0; i < sats.size(); ++i)
379  EXPECT_NEAR(sats[i],
381  pc[i], 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
382  1.0E-5);
383 
384  // different lower extension
385  pc = {3.9304232526771696,
386  2.8885549236001244,
387  1.5730646091089062,
388  0.7233512030263158,
389  0.11727884570711045,
390  0.05300654102157442,
391  0.006681337544884095,
392  2.7847615834816514e-07,
393  0.0};
394  for (unsigned i = 0; i < sats.size(); ++i)
395  EXPECT_NEAR(sats[i],
397  pc[i], 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
398  1.0E-5);
399 
400  // different low extension
401  sats = {low_ext_none.S, low_ext_none.S, 0.2, 0.5, 0.63, 0.8, 0.99, 1.0};
402  pc = {2.5,
403  1.5,
404  0.7233512030263158,
405  0.11727884570711045,
406  0.05300654102157442,
407  0.006681337544884095,
408  2.7847615834816514e-07,
409  0.0};
410  for (unsigned i = 0; i < sats.size(); ++i)
411  EXPECT_NEAR(sats[i],
413  pc[i], 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
414  1.0E-5);
415 
416  // different high extension
417  pc = {2.5, 1.5, 0.7233512030263158, 0.11727884570711045, 0.05300654102157442, 1E-10};
418  sats = {low_ext_none.S, low_ext_none.S, 0.2, 0.5, 0.63, 0.8};
419  for (unsigned i = 0; i < sats.size(); ++i)
420  EXPECT_NEAR(sats[i],
422  pc[i], 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none),
423  1.0E-5);
424 }
425 
427 TEST(PorousFlowVanGenuchtenTest, dcaphys)
428 {
429  const Real eps = 1.0E-9;
430 
431  // first define some extensions that do not actually induce any extension, so the non-extended
432  // Pc can be checked
433  std::vector<Real> sats{1.1, 0.75, -1.0, 0.05};
434  for (const auto & sat : sats)
435  {
436  EXPECT_NEAR(0.0,
438  sat, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
439  1.0E-5);
440  EXPECT_NEAR(
441  0.0, PorousFlowVanGenuchten::dcapillaryPressureHys(sat, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
442  }
443 
444  sats = {0.2, 0.4, 0.6};
445  for (const auto & sat : sats)
446  {
447  const Real fd = 0.5 *
448  (PorousFlowVanGenuchten::capillaryPressureHys(sat + eps, 0.1, 0.3, 10.0, 1.9) -
449  PorousFlowVanGenuchten::capillaryPressureHys(sat - eps, 0.1, 0.3, 10.0, 1.9)) /
450  eps;
451  EXPECT_NEAR(fd,
453  sat, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
454  1.0E-5);
455  EXPECT_NEAR(
456  fd, PorousFlowVanGenuchten::dcapillaryPressureHys(sat, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
457  };
458 
459  // now with extensions
460  sats = {0.01, 0.1, 0.15, 0.2, 0.5, 0.63, 0.8, 0.99, 1.0};
461 
462  for (const auto & sat : sats)
463  {
464  const Real fd = 0.5 *
466  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power) -
468  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power)) /
469  eps;
470  EXPECT_NEAR(fd,
472  sat, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
473  1.0E-5);
474  };
475 
476  // different low extension
477  for (const auto & sat : sats)
478  {
479  const Real fd = 0.5 *
481  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power) -
483  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power)) /
484  eps;
485  EXPECT_NEAR(fd,
487  sat, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
488  1.0E-5);
489  };
490 
491  // different lower extension
492  for (const auto & sat : sats)
493  {
494  const Real fd = 0.5 *
496  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power) -
498  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power)) /
499  eps;
500  EXPECT_NEAR(fd,
502  sat, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
503  1.0E-5);
504  };
505 
506  // different upper extension (cannot evaluate derivative at s = 0.63)
507  sats = {0.01, 0.1, 0.15, 0.2, 0.5, 0.8, 0.99, 1.0};
508  for (const auto & sat : sats)
509  {
510  const Real fd = 0.5 *
512  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2) -
514  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2)) /
515  eps;
516  EXPECT_NEAR(fd,
518  sat, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2),
519  1.0E-5);
520  };
521 }
522 
524 TEST(PorousFlowVanGenuchtenTest, d2caphys)
525 {
526  const Real eps = 1.0E-9;
527 
528  // first define some extensions that do not actually induce any extension, so the non-extended
529  // Pc can be checked
530  std::vector<Real> sats{1.1, 0.75, -1.0, 0.05};
531  for (const auto & sat : sats)
532  {
533  EXPECT_NEAR(0.0,
535  sat, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
536  1.0E-5);
537  EXPECT_NEAR(
538  0.0, PorousFlowVanGenuchten::d2capillaryPressureHys(sat, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
539  }
540 
541  sats = {0.2, 0.4, 0.6};
542  for (const auto & sat : sats)
543  {
544  const Real fd =
545  0.5 *
546  (PorousFlowVanGenuchten::dcapillaryPressureHys(sat + eps, 0.1, 0.3, 10.0, 1.9) -
547  PorousFlowVanGenuchten::dcapillaryPressureHys(sat - eps, 0.1, 0.3, 10.0, 1.9)) /
548  eps;
549  EXPECT_NEAR(fd,
551  sat, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext),
552  1.0E-5);
553  EXPECT_NEAR(
554  fd, PorousFlowVanGenuchten::d2capillaryPressureHys(sat, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
555  };
556 
557  // now with extensions
558  sats = {0.01, 0.1, 0.15, 0.2, 0.5, 0.6, 0.7, 0.8, 0.99, 1.0};
559 
560  for (const auto & sat : sats)
561  {
562  const Real fd = 0.5 *
564  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power) -
566  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power)) /
567  eps;
568  if (std::abs(fd) > 10)
569  EXPECT_NEAR(1.0,
571  sat, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
572  1.0E-5);
573  else
574  EXPECT_NEAR(fd,
576  sat, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
577  1.0E-5);
578  };
579 
580  // different low extension
581  for (const auto & sat : sats)
582  {
583  const Real fd = 0.5 *
585  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power) -
587  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power)) /
588  eps;
589  if (std::abs(fd) > 10)
590  EXPECT_NEAR(1.0,
592  sat, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
593  1.0E-5);
594  else
595  EXPECT_NEAR(fd,
597  sat, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
598  1.0E-5);
599  };
600 
601  // different lower extension
602  for (const auto & sat : sats)
603  {
604  const Real fd = 0.5 *
606  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power) -
608  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power)) /
609  eps;
610  if (std::abs(fd) > 10)
611  EXPECT_NEAR(1.0,
613  sat, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
614  1.0E-5);
615  else
616  EXPECT_NEAR(fd,
618  sat, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
619  1.0E-5);
620  };
621 
622  // different upper extension (cannot evaluate derivative at s = 0.63)
623  sats = {0.01, 0.1, 0.15, 0.2, 0.5, 0.8, 0.99, 1.0};
624  for (const auto & sat : sats)
625  {
626  const Real fd = 0.5 *
628  sat + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2) -
630  sat - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2)) /
631  eps;
632  if (std::abs(fd) > 10)
633  EXPECT_NEAR(1.0,
635  sat, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2),
636  1.0E-5);
637  else
638  EXPECT_NEAR(fd,
640  sat, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none2),
641  1.0E-5);
642  };
643 }
644 
646 TEST(PorousFlowVanGenuchtenTest, dsathys)
647 {
648  const Real eps = 1E-9;
649 
650  // first define some extensions that do not actually induce any extension, so the non-extended Pc
651  // can be checked
652  std::vector<Real> pcs{-1.1, 1234.0};
653  for (const auto & pc : pcs)
654  {
655  EXPECT_NEAR(
656  0.0,
658  1.0E-5);
659  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::dsaturationHys(pc, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
660  }
661 
662  pcs = {0.7, 0.2, 0.07};
663  for (const auto & pc : pcs)
664  {
665  const Real fd = 0.5 *
667  pc + eps, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext) -
669  pc - eps, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext)) /
670  eps;
671  EXPECT_NEAR(
672  fd,
674  1.0E-5);
675  EXPECT_NEAR(fd, PorousFlowVanGenuchten::dsaturationHys(pc, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
676  }
677 
678  // now with low and high extensions
679  pcs = {31.385947046636815,
680  4.5861935551774735,
681  1.5754562501536364,
682  0.7233512030263158,
683  0.11727884570711045,
684  0.05300654102157442,
685  0.006681337544884095};
686  for (const auto & pc : pcs)
687  {
688  const Real fd = 0.5 *
690  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power) -
692  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power)) /
693  eps;
694  EXPECT_NEAR(fd,
696  pc, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
697  1.0E-5);
698  }
699 
700  // different lower extension
701  pcs = {3.9304232526771696,
702  2.8885549236001244,
703  1.5730646091089062,
704  0.7233512030263158,
705  0.11727884570711045,
706  0.05300654102157442,
707  0.006681337544884095};
708  for (const auto & pc : pcs)
709  {
710  const Real fd = 0.5 *
712  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power) -
714  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power)) /
715  eps;
716  EXPECT_NEAR(fd,
718  pc, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
719  1.0E-5);
720  }
721 
722  // different lower extension
723  pcs = {2.5, 0.7233512030263158, 0.11727884570711045, 0.05300654102157442, 0.006681337544884095};
724  for (const auto & pc : pcs)
725  {
726  const Real fd = 0.5 *
728  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power) -
730  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power)) /
731  eps;
732  EXPECT_NEAR(fd,
734  pc, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
735  1.0E-5);
736  }
737 
738  // different upper extension
739  pcs = {2.5, 0.7233512030263158, 0.11727884570711045, 0.05, 0.04};
740  for (const auto & pc : pcs)
741  {
742  const Real fd = 0.5 *
744  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none) -
746  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none)) /
747  eps;
748  EXPECT_NEAR(fd,
750  pc, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none),
751  1.0E-5);
752  }
753 }
754 
756 TEST(PorousFlowVanGenuchtenTest, d2sathys)
757 {
758  const Real eps = 1E-9;
759 
760  // first define some extensions that do not actually induce any extension, so the non-extended Pc
761  // can be checked
762  std::vector<Real> pcs{-1.1, 1234.0};
763  for (const auto & pc : pcs)
764  {
765  EXPECT_NEAR(
766  0.0,
768  1.0E-5);
769  EXPECT_NEAR(0.0, PorousFlowVanGenuchten::d2saturationHys(pc, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
770  }
771 
772  pcs = {0.7, 0.2, 0.07};
773  for (const auto & pc : pcs)
774  {
775  const Real fd = 0.5 *
777  pc + eps, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext) -
779  pc - eps, 0.1, 0.3, 10.0, 1.9, no_low_ext, no_high_ext)) /
780  eps;
781  EXPECT_NEAR(
782  fd,
784  1.0E-5);
785  EXPECT_NEAR(fd, PorousFlowVanGenuchten::d2saturationHys(pc, 0.1, 0.3, 10.0, 1.9), 1.0E-5);
786  }
787 
788  // now with low and high extensions
789  pcs = {31.385947046636815,
790  4.5861935551774735,
791  1.5754562501536364,
792  0.7233512030263158,
793  0.11727884570711045,
794  0.06300654102157442,
795  0.006681337544884095};
796  for (const auto & pc : pcs)
797  {
798  const Real fd = 0.5 *
800  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power) -
802  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power)) /
803  eps;
804  EXPECT_NEAR(fd,
806  pc, 0.1, 0.3, 10.0, 1.9, low_ext_exp, high_ext_power),
807  1.0E-5);
808  }
809 
810  // different lower extension
811  pcs = {3.9304232526771696,
812  2.8885549236001244,
813  1.5730646091089062,
814  0.7233512030263158,
815  0.11727884570711045,
816  0.06300654102157442,
817  0.006681337544884095};
818  for (const auto & pc : pcs)
819  {
820  const Real fd = 0.5 *
822  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power) -
824  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power)) /
825  eps;
826  EXPECT_NEAR(fd,
828  pc, 0.1, 0.3, 10.0, 1.9, low_ext_quad, high_ext_power),
829  1.0E-5);
830  }
831 
832  // different lower extension
833  pcs = {2.5, 0.7233512030263158, 0.11727884570711045, 0.06300654102157442, 0.006681337544884095};
834  for (const auto & pc : pcs)
835  {
836  const Real fd = 0.5 *
838  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power) -
840  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power)) /
841  eps;
842  EXPECT_NEAR(fd,
844  pc, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_power),
845  1.0E-5);
846  }
847 
848  // different upper extension
849  pcs = {2.5, 0.7233512030263158, 0.11727884570711045, 0.05, 0.04};
850  for (const auto & pc : pcs)
851  {
852  const Real fd = 0.5 *
854  pc + eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none) -
856  pc - eps, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none)) /
857  eps;
858  EXPECT_NEAR(fd,
860  pc, 0.1, 0.3, 10.0, 1.9, low_ext_none, high_ext_none),
861  1.0E-5);
862  }
863 }
864 
866 TEST(PorousFlowVanGenuchtenTest, relativePermeabilityHys)
867 {
868  // Tests for sldel = 0.5 >= slr = 0.2
869  EXPECT_NEAR(0.0,
871  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
872  1.0E-12); // zero because sl < slr
873  EXPECT_NEAR(0.0,
875  0.2, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
876  1.0E-12); // zero because sl = slr
877  EXPECT_NEAR(0.002847974503642625,
879  0.3, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
880  1.0E-12); // drying because sl <= sldel
881  EXPECT_NEAR(0.002847974503642625,
883  0.3, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
884  1.0E-12); // drying because sgrdel = 0
885  EXPECT_NEAR(0.05828443549816974,
887  0.5, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
888  1.0E-12); // drying because sl <= sldel
889  EXPECT_NEAR(0.10056243969693253,
891  0.55, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
892  1.0E-12); // wetting
893  EXPECT_NEAR(0.08943153676247108,
895  0.55, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
896  1.0E-12); // drying because sgrdel = 0
897  EXPECT_NEAR(0.3159149169921876,
899  0.8, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
900  1.0E-12); // cubic
901  EXPECT_NEAR(0.8011290515690178,
903  0.95, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
904  1.0E-12); // drying, because sl > cubic modification region
905 
906  // Tests for sldel = 0.15 < slr = 0.2
907  EXPECT_NEAR(0.0,
909  0.1, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
910  1.0E-12); // zero because sl < slr
911  EXPECT_NEAR(0.0,
913  0.2, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
914  1.0E-12); // zero because sl = slr
915  EXPECT_NEAR(0.005858393312913491,
917  0.3, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
918  1.0E-12); // wetting
919  EXPECT_NEAR(0.002847974503642625,
921  0.3, 0.2, 0.0, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
922  1.0E-12); // drying because sgrdel = 0
923  EXPECT_NEAR(0.1363562523627124,
925  0.55, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
926  1.0E-12); // wetting
927  EXPECT_NEAR(0.31,
929  0.7, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
930  1.0E-12); // cubic
931  EXPECT_NEAR(0.8011290515690178,
933  0.95, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
934  1.0E-12); // drying, because sl > cubic modification region
935 }
936 
938 TEST(PorousFlowVanGenuchtenTest, drelativePermeabilityHys)
939 {
940  // essentially follow the testing strategy in the relativePermeabilityHys Test, but do not test
941  // the derivative at the points where it is discontinuous
942  EXPECT_NEAR(0.0,
944  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
945  1.0E-12);
947  0.3, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
949  0.3 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
951  0.3, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
952  eps,
953  1.0E-5);
955  0.3, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
957  0.3 + eps, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
959  0.3, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
960  eps,
961  1.0E-5);
963  0.55, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
965  0.55 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
967  0.55, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
968  eps,
969  1.0E-5);
971  0.55, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
973  0.55 + eps, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
975  0.55, 0.2, 0.0, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
976  eps,
977  1.0E-5);
979  0.8, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
981  0.8 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
983  0.8, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
984  eps,
985  1.0E-5);
987  0.95, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
989  0.95 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
991  0.95, 0.2, 0.15, 0.25, 0.5, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
992  eps,
993  1.0E-5);
994 
995  EXPECT_NEAR(0.0,
997  0.1, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
998  1.0E-5);
1000  0.3, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
1002  0.3 + eps, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
1004  0.3, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
1005  eps,
1006  1.0E-5);
1008  0.3, 0.2, 0.0, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
1010  0.3 + eps, 0.2, 0.0, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
1012  0.3, 0.2, 0.0, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
1013  eps,
1014  1.0E-5);
1016  0.55, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
1018  0.55 + eps, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
1020  0.55, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
1021  eps,
1022  1.0E-5);
1024  0.7, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
1026  0.7 + eps, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
1028  0.7, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
1029  eps,
1030  1.0E-5);
1032  0.95, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2),
1034  0.95 + eps, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2) -
1036  0.95, 0.2, 0.15, 0.25, 0.15, 0.9, 0.9, 0.3, 0.5, 0.45, 2.2)) /
1037  eps,
1038  1.0E-5);
1039 }
1040 
1042 TEST(PorousFlowVanGenuchtenTest, relativePermeabilityNWHys)
1043 {
1044  // Tests for sldel = 0.5 >= slr = 0.2
1045  EXPECT_NEAR(0.91875,
1047  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1048  1.0E-12); // cubic extension region because sl < slr
1049  EXPECT_NEAR(1.0,
1051  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 1.0, -0.75),
1052  1.0E-12); // cubic extension region because sl < slr, but k_rg_max = 1
1053  EXPECT_NEAR(0.8,
1055  0.2, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1056  1.0E-12); // at boundary of extension since sl = slr
1057  EXPECT_NEAR(0.6368139633459233,
1059  0.3, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1060  1.0E-12); // drying because sl <= sldel
1061  EXPECT_NEAR(0.6368139633459233,
1063  0.3, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1064  1.0E-12); // drying because sgrdel = 0
1065  EXPECT_NEAR(0.33222054246699,
1067  0.5, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1068  1.0E-12); // drying because sl <= sldel
1069  EXPECT_NEAR(0.24397255389213568,
1071  0.55, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1072  1.0E-12); // wetting
1073  EXPECT_NEAR(0.2691316236913443,
1075  0.55, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1076  1.0E-12); // drying because sgrdel = 0
1077  EXPECT_NEAR(0.01509148277290631,
1079  0.85, 0.2, 0.05, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1080  1.0E-12); // wetting
1081  EXPECT_NEAR(0.0,
1083  0.85, 0.2, 0.18, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1084  1.0E-12); // sl > 1 - s_gr_del
1085 
1086  // Tests for sldel = 0.15 < slr = 0.2
1087  EXPECT_NEAR(0.91875,
1089  0.1, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1090  1.0E-12); // cubic extension region because sl < slr
1091  EXPECT_NEAR(1.0,
1093  0.1, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 1.0, -0.75),
1094  1.0E-12); // cubic extension region because sl < slr, but k_rg_max = 1
1095  EXPECT_NEAR(0.8,
1097  0.2, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1098  1.0E-12); // at boundary of extension since sl = slr
1099  EXPECT_NEAR(0.5616820966427329,
1101  0.3, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1102  1.0E-12); // wetting
1103  EXPECT_NEAR(0.6368139633459233,
1105  0.3, 0.2, 0.0, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1106  1.0E-12); // wetting = drying because sgrdel = 0
1107  EXPECT_NEAR(0.11086138435665097,
1109  0.55, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1110  1.0E-12); // wetting
1111  EXPECT_NEAR(0.0,
1113  0.76, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1114  1.0E-12); // always zero for large saturation
1115 }
1116 
1118 TEST(PorousFlowVanGenuchtenTest, drelativePermeabilityNWHys)
1119 {
1120  // Testing strategy follows the relativePermeabilityNWHys strategy, except the points at which the
1121  // derivative is not defined are not tested
1123  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1125  0.1 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1127  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1128  eps,
1129  1.0E-5); // cubic extension region because sl < slr
1130  EXPECT_NEAR(0.0,
1132  0.1, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 1.0, -0.75),
1133  1.0E-12); // cubic extension region because sl < slr, but k_rg_max = 1
1135  0.3, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1137  0.3 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1139  0.3, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1140  eps,
1141  1.0E-5); // drying because sl <= sldel
1143  0.3, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1145  0.3 + eps, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1147  0.3, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1148  eps,
1149  1.0E-5); // drying because sgrdel = 0
1151  0.45, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1153  0.45 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1155  0.45, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1156  eps,
1157  1.0E-5); // drying because sl <= sldel
1159  0.55, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1161  0.55 + eps, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1163  0.55, 0.2, 0.15, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1164  eps,
1165  1.0E-5); // wetting
1167  0.55, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1169  0.55 + eps, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1171  0.55, 0.2, 0.0, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1172  eps,
1173  1.0E-5); // drying because sgrdel = 0
1175  0.85, 0.2, 0.05, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1177  0.85 + eps, 0.2, 0.05, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75) -
1179  0.85, 0.2, 0.05, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75)) /
1180  eps,
1181  1.0E-5); // wetting
1182  EXPECT_NEAR(0.0,
1184  0.85, 0.2, 0.18, 0.25, 0.5, 0.9, 0.3, 0.8, -0.75),
1185  1.0E-12); // sl > 1 - s_gr_del
1186 
1187  // Tests for sldel = 0.15 < slr = 0.2
1189  0.1, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1191  0.1 + eps, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75) -
1193  0.1, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75)) /
1194  eps,
1195  1.0E-5); // cubic extension region because sl < slr
1196  EXPECT_NEAR(0.0,
1198  0.1, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 1.0, -0.75),
1199  1.0E-12); // cubic extension region because sl < slr, but k_rg_max = 1
1201  0.3, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1203  0.3 + eps, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75) -
1205  0.3, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75)) /
1206  eps,
1207  1.0E-5); // wetting
1209  0.3, 0.2, 0.0, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1211  0.3 + eps, 0.2, 0.0, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75) -
1213  0.3, 0.2, 0.0, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75)) /
1214  eps,
1215  1.0E-5); // wetting = drying because sgrdel = 0
1217  0.55, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1219  0.55 + eps, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75) -
1221  0.55, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75)) /
1222  eps,
1223  1.0E-5); // wetting
1224  EXPECT_NEAR(0.0,
1226  0.76, 0.2, 0.18, 0.25, 0.15, 0.9, 0.3, 0.8, -0.75),
1227  1.0E-12); // always zero for large saturation
1228 }
const PorousFlowVanGenuchten::LowCapillaryPressureExtension low_ext_exp(PorousFlowVanGenuchten::LowCapillaryPressureExtension::EXPONENTIAL, low_ext_S, low_ext_Pc, low_ext_dPc)
Real dcapillaryPressureHys(Real sl, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
Derivative of capillaryPressureHys with respect to sl.
TEST(PorousFlowVanGenuchtenTest, sat)
const Real low_ext_Pc
Real d2capillaryPressureHys(Real sl, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
Second derivative of capillaryPressureHys with respect to sl.
const PorousFlowVanGenuchten::HighCapillaryPressureExtension no_high_ext(PorousFlowVanGenuchten::HighCapillaryPressureExtension::NONE, 2.0, 0.0, 0.0)
Real drelativePermeabilityHys(Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real upper_liquid_param, Real y0, Real y0p, Real y1, Real y1p)
Derivative of Hysteretic relative permeability for liquid, with respect to liquid saturation...
Real relativePermeabilityNWHys(Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real gamma, Real k_rg_max, Real y0p)
Hysteretic relative permeability for gas.
const PorousFlowVanGenuchten::LowCapillaryPressureExtension no_low_ext(PorousFlowVanGenuchten::LowCapillaryPressureExtension::NONE, -1.0, 123.0, 0.0)
const Real high_ext_Pc
Parameters associated with the extension of the hysteretic wetting capillary pressure function to hig...
T relativePermeabilityNW(const T &seff, Real m)
Relative permeability for a non-wetting phase as a function of effective saturation.
const double eps
const Real high_ext_S
const PorousFlowVanGenuchten::HighCapillaryPressureExtension high_ext_power(PorousFlowVanGenuchten::HighCapillaryPressureExtension::POWER, high_ext_S, high_ext_Pc, high_ext_dPc)
DualNumber< Real, DNDerivativeType, true > ADReal
Real capillaryPressureHys(Real sl, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
Hysteretic capillary pressure function (Eqn(1) of Doughty2007) with extensions (page5 and Fig1 of Dou...
Real drelativePermeabilityNWHys(Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real gamma, Real k_rg_max, Real y0p)
Derivative of hysteretic relative permeability for gas with respect to the liquid saturation...
const Real low_ext_dPc
Parameters associated with the extension of the hysteretic capillary pressure function to low saturat...
Real d2RelativePermeabilityNW(Real seff, Real m)
Second derivative of relative permeability for a non-wetting phase with respect to effective saturati...
Real relativePermeabilityHys(Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real upper_liquid_param, Real y0, Real y0p, Real y1, Real y1p)
Hysteretic relative permeability for liquid.
const PorousFlowVanGenuchten::HighCapillaryPressureExtension high_ext_none2(PorousFlowVanGenuchten::HighCapillaryPressureExtension::NONE, high_ext_S, high_ext_Pc, high_ext_dPc)
const Real high_ext_dPc
Real d2CapillaryPressure(Real seff, Real alpha, Real m, Real pc_max)
Second derivative of capillary pressure wrt effective saturation.
Real dRelativePermeability(Real seff, Real m)
Derivative of relative permeability with respect to effective saturation.
T relativePermeability(const T &seff, Real m)
Relative permeability as a function of effective saturation.
Real effectiveSaturation(Real p, Real alpha, Real m)
Effective saturation as a function of porepressure.
const PorousFlowVanGenuchten::HighCapillaryPressureExtension high_ext_none(PorousFlowVanGenuchten::HighCapillaryPressureExtension::NONE, 0.8, high_ext_Pc, high_ext_dPc)
const PorousFlowVanGenuchten::LowCapillaryPressureExtension low_ext_none(PorousFlowVanGenuchten::LowCapillaryPressureExtension::NONE, low_ext_S, low_ext_Pc, low_ext_dPc)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Real dCapillaryPressure(Real seff, Real alpha, Real m, Real pc_max)
Derivative of capillary pressure wrt effective saturation.
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N >> &derivs, libMesh::dof_id_type index, Real value)
Real d2EffectiveSaturation(Real p, Real alpha, Real m)
Second derivative of effective saturation wrt porepressure.
Real dsaturationHys(Real pc, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
Derivative of Hysteretic saturation function with respect to pc.
const Real low_ext_S
Real d2RelativePermeability(Real seff, Real m)
Second derivative of relative permeability with respect to effective saturation.
Real d2saturationHys(Real pc, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
Second derivative of Hysteretic saturation function with respect to pc.
Real dEffectiveSaturation(Real p, Real alpha, Real m)
Derivative of effective saturation wrt porepressure.
Real dRelativePermeabilityNW(Real seff, Real m)
Derivative of relative permeability for a non-wetting phase with respect to effective saturation...
Real saturationHys(Real pc, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
Hysteretic saturation function (Eqn(1) of Doughty2007) with extensions (page5 and Fig1 of Doughty2008...
Real capillaryPressure(Real seff, Real alpha, Real m, Real pc_max)
Capillary pressure as a function of effective saturation.
const PorousFlowVanGenuchten::LowCapillaryPressureExtension low_ext_quad(PorousFlowVanGenuchten::LowCapillaryPressureExtension::QUADRATIC, low_ext_S, low_ext_Pc, low_ext_dPc)