Project Background
==================

I started writing :mod:`inpRW` because I frequently needed to edit Abaqus input files, but it was tedious to do so using
text editors. Working on the input file itself is convenient because it is well-defined, open, portable, and supports every
Abaqus keyword. I wanted a tool that could run on any operating system and that could work on input files generated by 
any pre-processor. 

Difficulties of parsing Abaqus input files
------------------------------------------

Writing parsers is a difficult task. While simpler than many languages, the Abaqus input file language still has some quirks
which make accurate parsing difficult. In particular:

* Abaqus is not case-sensitive nor space-sensitive for keywords and parameters, while Python is sensitive to both.
* Keyword blocks are denoted with one \* character and end with the next keyword block.
* Comments are denoted with two \* characters and can start any line in the input file.
* Keywords and parameters do not need to be fully written out; they only need enough information to uniquely identify them.
* Data formatting varies per keyword, and different parameters can change the data for a given keyword.
* Many keywords directly enhance other keywords, and need to directly follow their parent keywords. There are three different methods for terminating these keyword groups:

   * \*END keyword (\*PART, \*STEP)
   * Keyword that is not a valid suboption of the parent keyword (\*MATERIAL, \*OUTPUT)
   * Read until the end of the file (\*INCLUDE, \*MANIFEST)
   
* Abaqus has many default values that do not need to be specified.

inpParser Module
----------------

The :term:`inpParser` module is included with Abaqus Python. 
It is essentially a Python API to the input file parser the Abaqus solver uses.
Its purpose is to interpret an Abaqus input file in a way the solver can understand, with acceptable performance for massive input files, and execute the job in a manner the user intended.
As part of this design, :term:`inpParser` makes changes to the input file data, such as changing the case and spacing of items to provide case- and space-insensitivity, filling in default values of some parameters and data, and ignoring comments that appear after the last keyword and in the data lines of a keyword.
There is also no method to write an input file from the parsed data in inpParser. Thus, :term:`inpParser` is not a great foundation upon which to build a parsing tool meant to modify input files prior to running Abaqus jobs.

inpRW History
-------------

:mod:`inpRW` was originally just meant to write out an input file from the data from :term:`inpParser`.
However, due to the changes :term:`inpParser` makes to the input data when parsing it, the module could not simply write out a new input file with whatever data was in the inp object, as it would not look anything like the original input file.
A module to write from an :term:`inpParser` inp object would likely require a special case for most keywords and parameter combinations, which would take an inordinate amount of work to create.
Therefore, I decided to write a new module for parsing the input file and writing out a new input file, and this of course needed some functions that could find and change data in the input file.
:mod:`inpRW` was originally written for Python 2.7, so that it could run in Abaqus Python. However, I converted the script to Python 3 for a few reasons.

   * Python 2.7 is end of life.
   * **3D**\ EXPERIENCE Keyword Edit tool in its initial form is hard-coded to use a Python 3 interpreter.
   * Python 3 will have performance improvements over Python 2.7, and some useful features (such as ordered keys in dictionaries).
   * Since the utility merely operates on the text of the input file, it does not need any features provided by the Abaqus Python API for pre-processing Abaqus/CAE models or post-processing Abaqus .odbs.

