From d93c2ca67454e99df7b361273e9500f1768f31c2 Mon Sep 17 00:00:00 2001 From: Severin <93776531+klappi-s@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:57:15 +0000 Subject: [PATCH 1/6] DOC: remove old IPPL1.0 manual --- manual/dingbat.sty | 50 -- manual/figures/psi_logo_wide.eps | 1266 ------------------------------ manual/figures/psi_logo_wide.pdf | Bin 5603 -> 0 bytes manual/html.sty | 887 --------------------- manual/introduction.tex | 348 -------- manual/ippl_centering_ref.tex | 251 ------ manual/ippl_fft.tex | 58 -- manual/ippl_field_ref.tex | 239 ------ manual/ippl_fieldlayout_ref.tex | 305 ------- manual/ippl_fields.tex | 646 --------------- manual/ippl_index_ref.tex | 313 -------- manual/ippl_mesh_ref.tex | 611 -------------- manual/ippl_particles.tex | 301 ------- manual/ippl_setup.tex | 99 --- manual/ippl_user_guide.tex | 292 ------- manual/pdfdraftcopy.sty | 198 ----- 16 files changed, 5864 deletions(-) delete mode 100644 manual/dingbat.sty delete mode 100644 manual/figures/psi_logo_wide.eps delete mode 100644 manual/figures/psi_logo_wide.pdf delete mode 100644 manual/html.sty delete mode 100644 manual/introduction.tex delete mode 100644 manual/ippl_centering_ref.tex delete mode 100644 manual/ippl_fft.tex delete mode 100644 manual/ippl_field_ref.tex delete mode 100644 manual/ippl_fieldlayout_ref.tex delete mode 100644 manual/ippl_fields.tex delete mode 100644 manual/ippl_index_ref.tex delete mode 100644 manual/ippl_mesh_ref.tex delete mode 100644 manual/ippl_particles.tex delete mode 100644 manual/ippl_setup.tex delete mode 100644 manual/ippl_user_guide.tex delete mode 100644 manual/pdfdraftcopy.sty diff --git a/manual/dingbat.sty b/manual/dingbat.sty deleted file mode 100644 index 9ac9f494c..000000000 --- a/manual/dingbat.sty +++ /dev/null @@ -1,50 +0,0 @@ -%% -%% This is file `dingbat.sty', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% dingbat.dtx (with options: `package') -%% -%% This is a generated file. -%% -%% Copyright (C) 2001 Scott Pakin -%% ------------------------------------------------------- -%% -%% This package may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.2 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.2 or later is part of all distributions of LaTeX -%% version 1999/12/01 or later. -%% -%% File: dingbat.dtx Copyright (C) 2001 Scott Pakin -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{dingbat} - [2001/04/27 v1.00 Hands and other dingbats] -\newcommand{\arkfamily}{\fontencoding{U}\fontfamily{ark}\selectfont} -\newcommand{\ark@sym}[1]{{\arkfamily\symbol{#1}}} -\newcommand{\carriagereturn}{\ark@sym{'103}} -\newcommand{\leftthumbsdown}{\ark@sym{'104}} -\newcommand{\eye}{\ark@sym{'105}} -\newcommand{\rightpointleft}{\ark@sym{'114}} -\newcommand{\smallpencil}{\ark@sym{'120}} -\newcommand{\leftpointright}{\ark@sym{'122}} -\newcommand{\leftthumbsup}{\ark@sym{'125}} -\newcommand{\largepencil}{\ark@sym{'127}} -\newcommand{\rightthumbsdown}{\ark@sym{'144}} -\newcommand{\rightthumbsup}{\ark@sym{'165}} -\newcommand{\dingbatfamily}{\fontencoding{U}\fontfamily{dingbat}\selectfont} -\newcommand{\dingbat@sym}[1]{{\dingbatfamily\symbol{#1}}} -\newcommand{\checkmark}{\dingbat@sym{'104}} -\newcommand{\satellitedish}{\dingbat@sym{'111}} -\newcommand{\rightpointright}{\dingbat@sym{'116}} -\newcommand{\anchor}{\dingbat@sym{'117}} -\newcommand{\squarewithdots}{\dingbat@sym{'102}} -\newcommand{\filledsquarewithdots}{\dingbat@sym{'103}} -\newcommand{\Sborder}{\dingbat@sym{'123}} -\newcommand{\Zborder}{\dingbat@sym{'132}} -\endinput -%% -%% End of file `dingbat.sty'. diff --git a/manual/figures/psi_logo_wide.eps b/manual/figures/psi_logo_wide.eps deleted file mode 100644 index 07df5b878..000000000 --- a/manual/figures/psi_logo_wide.eps +++ /dev/null @@ -1,1266 +0,0 @@ -%!PS-Adobe-3.0 EPSF-3.0 -%%BoundingBox: 40 612 511 642 -%%Creator: CorelDRAW 7 -%%Title: -%%CreationDate: Thu Sep 14 10:45:34 2000 -%%DocumentProcessColors: Black -%%DocumentSuppliedResources: (atend) -%%EndComments -%%BeginProlog -/AutoFlatness true def -/AutoSteps 0 def -/CMYKMarks false def -/UseLevel2 false def -%Color profile: _DEFAULT.CCM - Generic Profile -%%BeginResource: procset wCorel7Dict 7.0 0 -/wCorel7Dict 300 dict def wCorel7Dict begin -% Copyright (c)1992-96 Corel Corporation -% All rights reserved. v7.0 r1.0 -/bd{bind def}bind def/ld{load def}bd/xd{exch def}bd/_ null def/rp{{pop}repeat} -bd/@cp/closepath ld/@gs/gsave ld/@gr/grestore ld/@np/newpath ld/Tl/translate ld -/$sv 0 def/@sv{/$sv save def}bd/@rs{$sv restore}bd/spg/showpage ld/showpage{} -bd currentscreen/@dsp xd/$dsp/@dsp def/$dsa xd/$dsf xd/$sdf false def/$SDF -false def/$Scra 0 def/SetScr/setscreen ld/setscreen{pop pop pop}bd/@ss{2 index -0 eq{$dsf 3 1 roll 4 -1 roll pop}if exch $Scra add exch load SetScr}bd -/SepMode_5 where{pop}{/SepMode_5 0 def}ifelse/CurrentInkName_5 where{pop} -{/CurrentInkName_5(Composite)def}ifelse/$ink_5 where{pop}{/$ink_5 -1 def} -ifelse/$c 0 def/$m 0 def/$y 0 def/$k 0 def/$t 1 def/$n _ def/$o 0 def/$fil 0 -def/$C 0 def/$M 0 def/$Y 0 def/$K 0 def/$T 1 def/$N _ def/$O 0 def/$PF false -def/s1c 0 def/s1m 0 def/s1y 0 def/s1k 0 def/s1t 0 def/s1n _ def/$bkg false def -/SK 0 def/SM 0 def/SY 0 def/SC 0 def/$op false def matrix currentmatrix/$ctm xd -/$ptm matrix def/$ttm matrix def/$stm matrix def/$ffpnt true def -/CorelDrawReencodeVect[16#0/grave 16#5/breve 16#6/dotaccent 16#8/ring -16#A/hungarumlaut 16#B/ogonek 16#C/caron 16#D/dotlessi 16#27/quotesingle -16#60/grave 16#7C/bar -16#82/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl -16#88/circumflex/perthousand/Scaron/guilsinglleft/OE -16#91/quoteleft/quoteright/quotedblleft/quotedblright/bullet/endash/emdash -16#98/tilde/trademark/scaron/guilsinglright/oe 16#9F/Ydieresis -16#A1/exclamdown/cent/sterling/currency/yen/brokenbar/section -16#a8/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/minus/registered/macron -16#b0/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered -16#b8/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown -16#c0/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla -16#c8/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis -16#d0/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply -16#d8/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls -16#e0/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla -16#e8/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis -16#f0/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide -16#f8/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def -/L2?/languagelevel where{pop languagelevel 2 ge}{false}ifelse def -/@BeginSysCorelDict{systemdict/Corel30Dict known{systemdict/Corel30Dict get -exec}if}bd/@EndSysCorelDict{systemdict/Corel30Dict known{end}if}bd AutoFlatness -{/@ifl{dup currentflat exch sub 10 gt{ -([Error: PathTooComplex; OffendingCommand: AnyPaintingOperator]\n)print flush -@np exit}{currentflat 2 add setflat}ifelse}bd/@fill/fill ld/fill{currentflat{ -{@fill}stopped{@ifl}{exit}ifelse}bind loop setflat}bd/@eofill/eofill ld/eofill -{currentflat{{@eofill}stopped{@ifl}{exit}ifelse}bind loop setflat}bd/@clip -/clip ld/clip{currentflat{{@clip}stopped{@ifl}{exit}ifelse}bind loop setflat} -bd/@eoclip/eoclip ld/eoclip{currentflat{{@eoclip}stopped{@ifl}{exit}ifelse} -bind loop setflat}bd/@stroke/stroke ld/stroke{currentflat{{@stroke}stopped -{@ifl}{exit}ifelse}bind loop setflat}bd}if L2?{/@ssa{true setstrokeadjust}bd}{ -/@ssa{}bd}ifelse/d/setdash ld/j/setlinejoin ld/J/setlinecap ld/M/setmiterlimit -ld/w/setlinewidth ld/O{/$o xd}bd/R{/$O xd}bd/W/eoclip ld/c/curveto ld/C/c ld/l -/lineto ld/L/l ld/rl/rlineto ld/m/moveto ld/n/newpath ld/N/newpath ld/P{11 rp} -bd/u{}bd/U{}bd/A{pop}bd/q/@gs ld/Q/@gr ld/&{}bd/@j{@sv @np}bd/@J{@rs}bd/g{1 -exch sub/$k xd/$c 0 def/$m 0 def/$y 0 def/$t 1 def/$n _ def/$fil 0 def}bd/G{1 -sub neg/$K xd _ 1 0 0 0/$C xd/$M xd/$Y xd/$T xd/$N xd}bd/k{1 index type -/stringtype eq{/$t xd/$n xd}{/$t 0 def/$n _ def}ifelse/$k xd/$y xd/$m xd/$c xd -/$fil 0 def}bd/K{1 index type/stringtype eq{/$T xd/$N xd}{/$T 0 def/$N _ def} -ifelse/$K xd/$Y xd/$M xd/$C xd}bd/x/k ld/X/K ld/sf{1 index type/stringtype eq{ -/s1t xd/s1n xd}{/s1t 0 def/s1n _ def}ifelse/s1k xd/s1y xd/s1m xd/s1c xd}bd/i{ -dup 0 ne{setflat}{pop}ifelse}bd/v{4 -2 roll 2 copy 6 -2 roll c}bd/V/v ld/y{2 -copy c}bd/Y/y ld/@w{matrix rotate/$ptm xd matrix scale $ptm dup concatmatrix -/$ptm xd 1 eq{$ptm exch dup concatmatrix/$ptm xd}if 1 w}bd/@g{1 eq dup/$sdf xd -{/$scp xd/$sca xd/$scf xd}if}bd/@G{1 eq dup/$SDF xd{/$SCP xd/$SCA xd/$SCF xd} -if}bd/@D{2 index 0 eq{$dsf 3 1 roll 4 -1 roll pop}if 3 copy exch $Scra add exch -load SetScr/$dsp xd/$dsa xd/$dsf xd}bd/$ngx{$SDF{$SCF SepMode_5 0 eq{$SCA} -{$dsa}ifelse $SCP @ss}if}bd/p{/$pm xd 7 rp/$pyf xd/$pxf xd/$pn xd/$fil 1 def} -bd/@MN{2 copy le{pop}{exch pop}ifelse}bd/@MX{2 copy ge{pop}{exch pop}ifelse}bd -/InRange{3 -1 roll @MN @MX}bd/@sqr{dup 0 rl dup 0 exch rl neg 0 rl @cp}bd -/currentscale{1 0 dtransform matrix defaultmatrix idtransform dup mul exch dup -mul add sqrt 0 1 dtransform matrix defaultmatrix idtransform dup mul exch dup -mul add sqrt}bd/@unscale{}bd/wDstChck{2 1 roll dup 3 -1 roll eq{1 add}if}bd -/@dot{dup mul exch dup mul add 1 exch sub}bd/@lin{exch pop abs 1 exch sub}bd -/cmyk2rgb{3{dup 5 -1 roll add 1 exch sub dup 0 lt{pop 0}if exch}repeat pop}bd -/rgb2cmyk{3{1 exch sub 3 1 roll}repeat 3 copy @MN @MN 3{dup 5 -1 roll sub neg -exch}repeat}bd/rgb2g{2 index .299 mul 2 index .587 mul add 1 index .114 mul add -4 1 roll pop pop pop}bd/WaldoColor_5 where{pop}{/SetRgb/setrgbcolor ld/GetRgb -/currentrgbcolor ld/SetGry/setgray ld/GetGry/currentgray ld/SetRgb2 systemdict -/setrgbcolor get def/GetRgb2 systemdict/currentrgbcolor get def/SetHsb -systemdict/sethsbcolor get def/GetHsb systemdict/currenthsbcolor get def -/rgb2hsb{SetRgb2 GetHsb}bd/hsb2rgb{3 -1 roll dup floor sub 3 1 roll SetHsb -GetRgb2}bd/setcmykcolor where{pop/SetCmyk_5/setcmykcolor ld}{/SetCmyk_5{ -cmyk2rgb SetRgb}bd}ifelse/currentcmykcolor where{pop/GetCmyk/currentcmykcolor -ld}{/GetCmyk{GetRgb rgb2cmyk}bd}ifelse/setoverprint where{pop}{/setoverprint{ -/$op xd}bd}ifelse/currentoverprint where{pop}{/currentoverprint{$op}bd}ifelse -/@tc_5{5 -1 roll dup 1 ge{pop}{4{dup 6 -1 roll mul exch}repeat pop}ifelse}bd -/@trp{exch pop 5 1 roll @tc_5}bd/setprocesscolor_5{SepMode_5 0 eq{SetCmyk_5}{0 -4 $ink_5 sub index exch pop 5 1 roll pop pop pop pop SepsColor true eq{$ink_5 3 -gt{1 sub neg SetGry}{0 0 0 4 $ink_5 roll SetCmyk_5}ifelse}{1 sub neg SetGry} -ifelse}ifelse}bd/findcmykcustomcolor where{pop}{/findcmykcustomcolor{5 array -astore}bd}ifelse/setcustomcolor where{pop}{/setcustomcolor{exch aload pop -SepMode_5 0 eq{pop @tc_5 setprocesscolor_5}{CurrentInkName_5 eq{4 index}{0} -ifelse 6 1 roll 5 rp 1 sub neg SetGry}ifelse}bd}ifelse/@scc_5{dup type -/booleantype eq{setoverprint}{1 eq setoverprint}ifelse dup _ eq{pop -setprocesscolor_5 pop}{findcmykcustomcolor exch setcustomcolor}ifelse SepMode_5 -0 eq{true}{GetGry 1 eq currentoverprint and not}ifelse}bd/colorimage where{pop -/ColorImage{colorimage}def}{/ColorImage{/ncolors xd pop/dataaq xd{dataaq -ncolors dup 3 eq{/$dat xd 0 1 $dat length 3 div 1 sub{dup 3 mul $dat 1 index -get 255 div $dat 2 index 1 add get 255 div $dat 3 index 2 add get 255 div rgb2g -255 mul cvi exch pop $dat 3 1 roll put}for $dat 0 $dat length 3 idiv -getinterval pop}{4 eq{/$dat xd 0 1 $dat length 4 div 1 sub{dup 4 mul $dat 1 -index get 255 div $dat 2 index 1 add get 255 div $dat 3 index 2 add get 255 div -$dat 4 index 3 add get 255 div cmyk2rgb rgb2g 255 mul cvi exch pop $dat 3 1 -roll put}for $dat 0 $dat length ncolors idiv getinterval}if}ifelse}image}bd -}ifelse/setcmykcolor{1 5 1 roll _ currentoverprint @scc_5/$ffpnt xd}bd -/currentcmykcolor{0 0 0 0}bd/setrgbcolor{rgb2cmyk setcmykcolor}bd -/currentrgbcolor{currentcmykcolor cmyk2rgb}bd/sethsbcolor{hsb2rgb setrgbcolor} -bd/currenthsbcolor{currentrgbcolor rgb2hsb}bd/setgray{dup dup setrgbcolor}bd -/currentgray{currentrgbcolor rgb2g}bd}ifelse/WaldoColor_5 true def/@sft{$tllx -$pxf add dup $tllx gt{$pwid sub}if/$tx xd $tury $pyf sub dup $tury lt{$phei -add}if/$ty xd}bd/@stb{pathbbox/$ury xd/$urx xd/$lly xd/$llx xd}bd/@ep{{cvx exec -}forall}bd/@tp{@sv/$in true def 2 copy dup $lly le{/$in false def}if $phei sub -$ury ge{/$in false def}if dup $urx ge{/$in false def}if $pwid add $llx le{/$in -false def}if $in{@np 2 copy m $pwid 0 rl 0 $phei neg rl $pwid neg 0 rl 0 $phei -rl clip @np $pn cvlit load aload pop 7 -1 roll 5 index sub 7 -1 roll 3 index -sub Tl matrix currentmatrix/$ctm xd @ep pop pop pop pop}{pop pop}ifelse @rs}bd -/@th{@sft 0 1 $tly 1 sub{dup $psx mul $tx add{dup $llx gt{$pwid sub}{exit} -ifelse}loop exch $phei mul $ty exch sub 0 1 $tlx 1 sub{$pwid mul 3 copy 3 -1 -roll add exch @tp pop}for pop pop}for}bd/@tv{@sft 0 1 $tlx 1 sub{dup $pwid mul -$tx add exch $psy mul $ty exch sub{dup $ury lt{$phei add}{exit}ifelse}loop 0 1 -$tly 1 sub{$phei mul 3 copy sub @tp pop}for pop pop}for}bd/$fm 0 def/wfill{1 -$fm eq{fill}{eofill}ifelse}bd/wclip{1 $fm eq{clip}{eoclip}ifelse}bd/@pf{@gs -$ctm setmatrix $pm concat @stb wclip Bburx Bbury $pm itransform/$tury xd/$turx -xd Bbllx Bblly $pm itransform/$tlly xd/$tllx xd/$wid $turx $tllx sub def/$hei -$tury $tlly sub def @gs $vectpat{1 0 0 0 0 _ $o @scc_5{wfill}if}{$t $c $m $y $k -$n $o @scc_5{SepMode_5 0 eq $pfrg or{$tllx $tlly Tl $wid $hei scale <00> 8 1 -false[8 0 0 1 0 0]{}imagemask}{/$bkg true def}ifelse}if}ifelse @gr $wid 0 gt -$hei 0 gt and{$pn cvlit load aload pop/$pd xd 3 -1 roll sub/$phei xd exch sub -/$pwid xd $wid $pwid div ceiling 1 add/$tlx xd $hei $phei div ceiling 1 add -/$tly xd $psx 0 eq{@tv}{@th}ifelse}if @gr @np/$bkg false def}bd/@Pf{@sv -SepMode_5 0 eq $Psc 0 ne or $ink_5 3 eq or{0 J 0 j[]0 d $t $c $m $y $k $n $o -@scc_5 pop $ctm setmatrix 72 1000 div dup matrix scale dup concat dup Bburx -exch Bbury exch itransform ceiling cvi/Bbury xd ceiling cvi/Bburx xd Bbllx exch -Bblly exch itransform floor cvi/Bblly xd floor cvi/Bbllx xd $Prm aload pop $Psn -load exec}{1 SetGry wfill}ifelse @rs @np}bd/F{matrix currentmatrix $sdf{$scf -$sca $scp @ss}if $fil 1 eq{@pf}{$fil 2 eq{@ff}{$fil 3 eq{@Pf}{$t $c $m $y $k $n -$o @scc_5{wfill}{@np}ifelse}ifelse}ifelse}ifelse $sdf{$dsf $dsa $dsp @ss}if -setmatrix}bd/f{@cp F}bd/S{matrix currentmatrix $ctm setmatrix $SDF{$SCF $SCA -$SCP @ss}if $T $C $M $Y $K $N $O @scc_5{matrix currentmatrix $ptm concat stroke -setmatrix}{@np}ifelse $SDF{$dsf $dsa $dsp @ss}if setmatrix}bd/s{@cp S}bd/B{@gs -F @gr S}bd/b{@cp B}bd/_E{5 array astore exch cvlit xd}bd/@cc{currentfile $dat -readhexstring pop}bd/@sm{/$ctm $ctm currentmatrix def}bd/@E{/Bbury xd/Bburx xd -/Bblly xd/Bbllx xd}bd/@c{@cp}bd/@p{/$fil 1 def 1 eq dup/$vectpat xd{/$pfrg true -def}{@gs $t $c $m $y $k $n $o @scc_5/$pfrg xd @gr}ifelse/$pm xd/$psy xd/$psx xd -/$pyf xd/$pxf xd/$pn xd}bd/@P{/$fil 3 def/$Psn xd/$Psc xd array astore/$Prm xd -}bd/@ii{concat 3 index 3 index m 3 index 1 index l 2 copy l 1 index 3 index l 3 -index 3 index l clip pop pop pop pop}bd/tcc{@cc}def/@i{@sm @gs @ii 6 index 1 ne -{/$frg true def pop pop}{1 eq{s1t s1c s1m s1y s1k s1n $O @scc_5/$frg xd}{/$frg -false def}ifelse 1 eq{@gs $ctm setmatrix F @gr}if}ifelse @np/$ury xd/$urx xd -/$lly xd/$llx xd/$bts xd/$hei xd/$wid xd/$dat $wid $bts mul 8 div ceiling cvi -string def $bkg $frg or{$SDF{$SCF $SCA $SCP @ss}if $llx $lly Tl $urx $llx sub -$ury $lly sub scale $bkg{$t $c $m $y $k $n $o @scc_5 pop}if $wid $hei abs $bts -1 eq{$bkg}{$bts}ifelse[$wid 0 0 $hei neg 0 $hei 0 gt{$hei}{0}ifelse]/tcc load -$bts 1 eq{imagemask}{image}ifelse $SDF{$dsf $dsa $dsp @ss}if}{$hei abs{tcc pop} -repeat}ifelse @gr $ctm setmatrix}bd/@I{@sm @gs @ii @np/$ury xd/$urx xd/$lly xd -/$llx xd/$ncl xd/$bts xd/$hei xd/$wid xd/$dat $wid $bts mul $ncl mul 8 div -ceiling cvi string def $ngx $llx $lly Tl $urx $llx sub $ury $lly sub scale $wid -$hei abs $bts[$wid 0 0 $hei neg 0 $hei 0 gt{$hei}{0}ifelse]/@cc load false $ncl -ColorImage $SDF{$dsf $dsa $dsp @ss}if @gr $ctm setmatrix}bd/COMP 0 def L2?{ -/@I_2{@sm @gs @ii @np/$ury xd/$urx xd/$lly xd/$llx xd/$ncl xd/$bts xd/$hei xd -/$wid xd/$dat $wid $bts mul $ncl mul 8 div ceiling cvi string def $ngx $ncl 1 -eq{/DeviceGray}{$ncl 3 eq{/DeviceRGB}{/DeviceCMYK}ifelse}ifelse setcolorspace -$llx $lly Tl $urx $llx sub $ury $lly sub scale 8 dict begin/ImageType 1 def -/Width $wid def/Height $hei abs def/BitsPerComponent $bts def/Decode $ncl 1 eq -{[0 1]}{$ncl 3 eq{[0 1 0 1 0 1]}{[0 1 0 1 0 1 0 1]}ifelse}ifelse def -/ImageMatrix[$wid 0 0 $hei neg 0 $hei 0 gt{$hei}{0}ifelse]def/DataSource -currentfile/ASCII85Decode filter COMP 1 eq{/DCTDecode filter}{COMP 2 eq -{/RunLengthDecode filter}if}ifelse def currentdict end image $SDF{$dsf $dsa -$dsp @ss}if @gr $ctm setmatrix}bd}{/@I_2{}bd}ifelse/@B{@gs S @gr F}bd/@b{@cp @B -}bd/@sep{CurrentInkName_5(Composite)eq{/$ink_5 -1 def}{CurrentInkName_5(Cyan) -eq{/$ink_5 0 def}{CurrentInkName_5(Magenta)eq{/$ink_5 1 def}{CurrentInkName_5 -(Yellow)eq{/$ink_5 2 def}{CurrentInkName_5(Black)eq{/$ink_5 3 def}{/$ink_5 4 -def}ifelse}ifelse}ifelse}ifelse}ifelse}bd/@whi{@gs -72000 dup m -72000 72000 l -72000 dup l 72000 -72000 l @cp 1 SetGry fill @gr}bd/@neg{[{1 exch sub}/exec cvx -currenttransfer/exec cvx]cvx settransfer @whi}bd/deflevel 0 def/@sax{/deflevel -deflevel 1 add def}bd/@eax{/deflevel deflevel dup 0 gt{1 sub}if def deflevel 0 -gt{/eax load}{eax}ifelse}bd/eax{{exec}forall}bd/@rax{deflevel 0 eq{@rs @sv}if} -bd/@daq{dup type/arraytype eq{{}forall}if}bd/@BMP{/@cc xd 12 index 1 gt -UseLevel2 true eq and{7 -2 roll pop pop @I_2}{11 index 1 eq{12 -1 roll pop @i} -{7 -2 roll pop pop @I}ifelse}ifelse}bd systemdict/pdfmark known not{/pdfmark -/cleartomark ld}if -end -%%EndResource -%%EndProlog -%%BeginSetup -wCorel7Dict begin -@BeginSysCorelDict -2.6131 setmiterlimit -1.00 setflat -/$fst 128 def -%%EndSetup - -%%Page: 1 1 -%LogicalPage: 1 -%%BeginPageSetup -@sv -@sm -@sv -%%EndPageSetup -@rax %Note: Object -41.13808 617.64888 157.41808 631.11288 @E - 0 O 0 @g -0.44 0.36 0.35 0.01 k -/$fm 0 def -67.41808 617.64888 m -42.79408 617.64888 L -42.14608 617.79288 L -41.64208 618.08088 L -41.28208 618.65688 L -41.13808 619.23288 L -41.13808 629.45688 L -41.28208 630.10488 L -41.64208 630.60888 L -42.14608 630.96888 L -42.79408 631.11288 L -155.76208 631.11288 L -156.41008 630.96888 L -156.91408 630.60888 L -157.27408 630.10488 L -157.41808 629.45688 L -157.41808 619.23288 L -157.27408 618.65688 L -156.91408 618.08088 L -156.41008 617.79288 L -155.76208 617.64888 L -67.41808 617.64888 L -@c -F - -@rax %Note: Object -67.41808 613.76088 92.76208 641.26488 @E - 0 O 0 @g -0.01 0.00 0.00 0.00 k -/$fm 0 def -76.41808 622.90488 m -76.41808 616.64088 L -76.34608 616.06488 L -76.20208 615.48888 L -75.91408 614.98488 L -75.55408 614.62488 L -75.19408 614.26488 L -74.69008 613.97688 L -74.11408 613.83288 L -73.53808 613.76088 L -70.29808 613.76088 L -69.72208 613.83288 L -69.21808 613.97688 L -68.71408 614.26488 L -68.28208 614.62488 L -67.92208 614.98488 L -67.70608 615.48888 L -67.49008 616.06488 L -67.41808 616.64088 L -67.41808 638.45688 L -67.49008 639.03288 L -67.70608 639.53688 L -67.92208 640.04088 L -68.28208 640.47288 L -68.71408 640.83288 L -69.21808 641.04888 L -69.72208 641.26488 L -70.29808 641.26488 L -89.88208 641.26488 L -90.45808 641.26488 L -90.96208 641.04888 L -91.46608 640.83288 L -91.89808 640.47288 L -92.25808 640.04088 L -92.54608 639.53688 L -92.69008 639.03288 L -92.76208 638.45688 L -92.76208 625.78488 L -92.69008 625.20888 L -92.54608 624.70488 L -92.25808 624.20088 L -91.89808 623.76888 L -91.46608 623.40888 L -90.96208 623.19288 L -90.45808 622.97688 L -89.88208 622.90488 L -76.41808 622.90488 L -@c -F - -@rax %Note: Object -67.41808 613.76088 92.76208 641.26488 @E -0 J 0 j [] 0 d 0 R 0 @G -0.84 0.73 0.72 0.91 K -[1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] 1 1.42753 1.42753 0.00000 @w -/$fm 0 def -76.41808 622.90488 m -76.41808 616.64088 L -76.41808 615.05688 75.12208 613.76088 73.53808 613.76088 C -70.29808 613.76088 L -68.71408 613.76088 67.41808 615.05688 67.41808 616.64088 C -67.41808 638.45688 L -67.41808 640.04088 68.71408 641.26488 70.29808 641.26488 C -89.88208 641.26488 L -91.46608 641.26488 92.76208 640.04088 92.76208 638.45688 C -92.76208 625.78488 L -92.76208 624.20088 91.46608 622.90488 89.88208 622.90488 C -76.41808 622.90488 L -@c -S - -@rax %Note: Object -75.84208 632.12031 84.41008 632.12145 @E -0 J 0 j [] 0 d 0 R 0 @G -0.84 0.73 0.72 0.91 K -[1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] 1 1.42753 1.42753 0.00000 @w -/$fm 0 def -75.84208 632.12088 m -84.41008 632.12088 L -S - -@rax %Note: Object -92.76208 613.76088 118.03408 641.26488 @E - 0 O 0 @g -0.01 0.00 0.00 0.00 k -/$fm 0 def -110.11408 622.90488 m -95.57008 622.90488 L -94.99408 622.97688 L -94.49008 623.19288 L -93.98608 623.40888 L -93.55408 623.76888 L -93.19408 624.20088 L -92.97808 624.70488 L -92.83408 625.20888 L -92.76208 625.78488 L -92.76208 638.45688 L -92.83408 639.03288 L -92.97808 639.53688 L -93.19408 640.04088 L -93.55408 640.47288 L -93.98608 640.83288 L -94.49008 641.04888 L -94.99408 641.26488 L -95.57008 641.26488 L -115.15408 641.26488 L -115.73008 641.26488 L -116.30608 641.04888 L -116.73808 640.83288 L -117.17008 640.47288 L -117.53008 640.04088 L -117.81808 639.53688 L -117.96208 639.03288 L -118.03408 638.45688 L -118.03408 635.00088 L -117.96208 634.42488 L -117.81808 633.84888 L -117.53008 633.34488 L -117.17008 632.98488 L -116.73808 632.62488 L -116.30608 632.33688 L -115.73008 632.19288 L -115.15408 632.12088 L -100.68208 632.12088 L -115.15408 632.12088 L -115.73008 632.04888 L -116.30608 631.90488 L -116.73808 631.61688 L -117.17008 631.25688 L -117.53008 630.82488 L -117.81808 630.39288 L -117.96208 629.81688 L -118.03408 629.24088 L -118.03408 616.64088 L -117.96208 616.06488 L -117.81808 615.48888 L -117.53008 614.98488 L -117.17008 614.62488 L -116.73808 614.26488 L -116.30608 613.97688 L -115.73008 613.83288 L -115.15408 613.76088 L -95.57008 613.76088 L -94.99408 613.83288 L -94.49008 613.97688 L -93.98608 614.26488 L -93.55408 614.62488 L -93.19408 614.98488 L -92.97808 615.48888 L -92.83408 616.06488 L -92.76208 616.64088 L -92.76208 620.09688 L -92.83408 620.67288 L -92.97808 621.17688 L -93.19408 621.68088 L -93.55408 622.11288 L -93.98608 622.47288 L -94.49008 622.68888 L -94.99408 622.90488 L -95.57008 622.90488 L -110.11408 622.90488 L -@c -F - -@rax %Note: Object -92.76208 613.76088 118.03408 641.26488 @E -0 J 0 j [] 0 d 0 R 0 @G -0.84 0.73 0.72 0.91 K -[1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] 1 1.42753 1.42753 0.00000 @w -/$fm 0 def -110.11408 622.90488 m -95.57008 622.90488 L -93.98608 622.90488 92.76208 624.20088 92.76208 625.78488 C -92.76208 638.45688 L -92.76208 640.04088 93.98608 641.26488 95.57008 641.26488 C -115.15408 641.26488 L -116.73808 641.26488 118.03408 640.04088 118.03408 638.45688 C -118.03408 635.00088 L -118.03408 633.41688 116.73808 632.12088 115.15408 632.12088 C -100.68208 632.12088 L -115.15408 632.12088 L -116.73808 632.12088 118.03408 630.82488 118.03408 629.24088 C -118.03408 616.64088 L -118.03408 615.05688 116.73808 613.76088 115.15408 613.76088 C -95.57008 613.76088 L -93.98608 613.76088 92.76208 615.05688 92.76208 616.64088 C -92.76208 620.09688 L -92.76208 621.68088 93.98608 622.90488 95.57008 622.90488 C -110.11408 622.90488 L -@c -S - -@rax %Note: Object -117.02608 631.11288 118.03408 632.69688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -117.02608 632.12088 m -118.03408 632.69688 L -118.03408 631.11288 L -117.02608 632.12088 L -@c -F - -@rax %Note: Object -118.03408 613.76088 131.06608 641.26488 @E - 0 O 0 @g -0.01 0.00 0.00 0.00 k -/$fm 0 def -118.03408 617.86488 m -118.03408 638.45688 L -118.10608 639.03288 L -118.25008 639.53688 L -118.53808 640.04088 L -118.89808 640.47288 L -119.25808 640.83288 L -119.76208 641.04888 L -120.33808 641.26488 L -120.91408 641.26488 L -128.25808 641.26488 L -128.83408 641.26488 L -129.33808 641.04888 L -129.84208 640.83288 L -130.27408 640.47288 L -130.63408 640.04088 L -130.85008 639.53688 L -130.99408 639.03288 L -131.06608 638.45688 L -131.06608 616.64088 L -130.99408 616.06488 L -130.85008 615.48888 L -130.63408 614.98488 L -130.27408 614.62488 L -129.84208 614.26488 L -129.33808 613.97688 L -128.83408 613.83288 L -128.25808 613.76088 L -120.91408 613.76088 L -120.33808 613.83288 L -119.76208 613.97688 L -119.25808 614.26488 L -118.89808 614.62488 L -118.53808 614.98488 L -118.25008 615.48888 L -118.10608 616.06488 L -118.03408 616.64088 L -118.03408 617.86488 L -@c -F - -@rax %Note: Object -118.03408 613.76088 131.06608 641.26488 @E -0 J 0 j [] 0 d 0 R 0 @G -0.84 0.73 0.72 0.91 K -[1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] 1 1.42753 1.42753 0.00000 @w -/$fm 0 def -118.03408 617.86488 m -118.03408 638.45688 L -118.03408 640.04088 119.33008 641.26488 120.91408 641.26488 C -128.25808 641.26488 L -129.84208 641.26488 131.06608 640.04088 131.06608 638.45688 C -131.06608 616.64088 L -131.06608 615.05688 129.84208 613.76088 128.25808 613.76088 C -120.91408 613.76088 L -119.33008 613.76088 118.03408 615.05688 118.03408 616.64088 C -118.03408 617.86488 L -@c -S - -@rax %Note: Object -199.39408 617.64888 207.31408 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -199.39408 630.53688 m -199.39408 617.64888 L -200.83408 617.64888 L -200.83408 623.12088 L -204.43408 623.12088 L -205.01008 623.19288 L -205.58608 623.40888 L -206.09008 623.69688 L -206.52208 624.20088 L -206.88208 624.70488 L -207.09808 625.35288 L -207.24208 626.07288 L -207.31408 626.86488 L -207.24208 627.65688 L -207.09808 628.37688 L -206.81008 628.95288 L -206.52208 629.52888 L -206.09008 629.96088 L -205.58608 630.24888 L -205.01008 630.46488 L -204.43408 630.53688 L -204.21808 630.53688 L -199.39408 630.53688 L -@c -200.83408 624.56088 m -200.83408 629.09688 L -203.78608 629.02488 L -204.65008 628.88088 L -205.29808 628.52088 L -205.73008 627.80088 L -205.87408 626.86488 L -205.73008 625.92888 L -205.29808 625.20888 L -204.72208 624.77688 L -203.85808 624.63288 L -200.83408 624.56088 L -@c -F - -@rax %Note: Object -213.14608 617.64888 222.65008 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -217.17808 630.53688 m -213.14608 617.64888 L -214.65808 617.64888 L -215.81008 621.39288 L -219.98608 621.39288 L -221.06608 617.64888 L -222.65008 617.64888 L -218.83408 630.53688 L -217.17808 630.53688 L -@c -217.89808 628.66488 m -219.48208 622.97688 L -216.24208 622.97688 L -217.89808 628.66488 L -@c -F - -@rax %Note: Object -228.98608 617.28888 237.33808 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -228.98608 630.53688 m -228.98608 621.75288 L -229.13008 620.60088 L -229.49008 619.52088 L -230.13808 618.51288 L -230.93008 617.86488 L -231.86608 617.43288 L -233.09008 617.28888 L -234.02608 617.36088 L -234.81808 617.64888 L -235.61008 618.08088 L -236.18608 618.65688 L -236.69008 619.30488 L -237.05008 620.09688 L -237.26608 620.96088 L -237.33808 621.82488 L -237.33808 630.53688 L -235.89808 630.53688 L -235.89808 622.18488 L -235.89808 622.04088 L -235.82608 621.46488 L -235.53808 620.38488 L -234.96208 619.59288 L -234.60208 619.23288 L -234.17008 619.01688 L -233.66608 618.87288 L -233.16208 618.87288 L -232.51408 618.87288 L -232.01008 619.08888 L -231.57808 619.37688 L -231.14608 619.73688 L -230.85808 620.24088 L -230.64208 620.81688 L -230.49808 621.53688 L -230.42608 622.32888 L -230.42608 630.53688 L -228.98608 630.53688 L -@c -F - -@rax %Note: Object -244.61008 617.64888 251.45008 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -244.61008 630.53688 m -244.61008 617.64888 L -251.45008 617.64888 L -251.45008 619.23288 L -246.05008 619.23288 L -246.05008 630.53688 L -244.61008 630.53688 L -@c -F - -@rax %Note: Object -272.40208 617.28888 280.82608 630.89688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -280.53808 626.79288 m -280.46608 627.72888 L -280.25008 628.52088 L -279.96208 629.24088 L -279.45808 629.81688 L -278.88208 630.32088 L -278.23408 630.60888 L -277.37008 630.82488 L -276.50608 630.89688 L -275.64208 630.82488 L -274.92208 630.60888 L -274.27408 630.32088 L -273.77008 629.81688 L -273.33808 629.24088 L -273.05008 628.59288 L -272.83408 627.80088 L -272.76208 626.93688 L -272.83408 626.21688 L -272.97808 625.64088 L -273.26608 625.06488 L -273.62608 624.63288 L -274.20208 624.20088 L -274.77808 623.91288 L -277.73008 623.12088 L -278.45008 622.76088 L -279.02608 622.32888 L -279.31408 621.75288 L -279.45808 621.03288 L -279.38608 620.45688 L -279.24208 620.02488 L -279.02608 619.66488 L -278.66608 619.37688 L -277.73008 618.94488 L -276.72208 618.80088 L -276.07408 618.87288 L -275.49808 619.01688 L -274.99408 619.23288 L -274.56208 619.59288 L -274.20208 620.02488 L -273.98608 620.52888 L -273.84208 621.10488 L -273.77008 621.82488 L -272.40208 621.82488 L -272.54608 620.45688 L -272.83408 619.52088 L -273.41008 618.58488 L -274.20208 617.93688 L -274.63408 617.64888 L -275.21008 617.43288 L -276.65008 617.28888 L -277.58608 617.36088 L -278.37808 617.57688 L -279.09808 617.86488 L -279.74608 618.29688 L -280.25008 618.87288 L -280.53808 619.52088 L -280.75408 620.31288 L -280.82608 621.17688 L -280.68208 622.40088 L -280.25008 623.40888 L -279.89008 623.84088 L -279.53008 624.12888 L -278.52208 624.63288 L -275.28208 625.56888 L -274.77808 625.78488 L -274.41808 626.14488 L -274.27408 626.57688 L -274.20208 627.22488 L -274.34608 628.08888 L -274.77808 628.80888 L -275.57008 629.24088 L -276.57808 629.38488 L -277.65808 629.24088 L -278.09008 629.02488 L -278.45008 628.73688 L -278.73808 628.30488 L -278.95408 627.87288 L -279.17008 626.79288 L -280.53808 626.79288 L -@c -F - -@rax %Note: Object -287.16208 617.28888 296.59408 630.89688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -296.45008 626.64888 m -296.30608 627.58488 L -296.09008 628.37688 L -295.65808 629.09688 L -295.15408 629.74488 L -294.50608 630.24888 L -293.78608 630.60888 L -292.99408 630.82488 L -292.13008 630.89688 L -291.05008 630.75288 L -290.11408 630.39288 L -289.25008 629.81688 L -288.53008 629.09688 L -287.95408 628.08888 L -287.52208 626.86488 L -287.30608 625.56888 L -287.16208 624.05688 L -287.30608 622.54488 L -287.52208 621.24888 L -287.95408 620.09688 L -288.45808 619.08888 L -289.17808 618.36888 L -289.97008 617.79288 L -290.90608 617.43288 L -291.98608 617.28888 L -292.85008 617.36088 L -293.71408 617.64888 L -294.43408 618.08088 L -295.08208 618.65688 L -295.58608 619.37688 L -296.01808 620.24088 L -296.37808 621.24888 L -296.59408 622.40088 L -295.15408 622.40088 L -294.79408 620.88888 L -294.50608 620.24088 L -294.14608 619.73688 L -293.71408 619.37688 L -293.28208 619.08888 L -292.70608 618.94488 L -292.13008 618.87288 L -291.33808 618.94488 L -290.69008 619.23288 L -290.04208 619.59288 L -289.53808 620.24088 L -289.17808 620.96088 L -288.89008 621.82488 L -288.74608 622.90488 L -288.67408 624.12888 L -288.74608 625.28088 L -288.89008 626.28888 L -289.17808 627.22488 L -289.61008 627.94488 L -290.11408 628.52088 L -290.69008 628.95288 L -291.41008 629.24088 L -292.20208 629.31288 L -293.28208 629.16888 L -294.14608 628.59288 L -294.43408 628.23288 L -294.72208 627.80088 L -295.08208 626.64888 L -296.45008 626.64888 L -@c -F - -@rax %Note: Object -303.36208 617.64888 311.71408 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -303.36208 630.53688 m -303.36208 617.64888 L -304.80208 617.64888 L -304.80208 623.69688 L -310.27408 623.69688 L -310.27408 617.64888 L -311.71408 617.64888 L -311.71408 630.53688 L -310.27408 630.53688 L -310.27408 625.20888 L -304.80208 625.20888 L -304.80208 630.53688 L -303.36208 630.53688 L -@c -F - -@rax %Note: Object -319.13008 617.64888 326.90608 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -319.13008 630.53688 m -319.13008 617.64888 L -326.90608 617.64888 L -326.90608 619.23288 L -320.57008 619.23288 L -320.57008 623.48088 L -326.33008 623.48088 L -326.33008 625.06488 L -320.57008 625.06488 L -320.57008 629.02488 L -326.83408 629.02488 L -326.83408 630.53688 L -319.13008 630.53688 L -@c -F - -@rax %Note: Object -333.96208 617.64888 342.81808 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -333.96208 630.53688 m -333.96208 617.64888 L -335.47408 617.64888 L -335.47408 623.19288 L -339.07408 623.19288 L -339.72208 623.04888 L -340.22608 622.76088 L -340.51408 622.40088 L -340.65808 621.96888 L -340.80208 620.16888 L -340.80208 619.37688 L -340.87408 618.80088 L -341.01808 617.64888 L -342.81808 617.64888 L -342.81808 617.93688 L -342.45808 618.29688 L -342.31408 618.72888 L -342.17008 621.82488 L -342.09808 622.61688 L -341.88208 623.19288 L -341.45008 623.62488 L -340.87408 623.98488 L -341.59408 624.56088 L -342.02608 625.20888 L -342.31408 626.07288 L -342.38608 627.15288 L -342.24208 628.37688 L -341.81008 629.31288 L -341.30608 629.81688 L -340.65808 630.24888 L -339.86608 630.46488 L -339.07408 630.53688 L -333.96208 630.53688 L -@c -335.47408 629.09688 m -339.07408 629.09688 L -339.14608 629.02488 L -339.65008 629.02488 L -340.15408 628.80888 L -340.58608 628.30488 L -340.80208 627.65688 L -340.87408 626.86488 L -340.80208 625.92888 L -340.44208 625.28088 L -339.86608 624.84888 L -339.14608 624.70488 L -335.47408 624.70488 L -335.47408 629.09688 L -@c -F - -@rax %Note: Object -349.65808 617.64888 358.44208 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -349.65808 630.53688 m -349.65808 617.64888 L -351.09808 617.64888 L -351.09808 623.19288 L -354.77008 623.19288 L -355.34608 623.04888 L -355.85008 622.76088 L -356.13808 622.40088 L -356.35408 621.96888 L -356.42608 620.16888 L -356.49808 619.37688 L -356.49808 618.80088 L -356.71408 617.64888 L -358.44208 617.64888 L -358.44208 617.93688 L -358.08208 618.29688 L -357.93808 618.72888 L -357.79408 621.82488 L -357.72208 622.61688 L -357.50608 623.19288 L -357.14608 623.62488 L -356.57008 623.98488 L -357.21808 624.56088 L -357.72208 625.20888 L -357.93808 626.07288 L -358.08208 627.15288 L -357.93808 628.37688 L -357.50608 629.31288 L -357.00208 629.81688 L -356.28208 630.24888 L -355.56208 630.46488 L -354.69808 630.53688 L -349.65808 630.53688 L -@c -351.09808 629.09688 m -354.69808 629.09688 L -354.77008 629.02488 L -355.27408 629.02488 L -355.77808 628.80888 L -356.21008 628.30488 L -356.49808 627.65688 L -356.57008 626.86488 L -356.42608 625.92888 L -356.06608 625.28088 L -355.49008 624.84888 L -354.77008 624.70488 L -351.09808 624.70488 L -351.09808 629.09688 L -@c -F - -@rax %Note: Object -365.28208 617.64888 373.13008 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -365.28208 630.53688 m -365.28208 617.64888 L -373.13008 617.64888 L -373.13008 619.23288 L -366.72208 619.23288 L -366.72208 623.48088 L -372.48208 623.48088 L -372.48208 625.06488 L -366.72208 625.06488 L -366.72208 629.02488 L -372.98608 629.02488 L -372.98608 630.53688 L -365.28208 630.53688 L -@c -F - -@rax %Note: Object -380.11408 617.64888 388.97008 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -380.11408 630.53688 m -380.11408 617.64888 L -381.62608 617.64888 L -381.62608 623.19288 L -385.22608 623.19288 L -385.87408 623.04888 L -386.37808 622.76088 L -386.66608 622.40088 L -386.81008 621.96888 L -386.95408 620.16888 L -386.95408 619.37688 L -387.02608 618.80088 L -387.17008 617.64888 L -388.97008 617.64888 L -388.97008 617.93688 L -388.61008 618.29688 L -388.46608 618.72888 L -388.32208 621.82488 L -388.25008 622.61688 L -388.03408 623.19288 L -387.60208 623.62488 L -387.02608 623.98488 L -387.74608 624.56088 L -388.17808 625.20888 L -388.46608 626.07288 L -388.53808 627.15288 L -388.39408 628.37688 L -387.96208 629.31288 L -387.45808 629.81688 L -386.81008 630.24888 L -386.01808 630.46488 L -385.22608 630.53688 L -380.11408 630.53688 L -@c -381.62608 629.09688 m -385.22608 629.09688 L -385.29808 629.02488 L -385.80208 629.02488 L -386.30608 628.80888 L -386.73808 628.30488 L -386.95408 627.65688 L -387.02608 626.86488 L -386.95408 625.92888 L -386.59408 625.28088 L -386.01808 624.84888 L -385.29808 624.70488 L -381.62608 624.70488 L -381.62608 629.09688 L -@c -F - -@rax %Note: Object -410.85808 617.64888 412.29808 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -410.85808 630.53688 m -410.85808 617.64888 L -412.29808 617.64888 L -412.29808 630.53688 L -410.85808 630.53688 L -@c -F - -@rax %Note: Object -419.71408 617.64888 428.13808 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -419.71408 630.53688 m -419.71408 617.64888 L -421.15408 617.64888 L -421.15408 628.08888 L -426.55408 617.64888 L -428.13808 617.64888 L -428.13808 630.53688 L -426.77008 630.53688 L -426.77008 620.09688 L -421.44208 630.53688 L -419.71408 630.53688 L -@c -F - -@rax %Note: Object -434.97808 617.28888 443.40208 630.89688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -443.11408 626.79288 m -443.04208 627.72888 L -442.82608 628.52088 L -442.53808 629.24088 L -442.03408 629.81688 L -441.45808 630.32088 L -440.81008 630.60888 L -439.94608 630.82488 L -439.08208 630.89688 L -438.21808 630.82488 L -437.49808 630.60888 L -436.85008 630.32088 L -436.34608 629.81688 L -435.91408 629.24088 L -435.62608 628.59288 L -435.41008 627.80088 L -435.33808 626.93688 L -435.41008 626.21688 L -435.55408 625.64088 L -435.84208 625.06488 L -436.20208 624.63288 L -436.77808 624.20088 L -437.35408 623.91288 L -440.30608 623.12088 L -441.02608 622.76088 L -441.60208 622.32888 L -441.89008 621.75288 L -442.03408 621.03288 L -441.96208 620.45688 L -441.81808 620.02488 L -441.60208 619.66488 L -441.24208 619.37688 L -440.30608 618.94488 L -439.29808 618.80088 L -438.65008 618.87288 L -438.07408 619.01688 L -437.57008 619.23288 L -437.13808 619.59288 L -436.77808 620.02488 L -436.56208 620.52888 L -436.41808 621.10488 L -436.34608 621.82488 L -434.97808 621.82488 L -435.12208 620.45688 L -435.41008 619.52088 L -435.98608 618.58488 L -436.77808 617.93688 L -437.21008 617.64888 L -437.85808 617.43288 L -439.22608 617.28888 L -440.16208 617.36088 L -440.95408 617.57688 L -441.67408 617.86488 L -442.32208 618.29688 L -442.82608 618.87288 L -443.11408 619.52088 L -443.33008 620.31288 L -443.40208 621.17688 L -443.25808 622.40088 L -442.82608 623.40888 L -442.46608 623.84088 L -442.10608 624.12888 L -441.09808 624.63288 L -437.85808 625.56888 L -437.35408 625.78488 L -436.99408 626.14488 L -436.85008 626.57688 L -436.77808 627.22488 L -436.92208 628.08888 L -437.35408 628.80888 L -438.14608 629.24088 L -439.15408 629.38488 L -440.23408 629.24088 L -440.66608 629.02488 L -441.02608 628.73688 L -441.31408 628.30488 L -441.53008 627.87288 L -441.74608 626.79288 L -443.11408 626.79288 L -@c -F - -@rax %Note: Object -449.30608 617.64888 457.94608 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -449.30608 630.53688 m -449.30608 629.02488 L -452.90608 629.02488 L -452.90608 617.64888 L -454.34608 617.64888 L -454.34608 629.02488 L -457.94608 629.02488 L -457.94608 630.53688 L -449.30608 630.53688 L -@c -F - -@rax %Note: Object -464.49808 617.64888 465.93808 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -464.49808 630.53688 m -464.49808 617.64888 L -465.93808 617.64888 L -465.93808 630.53688 L -464.49808 630.53688 L -@c -F - -@rax %Note: Object -472.41808 617.64888 481.05808 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -472.41808 630.53688 m -472.41808 629.02488 L -476.01808 629.02488 L -476.01808 617.64888 L -477.45808 617.64888 L -477.45808 629.02488 L -481.05808 629.02488 L -481.05808 630.53688 L -472.41808 630.53688 L -@c -F - -@rax %Note: Object -487.39408 617.28888 495.74608 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -487.39408 630.53688 m -487.39408 621.75288 L -487.53808 620.60088 L -487.89808 619.52088 L -488.54608 618.51288 L -489.33808 617.86488 L -490.34608 617.43288 L -491.49808 617.28888 L -492.43408 617.36088 L -493.29808 617.64888 L -494.01808 618.08088 L -494.59408 618.65688 L -495.09808 619.30488 L -495.45808 620.09688 L -495.67408 620.96088 L -495.74608 621.82488 L -495.74608 630.53688 L -494.30608 630.53688 L -494.30608 622.18488 L -494.30608 622.04088 L -494.23408 621.46488 L -494.01808 620.38488 L -493.44208 619.59288 L -493.01008 619.23288 L -492.57808 619.01688 L -492.07408 618.87288 L -491.57008 618.87288 L -490.99408 618.87288 L -490.41808 619.08888 L -489.98608 619.37688 L -489.55408 619.73688 L -489.26608 620.24088 L -489.05008 620.81688 L -488.90608 621.53688 L -488.83408 622.32888 L -488.83408 630.53688 L -487.39408 630.53688 L -@c -F - -@rax %Note: Object -502.08208 617.64888 510.72208 630.53688 @E - 0 O 0 @g -0.84 0.73 0.72 0.91 k -/$fm 0 def -502.08208 630.53688 m -502.08208 629.02488 L -505.68208 629.02488 L -505.68208 617.64888 L -507.12208 617.64888 L -507.12208 629.02488 L -510.72208 629.02488 L -510.72208 630.53688 L -502.08208 630.53688 L -@c -F - -%%PageTrailer -@rs -@rs -%%Trailer -@EndSysCorelDict -end -%%DocumentSuppliedResources: procset wCorel7Dict -%%EOF \ No newline at end of file diff --git a/manual/figures/psi_logo_wide.pdf b/manual/figures/psi_logo_wide.pdf deleted file mode 100644 index e713fcb504a3da8579f4fba9201f15abf8fb9502..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5603 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 QQGg;9n8d{N%?z0S3yH3GTmS$7 diff --git a/manual/html.sty b/manual/html.sty deleted file mode 100644 index b5f8fbb84..000000000 --- a/manual/html.sty +++ /dev/null @@ -1,887 +0,0 @@ -% -% $Id: html.sty,v 1.23 1998/02/26 10:32:24 latex2html Exp $ -% LaTeX2HTML Version 96.2 : html.sty -% -% This file contains definitions of LaTeX commands which are -% processed in a special way by the translator. -% For example, there are commands for embedding external hypertext links, -% for cross-references between documents or for including raw HTML. -% This file includes the comments.sty file v2.0 by Victor Eijkhout -% In most cases these commands do nothing when processed by LaTeX. -% -% Place this file in a directory accessible to LaTeX (i.e., somewhere -% in the TEXINPUTS path.) -% -% NOTE: This file works with LaTeX 2.09 or (the newer) LaTeX2e. -% If you only have LaTeX 2.09, some complex LaTeX2HTML features -% like support for segmented documents are not available. - -% Changes: -% See the change log at end of file. - - -% Exit if the style file is already loaded -% (suggested by Lee Shombert -\ifx \htmlstyloaded\relax \endinput\else\let\htmlstyloaded\relax\fi -\makeatletter - -\providecommand{\latextohtml}{\LaTeX2\texttt{HTML}} - - -%%% LINKS TO EXTERNAL DOCUMENTS -% -% This can be used to provide links to arbitrary documents. -% The first argumment should be the text that is going to be -% highlighted and the second argument a URL. -% The hyperlink will appear as a hyperlink in the HTML -% document and as a footnote in the dvi or ps files. -% -\newcommand{\htmladdnormallinkfoot}[2]{#1\footnote{#2}} - - -% This is an alternative definition of the command above which -% will ignore the URL in the dvi or ps files. -\newcommand{\htmladdnormallink}[2]{#1} - - -% This command takes as argument a URL pointing to an image. -% The image will be embedded in the HTML document but will -% be ignored in the dvi and ps files. -% -\newcommand{\htmladdimg}[1]{} - - -%%% CROSS-REFERENCES BETWEEN (LOCAL OR REMOTE) DOCUMENTS -% -% This can be used to refer to symbolic labels in other Latex -% documents that have already been processed by the translator. -% The arguments should be: -% #1 : the URL to the directory containing the external document -% #2 : the path to the labels.pl file of the external document. -% If the external document lives on a remote machine then labels.pl -% must be copied on the local machine. -% -%e.g. \externallabels{http://cbl.leeds.ac.uk/nikos/WWW/doc/tex2html/latex2html} -% {/usr/cblelca/nikos/tmp/labels.pl} -% The arguments are ignored in the dvi and ps files. -% -\newcommand{\externallabels}[2]{} - - -% This complements the \externallabels command above. The argument -% should be a label defined in another latex document and will be -% ignored in the dvi and ps files. -% -\newcommand{\externalref}[1]{} - - -% Suggested by Uffe Engberg (http://www.brics.dk/~engberg/) -% This allows the same effect for citations in external bibliographies. -% An \externallabels command must be given, locating a labels.pl file -% which defines the location and keys used in the external .html file. -% -\newcommand{\externalcite}{\nocite} - - -%%% HTMLRULE -% This command adds a horizontal rule and is valid even within -% a figure caption. -% Here we introduce a stub for compatibility. -\newcommand{\htmlrule}{\protect\HTMLrule} -\newcommand{\HTMLrule}{\@ifstar\htmlrulestar\htmlrulestar} -\newcommand{\htmlrulestar}[1]{} - -% This command adds information within the ... tag -% -\newcommand{\bodytext}[1]{} -\newcommand{\htmlbody}{} - - -%%% HYPERREF -% Suggested by Eric M. Carol -% Similar to \ref but accepts conditional text. -% The first argument is HTML text which will become ``hyperized'' -% (underlined). -% The second and third arguments are text which will appear only in the paper -% version (DVI file), enclosing the fourth argument which is a reference to a label. -% -%e.g. \hyperref{using the tracer}{using the tracer (see Section}{)}{trace} -% where there is a corresponding \label{trace} -% -\newcommand{\hyperref}{\hyperrefx[ref]} -\def\hyperrefx[#1]{{\def\next{#1}% - \def\tmp{ref}\ifx\next\tmp\aftergroup\hyperrefref - \else\def\tmp{pageref}\ifx\next\tmp\aftergroup\hyperpageref - \else\def\tmp{page}\ifx\next\tmp\aftergroup\hyperpageref - \else\def\tmp{noref}\ifx\next\tmp\aftergroup\hypernoref - \else\def\tmp{no}\ifx\next\tmp\aftergroup\hypernoref - \else\typeout{*** unknown option \next\space to hyperref ***}% - \fi\fi\fi\fi\fi}} -\newcommand{\hyperrefref}[4]{#2\ref{#4}#3} -\newcommand{\hyperpageref}[4]{#2\pageref{#4}#3} -\newcommand{\hypernoref}[3]{#2} - - -%%% HYPERCITE --- added by RRM -% Suggested by Stephen Simpson -% effects the same ideas as in \hyperref, but for citations. -% It does not allow an optional argument to the \cite, in LaTeX. -% -% \hypercite{}{}{}{} -% -% uses the pre/post-texts in LaTeX, with a \cite{} -% -% \hypercite[ext]{}{}{} -% -% uses the pre/post-texts in LaTeX, with a \nocite{} -% the actual reference comes from an \externallabels file. -% -\newcommand{\hypercite}{\hypercitex[int]} -\def\hypercitex[#1]{{\def\next{#1}% - \def\tmp{int}\ifx\next\tmp\aftergroup\hyperciteint - \else\def\tmp{cite}\ifx\next\tmp\aftergroup\hyperciteint - \else\def\tmp{ext}\ifx\next\tmp\aftergroup\hyperciteext - \else\def\tmp{nocite}\ifx\next\tmp\aftergroup\hyperciteext - \else\def\tmp{no}\ifx\next\tmp\aftergroup\hyperciteext - \else\typeout{*** unknown option \next\space to hypercite ***}% - \fi\fi\fi\fi\fi}} -\newcommand{\hyperciteint}[4]{#2{\def\tmp{#3}\def\emptyopt{}% - \ifx\tmp\emptyopt\cite{#4}\else\cite[#3]{#4}\fi}} -\newcommand{\hyperciteext}[3]{#2\nocite{#3}} - - - -%%% HTMLREF -% Reference in HTML version only. -% Mix between \htmladdnormallink and \hyperref. -% First arg is text for in both versions, second is label for use in HTML -% version. -\newcommand{\htmlref}[2]{#1} - -%%% HTMLCITE -% Reference in HTML version only. -% Mix between \htmladdnormallink and \hypercite. -% First arg is text for in both versions, second is citation for use in HTML -% version. -\newcommand{\htmlcite}[2]{#1} - - -%%% HTMLIMAGE -% This command can be used inside any environment that is converted -% into an inlined image (eg a "figure" environment) in order to change -% the way the image will be translated. The argument of \htmlimage -% is really a string of options separated by commas ie -% [scale=],[external],[thumbnail= -% The scale option allows control over the size of the final image. -% The ``external'' option will cause the image not to be inlined -% (images are inlined by default). External images will be accessible -% via a hypertext link. -% The ``thumbnail'' option will cause a small inlined image to be -% placed in the caption. The size of the thumbnail depends on the -% reduction factor. The use of the ``thumbnail'' option implies -% the ``external'' option. -% -% Example: -% \htmlimage{scale=1.5,external,thumbnail=0.2} -% will cause a small thumbnail image 1/5th of the original size to be -% placed in the final document, pointing to an external image 1.5 -% times bigger than the original. -% -\newcommand{\htmlimage}[1]{} - - -% \htmlborder causes a border to be placed around an image or table -% when the image is placed within a cell. -\newcommand{\htmlborder}[1]{} - -% Put \begin{makeimage}, \end{makeimage} around LaTeX to ensure its -% translation into an image. -% This shields sensitive text from being translated. -\newenvironment{makeimage}{}{} - - -% A dummy environment that can be useful to alter the order -% in which commands are processed, in LaTeX2HTML -\newenvironment{tex2html_deferred}{}{} - - -%%% HTMLADDTONAVIGATION -% This command appends its argument to the buttons in the navigation -% panel. It is ignored by LaTeX. -% -% Example: -% \htmladdtonavigation{\htmladdnormallink -% {\htmladdimg{http://server/path/to/gif}} -% {http://server/path}} -\newcommand{\htmladdtonavigation}[1]{} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Comment.sty version 2.0, 19 June 1992 -% selectively in/exclude pieces of text: the user can define new -% comment versions, and each is controlled separately. -% This style can be used with plain TeX or LaTeX, and probably -% most other packages too. -% -% Examples of use in LaTeX and TeX follow \endinput -% -% Author -% Victor Eijkhout -% Department of Computer Science -% University Tennessee at Knoxville -% 104 Ayres Hall -% Knoxville, TN 37996 -% USA -% -% eijkhout@cs.utk.edu -% -% Usage: all text included in between -% \comment ... \endcomment -% or \begin{comment} ... \end{comment} -% is discarded. The closing command should appear on a line -% of its own. No starting spaces, nothing after it. -% This environment should work with arbitrary amounts -% of comment. -% -% Other 'comment' environments are defined by -% and are selected/deselected with -% \includecomment{versiona} -% \excludecoment{versionb} -% -% These environments are used as -% \versiona ... \endversiona -% or \begin{versiona} ... \end{versiona} -% with the closing command again on a line of its own. -% -% Basic approach: -% to comment something out, scoop up every line in verbatim mode -% as macro argument, then throw it away. -% For inclusions, both the opening and closing comands -% are defined as noop -% -% Changed \next to \html@next to prevent clashes with other sty files -% (mike@emn.fr) -% Changed \html@next to \htmlnext so the \makeatletter and -% \makeatother commands could be removed (they were causing other -% style files - changebar.sty - to crash) (nikos@cbl.leeds.ac.uk) -% Changed \htmlnext back to \html@next... - -\def\makeinnocent#1{\catcode`#1=12 } -\def\csarg#1#2{\expandafter#1\csname#2\endcsname} - -\def\ThrowAwayComment#1{\begingroup - \def\CurrentComment{#1}% - \let\do\makeinnocent \dospecials - \makeinnocent\^^L% and whatever other special cases - \endlinechar`\^^M \catcode`\^^M=12 \xComment} -{\catcode`\^^M=12 \endlinechar=-1 % - \gdef\xComment#1^^M{\def\test{#1}\edef\test{\meaning\test} - \csarg\ifx{PlainEnd\CurrentComment Test}\test - \let\html@next\endgroup - \else \csarg\ifx{LaLaEnd\CurrentComment Test}\test - \edef\html@next{\endgroup\noexpand\end{\CurrentComment}} - \else \csarg\ifx{LaInnEnd\CurrentComment Test}\test - \edef\html@next{\endgroup\noexpand\end{\CurrentComment}} - \else \let\html@next\xComment - \fi \fi \fi \html@next} -} - -\def\includecomment - #1{\expandafter\def\csname#1\endcsname{}% - \expandafter\def\csname end#1\endcsname{}} -\def\excludecomment - #1{\expandafter\def\csname#1\endcsname{\ThrowAwayComment{#1}}% - {\escapechar=-1\relax - \edef\tmp{\string\\end#1}% - \csarg\xdef{PlainEnd#1Test}{\meaning\tmp}% - \edef\tmp{\string\\end\string\{#1\string\}}% - \csarg\xdef{LaLaEnd#1Test}{\meaning\tmp}% - \edef\tmp{\string\\end \string\{#1\string\}}% - \csarg\xdef{LaInnEnd#1Test}{\meaning\tmp}% - }} - -\excludecomment{comment} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% end Comment.sty -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% -% Alternative code by Robin Fairbairns, 22 September 1997 -% -\newcommand\@gobbleenv{\let\reserved@a\@currenvir\@gobble@nv} -\long\def\@gobble@nv#1\end#2{\def\reserved@b{#2}% - \ifx\reserved@a\reserved@b - \edef\reserved@a{\noexpand\end{\reserved@a}}% - \expandafter\reserved@a - \else - \expandafter\@gobble@nv - \fi} - -\renewcommand{\excludecomment}[1]{% - \csname newenvironment\endcsname{#1}{\@gobbleenv}{}} - -%%% RAW HTML -% -% Enclose raw HTML between a \begin{rawhtml} and \end{rawhtml}. -% The html environment ignores its body -% -\excludecomment{rawhtml} - - -%%% HTML ONLY -% -% Enclose LaTeX constructs which will only appear in the -% HTML output and will be ignored by LaTeX with -% \begin{htmlonly} and \end{htmlonly} -% -\excludecomment{htmlonly} -% Shorter version -\newcommand{\html}[1]{} - -% for images.tex only -\excludecomment{imagesonly} - -%%% LaTeX ONLY -% Enclose LaTeX constructs which will only appear in the -% DVI output and will be ignored by latex2html with -%\begin{latexonly} and \end{latexonly} -% -\newenvironment{latexonly}{}{} -% Shorter version -\newcommand{\latex}[1]{#1} - - -%%% LaTeX or HTML -% Combination of \latex and \html. -% Say \latexhtml{this should be latex text}{this html text} -% -%\newcommand{\latexhtml}[2]{#1} -\long\def\latexhtml#1#2{#1} - - -%%% tracing the HTML conversions -% This alters the tracing-level within the processing -% performed by latex2html by adjusting $VERBOSITY -% (see latex2html.config for the appropriate values) -% -\newcommand{\htmltracing}[1]{} -\newcommand{\htmltracenv}[1]{} - - -%%% \strikeout for HTML only -% uses ... tags on the argument -% LaTeX just gobbles it up. -\newcommand{\strikeout}[1]{} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% JCL - stop input here if LaTeX2e is not present -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\ifx\if@compatibility\undefined - %LaTeX209 - \makeatother\relax\expandafter\endinput -\fi -\if@compatibility - %LaTeX2e in LaTeX209 compatibility mode - \makeatother\relax\expandafter\endinput -\fi - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Start providing LaTeX2e extension: -% This is currently: -% - additional optional argument for \htmladdimg -% - support for segmented documents -% - -\ProvidesPackage{html} - [1996/12/22 v1.1 hypertext commands for latex2html (nd, hws, rrm)] -%%%%MG - -% This command takes as argument a URL pointing to an image. -% The image will be embedded in the HTML document but will -% be ignored in the dvi and ps files. The optional argument -% denotes additional HTML tags. -% -% Example: \htmladdimg[ALT="portrait" ALIGN=CENTER]{portrait.gif} -% -\renewcommand{\htmladdimg}[2][]{} - -%%% HTMLRULE for LaTeX2e -% This command adds a horizontal rule and is valid even within -% a figure caption. -% -% This command is best used with LaTeX2e and HTML 3.2 support. -% It is like \hrule, but allows for options via key--value pairs -% as follows: \htmlrule[key1=value1, key2=value2, ...] . -% Use \htmlrule* to suppress the
tag. -% Eg. \htmlrule[left, 15, 5pt, "none", NOSHADE] produces -%

. -% Renew the necessary part. -\renewcommand{\htmlrulestar}[1][all]{} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% renew some definitions to allow optional arguments -% -% The description of the options is missing, as yet. -% -\renewcommand{\latextohtml}{\textup{\LaTeX2\texttt{HTML}}} -\renewcommand{\htmladdnormallinkfoot}[3][]{#2\footnote{#3}} -\renewcommand{\htmladdnormallink}[3][]{#2} -\renewcommand{\htmlbody}[1][]{} -\renewcommand{\hyperref}[1][ref]{\hyperrefx[#1]} -\renewcommand{\hypercite}[1][int]{\hypercitex[#1]} -\renewcommand{\htmlref}[3][]{#2} -\renewcommand{\htmlcite}[1]{#1\htmlcitex} -\newcommand{\htmlcitex}[2][]{{\def\tmp{#1}\ifx\tmp\@empty\else~[#1]\fi}} -\renewcommand{\htmlimage}[2][]{} -\renewcommand{\htmlborder}[2][]{} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% HTML HTMLset HTMLsetenv -% -% These commands do nothing in LaTeX, but can be used to place -% HTML tags or set Perl variables during the LaTeX2HTML processing; -% They are intended for expert use only. - -\newcommand{\HTMLcode}[2][]{} -\ifx\undefined\HTML\newcommand{\HTML}[2][]{}\else -\typeout{*** Warning: \string\HTML\space had an incompatible definition ***}% -\typeout{*** instead use \string\HTMLcode\space for raw HTML code ***}% -\fi -\newcommand{\HTMLset}[3][]{} -\newcommand{\HTMLsetenv}[3][]{} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% The following commands pertain to document segmentation, and -% were added by Herbert Swan (with help from -% Michel Goossens ): -% -% -% This command inputs internal latex2html tables so that large -% documents can to partitioned into smaller (more manageable) -% segments. -% -\newcommand{\internal}[2][internals]{} - -% -% Define a dummy stub \htmlhead{}. This command causes latex2html -% to define the title of the start of a new segment. It is not -% normally placed in the user's document. Rather, it is passed to -% latex2html via a .ptr file written by \segment. -% -\newcommand{\htmlhead}[3][]{} - -% In the LaTeX2HTML version this will eliminate the title line -% generated by a \segment command, but retains the title string -% for use in other places. -% -\newcommand{\htmlnohead}{} - - -% In the LaTeX2HTML version this put a URL into a tag -% within the ... portion of a document. -% -\newcommand{\htmlbase}[1]{} -% - -% -% The dummy command \endpreamble is needed by latex2html to -% mark the end of the preamble in document segments that do -% not contain a \begin{document} -% -\newcommand{\startdocument}{} - - -% \tableofchildlinks, \htmlinfo -% by Ross Moore --- extensions dated 27 September 1997 -% -% These do nothing in LaTeX but for LaTeX2HTML they mark -% where the table of child-links and info-page should be placed, -% when the user wants other than the default. -% \tableofchildlinks % put mini-TOC at this location -% \tableofchildlinks[off] % not on current page -% \tableofchildlinks[none] % not on current and subsequent pages -% \tableofchildlinks[on] % selectively on current page -% \tableofchildlinks[all] % on current and all subsequent pages -% \htmlinfo % put info-page at this location -% \htmlinfo[off] % no info-page in current document -% \htmlinfo[none] % no info-page in current document -% *-versions omit the preceding
tag. -% -\newcommand{\tableofchildlinks}{% - \@ifstar\tableofchildlinksstar\tableofchildlinksstar} -\newcommand{\tableofchildlinksstar}[1][]{} - -\newcommand{\htmlinfo}{\@ifstar\htmlinfostar\htmlinfostar} -\newcommand{\htmlinfostar}[1][]{} - - -% This redefines \begin to allow for an optional argument -% which is used by LaTeX2HTML to specify `style-sheet' information - -\let\realLaTeX@begin=\begin -\renewcommand{\begin}[1][]{\realLaTeX@begin} - - -% -% Allocate a new set of section counters, which will get incremented -% for "*" forms of sectioning commands, and for a few miscellaneous -% commands. -% - -\newcounter{lpart} -\newcounter{lchapter}[part] -\@ifundefined{c@chapter}% - {\let\Hchapter\relax \newcounter{lsection}[part]}% - {\let\Hchapter=\chapter \newcounter{lsection}[chapter]} -\newcounter{lsubsection}[section] -\newcounter{lsubsubsection}[subsection] -\newcounter{lparagraph}[subsubsection] -\newcounter{lsubparagraph}[paragraph] -\newcounter{lequation} - -% -% Redefine "*" forms of sectioning commands to increment their -% respective counters. -% -\let\Hpart=\part -%\let\Hchapter=\chapter -\let\Hsection=\section -\let\Hsubsection=\subsection -\let\Hsubsubsection=\subsubsection -\let\Hparagraph=\paragraph -\let\Hsubparagraph=\subparagraph -\let\Hsubsubparagraph=\subsubparagraph - -\ifx\c@subparagraph\undefined - \newcounter{lsubsubparagraph}[lsubparagraph] -\else - \newcounter{lsubsubparagraph}[subparagraph] -\fi - -% -% The following definitions are specific to LaTeX2e: -% (They must be commented out for LaTeX 2.09) -% -\renewcommand{\part}{\@ifstar{\stepcounter{lpart}% - \bgroup\def\tmp{*}\H@part}{\bgroup\def\tmp{}\H@part}} -\newcommand{\H@part}[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hpart\tmp} - -\ifx\Hchapter\relax\else - \def\chapter{\resetsections \@ifstar{\stepcounter{lchapter}% - \bgroup\def\tmp{*}\H@chapter}{\bgroup\def\tmp{}\H@chapter}}\fi -\newcommand{\H@chapter}[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hchapter\tmp} - -\renewcommand{\section}{\resetsubsections - \@ifstar{\stepcounter{lsection}\bgroup\def\tmp{*}% - \H@section}{\bgroup\def\tmp{}\H@section}} -\newcommand{\H@section}[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hsection\tmp} - -\renewcommand{\subsection}{\resetsubsubsections - \@ifstar{\stepcounter{lsubsection}\bgroup\def\tmp{*}% - \H@subsection}{\bgroup\def\tmp{}\H@subsection}} -\newcommand{\H@subsection}[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hsubsection\tmp} - -\renewcommand{\subsubsection}{\resetparagraphs - \@ifstar{\stepcounter{lsubsubsection}\bgroup\def\tmp{*}% - \H@subsubsection}{\bgroup\def\tmp{}\H@subsubsection}} -\newcommand{\H@subsubsection}[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hsubsubsection\tmp} - -\renewcommand{\paragraph}{\resetsubparagraphs - \@ifstar{\stepcounter{lparagraph}\bgroup\def\tmp{*}% - \H@paragraph}{\bgroup\def\tmp{}\H@paragraph}} -\newcommand\H@paragraph[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hparagraph\tmp} - -\renewcommand{\subparagraph}{\resetsubsubparagraphs - \@ifstar{\stepcounter{lsubparagraph}\bgroup\def\tmp{*}% - \H@subparagraph}{\bgroup\def\tmp{}\H@subparagraph}} -\newcommand\H@subparagraph[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hsubparagraph\tmp} - -\ifx\Hsubsubparagraph\relax\else\@ifundefined{subsubparagraph}{}{% -\def\subsubparagraph{% - \@ifstar{\stepcounter{lsubsubparagraph}\bgroup\def\tmp{*}% - \H@subsubparagraph}{\bgroup\def\tmp{}\H@subsubparagraph}}}\fi -\newcommand\H@subsubparagraph[1][]{\def\tmp@a{#1}\check@align - \expandafter\egroup\expandafter\Hsubsubparagraph\tmp} - -\def\check@align{\def\empty{}\ifx\tmp@a\empty - \else\def\tmp@b{center}\ifx\tmp@a\tmp@b\let\tmp@a\empty - \else\def\tmp@b{left}\ifx\tmp@a\tmp@b\let\tmp@a\empty - \else\def\tmp@b{right}\ifx\tmp@a\tmp@b\let\tmp@a\empty - \else\expandafter\def\expandafter\tmp@a\expandafter{\expandafter[\tmp@a]}% - \fi\fi\fi \def\empty{}\ifx\tmp\empty\let\tmp=\tmp@a \else - \expandafter\def\expandafter\tmp\expandafter{\expandafter*\tmp@a}% - \fi\fi} -% -\def\resetsections{\setcounter{section}{0}\setcounter{lsection}{0}% - \reset@dependents{section}\resetsubsections } -\def\resetsubsections{\setcounter{subsection}{0}\setcounter{lsubsection}{0}% - \reset@dependents{subsection}\resetsubsubsections } -\def\resetsubsubsections{\setcounter{subsubsection}{0}\setcounter{lsubsubsection}{0}% - \reset@dependents{subsubsection}\resetparagraphs } -% -\def\resetparagraphs{\setcounter{lparagraph}{0}\setcounter{lparagraph}{0}% - \reset@dependents{paragraph}\resetsubparagraphs } -\def\resetsubparagraphs{\ifx\c@subparagraph\undefined\else - \setcounter{subparagraph}{0}\fi \setcounter{lsubparagraph}{0}% - \reset@dependents{subparagraph}\resetsubsubparagraphs } -\def\resetsubsubparagraphs{\ifx\c@subsubparagraph\undefined\else - \setcounter{subsubparagraph}{0}\fi \setcounter{lsubsubparagraph}{0}} -% -\def\reset@dependents#1{\begingroup\let \@elt \@stpelt - \csname cl@#1\endcsname\endgroup} -% -% -% Define a helper macro to dump a single \secounter command to a file. -% -\newcommand{\DumpPtr}[2]{% -\count255=\arabic{#1}\def\dummy{dummy}\def\tmp{#2}% -\ifx\tmp\dummy\else\advance\count255 by \arabic{#2}\fi -\immediate\write\ptrfile{% -\noexpand\setcounter{#1}{\number\count255}}} - -% -% Define a helper macro to dump all counters to the file. -% The value for each counter will be the sum of the l-counter -% actual LaTeX section counter. -% Also dump an \htmlhead{section-command}{section title} command -% to the file. -% -\newwrite\ptrfile -\def\DumpCounters#1#2#3#4{% -\begingroup\let\protect=\noexpand -\immediate\openout\ptrfile = #1.ptr -\DumpPtr{part}{lpart}% -\ifx\Hchapter\relax\else\DumpPtr{chapter}{lchapter}\fi -\DumpPtr{section}{lsection}% -\DumpPtr{subsection}{lsubsection}% -\DumpPtr{subsubsection}{lsubsubsection}% -\DumpPtr{paragraph}{lparagraph}% -\DumpPtr{subparagraph}{lsubparagraph}% -\DumpPtr{equation}{lequation}% -\DumpPtr{footnote}{dummy}% -\def\tmp{#4}\ifx\tmp\@empty -\immediate\write\ptrfile{\noexpand\htmlhead{#2}{#3}}\else -\immediate\write\ptrfile{\noexpand\htmlhead[#4]{#2}{#3}}\fi -\dumpcitestatus \dumpcurrentcolor -\immediate\closeout\ptrfile -\endgroup } - - -%% interface to natbib.sty - -\def\dumpcitestatus{} -\def\loadcitestatus{\def\dumpcitestatus{% - \ifciteindex\immediate\write\ptrfile{\noexpand\citeindextrue}% - \else\immediate\write\ptrfile{\noexpand\citeindexfalse}\fi }% -} -\@ifpackageloaded{natbib}{\loadcitestatus}{% - \AtBeginDocument{\@ifpackageloaded{natbib}{\loadcitestatus}{}}} - - -%% interface to color.sty - -\def\dumpcurrentcolor{} -\def\loadsegmentcolors{% - \let\real@pagecolor=\pagecolor - \let\pagecolor\segmentpagecolor - \let\segmentcolor\color - \ifx\current@page@color\undefined \def\current@page@color{{}}\fi - \def\dumpcurrentcolor{\bgroup\def\@empty@{{}}% - \expandafter\def\expandafter\tmp\space####1@{\def\thiscol{####1}}% - \ifx\current@color\@empty@\def\thiscol{}\else - \expandafter\tmp\current@color @\fi - \immediate\write\ptrfile{\noexpand\segmentcolor{\thiscol}}% - \ifx\current@page@color\@empty@\def\thiscol{}\else - \expandafter\tmp\current@page@color @\fi - \immediate\write\ptrfile{\noexpand\segmentpagecolor{\thiscol}}% - \egroup}% - \global\let\loadsegmentcolors=\relax -} - -% These macros are needed within images.tex since this inputs -% the .ptr files for a segment, so that counters are -% colors are synchronised. -% -\newcommand{\segmentpagecolor}[1][]{% - \@ifpackageloaded{color}{\loadsegmentcolors\bgroup - \def\tmp{#1}\ifx\@empty\tmp\def\next{[]}\else\def\next{[#1]}\fi - \expandafter\segmentpagecolor@\next}% - {\@gobble}} -\def\segmentpagecolor@[#1]#2{\def\tmp{#1}\def\tmpB{#2}% - \ifx\tmpB\@empty\let\next=\egroup - \else - \let\realendgroup=\endgroup - \def\endgroup{\edef\next{\noexpand\realendgroup - \def\noexpand\current@page@color{\current@color}}\next}% - \ifx\tmp\@empty\real@pagecolor{#2}\def\model{}% - \else\real@pagecolor[#1]{#2}\def\model{[#1]}% - \fi - \edef\next{\egroup\def\noexpand\current@page@color{\current@page@color}% - \noexpand\real@pagecolor\model{#2}}% - \fi\next} -% -\newcommand{\segmentcolor}[2][named]{\@ifpackageloaded{color}% - {\loadsegmentcolors\segmentcolor[#1]{#2}}{}} - -\@ifpackageloaded{color}{\loadsegmentcolors}{\let\real@pagecolor=\@gobble - \AtBeginDocument{\@ifpackageloaded{color}{\loadsegmentcolors}{}}} - - -% Define the \segment[align]{file}{section-command}{section-title} command, -% and its helper macros. This command does four things: -% 1) Begins a new LaTeX section; -% 2) Writes a list of section counters to file.ptr, each -% of which represents the sum of the LaTeX section -% counters, and the l-counters, defined above; -% 3) Write an \htmlhead{section-title} command to file.ptr; -% 4) Inputs file.tex. - -\def\segment{\@ifstar{\@@htmls}{\@@html}} -\def\endsegment{} -\newcommand{\@@htmls}[1][]{\@@htmlsx{#1}} -\newcommand{\@@html}[1][]{\@@htmlx{#1}} -\def\@@htmlsx#1#2#3#4{\csname #3\endcsname* {#4}% - \DumpCounters{#2}{#3*}{#4}{#1}\input{#2}} -\def\@@htmlx#1#2#3#4{\csname #3\endcsname {#4}% - \DumpCounters{#2}{#3}{#4}{#1}\input{#2}} - -\makeatother -\endinput - - -% Modifications: -% -% (The listing of Initiales see Changes) - -% $Log: html.sty,v $ -% Revision 1.23 1998/02/26 10:32:24 latex2html -% -- use \providecommand for \latextohtml -% -- implemented \HTMLcode to do what \HTML did previously -% \HTML still works, unless already defined by another package -% -- fixed problems remaining with undefined \chapter -% -- defined \endsegment -% -% Revision 1.22 1997/12/05 11:38:18 RRM -% -- implemented an optional argument to \begin for style-sheet info. -% -- modified use of an optional argument with sectioning-commands -% -% Revision 1.21 1997/11/05 10:28:56 RRM -% -- replaced redefinition of \@htmlrule with \htmlrulestar -% -% Revision 1.20 1997/10/28 02:15:58 RRM -% -- altered the way some special html-macros are defined, so that -% star-variants are explicitly defined for LaTeX -% -- it is possible for these to occur within images.tex -% e.g. \htmlinfostar \htmlrulestar \tableofchildlinksstar -% -% Revision 1.19 1997/10/11 05:47:48 RRM -% -- allow the dummy {tex2html_nowrap} environment in LaTeX -% use it to make its contents be evaluated in environment order -% -% Revision 1.18 1997/10/04 06:56:50 RRM -% -- uses Robin Fairbairns' code for ignored environments, -% replacing the previous comment.sty stuff. -% -- extensions to the \tableofchildlinks command -% -- extensions to the \htmlinfo command -% -% Revision 1.17 1997/07/08 11:23:39 RRM -% include value of footnote counter in .ptr files for segments -% -% Revision 1.16 1997/07/03 08:56:34 RRM -% use \textup within the \latextohtml macro -% -% Revision 1.15 1997/06/15 10:24:58 RRM -% new command \htmltracenv as environment-ordered \htmltracing -% -% Revision 1.14 1997/06/06 10:30:37 RRM -% - new command: \htmlborder puts environment into a
cell -% with a border of specified width, + other attributes. -% - new commands: \HTML for setting arbitrary HTML tags, with attributes -% \HTMLset for setting Perl variables, while processing -% \HTMLsetenv same as \HTMLset , but it gets processed -% as if it were an environment. -% - new command: \latextohtml --- to set the LaTeX2HTML name/logo -% - fixed some remaining problems with \segmentcolor & \segmentpagecolor -% -% Revision 1.13 1997/05/19 13:55:46 RRM -% alterations and extra options to \hypercite -% -% Revision 1.12 1997/05/09 12:28:39 RRM -% - Added the optional argument to \htmlhead, also in \DumpCounters -% - Implemented \HTMLset as a no-op in LaTeX. -% - Fixed a bug in accessing the page@color settings. -% -% Revision 1.11 1997/03/26 09:32:40 RRM -% - Implements LaTeX versions of \externalcite and \hypercite commands. -% Thanks to Uffe Engberg and Stephen Simpson for the suggestions. -% -% Revision 1.10 1997/03/06 07:37:58 RRM -% Added the \htmltracing command, for altering $VERBOSITY . -% -% Revision 1.9 1997/02/17 02:26:26 RRM -% - changes to counter handling (RRM) -% - shuffled around some definitions -% - changed \htmlrule of 209 mode -% -% Revision 1.8 1997/01/26 09:04:12 RRM -% RRM: added optional argument to sectioning commands -% \htmlbase sets the tag -% \htmlinfo and \htmlinfo* allow the document info to be positioned -% -% Revision 1.7 1997/01/03 12:15:44 L2HADMIN -% % - fixes to the color and natbib interfaces -% % - extended usage of \hyperref, via an optional argument. -% % - extended use comment environments to allow shifting expansions -% % e.g. within \multicolumn (`bug' reported by Luc De Coninck). -% % - allow optional argument to: \htmlimage, \htmlhead, -% % \htmladdimg, \htmladdnormallink, \htmladdnormallinkfoot -% % - added new commands: \htmlbody, \htmlnohead -% % - added new command: \tableofchildlinks -% -% Revision 1.6 1996/12/25 03:04:54 JCL -% added patches to segment feature from Martin Wilck -% -% Revision 1.5 1996/12/23 01:48:06 JCL -% o introduced the environment makeimage, which may be used to force -% LaTeX2HTML to generate an image from the contents. -% There's no magic, all what we have now is a defined empty environment -% which LaTeX2HTML will not recognize and thus pass it to images.tex. -% o provided \protect to the \htmlrule commands to allow for usage -% within captions. -% -% Revision 1.4 1996/12/21 19:59:22 JCL -% - shuffled some entries -% - added \latexhtml command -% -% Revision 1.3 1996/12/21 12:22:59 JCL -% removed duplicate \htmlrule, changed \htmlrule back not to create a \hrule -% to allow occurrence in caption -% -% Revision 1.2 1996/12/20 04:03:41 JCL -% changed occurrence of \makeatletter, \makeatother -% added new \htmlrule command both for the LaTeX2.09 and LaTeX2e -% sections -% -% -% jcl 30-SEP-96 -% - Stuck the commands commonly used by both LaTeX versions to the top, -% added a check which stops input or reads further if the document -% makes use of LaTeX2e. -% - Introduced rrm's \dumpcurrentcolor and \bodytext -% hws 31-JAN-96 - Added support for document segmentation -% hws 10-OCT-95 - Added \htmlrule command -% jz 22-APR-94 - Added support for htmlref -% nd - Created diff --git a/manual/introduction.tex b/manual/introduction.tex deleted file mode 100644 index 0d305a764..000000000 --- a/manual/introduction.tex +++ /dev/null @@ -1,348 +0,0 @@ -\chapter{Introduction} -\label{sec:Introduction} -One of \ippl 's most attractive features is its high performance on both single-processor and distributed-memory multiprocessor machines. As future releases of the library will also support shared-memory machines. - -The heart of the problem \ippl 's authors face is that while data-parallel programming is a natural way to express many scientific and numerical algorithms, straightforward implementations of it do exactly the wrong thing on modern architectures, whose performance depends critically on the re-use of data loaded into cache. If a program evaluates A+B+C for three arrays A, B, and C by adding A to B, then adding C to that calculation's result, performance suffers both because of the overhead of executing two loops instead of one, but also (and more importantly) because every value in the temporary array that stores the result of A+B has to be accessed twice: once to write it, and once to read it back in. As soon as this array is too large to fit into cache, the program's performance will drop dramatically. - -%The first section of this tutorial explains what \ippl does to solve this problem. Subsequent sections discuss other advanced aspects of \ippl , such as how to build pointwise functions, or reduction functions that will execute efficiently regardless of how arrays are laid out in memory. - -%\ippl tries to resolve the tension between how programmers want to express their ideas, and what runs most efficiently on modern architectures, by delaying the evaluation of expressions until enough is known about their context to ensure that they can be evaluated efficiently. It does this by blocking calculations into units called iterates, and putting those iterates into a queue of work that is still to be done. Each iterate is a portion of a computation, over a portion of a domain. \ippl tracks data dependencies between iterates dynamically to ensure that out-of-order computation cannot occur. - -%Depending on the switches specified during configuration when the library is installed, and the version of the \ippl library that a program is linked against, \ippl will run in one of four different modes. In the first mode, the work queue doesn't actually exist. Instead, the single thread of execution in the program evaluates iterates as soon as they are "enqueued", i.e. work is done immediately. The result is that all of the calculations in a statement are completed by the time execution reaches the semi-colon at the end of that statement. - -%In its second mode, \ippl maintains the work queue, but all work is done by a single thread. The queue is used because the explicit parceling up of work into iterates gives \ippl an opportunity to re-order or combine those iterates. While the overhead of maintaining and inspecting the work queue can slow down operations on small arrays, it makes operations on large arrays much faster. - -%For example, consider the four function calls that perform red/black relaxation in the second tutorial. In order to get the highest possible performance out of the cache, all four of these expressions should be evaluated on a given cache block before any of the expressions are evaluated for the next cache block. Managing this by hand is a nightmare, both because cache size varies from machine to machine (even when those machines come from the same manufacturer), and because very slight changes in the dimensions of arrays can tip them in or out of cache. \ippl 's array classes and overloaded operators do part of the job by creating appropriately-sized iterates; its work queue does the rest of the job by deciding how best to evaluate them. The net result is higher performance for less programmer effort. - -%\ippl 's third and fourth modes of operation are multi-threaded. Each thread in a pool takes iterates from the work queue when and as they become available. Iterates are evaluated independently; the difference between the two modes is that one is synchronous, and blocks after evaluating each data-parallel statement, while the other is asynchronous, i.e. permits out-of-order execution. The table below summarizes these four modes, along with the configuration arguments used to produce each. - - -\section{Example 1 Laplace solver using Jacobi iteration} -\begin{code}[caption={Laplace solver}] -#include "Ippl.h" -int main(int argc, char *argv[]) -{ - Ippl ippl(argc,argv); - Inform msg(argv[0]); - const unsigned N=8; - const unsigned Dim=2; - - Index IGLOBAL(N); // Specify the global domain - Index JGLOBAL(N); - - Index I(1, N-1); // Specify the interior domain - Index J(1, N-1); - FieldLayout layout(IGLOBAL,JGLOBAL); - GuardCellSizes gc(1); - typedef UniformCartesian Mesh; - Field A(layout,gc); - Field b(layout,gc); - - assign(A,0.0); // Assign initial conditions - assign(b,0.0); - - b[N/2][N/2] = -1.0; // put a spike on the RHS - double fact = 0.25; - - // Iterate 200 times - for (int i=0; i<200; ++i) { - assign(A[I][J],fact*(A[I+1][J] + - A[I-1][J] + - A[I][J+1] + - A[I][J-1] - b[I][J])); - } - msg << A << endl; - return 0; -} -\end{code} -The syntax is very similar to that of Fortran 90: a single assignment fills an entire array with a scalar value, subscripts express ranges as well as single points, and so on. In fact, the combination of C++ and \ippl provides so many of the features of Fortran 90 that one might well ask whether it wouldn't better to just use the latter language straight up. One answer comes down to economics. While the various flavors of Fortran are still used in scientific computing, Fortran's user base is shrinking, particularly in comparison to C++. Networking, graphics, database access, and operating system interfaces are available in C++ programmers long before they're available in Fortran (if they become available at all). What's more, support tools such as debuggers and memory inspectors are primarily targeted at C++ developers, as are hundreds of books, journal articles, and web sites. - -Another answer is that the abstraction facilities of C++ are much more powerful that those in Fortran. While Fortran 90 supports an attractive array syntax for floating point arrays one could not, for example, efficiently extend this high level syntax to arrays of vectors or tensors. Until recently, Fortran has had two powerful arguments in its favor: legacy applications, and performance. However, the importance of the former is diminishing as the invention of new algorithms force programmers to rewrite old codes, while the invention of techniques such as {\it expression templates} has made it possible for C++ programs to match, or exceed, the performance of highly-optimized Fortran 77. -%!TEX encoding = UTF-8 Unicode - -\section{Example 2 Power Spectrum} -A sinussoidal field $\rho(i,j,k) = a_1sin(k_1 \frac{2\pi}{n_x} i) + a_5 sin(k_5 \frac{2\pi}{n_x} i)$, -$i= 1 \dots n_x, ~ j= 1 \dots n_y, ~ k= 1 \dots n_z $ with $n_x,n_y$ and $n_z$ denoting the grid size is generated and -the power spectrum calculated. This examples shows how to initialise fields, compute discrete complex-complex FFT and -compute the resulting powerspectrum. - -Assume a real density field is defined like -\begin{smallcode} -typedef Field Field_t; -Field_t rho; -\end{smallcode} -we then can immediately initialize the field according to the above formula -\begin{smallcode} -assign(rho[I][J][K], a1*sin(2.0*pi/nr_m[0]*k1*I) + - a5*sin(2.0*pi/nr_m[0]*k5*I)); -\end{smallcode} -Normalizing to $\max(\rho) \le 1.0 $ with -\begin{smallcode} -rho /= max(rho) -\end{smallcode} -we then assume to have defined a complex field "fC" and a complex-complex FFT. -\begin{smallcode} -fC = rho; -fft->transform("forward" , fC); - \end{smallcode} -Here we used the in place version of the FFT to obtain $\rho $ in Fourier space. Now -we can compute the power spectrum: -\begin{smallcode} -pwrSpec = real(fC*conj(fC)); -\end{smallcode} -%\pagebreak -and calculate the 1D pwr-spectrum (in x direction) by integrating over y and z: \\ -\begin{code} - NDIndex<3> elem; - for (int i=lDomain[0].min(); i<=(lDomain[0].max()-1)/2; ++i) { - elem[0]=Index(i,i); - for (int j=lDomain[1].min(); j<=(lDomain[1].max()-1)/2; ++j) { - elem[1]=Index(j,j); - for (int k=lDomain[2].min(); k<=(lDomain[2].max()-1)/2; ++k) { - elem[2]=Index(k,k); - f1D[i] += pwrSpec.localElement(elem); - } - } - } -\end{code} -The power spectra of the local domain is stored in $f1$. We have to update all other node -so that each node has the full power spectrum by: -\begin{smallcode} -reduce(&(f1[0]),&(f1[0])+f1_lenght,OpAddAssign()); -\end{smallcode} -assuming the non local part of $f1$ is initialized with zero. - -%The full code pwrspec-1.cpp is located at $\ippl_ROOT/test/simple. - - - \section{Example 3 Particle in Cell Code (PIC)} - This example discusses how to write a 3D Particle in Cell Code (PIC). The - complete source file can be found at {\em \$IPPL\_ROOT/test/particles}. The - this presentation details are omitted, only the structure and important issues are - highlighted. - \subsection{The {\em ChargedParticles} Class} - The base class {\tt ParticleBase} is augmented with attributes such as charge to mass ration - {\tt qm}, the vector momenta {\tt P} and the vector holding the electric field {\tt E}. - \begin{code} - ChargedParticles(PL* pl, Vector_t hr, Vector_t rmin, - Vector_t rmax, e_dim_tag decomp[Dim]) : - ParticleBase(pl), - hr_m(hr), - rmin_m(rmin), - rmax_m(rmax), - fieldNotInitialized_m(true) -{ - this->addAttribute(qm); - this->addAttribute(P); - this->addAttribute(E); - - for (int i=0; i < 2*Dim; i++) { - this->getBConds()[i] = ParticlePeriodicBCond; - bc_m[i] = new PeriodicFace(i); - vbc_m[i] = new PeriodicFace(i); - } - for(int i=0; i nr(atoi(argv[1]),atoi(argv[2]),atoi(argv[3])); - - const unsigned int totalP = atoi(argv[4]); - const int nt = atoi(argv[5]); - - e_dim_tag decomp[Dim]; - int serialDim = 2; - - Mesh_t *mesh; - FieldLayout_t *FL; - ChargedParticles *partBunch; - - NDIndex domain; - for(int d=0; d(PL,hr,rmin,rmax,decomp); -\end{code} - Here we construct the {\tt mesh} the field layout ({\tt FL}), describing how the fields are distributed - and finally the particle layout {\tt PL}. The latter is the used as a template argument to construct the - particle container. For this example the mesh size is set to unity and the computational domain is - the given by the number of mesh points defined in {\tt nr}. \\ -\begin{code} - unsigned long int nloc = totalP / Ippl::getNodes(); - - partBunch->create(nloc); - for (unsigned long int i = 0; i< nloc; i++) { - for (int d = 0; dR[i](d) = IpplRandom() * nr[d]; - } - - partBunch->qm = 1.0/totalP; - partBunch->myUpdate(); - partBunch->initFields(); -\end{code} - Now each node created {\tt nloc} particles and initialized the coordinates randomly in the - computational domain. A fixed charge to mass ration is assigned. The \texttt{myUpdate()} moves - all particles to their node defined by the domain decomposition and initialized the fields. In the last - call the fields gets initialized with the sinusoidal electric field. - \clearpage -\begin{code} - for (unsigned int it=0; itR = partBunch->R + dt * partBunch->P; - partBunch->myUpdate(); - partBunch->gather(); - partBunch->P += dt * partBunch->qm * partBunch->E; - } - return 0; -} -\end{code} -The last part of main consists of a simple integration scheme to advance the particles. The call -{\tt gather} interpolates the electric field at the particle position form the nearby grid points by a second -order {\it cloud in cell} (CIC) interpolation scheme. - - -\subsection{{\em initFields}} - -\begin{code} -void initFields() { - - NDIndex domain = getFieldLayout().getDomain(); - - for(int i=0; i(1), vbc_m); - EFDMag_m.initialize(getMesh(), getFieldLayout(), GuardCellSizes(1), bc_m); - } - this->update(); -} -\end{code} - - \subsection{{\em gather}} - -\begin{code} -void gather() { - IntCIC myinterp; - E.gather(EFD_m, this->R, myinterp); -} -\end{code} - -\section{Installation} - \ippl uses the {\em cmake } build philosophy. The following environment variables must be set -\begin{verbatim} -IPPL_ROOT -\end{verbatim} -defining where \ippl is installed. - -\subsection{Building \ippl} -\begin{verbatim} -cd $IPPL_ROOT -CXX=mpicxx F77=gfortran cmake -DCMAKE_VERBOSE_MAKEFILE=OFF --DCMAKE_INSTALL_PREFIX=~/extlib/ippl $IPPL_ROOT -\end{verbatim} - - -\subsection{Used Compilers and Libraries} -The supported operating systems and libraries are listed in Table \ref{tab:archlib}. -\begin{table}[h] - \caption{Supported Architectures and needed Libraries} - \label{tab:archlib} - \begin{center} - \begin{tabular}{|lcccc|} - \hline - Operating System & HDF5 & H5hut & Compiler & Open MPI\\ - \hline - Linux (SL) 2.6.18 & hdf5-1.8.5 & V0.99 & GNU 4.4.x, icc11.1 & 1.4.2 \\ - Cray XTx & hdf5-1.8.5 & V0.99 & GNU 4.4 & - \\ - \hline - \end{tabular} - \end{center} -\end{table} - - - - - -\clearpage -\section{Acknowledgements} -The contributions of various individuals and groups are acknowledged in the relevant chapters, -however a few individuals have or had considerable influence on the -development, Julian Cummings, Yves Ineichen and Jakob Progsch. -Misprints and obscurity are almost inevitable in a document of this size. -Comments and {\em active contributions} from readers are therefore most welcome. -They may also be sent to \htmladdnormallink{\texttt{andreas.adelmann@psi.ch}}{mailto:andreas.adelmann@psi.ch}. - -\subsection{Citation} -Please cite \ippl in the following way: -\begin{small} -\begin{verbatim} -@techreport{ippl-User-Guide, -title = "{The IPPL (Independent Parallel Particle Layer) - Framework }", -author = "A. Adelmann", -institution = "Paul Scherrer Institut", -number = "PSI-PR-09-05", -year = 2009} -\end{verbatim} -\end{small} - - -%& OPAL \\ -% & V 1.0 - - diff --git a/manual/ippl_centering_ref.tex b/manual/ippl_centering_ref.tex deleted file mode 100644 index fd6256363..000000000 --- a/manual/ippl_centering_ref.tex +++ /dev/null @@ -1,251 +0,0 @@ -\chapter{Centering} -\label{sec:cent} -Classes in this chapter represent the abstraction of centering at particular positions on a \texttt{Mesh}. -For any type of mesh, vertex (mesh-node) centering is well-defined. For Cartesian meshes, cell centering is well defined, because each -rectangular mesh cell has a well-defined center, the midpoint along each dimension. Also, for Cartesian meshes, combinations of cell and vertex centering -along the various dimensions clearly define common centerings such as face centering and edge centering. \ippl predefines classes for cell and vertex centering, -as well as classes to represent all possible combination centerings for Cartesian meshes. These classes are all static in the current implementation -(you do not instantiate objects of the class types, you just refer to the centerings by class name). The centering classes typically serve as the centering -template parameter for Field and other \ippl classes parameterized on centering. -\section{\texttt{Cell} Class} -The static \texttt{Cell} class represents the abstraction of cell-centering of something on a \texttt{Mesh}. -That "something" is usually a \texttt{Field}. \texttt{Cell} can serve as a value for the \texttt{Centering} template parameter of the \texttt{Field} class. Every \texttt{Field} element, whatever its type, -is centered at the position of the corresponding cell center in the \texttt{Mesh} using the same index space for mesh cell centers as -(or the \texttt{Field} elements. If the Field elements (\texttt{T} parameter for \texttt{Field} class) is some kind of multi component type such as \texttt{Vektor}, the whole object of that type in every \texttt{Field} -element is cell-centered (that is, all components have the same centering). The \texttt{CartesianCentering} class allows you to center components of \texttt{Field} elements independently. -If you center a \texttt{Field} on a \texttt{Mesh} using \texttt{Cell}, you must make sure that you construct the \texttt{Field} to have the proper number of elements so that it has one-for every cell in the mesh. -When you use \texttt{Field} constructors taking a \texttt{Mesh} object argument (instance' of the class specified as the \texttt{Mesh} template parameter for \texttt{Field}), the extents of the -\texttt{NDIndex} object or index field constructor arguments match those used to instantiate that \texttt{Mesh}. When you instantiate a \texttt{Field} with \texttt{Cell} centering using -constructors without a mesh object argument, the internally-constructed mesh object will automatically have the right number of cells. -subsection{Cell Definition (Public Interface)} -\begin{smallcode} -class Cell { -public: - static char* CenteringName ; - static void print_Centerings(ostream&) ; -}; -\end{smallcode} - - - -\subsection{\texttt{Cell} Constructors} -\texttt{Cell} is a static class you don't instantiate objects, but rather only refer to it by its class name. - -\subsection{\texttt{Cell} Member Functions and Member Data} - -\begin{smallcode} -static char* CenteringName; -\end{smallcode} -Public data member, having static value "\texttt{Cell}". - -\begin{smallcode} -static void print_Centerings(ostream&) ; -\end{smallcode} -Invoked as \texttt{Cell::printCenterings(ostream\&)} prints the value of the \texttt{string Cell::CenteringName}. - -\section{\texttt{Vert} Class} -The static \texttt{Vert} class represents the abstraction of vertex-centering of something on a mesh. -That "something" is usually a \texttt{Field}. \texttt{Vert} can serve as a value for the \texttt{Centering} template parameter of the \texttt{Field} class. Every \texttt{Field} element, whatever its type, -is centered at the position of the corresponding vertex center in the mesh-using the same index space for \texttt{Mesh} vertex centers as for the \texttt{Field} elements. If the \texttt{Field} elements -(\texttt{T} parameter for \texttt{Field} class) is some kind of multicomponent type such as \texttt{Vektor}, the whole object of that type in every \texttt{Field} element is vertex-centered -(that is, all components have the same centering). The \texttt{CartesianCentering} class allows you to center components of \texttt{Field} elements independently. -If you center a \texttt{Field} on a \texttt{Mesh} using \texttt{Vert}, you must make sure that you construct the Field to have the proper number of elements so that it has one for every vertex in the mesh. -When you use \texttt{Field} constructors taking a mesh object argument (instance of the class specified as the \texttt{Mesh} template parameter for \texttt{Field}), the extents of the \texttt{NDIndex} object or \texttt{Index} -\texttt{Field} constructor arguments match those used to instantiate that \texttt{Mesh}. When you instantiate a \texttt{Field} with \texttt{Vert} centering using constructors without a mesh object argument, -the internally constructed mesh object will automatically have the right number of vertices. - -subsection{Vert Definition (Public Interface)} -\begin{smallcode} -class Vert { -public: - static char* CenteringName; - static void print_Centerings(ostream&); -} ; -\end{smallcode} - - -\subsection{\texttt{Vert} Constructors} -\texttt{Vert} is a static class you don't instantiate objects, but rather only refer to it by its class name. - -\subsection{\texttt{Vert} Member Functions and Member Data} - -\begin{smallcode} -static char* CenteringName; -\end{smallcode} -Public data member, having static value "\texttt{Vert}". - -\begin{smallcode} -static void print_Centerings(ostream&) ; -\end{smallcode} -Invoked as \texttt{Vert::printCenterings(ostream\&)} prints the value of the \texttt{string Vert::CenteringName}. - - -\section{\texttt{CommonCartesianCenterings} Class} -The static CommonCartesianCenterings class is a wrapper class for commonly-used special cases ofthe \texttt{CartesianCentering} class, predefinedby \ippl as a convenience for the user. -Basically, it is a collection of typedef's. \\ -\texttt{CartesianCentering} is a parameterized static class representing the abstraction of componentwise centering of a multicomponent object (typically a \texttt{Field}) -on a cartesian mesh. Via the template parameters, the user specifies the centering of the various components along the various directions. See next section for more details. -\texttt{CommonCartesianCenterings} provides a, shorthand definition for some of the common cases expressible by \texttt{CartesianCentering}. \\ -Also shown in the definition of \texttt{CommonCartesianCenterings} below are the \texttt{CenteringEnum} which it uses and the static wrapper class \\ \texttt{commonCartesianCenteringEnums}. -This last class contains the special-case arrays of \texttt{CenteringEnum} values (\texttt{CELL} or \texttt{VERT}) which represent the various centerings for various specializations of the template parameters. \\ -\texttt{CommonCartesianCenterings} parameterized on dimensionality \texttt{Dim}, which has the same meaning as the dimensionality parameter in \texttt{Field} or \texttt{UniformCartesian} (for example). - -The unsigned value \texttt{NComponents} and the unsigned value \texttt{Direction}. \texttt{NComponents} represents the number of components in a multicomponent object to be centered on the mesh, -for example, if you are centering a \texttt{Field} ,the number of components is three. Direction represents a specifying direction, and is only really used in some of the -\texttt{CommonCartesianCenterings} members. For example, to specify face centering of a scalar field (or single component of a non-scalar field), you must specify which direction is perpendicular -to the faces where you are centering. If you wanted to center a scalar field on the $xy$ faces in 3D, you would use the value \texttt{2U} for \texttt{Direction}; because the $xy$ faces are perpendicular to -the $z$ direction (the directions are numbered sequentially, $x$ is \texttt{0U}, $y$ is \texttt{1U}, and $z$ is \texttt{2U}). - -\subsection{\texttt{CommonCartesianCenterings} Definition (Public Interface)} -\begin{smallcode} - -enum CenteringEnum {CELL=0, VERTEX=1, VERT=1}; - -template -class CommonCartesianCenteringEnums -{ -public: -// CenteringEnum arrays Classes with simple, des'criptive names - -// All components of Field cell-centered in all directions: -static CenteringEnum allCell [NComponents*Dim] ; - -// All components of Field vertex-ceritered in all directions: -static CenteringEnum allVertex[NComponents*Dim] ; - -// All components of Field face-centered in specified -// direction (meaning vertex centered in that direction, cell-centered in others): -static CenteringEnum allFace[NComponents*Dim]; - -// All components of Field edge-centered along specified direction -// (cell centered in that direction, vertex-centered in others): -static CenteringEnum allEdge[NComponents*bim];, - -// Each vector component of Field face-centered in the corresponfing direction -staticCenteringEnum vectorFace[NComponents*Dim]; -} ; - -template -class CommonCartesianCenterings -{ -public: -typedef CartesianCentering::allCell, Dim, NComponents> allCell; -typedef CartesianCentering::allVertex, Dim, NComponents> allVertex; -typedef CartesianCentering::allFace, pim, NComponehts> allFace; -typedef CartesianCentering::allEdge, Dim, NComponents> allEdge; -typedef CartesianCentering::vectorFace, Dim, NComponents> vectorFace; -}; -\end{smallcode} - - -\subsection{\texttt{CommonCartesianCenterings} Constructors} -\texttt{CommonCartesianCenterings} is a static class, you don't instantiate objects, but rather only refer to it by its class name. -Refer to its members his way also for example: \texttt{CartesianCenterings<3U, 1U>} for the member representing centering on a 3D mesh of a scalar -( one-component) object. - -\subsection{\texttt{CommonCartesianCenterings} Member Data} -\begin{smallcode} -typedef CartesianCentering::allCell, Dim, NComponents> allCell ; -\end{smallcode} -Specifies \texttt{CELL} centering of all components along all dimensions. Functionally equivalent to the \texttt{Cell} centering class. - -\begin{smallcode} -typedef CartesianCentering::allVertex, Dim, NComponents> allVertex ; -\end{smallcode} -Specifies \texttt{VERTEX} centering of all components along all dimensions. Functionally equivalent to the \texttt{Vert} centering class. - -\begin{smallcode} -typedef CartesianCentering::allFace, Dim, NComponents> allFace ; -\end{smallcode} -Specifies centering of all components on the faces which are orthogonal to the specified direction (Direction=0 means x, 1 means y, 2 means z). -That is, vertex-centering along direction \texttt{Direction}, and cell-centering along all other directions. - -\begin{smallcode} -typedef CartesianCentering::allEdge, Dim, NComponents> allEdge ; -\end{smallcode} -Specifies centering of all components on the edges which are parallel to the specified direction (Direction=0 means x, 1 means y, 2 means z). That is, cell-centering -along direction Direction, and vertex-centering along all other directions. - -\begin{smallcode} -typedef CartesianCentering::vectorFace, Dim, NComponents> vectorFace ; -\end{smallcode} - -Specifies componentwise face centering of the components of a \texttt{Vector}. Usually you use this for centering a \ippl \texttt{Field} whose elements are \texttt{Vektor}'s. -For example, -\begin{smallcode} -Field, 3,UniformCartesian<3>,CommonCartesianCenterings<3,3,3>> -\end{smallcode} - -\section{\texttt{CartesianCentering} Class} -The static \texttt{CartesianCentering} class represents the abstraction of component-wise centering of a multicomponent object (typically a \texttt{Field}) on a cartesian mesh. Via the template parameters, -the user specifies the centering of the various components along the various directions. - -\subsection{CartesianCenteringDefinition(Public Interface)} -\begin{smallcode} -template -class CartesianCentering -{ -public: -static char* CenteringName; -static void print_Centerings(ostream&) ; -}; -\end{smallcode} - -\subsection{\texttt{CartesianCentering} Constructors} -\texttt{CartesianCentering} is a static class, you don't instantiate objects, but rather only refer to it by its class name, with fully-specified template parameter values. -If you have defined a static array of type \texttt{CenteringEnumcalled myCEArray}, the identifier \texttt{CartesianCenterings} refers to the static class -representing centering on a 3D mesh of a scalar (one-component) object according to the centering specifiers in \texttt{myCEArray}. In this case, \texttt{myCEArray} would -have to have three elements (each having the value \texttt{CELL} or \texttt{VERT}). -In general, the number of elements in the array of \texttt{CenteringEnum} (the CE template parameter value) must equal the value of the \texttt{Dim} parameter multiplied by the value of the \texttt{NComponent} parameter. -The ordering of the elements is so that the component indices vary fastest, and the dimensions indices vary the slowest (like a 2D C array dimensioned as \texttt{[Dim][NComponent]}). -You must declare the \texttt{CenteringEnum} array you use as the value of the CE template parameter as static, and at global scope. - -\subsection{\texttt{CartesianCentering} Member Functions and Member Data} -All the member functions of \texttt{CartesianCentering} are of course static. Refer to them with the syntax \texttt{classname::membername}, where classname is, a name identifying aparticular \texttt{CartesianCentering} -class specialization, as described in this Appendix. - -\begin{smallcode} -static char* CenteringName ; -\end{smallcode} -A string containing a identifying name for a particular template instance of\\ \texttt{CartesianCentering}. Currently, there is only a single name, so that the value of -\texttt{CartesianCentering }is the same for any values of the template parameters. - -\begin{smallcode} -static void print_Centerings(ostream&) ; -\end{smallcode} -Prints a formatted version of the \texttt{CartesianCentering} class. Specifically, it prints the values of the elements of the \texttt{CE} template parameter (as an array with \texttt{Dim*NComponents} elements). - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/manual/ippl_fft.tex b/manual/ippl_fft.tex deleted file mode 100644 index 2a4c326ae..000000000 --- a/manual/ippl_fft.tex +++ /dev/null @@ -1,58 +0,0 @@ -\chapter{FFT} -\label{sec:fft} - -The FFT class provides an interface for performing parallel Fourier transforms of various types on \ippl \texttt{\texttt{Field}} objects. FFT is templated on the type of transform to perform (\texttt{CCTransform}, \texttt{RCTransform}, or \texttt{SineTransform}); the dimensionality \texttt{\texttt{Dim}} of the fields to be transformed, and the floating-point precision type (either \texttt{float} or \texttt{double}). It is capable of transforming along all dimensions of a \texttt{\texttt{Field}} or only specified dimensions, and it handles all of the data transposes required to make the Fourier transforms efficient automatically. The FFT constructor arguments vary slightly depending upon which type of transform you wish to perform. Generally speaking, you provide an {\tt NDIndex} object or objects which contain the domains of the input and/or output \texttt{Field}s for the Fourier transform, an optional array of bools of length \texttt{Dim} indicating which dimensions are to be transformed (default is all dimensions), and an optional bool indicating whether or not to compress the intermediate \texttt{Field}s needed to perform data transposes when they are not in use. The default value of this optional argument is false, but the user can set this argument to true if it is necessary to conserve memory. For a complex--to--complex Fourier transform, the input and output fields are of the same element type and are the same size, so only one domain argument is needed. So in the simple case of transforming all dimensions of a \texttt{Field} of type {\tt complex}, we would construct the FFT object with the code -\begin{smallcode} -FFT ccfft(domain); -\end{smallcode} -where domain is an {\tt NDIndex} describing the domain of complex \texttt{Field}s to be transformed with the FFT object. -A real--to--complex Fourier transform takes a field of real numbers and returns a field of complex numbers (or vice-versa for an inverse complex--to--real transform), so we require separate domain arguments describing each \texttt{Field} in the FFT constructor. From the theory of Fourier mode analysis, we know that a Fourier transform of $N$ real numbers will produce $N/2+ 1$ unique complex modes, with modes $0$ and $N/2$ being purely real. Some FFT routines take advantage of the fact that if you pack together the real parts of modes $0$ and $N/2$ as one complex number, you can store all the resulting mode information in the same space as required for the input (i.e., $N$ real numbers or $N/2$ complex numbers). Such a technique tends to cause confusion in multidimensional real--to--complex FFTs, since mode data must then be separated out afterwards. So we choose a format in which the $N/2+ 1$ complex modes are stored separately as complex numbers. Thus, when a real--to--complex transform is performed on a {\tt \texttt{Field}} of doubles, the resulting {\tt \texttt{Field}} of type {\tt complex} will have an extent one greater than half the length of the input field along the first dimension to be transformed and the same length along all other dimensions. This conformance of domains is checked by the FFT constructor. We might construct an FFT object for real--to--complex transforms with the line -\begin{smallcode} -FFT rcfft(rdomain,cdomain,tdim); -\end{smallcode} -where {\tt rdomain} and {\tt cdomain} are the conforming domains for the {\tt real} and {\tt complex} fields and {\tt tdim} is an array of bools indicating whether or not to transform each dimension. Note that we assume the axes of the field are to be transformed along in the order indicated by the domain arguments for a forward FFT and in the reverse order for an inverse FFT. Each \texttt{Index} object inside the provided domain should refer to a particular axis of the input \texttt{Field}, and these axes are transformed along in order. A sine transform is a special type of Fourier transform in which only the sine (odd) modes are retained. This transform has a field of real numbers for both its input and output, and its effect is to keep only that portion of the data which exhibits odd parity (i.e., vanishes at the endpoints of the interval). Typically, one wishes to enforce odd parity along one or more dimensions of a field, and then perform a standard real-to-complex transform along remaining dimensions. Hence, we require that the user provide two arrays of bools in the constructor: the first to indicate along which dimensions to perform a sine transform, and the second to indicate all of the transform dimensions (both sine transforms and standard FFTs). For example, -\begin{smallcode} -FFT sinefft(rdomain,cdomain,sinedim,tdim); -\end{smallcode} - - -constructs an FFT object for doing sine transforms along the dimensions indicated by sinedim and a standard real-to-complex FFT over the other dimensions included in tdim. Alternatively, such transforms could be achieved in two steps, doing the sine transforms and the standard FFTs separately. In this case, we might construct our sine transform FFT object with the code -\begin{smallcode} -FFT sinefft2(rdomain,sinedim); -\end{smallcode} - - -and then construct a second FFT object for handling the real-to-complex transform. Note that a sine transform FFT object which is doing only sine transforms requires only a single domain argument describing the real input and output \texttt{Field}s in its constructor. - -Once the appropriate FFT object has been constructed, a Fourier transform of data is invoked using the transform member function. The normal arguments to this function are an integer value of + 1 or -1 to indicate the sign of the exponential used in the transform (i.e., the direction of the transform, forward or inverse), and the input and output \texttt{Field}s. For this "two-field" form of the transform function, there is also an optional argument of type bool, which indicates whether or not the input \texttt{Field} is considered to be constant by the transform function. The default value of this optional argument is false, which allows the transform routine to attempt to use the input \texttt{Field} as temporary storage and avoid doing an additional data transpose. You should set the value of this argument to true if you must preserve the contents of the input \texttt{Field} for later use. We would use our previously constructed FFT object for real--to--complex transforms to perform a forward FFT in the following manner: -\begin{smallcode} -rcfft.transform(+l,realField,complexField); -\end{smallcode} - - -The results of the transform are automatically normalized such that a forward transform followed by an inverse transform returns the original data. For convenience, the FFT class has a member function \texttt{setDirectionName} which allows you to associate a character string with each of the transform directions + 1 and -1. You might choose to refer to these directions as "xtok" and "ktox", for example. - -In the case of a complex-to-complex FFT or a pure sine transform; the input and output fields are the same size and of the same type. In these instances, we offer the option of performing the transform "in place"; that is, using just one \texttt{Field} argument for both the input and output. For example, we could perform an inverse complex-to-complex FFT with the code -\begin{smallcode} -ccfft.transform(-1,complexField2); -\end{smallcode} - - - -\subsection{Improving FFT Performance} -Some improvement in performance of the transform method may be obtained by careful selection of the axis ordering of input and output \texttt{Field}s. In order to perform a parallel FFT along a particular dimension, the FFT object will first reorder the axes so that the first axis is the one to be transformed. It does this by assigning the field data into a new \texttt{Field} with a domain in which the order of the original \texttt{Index} objects has been permuted. This new \texttt{Field}, -which is maintained internally by the FFT class, has a data layout that is serial along this first dimension and parallel along all other dimensions. With this layout, each processor can independently perform FFTs along the serial axis for each of the one-dimensional strips of data it owns. To subsequently transform along another dimension, the FFT object must again transpose the data so that the next dimension to be transformed is now the first dimension and is serial. These data -transposes can be fairly costly to perform. We can eliminate at least one data transpose if the output \texttt{Field} supplied by the user has the same layout characteristics needed for the final transform (or, in the case of an "in place" transform, if the input \texttt{Field} matches the layout needed for either the first or last transform), and has no guard cell layers. For instance, let us assume we have a three-dimensional \texttt{Field} of complex numbers and we want to transform -all dimensions. If the \texttt{Index} objects {\tt I,J}, and {\tt K} describe the first, second, and third axes of our \texttt{Field} domain, we could perform a forward FFT with the line -\begin{smallcode} -ccfft.transform(+l,complexFieldl); -\end{smallcode} - -If the first dimension of \texttt{complexField} is serial, the transform method will skip the first data transpose because the input data is already distributed appropriately for transforming along the first dimension. Similarly, if we were to call an inverse transform with this same \texttt{Field}, it would transform the axes in reverse order, and we would be able to skip the final data transpose. Alternatively, we might choose to do this FFT using separate input and output \texttt{Field}s: -\begin{smallcode} -ccfft.transform(+1,complexField1,complexField2); -\end{smallcode} -In this case, the final optional argument to the "two-field" trans form function defaults to false, meaning that \texttt{complexFieldl} is not considered constant and may be used in place of a temporary \texttt{Field} to avoid the first data transpose. In addition, the output \texttt{Field} can be used in place of the final temporary \texttt{Field} if it has the proper layout. If \texttt{complexField2} has its axes reordered so that its first axis is the final axis to be transformed -(e.g., \texttt{K}, then \texttt{I}, then \texttt{J}) and that first axis is serial, then we can skip the final data transpose. This choice of data layout results in a slightly faster parallel FFT, and it is often convenient if all you need to do is transform the data, do a brief computation with the transformed data, and then invert the transform. - -Another issue of relevance to the performance of the transform method is the type of routine used to perform the actual one-dimensional FFT. Currently, we provide two options for this. The first is Fortran 77 implementations of FFT routines from the Netlib repository. These are portable and highly optimized routines that we invoke via C++ wrapper functions. The second option (available only on SGI and Cray systems) is native FFT routines from the SGI/Cray Scientific Library. These routines can be substituted for the portable Netlib routines by supplying the option {\tt USE\_SCSL\_FFT} to the configure utility before compiling the \ippl library. These native library routines tend to be somewhat faster than the portable Fortran routines, and we plan to offer the ability to use native FFT routines such as FFTW in the future. diff --git a/manual/ippl_field_ref.tex b/manual/ippl_field_ref.tex deleted file mode 100644 index 0b8996677..000000000 --- a/manual/ippl_field_ref.tex +++ /dev/null @@ -1,239 +0,0 @@ -\chapter{Fields} -\label{sec:fields} -The Field class represents the common computational science abstraction of a continuum (mathematical) field discretized on a mesh, -with some centering on that mesh. Used in it simplest, default, way with basic-type elements such as double's or float's. Field serves as a -multidimensional array class. Similarly, you can use collections of simple or not-so-simple instances of the Field class to represent almost any -data structure found in computational science; but this is against the philosophy of object-oriented design, in which you should design classes -to represent the physics/numerical-mathematics abstractions of the problem domain, rather than the data structures typically found in computer codes. -\section{Field Class Definition} -The Field class is parameterized on the type \texttt{T} of elements (typically a type like \texttt{double,Vektor}, or \texttt{Tenzor}), dimensionality, mesh type, and centering on the mesh: -\begin{smallcode} -template -class Field : public FieldBase -\end{smallcode} -\pagebreak -\section{Field Constructors} -To instantiate a \texttt{Field} we use the following of Field constructors: -\begin{smallcode} -Field(FieldLayout&); -Field (FieldLayout&, const GuardCellSizes&); -Field (FieldLayout&, const BConds&); -Field (FieldLayout&, const GuardCellSizes&, - const BConds&); -Field (FieldLayout&, const BConds&, - const GuardCellSizes&); -\end{smallcode} -\section{Field Member Functions and Member Data} - -\begin{smallcode} -IndexingField operator[] (const Index& idx) -IndexingField operator[] (int i) -const iterator& begin() const { return Begin; } -const iterator& end() const { return End; } -void fillGuardCells() ; -const GuardCellSizes& getGuardCellSizes() { return Allocated; - -// Boundary condition handling. -unsigned leftGuard(unsigned d) { return Allocated.left(d); } -unsigned rightGuard(unsigned d) { return Allocated.right(d); } -const Index&: getIndex(unsigned d) { return Layout~>get_Domain() [d]; -const NDIndex& getDomain() {returnLayout->get_Domain();} - -// Definitions for accessing boundary conditions. -typedef BCondBase bcond_value; -typedef BConds bcond_container; -typedef bcond_container::iterator bcond_iterator; -bcond_value& getBCond(int bC); -bcond_container& getBConds(){return *BC;} -\end{smallcode} - -\section{Operations on Field Objects} -\subsection{Assignment} -For the special case where there is only one term on the right-hand side of an assignment, the assignment operator can be utilized. -Examples of single term assignments include: -\begin{smallcode} -unsigned Dim = 2,int N = 100; -Index I (N), J (N) ; -FieldLayout layout(I,J)i Field A(layout) , B(layout); -A = 2.0; -B = A; -\end{smallcode} -For cases where more than one term exists on the right hand side of an assignment, the \texttt{assign()} call must be made. Any combination of scalars, \texttt{Field}'s, \texttt{IndexingField}'s, and\texttt{ Index}'s -can be put as the second argument of the \texttt{assign()} call. The only requirement in combining terms is that the appearance of an\texttt{ Index} object anywhere inside of an expression requires, -that all the \texttt{Field} contained in the expression must be indexed. It is not possible to combine \texttt{Field}'s and \texttt{IndexingField}'s in a single expression. -Nor is it possible to combine \texttt{Field}'s and \texttt{Index} objects in a single expression. The following examples define legal expressions: -\begin{smallcode} -unsigned Dim = 2; -int N = 100; -Index I(N), J(N); -FieldLayout layout(I,J); -Field A(layout) , B(layout) , C.(layout); - -assign(A, 2.0 + B); -assign(B , A + 2.0); -assign(B[I][J],3.0+B[I][J]); -assign(A[I][J] , I + A[I][J]/C[I][J]); -\end{smallcode} - -The following are examples of illegal expression: -\begin{smallcode} -B[I][J] = 3.0 + B[I][J]; // must use assign() with indexed Field~s, -assign(A, 2.0 + B[I][J]); // can't combine indexed Band non~indexed B -assign(B[I][J] , A + 2.0); // can't combine indexed B and non-indexed A -assign(A[I][J] , I + A/C[I][J]); // can't combine indexed C ,and non-indexed A -\end{smallcode} - -\subsection{Boundary Conditions} -\ippl pre-defines classes to represent 7 different forms of boundary conditions: -\begin{enumerate} -\item Periodic boundary condition: \texttt{PeriodicFace} -\item Positive reflecting boundary condition: \texttt{PosReflectFace} -\item Negative reflecting boundary condition: \texttt{NegReflectFace} -\item Constant boundary condItion: \texttt{ConstantFace} -\item Zero boundary condition (special case of constant): \texttt{ZeroFace} -\item Linear extrapalation baundary condition: \texttt{ExtrapolateFace} -\item none (should not be used) -\end{enumerate} -Let's examine each boundary condition as applied to. the same shift operation. In each case, the first \texttt{assign()} invocation shows how the \texttt{Field A} with the following values: -\begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 0 & 1 & 2 & 3 \\ \hline - 1 & 2 & 3 & 4 \\ \hline - 2 & 3 & 4 & 5 \\ \hline - 3 & 4 & 5 & 6 \\ \hline - \end{tabular} - \label{tbl:t1} - \end{center} -The results after the second \texttt{assign()} invocation show how the boundary conditions on \texttt{A} affect the calculation. -For the first example, consider the case where each boundary of the \texttt{Field} object \texttt{A} has periodic boundary conditions: - -\begin{smallcode} -unsigned Dim = 2; -Index 1(4), J(4); -BConds bc; - -bc[0] = new PeriodicFace(0); -bc[1] = new PeriodicFace(1); -bc[2] = new PeriodicFace(2); -be[3] = new PeriodicFace(3); - -FieldLayout layout(I,J); -Field A( layout, GuardCellSizes (1) , bc) ; -Field B(layout); -assign(A[I][J] ,I + J); -assign(B[I][J] ,A[I+l][J+l]) -\end{smallcode} -This code segment produces the following values in the \texttt{Field B}: -\begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 2 & 3 & 4 & 1 \\ \hline - 3 & 4 & 5 & 2 \\ \hline - 4 & 5 & 6 & 3 \\ \hline - 1 & 6 & 3 & 0 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} -In the case af the periodic boundary conditions, we see that the values wrap around the domain of the \texttt{Field} and pull values from the opposite side of the \texttt{Field} when the -indexing operations reference positions outside the domain. Note that the specification of a boundary condition above overrides the default behavior, which places zeroes into -positions that attempt to obtain data from outside the domain. - -Next we consider the case where positive reflecting boundary conditions are applied to each -boundary of the \texttt{Field} object \texttt{A} in the same shift operation: -\begin{smallcode} -bc[0] = new PosReflectFace (0); -bc[1] = new PosReflectFace (1); -bc[2] = new PosReflectFace (2); -be[3] = new PosReflectFace (3); - -assign(A[I][J] ,I+ J); -assign(B[I][J] ,A[I+1][J+1); -\end{smallcode} -This code segment produces the following values in \texttt{Field B}: -\begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 2 & 3 & 4 & 4 \\ \hline - 3 & 4 & 5 & 5 \\ \hline - 4 & 5 & 6 & 6 \\ \hline - 4 & 5 & 6 & 6 \\ \hline - \end{tabular} - \label{tbl:t3} -\end{center} -In the case of the positive reflecting boundary conditions, we see that the values are simply reflected across the boundary over which the \texttt{Field} indexing operation occur. -This boundary condition is meant to represent Neuman boundary conditions in physical systems. - -Next, consider the case where each boundary of the \texttt{Field} object \texttt{A} has negative reflecting boundary conditions: -\begin{smallcode} -bc[0] = new NegReflectFace (0); -bc[1] = new NegReflectFace (1); -bc[2] = new NegReflectFace (2); -be[3] = new NegReflectFace (3); - -assign(A[I][J] ,I+ J); -assign(B[I][J] ,A[I+1][J+1]); -\end{smallcode} -This code segment produces the following values in \texttt{Field B}: -\begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 2 & 3 & 4 & -4 \\ \hline - 3 & 4 & 5 & -5 \\ \hline - 4 & 5 & 6 & -6 \\ \hline - -4 & -5 & -6 & -6 \\ \hline - \end{tabular} - \label{tbl:t4} -\end{center} -In the case of the negative reflecting boundary conditions, we see that the values are simply reflected across the boundary over which the \texttt{Field} indexing operation occur and negated. -This boundary condition is meant to represent Dirichlet boundary conditions in physical systems. - - -Next, consider the case where each boundary of the \texttt{Field} object \texttt{A} has constant boundary conditions: -\begin{smallcode} -bc[0] = new ConstantFace (0,9.0); -bc[1] = new ConstantFace (1,9.0); -bc[2] = new ConstantFace (2,9.0); -be[3] = new ConstantFace (3,9.0); - -assign(A[I][J] ,I+ J); -assign(B[I][J] ,A[I+1][J+1]); -\end{smallcode} -Note additional argument to the \texttt{constantFace} constructor. This argument represents the value which is to be fixed on the boundary in that direction. -The code segment above produces the following values in \texttt{Field B}: -\begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 2 & 3 & 4 & 9 \\ \hline - 3 & 4 & 5 & 9 \\ \hline - 4 & 5 & 6 & 9 \\ \hline - 9 & 9 & 9 & 9 \\ \hline - \end{tabular} - \label{tbl:t5} -\end{center} -In the case of the constant boundary conditions, we see that a fixed value is shifted into the domain across the boundary over which the \texttt{Field} indexing operation occur. - -Finally, consider the case where the \texttt{Field} object \texttt{A} has mixed boundary conditions, boundary-by-boundary (i.e., face-by-face): -\begin{smallcode} -be[0] = new PeriodicFace (0); -be[1] = new PeriodicFace (1); -be[2] = new PosReflectFace (2); -be[3] = new NegReflectFace (3); -assign(A[I][J] ,I+ J); -assign(B[I][J] ,A[I+1][J+1]); -\end{smallcode} -The code segment above produces the following values in \texttt{Field B}: -\begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 2 & 3 & 4 & 1 \\ \hline - 3 & 4 & 5 & 2 \\ \hline - 4 & 5 & 6 & 3 \\ \hline - -4 & -5 & -6 & -3 \\ \hline - \end{tabular} - \label{tbl:t6} -\end{center} - - diff --git a/manual/ippl_fieldlayout_ref.tex b/manual/ippl_fieldlayout_ref.tex deleted file mode 100644 index 1f5dbbfae..000000000 --- a/manual/ippl_fieldlayout_ref.tex +++ /dev/null @@ -1,305 +0,0 @@ -\chapter{FieldLayout Class} -\label{sec:flcl} -The \texttt{FieldLayout} class represents the abstraction of a decomposition of a Field object into pieces (subsets of elements). The number of pieces need not be, but typically is, greater than or equal to the number of physical processors or cores used to run the \ippl program in parallel. This is a decomposition in the sense that the parallel computing literature talks about domain decomposition. The Field object represents a mathematical -field discretized on a spatial domain, each piece of it is a subdomain. Equivalent to the actual spatial subdomain is the subset of the index space of the discretization. Currently in \ippl, these subsets are contiguous, stride-1 subranges of the global (N -dimensional) index space. Other \ippl mechanisms assign each sub domain to a processor or core. The \texttt{FieldLayout} class provides mechanisms for specifying decomposition, and has two relationships with the \texttt{Field} class: \texttt{Field} uses a \texttt{FieldLayout} reference and invokes its mechanisms to manage the distribution of its data, and \texttt{FieldLayout} maintains a container of pointers to all the -\texttt{Field}'s it is used by. When the user requests that a \texttt{FieldLayout} be redistributed, the \texttt{FieldLayout} goes through its list of Field pointers and tells the -\texttt{Field}' s to effect the redistribution of their data. -\section{FieldLayout Definition (Public Interface)} - -\begin{smallcode} -// enumeration used to select serial or parallel axes -enum e_dim_tag { SERIAL=O, PARALLEL=l } - -// A base class for FieldLayout that is independent of dimension. - -class FieldLayoutBase -{ -private: -// Some dummy storage so that it doesn't confuse purify. -char Dummy; - -public: - -FieldLayoutBase() : Dummy(0) {} -}; - -template -class FieldLayout public FieldLayoutBase { -public: - -// Typedefs'for containers. - -typedef vmap > >ac_id_vodes; -typedef DomainMap,RefCountedP< Vnode >, - Touches,Contains, - Split > ac_domain_vnodes; -typedef vmap,my_auto_ptr > - ac_gc_domain_vnodes; - -typedef vmap ac_id_fields; - -// Typedefs for iterators. - -typedef ac_id_vodes::iterator iterator_iv; -typedef ac_id_vodes: :const_iterator const_iterator_iv; -typedef ac_domain_vnodes::iterator iterator_dv; -typedef ac_domain_vnodes::touch_iterator touch_iterator_dv; -typedef pair touch_range_dv; -typedef ac_id_fields::iterator iterator_if; -typedef ac_id_fields::const_iterator const_iterator_if; -typedef ac_gc_domain_vnodes: :iterator iterator_gdv; -public: - -// Accessors for the locals by Id. -ac_id_vnodes: : size_type size_iv(); -iterator_iv begin_iv(); -iterator_ivend_iv(); -const_iterator_iv begin_iv() const; -const_iterator_iv end_iv() const; - -// Accessors for the remote vnode containers. -ac_gc_domain_vnodes::size_type size_rgdv(); -iterator_gdv begin_rgdv(); -iterator_gdvend_rgdv(); - -// Accessors for the remote vnodes themselves. -ac_domain_vnodes::size_type size_rdv( const GuardCellSizes& gc = gc0()) ; - -iterator_dv begin_rdv(const GuardCellSizes& gc = gcO()); -iterator_dv end_rdv(const GuardCellSizes& gc= gcO()); -touch_range_dv touch_range_rdv(const NDIndex& domain, - const GuardCellSizes& gc = gcO()); - -// Accessors for the fields declared on this -// FieldLayout. ac_id_fields:.: size_type size_if () ; -iterator_if begin_if () ; -iterator_ifend_if(); -const_iterator_if begin_if() const; -const_iterator_if end_if() const; - -// Tell the FieldLayout that a FieldBase has been declared on it -void checkin(FieldBase&f, const GuardCellSizes& gc= gcO()); -// Tell the FieldLayout that a FieldBase is no longer using it. - -void checkout(FieldBase& f); - -// Compare FieldLayouts to see if they represent the same domain. - -bool operator==(const FieldLayout& x) -{ -return Domain == x.Domain; -} -// Constructors. -// Default constructor, which should only be used if you are going to -// call 'initialize' soon after (before using in any context) - -FieldLayout() { } - -//Constructorsfor 1 ... 6 dimensions - -FieldLayout(const Index& il, e_dim_tag pl=PARALLEL, int vnodes=-1); - -FieldLayout(const Index&il, const Index& i2, e_dim_tag pl=PARALLEL, - e_dim_tag p2=PARALLEL, int vnodes=-1); - -FieldLayout(const Index& il, const Index& i2, const Index& i3, -e_dim_tag pl=PARALLEL, e_dim_tag p2=PARALLEL, e_dim_tag p3=PARALLEL, int vnodes=-1); - -FieldLayout(const Index& il, const Index& i2, const Index& i3, -const Index& i4, e_dim_tag pi = PARALLEL , e_dim_tag p2 = PARALLEL , e_dim_tag p3=PARALLEL, -e_dim_tag p4=PARALLEL, int vnodes=-1) ; - -FieldLayout(const Index& il, const Index& i2, const Index& i3, -const Index& i4, const Index& i5, e_dim_tag pl=PARALLEL, e_dim_tag p2=PARALLEL, -e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL, e_dim_tag p5=PARALLEL, int vnodes=-1) ; - -FieldLayout(const Index& il, const Index& i2, const Index& i3, -const Index&i4, const Index& is, const Index& i6, e_dim_tag pl=PARALLEL, e_dim_tag. p2=PARALLEL, -e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL, e_dim_tag pS = PARALLEL , -e_dim_tag p6=PARALLEL, int vnodes=-1); - -// Next we have one for arbitrary dimension. -FieldLayout(const NDIndex& domain, e_dim_tag *p==O, int vnodes"=-1) -{ initialize (domain,p,vnodes) ; - -//Build a FieldLayout given the whole domain and -//begin and end iterators for the set of domains for the local Vnodes. -//It does a collective computation to find the remote Vnodes. - -FieldLayout(const NDIndex& Domain, NDIndex* begin, NDIndex* end); - -// initialization functions, for use when the FieldLayout was created using the default constructor. -void initialize(const Index& il, e_dim_tag pl=PARALLEL,int vnodes=-1); - -void initialize(const Index& il, const Index& i2, e_dim_tag pl=PARALLEL, - e_dim_tag p2=PARALLEL, int vnodes=-l); - -void initialize{const Index& il, const Index& i2. const Index& i3, e_dim_tag pl=PARALLEL, - e_dim_tag p2=PARALLEL, e_dim_tag p3=PARALLEL, int vnodes=-1); - -void initialize(const Index& il, const Index&i2, const Index& i3, const.Index& i4, - e_dim_tag pl=PARALLEL, e_dim_tag p2=PARALLEL, - e_dim~tag p3=PARALLEL, e_dim_tag p4=PARALLEL, int vnodes=-1); - -void initialize(const Index& il,.const Index&, i2, Cbnst Index& i3, const Index& i4, -const Index& is, e_dim_tag pl=PARALLEL, -e_dim_tag p2=PARALLEL, e_dim_tag p3=PARALLELi e_dim_tag p4=PARALLEL, -e_dim_tag pS = PARALLEL , int vnodes=-1); - -void initialize(const Index& il, constIndex& i2, const Index& i3, const Inde.x& i4, const Index& is, -const Index& i6, e_dim_tag pl=PARALLEL,e_dim_tag p2=PARALLEL, e_dim tagp3=PARALLEL, -e_dim_tag p4=PARALLEL, e_dim_tag p5=PARALLEL, e_dim_tagp6=PARALLEL, int vnodes=-1); - -void initialize(const NDIndex& domain, e_dim_tag *p=O" int vnodes=-1); - -// Let the user set the local vnodes. -// this does everything necessary to realign all the fields associated with this FieldLayout! -// It inputs begin and end iterators for the local vnodes. - -void Repartition(NDIndex*,NDIndex*); - -void Repartition(NDIndex& domain) -{ -Repartition(&domain, (&domain) +1); -} - -// Destructor: Everything deletes itself automatically, -// except we must tell all the registered FieldBase's we're going away. -~FieldLayout(); - -// Return the domain. -constNDIndex& getDomain() const { return Domain; } - -// Print it out. -void write (ostream&) const; -friend ostream& operator<<(ostream&, const FieldLayout&); -}; - -\end{smallcode} - -\section{FieldLayout Constructors} - -\texttt{FieldLayout} is parameterized on (\texttt{unsigned}) dimensionality, having the same meaning as the dimensionality template parameter for the \texttt{Field} class. - When constructing a \texttt{FieldLayout} object, you must specify the index range for each dimension (or axis). To do this, you can - use a single \texttt{NDIndex} object: - -\begin{smallcode} -index I(S), J(9), K(4); -NDIndex<3> Domain(l, J, K); -FieldLayout<3> Layout(Domain); -\end{smallcode} -For \texttt{FieldLayout}'s of $N$ dimensions up to six, you may instead specify $N$ Index objects to the constructor of \texttt{FieldLayout} directly, without creating an \texttt{NDIndex} object: -\begin{smallcode} -Index l(5), J(9), K(4); -FieldLayout<3> Layout (I, J, K); -\end{smallcode} - -\subsection{Specifying Serial or Parallel Layout} -'By default, \texttt{FieldLayout} will attempt to distribute the data among the processors (vnodes, actually) by subdividing each dimension in turn until it has the proper number of subregions. -Those axes which are considered for subdivision are the parallel axes, which means that a given node will only contain \texttt{Field} data for a subset of the indices along that dimension. -You can, however, tell \texttt{FieldLayout} which axes to subdivide, and which to maintain as serial. Serial axes are not ever partitioned by \texttt{FieldLayout}. -You must have at least one parallel dimension in a given \texttt{FieldLayout}; by default, all axes are parallel. -To specify things, use the predefined enumeration \texttt{e\_dim\_tag}, which has values \texttt{SERIAL} and \texttt{PARALLEL}. When you pass a \texttt{NDIndex} as the\\ \texttt{FieldLayout} -constructor argument, you pass an array of \texttt{e\_dim\_tag} values, having length Dim. When you construct a \texttt{FieldLayout} with $N$ \texttt{Index} arguments, you may also include -up to $N$ more arguments of type \texttt{$e\_dim\_tag$} to set the corresponding dimensions layout methods; any omitted dimensions at the end of the list default to \texttt{PARALLEL}. -Refer to the first few chapters of this report for appropriate examples. - -\section{FieldLayout Member Functions and Member Data} -\subsection{Access Functions to Containers in \texttt{FieldLayout}} -The \texttt{Index} class has several private members whose types are parameterized container classes patterned after STL containers. These have STL-like semantics, including iterators. -The container objects themselves are private, but the user has public access to their sizes and iterators over them via \texttt{Index} public member functions. -\texttt{Index} provides some typedef's to make this access easier: - -\begin{smallcode} -typedef vmap > > ac_id_vnodes; -\end{smallcode} -Type for \texttt{FieldLayout}'s container of pointers to \texttt{Vnode} objects; the \ippl internal \texttt{Vnode} class represents the vnode, or index-space subdomain in this context. -The number of subdomains is equal to the number of vnodes, and\\ \texttt{FieldLayout}' s serial/parallel specification determines the extents of the subdomains in \texttt{Index} space. - - - -\begin{smallcode} -typedef DomainMap,RefCountedP< Vnode >, -Touches,Contains,Split > ac_domain_vnodes; -typedef vrnap, my_auto_ptr > ac_gc_domain_vnodes; -\end{smallcode} -The first of these typedef's is only used inside the second. -\begin{smallcode} -typedef vmap ac_id_fields; -\end{smallcode} -Type for \texttt{FieldLayout}'s container of pointers to \texttt{Field}'s using this \texttt{FieldLayout} object, mentioned in the general discussion anhe beginning of this chapter. - -\begin{smallcode} -typedef ac_id_vnodes: :iterator iterator_iv; -typedef ac_id_vnodes: :const_iteratorconst_iterator_iv; -typedef ac_domain_vnodes::iterator iterator_dv; -typedef ac_domain_vnodes::touch_iterator touch_iterator_dv; -typedef pair touch_range_dv; -typedef ac_id_fields::iterator iterator_if; -typedef ac_iQ._fields::const_iterator const_iterator_if; -typedef ac_gc_domain_vnodes::iterator iterator_gdv; -\end{smallcode} - -More to come ..... - - - -\chapter{\texttt{CenteredFieldLayout} Class} -\label{sec:flcent} -The \texttt{CenteredFieldLayout} class inherits from \texttt{FieldLayout}. It represents the same abstraction as \texttt{FieldLayout}, except specialized to a particular type of -centering on a particular type of \texttt{Mesh}; it is parameterized on mesh type and centering type. -These template parameters have the same meaning as the corresponding parameters for the \texttt{Field} class. \\ -The primary use of \texttt{CenteredFieldLayout} is for guaranteeing correct specification of numbers of elements in -\texttt{Field}'s along the various dimensions according to the centering along those dimensions. The \texttt{Mesh} object reference constructor arguments provide for this. -\section{\texttt{CenteredFieldLayout} Definition (Public Interface)} -\begin{smallcode} -template -class CenteredFieldLayout : public FieldLayout { -public: -//-------------~--------~----------------------~----~----------------------- -// Constructors from a mesh object only and parallel/serial specifiers. -//--------------------~---------------------~------------------------------- -// Constructor for arbitrary dimension with parallel/serial specifier array: -//This one also works if nothing except mesh is specified: - -CenteredFieldLayout(Mesh& mesh, e_dim_tag *p=0, int vnoqes=-1); - -// Constructors for 1 ... 6 dimenslons with parallel/serial specifiers: - -CenteredFieldLayout(Mesh& mesh, e_dim_tag pI, int vnodes=-1); -CenteredFieldLayout(Mesh& mesh, e_dim_tagpI, e_dim_tag p2, int vnodes=-1); -CenteredFieldLayout(Mesh& mesh, e_dim_tag pI, e_dim_tag p2, e_dim_tag p3, int vnodes=-1); -CenteredFieldLayout(Mesh&mesh, e_dim_tag pI, e_dim_tag p2, e_dim_tag p3, -e_dim_tag p4, int vnodes=-1); -CenteredFieldLayout(Mesh&mesh, e_dim_tag pI, e_dim_tag p2, e_dim_tag p3, -e_dim_tag p4, e_dim_tag p5, int vnodes=-1); -CenteredFieldLayout(Mesh& mesh,e_dim_tag pI, e_dim_tag p2, e_dim_tag p3, -e_dim_tag p4, e_dim_tag p5, e_dim_tag p6, int vnodes=-1); -}; -\end{smallcode} -\section{\texttt{CenteredFieldLayout} Constructors} - -Here is where \texttt{CenteredFieldLayout} differs from \texttt{FieldLayout}. Instead of taking \texttt{NDIndex\&} or \texttt{Index\&} arguments to specify the numbers of elements along the -various dimensions, the constructors take an argument having the type ofthe \texttt{Mesh} template parameter. This might be, for example, a \texttt{UniformCartesian} object reference. -\texttt{CenteredFieldLayout} queries the mesh object for numbers of grid nodes arid sets up the right number of elements for subsequent \texttt{Field} objects instantiated to use this \texttt{CenteredFieldLayout}. -There are implementations for \texttt{Cell}, \texttt{Vert}, and \texttt{Cartesian} centerings on \texttt{UniformCartesian} and \texttt{Cartesian} meshes. -If you are not providing a \texttt{Mesh} object to construct a \texttt{CenteredFieldLayout}, you probably should be just using simple \texttt{FieldLayout} objects instead, though no harm would be done by constructing a \texttt{CenteredFieldLayout} with \texttt{Index/NDIndex} arguments via the inherited constructors from \texttt{FieldLayout}. Refer to Appendix \ref{sec:flcl} for more details about \texttt{FieldLayout}. Other than these different constructors, \texttt{CenteredFieldLayout} is the same as \texttt{FieldLayout}. - - - - - - - - - - - - - - - - - - - diff --git a/manual/ippl_fields.tex b/manual/ippl_fields.tex deleted file mode 100644 index 608f6c591..000000000 --- a/manual/ippl_fields.tex +++ /dev/null @@ -1,646 +0,0 @@ -\chapter{Using the \texttt{Field} and Related Classes} - -This section introduces the interface of the \texttt{Field} class and related classes. We describe how -to instantiate \texttt{Field} objects, use \texttt{Index} objects to perform index operations, perform expression -operations with overloaded operators, apply boundary conditions, use the where construct for -conditionals, invoke reduction operations, and use mathematical functions. - -\section{\texttt{Field} Object Instantiation} - -\subsection{\texttt{Field} Template Parameters} \label{sec:tmpl_params} - -The \texttt{Field} class is parametrized on 4 template parameters: type \texttt{T}, dimensionality \texttt{Dim}, -mesh type \texttt{Mesh}, and centering \texttt{Centering}. -\begin{smallcode} -Field, - class Centering=Mesh::DefaultCentering> -\end{smallcode} -The \texttt{T} parameter represents the type of data that can be stored inside of a \texttt{Field}. Currently, -the \texttt{Field} class supports the intrinsic types \texttt{bool, int, float, double}. One may use any -user-defined type or class as the template parameter; however, one must also add traits to the -framework to implement the desired data-parallel promotion properties so that \texttt{Field} operations -work. The framework includes -\begin{smallcode} -Vektor, Tenzor, SymTenzor -\end{smallcode} -classes\footnote{The strange spellings avoid conflicts with other classes such as the STL vector class.} -, which are (mathematical) vectors, tensors, and symmetric tensors whose -elements are of type \texttt{T}. Traits are implemented in these classes so that they may serve as elements -of fully-functional \texttt{Field} objects. -The \texttt{Dim} parameter represent the dimensionality of the \texttt{Field} that is being constructed. This -must correspond to the \texttt{Dim} parameters in all other objects used to construct the \texttt{Field}. -The \texttt{Mesh} parameter represents the mesh on which the field is discretized. \ippl -pre-defines two appropriate classes (\texttt{Cartesian} and \texttt{UniformCartesian}) to use for this -parameter, one of which serves as the default value of the \texttt{Field} ``Mesh'' template parameter: -\texttt{UniformCartesian}. Refer to the \ippl User Refercnce for details on the -\texttt{UniformCartesian} class; basically, it represents a \texttt{Cartesian} mesh with uniform grid spacings. -The \texttt{Cartesian} class represents a cartesian mesh with nonuniform grid spacings. NB.: -the type parameter \texttt{MFLOAT} for \texttt{Cartesian} represents only the data type used to store internal -information like mesh spacing values; if \texttt{double} satisfies the user, he need not specify it. - -The \texttt{Centering} parameter represents the centering of the field on its mesh. \ippl -pre-defines \texttt{Cell} and \texttt{Vert} classes to represent cell and vertex centering, and has implementations -of appropriate mechanisms for \texttt{Cartesian} and other classes which use them. \ippl -also predefines a \texttt{CartesianCentering} class to represent more general centerings--combinations -of vertex and cell centering direction-by-direction and component-by-component for -\texttt{Field}s with multicomponent element types such as \texttt{Vektor}. Finally, \ippl predefines a -wrapper class \texttt{CommonCartesianCenterings} with typedef’s several common special -cases to represent face and edge centerings, for example, refer to the \ippl User Reference -for details. - -\subsection{Invoking the \texttt{Field} Constructor} \label{sec:inv_field} - -There are six steps in the general construction of a \texttt{Field}: -\begin{enumerate} - \item Construct \texttt{Index} objects, one for each dimension of the \texttt{Field}. The \texttt{Index} objects describe the desired index domain along the axis. - \item Construct an \texttt{NDIndex} object with the dimensions of the \texttt{Field}. A single \texttt{NDIndex} object contains N \texttt{Index} objects, and fully describes the total index domain. - \item Populate the \texttt{NDIndex} with the \texttt{Index} objects created in step 1. - \item Construct a \texttt{FieldLayout} object with the \texttt{NDIndex} object. The \texttt{FieldLayout} object will control how the data of a specified \texttt{Field} object will be partitioned among physical nodes in a parallel environment. - \item If desired, construct \texttt{BConds} and \texttt{GuardCellSizes} objects for specifying boundary conditions and guard-cell layers, respectively. If unspecified, these default to no-op and zero. - \item Finally, construct a \texttt{Field} with the \texttt{FieldLayout}, \texttt{BConds}, and \texttt{GuardCellSizes} object as arguments to the constructor. This target \texttt{Field} must be parametrized as described in Section \ref{sec:tmpl_params}. The \texttt{Dim} template parameter must match the one for the \texttt{FieldLayout} and other objects involved, or you will get a compiler error. -\end{enumerate} - -For the cases of a 1,2, or 3 dimensional \texttt{Field}, you may omit steps 2 and 3; instead directly pass the one, two, or three \texttt{Index} objects as arguments to the \texttt{FieldLayout()} constructor. The \texttt{Dim} template parameter must match the number of \texttt{Index} objects passed or you will get a compiler error. - -The following code segment demonstrates the construction of a single two dimensional \texttt{Field} of \texttt{double}'s using the six-step method described above: \\ -\begin{code} -unsigned Dim = 2; -int Nx = 100, Ny = 50; -Index I(Nx), J(Ny)l // Step 1 -NDIndex domain; // Step 2 -domain[0] = I; // Step 3 -domain[1] = J; // Step 3 -FieldLayout layout(domain); // Step 4 -Field A(layout); // Step 5 -\end{code} - -The following three examples show the construction of a 3 dimensional \texttt{Field} without the intermediate \texttt{NDIndex} construction: -\begin{smallcode} -Index I(100), J(5), K(25); -FieldLayout<3> layout(I,J,K); -Field A(layout); -\end{smallcode} - -You may also construct \texttt{Field} via copy constructor, wherein a \texttt{Field} is copied into another \texttt{Field}. This results in an element-by-element copy of the data: -\begin{smallcode} -// assuming we have constructed a 2D Field of doubles in A -A = 2.0; -Field B(A); -// B now contains the values 2.0 everywhere -\end{smallcode} - -\section{The \texttt{Index} Class} - -The \texttt{Index} class represents a strided range of indices, and it is used to define the index extent of \texttt{Field} objects on construction and to reference subranges within \texttt{Field}'s in expressions. The constructor for \texttt{Index} takes one, two or three int arguments. In the case of three arguments, these represent the base index value, the bounding index value and the stride. The two and one-argument cases are simplifications, with the one-argument case being qualitatively different; in -particular, -\begin{smallcode} -Index I(8); -\end{smallcode} -instantiates an \texttt{Index} object representing the range of integers from $0$ to $7$ inclusive, with implied stride $1$. The two-argument -\begin{smallcode} -Index J(2,8); -\end{smallcode} -instantiates an \texttt{Index} object representing the range of integers $[2,8]$, with implied stride 1. The three-argument -\begin{smallcode} -Index K(1,8,2); -\end{smallcode} -instantiates an \texttt{Index} object representing the range of integers $[1,8]$, with stride 2; that is the ordered set $\{1,3,5,7\}$. - -Note that the single argument in the one-argument case defines the number of elements, rather than the bound. This means that \texttt{Index J(8)}, which represents $[0,7]$, is different than \texttt{Index J(0,8)} and \texttt{Index J(0,8,1)}, which both mean $[0,8]$. - -As illustrated in Section \ref{sec:inv_field}, you use \texttt{Index}'s in constructing the \texttt{FieldLayout} object which goes into the \texttt{Field} constructor. The sizes of the \texttt{Index}'s used to construct the \texttt{FieldLayout} determine the size of the \texttt{Field} in each dimension; here size means the number of integers in the range represented by the \texttt{Index}. For example, the following code segment instantiates a 3-dimensional \texttt{Field A} having size 5 in the first dimension, size 9 in the second dimension, and size 4 in the -third dimension: \\ -\begin{code} -unsigned Dim = 3; -int Nx = 5; -int Ny = 9; -int Nx = 4; -Index I(Nx), J(Ny), K(Nz); -FieldLayout layout(I,J,K); -Field A(layout); -\end{code} - -You can also use \texttt{Index} objects for initializing \texttt{Field} elements with integer ranges of values. This and more typical use of \texttt{Index} object in conjunction with \texttt{Field} objects is discussed in Section \ref{sec:index_fields}. - -Finally, \ippl defines various operators on \texttt{Index} objects, mostly used to represent finite-different stencil operations on \texttt{Field}'s, as described in Section \ref{sec:index_fields}. If -\begin{smallcode} -Index I(8); -\end{smallcode} -is an \texttt{Index} object representing $[0,7]$, then the expression -\begin{smallcode} -I - 1 -\end{smallcode} -represents the range of the same length offset by $-1$, or $[-1,6]$. Similarly, the expression -\begin{smallcode} -I + 1 -\end{smallcode} -represents $[2,8]$. - -\section{The \texttt{NDIndex} Class} - -The \texttt{NDIndex} class is primarily a container which holds \texttt{N} \texttt{Index} objects. It is templated on the spatial dimension \texttt{N}, and the constructor takes \texttt{N} \texttt{Index} arguments. For example: -\begin{smallcode} -Index I(5), J(9), K(4); -NDIndex<3> Domain(I, J, K); -\end{smallcode} - -An \texttt{NDIndex} object appears as an array of \texttt{Index} objects; you may access the \texttt{Index} object for and dimension using the \texttt{[]} operator. For example: -\begin{smallcode} -Index tmpJ = Domain[1]; -\end{smallcode} - -\section{The \texttt{FieldLayout} Class} - -\texttt{FieldLayout} is the class responsible for determining where the data in a \texttt{Field} object is located. It is templated on the number of indices for the \texttt{Field}; when constructing a new \texttt{FieldLayout} object, you must tell it what is the index range for each dimension (or axis). A single \texttt{NDIndex} object may be used as the argument to a new \texttt{FieldLayout} instance: -\begin{smallcode} -Index I(5), J(9), K(4); -NDIndex<3> Domain(I, J, K); -FieldLayout<3> Layout(Domain); -\end{smallcode} -Or, possibly more conveniently, you may just specify the N \texttt{Index} objects to the constructor of the \texttt{FieldLayout} directly, without explicitly creating an \texttt{NDIndex} object: -\begin{smallcode} -Index I(5), J(9), K(4); -FieldLayout<3> Layout(I, J, K); -\end{smallcode} - -\subsection{Specifying Serial or Parallel Layout} - -By default, a \texttt{FieldLayout} object will partition all \texttt{N} dimensions in a parallel fashion. For example a 2D \texttt{Field} with indices running from $0 \ldots 5$ in each dimension, created with a \texttt{FieldLayout} specified as follows: -\begin{smallcode} -Index I(6), J(6); -FieldLayout<3> Layout(I, J); -\end{smallcode} -will have both the \texttt{I} and \texttt{J} indices partitioned across the nodes in parallel. This would lead to a layout something like that shown in the following figure, if there are four nodes: - -TODO: BILD - -Unless you tell it otherwise, \texttt{FieldLayout} will attempt to distribute the data among the processors by subdividing each dimension in turn until it has the proper number of subregions. Those axes which are considered for subdivision are the \textit{parallel} axes, which means that a given node will only contain \texttt{Field} data for a subset of the indices along that dimension. You can, however, tell \texttt{FieldLayout} which axes to subdivide, and which to maintain as \textit{serial}. Serial axes are -not ever partitioned by \texttt{FieldLayout}. You must have at least on parallel dimension in a given \texttt{FieldLayout}; by default, all axes are parallel. - -To specify serial axes, you provide additional arguments to the \texttt{FieldLayout} constructor, using the keywords \texttt{SERIAL} or \texttt{PARALLEL}. If you create a new \texttt{FieldLayout} by just specifying \texttt{N} \texttt{Index} objects, then you may provide up to \texttt{N} more arguments to the constructor to set the corresponding dimension's layout method. For example, we may change the earlier example of a 2D \texttt{Field} to have the second dimension use a serial layout as follows: -\begin{smallcode} -Index I(6), J(6); -FieldLayout<3> Layout(I, J, PARALLEL, SERIAL); -\end{smallcode} -In this case, the data would be partitioned into four subregions like the following (the horizontal direction is the first dimension, the vertical direction the second) - -TODO: BILD - -If an \texttt{NDIndex} object is used to create the \texttt{FieldLayout} instead of several \texttt{Index} objects, to change the default layout style you must instead provide an array of keywords (of type \texttt{e\_dim\_tag}) specifying the layout for the \texttt{N} dimensions. For example: \\ -\begin{code} -Index I(5), J(9), K(4); -NDIndex<3> Domain(I, J, K); -e_dim_tag ParallelMethod[2]; -ParallelMethod[0] = PARALLEL; -ParallelMethod[1] = SERIAL; -ParallelMethod[2] = SERIAL; -FieldLayout<3> Layout(Domain, ParallelMethod); -\end{code} - -\section{Boundary Condition Classes} - -One of the great frustrations in using data parallel objects is the proper representation of boundary conditions. Most data parallel environments (such as HPF or CMFortran) require that one perform special operations to observe periodic or reflected behaviour at the boundary. This requirement obscures the original clarity of the index notation. You construct \texttt{Field} objects within the \ippl framework using \texttt{BConds} boundary condition object which defines the behaviour of \texttt{Field} and \texttt{Field} -indexing operations at the boundaries. This makes the same, clear indexing notation do the right thing under a variety of imposed boundary conditions. - -\subsection{Available Boundary Conditions} - -\ippl pre-defines classes to represent 6 different forms of boundary conditions: -\begin{enumerate} - \item Periodic boundary condition: \texttt{PeriodicFace} - \item {\color{red} Positive reflecting boundary condition: \texttt{PosReflectFace} - \item Negative reflecting boundary condition: \texttt{NegReflectFace} - \item Constant boundary condition: \texttt{ConstantFace}} - \item Zero boundary condition (special case of constant): \texttt{ZeroFace} - \item {\color{red} Linear extrapolation boundary condition: \texttt{ExtrapolateFace}} -\end{enumerate} -The {\color{red} red} ones are not yet important. - - -They represent boundary conditions for a single dimension of a (possibly) multidimensional field, for one ``side'' (or face) of the mesh along that dimension. That is, you must specify two boundary condition objects for each dimension of the \texttt{Field} -- one for each face of the mesh along that dimension. These classes are parametrized on the same four template parameters as \texttt{Field} (see Section \ref{sec:tmpl_params}); the defaults for \texttt{Mesh} and \texttt{Centering} are -\texttt{UniformCartesian} and \texttt{Cell}. As a -further refinement, you may specify boundary conditions for individual components of multicomponent \texttt{Field} elements such as \texttt{Vektor}. - -\subsection{Using Boundary Conditions With \texttt{Field}s} - -The \texttt{BConds} class is a container for the individual specialized boundary conditions; this is the argument passed to the \texttt{Field} constructor. A \texttt{BConds} object acts very much like an array of boundary conditions: when first created, the \texttt{BConds} object is empty, and you add new boundary condition objects to it by treating it as a vector and assigning to its elements. The basic procedure is to construct a \texttt{BConds} object, then construct new or use existing boundary condition objects (from the list -above) to fill it, as illustrated in this example: \\ -\begin{code} -unsigened Dim = 2; -Index I(4), J(4); -BConds bc; -bc[0] = new PeriodicFace(0); -bc[1] = new PeriodicFace(1); -bc[2] = new PeriodicFace(2); -bc[3] = new PeriodicFace(3); -Field Layout layout(I, J); -Field A(layout, GuardCellSizes(1), bc); -\end{code} -Again, the individual face boundary condition objects (in this example, \texttt{PeriodicFace}) perform their task for only a single face of the mesh. In this way, there may be different types of boundary conditions in different dimensions. The face boundary-condition constructors take an unsigned argument designating the face according the following numbering convention: The integers 0 and 1 apply to the boundaries of the first coordinate direction where 0 represents the negative face and 1 -represents the positive face. The integers 2 and 3 apply to the boundaries of the second coordinate direction where 2 represents the negative face and 3 represents the positive face. This pairing of integers and domains continues into higher dimensions. The constructors also take optional second and third unsigned parameters to specify a single \texttt{Field} element component rather than all of them. Refer to the \ippl User Reference for more details on these classes, and a detailed discussion -of how the various boundary conditions affect \texttt{Field} operations. - -\subsection{Default Boundary Condition} - -If a \texttt{Field} is constructed with no \texttt{BConds} object specified, the default is for that \texttt{Field} to have NO boundary conditions. In that case, the boundary conditions container within the \texttt{Field} is empty. It is possible to add additional boundary conditions for a specific face to a \texttt{Field} after it has been constructed; to do so, retrieve the boundary condition container from the \texttt{Field} using the method \texttt{Field::getBConds()}, and then add new face-specific boundary conditions to the returned -\texttt{BConds} container object as shown in the previous example. - -\section{The \texttt{GuardCellSizes} Class} - -A \texttt{GuardCellSizes} class, an optional argument to the \texttt{Field} constructor, represents the maximum separation (in elements) of \texttt{Field} elements which will be combined in \texttt{Field} expressions. Typically, this reflects the order of finite differencing in stencil operations. The primary reason for guard cells is parallelism -- a \texttt{Field} domain-decomposed into multiple subdomains with data from adjacent subdomains, so that the stencil operations -have all required data locally. The \texttt{GuardCellSizes} -class is parameterized on the unsigned value \texttt{Dim}, which represents the number of dimensions of the \texttt{Field} object. This \texttt{Dim} value must match the corresponding parameter value of the \texttt{Field} object. - -The constructor for \texttt{GuardCellSizes} takes either one or two arguments, which are either \texttt{unsigned} or \texttt{unsigned*}. The one-argument forms specify the same number of guard layers for all dimensions; the two-argument forms specify different numbers for the right and left faces; the unsigned forms specify the same number of layers for all dimensions; and the \texttt{unsigned*} forms specify different number of layers for the different dimensions: -\begin{smallcode} -GuardCellSizes(unsigned s); // Same no. left&right, same for all directions -GuardCellSizes(unsigned *s); // Same no. left&right, value for each direction -// Diff. left&right, same for all directions -GuardCellSizes(unsigned l, unsigned r); -// Diff. left&right, value for each direction -GuardCellSizes(unsigned *l, unsigned *r); -\end{smallcode} - -Section \ref{sec:index_fields}, ``Using \texttt{Index} Objects with \texttt{Field}'s'', shows examples using \texttt{Field} indexing to implement stencil operations. It discusses the numbers of guard layers required by one of the examples. - -\section{Operations on \texttt{Field} Objects} - -\subsection{Assignment} - -A single line of code which contains an assignment operator and a \texttt{Field} on the left hand side of the assignment operator is called a \texttt{Field} expression. Many different terms may appear on the right-hand side of a \texttt{Field} expression (or as the second argument in an \texttt{assign()} call as described below). These include scalars, \texttt{Index}'s, \texttt{Field}'s and \texttt{IndexingField}s's. Currently because of the lack of template member functions in -C++ compilers, you must use the \texttt{assign()} function rather than the -\texttt{operator=}: -\begin{smallcode} -assign(Lhs, Rhs); -\end{smallcode} -where \texttt{Lhs} and \texttt{Rhs} are \texttt{Field} expressions. When template member functions become available, you will simply write: -\begin{smallcode} -Lhs = Rhs -\end{smallcode} - -Refer to the \ippl Users Reference for more details, and examples showing where you may use \texttt{operator=} and where you must use \texttt{assign()}. The following are examples of legal assignments:\\ -\begin{code} -unsigned Dim = 2, int N = 100; -Index I(N), J(N); -FieldLayout layout(I, J); -Field A(layout), B(layout), C(layout); -A = 2.0; -assign(A, 2.0 + B); -assign(B, A + 2.0); -assign(B[I][J], 3.0 + B[I][J]); -assign(A[I][J], I + A[I][J]/C[I][J]); -\end{code} - -For cases where more than one term exists on the right hand side of an assignment, the \texttt{assign()} call must be made. Any combination of scalars, \texttt{Field}'s, \texttt{IndexingField}'s (indexed \texttt{Field} objects; see Section \ref{sec:index_fields}), and \texttt{Index}'s can be put as the second argument of the \texttt{assing()} call. The only requirement in combining terms is that the appearance of an \texttt{Index} object anywhere inside of an expression requires that all the \texttt{Field} objects contained in the expression must be indexed. It -is not possible to combine \texttt{Field}'s and \texttt{IndexingField}'s in a single expression. Nor is it possible to combine \texttt{Field}'s and \texttt{Index} objects in a single expression. - -Another intermediate solution to accommodate the lack of member function templates (and therefore the ability to use the \texttt{operator=} member function with more than one term on the right hand side of an expression) is the utilization of the accumulation operators (since this does not require member function templates). Thus, instead of writing -\begin{smallcode} -assign(A, 4.0 + B); -\end{smallcode} -one could write -\begin{smallcode} -A = 0.0; -A += 4.0 + B; -\end{smallcode} -This technique can be used with any of the accumulation operators (\texttt{+=,-=,*=,/=}). - -\subsection{Using \texttt{Index} Objects with \texttt{Field}'s} \label{sec:index_fields} - -The \texttt{Field} object works intimately with \texttt{Index} objects to perform a wide variety of operations. Use the \texttt{Index} object to specify the access pattern into a data parallel \texttt{Field} object. Do this by using \texttt{Index} objects inside the brackets following a \texttt{Field} object as follows: -\begin{smallcode} -A[I][J] = B[I][J]; -\end{smallcode} -A \texttt{Field} object followed by brackets containing \texttt{Index} objects is called an \texttt{IndexingField}, because \ippl internally uses an \texttt{IndexingField} class as the return value for the \texttt{Field::operator[]}. - -You can use \texttt{Index} objects to initialize a \texttt{Field} with integer range data -- that is, assign to a strided range of \texttt{Field} elements the values of a strided range of integers multiplied by the element type. This only works of multiplication by an int is defined for the \texttt{Field} element type, which it is for the intrinsic types $\{$\texttt{int, float, double, bool}$\}$ and the \ippl pre-defined \texttt{Field} element classes $\{$\texttt{Vektor, Tenzor, -SymTenzor}$\}$. For multidimensional \texttt{Field}'s, the range of values is replicated along -the other dimensions. For example, given a \texttt{Field} that is size 8 in its first dimension and size 4 in its second dimension, the code segment -\begin{smallcode} -assign(A[I][J], I); -\end{smallcode} -produces the following values in the \texttt{Field A}: -% - \begin{center} - \begin{tabular}{|c|c|c|c|c|c|c|c|} - \hline - 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ - \hline - 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ \hline - 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ \hline - 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ \hline - \end{tabular} - \label{tbl:t1} - \end{center} -% -(Here, as in subsequent figures like this displaying \texttt{Field} values, the positive direction of the first coordinate is from left to right and the positive direction for the second coordinate is from top to bottom.) Likewise, an assignment of the form -\begin{smallcode} -assign(A[I],[J], J); -\end{smallcode} -produces -% - \begin{center} - \begin{tabular}{|c|c|c|c|c|c|c|c|} - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \hline - 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ \hline - 2 & 2 & 2 & 2 & 2 & 2 & 2 & 2 \\ \hline - 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} - -The \texttt{Index} objects used to access ranges of values in a \texttt{Field} object do not have to be the same \texttt{Index}'s used in constructing the \texttt{FieldLayout} object used to construct the \texttt{Field}. You can use \texttt{Index} objects of smaller size to access a subrange of the \texttt{Field}. For example, if we wanted to have an 8 by 8 \texttt{Field} with zeros everywhere except for a 4 by 4 subregion in the center, the following code segment would accomplish this goal: \\ -\begin{code} -unsigned Dim = 2; -Index I(8), J(8); -Index I2(2,5), J2(2,5); -FieldLayout layout(I, J); -Field A(layout); -A = 0.0; -A[I2][J2] = 1.0; -\end{code} -This would produce the following values in the \texttt{Field A}: -% - \begin{center} - \begin{tabular}{|c|c|c|c|c|c|c|c|} - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \hline - 0 & 0 & 1 & 1 & 1 & 1 & 0 & 0 \\ \hline - 0 & 0 & 1 & 1 & 1 & 1 & 0 & 0 \\ \hline - 0 & 0 & 1 & 1 & 1 & 1 & 0 & 0 \\ \hline - 0 & 0 & 1 & 1 & 1 & 1 & 0 & 0 \\ \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} - -The lower-limiting case range for an \texttt{Index} object is, of course, a single element. For this case you can just use an integer constant or variable; the following assigns a single element of the \texttt{Field A}: \\ -\begin{code} -Index I(4), J(4); -FieldLayout<2> layout(I, J); -Field A(layout); -A = 0.0; -A[1][1] = 1.0; -\end{code} -The resultant \texttt{Field A} contains the values: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 0 & 0 & 0 & 0 \\ \hline - 0 & 1 & 0 & 0 \\ \hline - 0 & 0 & 0 & 0 \\ \hline - 0 & 0 & 0 & 0 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} - -The typical use for indexing is stencil operations, using \texttt{Index} expressions adding or subtracting integer constants to represent the finite differences. This amounts to global data transformation upon a \texttt{Field} through the use of \texttt{Index} operations. For example, if a 4 by 4 \texttt{Field} named \texttt{A} is initialized as follows: \\ -\begin{code} -unsigned Dim = 2; -int N = 4; -Index I(N), J(N); -FieldLayout layout(I, J); -Field A(layout, GuardCellSizes(1)); -assign(A[I][J], I + 1); -\end{code} -then the values in the \texttt{Field A} will be: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 1 & 2 & 3 & 4 \\ \hline - 1 & 2 & 3 & 4 \\ \hline - 1 & 2 & 3 & 4 \\ \hline - 1 & 2 & 3 & 4 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} - -Now, let's form another \texttt{Field}, \texttt{B}, and assign to it the value of an \texttt{IndexingField} of A which represents an indexed operation: -\begin{smallcode} -Field B(layout); -assign(B[I][J], A[I+1][J]); -\end{smallcode} - -Here we see that the \texttt{Field A} has been indexed with something other than a plain \texttt{Index} object. Rather, it has been indexed by an index expression. The \texttt{Index} objects have been overloaded to allow addition and subtraction by integers to produce other \texttt{Index} objects. The framework recognizes this operation as requesting that all the data in \texttt{A} be shifted to the left (along the first dimension in the negative direction) by 1 position. The \texttt{Field B} contains the values: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 2 & 3 & 4 & 0 \\ \hline - 2 & 3 & 4 & 0 \\ \hline - 2 & 3 & 4 & 0 \\ \hline - 2 & 3 & 4 & 0 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} - -\texttt{Index}ing operations which access data beyond a \texttt{Field} boundary set the target positions to zero. For the reminder of this section, we shall assume this zero valued boundary condition (which is the default condition when no boundary condition is specified). A variety of boundary conditions can be set on each boundary of a \texttt{Field} and are discussed in detail in the next section. - -The \texttt{GuardCellSizes} object used to construct \texttt{Field A} in this example must specify at least on guard layer in the 1st dimension, to accommodate the ``$+1$'' in the indexing operation. The one used, \texttt{GuardCellSizes(1)} allows ``$+/-1$'' indexing (as in a width-one stencil), and also allows width-one stencils in the 2nd dimension, because the use of the unsigned argument (the constant, 1) specifies one guard layer both left and right for all directions. - -Had we wished to shift the \texttt{Field A} down (along the second dimension in the negative direction) we could have written -\begin{smallcode} -assign(B[I][J], A[I][J+1]); -\end{smallcode} -Then the values in the \texttt{Field B} are: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 1 & 2 & 3 & 4 \\ \hline - 1 & 2 & 3 & 4 \\ \hline - 1 & 2 & 3 & 4 \\ \hline - 0 & 0 & 0 & 0 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} - -You can shift in the positive or negative direction on any \texttt{Index} object used to index a \texttt{Field}. For example, \\ -\begin{code} -unsigned Dim = 2; -int N = 4; -Index I(N), J(N); -FieldLayout layout(I, J); -Field A(layout, GuardCellSizes(1)); -assign(A[I][J], I + J + 1); -\end{code} -will initialize the values in the \texttt{Field A} to: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 1 & 2 & 3 & 4 \\ \hline - 2 & 2 & 4 & 4 \\ \hline - 3 & 4 & 5 & 6 \\ \hline - 4 & 5 & 6 & 7 \\ \hline - \end{tabular} - \label{tbl:t2} - \end{center} -% -and the operation -\begin{smallcode} -Field B(layout); -assign(B[I][J], A[I+1][J-2]); -\end{smallcode} -will produce a \texttt{Field B} with the values: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - 0 & 0 & 0 & 0 \\ \hline - 0 & 0 & 0 & 0 \\ \hline - 3 & 4 & 5 & 0 \\ \hline - 4 & 5 & 6 & 0 \\ \hline - \end{tabular} - \end{center} - -\subsection{Overloaded operators} - -\ippl pre-defines a suite of overloaded operators with the \texttt{Field} class. These include the unary $-$ operator; the binary operators, $+$, $-$, $*$, and $/$; and the accumulation operators \texttt{+=, -=, *=, /=}. Traits~\cite{traits} determine the appropriate casts and promotions of mixed types inside \texttt{Field}. For example, a \texttt{Field} of \texttt{int}'s added to a \texttt{Field} of \texttt{double}'s would perform the correct promotion of \texttt{int} to \texttt{double} element by element. As mentioned earlier, the assign operator $=$ does not work -for most cases because of the lack of member function templates. In addition, the relational operators are not directly available due to conflicts in the current HP reference STL implementation. This functionality is provided through the explicit inlined binary function calls: -% - \begin{center} - \begin{tabular}{ll} - \hline - binary function relationals & corresponding relation operator \\ - \hline - gt(A, B) & $A > B$ \\ - lt(A, B) & $A < B$ \\ - ge(A, B) & $A >= B$ \\ - le(A, B) & $A <= B$ \\ - eq(A, B) & $A == B$ \\ - ne(A, B) & $A != B$ \\ - \hline - \end{tabular} - \end{center} -% -The return value of these binary relational functions is a conforming \texttt{Field} of \texttt{bool}'s. Here is an example using binary functional relationals in an expression: \\ -\begin{code} -unsigned Dim = 2; -Index I(8), J(4); -FieldLayout layout(I, J); -Field A(layout), B(layout), C(layout); -A = 0.0; -assign(B[I][J], J); -assign(C[I][J], I); -assign(A, lt(B, 2,0)*C); -\end{code} -The resulting \texttt{Field A} contains the values -% - \begin{center} - \begin{tabular}{|c|c|c|c|c|c|c|c|} - \hline - 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7\\ \hline - 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7\\ \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ \hline - 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ \hline - \end{tabular} - \end{center} - -\subsection{The \texttt{where()} Function} - -Data parallel simulations often require element-by-element conditionals. The \ippl framework provides a \texttt{where} functions which reduces to the inlined conditional \texttt{operator?}: for each element of the \texttt{Field} objects passed to the \texttt{where()} function. The \texttt{where()} function takes three \texttt{Field} arguments: -\begin{smallcode} -assign(A, where(B, C, D)); -\end{smallcode} -where the \texttt{Field B}'s a \texttt{Field} of \texttt{bool}'s. The value of \texttt{C} is placed into \texttt{A} everywhere that \texttt{B} is \texttt{true}, and the value of \texttt{D} is placed into \texttt{A} everywhere that \texttt{B} is \texttt{false}. Thus, \\ -\begin{code} -unsigned Dim = 2; -Index I(4), J(4); -FieldLayout layout(I, J); -Field A(layout), B(layout), C(layout); -assign(B[I][J], I - 1); -C = 1.0; -assign(A[I][J], where( lt(B, C), B, C)); -\end{code} -leaves the following values in \texttt{Field A}: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - -1 & 0 & 1 & 1 \\ \hline - -1 & 0 & 1 & 1 \\ \hline - -1 & 0 & 1 & 1 \\ \hline - -1 & 0 & 1 & 1 \\ \hline - \end{tabular} - \end{center} - -Since \texttt{where()} returns a \texttt{Field}, invocations of \texttt{where()} may be used as arguments to where(); this allows nested element-by-element conditionals. The following example code\\ -\begin{code} -unsigned Dim = 2; -Index I(4), J(4); -FieldLayout layout(I, J); -Field A(layout), B(layout), C(layout), D(layout); -assign(B[I][J], I - 1); -assign(C[I][J], J - 1); -D = 1.0; -assign(A[I][J], where( lt(B, D), B, where( lt(C, D), C, D))); -\end{code} -leaves the following values in \texttt{Field A}: -% - \begin{center} - \begin{tabular}{|c|c|c|c|} - \hline - -1 & 0 & -1 & -1 \\ \hline - -1 & 0 & 0 & 0 \\ \hline - -1 & 0 & 1 & 1 \\ \hline - -1 & 0 & 1 & 1 \\ \hline - \end{tabular} - \end{center} - -\subsection{Mathematical Functions on \texttt{Field}'s} - -As would be expected of any framework for scientific simulation, all the standard mathematical operations are included. The unary functions take a \texttt{Field} object and return a \texttt{Field} object of the same dimension and size where the unary operation has been performed upon each element of the \texttt{Field}. The binary functions take two conforming \texttt{Field}'s and apply the function pairwise to each member of the two \texttt{Field}'s to produce a new conforming \texttt{Field} containing the resultant values. The following -functions, mirroring those in math.h, are available in the framework for \texttt{Field} operations: -\begin{smallcode} -acos, asine, atan, cos, sin, tan, cosh, sinh, tanh, -exp, log, log10, pow, sqrt, ceil, fabs, floor. -\end{smallcode} -For machines which provide them in \texttt{math.h}, \ippl provides the \texttt{Field} version of the \texttt{Bessel, gamma, and error} functions -\begin{smallcode} -erf, erfc, gamma, j0, j1, y0, y1. -\end{smallcode} - -\subsection{Reduction Operations} - -\ippl includes several reduction operations with the \texttt{Field} class. These include determining the maximum and minimum elements of a \texttt{Field}, the global sum and product of all the elements in a \texttt{Field}, and determining the location of the minimum and maximum values within a \texttt{Field} (typically called minloc and maxloc). - -\textit{WARNING: Currently, these functions are only implemented on \texttt{Field} objects; they will not work on \texttt{Field} expressions. This means that invocations like \texttt{min(A+B)} and \texttt{min(2.0*A)} are illegal!} - -The following exampled code, which demonstrates the usage of these operators,\\ -\begin{code} -unsigned Dim = 2; -Index I(10), J(10); -FieldLayout layout(I, J); -Field A(layout); -assign(A[I][J], I + J); -cout << min(A) << endl; -cout << max(A) << endl; -cout << sum(A) << endl; -cout << prod(A) << endl; -\end{code} -produces the following output: -\begin{smallcode} -0 -18 -900 -0 -\end{smallcode} - -The minloc and maxloc capabilities, rather than being separately named functions, are two-argument forms of the \texttt{min()} and \texttt{max()} functions. The second argument is an \texttt{NDIndex} object, which is a multi-dimensional container for \texttt{Index} objects. The minloc and maxloc operations fill an \texttt{NDIndex} object with one \texttt{Index} object for each dimension; each \texttt{Index} is of size one, representing a single point. The following code segment demonstrates: \\ -\begin{code} -unsigned Dim = 2; -Index I(10), J(10); -FieldLayout layout(I, J); -Field A(layout); -assign(A[I][J], cos((I-2)*(I-2) + (J-2)*(J-2))); -NDIndex LocMin, LocMax; -min(A, LocMin); -max(A, LocMax); -\end{code} -The \texttt{NDIndex} objects \texttt{LocMin} and \texttt{LocMax} now contain the position (index location) of the minimum and maximum elements of the \texttt{Field} object \texttt{A}. - diff --git a/manual/ippl_index_ref.tex b/manual/ippl_index_ref.tex deleted file mode 100644 index 7d15929db..000000000 --- a/manual/ippl_index_ref.tex +++ /dev/null @@ -1,313 +0,0 @@ -\chapter{Index Class} -\label{sec:index} -The \texttt{Index} class represents a strided range of integer indices (described by base, bound, and stride integer values). -You use it to define the size (index extent) per dimension of \texttt{Field} objects on construction and to specify subsets of -\texttt{Field} elements along a dimension in \texttt{Field} expressions. - -It is important to note that the actual memory address of an \texttt{Index} object is relevant to whether that object may be used -interchangeably with another \texttt{Index} object specifying the same index values. In fact, two \texttt{Index} objects specifying -the same index values are not interchangeable. This is qualitatively different than the semantics of Fortran 90 array-syntax, -for example. You may construct a "new" \texttt{Index} object with a different name, but which has the same values and -is interchangeable with a given \texttt{Index} by setting it equal to the first Index object on construction. -\section{Index Definition} -\label{sec:indpubldef} -\begin{smallcode} -class Index { -public: -// Public data member -- iterator class: class iterator -{ -public: -iterator() : Current (0) , Stride(0) {} -iterator(int current, int stride=l) : Current (current) , Stride(stride){} -int operator*(); -iterator operator--(int); // Post decrement iterator& operator--(); -iterator operator++(int); // Post increment iterator& operator++(); -iterator& operator+=(int); -iterator& operator-=(int); -iterator operator+(int) const; -iterator operator-(int) const; -int operator[] (int); -bool operator==(const iterator &) const; -bool pperator (const iterator &) const; -bool operator<=(const iterator &) const; -bool operator>=(const iterator &) const; -private: -int Stride; -intCurrent; -}; - -// Public member functions. -// Constructors: -Index ( ) ; // null range -inline Index(unsigned n); // [0 .. n-1] -inline Index(int f, int l); // [f .. l] -inline Index(int f, int l, int s); // First to Last using Step. - -// Destructor -~Index () {}; // Don't need to do anything. - -int id () { return 1 ; } - -inline int min() const; // the smallest element. -inline int max() const; // the largest element. -inline int length() const; // the number of elems. -inline int stride() const; // the stride. -inline int first() const; // the first element. -inline int last() const; // the last element. -inline bool emty() const; // is it empty? -inline const Index* getBase() const; // the base index - -// Additive operations. -friend inline Index operator+ (const Index&, int); -friend inline Index operator+(int,const Index&); -friend inline Index operator~(const Index&,int); -friend inline Index operator-(int,const Index&); - -// Multiplicative operations. -friend inline Index operator-(const'Index&); -friend inline Index operator*(const Index&,int); -friend inline Index operator*(int,const Index&); -friend inline Index operator I (const Index&,int); - -// Intersect with another Index. -Index intersect(const Index&) const; - -// Plug the base range of one into another. -Index plugBase(const Index &) const; - -// Test to see if two indexes are from the same base. -inline bool sameBase(const Index &) const; - -// Test to see if there is any overlap between two Indexes. -inline bool touches (const Index& a) const; - -// Test to see if one contains another. , -inline bool contains(const Index& a) const; - -// Split one. into two. -inline bool split(Index& I, Index& r) const; - -// iterator begin -iterator begin() { return iterator(First,Stride); } - -// iterator end -iterator end () { return iterator (First+Stride*Length, Stride); - -// An operator< so we can impose some sort of ordering. -bool operator< (const Index& r) const; - -// Test for equality. -bool operator==(const Index& r) const; - -static void findPut(const Index&,const Index&, const Index&, Index&, Index&); - -// put data into a message to send to another node -Message& putMessage(Message& m); - -// get data out from a message -Message& getMessage(Message& m); - -// Print it out. -friend ostream& operator<<(ostream& out, const Index& I); -}; -\end{smallcode} - - -\section{Index Constructors} -The constructor for \texttt{Index} takes one, two, or three in arguments. In the case of three arguments, -these represent the base index value, the bounding index value, and the stride. The two and one-argument cases are simplifications. -\begin{smallcode} -Index I(8); -\end{smallcode} -instantiates an \texttt{Index} object representing the range of integers from 0 through 7 (i.e" [0,7]) with implied stride 1. The two-argument -\begin{smallcode} -Index J(2,8); -\end{smallcode} -instantiates an \texttt{Index} object representing the range of integers [2,8] with implied stride 1. The three-argument -\begin{smallcode} -Index(1,8,2); -\end{smallcode} -instantiates an Index object representing the range of integers [1,8] with stride 2- .. that is, the ordered set ${1,3,5,7}$. - -Note that the single argument in the one-argument case defines the number of elements, rather than the bound. This means that \texttt{Index J(8)} , which represents $[0,7]$, -is different than \texttt{Index J(0,8)} \texttt{and Index J(0,8,1)} , which both mean $[0,8]$. - -There is also a special special constructor taking no arguments; this is meant for use in constructing arrays of\texttt{ Index}'s. - -\section{Index Member Functions and Member Data} -\subsection{Index iterator} -The only public member data is the \texttt{Index::iterator} class. This class has the semantics of an STL random access iterator; the advanced user can use -it to iterate over integer index values represented by the containing \texttt{Index} object. -The STL semantics means that the class provides increment and decrement operators, increment/decrement by specified integer amounts, deference operator, -random-access \texttt{operator[]}, and comparison operators. See the class definition in Section \ref{sec:indpubldef} for the full list. The \texttt{iterator class} definition is contained within. - -\begin{smallcode} -iterator begin () -\end{smallcode} -Returns an \texttt{Index: : iterator} positioned at the beginning of the index values represented by the \texttt{Index} object. -\begin{smallcode} -iterator end ( ) -\end{smallcode} -Returns an \texttt{Index::iterator} positioned beyond the last index value represented by the \texttt{Index} object. - - -\subsection{Index Query/Accessor Functions} -These functions mostly return values of or values computed from private data members of the \texttt{Index}. -\begin{smallcode} -int min () const -\end{smallcode} -Returns the smallest integer value allowed for the \texttt{Index} object. -\begin{smallcode} -int max () const -\end{smallcode} -Returns the largest integer value allowed for the \texttt{Index} object. -\begin{smallcode} -int length() const -\end{smallcode} -Returns the total number of integer values spanned by the \texttt{Index} object. -\begin{smallcode} -int stride()const -\end{smallcode} -Returns the value of the stride for the \texttt{Index} object. -\begin{smallcode} -int first() const -\end{smallcode} -Returns the integer value ofthe first element in the \texttt{Index} object. -\begin{smallcode} -int last () const -\end{smallcode} -Returns the integer value of the last element the \texttt{Index} object. -\begin{smallcode} -bool empty() const -\end{smallcode} -Returns true/false depending on whether the \texttt{Index} object is empty. Empty (true) means, that it was constructed with the zero-argument constructor. -\begin{smallcode} -const Index* getBase() const -\end{smallcode} -Returns a pointer to the base \texttt{Index} object associated with the \texttt{Index} object. As described at the beginning of this chapter, the memory address of an \texttt{Index} -is important, and if two \texttt{Index}'s are to be interchangeable they must share the same base address as well as be conforming (have the same base, bound, and stride values). - - -\subsection{Index Arithmetic operator Functions} -Here we describe the arithmetic operator functions defined in the Index class to act on \texttt{Index} objects. In the example code in these descriptions, \texttt{I} is an \texttt{Index} object and \texttt{n} is an \texttt{int}. -\begin{smallcode} -friend Index operator+(const Index&,int) -\end{smallcode} -The \texttt{Index} expression\texttt{I +n} invokes this operator. It adds an integer value \texttt{n} to the base and bound values of \texttt{I}, then constructs and returns the resulting \texttt{Index} object using those - revised values. - -\begin{smallcode} -friend Index operator+(int,const Index&) -\end{smallcode} -Same as the previous, except for the order of the operands. That is, the \texttt{Index} expression \texttt{n+I} invokes this operator. - -\begin{smallcode} -friend Index operator-(const Index&,int) -\end{smallcode} -Invoked by \texttt{ I-n} subtracts \texttt{n} from the base and bound of \texttt{I} and returns the resulting \texttt{Index}. -\begin{smallcode} -friend Index operator-(int,const Index&) -\end{smallcode} -Invoked by \texttt{n-I} subtracts the base of \texttt{I} from \texttt{n}, multiplies the stride by \texttt{ -1},and returns the - resulting \texttt{Index} object. - -\begin{smallcode} -friend Index operator-(const Index&) -\end{smallcode} -Negation operator, invoked by \texttt{-1}. This multiplies the base and bound of \texttt{I} by \texttt{-1} and returns the resulting Index object. -\begin{smallcode} -friend Index operator*(const Index&,int) -friend Index operator*(int,const Index&) -\end{smallcode} - -Invoked by \texttt{I*n} and \texttt{n*I}, respectively. These multiply the base, bound, and stride of \texttt{I} by \texttt{n} and return the resulting \texttt{Index} object -\begin{smallcode} -friend Index operator /(const Index&,int) -\end{smallcode} -Invoked by \texttt{I/n}. These divide the base, bound, and stride of \texttt{I} by \texttt{n} and return the resulting \texttt{Index} object (integer division, truncates). -Note that the division operator with the operands the other way around (\texttt{n/I}) is not defined. - -\subsection{Index I/O and Message-Passing Functions} -These are functions are to write out an \texttt{Index} object, and to pack/unpack and send/receive an \texttt{Index} object as a message between two processes. -\begin{smallcode} -friend ostream& operator<<(ostream&, const Index&) -\end{smallcode} -Formatted insertion of the contents of an \texttt{Index} object into the output stream. The interface is the stream I/O \texttt{operator <<}, invoked by \texttt{os< -class Mesh -{}; -\end{smallcode} - -\section{\texttt{UniformCartesian} Class} -\label{app:unifcart} -The \texttt{UniformCartesian} class represents the abstraction of a uniform-spacing Cartesian mesh discretizing a rectangular region of space. The \texttt{Mesh} has -uniform spacing in the sense that the mesh spacings (vertex-vertex distances) along a dimension are the same {\it all along that dimension}. The different dimensions -may have different (single) values for mesh spacing. The \texttt{Cartesian} class (Appendix \ref{app:cartclass}) generalizes this to meshes whose spacings vary cell-by-cell along each -dimension. \texttt{UniformCartesian} has mechanisms for returning various kinds of geometrical information from the mesh: cell-cell and vertex-vertex spacings, -nearest mesh vertex positions to a given point in space, and others. Many of these; such as a function to return the volume of a particular indexed cell in the mesh, -are somewhat redundant, for the uniform case, but make more sense in the nonuniform case (\texttt{Cartesian}); the interfaces of \texttt{UniformCartesian} and -\texttt{Cartesian} are meant to be as much alike as possible. -\texttt{UniformCartesian} is parameterized on dimensionality Dim, and another parameter MFLOAT. The MFLOAT parameter specifies the elemental type to use -in storing and returning mesh geometrical information such as spacings and position coordinates. Generally, this should be a floating-point type, and it defaults -to double. Vector values are represented using \texttt{Vektor}. - -\subsection{\texttt{UniformCartesian} Definition (Public Interface)} -\begin{smallcode} -template < unsigned Dim, class MFLOAT=double> -class UniformCartesian : public Mesh -{ ); -public: -// Public member data: -unsigned gridSizes[Dim]; // Sizes (number of vertices) -typedef Cell DefaultCentering; // used by Field -Vektor Dvc[1<, Dim>* VertSpacings ; -BareField, Dim>* CellSpacings ; - -// Public member functions: -// Constructors -UniformCartesian() {}; // Default constructor - -// Non-default constructors -UniformCartesian(NDIndex& ndi); -UniformCartesian(Index& I); -UniformCartesian(Index& I, Index& J); -UniformCartesian(Index& I, Index& J, Index& K); -// These also take a MFLOAT* specifying the mesh spacings: -UniformCartesian(NDIndex& ndi, MFLOAT* delX); -UniformCartesian(Index& I, MFLOAT* delX); -UniformCartesian(Index& I, Index& J, MFLOAT* delX); -UniformCartesian(Index& I, Index& J, Index& K, MFLOAT* delX); -// These further take a Vektor& specifying the origin: -UniformCartesian(NDIndex& ndi, MFLOAT*delX, Vektor& orig); -UniformCartesian(Index& I, MFLOAT* delX, Vektor orig); -UniformCartesian(Index& I, Index& J, MFLOAT* delX, Vektor& orig) ; -UniformCartesian(Index& I, Index& J, Index& K, MFLOAT* delX, Vektor& orig); - -~UniformCartesian() { }; // Destructor - -// Set functions for member data: -// Create BareField's of vertex and cell spacingsi allow for specifying -// layouts via the FieldLayout e_dim_tag and vnodes parameters (these -// get passed in to construct the FieldLayout used to construct the BareField's). - -void storeSpacingFields(); // Defaulti will have default layout - -// Special cases for 1-3 dimensions, a la FieldLayout ctors -void storeSpacingFields(e_dim_tag pI, int vnodes=-1); -void storeSpacingFields (e_dim_tag pI, e_dim_tag p2', int vnodes=-l) ; -void storeSpacingFields (e_dim_tag pI, e_dim_tag p2, e_dim_tag p3,int vnodes=-1); - -// It Next we have one for arbitrary dimension, a la FieldLayout ctor: -// All the others call this one internally: -void storeSpacingFields(e_dim_tag *p, int vnodes=-1); - -// Accessorfunctions for member data: -// Get the origin of mesh vertex positions: -Vektor get_origin(); - -// Get the spacings of mesh vertex positions along specified direction: -MFLOAT get_meshSpacing(int d); - -// Get the cell volume: -MFLOAT get_volume(); - -// Formatted output of UniformCartesian object: -void print (ostream&); -// Stream formatted output of UniformCartesian object: -friend ostream& operator<<(ostream&, const UniformCartesian&); - -// Other UniformCartesian methods - -// Volume of single cell indexed by input NDIndex -MFLOAT getCellVolume(NDIndex&); - -// Field of volumes of all cells: ' Field,Cel1>& -getCellVolumeField (Field,Cell>&); - -// Volume of range of cells bounded by verticies specified by inputNDIndex: -MFLOAT getVertRangeVolume(NDIndex&); - -// Volume of range of cells spanned by input NDIndex (index o'f cells): -MFLOAT getCe//Rangevolume(NDIndex&); - -// Nearest vertex index to (x,y,z) -NDIndex& getNearestVertex(Vektor&); - -// Nearest vertex index with all vertex coordinates below (x,y,z): -NDIndex& getVertexBelow(Vektor&); - -// NDIndex for cell incell-ctrd Field containing the point (x,y,z): -NDIndez& getCellContaining(Vektor&); - -// (x,y,z) coordinates of indexed vertex: _ -Vektor getVertexPosition (NDIndex&); - -// Field of (x,y,z) coordinates of all vertices: -Field, Dim, UniformCartesian, Vert>& -getvertexPositionField(Field,Dim, UniformCartesian,Vert>& ); - -//Vertex-vertex grid spacing of indexed cell: -Vektor getDeltaVertex(NDIndex&); - -// Field of vertex-vertex ,grid spacings of all cells: -Field,Dim,UniformCartesian,Cell>& -getDeltaVertexField (Field, Dim, UniformCartesian,Cell>& ); - -// Cell-cell grid spacing of indexed vertex: -Vektor getDeltaCell(NDIndex&); - -// Field of cell-cell grid spacingsof all vertices: -Field, Dim,UniformCar,tesian, Vert>& -getDeltaCellField(Field,Dim, UniformCartesian,Vert>& ); - -// Array of surface normals to cells adjoining indexed cell: -Vektor* getSurfaceNormals(NDIndex&); - -// Array of {pointers to} Fields of surface normals to all cells: -void getSurfaceNormalFields(Field,Dim, UniformCartesian,Cell>** ); - -// Similar functions, but specify the surface normal to a single face, using -// the following numbering convention: 0 means low face of 1st dim, 1 means -// high face of 1st dim, 2 means low face of 2nd dim, 3 means high face of 2nd dim, and so on: , - -Vektor getSurfaceNormal(NDIndex&, unsigned); - -Field,Dim,UniformCartesian,Cell>& getSurfaceNormalField( -Field,Dim, UniformCartesian,Cell>&, unsigned); -\end{smallcode} - - -\subsection{UniformCartesian Constructors} -Aside from the default constructor, which you should not be used if you, don't know what it's there for, there are three categories of \texttt{UniformCartesian} constructors. -All require an argument or set of \texttt{Dim} arguments specifying the number of mesh nodes along each dimension. The one-argument form takes an \texttt{NDIndex\&} -to specify this: the \texttt{length()} value of each \texttt{Index} and the \texttt{NDIndex} represents the number of mesh nodes (vertices); the multi-argument forms take -\texttt{Dim Index\&}'s (these are implemented only up to Dim = 3). {\it Warning:} be sure to use zero-based, unit-stride \texttt{NDIndex Index} objects; \texttt{UniformCartesian} -should eventually work for other cases, but for now the implementation doesn't account for non-zero base or non-unit stride for the index space spanning the mesh nodes/cells. -The first and simplest category of constructors has only the size arguments; here are examples of the one-argument and multi-argument case: -\begin{smallcode} -Index I {5} , J {5} , K (5 ); -NDIndex<3> ndi; -ndi[0] = I; ndi[1] = J; ndi[2] = K; - -UniformCartesian<3> umesh1(ndi); -UniformCartesian<3> umesh2(I,J,K); -\end{smallcode} - -Both of these \texttt{UniformCartesian} objects will have default mesh spacings of 1.0 in all directions and an origin (location of first vertex) at (0.0, 0.0, 0.0). -The second category adds specification of the mesh spacings. You create an array of type MFLOAT and pass it to the constructor: - -\begin{smallcode} -double spacings[3] = {1. 0, 1,.0, 2.0}; //double because default of MFLOAT -UniformCartesian<3> umesh3{ndi, spacings); -\end{smallcode} - -The \texttt{umesh3} object has mesh spacings $\Delta_x= 1.0,~\Delta_y=1.0, \text{ and }\Delta_z = 2.0$. We used type \texttt{double} for the array of spacings because we used the -default \texttt{MFLOAT} template parameter value of \texttt{double} when instantiating \texttt{umesh3}. If we had specified something else, \texttt{UniformCartesian<3,float>}, we -would have had to specify \texttt{float} as the type of the spacings array. The \texttt{umesh3} object has a default origin (location of first vertex) at (0:0, 0.0, 0.0). - -The third category adds specification of the origin (location of the first vertex). You create a \texttt{Vektor} and pass it as the last constructor argument: - -\begin{smallcode} -// Defining spacings and origin, use double because it's default .of MFLOAT: -double spacings[3] = {1.0,1.0,2.0}; -Vektor origin; -origin(0) = 5.0; origin(1) = 6.0; origin(2)= 7.0; -UniformCartesian<3> umesh4(ndi, spacings, origin); -\end{smallcode} -The umesh4 object has mesh spacings $\Delta_x= 1.0,~\Delta_y=1.0, \text{ and }\Delta_z = 2.0$ and origin at (5.0,6.0,7.0). - - - -\subsection{\texttt{UniformCartesian} Member Functions and Member Data} -\texttt{UniformCartesian} Member Data for Sizes and Spacings. There are several-public data members representing mesh size and spacing information: -\begin{smallcode} -unsigned gridSizes[Dim] ; -\end{smallcode} -An array containing the mesh sizes-numbers of vertices along each dimension. -\begin{smallcode} -typedef Cell DefaultCentering ; -\end{smallcode} -Used by \texttt{Field} and other classes which are parameterized on \texttt{Mesh} and centering classes and require consistent defaults for both. -The general user probably need never use this member. -\begin{smallcode} -Vektor Dvc[1<,Dim>* VertSpacings; -BareField,Dim>* CellSpacings; -\end{smallcode} -If you invoke the \texttt{storeSpacingFields()} function, \texttt{UniformMesh} will allocate two \texttt{BareField}'s and fill them with vertex-vertex and cell-cell mesh spacing values -(stored as vectors whose components are the spacings along each dimension of the cell or shifted cell). These pointers provide public access to them. -The general user can always use the functions like \texttt{getDeltaVertexField ()} to put spacing values into his own \texttt{Field} objects, and this may be the best way to do this in general. -Certain predefined \ippl global functions, such as the \texttt{Div()} differential operators, might rely on having these BareField's internally available from the mesh object associated with -the \texttt{Field}'s on which they operator. -Note: These internal \texttt{BareField}'s are redundant for \texttt{UniformCartesian} in a couple of ways. First, the mesh spacing information is the same everywhere in the \texttt{Mesh}, -and the vertex-vertex spacing is the same as the cell-cell spacing. The operators like \texttt{Div()} don't need \texttt{BareField}'s of spacings for the uniform Cartesian case; and they don't, -in fact, use them or check if they exist. Both of these redundancies are removed in the nonuniform Cartesian case, however. In this case, storing this information in the internal -\texttt{BareField}'s in the Cartesian objects is essential for functions like \texttt{Div(}) -they return errors if \texttt{hasSpacingFields} is false. - - -\subsection{\texttt{UniformCartesian} Set/Accessor Functions for Member Data} - -\begin{smallcode} -void storeSpacingFields ( ); -void storeSpacingFields(e_dim_tag pI, int vnodes=-I) -void storeSpacingFields(e_dim_tag pl, e_dim_tag p2, int vnodes=-1); -void storeSpacingFields(e_dim_tag pI, e_dim_tag p2, e_dim_tag p3, int vnodes=-1); -void storeSpacingFields(e_dim_tag *p, int vrlodes=-1); -\end{smallcode} -The \texttt{UniformCartesian} class will optionally create internal \texttt{BareField}'s of appropriate sizes and fill them with vertex-vertex arid cell-cell spacing values. -You access these \texttt{BareField}'s via the \texttt{VertSpacings} and \texttt{CellSpacings} pointers described above. -The \texttt{storeSpacingFields()} functions make this happen. Because they are constructing \texttt{BareField}'s, they provide prototypes based on those for \texttt{FieldLayout} -so you can control the serial/parallel layout of the \texttt{BareField}'s, you specify which dimensions are serial or parallel using lists or an array of \texttt{e\_dim\_tag} -values (\texttt{SERIAL} or \texttt{PARALLEL}). If you use the first prototype, with no arguments, you will get the default \texttt{FieldLayout} for the internal \texttt{BareField}'s: -parallel for all dimensions. - -\begin{smallcode} -Vektor get_origin(); -\end{smallcode} -Returns the value of the origin of the mesh (position in space of the lowest mesh vertex). - -\begin{smallcode} -MFLOAT get_meshSpacing(int d); -\end{smallcode} -Returns the mesh spacing value for the specified direction. There is only one value for uniform spacing; thus the return type \texttt{MFLOAT}. -\begin{smallcode} -MFLOAT get_volume() ; -\end{smallcode} -Returns the volume of a cell, which is the same everywhere in a uniform Cartesian mesh. - - -\subsection{Other UniformCartesian Methods} -Most of the public member functions in \texttt{UniformCartesian} are designed to return some typical kinds of geometrical information about the \texttt{Mesh} that a user (programmer or class) might want. -Where the information or input parameters are more complex than single \texttt{MFLOAT} values, the function return values or arguments are typically \ippl classes such as \texttt{Field}. -The set of functions evolved from general discussions among application programmers of, what is expected of a mesh, and we will continue to evolve its design iteratively as new applications demand new \texttt{Mesh} -information. Many of these functions use \texttt{NDIndex} to index mesh vertices and cells. \texttt{NDIndex} has no intrinsic awareness of centering, but can clearly represent index values specifying -mesh node or cell positions. The user must keep in mind that cell 0 along a dimension is between node 0 and node 1, and that there are one fewer cells than vertices. -\begin{smallcode} -MFLOAT getCellVolume(NDIndex&); -\end{smallcode} -Volume of single cell indexed by input \texttt{NDIndex}. The argument must describe a single element. That is, the range of every \texttt{Index} in the \texttt{NDIndex} must be 1. The \texttt{getCellVolume()} function -returns an error otherwise. - -\begin{smallcode} -Field, Cell>& -getCellVolumeField (Field,Cell>&); -\end{smallcode} -Field of volumes of all cells. This function basically assigns every element of the cell-centered Field to the return value of \texttt{getCellVolume ( )}. For a \texttt{UniformCartesian} mesh, this is obviously redundant, -but the function is here for interface compatibility with \texttt{Cartesian} (which represents a nonuniform Cartesian mesh, for which this is not redundant). -If you are only using \texttt{UniformCartesian} mesh objects, you should just use the single cell-volume value retuned by \texttt{getCellVolume}; this will combine with other\texttt{ Field}'s of -values in your code the same way any scalar value will do. -\begin{smallcode} -MFLOAT getVertRangeVolume(NDIndex&); -\end{smallcode} -Volume of range of cells bounded by vertices specified by input \texttt{NDIndex}, which in this context will generally have a range greater than one in at least one dimension. The vertices represented by the lowest and -highest index value set contained in the \texttt{NDIndex} mark the corners of a rectangular solid region; this function returns the volume of that region. -\begin{smallcode} -MFLOAT getCellRangevolume(NDIndex&); -\end{smallcode} -Volume of range of cells spanned by input \texttt{NDIndex} (index of cells). This is like \texttt{getVertRangeVolume( )} , except that the corners of the rectangular solid are -cell-center positions rather than vertex positions. - -\begin{smallcode} -NDIndex& getNearestvertex(Vektbr&); -\end{smallcode} -Nearest vertex index to a point in space (x,y,z). - -\begin{smallcode} -NDIndex& getVertexBelow(Vektor&); -\end{smallcode} -Nearest vertex inpex with all vertex coordinates below a point in space (x,y,z). - -\begin{smallcode} -NDIndex& getCellContaining(Vektor&) ; -\end{smallcode} -\texttt{NDIndex} for the mesh cell containing the point (x,y,z). Use this, for example, to index a corresponding element in a cell-centered \texttt{Field}. - -\begin{smallcode} -Vektor getVertexposition(NDIndex&) ; -\end{smallcode} -(x,y,z) coordinates of the \texttt{Mesh} vertex indexed by the \texttt{NDIndex}, which just have a range of one in all dimensions (that is, it must index a single point in index space). - -\begin{smallcode} -Field, Dim, UniformCartesian,Vert>& -getVertexPositionField(Field, Dim, UniformCartesian,Vert>& ); -\end{smallcode} -Fills a vertex-centeredField with the (x,y,z) coordinates of all mesh vertices. - -\begin{smallcode} -Vektor getDeltaVertex (NDIndex&); -\end{smallcode} -Vertex-vertex grid spacing $(\Delta_x, \Delta_y, \Delta_z)$ of the cell indexed by the NDIndex. - -\begin{smallcode} -Field, Dim, UniformCartesian,Cell>& -getDeltaVertexField(Field,Dim, UniformCartesiap,Cell>& ); -\end{smallcode} -Fills a cell-centered Field with the vertex-vertex grid spacings $(\Delta_x, \Delta_y, \Delta_z)$ of all cells. - -\begin{smallcode} -Vektor getDeltaCell(NDIndex&) ; -\end{smallcode} -Cell-cell grid spacing $(\Delta_x, \Delta_y, \Delta_z)$ of indexed cell vertex. That is, this returns the distance between the cell centers on either side of the vertex position indexed by the \texttt{NDIndex} for each dimension. - -\begin{smallcode} -Field, Dim,uniforrnCartesian, Vert>& -getDeltaCellField(Field,Dim, UniformCartesian,Vert>& ) ; -\end{smallcode} -Fills a vertex-centered Field with,the cell-cell grid spacings $(\Delta_x, \Delta_y, \Delta_z)$ around all vertices. - -\begin{smallcode} -Vektor* getSurfaceNormals(NDIndex&) ; -\end{smallcode} -Array of surface normals to cells adjoining indexed cell. This is trivial for a Cartesian mesh, and is the same for every cell even in the nonuniform spacing cases represented by \texttt{Cartesian}. -Future implementations in non-cartesian mesh classes would be more complicated. - -\begin{smallcode} -void getSurfaceNormalFields(Field,Dim, UniformCartesian,Cell>**); -\end{smallcode} -Fills the Field's pointed to by the array with of surface normals to all cells. Again, this is trivial for a cartesian mesh, and the values are the same everywhere; but future implementations in non-cartesian meshes would be more complicated. - -\begin{smallcode} -Vektor getSurfaceNormal(NDIndex&, unsigned) ; - -Field,Dim, UniformCartesian,Cell>& -getSurfaceNormalField(Field,Dim, - UniformCartesian,Cell>&, unsigned) ; -\end{smallcode} -Similar functions to \texttt{getSurfaceNormals()} and \texttt{getSurfaceNormalFields()}, but specify the surface normal to a single face, using the following numbering convention: -0 means low face of 1st dimension, 1 means high face of 1st dimension, 2 means low face of 2nd dimension, 3 means high face of 2nd dimension; and so on. - -\section{\texttt{Cartesian} Class} -\label{app:cartclass} -The \texttt{Cartesian} class represents the abstraction of a nonuniform-spacing Cartesian mesh discretizing a rectilinear region of space. The mesh spacings vary cell-by-cell along each dimension. As much as possible, the -\texttt{Cartesian} interface is identical to the \texttt{UniformCartesian} interface described in Section xxx. It has the same mechanisms for returning various kinds of geometrical information from the \texttt{Mesh}: -cell-cell and vertex-vertex spacings, nearest mesh vertex positions to a given point in space, and others. -Like \texttt{UniformCartesian, Cartesian} is parameterized on dimensionality \texttt{Dim}, and another parameter \texttt{MFLOAT} which specifies the elemental type to use in storing and returning mesh geometrical -information such as spacings and position coordinates. Generally, this should be a floating-point type, and it defaults to \texttt{double}. Vector values are represented using \texttt{Vektor}. -This chapter only discusses the places where the \texttt{Cartesian} interface differs from the \texttt{UniformCartesian} interface. Refer to Section xxx for all other information about \texttt{Cartesian}; substitute "\texttt{Cartesian}" for "\texttt{UniformCartesian}" in places such as the \texttt{Mesh} parameter for \texttt{Field} arguments to the member functions. To help with this, we show the entire \texttt{Cartesian} public definition in the next section; -in the subsequent sections discussing the member functions and data, we discuss only the cases that differ from \texttt{UniformCartesian}. - -\subsection{\texttt{Cartesian} Definition (Public Interface)} - Enumeration used for specifying mesh boundary conditions. Mesh BC are used for things like figuring out how to return the mesh spacing for a cell -beyond the edge of the physical mesh, as might arise in stencil operations lion Field's on the mesh. - -\begin{smallcode} - -enum MeshBC_E { Reflective, Periodic, None }; -char* MeshBC_E_Names"[3] = {"Reflective", "Periodic ", "None"} ; - -template < unsigned Dim, class MFLOAT=double> -class Cartesian : public Mesh -{ -public: -// Public member data: -unsigned gridSizes[Dim]; // Sizes (number of vertices) -typedef Cell DefaultCentering; //Default cemtering (used by Field,etc.) -Vektor Dvc[1<, Dim>* VertSpacings; -BareField, Dim>* CellSpacings; - -// Public member functions: -// Constructors -Cartesian() {} ; // Default constructor - -// Non-default constructors -Cartesian (NDIndex& ndi); -Cartesian(Index& I); -Cartesian(Index& I; Index& J); -Cartesian(Ihdex& I, Index& J, Index& K); - -// These also take a MFLOAT** specifying the mesh spacings: -Cartesian(NDIndex& ndi, MFLOAT** delX); -Cartesian(Index& I, MFLOAT** delX); -Cartesian(Index& I, Index& J, MFLOAT**deIX); -Cartesian(Index& I, Index& J, Index& K, MFLOAT** deIX); - -// These further take a Vektor& specifying the origin: -Cartesian(NDIndex& ndi, MFLOAT** deIX,Vektor& orig); -Cartesian(Index& I, MFLOAT** delX, Vektor orig); -Cartesian (Index& I, Index& J, MFLOAT* * delX, Vektor& orig) ; -Cartesian(Index& I, Index& J, Index& K, MFLOAT** delX, Vektor& orig); - -// These further take a MeshBC_E array specifying mesh boundary conditions, -Cartesian(NDIndex& ndi, MFLOAT** delX, Vektor& arig, MeshBC_E* mbc); -Cartesian (Index& I, MFLOAT* * deIX, Vektor arig, MeshBC_E* mbc); -Cartesian(Index& I, Iridex& J, MFLOAT** delX, Vektor& orig, MeshBC_E* mbc); -Cartesian(Index& I, Index& J, Index& K, MFLOAT** delX, Vektor& arig, MeshBC_E* mbc); --Cartesian () { }; -\end{smallcode} - -Set functions for member data: create\texttt{ BareField}'s of vertex and cell spacings; allow for specifying layouts via the \texttt{FieldLayaut e\_dim\_tag} and vnodes parameters -(these get passed by constructing the \texttt{FieldLayaut} and used to, construct the \texttt{BareField}' s) . - -\begin{smallcode} - -void stareSpacingFields(); // Default will have default layaut - -// Special cases far 1-3 dimensians, ala FieldLayaut ctars: -void stareSpacingFields(e_dim_tag p1; int vnodes=-1); -void stareSpacingFields (e_dim_tag pl, e_dim_tag p2, int vnodes=-1); -void stareSpacingFields(e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, int vnodes=-1); - -// Next we have ane far arbitrary dimensian,a la FieldLayaut ctor: -// All the others call this one internally: -void storeSpacingFields(e_dim_tag *p, int vnodes=-1); - -// Accessar functians far member data: -// Get the arigin of mesh vertex pasitians: -Vektor get_orgin(); - -// Get the spacings of mesh vertex positions along specified direction: -MFLOAT* get_meshSpacing(int d); - -// Get mesh boundary conditions: -MeshBC_E get_MeshBC(unsigned face); // One face at a time -MeshBC_E* get_MeshBC () ; // All faces at ance - -// Formatted output of Cartesian object: -void print(ostream&); - -// Stream formatted output of Cartesian abject: -friend ostream& operato<<(ostream&, const Cartesian&); - - -// Other Cartesian methods - -// Volume of a single cell indexed by input NDIndex -MFLOAT getCellVolume(NDIndex&); - -// Field of Volumesof of all cells -Field, Cell>& getCellVolumeField( -Field,Cell>&); - -// Volume of range of cells bounded by verticies specified by input NDIndex: -MFLOAT getVertRangeVolume (NDIndex&); - -// Volume of range of cells spanned by input NDIndex (index of cells) -MFLOAT getCellRangeVolume(NDIndex&); - -// Nearest vertex index to, (x,y,z) -NDIndex& getNearestVertex (Vektor&); - -// Nearest vertex index with all vertex coordinates below (x,y, z) -NDIndex& getVertexBelow(Vektor&); - -// NDIndex for cell in cell-ctrd Field containing the point (x,y, z) -NDIndex& getCellContaining(Vektor&); - -// (x,y,z) coordinates of indexed vertex -Vektor getVertexPosition(NDIndex&); - -// Field of (x,y,z) coordinates of all vertices: -Field ,Dim, Cartesian,Vert>& getVertexPositionField( -Field, Dim, Cartesian,Vert>&); - -// Vertex-vertex grid spacing of indexed vertex -Vektor getDeltaVertex(NDIndex&); - -// Field of vertex-vertex grid spacings of all vertices -Field ,Dim, Cartesian , Cel 1>& getDeltaVertexField( -Field, Dim, Cartesian,Cell>& ); - -// Cell-cell grid spacing of indexed cell: -Vektor getDeltaCell(NDIndex&); - -// Field of cell-cell grid spacings of all vertices: -Field, Dim, Cartesian,Vert>& getDeltaCellField( -Field,Dim, Cartesian,Vert>& ); - -// Array of surface normals to cells adjoining indexed cell: -Vektor* getSurfaceNormals(NDIndex&); - -// Array of (pointers to) Fields of surface normals to all cells: -void getSurfaceNormalFields(Field,Dim, Cartesian,Cell>** ); -\end{smallcode} - Similar functions, but specify the surface normal to a single face, using the following numbering convention: 0 means low face of 1st dim, 1 means - high face of 1st dim, 2. means low face of 2nd dim, 3 means high face of 2nd dim, and so on: - \begin{smallcode} -Vektor getSurfaceNormal(NDIndex&, unsigned); -Field,Dim, Cartesian , Cel 1>& getSurfaceNormalField( -Field,Dim, Cartesian,Cell>&, unsigned); -} ; -\end{smallcode} - - - -\subsection{Cartesian Constructors} -Aside from the default constructor, which you should not be using if you don't know what it's there for, there are four categories of \texttt{Cartesian} constructors. -The first three are the same as for \texttt{UniformCartesian} (see Section xxx), except that specifying mesh spacings requires more than just a single \texttt{MFLOAT} value for \texttt{Cartesian( )}. -You must pass in an array of arrays of \texttt{MFLOAT} values \texttt{(MFLOA T * * )} one array for each dimension, having size given by the number of cells along that dimension. -The new fourth constructor category adds specification of mesh-spacing boundary conditions. -You create an array of type \texttt{MeshBC\_E}, an enumeration having values \texttt{\{Reflective,Periodic,None\}}. This tells \texttt{Cartesian} how to provide geometry information such as -mesh spacings beyond the physical edge of the mesh, as might arise in implementing differential operators using finite differencing of \texttt{Field}'s centered on the mesh. There are -basically only two ways to do this: wrap around periodically to mesh spacing values inside the physical mesh, or reflect the mesh spacing values across the boundary. The user should -avoid specifying \texttt{None} for mesh boundary-condition types. The following code example illustrates using this fourth constructor category for \texttt{Cartesian()}, and how to set up -mesh spacing and boundary condition specifiers: -\begin{smallcode} - -const unsigned Dim = 3U; -unigned nx=5, ny=5, nz=5; -Index I(nx),J(nz) ,K(nz); - -NDIndex ndi; -ndi[0] = I; ndi[1] = J; ndi[2] =K; - -// Defining spacings and origin, use double because it's default of MFLOAT: -double* spacings[Dim]; -spacings[0] = new double [nx] ; -spacings[1] = new double [ny] ; -spacings[2] = new double [nz]; - -int vert; -for (vert=0; vert < nx; vert++) (delX[0]) [vert] = 1.0 + vert*1.0; -for (vert=0; vert < ny; vert++) (delX[1]) [vert] = 2.0 + vert*2.0; -for (vert=0; vert < nz; vert++) (delX[2]) [vert] = 3.0 + vert*3.0; - -Vektor origin; -origin(0) = 5.0; -origin(1) = 6.0; -origin(2) = 7.0' - -MeshBC_E meshbc[2*Dim]; - -for (unsigned face=0; face < (2*Dim); face++) - meshbc[face] =Reflective; - -Cartesian cmesh(ndi, ,spacings, origin, meshbc); - -\end{smallcode} -The \texttt{cmesh} object has mesh spacings $\Delta_x = {1.,2., \dots}, \Delta_y = {2.,3., \dots} \text{ and } \Delta_z = {3.,6., \dots}$ the origin is at (5.0, 6.0, 7.0) and reflective mesh boundary conditions on all faces. -The other three cases of \texttt{Cartesian ()} are like this but with fewer parameters. As in \texttt{UniformCartesian}, if the origin is unspecified it defaults to (0,0,0), -if the mesh spacings are unspecified they default to uniform values of 1.0 for all cells along all axes. The mesh boundary conditions default to \texttt{Reflective} on all faces. - -\subsection{\texttt{Cartesian} Member Functions and Member Data} -\subsubsection{ \texttt{Cartesian} Member Data for Sizes and Spacings} -The types are all the same as for \texttt{UniformCartesian} (See Appendix \ref{app:unifcart} ). The values of and interpretation of the \texttt{Dvc} data member are completely different; functions such as \texttt{Div()} which -use this information to implement differential operators must account properly for the variation of mesh spacing values and the difference between cell-cell and vertex-vertex spacings in the nonuniform case. -For \texttt{UniformCartesian}, the single \texttt{Dvc} array could hold all the necessary information; for \texttt{Cartesian}, a slightly different \texttt{Dvc} coordinates with VertSpacings and CellSpacings, -which must exist before the user can invoke operators such as \texttt{Div()}. - -\subsubsection{\texttt{Cartesian} Set/Accessor Functions for Member Data} -Except for the return value of\texttt{ get\_meshSpacing()} , and the new functions \texttt{get\_MeshBC()} ,the interfaces and descriptionsare all the same as for\\ \texttt{UniformCartesian}. (See Appendix \ref{app:unifcart}). -\begin{smallcode} -MFLOAT* get_meshSpacing(int d); -\end{smallcode} -Returns the array of mesh-spacing values along the specified direction. The number of elements in the arrays the number of cells in the mesh along that dimension. -\begin{smallcode} -MeshBC_Eget_MeshBC (uns,igned face) ; -\end{smallcode} -Returns the value of the mesh boundary-condition specifier for the requested face of the mesh. The numbering convention for faces is: 0 means low face of 1st dimension, 1 means high face of 1 st dimension, -2 means low face of 2nd dimension, 3 means high face of 2nd dimension, and so on. -\begin{smallcode} -MeshBC_E* get_MeshBC(); -\end{smallcode} -Returns the array of values of mesh boundary-condition specifiers for all faces of the \texttt{Mesh}, following the numbering convention described in the description of the one-argument prototype -of this function above. The number of elements in the array is two times the number of dimensions. - -\subsubsection{Other Cartesian Methods} -As for \texttt{UniformCartesian}, most of the public member functions in \texttt{Cartesian} are designed to return some typical kinds of geometrical information about the mesh that a user (programmer or class) -might want. So far, all of the member functions mirror \texttt{UniformCartesian} exactly, except for the occasional replacement of \\ "\texttt{Cartesian}" for -"\texttt{UniformCartesian}" in mesh template-parameters for \texttt{Field} arguments. - - - - - - - - - diff --git a/manual/ippl_particles.tex b/manual/ippl_particles.tex deleted file mode 100644 index 0e144747c..000000000 --- a/manual/ippl_particles.tex +++ /dev/null @@ -1,301 +0,0 @@ -\chapter{Particles} -\label{sec:particles} -This section describes the \ippl framework classes which provide the capability to performing particle-based simulations. We first describe how to design and instantiate \texttt{Particle} classes customized to the needs of a specific application, and then discuss the possible operations and expressions in which a particle object may be employed and end with an ready to use example. - -\section{Basic \texttt{Particle} Object Characteristics} - -The \ippl framework treats \texttt{Particle} classes as containers which store the characteristic data for \texttt{N} individual particles. Each particle has several attributes, such as position, mass, velocity, etc. Looked at in another way, \texttt{Particle} classes store several attribute containers, where each attribute container holds the value of that attribute for all \texttt{N} particles. \texttt{Particle} objects in \ippl may be thought of as shown in the following diagram: ... - -There are two particle attributes predefined, namely R (position) and ID a global unique identifier. - -The data type of each attribute, the number of attributes, and the names for these attributes are completely customizable, and are specified in the manner described in the following sections. Any number of different \texttt{Particle} classes may be defined and used within a given simulation. Also, the \texttt{Particle} objects may interact with \ippl \texttt{Field} objects or may be used independently. In addition to the attributes, each \texttt{Particle} object uses a specific layout mechanism, which describes the data of the individual particles is spread across the processors in a parallel environment. The \ippl framework provides several different \texttt{Particle} layout classes, any of which may be selected to partition the particle data among processors. The choice of layout depends on the intended use of the \texttt{Particle} object, as discussed later. Once defined and instantiated, \texttt{Particle} objects in the \ippl framework may be used in many ways, including: -\begin{itemize} - \item Operations involving all the particles within a \texttt{Particle} object may be specified using simple expressions, in a manner very similar to that used for \texttt{Field} objects. These expressions may involve any of the attributes of the particles as well as other scalar data, and they may use not only the standard mathematical operators +, -, *, /, etc., but also standard mathematical functions such a s cos ( ) , exp ( ) , mod ( ) , etc. - \item Alternatively, you may set up explicit loops that perform operations involving the attributes of a single particle or a subset of all the particles. - \item \texttt{Particle}s may be created or destroyed during a simulation. - \item \texttt{Particle}-to-\texttt{Field} and \texttt{Field}-to-\texttt{Particle} operations may be performed (e.g., a particular \texttt{Particle} attribute may be deposited onto a specified \texttt{Field} using a chosen interpolation method). -\end{itemize} - -\section{Defining a User-Specified \texttt{Particle} Class} - -There is no specific class within the \ippl framework called \texttt{Particle}. Rather, the first step in deploying particles within a \ippl application is to define a user-specified \texttt{Particle} class, which contains the attributes required for each particle, as well as any, specific methods or data the user may need. To do this, the \texttt{ParticleBase} and \texttt{ParticleAttrib} classes are used, along with a selected subclass of the \texttt{ParticleLayout} class. The steps to follow in creating a new \texttt{Particle} class are: -\begin{itemize} - \item Based on the type of interactions which the particles have with each other and with external objects such as a \texttt{Field}, select a method of distributing the particles among the nodes in a parallel machine. - \item Next, decide what attributes each particle should possess. - \item Third, create a subclass of \texttt{ParticleBase} which includes these attributes (specified as instances of the \texttt{ParticleAttrib} class template). - \item Finally, instantiate this user-defined subclass of \texttt{ParticleBase} and create and initialize storage for the particles which are to be maintained by this object. -\end{itemize} - -The following sections describe in more detail how to accomplish these steps. - -\subsection{Selecting a Layout: \texttt{ParticleLayout} and Derived Classes} - -When used in a parallel environment, the \ippl framework partitions the particles in a \texttt{Particle} container among the separate processors and includes tools to spread the work of computing and the results of expressions involving \texttt{Particle} attributes among the processing nodes. There are, however, different ways in which particles may be distributed among the processors, and the method which should be used depends upon how the particles in a \texttt{Particle} -object will interact with each other and with \texttt{Field} objects (if at all). The \ippl framework includes different \texttt{Particle} layout mechanisms, which are all derived from the \texttt{ParticleLayout} class. Each \texttt{Particle} object needs its own layout object; that is, you cannot create a layout object and give it to more than one \texttt{Particle} object. The methods typically used to determine how to assign particles to particular nodes are based on analysis of the -position (\texttt{R} attribute) of each particle. Thus, \texttt{ParticleLayout} and its derived classes have two template parameters: the type and the dimensionality of the particle position attribute (this particle position attribute is discussed in more detail later). The following sections describe the particle layout mechanisms currently available in the \ippl framework. - -\subsection{The \texttt{{\color{red} ParticleUniformLayout} Class}} -{\color{red} can be removed} - -\subsection{The \texttt{ParticleSpatialLayout} Class} - -\texttt{ParticleSpatialLayout}, in contrast to \texttt{ParticleUniformLayout}, assigns particles to nodes based upon their spatial location relative to a \texttt{FieldLayout}. It is useful when the particles will be interacting with other particles in their neighborhood or with a \texttt{Field} object. \texttt{ParticleSpatialLayout} will keep a particle on the same node as that which contains the section of the \texttt{Field} in which the particle is located. If the particle moves to a new position, this layout will reassign it to a new node when necessary. This will maintain locality between the particles and any \texttt{Field} distributed using this \texttt{FieldLayout}. Further more it will help keep particles which are spatially close to each other local to the same processor as well. As with all the layout classes, \texttt{ParticleSpatialLayout} requires the type and dimensionality of the particle position attribute as template parameters. The constructor for \texttt{ParticleSpatialLayout} takes one argument: a pointer to a \texttt{FieldLayout} object that tells the \texttt{ParticleSpatialLayout} how the \texttt{Field} is allocated among the parallel processors, so that the particles may be maintained local to this \texttt{Field}. Note that you do not, need to create a \texttt{Field} instance itself, you only need to give \texttt{ParticleSpatialLayout} a \texttt{FieldLayout} object. An example of creating an instance of this class is as follows: -\begin{smallcode} -FieldLayout<3> myfieldlayout(Index(l6), Index(16), Index(32)); -ParticleSpatialLayout myparticlelayout(&myfieldlayout); -\end{smallcode} - - -Note that the dimensionality of the \texttt{FieldLayout} and the \texttt{ParticleSpatialLayout} (in this example, 3) must be the same. You may also create a \texttt{ParticleSpatialLayout} instance without providing a \texttt{FieldLayout}. In this case, particles will remain on the node on which they were created. If at some future time you wish to provide a \texttt{FieldLayout} object to tell the \texttt{ParticleSpatialLayout} where to place the particles, you may do so using the \texttt{setFieldLayout} (\texttt{FieldLayout*}) method of \texttt{ParticleSpatialLayout}. This is useful when reading particles in from an external source and the size of the spatial domain containing the particles is not known until all the particles have been read. The following example demonstrates the use of the capability: -\begin{smallcode} -ParticleSpatiaILayout myparticleLayout; -// calculate the size of the domain required to contain all the particles -// create a new FieldLayout object based on these calculations -FieldLayout<3> myfieldlayout(Index(minx, maxx), Index (miny, maxy), - Index(minz,maxz); -myparticlelayout.setFieldLayout(&myfieldlayout); -\end{smallcode} - -\texttt{ParticleSpatialLayout} also provides functionality to maintain cached ghost particles from neighboring nodes which might be required for particle - particle interaction. A caching policy can be defined using the fourth template parameter of \texttt{ParticleSpatialLayout}: -\begin{smallcode} -typedef UniformCartesian Mesh_t; -typedef ParticleSpatialLayout > playout_t; -\end{smallcode} -The available chaching policies are: \texttt{NoParticleCachingPolicy},\texttt{BoxParticleCachingPolicy} and \texttt{CellParticleCachingPolicy}. With \texttt{NoParticleCachingPolicy} there is no caching whatsoever. \texttt{BoxParticleCachingPolicy} extends the interface of \texttt{ParticleSpatialLayout} by two functions \texttt{void setCacheDimension(int d, T length)} and \texttt{void setAllCacheDimensions(T length)} which are used to set the size of the cached region around the local domain in units of space. \texttt{CellParticleCachingPolicy} extends the interface of \texttt{ParticleSpatialLayout} by two functions \texttt{void setCacheCellRange(int d, int length)} and \texttt{void setCacheCellRanges(int d, int length)} which are used to set the size of the cached region around the local domain in units of grid cells of the mesh. \texttt{BoxParticleCachingPolicy} is the default policy. - -The caching can be enabled or disabled by calling the \texttt{enableCaching()} or \texttt{disableCaching()} member functions of \texttt{ParticleSpatialLayout}. Caching is disabled by default. - - -\subsection{Selecting Particle Attributes: The \texttt{ParticleAttrib} \\Class} - -\texttt{ParticleAttrib} is a class template that represents a single attribute of the particles in a \texttt{Particle} object. Each \texttt{ParticleAttrib} contains the data for that attribute for all the particles. Within a user-defined \texttt{Particle} class, you declare an instance of \texttt{ParticleAttrib} for each attribute the particles will possess and assigns to it an arbitrary name. \texttt{ParticleAttrib} requires one template parameter, the type of the data for the attribute. As an example, the statement: -\begin{smallcode} -ParticleAttrib density; -\end{smallcode} - -declares an instance of \texttt{ParticleAttrib} named 'density', which will store a quantity of type double for all the particles of the \texttt{Particle} class that contains this data member. - -\subsection{Specifying a User-Defined \texttt{Particle} Class: \\The \texttt{ParticleBase} Class} - -\texttt{ParticleBase} is the class that all user-defined \texttt{Particle} classes must specify as their base class. It stores the list of attributes for the particles (which are maintained as instances of \texttt{ParticleAttrib}) and a selected parallel layout mechanism. In addition to providing all the capabilities for performing operations on the particles and their attributes, \texttt{ParticleBase} also defines two specific attributes which all user-defined \texttt{Particle} classes inherit: -\begin{smallcode} -ParticleAttrib> R; -ParticleAttrib ID; -\end{smallcode} - - -The first attribute, \texttt{R}, represents the position of each particle. Each position is stored as a \texttt{Vektor}, which is a \ippl data type representing a dim-dimensional vector with elements of type \texttt{T}. The second attribute, \texttt{ID}, stores a unique unsigned integer value for each particle. The values are not guaranteed to be in any particular order, but they are guaranteed to be unique for each particle. \texttt{ParticleBase} has one template parameter, the layout class to be used to assign particles -to processors (e.g., \texttt{ParticleSpatialLayout}). The data type and dimensionality of the particle position attribute (\texttt{R}) will be the same as those used to create the specific \texttt{ParticleLayout} derived class. Each \texttt{ParticleBase} contains one instance of the chosen layout class. There are two constructors for \texttt{ParticleBase}: a default constructor that creates a new instance of the layout class using the layout's default constructor, and a constructor which takes a pointer to an instance of the -layout class. The second version of the \texttt{ParticleBase} constructor is useful when the desired layout class requires arguments to its constructor (e.g., \texttt{ParticleSpatialLayout}, which may be give in a \texttt{FieldLayout} pointer). - -Using \texttt{ParticleBase}, \texttt{ParticleAttrib}, and a selected class derived from \texttt{ParticleLayout,} you can create a user-defined \texttt{Particle} class using the following code template: \\ -\clearpage -\begin{codeln} -class Bunch : public ParticleBase< ParticleSpatiaILayout > -{ -public: - // Attributes for this particle class (besides position and ID). - ParticleAttrib qm; // q/m ratio - ParticleAttribs Vektor > vel; // velocity - - // constructor - Bunch(Layout\_t *L) : ParticleBase(L) { - addAttribute(qm); - addAttribute(vel); - } -}; -\end{codeln} - -Let us describe this example in detail by discussing the important lines in the order of use. - -Line 1: You may select whatever name is appropriate for the specialized \texttt{Particle} class, but it must be derived from \texttt{ParticleBase}. - -In this case, we explicitly specify the type of layout to use (\texttt{ParticleSpatialLayout}), with particle position attribute type and dimensionality template parameters of double and 3, respectively. Alternatively, \texttt{Bunch} may have been declared as a class template itself and may have passed on the layout template parameters to \texttt{ParticleBase}. In that case, the first line would instead look like -\begin{smallcode} -template -class Bunch : public ParticleBase -\end{smallcode} - -Lines 5-6: Here is where the attributes for the particles in the \texttt{Particle} object are declared. They may be given any name other than \texttt{R} or \texttt{ID}. Instead of stating the type and dimensionality of this attribute specifically, you may also use one of the following typedefs and constants defined in \texttt{ParticleBase}: -\begin{itemize} - \item \texttt{Dim} - the dimensionality of the particle position attribute (in this example, 3) - \item \texttt{Position\_t} - the type of data used to store the position attribute components (here, this type is double) - \item \texttt{Layout\_t} - a synonym for the specified layout class - \item \texttt{ParticlePos\_t} - a typedef for the particle position attribute; it is shorthand for \texttt{ParticleAttrib< Vektor >} -\end{itemize} -and could have been used to specify the attribute \texttt{vel} in the above example as \texttt{ParticlePos\_t vel}; -\begin{itemize} -\item \texttt{ParticleIndex\_t} - a typedef for the particle global \texttt{ID} attribute; it is short for \texttt{ParticleAttrib} -\end{itemize} -The constructor for this user-defined class must initialize \texttt{ParticleBase} with a pointer to an instance of the selected layout class. - -In this example, the layout class is \texttt{ParticleSpatialLayout}, but using one of the typedefs listed above, we can abbreviate this as \texttt{Layout\_t}. Note that we only define one constructor here, omitting the default constructor. This is done because \texttt{ParticleSpatialLayout} (which we have hard-coded as the layout for this user-defined \texttt{Particle} class) requires an argument to its constructor, and this can only be provided if we use a constructor for our \texttt{Particle} class as shown here. A new instance of this class would be declared in an application as follows: -\begin{smallcode} -Bunch myBunch (new ParticleSpatialLayout(myFieldLayout)); -\end{smallcode} -where my\texttt{FieldLayout} was a \texttt{FieldLayout} object created previously. The only action that is required in the constructor for the derived class is to inform the base class of the declared attributes, -using the \texttt{addAttribute(.)} method of \texttt{ParticleBase}, which registers the specified \texttt{ParticleAttrib} instance with the parent class \texttt{ParticleBase}. The order in which attributes are registered is not important. - -\subsection{Example \texttt{Particle} Classes: {\color{red} The \texttt{Genparticle} and \texttt{GenArrayParticle}} Classes} -{\color{red} can be removed} - - -\subsection{Using \texttt{Particle} Classes in an Application} - -After a specific \texttt{Particle} class has been defined and created in a \ippl application, you may create and initialize new particles, delete unwanted particles, and perform computations involving these particles. This section describes how to accomplish these tasks. - -\subsection{Creating New \texttt{Particle}s} - -When a \texttt{Particle} object is created, it is initially empty. Storage for new particles is allocated using the create (unsigned) method of \texttt{ParticleBase}. For example, if a \texttt{Particle} object bunch has been created already, the statement -\begin{smallcode} -bunch.create(100); -\end{smallcode} - - -will allocate storage for 100 new particles. All the attributes for the particles in the \texttt{Particle} object will have this new storage allocated. The data is uninitialized, except for the global \texttt{ID} attribute; you must assign the proper values to the position and any other attributes that have been defined. The new storage is appended to the end of any existing storage. - -\texttt{ParticleBase} includes two methods that allow you to query how many particles exist. The function \texttt{getTotalNum()} will return the total number of particles being stored among all the processors; the function \texttt{getLocalNum()} will return the number of particles just on the local node. Although the new storage space is allocated on the local processor on which the call to create was executed, the \texttt{Particle} class will not officially add the particles to its -local count (and will not tell any other processors it has created these new particles) until you call the \texttt{update()} method of \texttt{ParticleBase}. Thus, a call to \texttt{getLocalNum()} will report the same number just before and just after the call to create. The storage does exist after create is called, but only after the \texttt{update} method (which is discussed in more detail in a later section) has been called will all the processors have correct information on their local and total particle counts. - -\subsection{Initializing Attribute Data} - -After calling create to allocate new storage, you must initialize the data. This should be done after calling create and before calling \texttt{update} for the \texttt{Particle} object. After the data is initialized, the \texttt{update} routine will properly distribute the particles to their correct node based on the layout mechanism chosen for that \texttt{Particle} object and possibly the positions of the particles as set during their initialization. The following example shows one way to initialize the data for newly -created particles when running on a single-processor machine. (This example will be modified in the following section for the case of running in parallel.) \\ -\begin{code} -// create and'initialize data for an instance of Bunch -Bunch myBunch(new Bunch::Layout\_t(myFieldLayout)); -int currLocalPtcls = myPtcls.getLocalNum(); -myBunch.create(100); -for (int i = 0; i < 100; i++) { - myBunch.R[currLocalPtcls + i] = Vektor(0.0, 1.0, 0.0); - myBunch.vel[currLocalPtcls + i] Vektor(1.0, 1.0, 1.0); -} -myBunch.update(); -\end{code} - - -In this example, 100 new particles are created, and the \texttt{R} and \texttt{vel} attributes are initialized to \texttt{Vektor} quantities. Notice that each attribute is accessed simply by specifying it as a data member of the \texttt{myBunch} object. After create was called, even though the 100 particles were not added to the \texttt{Particle} object's count of local particles, the storage was allocated and it was possible to assign values to the new elements in the attribute storage -(accessed simply using the \texttt{[]} indexing operator). Finally, calling \texttt{update} added the new storage to the count, of particles stored in \texttt{myBunch}. Further calls to getLocalNum and getTotalNum would report the proper values. - -\subsection{Initializing Attribute Data on Parallel Architectures} - -The code shown in the previous example has one problem when used on parallel architectures: the call to create is performed on each processor, so if there were P processors a total of 100*P particles would be created. This may be the desired behavior, if so, the previous example is sufficient. However, if you are reading data on particle positions and other attributes from a file or some other source, you may wish to create particles on a single processor, and then distribute the -data to the proper nodes. To do this, you need to call create and assign initial data on only one node but call update on all the processors. The \texttt{singlelnitNode()} method of \texttt{ParticleBase} will return a boolean value indicating whether the local processor should be used to create and initialize new particles in this way. The following example demonstrates how to use this method for initializing particles: \\ -\begin{code} -// create and'initialize data for an instance of Bunch -Bunch myBunch(new Bunch::Layout\_t(myFieldLayout)); -int currLocalPtcls = myPtcls.getLocalNum(); -if (myBunch.singleInitNode()) { - myBunch.create(100); - for (int i = 0; i < 100; i++) { - myBunch.R[currLocalPtcls + i] = Vektor(0.0, 1.0, 0.0); - myBunch.vel[currLocalPtcls + i] Vektor(1.0, 1.0, 1.0); - } -} -myBunch.update(); -\end{code} - - -\subsection{Deleting \texttt{Particle}s} - -\texttt{Particle}s may also be deleted during a simulation. The method \texttt{destroy (unsigned M, unsigned I)} of \texttt{ParticleBase} will delete \texttt{M} particles, starting with the \texttt{I}th particle. The index \texttt{I} here refers to the local particle index, not the global \texttt{ID} value. Thus \texttt{I = 0} means delete particles starting with the first one on the local processor. - -Unlike the situation when creating new particles, the storage locations for the deleted particles will not be removed from attribute data storage until \texttt{update} is called. Instead, the requests to delete particles are cached until the update phase, at which time all the deletions are performed. You are allowed to issue multiple delete requests between \texttt{update}s. For example, if there are 100 particles on a local node, and you request to delete particles 0 to 10 -and then request to delete particles 60 to 70, nothing will change in the attribute storage until you call \texttt{update}, and no change will occur to the local and total particle counts until \texttt{update()} is complete. - -\subsection{Updating \texttt{Particle}s: The \texttt{update()} Method} - -The \texttt{update()} method of \texttt{ParticleBase} is responsible for making sure that all processors have correct information about how many particles exist and where they are located in a parallel machine. As mentioned previously, \texttt{update} must be called by all processors after a sequence of particle creation or deletion operations. The \texttt{update} method is also responsible for maintaining a proper assignment of particles to processors, based on the particular -\texttt{ParticleLayout} class used to create the -\texttt{ParticleBase} object. Typically, this layout mechanism depends on the position of particles, so when particles change their position, they may need to be reassigned to a new processor to maintain the proper layout. In this case, the \texttt{update} method should be called whenever a computation is complete which alters the attributes (e.g. position) that a layout depends upon. The following short example demonstrates using \texttt{update} in conjunction with some operation that alters the x-coordinate of a -set of particles. \\ -\begin{code} -// do some computation involving myBunch for several time steps -while (computation_done == false) { - // for each particle, add some constant to the x coordinate - myBunch.R(0) += 0.li - // update the Particle object; this may move particles between nodes - myBunch.update(); - // determine if the computation is done, etc. -} -\end{code} - -\subsection{Using Particle Attributes in Expressions} - -Computations involving particle attributes may be performed in many ways. Data-parallel expressions that involve all particles of a given \texttt{Particle} object may be used, or specific loops may be written that employ attribute iterators. - - -\subsubsection{Attribute Expressions} - -Just as with the \texttt{Field} class, you may perform data-parallel operations on particle attributes using a simple expression syntax, which the \ippl framework will translate into efficient inlined code. These operations will be performed for every particle. The expressions may include any of the attributes in a \texttt{Particle} object as well as scalar values, may use mathematical operators such as +, -, *, / etc., and may call standard mathematical functions such as \texttt{cos( -)}, \texttt{exp( )}, \texttt{mod( )} , etc. for an attribute value of each particle. Some examples are shown below. -\begin{smallcode} -double dt = 2.0; -myBunch.R += myBunch.vel* dt; -myBunch. vel = 1. - log (1. + myBunch. R * myBunch. R) ; -myBunch.update(); -\end{smallcode} - - -Attribute expressions will perform their operations on all the particles in the \texttt{Particle} object, including any new particles allocated via a call to create, even before update has been called. This fact is useful when initializing the attributes for newly created particles (e.g., to set the init value for some scalar quantity to zero). Generally, however, unless you are performing an initialization of new particles, you should avoid using particle expressions of this type after calls to create or destroy and before a call to update. - -Some attributes, such as \texttt{Vektor}s or \texttt{Tenzor}s, have multiple components, and you may wish to involve only the \texttt{N}th component of the attribute in an expression. To do so, use the \texttt{()} operator to select the \texttt{N}th component of that attribute. For instance, using \texttt{myBunch} from the previous example, you can change just the x-coordinate of the particle position attribute \texttt{R} as follows: -\begin{smallcode} -myBunch.R(0) = myBunch.R(l) - cos(myBunch.R(2)); -\end{smallcode} - - -For 2D or 3D quantities, use two or three indices. For example, if rho is a 3x3 \texttt{Tenzor} attribute of myBunch, you can do the following: -\begin{smallcode} -myBunch.rho(0,0) = -(myBunch.rho(0,l) + myBunch.rho(0,2)); -\end{smallcode} - -Attribute expressions may also use the where operator in much the same way as for \texttt{Field} expressions. The first argument to where is some expression that results in a \texttt{boolean} value for each particle. The second and third arguments are expressions that will be evaluated for a particle if the first argument is \texttt{true} or \texttt{false}, respectively, for that particle. For example, -\begin{smallcode} -myBunch.vel = where(myBunch.R(0) > 0.0, -2.0 * myBunch.vel, myBunch.vel) -\end{smallcode} - -changes the value of the \texttt{vel} attribute in \texttt{myBunch} when the x-coordinate of the particle position is positive. - -\subsection{\texttt{Particle} Iterator Loop} - -You also have the capability of performing operations on specific particles using iterators or standard indexing operations. The \texttt{ParticleAttrib} containers in a \texttt{Particle} class may be used just as regular \texttt{STL} containers. The \texttt{begin()} and \texttt{end()} methods of the \texttt{ParticleAttrib} class will return an iterator pointing to the first element and just past the last element, respectively, of the attribute. These iterators may be used in an explicit loop just as if they were pointers into the attribute array. -\begin{smallcode} -ParticleAttrib::iterator idptr, idend = myBunch.ID.end(); -for (idptr = myBunch.ID.begin(); idptr != idend; ++idptr) - cout << "Particle ID value: " << *idptr << endl; -\end{smallcode} - - -Iterators are available for all \texttt{ParticleAttribs}. As an alternative, you may simply use the \texttt{[]} operator to access the attribute data of the \texttt{N}th particle on a node, treating \texttt{ParticleAttrib} as a regular array of data. -\begin{smallcode} -int nptcls = myBunch.getLocalNum(); -for(int i=0; i < nptcls ++i) { - cout << "Particle ID value: " << myPtcls.ID[i] << endl; -} -\end{smallcode} - - -\section{{\color{red}Nearest-Neighbor Interactions (Jakob)}} -{\color{red} can be removed} - - -\subsection{{\color{red}\texttt{Particle} - \texttt{Particle} Interactions}} -{\color{red} can be removed} - -\subsection{\texttt{Particle} - \texttt{Field} Interactions} - -%\section{\texttt{Particle} - \texttt{Field} Interactions} - -Many particle-based simulation methods, including "particle-in-cell" (PIC) simulations, rely on the ability of particles to interact with field quantities. For instance, in particle-based accelerator (plasma) simulations, you typically track the motions of charged plasma particles in a combination of externally applied and self-generated electromagnetic fields. In a \ippl application, such fields might be stored as \texttt{Field} objects of type \texttt{Vektor} existing on a pre-defined mesh. Particles moving through this mesh must be able to "gather" the current value of a \texttt{Field} to their exact positions. Additionally, in order to compute the values of self-generated fields, the particles must be able to "scatter" the value of an attribute onto nearby mesh points, producing a \texttt{Field}. These gather/scatter operations are done using a set of \ippl interpolation methods. - -\ippl provides a hierarchy of interpolation classes, each derived from the base class \texttt{Interpolate} and each containing the basic \texttt{gather} and \texttt{scatter} functions. The \texttt{gather} method allows you to gather one or more specified \texttt{Field}s into an equal number of \texttt{ParticleAttribs}. Similarly, \texttt{scatter} will accumulate one or more \texttt{ParticleAttribs} on to an equal number of \texttt{Field} objects. An example of how to scatter the particle density to a \texttt{Field} is shown below. -\begin{smallcode} -InterpolateNGP mylnterpolater(myBunch); // create NGP interpolater -Field ptcl_density(myfieldlayout); // create density field -myInterpolator.scatter(myBunch.density,ptcl_density); // do scattet -\end{smallcode} -The various classes derived from \texttt{Interpolate} implement these \texttt{gather} and \texttt{scatter} methods using different well-known interpolation schemes, such as nearest grid point (NGP), linear interpolation, and the subtracted-dipole scheme (SUDS). You may use these provided classes as a template for deriving new classes from \texttt{Interpolate} that implement other interpolation schemes of interest. - -In case of the CIC Interpolation and non-cyclic boundary condition, care has to be taken to not place particles in the outer half of boundary cells. Otherwise values will be scattered out of the grid and be irretrivable. diff --git a/manual/ippl_setup.tex b/manual/ippl_setup.tex deleted file mode 100644 index 689f6bb34..000000000 --- a/manual/ippl_setup.tex +++ /dev/null @@ -1,99 +0,0 @@ -\chapter{Framework Setup} -\label{sec:setup} - -\section{Initialising \ippl} -\ippl is initialized by passing \texttt{argc} and \texttt{argv} to \texttt{Ippl()} constructor or by creating an instance of \texttt{Ippl::Options}, configuring it, and then passing that options object to \texttt{Ippl::initialize()}. After the \texttt{Ippl()} constructor call MPI (or any other parallel subsystem) is proper initialized. \\ -With \texttt{Ippl::getNodes()} or \texttt{Ippl::myNode()} you can for example gather information how many compute nodes/cores are available and on which of the nodes you are running. \\ -\begin{code} -#include "Ippl.h" -int main(int argc, char *argv[]) -{ - Ippl ippl(argc,argv); - ..... -\end{code} - -\section{ Utility Classes in \ippl} -\ippl provides, and uses internally, a number of useful utility classes which you may find helpful when developing new applications. - -\subsection{Inform Class} -The Inform class is used to print messages to the console or to a file. It has an interface which is very similar to the iostream classes in C++, and it is mostly used in those situation where you might print a message to cout or cerr. An Inform object is created with a prefix string, which is then appended to all lines of output from the Inform object. Inform essentially takes in data to be printed, formats it for printing just as an ostream object would, but also appends the prefix message to all lines of output. Most important Inform will also indicate which node printed the message when running in parallel. - -\subsubsection{Constructing New Inform Objects} - -The constructor for Inform has the form -\begin{smallcode} -Inform(char *prefix = 0, int node = 0) -\end{smallcode} -where prefix is a string to prepend to all output lines, and node indicates on what node the Inform object should actually print out the information it is given. Notice that both of these arguments have default values; if no arguments are used when creating a new Inform object, no prefix will be used, if only one argument is given, then node default to 0, which means this Inform object will only print out messages on node 0. -\begin{smallcode} -Inform blankmsg; -blankmsg << "Some text." << endl; -\end{smallcode} -This Inform object will print the text it is given to standard out. The final "\texttt{endl}" is a special manipulator object, which signals the Inform objec t to print out the message it has been given. It will automatically append an endline to the message if it does not already have one at the end. It is important to use endl with an Inform object if it is not ever used, the Inform object will never print out its accumulated text. -\begin{smallcode} -Inform testmsg("mytest"); -testmsg << "More text. argc = " << argc << endl; -\end{smallcode} -Here, the prefix is given, if this is used when running in serial, the output will look like: -\begin{smallcode} -mytest> More text. argc = 1 -\end{smallcode} -or, if you use this when there is more than one processor in use, the prefix will also include the node number in curly brackets: -\begin{smallcode} -mytest{0}> More text. argc = 1 -\end{smallcode} -On all other nodes than node 0, when this Inform object is used, it will not print out the message. -\begin{smallcode} -Inform testmsg("testall", INFORM_ALL_NODES); -\end{smallcode} -This example is similar to the previous example, except the second argument explicitly specifies which node to print on. This can be a number from 0 .... (num nodes - 1), or, as in this example, it can be \texttt{INFORM\_ALL\_NODES} which indicates the message should be printed on ALL the nodes instead of just one. You can also change the node on which an Inform object will print after it has been created by using the \texttt{setprintNode(int)} method of \texttt{Inform}. - -\subsubsection{Predefined Inform Objects} -Creating new Inform objects for printing messages is useful in contexts where you would like a unique prefix to indicate where the message originated, say in a specific class method. However, the \ippl framework provides a set of predefined Inform instances which may be used to quickly generate output message or to make sure all messages have a common prefix. These Inform objects are static members of the IPPL class, which is used to initialize the framework. The predefined instances are: -\begin{smallcode} -IPPL::Info = new Inform ("IPPL") ; -IPPL::Warn = new Inform("Warning"); -IPPL::Error = new Inform("Error", INFORM_ALL_NODES); -\end{smallcode} -These three instances are used to print generally informative messages, warning messages, and error messages. \texttt{Info} and \texttt{Warn} only print on node 0 by default; \texttt{Error} will print on all nodes. You may use these to printmessages in your own application: -\begin{smallcode} -*IPPL::Info << "An informative message." << endl; -\end{smallcode} -Notice that here that \texttt{Info} was first dereferenced, since it actually is a pointer to an \texttt{Inform} object. A better (and recommended) way to use these predefined instances is to use a macro which is defined for each instance. The macros to use are \texttt{INFOMSG}, \texttt{WARNMSG}, and \texttt{ERRORMSG}; an example of their use is: -\begin{smallcode} -WARNMSG("rhis is a warning: value = " << warnvalue << endl); -\end{smallcode} -The argument to the macro is then given to the associated \texttt{Inform} object for printing. - -\subsection{Timer Class} -Timer is used to perform simple timings within a program for use in, e.g., benchmarking. It tracks real (clock) time elapsed, user time, and system time. It acts essentially as a stopwatch: -initially it is stopped, and YOU tell it to stop and start with method calls. The Timer constructor takes no arguments; you create a new Timer object, and use the following methods: -\begin{smallcode} -//Start the clock running. Time only accumulates in the Timer when it is running. -void start() -void stop() //Stop the clock. The clock may be started again later. -void clear() //Resets the accumulated time to zero -float clock_time() //Reports the accumulated "wall clock" time in seconds. -float user_time() //Reports theaccurnulated user CPU time in seconds. -float system_time() //Reports the accumulated system CPU time in seconds. -float cpu_time() //Reports user_time() + system_time() -\end{smallcode} - -\clearpage - -Example how to use the timer class: \\ -\begin{code} - -IpplTimings::TimerRef selfFieldTimer_m; \\ definition - -selfFieldTimer_m = IpplTimings::getTimer("computeSelfField"); - -selfFieldTimer_m.start(); - /* compute something */ -selfFieldTimer_m.stop(); - -IpplTimings::print(); - -\end{code} - - diff --git a/manual/ippl_user_guide.tex b/manual/ippl_user_guide.tex deleted file mode 100644 index 7b0b0be5e..000000000 --- a/manual/ippl_user_guide.tex +++ /dev/null @@ -1,292 +0,0 @@ -\documentclass[12pt,a4paper]{report} -%% does not work in Latex2Html mode -%\usepackage{hyperref} -\usepackage{url} -\usepackage{html} -\usepackage{epic} -\usepackage{eepic} -\usepackage{makeidx} -\usepackage{array} -\usepackage{times} -\usepackage{amsmath} -\usepackage[dvips]{epsfig,rotating} -\usepackage{dingbat} -\usepackage{listings} -\usepackage{graphicx} - -\lstnewenvironment{code}[1][] -{\textbf{Code Listing} \hspace{1cm} \hrulefill \lstset{language=C++, basicstyle=\ttfamily\scriptsize}} -{\hrule\smallskip} -%{\textbf{Code Listing} \hspace{1cm} \hrulefill \lstset{language=C++, basicstyle=\ttfamily\scriptsize, #1}} - -\lstnewenvironment{codeln}[1][] -{\textbf{Code Listing} \hspace{1cm} \hrulefill \lstset{language=C++, basicstyle=\ttfamily\scriptsize, numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt}} -{\hrule\smallskip} - -\lstnewenvironment{smallcode}[1][] -{\lstset{language=C++, basicstyle=\ttfamily\scriptsize}} -{\smallskip} - -\usepackage{pdfdraftcopy} % Draft -\draftstring{V 2.0 - with Kokos} -%% Define a new 'leo' style for the package that will use a smaller font. -%\makeatletter -%\def\url@leostyle{% - % \@ifundefined{selectfont}{\def\UrlFont{\sf}}{\def\UrlFont{\small\ttfamily}}} -%\makeatother -%% Now actually use the newly defined style. -%\urlstyle{leo} - -\setlength\topmargin{0.0cm} -%\setlength\oddsidemargin{3.501cm} -%\setlength\evensidemargin{3.501cm} -\renewcommand{\arraystretch}{1.5} - - -% Definition neuer Zeichen -\newcommand{\R}{{\mathbb R}} -\newcommand{\N}{{\mathbb N}} -\newcommand{\Z}{{\mathbb Z}} -% Standard Notationen -\newcommand{\vc}[1]{\mbox{\boldmath $#1$}} -\newcommand{\sv}[1]{\mbox{\boldmath $\vec{#1}$}} -\newcommand{\mx}[1]{\mbox{\boldmath $\underline{#1}$}} -\newcommand{\op}[1]{\mathcal{#1}} -% Sonstige Abkuerzungen -\newcommand{\backpar}{\rule{1mm}{0mm}\\[-5ex]\rule{1mm}{0mm}} -\newcommand{\ds}{\displaystyle} -\newcommand{\AND}{\quad\mbox{and}\quad} -\newcommand{\diag}{\mbox{diag }} -\newcommand{\arrstr}[1]{\rule[0mm]{0mm}{#1}} -\newcommand{\hstrut}[1]{\rule{0mm}{#1}} -\newlength{\mylablen} -\newlength{\mycaplen} -\newlength{\myislen} -% caption fuer Bilder -\newcommand{\fcap}[2]{\refstepcounter{figure} \settowidth{\mycaplen}{#2} -\settowidth{\mylablen}{\bf Figure \thefigure:~} -\settowidth{\myislen}{\textwidth-\mylablen} -\begin{center} -{\bf Figure \thefigure:~}\ifthenelse{\mycaplen > \myislen}{\parbox[t]{\textwidth-\mylablen}{#2}\label{#1}}{#2\label{#1}}\end{center}} -% caption fuer Tabellen -\newcommand{\tcap}[2]{\refstepcounter{table} \settowidth{\mycaplen}{#2} -\settowidth{\mylablen}{\bf Table \thetable:~} -\settowidth{\myislen}{\textwidth-\mylablen} -\begin{center} -{\bf Table \thetable:~}\ifthenelse{\mycaplen > \myislen}{\parbox[t]{\textwidth-\mylablen}{#2}\label{#1}}{#2\label{#1}}\end{center}} -% -\newtheorem{theorem}{Theorem} -\newtheorem{lemma}{Lemma} -\newtheorem{corollary}{Corollary} -\newtheorem{remark}{Remark} -\newtheorem{definition}{Definition} -\newtheorem{proposition}{Proposition} -\newenvironment{proof}{{\bf Proof:}}{{}\hfill{$\square$}\par\smallskip} - -\renewcommand{\topfraction}{0.9} -\renewcommand{\bottomfraction}{0.9} -\renewcommand{\textfraction}{0.1} - -\newcommand{\ipplversion}{\text{2.0 }} -\newcommand{\mad}{\textsc{mad }} -\newcommand{\madnine}{\textsc{mad9 }} -\newcommand{\madninep}{\textsc{mad9p }} -\newcommand{\madeight}{\textsc{mad8 }} -\newcommand{\pooma}{\textsc{pooma }} -\newcommand{\classic}{\textsc{classic }} - -\newcommand{\ippl}{\textsc{I$\text{P}^2$L }} - - -\newcommand{\opal}{\textsc{OPAL }} -\newcommand{\opalt}{\textsc{OPAL-t }} -\newcommand{\opalcycl}{\textsc{OPAL-cycl }} -\newcommand{\opalmap}{\textsc{OPAL-map }} - -\newcommand{\partroot}{\textsc{H5PartROOT }} - -\newcommand{\lieop}[1] -{{:}{#1}{:}} -\renewcommand{\arraystretch}{2.0} - -\newcommand{\rms}[1] -{\overset{\sim}{#1}} - -% Pfister stuff -\def\C{{{{\rm {\mbox{\small l}}} \kern -.50em {\rm C}}}} -\def\R{{{{\rm l} \kern -.15em {\rm R}}}} -\def\N{{{{\rm l} \kern -.15em {\rm N}}}} -\def\E{{{{\rm l} \kern -.15em {\rm E}}}} -\def\P{{{{\rm l} \kern -.15em {\rm P}}}} -\def\D{{{{\rm l} \kern -.15em {\rm D}}}} -\def\L{{{{\rm l} \kern -.15em {\rm L}}}} -\def\Z{{{{\rm Z} \kern -.35em {\rm Z}}}} -\def\Q{{{{\rm {\mbox{\small l}}} \kern -.45em {\rm Q}}}} -\def\qQ{{{{\rm {\mbox{\scriptsize l}}} \kern -.33em {\rm Q}}}} -\def\v{\vspace{1ex}} -\def\-v{\vspace{-1ex}} -\def\vv{\vspace{2ex}} -\def\vvv{\vspace{3ex}} -\def\vn{\vspace{3ex}\noindent} -\def\hs{\hspace{-1ex}} -\def\n{\noindent} -\def\dsl{\dis\sum\limits} -\def\dis{\displaystyle} -\def\O{\Omega} -\def\o{\omega} -\def\fr{\mbox{\footnotesize $\dis\frac{1}{2}$}} -\def\frvier{\mbox{\footnotesize $\dis\frac{1}{4}$}} -\def\ov{\overline} -\def\b{\big[} -\def\B{\big]} -\def\i{\big\{} -\def\g{\big\}} -\def\e{\epsilon} -\def\f{\footnotesize} -\def\l{\ell^\prime} -\def\ll{\ell,\ell^\prime} -\def\r{\rightarrow} -\def\point{{\mbox{\large $.$}}} -\def\wl{\widetilde{\ell}} -\def\wll{\widetilde{\ell},\widetilde{\ell}^\prime} -\def\w{\widetilde} -\def\wh{\widehat} -\def\wt{\widetilde} -\def\cA{{\cal A}} -\def\cT{{\cal T}} -\def\cE{{\cal E}} -\def\oS{\overline{S}} -\def\oT{\overline{T}} -\def\cI{{\cal I}} -\def\cK{{\cal K}} -\def\cH{{\cal H}} -\def\cP{{\cal P}} -\def\cF{{\cal F}} -\def\cS{{\cal S}} -\def\cG{{\cal G}} -\def\cO{{\cal O}} -\def\cU{{\cal U}} - -%% REAL ADA STUFF -\def\bx{{\bf x}} -\def\br{{\bf r}} -\def\bv{{\bf v}} -\newcommand{\matr}[1]{\mathcal{#1}} - \newcommand{\myvec}[1]{\bf{#1}} -%\newcommand{\figref}[2]{#1 (see~Figure~\ref{fig:#2})} -%\newcommand{\tabref}[2]{#1 (see~Table~\ref{tab:#2})} -%\newcommand{\secref}[2]{#1 (see~Section~\ref{sec:#2})} -\newcommand{\mytabline}[2]{\texttt{#1} & #2 \\} -\renewcommand{\vec}{\myvec} - -\makeindex - -\renewcommand{\topfraction}{1.0} -\renewcommand{\bottomfraction}{1.0} -\renewcommand{\textfraction}{0.0} - -\newenvironment{tex2html_nowrap}{}{} - -\newcommand{\bibref}[2]{\hypercite{#1}{}{}{bib:#2}} - -\newcommand{\tabline}[3]{\hyperref{\texttt{#1}}% - {\texttt{#1} (}{)}{sec:#3} & #2 \\} -\newcommand{\figref}[2]{\hyperref{#1}{#1 (see~Figure~}{)}{fig:#2}} -\newcommand{\secref}[2]{\hyperref{#1}{#1 (see~Section~}{)}{sec:#2}} -\newcommand{\tabref}[2]{\hyperref{#1}{#1 (see~Table~}{)}{tab:#2}} -\begin{htmlonly} -\bodytext{bgcolor = "#ffffff"} -\end{htmlonly} - -%\newcommand{\documentlabel}{ } - -\begin{document} - -\begin{titlepage} - -\begin{htmlonly} -\begin{rawhtml} -
-PAUL SCHERRER INSTITUT -
-

The IPPL Framework , Version 2.0

-

(Independent Parallel Particle Layer)

-

User's Reference Manual

-
-Andreas Adelmann -
-\end{rawhtml} -\end{htmlonly} - -\begin{latexonly} -\begin{center}\normalsize -\includegraphics[width=1.\linewidth,angle=0]{figures/psi_logo_wide} -\end{center} -\vskip 0.7cm -PSI-PR-09-05 -\begin{flushright} -%\documentlabel \\ % document label -\end{flushright} -%\vskip 2.3cm -\begin{center}\LARGE % document title -{\bf The \ippl Framework} \\ -(Independent Parallel Particle Layer) \\ -Version \ipplversion \footnote{Release Date: \today} \\ -{\bf User's Reference Manual} -\end{center} -\vskip 1.5em -\begin{center} % author -Andreas Adelmann, ..... \vskip 2em -{\large Abstract} -\end{center} -\end{latexonly} -\begin{quotation} - \ippl (Independent Parallel Particle Layer) is an object-oriented framework for particle based applications in computational science -requiring high-performance parallel computers. One of \ippl 's most attractive features is its high performance on both single-processor and distributed-memory multicomputers machines. As future releases of the library will also support shared-memory multicomputers, \ippl 's authors have had to think very carefully about how to obtain the best possible performance across a wide range of applications on different architectures. -\ippl is a library of C++ classes designed to represent common abstractions in applications where {\em particles, fields} and operators like {\em FFT's} are needed. - -Application programmers use and derive from these classes, which present a data-parallel programming interface at the highest abstraction layer. - -Lower, to the user (programmer) hidden implementation layers encapsulate distribution and communication of data among processors. The supported platforms are: Linux based Beowulf clusters, Cray XT5/6, SGI Ultrix and the IBM Blue Gene series. - -The main goals of the \ippl framework includes: -\begin{itemize} - \item Portability across serial, distributed, and parallel architectures with no change to source code - \item Development of reusable, cross-problem-domain components to enable rapid application development - \item High efficiency for kernels and components relevant to scientific simulation - \item Framework design and development driven by applications from a diverse set of scientific problem domains - \item Shorter time from problem inception to working parallel simulations -\end{itemize} - \ippl is currently in development the version here is the first "developer release". \ippl is inspired and partially based on POOMA r1 designed and implemented by scientists working at the Los Alamos National Laboratory's Advanced Computing Laboratory. - %Although \ippl has received numerous additions the most importand are: -%Fully ANSI C++ compatible, full 64Bit, HDF5 support and a Trilinos interface. - -The report is organized as follow: in chapter 1 an introduction based on examples including installation instructions is presented. Chapter 2 and 3 are describing support classes followed by an discussion -on 3D parallel FFT's in \ippl. The next two chapters explaining the use of particles and fields. Appendix A - F describing design and implementation details of the most important classes in the -framework. -\end{quotation} -\vfill - - -\end{titlepage} - -\tableofcontents -\listoftables -\listoffigures -\include{introduction} -\include{ippl_setup} -\include{ippl_fft} -\include{ippl_particles} -\include{ippl_fields} - -\appendix -\include{ippl_field_ref} -\include{ippl_index_ref} -\include{ippl_fieldlayout_ref} -\include{ippl_mesh_ref} -\include{ippl_centering_ref} -\include{bibliography} - -\printindex - -\end{document} diff --git a/manual/pdfdraftcopy.sty b/manual/pdfdraftcopy.sty deleted file mode 100644 index 1390ba1e1..000000000 --- a/manual/pdfdraftcopy.sty +++ /dev/null @@ -1,198 +0,0 @@ -%% -%% -%% This is file 'pdfdraftcopy.sty', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% -%% pdfdraftcopy.dtx (with options: 'package') -%% -%% File: pdfdraftcopy.dtx Copyright (c) 2003, C. V. Radhakrishnan -%% C. V. Rajagopal -%% River Valley Technologies, Floor III, SJP Buildings -%% Cotton Hills, Trivandrum, India 695014 -%% http://www.river-valley.com -%% -%% This package may be distributed under the terms of the LaTeX Project -%% Public License, as described in lppl.txt in the base LaTeX distribution. -%% Either version 1.0 or, at your option, any later version. -%% -%% $Id: pdfdraftcopy.sty,v 1.2 2003/08/11 20:31:07 cvr Exp cvr $ -%% -\NeedsTeXFormat{LaTeX2e} -\def\Fileversion$#1: #2 ${\gdef\fileversion{#2}} -\def\Filedate$#1: #2 #3 ${\gdef\filedate{#2}} -\Fileversion$Revision: 1.2 $ -\Filedate$Date: 2003/08/11 20:31:07 $ -\ProvidesPackage{pdfdraftcopy} - [\filedate\space\fileversion\space Draft copy in PDF (CVR)] -\PackageWarningNoLine{pdfdraftcopy} - {****************************************\MessageBreak - Package pdfdraftcopy v,\fileversion\space loaded\MessageBreak - [Draft copy in PDF (CVR)]\MessageBreak - ****************************************} -\DeclareOption{watermark}{\AtBeginDocument{% - \begingroup\watermark\endgroup}} -\DeclareOption{draft}{\AtBeginDocument{% - \begingroup\draftcopy\endgroup}} -\ExecuteOptions{draft} -\ProcessOptions\relax - -\RequirePackage{color,graphicx} - -\let\@DRAFTout@Hook\@empty -\newcommand{\DRAFTout}{\g@addto@macro\@DRAFTout@Hook} -\newcommand{\@DRAFTout@Out}{% - \afterassignment\@DRAFTout@Test - \global\setbox\@cclv= % - } -\newcommand{\@DRAFTout@Test}{% - \ifvoid\@cclv\relax - \aftergroup\@DRAFTout@Output - \else - \@DRAFTout@Output - \fi% - } -\newcommand{\@DRAFTout@Output}{% - \@DRAFTout@Hook% - \@DRAFTout@Org@Out\box\@cclv% - } -\newcommand{\@DRAFTout@Org@Out}{} -\newcommand*{\@DRAFTout@Init}{% - \let\@DRAFTout@Org@Out\shipout - \let\shipout\@DRAFTout@Out - } -\AtBeginDocument{\@DRAFTout@Init} -\newcommand{\@DraftOverlay@Hook}{} -\newcommand{\AddToDraftOverlay}{\g@addto@macro\@DraftOverlay@Hook} -\newcommand{\ClearDraftOverlay}{\let\@DraftOverlay@Hook\@empty} -\newcommand{\@DraftOverlay}{% - \ifx\@DraftOverlay@Hook\@empty - \else - \bgroup - \@tempdima=1in - \@tempcnta=\@tempdima - \@tempcntb=-\@tempdima - \advance\@tempcntb\paperheight - \global\setbox\@cclv\vbox{% - \vbox{\let\protect\relax% - \unitlength=1sp% - \pictur@(0,0)(\@tempcnta,\@tempcntb)% - \@DraftOverlay@Hook% - \endpicture}% - \box\@cclv% - }% - \egroup - \fi -} - -\definecolor{gray30}{gray}{.7} -\definecolor{gray20}{gray}{.8} -\definecolor{gray10}{gray}{.9} - -\DRAFTout{\@DraftOverlay} -\newdimen\LLY -\newdimen\LLX -\newdimen\URX -\newdimen\URY -\newdimen\topmargin -\newdimen\bottommargin -\def\@printdimen{%\ifthenelse{\equal{\@debug}{true}}% - {\PackageWarningNoLine{PDFdraftcopy}% - {\LLX::::::::::::=\the\LLX\MessageBreak - \LLY::::::::::::=\the\LLY\MessageBreak - \URX::::::::::::=\the\URX\MessageBreak - \URY::::::::::::=\the\URY\MessageBreak - \oddsidemargin::=\the\oddsidemargin\MessageBreak - \evensidemargin:=\the\evensidemargin\MessageBreak - \textheight:::::=\the\textheight\MessageBreak - \textwidth::::::=\the\textwidth\MessageBreak - \paperwidth:::::=\the\paperwidth\MessageBreak - \paperheight::::=\the\paperheight\MessageBreak - \topmargin::::::=\the\topmargin\MessageBreak - \headheight:::::=\the\headheight\MessageBreak - \headsep::::::::=\the\headsep\MessageBreak - \footskip:::::::=\the\footskip\MessageBreak - \topskip::::::::=\the\topskip\MessageBreak - Now fixing the overlay in place - }}{} -} -\def\@DRAFTdimen{% - \setlength\LLY{\paperheight} - \addtolength\LLY{-\textheight} - \addtolength\LLY{-\headheight} - \addtolength\LLY{-\headsep} - \addtolength\LLY{-1in} - \addtolength\LLY{-3pt} - \setlength\LLX{1in} - \ifodd\thepage - \addtolength\LLX{\oddsidemargin}\else - \addtolength\LLX{\evensidemargin}\fi - \setlength\URX{\textwidth} - \setlength\URY{\textheight} -} -\def\LoadWaterMark{\watermark} -\def\watermark{\AddToDraftOverlay{% - \@DRAFTdimen%\@printdimen% - \setlength{\@tempdima}{0pt} - \setlength{\@tempdimb}{\paperwidth} - \addtolength{\@tempdimb}{-\@tempdima} - \addtolength{\@tempdimb}{-\@tempdima} - \setlength{\@tempdimc}{\paperheight} - \addtolength{\@tempdimc}{-\@tempdima} - \addtolength{\@tempdimc}{-\@tempdima} - \setlength{\unitlength}{1pt}\thinlines% -% - \put(0,\strip@pt\paperheight){\fboxrule0pt\fboxsep0pt% - %\fcolorbox{white}{red}% - {\begin{minipage}[t][\paperheight][c]{\paperwidth} - \centering - \ifx\@@watermark\@empty\relax\else - \includegraphics%[width=\paperwidth,height=\paperheight]% - {\@@watermark}\fi% - \end{minipage}}}}}% - -\let\@@watermark\@empty -\def\watermarkgraphic#1{\gdef\@@watermark{#1}} - -\def\draftcopy{\AddToDraftOverlay{% - \@DRAFTdimen%\@printdimen% - \setlength{\@tempdima}{0pt} - \setlength{\@tempdimb}{\paperwidth} - \addtolength{\@tempdimb}{-\@tempdima} - \addtolength{\@tempdimb}{-\@tempdima} - \setlength{\@tempdimc}{\paperheight} - \addtolength{\@tempdimc}{-\@tempdima} - \addtolength{\@tempdimc}{-\@tempdima} - \setlength{\unitlength}{1pt}\thinlines% -% - \put(0,\strip@pt\paperheight){\fboxrule0pt\fboxsep0pt% - %\fcolorbox{white}{red}% - {\begin{minipage}[t][\paperheight][c]{\paperwidth} - \centering - \begingroup - \rotatebox{\@draftangle}{\color{\@draftcolor} - \fontfamily{\@draftfontfamily}% - \fontsize{\@draftfontsize}{\@draftfontsize}\selectfont - {\@draftfontattrib\@draftstring} - }\endgroup - \end{minipage}}}}}% - -\def\@draftangle{45} -\def\@draftstring{DRAFT COPY} -\def\@draftcolor{gray10} -\def\@draftfontfamily{ptm} -\def\@draftfontsize{80} -\def\@draftfontattrib{\upshape} -\def\draftstring#1{\gdef\@draftstring{#1}} -\def\draftcolor#1{\gdef\@draftcolor{#1}} -\def\draftfontfamily#1{\gdef\@draftfontfamily{#1}} -\def\draftfontsize#1{\gdef\@draftfontsize{#1}} -\def\draftfontattrib#1{\gdef\@draftfontattrib{#1}} -\def\draftangle#1{\gdef\@draftangle{#1}} -\endinput -%% -%% -%% End of package 'pdfdraftcopy.sty' -%% From 2ec2635c060bad9912ee1c5f67ab14876cad4a61 Mon Sep 17 00:00:00 2001 From: Severin <93776531+klappi-s@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:56:52 +0000 Subject: [PATCH 2/6] DOC: remove handwritten markdown pages from doxygen (moved to repo "Manual") --- doc/Doxyfile | 6 +- doc/DoxygenLayout.xml | 3 - doc/examples/BasicsFFT.hpp | 99 ----------- doc/examples/BasicsFields.hpp | 238 -------------------------- doc/examples/BasicsIndex.hpp | 62 ------- doc/examples/BasicsMesh.hpp | 25 --- doc/examples/BasicsParticles.hpp | 191 --------------------- doc/examples/BasicsSolver.hpp | 120 ------------- doc/examples/CustomPreconditioner.hpp | 89 ---------- doc/examples/CustomSolver.hpp | 77 --------- doc/examples/HelloWorld.hpp | 29 ---- doc/examples/LandauDampingEx.hpp | 122 ------------- doc/extras/Basics.md | 29 ---- doc/extras/CodeFormattingSetup.md | 188 -------------------- doc/extras/IPPLonEULER.md | 84 --------- doc/extras/MainPage.md | 14 -- doc/extras/Profiling.md | 220 ------------------------ doc/images/hello_world.png | Bin 125640 -> 0 bytes doc/images/ippl_structure.jpg | Bin 116519 -> 0 bytes 19 files changed, 3 insertions(+), 1593 deletions(-) delete mode 100644 doc/examples/BasicsFFT.hpp delete mode 100644 doc/examples/BasicsFields.hpp delete mode 100644 doc/examples/BasicsIndex.hpp delete mode 100644 doc/examples/BasicsMesh.hpp delete mode 100644 doc/examples/BasicsParticles.hpp delete mode 100644 doc/examples/BasicsSolver.hpp delete mode 100644 doc/examples/CustomPreconditioner.hpp delete mode 100644 doc/examples/CustomSolver.hpp delete mode 100644 doc/examples/HelloWorld.hpp delete mode 100644 doc/examples/LandauDampingEx.hpp delete mode 100644 doc/extras/Basics.md delete mode 100644 doc/extras/CodeFormattingSetup.md delete mode 100644 doc/extras/IPPLonEULER.md delete mode 100644 doc/extras/MainPage.md delete mode 100644 doc/extras/Profiling.md delete mode 100644 doc/images/hello_world.png delete mode 100644 doc/images/ippl_structure.jpg diff --git a/doc/Doxyfile b/doc/Doxyfile index 614f32622..7872d0515 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -771,7 +771,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../src/ ../alpine/ ../README.md examples extras +INPUT = ../README.md ../src/ # ../demos/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -844,7 +844,7 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = ../alpine/ ../examples/ #mainpage.md +EXAMPLE_PATH = # ../demos # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and @@ -864,7 +864,7 @@ EXAMPLE_RECURSIVE = YES # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = images +IMAGE_PATH = # images # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml index bc72f6dec..c87d37cfb 100644 --- a/doc/DoxygenLayout.xml +++ b/doc/DoxygenLayout.xml @@ -4,9 +4,6 @@ - - - diff --git a/doc/examples/BasicsFFT.hpp b/doc/examples/BasicsFFT.hpp deleted file mode 100644 index 010e8a92a..000000000 --- a/doc/examples/BasicsFFT.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/** -@page basics_fft Basics: FFT -@section fft Introduction -The FFT(Fast Fourier Transform) class performs complex-to-complex, real-to-complex and real-to-real -on IPPL Fields. Currently, we use heffte for taking the transforms and the class FFT serves as an -interface between IPPL and heffte. In making this interface, we have referred Cabana library -https://github.com/ECP-copa/Cabana. - - * @subsection FFT Transformation Types - * - * FFT is templated on the type of transform to be performed, the dimensionality of the Field to -transform, and the - * floating-point precision type of the Field (float or double). - * - * **Types of transformation** - * - complex-to-complex FFT: 'ippl::CCTransform' - * - real-to-complex FFT: 'ippl::RCTransform' - * - Sine transform: 'ippl::SineTransform' - * - Cosine transform: 'ippl::CosTransform' - * - Cosine type 1 transform: 'ippl::Cos1Transform' - -@section Example Usage - -Consider an example of a transformation from real valued Field to complex valued Field. -Given a Field fieldInput, we can perform a forward FFT as follows: -@code -// Define FFT-Parameters -ippl::ParameterList fftParams; -fftParams.add("use_heffte_defaults", true); -fftParams.add("r2c_direction", 0); - - -// Define layout of complex valued Field output -std::array pt = {64, 64, 64}; -std::array dx = { - 1.0 / double(pt[0]), - 1.0 / double(pt[1]), - 1.0 / double(pt[2]), -}; -ippl::Vector hx = {dx[0], dx[1], dx[2]}; -ippl::Vector origin = {0, 0, 0}; - -ippl::NDIndex ownedOutput; -if (fftParams.get("r2c_direction") == 0) { - ownedOutput[0] = ippl::Index(pt[0] / 2 + 1); - ownedOutput[1] = ippl::Index(pt[1]); - ownedOutput[2] = ippl::Index(pt[2]); -} else if (fftParams.get("r2c_direction") == 1) { - ownedOutput[0] = ippl::Index(pt[0]); - ownedOutput[1] = ippl::Index(pt[1] / 2 + 1); - ownedOutput[2] = ippl::Index(pt[2]); -} else if (fftParams.get("r2c_direction") == 2) { - ownedOutput[0] = ippl::Index(pt[0]); - ownedOutput[1] = ippl::Index(pt[1]); - ownedOutput[2] = ippl::Index(pt[2] / 2 + 1); -} else { - if (ippl::Comm->rank() == 0) { - std::cerr << "RCDirection need to be 0, 1 or 2 and it" - << "indicates the dimension in which data is shortened" << std::endl; - } - return 0; -} - -ippl::FieldLayout layoutOutput(MPI_COMM_WORLD, ownedOutput, isParallel); -Mesh_t meshOutput(ownedOutput, hx, origin); -field_type_complex fieldOutput(meshOutput, layoutOutput); - - -// Fill Field fieldInput with random numbers -typename field_type_real::view_type& view = fieldInput.getView(); -typename field_type_real::host_mirror_type fieldInput_host = fieldInput.getHostMirror(); - -const int nghost = fieldInput.getNghost(); -std::mt19937_64 eng(42 + ippl::Comm->rank()); -std::uniform_real_distribution unif(0, 1); - -for (size_t i = nghost; i < view.extent(0) - nghost; ++i) { - for (size_t j = nghost; j < view.extent(1) - nghost; ++j) { - for (size_t k = nghost; k < view.extent(2) - nghost; ++k) { - fieldInput_host(i, j, k) = unif(eng); // 1.0; - } - } -} -Kokkos::deep_copy(fieldInput.getView(), fieldInput_host); - - -// Define FFT object -typedef ippl::FFT FFT_type; -std::unique_ptr fft; -fft = std::make_unique(layoutInput, layoutOutput, fftParams); - - -// Perform FFT -fft->transform(ippl::FORWARD, fieldInput, fieldOutput); // Forward transform -fft->transform(ippl::BACKWARD, fieldInput, fieldOutput); // Reverse transform - - -@endcode -*/ \ No newline at end of file diff --git a/doc/examples/BasicsFields.hpp b/doc/examples/BasicsFields.hpp deleted file mode 100644 index ce1802a2a..000000000 --- a/doc/examples/BasicsFields.hpp +++ /dev/null @@ -1,238 +0,0 @@ - -/** -* @page basics_fields Basics: Fields - * - * - * -@section field_intro Introduction -This sections provides the readers with a brief background on the used classes for handling Fields -in IPPL. -* ## FieldLayout -// -FieldLayout describes how a given index space (represented by an NDIndex -object) is distributed among MPI ranks. It performs the initial -partitioning. The user may request that a particular dimension not be -partitioned by flagging that axis as 'SERIAL' (instead of 'PARALLEL'). -* @code - int pt = 25; - ippl::Index I(pt); - ippl::NDIndex owned(I, I, I); - std::array isParallel; - isParallel.fill(true); // Specifies SERIAL, PARALLEL dims - // all parallel layout, standard domain, normal axis order - ippl::FieldLayout layout(MPI_COMM_WORLD, owned, isParallel); -* @endcode -In this example, we create a 3-dimensional FieldLayout with 25 points in each direction. The layout -is distributed among MPI ranks. - - -* ## BareField -The BareField class in IPPL is a template class that represents a numerical field in a computational -domain. It is designed to handle data in up to three dimensions and supports various data types -through its template parameter T. It provides a Kokkos-based multidimensional array, or view, which -is the main data structure used to store field values. The class is integrated with IPPL's field -layout and halo cell system for managing computational domains and communication between them, -especially in parallel computing environments. A field can be initialized with a specific layout, -and it supports operations such as resizing, updating the layout, and operations related to ghost -cells which are used for boundary conditions and domain communication. It offers functions for -calculating aggregate values over the field, such as sums, maxima, minima, and products. Fields can -be assigned values from constants or other fields through expression templates, allowing for complex -computations and assignments. The class provides range policies for iteration that can exclude or -include ghost layers, giving flexibility in how the field data is traversed and manipulated. - - -*@code -constexpr unsigned int dim = 3; -int numPoints = 100; -ippl::Index domainIndex(numPoints); -ippl::NDIndex domain(domainIndex, domainIndex, domainIndex); - -ippl::FieldLayout layout(domain); - // Create a BareField with 3 dimensions, double data type, and 1 ghost layer. -ippl::BareField field(layout, 1); -*@endcode - - - -*@section Field Field -The Field class in IPPL is an advanced version of BareField, augmented with a mesh for defining the -spatial domain and equipped with customizable boundary conditions. The class is templated to be -flexible for various data types (T), dimensions (Dim), mesh types (Mesh), and centering schemes -(Centering), along with additional Kokkos view arguments (ViewArgs...). It's associated with a Mesh -object that dictates the structure of the simulation space. Boundary conditions can be set and -updated, affecting how the field interacts with the limits of the simulation space. Offers methods -for calculating volume integrals and averages, which are useful for analyzing the field over its -entire domain. Inherits from BareField, allowing for basic field operations and attribute access. - -### Example: Creating a Field - * The following example showcases the creation and basic manipulation of a field in IPPL: - * - * @code{.cpp} -using namespace ippl; - -constexpr unsigned int dim = 3; -std::array points = {256, 256, 256}; - -ippl::Index Iinput(points[0]); -ippl::Index Jinput(points[1])); -ippl::Index Kinput(points[2]); -ippl::NDIndex ownedInput(Iinput, Jinput, Kinput); - -// specifies SERIAL, PARALLEL dimensions -std::array isParallel; -isParallel.fill(true); - -ippl::FieldLayout layoutInput(MPI_COMM_WORLD, ownedInput, isParallel); - -double dx = 1.0 / double(points); -Vector hx = {dx, dx, dx}; -Vector origin = {0.0, 0.0, 0.0}; - -UniformCartesian mesh(owned, hx, origin); -Field field(mesh, layout); -@endcode -* -* This example outlines the steps to define a three-dimensional field, specifying its layout and -parallelization strategy. -* - - - - - -* @subsection useful_field_functions Useful Field Functions -* @subsubsection useful_field_ops Mathematical Operations -* @code -// Computes Lp norm of the field. For Max. norm p=0. Default is 2-norm. -auto fieldNorm = norm(field,p); - -// Computes dot product of vector fields (in each element) and returns a scalar field -auto field = dot(vfield, vfield) - -// Innerproduct of two scalar fields and returns a scalar -auto fSquare = innerProduct(field, field); - -// Computes the sum of the field -auto fieldSum = field.sum(); - -// $\int f dV$ computed using midpoint rule -auto fieldVolIntegral = field.getVolumeIntegral(); -* @endcode - - -*@subsubsection field_properties Field Properties -*@code -// Returns the range policy for the fields excluding the ghosts layers. -// If you want to include ghost layers specify nghost as an argument -auto fieldRange = field.getFieldRangePolicy(); - -// Return the number of ghost layers in the field -auto nghost = field.getNghost(); - -// Returns the underyling field layout -auto layout = field.getLayout(); - -// Get the local n-dimension indices from the field layout -auto lDom = layout.getLocalNDIndex(); - -// Get the global domain indices from the field layout -auto gDom = layout.getDomain(); - -// Shallow copy of fields. Changing field2 changes field1 also. -auto field2 = field1; - -// Deep copy of fields. Changing field2 does not change field1. -auto field2 = field1.deepCopy(); -*@endcode - -*@subsubsection field_distributed Parallel Helper Functions -*@code -// Return the underyling Kokkos View of the field -auto fview = field.getView(); - -// Return the Host Mirror corresponding to the Kokkos device view -// of the field. It is a no-op if the field is already on the host. -auto fHostView = field.getHostMirror(); - -// You still have to do a deep copy to get the data from the device to host or vice-versa -Kokkos::deep_copy(fHostView, fview); // device to host -Kokkos::deep_copy(fview, fHostView); // host to device -*@endcode - -* @subsubsection init_field_from_func Initializing a Field from a Function -* @code -const ippl::NDIndex& lDom = fieldLayout.getLocalNDIndex(); -const int nghost = field.getNghost(); -auto fview = field.getView(); - -using index_array_type = typenamep ippl::RangePolicy::index_array_type; - -ippl::parallel_for( - "Assign a field based on func", field.getFieldRangePolicy(), - KOKKOS_LAMBDA(const index_array_type& args) { - // local to global index conversion - Vector xvec = (args + lDom.first() - nghost + 0.5) * hr + origin; - - // ippl::apply accesses the view at the given indices and obtains a - // reference; see src/Expression/IpplOperations.h - ippl::apply(fview, args) = func(xvec); - }); -*@endcode - -- To write dimension independent kernels use the wrappers 'ippl::parallel_for' and -'ippl::parallel_reduce'. -- If you don't want dimension independence in your application then you can just use -'Kokkos::parallel_for' and 'Kokkos::parallel_reduce'. -* @subsubsection boundary_conditions_fields Boundary Conditions for Fields -Setting BCs for fields is a necessary prerequisite before applying differential operators on fields! -Otherwise you will get garbage for the points close to the boundary. -*@code -typedef ippl::BConds, Dim> bc_type; -bc_type bc; -// Available BCs in Ippl see src/Field/BcTypes.h -for(unsigned i = 0; i < 2*Dim; ++i){ - bc[i]= std::make_shared>>(i); -} - -field.setFieldBC(bc); -bc_type BCs = field.getFieldBC(); -* @endcode -* @subsubsection diff_op_fields Differential Operators for Fields -* @code -using mesh_type = ippl::UniformCartesian; -using centering_type = typename mesh_type::DefaultCentering ; -using sfield_type = Field; -using vfield_type = Field, Dim, mesh_type, centering_type>; -using mfield_type = Field , Dim>, Dim, mesh_type, centering_type>; - -sfield_type sfield (field.get_mesh(), field.getLayout()); -vfield_type vfield (field.get_mesh (), field.getLayout ()); -mfield_type mfield (field.get_mesh (), field.getLayout ()); - -// Computes gradient of a scalar field by cell - centered finite difference and returns a vector -field vfield = grad(field); - -// Computes divergence of a vector field by cell - centered finite difference and returns a scalar -field field = div(vfield); - -// Computes curl of a scalar field by cell - centered finite difference and returns a vector field -// Only available in 3 D for the moment -vfield = curl(field); - -// Computes Hessian of a scalar field by cell - centered finite difference and returns a matrix -field -// There is no native matrix data type in ippl so the output field is vector of vectors -mfield = hess(field); - -// Computes Laplacian of a scalar field by cell - centered finite difference and returns a scalar -field . -// At the moment ippl does not do a copy of the original field when you specify the same scalar -field -// in both rhs and lhs . So the user has to allocate a different scalar field for lhs and rhs . -sfield = laplace(field); - -* @endcode - - - -*/ diff --git a/doc/examples/BasicsIndex.hpp b/doc/examples/BasicsIndex.hpp deleted file mode 100644 index 13c87b239..000000000 --- a/doc/examples/BasicsIndex.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/** -@page basic_index Basics: Index and NDIndex - * @section index Introduction - * ## Index - * - * The Index class represents a strided range of indices, and it is used to define the index extent -of Field objects on construction. - * - * **Constructors**: - * - `Index()`: Creates a null interval with no elements. - * - `Index(n)`: Instantiates an Index object representing the range of integers from 0 to n-1 -inclusive, with implied stride 1. - * - `Index(a,b)`: Instantiates an Index object representing the range of integers [a , b], with -implied stride 1. - * - `Index(a,b,s)`: Instantiates an Index object representing the range of integers [a , b], with -stride s. - * - * **Examples**: - * ```cpp - * Index I(10); // Integer set [0..9] - * Index Low(5); // Integer set [0..4] - * Index High(5,9); // Integer set [5..9] - * Index IOdd(1,9,2); // Integer set [1..9] with stride 2 - * Index IEven(0,9,2); // Integer set [0..9] with stride 2 - * ``` - * **Operations**: - * - * Given `Index I(a,n,s)` and an integer `j`, the following operations are possible: - * ```cpp - * I+j : a+j+i*s // For i in [0..n-1] - * j-I : j-a-i*s - * j*I : j*a + i*j*s - * I/j : a/j + i*s/j // Note: j/I is not defined due to non-uniform stride and fraction -prohibition. - * ``` - * - * ## NDIndex - * - * NDIndex is a class that acts as a container for multiple Index instances. It simplifies -operations such as intersections across N dimensions by forwarding requests to its contained Index -objects. - * - @section Example Usage -The following example demonstrates the use of Index and NDIndex classes. -@code -std::array pt = {64, 64, 64}; -ippl::Index Iinput(pt[0]); -ippl::Index Jinput(pt[1]); -ippl::Index Kinput(pt[2]); -ippl::NDIndex ownedInput(Iinput, Jinput, Kinput); - -std::array isParallel; // Specifies SERIAL, PARALLEL dims -isParallel.fill(true); - -ippl::FieldLayout layoutInput(MPI_COMM_WORLD, ownedInput, isParallel); -@endcode - * - * In this example, we define an NDIndex object `ownedInput` with three Index objects `Iinput`, -`Jinput`, and `Kinput`. We then create a FieldLayout object `layoutInput` using the NDIndex object -and a boolean array `isParallel` that specifies the parallel dimensions. - * -*/ \ No newline at end of file diff --git a/doc/examples/BasicsMesh.hpp b/doc/examples/BasicsMesh.hpp deleted file mode 100644 index 0b1989bdf..000000000 --- a/doc/examples/BasicsMesh.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/** -@page basic_mesh Basics: Mesh -*@section mesh Introduction -*The Mesh class in IPPL is a basic class used for creating and handling meshes in simulations. -*It lets you work with meshes of different sizes and types. You can get or set where the mesh starts -(its origin) and find out the size of the grid it covers. *It's set up so other parts of the program -can be updated if the mesh changes, like if it gets bigger or needs to be rearranged. -@section example_usage Example Usage -The following example demonstrates the use of the Mesh class in IPPL: -* @code - using Mesh_t = ippl::UniformCartesian; - - int pt = 25; - ippl::Index I(pt); - ippl::NDIndex owned(I, I, I); - - double dx = 1.0 / double(pt); - ippl::Vector hx = {dx, dx, dx}; - ippl::Vector origin = {0.0, 0.0, 0.0}; - Mesh_t mesh(owned, hx, origin); -* @endcode -In this example, we initialize a 3-dimensional mesh using 25 points in each direction. -We then define the mesh's origin, spacing, and size, and create a Mesh object using these -parameters. -*/ diff --git a/doc/examples/BasicsParticles.hpp b/doc/examples/BasicsParticles.hpp deleted file mode 100644 index 58aa2bc14..000000000 --- a/doc/examples/BasicsParticles.hpp +++ /dev/null @@ -1,191 +0,0 @@ -/** -* @page basic_particle Basics: Particles -* -* Introduction to handling particles in IPPL. -* @section particles Particles in IPPL -* -* IPPL provides a flexible and efficient framework for handling particles in parallel computing -environments. -* -* @subsection particle_concepts Key Concepts -* The core components are `ParticleBase` and `ParticleAttrib` classes, which provide the base -functionality and attributes for particles. -* - `ParticleBase` acts as the abstract base class for a set of particles, requiring a derived class -to specify data attributes (e.g., mass, charge). -* - `ParticleAttrib` represents a single particle attribute, with T indicating the data type. - - -@subsubsection particle_base 'ParticleBase' -* The user must define a class derived from 'ParticleBase' which describes -* what specific data attributes the particle has (e.g., mass or charge). -* 'ParticleBase' is the abstract base class for a set of particles. -* Each attribute is an instance of a ParticleAttribute class; 'ParticleBase' -* keeps a list of pointers to these attributes, and performs particle creation -* and destruction. -* -* 'ParticleBase' is templated on the 'ParticleLayout' mechanism for the particles. -* This template parameter should be a class derived from 'ParticleLayout'. -* 'ParticleLayout'-derived classes maintain the info on which particles are -* located on which processor, and performs the specific communication -* required between processors for the particles. The 'ParticleLayout' is -* templated on the type and dimension of the atom position attribute, and -* 'ParticleBase' uses the same types for these items as the given -* 'ParticleLayout'. -* -* 'ParticleBase' and all derived classes have the following common -* characteristics: -* - The spatial positions of the N particles are stored in the -* particle_position_type variable R -* - The global index of the N particles are stored in the -* particle_index_type variable ID -* - A pointer to an allocated layout class. When you construct a -* 'ParticleBase', you must provide a layout instance, and 'ParticleBase' -* will delete this instance when it (the 'ParticleBase') is deleted. -* -* To use this class, the user defines a derived class with the same -* structure as in this example: -* @code -* class UserParticles : -* public ParticleBase< ParticleSpatialLayout > { -* public: -* // attributes for this class -* ParticleAttribute rad; // radius -* particle_position_type vel; // velocity, same storage type as R -* -* // constructor: add attributes to base class -* UserParticles(ParticleSpatialLayout* L) : ParticleBase(L) { -* addAttribute(rad); -* addAttribute(vel); -* } -* }; -* @endcode -* This example defines a user class with 3D position and two extra -* attributes: a radius rad (double), and a velocity vel (a 3D Vector). - -* @subsubsection particle_attrib ParticleAttrib and ParticleAttribBase - * - * These classes form the foundation for all particle attribute classes within the framework. - * - * ParticleAttrib is a templated class designed to represent a single particle attribute, such as -mass or charge. - * It encapsulates an attribute as a data element within a particle object, stored using a -Kokkos::View for efficient parallel computation. - * This class is essential for handling the type information of the attribute and provides a suite -of methods for creating, destroying, and performing operations on particle attributes. - * - * ParticleAttribBase serves as the generic base class for the templated ParticleAttrib class. - * It provides a common interface for all particle attribute classes, including virtual methods for -creating and destroying elements of the attribute array. - * By encapsulating data for a variable number of particles in a Kokkos::View, it facilitates -operations on this data. - * - * @subsubsection particle_layout ParticleLayout and ParticleSpatialLayout - * - * ParticleLayout manages particle distribution and serves as a base class for -ParticleSpatialLayout. - * - * ParticleSpatialLayout is a derivative of ParticleLayout, ParticleSpatialLayout specifically -handles particle distribution based on spatial positions relative to a predefined grid. - * It ensures particles are processed on the same MPI rank as their corresponding spatial region, -defined by 'FieldLayout'. - * It requires periodic updates to adjust particle locations. - * - - - - - * @subsection particle_example Example: Defining a Particle Bunch - * Here's how you can define a simple particle bunch in IPPL: - * - * @code{.cpp} - * using namespace ippl; - * - * template - * struct Bunch : public ParticleBase { - * ParticleAttrib mass, charge; - * ParticleAttrib> R, V; - * - * Bunch(PLayout& layout) : ParticleBase(layout) { - * // add your own application attributes ! - * this->addAttribute(mass); - * this->addAttribute(charge); - * this->addAttribute(R); - * this->addAttribute(V); - * } - * ~Bunch() = default; - * }; - * // Compiled to single Kokkos Kernel - * bunch->R = bunch->R + dt * bunch->V; - * @endcode - * - * This example demonstrates how to extend `ParticleBase` to create a `Bunch` class that includes -common particle attributes and how to perform a single timestep. - * - * @subsection useful_particle_functions Useful Particle Functions - * Consider bunch a pointer to a derived class 'Bunch' from 'ParticleBase' and has attributes 'R', -'V', - *'mass', 'charge' - * @subsubsection helper_particle_functions Helper Functions - * A collection of essential functions for particle manipulation and attribute management, such as -creation, deletion, and data operations. -@code - // Creates nParticles locally by a core or GPU ( not the total no . of particles ) - bunch->create( nParticles ); - - // Get the local number of particles in that rank ( in ippl there is a one - one correspondence -between - // MPI ranks and GPUs - size_t localnum = bunch->getLocalNum (); - - // Particle deletion Function . invalid is a boolean View - // marking which indices are invalid . destroyNum is the - // total number of invalid particles - bunch->destroy(invalid, destroyNum ); - - // Device and host views and the deep copy operations between them - // similar to fields - Kokkos::deep_copy(bunch->R.getHostMirror(), bunch->R.getView ()); // device to host - Kokkos::deep_copy(bunch->R.getView() , bunch->R.getHostMirror()); // host to device - - // sum () , prod () , min () and max () functions available for - // particle attributes similar to fields - auto Rsum = bunch->R.sum (); -*@endcode -*@subsubsection bdry_condition_particles Boundary Conditions for Particles -* Setting up boundary conditions (e.g., periodic, reflective) for particle simulations. -*@code - -// Types of BCs : PERIODIC , SINK , RFELECTIVE , NO -// Sets periodic BCs in all directions -bunch->setParticleBC(ippl::BC::PERIODIC); - -// Assume a 3D problem -typedef std::array bc_container_type ; -bc_container_type bcs ; - -for ( unsigned int i = 0; i < 4; ++ i ) { - bcs[i] = ippl::BC::NO; -} - -bcs[4] = ippl::BC::PERIODIC; -bcs[5] = ippl::BC::PERIODIC; -// Sets open BCs in x and y directions but periodic in z direction -bunch->setParticleBC( bcs ); -*@endcode -*@subsubsection Interpolation_grid_particles Interpolation between Grid and Particles - * Methods for data transfer between particles and grid, supporting operations like scatter and -gather for efficient particle-field interaction. -*@code -// Particles-> grid -// Can interpolate any particle attribute ( both scalar and vectors ) to the grid . -// Only linear ( cloud - in - cell ) interpolation is available at the moment . -// Interpolate a scalar particle attribute q ( e . g . charge ) onto the field rho . -scatter(bunch->q , rho , this->R); - -// Grid - > particles -// Can interpolate any field ( both scalar and vectors ) to the particles . -// Only linear interpolation is available at the moment . -// Interpolate a vector field E ( e . g . electric field ) to the particles -gather (bunch->E , Efield , this->R); -*@endcode -*/ diff --git a/doc/examples/BasicsSolver.hpp b/doc/examples/BasicsSolver.hpp deleted file mode 100644 index b88784fae..000000000 --- a/doc/examples/BasicsSolver.hpp +++ /dev/null @@ -1,120 +0,0 @@ -/** -@page basic_solver Basics: Solver {#Solver} - -@section solvers Solvers - -Different types of Poisson solvers and a biharmonic solver are available in IPPL. - -Poisson solvers are numerical method used to solve Poisson's equation, a PDE that appears in many -areas of physics. The equation is of the form: - -\f[ - - \nabla^2 \phi = f -\f] - -where \f$\nabla^2 \f$ is the Laplace operator, \f$\phi\f$ is the unknown function, and \f$ f \f$ is -a given function. - -IPPL provides different variants: - -- ippl::FFTPeriodicPoissonSolver: Solves Poisson equation with periodic bcs spectrally -- ippl::FFTOpenPoissonSolver: Solves Poisson equation with Open BCs using FFTs (subtypes: Hockney -(2nd order solver), Vico (spectral solver)) -- ippl::FFTTruncatedGreenSolver: Solves Poisson equation with periodic bcs, based on FFT -- ippl::PoissonCG: Solves Poison equation with Conjugate Gradient method - -All these inherit from the Poisson class. - -The FFT based solvers are not available for 1D as heFFTe doesn't support 1D FFTs. - -For Poisson equation solved with these different types of solvers see: - -- test/solver/TestFFTPeriodicPoissonSolver.cpp (for FFTPeriodicPoissonSolver) -- test/solver/TestGaussian_convergence.cpp (for FFTOpenPoissonSolver) -- test/solver/TestFFTTruncatedGreenSolver.cpp (for FFTTruncatedGreenSolver) -- test/solver/TestCGSolver.cpp (for CG Poisson solver) - -@subsection example_poisson_solver Example: Poisson solver - -This section shows how to use the solvers. This example uses the FFTOpenPoissonSolver. The concepts -used here are the same for the other solvers. -___ - -To start we define the mesh and the field types: -@code -using Mesh_t = ippl::UniformCartesian; -using Centering_t = Mesh_t::DefaultCentering; -typedef ippl::Field field; -typedef ippl::Field, Dim, Mesh_t, Centering_t> fieldV; - - -// .... Define the mesh and the field types .... // - - -// define the R (rho) field -field exact, rho; -exact.initialize(mesh, layout); -rho.initialize(mesh, layout); - -// define the Vector field E (LHS) -fieldV exactE, fieldE; -exactE.initialize(mesh, layout); -fieldE.initialize(mesh, layout); - -@endcode - -Then we need to define the solver type we want to use: -@code -using Solver_t = ippl::FFTOpenPoissonSolver -@endcode -We define the parameters to pass to the solver. Consider the not declared variable to be your choice -for your own simulation: -@code -// Parameter List to pass to solver -ippl::ParameterList params; - -// Set the parameters -params.add("use_pencils", true); // can be true or false -params.add("comm", ippl::a2a); // can be ippl::a2a, ippl::a2av, ippl::p2p, ippl::p2p_pl -params.add("use_reorder", true); // can be true or false -params.add("use_heffte_defaults", false); // can be true or false -params.add("use_gpu_aware", true); // can be true or false -params.add("r2c_direction", 0); // can be 0, 1, 2 -params.add("algorithm", Solver_t::HOCKNEY); // can be Solver_t::HOCKNEY or Solver_t::VICO -params.add("output_type", Solver_t::SOL_AND_GRAD); // can be Solver_t::SOL_AND_GRAD or -Solver_t::SOL_ONLY -@endcode - - - - -Now we can define the solver object and solve the Poisson equation: -@code -Solver_t FFTsolver(fieldE, rho, params); -FFTsolver.solve(); -@endcode -The potential is stored in the rho Field. The E-Field is stored in the fieldE Field. - - -## [Optional] Using a Preconditioner - -If you want to precondition the solver you can add following parameters to the parameter list: -@code -// Define the preconditioner type (jacobi, newton, chebyshev, richardson or gauss_seidel) -params.add("preconditioner_type", preconditioner_type); -// Define the gauss_seidel parameters -params.add("gauss_seidel_inner_iterations", gauss_seidel_inner_iterations); -params.add("gauss_seidel_outer_iterations", gauss_seidel_outer_iterations); -// Define the newton parameters -params.add("newton_level", newton_level); -// Define the chebyshev parameters -params.add("chebyshev_degree", chebyshev_degree); -// Define the richardson parameters -params.add("richardson_iterations", richardson_iterations); -// Define the communication parameters (needed for richardson and gauss_seidel) -params.add("communication", communication); -// Merge the parameters -solver.mergeParameters(params); -@endcode - -*/ diff --git a/doc/examples/CustomPreconditioner.hpp b/doc/examples/CustomPreconditioner.hpp deleted file mode 100644 index ac4e9f261..000000000 --- a/doc/examples/CustomPreconditioner.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/** @page custom_preconditioner Defining Custom Preconditioners - -# Introduction to the Preconditioner Base Class - -The preconditioner class in the IPPL framework serves as an abstract base class for different preconditioning strategies applied in iterative solvers. It encapsulates common functionalities and interfaces that are essential for all types of preconditioners. -Structure of the Preconditioner Base Class - -- Template Parameter: The class template Field determines the type of the numerical field the preconditioner will operate on. -- Constructor: Constructors initialize the preconditioner, optionally setting a type name to identify the preconditioner strategy. -- Virtual Function ('operator()'): This is a pure virtual function in the base class that must be implemented by derived classes to define the specific preconditioning behavior. - -Steps to Create a Custom Preconditioner -## Step 1: Define the Preconditioner Class - -Begin by defining a new class that inherits from the 'preconditioner' provided by the IPPL framework. This new class should implement all abstract methods from the base class and can add additional members as needed for its specific strategy. - -@code -template -struct custom_preconditioner : public preconditioner { - // Additional member variables here - - custom_preconditioner(std::string name = "Custom") : preconditioner(name) { - // Initialization code here - } - - Field operator()(Field& u) override { - // Implementation of preconditioning logic here - return u; // Placeholder return - } -}; -@endcode - -## Step 2: Implement the Constructor - -Use the constructor of your custom preconditioner to initialize any data members and forward any necessary parameters to the base class constructor, which sets the type name of the preconditioner. -## Step 3: Override the Operator Function - -Implement the 'operator()' function to apply your preconditioning logic to the input field. This method is crucial as it defines how the preconditioner modifies the input data, aligning with the specific algorithmic needs of your solver. -# Example Implementations - -## Jacobi Preconditioner - -The 'jacobi_preconditioner' provided by IPPL is a derived class of preconditioner. It implements a specific preconditioning strategy using an inverse diagonal matrix and a damping factor. Here is how it extends the base class: - - -@code -template -struct jacobi_preconditioner : public preconditioner { - InvDiagF inverse_diagonal_m; - double w_m; // Damping factor - - jacobi_preconditioner(InvDiagF&& inverse_diagonal, double w = 1.0) - : preconditioner("Jacobi"), inverse_diagonal_m(std::move(inverse_diagonal)), w_m(w) {} - - Field operator()(Field& u) override { - typename Field::mesh_type& mesh = u.get_mesh(); - typename Field::layout_type& layout = u.getLayout(); - Field res(mesh, layout); - - res = inverse_diagonal_m(u); // Apply inverse diagonal matrix - res = w_m * res; // Apply damping factor - return res; - } -}; -@endcode -## Scaling Preconditioner - -A simple example of a custom preconditioner that scales the input field can be structured as follows: - - -@code -template -struct scaling_preconditioner : public preconditioner { - double scale_factor; - - scaling_preconditioner(double factor = 1.0) - : preconditioner("Scaling"), scale_factor(factor) {} - - Field operator()(Field& u) override { - return scale_factor * u; // Scales the input field - } -}; -@endcode - -# Integration with Solvers - -To utilize your custom preconditioner in a solver, instantiate it and configure the solver to use it. - -*/ \ No newline at end of file diff --git a/doc/examples/CustomSolver.hpp b/doc/examples/CustomSolver.hpp deleted file mode 100644 index 2d6644329..000000000 --- a/doc/examples/CustomSolver.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/** -@page custom_solver Creating Custom Solver - -Here, we'll provide detailed guidelines on how to extend this base class of the 'SolverAlgorithm' to develop your own solver algorithm, -using the PCG (Preconditioned Conjugate Gradient) solver as an example. - -## Introduction to SolverAlgorithm Base Class - -The SolverAlgorithm class is a template abstract class designed to serve as a -foundation for various numerical solver algorithms. -It provides a common interface for solving problems of the form -Op(lhs) = rhs, where Op is a differential operator and lhs and rhs are fields. - -** Key Components of SolverAlgorithm ** -- Template Parameters: The class template parameters FieldLHS and FieldRHS define the types for the left-hand side (LHS) and right-hand side (RHS) of the equation respectively. -- Virtual Function: The operator() function is a pure virtual function that must be implemented by derived classes. It is where the main logic of the solver is implemented. - - -@code -* -#include - -#include "Utility/ParameterList.h" - -namespace ippl { - - template - class SolverAlgorithm { - public: - using lhs_type = FieldLHS; - using rhs_type = FieldRHS; - - /*! - * Solve the problem described by Op(lhs) = rhs, where Op is an unspecified - * differential operator (handled by derived classes) - * @param lhs The problem's LHS - * @param rhs The problem's RHS - * @param params A set of parameters for the solver algorithm - * / - virtual void operator()(lhs_type& lhs, rhs_type& rhs, const ParameterList& params) = 0; - }; - -} // namespace ippl - -@endcode - - -## Steps to Create a Custom Solver -### 1. Define the Solver Class - -Start by defining your solver class that inherits from SolverAlgorithm. Specify any additional data members or methods needed for your solver. - -@code -#include "SolverAlgorithm.h" - -template -class MySolver : public ippl::SolverAlgorithm { - using Base = ippl::SolverAlgorithm; -public: - // Additional methods or data members here - -}; -@endcode -## 2. Implement the Solver Logic - -Implement the operator() function, which contains the core logic for the solver. This function should use the provided lhs, rhs, and params to compute the solution to the problem. - -@code -void operator()(typename Base::lhs_type& lhs, typename Base::rhs_type& rhs, const ParameterList& params) override { - // Initialization and setup - // Iterative solution process - // Post-processing and cleanup -} -@endcode - - -*/ diff --git a/doc/examples/HelloWorld.hpp b/doc/examples/HelloWorld.hpp deleted file mode 100644 index cbe802ed1..000000000 --- a/doc/examples/HelloWorld.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/** -@page hello_world HelloWorld - -This is Hello World in IPPL. - -@code - -const char* TestName = "IPPL_Test"; - -#include "Ippl.h" - -int main(int argc, char* argv[]) { - ippl::initialize(argc, argv); - { - Inform msg(TestName); - - msg << "Hello World" << endl; - } - ippl::finalize(); - - return 0; -} -@endcode - -The executable can be run with the following command-line arguments: -``` -./HelloWorld --info 10 -``` -*/ diff --git a/doc/examples/LandauDampingEx.hpp b/doc/examples/LandauDampingEx.hpp deleted file mode 100644 index 8942edcaf..000000000 --- a/doc/examples/LandauDampingEx.hpp +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @page LandauDamping LandauDamping - - * This is an example demonstrating the setup and execution of a Landau damping simulation using the -IPPL framework. - * - * ### Usage - * The executable can be run with the following command-line arguments: - * ``` - * srun ./LandauDamping [...] --overallocate - --info 10 - * ``` - * - **nx**: Number of cell-centered points in the x-direction. - * - **ny...**: Number of cell-centered points in the y-, z-, ...-direction. - * - **Np**: Total number of macro-particles in the simulation. - * - **Nt**: Number of time steps to execute. - * - **stype**: Field solver type, with FFT and CG (Conjugate Gradient) being supported. - * - **lbthres**: Load balancing threshold. For example, a value of 0.01 means load balancing occurs -if the load imbalance exceeds 1%. - * - **tintegr**: Type of time integrator. For example Leapfrog. - * - **ovfactor**: Over-allocation factor for buffers used in communication. A value of 1.0 means no -over-allocation. - * - * ### Example Command - * ``` - * srun ./LandauDamping 128 128 128 10000 10 FFT 0.01 LeapFrog --overallocate 2.0 --info 10 - * ``` - * This command runs a simulation with a 128x128x128 grid, 10,000 particles, for 10 time steps, -using the FFT solver, - * a load balancing threshold of 1%, with LeapFrog integration, overallocating buffers by a factor -of 2. - * - * ### Implementation Detail - * The main function initializes the Ippl framework, sets up the simulation parameters from -command-line arguments, - * and then creates and configures an instance of `LandauDampingManager` to manage the simulation. -It performs pre-run - * operations to set up the simulation environment and then runs the simulation for the specified -number of time steps. - * Timing information is collected and output for performance analysis. - * @code -constexpr unsigned Dim = 3; -using T = double; -const char* TestName = "LandauDamping"; - -#include "Ippl.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "datatypes.h" - -#include "Utility/IpplTimings.h" - -#include "LandauDampingManager.h" -#include "Manager/PicManager.h" - -int main(int argc, char* argv[]) { - ippl::initialize(argc, argv); - { - - Inform msg(TestName); - Inform msg2all(TestName, INFORM_ALL_NODES); - static IpplTimings::TimerRef mainTimer = IpplTimings::getTimer("total"); - IpplTimings::startTimer(mainTimer); - - -//Parses command-line arguments to set up simulation parameters. -// This segment of code iterates through the command-line arguments provided to the application, -// assigning each parameter to the corresponding variable. These parameters define the -// simulation's grid size, number of particles, number of time steps, solver type, load balancing -// threshold, and overallocation factor. -// - int arg = 1; - Vector_t nr; - for (unsigned d = 0; d < Dim; d++) { - nr[d] = std::atoi(argv[arg++]); - } - size_type totalP = std::atoll(argv[arg++]); - int nt = std::atoi(argv[arg++]); - std::string solver = argv[arg++]; - double lbt = std::atof(argv[arg++]); - std::string step_method = argv[arg++]; - -//Sets up and executes the Landau damping simulation. -// After parsing the input parameters, this code initializes the LandauDampingManager with the -// specified configuration. It then calls pre_run to prepare the simulation environment, sets -// the simulation start time, and executes the simulation for the defined number of time steps. - - - // Create an instance of a manger for the considered application - LandauDampingManager manager(totalP, nt, nr, lbt, solver, step_method); - // Perform pre-run operations, including creating mesh, particles,... - manager.pre_run(); - manager.setTime(0.0); - msg << "Starting iterations ..." << endl; - manager.run(manager.getNt()); - msg << "End." << endl; - - -//Collects timing information and finalizes the simulation. -// Marks the end of the simulation execution, stops the main timer, and outputs timing -// information. This helps in analyzing the performance of the simulation. Finally, it -// calls `ippl::finalize()` to clean up the Ippl framework and gracefully exit the application. - - IpplTimings::stopTimer(mainTimer); - IpplTimings::print(); - IpplTimings::print(std::string("timing.dat")); - } - ippl::finalize(); - - return 0; -} -* @endcode -*/ \ No newline at end of file diff --git a/doc/extras/Basics.md b/doc/extras/Basics.md deleted file mode 100644 index fca574f40..000000000 --- a/doc/extras/Basics.md +++ /dev/null @@ -1,29 +0,0 @@ -Basic Usage of Main IPPL Classes {#Basics} -=============== -Following classes are core components of the IPPL library. The examples are meant to show how to use these classes. - - -# Structure of IPPL - -ippl_structure - - -- [Index](basic_index.html) -- [Mesh](basic_mesh.html) -- [Fields](basics_fields.html) -- [Particles](basic_particle.html) -- [FFT](basics_fft.html) -- [Solver](basic_solver.html) - -**Extras** -- [Creating a Custom Preconditioner](custom_preconditioner.html) -- [Creating a Custom Solver](custom_solver.html) - -# Example Code - -**Hello World in IPPL** -- [HelloWorld](hello_world.html) - -**Case Study of the LandauDamping Manager** -- [LandauDamping](LandauDamping.html) - diff --git a/doc/extras/CodeFormattingSetup.md b/doc/extras/CodeFormattingSetup.md deleted file mode 100644 index cc69678dd..000000000 --- a/doc/extras/CodeFormattingSetup.md +++ /dev/null @@ -1,188 +0,0 @@ -# Code Formatting Setup Guide - -This guide explains how to set up automatic code formatting for IPPL development using the pre-commit git hook. - -## Overview - -IPPL uses two automatic formatters: -- **clang-format-21**: For C/C++ source files (`.c`, `.cc`, `.cpp`, `.cxx`, `.h`, `.hpp`, etc.) -- **cmake-format**: For CMake configuration files (`CMakeLists.txt`, `*.cmake`) - -The pre-commit hook runs these formatters automatically before each commit, ensuring all committed code adheres to the project's styling conventions. - -## 1. Installing clang-format-21 - -### Ubuntu/Debian - -Add the LLVM repository and install clang-format-21: - -```bash -# Add LLVM repository (Ubuntu 20.04+, Debian 11+) -wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - -sudo apt-add-repository "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-21 main" -sudo apt update - -# Install clang-format-21 -sudo apt install clang-format-21 -``` - -Verify the installation: - -```bash -clang-format-21 --version -``` - -Note: If you have `clang-format` installed but it doesn't use the full name `clang-format-21`, then just create a symlink in your `.local` path that redirects `clang-format-21` to your real `clang-format` executable - -### APPLE macOS Tahoe -```bash -brew install llvm@21 -clang-format --version -``` - -### Other Systems - -For other operating systems, visit the [LLVM download page](https://releases.llvm.org/) or use your system's package manager to locate `clang-format` version 21 or later. - -## 2. Installing cmake-format - -cmake-format is a Python package available via pip: - -```bash -# Install cmake-format (Python 3.x required) -pip install cmake-format -``` - -Verify the installation: - -```bash -cmake-format --version -``` - -If you prefer to install it system-wide or in a virtual environment, refer to the [cmake-format documentation](https://cmake-format.readthedocs.io/). - -## 3. Setting Up the Pre-Commit Hook - -### Basic Setup - -The repository includes the git hook script. From the repository root, setup a symlink to the git hook (in the .git/hooks dir): - -```bash -cd /path/to/ippl -ln -s -f ../../scripts/pre-commit .git/hooks/pre-commit -chmod +x .git/hooks/pre-commit -``` -(note that the extra ../../ in the path is because git runs the hook from the .git/hooks directory, so the symlink has to be redirected) - -Alternatively, create a symbolic link manually directly from the git hooks dir: - -```bash -cd /path/to/ippl/.git/hooks -ln -s -f ../../scripts/pre-commit pre-commit -chmod +x pre-commit -``` - -### Verification - -To verify the hook is installed, check that the symlink exists: - -```bash -ls -la /path/to/ippl/.git/hooks/pre-commit -``` - -You should see output similar to: - -``` -lrwxrwxrwx 1 user group 23 Mar 4 12:00 pre-commit -> ../../scripts/pre-commit -``` - -## 4. How the Hook Works - -When you run `git commit`: - -1. The pre-commit hook identifies all staged C/C++ and CMake files -2. For each file, it checks if formatting is needed by comparing the staged content with the formatted version -3. If formatting is needed, the hook: - - Reports which files need reformatting - - Displays the command to fix each file - - Prevents the commit from proceeding -4. Run the suggested command and re-stage the files -5. Retry `git commit` - -Note that we include the command-line parameter `-style=file` in all clang-format commands mentioned here, but this is actually the default and skipping it should not cause problems. Providing there is a `.clang-format` file present in the repository root, all should work as expected. - -### Example Workflow - -```bash -# Make changes and stage them -git add src/myfile.cpp - -# Try to commit -git commit -m "Add feature" - -# If formatting is needed, you'll see: -# clang-format-21 -style=file -i src/myfile.cpp -# Then re-stage and retry -git add src/myfile.cpp -git commit -m "Add feature" -``` - -## 5. Bypassing the Hook - -If you need to commit without running the hook (not recommended), use: - -```bash -git commit --no-verify -``` - -**Warning**: Code committed without formatting may not adhere to project standards. - -## 6. Manual Formatting - -To format files without committing: - -```bash -# Format a single C/C++ file -clang-format-21 -style=file -i src/myfile.cpp - -# Format all C/C++ files in a directory -find src -type f \( -name "*.cpp" -o -name "*.hpp" \) -exec clang-format-21 -style=file -i {} \; - -# Format CMake files -cmake-format -c /path/to/ippl/.cmake-format.py -i CMakeLists.txt -``` - -## 7. Troubleshooting - -### Hook not executing? - -- Verify the script is executable: `chmod +x .git/hooks/pre-commit` -- Verify the symlink points to the correct location: `ls -la .git/hooks/pre-commit` -- Ensure `clang-format-21` and `cmake-format` are in your `$PATH`: `which clang-format-21 cmake-format` - -### Formatting succeeds locally but hook still rejects? - -This is typically due to: -- Different `clang-format-21` versions installed (ensure you have version 21) -- Nested `.clang-format` configuration files in subdirectories that override the root config - -### Path issues on HPC systems? - -If you're on a shared HPC system where multiple compiler modules are available: -- Load the correct module before working: `module load llvm/21` or similar -- Create a symlink to `clang-format` in `~/.local/bin` if module loading is inconvenient - -## 8. Configuration Files - -The formatting behavior is controlled by: - -- **C/C++ formatting**: `.clang-format` (repository root and subdirectories) -- **CMake formatting**: `.cmake-format.py` (repository root) - -These files define all style rules. For detailed customization, refer to: -- [clang-format documentation](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) -- [cmake-format documentation](https://cmake-format.readthedocs.io/) - -## Questions? - -Refer to the main [WORKFLOW.md](../WORKFLOW.md) guide for additional context on IPPL's development practices. diff --git a/doc/extras/IPPLonEULER.md b/doc/extras/IPPLonEULER.md deleted file mode 100644 index 36a243e9f..000000000 --- a/doc/extras/IPPLonEULER.md +++ /dev/null @@ -1,84 +0,0 @@ -# Installing IPPL on EULER {#Installation} - -This guide outlines the steps to install the IPPL library on the EULER cluster. Before beginning, ensure you are connected to the ETH-VPN to access the cluster. - -## Connecting to the EULER Cluster - -Use SSH to connect to EULER. Replace '\' with your actual username. - - ssh -Y @euler.ethz.ch - -The '-Y' flag enables trusted X11 forwarding, necessary for running graphical applications remotely. - -## Preparing the Environment - -_Load the New Software Stack:_ Transition to the new software stack to access the latest dependencies: - - env2lmod - -_Clean the Environment:_ Ensure no previous modules are loaded to avoid conflicts: - - module purge - -_Load Dependencies:_ Load the required modules for IPPL: - - module load gcc/11.4.0 cmake/3.26.3 cuda/12.1.1 openmpi/4.1.4 - -## Cloning the IPPL Library - -Clone the IPPL library from its repository: - - git clone https://github.com/IPPL-framework/ippl.git - -## Building IPPL - -#### Setup a build directory: - - cd ippl - mkdir build - cd build - -#### Create build files - -Choose from the following options based on your needs. If necessary, you can build multiple versions in separate directories. - -**Serial Version** (for single-node computing) - - cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=SERIAL -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON - -**OpenMP Version** (for multi-threaded computing): - - cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=OPENMP -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON - -**Cuda Version** (for GPU computing): - - cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=CUDA -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON -DIPPL_USE_ALTERNATIVE_VARIANT=OFF -DKokkos_ARCH_[architecture]=ON - -[architecture] should be the target architecture, e.g. - -- PASCAL60 -- VOLTA70 -- TURING75 -- AMPERE80 - - -#### Compile - - make - -## Testing Your Installation - -Launch an interactive job on EULER to test your installation: - - srun -n 1 --time=1:00:00 --mem-per-cpu=32g --pty bash - -This command allocates one computing node with 32GB of RAM for 60 minutes. - -**Task** : Execute a miniapp in the '/alpine' folder to verify the installation (don't forget to compile with Make). - - -## Links - -Repository for Independent Parallel Particle Layer (IPPL) - - https://github.com/IPPL-framework/ippl diff --git a/doc/extras/MainPage.md b/doc/extras/MainPage.md deleted file mode 100644 index c26f4d6b2..000000000 --- a/doc/extras/MainPage.md +++ /dev/null @@ -1,14 +0,0 @@ -# Independent Parallel Particle Layer (IPPL) -Independent Parallel Particle Layer (IPPL) is a performance portable C++ library for Particle-Mesh methods. IPPL makes use of Kokkos (https://github.com/kokkos/kokkos), HeFFTe (https://github.com/icl-utk-edu/heffte), and MPI (Message Passing Interface) to deliver a portable, massively parallel toolkit for particle-mesh methods. IPPL supports simulations in one to six dimensions, mixed precision, and asynchronous execution in different execution spaces (e.g. CPUs and GPUs). - -All IPPL releases (< 3.2.0) are available under the BSD 3-clause license. Since version 3.2.0, this repository includes a modified version of the `variant` header by GNU, created to support compilation under CUDA 12.2 with GCC 12.3.0. This header file is available under the same terms as the [GNU Standard Library](https://github.com/gcc-mirror/gcc); note the GNU runtime library exception. As long as this file is not removed, IPPL is available under GNU GPL version 3. - - -# Goals of Independent Parallel Particle Layer (IPPL) -- Open source modern C++ (requires at least C++ 20) library for grid and particle-based methods -- Performance Portability across heterogeneous parallel architectures (different CPUs, GPUs etc.) -- Development of reusable, cross-domain components to enable rapid application development -- Prototyping library for the development of novel numerical methods targeting exascale architectures -- Shorter time from problem inception to working parallel simulations -- Primary application is particle-in-cell methods (backend of production particle accelerator code OPAL) but applicable for other use cases too - diff --git a/doc/extras/Profiling.md b/doc/extras/Profiling.md deleted file mode 100644 index 3ab7c3006..000000000 --- a/doc/extras/Profiling.md +++ /dev/null @@ -1,220 +0,0 @@ -# Profiling in IPPL {#Profiling} - -In certain applications, you might want to use profiling tools for debugging and testing. Since IPPL uses **Kokkos** as a backend, you can leverage Kokkos' built-in profiling tools. - -This guide explains how to use Kokkos' profiling tools, using the **MemoryEvents** tool as an example. - -### Description of MemoryEvents - -MemoryEvents tracks a timeline of allocation and deallocation events in Kokkos Memory Spaces. It records time, pointer, size, memory-space-name, and allocation-name. This is in particular useful for debugging purposes to understand where all the memory is going. - -Additionally, the tool provides a timeline of memory usage for each individual Kokkos Memory Space. - -The tool is located at: https://github.com/kokkos/kokkos-tools/tree/develop/profiling/memory-events - - ---- - -## Steps to Use Kokkos Profiling Tools - -### 1. Clone the Kokkos Tools Repository - -First, clone the Kokkos tools repository, which contains a variety of profiling tools: -``` -git clone https://github.com/kokkos/kokkos-tools -``` - -### 2. Build and Install the Tools - -Navigate into the repository and build the tools using CMake: - -``` -cd kokkos-tools -cmake .. -make -j -sudo make install -``` - -### 3. Set Up the Profiling Tool - -Before running your application, export the Kokkos Tools environment variable to point to the `kp_memory_events.so` tool: -``` -export KOKKOS_TOOLS_LIBS={PATH_TO_TOOL_DIRECTORY}/kp_memory_events.so -``` -Replace `{PATH_TO_TOOL_DIRECTORY}` with the actual path where the tool is located. - - -### 4. Run your Application - -Execute your application normally. The MemoryEvents tool will automatically collect data during execution. For example: - -``` -./application COMMANDS -``` - -### 5. Output Files - -The MemoryEvents tool will generate the following files: - -- `HOSTNAME-PROCESSID.mem_events:` Lists memory events. -- `HOSTNAME-PROCESSID-MEMSPACE.memspace_usage:` Provides a utilization timeline for each active memory space. - -### 6. Example on with SLURM - -Here’s an example of how to run the profiling with a SLURM system using `sbatch`: -``` -sbatch -n 2 --wrap="export KOKKOS_TOOLS_LIBS=$HOME/kokkos-tools/kp_memory_events.so; \ -mpirun -n 2 LandauDamping 128 128 128 10000 10 FFT 0.01 LeapFrog --overallocate 2.0 --info 10" -``` - -In this example: - -- `sbatch -n 2` specifies 2 nodes. -- The Kokkos tool is exported and applied to the `LandauDamping` application. - -This guide provides the basic steps for integrating Kokkos profiling tools into your IPPL-based projects. You can adjust the commands as needed depending on your specific application and environment. - -## Example - -Consider the following code: - -``` -#include - - typedef Kokkos::View a_type; - typedef Kokkos::View b_type; - typedef Kokkos::View c_type; - -int main() { - Kokkos::initialize(); - { - int N = 10000000; - for(int i =0; i<2; i++) { - a_type a("A",N); - { - b_type b("B",N); - c_type c("C",N); - for(int j =0; j). This is useful when debugging N mpi ranks and you want to attach gdb to one or more of them, but can't launch using gdb directly. - -Usually one would attach gdb using a launch command such as this (on a remote machine supporting xterm over X11 for example, to open N xterm windows with gdb attached to one rank in each) -``` -srun -N 1 -n 2 wrapper-script.sh xterm -fn 10x20 -e gdb - -ex='set confirm on' \ - -ex=record \ - -ex=run \ - -ex="set pagination off" \ - --args my/path/to/executable -``` -The extra `-ex` parameters tell gdb to launch the application and start executing and not wait for additional prompting. diff --git a/doc/images/hello_world.png b/doc/images/hello_world.png deleted file mode 100644 index b7b82c5aecb38102331d7630e2e4aacbd7fe6866..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125640 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
1b&RV`4>>Mi^)8p+2QZ;2Prw|X$$ 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

87-|G+rf$n3R}U(A$QluRXpXP2<&= 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 br_e^;wwG#mwG7w={#;klR?feA$N#?oUy0MS diff --git a/doc/images/ippl_structure.jpg b/doc/images/ippl_structure.jpg deleted file mode 100644 index f773cb7c74548bd4232f09ca81cc94aa6b6cadd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116519 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 Date: Thu, 9 Jul 2026 11:10:15 +0000 Subject: [PATCH 3/6] DOC: remove markdown-documentation-files (moved to repo "Manual" --- INSTALLATION.md | 249 ------------------------------------------------ UNIT_TESTS.md | 155 ------------------------------ WORKFLOW.md | 58 ----------- 3 files changed, 462 deletions(-) delete mode 100644 INSTALLATION.md delete mode 100644 UNIT_TESTS.md delete mode 100644 WORKFLOW.md diff --git a/INSTALLATION.md b/INSTALLATION.md deleted file mode 100644 index 6f5a2d14e..000000000 --- a/INSTALLATION.md +++ /dev/null @@ -1,249 +0,0 @@ -All the new developments of IPPL are merged into the `master` branch which can make it potentially unstable from time to time. So if you want a stable and more tested version -please checkout the tagged branch corresponding to the latest release (e.g. `git checkout tags/IPPL-x.x.x`). Otherwise if you want the latest developments go with the master with the above caveat in mind. - -## Requirements - -* [CMake](https://cmake.org/download/) -* A C++ compilation toolchain (GPU-capable for GPU builds, e.g. [nvcc](https://developer.nvidia.com/cuda-downloads), [clang]() or [rocmcc](https://rocm.docs.amd.com/en/docs-5.0.2/reference/rocmcc/rocmcc.html)) -* MPI (GPU-aware if building for GPUs) - -### Optional requirements -* FFTW -* CuFFT - -## Compilation -IPPL is a CMake Project and can be configured by passing options in CMake syntax: -``` -cmake -D