Skip to content

Commit

Permalink
Add get_element_areas
Browse files Browse the repository at this point in the history
  • Loading branch information
hatch-tyler committed May 10, 2023
1 parent bb7723b commit 02b121c
Showing 1 changed file with 102 additions and 38 deletions.
140 changes: 102 additions & 38 deletions src/pywfm/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def __init__(
delete_inquiry_data_file=True,
log_file="message.log",
):

if not isinstance(preprocessor_file_name, str):
raise TypeError("preprocessor_file_name must be a str")

Expand Down Expand Up @@ -793,7 +792,7 @@ def get_element_config(self, element_id):

# convert node indices to node IDs
nodes_in_element = np.array(nodes_in_element)

# get all node IDs in model
node_ids = self.get_node_ids()

Expand All @@ -807,6 +806,60 @@ def get_element_config(self, element_id):

return np.array(elem_config)

def get_element_areas(self):
"""
Return the area of each element in an IWFM model

Returns
-------
np.ndarray of float
array of element areas

Note
----
Areas are returned in the basic model unit of length e.g. feet or meters

See Also
--------
IWFMModel.get_n_elements : Return the number of elements in an IWFM model
IWFMModel.get_element_ids : Return an array of element IDs in an IWFM model
IWFMModel.get_element_config : Return an array of node ids for an IWFM element

Example
-------
>>> from pywfm import IWFMModel
>>> pp_file = '../Preprocessor/PreProcessor_MAIN.IN'
>>> sim_file = 'Simulation_MAIN.IN'
>>> model = IWFMModel(pp_file, sim_file)
>>> model.get_element_areas()
array([40202957.63300251, 41028736.91115934, 56276024.67195904, ...,
54247279.94228962, 63481519.80703662, 22859442.03660104])
>>> model.kill()
>>> model.close_log_file()
"""
# check to see if IWFM procedure is available in user version of IWFM DLL
if not hasattr(self.dll, "IW_Model_GetElementAreas"):
raise AttributeError(
'IWFM API does not have "{}" procedure. Check for an updated version'.format(
"IW_Model_GetElementAreas"
)
)

# set instance variable status to 0
status = ctypes.c_int(0)

# get number of elements
n_elements = ctypes.c_int(self.get_n_elements())

# initialize element areas array
element_areas = (ctypes.c_double * n_elements.value)()

self.dll.IW_Model_GetElementAreas(
ctypes.byref(n_elements), element_areas, ctypes.byref(status)
)

return np.array(element_areas)

def get_n_subregions(self):
"""
Return the number of subregions in an IWFM model
Expand Down Expand Up @@ -995,7 +1048,7 @@ def get_subregions_by_element(self):
-------
np.ndarray
array identifying the subregion where each model element is assigned

Note
----
The resulting integer array will have a length equal to the value returned by get_n_elements method
Expand Down Expand Up @@ -2928,7 +2981,9 @@ def get_stream_diversion_locations(self, diversion_locations="all"):
if stream_diversion_index == 0:
stream_diversion_locations.append(0)
else:
stream_diversion_locations.append(stream_node_ids[stream_diversion_index - 1])
stream_diversion_locations.append(
stream_node_ids[stream_diversion_index - 1]
)

return np.array(stream_diversion_locations)

Expand All @@ -2945,7 +3000,7 @@ def get_stream_diversion_n_elements(self, diversion_id):
-------
int
number of elements where the diversion provides water

See Also
--------
IWFMModel.get_n_diversions : Return the number of surface water diversions in an IWFM model
Expand All @@ -2958,7 +3013,7 @@ def get_stream_diversion_n_elements(self, diversion_id):
>>> sim_file = 'Simulation_MAIN.IN'
>>> model = IWFMModel(pp_file, sim_file)
>>> model.get_stream_diversion_n_elements(1)

>>> model.kill()
>>> model.close_log_file()
"""
Expand All @@ -2980,7 +3035,9 @@ def get_stream_diversion_n_elements(self, diversion_id):
raise ValueError("diversion_id is not valid")

# convert diversion_id to diversion_index
diversion_index = ctypes.c_int(np.where(diversion_ids == diversion_id)[0][0] + 1)
diversion_index = ctypes.c_int(
np.where(diversion_ids == diversion_id)[0][0] + 1
)

# initialize output variables
n_elements = ctypes.c_int(0)
Expand All @@ -2989,7 +3046,7 @@ def get_stream_diversion_n_elements(self, diversion_id):
self.dll.IW_Model_GetStrmDiversionNElems(
ctypes.byref(diversion_index),
ctypes.byref(n_elements),
ctypes.byref(status)
ctypes.byref(status),
)

return n_elements.value
Expand Down Expand Up @@ -3020,7 +3077,7 @@ def get_stream_diversion_elements(self, diversion_id):
>>> sim_file = 'Simulation_MAIN.IN'
>>> model = IWFMModel(pp_file, sim_file)
>>> model.get_stream_diversion_elements(1)

>>> model.kill()
>>> model.close_log_file()
"""
Expand All @@ -3042,20 +3099,24 @@ def get_stream_diversion_elements(self, diversion_id):
raise ValueError("diversion_id is not valid")

# convert diversion_id to diversion_index
diversion_index = ctypes.c_int(np.where(diversion_ids == diversion_id)[0][0] + 1)
diversion_index = ctypes.c_int(
np.where(diversion_ids == diversion_id)[0][0] + 1
)

# get number of elements
n_delivery_elements = ctypes.c_int(self.get_stream_diversion_n_elements(diversion_index.value))
n_delivery_elements = ctypes.c_int(
self.get_stream_diversion_n_elements(diversion_index.value)
)

# initialize output variables
element_indices = (ctypes.c_int * n_delivery_elements.value)()
status = ctypes.c_int(0)

self.dll.IW_Model_GetStrmDiversionElems(
ctypes.byref(diversion_index),
ctypes.byref(n_delivery_elements),
element_indices,
ctypes.byref(status)
ctypes.byref(status),
)

element_ids = self.get_element_ids()
Expand Down Expand Up @@ -4117,9 +4178,7 @@ def get_n_bypasses(self):
# initialize n_stream_reaches variable
n_bypasses = ctypes.c_int(0)

self.dll.IW_Model_GetNBypasses(
ctypes.byref(n_bypasses), ctypes.byref(status)
)
self.dll.IW_Model_GetNBypasses(ctypes.byref(n_bypasses), ctypes.byref(status))

return n_bypasses.value

Expand Down Expand Up @@ -4234,7 +4293,9 @@ def get_bypass_export_nodes(self, bypass_list):
n_bypasses = ctypes.c_int(len(bypass_list))

# convert bypass IDs to bypass indices
bypass_indices = np.array([np.where(bypass_ids == item)[0][0] for item in bypass_list]) + 1
bypass_indices = (
np.array([np.where(bypass_ids == item)[0][0] for item in bypass_list]) + 1
)
bypass_indices = (ctypes.c_int * n_bypasses.value)(*bypass_indices)

# initialize output variables
Expand All @@ -4245,7 +4306,7 @@ def get_bypass_export_nodes(self, bypass_list):
ctypes.byref(n_bypasses),
bypass_indices,
stream_node_indices,
ctypes.byref(status)
ctypes.byref(status),
)

# convert stream node indices to stream node IDs
Expand Down Expand Up @@ -4280,7 +4341,7 @@ def get_bypass_exports_destinations(self, bypass_list):
IWFMModel.get_bypass_outflows : Return the bypass outflows for the current simulation timestep
IWFMModel.get_bypass_recoverable_loss_factor : Return the recoverable loss factor for a bypass
IWFMModel.get_bypass_recoverable_loss_factor : Return the nonrecoverable loss factor for a bypass

Example
-------
>>> from pywfm import IWFMModel
Expand All @@ -4296,7 +4357,9 @@ def get_bypass_exports_destinations(self, bypass_list):
if not hasattr(self.dll, "IW_Model_GetBypassExportDestinationData"):
raise AttributeError(
'IWFM API does not have "{}" procedure. '
"Check for an updated version".format("IW_Model_GetBypassExportDestinationData")
"Check for an updated version".format(
"IW_Model_GetBypassExportDestinationData"
)
)

# handle case where bypass_list is provided as an int
Expand All @@ -4322,7 +4385,9 @@ def get_bypass_exports_destinations(self, bypass_list):
n_bypasses = ctypes.c_int(len(bypass_list))

# convert bypass IDs to bypass indices
bypass_indices = np.array([np.where(bypass_ids == item)[0][0] for item in bypass_list]) + 1
bypass_indices = (
np.array([np.where(bypass_ids == item)[0][0] for item in bypass_list]) + 1
)
bypass_indices = (ctypes.c_int * n_bypasses.value)(*bypass_indices)

# initialize output variables
Expand All @@ -4337,7 +4402,7 @@ def get_bypass_exports_destinations(self, bypass_list):
export_stream_node_indices,
destination_types,
destination_indices,
ctypes.byref(status)
ctypes.byref(status),
)

# get destination IDs
Expand Down Expand Up @@ -4407,7 +4472,7 @@ def get_bypass_outflows(self, bypass_conversion_factor=1.0):
# get number of bypasses
n_bypasses = ctypes.c_int(self.get_n_bypasses())

# convert bypass conversion factor to ctypes
# convert bypass conversion factor to ctypes
bypass_conversion_factor = ctypes.c_double(bypass_conversion_factor)

# initialize output variables
Expand All @@ -4418,7 +4483,7 @@ def get_bypass_outflows(self, bypass_conversion_factor=1.0):
ctypes.byref(n_bypasses),
ctypes.byref(bypass_conversion_factor),
bypass_outflows,
ctypes.byref(status)
ctypes.byref(status),
)

return np.array(bypass_outflows)
Expand Down Expand Up @@ -4460,7 +4525,9 @@ def get_bypass_recoverable_loss_factor(self, bypass_id):
if not hasattr(self.dll, "IW_Model_GetBypassRecoverableLossFactor"):
raise AttributeError(
'IWFM API does not have "{}" procedure. '
"Check for an updated version".format("IW_Model_GetBypassRecoverableLossFactor")
"Check for an updated version".format(
"IW_Model_GetBypassRecoverableLossFactor"
)
)

if not isinstance(bypass_id, int):
Expand All @@ -4482,7 +4549,7 @@ def get_bypass_recoverable_loss_factor(self, bypass_id):
self.dll.IW_Model_GetBypassRecoverableLossFactor(
ctypes.byref(bypass_index),
ctypes.byref(recoverable_loss_factor),
ctypes.byref(status)
ctypes.byref(status),
)

return recoverable_loss_factor.value
Expand All @@ -4506,7 +4573,7 @@ def get_bypass_nonrecoverable_loss_factor(self, bypass_id):
IWFMModel.get_n_bypasses : Return the number of bypasses in an IWFM model
IWFMModel.get_bypass_ids : Return the bypass identification numbers specified in an IWFM model
IWFMModel.get_bypass_export_nodes : Return the stream node IDs corresponding to bypass locations
IWFMModel.get_bypass_exports_destinations :
IWFMModel.get_bypass_exports_destinations :
IWFMModel.get_bypass_outflows : Return the bypass outflows for the current simulation timestep
IWFMModel.get_bypass_recoverable_loss_factor : Return the recoverable loss factor for a bypass

Expand All @@ -4524,7 +4591,9 @@ def get_bypass_nonrecoverable_loss_factor(self, bypass_id):
if not hasattr(self.dll, "IW_Model_GetBypassNonRecoverableLossFactor"):
raise AttributeError(
'IWFM API does not have "{}" procedure. '
"Check for an updated version".format("IW_Model_GetBypassNonRecoverableLossFactor")
"Check for an updated version".format(
"IW_Model_GetBypassNonRecoverableLossFactor"
)
)

if not isinstance(bypass_id, int):
Expand All @@ -4546,7 +4615,7 @@ def get_bypass_nonrecoverable_loss_factor(self, bypass_id):
self.dll.IW_Model_GetBypassNonRecoverableLossFactor(
ctypes.byref(bypass_index),
ctypes.byref(nonrecoverable_loss_factor),
ctypes.byref(status)
ctypes.byref(status),
)

return nonrecoverable_loss_factor.value
Expand Down Expand Up @@ -6429,7 +6498,7 @@ def get_well_ids(self):
)

return np.array(well_ids)

def get_well_coordinates(self):
"""
Return the pumping well x- and y-coordinates
Expand All @@ -6439,7 +6508,7 @@ def get_well_coordinates(self):
tuple of np.ndarrays
x-coordinates for wells
y-coordinates for wells

See Also
--------
IWFMModel.get_n_wells : Return the number of wells simulated in an IWFM model
Expand All @@ -6454,7 +6523,7 @@ def get_well_coordinates(self):
>>> sim_file = 'Simulation_MAIN.IN'
>>> model = IWFMModel(pp_file, sim_file)
>>> model.get_well_coordinates()

>>> model.kill()
>>> model.close_log_file()
"""
Expand All @@ -6474,13 +6543,10 @@ def get_well_coordinates(self):
x = (ctypes.c_double * n_wells.value)()
y = (ctypes.c_double * n_wells.value)()

self.dll.IW_Model_GetWellXY(
ctypes.byref(n_wells), x, y, ctypes.byref(status)
)
self.dll.IW_Model_GetWellXY(ctypes.byref(n_wells), x, y, ctypes.byref(status))

return np.array(x), np.array(y)


def get_n_element_pumps(self):
"""
Return the number of element pumps simulated in an
Expand Down Expand Up @@ -8715,7 +8781,6 @@ def _get_hydrograph_ids(self, location_type_id):
num_hydrographs = ctypes.c_int(self._get_n_hydrographs(location_type_id.value))

if num_hydrographs.value != 0:

# initialize output variables
hydrograph_ids = (ctypes.c_int * num_hydrographs.value)()

Expand Down Expand Up @@ -8960,7 +9025,6 @@ def _get_hydrograph_coordinates(self, location_type_id):
num_hydrographs = ctypes.c_int(self._get_n_hydrographs(location_type_id.value))

if num_hydrographs.value != 0:

# initialize output variables
x = (ctypes.c_double * num_hydrographs.value)()
y = (ctypes.c_double * num_hydrographs.value)()
Expand Down

0 comments on commit 02b121c

Please sign in to comment.