#=============================================================================
# Monolithic FE^2
# Nils Lange, Geralf Huetter, Bjoern Kiefer
#   Nils.Lange@imfd.tu-freiberg.de, Geralf.Huetter@imfd.tu-freiberg.de, 
#   Bjoern.Kiefer@imfd.tu-freiberg.de
# distributed under CC BY-NC-SA 4.0 license
# (https://creativecommons.org/licenses/by-nc-sa/4.0/)
# Reference: 
#   N. Lange, G. Huetter, B. Kiefer: "An efficient monolithic solution scheme for FE2 problems",
#   https://arxiv.org/abs/2101.01802
#
# Further information on the implementation, structure of the source code,
# examples and tutorials can be found in the file doc/documentation.pdf
#
#=============================================================================

from abaqus import *	#import abaqus functionalities
from abaqusConstants import *
import odbAccess

def generate_postprocessing_data(macro_odbName,macro_partName, element,
								 integration_point,micro_modelName,
								 micro_partName,source):

	strains=['SDV1','SDV2','SDV3','SDV4','SDV5','SDV6','SDV7','SDV8','SDV9'] #strains (resp. displacement gradient) are written in the solution dependend variables array
	strain_dict={'SDV1':'E11','SDV2':'E22','SDV3':'E33','SDV4':'E12','SDV5':'E21','SDV6':'E23','SDV7':'E32','SDV8':'E13','SDV9':'E31'}
	#strains symmetric: if source=='E'
	strain_symm={'E11':'E11','E22':'E22','E33':'E33','E12':'E12','E21':'E12','E13':'E13','E31':'E13','E23':'E23','E31':'E13'}

	data_error=0

	for i in range(9):
		#extract the strains from the odb
		if source=='SDV':
			try:
				data=session.xyDataListFromField(odb=session.odbs[macro_odbName], outputPosition=INTEGRATION_POINT, 
				variable=((strains[i], INTEGRATION_POINT), ), elementLabels=((element.instanceName,element.label),))
			except:
				raise Exception('No SDV odb data created by MonolithFE2 was found!')
		else:
			try:
				data=session.xyDataListFromField(odb=session.odbs[macro_odbName], outputPosition=INTEGRATION_POINT, 
				variable=(('E', INTEGRATION_POINT, ((COMPONENT, strain_dict[strains[i]]), )), ), elementLabels=((element.instanceName,element.label),))
			except:
				pass
		#create the Amplitudes
		if source=='SDV':
			try: #try to create amplitude data for the selected integration point
				data=session.xyDataObjects[strains[i]+' PI: '+str(element.instanceName)+' E: '+str(element.label)+' IP: '+str(integration_point)]
				amplitude=mdb.models[micro_modelName].TabularAmplitude(name=strain_dict[strains[i]],data=[tup for tup in data])
				print 'Amplitude for '+strain_dict[strains[i]]+' created.'
			except: #raise error if the integration point does not exist
				delete_xydata_SDV()
				raise Exception('Integration point does not exist!')
		else:
			try: #try to create amplitude data for the selected integration point
				data=session.xyDataObjects['E:'+strain_symm[strain_dict[strains[i]]]+' PI: '+str(element.instanceName)+' E: '+str(element.label)+' IP: '+str(integration_point)]
				amplitude=mdb.models[micro_modelName].TabularAmplitude(name=strain_dict[strains[i]],data=[tup for tup in data])
				print 'Amplitude for '+strain_dict[strains[i]]+' created.'
			except:
				amplitude=mdb.models[micro_modelName].TabularAmplitude(name=strain_dict[strains[i]],data=[(0.0,0.0),(1000000.0,0.0)])
				data_error=data_error+1
			
	delete_xydata_SDV()
	
	if (source=='E' and data_error==9):
		raise Exception('No data could be extracted from strain E!')
			
def delete_xydata_SDV():
	#delete all the created xy-Data
	getridkeys=session.xyDataObjects.keys()
	for i in range(len(getridkeys)):
		del session.xyDataObjects[getridkeys[i]] 
