xref: /petsc/src/sys/tutorials/ex3f90.F90 (revision c5e229c2f66f66995aed5443a26600af2aec4a3f)
12dfe2926SJacob Faibussowitsch!
22dfe2926SJacob Faibussowitsch!
32dfe2926SJacob Faibussowitsch!   Description: Demonstrates how users can augment the PETSc profiling by
42dfe2926SJacob Faibussowitsch!                inserting their own event logging.
52dfe2926SJacob Faibussowitsch!
62dfe2926SJacob Faibussowitsch#include <petsc/finclude/petscsys.h>
72dfe2926SJacob Faibussowitsch#include <petsc/finclude/petsclog.h>
8*c5e229c2SMartin Diehlprogram SchoolDay
92dfe2926SJacob Faibussowitsch  use petscmpi  ! or mpi or mpi_f08
102dfe2926SJacob Faibussowitsch  use petscsys
112dfe2926SJacob Faibussowitsch  implicit none
122dfe2926SJacob Faibussowitsch
132dfe2926SJacob Faibussowitsch  ! Settings:
142dfe2926SJacob Faibussowitsch  integer, parameter        :: verbose = 0               ! 0: silent, >=1 : increasing amount of debugging output
152dfe2926SJacob Faibussowitsch  integer, parameter        :: msgLen = 30             ! number of reals which is sent with MPI_Isend
16ccfd86f1SBarry Smith  PetscReal, parameter      :: second = 0.1             ! time is sped up by a factor 10
172dfe2926SJacob Faibussowitsch
182dfe2926SJacob Faibussowitsch  ! Codes
192dfe2926SJacob Faibussowitsch  integer, parameter        :: BOY = 1, GIRL = 2, TEACHER = 0
20ccfd86f1SBarry Smith  PetscMPIInt, parameter    :: tagMsg = 1200
212dfe2926SJacob Faibussowitsch
222dfe2926SJacob Faibussowitsch  ! Timers
232dfe2926SJacob Faibussowitsch  PetscLogEvent :: Morning, Afternoon
242dfe2926SJacob Faibussowitsch  PetscLogEvent :: PlayBall, SkipRope
252dfe2926SJacob Faibussowitsch  PetscLogEvent :: TidyClass
262dfe2926SJacob Faibussowitsch  PetscLogEvent :: Lessons, CorrectHomework
272dfe2926SJacob Faibussowitsch  PetscClassId classid
282dfe2926SJacob Faibussowitsch
292dfe2926SJacob Faibussowitsch  ! Petsc-stuff
302dfe2926SJacob Faibussowitsch  PetscErrorCode            :: ierr
312dfe2926SJacob Faibussowitsch
322dfe2926SJacob Faibussowitsch  ! MPI-stuff
332dfe2926SJacob Faibussowitsch  PetscMPIInt              :: rank, size
342dfe2926SJacob Faibussowitsch  PetscReal, allocatable    :: message(:, :)
352dfe2926SJacob Faibussowitsch  integer                   :: item, maxItem
362dfe2926SJacob Faibussowitsch  integer4                  :: status(MPI_STATUS_SIZE)
372dfe2926SJacob Faibussowitsch  PetscMPIInt req
38cb9ef012SToby Isaac  integer(c_int) msgLen_c_int
392dfe2926SJacob Faibussowitsch
402dfe2926SJacob Faibussowitsch  ! Own stuff
412dfe2926SJacob Faibussowitsch  integer4                  :: role                 ! is this process a BOY, a GIRL or a TEACHER?
422dfe2926SJacob Faibussowitsch  integer4                  :: i, j
432dfe2926SJacob Faibussowitsch  integer4, parameter        :: one = 1
44f8402805SBarry Smith
452dfe2926SJacob Faibussowitsch!     Initializations
46d8606c27SBarry Smith  PetscCallA(PetscInitialize(ierr))
47f8402805SBarry Smith  PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr))
48f8402805SBarry Smith  PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr))
492dfe2926SJacob Faibussowitsch
502dfe2926SJacob Faibussowitsch  if (rank == 0) then
512dfe2926SJacob Faibussowitsch    role = TEACHER
522dfe2926SJacob Faibussowitsch  else if (rank < 0.4*size) then
532dfe2926SJacob Faibussowitsch    role = GIRL
542dfe2926SJacob Faibussowitsch  else
552dfe2926SJacob Faibussowitsch    role = BOY
562dfe2926SJacob Faibussowitsch  end if
572dfe2926SJacob Faibussowitsch
582dfe2926SJacob Faibussowitsch  allocate (message(msgLen, msglen))
592dfe2926SJacob Faibussowitsch  do i = 1, msgLen
602dfe2926SJacob Faibussowitsch    do j = 1, msgLen
612dfe2926SJacob Faibussowitsch      message(i, j) = 10.0*j + i*1.0/(rank + one)
622dfe2926SJacob Faibussowitsch    end do
632dfe2926SJacob Faibussowitsch  end do
642dfe2926SJacob Faibussowitsch!
652dfe2926SJacob Faibussowitsch!     Create new user-defined events
662dfe2926SJacob Faibussowitsch  classid = 0
67f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Morning', classid, Morning, ierr))
68f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Afternoon', classid, Afternoon, ierr))
69f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Play Ball', classid, PlayBall, ierr))
70f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Skip Rope', classid, SkipRope, ierr))
71f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Tidy Classroom', classid, TidyClass, ierr))
72f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Lessons', classid, Lessons, ierr))
73f8402805SBarry Smith  PetscCallA(PetscLogEventRegister('Correct Homework', classid, CorrectHomework, ierr))
742dfe2926SJacob Faibussowitsch  if (verbose >= 1) then
752dfe2926SJacob Faibussowitsch    print '(a,i0,a)', '[', rank, '] SchoolDay events have been defined'
762dfe2926SJacob Faibussowitsch  end if
772dfe2926SJacob Faibussowitsch
782dfe2926SJacob Faibussowitsch!     Go through the school day
79f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Morning, ierr))
802dfe2926SJacob Faibussowitsch
81f8402805SBarry Smith  PetscCallA(PetscLogFlops(190000d0, ierr))
82f8402805SBarry Smith  PetscCallA(PetscSleep(0.5*second, ierr))
832dfe2926SJacob Faibussowitsch
84f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
85f8402805SBarry Smith  PetscCallA(PetscLogFlops(23000d0, ierr))
86f8402805SBarry Smith  PetscCallA(PetscSleep(1*second, ierr))
872dfe2926SJacob Faibussowitsch  if (size > 1) then
88d8606c27SBarry Smith    PetscCallMPIA(MPI_Isend(message, msgLen, MPI_DOUBLE_PRECISION, mod(rank + 1, size), tagMsg + rank, PETSC_COMM_WORLD, req, ierr))
89d8606c27SBarry Smith    PetscCallMPIA(MPI_Recv(message, msgLen, MPI_DOUBLE_PRECISION, mod(rank - 1 + size, size), tagMsg + mod(rank - 1 + size, size), PETSC_COMM_WORLD, status, ierr))
90f8402805SBarry Smith    PetscCallMPIA(MPI_Wait(req, MPI_STATUS_IGNORE, ierr))
91cb9ef012SToby Isaac    msgLen_c_int = msgLen
92cb9ef012SToby Isaac    ierr = PetscASend(msgLen_c_int, MPI_DOUBLE_PRECISION)
93cb9ef012SToby Isaac    ierr = PetscARecv(msgLen_c_int, MPI_DOUBLE_PRECISION)
942dfe2926SJacob Faibussowitsch  end if
95f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
962dfe2926SJacob Faibussowitsch
972dfe2926SJacob Faibussowitsch  if (role == TEACHER) then
98f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(TidyClass, ierr))
99f8402805SBarry Smith    PetscCallA(PetscLogFlops(600000d0, ierr))
100f8402805SBarry Smith    PetscCallA(PetscSleep(0.6*second, ierr))
101f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(CorrectHomework, ierr))
102f8402805SBarry Smith    PetscCallA(PetscLogFlops(234700d0, ierr))
103f8402805SBarry Smith    PetscCallA(PetscSleep(0.4*second, ierr))
104f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(CorrectHomework, ierr))
105f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(TidyClass, ierr))
1062dfe2926SJacob Faibussowitsch  else if (role == BOY) then
107f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(SkipRope, ierr))
108f8402805SBarry Smith    PetscCallA(PetscSleep(0.8*second, ierr))
109f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(SkipRope, ierr))
1102dfe2926SJacob Faibussowitsch  else
111f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(PlayBall, ierr))
112f8402805SBarry Smith    PetscCallA(PetscSleep(0.9*second, ierr))
113f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(PlayBall, ierr))
1142dfe2926SJacob Faibussowitsch  end if
1152dfe2926SJacob Faibussowitsch
116f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
117f8402805SBarry Smith  PetscCallA(PetscLogFlops(120000d0, ierr))
118f8402805SBarry Smith  PetscCallA(PetscSleep(0.7*second, ierr))
119f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
1202dfe2926SJacob Faibussowitsch
121f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Morning, ierr))
1222dfe2926SJacob Faibussowitsch
123f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Afternoon, ierr))
1242dfe2926SJacob Faibussowitsch
1252dfe2926SJacob Faibussowitsch  item = rank*(3 - rank)
126f8402805SBarry Smith  PetscCallMPIA(MPI_Allreduce(item, maxItem, 1, MPI_INTEGER, MPI_MAX, PETSC_COMM_WORLD, ierr))
127cb9ef012SToby Isaac  ierr = PetscAReduce()
1282dfe2926SJacob Faibussowitsch
1292dfe2926SJacob Faibussowitsch  item = rank*(10 - rank)
130f8402805SBarry Smith  PetscCallMPIA(MPI_Allreduce(item, maxItem, 1, MPI_INTEGER, MPI_MAX, PETSC_COMM_WORLD, ierr))
131cb9ef012SToby Isaac  ierr = PetscAReduce()
1322dfe2926SJacob Faibussowitsch
133f8402805SBarry Smith  PetscCallA(PetscLogFlops(58988d0, ierr))
134f8402805SBarry Smith  PetscCallA(PetscSleep(0.6*second, ierr))
1352dfe2926SJacob Faibussowitsch
136f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
137f8402805SBarry Smith  PetscCallA(PetscLogFlops(123456d0, ierr))
138f8402805SBarry Smith  PetscCallA(PetscSleep(1*second, ierr))
139f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
1402dfe2926SJacob Faibussowitsch
1412dfe2926SJacob Faibussowitsch  if (role == TEACHER) then
142f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(TidyClass, ierr))
143f8402805SBarry Smith    PetscCallA(PetscLogFlops(17800d0, ierr))
144f8402805SBarry Smith    PetscCallA(PetscSleep(1.1*second, ierr))
145f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(Lessons, ierr))
146f8402805SBarry Smith    PetscCallA(PetscLogFlops(72344d0, ierr))
147f8402805SBarry Smith    PetscCallA(PetscSleep(0.5*second, ierr))
148f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(Lessons, ierr))
149f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(TidyClass, ierr))
1502dfe2926SJacob Faibussowitsch  else if (role == GIRL) then
151f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(SkipRope, ierr))
152f8402805SBarry Smith    PetscCallA(PetscSleep(0.7*second, ierr))
153f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(SkipRope, ierr))
1542dfe2926SJacob Faibussowitsch  else
155f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(PlayBall, ierr))
156f8402805SBarry Smith    PetscCallA(PetscSleep(0.8*second, ierr))
157f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(PlayBall, ierr))
1582dfe2926SJacob Faibussowitsch  end if
1592dfe2926SJacob Faibussowitsch
160f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
161f8402805SBarry Smith  PetscCallA(PetscLogFlops(72344d0, ierr))
162f8402805SBarry Smith  PetscCallA(PetscSleep(0.5*second, ierr))
163f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
1642dfe2926SJacob Faibussowitsch
165f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Afternoon, ierr))
1662dfe2926SJacob Faibussowitsch
1672dfe2926SJacob Faibussowitsch  if (.false.) then
1682dfe2926SJacob Faibussowitsch    continue
1692dfe2926SJacob Faibussowitsch  else if (role == TEACHER) then
170f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(TidyClass, ierr))
171f8402805SBarry Smith    PetscCallA(PetscLogFlops(612300d0, ierr))
172f8402805SBarry Smith    PetscCallA(PetscSleep(1.1*second, ierr))
173f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(TidyClass, ierr))
174f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(CorrectHomework, ierr))
175f8402805SBarry Smith    PetscCallA(PetscLogFlops(234700d0, ierr))
176f8402805SBarry Smith    PetscCallA(PetscSleep(1.1*second, ierr))
177f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(CorrectHomework, ierr))
1782dfe2926SJacob Faibussowitsch  else
179f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(SkipRope, ierr))
180f8402805SBarry Smith    PetscCallA(PetscSleep(0.7*second, ierr))
181f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(SkipRope, ierr))
182f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(PlayBall, ierr))
183f8402805SBarry Smith    PetscCallA(PetscSleep(0.8*second, ierr))
184f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(PlayBall, ierr))
1852dfe2926SJacob Faibussowitsch  end if
1862dfe2926SJacob Faibussowitsch
187f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
188f8402805SBarry Smith  PetscCallA(PetscLogFlops(120000d0, ierr))
189f8402805SBarry Smith  PetscCallA(PetscSleep(0.7*second, ierr))
190f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
1912dfe2926SJacob Faibussowitsch
192f8402805SBarry Smith  PetscCallA(PetscSleep(0.25*second, ierr))
1932dfe2926SJacob Faibussowitsch
194f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Morning, ierr))
1952dfe2926SJacob Faibussowitsch
196f8402805SBarry Smith  PetscCallA(PetscLogFlops(190000d0, ierr))
197f8402805SBarry Smith  PetscCallA(PetscSleep(0.5*second, ierr))
1982dfe2926SJacob Faibussowitsch
199f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
200f8402805SBarry Smith  PetscCallA(PetscLogFlops(23000d0, ierr))
201f8402805SBarry Smith  PetscCallA(PetscSleep(1*second, ierr))
2022dfe2926SJacob Faibussowitsch  if (size > 1) then
203d8606c27SBarry Smith    PetscCallMPIA(MPI_Isend(message, msgLen, MPI_DOUBLE_PRECISION, mod(rank + 1, size), tagMsg + rank, PETSC_COMM_WORLD, req, ierr))
204d8606c27SBarry Smith    PetscCallMPIA(MPI_Recv(message, msgLen, MPI_DOUBLE_PRECISION, mod(rank - 1 + size, size), tagMsg + mod(rank - 1 + size, size), PETSC_COMM_WORLD, status, ierr))
205f8402805SBarry Smith    PetscCallMPIA(MPI_Wait(req, MPI_STATUS_IGNORE, ierr))
206cb9ef012SToby Isaac    msgLen_c_int = msgLen
207cb9ef012SToby Isaac    ierr = PetscASend(msgLen_c_int, MPI_DOUBLE_PRECISION)
208cb9ef012SToby Isaac    ierr = PetscARecv(msgLen_c_int, MPI_DOUBLE_PRECISION)
2092dfe2926SJacob Faibussowitsch  end if
210f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
2112dfe2926SJacob Faibussowitsch
2122dfe2926SJacob Faibussowitsch  if (role == TEACHER) then
213f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(TidyClass, ierr))
214f8402805SBarry Smith    PetscCallA(PetscLogFlops(600000d0, ierr))
215f8402805SBarry Smith    PetscCallA(PetscSleep(1.2*second, ierr))
216f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(TidyClass, ierr))
2172dfe2926SJacob Faibussowitsch  else if (role == BOY) then
218f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(SkipRope, ierr))
219f8402805SBarry Smith    PetscCallA(PetscSleep(0.8*second, ierr))
220f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(SkipRope, ierr))
2212dfe2926SJacob Faibussowitsch  else
222f8402805SBarry Smith    PetscCallA(PetscLogEventBegin(PlayBall, ierr))
223f8402805SBarry Smith    PetscCallA(PetscSleep(0.9*second, ierr))
224f8402805SBarry Smith    PetscCallA(PetscLogEventEnd(PlayBall, ierr))
2252dfe2926SJacob Faibussowitsch  end if
2262dfe2926SJacob Faibussowitsch
227f8402805SBarry Smith  PetscCallA(PetscLogEventBegin(Lessons, ierr))
228f8402805SBarry Smith  PetscCallA(PetscLogFlops(120000d0, ierr))
229f8402805SBarry Smith  PetscCallA(PetscSleep(0.7*second, ierr))
230f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Lessons, ierr))
2312dfe2926SJacob Faibussowitsch
232f8402805SBarry Smith  PetscCallA(PetscLogEventEnd(Morning, ierr))
2332dfe2926SJacob Faibussowitsch
2342dfe2926SJacob Faibussowitsch  deallocate (message)
2352dfe2926SJacob Faibussowitsch
236f8402805SBarry Smith  PetscCallA(PetscFinalize(ierr))
2372dfe2926SJacob Faibussowitschend program SchoolDay
2382dfe2926SJacob Faibussowitsch
2392dfe2926SJacob Faibussowitsch!/*TEST
2402dfe2926SJacob Faibussowitsch!
2412dfe2926SJacob Faibussowitsch! testset:
2422dfe2926SJacob Faibussowitsch!   suffix: no_log
2432dfe2926SJacob Faibussowitsch!   requires: !defined(PETSC_USE_LOG)
2442dfe2926SJacob Faibussowitsch!   test:
2452dfe2926SJacob Faibussowitsch!     suffix: ascii
246758f5028SMatthew G. Knepley!     args: -log_view ascii:filename.txt -log_all
2472dfe2926SJacob Faibussowitsch!   test:
2482dfe2926SJacob Faibussowitsch!     suffix: detail
2492dfe2926SJacob Faibussowitsch!     args: -log_view ascii:filename.txt:ascii_info_detail
2502dfe2926SJacob Faibussowitsch!   test:
2512dfe2926SJacob Faibussowitsch!     suffix: xml
2522dfe2926SJacob Faibussowitsch!     args: -log_view ascii:filename.xml:ascii_xml
2532dfe2926SJacob Faibussowitsch!
2542dfe2926SJacob Faibussowitsch! testset:
2552dfe2926SJacob Faibussowitsch!   args: -log_view ascii:filename.txt
2563886731fSPierre Jolivet!   output_file: output/empty.out
2572dfe2926SJacob Faibussowitsch!   requires: defined(PETSC_USE_LOG)
2582dfe2926SJacob Faibussowitsch!   test:
2592dfe2926SJacob Faibussowitsch!     suffix: 1
2602dfe2926SJacob Faibussowitsch!     nsize: 1
2612dfe2926SJacob Faibussowitsch!   test:
2622dfe2926SJacob Faibussowitsch!     suffix: 2
2632dfe2926SJacob Faibussowitsch!     nsize: 2
2642dfe2926SJacob Faibussowitsch!   test:
2652dfe2926SJacob Faibussowitsch!     suffix: 3
2662dfe2926SJacob Faibussowitsch!     nsize: 3
2672dfe2926SJacob Faibussowitsch!
2682dfe2926SJacob Faibussowitsch! testset:
2692dfe2926SJacob Faibussowitsch!   suffix: detail
2702dfe2926SJacob Faibussowitsch!   args: -log_view ascii:filename.txt:ascii_info_detail
2713886731fSPierre Jolivet!   output_file: output/empty.out
2722dfe2926SJacob Faibussowitsch!   requires: defined(PETSC_USE_LOG)
2732dfe2926SJacob Faibussowitsch!   test:
2742dfe2926SJacob Faibussowitsch!     suffix: 1
2752dfe2926SJacob Faibussowitsch!     nsize: 1
2762dfe2926SJacob Faibussowitsch!   test:
2772dfe2926SJacob Faibussowitsch!     suffix: 2
2782dfe2926SJacob Faibussowitsch!     nsize: 2
2792dfe2926SJacob Faibussowitsch!   test:
2802dfe2926SJacob Faibussowitsch!     suffix: 3
2812dfe2926SJacob Faibussowitsch!     nsize: 3
2822dfe2926SJacob Faibussowitsch!
2832dfe2926SJacob Faibussowitsch! testset:
2842dfe2926SJacob Faibussowitsch!   suffix: xml
2852dfe2926SJacob Faibussowitsch!   args: -log_view ascii:filename.xml:ascii_xml
2863886731fSPierre Jolivet!   output_file: output/empty.out
2872dfe2926SJacob Faibussowitsch!   requires: defined(PETSC_USE_LOG)
2882dfe2926SJacob Faibussowitsch!   test:
2892dfe2926SJacob Faibussowitsch!     suffix: 1
2902dfe2926SJacob Faibussowitsch!     nsize: 1
2912dfe2926SJacob Faibussowitsch!   test:
2922dfe2926SJacob Faibussowitsch!     suffix: 2
2932dfe2926SJacob Faibussowitsch!     nsize: 2
2942dfe2926SJacob Faibussowitsch!   test:
2952dfe2926SJacob Faibussowitsch!     suffix: 3
2962dfe2926SJacob Faibussowitsch!     nsize: 3
2972dfe2926SJacob Faibussowitsch!
2982dfe2926SJacob Faibussowitsch!TEST*/
299