Coverage for C:\src\imod-python\imod\mf6\adv.py: 91%
34 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-08 14:15 +0200
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-08 14:15 +0200
1"""
2When simulating transport, MODFLOW6 needs to compute the concentration at a
3cellface between 2 adjacent cells. It supports 3 ways of doing this. Each of
4those has its own wrapper class. These numerical schemes differ in how much
5numerical dispersion they cause, how much oscillations, and how timestep and
6grid size affect stability. Central-in-space weighting is not often used
7because it can result in spurious oscillations in the simulated concentrations.
8Upstream weighting is a fast alternative, and TVD is a more expensive and more
9robust alternative.
10"""
12from copy import deepcopy
13from typing import Optional, Tuple
15from imod.mf6.interfaces.iregridpackage import IRegridPackage
16from imod.mf6.package import Package
17from imod.mf6.utilities.regrid import RegridderType
20class Advection(Package, IRegridPackage):
21 _pkg_id = "adv"
22 _template = Package._initialize_template(_pkg_id)
23 _regrid_method: dict[str, tuple[RegridderType, str]] = {}
25 def __init__(self, scheme: str):
26 dict_dataset = {"scheme": scheme}
27 super().__init__(dict_dataset)
29 def render(self, directory, pkgname, globaltimes, binary):
30 scheme = self.dataset["scheme"].item()
31 return self._template.render({"scheme": scheme})
33 def mask(self, _) -> Package:
34 """
35 The mask method is irrelevant for this package , instead this method
36 retuns a copy of itself.
37 """
38 return deepcopy(self)
40 def get_regrid_methods(self) -> Optional[dict[str, Tuple[RegridderType, str]]]:
41 return self._regrid_method
44class AdvectionUpstream(Advection):
45 """
46 The upstream weighting (first order upwind) scheme sets the concentration
47 at the cellface between two adjacent cells equal to the concentration in
48 the cell where the flow comes from. It surpresses oscillations.
49 Note: all constructor arguments will be ignored
50 """
52 def __init__(self, scheme: str = "upstream"):
53 if not scheme == "upstream":
54 raise ValueError(
55 "error in scheme parameter. Should be 'upstream' if present."
56 )
57 super().__init__(scheme="upstream")
60class AdvectionCentral(Advection):
61 """
62 The central-in-space weighting scheme is based on a simple
63 distance-weighted linear interpolation between the center of cell n and the
64 center of cell m to calculate solute concentration at the shared face
65 between cell n and cell m. Although central-in-space is a misnomer for
66 grids without equal spacing between connected cells, it is retained here
67 for consistency with nomenclature used by other MODFLOW-based transport
68 programs, such as MT3D.
69 Note: all constructor arguments will be ignored
70 """
72 def __init__(self, scheme: str = "central"):
73 if not scheme == "central":
74 raise ValueError(
75 "error in scheme parameter. Should be 'central' if present."
76 )
77 super().__init__(scheme="central")
80class AdvectionTVD(Advection):
81 """
82 An implicit second order TVD scheme. More expensive than upstream
83 weighting but more robust.
84 Note: all constructor arguments will be ignored
85 """
87 def __init__(self, scheme: str = "TVD"):
88 if not scheme == "TVD":
89 raise ValueError("error in scheme parameter. Should be 'TVD' if present.")
90 super().__init__(scheme="TVD")