Ejemplo n.º 1
0
def main():
    logger.info("**********************************************************************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("************************STARTING FEA MODEL-BASED v1.3.0***************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("Initializing Abaqus/CAE" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    
    # take command line arguments
    usage = "usage: abaqus cae script=CyPhy2AbaqusCmd.py -- [options]"
    parser = OptionParser(usage=usage)
    parser.add_option("-o","--meshOnly", default=False, action="store_true",
        help="""disable assembly of faces from datum points and creation of loads and BCs
            (necessary for META 13.13)""")
    parser.add_option("-b","--meshAndBC", default=False, action="store_true",
        help="Create mesh and generate loads/boundary conditions. Do not run analysis.")
    parser.add_option("-s","--standard", default=False, action="store_true",
        help="run a standard FEA analysis")
    parser.add_option("-i","--dynamicImplicit", default=False, action="store_true",
        help="run a dynamic implicit FEA analysis")
    parser.add_option("-e","--dynamicExplicit", default=False, action="store_true",
        help="run a dynamic explicit FEA analysis")
    parser.add_option("-m","--modal", default=False, action="store_true",
        help="run a modal analysis")
    parser.add_option("-p","--parallelCores", default=1, type=int,
        help="number of CPU cores to use in solver")
    parser.add_option("-r","--ramAllocated", default=90, type=int,
        help="integer amount of memory allocated to solver, defined in units memoryUnits")
    parser.add_option("-u","--memoryUnits", default="PERCENTAGE",
        choices=["PERCENTAGE","MEGA_BYTES","GIGA_BYTES"],
        help="units of memory allocated to solver")
    parser.add_option("-t","--separationTolerance", default=1E-3, type=float,
        help="tolerance for separation between faces when creating tie constraints")
    parser.add_option("-q","--errorIndicator", default="ENDENERI",
        choices=["MISESERI","ENDENERI","CPRESSERI","CSHEARERI","PEEQUERI",
                 "PEERI","CEERI","HFLERI","EFLERI","EPGERI"],
        help="""error indicator variable for adaptive meshing;
                not all variables are supported yet
                (see Section 4.1.4 of the Abaqus Analysis Manual)""")
    parser.add_option("-v","--rigidParts", default=True, action="store_true",
        help="use Rigid parts as specified in CADAssembly.xml")

    if sys.argv[2] == '-noGUI':
        (args,testBenchArg) = parser.parse_args(sys.argv[8:])
    else:
        (args,testBenchArg) = parser.parse_args(sys.argv[6:])

    # Assign variable to the blank model produced at startup
    myModel = mdb.models['Model-1']
    myAsm = myModel.rootAssembly

    # Determine if ADAMS analysis preceeded this FEA run
    runAdams = check_for_adams(runAdams=False)
    
    # Parse necessary information from the XML files  
    (xmlName, feaXML, cadAssemblyXML, metricSetXML, metricsSetXML,
     metricsComponentSetXML, maxNumberIter, analysisConstraintSetXML, thermalSetXML) \
        = parseCADAssemblyXML(args)
    
    # TODO: this first check should only be temporary.
    if maxNumberIter > 1 and any([args.dynamicImplicit, args.dynamicExplicit, runAdams]):
        msg = "Adaptive remeshing requested with invalid analysis type. Currently " + \
              "supported type is static/standard standalone FEA."
        logger.error(msg)
        raise Exception(msg)
        
    if runAdams and args.dynamicImplicit or not runAdams and args.dynamicExplicit:
        msg = "Invalid combination of dynamic analysis type and ADAMS analysis data. " + \
              "Available options are Standalone FEA with Implicit Dynamics or " + \
              "FEA with ADAMS load data with Explicit Dynamics."
        logger.error(msg)
        raise Exception(msg)
        
    elif runAdams and args.meshAndBC or runAdams and args.modal:
        msg = "ADAMS-to-Abaqus runs can not have the Abaqus analysis set to " + \
              "MeshAndBoundaryConditions or Modal."
        logger.error(msg)
        raise Exception(msg)
        
    if thermalSetXML and any([args.dynamicImplicit, args.dynamicExplicit, args.modal, runAdams]):
        msg = "Coupled Thermal analysis currently only supported for standalone FEA static runs."
        logger.error(msg)
        raise Exception(msg)
    
    # Parse STEP file for raw assembly data
    (stepPath, testBenchName, step) = parseStep(cadAssemblyXML)  
    
    # Parse CADMetrics file for CreateAssembly program data
    (xmlMetricsName, metricComponentsXML, metricComponentXML, 
         metricAssembliesXML, metricAssemblyXML, 
         metricCADComponentsXML, jointsXML) = parseCADAssemblyMetricsXML(runAdams)
    
    # Determine unit length of CAD files    
    unitLength = getUnitLength(metricComponentsXML)
    
    if runAdams:
        # Parse kinematic computed values (ADAMS data)
        (anchorID, anchorPointID) = parseKinComputedValuesXML()

    # Calculate scale factor (with respect to meters)
    (unitScale, unitShort) = calcGeoScaleFac(unitLength)
    conv = generateConvDict(unitScale)
    
    # Generate necessary general dictionaries
    (instRef, instIndex, instAssemblyRef, instAssemblyIndex,
      rigidPartMasses, rigidPartVolumes, rigidPartDensities,
      rigidParts, rigidPartPresent, Jan24_deactivate_rigidity) \
           = generateInstRef(metricComponentsXML, metricCADComponentsXML, 
                             xmlMetricsName, jointsXML, xmlName, runAdams, args)

    libraryManager = parseMaterialLibrary()    
    mtrlRef = generateMtrlRef(libraryManager, metricComponentsXML, 
                              metricCADComponentsXML, thermalSetXML, rigidParts, unitScale, conv)
                              
    (metricRef, metricRef2, metricRef3, allAssembly) \
        = generateMetricRef(metricSetXML, metricsComponentSetXML, instIndex)
    if not runAdams:
        (loadBCLib, accel) = generateLoadBCLib(analysisConstraintSetXML, feaXML, thermalSetXML, conv)
    else:
        (loadBCLib, accel) = ([],[])
    superRef = generateSuperRef(instRef, instAssemblyRef, mtrlRef, metricRef, metricRef2, metricRef3,
                                instIndex, loadBCLib, unitLength, allAssembly) 
    
    # Process the data obtained from the step file
    (pointsBySR, inst2SR, localTMs, localTVs, topLevelAsm, subAsms,
         asmParts) = processStep(stepPath, testBenchName) 
    
    # Generate necessary geometric dictionaries
    (localCoords, CGs) = generateLocalCoords(inst2SR, pointsBySR,
                                             metricCADComponentsXML, metricComponentsXML)
    logger.info("Creating a new dictionary with points translated into the global coordinate system" + '\n')
    datumPointDict = coordTransform(localTMs,localTVs,topLevelAsm,
                                    subAsms,asmParts,localCoords)
    logger.info("**********************************************************************************" + '\n')

    # Start building Abaqus model
    createParts(myModel, step, CGs)  
    deleteInvalidParts(myModel)

    # Define step - standard default
    if thermalSetXML:
        (myStep, amp, analysisStepName) = defineCoupledThermalDisplacementStep(myModel)
    else:
        if args.dynamicImplicit or args.dynamicExplicit:
            (myStep, amp, analysisStepName) = defineDynamicStep(myModel, runAdams)
        elif args.modal:
            (myStep, amp, analysisStepName) = defineModalStep(myModel)
        else:
            (myStep, amp, analysisStepName) = defineStaticStep(myModel)
    
    defineMaterials(myModel, mtrlRef)
        
    if not runAdams:
        assignSections(instRef, myModel, myAsm)
        mergeAssemblyComponents(myAsm, instAssemblyRef, asmParts)
        defineContactInteractions(myModel)
        defineRigidBodyConstraints(instRef, Jan24_deactivate_rigidity,
                                   instIndex, myAsm, myModel)
        EliminateOverlaps(instRef, rigidParts, myAsm, myModel)
        
        meshInstances(40.0, unitShort, instRef, instAssemblyRef, myAsm,
                      feaXML, metricComponentsXML, metricAssemblyXML, args) 
        
        if not args.meshOnly:
            apply_loads_and_bcs(myModel, myAsm, myStep, instRef, loadBCLib, instIndex, instAssemblyIndex,
                                datumPointDict, accel, amp, args, Jan24_deactivate_rigidity, thermalSetXML)
    
           

    if runAdams:
        EliminateOverlaps(instRef, rigidParts, myAsm, myModel)
        
        (includeAnchoredPart, anchoredPart) = decideAnchoredPart(jointsXML,
                        anchorID, anchorPointID, instRef, myModel)

        AbaqusCAE_ADAMS(instRef, includeAnchoredPart, anchoredPart, myModel,
                        myAsm, 40.0, unitShort, jointsXML, 
                        feaXML, metricComponentsXML, metricAssemblyXML,
                        args.parallelCores, args.ramAllocated, args, instAssemblyRef, asmParts)
    else:
        includeAnchoredPart, anchoredPart = None, None
                   
    logger.info("**********************************************************************************" + '\n')               
                   
    if not runAdams:
        if not args.meshOnly:
            connectParts(myModel, myAsm, args)
            try:
                CreateLOADSBCPNG('PreProcessing', myAsm, analysisStepName, os.getcwd())
            except:
                logger.info('ERROR: Error during creating BC PNG files - Program will keep executing \n')
                pass
            
            checkConstraintErrors(myModel, args)
            
            exportNastranDeck()
        
        createCAE(os.getcwd(), testBenchName, args)
      
    if not args.meshOnly and not args.meshAndBC:    
        jobName = runAbaqusDispatch(myModel, myAsm, superRef, analysisStepName, rigidPartPresent,
                                     rigidParts, args, includeAnchoredPart, anchoredPart, maxNumberIter)

    if not runAdams:
        if args.dynamicImplicit or args.dynamicExplicit or args.standard:
            afterJob(jobName, superRef, analysisStepName, runAdams, thermalSetXML)
        elif args.modal:
            afterJobModal(jobName,analysisStepName)
Ejemplo n.º 2
0
def main():
    logger.info(
        "**********************************************************************************"
        + '\n')
    logger.info(
        "**********************************************************************************"
        + '\n')
    logger.info(
        "*************************   STARTING FEA MODEL-BASED   ***************************"
        + '\n')
    logger.info(
        "**********************************************************************************"
        + '\n')
    logger.info(
        "**********************************************************************************"
        + '\n')
    logger.info("Initializing Abaqus/CAE" + '\n')
    logger.info(
        "**********************************************************************************"
        + '\n')
    logger.info(
        "**********************************************************************************"
        + '\n')

    # take command line arguments
    usage = "usage: abaqus cae script=AbaqusMain.py -- [options]"
    parser = OptionParser(usage=usage)
    parser.add_option(
        "-o",
        "--meshOnly",
        default=False,
        action="store_true",
        help="""disable assembly of faces from datum points and creation
                      of loads and BCs (necessary for META 13.13)""")
    parser.add_option(
        "-b",
        "--meshAndBC",
        default=False,
        action="store_true",
        help=
        "Create mesh and generate loads/boundary conditions. Do not run analysis."
    )
    parser.add_option("-s",
                      "--standard",
                      default=False,
                      action="store_true",
                      help="run a standard FEA analysis")
    parser.add_option("-i",
                      "--dynamicImplicit",
                      default=False,
                      action="store_true",
                      help="run a dynamic implicit FEA analysis")
    parser.add_option("-e",
                      "--dynamicExplicit",
                      default=False,
                      action="store_true",
                      help="run a dynamic explicit FEA analysis")
    parser.add_option("-m",
                      "--modal",
                      default=False,
                      action="store_true",
                      help="run a modal analysis")
    parser.add_option("-p",
                      "--parallelCores",
                      default=1,
                      type=int,
                      help="number of CPU cores to use in solver")
    parser.add_option(
        "-r",
        "--ramAllocated",
        default=90,
        type=int,
        help=
        "integer amount of memory allocated to solver, defined in units memoryUnits"
    )
    parser.add_option("-u",
                      "--memoryUnits",
                      default="PERCENTAGE",
                      choices=["PERCENTAGE", "MEGA_BYTES", "GIGA_BYTES"],
                      help="units of memory allocated to solver")
    parser.add_option(
        "-t",
        "--separationTolerance",
        default=1E-3,
        type=float,
        help=
        "tolerance for separation between faces when creating tie constraints")
    parser.add_option("-q",
                      "--errorIndicator",
                      default="ENDENERI",
                      choices=[
                          "MISESERI", "ENDENERI", "CPRESSERI", "CSHEARERI",
                          "PEEQUERI", "PEERI", "CEERI", "HFLERI", "EFLERI",
                          "EPGERI"
                      ],
                      help="""error indicator variable for adaptive meshing;
                      not all variables are supported yet
                      (see Section 4.1.4 of the Abaqus Analysis Manual)""")
    parser.add_option("-v",
                      "--rigidParts",
                      default=True,
                      action="store_true",
                      help="use Rigid parts as specified in CADAssembly.xml")

    if sys.argv[2] == '-noGUI':
        (args, testBenchArg) = parser.parse_args(sys.argv[8:])
    else:
        (args, testBenchArg) = parser.parse_args(sys.argv[6:])

    # Initialize constants to be used throughout the analysis.
    (cadAssemblyXML, cadMetricsXML, requestedMetricsXML, computedValuesXML, kinComputedValuesXML,
     analysisMetaDataXML, testbench_manifest, postprocessingScript, resultsDir, solverDir,
     stepDir, myModel, myAsm, uniqueSuffix, asmIdentifier, structuralOutputs, thermalOutputs) \
        = initializeConstants()

    # Determine if ADAMS analysis preceeded this FEA run
    # Looks for dependency notifications in the testbench_manifest.json file.
    runAdams = check_for_adams(False, testbench_manifest, kinComputedValuesXML,
                               computedValuesXML, cadMetricsXML, resultsDir,
                               solverDir)

    # Parse necessary information from the XML files
    (feaXML, cadAssemblyXMLTree, maxNumberIter, analysisConstraintSetXML, thermalSetXML) \
        = parseCADAssemblyXML(cadAssemblyXML, resultsDir, args)

    # TODO: remove runAdams constraint
    if maxNumberIter > 1 and any(
        [args.dynamicImplicit, args.dynamicExplicit, runAdams]):
        cad_library.exitwitherror(
            "Adaptive remeshing requested with invalid analysis type. Only static, "
            "thermal, and coupled thermal/displacement analyses are supported. FEA "
            "analyses launched from a ADAMS kinematic test bench are also currently "
            "invalid. Please change your GME test bench settings.", 1,
            'AbaqusMain.py')

    elif runAdams and args.meshAndBC or runAdams and args.modal:
        cad_library.exitwitherror(
            "ADAMS-to-Abaqus runs can not have the Abaqus analysis set to "
            "MeshAndBoundaryConditions or Modal.", 1, 'AbaqusMain.py')

    if thermalSetXML and any([args.modal, runAdams]):
        cad_library.exitwitherror(
            "Coupled Thermal analysis not supported for modal or Adams-to-Abaqus"
            "analyses.", 1, 'AbaqusMain.py')

    # Parse STEP file for raw assembly data
    (stepPath, testBenchName, step) = parseStep(cadAssemblyXMLTree, stepDir)

    # Populate assembly information from CADAssembly_metrics.xml
    asminfo = cad_library.AssemblyInfo()
    asminfo.read_metrics_file(cadMetricsXML)

    # Determine unit length of CAD files
    unitLength = unit_utils.getUnitLength(asminfo)

    if runAdams:
        # Parse kinematic computed values (ADAMS data)
        (anchorID,
         anchorPointID) = parseKinComputedValuesXML(kinComputedValuesXML)

    # Calculate scale factor (with respect to meters)
    (unitScale, unitShort) = unit_utils.calcGeoScaleFac(unitLength)
    # Create dictionary of all possibly used units throughout the analysis along with their conversion factors.
    conv = unit_utils.generateConvDict(unitScale)

    # Generate necessary general dictionaries
    # These contain information parsed from the various input XML files.
    # InstRef creates a dictionary entry for each component.
    (instRef, instIndex, instAssemblyRef, instAssemblyIndex,
     rigidPartMasses, rigidPartVolumes, rigidPartDensities,
     rigidParts, rigidPartPresent, Jan24_deactivate_rigidity) = \
        generateInstRef(asminfo, cadAssemblyXML, uniqueSuffix, asmIdentifier, runAdams, args)

    # Generate a dictionary containing material properties for each component in the assembly.
    mtrlRef = generateMtrlRef(asminfo, thermalSetXML, rigidParts,
                              rigidPartDensities, conv)

    if not runAdams:
        # If no Adams dependency is found, generate dictionary of loads and boundary conditions placed on each part.
        (loadBCLib, accel) = generateLoadBCLib(analysisConstraintSetXML,
                                               feaXML, thermalSetXML, conv,
                                               asminfo)
    else:
        # If Adams dependency exists, loads are defined in the LOD files output from Adams. Boundary conditions
        # are applied at a later point.
        (loadBCLib, accel) = ([], [])

    # Process the data obtained from the step file
    (pointsBySR, inst2SR, localTMs, localTVs, topLevelAsm, subAsms,
     asmParts) = processStep(stepPath, testBenchName, uniqueSuffix,
                             asmIdentifier)

    # Generate necessary geometric dictionaries
    (localCoords, CGs) = generateLocalCoords(inst2SR, pointsBySR, asminfo,
                                             uniqueSuffix)
    logger.info(
        "Creating a new dictionary with points translated into the global coordinate system"
        + '\n')
    datumPointDict = coordTransform(localTMs, localTVs, topLevelAsm, subAsms,
                                    asmParts, localCoords)
    logger.info(
        "**********************************************************************************"
        + '\n')

    # Directory where analysis output files and post-processing files will be written to.
    if not os.path.exists(solverDir):
        os.mkdir(solverDir)
    os.chdir(solverDir)

    # Start building Abaqus model
    createParts(myModel, step, CGs)
    deleteInvalidParts(myModel)

    # Define step - standard 'static' default
    if thermalSetXML:
        if args.dynamicExplicit:
            (myStep, amp, analysisStepName) = \
                defineDynamicExplicitCoupledThermalDisplacementStep(myModel, structuralOutputs+thermalOutputs)
        else:
            (myStep, amp,
             analysisStepName) = defineCoupledThermalDisplacementStep(
                 myModel, args.dynamicImplicit,
                 structuralOutputs + thermalOutputs)
    else:
        if args.dynamicImplicit or args.dynamicExplicit:
            (myStep, amp,
             analysisStepName) = defineDynamicStep(myModel,
                                                   args.dynamicExplicit,
                                                   structuralOutputs)
        elif args.modal:
            (myStep, amp, analysisStepName) = defineModalStep(myModel)
        else:
            (myStep, amp,
             analysisStepName) = defineStaticStep(myModel, structuralOutputs)

    # Assign materials to each component.
    defineMaterials(myModel, mtrlRef)

    if not runAdams:
        assignSections(instRef, myModel, myAsm, subAsms, asmParts)
        mergeAssemblyComponents(myModel, myAsm, instAssemblyRef, asmParts)
        defineContactInteractions(myModel, args.dynamicExplicit)
        defineRigidBodyConstraints(instRef, Jan24_deactivate_rigidity,
                                   instIndex, myAsm, myModel)
        EliminateOverlaps(instRef, rigidParts, myAsm, myModel)

        apply_loads_and_bcs(myModel, myAsm, myStep, instRef, loadBCLib,
                            instIndex, instAssemblyIndex, datumPointDict,
                            accel, amp, args, Jan24_deactivate_rigidity,
                            thermalSetXML)

        meshInstances(asminfo, 40.0, unitShort, instRef, instAssemblyRef,
                      myAsm, feaXML, args)

    if runAdams:
        EliminateOverlaps(instRef, rigidParts, myAsm, myModel)

        (includeAnchoredPart,
         anchoredPart) = decideAnchoredPart(anchorID, anchorPointID, instRef,
                                            myModel)

        AbaqusCAE_ADAMS(asminfo, instRef, includeAnchoredPart, anchoredPart,
                        myModel, myAsm, 40.0, unitShort, feaXML,
                        args.parallelCores, args.ramAllocated, args,
                        instAssemblyRef, asmParts)

    else:
        includeAnchoredPart, anchoredPart = None, None

    logger.info(
        "**********************************************************************************"
        + '\n')

    if not runAdams:
        if not args.meshOnly:
            connectParts(myModel, myAsm, args)
            try:
                CreateLOADSBCPNG(myAsm, analysisStepName, solverDir)
            except:
                logger.info(
                    'ERROR: Error during creating BC PNG files - Program will keep executing \n'
                )
                pass
            createCAE(solverDir, testBenchName, args)

            checkConstraintErrors(myModel, args)

            exportNastranDeck()

    modifyMetaDataFile(os.path.join(solverDir, '..', analysisMetaDataXML),
                       asminfo, uniqueSuffix, asmIdentifier)

    if not args.meshOnly and not args.meshAndBC:
        jobName = runAbaqusDispatch(myModel, myAsm, instRef, analysisStepName,
                                    rigidPartPresent, rigidParts, args,
                                    includeAnchoredPart, anchoredPart,
                                    maxNumberIter, postprocessingScript,
                                    analysisMetaDataXML, requestedMetricsXML,
                                    testbench_manifest)

    if not runAdams:
        if args.dynamicImplicit or args.dynamicExplicit or args.standard:
            check = 0
            # Adaptive runs can complete before the MaxNumberIterations,
            # so multiple checks need to be done. Start with assuming it went to MaxNumberIter
            if jobName.startswith("Adaptivity-1-iter"):
                lastIterStr = jobName.replace("Adaptivity-1-iter", "")
                lastIter = int(lastIterStr)

                while lastIter > 0 and check == 0:
                    try:
                        AdaptiveJobName = "Adaptivity-1-iter" + str(lastIter)
                        odbAccess.openOdb(path=AdaptiveJobName + '.odb')
                        check = 1
                        jobName = AdaptiveJobName
                    except:
                        # Error thrown because file does not exist. If lastIter > 1, this means the analysis
                        # completed before the max number allowed. Decrease lastIter and try opening again.
                        logger.info(
                            'ERROR: Error in reading results of %s.\n' %
                            AdaptiveJobName)
                        lastIter -= 1

            os.chdir(solverDir)
            # Invoke post processing
            # Spawn new Python process by calling the post-processing script along with necessary arguments.
            os.system("abaqus cae noGUI=" + os.path.join(
                cad_library.META_PATH, "bin", "CAD", postprocessingScript) +
                      " -- " + "-o " + jobName + ".odb " + "-p " + "..\\" +
                      analysisMetaDataXML + " -m " + "..\\..\\" +
                      requestedMetricsXML + " -j " + "..\\..\\" +
                      testbench_manifest)
        elif args.modal:
            # Modal analyses use a different, older post-processing method as the output ODB is analyzed different.
            ABQ_CompletePostProcess.afterJobModal(jobName, analysisStepName)
Ejemplo n.º 3
0
def main():
    logger.info("**********************************************************************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("*************************   STARTING FEA MODEL-BASED   ***************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("Initializing Abaqus/CAE" + '\n')
    logger.info("**********************************************************************************" + '\n')
    logger.info("**********************************************************************************" + '\n')

    # take command line arguments
    usage = "usage: abaqus cae script=AbaqusMain.py -- [options]"
    parser = OptionParser(usage=usage)
    parser.add_option("-o", "--meshOnly", default=False, action="store_true",
                      help="""disable assembly of faces from datum points and creation
                      of loads and BCs (necessary for META 13.13)""")
    parser.add_option("-b", "--meshAndBC", default=False, action="store_true",
                      help="Create mesh and generate loads/boundary conditions. Do not run analysis.")
    parser.add_option("-s", "--standard", default=False, action="store_true",
                      help="run a standard FEA analysis")
    parser.add_option("-i", "--dynamicImplicit", default=False, action="store_true",
                      help="run a dynamic implicit FEA analysis")
    parser.add_option("-e", "--dynamicExplicit", default=False, action="store_true",
                      help="run a dynamic explicit FEA analysis")
    parser.add_option("-m", "--modal", default=False, action="store_true",
                      help="run a modal analysis")
    parser.add_option("-p", "--parallelCores", default=1, type=int,
                      help="number of CPU cores to use in solver")
    parser.add_option("-r", "--ramAllocated", default=90, type=int,
                      help="integer amount of memory allocated to solver, defined in units memoryUnits")
    parser.add_option("-u", "--memoryUnits", default="PERCENTAGE",
                      choices=["PERCENTAGE", "MEGA_BYTES", "GIGA_BYTES"],
                      help="units of memory allocated to solver")
    parser.add_option("-t", "--separationTolerance", default=1E-3, type=float,
                      help="tolerance for separation between faces when creating tie constraints")
    parser.add_option("-q", "--errorIndicator", default="ENDENERI",
                      choices=["MISESERI", "ENDENERI", "CPRESSERI", "CSHEARERI", "PEEQUERI",
                               "PEERI", "CEERI", "HFLERI", "EFLERI", "EPGERI"],
                      help="""error indicator variable for adaptive meshing;
                      not all variables are supported yet
                      (see Section 4.1.4 of the Abaqus Analysis Manual)""")
    parser.add_option("-v", "--rigidParts", default=True, action="store_true",
                      help="use Rigid parts as specified in CADAssembly.xml")

    if sys.argv[2] == '-noGUI':
        (args, testBenchArg) = parser.parse_args(sys.argv[8:])
    else:
        (args, testBenchArg) = parser.parse_args(sys.argv[6:])
    
    # Initialize constants to be used throughout the analysis.
    (cadAssemblyXML, cadMetricsXML, requestedMetricsXML, computedValuesXML, kinComputedValuesXML,
     analysisMetaDataXML, testbench_manifest, postprocessingScript, resultsDir, solverDir,
     stepDir, myModel, myAsm, uniqueSuffix, asmIdentifier, structuralOutputs, thermalOutputs) \
        = initializeConstants()

    # Determine if ADAMS analysis preceeded this FEA run
    # Looks for dependency notifications in the testbench_manifest.json file.
    runAdams = check_for_adams(False, testbench_manifest, kinComputedValuesXML,
                               computedValuesXML, cadMetricsXML, resultsDir, solverDir)

    # Parse necessary information from the XML files
    (feaXML, cadAssemblyXMLTree, maxNumberIter, analysisConstraintSetXML, thermalSetXML) \
        = parseCADAssemblyXML(cadAssemblyXML, resultsDir, args)

    # TODO: remove runAdams constraint
    if maxNumberIter > 1 and any([args.dynamicImplicit, args.dynamicExplicit, runAdams]):
        cad_library.exitwitherror("Adaptive remeshing requested with invalid analysis type. Only static, "
                                  "thermal, and coupled thermal/displacement analyses are supported. FEA "
                                  "analyses launched from a ADAMS kinematic test bench are also currently "
                                  "invalid. Please change your GME test bench settings.", 1, 'AbaqusMain.py')

    elif runAdams and args.meshAndBC or runAdams and args.modal:
        cad_library.exitwitherror("ADAMS-to-Abaqus runs can not have the Abaqus analysis set to "
                                  "MeshAndBoundaryConditions or Modal.", 1, 'AbaqusMain.py')

    if thermalSetXML and any([args.modal, runAdams]):
        cad_library.exitwitherror("Coupled Thermal analysis not supported for modal or Adams-to-Abaqus"
                                  "analyses.", 1, 'AbaqusMain.py')

    # Parse STEP file for raw assembly data
    (stepPath, testBenchName, step) = parseStep(cadAssemblyXMLTree, stepDir)

    # Populate assembly information from CADAssembly_metrics.xml
    asminfo = cad_library.AssemblyInfo()
    asminfo.read_metrics_file(cadMetricsXML)

    # Determine unit length of CAD files    
    unitLength = unit_utils.getUnitLength(asminfo)

    if runAdams:
        # Parse kinematic computed values (ADAMS data)
        (anchorID, anchorPointID) = parseKinComputedValuesXML(kinComputedValuesXML)

    # Calculate scale factor (with respect to meters)
    (unitScale, unitShort) = unit_utils.calcGeoScaleFac(unitLength)
    # Create dictionary of all possibly used units throughout the analysis along with their conversion factors.
    conv = unit_utils.generateConvDict(unitScale)

    # Generate necessary general dictionaries
    # These contain information parsed from the various input XML files.
    # InstRef creates a dictionary entry for each component.
    (instRef, instIndex, instAssemblyRef, instAssemblyIndex,
     rigidPartMasses, rigidPartVolumes, rigidPartDensities,
     rigidParts, rigidPartPresent, Jan24_deactivate_rigidity) = \
        generateInstRef(asminfo, cadAssemblyXML, uniqueSuffix, asmIdentifier, runAdams, args)
    
    # Generate a dictionary containing material properties for each component in the assembly.
    mtrlRef = generateMtrlRef(asminfo, thermalSetXML, rigidParts, rigidPartDensities, conv)

    if not runAdams:
        # If no Adams dependency is found, generate dictionary of loads and boundary conditions placed on each part.
        (loadBCLib, accel) = generateLoadBCLib(analysisConstraintSetXML, feaXML, thermalSetXML, conv, asminfo)
    else:
        # If Adams dependency exists, loads are defined in the LOD files output from Adams. Boundary conditions
        # are applied at a later point.
        (loadBCLib, accel) = ([], [])

    # Process the data obtained from the step file
    (pointsBySR, inst2SR, localTMs, localTVs, topLevelAsm, subAsms,
     asmParts) = processStep(stepPath, testBenchName, uniqueSuffix, asmIdentifier)

    # Generate necessary geometric dictionaries
    (localCoords, CGs) = generateLocalCoords(inst2SR, pointsBySR, asminfo, uniqueSuffix)
    logger.info("Creating a new dictionary with points translated into the global coordinate system" + '\n')
    datumPointDict = coordTransform(localTMs, localTVs, topLevelAsm, subAsms, asmParts, localCoords)
    logger.info("**********************************************************************************" + '\n')
    
    # Directory where analysis output files and post-processing files will be written to.
    if not os.path.exists(solverDir):
        os.mkdir(solverDir)
    os.chdir(solverDir)

    # Start building Abaqus model
    createParts(myModel, step, CGs)
    deleteInvalidParts(myModel)

    # Define step - standard 'static' default
    if thermalSetXML:
        if args.dynamicExplicit:
            (myStep, amp, analysisStepName) = \
                defineDynamicExplicitCoupledThermalDisplacementStep(myModel, structuralOutputs+thermalOutputs)
        else:
            (myStep, amp, analysisStepName) = defineCoupledThermalDisplacementStep(myModel, args.dynamicImplicit,
                                                                                   structuralOutputs+thermalOutputs)
    else:
        if args.dynamicImplicit or args.dynamicExplicit:
            (myStep, amp, analysisStepName) = defineDynamicStep(myModel, args.dynamicExplicit, structuralOutputs)
        elif args.modal:
            (myStep, amp, analysisStepName) = defineModalStep(myModel)
        else:
            (myStep, amp, analysisStepName) = defineStaticStep(myModel, structuralOutputs)
    
    # Assign materials to each component.
    defineMaterials(myModel, mtrlRef)

    if not runAdams:
        assignSections(instRef, myModel, myAsm, subAsms, asmParts)
        mergeAssemblyComponents(myModel, myAsm, instAssemblyRef, asmParts)
        defineContactInteractions(myModel, args.dynamicExplicit)
        defineRigidBodyConstraints(instRef, Jan24_deactivate_rigidity,
                                   instIndex, myAsm, myModel)
        EliminateOverlaps(instRef, rigidParts, myAsm, myModel)

        apply_loads_and_bcs(myModel, myAsm, myStep, instRef, loadBCLib, instIndex, instAssemblyIndex,
                            datumPointDict, accel, amp, args, Jan24_deactivate_rigidity, thermalSetXML)

        meshInstances(asminfo, 40.0, unitShort, instRef,
                      instAssemblyRef, myAsm, feaXML,  args)

    if runAdams:
        EliminateOverlaps(instRef, rigidParts, myAsm, myModel)

        (includeAnchoredPart, anchoredPart) = decideAnchoredPart(anchorID, anchorPointID, instRef, myModel)

        AbaqusCAE_ADAMS(asminfo, instRef, includeAnchoredPart, anchoredPart, myModel,
                        myAsm, 40.0, unitShort, feaXML, args.parallelCores,
                        args.ramAllocated, args, instAssemblyRef, asmParts)

    else:
        includeAnchoredPart, anchoredPart = None, None

    logger.info("**********************************************************************************" + '\n')

    if not runAdams:
        if not args.meshOnly:
            connectParts(myModel, myAsm, args)
            try:
                CreateLOADSBCPNG(myAsm, analysisStepName, solverDir)
            except:
                logger.info('ERROR: Error during creating BC PNG files - Program will keep executing \n')
                pass
            createCAE(solverDir, testBenchName, args)

            checkConstraintErrors(myModel, args)

            exportNastranDeck()

    modifyMetaDataFile(os.path.join(solverDir, '..', analysisMetaDataXML), asminfo, uniqueSuffix, asmIdentifier)

    if not args.meshOnly and not args.meshAndBC:
        jobName = runAbaqusDispatch(myModel, myAsm, instRef, analysisStepName, rigidPartPresent,
                                    rigidParts, args, includeAnchoredPart, anchoredPart, maxNumberIter,
                                    postprocessingScript, analysisMetaDataXML, requestedMetricsXML, testbench_manifest)

    if not runAdams:
        if args.dynamicImplicit or args.dynamicExplicit or args.standard:
            check = 0
            # Adaptive runs can complete before the MaxNumberIterations,
            # so multiple checks need to be done. Start with assuming it went to MaxNumberIter
            if jobName.startswith("Adaptivity-1-iter"):
                lastIterStr = jobName.replace("Adaptivity-1-iter", "")
                lastIter = int(lastIterStr)

                while lastIter > 0 and check == 0:
                    try:
                        AdaptiveJobName = "Adaptivity-1-iter" + str(lastIter)
                        odbAccess.openOdb(path=AdaptiveJobName + '.odb')
                        check = 1
                        jobName = AdaptiveJobName
                    except:
                        # Error thrown because file does not exist. If lastIter > 1, this means the analysis
                        # completed before the max number allowed. Decrease lastIter and try opening again.
                        logger.info('ERROR: Error in reading results of %s.\n' % AdaptiveJobName)
                        lastIter -= 1

            os.chdir(solverDir)
            # Invoke post processing
            # Spawn new Python process by calling the post-processing script along with necessary arguments.
            os.system("abaqus cae noGUI=" + os.path.join(cad_library.META_PATH, "bin", "CAD", postprocessingScript) +
                      " -- " + "-o " + jobName + ".odb " + "-p " + "..\\" + analysisMetaDataXML + " -m " +
                      "..\\..\\" + requestedMetricsXML + " -j " + "..\\..\\" + testbench_manifest)
        elif args.modal:
            # Modal analyses use a different, older post-processing method as the output ODB is analyzed different.
            ABQ_CompletePostProcess.afterJobModal(jobName, analysisStepName)