doc: (almost) finish the design patterns chapter in the handbook

also remove the ReferenceElements property because changing to the old
DUNE entity numbering would not work anyways...
This commit is contained in:
Andreas Lauser 2010-11-08 18:02:44 +00:00 committed by Andreas Lauser
parent 99e13c14fe
commit 02ddfea028
10 changed files with 21692 additions and 188 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,554 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1035.3572"
height="581.78564"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="car-propertynames.svg">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible">
<path
id="path3793"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<linearGradient
id="linearGradient3624">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624"
id="radialGradient3630"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<inkscape:perspective
id="perspective3640"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-4"
id="radialGradient3630-0"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-4">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-7" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-6" />
</linearGradient>
<inkscape:perspective
id="perspective3640-9"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-8"
id="radialGradient3630-06"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-8">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-79" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-0" />
</linearGradient>
<inkscape:perspective
id="perspective3640-3"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient3630-7"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-3">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-2" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-65" />
</linearGradient>
<inkscape:perspective
id="perspective3640-5"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-7"
id="radialGradient3630-8"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-7">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-9" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-60" />
</linearGradient>
<radialGradient
r="154.82143"
fy="-38.634254"
fx="117.96088"
cy="-38.634254"
cx="117.96088"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,401.50169,134.21685)"
gradientUnits="userSpaceOnUse"
id="radialGradient3649-4"
xlink:href="#linearGradient3624-7"
inkscape:collect="always" />
<inkscape:perspective
id="perspective3640-0"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-87"
id="radialGradient3630-4"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-87">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-0" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-8" />
</linearGradient>
<radialGradient
r="154.82143"
fy="-38.634254"
fx="117.96088"
cy="-38.634254"
cx="117.96088"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,364.35883,551.34436)"
gradientUnits="userSpaceOnUse"
id="radialGradient3649-6"
xlink:href="#linearGradient3624-87"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient3777"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,-501.35545,-167.22707)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-4"
id="radialGradient3779"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,-85.641168,-148.65564)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-8"
id="radialGradient3783"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,332.93026,-141.51278)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<inkscape:perspective
id="perspective4243"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-9"
style="overflow:visible">
<path
id="path3793-3"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:perspective
id="perspective4271"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-2"
style="overflow:visible">
<path
id="path3793-8"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:perspective
id="perspective4299"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-0"
style="overflow:visible">
<path
id="path3793-1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:perspective
id="perspective4327"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-8"
style="overflow:visible">
<path
id="path3793-9"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="116.87789"
inkscape:cy="598.80626"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1180"
inkscape:window-x="-3"
inkscape:window-y="-3"
inkscape:window-maximized="1">
<sodipodi:guide
orientation="0,1"
position="1216.25,580.53564"
id="guide3781" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(333.39286,111.74492)">
<g
id="g3766"
transform="translate(-771.42857,-160.96781)">
<rect
ry="24.285715"
y="223.09183"
x="439.28571"
height="61.42857"
width="307.14285"
id="rect2816-1"
style="color:#000000;fill:url(#radialGradient3649-4);fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2830"
y="268.7182"
x="530.60126"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="268.7182"
x="530.60126"
id="tspan2832"
sodipodi:role="line">Sedan</tspan><tspan
id="tspan2834"
y="318.7182"
x="530.60126"
sodipodi:role="line" /></text>
</g>
<g
id="g3761"
transform="translate(-84.999983,123.80949)">
<rect
ry="24.285715"
y="110.93361"
x="115.71429"
height="61.42857"
width="307.14285"
id="rect2816"
style="color:#000000;fill:url(#radialGradient3630);fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2836"
y="152.68304"
x="203.84625"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="152.68304"
x="203.84625"
id="tspan2838"
sodipodi:role="line">Pickup</tspan></text>
</g>
<g
id="g3772"
transform="translate(-8.5713543,-232.85715)">
<rect
ry="24.285715"
y="640.2193"
x="402.14285"
height="61.42857"
width="307.14285"
id="rect2816-2"
style="color:#000000;fill:url(#radialGradient3649-6);fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2848"
y="685.23047"
x="434.20062"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="685.23047"
x="434.20062"
id="tspan2850"
sodipodi:role="line">Hummer H1</tspan></text>
</g>
<g
id="g3746"
transform="translate(131.42858,-32.142813)">
<rect
ry="24.285715"
y="-78.352104"
x="-463.57144"
height="61.42857"
width="307.14285"
id="rect2816-6"
style="color:#000000;fill:url(#radialGradient3777);fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818"
y="-36.954224"
x="-441.49414"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824"
y="-36.954224"
x="-441.49414"
sodipodi:role="line">Compact Car</tspan></text>
</g>
<g
id="g3751"
transform="translate(78.571443,-50.714243)">
<rect
ry="24.285715"
y="-59.780674"
x="-47.85714"
height="61.42857"
width="307.14285"
id="rect2816-8"
style="color:#000000;fill:url(#radialGradient3779);fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2840"
y="-14.15428"
x="52.999443"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="-14.15428"
x="52.999443"
id="tspan2842"
sodipodi:role="line">Truck</tspan></text>
</g>
<g
id="g3756"
transform="translate(22.857204,-57.8571)">
<rect
ry="24.285715"
y="-52.637817"
x="370.71429"
height="61.42857"
width="307.14285"
id="rect2816-3"
style="color:#000000;fill:url(#radialGradient3783);fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2844"
y="-9.0663891"
x="472.85715"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
y="-9.0663891"
x="472.85715"
id="tspan2846"
sodipodi:role="line">Tank</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
d="m -178.57144,-50.494961 0,107.856887"
id="path3785"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
d="m 184.28573,-47.280549 0,276.428319"
id="path3785-9"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
d="m 547.14292,-48.709121 0,450.174561"
id="path3785-9-3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
d="M -178.57144,124.65179 33.560595,236.54929"
id="path3785-7"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
d="m 184.85791,297.38788 212.13203,111.8975"
id="path3785-7-1"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,820 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="510.65839"
height="508.60782"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="car-propertynames.svg">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible">
<path
id="path3793"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<linearGradient
id="linearGradient3624">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<inkscape:perspective
id="perspective3640"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-4"
id="radialGradient3630-0"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-4">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-7" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-6" />
</linearGradient>
<inkscape:perspective
id="perspective3640-9"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-8"
id="radialGradient3630-06"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-8">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-79" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-0" />
</linearGradient>
<inkscape:perspective
id="perspective3640-3"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient3630-7"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-3">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65" />
</linearGradient>
<inkscape:perspective
id="perspective3640-5"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-7"
id="radialGradient3630-8"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-7">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-9" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-60" />
</linearGradient>
<inkscape:perspective
id="perspective3640-0"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-87"
id="radialGradient3630-4"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,77.93026,22.058642)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3624-87">
<stop
style="stop-color:#ffccaa;stop-opacity:0;"
offset="0"
id="stop3626-0" />
<stop
style="stop-color:#ffccaa;stop-opacity:1;"
offset="1"
id="stop3628-8" />
</linearGradient>
<inkscape:perspective
id="perspective4243"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-9"
style="overflow:visible">
<path
id="path3793-3"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:perspective
id="perspective4271"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-2"
style="overflow:visible">
<path
id="path3793-8"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:perspective
id="perspective4299"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-0"
style="overflow:visible">
<path
id="path3793-1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<inkscape:perspective
id="perspective4327"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-8"
style="overflow:visible">
<path
id="path3793-9"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient4540"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,-369.92687,-199.36988)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<inkscape:perspective
id="perspective4682"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7"
id="radialGradient4540-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,-369.92687,-199.36988)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<linearGradient
id="linearGradient3624-3-7">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2-8" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65-2" />
</linearGradient>
<radialGradient
r="154.82143"
fy="-38.634254"
fx="117.96088"
cy="-38.634254"
cx="117.96088"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
gradientUnits="userSpaceOnUse"
id="radialGradient4693"
xlink:href="#linearGradient3624-3-7"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7"
id="radialGradient4723"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<inkscape:perspective
id="perspective4738"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-0"
id="radialGradient4723-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<linearGradient
id="linearGradient3624-3-7-0">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2-8-2" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65-2-0" />
</linearGradient>
<inkscape:perspective
id="perspective4738-1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-07"
id="radialGradient4723-2"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<linearGradient
id="linearGradient3624-3-7-07">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2-8-3" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65-2-1" />
</linearGradient>
<inkscape:perspective
id="perspective4738-7"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-4"
id="radialGradient4723-7"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<linearGradient
id="linearGradient3624-3-7-4">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2-8-0" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65-2-6" />
</linearGradient>
<inkscape:perspective
id="perspective4738-5"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-2"
id="radialGradient4723-8"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<linearGradient
id="linearGradient3624-3-7-2">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2-8-6" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65-2-06" />
</linearGradient>
<inkscape:perspective
id="perspective4738-6"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-7"
id="radialGradient4723-0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-297.23817,-95.263514)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<linearGradient
id="linearGradient3624-3-7-7">
<stop
style="stop-color:#aaccff;stop-opacity:0;"
offset="0"
id="stop3626-2-8-01" />
<stop
style="stop-color:#abaaff;stop-opacity:1;"
offset="1"
id="stop3628-65-2-01" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient4865"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22529395,0.74034487,-0.6737436,0.2050266,-369.92687,-199.36988)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient4870"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.37222048,0.73916728,-1.1131288,0.20470048,-394.48823,-198.87502)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7"
id="radialGradient4875"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,-121.57274)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-0"
id="radialGradient4880"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,-45.041711)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-07"
id="radialGradient4885"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,31.489319)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-4"
id="radialGradient4890"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,108.02036)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-2"
id="radialGradient4895"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,184.55139)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-7"
id="radialGradient4900"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.22383877,0.73556295,-0.66939186,0.20370232,-369.96915,261.32034)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-2"
id="radialGradient4932"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,184.55139)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3"
id="radialGradient4934"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.37222048,0.73916728,-1.1131288,0.20470048,-394.48823,-198.87502)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-4"
id="radialGradient4936"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,108.02036)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-07"
id="radialGradient4938"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,31.489319)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7-0"
id="radialGradient4940"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,-45.041711)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3624-3-7"
id="radialGradient4942"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.36981629,0.73439296,-1.105939,0.20337831,-394.09834,-121.57274)"
cx="117.96088"
cy="-38.634254"
fx="117.96088"
fy="-38.634254"
r="154.82143" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="480.81912"
inkscape:cy="235.68721"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1180"
inkscape:window-x="-3"
inkscape:window-y="-3"
inkscape:window-maximized="1">
<sodipodi:guide
orientation="0,1"
position="1216.5287,507.35588"
id="guide3781" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(333.67159,111.74684)">
<g
id="g4927"
transform="translate(-0.00299716,0)">
<rect
ry="0"
y="-110.14142"
x="-332.06317"
height="61.33086"
width="507.44754"
id="rect2816-6"
style="color:#000000;fill:url(#radialGradient4934);fill-opacity:1;stroke:#000000;stroke-width:3.21084785;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818"
y="-69.097038"
x="-310.34381"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824"
y="-69.097038"
x="-310.34381"
sodipodi:role="line">GasUsage</tspan></text>
</g>
<g
id="g4922"
transform="translate(0,12.323853)">
<rect
ry="0"
y="-33.412281"
x="-332.07654"
height="60.934723"
width="504.16992"
id="rect2816-6-5"
style="color:#000000;fill:url(#radialGradient4942);fill-opacity:1;stroke:#000000;stroke-width:3.19010878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818-3"
y="7.5559573"
x="-311.34378"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824-4"
y="7.5559573"
x="-311.34378"
sodipodi:role="line">TopSpeed</tspan></text>
</g>
<g
id="g4917"
transform="translate(0,24.647736)">
<rect
ry="0"
y="43.118752"
x="-332.07654"
height="60.934723"
width="504.16992"
id="rect2816-6-5-9"
style="color:#000000;fill:url(#radialGradient4940);fill-opacity:1;stroke:#000000;stroke-width:3.19010878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818-3-6"
y="84.208916"
x="-311.34378"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824-4-2"
y="84.208916"
x="-311.34378"
sodipodi:role="line">NumSeats</tspan></text>
</g>
<g
id="g4912"
transform="translate(0,36.971619)">
<rect
ry="0"
y="119.64978"
x="-332.07654"
height="60.934723"
width="504.16992"
id="rect2816-6-5-0"
style="color:#000000;fill:url(#radialGradient4938);fill-opacity:1;stroke:#000000;stroke-width:3.19010878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818-3-5"
y="160.86186"
x="-311.34378"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824-4-6"
y="160.86186"
x="-311.34378"
sodipodi:role="line">AutomaticTransmission</tspan></text>
</g>
<g
id="g4907"
transform="translate(0,49.295471)">
<rect
ry="0"
y="196.18082"
x="-332.07654"
height="60.934723"
width="504.16992"
id="rect2816-6-5-7"
style="color:#000000;fill:url(#radialGradient4936);fill-opacity:1;stroke:#000000;stroke-width:3.19010878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818-3-4"
y="237.51483"
x="-311.34378"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824-4-8"
y="237.51483"
x="-311.34378"
sodipodi:role="line">CannonCalibre</tspan></text>
</g>
<g
id="g4902"
transform="translate(0,61.619305)">
<rect
ry="0"
y="272.71188"
x="-332.07654"
height="60.934723"
width="504.16992"
id="rect2816-6-5-4"
style="color:#000000;fill:url(#radialGradient4932);fill-opacity:1;stroke:#000000;stroke-width:3.19010878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text2818-3-62"
y="314.16779"
x="-311.34378"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
id="tspan2824-4-89"
y="314.16779"
x="-311.34378"
sodipodi:role="line">Payload</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -866,8 +866,23 @@
key = {DUNE}
}
@MISC{FENICS-HP,
title = {The {FEniCS} Project: \url{http://www.fenicsproject.org/}},
key = {FENICS}
}
@MISC{STL-REF-HP,
title = {A {STL} Reference: \url{http://www.cplusplus.com/reference/stl/}},
key = {STL}
}
@MISC{BOOST-HP,
title = {The {Boost} Homepage: \url{http://www.boost.org/}},
key = {BOOST}
}
@MISC{UG-HP,
title = {The {UG} Homepage: \url{http://sit.iwr.uni-heidelberg.de/~ug/}},
title = {The {UG} Homepage: \url{http://atlas.gcsc.uni-frankfurt.de/~ug/}},
key = {UG}
}

View File

@ -19,6 +19,7 @@
\usepackage{lscape}
\usepackage{enumerate}
\usepackage{rotating}
\usepackage{subfig}
\DeclareGraphicsExtensions{.eps, .jpg}

View File

@ -1,29 +1,108 @@
\chapter{The \Dumux Property System}
\label{sec:propertysytem}
\chapter{\Dumux Design Patterns}
\label{chap:DesignPatterns}
This chapter tries to give high-level understanding of the motivation
for the \Dumux property system and how to use it. First, an
introduction to polymorphism is given. After this, the fundamental
motivation and the ideas behind the \Dumux property system are
highlighted and the implementation is outlined from a high-level
This chapter tries to give high-level understanding of some of the
fundamental techniques which are used by \Dumux and the motivation
behind these design decisions. It is assumed that the reader already
posseses some basic knowledge in object oriented programming with C++.
First, a quick motivation of C++ template programming is given. Then
follows an introduction to polymorphism and the opportunities for it
opened by the template mechanism. After that, there is a look at some
drawbacks associated with template programming. One of these drawbacks
-- deep nesting of template parameters -- motivates the \Dumux
property system which, in this chapter is outlined from the user
perspective. The chapter concludes with a simple example of how to use
the \Dumux property system.
\section{C++ Template Programming}
One of the main features of modern versions of the C++ language is
robust support for templates. Templates are a mechanism for code
generation build directly into the compiler. To see the motivation of
templates, consider a linked list of \texttt{double} values which
could be implemented like this:
\begin{verbatim}
struct DoubleList {
DoubleList(const double &val, DoubleList *prevNode = 0)
{ value = val; if (prevNode) prevNode->next = this; };
double value;
DoubleList *next;
};
int main() {
DoubleList *head, *tail;
head = tail = new DoubleList(1.23);
tail = new DoubleList(2.34, tail);
tail = new DoubleList(3.56, tail);
};
\end{verbatim}
But what if a list of strings is also required? The only ``clean'' way
to achive this without templates would be to copy
\texttt{DoubleListNode}, then rename it and change the type of the
\texttt{value} attribute. It should be clear that this is a very
cumbersome and error-prone process, so recent standards of the C++
programming language provide the template mechanism, which is a way
let the compiler do the tedious work. Using templates, a generic
linked list can be implemented like this:
\begin{verbatim}
template <class ValueType>
struct List {
List(const ValueType &val, List *prevNode = 0)
{ value = val; if (prevNode) prevNode->next = this; };
ValueType value;
List *next;
};
int main() {
typedef List<double> DoubleList;
DoubleList *head, *tail;
head = tail = new DoubleList(1.23);
tail = new DoubleList(2.34, tail);
tail = new DoubleList(3.56, tail);
typedef List<const char*> StringList;
StringList *head2, *tail2;
head2 = tail2 = new StringList("Hello");
tail2 = new StringList(", ", tail2);
tail2 = new StringList("World!", tail2);
};
\end{verbatim}
Compared to code generation approaches using external tools -- which
is the approach chosen for example by the FEniCS~\cite{FENICS-HP}
project -- or heavy use of the C preprocessor -- as done for example
within the UG framework~\cite{UG-HP} -- the template approach has
several advantages:
\begin{description}
\item[Well Programmable:] Programming errors are directly detected by
the C++ compiler and compiler messages also yield useful information
since the actual source code is visible to the developer and not
obfuscated by macros or code generation.
\item[Easily Debugable:] Programs which use the template mechanism can be
debugged almost as easily as C++ programs which do not use
templates. This is due to the fact that the debugger always knows
the ``real'' source file and line number.
\end{description}
For these reasons \Dune and \Dumux extensively use the template
mechanism. Both projects also try to avoid duplicating functionality
provided by the Standard Template Library (STL,~\cite{STL-REF-HP})
which is part of the C++ standard and functionality provided by the
quasi-standard Boost~\cite{BOOST-HP} libraries.
\section{Polymorphism}
In object oriented programming, it often happens that some
functionality make sense for all classes in a hierarchy, but what
actually need to be \textit{done} can be quite different. This
observation gives rise to \textit{polymorphism}. In polymorphism, a
call to an object's method \textit{means} the same thing, but how this
method is \textit{implemented} is case specific\footnote{This
\textit{poly} of polymorphism: There are multiple ways to achieve
the same goal.}.
In object oriented programming, some functionality often makes sense
for all classes in a hierarchy, but what actually needs to be
\textit{done} can differ for each concrete class. This observation
motivates \textit{polymorphism}. Fundamentally, polymorphism is all
techniques where a method call results in the processor executing code
which is specific to the type of object for which the method is
called\footnote{This is \textit{poly} of polymorphism: There are
multiple ways to achieve the same goal.}.
In C++, there are two common approaches to polymorphism: The
traditional -- i.e. non-template programming -- dynamic polymorphism,
and static polymorphism which is made possible by template
programming.
In C++, there are two common ways to achieve polymorphism: The
traditional dynamic polymorphism which is not based on template
programming, and static polymorphism which is only made possible by
template programming.
\subsection*{Dynamic Polymorphism}
@ -36,8 +115,8 @@ of each method which is declared virtual. If such a method is called
on an object, the compiler generates code which retrieves the method's
address from the object's \texttt{vtable} and then calls it. This
explains why this mechanism is called \textbf{dynamic} polymorphism:
the methods which are actually called are dynamically determined at
run time.
the code which is actually called are dynamically determined at run
time.
\begin{example}
\label{example:DynPoly}
@ -63,7 +142,7 @@ class Car
double range(double fuelTankFillLevel)
{ return 100*fuelTankFillLevel*fuelTankSize()/gasUsage(); }
}
};
\end{verbatim}
Actual car models can now derived from the base class:
@ -73,14 +152,14 @@ class S : public Car
{public:
virtual double gasUsage() { return 9.0; };
virtual double fuelTankSize() { return 65.0; };
}
};
// A VW Lupo
class Lupo : public Car
{public:
virtual double gasUsage() { return 2.99; };
virtual double fuelTankSize() { return 30.0; };
}
};
\end{verbatim}
The \text{range} method called on the base class yields correct result
@ -93,13 +172,12 @@ int main()
{
Lupo lupo;
S s;
std::cout << "VW Lupo:"
std::cout << "VW Lupo:";
std::cout << "Median range: " << lupo.range(0.50) << "\n";
printMaxRange(lupo);
std::cout << "Mercedes S-Class:"
std::cout << "Mercedes S-Class:";
std::cout << "Median range: " << s.range(0.50) << "\n";
printMaxRange(s);
return 0;
}
\end{verbatim}
@ -123,27 +201,28 @@ What happens if \dots
\subsection*{Static Polymorphism}
Static polymorphism has a few disadvantages, probably the most
Dynamic polymorphism has a few disadvantages, probably the most
relevant in the context of \Dumux is that the compiler can not see
``inside'' the called methods and thus cannot properly optimize
them. For example modern C++ compilers 'inline' short methods, that is
they copy the body the function body to where it is called which saves
a few instructions as well as allows further optimizations across the
function call. Inlining and other cross call optimizations are next to
impossible in conjunction with dynamic polymorphism, since these
``inside'' the called methods and thus cannot properly optimize. For
example modern C++ compilers 'inline' short methods, i.e. they copy
the body the method's body to where it is called. This allows to save
a few instructions as well as enables further optimizations which may
depend on specific properties of the function arguments (e.g. constant
value elimination, etc). Inlining and other cross-method optimizations
are next to impossible when using dynamic polymorphism, since these
techniques need to be done by the compiler (i.e. at compile time)
while the actual code which gets called is only determined at run time
for virtual methods. To overcome this issue, template programming
allows a compile time polymorphism. This scheme works by supplying an
additional template parameter to the base class which specifies the
type of the derived class. Whenever the base class needs to call back
at the derived class, the memory of the current object is
while, for virtual methods, the actual code that gets executed is
determined at run time. To overcome this issue, template programming
can be used to achive polymorphism at compile time. This works by
supplying the type of the derived class as an additional template
parameter to the base class. Whenever the base class needs to call
back the derived class, the \texttt{this} pointer of the base class is
reinterpreted as a derived object and the method is then called. This
scheme gives the C++ compiler complete transparency of the code
executed and thus opens for much better optimization
oportunities. Also, since this mechanism completely happens at compile
time, it is called ``static polymorphism'' because the called method
cannot be changed dynamically at runtime.
executed and thus opens much better optimization oportunities. Since
this mechanism completely happens at compile time, it is called
``static polymorphism'' because the called method cannot be changed
dynamically at runtime.
\begin{example}
Using static polymorphism, the base class of example \ref{example:DynPoly}
can be written as
@ -156,17 +235,15 @@ class Car
double gasUsage()
{ return 4.5; };
double fuelTankSize()
{ throw "The derived class needs to implement the fuelTankSize() method" };
{ throw "The derived class needs to implement the fuelTankSize() method"; };
double range(double fuelTankFillLevel)
{ return 100*fuelTankFillLevel*asImp_().fuelTankSize()/asImp_().gasUsage(); }
protected:
// reinterpret the 'this' object as an object of type 'Imp'
// reinterpret 'this' as a pointer to an object of type 'Imp'
Imp &asImp_() { return *static_cast<Imp*>(this); }
// version for constant 'this' objects
const Imp &asImp_() const { return *static_cast<const Impl*>(this); }
}
};
\end{verbatim}
(Note the \texttt{asImp\_()} calls in the \texttt{range} method.)
@ -177,14 +254,14 @@ class S : public Car<S>
{public:
double gasUsage() { return 9.0; };
double fuelTankSize() { return 65.0; };
}
};
// A VW Lupo
class Lupo : public Car<Lupo>
{public:
double gasUsage() { return 2.99; };
double fuelTankSize() { return 30.0; };
}
};
\end{verbatim}
\end{example}
@ -199,10 +276,10 @@ int main()
{
Lupo lupo;
S s;
std::cout << "VW Lupo:"
std::cout << "VW Lupo:";
std::cout << "Median range: " << lupo.range(0.50) << "\n";
printMaxRange(lupo);
std::cout << "Mercedes S-Class:"
std::cout << "Mercedes S-Class:";
std::cout << "Median range: " << s.range(0.50) << "\n";
printMaxRange(s);
return 0;
@ -211,87 +288,418 @@ int main()
\textbf{TODO: Exercise}
\subsection*{Explosion of Template Arguments}
\section{Common Template Programming Related Problems}
A major drawback with template programming in general and with static
polymorphism in particular is that the template arguments required for
the base class tend to explode quickly. This is due to the fact that
often template arguments are often used as arguments for other
template classes. To demonstrate this point consider the local
jacobian class of the two-phase, two-component box model before the
\Dumux property system was introduced:
Although C++ template programming opens a few intriguing
possibilities, it also has a few disadvantages. In this section a few
of those are outlined and some hints how they can be dealt with are
provided.
\subsection*{Blow-Up of Identifiers}
One particular problem with advanced use of templates is that the full
identifier names for types and methods quickly become really long and
unreadable. For example a typical line of an error message generated
using GCC 4.5 in conjunction with \Dune-PDELab looks like
\begin{verbatim}
template<class ProblemT, class BoxTraitsT, class TwoPTwoCTraitsT>
class TwoPTwoCBoxJacobian
: public TwoPTwoCBoxJacobianBase<
ProblemT,
BoxTraitsT,
TwoPTwoCTraitsT,
TwoPTwoCElementData<TwoPTwoCTraitsT,ProblemT>,
TwoPTwoCVertexData<TwoPTwoCTraitsT,ProblemT>,
TwoPTwoCFluxData<TwoPTwoCTraitsT,
ProblemT,
TwoPTwoCVertexData<TwoPTwoCTraitsT,
ProblemT> >,
TwoPTwoCBoxJacobian<ProblemT,
BoxTraitsT,
TwoPTwoCTraitsT> >
{
// ...
}
test_pdelab.cc:171:9: error: no matching function for call to Dune::\
PDELab::GridOperatorSpace<Dune::PDELab::PowerGridFunctionSpace<Dune::\
PDELab::GridFunctionSpace<Dune::GridView<Dune::DefaultLeafGridViewTraits\
<const Dune::UGGrid<3>, (Dune::PartitionIteratorType)4u> >, Dune::\
PDELab::Q1LocalFiniteElementMap<double, double, 3>, Dune::PDELab::\
NoConstraints, Dumux::PDELab::BoxISTLVectorBackend<Dumux::Properties::\
TTag::LensProblem> >, 2, Dune::PDELab::GridFunctionSpaceBlockwiseMapper>\
, Dune::PDELab::PowerGridFunctionSpace<Dune::PDELab::GridFunctionSpace<\
Dune::GridView<Dune::DefaultLeafGridViewTraits<const Dune::UGGrid<3>, \
(Dune::PartitionIteratorType)4u> >, Dune::PDELab::Q1LocalFiniteElementMap\
<double, double, 3>, Dune::PDELab::NoConstraints, Dumux::PDELab::\
BoxISTLVectorBackend<Dumux::Properties::TTag::LensProblem> >, 2, Dune::\
PDELab::GridFunctionSpaceBlockwiseMapper>, Dumux::PDELab::BoxLocalOperator\
<Dumux::Properties::TTag::LensProblem>, Dune::PDELab::\
ConstraintsTransformation<long unsigned int, double>, Dune::PDELab::\
ConstraintsTransformation<long unsigned int, double>, Dune::PDELab::\
ISTLBCRSMatrixBackend<2, 2>, true>::GridOperatorSpace()
\end{verbatim}
This seriously complicates diagnostics. Although there is no full
solution for this problem yet, an effective way of dealing with such
kinds of error messages is to ignore the type information and to just
go to the location given at the beginning of the line and also
consider the error text. If nested templates are used and the given
location looks well, the lines above the actual error specify how
exactly the code was instantiated by the compiler (the lines starting
with \texttt{instantiated from}). In this case it is advisable to look
at the innermost location of the code which has been most recently
added.
\subsection*{Proliferation of Template Parameters}
Writing flexible templates often requires a large -- and in some cases
even unknown -- number of template parameters. As an example, the type
of the global operator space from \Dune-PDELab which produced the error
message above is specified like this:
\begin{verbatim}
enum {numEq = 2};
enum {dim = 2};
typedef Dune::UGGrid<2> Grid;
typedef Grid::LeafGridView GridView;
typedef Dune::PDELab::Q1LocalFiniteElementMap<double,double,dim> FEM;
typedef TTAG(LensProblem) TypeTag;
typedef Dune::PDELab::NoConstraints Constraints;
typedef Dune::PDELab::GridFunctionSpace<
GridView, FEM, Constraints, Dumux::PDELab::BoxISTLVectorBackend<TypeTag>
>
doubleGridFunctionSpace;
typedef Dune::PDELab::PowerGridFunctionSpace<
doubleGridFunctionSpace,
numEq,
Dune::PDELab::GridFunctionSpaceBlockwiseMapper
>
GridFunctionSpace;
typedef typename GridFunctionSpace::ConstraintsContainer<double>::Type
ConstraintsTrafo;
typedef Dumux::PDELab::BoxLocalOperator<TypeTag> LocalOperator;
typedef Dune::PDELab::GridOperatorSpace<
GridFunctionSpace,
GridFunctionSpace,
LocalOperator,
ConstraintsTrafo,
ConstraintsTrafo,
Dune::PDELab::ISTLBCRSMatrixBackend<numEq, numEq>,
true
>
GOS;
GOS gos; // instantiate grid operator space
\end{verbatim}
Although the code above is not really intuitive, it is not a big
problem if the type in case the grid operator space is only required
at exactly one location. If, on the other hand, it needs to be
consistend over many locations in the source code, something has to be
done in order to keep the code maintainable. The next section outlines
approaches on how to tackle this particular problem.
% \begin{frame}[fragile]
% \frametitle{Nested template arguments}
\section{The \Dumux Property System}
\label{sec:propertysystem}
% One problem of static Polymorphism:
% \begin{itemize}
% \item Template arguments often also require template parameters
% \item ``Implementation'' arguments are especially nasty:
% \begin{itemize}
% \item Assume a base class Base<A, B, Imp>
% \item Assume a class Derived<B> and that A is C< Derived<B> >
% \item To specify Derived:
% \end{itemize}
% \end{itemize}
% {\scriptsize
% \begin{verbatim}
% template <class B>
% class Derived : public Base< C<Derived<B> >, B, Derived<B> >
% \end{verbatim}
% }
% \end{frame}
This section is dedicated to means on how to solve the problem of
template argument proliferation. First, a short look on the more
traditional approach using traits classes is taken, then the design of
the \Dumux property system is explained and finally a short example on
how the system can be used is given.
% \begin{frame}[fragile]
% \frametitle{A real-world example}
\subsection*{Traits Classes}
% {\scriptsize
% }
% \end{frame}
A classic approach to reduce the number of template parameters is to
gather the all arguments in a special class, a so-called traits
class. For example instead of writing
\begin{verbatim}
template <class A, class B, class C, class D>
class MyClass {};
\end{verbatim}
one can use
\begin{verbatim}
template <class Traits>
class MyClass {};
\end{verbatim}
where the \texttt{Traits} class contains public type definitions for
\texttt{A}, \texttt{B}, \texttt{C} and \texttt{D}, e.g.
\begin{verbatim}
struct MyTraits
{
typedef float A;
typedef double B;
typedef short C;
typedef int D;
};
\end{verbatim}
% \begin{frame}[fragile]
% \frametitle{Traits}
% A possible solution is to specify a class which specifies the
% template parameters as type definitions (often called a Traits
% class): {\scriptsize
% \begin{verbatim}
% class Traits
% { public:
% typedef int A;
% typedef C<A> B;
% };
As there is no a free lunch, the traits approach comes with a few
disadvantages of its own:
\begin{enumerate}
\item Trait class hierarchies are problematic. This is due to the fact
that type defintions must always be defined for the lowest level
traits class if it is to be used by higher level classes.
\item Traits quickly lead to circular dependencies. This implies that
types can not be extracted from classes which get the trait class as
an argument.
\end{enumerate}
% template <class Traits, class Implementation>
% class Base {};
To see the point of the first issue, consider the following example:
\begin{verbatim}
struct MyBaseTraits {
typedef int Scalar;
typedef std::vector<Scalar> Vector;
};
% template <class Traits>
% class Derived : public class Base<Traits, Derived<Traits>
% {};
% \end{verbatim}
% }
struct MyDerivedTraits : public MyBaseTraits {
typedef double Scalar;
};
int main() {
MyDerivedTraits::Vector v{1.41421, 1.73205, 2};
for (int i = 0; i < v.size(); ++i)
std::cout << v[i]*v[i] << std::endl;
}
\end{verbatim}
Contrary to what is wanted, the \texttt{v} variable is a vector of
integers. In this case, static polymorphsism does not come to rescue,
since it would lead to a dependency cycle between
\texttt{MyBaseTraits} and \texttt{MyDerivedTraits}.
The second point is illuminated by the following example, where one
would expect the \texttt{MyTraits::\-VectorType} to be \texttt{std::vector<double>}:
\begin{verbatim}
template <class Traits>
class MyClass {
public: typedef double ScalarType;
private: typedef typename Traits::VectorType VectorType;
};
struct MyTraits {
typedef MyClass<MyTraits>::ScalarType ScalarType;
typedef std::vector<ScalarType> VectorType
};
\end{verbatim}
Although this example seems to be quite pathetic, it is often useful
in reality to specify parameters in such a way.
\subsection*{Features of the \Dumux Property System}
To get around the issues with traits classes, the \Dumux property
system was designed. It can be seen as a traits system which allows
easy type inheritance and any acyclic dependency of types. The scope
at which the property system is executed is completely compile
time. It is based on the following concepts:
\begin{itemize}
\item[Property:] In the context of the \Dumux property system, a
property is an arbitrary class body which may contain type
definitions, values and methods. Each property has a so-called
\textbf{property tag} which can be seen as a label with its name.
\item[Property Inheritance:] Properties can be arranged in
hierarchies, just like normal classes. Each in the context of the
\Dumux property system the nodes in the inhertitance hierarchy on
which the property is defined are called \textbf{type tags}.
\item[Property Nesting:] The definition of a property can depend on
the value of other properties (as long as there are no cyclic
dependencies).
\item[Introspection:] The \Dumux property systems supports
\textbf{diagnostic messages} which can be used to find out how a
certain property was inherited and where it was defined.
\end{itemize}
\subsection*{\Dumux Property System Reference}
All files where the \Dumux property system is utilized should include
the header file \texttt{dumux/common/propertysystem.hh}, declaration
of new type tags and property tags as well as property definitions
must be done inside the namespace \texttt{Dumux::Properties}.
\subsection*{Defining Type Tags}
New nodes in the type tag hierarchy can be defined using
\begin{verbatim}
NEW_TYPE_TAG(NewTypeTagName, INHERITS_FROM(BaseTagName1, BaseTagName2, ...));
\end{verbatim}
where the \texttt{INHERITS\_FROM} part is optional. To avoid
inconsistencies in the hierarchy, type tags may only be defined
exactly once in the whole program.
\subsubsection*{Declaring Property Tags}
New property tags -- i.e. labels for properties -- are be declared
using
\begin{verbatim}
NEW_PROP_TAG(NewPropTagName);
\end{verbatim}
A property tag can be declared arbitrarily often inside a program, in
fact it is recomended that all properties are declared in each file
where they are used.
\subsubsection*{Defining Properties}
The actual value of a property on a given node of the type tag
hierarchy is defined using
\begin{verbatim}
SET_PROP(TypeTagName, PropertyTagName)
{
// arbitrary body of a struct
};
\end{verbatim}
For each a program, a property itself can be declared at most once,
although properties may be overwritten at derived type tags.
Also, the following convenience macros available to define simple
properties:
\begin{verbatim}
SET_TYPE_PROP(TypeTagName, PropertyTagName, type);
SET_BOOL_PROP(TypeTagName, PropertyTagName, booleanValue);
SET_INT_PROP(TypeTagName, PropertyTagName, integerValue);
SET_SCALAR_PROP(TypeTagName, PropertyTagName, floatingPointValue);
\end{verbatim}
\subsubsection*{Unsetting Properties}
\subsubsection*{Converting Tag Names to Tag Types}
For the C++ compiler property and type tags look like ordinary
types. Both can thus be used as template or function arguments,
etc. To convert the name of a property tag or a type tag into the
corrosponding type, the macros \texttt{TTAG(TypeTagName)} and
\texttt{PTAG(PropertyTagName)} ought to be used.
\subsubsection*{Retrieving Property Values}
\begin{verbatim}
GET_PROP(TypeTag, PropertyTag)
\end{verbatim}
Convenience macros:
\begin{verbatim}
GET_PROP_TYPE(TypeTag, PropertyTag)
GET_PROP_VALUE(TypeTag, PropertyTag)
\end{verbatim}
\subsubsection*{Nesting Property definitions}
\subsection*{A Simple Example}
As a concrete example, let us consider some kinds of cars: Compact
cars, sedans, trucks, pickups, military tanks and the Hummer-H1 sports
utility vehicle. Since all these cars share some characteristics it
makes sense to derive the shared properties from the closest matching
car type and only specify the properties which are different. Thus, an
inheritance diagram for the car types above might look like in figure
\ref{fig:car-hierarchy}.
\begin{figure}[t]
\centering
\subfloat[]{
\includegraphics[width=.6\textwidth]{EPS/car-hierarchy.eps}
\label{fig:car-hierarchy}
}
\subfloat[]{
\includegraphics[width=.35\linewidth, keepaspectratio]{EPS/car-propertynames.eps}
\label{fig:car-propertynames}
}
\caption{ \textbf{(a)}~~A possible property inheritance graph for
various kinds of cars. The lower nodes inherit from higher ones;
Inherited properties from nodes on right take precedence over the
properties defined on the left. ~~\textbf{(b)}~~Property names
which make sense for at least one of the car types of (a). }
\end{figure}
Using the \Dumux property system, the inheritance hierarchy can be
defined using
\begin{verbatim}
namespace Dumux {
namespace Properties {
NEW_TYPE_TAG(CompactCar);
NEW_TYPE_TAG(Truck);
NEW_TYPE_TAG(Tank);
NEW_TYPE_TAG(Sedan, INHERITS_FROM(CompactCar));
NEW_TYPE_TAG(Pickup, INHERITS_FROM(Sedan, Truck));
NEW_TYPE_TAG(HummerH1, INHERITS_FROM(Pickup, Tank));
}}
\end{verbatim}
Figure \ref{fig:car-propertynames} lists a few property names which
make sense for at least one of the nodes of figure
\ref{fig:car-hierarchy}. These property names can be declared as
follows:
\begin{verbatim}
namespace Dumux {
namespace Properties {
NEW_PROP_TAG(TopSpeed); // [km/h]
NEW_PROP_TAG(NumSeats); // []
NEW_PROP_TAG(CanonCaliber); // [mm]
NEW_PROP_TAG(GasUsage); // [l/100km]
NEW_PROP_TAG(AutomaticTransmission); // true/false
NEW_PROP_TAG(Payload); // [t]
}}
\end{verbatim}
So far the inheritance hierarchy and the property names are completely
separate. What is missing is setting some values for the property
names on specific nodes of the inheritance hierarchy. Let us assume
the following:
\begin{itemize}
\item For a compact car, the top speed is the gas usage in $l/100km$
times $30$, the number of seats is $5$ and the gas usage is
$4\;l/100km$.
\item A truck is by law limited to $100\;km/h$ top speed, the number
of seats is $2$, it uses $18\;l/100km$ and has a cargo payload of
$35\;t$.
\item A tank exhibits a top speed of $60\;km/h$, uses $65\;l/100km$
and features a $120\;mm$ diameter canon
\item A sedan has a gas usage of $7\;l/100km$, as well as an automatic
transmission, in every other aspect it is like for a compact car.
\item A pick-up truck has a top speed of $120\;km/h$ and a payload of
$5\;t$. In every other aspect it is like sedan or a truck but if in
doubt it is more like a truck.
\item The Hummer-H1 SUV exhibits the same top speed as a pick-up
truck. In all other aspects it is similar to a pickup and a tank,
but if in doubt more like a tank.
\end{itemize}
Using the \Dumux property system, these characteristics can be
expressed using
\begin{verbatim}
namespace Dumux {
namespace Properties {
SET_INT_PROP(CompactCar, TopSpeed, GET_PROP_VALUE(TypeTag, PTAG(GasUsage)) * 30);
SET_INT_PROP(CompactCar, NumSeats, 5);
SET_INT_PROP(CompactCar, GasUsage, 4);
SET_INT_PROP(Truck, TopSpeed, 100);
SET_INT_PROP(Truck, NumSeats, 2);
SET_INT_PROP(Truck, GasUsage, 18);
SET_INT_PROP(Truck, Payload, 35);
SET_INT_PROP(Tank, TopSpeed, 60);
SET_INT_PROP(Tank, GasUsage, 65);
SET_INT_PROP(Tank, CanonCaliber, 120);
SET_INT_PROP(Sedan, GasUsage, 7);
SET_BOOL_PROP(Sedan, AutomaticTransmission, true);
SET_INT_PROP(Pickup, TopSpeed, 120);
SET_INT_PROP(Pickup, Payload, 5);
SET_INT_PROP(HummerH1, TopSpeed, GET_PROP_VALUE(TTAG(Pickup), PTAG(TopSpeed)));
}}
\end{verbatim}
At this point, the Hummer-H1 has a $120\;mm$ canon which it inherited
from its military ancestor. It can be removed by
\begin{verbatim}
namespace Dumux {
namespace Properties {
UNSET_PROP(HummerH1, CanonCaliber);
}}
\end{verbatim}
Now the hierarchy can be queried and some diagnostic messages can be
generated. For example
\begin{verbatim}
int main()
{
std::cout << "top speed of sedan: " << GET_PROP_VALUE(TTAG(Sedan), PTAG(TopSpeed)) << "\n";
std::cout << "top speed of truck: " << GET_PROP_VALUE(TTAG(Truck), PTAG(TopSpeed)) << "\n";
std::cout << PROP_DIAGNOSTIC(TTAG(Sedan), PTAG(TopSpeed));
std::cout << PROP_DIAGNOSTIC(TTAG(HummerH1), PTAG(CanonCaliber));
}
\end{verbatim}
will yield in the following output:
\begin{verbatim}
top speed of sedan: 210
top speed of truck: 100
Property 'TopSpeed' for type tag 'Sedan'
inherited from 'CompactCar'
defined at test_propertysystem.cc:90
Property 'CanonCaliber' for type tag 'HummerH1'
explicitly unset at test_propertysystem.cc:113
\end{verbatim}
%%% Local Variables:

View File

@ -31,8 +31,7 @@ int main(int argc, char** argv)
{
try {
typedef TTAG(TutorialProblemCoupled) TypeTag; /*@\label{tutorial-coupled:set-type-tag}@*/
typedef GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; /*@\label{tutorial-coupled:retrieve-types-begin}@*/
typedef GET_PROP_TYPE(TypeTag, PTAG(Grid)) Grid;
typedef GET_PROP_TYPE(TypeTag, PTAG(Grid)) Grid; /*@\label{tutorial-coupled:retrieve-types-begin}@*/
typedef GET_PROP_TYPE(TypeTag, PTAG(TimeManager)) TimeManager;
typedef GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem; /*@\label{tutorial-coupled:retrieve-types-end}@*/

View File

@ -88,7 +88,7 @@ int main(int argc, char** argv)
Problem problem(gridPtr->leafView()); /*@\label{tutorial-decoupled:instantiate-problem}@*/
// load restart file if necessarry
// load restart file if necessary
if (restart) /*@\label{tutorial-decoupled:restart}@*/
problem.deserialize(restartTime);

View File

@ -17,17 +17,13 @@
#ifndef DUMUX_TUTORIALPROBLEM_COUPLED_HH
#define DUMUX_TUTORIALPROBLEM_COUPLED_HH
// fluid properties
#include <dumux/material/fluidsystems/2p_system.hh>
// the numerical model
#include <dumux/boxmodels/2p/2pmodel.hh>
// the grid used
#include <dune/grid/yaspgrid.hh>
#include <dune/grid/io/file/dgfparser/dgfs.hh>
// the DUNE grid used
#include <dune/grid/sgrid.hh>
// assign parameters dependent on space (e.g. spatial parameters)
// spatialy dependent parameters
#include "tutorialspatialparameters_coupled.hh"
namespace Dumux
@ -44,9 +40,7 @@ NEW_TYPE_TAG(TutorialProblemCoupled, INHERITS_FROM(BoxTwoP)); /*@\label{tutorial
// Set the "Problem" property
SET_PROP(TutorialProblemCoupled, Problem) /*@\label{tutorial-coupled:set-problem}@*/
{
typedef Dumux::TutorialProblemCoupled<TTAG(TutorialProblemCoupled)> type;
};
{ typedef Dumux::TutorialProblemCoupled<TypeTag> type;};
// Set the grid
SET_PROP(TutorialProblemCoupled, Grid) /*@\label{tutorial-coupled:set-grid}@*/
@ -71,61 +65,49 @@ SET_PROP(TutorialProblemCoupled, Grid) /*@\label{tutorial-coupled:set-grid}@*/
// Set the wetting phase
SET_PROP(TutorialProblemCoupled, WettingPhase) /*@\label{tutorial-coupled:2p-system-start}@*/
{
private:
typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
public:
typedef Dumux::LiquidPhase<Scalar, Dumux::H2O<Scalar> > type; /*@\label{tutorial-coupled:wettingPhase}@*/
private: typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
public: typedef Dumux::LiquidPhase<Scalar, Dumux::H2O<Scalar> > type; /*@\label{tutorial-coupled:wettingPhase}@*/
};
// Set the non-wetting phase
SET_PROP(TutorialProblemCoupled, NonwettingPhase)
{
private:
typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
public:
typedef Dumux::LiquidPhase<Scalar, Dumux::Oil<Scalar> > type; /*@\label{tutorial-coupled:nonwettingPhase}@*/
private: typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
public: typedef Dumux::LiquidPhase<Scalar, Dumux::Oil<Scalar> > type; /*@\label{tutorial-coupled:nonwettingPhase}@*/
}; /*@\label{tutorial-coupled:2p-system-end}@*/
// Set the spatial parameters
SET_PROP(TutorialProblemCoupled, SpatialParameters) /*@\label{tutorial-coupled:set-spatialparameters}@*/
{
typedef Dumux::TutorialSpatialParametersCoupled<TypeTag> type;
};
{ typedef Dumux::TutorialSpatialParametersCoupled<TypeTag> type; };
// Disable gravity
SET_BOOL_PROP(TutorialProblemCoupled, EnableGravity, false); /*@\label{tutorial-coupled:gravity}@*/
}
// Definition of the actual problem
template <class TypeTag = TTAG(TutorialProblemCoupled) >
template <class TypeTag>
class TutorialProblemCoupled : public TwoPProblem<TypeTag> /*@\label{tutorial-coupled:def-problem}@*/
{
typedef TutorialProblemCoupled<TypeTag> ThisType;
typedef TwoPProblem<TypeTag> ParentType;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(TimeManager)) TimeManager;
// Grid and world dimension
enum {
dim = GridView::dimension,
dimWorld = GridView::dimensionworld,
};
typedef typename GridView::Grid::ctype CoordScalar;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices;
// Grid dimension
enum { dim = GridView::dimension };
// Types from DUNE-Grid
typedef typename GridView::template Codim<0>::Entity Element;
typedef typename GridView::template Codim<dim>::Entity Vertex;
typedef typename GridView::Intersection Intersection;
typedef Dune::FieldVector<CoordScalar, dim> LocalPosition;
typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
typedef Dune::FieldVector<Scalar, dim> GlobalPosition;
// Dumux specific types
typedef typename GET_PROP_TYPE(TypeTag, PTAG(TimeManager)) TimeManager;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(BoundaryTypes)) BoundaryTypes;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
public:
TutorialProblemCoupled(TimeManager &timeManager,
@ -133,37 +115,35 @@ public:
: ParentType(timeManager, gridView)
{
// initialize the tables of the fluid system
FluidSystem::init();
GET_PROP_TYPE(TypeTag, PTAG(FluidSystem))::init();
}
/*!
* \brief The problem name.
*
* This is used as a prefix for files generated by the simulation.
*/
// Specified the problem name. This is used as a prefix for files
// generated by the simulation.
const char *name() const
{ return "tutorial_coupled"; }
// Return the temperature within the domain. We use 10 degrees Celsius.
// Return the temperature within a finite volume. We use constant
// 10 degrees Celsius.
Scalar temperature(const Element &element,
const FVElementGeometry &fvElemGeom,
int scvIdx) const
{ return 283.15; };
// Specifies which kind of boundary condition should be used for
// which equation on a given boundary segment.
void boundaryTypes(BoundaryTypes &BCtype, const Vertex &vertex) const
// which equation for a finite volume on the boundary.
void boundaryTypes(BoundaryTypes &BCtypes, const Vertex &vertex) const
{
const GlobalPosition &pos = vertex.geometry().center();
if (pos[0] < eps_) // dirichlet conditions on left boundary
BCtype.setAllDirichlet();
if (pos[0] < eps_) // Dirichlet conditions on left boundary
BCtypes.setAllDirichlet();
else // neuman for the remaining boundaries
BCtype.setAllNeumann();
BCtypes.setAllNeumann();
}
// Evaluate the boundary conditions for a dirichlet boundary
// segment. For this method, the 'values' parameter stores
// Evaluate the Dirichlet boundary conditions for a finite volume
// on the grid boundary. Here, the 'values' parameter stores
// primary variables.
void dirichlet(PrimaryVariables &values, const Vertex &vertex) const
{
@ -171,10 +151,9 @@ public:
values[Indices::SnIdx] = 0.0; // 0 % oil saturation on left boundary
}
// Evaluate the boundary conditions for a neumann boundary
// segment. For this method, the 'values' parameter stores the
// mass flux in normal direction of each phase. Negative values
// mean influx.
// Evaluate the boundary conditions for a Neumann boundary
// segment. Here, the 'values' parameter stores the mass flux in
// normal direction of each phase. Negative values mean influx.
void neumann(PrimaryVariables &values,
const Element &element,
const FVElementGeometry &fvElemGeom,
@ -186,12 +165,11 @@ public:
fvElemGeom.boundaryFace[boundaryFaceIdx].ipGlobal;
Scalar right = this->bboxMax()[0];
if (pos[0] > right - eps_) {
// oil outflux of 0.3 g/(m * s) on the right boundary of
// the domain.
// oil outflux of 0.3 g/(m * s) on the right boundary.
values[Indices::contiWEqIdx] = 0;
values[Indices::contiNEqIdx] = 3e-4;
} else {
// no-flow on the remaining neumann-boundaries
// no-flow on the remaining Neumann-boundaries.
values[Indices::contiWEqIdx] = 0;
values[Indices::contiNEqIdx] = 0;
}
@ -209,10 +187,9 @@ public:
}
// Evaluate the source term for all phases within a given
// sub-control-volume. For this method, the \a values parameter
// stores the rate mass generated or annihilate per volume
// unit. Positive values mean that mass is created, negative ones
// mean that it vanishes.
// sub-control-volume. In this case, the 'values' parameter stores
// the rate mass generated or annihilate per volume unit. Positive
// values mean that mass is created.
void source(PrimaryVariables &values,
const Element &element,
const FVElementGeometry &fvElemGeom,
@ -223,6 +200,7 @@ public:
}
private:
// small epsilon value
static const Scalar eps_ = 3e-6;
};
}