Utvecklat av Gunnar Joki,
med modifieringar för Visual Studio 2005 av
Thomas Padron-McCarthy
(thomas.padron-mccarthy@tech.oru.se).
Senaste ändring: 5 oktober 2007.
Den här bilden föreställer ett kyl- och reningssystem för vattnet i en reaktortank
i ett kärnkraftverk:
(Klicka på bilden för att se den i större format.)
Det heta vattnet i tanken cirkuleras med hjälp av pumpen P1 från
tanken genom värmeväxlaren VVXL1 och filtret F1. Normalt är ventilerna
V1, V2 och V3 öppna och V4 och V5 stängda. Med tiden blir filtret
igensatt, varvid flödet genom systemet minskar. Filtret spolas rent
med ett backflöde. Genom att stänga ventilen V2 och öppna V4 och V5
styrs delar av flödet bakvägen genom filtret F1 och ut i avloppet nod
N8. Höjdskillnader behöver ej beaktas.
Skriv ett program, Kylsim, som simulerar systemet. Vattenflödet i
flödesvägarna och trycket i noderna ska simuleras. Manövrering av
ventilerna, dvs öppna/stäng, ska simuleras. Manövrering av pumpen, dvs
start/stopp, ska simuleras. Värmetransporten genom systemet ska inte
simuleras, utan bara vattenflödet.
[5~Programmet ska innehålla ett grafiskt användargränssnitt
(GUI, Graphical User Interface)
med vilket man kan betrakta och manövrera systemet enligt
(för betygsnivå 3):
-
En dynamisk bild av systemet ska visas på en grafisk skärm där
noderna N1 och N7 är icke reglerbara med konstanta trycket 2 och N8
också icke reglerbar med trycket 1.
-
I anslutning till varje nod ska
nodens namn och tryck presenteras.
-
I anslutning till varje ventil ska
ventilens namn, ventilkäglans position och flödet genom ventilen
presenteras.
-
I anslutning till pumpen ska namnet, flödet och
pumpvarvtalet presenteras.
-
I anslutning till filtret ska namnet,
filteröppningen (2 decimaler) och flödet presenteras. Larm (blinkande
rött ljus) visas då filtret är igensatt till mer än hälften.
-
I
anslutning till värmeväxlaren ska namnet och flödet presenteras.
-
När
man klickar på en ventil ska en popupmeny dyka upp. I menyn ska finnas
alternativ för att öppna och stänga ventilen.
-
När man klickar på
pumpen ska en popupmeny dyka upp. I menyn ska finnas alternativ för
att starta och stoppa pumpen.
Programmet ska skrivas i Microsoft Visual C++ och köras i Windows.
Redovisning
Programmet ska lämnas in i form av en rapport med försättsblad,
innehållsförteckning, specifikation av uppgiften där ovanstående krav
framgår, implementation av uppgiften som visar klasserna med
medlemsdata, medlemsfunktioner och beroenden mellan klasserna
(UML-klassdiagram). Rapporten ska även innehålla en sammanfattning som
visar resultatet, vilken nivå du har gjort och vad programmet kan
användas till. Som bilaga ska en manual vara med som visar hur man kör
programmet.
Läraren måste kunna provköra programmet.
Det bästa sättet är att
packa ihop hela katalogen med applikationen i en Zip-fil och skicka den med e-post.
Men döp först om Zip-filen från nånting.zip till exempelvis nånting.info
för att överlista överambitiösa virusfilter.
Inlämnat projekt ger
betyget underkänd, 3, 4 eller 5 på delkurs 2. För betyget 3 krävs nivå
3, för betyget 4 krävs nivå 4 och för betyget 5 krävs nivå 5. Vilka
uppgifter som ska göras för de olika nivåerna framgår nedan.
Fysikalisk bakgrund
En ventil har en genomsläppsförmåga, sk admittans, jfr ohm-invers.
Ventilen har en ventilkägla som kan strypa flödet. Man anger
ventilkäglans öppning med ett tal mellan 0.0 och 1.0. Om ventilen är
helt öppen är ventilöppning = 1.0 och om den är helt stängd är
ventilöppning = 0.0. Med hjälp av trycket i noderna på ömse sidor om
ventilen beräknas flödet enligt:
där tryckin och tryckut är trycket i anslutningsnoderna på resp. sida om ventilen.
Flödet genom en pump kan approximativt beräknas enligt:
där k, a och b är konstanter, varvtal är det normaliserade
pumpvarvtalet och tryckin resp. tryckut är trycket i
anslutningsnoderna på resp. sida.
Dessutom gäller för pumpen att om trycket på sugsidan faller under en
kritisk gräns kaviterar pumpen, den börjar sörpla. Pumpen kan inte
pumpa mer vatten än vad som finns tillgängligt. I modellen räcker det
med att begränsa flödet med en linjär funktion då sugtrycket närmar
sig noll.
Summaflöde i en nod (anslutningspunkten mellan
komponenterna) ska vara noll. Inget vatten kan produceras i en sådan
punkt vilket innebär att det vatten som flödar in också måste flöda
ut. Detta faktum kan användas för att reglera trycket i noderna. Om
summaflödet är större än noll, dvs inflödet är större än utflödet är
trycket i noden för lågt och måste höjas. Är inflödet lägre än
utflödet är trycket för högt och måste sänkas.
Arbetsgång
Steg 1
Skapa i utforskaren en ny katalog M:\PCSA\KYL och kopiera dit
demoprogrammet Kyldemo.exe, som ingår i filen OOP-hjalpfiler.zip,
vilken kan laddas ner från kursens hemsida.
Kör demoprogrammet. Starta pumpen genom att klicka på den med musen och
välja Starta från menyn. Klicka på någon ventil och öppna eller stäng
den. Backspola filtret rent genom att öppna ventilerna v4 och v5 och
stänga v2. Återställ ventilerna efter stängning och avsluta programmet
genom att stänga fönstret.
Steg 2
Läs först
här
om hur man använder Microsoft Visual Studio 2005 för att skapa
C++-program med grafik för .NET.
Starta sen Visual Studio 2005 och skapa ett nytt
projekt Kylsim med Visual C++ och typen Windows Forms Application.
Du kommer att
få ett huvudfönster som du kan anpassa i filen Form1.h. Klicka
med höger musknapp på fönstret Form1 och sätt dess property (egenskap)
Text till "Kylsystem av Kalle Anka" (men med ditt namn). Använd egenskapen Size
för att sätta storleken på huvudfönstret till 640;480. Du har nu fått
ett fönster med följande koordinatsystem:
Ta fram koden för fönstret (Form1.h) genom att högerklicka på fönstret
och välja View Code. All kod som kommer att gälla för fönstret kommer
att skrivas i denna headerfil.
Du skaffar en rityta i detta fönster genom att i private-delen av
filen Form1.h definiera en pekare till ett Graphics-objekt inte som vanligt i C++ så här:
Graphics *canvas;
utan i stället så här:
Graphics ^canvas;
Objekt av klassen Graphics är nämligen så kallade hanterade data
(på engelska: managed data),
och måste pekas på med ^-pekare i stället för *-pekare.
Detta är en utökning som finns i Microsofts .NET-miljö och i Visual C++,
men inte i standard-C++.
Repetera
här
om hanterade och ohanterade data.
I konstruktorn, som du också hittar i filen Form1.h, skapa ritytan genom att skriva:
canvas = this->CreateGraphics();
I designfilen för huvudformuläret, Form1(Design), skapar du en
händelsefunktion som alltid kommer att köras då fönstret ändrar sitt
utseende, exempelvis då det skapas, genom att klicka först på
formuläret, sedan på events (blixten) och slutligen på händelsen
Paint. Dubbelklicka sedan på den vita ytan bredvid Paint och det
skapas en händelsefunktion där du fyller i önskad kod för att ex. rita
en röd linje enligt:
// Skapa en röd penna
Pen^ pen = gcnew Pen(Color::Red);
// Rita en (röd) linje från 100, 100 till 200, 200
canvas->DrawLine(pen, 100, 100, 200, 200);
Notera att pennan är ett "hanterat objekt",
och att den därför ska pekas på med en ^-pekare
och skapas med gcnew och inte vanliga new.
Provkör programmet genom att först bygga systemet med Build -> Build Solution (eller motsvarande snabbtangent)
och sedan köra med Debug -> Start (eller snabbtangenten).
Steg 3
Ta fram Solution Explorer och skapa en NOD-klass genom att klicka
med högerknappen på Source Files och välj Add New Item och sedan C++
File med namnet Nod.cpp. På samma sätt skapar du Nod.h genom att i
Solution Explorer klicka på Headerfiles och sedan med Add New Item
skapa filen.
Vi vill att klassen NOD ska vara hanterade data,
och därför inleder vi klassdefinitionen med nyckelordet ref, så här:
ref class NOD {
Noden ska ha medlemsvariabler för tryck, reglerbar (false för icke
reglerbar nod och true annars),
namn (en sträng, antingen i form av en *-pekare till std::string,
eller en ^-pekare till System::String),
canvas (rityta som en ^-pekare till klassen Graphics), x och y.
Alla dessa ska initieras via parametrar till konstruktorn.
Nod-klassen ska känna till den canvas som skapats i huvudfönstret och
skickas därför som en pekare Dessutom ska det finnas en
medlemsvariabel för summaflöde som alltid initieras till 0.0.
Summaflödet är summan av inflöde och utflöde till noden, där utflödet
räknas negativt. Dessa flöden kommer att skickas till noderna från
komponenterna på ömse sidor om resp. nod. Förutom konstruktorn ska det
finnas medlemsfunktioner för att rita, avläsa tryck (get_tryck),
avläsa x- och ykoordinat (get_x, get_y), add_summaflode,
dynamik(reglerar) och display(visar). Funktionen rita ska förutom att
rita en cirkel också skriva ut nodens namn. Använd Graphics-klassens
funktioner DrawEllipse och DrawString (se hjälpen).
DrawEllipse påminner mycket om DrawLine,
men DrawString är lite klurigare.
Den behöver en Brush, en Font och sen en sträng
av typen System::String, som är en särskild hanterad sträng.
Om man har en variabel namn som är en vanlig std::string,
kan man skriva så här:
Brush^ brush = gcnew SolidBrush(Color::Black);
Font^ font = gcnew Font(L"Courier", 30);
const char* cp = namn->c_str();
System::String^ n = gcnew System::String(cp);
canvas->DrawString(n, font, brush, (float)x + 10, (float)y);
Tips:
Strunta i standardbiblioteket, med dess strängar mm,
och använd .NET-klasser (som System::String) överallt.
Det blir enklare så.
|
Funktionen add_summaflode ska anropas av de till noden anslutna
komponenterna, som vid anropet skickar det aktuella flödet till noden
som parameter. Inflöde till noden skickas positivt och utflöde
negativt.
Funktionen dynamik ska reglera trycket med hjälp av summaflödet. Är summaflödet positivt är trycket i noden för lågt och måste ökas. Ökar trycket kommer det att flöda in mindre och ut mera och summaflödet minskar. Använd till att börja med följande enkla regleralgoritm:
if (reglerbar) {
if ( summaflode > 0 )
tryck += 0.1;
else if ( summaflode < 0 )
tryck -= 0.1;
summaflode = 0;
}
Funktionen display ska visa trycket i noden. Innan du använder
DrawStringfunktionen måste du göra om trycket till en sträng med
exempelvis sprintf (se hjälpen).
Det kan vara lite krångel med att få filerna genom kompilatorn,
med namnrymder och allt.
Som hjälp kommer här hur inledningen av filen NOD.cpp kan se ut:
#include "stdafx.h"
using namespace System::Drawing;
#include <string>
using std::string;
#include "NOD.h"
Steg 4
Nu ska du skriva de händelsefunktioner i klassen Form1 som ska anropa
ovanstående medlemsfunktioner i NOD-klassen. Du ska dock börja med att
skapa tre nodbjekt som pekarobjekt i private-delen av Form1-klassen
och objekten skapar du dynamiskt med konstruktoranrop i konstruktorn
för Form1. För att rita ut noderna på vårt formulär måste nodobjektens
ritafunktion anropas. Den händelse som du ska ta hand om och skriva en
händelsefunktion för heter Paint, enligt 3 ovan. Anropa de tre
nodobjektens ritafunktioner i denna händelsefunktion. Testkör
programmet och kontrollera att dina tre noder ritas med namnen
utsatta. Nodfunktionerna dynamik och display måste anropas med jämna
mellanrum. För detta behöver du en klocka. Ta fram ToolBoxen med View
-> ToolBox och ta in en Timer och ställ den på valfri plats på
huvudformuläret, Form1 (Form1.h(Design)). Du har nu en klocka i ditt
kylsystem. Använd property-fönstret för att ge namn åt klockan och
ställa in tidsintervallet, 1000 ms och se till att enable är satt till
true. Skapa sedan en händelsefunktion med händelsen Tick. I denna
händelsefunktion, som kommer att köras med 1000ms intervaller, anropar
du dynamik- och displayfunktionen för dina noder. Testkör.
Dynamikfunktionen kan du inte kontrollera innan du utökat systemet med
ventiler men displayfunktionen ska skriva ut trycket som noderna har
vid skapandet.
Steg 5
På samma sätt som du skapade NOD-klassen ska du skapa en klass VENTIL
i Ventil.h och Ventil.cpp. Ventilobjekten ska ha medlemsvariabler för
admittans, ventilkäglans position, namn, rityta, x, y, in-nod-pekare
och ut-nod-pekare, som alla ska initieras via parametrar i
konstruktorn. (Pekarna ska vara ^-pekare, inte vanliga *-pekare.)
Lämpligt värde på admittansen är 10. Dessutom ska det
finnas en medlemsvariabel för flöde, som alltid initieras till 0 i
konstruktorn. Förutom konstruktorn ska det finnas medlemsfunktioner
rita, oppna, stang, dynamik och display. Rita ska förutom att rita
själva ventilen även rita ledningar till de omgivande noderna som
ventilen har pekare till genom att anropa nodernas get_x och get_y.
Dynamikfunktionen utnyttjar också pekarna till nodernas get_p på ömse
sidor för att beräkna tryckskillnaden. Sedan beräknas flödet enligt
fysiken ovan och skickas till resp. nod genom att anropa funktionen
add_summaflode. Observera att flödet skickas negativt till in-noden
(utflöde sett ifrån noden) och positivt till ut-noden.
Displayfunktionen ska skriva ut flödet och käglans position.
Steg 6
Skapa ett testsystem genom att i kylsystemet lägga till två ventiler.
Den första ventilen placerar du mitt i mellan den första och den andra
noden och den andra ventilen mitt i mellan den andra och tredje noden.
Lägg till ventilobjektens anrop av ritafunktionen och dynamik- och
displayfunktionen i rätt händelsefunktion. Låt de två yttersta noderna
vara icke reglerbara med trycken 5 resp. 1 och låt mittnoden vara
reglerbar med starttrycket 1. Kör programmet och kontrollera trycket i
den mittersta noden och flödet genom ventilerna. Du kan inte se mycket
eftersom värdena skrivs på varandra. Du måste först ta bort den gamla
utskriften genom att skriva över den med bakgrundsfärg och sedan
skriva det nya värdet med den aktuella textfärgen. Använd en sträng
old_str som medlemsvariabel i NOD-klassen som kommer ihåg det gamla
värdet på trycket och som skriver över trycket med bakgrundsfärg innan
det nya trycket skrivs ut. På samma sätt måste du göra med flödet i
VENTIL-klassen. Kontrollera nu att trycket i mittnoden regleras mot
ett korrekt konstant värde och att flödet genom ventilerna blir rätt.
Steg 7
Nästa steg är att kunna öppna och stänga ventilerna med musen. När man
klickar på en ventil ska det komma upp en meny i vilken man kan välja
'Öppna' eller 'Stäng'. Börja med att skaffa dig en ventilmeny genom
att från Toolboxen hämta en ContextMenu, placera den på valfri plats
på ditt formulär och skriv in alternativen Öppna och Stäng i menyn.
Skapa sedan en pekare till menyn och skicka den som parameter till
VENTIL-klassens konstruktor, precis som du gjorde med ritytan canvas.
Klicka sedan på formuläret och skaffa dig en händelsefunktion för
händelsen MouseDown där du anropar en klickfunktionen som du måste
skriva i VENTIL-klassen med parametrar i form av klickpositionens
koordinater e->get_X() resp. e->get_Y() och huvudfönstrets adress (som
är av typen Control^, eller om man vill vara mer specifik Form1^).
I klickfunktionen ska du jämföra musklickets
position med den aktuella ventilens position, visa menyn bredvid den
ventil som du klickat på med funktionen Show och returnera adressen
till den klickade ventilen.
Om det är fel ventil, ska funktionen returnera nullptr,
som är ref-klass-motsvarigheten till det vanliga NULL.
I händelsefunktonen MouseDown kollar huvudfönstret returvärdet från
klick-funktionen ventil för ventil och så fort det inte är nullptr slutar
den att kolla och sparar adressen till den utpekade ventilen i en
medlemsvariabel klickad_ventil. Skapa sedan händelsefunktioner för
alternativen 'Öppna' och 'Stäng' i din ventilmeny i form av Click för
båda. I dessa händelsefunktioner anropar du openoch close-funktionerna
i klassen VENTIL. Testkör!
Steg 8
Både noder och ventiler kan generaliseras till VVS-komponenter och
snart blir det fler sådana komponenter. Definiera en basklass VVS i
Vvs.h och Vvs.cpp, där medlemsvariabler som är gemensamma för alla
komponenter, som namn, rityta , meny, x- och y-koordinaten samlas och
där man har virtuella rita-, dynamik-, displayoch klickfunktioner, som
inget gör. Gör om NOD- och VENTIL-klassen till subklasser som ärver
från VVS. Gör de ärvda medlemsvariablerna protected i VVS-klassen så
kommer du åt dessa direkt i subklasserna.
Steg 9
När man bygger ut systemet är det lämpligt att alla VVS-objekten ingår
i en länkad lista. På detta sätt kan man bygga ut systemet genom att
enbart deklarera nya objekt. Loopar inne i händelsefunktionerna
arbetar igenom alla objekt i listan med hjälp av en next-pekare,
oberoende av hur många objekt där finns. Lägg till en next-pekare i
VVSklassen som pekar vidare till nästa objekt. Konstruktorn till
VVS-klassen anropas första gången med en nullptr-ställd listpekare som
sedan ändras till att peka på den skapade komponenten med hjälp av
this-pekaren samtidigt som next-pekaren ställs om att peka på
föregående komponent. Ändra i händelsefunktionerna så att de loopar
igenom en lista av komponenter där man anropar rita-, dynamik-,
display- och klickfunktionerna via listpekaren.
Steg 10
Skapa en klass PUMP i Pump.h och Pump.cpp. Pumpen ska ha liknande data
och funktioner som ventilerna. Dynamikfunktionen ska beräkna flödet
för en centrifugalpump enligt fysiken ovan, där k, a och b är
konstanter, varvtal är det normaliserade pumpvarvtalet och
tryckin resp. tryckut är trycket i
anslutningsnoderna på resp. sida. Konstanten k är en faktor som
begränsar flödet då trycket på ingångssidan närmar sig 0. I
verkligheten börjar pumpen sörpla, vattnet kommer stötvis. I modellen
kan man nöja sig med att begränsa flödet med en linjär funktion. För
enkelhets skull sätter vi den kritiska gränsen till 1.0 på intrycket.
Följande algoritm kan användas, där k kan vara en lokal variabel:
// k begränsar flödet
k = tryckin;
if ( k > 1.0 )
k = 1.0;
Varvtal är pumpens varvtal. Använd de normaliserade värdena varvtal =
1.0 om pumpen är igång och varvtal = 0.0 om pumpen ej är igång.
Konstanterna a och b har att göra med pumpkurvans form och initieras i
konstruktorn till 5.0 resp. 10.0. De behöver ej vara parametrar i
konstruktorn.
Låt pumpens displayfunktion visa flöde och varvtal. Skapa en ny
pumpmeny för pumpen med alternativen 'Starta' och 'Stoppa' precis som
du gjorde för ventilerna. Ändra testprogrammet genom att ersätta den
andra ventilen med en pump och därefter lägga in den andra ventilen
och en 4:de nod. Ändra trycket så att det blir samma i båda
gränsnoderna. Nu finns det en pump som står för flödet och som ger
tryckskillnad.
Steg 11
Skapa en FILTER-klass i Filter.h och Filter.cpp. Flödesekvationen är
densamma som för ventiler men där ventilkäglans position ersätts av
filteröppningen som kommer att minska kontinuerligt eftersom filtret
smutsas ner. Varje iteration sätter igen filtret något varvid
öppningen minskar lite enligt:
// igensättning av filter
filteröppning = filteröppning - g*flöde;
där g är ett mycket litet värde för positivt flöde (0.0001) och något
större för negativt. Ett negativt flöde (backflöde) innebär att
filtret spolas rent och filteröppningen ökar. Filtret ska ge larm med
blinkande rött ljus då öppningen understiger 0.5. Filtret ska ej kunna
manövreras och dess admittans kan som för ventilerna initieras till
10.
Steg 12
Skapa en klass för värmeväxlare VVXL i filerna Vvxl.h och Vvxl.cpp.
Flödesekvationen är likadan som för ventilerna men värmeväxlaren har
öppningen 1 hela tiden. Egentligen borde värmeväxlaren förses med
noder även för sekundärkretsen och dynamikfunktionen borde
kompletteras med ekvationer för värmeutbytet men detta skulle ej
behandlas i denna modell. Värmeväxlaren ska ej kunna manövreras.
Steg 13
Skapa nu det kompletta systemet. Alla pusselbitar ska nu finnas
färdiga. Testa systemet genom att starta pumpen och stänga ventilerna
v4 och v5. Flödet ska nu vara samma i alla seriekopplade komponenter
och filtret ska börja sättas igen. Reglera konstanten g så att
igensättningen av filtret sker med lämplig fart. Backspola filtret då
larmet går. Test alla krav enligt specifikationen och skriv rapport.
Förbättringar (* obligatoriska för betyget 4 och ** obligatoriska för betyget 5)
Steg 14 *
Komplettera systemet med en logfunktion. Varje manöver för de
manövrerbara komponenterna ska loggas i en textfil, Kylsim.log, där
komponentens namn, manövertyp, datum och tid skrivs in.
Steg 15 *
Dynamikfunktionen för noderna kan förbättras så att man reglerar
utgående ifrån felsignalens storlek och ej bara dess tecken som ovan.
Det är svårt att bedöma värdet på proportionalitetskonstanten m.
Följande algoritm trimmar sakta upp konstanten tills trycket börjar
självsvänga och när det självsvänger trimmas konstanten ner något.
// Reglera nod-trycket utgående från summaflöde
if (reglerbar) // om reglerbar
{
if ( fabs(sf) > 0.1 )
{
if ( sf * sf_old < 0 && fabs(sf) > fabs(sf_old) )
m *= 0.8;
else
m *= 1.05;
if ( m * fabs(sf) > 0.8 * p )
m = 0.8 * p / fabs(sf);
if ( m < 0.0001 )
m = 0.0001;
}
i += m * sf;
p = sf * m * 0.25 + i;
if ( p < 0.001 )
p = 0.001;
}
sf_old = sf;
sf = 0;
där p är trycket, sf är aktuellt summaflöde, sf_old är samma
summaflöde men från föregående iteration, m är
proportionalitetskonstanten och i är det integrerade felet. Du kan
sätta i=0.001 och m = 0.05 som medlemsvariabler i konstruktorn. De
behöver ej komma in som parametrar.
Steg 16 **
Att ändra ventilposition eller pumpvarvtal från 0 till 1 i ett steg är
ej realistiskt. Ventiler har en viss gångtid och pumpar har en
accelerationstid. Med klockan kan du få tidsintervallet mellan två
anrop av dynamikfunktionen. Genom att skicka detta tidsintervall (dt)
som parameter i dynamikfunktionen kan du öppna eller stänga ventilerna
på ett mer realistiskt sätt genom att komplettera dynamikfunktionen
med:
if (vp < set_vp)
{
vp += dt*gt;
if (vp > set_vp)
vp = set_vp;
}
else if (vp > set_vp)
{
vp -= dt*gt;
if (vp < set_vp)
vp = set_vp;
}
Komplettera VENTIL-klassen med medlemsvariabler för gångtidskonstant
gt och en variabel set_vp som betecknar önskad ventilposition. Låt
oppna- och stangfunktionen arbeta på set_vp istället för vp.
På samma
sätt kompletterar du PUMP-klassen för en realistisk acceleration vid
start och stopp.
Steg 17 **
Komplettera popupmenyerna med alternativ för att ändra
gångtidskonstanten, gt. När man väljer ett sådant alternativ ska en
dialogbox dyka upp som frågar efter ett nytt värde på gångtiden. Det
nya värdet ska läsas in säkert.
Steg 18 **
Komplettera FILTER-klassen med en säkerhetsfunktion som gör att
filterobjektet rensar sig självt, då genomsläppligheten minskat till
0.2. Rensningen ska hanteras av filterobjektet.