Ruralwater

GPLv3 license

Purpose of the project

Open source webapp to allow the design of rural water supplies for non-specialists.

Motivation

This project exists because the design of rural water supplies poses challenges to optimize the investment costs and limit the running costs.
This may be particularly interesting in the case of humanitarian interventions (say in rural communities of Africa, Asia, Latin America), where the funds may be limited and where personnel deployed by humanitarian organizations may not have an engineering professional background.
More information on our website and its quickstart (2019 version, will be updated soon).

How to install ‘ruralwater’ on your local machine

These steps will get you a copy of the project up and running on your local machine for development and testing purposes.
Prerequisites:
  • Python 3.7+

  • Redis

Remark: if, for any reason, you do not want to install redis on your local machine, then, once you have cloned the repository, edit the following setting inside file webapp.core.settings.redis.py: USE_REDIS = True and set it to False.
Installation:
We have created a setup script that should install ruralwater on your local machine in a single command. If this fails, we detailed below the manual installation process.
Once python (and optionally redis) are installed on your local machine and you have cloned the repository, follow the steps below:
  • clone the development branch on you local machine

  • run the script setup_linux_complete.sh (linux) or setup_win_complete.ps1 (windows)

  • Navigate to localhost (http://127.0.0.1:8000/)

You will now see “ruralwater” up and running.
If anything went wrong, then apologise us and follow the steps below.

Manual installation

Once python (and optionally redis) are installed on your local machine and you have cloned the repository, follow the steps below:
  • clone the “development” branch on you local machine

  • create and activate a virtual environment

  • install the requirements at requirements/development.txt

  • run the script setup_linux_database.sh (linux) or setup_win_database.ps1 (windows)

  • Navigate to localhost (http://127.0.0.1:8000/)

You will now see “ruralwater” up and running.

More specifically, setup_*_database implements the following operations:
  • generates the database (using the django framework)

  • populates the database with the hydraulic hardware data

  • creates a superuser and two mock users:

    1. ‘demo’, who is the superuser, with password: pippo121

    2. ‘cat’, with password: meow

    3. ‘dog’, with password: bark

What is ‘hydraulic hardware’? The hydraulic hardware data are the data of the commercially available water pipes, and a selection of some water pumps and diesel engines available from manufacturers. Data include bores of pipes and plate data of pumps and engines. These data are needed since the software algorithms needs them to run its algorithms.

Contributing

The mission of this project is stated at our website.
Additional information may be found in the following documents:
  • XXX for an introduction to the ‘application programming interface’ exposed by the ‘business logic’

  • For contributors more interested in “test-driven development” XXX provides the description of the tests currently included in this repository.

More documentation on the project can be found here:

Current status of the project

The project at present (october 2020) is a ‘proof of concept’. Contributions are welcomed especially in the following fields:
  • the algorithm to optimize the design of dendridic gravity-fed water supplies

  • the design of the user interface, more specifically the javascript for the client side controls to define the water supply.|

Tech/framework used

Ruralwater is built with:

Tests

If you desire to test the entire webapp, do the following:
  • cd into the ‘webapp’ folder

  • run: python manage.py runserver

  • run: python manage.py test

Remark: it is necessary to run the server before running the tests, as it is shown in the above code snippet, becasue the tests must access those “hydraulic hardware data” referred to above (section hydraulic_hardware)
More information about testing may be found in the testing forlder and specifically inside the file howto_casestudies.md.
If you desire to simply thest the ‘business logic’ (not the entire webapp), then do the following:
  • cd into the ‘webapp’ folder

  • run: python manage.py runserver

Authors

Manual

Hydraulics

Note: Once you have read through all the documentation, you can then see business package
Ruralwater models two kinds of rural water supplies: “gravity” and “from a borehole”, also known as “station” (short form for “pump station from borehole”).
Remark in all the images in this page, the vertical dimension has

been enhaced to make it more evident all calculations based on altimetric elevation and hydraulic energy. So, the slopes of the pathways appear very steep, much more than the reality found walking on the ground.

here is a pdf file pdf

5_pathways_overbank.svg

What the software does

The software tackles two distinct kinds of hydraulic problems:

  • the hydraulic design problem - given the required water flow, find the pipes that will provide such water at the minimum cost

  • the hydraulic check problem - given the pipes, find the water flows and perform a control to see whether the working conditions do not exceed the rated limits of the installed hydraulic hardware.

Gravity

The physical system

In a gravity water supply we have a water spring and a network of pipes, shaped as a tree, which brings the water to a number of water reservoirs at a lower elevation than the spring itself.

General concepts

The names in bold below correspond to those used by the classes of the software.

The ‘topology’ of the water supply system
A tree represents the water supply system composed of its pathways from the source to each water reservoir. A pathway represents the trench along which the pipes are laid down.
A pathway has a ‘tail end’ and a ‘head end’ and water flows from tail to head. A pathway has an altimetric profile associated with it.
Since the pathways are laid down as the branches of a tree, then each pathway may have ‘children’ pathways that branch off its head end.
The network is a tree; therefore water flows in a unique path and direction towards each reservoir.

The ‘water demand’ in the water supply system
Water abstraction takes place only at the reservoirs; indeed, we assume that the users live ‘nearby’ the reservoirs. One may imagine that the reservoirs are placed in the centre of the various village neighbourhoods (or near a school, near the market, near the location where the village houses or huts are more scattered). There are no water abstractions along the pathway. Therefore water flow along each pathway remains constant along the pathway itself.

The ‘independent parts’ in the water supply system (a.k.a. the ‘pressure zones’)
Let’s imagine that we have a spring that serves two villages located in a valley, and the second village is further downstream in the valley. In this case the topology of the water supply will be: (1) a pathway from the spring to the ‘nearest village’ and a second pathway from the ‘nearest’ to the ‘farthest village’. In this case, all the water that reaches the second village (the farthest) will flow through the reservoir of the first (the closest) village. This is a common scenario and more complex topologies could also exists, like in the images of the tutorial, where there is a Y-shaped water supply, and one of the reservoirs feeds another village, more far away. Remark: in all such cases, the water reservoir behaves like a ‘spring’ for any other pathway that abstracts water from such reservoir and transports it further away downstream. Therefore a tree of pathways may be split into one or more disjoint pressure zones.
From the point of view of hydraulic equations, every pathway whose head end is a reservoir gives rise to an independent water supply system stemming from each of its child pathways. In fact, from the point of view of solving the hydraulic equations, a reservoir is identical to the spring: it is “what provides water” into the “downstream” pipes (otherwise said: it provides water into the downstream section of the water supply). This independent system is called a pressure zone. Each pressure zone is independent of the others and their hydraulic energy equations are solved separately.
How water flow is controlled in the water supply system
Nothing controls the water flow better than the law of gravity. Since we are talking about reliable solutions and intrinsic technology, with as little maintenance as possible, we avoid using ‘gate-valves’ installed along the pathways and then partially closed to the required amount of water. Instead, the pipes have no gate-valves, the flow flows continuously along the 24 hours and fills the water reservoirs. The water flow is set by the diameters of the commercial pipes and by the continuous flow under gravity. The next section introduces the equations of flow under the pure force of gravity.

The equations that model the system

The gravity water supply is modelled by two kinds of equations:
  • the continuity of water flows.

  • the continuity of hydraulic energy.

Continuity of water flows:
For each pathway, its water flow is the sum of the water flows in its children pathways plus the water flow, if any, required at its head end. If such water flow at the head end exists, then the head end is a reservoir and each of the children pathways represents the source for a “separated” or “independent” water supply.

Continuity of hydraulic energy:
This is the law of Bernoulli. For each pathway, the hydraulic energy at its head end is equal to the energy at the tail end minus the hydraulic friction in the pathway due to its water flow and to the sequence of pipes laid down along the trench.

Example
Imagine you have the following gravity water supply:
  • there is a spring

  • from th spring the pipeline goes to a junction where the pipe branches in two

  • the two branches go to Tank1 and Tank2 respectively.

This is therefore a Y-shaped water supply, a typical configuration where one source, the spring, must be shared by two villages or by two water tanks at the opposite ends of a larger village.
The equations that describe this system are:
  • the conservation of water flows

  • the energy difference in each of the 3 branches is the hydraulic friction in the pipes

These equations are written below:

We start with the conservation of flows:

\[\begin{eqnarray} Q_{Spring\rightarrow{Tee}} = Q_{Tee\rightarrow{Tank1}} + Q_{Tee\rightarrow{Tank2}} \end{eqnarray}\]

Next comes the conservation of energy:

\[\begin{split}\begin{eqnarray} Z_{Spring} - kQ_{Spring\rightarrow{Tee}}^2(\sum_{j=1,...,segments} {\frac{L_j}{D^5_j}}) = H_{Tee} \\ H_{Tee} - kQ_{Tee\rightarrow{Tank1}}^2(\sum_{j=1,...,segments} {\frac{L_j}{D^5_j}}) = Z_{Tank1} \\ H_{Tee} - kQ_{Tee\rightarrow{Tank2}}^2(\sum_{j=1,...,segments} {\frac{L_j}{D^5_j}}) = Z_{Tank2} \end{eqnarray}\end{split}\]
Where the symbols represent:
\(Z_{Spring}\) is the elevation of the spring
\(H_{Tee}\) is the hydraulic energy at the junction of the Y-shaped pathways
\(Z_{Tank1}\) and \(Z_{Tank2}\) are the elevations of the two water tanks where the water flows to
for each segment, \(L_j\) and \(D_j\) represent xxx and \(j\) is the index over the piped segments. A piped segment is a stretch along which the same pipe is used.
Example explaining the piped segments: Imagine to have one pathway is long 1000 meters and that we use a ‘2 inches pipe rated for 60 meters of water pressure’ (short-handed as 2”PN6 pipe) for 600 meters followed by a ‘3 inches with the same pressure rating’ (short-handed 3”PN6) in the remaining 400 meters of the pathway pathlength. Then, we have two segments and the symbols in the above sum would bear the values of:

\(L_1\) would be 600 \(D_1\) would be the internal diameter of a 2 inches pipe \(L_2\) would be 600 \(D_2\) would be the internal diameter of a 2 inches pipe

In the ‘hydraulic design problem’ the unknowns are: \(Q_{Spring\rightarrow{Tee}}\) \(Q_{Tee\rightarrow{Tank1}}\) \(Q_{Tee\rightarrow{Tank2}}\) The known data are all the other symbols. Therefore we have 4 equations and 4 unknowns and the system can be solved.

Check

With reference to the above equations, the hydraulic check problem is the problem of solving the above equation, where the unknowns are the water flows.

Design

This requires much more engineering judgement than the hydraulic check.
Let’s investigate the tree of pipes. In such condition there is an interesting problem of economics. At each pathway, the hydraulic energy at its tail end and head end should remain close to the ground elevation so that the pressure along the pathway remains low and all the pipes may be selected from those commercial pipes belonging to the lowest rated pressure class. If this is the case then each pathway may be solved separately with the technique of the “simplex”. pressures.
However, real life cases may involve hilly profiles. The pathway may cross a deep valley. This is the case when the villages are scattered on the other flank of a valley from that were the water spring is located. In such cases, the values of hydraulic energy at tail and head ends of the pathways must be kept “far above” the ground elevation if a head end lies in the middle of a valley that is crossed by the water supply. In this case an interesting (and difficult) problem of optimization arises: is is preferable to burn more hydraulic energy through friction in the pipe sections with higher pressure rating or the opposite? The solution depends, case by case, from the amount of water required and from the elevation profile along the pathways. This problem of optimization cannot be solved using the “simplex” method. In fact, it is not a “convex problem” due to the discontinuities introduced by the existence of both discrete diameters and discrete pressure ratings. See :ref: algorithms_gravity_design how this translates in an algorithm.
base.svg

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Y_shaped_pathways.svg

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Y_waterflow_right.svg

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Y_waterflow_left.svg

Borehole’s station

I link with the module gravity now i link with the class GravityDesign and even the method solve_hydraulic_design_problem()

I want to refer to the equations (system_of_equations) and to the algorithm (the_algorithm)

We now move to the second typology of rural water supply system: a small pumping station that connects a borehole, with a water reservoir which is far from the borehole and usually at higher that that of the site where the borehole is located.

We deal with two kinds of borehole stations: with and without electric power. The reason is because this software is dedicated to rural solutions and, as such, it must consider the case where electric power is not available.

Remark: with ‘not available’ here we mean an arrangement that works entirely *without electric power. With ‘electricless’ we mean a solution that is not *making use of electric power because it is preferred to have a rural plant

Where electric current is not available, it can nonetheless be produced by an electric generator set.

However, when we speak of ‘electricless’ pumping station, we mean that the presence of electric power is intentionally avoided (and so it is avoided to use an electric generator) despite it can always be generated even in remote area by a generating set. The logic is that electric power is both a difficult subject and it introduces complexity in the hardware and the need for spare parts.

The key point is that electric power might be tricky in a rural context. Knowledge about how to run the maintenance of an electric pumping station is hard and could be not available locally; perhaps the spare parts could be difficult to find on the local market. For these reasons, this software allows you to design a pumping station composed of electricity-free parts, and more precisely: a diesel engine with manual start, that drives directly a pump, with no need of electric motor in the pump (since it is driven directly by the engine through a system of belts and pulleys) nor of electric start in the diesel engine itself (which is indeed started manually with a handle keyed on the crankshaft). Readers who have experience in humanitarian water supply interventions in rural areas of the world will recognise in this ‘electricless’ station the arrangement with a Listeroid diesel engine and a monopump. We provide more information about such equipment in these pages: LINK engine and LINK pump.

  • the ‘electric’ arrangement, where we may use electric power.

IMPORTANT: this a work in progress so the sections below are now kept as stubs for future implementation.

Electric Station

Check problem

TODO

Design problem

We examine the case of a feeder. The feeder entails an interesting problem of economics.

Will it be preferable to adopt small bore feeders (and therefore limit the cost of pipes) and consequently have a high hydraulic energy to overcome (and therefore install more expensive pumps) or adopt the opposite solution (larger pipes and smaller pumps)?

Electricless Station

Check problem

TODO

Design problem

TODO

Algorithms

Gravity

As seen in Gravity, the network of pipes is shaped as a tree. Ruralwater models the network of pipes as a directed acyclic graph (i.e.: a tree) whose nodes are the pathways.

here is a pdf file pdf

Check problem

The hydraulic check problem algorithm is the following:
  • create the hydraulic energy equations of the law of Bernoulli, where the known data are: the friction per unit water flow, the elevation at the spring and at all the reservoirs.

  • create the water flow continuity equations for each pathway that has children.

  • the unknowns are: the water flow in each pathway

  • create the symbolic equations of the law of Bernoulli

  • create the symbolic equations of the law conservation of water flow

  • consider the equations above as a system of equations and solve it.

  • once the system of equation is solved, consider the water flow obtained in each pathway and calculate the hydraulic energy along each pathway.

  • detect if at any point in any of the pathways, the resulting water pressure (hydraulic energy minus elevation) exceeds the pressure limit for the pipe used in that position.

Design problem

The overbanking energy, an introductory concept, is now introduced.

Overbanking energy

Water flows from higher to lower hydraulic energy… 💪 Therefore we set recursively the minimum hydraulic energy at a pathway’s tail end to be the energy at the head end plus “some energy” to allow a difference of hydraulic energy along the pathway and therefore the water flow. Typically the overbanking energy is the elevation plus “some energy”, but in the case that the pathway climbs a hill then the overbanking energy is the highest elevation point downstream plus “some energy”.

Steps of the algorithm

The idea is then to perform a “search” by inspecting all possible combinations of hydraulic energy the pathways. This is therefore a permutation. For the allowed value of energy, the root pathway has a tail end energy fixed (it is the elevation), each of the leaves have a head end fixed energy (their elevations). The permutations regard therefore the head energy of the root pathway, the tail energy of the leaves pathways and both tail and head energy of each pathway that are neither root nor leaf. Also, the permutation must be limited to those combinations that allow an energy differential between tail and head end. The goal of the coroutine is exactly to ensure the above conditions. This is so because the coroutine is a generator that allow to loop and ensure the above conditions. Since this process must be valid for each possible topology of the branched network, then the coroutine is in charge of tackling this problem in a generic approach valid for each topology.

Image “5_pathways_overbank - only maxmin hydr energy” shows this idea.

  • the “Tee Up” may have a max energy of X otherwise water could not flow from the spring

  • the “Tee left” must

  • the same logic applies to “Tee right”

  • The pathways are nodes and some of them are leaves.

  • the algorithm breaks down the tree of pathways into the pressure zones

  • for each pressure zone it executes the steps below

  • it sets the hydraulic energy at the tail end of the root node to be identical to the elevation at that end

  • it sets the hydraulic energy at the head end of each leaf node to be identical to the elevation at that end

  • it traverses the tree with a ‘depth-first search’ methodology

  • while performing such depth-first search, it sets the ‘over-banking’ hydraulic energy to each node (apart from the leaves nodes) tail end. QUESTA FRASE IN MAIUSCOLO EST INCOMPLETA : THIS OVERBANKING ENERGY IS SET RECURSIVELY TO BE “A BIT” GREATER THAN THE OVERBANKING ENERGY AT THE LEAF NODES. COSA FAI AI NODI INTERNI? NON LO HA DETTO

  • it permutes through all the combinations of over-banking energy at each non-leaf node. At this point each pathway has a value of tail end and head end hydraulic energy set.

  • it evaluates the most economic pipes for those values of energy; this is the XXX algorithm and is still source of study. The evaluation of which are the most economic pipes cannot be solved by use of the simplex algorithm (as other softwares do) becasue we are dealing with hilly profiles (rural indeed) and therefore the pipe pressure classes must be taken in account and the problem to solve becomes non-convex. So, no simplex algorithm of use here…. 😞

  • it sums the economic cost from each pathway

  • it selects the solution which led to the lowest economic cost.

Electric Station

Check problem

TODO

Design problem

TODO

Electricless Station

Check problem

TODO

Design problem

TODO

The hydraulic problem

Here we talk about the problem in the hydraulicn theory. See Hydraulics to know what the water engineer must do.

The computer software algorithm

Here we talk about the computer algorithm to tackle the hydraulic theory. See Algorithms to know what the computer scientist must do.

business package

Provide the business logic for rural water supplies.

Solves the ‘hydraulic design problem’ and the ‘hydraulic check problem’ for two typologies of water supply, fit for the rural environment: gravity and station.

Modules

The public API of ruralwater is composed of two modules:

  • gravity:

    models the transport of water by gravity

  • station:

    models the transport of water from a borehole to a reservoir

Subpackages

business.commons package

business.commons.no_piped_segments = <business.commons.definitions.NoPipedSegments object>

Prescribes the handle to the singleton of ‘spurious piped segment’ when the linear optimization algorithm fails to find a solution.

business.commons.simplex_failure_list = SimplexFailure

Prescribes the handle to the singleton of ‘list of spurious piped segments’ when the linear optimization algorithm fails to find a solution. It may be due to either a numerical issue or to ‘flat’ or ‘steep’ profile. See SlopeOutsideFeasibleRange.

Subpackages

business.commons.mixins package
Submodules
business.commons.mixins.cost module
class business.commons.mixins.cost.PipesCostMixin

Bases: object

Functionalities to evaluate the cost of _piped_segments.

property get_cost

Return cost estimates for a Trunk*or a *SoilStretch

Note

Precondition: piping_list is set.

Returns

The cost of the sequence of PipingList instances associated with the Trunk*or or with the *SoilStretch.

Return type

decimal.Decimal

business.commons.mixins.interpolation module
class business.commons.mixins.interpolation.PointFactoryMixin

Bases: object

Mixin holding functionalities to crete points of the elevation profile.

create_point_at_given_downrange(downrange)

Create and return a new ElevationProfile point.

The point is created through interpolation of elevation and pathlength along the sequence of downranges of the ElevationProfile. The caller will be in charge of inserting the ElevationProfilePoint here returned into the ElevationProfile.

Parameters

downrange (Quantity("length", float)) – the downrange at which interpolation is evaluated

Returns

the newly created point.

Return type

commons.ElevationProfilePoint

class business.commons.mixins.interpolation.ProfileInterpolationMixin

Bases: object

Mixin holding functionalities to interpolate a point of an ElevationProfile.

get_elevation_at_given_downrange(downrange)

Return the interpolated elevation at a given downrange.

Parameters

downrange (Quantity("length", float)) – the downrange at which the elevation must be evaluated

Returns

the interpolated elevation

Return type

Quantity(“length”, float)

get_interpolated_downrange_at_pathlength(pathlength)

Return the interpolated downrange at a given pathlength.

Parameters

pathlength (Quantity("length", float)) – the pathlength at which the downrange must be evaluated

Returns

the interpolated downrange

Return type

Quantity(“length”, float)

get_interpolated_elevation_at_pathlength(pathlength)

Return the interpolated elevation at a given pathlength.

Parameters

pathlength (Quantity("length", float)) – the pathlength at which the elevation must be evaluated

Returns

the interpolated elevation

Return type

Quantity(“length”, float)

get_interpolated_pathlength_at_downrange(downrange)

Return the interpolated pathlength at a given downrange.

Parameters

downrange (Quantity("length", float)) – the downrange at which the elevation must be evaluated

Returns

the interpolated pathlength

Return type

Quantity(“length”, float)

business.commons.mixins.linear module

Provide algorithms performing linear programming optimization.

class business.commons.mixins.linear.SingleLinprogStretchMixin

Bases: object

Algorithms for linear programming algorithms in use by BaseStretch.

linear_solver()

return the piped segments resulting from linear programming optimization

get_open_flow_pipe_segments()

return the single piped segment when ‘open flow’ conditions occour

property get_open_flow_pipe_segments

Return the single piped segment when ‘open flow’ conditions occour

This method is called when, in a **, the elevation prfile is so steep that the required water flow is carried ‘as in a canal’. Any commercial pipe from the catalog is fit and hence it must be chosen the one which costs less.

Returns

a one-element list; the element is a piped segment which extends for the whole length of the trunk, and whose pipe is the most economical picked from the catalog of available pipes.

Return type

List[PipedSegmentDesign]

property linear_solver

Return the piped segments resulting from linear programming optimization.

Functionality: Returns the sequence of piped segments which leads to the ‘least cost’ at the given _water_flow and at the given hydraulic energy at tail and head ends.

If linear programming detects that there is no solution, then an exception is raised and will be handled by the caller of this method.

Returns

list(helpers.definitions.PipedSegmentDesign): the list of piped segments resulting from successful implementation of the ‘simplex’ methodology (Dantzig theorem).

Return type

List[PipedSegmentDesign]

Submodules

business.commons.TODO_settings module

business.commons.adapters module

Provide the adapters reading altimetric data from external files.

class business.commons.adapters.AltimeterFileAdapter(fullpath)

Bases: object

Adapter from field surveys carried with ‘rope and barometric altimeter’

cleaned_data

return the csv data, packed in ElevationProfilePoint namedtuples

property cleaned_data

Return the elevation profile as a tuple of points.

Each point bears dimensional data.

Returns

the elevation profile, each point packed in a namedtuple.

Return type

Tuple[ElevationProfilePoint]

class business.commons.adapters.CacheCsvRows(*args, **kwargs)

Bases: dict

A dictionary that caches the data returned by a csv reader.

Functionality: cache for csv reader, when data must be iterated over multiple times.

The keys are the paths (strings) to the csv files. When a key is missing, this dictionary reads and stores the csv file rows. When a key is present, this dictionary returns the csv rows.

This class is used to read a csv file once and then to be able to iterate over the rows multiple times without reading again the source file. It is used when an adapter iterates multiple times over the rows, once for data cleaning, then for adapting the data into a required format.

Important

It inherits from dict directly because we are changing functionality that’s limited to a single method.

class business.commons.adapters.LevelrodFileAdapter(_fullpath: str)

Bases: business.commons.loggers.InitLoggerMixin

Adapter from field surveys carried with the ‘level rod’.

Open, read and validate data from the file describing the field readings taken from a level rod survey.

Parameters

fullpath (str) – the full path to the external source which contains the data.

class TurningPointReading(back_low: int, back_mid: int, back_high: int, fore_low: int, fore_mid: int, fore_high: int, remarks: any)

Bases: business.commons.loggers.InitLoggerMixin

A dataclass record to represent one levelrod reading.

back_high: int
back_low: int
back_mid: int
fore_high: int
fore_low: int
fore_mid: int
remarks: any
property cleaned_data

Return the elevation profile as a tuple of points.

Each point bears dimensional data. The values of each point (downrange, elevation, pathlength) are evaluated according to levelrod trigonometry. Refer to textbooks for the theory.

Returns

the elevation profile, each point packed in a namedtuple.

Return type

Tuple[ElevationProfilePoint]

class business.commons.adapters.MapQuestApiAdapter(fullpath)

Bases: business.commons.adapters.TrustedRawAltimetricFileAdapter

Adapter from MapQuest api service (https://www.mapquest.com/)

Important

There is no need to clean the data: they are provided by an external service (MapQuest) and are therefore assumed to be correct.

class business.commons.adapters.TrustedRawAltimetricFileAdapter(fullpath)

Bases: object

Adapter from a ‘trusted’ source: no data cleaning performed.

cleaned_data

return the csv data, packed in ElevationProfilePoint namedtuples

property cleaned_data

Return the elevation profile as a tuple of points.

Each point bears dimensional data.

Returns

the elevation profile, each point packed in a namedtuple.

Return type

Tuple[ElevationProfilePoint]

class business.commons.adapters.UntrustedRawAltimetricFileAdapter(fullpath)

Bases: business.commons.adapters.TrustedRawAltimetricFileAdapter

Adapter from an ‘untrusted’ source: data cleaning is provided.

property cleaned_data

Return the elevation profile as a tuple of points. Each point bears dimensional data.

business.commons.constants module

Collection of constants used by gravity and pumpstation folders.

business.commons.constants.FLOW_EXPONENT = 2

Prescribes the exponents used in the Darcy-Weisbach hydraulic friction formulae.

business.commons.constants.MIN_TO_MAX_WIGGLE_DEMAND_PERCENT = 0.6

Prescribes a default ration between forecasted demand and a minimal acceptable demand.

business.commons.coroutines module

Avoid running useless heavy computations.

class business.commons.coroutines.CoroutineMinima(*args, **kwargs)

Bases: collections.defaultdict, business.commons.loggers.InitLogger

Cache to store the best result so far in a systematic seach process.

Functionality: store the best result so far in a systematic search optimization process.

When the coroutines perform a systematic search process aiming at optimizing the design of a rural system, the penalty of each solution may be compared with the ‘best minimum so far’ available from this class. If the best minimum is exceeded, then the coroutine may skip calculations. INGLESE, QUESTA E’ UNA FRASE CHE NON SO COME SCRIVERE.

store(root_slug, candidate_minimum)

Set the value for a given key.

Parameters
  • root_slug (str) – the key where to set the value

  • candidate_minimum (decimal.Decimal) – the value to be set.

business.commons.defaults module

Collection of default input values used by gravity and pumpstation folders.

business.commons.defaults.design_years = 20

Prescribes the default number of years to evaluate the forecasted demand.

business.commons.defaults.population_growth_rate = 0.15

Prescribes the default demographic growth to evaluate the forecasted demand.

business.commons.definitions module

Provide definitions used when solving the ‘hydraulic design problem’.

class business.commons.definitions.CheckCalculationsReport(check_is_completed: bool = None, check_solution: business.commons.definitions.CheckSolution = None, errors: dict = None)

Bases: object

check_is_completed: bool = None
check_solution: business.commons.definitions.CheckSolution = None
errors: dict = None
class business.commons.definitions.CheckSolution(status: Any = None)

Bases: tuple

Store the report from the hydraulic check problem calculations..

property status

Alias for field number 0

class business.commons.definitions.DesignCalculationsReport(design_is_successful: bool = None, optimized_solution: Set[business.commons.definitions.TraversalSolution] = None, errors: dict = None)

Bases: object

design_is_successful: bool = None
errors: dict = None
optimized_solution: Set[business.commons.definitions.TraversalSolution] = None
class business.commons.definitions.DesignSolution(cost_per_beneficiary: decimal.Decimal = Decimal('0'), cost_per_liter: decimal.Decimal = Decimal('0'), design_details: Any = None, errors: Any = None, investment_cost: decimal.Decimal = Decimal('0'), running_cost: decimal.Decimal = Decimal('0'), water_flow: pint.quantity.build_quantity_class.<locals>.Quantity = None)

Bases: tuple

Store the report from the ‘hydraulic design problem’ calculations..

property cost_per_beneficiary

Alias for field number 0

property cost_per_liter

Alias for field number 1

property design_details

Alias for field number 2

property errors

Alias for field number 3

property investment_cost

Alias for field number 4

property running_cost

Alias for field number 5

property water_flow

Alias for field number 6

class business.commons.definitions.NoPipedSegments(*args, **kwargs)

Bases: object

An empty iterable.

Functionality: interpreted by calling code as ‘no solution found by the simplex algorithm’

Notes

Implements an Iterable because the simplex solution is iterable.

class business.commons.definitions.SimplexFailureList(*args, **kwargs)

Bases: object

A spurious sequence of PipedSegments.

Functionaity: it means that the simplex design algorithm could not find a solution.

Notes

Returned by returned by SingleLinprogStretchMixin. SingleLinprogStretchMixin is in charge of solving a linear problem. However, if a solution cannot be found, it returns this class so to comply with the interface returned when a solution is found. INGLESE DA MIGLIORARE

piped_segment = <business.commons.definitions.NoPipedSegments object>
class business.commons.definitions.TraversalSolution(energy_at_tail_point: pint.quantity.build_quantity_class.<locals>.Quantity = None, energy_at_head_point: pint.quantity.build_quantity_class.<locals>.Quantity = None, is_failed: bool = None, penalty: decimal.Decimal = Decimal('0'), piped_segments: Tuple[business.helpers.definitions.PipedSegment] = (), trunk: Any = None, water_flow: pint.quantity.build_quantity_class.<locals>.Quantity = None)

Bases: tuple

Store the result of CoroutineMixin.solve_traversal.

property energy_at_head_point

Alias for field number 1

property energy_at_tail_point

Alias for field number 0

property is_failed

Alias for field number 2

property penalty

Alias for field number 3

property piped_segments

Alias for field number 4

property trunk

Alias for field number 5

property water_flow

Alias for field number 6

business.commons.energy module

Collection of classes used to represent the ‘hydraulic grade line’.

classes
EnergyProfilePoint

A point belonging to the water energy line along a pipe trench.

ElevationProfilePoint

A point belonging to altimetric elevation profile along a pipe trench.

BaseEnergyProfileMixin

A base class for other classes which bear the name ‘profile’.

ElevationProfile

The altimetric elevation profile along a pipe trench.

EnergyProfile

The profile of the hydraulic energy line along a pipe trench.

class business.commons.energy.BaseEnergyProfileMixin

Bases: business.commons.energy.PlotBaseEnergyProfileMixin

A mixin class gathering methods used to do geometric calculations.

downrange()

Return the horizontal span of the hydraulic energy line.

pathlength()

Return the linear length of the hydraulic energy line.

translate_vertically(vertical_shift=Quantity('length'))

Shift vertically the energy line by vertical_shift

get_unique_intersection_with(other: BaseEnergyProfileMixin)

Return the unique intersection point with another energy line

get_tailmost_intersection_with(other: BaseEnergyProfileMixin)

Return the first intersection point with another energy line

get_headmost_intersection_with(other: BaseEnergyProfileMixin)

Return the last intersection point with another energy line

as_linestring()

Return the energy line represented as a Shapely LineString object

intersects_with()

Boolean test checking if two energy lines do intersect or not

get_section_inbetween_downranges(from_downrange, until_downrange: Quantity(‘length’))

Create a new energy line by slicing the current one among given ends

property as_linestring

Return this instance as a shapely linestring object.

The Shapely LineString instance generated will have the same coordinates as those of ElevationProfilePoint’s which constitute this energy line.

The linestring is a collection of adimensional 2-tuples. You may feed matplotlib ‘plot’ method with linestring.xy method.

>>> elevation_profile.as_linestring
[(20, 35), (22, 36), (23, 37), ..., (800, 145)]
property downrange

Return the horizontal span of the BaseProfile.

Returns

a dimensional value

Return type

Quantity(“length”)

get_headmost_intersection_with(other: business.commons.energy.EnergyProfile)business.commons.energy.ElevationProfilePoint

Return the last (rightmost) intersection between two energy lines.

If there is more than one intersection point, this method will return the one nearest to the head end of the energy line.

Parameters

other (EnergyProfile) – the energy line that might intersect this energy line

Raises

NonExistentIntersection – If no intersection point was found. This exception is raised from method _get_intersections_with

get_section_inbetween_downranges(from_downrange: pint.quantity.build_quantity_class.<locals>.Quantity, until_downrange: pint.quantity.build_quantity_class.<locals>.Quantity)business.commons.energy.EnergyProfile

Create a new energy line by slicing the current one among given ends.

If the ends provided (see parameters) exceed the horizontal span of the current energy line, then no exception is raised and the slicing will include the beginning (or the end) of this energy line. This is the same behaviour as python’s list slicing.

Parameters
  • from_downrange (Quantity("length")) – the downrange the new energy line starts from

  • until_downrange (Quantity("length")) – the downrange the new energy line ends to

Returns

a new profile whose first and last point are evaluated by interpolating on the pathlengths of this energy line, while all inner points are the copied from this energy line.

Return type

EnergyProfile

get_tailmost_intersection_with(other: business.commons.energy.EnergyProfile)business.commons.energy.ElevationProfilePoint

Return the first (leftmost) intersection between two energy lines.

If there is more than one intersection point, this method will return the one nearest to the tail end of the energy line.

Parameters

other (EnergyProfile) – the energy line that might intersect this energy line

Raises

NonExistentIntersection – If no intersection point was found. This exception is raised from method _get_intersections_with

Returns

whose downrange, elevation fields store the (dimensionalized) geometrical intersection point between ‘self’ profile and other profile.

Return type

ElevationProfilePoint

get_unique_intersection_with(other: business.commons.energy.EnergyProfile)business.commons.energy.ElevationProfilePoint

Return the unique intersection between two energy lines.

It is responsibility of the caller to ensure that the two energy lines may intersect at most once. A typical use case is when the hydraulic design algorithms attempt to find the swivel point from the simplex solution.

Parameters

other (EnergyProfile) – the energy line that might intersect this energy line

Raises

UnforeseenMultipleIntersection – If more than one intersection point was found or no intersections were found.

Returns

whose downrange, elevation fields store the values (dimensionalized) from .x and .y coordinated of the intersection point

Return type

ElevationProfilePoint

intersects_with(other: business.commons.energy.EnergyProfile) → bool

Return boolean test if this energy line intersects with another.

Parameters

other (EnergyProfile) – the energy line that might intersect this one

property pathlength

Return the linear length of the hydraulic energy line.

Returns

a dimensional value

Return type

Quantity(“length”)

translate_vertically(vertical_shift: pint.quantity.build_quantity_class.<locals>.Quantity) → None

Shift the current instance vertically by vertical_shift.

The shift is done ‘in-place’, no new instance of EnergyProfile is created.

property x_axis_coordinates_array

Return the sequence of x coordinates of the energy line.

The data are formatted to match matplotlib library interface.

property y_axis_coordinates_array

Return the sequence of y coordinates of the energy line.

The data are formatted to match matplotlib library interface.

class business.commons.energy.ElevationProfile(iterable: Iterable = [])

Bases: business.commons.mixins.interpolation.PointFactoryMixin, business.commons.mixins.interpolation.ProfileInterpolationMixin, business.commons.energy.BaseEnergyProfileMixin, business.helpers.utils.TypedList

A class to represent the altimetric elevation profile along a pipe trench.

get_pressure_limit_profile(pressure_limit=Quantity[pressure])

return the elevation profile shifted vertically by the pressure limit

property elevation_at_tail_end

Return the elevation measured at the first point of this profile.

get_pressure_limit_profile(pressure_limit: pint.quantity.build_quantity_class.<locals>.Quantity)business.commons.energy.EnergyProfile

Return an EnergyProfile raised from this altrimetric profile by pressure_limit.

It is used to check geometrically if an energy line, once calculated, will lie between the elevation profile and the pressure limit profile.

Parameters

pressure_limit (Quantity("length")) – a value of pressure expressed, as per hydarulic engineering, HAESTADT expressed in units of length (usually ‘meters of water’). The value of pressure_limit passed to this function is usually taken from one of the rated working pressures available from the catalog of pipes: manufacturers.catalogs.pipes

Returns

the energy profile fit for pressure_limit rating.

Return type

EnergyProfile

class business.commons.energy.ElevationProfilePoint(downrange: float, elevation: float, remarks: Optional[Dict] = None, pathlength: Optional[float] = None)

Bases: business.commons.energy.EnergyProfilePoint

Represent point belonging to altimetric elevation profile.

pathlength

the pathlength measured along the pipe trench.

Type

Quantity(“length”)

pathlength: float = None
class business.commons.energy.EnergyProfile(iterable: Iterable = [])

Bases: business.commons.energy.BaseEnergyProfileMixin, business.helpers.utils.TypedList

A class to represent the hydraulic grade line HAESTADT.

property as_serializable
class business.commons.energy.EnergyProfilePoint(downrange: float, elevation: float, remarks: Optional[Dict] = None)

Bases: object

Represent a point along the water energy line.

The water energy line is defined piecewise as a collection of instances belonging to this class.

downrange

the x coordinate of the point in a 2-d plan

Type

Quantity(“length”)

elevation

the y coordinate of the point in a 2-d plan

Type

Quantity(“length”)

remarks

any information added to the point, typically from field notes. Example: “soil is hard to dig starting from this point”

Type

dict

property as_geometry

Return a Shapely object from the current instance.

Returns

  • A new *shapely.geometry.Point instance whose coordinates are given*

  • by the magnitude of the *ElevationProfilePoint coordinates.*

property as_humanised

Return a string having field values truncated to few decimals.

It is used for improved readability.

downrange: float
elevation: float
remarks: Dict = None
class business.commons.energy.PlotBaseEnergyProfileMixin

Bases: object

A mixin class gathering methods used to do geometric calculations.

x_axis_coordinates_array

Return the sequence of x coordinates of the energy line

y_axis_coordinates_array

Return the sequence of y coordinates of the energy line

property as_matplotlib_curve

Return this instance as a Matplotlib curve, ready to be plotted.

business.commons.exceptions module

Collection of exceptions raised by ‘gravity’ and ‘pumpstation’ folders.

exception business.commons.exceptions.CorruptedLandElevationFile

Bases: business.commons.exceptions.ImproperlyConfiguredTrunk

The trunk topographic survey file contains nonsensical data.

exception business.commons.exceptions.ImproperlyConfiguredTrunk

Bases: business.commons.exceptions.ImproperlyConfiguredWaterSystem

Exception class to indicate errors during Trunk initialization.

Some data needed to describe a Trunk were not provided by the user. It may be raised by any class that extends Watermain

exception business.commons.exceptions.ImproperlyConfiguredWaterSystem

Bases: business.commons.exceptions.RuralwaterException

Exception class to indicate errors during water supply initialization.

Some data needed to solve the hydraulic design/check problem were not provided by the user.

It may be raised by any class that extends Station or BaseGravity

exception business.commons.exceptions.NonExistentIntersection

Bases: business.commons.exceptions.RuralwaterException

The HGL tract and the PN-_elevation_profile do not intersect.

Raised by the algorithms that seach for optimization of the hydraulic grade line: * commons.energy * gravity.mixins.trimming * gravity.stretches * gravity.stretching.pressure * pumpstation.climb

exception business.commons.exceptions.NonsensicalLandElevationData

Bases: business.commons.exceptions.ImproperlyConfiguredTrunk

A file can be read but the data make no logical sense.

exception business.commons.exceptions.NotImplementedInRuralwater

Bases: business.commons.exceptions.RuralwaterException

Invoked method is not implemented in this version of ruralwater.

exception business.commons.exceptions.RuralwaterException

Bases: Exception

Basic exception for all errors raised by ruralwater.

Base exception class for all exceptions raised in ruralwater/webapp/business. No code in the business logic will raise this exception directly; it serves solely to provide a distinguishing parent class for other errors.

exception business.commons.exceptions.UnadvisableDuty

Bases: business.commons.exceptions.RuralwaterException

The working conditions exceed the limits imposed by hydraulic hardware or by available water sources.

Exceptions that ovveride this one are found in the pumpstation and groundwater modules.

The message attached to the Exception, carries the information about the exact nature of the engineering problem identified.

Examples:
“water hammer exceeds pipes pressure ratings”:

raised by australia.system when tripping the “monopump” results in water hammer transient above the feeder pipes classes.

“diesel engine carbonation”

raised by australia.system when the continuous working conditions impose a load on DieselEngine below 50%.

exception business.commons.exceptions.UnforeseenMultipleIntersection

Bases: business.commons.exceptions.RuralwaterException

The HGL tract and the PN-_elevation_profile intersect (unexpectedly) more than once.

This exceptions should never be raised. If it will occour it is likely that it will have been caused by a bug not yet detected or fixed.

business.commons.loggers module

class business.commons.loggers.InitLogger

Bases: business.commons.loggers.LoggerMixin

Allow the class instances to use python logging mechanism.

class business.commons.loggers.InitLoggerMixin

Bases: business.commons.loggers.LoggerMixin

Allow hooking into __post_init__ to use python logging mechanism.

class business.commons.loggers.LoggerMixin

Bases: object

Algorithms to use python logging mechanism.

business.commons.traversals module

Provide common methods aspects of a ‘subnode’ and a ‘soil stretch’.

class business.commons.traversals.PipeDesignPoolMixin

Bases: object

Mixin to get a handle to the catalog of commercial pipes.

Functionality: accessor to the catalog of pipes for the trunk.

commercial_pipes

return a handle to the catalog of commercial pipes available to run the hydraulic calculations.

property commercial_pipes

Return a handle to the catalog of commercial pipes.

Pipes may be either plastic or metallic. Further typologies of pipes might be added in the future.

class business.commons.traversals.TraversalsTrunkOrStretchMixin

Bases: object

Algorithms common to Trunk and Subtrunk.

Functionality: algorithms dealing with the rated working pressure.

Notes

Algorithms fired by __init__ of ‘subnode’ and ‘soil stretch’.

_tail_point_pressure

return the hydraulic pressure felt at the tail point of the ‘subnode’ or ‘soil stretch’.

_head_point_pressure

return the hydraulic pressure felt at the head point of the ‘subnode’ or ‘soil stretch’.

business.commons.watermains module

Provide commons elements of DendridicTrunks and Feeders.

Functionality: ‘gravity’ has a tree of pathways, while ‘station’ has a single feeder. Since the single feeder is a ‘spurious’ tree, we can say that ‘gravity’ and ‘station’ share common elements of directed acyclic graph. This module provides the common functionalities of a tree (the gravity’s pathway topology) and of a ‘single node’ (the station’s pathways topology).

class business.commons.watermains.Watermain(**kwargs)

Bases: business.commons.watermains.WatermainMixin, business.commons.mixins.cost.PipesCostMixin, business.commons.loggers.InitLogger

Represent a pathway with or without the pipes defined.

Common to trunks and feeders, both in design and check calculations.

Notes

Along the watermain the flow of water is the same. The Watermain is composed of a sequence of different diameters, pipe materials and pipe pressure specifications. Along the pipeline the flow of water is constant, i.e.: there are no water flow abstractions from the ‘tail end’ to the ‘head end’.

pathlength

the linear distance of a man walking along the pipeline.

Type

Quantity(“length”)

profile_elevation_at_head_end

the altimetric elevation at the ‘beginning’, i.e.: where the water flows from.

Type

Quantity(“length”)

profile_elevation_at_tail_end

the altimetric elevation at the ‘end’, i.e.: where the water flows to.

Type

Quantity(“length”)

get_hydraulic_friction

the energy burned off in the pipeline by the water flowing inside it.

Type

Quantity(“length”)

class business.commons.watermains.WatermainCheck(**kwargs)

Bases: business.commons.watermains.Watermain

Represent a pathway with the pipes defined

Functionality: common to trunks and feeders, specific for hydraulic check calculations.

Overrides Watermain and sets the catalog of pipes available to run the hydraulic check calculations. The catalog of pipes corresponds to “ALL_PIPE_MATERIALS_ALLOWED” since check calculations must access data from any possible typology of pipe.

property get_hgl_profile

evaluate the hydraulic energy profile arising from the piped segments set in the __init__ of the TrunkCheck and with: * the hydraulic energy at head and tail points and… * …the water flow… …following to the solution of the ‘hydraulic check problem’.

See also

_interpret_sympy_result()

which sets the water flows and

the, when

Notes

The solution of the ‘hydraulic check problem’makes use of the hydraulic friction coefficients 2 and 5 (instead of 1.8 and 4.8 as in the theory); see _darcy_weisbach(). This change of coefficient is imposed by the requirements of the sympy package, which could not otherwise solve a system of algebraic equations with fractional powers. As a consequence if you run a ‘hydraulic design problem’ followed by an ‘hydraulic check problem’, the water flows obtained from the chekc problem will not be identical (albeit similar) to those inputted in the design problem. For the same reason, the shape of the hydraulic energy along each pathway, returned by the plots of the resuts, will slightly differ between the design and the check problem.

Type

Functionality

property piped_segments

Return the sequence of commercial pipes and lengths for this trunk.

The setter converts the json data received into the proper PipedSegment instances, by retrieving the commercial pipe for each piped segment.

Parameters

TODO

class business.commons.watermains.WatermainDesign(**kwargs)

Bases: business.commons.watermains.Watermain

Represent a pathway without the pipes defined.

Functionality: common to trunks and feeders, specific for hydraulic design calculations.

Overrides Watermain and sets the catalog of pipes available to run the hydraulic design calculations. The catalog of pipes may be restrictive, in the sense that some pipelines only allow for metallic pipes (for example: where a trench cannot be dug due to the hard soil conditions).

just for testing sphinx: here I have a link to Watermain and ciao

just for testing sphinx: here I have a link to business.gravity.arrangements.design.GravityDesign and ciao

just for testing sphinx: here I have a tilde link to GravityDesign and ciao

piped_segments

the sequence of commercial pipes (and their length) along the pipeline.

Type

List[PipedSegment]

property piped_segments

Return the sequence of commercial pipes and lengths for this trunk.

The setter sets the state of each commercial pipe belonging to piped_segments to carry the water flow of the trunk.

Parameters

TODO

class business.commons.watermains.WatermainMixin

Bases: object

Algorithms common to all trunks.

get_ratings_to_plot()

return the pressure ratings of the pipes used in this trunk instance.

property get_ratings_to_plot

Return the pressure ratings of the piped segments of the Trunk.

Each commercial pipe has an associated pressure rating. When the Trunk has _piped_segments set, this methods returns these ratings, so to allow the caller to draw the pressure limit profile for each commercial pipe used in _piped_segments.

Example

If, for example, we used a 2” HDPE PN6 pipe, then it will be interesting to draw the PN6 pressure limit to check visually how much the energy line lies below such limit.

Returns

the list of pressure ratings, sorted from the smallest.

Return type

List(Quantity(“length”))

property name
property pathlength

Return the linear distance of a man walking along the pipeline.

property plot_as_svg
property profile_elevation_at_head_end

Return the altimetric elevation at the ‘beginning’, i.e.: where the water flows from.

property profile_elevation_at_tail_end

Return the altimetric elevation at the ‘end’, i.e.: where the water flows to.

property water_flow

business.gravity package

Design and check projects of water supplies fed by gravity.

Classes

  • GravityCheck:

    models the ‘hydraulic check problem’ for a ‘gravity’ water supply.

  • GravityDesign:

    models the ‘hydraulic design problem’ for a ‘gravity’ water supply.

Subpackages

business.gravity.arrangements package

Define the hydraulic problems for a ‘gravity’ water supply.

Submodules
business.gravity.arrangements.base module

Define a gravity-fed dendridic network, with all common features to both the hydraulic design and hydraulic check problems.

class business.gravity.arrangements.base.BaseGravity(**kwargs)

Bases: business.commons.loggers.InitLogger, business.gravity.views.plots.PlotGravityMixin

A class used to represent a gravity-fed dendridic water supply.

Functionality: provides the dendridic topology of its trunks. Provides also base tree concepts such as: the calculation of the water flow.

Notes

Ancestor of GravityCheck and GravityDesign. Subclasses GravityChech and Gravity Design differ since they implement the equations that describe the ‘hydraulic check’ and ‘hydraulic design’ problems respectvely.

business.gravity.arrangements.check module

Define the ‘hydraulic check problem’ for a ‘gravity’ water supply .

class business.gravity.arrangements.check.GravityCheck(**kwargs)

Bases: business.gravity.solvers.check.DendridicCheckMixin, business.gravity.mixins.energy.CheckEnergyNetworkMixin, business.gravity.mixins.topology.CheckTrunksNetworkMixin, business.gravity.mixins.zoning.ZoningMixin, business.gravity.views.reports.GravityCheckReportMixin, business.tests.gravity.utils.GravityCheckTestMixin, business.gravity.arrangements.base.BaseGravity

Represent the ‘hydraulic check problem’ of a ‘gravity’ water supply.

Functionality: define and solve the mathematical equations that solve the ‘hydarulic check problem’ of a gravity-fed dendridic water supply.

Parameters
  • trunks (iterable[TrunkCheck]) – the collection of TrunkCheck instances. The collection describes the dendridic topology of the water supply.

  • intake_elevation (Quantity(length)) – the elevation above the sea level of the point where water is abstracted from a natural source and sent into the dendridic tree.

solve_hydraulic_check_problem()

solves the ‘’hydarulic check problem’’ equations.

Notes

The water supply is composed of: * a spring * a dendridic network of conduits where water flow is constant * The water flow is entirely gravity driven. * The water flow is determined purely by the gravity force; therefore there are no pressure reducing valves in the entire water supply.

The model of the water supply is composed of: * the sequence of trunks whch represent the dendridic network. * Trunks are topologically the nodes of a tree. * The tree is represented by the adjacnecy list of each trunk. Remark that: * the trunks play the role of topological ‘nodes’ of a tree; they are not ‘edges’. The tree is composed of nodes without the need of introducing edges. * each Trunk has a set of attributes, prefiex by, ‘tail’ and ‘head’ that refer to properties of the two ends of the pipeline.

business.gravity.arrangements.design module

Define the ‘hydraulic design problem’ for a ‘gravity’ water supply .

class business.gravity.arrangements.design.GravityDesign(**kwargs)

Bases: business.gravity.mixins.flows.FlowDesignMixin, business.gravity.mixins.energy.EnergyDesignMixin, business.gravity.mixins.topology.DesignTrunksNetworkMixin, business.gravity.mixins.zoning.ZoningMixin, business.gravity.solvers.design.GravityDesignMixin, business.gravity.views.reports.GravityDesignReportMixin, business.tests.gravity.utils.GravityDesignTestMixin, business.gravity.arrangements.base.BaseGravity

Represent the gravity-fed dendridic water supply, modelled to solve the ‘hydarulic check problem’.

Functionality: define and solve the mathematical equations that solve the ‘hydarulic design problem’ of a gravity-fed dendridic water supply.

Note

Physical characteristic of the system. A typical rural gravity-fed scheme has a simple topology: the source is a spring. From there water flows by gravity to a main tank. Downstream of the tank a distribution system is laid down, which is generally branched instead of looped as fire flows and redundancy of distribution are not major concerns.

The branched mains deliver water to the villages reservoirs and typically follow the general topology of valleys and position of villages. In a branched system, also called tree, the water has only one possible path from the source to a village reservoir.

Service lines transmit the water from the village reservoirs to the end customers (public fountains, water troughs for cattle….)

solve_hydraulic_design_problem()

solve the hydarulic design problem and set the results in the calculations report.

class DesignSolutionDetails(treatment: Any = None, trunks: Tuple[business.gravity.trunks.TrunkDesign] = None)

Bases: tuple

The report of the technical calculations from the solution of the hydraulIC design problem.

treatment

futures: treatment may be implemented in a future version of this software package

trunks

maps every trunk of the dendridic network to the trunk’s report of its ‘hydraulic design problem’.

Type

dictionary

property treatment

Alias for field number 0

property trunks

Alias for field number 1

business.gravity.mixins package
Submodules
business.gravity.mixins.airlock module

Provide ‘air-lock’ calculations in a tree-like topology.

class business.gravity.mixins.airlock.OpenEndsTrunkStretchAirlockMixin

Bases: object

Mixin gathering algorithms to detect the onset of an ‘air-lock’ in

the pipes.

hgl_is_vapour_compliant()

Boolean test checking whether a Trunk will suffer from ‘air-lock’. limits.

hgl_prevents_air_locks()

TODO:

property hgl_is_vapour_compliant
Returns

  • True – if the hydraulic pressure along the entire trunk length remains above the minimal value that prevents air-lock formation

  • False – otherwise

property hgl_prevents_air_locks
Returns

  • True – if the hydraulic pressure along the entire trunk length remains above the minimal value that prevents air-lock formation

  • False – otherwise

business.gravity.mixins.crawl module
class business.gravity.mixins.crawl.TrunkSolverStretchMixin

Bases: object

property crawl_pipes
business.gravity.mixins.energy module

Provide ‘hydraulic energy’ calculations in a tree-like topology.

class business.gravity.mixins.energy.BaseEnergyMixin

Bases: object

Algorithms for ‘hydraulic energy’ calculations in a gravity system.

class business.gravity.mixins.energy.CheckEnergyNetworkMixin

Bases: business.gravity.mixins.energy.BaseEnergyMixin

Algorithms for hydraulic energy calculations needed when solving the hydraulic check problem.

class business.gravity.mixins.energy.EnergyDesignMixin

Bases: business.gravity.mixins.energy.BaseEnergyMixin

Algorithms for hydraulic energy calculations needed when solving the ‘hydraulic design problem’.

business.gravity.mixins.flows module

Provide water flow calculations in a tree-like topology.

class business.gravity.mixins.flows.FlowDesignMixin

Bases: object

Algorithms for ‘water flow’ calculations in a gravity system.

Functionality: evaluate the water demand as a sum of the water demand for each downstream Trunk.

Ancestor of ZoningMixin and ZoningMixin.

Notes

Flows must be set before solving the ‘hydraulic design problem’. The Trunks have the demand defined at their ‘head end’. The demand at a ‘tail end’ is not part of this model since such demand is the ‘head end’ demand of the parent Trunk. The spring intake has no demand, since this has no impact on the calculations of the pipes.

business.gravity.mixins.topology module

Provide algorithms and methods pertaining to the tree-like topology of the water supply.

class business.gravity.mixins.topology.BaseTrunksNetworkMixin

Bases: object

Algorithms for common topographical calculations to BaseGravity.

Ancestor of CheckTrunksNetworkMixin and DesignTrunksNetworkMixin.

class business.gravity.mixins.topology.CheckTrunksNetworkMixin

Bases: business.gravity.mixins.topology.BaseTrunksNetworkMixin

Topology algorithms specific to the hydraulic check problem.

class business.gravity.mixins.topology.DesignTrunksNetworkMixin

Bases: business.gravity.mixins.topology.BaseTrunksNetworkMixin

Topology algorithms specific to the ‘hydraulic design problem’.

business.gravity.mixins.trimming module

Collection of algorithms that slice a Subtrunk into subsections.

class business.gravity.mixins.trimming.TrunkStretchTrimmingMixin

Bases: object

Mixin gathering methods used to slice the Subtrunk profile or its piped segments.

Slicing is required because a Subtrunk may have sections where the hydraulic pressure limits are exceeded. It is therefore necessary to slice a Subtrunk into valid and unacceptable sections.

business.gravity.mixins.zoning module

Define the concept of ‘splitting’ a tree into independent subtrees.

class business.gravity.mixins.zoning.ZoningMixin

Bases: object

Algorithms for pressure zone calculations.

Functionality: split the dendridic network in subnetworks. Each subnetwork originates from an atmospheric ‘tail end’.

Ancestor of ZoningMixin and ZoningMixin.

Notes

The hydraulic design and check problems are solved separately within each subtrunk. From a mathematical perspective, each subtrunk is a water supply system, with water under pressure.

business.gravity.solvers package
Submodules
business.gravity.solvers.check module

Solve the ‘hydraulic check problem’ in a ‘gravity’ water supply.

class business.gravity.solvers.check.DendridicCheckMixin

Bases: object

Methods used by GravityCheck to solve a system on algebraic equations.

property solve_hydraulic_check_problem

Attempt solving a system of algebraic equations.

Functionality: solves the equations of the ‘hydraulic check problem’. The preconditions ensure that the equations are meaningful. The postcondition produces a report of the calculations.

business.gravity.solvers.design module

Provide methods used to solve the gravity ‘hydraulic design problem’.

Notes

The decision variables are the pipes The obejctive function is to minimize the cost of the pipes

class business.gravity.solvers.design.GravityDesignMixin

Bases: object

Algorithms to solve the ‘hydraulic design problem’.

solve_hydraulic_design_problem(strategy: str = 'fixed_flows') → None

Solve the ‘hydarulic design problem’, if init data were provided correctly.

Acts as a ‘layer’ between the algorithm and the client code. The layer ensures separation of concerns: * the algorithm attempts to find a solution * this method either reports the algorithm outcome or raises and logs exceptions

Parameters

strategy (str) – the name of the design algorithm to be invoked (default is TODO)

Raises

ImproperlyConfiguredTrunk – if the initkwargs were mistaken

business.gravity.stretching package
Submodules
business.gravity.stretching.crawl module

Implement the ‘crawl’ algorithm for the Subtrunk.

class business.gravity.stretching.crawl.CrawlSolverStretchMixin

Bases: object

Algorithms to return sequences of commercial pipes.

Functionality: return sequences of commercial pipes while performing systematic search of the hydraulic grade line inside a Subtrunk.

Notes

These sequences are used when performing systematic search of the various possible hydrauli grade lines.

business.gravity.stretching.linear module

Implement the ‘simplex’ algorithm for the Subtrunk.

class business.gravity.stretching.linear.SwapStretchMixin

Bases: object

Algorithms used to optimize the trunk stretch running the simplex just once.

Functionality: perform systematic search of the hydraulic grade line inside a Subtrunk.

attempt_simplex()

Return the optimal solution if this entails pressure compliance of the energy line

swap_piped_segments()

Swap in-place the order of the trunk stretch’s piped segments

attempt_simplex(message) → List[business.helpers.definitions.PipedSegmentDesign]
property swap_piped_segments

Swap in-place the order of the trunk stretch’s piped segments.

business.gravity.stretching.pressure module

Provide pressure calculations for the Subtrunk.

class business.gravity.stretching.pressure.PressureStretchMixin

Bases: object

A mixin gathering methods that deal with hydraulic pressure.

Functionality: analyse the hydraulic pressure while performing systematic search of the hydraulic grade line inside a Subtrunk.

property hgl_is_pressure_compliant

Return True if the hydraulic grade line is pressure compliant. False otherwise.

The check is run considering the current status of the Subtrunk, namely: * its piped segments * its hydraulic energy at ‘tail’ and ‘head’ ends * its water flow

property hgl_lies_above_elevation_profile

Check if the hydraulic energy line is ‘always above’ the soil.

Returns

  • True – if the hydraulic grade line lies above the elevation profile for the whole extent of the Subtrunk.

  • False – otherwise.

  • Remarks

  • ——-

  • The inheritor *AtmosphericSubtrunk overrides it.*

business.gravity.stretching.setters module

Provide mutators for the Subtrunk.

class business.gravity.stretching.setters.SettersStretchMixin

Bases: object

The mixin gathering setters of Subtrunk.

property pipes_in_pair
property segments_in_pair

Get or set the a sequence of exactly two piped segments.

Setting the two piped segments will reconfigure the energy line and evaluate the swivel point, i.e.: the point where the energy line changes its slope due to water flowing from the first to the second piped segment.

The most economical pipes (i.e.: the optimal solution) for a Subtrunk is composed by two piped segments (ref.: Dantzig theorem). Setting this couple of piped segments sets the inner variables _tail_side_segment and _head_side_segment.

Once this setter completes, the energy line will change and it is a priori not known whether it is pressure compliant. Several algorithms in the code check and take action if there is no compliance.

business.gravity.trunking package
Submodules
business.gravity.trunking.setters module

Provide mutators for the TrunkDesign.

class business.gravity.trunking.setters.TrunkDesignSettersMixin

Bases: object

The mixin gathering setters of TrunkDesign.

energy_at_tail_point

Get or set the hydraulic energy at the ‘tail’ end of the Trunk

energy_at_head_point

Get or set the hydraulic energy at the ‘head’ end of the Trunk

property energy_at_head_point

Get or set the hydraulic energy at the ‘head’ end of the Trunk.

Setting the hydraulic energy to a new value will update the pressure at the ‘head’ end.

Setting the hydraulic energy to a new value will not modify the hydraulic energy line or the piped_segments in the Trunk.

property energy_at_tail_point

Get or set the hydraulic energy at the ‘tail’ end of the Trunk.

Setting the hydraulic energy to a new value will update the pressure at the ‘tail’ end.

Setting the hydraulic energy to a new value will not modify the hydraulic energy line or the piped_segments in the Trunk. Usually, once the energy_at_tail_point is set, the code runs the simplex solver and then sets the piped segments to the Trunk. Then it evaluates the new water energy line, and finally checks for hydraulic pressure compliance of the energy line. This setter is then run at an initial stage of the design algorithm.

business.gravity.trunking.traversals module

Provide algorithms solving the ‘hydraulic design problem’ within a Trunk.

class business.gravity.trunking.traversals.AtmosphericTraversalTrunkMixin

Bases: object

property get_traversal_solution

it dispatches always the _delta_zero approach when solving the ‘hydraulic design problem’.

An AtmosphericTrunkDesign will always have zero hydraulic pressure at its ends and therefore its traversal algorithm is surely the _delta_zero.

Type

Override the parent class method

class business.gravity.trunking.traversals.TraversalsTrunkDesignMixin

Bases: business.commons.traversals.TraversalsTrunkOrStretchMixin

Algorithms to find the optimal piped segments in the Trunk.

get_traversal_solution()

return the optimal piped segments, with given water flow and energy constraints at ‘tail’ and ‘head’ ends

property get_traversal_solution

Return the optimal piped segments, with given water flow and energy constraints at ‘tail’ and ‘head’ ends.

This method dispatches the execution to specific methods depending on the number of rated working pressure classes that the hydraulic energy line crosses from ‘tail’ to ‘head’.

Returns

  • either – list(PipedSegment), if a solution was found

  • or – list(simplex_failure_list) otherwise TODO: questo simbolo di [] confonde! Non è chiaro se restituisci una ‘lista di liste’ o cosa! E lo hai scritto tu.

  • TODOs

  • —–

  • il fatto che questa def restituisce either…or la rende difficile.

  • Ricorda però che siamo dentro una coroutine e non si possono sollevare le eccezioni.

business.gravity.trunking.traversals.filter_accomplished_solutions(function: Callable) → Callable
business.gravity.views package
Submodules
business.gravity.views.definitions module

Collection of data structures used to report the hydraulic design and check calculations.

class business.gravity.views.definitions.ZoneDesignReport(design_is_successful: bool = None, optimized_solution: Set[business.commons.definitions.TraversalSolution] = None, errors: dict = None)

Bases: object

Record storing outcomes of the ‘hydraulic design’ in a pressure zone.

design_is_successful: bool = None
errors: dict = None
optimized_solution: Set[business.commons.definitions.TraversalSolution] = None
business.gravity.views.plots module

Provide matplotlib functionalities to plot the data.

Notes

This module is based on third-party <matplotlib> library.

class business.gravity.views.plots.PlotGravityMixin

Bases: business.commons.views.plots.PlotStreamMixin

Algorithms to plot all Trunks in a dendridic network.

business.gravity.views.reports module

Provide functionalities to report the data in textual form.

class business.gravity.views.reports.BaseGravityReportMixin

Bases: object

Methods used by BaseGravity to output the results from hydraulics equations.

class business.gravity.views.reports.GravityCheckReportMixin

Bases: business.gravity.views.reports.BaseGravityReportMixin

Method to output the results from ‘hydraulic check problem’.

property get_ux_context

Return the dictionary that Django uses to render a template.

class business.gravity.views.reports.GravityDesignReportMixin

Bases: business.gravity.views.reports.BaseGravityReportMixin

Method to output the results from ‘hydraulic check problem’.

property get_ux_context

Return the dictionary that Django uses to render a template.

Functionality: create a check problem, solve and return its report by returning its template context.

Notes

Performs three steps: * Clone this instance in a Check problem. * Solve the check problem in the clone. * Show the results from the check problem.

Submodules

business.gravity.constants module

Collection of constants used by the gravity foldes.

business.gravity.constants.RANDOM_SEARCH_RANGE_PAD = <Quantity(25, 'meter')>

Prescribes the minimal hydraulic energy to be burned along a Trunk during gravity tree random search. This value magnitude is expected to be an integer.

business.gravity.coroutines module

Find an optimal solution to the ‘hydraulic design problem’.

Functionality: Perform the systematic search of the optimal values of hydarulic energy at all junctions internal to a rpessure zone.

class business.gravity.coroutines.AccumulatorDuringRange

Bases: business.helpers.utils.TypedSet

Collection of solutions of the ‘hydraulic design problem’ within the subtree.

Functionality: accumulate the feasible solutions (while the ‘systmatic search’ algorithm runs) of the ‘hydraulic design problem’ so to allow, once the systematic search algorith ends, to collect the one with the least economic cost.

Notes

Extends a strongly typed set.

property best_during_range
class business.gravity.coroutines.CoroutineLeaf(trunk: business.gravity.trunks.TrunkDesign, name: str, down_elev: int)

Bases: business.gravity.coroutines.CoroutineMixin

Represent a root where the coroutine process ends (and starts sending data back towards the root)

There is one instance for each TrunkDesign whose ‘head’ end is atmospheric.

merger()

Return the optimal solution for this trunk

down_elev: int
merger()business.gravity.coroutines.CurrentSimplexesList

Advance the coroutine pipeline and return the optimal solution at the current energy constraints.

Yields

CurrentSimplexesList – the result from linear optimization of the trunk

name: str
send(arg)
trunk: business.gravity.trunks.TrunkDesign
class business.gravity.coroutines.CoroutineMixin

Bases: business.commons.loggers.InitLoggerMixin

Algorithms common to CoroutineRoot, CoroutineNode and CoroutineLeaf.

class business.gravity.coroutines.CoroutineNode(trunk: business.gravity.trunks.TrunkDesign, name: str, down_flight: int, adj_list: Any)

Bases: business.gravity.coroutines.CoroutineMixin

Represent a pathway where the coroutine process is executed.

There is one instance for each TrunkDesign which is ‘internal’ of a PressureZone. More specifically: neither the trunk ‘tail’ nor the ‘head’ are atmospheric.

merger()

Return the optimal solution for this trunk and its children

adj_list: Any
down_flight: int
merger()business.gravity.coroutines.CurrentSimplexesList

Advance the coroutine pipeline and return the optimal solution at the current energy constraints.

Yields

CurrentSimplexesList – the best result from linear optimization of the trunk and all of its children trunks belonging to the pressure zone.

name: str
send(arg)
trunk: business.gravity.trunks.TrunkDesign
class business.gravity.coroutines.CoroutineRoot(trunk: business.gravity.trunks.TrunkDesign, name: str, up_elev: int, down_flight: int, adj_list: Any)

Bases: business.gravity.coroutines.CoroutineMixin

Represent a root where the coroutine process starts from.

There is one instance for each TrunkDesign which is a root of a PressureZone.

merger()

Return the optimal solution for the pressure zone

adj_list: Any
down_flight: int
merger()business.gravity.coroutines.CurrentSimplexesList

Return the optimal solution.

Returns

the list of namedtuples that describe the optimal solution for each trunk in the entire pressure zone

Return type

CurrentSimplexesList

name: str
trunk: business.gravity.trunks.TrunkDesign
up_elev: int
class business.gravity.coroutines.CurrentSimplexesList(iterable: List = [])

Bases: business.helpers.utils.TypedList

Accumulator

property get_my_cost
property is_failed

business.gravity.exceptions module

Collection of exceptions raised by ‘gravity’ folder.

exception business.gravity.exceptions.AllCommercialPipesAreUnsuitableForSimplex(message, desired_flow, required_rating)

Bases: business.manufacturers.exceptions.pipes.AllCommercialPipesAreUnsuitableSpeedwise, business.gravity.exceptions.OpenEndsTrunkEdgeCase, business.gravity.exceptions.BaseLinprogFailure

No pipe is suitable to carry the desired _water_flow within the advisable _water_flow speed limits.

Raised by BasePipePool.

exception business.gravity.exceptions.BaseLinprogFailure

Bases: business.commons.exceptions.RuralwaterException

Base exception class when the linear optimization algorithm fails.

Applies to: * Subtrunk * SoilStretch

Occours in situations where there is: (1) flat slope (2) steep slope (3) floating point arithmetic problems (raise from inside the scipy.optimize.linprog library)

Raised if both method=”simplex” and method=”interior-point” fail to find the minimum of the objective function. See “notes” section from page: https://docs.scipy.org/doc/scipy/reference/optimize.linprog-interior-point.html

exception business.gravity.exceptions.FailedSubtreeDesign

Bases: business.commons.exceptions.RuralwaterException

The ‘hydraulic design problem’ of a pressure zone could not be solved.

Raised, for example, by *business.gravity.coroutines.CoroutineRoot when no solution could be found by the coroutine algorithm.

exception business.gravity.exceptions.FlatSlope(message, subnode_headloss_slope, min_pipe_headloss)

Bases: business.gravity.exceptions.SlopeOutsideFeasibleRange

The trunk energy is too little.

Even the largest commercial pipe burns more than the hydraulic energy, at the current water flow.

exception business.gravity.exceptions.LeafNodeDemandDataMissing(message, leaf_missing_demand_data)

Bases: business.commons.exceptions.RuralwaterException

The demand data at some leaf node is missing.

A trunk may have no demand data and just carry water to its children. However, if a trunk is a ‘leaf’ (i.e.: it discarges in a reservoir at the end of the dendridi network) then it must have a demand. Otherwise, is no reason why the Trunk should exists.

Raised when the TrunkDesign._water_flow value is zero after TrunkDesign.set_flow.

exception business.gravity.exceptions.LinprogNumericalIssue

Bases: business.gravity.exceptions.BaseLinprogFailure

Package scipy.optimize.linprog failed performing the linear optimization.

exception business.gravity.exceptions.OpenChannelFlow(message, piped_segments)

Bases: business.commons.exceptions.RuralwaterException

A TrunkDesign shows MOTO A CANALETTA.

exception business.gravity.exceptions.OpenEndsTrunkEdgeCase

Bases: business.commons.exceptions.RuralwaterException

Base class for the exceptions raised by an atmospheric node.

Raised when the HGL gradient is too flat / too steep with resepct to the range of HGL gradients returned by the available pipes. Also, raised when the *MOTO A CANALETTA* occours.

exception business.gravity.exceptions.PressureLimitsExceeded(message, piped_segments)

Bases: business.gravity.exceptions.BaseLinprogFailure

Pipes result in exceeding pressure limits.

Raised for example when the solution of linear programming (simplex) results in pressure exceeding the pipes’ max allowed pressure.

exception business.gravity.exceptions.SlopeOutsideFeasibleRange

Bases: business.gravity.exceptions.BaseLinprogFailure

The constraints of the optimization problem are too stringent.

Raised when the hydraulic energy to be burned off is too high/too low for any of the commercial pipes available from the catalog of hydraulic hardware.

exception business.gravity.exceptions.SteepSlope(message, subnode_headloss_slope, candidate_pipes_headlosses, open_flow_pipe_segments)

Bases: business.gravity.exceptions.SlopeOutsideFeasibleRange

The trunk energy is too little.

Even the smallest commercial pipe burns less than the hydraulic energy, at the current water flow.

If raised by an AtmosphericTrunkDesign, it entails that the trunk shows ‘open channel flow’.

exception business.gravity.exceptions.WaterSystemIsNotATree

Bases: business.commons.exceptions.RuralwaterException

The topology of the water supply system is not a tree.

business.gravity.stretches module

Define the concept of ‘splitting’ a Subtrunk into sections.

class business.gravity.stretches.AtmosphericSubtrunk(_energy_at_tail_point: float, _energy_at_head_point: float, _elevation_profile: business.commons.energy.ElevationProfile, _pressure_limit: pint.quantity.build_quantity_class.<locals>.Quantity, _water_flow: pint.quantity.build_quantity_class.<locals>.Quantity, _pathlength_starts_at: pint.quantity.build_quantity_class.<locals>.Quantity, _requires_metallic_pipes: bool, _trunk_name: str = 'Trunk default name')

Bases: business.gravity.stretches.Subtrunk

A stretch of a Trunk whose ends are both at atmospheric pressure.

property hgl_lies_above_elevation_profile

Overrides parent’s method.

Important

This is an atmospheric TrunkDesign, therefore there are at least two intersections, found at the first and the last point of the _profile. More than two intersection points require the HGL to cross the terrain inside the pathlength. Therefore the HGL intersects the elevation profile.

class business.gravity.stretches.SubstretchMixin

Bases: object

Common ancestro of Subtrunk and SoilStretch.

class business.gravity.stretches.Subtrunk(_energy_at_tail_point: float, _energy_at_head_point: float, _elevation_profile: business.commons.energy.ElevationProfile, _pressure_limit: pint.quantity.build_quantity_class.<locals>.Quantity, _water_flow: pint.quantity.build_quantity_class.<locals>.Quantity, _pathlength_starts_at: pint.quantity.build_quantity_class.<locals>.Quantity, _requires_metallic_pipes: bool, _trunk_name: str = 'Trunk default name')

Bases: business.commons.loggers.InitLoggerMixin, business.commons.mixins.linear.SingleLinprogStretchMixin, business.gravity.mixins.trimming.TrunkStretchTrimmingMixin, business.gravity.stretching.linear.SwapStretchMixin, business.gravity.stretching.crawl.CrawlSolverStretchMixin, business.commons.traversals.PipeDesignPoolMixin, business.gravity.stretching.pressure.PressureStretchMixin, business.gravity.stretching.setters.SettersStretchMixin, business.gravity.stretches.SubstretchMixin

A class to represent a section of DendridicTrunk.

The ‘section’ is where the ‘hydraulic design problem’ is solved. The section has boundary constraints, defined by the hydraulic energy values at its ‘tail’ and ‘head’ ends. The section has a rated working pressure set, and the hydraulic design problem solution must comply with such pressure requirement. The section has the same water flow as the Trunk it belongs to.

A section may correspond to the whole TrunkDesign.

Important

A TrunkDesign’s _elevation_profile list may be sliced and each slice is then used to initialize a Subtrunk.

recursive_linear_solver()

return the economically optimal pipes, using a ‘simpex’ approach

crawl()

return the economically optimal pipes, fit for profiles traversing deep valleys or overbanking ridges

property attempt_crawling

A largest-smallest pipe approach, repeated recursively whenever a solution exceedes the rated pressure limits.

Such approach aims at ‘bending’ the hydraulic energy line and appears to be fit especially for surpassing deep valleys or to overbank ridges between two contiguous vallyes.

Return the optimal pipes by investigating recursively whenever the pressure limits are exceeded by solution obtained during the recursive process.

Returns

Return type

TODO

property pathlength

Return the linar pathlength of the stretch.

Returns

the linear length of the profile pertaining to this section.

Return type

Quantity(“length”)

property recursive_linear_solver

A linear optimization approach, repeated recursively whenever a solution exceedes the rated pressure limits.

Return the optimal pipes by investigating recursively whenever the pressure limits are exceeded by solution obtained during the recursive process.

Returns

Return type

TODO

property xxx_repr

business.gravity.trunks module

class business.gravity.trunks.AtmosphericTrunkCheck(**kwargs)

Bases: business.gravity.trunks.TrunkCheck, business.gravity.trunks.AtmosphericTrunkMixin

A TrunkCheck, with both ends at atmospheric pressure.

Functionality: a Trunk, with both ends at atmospheric pressure, modelled to solve the ‘hydarulic check problem’.

Notes

This is the case of a Trunk connecting directly two reservoirs, or a spring to a reservoir.

class business.gravity.trunks.AtmosphericTrunkDesign(**kwargs)

Bases: business.gravity.trunks.AtmosphericTrunkMixin, business.gravity.trunking.traversals.AtmosphericTraversalTrunkMixin, business.gravity.trunks.TrunkDesign

A TrunkDesign, with both ends at atmospheric pressure.

Functionality: a Trunk, with both ends at atmospheric pressure, modelled to solve the ‘hydarulic design problem’.

Notes

This is the case of a Trunk connecting directly two reservoirs, or a spring to a reservoir.

property as_subtrunk

Return a Subtrunk spanning the entire AtmosphericTrunkDesign.

The subnode._pressure_limit is the lowest available from the catalog of pipes.

Important

Used to create a Subtrunk that covers the entire _elevation_profile of this node. This is necessary when starting the get_traversal_solution method. The subnode._pressure_limit is the lowest available since the atmospheric node entails to use the lowest possible pressure.

Returns

the atmospheric stretch whose profile is the entire profile sequence of this atmospheric Trunk.

Return type

AtmosphericSubtrunk

property get_open_channel_hgl_profile

Return an EnergyProfile raised from the altrimetric profile by one meter.

Its is used to render graphically the idea of ‘open flow’

class business.gravity.trunks.AtmosphericTrunkMixin

Bases: object

Hook for a common ancestor to AtmosphericTrunkCheck and AtmosphericTrunkDesign.

class business.gravity.trunks.BaseTrunk(**kwargs)

Bases: business.commons.watermains.Watermain

Ancestor of TrunkCheck and TrunkDesign.

Functionality: define the mathematical properties of the node of a tree. The BaseTrunk is ancestor of all trunks belonging to a gravity water supply.

Note

  • The gravity water supply is modelled as a dendridic network; each node

of this network is a BaseTrunk (or child). * The Trunk is a pipeline along which the water flow is constant. * The Trunks is composed of a sequence of different diameters, pipe materials and pipe pressure specifications.

class business.gravity.trunks.TrunkCheck(**kwargs)

Bases: business.commons.watermains.WatermainCheck, business.gravity.trunks.BaseTrunk

A BaseTrunk, modelled to solve the ‘hydarulic check problem’.

Functionality: define the properties required to solve the ‘hydarulic check problem’ of a gravity-fed dendridic water supply.

property get_hydraulic_friction_per_unit_waterflow

Return the hydraulic energy burned off along the Trunk for a unitary water flow.

The hydraulic friction is dimensionless: it represents meters of energy loss per meters of pipe length; it is a percentage.

Returns

the energy burned off by friction along the whole length of the Trunk, for a water flow of magnitude ‘1’ and units defined by the pacakge constants.

Return type

float

property water_flow

Set the water flow in the Trunk, in its piped segments and pipes.

Functionality: once the ‘hydraulic check problem’ is solved, the code sets the resulting ‘water flow’ in each trunk of the gravity pipeline. This mutator allows to set such value of the water flow in each of the pipes, so that it will then be possible to plot the hydraulic energy profile with the correct water flow.

class business.gravity.trunks.TrunkDesign(**kwargs)

Bases: business.gravity.trunking.setters.TrunkDesignSettersMixin, business.gravity.trunking.traversals.TraversalsTrunkDesignMixin, business.commons.watermains.WatermainDesign, business.commons.traversals.PipeDesignPoolMixin, business.gravity.trunks.BaseTrunk

A BaseTrunk, modelled to solve the hydarulic design problem.

property as_subtrunk

Return a ‘stretch’ which stretches along the entire length of this Trunk.

Returns

the stretch whose profile is the entire profile sequence of this Trunk.

Return type

Subtrunk

property get_my_water_demand_as_steady_flow

Return the water flow required by the ‘hydraulic design problem’.

Return the steady flow, flowing continuously along the 24 hours of the day, which satisfies the water demand associated with the Trunk.

business.groundwater package

This package models the borehole and the acquifer as a whole.

Classes

  • BoreholeCheck:

    performs hydraulic check calculations once the hydraulic hardware is set

  • BoreholeDesign:

    allows to design the borehole the once the demand and the environmental data are set

Exceptions: (see exceptions)

exceptions raised by the Borehole are intercepted by the PumpStation during the execution of hydraulic design and hydraulic check calculations.

Submodules

business.groundwater.boreholes module

Models how much water may be abstracted from a borehole.

class business.groundwater.boreholes.BaseBorehole(**kwargs)

Bases: business.groundwater.plots.PerformancePlotMixin, business.commons.loggers.InitLogger

Represent (simplistically) a borehole.

Functionality: the class takes in account only two parameters: * the flow-dwl relationship * the drilled bore

Notes

More specifically, other parameters are not included in this model: * drilled depth * depth of solid casing * depth of screen. These shall be included in a future version.

Also, the flow-dwl relation is passed as a tuple of 2-tuples. This version does not include any study of step-tests, recoveryand continuous discharge test. The maximum licensed abstraction is assumerd to be the highest flow for which the flow-dwl relation was provided.

When the pump is started the water in the borehole lowers its level. This model is in charge of evaluating the flow vs. drawdown curve. The greater the flow rate through the pump, the larger the drop in water table elevation in the borehole.

_get_max_allowed_water_flow : Quantity("volume/time")

get the maximum amount of water that may be abstracted,

get_pump_depth_down_the_hole : Quantity("length")

get the depth of the pump below ground surface,

water_flow : Quantity("volume/time")

get the abstracted water flow.

property dwl

Return the current drawdown.

Returns

Return type

Quantity(“length”)

property get_flow_range

Return a sequence of equidistant water flows.

The range of water flows spans from ‘zero’ to the maximum sustainable yield from the borehole (i.e.: from the water source).

The return values are rounded since this appeared to be necessary during the hydraulic friction calculations (refer to methods _darcy_weisbach and _gs042)

Returns

an array of dimensional values (Quantity(“volume/time”)) with np.float64 magnitudes and rounded.

Return type

np.array

property water_flow

Get or set the current pumped water flow.

Setting the flow to a new value will reconfigure the borehole and evaluate a new value of drawdown and pump setting.

Raises

AquiferDepletion – if the proposed water flow exceeds the limits imposed by _get_max_allowed_water_flow.

class business.groundwater.boreholes.BoreholeCheck(**kwargs)

Bases: business.groundwater.boreholes.BaseBorehole

Override a borehole and add functionalities to solve the hydraulic check problem.

Note

A check borehole does not need the drilled bore (unlike the design borehole) because in the check problem the riser bore is already known from input data. The drilled bore is therefore useless for the hydraulic check calculations.

property get_pump_depth_down_the_hole

Return the pump depth set by the input data of the hydraulic check problem.

Note

This method is present in both BoreholeCheck and BoreholeDesign but the two implementations differ, rerlecting the different nature of the hydraulic design and hydraulic check problems.

Returns

the input data.

Return type

Quantity(“length”)

property water_flow

Get or set the current pumped water flow.

Setting the flow to a new value will reconfigure the borehole and evaluate a new value of drawdown and pump setting.

Raises

AquiferDepletion – if the proposed water flow exceeds the limits imposed by _get_max_allowed_water_flow.

class business.groundwater.boreholes.BoreholeDesign(**kwargs)

Bases: business.groundwater.boreholes.BaseBorehole

Borehole for calculations during the ‘hydraulic design’.

A ‘design’ borehole has a known dwl curve; therefore it has also a known drilled bore. More precisely, a ‘design’ borehole is a borehole considered for a ‘hydraulic design problem’ of a water supply system, but it is assumed that the borehole itsef was already drilled, and its aquifer studied through the pumpin test.

property get_pump_depth_down_the_hole

Return the suitable pump depth compatible with the pumped flow.

Returns

the minimum suitable depth of the pump body. Positive values point ‘into’ the ground.

Return type

Quantity(“length”)

class business.groundwater.boreholes.DwlVsFlowPoint(water_flow: pint.quantity.build_quantity_class.<locals>.Quantity, dwl: pint.quantity.build_quantity_class.<locals>.Quantity)

Bases: tuple

Represent a point in the 2-d planee whose coordinates are “_water_flow” and “dwl”.

_water_flow - the abscissa: abstracted _water_flow from borehole dwl - the ordinate: observed water level when pumping at _water_flow rate.

Units of measure:
  • _water_flow: Quantity(“volume/time”)

  • dwl: Quantity(“length”)

property dwl

Alias for field number 1

property water_flow

Alias for field number 0

business.groundwater.constants module

Collection of constants used and exported by ‘groundwater’ package.

business.groundwater.constants.DEFAULT_SUBMERGENCE = <Quantity(3, 'meter')>

Prescribes the minimum difference between the pump depth and the drawdown.

business.groundwater.exceptions module

Collection of the exceptions raised inside groundwater package.

exception business.groundwater.exceptions.AquiferDepletion

Bases: business.groundwater.exceptions.UnadvisableExploitation

A BaseBorehole is set with exaggerate _water_flow.

exception business.groundwater.exceptions.CorruptedDrawdownData

Bases: business.groundwater.exceptions.ImproperlyConfiguredBorehole

A drawdown csv file can be read but the data make no logical sense.

Example

  • the csv columns contain string instead of positive floats,

  • the csv columns are unexpectedly empty.

exception business.groundwater.exceptions.ImproperlyConfiguredBorehole

Bases: business.commons.exceptions.ImproperlyConfiguredWaterSystem

Some data needed to describe the BaseBorehole (and its derived classes) are missing.

exception business.groundwater.exceptions.NonsensicalDrawdownData

Bases: business.groundwater.exceptions.ImproperlyConfiguredBorehole

A file can be read but the data make no logical sense.

Raised when the csv data are not monotonic, where expected.

exception business.groundwater.exceptions.PumpRunningDry

Bases: business.groundwater.exceptions.UnadvisableExploitation

A BaseBorehole is set with _water_flow so high that the water level descreases and leaves the pump run dry.

exception business.groundwater.exceptions.SwlDataMissing

Bases: business.groundwater.exceptions.ImproperlyConfiguredBorehole

The static water level could not be inferred from anay data.

Raised when the first row of a csv drawdown file does not bear the value 0 for the water flow.

exception business.groundwater.exceptions.UnadvisableExploitation

Bases: business.commons.exceptions.UnadvisableDuty

The rate of pumping is excessive and may damage the borehole.

This exceptions may be raised when too much water is abstracted from the borehole. The classes that ovveride this exception detail the various problems that may occur with excessive abstraction of water. HAESTADT

business.groundwater.plots module

Provide matplotlib functionalities to plot the data.

Notes

This module is based on third-party <matplotlib> library.

class business.groundwater.plots.PerformancePlotMixin

Bases: object

A mixin class used to lookup drawdown data and then format them according to matplotlib interface.

get_dwl_curve_as_matplotlib()

returns the drawdown curve

property get_dwl_curve_as_matplotlib

Return the drawdown vs. the water flow.

The drawdown curve is a collection of (flow, drawdown) discrete points.

Returns

  • 2-tuple of N-tuples

  • first N-tuple (Quantity(“length”))

  • second N-tuple (Quantity(“volume/time”)) – the first tuple is the sequence of discrete values of drawdown the second tuple is the sequence of discrete values of water flows

business.groundwater.units module

Collection of the units used by groundwater package. PIERGIORGIO2: è giusto dire che groundwater è un package?

business.groundwater.units.DWL_UNITS = <Unit('meter')>

Prescribes the units to measure the water level in inside the borehole.

business.groundwater.units.SWL_UNIT = <Unit('meter')>

Prescribes the units to measure the water level in inside the borehole.

business.helpers package

Collection of code architectural snippets essential for bootstrapping components

Submodules

business.helpers.definitions module

Collection of data structures used throughout all the other packages that constitute ‘ruralwater’. PIERGIORGIO2: Se ‘helpers’ è un package allora ‘ruralwater’ cosa è? Mi riferisco a come scrivere la frase sopra.

Data structures
EngineWorkingConditions

requirements to select a engine from a catalog of commercial engines.

PipeWorkingConditions: (namedtuple)

requirements to select a pipe from a catalog of commercial pipes.

RiserAssemblyWorkingConditions

defines the duty a down-the-hole shaft riser must be able to sustain.

SubmersibleWorkingConditions

requirements to select a submersible pump from a catalog of commercial pumps.

class business.helpers.definitions.EngineWorkingConditions(brake_power, rpm)

Bases: tuple

The requirements the engine must be able to satify.

Notes

May be used either to select an engine off a catalog of engines commercially available. May be used to evaluate the engine load and consumption at the given woring conditions.

brake_power

the engine brake power TODO: HAESTADT, cerca definizione

Type

Quantity(“TODO”) float TODO: non è un float ma una quantity; scrivi le unità di misura corrette.

rpm

the engine crankshaft rotational speed

Type

Quantity(“TODO”) float TODO: non è un float ma una quantity; scrivi le unità di misura corrette.

property brake_power

Alias for field number 0

property rpm

Alias for field number 1

class business.helpers.definitions.FlowVsEnergyCurve(typed_sequence)

Bases: business.commons.energy.PlotBaseEnergyProfileMixin, business.helpers.utils.TypedList

Sequence of (water_flow, water_energy) points that approximate the flow-hydraulic_energy curve in nature.

Note

Overrides TypedList to ensure that each point of the sequence is a (flow, energy) tuple.

as_linestring:

Geometric representation of the curve in a 2-d plane.

property as_linestring

Return this sequence as a shapely object.

Represent a polygonal chain in the 2-d plane which is the piecewise linear approximation of the flow-hydraulic_energy curve in nature.

Important

In geometry, a polygonal chain is a connected series of line segments. Return this record as a shapely object. Refer to https://pypi.org/project/Shapely/ for a description of the shapely package.

Returns

The shapely LineString instance. For each of the points of the polygonal chain, magnitudes are expressed in the unit of measure set in ruralwater.helpers.units, see HYDRAULIC_ENERGY_UNITS for the energy and WATERFLOW_UNITS for the water flow.

Return type

shapely.geometry.LineString

get_intersection_with(other)
misses(other)
class business.helpers.definitions.FlowVsEnergyPoint(hydraulic_energy: pint.quantity.build_quantity_class.<locals>.Quantity, water_flow: pint.quantity.build_quantity_class.<locals>.Quantity)

Bases: object

A class used to represent the duty of a pump.

water_flow

the abstracted water flow from the borehole

Type

Quantity(“volume/time”)

hydraulic_energy

the hydraulic energy provided to or required by the water flow.

Type

Quantity(“TODO”)

as_shapely_point()

Geometric representation of the record in a 2-d plane.

Notes

Overloads __add__, __sub__

In a pump station (class ElectriclessDesign) the flow of water is the same through all the mechanical parts (borehole colum, feeder, pump body, shaft) therefore the duty is a sum of energy requirements, while the water_flow value remains constant.

property as_shapely_point

Return this record as a shapely object.

Represent a point in the 2-d plane whose abscissa matches the hydraulic energy and whose ordinate matches the water flow. Refer to https://pypi.org/project/Shapely/ for a description of the shapely package.

Returns

The shapely point instance. Magnitudes are expressed in the unit of measure set in ruralwater.helpers.units, see HYDRAULIC_ENERGY_UNITS for the energy and WATERFLOW_UNITS for the water flow.

Return type

shapely.geometry.Point

hydraulic_energy: pint.quantity.build_quantity_class.<locals>.Quantity
water_flow: pint.quantity.build_quantity_class.<locals>.Quantity
class business.helpers.definitions.PipeWorkingConditions(water_flow, rated_working_pressure)

Bases: tuple

The requirements the pipe must be able to satify.

Notes

May be used to select a pipe off a catalog of pipes commercially available.

water_flow

the water flow throughout the pipe

Type

Quantity(“volume/time”, float)

rated_working_pressure

the working pressure for which the pipe is rated by the manufacturer

Type

Quantity(“TODO”) float TODO: non è un float ma una quantity; scrivi le unità di misura corrette.

property rated_working_pressure

Alias for field number 1

property water_flow

Alias for field number 0

class business.helpers.definitions.PipedSegment(_commercial_pipe: str, _starts_at_pathlength: float, _ends_at_pathlength: float = None)

Bases: object

A class used to represent a stretch of a commercial pipe. INGLESE: non è uno stretch ma….?

_commercial_pipe

the commercial pipe

Type

Pipe

_starts_at_pathlength

the linear distance where the stretch begins

Type

Quantity(“length”)

_ends_at_pathlength

the linear distance where the stretch ends. It is optional: either it can be assigned or it can be evaluated looping in the ordered collection of PipedSegments.

Type

Quantity(“length”), optional

Linear distances refer to a zero which is defined in *Trunk* class.
water_flow()

Geometric representation of the record in a 2-d plane.

burned_energy()

the amount of hydraulic energy burned off at a given water_flow

pathlength()

the linear extension of the stretch

penalty()

the investment cost to build the stretch

property burned_energy

Return the hydraulic energy burned off by the commercial pipe.

Note

Precondition: self._ends_at_pathlength is set.

property pathlength

Return the linear length of the stretch instance.

Note

Precondition: self._ends_at_pathlength is set.

class business.helpers.definitions.PipedSegmentCheck(_commercial_pipe: str, _starts_at_pathlength: float, _ends_at_pathlength: float = None)

Bases: business.helpers.definitions.PipedSegment

get_headloss_at_sample_flow(sample_water_flow)
get_humanized_pipe_name()

Return the name of the commercial pipe, suitable for django templates.

Functionality: accessing the name of the commercial pipe cannot be achieved simply using the django template language because the language must access two custom template filters in sequence. These filters are needed to access dictionary keys (_commercial_pipe and _natural_key_as_string) wich have an underscore prepended. It’s too much logic to be put in the template (and makes the line of code to be too long). Therefore we resort to this method, which may be accessed directly using the {{ context.key }} syntax of the template language.

Returns

the unique identifier of a commercial pipe, formatted as ‘human readable’, with underscores replaced by spaces.

Return type

str

property non_fractional_burned_energy

Return the hydraulic energy burned off by the commercial pipe, if friction is evaluated with integer-powers only.

property water_flow
class business.helpers.definitions.PipedSegmentDesign(_commercial_pipe: str, _starts_at_pathlength: float, _ends_at_pathlength: float = None)

Bases: business.helpers.definitions.PipedSegment

property water_flow

Set the water flow in the commercial pipe.

class business.helpers.definitions.RiserAssemblyWorkingConditions(water_flow, pump_depth)

Bases: tuple

The requirements the monopump riser assembly must be able to satify.

Notes

May be used to select a riser and shaft combination off a catalog of commercially available combinations.

water_flow

the water flow throughout the riser assembly pipe.

Type

Quantity(“volume/time”, float)

pump_depth

the depth at which the pump body is set.

Type

Quantity(“length”, float)

property pump_depth

Alias for field number 1

property water_flow

Alias for field number 0

class business.helpers.definitions.SubmersibleWorkingConditions(water_flow)

Bases: tuple

The requirements the submersible pump must be able to satify.

Notes

May be used either to select an submersible pump off a catalog of submersible pumps commercially available. May be used to evaluate the engine load and consumption at the given woring conditions.

water_flow

the water flow throughout the pump.

Type

Quantity(“volume/time”, float)

property water_flow

Alias for field number 0

business.helpers.guards module

Collection of utilities to chek the dimension of a physical quantities.

All physical variables in ruralwater are expressed as dimensional quantities, thanks to the ‘pint’ package. These methods are used by property setters as precondition check.

Data structures
check_is_waterflow:

ensure the variable under observation represents a water flow.

business.helpers.guards.check_is_column_working_conditions(function)
business.helpers.guards.check_is_pipe_working_conditions(function)
business.helpers.guards.check_is_pressure(function)

Chek a precondition: if the ‘value’ passed to a setter is meaningful.

Checks that the value passed to a setter represents a geometric distance.

Parameters

function (@property.setter) – a setter method of a class

Raises

ValueError – If value has not the prescribed instance, dimensionality and magnitude.

Example

It is used as a guard when creating a rated pressure profile starting from an altimetric profile.

business.helpers.guards.check_is_rpm(function)

Chek a precondition: if the ‘value’ passed to a setter is meaningful.

Checks that the value passed to a setter represents an angular speed.

Parameters

function (@property.setter) – a setter method of a class

Raises

ValueError – If value has not the prescribed instance, dimensionality and magnitude.

Example

It is used as a guard when setting rotational speed of engines, pumps, shafts and centrifugal clutches.

business.helpers.guards.check_is_vertical_shift(function)

Chek a precondition: if the ‘value’ passed to a setter is meaningful.

Checks that the value passed to a setter represents a geometric distance.

Parameters

function (@property.setter) – a setter method of a class

Raises

ValueError – If value has not the prescribed instance, dimensionality and magnitude.

Example

It is used as a guard when creating a rated pressure profile starting from an altimetric profile.

business.helpers.guards.check_is_waterflow(function)

Chek a precondition: if the ‘value’ passed to a setter is meaningful.

Checks that the value passed to a setter represents a water flow.

Parameters

function (@property.setter) – a setter method of a class

Raises

ValueError – If value has not the prescribed instance, dimensionality and magnitude.

business.helpers.roundings module

Collection of constants used to round physical quantities magnitude.

It is used to render the logging of physical values easier to read, cutting away unnecessary decimal digits .

business.helpers.units module

Provide utilities and constants for modelling dimensional units.

Notes

This module is based on third-party <pint> library.

business.helpers.units.BSDC_UNITS = <Unit('gram / kilowatt_hour')>

Prescribes the units to express the specific diesel consumption

business.helpers.units.DAILY_DEMAND_UNITS = <Unit('liter / day')>

Prescribes the units to express the daily water demand.

business.helpers.units.DIAMETER_UNITS = <Unit('millimeter')>

namely, the inner diameter of the borehole and the width of the pipes inside it.

Type

Prescribes the units to express “width” inside the borehole

business.helpers.units.DISTANCE_UNITS = <Unit('meter')>

Prescribes the units to express linear distances. Definitions:

downrange

xxx

elevation

xxx

pathlength:

linear distance along the pipe trench

Prescribes the units to express pipe trench profiles.

business.helpers.units.ELECTRIC_ENERGY_UNITS = <Unit('hour * kilowatt')>

Prescribes the units to express the electric energy consumed each hour.

business.helpers.units.POWER_UNITS = <Unit('kilowatt')>

Prescribes the units to express the mechanical power

business.helpers.units.PULLEY_DIAMETER_UNITS = <Unit('centimeter')>

Prescribes the units to express pulley diameters.

business.helpers.units.PUMP_BODY_VERTICAL_ENCUMBRANCE = <Unit('meter')>

Prescribes the units to express how ‘long’ is the pump body.

business.helpers.units.RPM_UNITS = <Unit('revolutions_per_minute')>

Prescribes the units to express rotational speed of shafts.

business.helpers.units.WATERFLOW_UNITS = <Unit('liter / second')>

Prescribes the units to express the water flow.

business.helpers.units.as_decimal(quantity)

Return a Q_ with a magnitude cast to a python’s decimal.Decimal.

Example

Allows to perform cost estimates by multiplying a float (such as the length of meters of a commercial pipe) times a Decimal (that is, a unit price).

Parameters

quantity (helpers.business_units.Q_) – the quantity whose magnitude is to cast to integer.

Returns

an instance of helpers.business_units.Q_ with a magnitude cast to decimal.Decimal

Return type

helpers.business_units.Q_

business.helpers.units.as_integer(quantity)

Return a Q_ with a magnitude cast to an integer.

Example

Converts logs such as ‘downrange=<Quantity(3045.1000000000004, ‘meter’)> into a more readable ‘downrange=<Quantity(3045, ‘meter’)>

Parameters

quantity (helpers.business_units.Q_) – the quantity whose magnitude is to cast to integer.

Returns

an instance of helpers.business_units.Q_ with a magnitude cast to integer

Return type

helpers.business_units.Q_

business.helpers.units.as_rounded(quantity, decimal_digits=0)

Return a Q_ with a magnitude rounded to some decimal places.

Example

Converts logs such as ‘downrange=<Quantity(3045.1000000000004, ‘meter’)> into a more readable ‘downrange=<Quantity(3045, ‘meter’)>

Parameters
  • quantity (helpers.business_units.Q_) – the quantity whose magnitude is to round.

  • decimal_digits (int) – the number of decimal digits in the return value magnitude.

Returns

an instance of helpers.business_units.Q_ with a rounded magnitude

Return type

helpers.business_units.Q_

business.helpers.utils module

Programming language utilities.

class business.helpers.utils.TypedList(ok_type, iterable=[])

Bases: collections.abc.MutableSequence, business.commons.loggers.InitLogger

Create a list that accepts only elements of a given type.

Raises

TypedListError – if trying to add an element not conform to the required type.

exception TypedListError

Bases: TypeError, business.commons.exceptions.RuralwaterException

An element to append to a typed list is not of the valid type.

insert(item, value)

S.insert(index, value) – insert value before index

class business.helpers.utils.TypedSet(ok_type, iterable=())

Bases: collections.abc.MutableSet, business.commons.loggers.InitLogger

Create a list that accepts only elements of a given type.

Raises

TypedListError – if trying to add an element not conform to the required type.

exception TypedSetError

Bases: TypeError, business.commons.exceptions.RuralwaterException

An item to append to a typed set is not of the valid type.

add(item)

Add an element.

discard(item)

Remove an element. Do not raise an exception if absent.

business.helpers.utils.ajaxpolling(message)
business.helpers.utils.coroutine(func)

Do prime a coroutine advancing to the first yield statement.

business.helpers.utils.do_postcondition(method)

Invoke a method after another method is invoked.

Parameters

method (callable) – the class instance method which represents the do_postcondition. method must be decorated as @property.

business.helpers.utils.do_precondition(method)

Invoke a method before another method is invoked.

Parameters

method (callable) – the class instance method which represents the check_precondition. method must be decorated with @property.

business.helpers.utils.lazyprop(fn)

Cache and return value of property after the first time it is evaluated.

business.interface package

business.manufacturers package

Subpackages

business.manufacturers.catalogs package

This module gathers the available hydraulic hardware (such as pipes, pumps…)

Each kind of hydraulic hardware is store in a separate collection. The hydraulic hardware taken in consideration is that typical of rural water supply schemes.

Example

BodyPool:

store all commercially available pumps which were loaded into the software

CatalogOfEngines:

store all commercially available diesel engines which were loaded into the software

Modules
bases:

common base classes and mixinx

progressives:

store positive dispacement pumps run by a shaft through the borehole

engines:

store diesel engines

pipes:

store polyethilene and galvanised pipes

submersibles:

store electric submersible pumps

Submodules
business.manufacturers.catalogs.bases module

Provide common functionalities to the modules of ~business.manufacturers.catalogs.

class business.manufacturers.catalogs.bases.BaseCatalog(*args, **kwargs)

Bases: business.commons.loggers.InitLogger

Class holding functionalities to read json data from a rest interface.

property as_dict
business.manufacturers.catalogs.engines module

Define the diesel engine installed in an ‘electricless’ station.

class business.manufacturers.catalogs.engines.EngineCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.engines.EnginePool

class business.manufacturers.catalogs.engines.EngineDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.engines.EnginePool

property pick_engine_by_min_diesel_consumption

Return the engine with the best energy efficiency.

The best energy efficiency is evaluated as the lowest diesel consumption.

Parameters
  • power (Quantity("POWER"))) – the duty point (flow, energy) that the combination must be able to deliver

  • power – the power output the engine must deliver

Returns

the engine with the lowest diesel consumption

Return type

manufacturers.components.Engine

property required_power
class business.manufacturers.catalogs.engines.EnginePool(*args, **kwargs)

Bases: business.manufacturers.catalogs.bases.BaseCatalog

A class used to represent the collection of commercially available diesel engines.

_api_key_to_load

the rest api uri to get the engine data

Type

str

_rest_api_reader

the adapter in charge of reading and cleaning the engine data.

Type

adapter class

makes

the engines mapped to a unique identifier

Type

dict

property mock_pick
business.manufacturers.catalogs.pipes module

Define the pipes installed in a water supply, either ‘gravity’ or ‘station’.

Notes

In rural water supply engineering, the materials of pipes are both plastic (PVC and polyethilene) and metallic (galvanised steel). The following classes are used when environmental conditions limit the choice of materials

Example

If a Trunk crosses areas where it is impossible to dig a trench, then the computer software will be asked to adopt the class SteelPipePool.

class business.manufacturers.catalogs.pipes.BasePipePool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.ShortFeederSelectionMixin

A class used to represent a catalog of pipes.

The singleton catalog holding all the commercial pipes available for the hydraulic design and check problem calculations.

working_condition

the tuple (water flow, pressure rating) for which a pipe must be chosen

get_suitable_rated_working_pressure()

Return the smallest rated working pressure above a given value

get_suitable_rated_working_pressure_index()

Return the index of smallest rated working pressure above a given value

lowest_available_rated_working_pressure()

Return the lowest (and hence ‘less expensive’) rated working pressure

sorted_rated_working_pressures()

Return a doubly linked list of ascending rated working pressures

get_suitable_pipes_list()

Return pipes with correct flow speed, sorted from optimal speed

filter_those_having_suitable_speed()

Filter the commercial pipes having suitable flow speed and sort them

property as_dict
static filter_those_having_suitable_speed(pipe: Union[business.manufacturers.components.pipes.PipeCheck, business.manufacturers.components.pipes.PipeDesign]) → bool

Filter the commercial pipes having suitable flow speed and sort them.

This method reads working_conditions and filters accordingly those commercial pipes which have both a suitable flow speed. Then, it returns the pipes sorted by the closest to the optimal value of flow speed.

Raises

AllCommercialPipesAreUnsuitableSpeedwise – If no commercial pipe may carry the flow set in working_conditions with a flow speed within the engineering advisable range. Exaggerate speeds result in wear and conversely slow speeds result in sedimentation and clogging.

property get_suitable_pipes_list

Return pipes with correct flow speed, sorted from optimal speed.

Sorting by optimal speed means that the pipes are ordered first those whose water flow speed is closest, either by excess or defect, to the optimla water flow speed.

This method reads working_conditions and filters accordingly those commercial pipes which have both a suitable flow speed and a suitable rated working pressure. Then, it returns the pipes sorted by the closest to the optimal value of flow speed.

Returns

the sequence of pipes TODO

Return type

Tuple[Pipe]

Raises

AllCommercialPipesAreUnsuitableSpeedwise – If no commercial pipe may carry the flow set in working_conditions with a flow speed within the engineering advisable range. Exaggerate speeds result in wear and conversely slow speeds result in sedimentation and clogging.

get_suitable_rated_working_pressure(working_pressure: pint.quantity.build_quantity_class.<locals>.Quantity) → pint.quantity.build_quantity_class.<locals>.Quantity

Return the smallest rated working pressure above a given value.

Parameters

working_pressure (Quantity("TODO pressure")) – the pressure that a commercial pipe must be able to sustain

Returns

The smallest coommercial rated working pressure above working_pressure

Return type

manufacturers.components.Pipe

Raises

NoSuitableRatedWorkingPressureAvailableFromCatalog – If the catalog does not have any commercia pipes able to sustain the pressure request

get_suitable_rated_working_pressure_index(working_pressure: pint.quantity.build_quantity_class.<locals>.Quantity) → int

Return the index of smallest rated working pressure above a given value.

Parameters

working_pressure (Quantity("TODO pressure")) – the pressure that a commercial pipe must be able to sustain

Returns

The index of the smallest coommercial rated working pressure above working_pressure

Return type

manufacturers.components.Pipe

Raises

NoSuitableRatedWorkingPressureAvailableFromCatalog – If the catalog does not have any commercia pipes able to sustain the pressure request

property lowest_available_rated_working_pressure

Return the lowest (and hence ‘less expensive’) rated working pressure among the commercial pipes stored in the catalog.

property pick_random_pipe

Returns a random pipe.

This method is useful to mock a feeder during a software test session.

property sorted_rated_working_pressures

Return a doubly linked list of ascending rated working pressures.

property working_condition
class business.manufacturers.catalogs.pipes.PipeCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.PipePool

class business.manufacturers.catalogs.pipes.PipeDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.PipePool

class business.manufacturers.catalogs.pipes.PipePool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.BasePipePool

A class used to represent the collection of all commercial pipes.

api_keys_to_load

the urls to query the rest interface. A string in the set queries for metallic pipes. The others query for the plastic ones (polyethilene).

Type

Set(str)

api_keys_to_load = {'polyethylene_pipes', 'steel_pipes'}
class business.manufacturers.catalogs.pipes.RiserPipeCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.RiserPipePool

class business.manufacturers.catalogs.pipes.RiserPipeDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.RiserPipePool

property water_flow
class business.manufacturers.catalogs.pipes.RiserPipePool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.BasePipePool

A class used to represent the collection of commercial pipes which may be used inside the borehole casing.

api_keys_to_load

The string in the set queries for sturdy metallic pipes.

Type

Set(str)

api_keys_to_load = {'steel_pipes'}
property get_suitable_pipes_list

Return the list of pipes compliant with working_conditions ordered from closest to optimal flow speed.

class business.manufacturers.catalogs.pipes.ShortFeederSelectionMixin

Bases: object

Collection of methods only used to pick a pipe in short feeders.

Short feeders are those where pressure rating effects do not occour. Further, short feeders imply limited headloss compared to a borehole, hence no simplex solver is necessary when approaching the design problem.

Example

A ‘short’ feeder is one where the pressure limits do not represent an hydraulic design hurdle. The lowest rated pressure class may be selected. This mixin may be used for this simple pressure-agnostic design procedure.

property pick_one_pipe_by_optimal_flow_speed

Return the pipe whose flow speed is closest to an optimum value.

yield_all_pipes_by_optimal_flow_speed() → Iterator[business.manufacturers.components.pipes.PipeDesign]

Yield pipes best to worst according to suitable flow speed.

class business.manufacturers.catalogs.pipes.SteelPipePool(*args, **kwargs)

Bases: business.manufacturers.catalogs.pipes.BasePipePool

A class used to represent the collection of commercial pipes which may laid exposed without being buried in a trench.

api_keys_to_load

the urls to query the rest interface. The string in the set queries for metallic pipes.

Type

Set(str)

api_keys_to_load = {'steel_pipes'}
business.manufacturers.catalogs.progressives module

Define the progressive cavity pump installed in an ‘electricless’ station.

Refer to progressives_nomenclature

class business.manufacturers.catalogs.progressives.BaseColumnLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

Adapter from a json source of progressive cavity pump riser assembly.

_component_class

the dataclass use to represent progressive cavity pump riser assemblies

class business.manufacturers.catalogs.progressives.BaseCombinationLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

class business.manufacturers.catalogs.progressives.BodyCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.BodyPool

class business.manufacturers.catalogs.progressives.BodyDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.BodyPool

class business.manufacturers.catalogs.progressives.BodyPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.bases.BaseCatalog

A class used to represent the collection of commercially available pumps.

every instance in the collections is an instance of components.progressives.Body. PIERGIORGIO2: è giusto scrivere come nella riga sopra in un docstring? Basta questa dot notation per fare capire dove si trova Body?

_api_key_to_load

the rest api uri to get the pump data

Type

str

_rest_api_reader

the adapter in charge of reading and cleaning the pump data.

Type

adapter class

makes

the pump bodies mapped to a unique identifier

Type

dict

class business.manufacturers.catalogs.progressives.ColumnCheckLoader(api_uri: str)

Bases: business.manufacturers.catalogs.progressives.BaseColumnLoader

class business.manufacturers.catalogs.progressives.ColumnCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.ColumnPool

class business.manufacturers.catalogs.progressives.ColumnDesignLoader(api_uri: str)

Bases: business.manufacturers.catalogs.progressives.BaseColumnLoader

class business.manufacturers.catalogs.progressives.ColumnDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.ColumnPool

class business.manufacturers.catalogs.progressives.ColumnPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.bases.BaseCatalog

A class used to represent the collection of feasible combinations that make up for a ‘riser assembly’.

_api_key_to_load

the rest api uri to get the riser assembly data

Type

str

_rest_api_reader

the adapter in charge of reading and cleaning the riser assembly data.

Type

adapter class

makes

the riser assemblies mapped to a unique identifier

Type

dict

class business.manufacturers.catalogs.progressives.CombinationCheckLoader(api_uri: str)

Bases: business.manufacturers.catalogs.progressives.BaseCombinationLoader

class business.manufacturers.catalogs.progressives.CombinationCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.CombinationPool

class business.manufacturers.catalogs.progressives.CombinationDesignLoader(api_uri: str)

Bases: business.manufacturers.catalogs.progressives.BaseCombinationLoader

class business.manufacturers.catalogs.progressives.CombinationDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.CombinationPool

property duty_before_column_friction
property pick_least_power_combination

Return the pump combination with the best energy efficiency.

Important

Why we have ‘duty_excluding_column_friction’: The consumer of this method knows the energy required by resistive system (aquifer, feeder) but, so far, does not know which pump model will be selected by the algorithm. When this method is invoked, the algorith selects a pump and its shaft, therefore perturbing the original ‘targeted duty’. The new duty, following to the pump selction is identified by <targeted_duty_including_riser_friction>.

Parameters
  • duty_excluding_column_friction (business_definitions.FlowVsEnergyPoint,) – the duty point (flow, energy) that the combination must be able to deliver

  • pump_depth (Quantity("length"))) – the depth at which the pump must be installed (it affects the efficiency through the shaft losses)

Returns

the pump combination with the best energy efficiency

Return type

manufacturers.components.Combination

property pump_depth
class business.manufacturers.catalogs.progressives.CombinationPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.PlotCombinationsMixin, business.manufacturers.catalogs.bases.BaseCatalog

A class used to represent the collection of feasible combinations that make up for a ‘pump’.

_api_key_to_load

the rest api uri to get the riser assembly data

Type

str

_rest_api_reader

the adapter in charge of reading and cleaning the riser assembly data.

Type

adapter class

pick_least_power_combination(

duty_excluding_column_friction : business_definitions.FlowVsEnergyPoint, pump_depth : Quantity(“length”)) return the pump combination with the best energy efficiency

property mock_pick
class business.manufacturers.catalogs.progressives.DriveheadPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.bases.BaseCatalog

A class used to represent the collection of commercially available driveheads.

_api_key_to_load

the rest api uri to get the drivehead data

Type

str

_rest_api_reader

the adapter in charge of reading and cleaning the drivehead data.

Type

adapter class

makes

the driveheads mapped to a unique identifier

Type

dict

class business.manufacturers.catalogs.progressives.PlotCombinationsMixin

Bases: object

A mixin class gathering methods used to send data to matplotlib package.

The methods here defined allow to iterate in the catalog.

Example

>>> catalog_of_combinations = CombinationCheckPool()
>>> for combination in catalog_of_combinations:
>>>     # do something with <combination>
class business.manufacturers.catalogs.progressives.ShaftCheckPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.ShaftPool

class business.manufacturers.catalogs.progressives.ShaftDesignPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.progressives.ShaftPool

class business.manufacturers.catalogs.progressives.ShaftPool(*args, **kwargs)

Bases: business.manufacturers.catalogs.bases.BaseCatalog

Represent the collection of commercially available shafts.

_api_key_to_load

the rest api uri to get the shaft data

Type

str

_rest_api_reader

the adapter in charge of reading and cleaning the shaft data.

Type

adapter class

makes

the shafts mapped to a unique identifier

Type

dict

business.manufacturers.catalogs.submersibles module

Define the electric submersible pump installed in an ‘electric’ station.

class business.manufacturers.catalogs.submersibles.SubmersiblePool(*args, **kwargs)

Bases: business.manufacturers.catalogs.bases.BaseCatalog

A class used to represent the collection of commercially available submersible pumps.

_api_key_to_load

the rest api uri to get the pump data

Type

str

list_suitable_pumps

Return the list of pumps compliant with working_conditions

working_condition

Get or set the current working conditions that pumps must sustain

property mock_pick
property working_condition
class business.manufacturers.catalogs.submersibles.SubmersiblePoolCheck(*args, **kwargs)

Bases: business.manufacturers.catalogs.submersibles.SubmersiblePool

class business.manufacturers.catalogs.submersibles.SubmersiblePoolDesign(*args, **kwargs)

Bases: business.manufacturers.catalogs.submersibles.SubmersiblePool

property get_suitable_pump_list

Return the list of pumps compliant with working_conditions.

property water_flow
business.manufacturers.components package

Collection of the models of hydraulic hardware (such as pipes, pumps…)

The hydraulic hardware taken in consideration is that typical of rural water supply schemes.

Modules
progressives:

models positive dispacement pumps run by a shaft through the borehole

engines:

models diesel engines

pipes:

models polyethilene and galvanised pipes

submersibles:

models electric submersible pumps

Submodules
business.manufacturers.components.engines module

Define the internal combustion engine installed in an ‘electricless’ station.

class business.manufacturers.components.engines.Clutch(_pulley_diameter: int)

Bases: business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class to represent a centrifugal clutch keyed to the engine crankshaft.

rpm

return the currrent rotation speed of the clutch pulley

Type

Quantity(“revolutions_per_minute”)

absorbed_power

return the mechanical power absorbed by the clutch at the currrent rotation speed

Type

Quantity(“power”)

property absorbed_power

Return the mechanical power absorbed by the clutch.

Returns

At present it returns a mock zero value.

Return type

Quantity(“power”)

class business.manufacturers.components.engines.Engine(_natural_key_as_string: str, _standard_clutch_pulley_diameter: float, _rating_data: List[Dict])

Bases: business.manufacturers.components.engines.EngineRatingMixin, business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class to represent an internal combution engine.

Parameters
  • name (string) – the make of the engine.

  • _guessed_unit_price (decimal) – the shelf price of the engine.

class business.manufacturers.components.engines.EngineCheck(_natural_key_as_string: str, _standard_clutch_pulley_diameter: float, _rating_data: List[Dict])

Bases: business.manufacturers.components.engines.Engine

Functionality: expose the methods needed in the resolution of the ‘hydarulic check problem’

property hourly_diesel_consumption

Return the diesel consumption per hour at the current woring conditions.

property load

Load is evaluated once the rpm is set.

property rpm_range

Return a sequence of equidistant operating speeds of the crankshaft.

Returns

an array of dimensional values (Quantity(“revolutions_per_minute”)) with np.int16 magnitudes

Return type

np.array

property working_conditions
class business.manufacturers.components.engines.EngineDesign(_natural_key_as_string: str, _standard_clutch_pulley_diameter: float, _rating_data: List[Dict])

Bases: business.manufacturers.components.engines.Engine

Model of a internal combustion engine during the hydraulic check problem.

Functionality: expose the methods needed in the resolution of the ‘hydarulic design problem’

In an hydraulic check problem, the goal is to find the engine that best suits the required mechanical power demanded by the pump. The pump has been identified in a previous step of the hydraulic check problem.

The state of the engine is defined by the required power.

The outcome is DEVO RESITUIRE SPEED O COSA? CREDO BASTO LA SPEED

property get_optimal_duty

Find the optimal revving speed to output the required power.

Performs linear interpolation between sample points.

Note

The optimal speed corresponds to minimal diesel consumption. Each speed implies a load and a diesel consumption; this method therefore evaluates the consumption along the power band and identifies its minimum.

property required_power
property required_power_is_suitable
class business.manufacturers.components.engines.EngineRatingMixin

Bases: object

A class to represent the engine rating and associated calculations.

Functionality: infer the engine behaviour based from the plate data provided by the engine manufacturer.

rpm_range

Return a sequence of equidistant operating speeds of the crankshaft

dispatch_np_type

stores the numerical types to be used with power output, diesel consumption and crankshaft rpm

dispatch_units

stores the dimensional units to be used with power output, diesel consumption and crankshaft rpm

required_power_is_suitable(power: Quantity(‘power’))

boolean test whether the required power lies within advisable load limits

get_optimal_duty(power: Quantity(‘power’))

Find the optimal revving speed to output the required power

Point

alias of EngineRatingPoint

dispatch_np_type = {'delivered_power': <class 'numpy.float64'>, 'rpm': <class 'numpy.int16'>, 'specific_diesel_consumption': <class 'numpy.float64'>}
dispatch_units = {'delivered_power': <Unit('kilowatt')>, 'rpm': <Unit('revolutions_per_minute')>, 'specific_diesel_consumption': <Unit('gram / kilowatt_hour')>}
business.manufacturers.components.mixins module
business.manufacturers.components.pipes module

Define the commercial pipes.

business.manufacturers.components.pipes.FUTURE_round_the_water_flow(function: Callable) → Callable
class business.manufacturers.components.pipes.Pipe(_natural_key_as_string: str, _material_name: str, _pressure_limit: int, _internal_diameter: float, _standard_unit_length: int, _external_diameter: float)

Bases: business.manufacturers.utils.MonostateMixin

A class to represent a commercial pipe.

Pipes vary in length from 3-6 m and longer by special order. Polyethylene coils are an exception. They come in lengths of 30 and 150 m with longer lengths available.

water_flow(Quantity("volume/time"))

Get or set the water flowing inside the pipe

flow_speed

return the velocity of the water flow inside the pipe

friction_per_unit_pathlength

Return the hydraulic energy loss per unit of length of the pipe

property friction_per_unit_pathlength

Return the hydraulic energy loss per unit of length of the pipe.

The calculation is evaluated at the current water flow. This method dispatches the actual calculation to three different methods, depending on the pipe material (polyethylene pipes, PVC pipes and steel pipes). These are the three materials adopted in rural water supply systems.

Returns

the hydraulic energy loss per unit of pipe length. It is adimensional since hydraulic energy has the dimensions of a length.

Return type

Quantity(“dimensionless”)

get_headloss_per_meter_at_sample_flow(sample_water_flow: pint.quantity.build_quantity_class.<locals>.Quantity) → pint.quantity.build_quantity_class.<locals>.Quantity

Return the hydraulic energy loss along 1 meter at a given water flow.

Functionality: allows to skip the water_flow setter, which is computationally heavier.

Notes

Pipes dataclasses are implemented with state and the state is the water_flow (such attribute has a setter and a getter). This function is used to evaluate the ‘hydraulic energy loss’ (due to water friction) due to a generic water flow, not the one set in the dataclass state.

property non_fractional_friction_per_unit_pathlength
class business.manufacturers.components.pipes.PipeCheck(_natural_key_as_string: str, _material_name: str, _pressure_limit: int, _internal_diameter: float, _standard_unit_length: int, _external_diameter: float)

Bases: business.manufacturers.components.pipes.Pipe

class business.manufacturers.components.pipes.PipeDesign(_natural_key_as_string: str, _material_name: str, _pressure_limit: int, _internal_diameter: float, _standard_unit_length: int, _external_diameter: float)

Bases: business.manufacturers.components.pipes.Pipe

property flow_speed
property water_flow
class business.manufacturers.components.pipes.RiserPipe(_natural_key_as_string: str, _material_name: str, _pressure_limit: int, _internal_diameter: float, _standard_unit_length: int, _external_diameter: float)

Bases: business.manufacturers.components.pipes.Pipe

class business.manufacturers.components.pipes.RiserPipeCheck(_natural_key_as_string: str, _material_name: str, _pressure_limit: int, _internal_diameter: float, _standard_unit_length: int, _external_diameter: float)

Bases: business.manufacturers.components.pipes.RiserPipe, business.manufacturers.components.pipes.PipeCheck

class business.manufacturers.components.pipes.RiserPipeDesign(_natural_key_as_string: str, _material_name: str, _pressure_limit: int, _internal_diameter: float, _standard_unit_length: int, _external_diameter: float)

Bases: business.manufacturers.components.pipes.RiserPipe, business.manufacturers.components.pipes.PipeDesign

business.manufacturers.components.pipes.round_the_water_flow(function: Callable) → Callable
business.manufacturers.components.progressives module

Define the ‘electricless progressive cavity pump’ installed in a borehole.

Nomenclature:
  • Body:

    the pumping element installed in the borehole

  • Drivehead:

    the gear element at the top of the borehole

  • Shaft:

    the shaft transmitting movement to the Body

  • Column:

    the combination of borehole pipe and the shaft inside it

  • Combination:

    the composite of Body, Column and Drivehead

Notes

The wording “deep progressive cavity” means that the pump is a ‘composition’ of three mechanical elements:

  • a pump body: installed down the borehole

  • a riser assembly, rising in the borehole (made of water pipe and shaft inside it)

  • a drivehead, installed at the wellhead

Each of these mechanical elements has a separate collection.

class business.manufacturers.components.progressives.Body(_natural_key_as_string: str, _flow_rating_data: List, _power_rating_data: List)

Bases: business.manufacturers.components.progressives.BodyHydraulicRatingMixin, business.manufacturers.components.progressives.BodyMechanicalRatingMixin, business.manufacturers.components.progressives.PlotsMixin, business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class used to represent the pump body.

rpm()

get and set the pump rotational speed

resistive_curve()

return the pump characteristic curve HAESTADT water flow versus hydraulic energy

class business.manufacturers.components.progressives.BodyCheck(_natural_key_as_string: str, _flow_rating_data: List, _power_rating_data: List)

Bases: business.manufacturers.components.progressives.Body

write

property absorbed_mechanical_power

Same logic holds as that in water_flow.

property resistive_curve
property rpm
property water_flow

Water flow is read only since you cannot impose a flow to a pump. You may only impose a rotational speed, if the engine is powerful enough. The water flow will physically update accordingly to the new rotational speed.

class business.manufacturers.components.progressives.BodyDesign(_natural_key_as_string: str, _flow_rating_data: List, _power_rating_data: List)

Bases: business.manufacturers.components.progressives.Body

CREDO QUESTA CLASSE FUNZIONI COSI’: 1 - RICEVE UN DUTY BEFORE COLUMN E CALCOLA LA RPM 2 - RICEVE UN DUTY AFTER COLUMN E IL MUTATOR CAMBIA LA RPM E ALLORA INNESCO GET_DUTY_POWER IN TTOTAL HA SOLO 3 METODI

property absorbed_mechanical_power
property coverage

HAESTADT

property duty_after_column_friction
property get_duty_rpm

Return the rpm at which the pump delivers the requested water flow and energy.

Performs linear interpolation between sample points.

Parameters

flow_vs_energy_point – the (water flow, hydraulic energy) tuple the pump is required to deliver

property rpm
class business.manufacturers.components.progressives.BodyHydraulicRatingMixin

Bases: object

A mixin collecting methods to analyse data of the pump rated water flow.

RatedPoint

a 3-d point in water flow, hydraulic energy, rpm coordinates

dispatch_np_type

stores the numerical types to be used with water flow, hydraulic energy, rpm

dispatch_units

stores the dimensional units to be used with water flow, hydraulic energy, rpm

coverage_as_matplotlib()

matplotlib coordinates of the pump coverage HAESTADT

coverage()

HAESTADT

get_duty_rpm()

return the rpm for which the pump attains a given (water flow, energy) duty

RatedPoint

alias of PumpFlowRatingPoint

dispatch_np_type = {'hydraulic_energy': <class 'numpy.int16'>, 'rpm': <class 'numpy.int16'>, 'water_flow': <class 'numpy.float64'>}
dispatch_units = {'hydraulic_energy': <Unit('meter')>, 'rpm': <Unit('revolutions_per_minute')>, 'water_flow': <Unit('liter / second')>}
class business.manufacturers.components.progressives.BodyMechanicalRatingMixin

Bases: object

A mixin collecting methods to analyse data of the pump rated mechanical power.

RatedPoint

a 3-d point in mechanical power, hydraulic energy, rpm coordinates

_get_absorbed_mechanical_power(duty_rpm, duty_head)

return the mechanical power required by the pump at given rpm and energy

Point__doc__ = '\n Represent a point in the 2-d plane whose coordinates are mechanical power, hydraulic energy and rpm.\n '
RatedPoint

alias of PumpPowerRatingPoint

class business.manufacturers.components.progressives.Column(_column_unit_length: int, _natural_key_as_string: str, _max_allowed_pump_depth: int, _rating_data: str)

Bases: business.manufacturers.components.progressives.ColumnRatingMixin, business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class used to represent the composite of the borehole pipe and the shaft rotating inside it.

get_duty_point()

return the hydraulic energy burned off by the pipe&shaft assembly

working_conditions()

set the requested duty point represented by a 2-tuple (water flow, pump depth)

property adopt

Return a copy of the dataclass instance.

Overrides the monostate becasue of the ‘foreign-key’ relations with the shaft and the pipe.

property get_duty_point

Return the hydraulic energy loss through the riser at the current water flow.

Returns

2-tuple (energy, water flow) with dimensional values (Quantity(“length”), Quantity(“volume / time”))

Return type

FlowVsEnergyPoint

property working_conditions
class business.manufacturers.components.progressives.ColumnCheck(_column_unit_length: int, _natural_key_as_string: str, _max_allowed_pump_depth: int, _rating_data: str, _shaft: business.manufacturers.components.progressives.ShaftCheck, _pipe: business.manufacturers.components.pipes.PipeCheck)

Bases: business.manufacturers.components.progressives.Column

property pump_depth
property rpm
class business.manufacturers.components.progressives.ColumnDesign(_column_unit_length: int, _natural_key_as_string: str, _max_allowed_pump_depth: int, _rating_data: str, _shaft: business.manufacturers.components.progressives.ShaftDesign, _pipe: business.manufacturers.components.pipes.PipeDesign)

Bases: business.manufacturers.components.progressives.Column

class business.manufacturers.components.progressives.ColumnRatingMixin

Bases: object

A mixin collecting methods to evaluate the hydraulic friction.

_get_friction_per_unit_pathlength()

Return the hydraulic friction in the assembly per meter

RatedPoint

alias of RiserFrictionPoint

class business.manufacturers.components.progressives.Combination(_natural_key_as_string: str)

Bases: business.manufacturers.utils.MonostateMixin

A class used to represent the composite of body, drivehead and riser assembly.

hydraulic_design_constraint(targeted_duty_excluding_riser, pump_depth)

sets the targeted design constraints in the Column instance associated to the Combination instance.

property absorbed_mechanical_power
class business.manufacturers.components.progressives.CombinationCheck(_natural_key_as_string: str, _body: business.manufacturers.components.progressives.BodyCheck, _drivehead: business.manufacturers.components.progressives.DriveheadCheck, _column: business.manufacturers.components.progressives.ColumnCheck)

Bases: business.manufacturers.components.progressives.Combination

property adopt

Return a copy of the dataclass instance.

Overrides the monostate becasue of the ‘foreign-key’ relations with the drivehead, the body and the column.

property pump_depth
property rpm
class business.manufacturers.components.progressives.CombinationDesign(_natural_key_as_string: str, _body: business.manufacturers.components.progressives.BodyDesign, _column: business.manufacturers.components.progressives.ColumnDesign, _drivehead: business.manufacturers.components.progressives.DriveheadDesign)

Bases: business.manufacturers.components.progressives.Combination

property rpm
class business.manufacturers.components.progressives.Drivehead(_natural_key_as_string: str, _max_transmittable_power: float, _absorbed_power_per_rpm: float)

Bases: business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class used to represent a drivehead.

The drivehead is the mechanical element that connects the top of the pump shaft with the prime mover. This connection here is done via belts.

absorbed_power()

return the mechanical absorbed mechanical power

property absorbed_mechanical_power

Return the drivehead’s mechanical absorbed mechanical power at the current rpm speed.

Returns

mechanical mechanical power

Return type

Quantity(“mechanical power”)

class business.manufacturers.components.progressives.DriveheadCheck(_natural_key_as_string: str, _max_transmittable_power: float, _absorbed_power_per_rpm: float)

Bases: business.manufacturers.components.progressives.Drivehead

class business.manufacturers.components.progressives.DriveheadDesign(_natural_key_as_string: str, _max_transmittable_power: float, _absorbed_power_per_rpm: float)

Bases: business.manufacturers.components.progressives.Drivehead

class business.manufacturers.components.progressives.PlotsMixin

Bases: object

A mixin collecting methods to adapt data to matplotlib interface.

coverage_as_matplotlib()

matplotlib coordinates of the pump coverage HAESTADT

property coverage_as_matplotlib

Return the coverage adimensional coordinates, as a 2-tuple of lists.

Selecting the pump can be an intimidating process n, given the number of pump modls available. This method returns a ‘pump coverage chart’ for choosing the pump model: it provides the boundary of working conditions on a hydraulic energy vs water flow 2-D chart.

shapely’s method boundary returns a LineString and then xy method extracts the coordinates as a 2-tuple of tuples of floats. These coordinates comply with matplotlib’s plot interface.

class business.manufacturers.components.progressives.Shaft(_natural_key_as_string: str, _absorbed_power_per_rpm_and_length: float, _standard_unit_length: int)

Bases: business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class used to represent a shaft inserted inside the borehole pipe.

absorbed_power()

return the mechanical absorbed mechanical power

property absorbed_mechanical_power

Return the shaft’s mechanical absorbed mechanical power at the current rpm speed.

absorbed_power()

return the mechanical absorbed mechanical power

class business.manufacturers.components.progressives.ShaftCheck(_natural_key_as_string: str, _absorbed_power_per_rpm_and_length: float, _standard_unit_length: int)

Bases: business.manufacturers.components.progressives.Shaft

class business.manufacturers.components.progressives.ShaftDesign(_natural_key_as_string: str, _absorbed_power_per_rpm_and_length: float, _standard_unit_length: int)

Bases: business.manufacturers.components.progressives.Shaft

business.manufacturers.components.submersibles module

Define the ‘electric submersible pump’ installed in a borehole.

class business.manufacturers.components.submersibles.SubmersiblePump(_natural_key_as_string: str, _rating_data: List[Dict])

Bases: business.commons.loggers.InitLoggerMixin, business.manufacturers.utils.MonostateMixin

A class to represent an electric submersible pump, togetehr with its electric motor.

Energy needs to be added to a hydraulic system to overcome elevation differences and friction losses. A pump is a device to which mechanical energy is applied and transferred to the water as total head. The relationship between pump head and pump discharge is given in the form of a head versus discharge curve.

water_flow

Get or set the water flow through the pump

is_suitable_for_given_flow

boolean test checking whether the pump may be deliver the water_flow

_min_rated_flow

Return the smallest water flow found in the discrete rating points

_max_rated_flow

Return the largest water flow found in the discrete rating points

get_duty_at_current_water_flow

Return the pump performance (delivered flow, power requirements) interpolated at the water_flow set

get_characteristic_curve

Return the curve (delivered flow vs required mechanical energy) of the pump

RatingPoint

a 3-d point in flow, head, rpm coordinates

dispatch_np_type

stores the numerical types to be used with flow, head, brake and input power

dispatch_units

stores the numerical types to be used with flow, head, brake and input power

RatingPoint

alias of SubmersiblePumpRatingPoint

dispatch_np_type = {'electric_power': <class 'numpy.float64'>, 'hydraulic_energy': <class 'numpy.int16'>, 'mechanical_power': <class 'numpy.float64'>, 'water_flow': <class 'numpy.float64'>}
dispatch_units = {'electric_power': <Unit('kilowatt')>, 'hydraulic_energy': <Unit('meter')>, 'mechanical_power': <Unit('kilowatt')>, 'water_flow': <Unit('liter / second')>}
property get_characteristic_curve

Return the (flow, water energy) curve characteristic of the pump.

Returns

the typed sequence whose elements are the points of the curve

Return type

FlowVsEnergyCurve

property get_duty_at_current_water_flow

Return the rating data inferred from linear interpolation over the delivered water_flow.

Performs linear interpolation between sample points.

property water_flow
class business.manufacturers.components.submersibles.SubmersiblePumpCheck(_natural_key_as_string: str, _rating_data: List[Dict])

Bases: business.manufacturers.components.submersibles.SubmersiblePump

class business.manufacturers.components.submersibles.SubmersiblePumpDesign(_natural_key_as_string: str, _rating_data: List[Dict])

Bases: business.manufacturers.components.submersibles.SubmersiblePump

get_duty()
property get_electric_power
property get_hydraulic_energy
property is_suitable_for_given_flow

Return True if the pump may be deliver the water_flow. False otherwise.

property water_flow
business.manufacturers.exceptions package
Submodules
business.manufacturers.exceptions.base module

Collection of the exceptions common to different typologies of products.

Example

Pumps may belong to different typologies (submersible, progressive) but, not withstanding their typology, there is a common exception “All pumps are unsuitable”

exception business.manufacturers.exceptions.base.AllElectricSourcesAreUnsuitable

Bases: business.commons.exceptions.RuralwaterException

The catalog of electric sources has no device capable of supplying the required electric power.

May be raised by any catalog of electric generators, or by a catalog of photovoltaic solar panels.

exception business.manufacturers.exceptions.base.AllPumpsAreUnsuitable

Bases: business.commons.exceptions.RuralwaterException

The catalog of pumps has no pump capable of supplying the required duty.

May be raised by any catalog of pumps, for example a catalog of submersibles or a catalog of positive displacement pumps.

business.manufacturers.exceptions.engines module

Collection of the exceptions raised inside manufacturers.components.engines package.

exception business.manufacturers.exceptions.engines.AllEnginesAreUnsuitable

Bases: business.commons.exceptions.RuralwaterException

The catalog of progressive displacement pumps has no pump capable of supplying the required duty.

This means, colloquially, that either all the pumps are ‘too big’ or they are ‘too small’.

exception business.manufacturers.exceptions.engines.EngineOverRevving

Bases: business.commons.exceptions.UnadvisableDuty

The Engine speed lies above the maximum advisable limit.

exception business.manufacturers.exceptions.engines.EngineOverload

Bases: business.commons.exceptions.UnadvisableDuty

The Engine load exceeds the maximum advisable limit specified by the manufacturer.

exception business.manufacturers.exceptions.engines.EngineUnderRevving

Bases: business.commons.exceptions.UnadvisableDuty

The Engine speed lies below the minimum advisable limit.

This condition is deemed unadvisable because it can lead to bad combustion and carbonation of the cylinders.

business.manufacturers.exceptions.pipes module

Collection of the exceptions raised inside manufacturers.components.pipes package.

exception business.manufacturers.exceptions.pipes.AllCommercialPipesAreUnsuitableBorewise(message, borehole_casing_bore)

Bases: business.commons.exceptions.RuralwaterException

No pipe has suitable bore to fit inside the borehole casing.

exception business.manufacturers.exceptions.pipes.AllCommercialPipesAreUnsuitableSpeedwise(message, desired_flow, required_rating)

Bases: business.commons.exceptions.RuralwaterException

No pipe is suitable to carry the desired _water_flow within the advisable _water_flow speed limits.

Raised by manufacturers.CommercialHdpePipes and manufacturers.CommercialGalvanisedSteelPipes.

exception business.manufacturers.exceptions.pipes.NoSuitableRatedWorkingPressureAvailableFromCatalog

Bases: business.commons.exceptions.RuralwaterException

The catalog of pipes has no pipe belonging to the required rated working pressure.

This means that the pipes are too ‘thin’ or ‘weak’ to sustain the hydraulic pressure required during the solution of the hydraulic design algorithm.

business.manufacturers.exceptions.progressives module

Collection of the exceptions raised inside manufacturers.components.progressives package.

exception business.manufacturers.exceptions.progressives.AllPumpCombinationsAreUnsuitable

Bases: business.manufacturers.exceptions.base.AllPumpsAreUnsuitable

The catalog of progressive progressives pumps has no pump capable of supplying the required duty.

This means, colloquially, that either all the pumps are ‘too big’ or they are ‘too small’.

exception business.manufacturers.exceptions.progressives.NonExistentDutyPoint

Bases: business.commons.exceptions.RuralwaterException

Base class for all cases where the duty point does not exist.

exception business.manufacturers.exceptions.progressives.PumpOverRevving

Bases: business.commons.exceptions.RuralwaterException

The Body shaft speed lies above the maximum advisable limit specified by the manufacturer.

business.manufacturers.exceptions.submersibles module

Collection of the exceptions raised inside manufacturers.components.submersibles package.

exception business.manufacturers.exceptions.submersibles.AllSubmersiblePumpsAreUnsuitable

Bases: business.manufacturers.exceptions.base.AllPumpsAreUnsuitable

The catalog of submesible pumps has no pump capable of supplying the required duty.

Submodules

business.manufacturers.constants module

Collection of constants used in both the hydraulic design and check problems.

business.manufacturers.constants.DIESEL_SPECIFIC_WEIGHT = <Quantity(0.835, 'dimensionless')>

Prescribes the specific weigth of fuel, used to run consumption calculations.

business.manufacturers.constants.ENGINE_MAX_ADVISABLE_LOAD = 1

Prescribes the maximum engine load before wear occours.

business.manufacturers.constants.ENGINE_MIN_ADVISABLE_LOAD = 0.1

Prescribes the minimal engine load before carbonation and wear occour.

business.manufacturers.constants.MAX_ADVISABLE_FLOW_SPEED = <Quantity(12.0, 'meter / second')>

Prescribes the maximal speed of water inside the pipes to prevent wear.

business.manufacturers.constants.MAX_ADVISABLE_VEE_BELT_TRANSMISSION_RATIO = 1.67

Prescribes the maximum vee-belt ratio before slipping occours.

business.manufacturers.constants.MIN_ADVISABLE_FLOW_SPEED = <Quantity(0.0005, 'meter / second')>

Prescribes the minimal speed of water inside the pipes to prevent sedimentation.

business.manufacturers.constants.MIN_CLUTCH_ENGAGEMENT_RPM_MAGNITUDE = 1600

Prescribes the minimal crankshaft speed to allow a centrifugal clutch to engage.

business.manufacturers.constants.PREFERRED_FLOW_SPEED = <Quantity(5, 'foot / second')>

Prescribes the optimal speed of water inside the pipes.

business.manufacturers.constants.VEE_BELTS_TRANSMISSION_EFFICIENCY = 0.96

Prescribes a default mechanical power loss between belts and pulleys.

business.manufacturers.readers module

Define readers of json data, able to populate hydraulic hardware dataclasses.

class business.manufacturers.readers.BaseComponentLoader(api_uri: str)

Bases: business.commons.loggers.InitLogger

Mixin gathering common method to read the data and assign the business_units.

api_uri

the uri of the json source providing the data

get_instances

Return a sequence of namedtuples storing the hydraulic hardware data

_get_dimensional_records_as_tuple

Return a tuple of dictionaries storing dimensional data

property get_instances

Return a sequence of namedtuples storing the hydraulic hardware data.

Returns

the sequence of namedtuples with the data. Each inheritor has a specific namedtuple.

Return type

Tuple[Namedtuple]

Example

DriveheadLoader will return a tuple of manufacturers.components.Drivehead ShaftLoader will return a tuple of manufacturers.components.Shaft

class business.manufacturers.readers.DriveheadLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

Adapter from a json source of progressive cavity pump driveheads.

_component_class

the dataclass use to represent progressive cavity pump drivehead

class business.manufacturers.readers.EngineCheckLoader(api_uri: str)

Bases: business.manufacturers.readers.EngineLoader

class business.manufacturers.readers.EngineDesignLoader(api_uri: str)

Bases: business.manufacturers.readers.EngineLoader

class business.manufacturers.readers.EngineLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

Adapter from a json source of diesel engines.

_component_class

the dataclass use to represent diesel engine

class business.manufacturers.readers.PipeCheckLoader(api_uri: str)

Bases: business.manufacturers.readers.PipeLoader

class business.manufacturers.readers.PipeDesignLoader(api_uri: str)

Bases: business.manufacturers.readers.PipeLoader

class business.manufacturers.readers.PipeLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

class business.manufacturers.readers.ProgressiveBodyCheckLoader(api_uri: str)

Bases: business.manufacturers.readers.ProgressiveBodyLoader

class business.manufacturers.readers.ProgressiveBodyDesignLoader(api_uri: str)

Bases: business.manufacturers.readers.ProgressiveBodyLoader

class business.manufacturers.readers.ProgressiveBodyLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

Adapter from a json source of progressive cavity pump bodies.

_component_class

the dataclass use to represent progressive cavity pump body

class business.manufacturers.readers.RiserPipeCheckLoader(api_uri: str)

Bases: business.manufacturers.readers.PipeLoader

class business.manufacturers.readers.RiserPipeDesignLoader(api_uri: str)

Bases: business.manufacturers.readers.PipeLoader

class business.manufacturers.readers.ShaftCheckLoader(api_uri: str)

Bases: business.manufacturers.readers.ShaftLoader

class business.manufacturers.readers.ShaftDesignLoader(api_uri: str)

Bases: business.manufacturers.readers.ShaftLoader

class business.manufacturers.readers.ShaftLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

Adapter from a json source of progressive cavity pump shafts.

_component_class

the dataclass use to represent progressive cavity pump shaft

class business.manufacturers.readers.SubmersibleCheckLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

class business.manufacturers.readers.SubmersibleDesignLoader(api_uri: str)

Bases: business.manufacturers.readers.BaseComponentLoader

business.manufacturers.readers.hydraulic_hardware_patch_attempt(api_uri)

business.manufacturers.services module

Collection of uri’s used to access the hydraulic hardware json data.

business.manufacturers.services.PERSISTENCE_HOST = '127.0.0.1:8000'

Prescribes the root url of the persistent data.

business.manufacturers.services.get_persistence_host()

Fake and temporary.

business.manufacturers.services.get_server_settings()
business.manufacturers.services.hydraulic_hardware_apis = {'bodies': 'http://127.0.0.1:8000/api/bodies/', 'bores': 'http://127.0.0.1:8000/api/bores/', 'carbon_pipes': 'http://127.0.0.1:8000/api/carbon_pipes/', 'combinations': 'http://127.0.0.1:8000/api/combinations/', 'driveheads': 'http://127.0.0.1:8000/api/driveheads/', 'engines': 'http://127.0.0.1:8000/api/engines/', 'materials': 'http://127.0.0.1:8000/api/materials/', 'pipes': 'http://127.0.0.1:8000/api/pipes/', 'plants': 'http://127.0.0.1:8000/api/plants/', 'polyethylene_pipes': 'http://127.0.0.1:8000/api/polyethylene_pipes/', 'riser_assemblies': 'http://127.0.0.1:8000/api/riser_assemblies/', 'shafts': 'http://127.0.0.1:8000/api/shafts/', 'steel_pipes': 'http://127.0.0.1:8000/api/steel_pipes/', 'submersibles': 'http://127.0.0.1:8000/api/submersibles/'}

Prescribes the url of hydraulic hardware catalogs.

business.manufacturers.services.mocked_persistence_host(*args, **kwargs)

business.manufacturers.utils module

Define an ancestor class common to hydraulic hardware dataclasses.

class business.manufacturers.utils.MonostateMixin

Bases: object

Add the monostate pattern to instances of dataclass.

property adopt

Return a copy of the dataclass instance.

After this method is called, the newly created instace will trigger its __post_init__ method to recreate the Rating instances.

Example

The following code: `new_engine = engine.adopt()` entails that <new_engine> will receive a copy of <rating_data> with which will create its own instance of EngineRating.

business.station package

Design and check projects of water supplies fed from a borehole.

Classes

  • ElectricCheck:

    models the ‘hydraulic check problem’ for an ‘electric station’ water supply.

  • ElectriclessCheck:

    models the ‘hydraulic check problem’ for an ‘electricless station’ water supply.

  • ElectricDesign:

    models the ‘hydraulic design problem’ for an ‘electric station’ water supply.

  • ElectriclessDesign:

    models the ‘hydraulic design problem’ for an ‘electricless station’ water supply.

Subpackages

business.station.arrangements package
Submodules
business.station.arrangements.base module

Define a borehole-to-reservoir pump station, common to:

  • both the hydraulic design and hydraulic check problems,

  • both electric and electricless stations.

class business.station.arrangements.base.Station(**kwargs)

Bases: business.commons.loggers.InitLogger

A class used to represent a pump station.

business.station.arrangements.check module

Define the ‘hydraulic check problem’ for a ‘station’ water supply .

Separate classes are provided for the electric station and the electricless station.

class business.station.arrangements.check.ElectricCheck(**kwargs)

Bases: business.station.solvers.base.StationMixin, business.station.solvers.check.ElectricCheckAlgorithmsMixin, business.station.views.reports.ElectricCheckReportMixin, business.tests.station.utils.ElectricCheckTestMixin, business.station.views.plots.ElectricCheckPlotMixin, business.station.arrangements.check.StationCheck

A class to represent an electric pumpstation when solving the hydraulic check problem.

The physical system is composed as follows: * a borehole * an electric submersible pump * a feeder pipeline from the borehole until a water storage reservoir

class business.station.arrangements.check.ElectriclessCheck(**kwargs)

Bases: business.station.solvers.base.StationMixin, business.station.solvers.check.ElectriclessCheckAlgorithmsMixin, business.station.views.reports.ElectriclessCheckReportMixin, business.station.views.plots.ElectriclessCheckPlotMixin, business.tests.station.utils.ElectriclessCheckTestMixin, business.station.arrangements.check.StationCheck

A class to represent pumpstation that works without electric power, when solving the hydraulic check problem.

The physical system is composed as follows: * a borehole * a positive displacement pump * a powertrain: (diesel engine, clutch, vee-belts, drivehead and pump shaft) * a feeder pipeline from the borehole until a water storage reservoir

property combination
property engine
property pump_depth
class business.station.arrangements.check.StationCheck(**kwargs)

Bases: business.station.arrangements.base.Station

A pumpstation defined to solve the hydraulic check problem, ancestor of classes specific to electric and electricless pumpstations.

xxx

xxx

Type

Xxx

business.station.arrangements.design module

Define the ‘hydraulic design problem’ for a ‘station’ water supply .

Separate classes are provided for the electric station and the electricless station.

class business.station.arrangements.design.ElectricDesign(**kwargs)

Bases: business.station.solvers.design.ElectricDesignAlgorithmsMixin, business.station.views.reports.ElectricDesignReportMixin, business.tests.station.utils.ElectricDesignTestMixin, business.station.arrangements.design.StationDesign

Represent the electric pump station in the hydraulic design process.

The physical system is composed as follows: * a borehole * an electric submersible pump * a feeder pipeline from the borehole until a water storage reservoir

DesignSolutionDetails

alias of ElectricDesignSolutionDetails

class business.station.arrangements.design.ElectriclessDesign(**kwargs)

Bases: business.station.solvers.base.StationMixin, business.station.solvers.design.ElectriclessDesignAlgorithmsMixin, business.station.views.reports.ElectriclessDesignReportMixin, business.tests.station.utils.ElectriclessDesignTestMixin, business.station.arrangements.design.StationDesign

A class to represent pumpstation that works without electric power, when solving the ‘hydraulic design problem’.

The physical system is composed as follows: * a borehole * a positive displacement pump * a powertrain: (diesel engine, clutch, vee-belts, drivehead and pump shaft) * a feeder pipeline from the borehole until a water storage reservoir

Note

There is no __init__ (unlike in ElectricDesign); why? Remarks ——- Becasue electric and electricless designs differ in what follows:

In an electric arrangement, the borehole riser is a ‘standard’ pipe (albeit metallic, sturdy), so the pipeline is made of two sections in series: the borehole riser and the feeder.

In an electricless arrangement, the borehole riser is part of the pump becasue the riser includes the pump shaft (which pertrbates the hydraulic friction), so the pipeline is made of two sections in series: the pump (its riser section) and the feeder.

DesignSolutionDetails

alias of ElectriclessDesignSolutionDetails

class business.station.arrangements.design.StationDesign(**kwargs)

Bases: business.station.arrangements.base.Station

A pumpstation defined to solve the hydraulic check problem, ancestor of classes specific to electric and electricless pumpstations.

business.station.mixins package
Submodules
business.station.mixins.interpolation module

Collection of mixins to interpolate hydraulic enrgy points along station feeders.

class business.station.mixins.interpolation.PointFactoryMixin

Bases: object

get_point_at_given_pathlength(pathlength)
business.station.mixins.traversals module
class business.station.mixins.traversals.SgrMockSimplexSoilStretchMixin

Bases: object

property energy_at_head_point
property energy_at_tail_point
property pathlength
class business.station.mixins.traversals.SgrTraversalSoilStretchMixin

Bases: object

Mixin gathering the methods to evaluate the most economical feeder coupled to a submersible pump.

traversal_sgr()

Return the most economical sequence of piped segments INGLESE constrained to: * a given _water_flow * a given water energy * a given sequence of soil requirements INGLESE

best_from_collect_ranges(list_of_lists)

Return the most economical piped sequence from those that complied with the energy constraints.

This method receives data from the ‘sink’

Returns

TODO

Return type

TODO

property traversal_sgr
business.station.mixins.traversals.check_self_has_smooth_elevation_profile(function)

Checks that the elevation profile along the soil stretch is ‘smooth enough’ that QUALE E’ LA LOGICA?

business.station.mixins.traversals.mock_temporarily_with_single_simplex(function)

Replace temporarily the decorated method with _mock_simplex.

business.station.solvers package

The purpose of a pump is to overcome elevation differences and head losses due to pipe friction. The amount of head the pump must add to overcome elevation differences is dependent on system characteristic and topology (and independent of the pump discharge rate), and is referenced to as static head or static lift. Friction and minor losses, however, zre highly dependent on the rate of discharge through the pump. When these losses are added to the static head for a series of discharge rates, the resulting plot is called a system head curve. The pump characteristic curve is a function of the pump and independent of the system, while the system head curve is dependent on the system and is independent of the pump. Unlike the pump curve, which is fixed for a given pump at a given speed, the system head curve slides up and down as the design flow changes / as different demands are chosen to for the design flow. Rather than there being a unique system head curve, a family of system head curves forms a band on the graph.

Submodules
business.station.solvers.base module

Colletion of mixins common to solving both the ‘hydraulic design and ‘hydraulic check’ problems.

class business.station.solvers.base.ElectricMixin

Bases: object

Placeholder for future methods common to design and check problems.

class business.station.solvers.base.ElectriclessMixin

Bases: object

Placeholder for future methods common to design and check problems.

class business.station.solvers.base.StationMixin

Bases: object

water_flow(Quantity("volume/time"))

Get or set the water flow of the pumpstation instance

property get_hydraulic_energy_excluding_riser_friction

Return the hydraulic energy required by the pumpstation without considering the friction energy loss in the riser.

This method is useful when dealing with progressive displacement pumps, because they require a two-step calculation: * first, the pump body is selected * then, the pump body dictates the shaft and therefore a correction to the riser friction, which is due to the shaft and could not be evaluated before the pump doby had been selected in the previous step.

Note

Precondition: The hardware is set: the pump depth, the _piped_segments in the feeder, the pump and the riser assembly.

property water_flow
business.station.solvers.check module

Collection of mixins that help solving the ‘hydraulic check problem’ for ‘station’ water supplies.

Separate classes are provided for the electric station and the electricless station.

class business.station.solvers.check.ElectricCheckAlgorithmsMixin

Bases: object

Algorithms for the check problem of an electric pumpstation.

solve_hydraulic_check_problem

solve the ‘hydarulic check problem’ and set the results in the calculations report.

property get_hydraulic_energy_at_wellhead
property solve_hydraulic_check_problem

Solve the ‘hydarulic check problem’.

Note

This is a fixed pump speed solution, so it differs from that of the ‘electricless’ problem, whch deals instead with variable speed pumping.

When the pump head discharge curve and the system head curve are plotted on the same axes, only one point lies on both the pump characteristic curve and the system head curve. The point where the two curves intersect, the operating point, is the actual combination of discharge and energy head that will be produced by the pump when insatlled in that piping system.

The problem is solved by finding the intersection between the system resititve curve (hydraulic energy required by the borehole and the pipeline) and the pump delivery curve.

The results are stored into the _calculations_report attribute and in the plots generated through the process.

Note

Precondition: The user interface (through javascript) ensures that the input data were provided.

class business.station.solvers.check.ElectriclessCheckAlgorithmsMixin

Bases: object

Algorithms for the check problem of a pumpstation that makes no use of electric power.

solve_hydraulic_check_problem

solve the ‘hydarulic check problem’ and set the results in the calculations report.

property solve_hydraulic_check_problem

Solve the ‘hydarulic check problem’.

Note

This is a variable pump speed solution, so it differs from that of the ‘electric’ problem, whch deals instead with fixed speed pumping.

The problem is solved by evaluating the pumpstation duty point and working conditions for every rotation speed of the engine.

The results are stored into the _calculations_report attribute and in the plots generated through the process.

Note

Precondition: The user interface (through javascript) ensures that the input data were provided.

business.station.solvers.design module

Collection of mixins that help solving the ‘hydraulic design problem’ for ‘station’ water supplies.

Separate classes are provided for the electric pumpstation and for the one without use of energy.

class business.station.solvers.design.ElectricDesignAlgorithmsMixin

Bases: business.station.solvers.base.ElectricMixin, business.station.plots.ElectricPlotMixin, business.station.reports.ElectricReportMixin

Algorithms for the check problem of an electric pumpstation.

solve_hydraulic_design_problem

solve the hydarulic design problem considering the current water flow and set the results in the calculations report

property solve_hydraulic_design_problem
class business.station.solvers.design.ElectriclessDesignAlgorithmsMixin

Bases: business.station.solvers.base.ElectriclessMixin, business.station.plots.ElectriclessPlotMixin, business.station.reports.ElectriclessReportMixin

Algorithms for the check problem of a pumpstation that does not make use of electric power.

Perform the ‘systematic search’ to optimize the ‘hydraulic design problem’.

property solve_hydraulic_design_problem

Submodules

business.station.adapters module

class business.station.adapters.SoilStretchAdapter(_stretches: Tuple[business.station.soils.SoilStretch])

Bases: object

cleaned_data()

business.station.climb module

class business.station.climb.ClimbStretch(_climbing_sequence: List[business.station.climb.ClimbingSegment], _soil_stretch: business.station.soils.SoilStretch, _pressure_limit: pint.quantity.build_quantity_class.<locals>.Quantity, _head_point: business.commons.energy.EnergyProfilePoint)

Bases: business.commons.loggers.InitLoggerMixin, business.station.plots.PlotClimbStretchMixin

property get_valid_pressure_pathlength
property recursive_climb
roba()
class business.station.climb.ClimbingConduit(iterable=(), /)

Bases: list

append(item)

Append object to the end of the list.

property as_piped_segments

Convert a ClimbingConduit into the corresponding tuple of PipedSegment’s.

property cost
class business.station.climb.ClimbingConduitsCollector(*args, **kwargs)

Bases: list

Implemented without extending business_utils.TypedList since TypedList extends collections.MutableSequence and makes the use of core_utils.Singleton unfeasible (due to metaclass conflict between Singleton and MutableSequence).

append(item)

Append object to the end of the list.

class business.station.climb.ClimbingSegment(pathlength, commercial_pipe)

Bases: tuple

Represent a segment of the feeder, with a given pipe and a given length. Used when solving the ‘hydraulic design problem’, to optmize the feeder with a systematic search approach.

property commercial_pipe

Alias for field number 1

property pathlength

Alias for field number 0

class business.station.climb.FeederClimbMixin

Bases: object

property get_candidate_conduits_list

the data structure must be must be a ‘list of lists’.

Type

Remark

business.station.climb.check_commercial_pipes_are_available(function)

business.station.constants module

Collection of constants used by the pumpstation foldes.

business.station.constants.RANDOM_SEARCH_RANGE_PAD = <Quantity(2, 'meter')>

Prescribes the minimal hydraulic energy to be burned along a Trunk during feeder random search. This value magnitude is expected to be an integer.

business.station.constants.RANDOM_SEARCH_RANGE_STEP = <Quantity(10, 'meter')>

Prescribes the difference of hydraulic energy between two successive attempts during feeder random search. This value magnitude is expected to be an integer.

business.station.coroutines module

class business.station.coroutines.AutomatedTypedList(ok_type, iterable=[])

Bases: business.helpers.utils.TypedList

property best_from_collect_ranges
class business.station.coroutines.CoroutineLeaf(soil_stretch: business.station.soils.SoilStretch, name: str, down_elev: int)

Bases: business.commons.loggers.InitLoggerMixin

down_elev: int
merger()
name: str
send(arg)
soil_stretch: business.station.soils.SoilStretch
class business.station.coroutines.CoroutineNode(soil_stretch: business.station.soils.SoilStretch, name: str, down_flight: int, next_coro_object: business.station.soils.SoilStretch)

Bases: business.commons.loggers.InitLoggerMixin

static best_from_collect_ranges(list_of_lists)
down_flight: int
static is_failed(child_simplex)
merger()
name: str
next_coro_object: business.station.soils.SoilStretch
send(arg)
soil_stretch: business.station.soils.SoilStretch
class business.station.coroutines.CoroutineReturn

Bases: business.helpers.utils.TypedList

property is_failed
class business.station.coroutines.CoroutineRoot(riser: business.station.riser.RiserDesign, name: str, down_flight: int, next_coro_object: business.station.soils.SoilStretch)

Bases: business.commons.loggers.InitLoggerMixin

static best_from_collect_ranges(list_of_lists)

Remark: this method could be turned into a @staticmethod. However, the self is used for logging purposes.

down_flight: int
static is_failed(child_simplex)

Remark: this method could be turned into a @staticmethod. However, the self is used for logging purposes.

merger()
name: str
next_coro_object: business.station.soils.SoilStretch
riser: business.station.riser.RiserDesign
set_hydraulic_energy_at_submersible_outlet(value)

business.station.defaults module

business.station.definitions module

class business.station.definitions.FeederSegment(piped_segments=None, penalty=None)

Bases: tuple

Represent a segment of the feeder, with a given pipe and a given length. Used when solving the ‘hydraulic design problem’, to optmize the feeder with a systematic search approach.

property penalty

Alias for field number 1

property piped_segments

Alias for field number 0

class business.station.definitions.StationCheckSolution(check_is_completed: str = None, solution: str = None, economic_cost: str = None)

Bases: object

Represent a report of the hydraulic check problem in a station.

Applies to both electric and electriless stations, and these station provide their customised values of fields ‘solution’ and ‘economic_cost’.

check_is_completed: str = None
economic_cost: str = None
property engine_power_curve_as_matplotlib
solution: str = None
class business.station.definitions.StationDesignSolution(check_is_completed: str = None, solution: str = None, economic_cost: str = None)

Bases: object

Represent a report of the hydraulic check problem in a station.

Applies to both electric and electriless stations, and these station provide their customised values of fields ‘solution’ and ‘economic_cost’.

check_is_completed: str = None
economic_cost: str = None
solution: str = None

business.station.exceptions module

exception business.station.exceptions.DemandMissing

Bases: business.commons.exceptions.ImproperlyConfiguredWaterSystem

The water demand is unknown.

exception business.station.exceptions.DesignAtFixedFlowFailed(message, TODO_some_hint='TODO')

Bases: business.station.exceptions.StationDesignUnfeasible

The ‘hydraulic design problem’ could not be solved for a given value of the water flow.

exception business.station.exceptions.ForceMainDemandDataMissing

Bases: business.commons.exceptions.RuralwaterException

The feeder has no water demand data associated with it.

Raised when running the ‘hydraulic design problem’: if water demand data are absent then the ‘hydraulic design problem’ cannot be solved because it is unknown for how much water the pumpstation must be designed.

exception business.station.exceptions.ImproperlyConfiguredPumpingStation

Bases: business.commons.exceptions.ImproperlyConfiguredWaterSystem

Some data needed to solve the hydraulic design/check problem for a pumping station were not provided by the user.

exception business.station.exceptions.NonsensicalSoilSectionsData

Bases: business.commons.exceptions.RuralwaterException

A file can be read but the data make no logical sense.

exception business.station.exceptions.StationCheckUnfeasible

Bases: business.commons.exceptions.RuralwaterException

The hydraulic check problem has a ‘does not work’ solution.

The station cannot be used in this case: the prime mover will not start. This exception is common to ‘electric’ and ‘electricless’ stations, which means both to fixed speed and variable speed pumping.

exception business.station.exceptions.StationDesignUnfeasible

Bases: business.commons.exceptions.RuralwaterException

The ‘hydraulic design problem’ has a ‘does not work’ solution.

The station cannot be used in this case: the prime mover will not start. This exception is common to ‘electric’ and ‘electricless’ stations, which means both to fixed speed and variable speed pumping.

exception business.station.exceptions.UnadvisablePcdArrangement

Bases: business.station.exceptions.UnadvisablePumpStationArrangement

UnadvisableDuty operating conditions in the electricless pump station.

Raised when setters of the components of the electricless pump station raise unsadvisable conditions.

Example

  • the plant’s borehole is set a flow exceeding its maximum abstraction

license. * the plant’s treatment facility is set a flow exceeding the facility capacity.

exception business.station.exceptions.UnadvisablePumpStationArrangement

Bases: business.commons.exceptions.UnadvisableDuty

UnadvisableDuty operating conditions in the pump station.

business.station.feeder module

class business.station.feeder.FeederBaseMixin(**kwargs)

Bases: business.commons.watermains.Watermain

property get_delta_elevation_wellhead_to_tank
Returns

  • Instance of helper.business_units.Q_,

  • expressed in helper.business_units.ELEVATION_UNITS.

  • Positive if water flows from a lower elevation to a higher.

  • This is usually the case of a feeder (the borehole wellhead)

  • is located at a lower elevation than the reservoir where the

  • feeder is dischargin into.

property get_hydraulic_friction

Return the energy burned off in the pipeline by the water flowing inside it at the rate set by water_flow and as a result of the current _piping_list

Note

Precondition: self._piped_segments are set and each pipe_segment has commercial pipe and start_at field set.

property water_flow

The water flow can never be set: * in the design problem, it is set by the head site demand and the daily workshift. * in the check problem it is evaluated by the ‘check’ calculations.

class business.station.feeder.FeederCheck(**kwargs)

Bases: business.station.feeder.FeederBaseMixin, business.commons.watermains.WatermainCheck

Represent the ‘hydraulic-check’ calculations in a feeder.

get_headloss_at_sample_flow(sample_water_flow)
class business.station.feeder.FeederDesign(**initkwargs)

Bases: business.commons.traversals.PipeDesignPoolMixin, business.station.soils.FeederSoilsMixin, business.station.climb.FeederClimbMixin, business.station.feeder.FeederBaseMixin, business.station.feeder.ShortFeederDesignMixin, business.commons.watermains.WatermainDesign

property get_daily_work_hours
property get_headmost_soil_stretch
property get_my_water_demand_as_steady_flow

Return the water flow required by the ‘hydraulic design problem’.

Return the steady flow, flowing continuously along the 24 hours of the day, which satisfies the water demand associated with the Feeder.

class business.station.feeder.ShortFeederDesignMixin

Bases: object

Algorithms to run first-guess calculations.

In a first gess calculation, the feeder of the pumpstation is considered ‘short’: under this assumption, the calcualtions do not need to consider the pressure classes in the feeder. Instead, the calculatins assume that the feeder may be designed with a unique diameter and with the lowest available pressure class.

This mixin is useful also in designing those pumpstations where the water is pumped from the borehole to a nearby reservoir.

business.station.initkwargs module

business.station.plots module

class business.station.plots.CheckProblemPlots

Bases: object

plot_something()
class business.station.plots.ElectricPlotMixin

Bases: business.station.plots.PlotAdaptersMixin

plot_check_problem_solution()
property plot_design_problem_solution
class business.station.plots.ElectriclessPlotMixin

Bases: business.station.plots.PlotAdaptersMixin

property plot_check_problem_solution
property plot_design_problem_solution
class business.station.plots.PlotAdaptersMixin

Bases: object

property get_max_design_flow_range
property get_min_design_flow_range
class business.station.plots.PlotClimbStretchMixin

Bases: object

plot_recursive_climb(single_pipe_energy_line, messaggio='climb')
plots_directory = 'plots'
plots_files_extension = 'png'
yield_integer = count(1)
business.station.plots.convert_to_adimensional(function)

business.station.profile module

class business.station.profile.FeederElevationProfile(iterable: Iterable = [])

Bases: business.station.mixins.interpolation.PointFactoryMixin, business.commons.energy.ElevationProfile

get_section_from_pathlength(from_pathlength)
get_section_inbetween_pathlengths(from_pathlength, until_pathlength)
class business.station.profile.SoilStretchElevationProfile(*args, **kwargs)

Bases: business.station.profile.FeederElevationProfile

property pathlength

Return the linear length of the hydraulic energy line.

Returns

a dimensional value

Return type

Quantity(“length”)

business.station.reports module

class business.station.reports.ElectricReportMixin

Bases: object

class business.station.reports.ElectriclessReportMixin

Bases: object

business.station.riser module

class business.station.riser.RiserCheck(pump_setting_magnitudo, commercial_pipe)

Bases: object

get_headloss_at_sample_flow(sample_water_flow)
class business.station.riser.RiserDesign

Bases: object

property get_burned_off_energy
property get_guessed_cost
property pathlength
property water_flow
property yield_single_diameter_solution

business.station.soils module

class business.station.soils.FeederSoilsMixin

Bases: object

precondition: ‘FeederDesign’ object has attribute ‘_elevation_profile’

class business.station.soils.SoilStretch(_elevation_profile: business.station.profile.FeederElevationProfile, _requires_metallic_pipes: bool, _water_flow: float, _previous_soil_stretch: Any = None)

Bases: business.commons.loggers.InitLoggerMixin, business.commons.mixins.linear.SingleLinprogStretchMixin, business.station.mixins.traversals.SgrMockSimplexSoilStretchMixin, business.commons.traversals.PipeDesignPoolMixin, business.commons.mixins.cost.PipesCostMixin, business.station.mixins.traversals.SgrTraversalSoilStretchMixin, business.commons.traversals.TraversalsTrunkOrStretchMixin

get_elevation_profile_from_tail_until_downrange(until_downrange)
property get_head_point_elevation
get_pathlength_inbetween_downranges(from_downrange, until_downrange)
get_rated_working_pressure(head_energy_point)
get_valid_pressure_pathlength(pressure_violation_point)

business.tests package

Submodules

business.tests.fixtures module

business.tests.run module

Submodules

business.loggers module

Module to handle logging of ruralwater. To be moved into ‘microservices’ package.

Functions

logger_factory

factory of loggers for each module

business.loggers.logger_factory(module_name)
Parameters

module_name (string) – the name of the module which is requesting an instance of logger.

Returns

The logger object from the standard python library.

Return type

logger

..see Section you want to reference for more detail

Indices and tables