c
c host.f  91/21/11 21:15:04
c
c This program calculates the value of pi, using numerical integration
c with parallel processing, and clocks the solution time.
c
c The user selects the number of processors and the number of points
c of integration.  By selecting and timing different cube sizes you
c obtain a measure of the speedup with perfectly parallel problems.
c
c
c   Program Components:
c
c   Constants:
c
c	TOP 		Network interconnection topology; 1 = Hypercube
c			(2 = Full connectivity, 3 = unidirectional ring, 4 = bidirectional ring)
c	ORD		Order of nodes in a ring; 1 = Gray code; 0 = Natural ordering
c               	ORD is ignored for the hypercube topology (TOP = 1)
c	DIR		Orientatoin of an unidirectional ring; 1 = forward; -1 = backward
c               	DIR is ignored for the hypercube topology (TOP = 1)
c
c	INITTYPE	Type of initial message sent from host to nodes
c	MSGSIZE 	Size of initial message
c	PARTTYPE	Type of message holding partial integrals 
c	TIMETYPE	Type of message holding timing information from the node
c	TIMESIZE	Size of timing message
c	ALLNODES	(= -1) Argument to represent all nodes				
c
c   Variables:
c
c	points		Number of points used in the integration. Input by the user
c	a		Lower limit of integration
c	b		Upper limit of integration
c	integral 	Calculated integral
c	msg		Message sent to the nodes. Holds a, b, & points
c
c	NPROCS		Cubesize to be used. Input by the user
c	ME		My processor ID number 
c	HOST		Host processor ID number
c
c	starttime	Starting time on the host
c	host_sec	Total running time on the host
c	node_sec 	Computation time on the node
c
c   Calls:
c
c	userinpt        to get integration parameters from user
c	open0		to enable interprocessor communication 
c	load0		to load program onto nodes
c	setarch0	to setup the number of node processors and interconnection topology	
c	clock0		to obtain the system clock in seconds
c	bcast0		to broadcast a message
c	gsum0		to compute the componentwise sum of a distributed set of vectors
c	close0		to disable interprocessor communication
c	traceenable     to open tracefile and enable tracing 

	program host

c
c	Include header file with PICL call declarations
c
	include 'picl_def.h'

 	external  userinpt
	integer*4 userinpt

	integer*4 INITTYPE, MSGSIZE, PARTTYPE, TIMESIZE, TIMETYPE

	integer*4 points, i
	integer*4 msg(5)

        integer*4 NPROCS, ALLNODES, TOP, ORD, DIR, ME, HOST

        double precision host_sec, node_sec
	double precision  integral, a, b
        double precision starttime
c
c	equivalence a, b, and points to elements of msg
c
	equivalence (msg(1), a)
	equivalence (msg(3), b)
	equivalence (msg(5), points)

	data 	  TOP /1/,
     >            ORD /1/,
     >            DIR /1/,
     >		  INITTYPE /5/, 
     >		  MSGSIZE /20/, 
     >		  ALLNODES /-1/, 
     >		  PARTTYPE /20/,
     >            TIMETYPE /10/,
     >            TIMESIZE /8/


c
c       Receive number of processors to be used and integration parameters from the user
c
100	i = userinpt(a,b,points,NPROCS)
	if (i.le.0) go to 200

c
c       Open tracefile and use Paragraph format
c
cc      call  traceenable("tracefile",0)

c
c	Allocate requested processors and enable interprocessor communication
c	Must be called on host and node
c	If requested number of processors not available - error msg reported and program exits
c	On host returns host's ID number
c
        call open0(NPROCS, ME, HOST)

c
c	Load node program onto the specified node; -1 implies all nodes
c
   	print *, 'LOADING THE CUBE ...' 
        call  load0("node",ALLNODES)

c
c       Setup the allocated processors in a Hypercube topology
c	Should be called by the host and the nodes
c
        call setarc0(NPROCS, TOP, ORD, DIR)

c
c 	Start the clock running
c
        starttime = clock0()

c
c 	Host broadcasts integration parameters to the nodes
c
        call bcast0(msg, MSGSIZE, INITTYPE, HOST)

c
c	Compute the sum of the partial integral from the nodes and 
c	return in into "integral" on the host
c
        call gsum0(integral,1,5,PARTTYPE,HOST)

c
c	Calculate execution time on the host
c
	host_sec = clock0() - starttime

c
c	Receive timing information from the node
c
        call recv0(node_sec, TIMESIZE, TIMETYPE)

c
c	Output results
c
	write(6, 110) integral
110	format('  pi is approximately : ', F18.16)

        print  *, 'time on node = ',node_sec
        print  *, 'time on host = ',host_sec

c
c	Disable interprocessor communication; release all allocated processors
c
        call close0(1)

	goto 100

200	continue

	end
