"""
#Job
	Methods for submitting a job and getting the relevant data from the 
	completed simulation. Note that running lots of simulations will generate
	huge amounts of data. For this reason each job file defaults to having the
	same name, so the data is overwritten each iteration. The information
	relevant to our experiment is written to a text file before the data is
	lost. 


	submitJob(fileName="Job-1") returns warningString and noElementsDistorted.
		*Input: 
			fileName: String to default to "Job-1". Name of the odb file.
		*Output:
			warningString: String containing "*" if warning encountered or 
				'' if nothing.
			noElementsDistorted : The number of distorted elements in the sim.
	
	EXAMPLE:
		warningString = submitJob()
		warningString = submitJob("Job-10")
	
	getThermalProperties opens the odb file generated by abaqus and calculates 
	the thermal conductivity by averaging the heat flux at the top and bottom 
	faces of the matrix and multiplying by the side length divided by the
	temperature difference. It returns the average heat flux and the thermal
	conductivity. 2D and 3D versions.
	
	getThermalProperties() returns avgHeatFlux and thermalCond
		*Input:
			None
		*Output: 
			avgHeatFlux: Numeric value of the average heat flux
			thermalCond: Numeric value of the thermal conductivity k.
			
	Example:
		avgHF, TC = getThermalProperties()
		
	dataString method is for outputing the appropriate information about each model to be easily written to file.
	
	dataString(matrixUsed, materialUsed, phrVal) returns a string containing relevant information about the model.
		*Input:
			matrixUsed: String containing the matrix material name
			materialUsed: String containing the particle filler material name.
			fillerPortion: Numeric value corresponding to either PHR or volume portion. Depending on paper used!
		*Output:
			String containing matrixUsed, materialUsed, fillerPortion, radius, number, side, randomSeed, numNodes,
			avgHF, temperature difference, TC, and the warningString
	
	Example:
		f.write(dataString("ESBR", "Alumina", 0.40))
"""

from odbAccess import *
from abaqus import mdb
from job import session
import abaqusConstants as aq

# SEPERATE INTO TWO METHODS
def submitJob(modelName, fileName="Job-1"):
	mdb.Job(atTime=None, contactPrint=aq.OFF, description='', echoPrint=aq.OFF, 
		explicitPrecision=aq.SINGLE, getMemoryFromAnalysis=True, historyPrint=aq.OFF, 
		memory=90, memoryUnits=aq.PERCENTAGE, model=modelName, modelPrint=aq.OFF, 
		multiprocessingMode=aq.DEFAULT, name=fileName, nodalOutputPrecision=aq.SINGLE, 
		numCpus=1, queue=None, scratch='', type=aq.ANALYSIS, userSubroutine='', 
		waitHours=0, waitMinutes=0)
	mdb.jobs[fileName].submit(consistencyChecking=aq.OFF)
	mdb.jobs[fileName].waitForCompletion()
	
	noElementsWarning = 0
	warningString = ''
	for ii in mdb.jobs[fileName].messages:
		if ii.type == aq.WARNING:
			warningString = '*'
			datmsg = ii.data
			if datmsg.has_key('message'):
				datstr = datmsg['message']
				nudat = datstr.split()
				noElementsWarning = nudat[0]
			
			break
		
		
	
	return warningString, noElementsWarning


# Get data 
def getThermalProperties2D(side, temp1, temp2, fileName='Job-1'):
	
	odb = session.openOdb(fileName+'.odb')
	lastFrame = odb.steps['applyHeat'].frames[-1]
	hfl = lastFrame.fieldOutputs['HFL']
	bottoms = odb.rootAssembly.instances['PART1'].elementSets['BOTTOM']
	tops = odb.rootAssembly.instances['PART1'].elementSets['TOP']
	bottomHFL = hfl.getSubset(region=bottoms)
	topHFL = hfl.getSubset(region=tops)
	botVals = bottomHFL.values
	topVals = topHFL.values
	sumsVals = 0.0
	count = 0.0
	
	for val1 in botVals:
		sumsVals = sumsVals + val1.magnitude
		count = count + 1.0
	
	for val2 in topVals:
		sumsVals = sumsVals + val2.magnitude
		count = count + 1.0 
	
	side1 = side * 10 ** -6
	avgHeatFlux = sumsVals / count
	thermalCond = avgHeatFlux * side1 / (temp1-temp2)
	del odb
	return int(round(avgHeatFlux, -1)), round(thermalCond, 4)

def dataString2D(matrix, filler, portion, radius, number, side, seed, nodes, elements,
	avgHF, temp1, temp2, TC, warningString, warningPoints):
	
	return matrix+'\t'+filler+'\t'+str(portion)+'\t'+str(radius)+'\t'+str(number)+'\t'+str(side)+'\t'+str(seed)+'\t'+str(nodes)+'\t'+str(elements)+'\t'+str(avgHF)+'\t'+str(temp1-temp2)+'\t'+str(TC)+'\t'+warningString+warningPoints+'\n'

def dataString(matrixUsed, materialUsed, fillerPortion, radius, number, side, 
	interfaceSize, deltaMinDist, calcPortion, interfaceConduct, randomSeed, nodes, elements, df,
	meshSeed, avgHF, temp1, temp2, TC, warningString, warningPoints,
	noElementsWarning):
	
	
	return matrixUsed+'\t'+materialUsed+'\t'+str(fillerPortion)+'\t'+str(radius)+'\t'+str(number)+'\t'+str(side)+'\t'+str(interfaceSize)+'\t'+str(deltaMinDist)+'\t'+str(calcPortion)+'\t'+str(interfaceConduct)+'\t'+str(randomSeed)+'\t'+str(nodes)+'\t'+str(elements)+'\t'+str(df)+'\t'+ str(meshSeed)+'\t'+str(avgHF)+'\t'+str(temp1-temp2)+'\t'+str(TC)+'\t'+str(noElementsWarning)+'\t'+warningString+warningPoints+'\n'

# Not general enough for different jobs
def getThermalProperties3D(matrixSide, temp1, temp2, fileName="Job-1"):
	import odbAccess
	odb = session.openOdb(name=fileName+'.odb')
	lastFrame = odb.steps['Step-1'].frames[-1]
	hfl = lastFrame.fieldOutputs['HFL']
	bottoms = odb.rootAssembly.instances['MATRIXFULL-1'].elementSets['BOT']
	tops = odb.rootAssembly.instances['MATRIXFULL-1'].elementSets['TOP']
	bottomHFL = hfl.getSubset(region=bottoms)
	topHFL = hfl.getSubset(region=tops)
	botVals = bottomHFL.values
	topVals = topHFL.values
	sumsVals = 0.0
	count = 0.0
	for val1 in botVals: # Sum bottom values 
		sumsVals = sumsVals + val1.magnitude
		count = count + 1.0
	
	for val2 in topVals: # Sum top values 
		sumsVals = sumsVals + val2.magnitude
		count = count + 1.0 
	
	side = matrixSide * 10 ** -6
	avgHeatFlux = sumsVals / count
	thermalCond = avgHeatFlux * side / (temp1-temp2)
	return int(round(avgHeatFlux, -1)), round(thermalCond, 4)

def createJob(modelName, fileName='Job-1'):
	mdb.Job(atTime=None, contactPrint=aq.OFF, description='', echoPrint=aq.OFF, 
		explicitPrecision=aq.SINGLE, getMemoryFromAnalysis=True, historyPrint=aq.OFF, 
		memory=90, memoryUnits=aq.PERCENTAGE, model=modelName, modelPrint=aq.OFF, 
		multiprocessingMode=aq.DEFAULT, name=fileName, nodalOutputPrecision=aq.SINGLE, 
		numCpus=1, queue=None, scratch='', type=aq.ANALYSIS, userSubroutine='', 
		waitHours=0, waitMinutes=0)
	return mdb.jobs[fileName]


def generateINP(fileName='Job-1'):
	mdb.jobs[fileName].writeInput(consistencyChecking=aq.TRUE)

def paraStudyDirectories():
	import os
	if not os.path.exists("inpFiles"):
		os.makedirs("inpFiles")

def simDir(id):
	import os
	if not os.path.exists("inpFiles"):
		if not os.path.exists("inpFiles/"+str(id)):
			os.makedirs("inpFiles/"+str(id))