### This script will read data from an excel file, run the model based on that
### data and write the result data to another excel file
### The code is commented to explain the concepts.

### Besides basic python knowledge, if you feel you are helpless in generating
### code related to ABAQUS, just perform the action through the UI
### and read the JNL file generated in the working directory. ABAQUS by-default
### creates python code for each and every step performed through
### UI

# Import all the the relevant modules, based on your requirement



from part import *
from material import *
from section import *
from assembly import *
from step import *
from interaction import *
from load import *
from mesh import *
from optimization import *
from job import *
from sketch import *
from visualization import *
from connectorBehavior import *

import os 
# change the abaqus working directory
os.chdir('E://rahul')

### This step might require some tweaking to work.
### Openpyxl doesnt ship with the standard abaqus python installation, so the
### suggested work-around is to install the version of python that your abaqus
### version comes with, this changes with your abaqus version. Generally 2.x
### Just run "python -v" on the the python interpreter inside abaqus to find
### this version. Now install the same version python on your system, by
### downloading from https://www.python.org/downloads/
### Once you have python installed on your system, you can install openpyxl, or
### any other library that you are interested in.
### Then copy the folder openpyxl from %python_install_dir%/lib/site-packages
### to the abaqus python installation, which is usually located at
### C:\SIMULIA\Abaqus\6.12-1\tools\SMApy\Lib\site-packages
### You might also have to copy jdcal from your system's python site-packages
### folder.

# import openpyxl for excel manupulation

from openpyxl import load_workbook

# Reading an excel file - load workbook at the specified location
wb = load_workbook(filename = "E://rahul//inputdynamic.xlsx")

# Select the worksheet you want to read, active means first
ws = wb.active

# Here, iterating through rows, reading each one, one at a time
for j in range(0, len(ws.rows)): 
    #pass
    width_beam  = float(ws.rows[j][0].value)
    height_beam = float(ws.rows[j][1].value) 
    length_beam = float(ws.rows[j][2].value) 
    nel = float(ws.rows[j][3].value)

    # This code is auto-generated by abaqus, although it can be
    # simplified and made more readable as explained in the API documentation

    mdb.models['Model-1'].ConstrainedSketch(name='__profile__', sheetSize=200.0)

    # First use of our parameters, rather than a fixed numerical value,
    # width and height defined as in excel file

    mdb.models['Model-1'].sketches['__profile__'].rectangle(point1=(0.0, 0.0), 
        point2= (width_beam, height_beam))
    mdb.models['Model-1'].Part(dimensionality=THREE_D, name='Part-1', type=
        DEFORMABLE_BODY)
    mdb.models['Model-1'].parts['Part-1'].BaseSolidExtrude(depth=length_beam, sketch=
        mdb.models['Model-1'].sketches['__profile__'])
    del mdb.models['Model-1'].sketches['__profile__']
    mdb.models['Model-1'].Material(name='Material-1')
    mdb.models['Model-1'].materials['Material-1'].Density(table=((1000.0, ), ))
    mdb.models['Model-1'].materials['Material-1'].Elastic(table=((100000000000.0, 
        0.2), ))
    mdb.models['Model-1'].HomogeneousSolidSection(material='Material-1', name=
        'Section-1', thickness=None)
    mdb.models['Model-1'].parts['Part-1'].SectionAssignment(offset=0.0, 
        offsetField='', offsetType=MIDDLE_SURFACE, region=Region(
        cells=mdb.models['Model-1'].parts['Part-1'].cells.getSequenceFromMask(
        mask=('[#1 ]', ), )), sectionName='Section-1', thicknessAssignment=
        FROM_SECTION)
    mdb.models['Model-1'].rootAssembly.DatumCsysByDefault(CARTESIAN)
    mdb.models['Model-1'].rootAssembly.Instance(dependent=ON, name='Part-1-1', 
        part=mdb.models['Model-1'].parts['Part-1'])
    mdb.models['Model-1'].FrequencyStep(name='Step-1', numEigen=12, previous=
        'Initial')
    mdb.models['Model-1'].parts['Part-1'].seedPart(deviationFactor=0.1, 
        minSizeFactor=0.1, size=(length_beam/nel))
    mdb.models['Model-1'].parts['Part-1'].generateMesh()
    mdb.models['Model-1'].parts['Part-1'].setElementType(elemTypes=(ElemType(
        elemCode=C3D8R, elemLibrary=STANDARD, secondOrderAccuracy=OFF, 
        kinematicSplit=AVERAGE_STRAIN, hourglassControl=DEFAULT, 
        distortionControl=DEFAULT), ElemType(elemCode=C3D6, elemLibrary=STANDARD), 
        ElemType(elemCode=C3D4, elemLibrary=STANDARD)), regions=(
        mdb.models['Model-1'].parts['Part-1'].cells.getSequenceFromMask(('[#1 ]', 
        ), ), ))
    mdb.models['Model-1'].rootAssembly.regenerate()
    mdb.models['Model-1'].EncastreBC(createStepName='Step-1', localCsys=None, name=
        'BC-1', region=Region(
        faces=mdb.models['Model-1'].rootAssembly.instances['Part-1-1'].faces.getSequenceFromMask(
        mask=('[#10 ]', ), )))
    mdb.Job(atTime=None, contactPrint=OFF, description='', echoPrint=OFF, 
        explicitPrecision=SINGLE, getMemoryFromAnalysis=True, historyPrint=OFF, 
        memory=50, memoryUnits=PERCENTAGE, model='Model-1', modelPrint=OFF, 
        multiprocessingMode=DEFAULT, name='Job_dyn', nodalOutputPrecision=SINGLE, 
        numCpus=1, numGPUs=0, queue=None, scratch='', type=ANALYSIS, 
        userSubroutine='', waitHours=0, waitMinutes=0)

    # Job submitted for running
    mdb.jobs['Job_dyn'].submit(consistencyChecking=OFF)

    # Wait for completion, as the result file will generated only after running,
    # so code should stop here
    mdb.jobs['Job_dyn'].waitForCompletion()

    ##############################   RESULT EXTRACTION ########################

    from openpyxl import Workbook

    # define an empty workbook
    wbo = Workbook()

    # Create a worksheet at the specified location, 0 means beginning
    wso = wbo.create_sheet(0)


    # Import abaqus odb work related modules
    from odbAccess import *
    
    # Read the odb file, change name and path as per your requirement
    odb = openOdb(path='vibration.odb')

    ### This is a typical procedure to read history-outputs, as 
    ### frequency etc. information is not available as field output

    # Create a step 
    step1 = odb.steps['Step-1']

    # Read the history region, the key for this call 
    # determines what you are picking as your region, 
    # it can be a node, an element or as in this case, 
    # the whole model. 
    region = step1.historyRegions['Assembly ASSEMBLY']

    # Once the history region has been set, all the history outputs can 
    # be referenced using their names. EIGFREQ for frequency etc. 
    freqData = region.historyOutputs['EIGFREQ'].data

    # Write the data to the excel file 
    for i in range(0, len(freqData)):
        wso['A' + str(i+1)].value = float(freqData[i][0])
        wso['B' + str(i+1)].value = float(freqData[i][1])

    # Save the excel file and move to the next iteration of the for loop
    # with new values for inputs    
    wbo.save("E://Vibration//output_dynamic"+ str(j) + ".xlsx")


