# MR , Version g6, 12.06.2015

from mpi4py import MPI
import bmp
import numpy as np
import matplotlib.pyplot as plt

welt   = MPI.COMM_WORLD
nummer = MPI.COMM_WORLD.Get_rank()
name   = MPI.Get_processor_name()
status = MPI.Status()

#
spalten = 1024   # x, Realteil
zeilen  = 1024   # y, Imaginaerteil
MAX_ITER= 1025 # 256
RE_MIN  = -0.088 #-2.0
RE_MAX  = -0.085 # 2.0
IM_MIN  = 0.856 # -2.0
IM_MAX  = 0.859 # 2.0

job_anzahl = np.zeros( welt.Get_size(), dtype=np.int16 )
#interactive:>plt.ion()

if welt.Get_rank() == 0:        # Master
    # init Bild
    bild = np.zeros( (zeilen,spalten) )
    #sehr langsam:>plt.imshow( bild , vmin=10, vmax=555 , cmap='gray') 
    #plt.show()
    aktive_sklaven      = 0
    naechste_zeilen_nr  = 0
    # los geht's: Auftraege an alle Sklaven
    for sklave in range( 1, welt.Get_size() ):
        welt.send( naechste_zeilen_nr, dest = sklave )
        naechste_zeilen_nr = naechste_zeilen_nr + 1  # naechste Zeile
        aktive_sklaven     = aktive_sklaven + 1
	
    # Master-Schleife
    while aktive_sklaven > 0:
        puffer = welt.recv( source=MPI.ANY_SOURCE, status=status )
        zeile, bildzeile = puffer
        sklaven_id = status.Get_source() # so erfahre ich woher das Ergebnis kommt
        #print(sklaven_id)
        job_anzahl[sklaven_id] += 1
        # speicher die Bildzeile im Bild 
        bild[zeile] = bildzeile
    	#sehr langsam:>plt.imshow( bild , vmin=10, vmax=555 , cmap='gray') 
    	#plt.draw()
        if naechste_zeilen_nr < zeilen:
            # neuer Auftrag an diesen Skalven
            welt.send( naechste_zeilen_nr, sklaven_id) 
            naechste_zeilen_nr += 1
        else:
            # schicke negative Zeilennummer (-1), um Ende zu symbolisieren
            welt.send( -1, sklaven_id )
            aktive_sklaven = aktive_sklaven - 1
 
    # Statistik
    for sklaven_id in range( 1, welt.Get_size() ):
        print("{0:5d} Arbeiten durch Sklave {1:3d} erledigt".format( job_anzahl[sklaven_id], sklaven_id ) )
    # plot  nur am Ende, da sonst SEHR langsam
    plt.imshow( bild , vmin=10, vmax=888 , cmap='gray')
    plt.show()
 
else:
    # Sklave
    while True:
        # welche Zeile
        zeilennummer = welt.recv( source=0 )
        # noch weiter, oder fertig
        if zeilennummer < 0:
            break
        # berechne Bildzeile
        bildzeile = np.zeros( spalten) # 
 
        # 1j = imaginaere Einheit
        c_im = ( IM_MAX - IM_MIN ) *1j * zeilennummer / zeilen + IM_MIN * 1j
        for x in range( spalten ):
	    # und hier der Realteil
            c =  c_im + ( RE_MAX - RE_MIN ) * x / spalten + RE_MIN 
	    z = 0
	    for iter in range(MAX_ITER):
	      z = z * z + c
	      if abs(z) >= 2.0:
		break  
	    
	    bildzeile[x] = iter - 1
        # sende Ergebnis an Master
        welt.send( [zeilennummer, bildzeile], 0 )