from landlab import VoronoiDelaunayGrid
import numpy as np

"""
Explanation: <a href="http://landlab.github.io"><img style="float: left" src="../../landlab_header.png"></a>
Setting Boundary Conditions on a Voronoi.
<hr>
<small>For more Landlab tutorials, click here: <a href="https://landlab.readthedocs.io/en/latest/user_guide/tutorials.html">https://landlab.readthedocs.io/en/latest/user_guide/tutorials.html</a></small>
<hr>

This tutorial illustrates how to modify the boundary conditions on a voronoi grid.
End of explanation
"""


np.random.seed(1234)
x, y = np.random.rand(25), np.random.rand(25)
vg = VoronoiDelaunayGrid(x, y)

"""
Explanation: Instantiate a grid.
End of explanation
"""


vg.status_at_node

"""
Explanation: The node boundary condition options are:

vg.BC_NODE_IS_CORE (status value = 0; all operations are performed on a mg.BC_NODE_IS_CORE)
vg.BC_NODE_IS_FIXED_VALUE (status value = 1; a boundary node with a fixed value)
vg.BC_NODE_IS_FIXED_GRADIENT (status value = 2; a boundary node with a fixed gradient)
vg.BC_NODE_IS_LOOPED (status value = 3; a boundary node that is wrap-around)
vg.BC_NODE_IS_CLOSED (status value = 4; closed boundary, or no flux can cross this node, or more accurately, can cross the faces around the node)

(Note that these options are designed for the convenience in writing Landlab applications, and  are not "automatically enforced" in internal Landlab functions. For example, if you add two node fields together, as in my_field1 + my_field2, all values will be added, not just core nodes; to take advantage of boundary coding, you would use a syntax like my_field1[grid.core_nodes] + my_field2[grid.core_nodes].)
Check the status of boundaries immediately after instantiating the grid:
End of explanation
"""


vg.imshow(vg.status_at_node, cmap="cool", show_elements=True)

"""
Explanation: The default conditions are for the perimeter to be fixed value (status of 1) and the interior nodes to be core (status of 0).
This is not actually much easier to see graphically, because the perimeter nodes are not colored.  Note that they have a value of 1, so it seems they should be shown as purple, but the plotter does not color them because they don't have a defined cell size.
End of explanation
"""


vg.status_at_node[
    vg.status_at_node == vg.BC_NODE_IS_FIXED_GRADIENT
] = vg.BC_NODE_IS_CLOSED
vg.imshow(
    vg.status_at_node,
    cmap="cool",
    limits=(-0.01, 4),
    color_for_closed="red",
    show_elements=True,
)
vg.status_at_node

"""
Explanation: Now suppose we want closed nodes on the boundary, instead of fixed value nodes.
We can change this by accessing the nodes that are currently fixed value and changing their status.
End of explanation
"""


np.random.seed(4321)
x, y = np.random.rand(25), np.random.rand(25)
vg2 = VoronoiDelaunayGrid(x, y)
vg2.add_ones("topographic__elevation", at="node")
vg2.at_node["topographic__elevation"][vg2.x_of_node < 0.5] = -1.0

"""
Explanation: Now all of the nodes that had a status value of 1 have a status value of 4, but again viewing this graphically is not very helpful.  The array values have appropriately changed.
Now let's instantiate a new grid and give it some elevation values.  In this case any node that has an x value < 0.5 will have an elevation of -1.  Othewise, the nodes have a value of 1.
End of explanation
"""


vg2.imshow(vg2.at_node["topographic__elevation"], cmap="cool", show_elements=True)
vg2.at_node["topographic__elevation"]

"""
Explanation: Illustrate the topography and show the values.
End of explanation
"""


vg2.set_nodata_nodes_to_closed(vg2.at_node["topographic__elevation"], -1.0)
vg2.imshow(
    vg2.status_at_node,
    color_for_closed="red",
    cmap="cool",
    limits=(-0.01, 1),
    show_elements=True,
)
vg2.status_at_node

"""
Explanation: Now we can illustrate the grid and see at least some of the closed elements by using the imshow option color_for_closed.  Again remember that some of the nodes that are plotting in white areas are closed as well - that is, the ones that have an x value less than 0.5 are closed.
End of explanation
"""


