Ontkoppelde bestanden
Terug naar Home
Een deel van de berekeningen in RSopen wordt niet elke run opnieuw gedaan, maar eenmalig weggeschreven naar een bestand dat een volgende run terugleest. Dat heet in dit model een ontkoppeld bestand. Deze pagina beschrijft wanneer dat gebeurt, hoe het model bepaalt of zo’n bestand nog bruikbaar is, en wat je moet doen als je iets verandert dat de inhoud ervan bepaalt.
Waarom ontkoppelen
Sommige stappen kosten veel rekentijd en veranderen zelden: de BGT-afgeleiden op 2,5 meter, de pandtypering van de hele BAG, de opbrengsten per ontwikkelpakket. Die hoeven niet bij elke run opnieuw.
GeoDMS houdt zelf niet bij welke uitkomsten door een configuratiewijziging ongeldig zijn geworden. Ontkoppelen is daarom handwerk: de configuratie bepaalt zelf wanneer een bestand hergebruikt mag worden. Het voordeel is snelheid, het risico is dat het model stilzwijgend met een verouderd bestand rekent. De fingerprint hieronder is er om dat risico af te dekken.
De drieslag
Een ontkoppeld item heeft drie takken, gestuurd door een schakelaar:
attribute<...> X := =!ModelParameters/<Iets>Ontkoppeld ? 'Calc_X' : Decoupling/MayReuse ? 'Read_X' : 'Make_X';
Calc_Xrekent zonder tussenbestand, voor wie het ontkoppelen helemaal uit wil zetten.Read_Xleest het bestaande bestand.Make_Xrekent en schrijft, metWrite_FingerprintalsExplicitSupplier, zodat het zijbestand altijd samen met het bestand zelf ververst wordt.
De schakelaars staan in ModelParameters:
| Schakelaar | Betekenis |
|---|---|
BaseDataOntkoppeld | Voorbereidende data die voor alle varianten gelijk is |
VariantDataOntkoppeld | Voorbereidende data per variant; in batchmodus gestuurd via de omgevingsvariabele met dezelfde naam |
StandAllocatieOntkoppeld | De standbestanden per zichtjaar; idem via omgevingsvariabele |
LandUseMapOntkoppeld | De landgebruikskaarten in de indicatoren |
BAG_WP5_rel_Ontkoppeld | De pandtypering van de BAG |
AlwaysRemakeDecoupledFiles | Zet alle hergebruik in een keer uit, ongeacht de fingerprints |
De fingerprint
Naast een ontkoppeld bestand staat een zijbestand met dezelfde naam plus .params.txt. Daarin staat de lijst waarden die de uitkomst bepalen, als sleutel=waarde gescheiden door puntkomma’s, met Engelse sleutelnamen:
bgt_date=20260819;study_area=Nederland;variant=BAU;class_set=Default;...
Bij de start vergelijkt het model de opgeslagen fingerprint met de huidige. Zijn ze gelijk en staat het bestand er, dan mag het teruggelezen worden. Anders wordt het opnieuw gemaakt en overschreven. Het mechanisme staat in Templates/DecoupledFile_T.dms en wordt aangeroepen als Templates/DecoupledFile_T(FileName, Fingerprint).
Drie regels bij het samenstellen van een fingerprint:
- Zet er alle waarden in die de uitkomst bepalen, ook de waarden die al in de bestandsnaam zitten. Dat is bewust dubbelop: zo blijft de regel zonder uitzonderingen en is het zijbestand een leesbaar verslag van waar het bestand vandaan komt.
- Het gaat niet alleen om
ModelParameters, maar ook om variantinstellingen, klassenindelingen en de datum of versie van de brondata. - Neem bij een klassenset niet alleen de naam op maar ook de inhoud. Een wijziging binnen de set
Defaultverandert de naam niet, dus zonder de vlaggenreeks zelf zou die wijziging onopgemerkt blijven.
Het mechanisme faalt de goede kant op. Ontbreekt het zijbestand, dan valt het model terug op cfg/no_fingerprint.txt, klopt de vergelijking nooit en wordt er opnieuw gerekend. Ontbreekt het bestand zelf, idem. Wie wil weten waarom een bestand wel of niet opnieuw gemaakt wordt, vraagt het item Decoupling/Explanation op: dat geeft het pad, of het bestand bestaat, de opgeslagen en de huidige fingerprint, en de uitkomst.
Wat nu een fingerprint heeft
| Bestand | Sleutels |
|---|---|
VariantData/<variant>/EvidentBenut en de zon-variant daarvan | bgt_date, study_area, variant, class_set, class_count, class_flags, grid_size |
BaseData/Zonneladder/PerAllocDomain | bgt_date, brt_date, bbg_year, study_area, alloc_grid, step_count, steps |
BaseData/StartState/Verblijfsrecreatie_Trends/Trends | regio_unit, object_years, area_years, study_area, max_objects_beta, max_area_beta, bag_year, bbg_year |
Wat nog geen fingerprint heeft
Deze bestanden worden wel ontkoppeld maar zonder fingerprint. Hieronder staat per bestand welke invoer de uitkomst bepaalt en dus niet vergeten mag worden bij een wijziging:
- Opbrengsten per ontwikkelpakket (
Templates/VariantData_T/Geschiktheden.dms): NVM_filedate, NVM_coeff_Year, Model_StartYear, de eigenschappen van de ontwikkelpakketten (dichtheid, woonoppervlakte, kamers, hoogbouw, wegingen), het perceeloppervlak per pakket, de locatievariabelen, en via de correctie op het gemiddelde wegingseffect ook de restricties- en stimuliselectie voor wonen. - Stand basisjaar (
BaseData/StateBasisjaar.dms): Model_StartYear, BAG_file_date, LISA_StartYear, LISA_FileYear, de AltLISA-schakelaar en -varianten, en de klassenindelingen WP2xVSSH en Jobs6. - Verwervingskosten van woningen en niet-woningen (
BaseData/Suitabilities/Verwervingskosten.dms): Model_StartYear, BAG_file_date, NVM_filedate, NVM_coeff_Year, de WP4-indeling, en voor niet-woningen de prijs per vierkante meter en het WOZ-jaar. - De pandtypering WP5 (
SourceData/Vastgoed/BAG/AfleidingPandtype.dms): het aantal tegels, de inflate-grootte, de criteria voor functioneel pand en de WP5-indeling. Dit bestand is bovendien een positionele reeks over de pandenset van dat jaar: hoort het bij een andere pandenset, dan schuift de typering op. De integriteitscontrole oppand/WP5_relvangt dat af. - De BGT-afgeleiden in
SourceData/Grondgebruik/bgt.dms(groen, water, verhard, halfverharding, spoor, autoweg). - De gemiddelde verharding per BGT-klasse. De inhoud hangt af van
ImperviousnessMapYear, maar dat jaar zit niet in de bestandsnaam. Zolang dat zo is, moet het bestand met de hand worden verwijderd wanneer die schakelaar verandert. - De logistieke pandenaanvulling (
WritePrivData/LogistiekAanvulling.dms, bestandLogistiekPandenAanvulling_BAG<jaar>_LISA<jaar>_<versie>.mmd): BAG_RecentYear, LISA_StartYear en een versienummer zitten in de bestandsnaam. Let op: die naam staat niet als parameter inModelParametersmaar wordt aan beide kanten uitgeschreven, inSourceData/Vastgoed.dmsen inWritePrivData/LogistiekAanvulling.dms, met het versienummer hard in de string. Er stond eerder een gedeelde parameter voor, die is er bewust uitgehaald. De versie moet worden opgehoogd bij elke wijziging aan de regeldrempels (kernaandeel, footprint-ondergrenzen, zoekafstand vanaf de pandrand): op de gedeelde opslag mag een eenmaal geplaatst bestand niet worden overschreven, dus elke inhoudelijke wijziging krijgt een nieuwe naam. Bijzonderheid: hergenereren kan alleen metBAG_LogistiekDynamischop FALSE, omdat het pand-domein anders het nog te schrijven bestand als supplier meetrekt; een integriteitscontrole op de schrijf-unit dwingt dat af. Zie BAG-verwerking voor wat het bestand doet.
De standbestanden per zichtjaar hebben bewust geen fingerprint. Die hangen af van vrijwel de hele configuratie, inclusief alle bestanden hierboven, dus een fingerprint zou daar de hele configuratie moeten omvatten. Ze worden per run beheerd met StandAllocatieOntkoppeld.
Wat te doen bij een wijziging
Verander je iets dat de uitkomst van een ontkoppeld bestand bepaalt, dan moet die invoer in de fingerprint staan, of moet het bestand op een andere manier ongeldig worden gemaakt: een nieuwe bestandsnaam, het bestand weggooien, of AlwaysRemakeDecoupledFiles aanzetten voor die run.
Dat geldt ook voor bestanden zonder fingerprint. Het peiljaar van de begrenzing bebouwd gebied verhuisde in augustus 2026 van 2012 naar 2022; dat werkt via de grondproductiekosten door in de residuele waarde en dus in de allocatie zelf, terwijl de standbestanden per zichtjaar geen fingerprint hebben. Zo’n wijziging vraagt dus een volledige herberekening van alle zichtjaren.
Twee GeoDMS-valkuilen
ExplicitSuppliersop een container lift niet mee wanneer je een los kind opvraagt. Bij containers die metfor_eachworden opgebouwd kan het schrijven van het zijbestand dus niet aan de container hangen. Vraag je zo’n item rechtstreeks op, dan wordt het wel gerekend en geschreven maar komt er geen zijbestand, en rekent de volgende run het opnieuw uit.PropValue(item, 'StorageName')geeft de expressietekst terug, niet de uitkomst. Dat werkt wanneer je hem weer alsStorageNamegebruikt, maar niet als invoer voorExistingFile. Zet het pad dan als eigenparameter<String>neer en verwijs daar vanuit beide kanten naar.