-
Notifications
You must be signed in to change notification settings - Fork 4
Software architecture
In synthesis, the input of the system consists of a model mesh and high-resolution bathymetric data. alphaBetaLab assumes that a mesh (represented by class abGrid) can be considered as a set of polygons, called cells. Ad hoc factory methods create the instances of abGrid objects for different types of meshes (e.g. regular, triangular or SMC meshes). Then the algorithm loops on the cells of the mesh and estimates the needed transparency coefficients for the local dissipation and for the shadow. The output is finally saved to a file format that can be read by the UOST source term of WW3.
The UOST/alphaBetaLab approach relies on the hypothesis that any mesh can be considered as a set of polygons, called cells, and that the model estimates the average value of the unknowns in each cell. In alphaBetaLab the generic mesh type is defined by in the module abGrid. For the definition of the polygons, and related logics, alphaBetaLab relies on the library shapely (https://pypi.python.org/pypi/Shapely).
The class _abGrid (in module abGrid) represents a grid as a collection of polygons, each representing a cell. The grid can be unstructured. The constructor takes as argument: cells: a list of n cells as shapely polygon objects, and a list of n tuples of integer indices (cellCoordinates), of the same length as cells, where each tuple represents the matrix indices of each cell in the model. The class is private, and the instances can be generated using the functions getLandSeaGrid, that builds a _abGrid instance with all the polygons contained in the list cells, and the function getSeaGrid, that filters out the polygons on land and along the resolved coasts. The difference between these two functions is that the second takes as further arguments a high-resolution matrix of alpha and a coastalCellDetector object, and excludes from the _abGrid instance coastal cells. The class _abGrid implements algorithms to find, for each cell, the neighboring cells (methods buildNeighCache and getNeighbors). It is worth mentioning that the sole cells containing unresolved obstacles are relevant to the algorithms implemented in alphaBetaLab, and although the presence of empty cell-polygons in the abGrid object does not change the output, filtering them out will speed up considerably the computational time.
abGrid builders are components to build abGrid objects from model meshes.
abRectangularGridBuilder: class for building a abGrid instance for lon-lat grids. The constructor takes as an input the coordinates of the grid and the grid paces, a mask defining the land points, and high-resolution matrix of alpha. In the buildGrid, the cell-polygons are instantiated, and the abGrid object is created. For the sake of reusability, this class does not load directly the grid files of ww3. This is done instead by the regularGridSpecWW3 method, in module abEstimateAndSave. Moreover, this method is not meant to be invoked directly by the final user, but handled by function abEstimateAndSaveRegularEtopo1 in module abEstimateAndSave.
abTriangularMeshGridBuilder: class for building a abGrid instance for a triangular mesh. For the sake of its re-usability, this class does not load directly gmesh files, but instead rely on class _abTriMeshSpec, in module abTriangularMesh, that defines the logical structure of a generic triangular mesh. Currently abTriangularMesh supports loading from gmesh format (msh files) used in WW3 and form the SCHISM-specific format Gr3. Moreover, this class is not meant to be handled directly by the final user, but is used in function abEstimateAndSaveTriangularEtopo1 in module abEstimateAndSave.
abSMCGridBuilder: to-be-implemented class for building a abGrid instance for a Spherical Multi-Cell (SMC) mesh. For the sake of its re-usability, this class should not load directly gmesh files, but instead rely on some half-way class defining the logical structure of a SMC mesh. Moreover, it should not be called directly by the user, but handled by proper methods in module abEstimateAndSave.
To be able to understand what unresolved obstacles/features are placed in each cell-polygon, and to estimate α and β, alphaBetLab needs a high-resolution definition of the obstacles/features. This definition is provided through the class abHighResAlphaMatrix, in terms of a high resolution regular matrix of transparency coefficients. The elements of the matrix can assume value between 1 (no obstruction) and 0 (land cell). At high resolution, the transparency coefficients are assumed to be independent from the direction. The constructor of abHighResAlphaMatrix takes as arguments a 2d matrix of alphas, and lists of x and y coordinates. In principle, this class also supports transparency coefficients dependent of frequency (the matrix would be in this case a 3d one). This option could be useful to model unresolved frequency-dependent energy dissipation, like for ice floes. However, this option is currently unsupported by other classes. Method getAlphaSubMatrix of this class returns an instance of abHighResAlphaMatrix corresponding to the minimum matrix covering the polygon passed as argument. This method is invoked within alphaBetaLab, when the α/β coefficients are evaluated for each polygon. Instances of abHighResAlphaMatrix based on etopo1 can be built using the function loadBathy, in module abEtopo1BathyLoader. In these instances, the transparency coefficient has value 1 for sea points, and 0 for land points.
To be able to estimate the Shadow Effect (SE) component of UOST, an upstream polygon needs to be computed for each cell-polygon and spectral component. The upstream polygon of a cell A is defined as the intersection between the joint cells neighboring A and the flux of the spectral component upstream of A. In alphaBetaLab it is computed within the module abUpstreamPolyEstimator, by function getUpstreamPoly. This function takes as arguments a cell-polygon, a neighborhood polygon and a direction. The neighborhood polygon is estimated in alphaBetaLab outside of this function, and is given by the union of the neighbor polygons, that can be retrieved with the function _abGrid.getNeighbors.
For each single polygon (that can be a cell or an upstream polygon), the value of the directional α transparency coefficients are computed by abSingleCellAlphaEstimator objects. The constructor of this class takes as an input a shapely polygon and a abHighResAlphaMatrix instance. The method computeAlpha computes the α transparency coefficient for a given spectral component, as a function of the cross section of the unresolved features inside the polygon, along the propagation direction. Inside the method, the problem is first rotated and reflected, to refer it to the first octant (class abFirstOctantTransformation in module abFirstOctantTransformation). Then the computation is done on the first octant problem (private method _getAlphaFirstOctant of class abSingleCellAlphaEstimator).
For each single polygon (that can be a cell or an upstream polygon), the value of the directional β transparency coefficients are computed by abSingleCellBetaEstimator objects. The constructor of this class takes as an input a shapely polygon and a abHighResAlphaMatrix instance. The method computeBeta computes the β transparency coefficient for a given spectral component. Similar to the method computeAlpha of abSingleCellAlphaEstimator, the problem is reflected and rotated to reduce it to the first octant, then the method _getBetaFirstOctant solves the first octant problem. The algorithm implemented in _getBetaFirstOctant applies the definition of β given in Mentaschi et al., 2015: estimates n polygon slices starting from the upstream side of the cell, for each of these slices estimates the α coefficient. The value of β is then given by the average of the slices’ α coefficients. This approach provides accurate estimations of β, but it is computationally expensive. A future, more optimized implementation will start from the value of α, and change it as a function of the distribution of the obstacles in the polygon: if the distribution mean lies at the upstream side of the cell, then β = α. If it lies at the downstream side, then β = 1. If distribution mean lies at a certain position between the two sides, β will be increased with respect to α by the corresponding fraction.
UOST source term depends on the size of the cell-polygon along the propagation direction of the spectral component. These distances (which must be estimated in meters, and not in geographical degrees) are computed within the class abCellSize, in the homonym module. The algorithm finds the main axes of the cell-polygon, and approximates it as an ellipse.
Class abCellsEstimator assembles together the concepts of mesh (abGrid), upstream polygons, high resolution matrix of transparency coefficients (abHighResAlphaMatrix), spectral grid (although in the current implementation only direction is supported), estimators of α and β and sizes for the single polygons (classes abSingleCellAlphaEstimator, abSingleCellBetaEstimator and abCellSize). This class has two blocks of methods, the first for the computation of α and β coefficients local to the cell-polygon, the second for the computation of α and β coefficients for the shadow, i.e. computed on the cell upstream polygons. These blocks of methods are organized to comply with the needs of the python multiprocessing framework, exploited in module abCellsEstimatorParallel. The main method of the first block is computeLocalAlphaBeta. It loops the cells of the mesh, and for each direction estimates the α and β coefficients. The main method of the second block is computeShadowAlphaBeta. Similar to computeLocalAlphaBeta, it loops the cells of the mesh, but for each cell it estimates the α and β coefficients on the upstream polygon of the cell for the given directional bin. In computeLocalAlphaBeta and computeShadowAlphaBeta, to speed up the computation, a few directional bins are considered (8 in Mentaschi et al., 2018), and the estimated α and β are subsequently interpolated to the directions of the spectral grid.
In cells intersecting large land bodies a parameterization of unresolved obstacles would conflict with the resolved portion of the coastal dynamics. Coastal cells are therefore excluded from the computation of both local dissipation and shadow effect. A coastal cell can, however, be affected by the shadow projected by an obstructed, non-coastal cell. The logics for the detection of coastal cells are implemented in class abCoastalCellDetector (module abCoastalCellDetector). The algorithm treats differently bodies of different size. If a land body is more than 10 (by default) times larger than the size of a cell (this threshold can change), the body is treated as large, and if the cell intersects it for more than 10% (by default) of its surface is excluded from the computation. If a land body is between 2 (by default) and 10 times larger than a cell, it is considered as small body, and the cell is excluded from the computation if it intersects the body for more than 50% (by default) of its surface. Finally, if the land body is smaller than twice the cell, it is considered as unresolved. The application of this algorithm in Mentaschi et al. (2018) showed its limits, especially in proximity of small resolved bodies.