Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add preparser to julia native #48

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

Joroks
Copy link

@Joroks Joroks commented Jul 14, 2024

I've started working on #47. This is just a quickly thrown together draft but read_keywords should correctly translate any valid .inp file (as defined here) into julia native datatypes while parsing the input as much as possible without any knowledge about the individual keyword specifications. This should make it easier to add support for more keywords in the future.

Is that something thats going in the right direction or should I take a different approach?

@KnutAM
Copy link
Member

KnutAM commented Jul 14, 2024

Thanks for the draft!

Is that something thats going in the right direction or should I take a different approach?

If you mean as a pre-step before actually parsing the input data, but I'm not sure what the advantage is over parsing it directly in place apart from the availability of the intermediate data-structure. I don't think this strategy can be used for parsing in the end though, since AFAIU it is required to know the specific keywords to parse the file correctly. For example, in the file I linked to in the issue,
everything between the line "*Step, name=Step-1" and "*End Step" belongs to the first load step, and should naturally be grouped. But for materials, there is only "*Material, name=usermat_elastic" followed by a set of belonging keys which specifies it, but no "*End Material" (not a great design IMO, but we can't change that)

So I think the more suitable option is to have a nested structure, and not a linear vector.

data = Dict(
    :parts => Dict{String, AbaqusPart}(p1 => AbaqusPart(), p2 => AbaqusPart()),
    :assembly => AbaqusAssembly(), # Or maybe [Ordered]Dict{String, AbaqusInstance}
    :materials => Dict{String, AbaqusMaterial}(),
    :steps => OrderedDict{String, AbaqusStep}()
    )

Where the AbaqusStep would need to contain a list of boundary conditions etc.

But as you say, this will be less flexible than simply parsing each key separately, but doing only that doesn't make that much sense to me in this package, since I don't think it gives much extra value wrt. how to use the data later.

And doing this properly might be a quite big task, which in the end might turn out to lead to too much code for it to be suitable for inclusion here. I don't want to be too dismissive (cause I think if it can be done in a sleek fashion it would be very nice), but also I don't want you to spend hours on implementing only for the PR not getting accepted (since this would be a nice-to-have addon, but not the core functionality of the package).

@Joroks
Copy link
Author

Joroks commented Jul 14, 2024

Thanks for the Feedback! I still think that it's usefull to first parse the .inp file directly into the julia native datastructure before interpreting the data. This parsing step doesn't remove any information, it just makes it easier to work with the data.

I've implemented the read_mesh function using this preparser. It's more robust than the current implementation (it should fix #31) and the overall amount of code has reduced as well.

I do agree that we should use a nested data structure if we want to properly support boundary conditions in the future. However, using this preparser should be a big step in the right direction, as it would make it much easer to construct this nested data as we then don't have to worry about parsing this data on the fly now.

Copy link
Member

@KnutAM KnutAM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to write this up!
After understanding how you think, I do agree that this is more flexible, and seems in general like a nice idea!

One issue, however, is that it is almost 2x slower than the current implementation. I think this extra flexibility can motivate a slightly slower implementation, e.g. 20 % slower or so, but almost 2x seems a bit too much? I guess the reason is that the process is split into two parts. If the performance issues can be mitigated, I think this strategy would be beneficial!

Here is a benchmark file to test.
hex100x3.zip

for (i, s) in pairs(quoted_split)
if isodd(i)
s = replace(s, " " => "")
s = uppercase(s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if this is not taken into account for Abaqus, we should not enforce that all is upper-cased. This isn't nice for users since they keys in the sets don't match their expectations.

Comment on lines +9 to +11
struct AbaqusInp
blocks::Vector{AbaqusInpBlock}
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this wrapper?
Seems better to me to store as OrderedDict{String, AbaqusInpBlock} or Vector{Pair{String, AbaqusInpBlock}} to allow iterating over the keys.

msg *= "Tip: If you want a single grid, merge parts and differentiated by Abaqus sets\n"
msg *= " If you want multiple grids, split into multiple input files"
throw(InvalidFileContent(msg))
for inpblock in inpblocks(inp)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be nice if inpblocks(inp) was an ordered dict,
for (keyword, block) in ... would be nicer.

line = readline(f)
while startswith(line, "**")
line = strip(readline(f))
isodd(count('"', line)) && throw(InvalidFileContent("Quoted strings cannot span multiple lines!"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose a single quotation mark is allowed inside a comment so we shouldn't error here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants