# Yield targeting

from definitions import *
from pyopus.design.yt import YieldTargeting
from pyopus.evaluator.aggregate import formatParameters
# If MPI is imported an application not using MPI will behave correctly
# (i.e. only slot 0 will run the program) even when started with mpirun/mpiexec
from pyopus.parallel.mpi import MPI
from pyopus.parallel.cooperative import cOS


if __name__=='__main__':
	atDesign={
		# Result of design across corners
		  'c_out':   3.4227551453164880e-13, 
		 'diff_l':   7.4308192182875534e-07, 
		 'diff_w':   1.2789110397149770e-06, 
		 'load_l':   2.1097689639936013e-06, 
		 'load_w':   2.3180449555941561e-06, 
		 'mirr_l':   4.0529113121872304e-07, 
		'mirr_ld':   1.3311984218957902e-06, 
		 'mirr_w':   3.4036562767439648e-05, 
		'mirr_wd':   2.3745920801687639e-06, 
		'mirr_wo':   2.1285465666785311e-05, 
		  'out_l':   5.3631175887258056e-07, 
		  'out_w':   2.6406246699146450e-05, 
		  'r_out':   3.0372450962642072e+00, 
	}
	
	# Create corner with the Monte Carlo model
	corners={
		'mc': {
			'params': {}, 
			'modules': [ 'mc' ]
		}
	}
	
	# Remove transient analysis measures, design with DC and AC measures only
	#for name in ['tsetup', 'tsetdn', 'slewup', 'slewdn', 'overshup', 'overshdn' ]:
	#	del measures[name]
		
	# Worst case performances (skip area, phase_slope)
	wcList=list(measures.keys())
	wcList.sort()
	wcList.remove('area')
	wcList.remove('ph_slope')
	
	# Prepare parallel environment
	cOS.setVM(MPI(mirrorMap={'*':'.'}))
	
	# CBD settings
	initialCbdOptions={ 
		'debug': 1, 'method': 'global', 'stepTol': 1e-5, 
		'norms': { 'area': 100e-12, 'vgs_drv': 1e-3, 'vds_drv':1e-3 }, 
		'failurePenalty': 1e6, 
		'tradeoffs': 1e-6, 
		'stopWhenAllSatisfied': True, 
	}
	
	# CBD settings for second and later passes
	cbdOptions={}
	cbdOptions.update(initialCbdOptions)
	# cbdOptions['method']='local'
	
	wcOptions={
		'stepTol': 0.01, 
		'debug': 0, 
	}
	
	# 3-sigma target yield
	yt=YieldTargeting(
		designParams, statParams, opParams, 
		heads, analyses, measures, corners, variables=variables, 
		beta=3.0, wcSpecs=wcList, 
		# Comment out start with initial point (lo+hi)/2 and perform initial nominal design
		initial=atDesign, initialNominalDesign=False, 
		# Initial nominal optimization
		initialCbdOptions=initialCbdOptions, 
		# First pass optiomation
		firstPassCbdOptions=initialCbdOptions, 
		# Main optimization
		cbdOptions=cbdOptions, 
		# Worst-case analysis
		wcOptions=wcOptions, 
		debug=2, spawnerLevel=1
	)
	atDesign, agg, wc, anCount = yt()
	print(formatParameters(atDesign))
	print(wc.formatResults())
	if agg is not None:
		print(agg.formatResults())
	print(anCount)
	
	# Finalize cOS parallel environment
	cOS.finalize()
	
# Result 
#           c_out:   6.5735996965011167e-13
#          diff_l:   1.1277590722388212e-06
#          diff_w:   7.4072078256213562e-06
#          load_l:   3.0190507158551772e-06
#          load_w:   7.1447511221840934e-06
#          mirr_l:   3.0463894159204191e-07
#         mirr_ld:   2.6572354878028799e-06
#          mirr_w:   1.7060021214780366e-05
#         mirr_wd:   4.1333975797905747e-06
#         mirr_wo:   2.6823400824029106e-05
#           out_l:   3.2878440134599452e-07
#           out_w:   1.5489295777951712e-05
#           r_out:   3.5673408168082747e+03

