A TypeScript library for designing drip irrigation systems. Calculate zone sizing, pressure loss, and timer schedules with hydraulic precision.
✅ Zone sizing – Calculate emitter counts and total flow based on plant water needs
✅ Hydraulic calculations – Pressure loss, velocity, and maximum run lengths using Hazen-Williams
✅ Pipe sizing – Automatically select appropriate pipe diameters for your flow requirements
✅ Multi-zone planning – Design complete irrigation systems with multiple zones
✅ Timer scheduling – Generate optimal watering schedules based on daily water requirements
✅ Type-safe API – Full TypeScript support with branded types for units (GPH, PSI, etc.)
# npm
npm install @adametherzlab/irrigation-planner
# bun
bun add @adametherzlab/irrigation-planner// REMOVED external import: import { calculateZone, PipeDiameter } from "@adametherzlab/irrigation-planner";
const zone = {
id: "vegetables",
name: "Vegetable Garden",
plants: [
{ name: "Tomato", waterNeed: 2 as GallonsPerDay, spacingFt: 3 },
{ name: "Pepper", waterNeed: 1.5 as GallonsPerDay, spacingFt: 2 }
],
emitter: {
model: "1 GPH",
flowRate: 1 as GallonsPerHour,
spacingFt: 1,
pressureRange: [15, 30] as [PSI, PSI]
},
pipeDiameter: PipeDiameter.HalfInch,
pipeLengthFt: 50
};
const result = calculateZone(zone, { emitterEfficiency: 0.9 });
console.log(`Zone needs ${result.emitterCount} emitters, total flow: ${result.totalFlowGph} GPH`);Parameters:
zone– Zone configuration with plants, emitter, and pipe detailsoptions– Optional calculation settings (emitter efficiency, operating hours)
Returns: ZoneCalculationResult with emitter count, total flow, and daily water volume
Example:
const result = calculateZone(zone, { emitterEfficiency: 0.9 });Parameters:
zones– Array of zone configurationsoptions– Calculation options applied to all zones
Returns: MultipleZoneResults with aggregated totals and individual zone results
Example:
const results = calculateMultipleZones([zone1, zone2], { operatingHoursPerDay: 12 });toZoneResult(zone: Zone, calculation: ZoneCalculationResult, hydraulics?: HydraulicResult): ZoneResult
Parameters:
zone– Original zone configurationcalculation– Zone calculation resultshydraulics– Optional hydraulic calculation results
Returns: ZoneResult compatible with the main types
Example:
const zoneResult = toZoneResult(zone, calculation, hydraulics);calculatePressureLoss(flowRateGph: number, diameterIn: number, roughnessCoefficient?: number): number
Parameters:
flowRateGph– Flow rate in gallons per hourdiameterIn– Pipe diameter in inchesroughnessCoefficient– Hazen-Williams C-factor (default: 150 for PVC)
Returns: Pressure loss in PSI per 100 feet
Example:
const loss = calculatePressureLoss(200, 0.75); // ~2.34 PSI/100ftParameters:
flowRateGph– Flow rate in gallons per hourdiameterIn– Pipe diameter in inches
Returns: Velocity in feet per second
Example:
const velocity = calculateVelocity(200, 0.75); // ~2.89 fpsParameters:
flowRateGph– Flow rate in gallons per houroptions– Pipe sizing options (max velocity, pressure loss limit)
Returns: Recommended pipe diameter from PipeDiameter enum
Example:
const diameter = selectPipeDiameter(500); // PipeDiameter.OneInchcalculateMaxRunLength(flowRateGph: number, diameterIn: number, inletPressurePsi: PSI, options?: PipeSizingOptions): number
Parameters:
flowRateGph– Flow rate in gallons per hourdiameterIn– Pipe diameter in inchesinletPressurePsi– Starting pressure at pipe inletoptions– Pipe sizing options
Returns: Maximum run length in feet
Example:
const maxLength = calculateMaxRunLength(200, 0.75, 50 as PSI); // ~2134 ftParameters:
input– Hydraulic input parameters (flow, diameter, length, inlet pressure)options– Pipe sizing options
Returns: HydraulicResult with pressure loss, velocity, and outlet pressure
Example:
const result = calculateHydraulics({
flowRateGph: 200,
pipeDiameterIn: 0.75,
pipeLengthFt: 100,
inletPressurePsi: 50 as PSI
});import {
calculateMultipleZones,
calculateHydraulics,
selectPipeDiameter,
PipeDiameter,
type Zone,
type PSI,
type GallonsPerDay,
type GallonsPerHour
} from "@adametherzlab/irrigation-planner";
// Zone 1: Vegetable garden
const vegetableZone: Zone = {
id: "zone1",
name: "Vegetables",
plants: [
{ name: "Tomato", waterNeed: 2 as GallonsPerDay, spacingFt: 3 },
{ name: "Lettuce", waterNeed: 1 as GallonsPerDay, spacingFt: 1 },
{ name: "Carrot", waterNeed: 0.8 as GallonsPerDay, spacingFt: 0.5 }
],
emitter: {
model: "1 GPH",
flowRate: 1 as GallonsPerHour,
spacingFt: 1,
pressureRange: [15, 30] as [PSI, PSI]
},
pipeDiameter: PipeDiameter.HalfInch,
pipeLengthFt: 75
};
// Zone 2: Fruit trees
const fruitZone: Zone = {
id: "zone2",
name: "Fruit Trees",
plants: [
{ name: "Apple", waterNeed: 10 as GallonsPerDay, spacingFt: 15 },
{ name: "Peach", waterNeed: 8 as GallonsPerDay, spacingFt: 12 }
],
emitter: {
model: "2 GPH",
flowRate: 2 as GallonsPerHour,
spacingFt: 2,
pressureRange: [20, 40] as [PSI, PSI]
},
pipeDiameter: PipeDiameter.ThreeQuarterInch,
pipeLengthFt: 120
};
// Calculate zone requirements
const results = calculateMultipleZones([vegetableZone, fruitZone], {
emitterEfficiency: 0.9,
operatingHoursPerDay: 6
});
console.log(`Total system flow: ${results.totalFlowGph} GPH`);
console.log(`Total daily water: ${results.totalDailyWaterGallons} gallons`);
// Check hydraulic performance for each zone
for (const zoneResult of results.zones) {
const hydraulics = calculateHydraulics({
flowRateGph: zoneResult.totalFlowGph,
pipeDiameterIn: zoneResult.zone.pipeDiameter,
pipeLengthFt: zoneResult.zone.pipeLengthFt,
inletPressurePsi: 45 as PSI
});
console.log(`${zoneResult.zone.name}: Outlet pressure ${hydraulics.outletPressurePsi.toFixed(1)} PSI`);
}// REMOVED external import: import { type TimerSchedule } from "@adametherzlab/irrigation-planner";
function createTimerSchedule(
totalFlowGph: number,
dailyWaterNeeded: number,
maxZonesPerController: number = 4
): TimerSchedule {
const hoursPerDay = dailyWaterNeeded / totalFlowGph;
const minutesPerZone = Math.ceil((hoursPerDay * 60) / maxZonesPerController);
return {
startTime: "06:00",
zoneDurations: Array(maxZonesPerController).fill(minutesPerZone),
daysOfWeek: [1, 3, 5, 7], // Monday, Wednesday, Friday, Sunday
totalDailyRuntimeMinutes: minutesPerZone * maxZonesPerController
};
}
// Example: 300 GPH system needing 1800 gallons daily
const schedule = createTimerSchedule(300, 1800);
console.log(`Water ${schedule.zoneDurations.length} zones for ${schedule.zoneDurations[0]} minutes each`);The library uses the Hazen-Williams equation for pressure loss calculations:
P = (4.52 * Q^1.85) / (C^1.85 * d^4.87)
Where:
P= Pressure loss (PSI per 100 feet)Q= Flow rate (gallons per hour)C= Hazen-Williams roughness coefficient (150 for new PVC pipe)d= Pipe diameter (inches)
Velocity is calculated as:
V = (0.4085 * Q) / d²
Where V is velocity in feet per second.
- Flow rates: Gallons per hour (GPH) for emitters and total flow
- Water needs: Gallons per day (GPD) for plant requirements
- Pressure: Pounds per square inch (PSI)
- Lengths: Feet for pipe runs and plant spacing
- Pipe diameters: Inches (½", ¾", 1", 1¼", 1½", 2")
- Time: Minutes for timer schedules, hours for operating durations
See CONTRIBUTING.md for development guidelines, code style, and pull request process.
MIT © AdametherzLab