# datafile:SpringOpt.nv

#############################################################################################
# Create some convenient aliases:
#############################################################################################
false = 0
true = 1
null = None

#############################################################################################
# If user chose a Name-Value file, cache all input parameter initial values:
#############################################################################################
if data.has("INPUT"):
	for assign in data.get("INPUT").getValueObj().getAsString().split("\n"):
		if assign.find("=") >= 0:
			nv = assign.split("=")
			blackboard.addEntry(nv[0].strip(),nv[1].strip())

#############################################################################################
# Make a routine to more easily build parameters:
#############################################################################################
def makeParam(name,mode,parent):
	param = DtModelManager.createScalarVariable(name,EsiTypes.REAL,Variable.ROLE_PARAMETER,mode,null,null)
	if mode==Variable.MODE_INPUT and blackboard.hasEntry(name):
		param.getValueObj().setValue(blackboard.getEntry(name))
	parent.addParameter(param)
	return param

#############################################################################################
# Build and configure the driver:
#############################################################################################
springOpt = DtModelManager.createComponent("com.engineous.component.Optimization","Spring Optimization")
SONumberOfCoils = makeParam("NumberOfCoils",Variable.MODE_INPUT,springOpt)
SOCoilDiameter = makeParam("CoilDiameter",Variable.MODE_INPUT,springOpt)
SOWireDiameter = makeParam("WireDiameter",Variable.MODE_INPUT,springOpt)
SOSize = makeParam("Size",Variable.MODE_OUTPUT,springOpt)
SOShearStress = makeParam("ShearStress",Variable.MODE_OUTPUT,springOpt)
SODeflection = makeParam("Deflection",Variable.MODE_OUTPUT,springOpt)
SOWeight = makeParam("Weight",Variable.MODE_OUTPUT,springOpt)
SOSurgeFrequency = makeParam("SurgeFrequency",Variable.MODE_OUTPUT,springOpt)

springOptAPI = springOpt.getAPI()
springOptPlan = springOptAPI.getPlan()

dvNumberOfCoils = springOptPlan.addDesignVariable("NumberOfCoils")
dvNumberOfCoils.setBound(DesignVariable.LOWER_BOUND,0.9999);
dvNumberOfCoils.setBound(DesignVariable.UPPER_BOUND,20.0);
dvCoilDiameter = springOptPlan.addDesignVariable("CoilDiameter")
dvCoilDiameter.setBound(DesignVariable.LOWER_BOUND,0.09999);
dvCoilDiameter.setBound(DesignVariable.UPPER_BOUND,1.0);
dvWireDiameter = springOptPlan.addDesignVariable("WireDiameter")
dvWireDiameter.setBound(DesignVariable.LOWER_BOUND,0.04999);
dvWireDiameter.setBound(DesignVariable.UPPER_BOUND,1.0);

springOptPlan.addConstraint("Size",OutputConstraint.ATTRIBUTE_UPPER_BOUND,0.0);
springOptPlan.addConstraint("ShearStress",OutputConstraint.ATTRIBUTE_UPPER_BOUND,0.0);
springOptPlan.addConstraint("Deflection",OutputConstraint.ATTRIBUTE_UPPER_BOUND,0.0);
springOptPlan.addConstraint("SurgeFrequency",OutputConstraint.ATTRIBUTE_UPPER_BOUND,0.0);

springOptPlan.addObjective("Weight",Objective.MINIMIZE)

springOptPlan.setTechnique("com.engineous.plugin.optimization.HookeJeeves")
springOptTech = springOptPlan.getTechnique()
springOptTech.setOptionValue("Max Evaluations",200,false)
springOptTech.updateOptionValues()

springOptAPI.apply()

#############################################################################################
# Build and configure the driver's workflow component(s):
#############################################################################################
springCalc = DtModelManager.createComponent("com.engineous.component.Calculator","Spring Calc")
SCNumberOfCoils = makeParam("NumberOfCoils",Variable.MODE_INPUT,springCalc)
SCCoilDiameter = makeParam("CoilDiameter",Variable.MODE_INPUT,springCalc)
SCWireDiameter = makeParam("WireDiameter",Variable.MODE_INPUT,springCalc)
SCSize = makeParam("Size",Variable.MODE_OUTPUT,springCalc)
SCShearStress = makeParam("ShearStress",Variable.MODE_OUTPUT,springCalc)
SCDeflection = makeParam("Deflection",Variable.MODE_OUTPUT,springCalc)
SCWeight = makeParam("Weight",Variable.MODE_OUTPUT,springCalc)
SCSurgeFrequency = makeParam("SurgeFrequency",Variable.MODE_OUTPUT,springCalc)

springCalcAPI = springCalc.getAPI()
springCalcAPI.addCalculation("Weight = (NumberOfCoils+2)*CoilDiameter*power(WireDiameter,2)")
springCalcAPI.addCalculation("Deflection = 1.0 - (power(CoilDiameter,3)*NumberOfCoils) / (71875*power(WireDiameter,4))")
springCalcAPI.addCalculation("ShearStress =(4*power(CoilDiameter,2) - WireDiameter*CoilDiameter)/(12566*(CoilDiameter*power(WireDiameter,3) - power(WireDiameter,4)) ) + 1/(5108*power(WireDiameter,2) ) - 1")
springCalcAPI.addCalculation("SurgeFrequency = 1 - 140.45*WireDiameter/( power(CoilDiameter,2)*NumberOfCoils)")
springCalcAPI.addCalculation("Size = (CoilDiameter+WireDiameter)/1.5 - 1")
springCalcAPI.apply()

#############################################################################################
# Assemble the model : replace the old root, build the workflow, create the dataflow
#############################################################################################
DtUtils.changeComponent(model.getRootComponent(),springOpt,false,false)
springOpt.addComponent(springCalc)
springOpt.addControlFlow(DtModelManager.createControlFlow(null,springCalc))
springOpt.addControlFlow(DtModelManager.createControlFlow(springCalc,null))
springOpt.addDataFlow(DtModelManager.createDataFlow(SONumberOfCoils,SCNumberOfCoils))
springOpt.addDataFlow(DtModelManager.createDataFlow(SOCoilDiameter,SCCoilDiameter))
springOpt.addDataFlow(DtModelManager.createDataFlow(SOWireDiameter,SCWireDiameter))
springOpt.addDataFlow(DtModelManager.createDataFlow(SCSize,SOSize))
springOpt.addDataFlow(DtModelManager.createDataFlow(SCShearStress,SOShearStress))
springOpt.addDataFlow(DtModelManager.createDataFlow(SCDeflection,SODeflection))
springOpt.addDataFlow(DtModelManager.createDataFlow(SCWeight,SOWeight))
springOpt.addDataFlow(DtModelManager.createDataFlow(SCSurgeFrequency,SOSurgeFrequency))
