• Nenhum resultado encontrado

This is a non-linear simulation problem. Using at least two integrating processors and MPI allows more values of the parameters to be studied in a given time than with a single processor. This code is valuable as a study guide when an application needs to estimate timing and other output parameters. The simulation time is controlled at the root node. An integration is started, after receiving results, within the first

SIM_TIME

seconds. The elapsed time will be longer than

SIM_TIME

by the slowest processor’s time for its last integration.

program PDE_1D_MG_EX09

! Electrodynamics Model, parameter study.

USE PDE_1d_mg USE MPI_SETUP_INT USE RAND_INT USE SHOW_INT IMPLICIT NONE INCLUDE "mpif.h"

INTEGER, PARAMETER :: NPDE=2, N=21

INTEGER I, IDO, IERROR, CONTINUE, STATUS(MPI_STATUS_SIZE) INTEGER, ALLOCATABLE :: COUNTS(:)

! Define array space for the solution.

real(kind(1d0)) :: U(NPDE+1,N), T0, TOUT

real(kind(1d0)) :: ZERO=0D0, ONE=1D0,DELTA_T=10D0, TEND=4D0

! SIM_TIME is the number of seconds to run the simulation.

real(kind(1d0)) :: EPS, P, ETA, Z, TWO=2D0, THREE=3D0, SIM_TIME=60D0

real(kind(1d0)) :: TIMES, TIMEE, TIMEL, TIME, TIME_SIM, V_MIN, DATA(5)

real(kind(1d0)), ALLOCATABLE :: AV_TIME(:), MAX_TIME(:) TYPE(D_OPTIONS) IOPT(4), SHOW_IOPT(2)

IMSL MATH/LIBRARY Chapter 5: Differential Equations · 943 TYPE(S_OPTIONS) SHOW_INTOPT(2)

MP_NPROCS=MP_SETUP(1)

MPI_NODE_PRIORITY=(/(I-1,I=1,MP_NPROCS)/)

! If NP_NPROCS=1, the program stops. Change

! MPI_ROOT_WORKS=.TRUE. if MP_NPROCS=1.

MPI_ROOT_WORKS=.FALSE.

IF(.NOT. MPI_ROOT_WORKS .and. MP_NPROCS == 1) STOP ALLOCATE(AV_TIME(MP_NPROCS), MAX_TIME(MP_NPROCS), COUNTS(MP_NPROCS))

! Get time start for simulation timing.

TIME=MPI_WTIME()

IF(MP_RANK == 0) OPEN(FILE='PDE_ex09.out',UNIT=7) SIMULATE: DO

! Pick random parameter values.

EPS=1D-1*(ONE+rand(EPS)) P=1D-1*(ONE+rand(P)) ETA=10D0*(ONE+rand(ETA))

! Start loop to integrate and communicate solution times.

IDO=1

! Get time start for each new problem.

DO

IF(.NOT. MPI_ROOT_WORKS .and. MP_RANK == 0) EXIT SELECT CASE (IDO)

! Define values that determine limits.

CASE (1) T0=ZERO TOUT=1D-3

U(NPDE+1,1)=ZERO;U(NPDE+1,N)=ONE IOPT(1)=PDE_1D_MG_MAX_BDF_ORDER IOPT(2)=5

IOPT(3)=D_OPTIONS(PDE_1D_MG_RELATIVE_TOLERANCE,1D-2) IOPT(4)=D_OPTIONS(PDE_1D_MG_ABSOLUTE_TOLERANCE,1D-2) TIMES=MPI_WTIME()

! Update to the next output point.

! Write solution and check for final point.

CASE (2)

T0=TOUT;TOUT=TOUT*DELTA_T IF(T0 >= TEND) IDO=3 TOUT=MIN(TOUT, TEND)

! All completed. Solver is shut down.

CASE (3)

TIMEE=MPI_WTIME() EXIT

! Define initial data values.

CASE (5)

U(1,:)=1D0;U(2,:)=0D0

! Define differential equations.

CASE (6)

D_PDE_1D_MG_C=0D0;D_PDE_1D_MG_C(1,1)=1D0;D_PDE_1D_MG_C(2,2)=1D0 D_PDE_1D_MG_R=P*D_PDE_1D_MG_DUDX

D_PDE_1D_MG_R(1)=D_PDE_1D_MG_R(1)*EPS

Z=ETA*(D_PDE_1D_MG_U(1)-D_PDE_1D_MG_U(2))/THREE D_PDE_1D_MG_Q(1)=EXP(Z)-EXP(-TWO*Z)

944 · Chapter 5: Differential Equations IMSL MATH/LIBRARY D_PDE_1D_MG_Q(2)=-D_PDE_1D_MG_Q(1)

! Define boundary conditions.

CASE (7)

IF(PDE_1D_MG_LEFT) THEN

D_PDE_1D_MG_BETA(1)=1D0;D_PDE_1D_MG_BETA(2)=0D0

D_PDE_1D_MG_GAMMA(1)=0D0;D_PDE_1D_MG_GAMMA(2)=D_PDE_1D_MG_U(2) ELSE

D_PDE_1D_MG_BETA(1)=0D0;D_PDE_1D_MG_BETA(2)=1D0 D_PDE_1D_MG_GAMMA(1)=D_PDE_1D_MG_U(1)-

1D0;D_PDE_1D_MG_GAMMA(2)=0D0 END IF END SELECT

! Reverse communication is used for the problem data.

CALL PDE_1D_MG (T0, TOUT, IDO, U) END DO

TIMEL=TIMEE-TIMES

DATA=(/EPS, P, ETA, U(2,N), TIMEL/) IF(MP_RANK > 0) THEN

! Send parameters and time to the root.

CALL MPI_SEND(DATA, 5, MPI_DOUBLE_PRECISION,0, MP_RANK, MP_LIBRARY_WORLD, IERROR)

! Receive back a "go/stop" flag.

CALL MPI_RECV(CONTINUE, 1, MPI_INTEGER, 0, MPI_ANY_TAG, MP_LIBRARY_WORLD, STATUS, IERROR)

! If root notes that time is up, it sends node a quit flag.

IF(CONTINUE == 0) EXIT SIMULATE ELSE

! If root is working, record its result and then stand ready

! for other nodes to send.

IF(MPI_ROOT_WORKS) WRITE(7,*) MP_RANK, DATA

! If all nodes have reported, then quit.

IF(COUNT(MPI_NODE_PRIORITY >= 0) == 0) EXIT SIMULATE

! See if time is up. Some nodes still must report.

IF(MPI_WTIME()-TIME >= SIM_TIME) THEN CONTINUE=0

ELSE

CONTINUE=1 END IF

! Root receives simulation data and finds which node sent it.

IF(MP_NPROCS > 1) THEN CALL MPI_RECV(DATA, 5,

MPI_DOUBLE_PRECISION,MPI_ANY_SOURCE, MPI_ANY_TAG, MP_LIBRARY_WORLD, STATUS, IERROR)

WRITE(7,*) STATUS(MPI_SOURCE), DATA

! If time at the root has elapsed, nodes receive signal to stop.

! Send the reporting node the "go/stop" flag.

! Mark if a node has been stopped.

CALL MPI_SEND(CONTINUE, 1, MPI_INTEGER, STATUS(MPI_SOURCE), 0, MP_LIBRARY_WORLD, IERROR)

IF (CONTINUE == 0)

MPI_NODE_PRIORITY(STATUS(MPI_SOURCE)+1) =- MPI_NODE_PRIORITY(STATUS(MPI_SOURCE)+1)-1 END IF

IF (CONTINUE == 0) MPI_NODE_PRIORITY(1)=-1

IMSL MATH/LIBRARY Chapter 5: Differential Equations · 945 END IF

END DO SIMULATE IF(MP_RANK == 0) THEN

ENDFILE(UNIT=7);REWIND(UNIT=7)

! Read the data. Find extremes and averages.

MAX_TIME=ZERO;AV_TIME=ZERO;COUNTS=0;V_MIN=HUGE(ONE) DO

READ(7,*, END=10) I, DATA COUNTS(I+1)=COUNTS(I+1)+1

AV_TIME(I+1)=AV_TIME(I+1)+DATA(5)

IF(MAX_TIME(I+1) < DATA(5)) MAX_TIME(I+1)=DATA(5) V_MIN=MIN(V_MIN, DATA(4))

END DO 10 CONTINUE CLOSE(UNIT=7)

! Set printing Index to match node numbering.

SHOW_IOPT(1)= SHOW_STARTING_INDEX_IS SHOW_IOPT(2)=0

SHOW_INTOPT(1)=SHOW_STARTING_INDEX_IS SHOW_INTOPT(2)=0

CALL SHOW(MAX_TIME,"Maximum Integration Time, per process:",IOPT=SHOW_IOPT)

AV_TIME=AV_TIME/MAX(1,COUNTS)

CALL SHOW(AV_TIME,"Average Integration Time, per process:",IOPT=SHOW_IOPT)

CALL SHOW(COUNTS,"Number of Integrations",IOPT=SHOW_INTOPT)

WRITE(*,"(1x,A,F6.3)") "Minimum value for v(x,t),at x=1,t=4: ",V_MIN

END IF

MP_NPROCS=MP_SETUP("Final") end program

946 · Chapter 5: Differential Equations IMSL MATH/LIBRARY