WaDemEsT
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
This model simulates household water consumption patterns in an urban environment.
Its current setup compares monthly water consumption data, and the results of a daily heuristic water demand model with the simulation results produced by household demographics that is fine tuned via some base demand model.
It's designed to estimate and analyze water demand based on various factors including:
- Household demographics
- Daily routines of residents (working, weekending, vacation patterns)
- Weather conditions (temperature and precipitation)
- Appliance usage patterns
- Seasonal variations
- Special periods (weekends and holidays)
The model aims to help understand how different factors influence residential water consumption and can be used for water demand forecasting and management planning.
HOW IT WORKS
The model operates through several key mechanisms:
Here all of the key specifications would be explained briefly.
Spatial Environment:
- Creates a grid world representing residential areas, workplaces, and outside areas
- Households are represented by yellow patches
- Workplaces are represented by grey patches
- Other areas are represented by black patches
Population Dynamics:
Creates human agents with different characteristics:
Age groups (infants, school-age, adults, seniors) Movement patterns (outsiders, weekenders, vacationists)
Each household has a variable number of residents
Water Consumption Calculation:
Tracks usage of different water-consuming appliances:
- Taps
- Toilets
- Showers
- Washing machines
- Dishwashers
Calculates consumption based on:
- Number of occupants present
- Usage frequency
- Water efficiency rates
- Weather factors
- Day type (weekday/weekend/vacation)
Decision Procedure:
Decisions are taken under the effect of a few different procedures.
HOW TO USE IT
- WaDemEsT 1.0 requires you to load a CSV file that contains required information to handle some external simulation parameters. Current configuration of the CSV file is as shown below:
However you could easily drop out unwanted parameters from your CSV setup. Just don't forget to drop the related parts of the code corresponding to CSV variables that you cancelled.
- WaDemEsT 1.0 requires you to adjust certain parameters before producing simulations.
Those steps are shown above, and explained below starting from "Setting Simulation Environment" step. But "Simulation Controls" deserve mentioning beforehand:
Simulation Controls:
- Load Data - Load the CSV file with required time series data
- Setup - Initialize the simulation environment
- Clear All - Reset the entire simulation
- Restart Data - Restarts the data variables coming for CSV file, to prepare restarting the simulation
- Delete log - Deletes the log file refreshing the simulation memory
- Clear All - Reset the entire simulation
- Go-Data - Runs data alone for viewing the change of environmental conditions shown on "Simulation Starters" plot.
- Go-Once - just lets simulation environment to run along one tick only.
- Go-forever - lets simulation run till the end of the date value indicated on CSV file.
- Go-until - lets user to indicate a date to stop the simulation, to adjust parameters of the simulation,if needed.
Setting Simulation Environment
- householdSize - Average number of people per household
- varHHS - Variance in household size
- residenceRatio - Ratio of residential to non-residential areas
- Adjust residenceRatio (lets the simluation environment to be shaped as yellow and gray patches, so you can approximate the residental areas real conditions)
- Adjust the householdSize (you should give simulation an average number of inhabitants to fill the created houses)
- Adjust varHHS (Variance of average household number makes you able to indicate the extreme points in your household population such as single person or 4 or more people households)
Demographic Parameters:
- %Under5 - Percentage of population under 5 years
- %5&17 - Percentage of population between 5-17 years
- %Seniors - Percentage of senior population
- Set the rate of seniors via %Seniors slider (You should indicate the rate of people above 65)
- Set the rate of infants via %Under5 slider (This indicates the rate of children living dependent on mother's care, thus leads the rise of people staying home)
- Set the rate of students via %5%17 slider (This parameter lets you control the preference of people going outside during the weekdays)
Number of adults calculated subtracting the total numbers of groups above from the >total number of people set by the CSV file.
Appliance Performance and Usage Parameters:
- tapUse - Frequency of tap usage
- toiletUse - Frequency of toilet usage
- showerUse - Frequency of shower usage
- wmUse - Frequency of washing machine usage
dwUse - Frequency of dishwasher usage
Tap-Lt-m - Liters per minute for taps
Flush-Lt - Liters per toilet flush
Shower-Lt-m - Liters per minute for showers
WM-Lt - Liters per washing machine cycle
DW-Lt - Liters per dishwasher cycle
Behavioral Parameters:
- Outsiders - Proportion of people who leave for work
- Weekenders - Proportion of people who leave during weekends
- Vacationists - Proportion of people who leave during vacations
Rates of the people going outside for different calendar day types, should be indicated via respective sliders.
All preferences could be dynamically adjusted during the simulation time. Only thing to consider for calculation consistency, just avoid changing sliders
without stopping the simulation, to make sure producing correct results.
Output Options:
- print-to-logfile? - Toggle logging to file
- print-to-output? - Toggle console output
THINGS TO NOTICE
Consumption Patterns:
- Observe how water consumption varies between weekdays and weekends
- Notice the impact of vacations on overall consumption
- Watch for seasonal patterns in water usage
Population Movement:
- Track how people move between homes, workplaces, and outside areas
- Observe the effect of weather on movement patterns
Visualization:
Multiple plots showing different aspects of water consumption:
- Daily consumption patterns
- Monthly trends
- Weekly variations
- Appliance-specific usage
Weather Effects:
- Notice how temperature and precipitation affect behavior and consumption
- Observe seasonal variations in water usage patterns
THINGS TO TRY
Demographic Experiments:
- Adjust household size and variance to see impact on consumption
- Modify age group distributions and observe changes
- Change the ratio of outsiders/weekenders/vacationists
Appliance Usage Scenarios:
- Modify appliance efficiency parameters
- Adjust usage frequencies
- Compare impact of different appliances on total consumption
Weather Impact Analysis:
- Run simulation during different seasons
- Compare consumption patterns during extreme weather conditions
- Analyze how precipitation affects outdoor water usage
Special Period Analysis:
- Compare weekday vs weekend consumption
- Analyze holiday period water usage
- Study vacation period patterns
EXTENDING THE MODEL
Additional Features:
- Add water pricing mechanisms
- Implement water conservation behaviors
- Include commercial water usage
- Add water supply constraints
- Implement emergency scenarios
Enhanced Demographics:
- Add income levels
- Include cultural factors
- Implement household types (apartments, houses)
- Add social network effects
Environmental Factors:
- Include humidity effects
- Add seasonal activities
- Implement drought conditions
- Add water quality factors
Behavioral Patterns:
- Add learning behaviors
- Implement conservation awareness
- Include peer influence
- Add policy response behaviors
RELATED NETLOGO MODELS
- SequentialtimeseriesusingCSV by Doug Edmunds (Author) https://modelingcommons.org/browse/onemodel/4990#modeltabsbrowse_info
CREDITS AND REFERENCES
Author: Kamil AYBUĞA 2024
Key References:
- Edmunds, Doug (2017). TimeSeries-core.nlogo v1.5
- Wilensky, U. (1999). NetLogo. http://ccl.northwestern.edu/netlogo/. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
Model code and documentation developed using NetLogo 6.4.0.
Comments and Questions
extensıons [csv] ;; Import the CSV extension for handling data files globals [ ;; Define global variables accessible throughout the model data ;; Stores the dataset read from a CSV file data-source ;; Specifies the file path or source of the data data-pointer ;; Tracks the current position in the dataset data-length ;; Holds the total number of data entries data-date ;; Stores the date information for data entries (e.g., "01.01.2020") DayofYear ;; Represents the day number in a year (1-365 or 1-366 for leap years) DayofMonth ;; Represents the day number in a month (1-31) Month ;; Stores the month number (1-12) Week ;; Stores the week number of the year data-weekday ;; Stores the day of the week (e.g., Monday, Tuesday) data-vacation ;; Indicates if the day is a vacation day (e.g., "none", "weekend", or another label) data-temp ;; Stores temperature data for each day data-prcp ;; Stores precipitation data for each day data-housesMonthly ;; Tracks the number of houses per month from the CSV data-popMonthly ;; Tracks the population per month from the CSV data-totalMonthly ;; Stores the total consumption per month from the CSV HeuristicMonthlyTotal ;; Stores heuristic estimates for monthly total consumption from the CSV data-avgDaily ;; Stores the average daily consumption from the CSV HeuristicDailyTotal ;; Stores heuristic estimates for daily total consumption from the CSV AverageWeekly ;; Stores the average weekly consumption from the CSV HeuristicWeekly ;; Stores heuristic estimates for weekly consumption from the CSV fwcf ;; Represents the weather correction factor (float) from the CSV file number-of-humans ;; Stores the total number of humans in the model number-of-houses ;; Stores the total number of houses in the model remaining ;; Tracks the remaining number of houses to be added into the world in each simulation time workingPeople ;; Stores the count of working individuals (i.e., is-outsider?) vacationistPeople ;; Stores the count of vacationists weekenderPeople ;; Stores the count of people who go outside on weekends num-under5 ;; Stores the number of children under 5 years old num-5&17 ;; Stores the number of children aged 5 to 17 num-seniors ;; Stores the number of senior citizens (e.g., > 65) num-adults ;; Stores the number of adults (e.g., 18-65) num-singles ;; Stores the number of single individuals num-2adults ;; Stores the number of households with two adults num-1parent+child ;; Stores the number of single-parent households with children start-res ;; Represents the number of starting residents on each tick water-consumption ;; Stores the total water consumption of the district at each tick worldSize ;; Stores the size of the simulated world (used to calculate worldDmnsn) worldDmnsn ;; Stores the dimensions of the simulated world (sqrt of worldSize) logfile ;; Stores the log file name or path previous-outsiders ;; Stores the count of outsiders from the previous period previous-weekenders ;; Stores the count of weekenders from the previous period previous-vacationists ;; Stores the count of vacationers from the previous period temp-outsiders ;; Temporary storage for outsider ratio temp-weekenders ;; Temporary storage for weekender ratio temp-vacationists ;; Temporary storage for vacationist ratio temp-change-active? ;; Flag indicating whether a temporary ratio change is active temp-change-pending? ;; Flag indicating whether a temporary ratio change is scheduled (waiting to start) temp-change-start-tick ;; The tick at which the temporary ratio change started temp-change-end-tick ;; The tick at which the temporary ratio change ends daily-consumption ;; Tracks daily water consumption monthly-consumption ;; Tracks monthly water consumption weekly-consumption ;; Tracks weekly water consumption yearly-consumption ;; Tracks yearly water consumption (if needed) data-loaded? ;; Indicates if data has been loaded successfully simulation-start-date ;; Numerical representation of the start date from CSV simulation-end-date ;; Numerical representation of the end date from CSV current-month ;; Tracks the current month (for aggregating monthly consumption) current-week ;; Tracks the current week (for aggregating weekly consumption) current-data-index ;; An index to navigate through unique months/weeks if needed unique-custom-months ;; A list of unique "custom months" (if used) unique-months ;; A list of unique months read from CSV unique-weeks ;; A list of unique weeks read from CSV current-custom-month ;; Tracks a custom month index if needed unique-custom-weeks ;; A list of unique "custom weeks" if used average-monthly-consumption ;; Average monthly consumption (running average over the simulation) average-weekly-consumption ;; Average weekly consumption (running average over the simulation) average-daily-consumption ;; Average daily consumption (running average over the simulation) monthly-consumption-list ;; A list collecting monthly consumption values weekly-consumption-list ;; A list collecting weekly consumption values daily-consumption-list ;; A list collecting daily consumption values total-water-consumption ;; Accumulated water consumption since start of sim weekday-consumption ;; Water consumption recorded for weekdays weekend-consumption ;; Water consumption recorded for weekends vacation-consumption ;; Water consumption recorded for vacation days weekday-consumption-total ;; Total water consumption for all weekdays so far weekend-consumption-total ;; Total water consumption for all weekends so far vacation-consumption-total ;; Total water consumption for all vacation days so far weekday-count ;; Number of weekday ticks encountered so far weekend-count ;; Number of weekend ticks encountered so far vacation-count ;; Number of vacation-day ticks encountered so far avg-weekday-consumption ;; Average consumption for weekdays avg-weekend-consumption ;; Average consumption for weekends avg-vacation-consumption ;; Average consumption for vacation days ] breed [humans human] ;; Define a "humans" breed of turtles humans-own [ age house workplace category education-age clmt-strtgy daily-strtgy status is-outsider? is-weekender? is-vacationist? ] patches-own [ hhs ;; The number of humans (household size) associated with a patch working ;; Number of "working" humans in that patch employees ;; Possibly used to store employees in that patch income ;; Household income or patch-level income if used hhtype ;; String describing patch type: "outside", "household", "workplace" avgHHAge ;; Average household age lvng-strtgy ;; Lifestyle strategy placeholder eat-strategy ;; Eating strategy placeholder clean-strategy ;; Cleaning strategy placeholder maintenance-strategy;; Maintenance strategy placeholder water-cnsmptn ;; Total water consumption in that patch tap-water ;; Water consumption from tap usage dw-water ;; Water consumption from dishwasher usage wm-water ;; Water consumption from washing machine usage toilet-water ;; Water consumption from toilet flushing shower-water ;; Water consumption from shower usage tap-use ;; Frequency or usage intensity for tap dw-use ;; Frequency or usage intensity for dishwasher wm-use ;; Frequency or usage intensity for washing machine toilet-use ;; Frequency or usage intensity for toilet shower-use ;; Frequency or usage intensity for shower eat-and-drink-water ;; Subtotal consumption for eating/drinking cleaning-water ;; Subtotal consumption for cleaning maintenance-water ;; Subtotal consumption for maintenance insiders ;; Number of "insider" humans in this patch dw-load ;; A running counter to track when a dishwasher load is triggered wm-load ;; A running counter to track when a washing machine load is triggered weekender ;; A counter or flag for weekenders in this patch vacationist ;; A counter or flag for vacationists in this patch tap-eat-drink ;; Detailed breakdown of tap usage for eating/drinking tap-clean-up ;; Detailed breakdown of tap usage for cleaning tap-maintenance ;; Detailed breakdown of tap usage for maintenance dw-eat-drink ;; Detailed breakdown of dishwasher usage for eating/drinking dw-clean-up ;; Detailed breakdown of dishwasher usage for cleaning wm-clean-up ;; Detailed breakdown of washing machine usage for cleaning wm-maintenance ;; Detailed breakdown of washing machine usage for maintenance ] ; ===== SETUP PROCEDURES ===== to setup ;; Primary setup procedure. Calls various sub-setup procedures only if data is loaded. ifelse data != 0 and data != false [ ;; Only proceed if 'data' is not empty or false. This checks if the user has loaded CSV data. clear-all-plots clear-patches clear-turtles clear-drawing clear-all-plots reset-ticks ;; Initialize simulation environment set-globals set-the-world set-the-household setup-human-types ;; Set up data tracking variables set data-length length data set current-data-index 0 set current-month 0 set current-week 0 set monthly-consumption 0 set weekly-consumption 0 set total-water-consumption 0 ;; Initialize consumption tracking counters set weekday-consumption-total 0 set weekend-consumption-total 0 set vacation-consumption-total 0 set weekday-count 0 set weekend-count 0 set vacation-count 0 ;; Initialize consumption tracking lists set monthly-consumption-list [] set weekly-consumption-list [] set daily-consumption-list [] ;; Set up logging set logfile "simulation_log.txt" ;; Default log file name ;; Extract simulation date range from data (the first and last rows) if not empty? data [ set simulation-start-date date-to-number item 0 (item 0 data) set simulation-start-date date-to-number item 0 (item 0 data) set simulation-end-date date-to-number item 0 (last data) set unique-months remove-duplicates map [d -> extract-month item 0 d] data set unique-weeks remove-duplicates map [d -> extract-week item 0 d] data ] ;; setup-water-consumption-plots (if you have a separate procedure for that) set simulation-start-date date-to-number (item 0 (item 0 data)) ;; Convert first row's date to a number set simulation-end-date date-to-number (item 0 (last data)) ;; Convert last row's date to a number ;; Initialize temporary change tracking set temp-change-active? false set temp-change-pending? false set temp-change-start-tick 0 set temp-change-end-tick 0 ;; Store initial population ratios set previous-outsiders Outsiders set previous-weekenders Weekenders set previous-vacationists Vacationists ;; Update population ratios once at the start update-population-ratios output-print "Simulation environment has been set up succesfully." ] [ user-message "Please first load the data using 'Load Data' button." ] end ; ===== DATA LOADING AND MANAGEMENT ===== to startup ;; This procedure runs automatically when the model is first opened. We initialize empty data structures. set data [] set data-length 0 set data-loaded? false end to Data-Load ;; Called from a button to load a CSV file. Uses the NetLogo 'carefully' to catch any errors during file operations. carefully [ let file user-file ifelse file != false [ ;; If the user selected a file: ;; Check if file is CSV format by checking the last 4 chars ifelse (substring file (length file - 4) length file) = ".csv" [ set data csv:from-file file ;; Use the CSV extension to read the file into 'data' if not empty? data [ ;; If data is not empty, store file info and handle potential header row set data-source file ;; Remove header row if the first row has strings in item 0 if length first data > 0 and is-string? item 0 first data [ set data but-first data ] set data-pointer 0 set data-length length data set-current-vals ;; Load values from the first row into the model's global variables output-print (word "Data has been successfully loaded: " data-source) output-print (word "Number of data points: " data-length) ] ] [ ;; If the file doesn't end with ".csv", show an error user-message "Please select a CSV file. The selected file does not appear to be a CSV file." output-print "Error: Non-CSV file selected." ] ] [ ;; If user canceled or no file selected output-print "No file was selected or the operation was cancelled." ] ] [ ;; 'carefully' error block: if anything goes wrong, show a user message user-message (word "An unexpected error has occurred while reading the file: " error-message) output-print (word "Error Details: " error-message) ;; Save error log if needed carefully [ file-open "error_log.txt" file-print (word date-and-time " - File Reading Error: " error-message) file-close ] [] ] end to-report read-data [ file-name ] ;; A helper reporter to read CSV data from a file let rows [] if file-name != false [ set data-source file-name file-open file-name set rows csv:from-file file-name file-close ] report rows end to update-population-ratios ;; Reassigns humans to outsider, weekender, or vacationist groups based on global ratio variables let total-humans count humans let new-outsiders round (total-humans * Outsiders) let new-weekenders round (total-humans * Weekenders) let new-vacationists round (total-humans * Vacationists) ;; Reset all humans to default (no special type) ask humans [ set is-outsider? false set is-weekender? false set is-vacationist? false ] ;; Assign 'Outsiders' let available-humans humans let outsiders-to-assign min (list new-outsiders count available-humans) ask n-of outsiders-to-assign available-humans [ set is-outsider? true ] ;; Update who is left set available-humans humans with [not is-outsider?] ;; Assign 'Weekenders' let weekenders-to-assign min (list new-weekenders count available-humans) ask n-of weekenders-to-assign available-humans [ set is-weekender? true ] ;; Update who is left set available-humans humans with [not is-outsider? and not is-weekender?] ;; Assign 'Vacationists' let vacationists-to-assign min (list new-vacationists count available-humans) ask n-of vacationists-to-assign available-humans [ set is-vacationist? true ] ;; Update global reference sets set workingPeople humans with [is-outsider?] set weekenderPeople humans with [is-weekender?] set vacationistPeople humans with [is-vacationist?] ;; Update any dependent variables or patch-level variables update-dependent-variables end to set-current-vals ;; Reads the current row in 'data' at 'data-pointer' and sets global variables. let vals-list item data-pointer data set data-date item 0 vals-list set DayofYear item 1 vals-list set DayofMonth item 2 vals-list set Month item 3 vals-list set Week item 4 vals-list set data-weekday item 5 vals-list set data-vacation item 6 vals-list set data-temp item 7 vals-list set data-prcp item 8 vals-list set data-housesMonthly item 9 vals-list set data-popMonthly item 10 vals-list set data-totalMonthly item 11 vals-list set HeuristicMonthlyTotal item 12 vals-list set data-avgDaily item 13 vals-list set HeuristicDailyTotal item 14 vals-list set AverageWeekly item 15 vals-list set HeuristicWeekly item 16 vals-list set fwcf item 17 vals-list end to set-globals ;; Initialize some global variables at setup set number-of-houses data-housesMonthly set start-res count patches with [pcolor = yellow] set number-of-humans count humans with [pcolor = yellow] end to set-the-world ;; Resizes and configures the NetLogo world based on the number of houses set worldSize number-of-houses * 3 set worldDmnsn sqrt worldSize resize-world (- worldDmnsn) worldDmnsn (- worldDmnsn) worldDmnsn ask patches [ set pcolor black set hhtype "outside" ] ;; Color some patches yellow to represent houses ask n-of number-of-houses patches [ set pcolor yellow set hhtype "household" ] ;; Convert a fraction of patches into workplaces ask n-of (number-of-houses * (100 - residenceRatio) * 0.01) patches with [pcolor = black] [ set pcolor grey set hhtype "workplace" ] end to set-the-household ;; Assign household sizes (hhs) to each household patch and create humans ask patches with [hhtype = "household"] [ set hhs round random-normal householdSize varHHS while [hhs < 1] [set hhs round random-normal householdSize varHHS] ] ;; Calculate sub-population sizes set num-under5 round (data-popMonthly * %Under5) set num-5&17 round (data-popMonthly * %5&17) set num-seniors round (data-popMonthly * %Seniors) set num-adults (data-popMonthly - num-under5 - num-5&17 - num-seniors) ;; Create humans in total equal to 'data-popMonthly' create-humans data-popMonthly [ set house one-of patches with [hhtype = "household"] move-to house set age assign-age set-human-category ] end to-report assign-age ;; Randomly assign an age to a new human based on population percentages let r random-float 1 (ifelse r < %Under5 [report random 5] r < (%Under5 + %5&17) [report 5 + random 13] r < (1 - %Seniors) [report 18 + random 48] [report 66 + random 35]) end to set-human-category ;; Assign a category (infant, school-age, adult, senior) and color (ifelse age < 6 [set category "infant" set color lime] age >= 6 and age < 18 [set category "school-age" set color cyan] age >= 18 and age < 66 [set category "adult" set color sky] [set category "senior" set color blue]) end to setup-human-types ;; Assign each human a boolean for is-outsider?, is-weekender?, is-vacationist? ask humans [ set is-outsider? random-float 1 < Outsiders set is-weekender? random-float 1 < Weekenders set is-vacationist? random-float 1 < Vacationists ] end ; ===== SIMULATION CONTROL PROCEDURES ===== to go ;; Main simulation loop, typically called by a "go" button ;; 1. Check for temporary population ratio changes if temp-change-active? and ticks >= temp-change-end-tick [ ;; If the current tick passes the end tick for a temporary change, revert revert-to-original-ratios ] ;; 2. Update population ratios if needed check-and-update-ratios ;; 3. Update the current date (if you store or display it) update-current-date ;; 4. Stop if we've reached the end of data if data-pointer >= data-length [stop] ;; 5. Execute main simulation steps get-next-record check-for-change ;; Check if number of houses changed this month move-humans ;; Humans move to workplaces, outside, or stay at home consume-water ;; Calculate water usage ;; 6. Update consumption tracking update-water-consumption set total-water-consumption total-water-consumption + water-consumption track-water-consumption ;; 7. Log results for analysis specifics-logfile tick ;; Advance NetLogo's time end to get-next-record ;; Moves the data pointer to the next row in 'data' set data-pointer data-pointer + 1 if data-pointer >= data-length [stop] set-current-vals end to check-and-update-ratios ;; Adjust population ratios if the global ratio variables changed or if a temporary change is in effect ifelse temp-change-active? [ ;; If a temporary change is active, ensure the ratio variables match the temporary ones if Outsiders != temp-outsiders or Weekenders != temp-weekenders or Vacationists != temp-vacationists [ set Outsiders temp-outsiders set Weekenders temp-weekenders set Vacationists temp-vacationists update-population-ratios ] ] [ ;; If not in a temporary change, watch if the user changed the ratio sliders if previous-outsiders != Outsiders or previous-weekenders != Weekenders or previous-vacationists != Vacationists [ update-population-ratios set previous-outsiders Outsiders set previous-weekenders Weekenders set previous-vacationists Vacationists ] ] end to check-for-change ;; If the monthly data shows a different # of houses than we currently have, adjust the world if data-housesMonthly != number-of-houses [ let diff data-housesMonthly - number-of-houses ifelse diff > 0 [create-new-houses diff] [remove-houses (- diff)] ] set number-of-houses data-housesMonthly end to create-new-houses [n] ;; Convert 'n' black patches into households, and create humans in each new house ask n-of n patches with [pcolor = black] [ set pcolor yellow set hhtype "household" set hhs round random-normal householdSize varHHS sprout-humans hhs [ set house patch-here set age assign-age set-human-category setup-human-types ] ] end to remove-houses [n] ;; Convert 'n' household patches back to black patches, killing any humans there ask n-of n patches with [hhtype = "household"] [ ask humans-here [die] set pcolor black set hhtype "outside" ] end ; ===== HUMAN MOVEMENT AND BEHAVIOR ===== to move-humans ;; Control movement of human agents based on their type and current conditions ask humans [ ifelse should-go-out? [ ;; If this human should go out, decide where based on type of day ifelse is-outsider? and data-vacation = "none" and not member? data-weekday ["Saturday" "Sunday"] ;; 1. Outsiders go to workplace on weekdays if not a vacation day [move-to one-of patches with [hhtype = "workplace"]] ;; 2. Otherwise, if it's a weekend or a vacation day, go 'outside' [if (is-weekender? and member? data-weekday ["Saturday" "Sunday"]) or (is-vacationist? and data-vacation != "none") [move-to one-of patches with [hhtype = "outside"]]] ] ;; If the human isn't going out, stay (or return) to their house [move-to house] ] end to-report should-go-out? ;; Decide probabilistically if a human should leave home based on temperature, precip, day-type, etc. let temp-factor temperature-factor data-temp let precip-factor precipitation-factor data-prcp let day-factor day-type-factor data-weekday data-vacation let go-out-probability temp-factor * precip-factor * day-factor ;; Younger than 5 or older than 65 => reduce their likelihood by 50% if age < 5 or age > 65 [set go-out-probability go-out-probability * 0.5] report random-float 1 < go-out-probability and (is-outsider? or is-weekender? or is-vacationist?) end to-report temperature-factor [temp] ;; Simple example that modifies a factor based on temperature ranges (ifelse temp < -10 [report 0.5] temp < 4 [report 0.5 + (temp + 10) / 28] temp < 13 [report 0.75 + (temp - 4) / 36] temp < 26 [report 1] [report 1 - (temp - 26) / 74]) end to-report precipitation-factor [precip] ;; A simple linear factor to reduce the probability if precipitation is high report 1 - (precip / 100) end to-report day-type-factor [weekday vacation] ;; Returns a factor based on day type or vacation ifelse vacation != "none" [report Vacationists] [ifelse member? weekday ["Saturday" "Sunday"] [report Weekenders] [report Outsiders]] end ; ===== WATER CONSUMPTION CALCULATIONS ===== to consume-water ;; Calculates water consumption in each household patch and sums the total let total-consumption 0 ask patches with [hhtype = "household"] [ let occupants count humans-here ifelse occupants > 0 [ ;; If there are occupants, calculate usage let tap-consumption occupants * tapUse * Tap-Lt-m set tap-eat-drink tap-consumption set tap-clean-up tap-consumption set tap-maintenance tap-consumption ;; Dishwasher usage set dw-eat-drink calculate-dw-usage occupants set dw-clean-up calculate-dw-usage occupants ;; Washing machine usage set wm-clean-up calculate-wm-usage occupants set wm-maintenance calculate-wm-usage occupants ;; Personal usage for toilet & shower set toilet-water occupants * toiletUse * Flush-Lt set shower-water occupants * showerUse * Shower-Lt-m ;; Group consumption by activity set eat-and-drink-water tap-eat-drink + dw-eat-drink set cleaning-water tap-clean-up + dw-clean-up + wm-clean-up + shower-water + toilet-water set maintenance-water tap-maintenance + wm-maintenance ;; Sum the consumption from all devices let total-appliance-consumption eat-and-drink-water + cleaning-water + maintenance-water ;; Apply weather correction factor (fwcf) from the CSV let adjusted-consumption ifelse-value (fwcf < 0) [total-appliance-consumption - (total-appliance-consumption * abs fwcf)] [total-appliance-consumption + (total-appliance-consumption * fwcf)] ;; Ensure at least a minimum consumption (base-demand-per-capita * occupants) set water-cnsmptn max list (occupants * base-demand-per-capita) adjusted-consumption ;; If we had to bump up consumption to meet the min threshold, scale each component if water-cnsmptn > adjusted-consumption [ let scaling-factor water-cnsmptn / adjusted-consumption set eat-and-drink-water eat-and-drink-water * scaling-factor set cleaning-water cleaning-water * scaling-factor set maintenance-water maintenance-water * scaling-factor ] ][ ;; If no occupants, consumption is 0 set water-cnsmptn 0 set eat-and-drink-water 0 set cleaning-water 0 set maintenance-water 0 ] set total-consumption total-consumption + water-cnsmptn ] set water-consumption total-consumption end to-report calculate-dw-usage [occupants] ;; Tracks dishwasher usage. If dw-load >= 1, we run the dishwasher once (DW-Lt). set dw-load dw-load + (dwUse * occupants) ifelse dw-load >= 1 [ set dw-load dw-load - 1 report DW-Lt ][ report 0 ] end to-report calculate-wm-usage [occupants] ;; Tracks washing machine usage. If wm-load >= 1, we run the washing machine once (WM-Lt). set wm-load wm-load + (wmUse * occupants) ifelse wm-load >= 1 [ set wm-load wm-load - 1 report WM-Lt ][ report 0 ] end to specifics-logfile ;; Creates a log entry for the current tick/day and writes it to file or output let monthly-water-use ifelse-value monthly-consumption != [] [precision (monthly-consumption / 1000) 0] [0] let weekly-water-use ifelse-value weekly-consumption != [] [precision (weekly-consumption / 1000) 0] [0] let log-entry (word "date:" data-date " weekday:" data-weekday " vacation:" data-vacation " temp:" data-temp " prcp:" data-prcp " NumberOfHumans:" count humans " NumberOfHouses:" number-of-houses " TotalWaterUse:" (total-water-consumption / 1000) " MonthlyWaterUse:" monthly-water-use " WeeklyWaterUse:" weekly-water-use " NumAdults:" count humans with [age > 17 and age < 66] " NumSeniors:" count humans with [ age > 65] " NumSchAge:" count humans with [ age > 5 and age < 18] " NumInfants:" count humans with [age < 6] " TapWater:" (sum [tap-eat-drink + tap-clean-up + tap-maintenance] of patches / 1000 ) " ToiletWater:" (sum [toilet-water] of patches / 1000) " ShowerWater:" (sum [shower-water] of patches / 1000) " WMWater:" (sum [wm-maintenance + wm-clean-up] of patches / 1000) " DWWater:" (sum [dw-eat-drink + dw-clean-up] of patches / 1000) ) if print-to-logfile? [ print-to-file log-entry ] if print-to-output? [ output-print log-entry ] end to print-to-file [file-text] ;; Appends a line to the log file (if logfile is valid) if is-string? logfile and logfile != "" [ carefully [ file-open logfile file-print file-text file-close ] [ print (word "Error writing to log file: " error-message) ] ] end to restart-data ;; Resets the data pointer and re-initializes consumption counters set data-pointer 0 set data-length length data set-current-vals output-print "Reset to first record" let log-entry (word "\r -- New Session -- " date-and-time) if print-to-logfile? [ carefully [ print-to-file log-entry print-to-file logfile print-to-file data-source ] [ print "Error writing to log file" ] ] ;; Reset tracking variables set monthly-consumption [] set weekly-consumption [] set weekday-consumption 0 set weekend-consumption 0 set vacation-consumption 0 set weekday-consumption-total 0 set weekend-consumption-total 0 set vacation-consumption-total 0 set weekday-count 0 set weekend-count 0 set vacation-count 0 ask patches [ set water-cnsmptn 0 set eat-and-drink-water 0 set cleaning-water 0 set maintenance-water 0 ] set water-consumption 0 specifics-logfile clear-plots reset-ticks end to delete-logfile ;; Deletes the current log file if it exists if is-string? logfile and file-exists? logfile [ file-delete logfile output-print "Log file deleted" ] end to go-data ;; If you want to just advance one day in the data, call get-next-record and log, then consume get-next-record specifics-logfile consume-water tick end to report-ratio-achievement ;; Prints how close we are to the desired ratio of outsiders/weekenders/vacationists let total-humans count humans let actual-outsiders count humans with [is-outsider?] let actual-weekenders count humans with [is-weekender?] let actual-vacationists count humans with [is-vacationist?] print (word "Desired Outsiders: " Outsiders " Actual: " (actual-outsiders / total-humans)) print (word "Desired Weekenders: " Weekenders " Actual: " (actual-weekenders / total-humans)) print (word "Desired Vacationists: " Vacationists " Actual: " (actual-vacationists / total-humans)) end to parse-and-set-temp-change [input-string new-outsiders new-weekenders new-vacationists] ;; Reads the user input string in format "DD.MM.YYYY duration" and sets temporary ratio changes let parts read-from-string (word "[" input-string "]") if length parts != 2 [ user-message "Invalid input format. Please use 'DD.MM.YYYY duration' format." stop ] set temp-outsiders new-outsiders set temp-weekenders new-weekenders set temp-vacationists new-vacationists set temp-change-pending? true end to activate-temporary-change ;; Activates a previously scheduled temporary ratio change set temp-change-active? true set temp-change-pending? false set temp-change-start-tick ticks set previous-outsiders Outsiders set previous-weekenders Weekenders set previous-vacationists Vacationists set Outsiders temp-outsiders set Weekenders temp-weekenders set Vacationists temp-vacationists update-population-ratios end to revert-to-original-ratios ;; Reverts from the temporary ratios back to the original ones set Outsiders previous-outsiders set Weekenders previous-weekenders set Vacationists previous-vacationists set temp-change-active? false update-population-ratios end to-report date-to-comparable [date-string] ;; An example procedure to convert a string date into a comparable numeric value let parts remove "." date-string report read-from-string (word (item 4 parts) (item 2 parts) (item 0 parts)) end to-report date-to-number [date-string] ;; Converts date "DD.MM.YYYY" into a single integer YYYYMMDD let parts splitt date-string "." if length parts != 3 [ user-message (word "Invalid date format: " date-string ". Please use DD.MM.YYYY format.") report false ] let day read-from-string item 0 parts set month read-from-string item 1 parts let year read-from-string item 2 parts report (year * 10000) + (month * 100) + day end to-report splitt [string delimiter] ;; Splits a string on a given delimiter and returns a list let result [] while [not empty? string] [ let index position delimiter string ifelse index != false [ set result lput (substring string 0 index) result set string substring string (index + 1) length string ] [ set result lput string result set string "" ] ] report result end to-report extract-month [date-string] ;; Extracts the month portion from a "DD.MM.YYYY" string as a number let parts split date-string "." if length parts != 3 [ user-message (word "Invalid date format: " date-string ". Please use DD.MM.YYYY format.") report false ] report read-from-string item 1 parts end to-report extract-week [date-string] ;; Approximate function to get a week number from a date (not ISO standard) let parts split date-string "." if length parts != 3 [ user-message (word "Invalid date format: " date-string ". Please use DD.MM.YYYY format.") report false ] let day read-from-string item 0 parts set month read-from-string item 1 parts let year read-from-string item 2 parts ;; Rough calculation (this is not calendar-accurate but might work for your needs) report (((month - 1) * 30 + day) / 7) + 1 end to update-current-date ;; A placeholder that could update data-date or other date variables each tick if needed. ;; For example: ;; set data-date read-next-date-from-file end to apply-temporary-ratio-change [start-date new-outsiders new-weekenders new-vacationists duration] ;; Another placeholder for a user command that schedules a ratio change set temp-outsiders read-from-string2 new-outsiders set temp-weekenders read-from-string2 new-weekenders set temp-vacationists read-from-string2 new-vacationists set temp-change-pending? true end to-report read-from-string2 [str] report read-from-string str end to-report date-to-list [date-string] ;; Converts "DD.MM.YYYY" to a list [day month year] report map [ s -> read-from-string s ] split date-string "." end to-report split [string delimiter] ;; Another version of 'split', similar to 'splitt' above let result [] while [not empty? string] [ let index position delimiter string ifelse index != false [ set result lput (substring string 0 index) result set string substring string (index + 1) length string ] [ set result lput string result set string "" ] ] report result end to update-water-consumption ;; Aggregates daily consumption into monthly and weekly totals, storing them in lists ifelse Month != current-month [ ;; If we have a new month, store the old month's consumption in a list if monthly-consumption > 0 [ set monthly-consumption-list lput monthly-consumption monthly-consumption-list ] set monthly-consumption water-consumption set current-month Month ] [ set monthly-consumption monthly-consumption + water-consumption ] ifelse Week != current-week [ ;; If we have a new week, store the old week's consumption in a list if weekly-consumption > 0 [ set weekly-consumption-list lput weekly-consumption weekly-consumption-list ] set weekly-consumption water-consumption set current-week Week ] [ set weekly-consumption weekly-consumption + water-consumption ] ;; Track daily usage in a list set daily-consumption-list lput water-consumption daily-consumption-list ;; Update overall average values update-average-consumptions end to update-average-consumptions ;; Calculate running averages for monthly, weekly, daily consumption set average-monthly-consumption ifelse-value not empty? monthly-consumption-list [mean monthly-consumption-list] [0] set average-weekly-consumption ifelse-value not empty? weekly-consumption-list [mean weekly-consumption-list] [0] set average-daily-consumption ifelse-value not empty? daily-consumption-list [mean daily-consumption-list] [0] end to clear-plots ;; Clears named plots so they can be re-drawn set-current-plot "Simulation Starters" clear-plot set-current-plot "Water Demand Estimation" clear-plot set-current-plot "Household Consumption" clear-plot set-current-plot "Monthly Water Consumption" clear-plot set-current-plot "Weekly Water Consumption" clear-plot set-current-plot "Water Consumption Based on Day Type" clear-plot end to update-dependent-variables ;; Update any variables that depend on outsider/weekender/vacationist counts ask patches with [hhtype = "household"] [ set working count humans-here with [is-outsider?] set weekender count humans-here with [is-weekender?] set vacationist count humans-here with [is-vacationist?] ] end to go-until ;; Run the simulation until a user-specified 'date-to-stop' if empty? date-to-stop [ user-message "Please enter a date to stop in the 'date-to-stop' input box." stop ] let start-date-list date-to-list data-date let stop-date-list date-to-list date-to-stop if not is-valid-date? start-date-list or not is-valid-date? stop-date-list [ ;; If either date is invalid, stop stop ] let days-to-run days-between start-date-list stop-date-list if days-to-run < 0 [ user-message "Stop date must be after the current simulation date." stop ] let target-tick ticks + days-to-run while [ticks < target-tick and data-pointer < data-length] [ go ] if ticks >= target-tick [ output-print (word "Simulation stopped at " data-date) ] if data-pointer >= data-length [ output-print "Reached end of data before stop date." ] end to-report days-between [start-date-list stop-date-list] ;; Calculate how many days are between two dates (day, month, year) let start-day item 0 start-date-list let start-month item 1 start-date-list let start-year item 2 start-date-list let stop-day item 0 stop-date-list let stop-month item 1 stop-date-list let stop-year item 2 stop-date-list let days 0 ;; Increment day-by-day until start date == stop date while [start-year < stop-year or (start-year = stop-year and start-month < stop-month) or (start-year = stop-year and start-month = stop-month and start-day < stop-day)] [ set days days + 1 set start-day start-day + 1 if start-day > days-in-month start-month start-year [ set start-day 1 set start-month start-month + 1 if start-month > 12 [ set start-month 1 set start-year start-year + 1 ] ] ] report days end to-report is-valid-date? [date-list] ;; Quick check that day, month, year are in plausible ranges if length date-list != 3 [ user-message "Invalid date format. Please use DD.MM.YYYY format." report false ] let day item 0 date-list set month item 1 date-list let year item 2 date-list if day < 1 or day > 31 or month < 1 or month > 12 or year < 1900 or year > 2100 [ user-message "Invalid date values. Please check your input." report false ] report true end to-report days-in-month [month-num year] ;; Returns the number of days in a given month, accounting for leap years in February let days-list [31 28 31 30 31 30 31 31 30 31 30 31] if month-num = 2 and is-leap-year? year [ report 29 ] report item (month-num - 1) days-list end to-report is-leap-year? [year] ;; Standard leap-year check report (year mod 4 = 0 and year mod 100 != 0) or (year mod 400 = 0) end to track-water-consumption ;; Categorizes today's water consumption into weekday, weekend, or vacation set weekday-consumption 0 set weekend-consumption 0 set vacation-consumption 0 ;; If it's not a vacation day if data-vacation = "none" [ ;; Check if it's a weekday or weekend ifelse not member? data-weekday ["Saturday" "Sunday"] [ ;; Weekday set weekday-consumption water-consumption set weekday-consumption-total weekday-consumption-total + water-consumption set weekday-count weekday-count + 1 ] ;; Weekend [ set weekend-consumption water-consumption set weekend-consumption-total weekend-consumption-total + water-consumption set weekend-count weekend-count + 1 ] ] ;; If it is a vacation day, decide if it's specifically "weekend" or other ifelse data-vacation = "weekend" [ set weekend-consumption water-consumption set weekend-consumption-total weekend-consumption-total + water-consumption set weekend-count weekend-count + 1 ] [ if data-vacation != "none" [ set vacation-consumption water-consumption set vacation-consumption-total vacation-consumption-total + water-consumption set vacation-count vacation-count + 1 ] ] ;; Update average usage for each day type set avg-weekday-consumption ifelse-value weekday-count > 0 [weekday-consumption-total / weekday-count] [0] set avg-weekend-consumption ifelse-value weekend-count > 0 [weekend-consumption-total / weekend-count] [0] set avg-vacation-consumption ifelse-value vacation-count > 0 [vacation-consumption-total / vacation-count] [0] end
There is only one version of this model, created 4 months ago by Kamil Aybuğa.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
WaDemEsT.png | preview | Preview for 'WaDemEsT' | 4 months ago, by Kamil Aybuğa | Download |
This model does not have any ancestors.
This model does not have any descendants.