Exodus.jl error in write from scratch example

@Craig_Hamel

I just installed Exodus.jl on my M2 MacBook Air running Julia 1.10.2.

When I try to run the " Write example from scratch" example shown here: GitHub - cmhamel/Exodus.jl: A julia interface for accessing the ExodusII data format
it gives the following error:
`ERROR: LoadError: MethodError: no method matching (Initialization{Int32})(::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64)
Stacktrace:
[1] top-level scope
@ ~/Documents/bob/code/julia/exodus_jl_test/write_example_from_scratch.jl:37
[2] include(fname::String)
@ Base.MainInclude ./client.jl:489
[3] top-level scope
@ REPL[2]:1
in expression starting at /Users/…/exodus_jl_test/write_example_from_scratch.jl:37

The line it’s hanging on is the following expression:

init = Initialization{bulk_int_type}(
  num_dim, num_nodes, num_elems,
  num_elem_blks, num_side_sets, num_node_sets
)

Thoughts?

1 Like

Sorry the README is out of date. I need to find time to update it.

The new syntax is the following

init = Initialization{
  num_dim, num_nodes, num_elems,
  num_elem_blks, num_side_sets, num_node_sets
}()

You just have to make sure that if you desire your exodusII file to be in say Int32 mode for integers that the variables in the above are also Int32. I made this change in a push towards making opening exodus files type stable which it currently is not due to having to peak at integer/float types and these initialization parameters.

If this still gives you issues, file an issue on the repo and I’ll patch it up ASAP.

@Craig_Hamel thanks for the quick reply. That fixed that part of the example but now it hangs on the next line:

exo = ExodusDatabase(
  "test_write.e", "w", init,
  maps_int_type, ids_int_type, bulk_int_type, float_type
)

which gives the following warning and error:

┌ Warning: This is deprecated. Use ExodusDatabase{M, I, B, F}(file_name, mode, init) instead. This method now wraps that.
â”” @ Exodus ~/.julia/packages/Exodus/Ozd3m/src/ExodusTypes.jl:451
ERROR: Exodus.ExodusError(-1, “Exodus.ExodusDatabase → libexodus.ex_create_int”)
Stacktrace:
[1] exodus_error_check
@ ~/.julia/packages/Exodus/Ozd3m/src/Errors.jl:21 [inlined]
[2] (ExodusDatabase{Int32, Int32, Int32, Float64})(file_name::String, mode::String, init::Initialization{2, 9, 4, 1, 0, 0})
@ Exodus ~/.julia/packages/Exodus/Ozd3m/src/ExodusTypes.jl:469
[3] ExodusDatabase(file_name::String, mode::String, init::Initialization{…}, ::Type{…}, ::Type{…}, ::Type{…}, ::Type{…})
@ Exodus ~/.julia/packages/Exodus/Ozd3m/src/ExodusTypes.jl:452
[4] top-level scope
@ ~/Documents/…/write_example_from_scratch.jl:51
Some type information was truncated. Use show(err) to see complete types.

I tried changing the above line to this:

exo = ExodusDatabase{maps_int_type, ids_int_type, bulk_int_type, float_type}(
  "test_write.e", "w", init
)

and that appears to have removed the warning but I still get a similar error:

ERROR: Exodus.ExodusError(-1, “Exodus.ExodusDatabase → libexodus.ex_create_int”)
Stacktrace:
[1] exodus_error_check
@ ~/.julia/packages/Exodus/Ozd3m/src/Errors.jl:21 [inlined]
[2] (ExodusDatabase{Int32, Int32, Int32, Float64})(file_name::String, mode::String, init::Initialization{2, 9, 4, 1, 0, 0})
@ Exodus ~/.julia/packages/Exodus/Ozd3m/src/ExodusTypes.jl:469
[3] top-level scope
@ ~/Documents/…/write_example_from_scratch.jl:57

Is there somethings else I need to tweak in the example?

Try the following instead

exo = ExodusDatabase{maps_int_type, ids_int_type, bulk_int_type, float_type, init}(
  "test_write.e", "w"
)

@Craig_Hamel

Tried the above but getting a different error.

The following code:

exo = ExodusDatabase{maps_int_type, ids_int_type, bulk_int_type, float_type, init}("test_write.e", "w")

gives the following error:

ERROR: MethodError: no method matching ExodusDatabase{Int32, Int32, Int32, Float64, Initialization{2, 9, 4, 1, 0, 0}()}(::String, ::String)

Closest candidates are:
(::Type{ExodusDatabase{M, I, B, F, Init}} where {M, I, B, F, Init})(::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any)
@ Exodus ~/.julia/packages/Exodus/Ozd3m/src/ExodusTypes.jl:184

Stacktrace:
[1] top-level scope
@ ~/Documents/…/write_example_from_scratch.jl:59

I did find that simply doing exo = ExodusDatabase("test_write.e", "w") seems to work, but I’m not sure if this is sufficient.

@jman87

using Exodus

# data to write
coords = [
  1.0 0.5 0.5 1.0 0.0 0.0 0.5 1.0 0.0
  1.0 1.0 0.5 0.5 1.0 0.5 0.0 0.0 0.0
]

conn = [
  1 2 4 3
  2 5 3 6
  3 6 7 9
  4 3 8 7
]

# make some hack variables to write
v_nodal_1 = rand(9)
v_nodal_2 = rand(9)

v_elem_1 = rand(4)
v_elem_2 = rand(4)

# set the types
maps_int_type = Int32
ids_int_type  = Int32
bulk_int_type = Int32
float_type    = Float64

# initialization parameters
num_dim, num_nodes = size(coords)
num_elems          = size(conn, 2)
num_elem_blks      = 1
num_side_sets      = 0
num_node_sets      = 0

# make init
init = Initialization{
  bulk_int_type(num_dim), bulk_int_type(num_nodes), bulk_int_type(num_elems),
  bulk_int_type(num_elem_blks), bulk_int_type(num_side_sets), bulk_int_type(num_node_sets)
}()

exo = ExodusDatabase{maps_int_type, ids_int_type, bulk_int_type, float_type}(
  "test_wrtie.e", "w", init
)

# how to write coordinates
write_coordinates(exo, coords)
# how to write a block
write_block(exo, 1, "QUAD4", conn)
# need at least one timestep to output variables
write_time(exo, 1, 0.0)
# write number of variables and their names
write_names(exo, NodalVariable, ["v_nodal_1", "v_nodal_2"])
write_names(exo, ElementVariable, ["v_elem_1", "v_elem_2"])
# write variable values the 1 is for the time step
write_values(exo, NodalVariable, 1, "v_nodal_1", v_nodal_1)
write_values(exo, NodalVariable, 1, "v_nodal_2", v_nodal_2)
# the first 1 is for the time step 
# and the second 1 is for the block number
write_values(exo, ElementVariable, 1, 1, "v_elem_1", v_elem_1)
write_values(exo, ElementVariable, 1, 1, "v_elem_2", v_elem_2)
# don't forget to close the exodusdatabase, it can get corrupted otherwise if you're writing
close(exo)

This worked for me.

You may want to freeze the version of Exodus.jl in your compat in your Project.toml files so this sort of thing doesn’t happen again. Writing an exodus file from scratch is pretty non-standard so this is likely the last thing I’ll check (if at all) when making changes. I guess I didn’t have this covered in my test suite. Feel free to open a PR to add test coverage if you’d like. Or open an issue and maybe I’ll get around to it.

I copied/pasted the above code into a new file and started a fresh Julia session but was still getting the following error:

ERROR: Exodus.ExodusError(-1, “Exodus.ExodusDatabase → libexodus.ex_create_int”)
Stacktrace:
[1] exodus_error_check
@ ~/.julia/packages/Exodus/Ozd3m/src/Errors.jl:21 [inlined]
[2] (ExodusDatabase{Int32, Int32, Int32, Float64})(file_name::String, mode::String, init::Initialization{2, 9, 4, 1, 0, 0})
@ Exodus ~/.julia/packages/Exodus/Ozd3m/src/ExodusTypes.jl:469
[3] top-level scope
@ ~/Documents/…/new_write_example_from_scratch.jl:42

I tried updating the Exodus package and now I get the error:

ERROR: UndefVarError: error not defined
Stacktrace:
[1] (ExodusDatabase{Int32, Int32, Int32, Float64})(file_name::String, mode::String, init::Initialization{2, 9, 4, 1, 0, 0})
@ Exodus ~/.julia/packages/Exodus/6y2Sw/src/ExodusTypes.jl:495
[2] top-level scope
@ ~/Documents/…/new_write_example_from_scratch.jl:42

FYI, my reason for giving this a try was that I’ve got some simple meshing routines I wrote in Julia and it would be nice to have an easy way to put them out in Exodus, but I get that that’s probably not the typical use-case you had in mind.

Ah, meshing routines are a good reason for this use case!

Could you copy-paste the output for

pkg> status

I want to see what version of everything you’re using.

Also if error is not defined there’s probably something else going on in your workflow and this is no longer an Exodus issue. That’s a julia function in Base.

@Craig_Hamel

Sorry for the big delay getting back to this… typical struggles of side projects! :slight_smile:

Here’s the output showing my Julia version and the package versions after running pkg> up just now. And after running that, I’m still getting the following errors, which I’ll show below.

Version Info:

julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 8 Ă— Apple M2
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)
Environment:
  DYLD_LIBRARY_PATH = /opt/intel/oneapi/compiler/2022.2.0/mac/compiler/lib/intel64_mac:/opt/intel/oneapi/compiler/2022.2.0/mac/compiler/lib

(@v1.10) pkg> st
Status `~/.julia/environments/v1.10/Project.toml`
  [f57ae99e] Exodus v0.13.1
  [91a5bcdd] Plots v1.40.4
  [24249f21] SymPy v2.0.1

So then, what I tried running was simply:

julia> include("new_write_example_from_scratch.jl")

where, the new_write_example_from_scratch.jl file contains the following code:

using Exodus

# data to write
coords = [
  1.0 0.5 0.5 1.0 0.0 0.0 0.5 1.0 0.0
  1.0 1.0 0.5 0.5 1.0 0.5 0.0 0.0 0.0
]

conn = [
  1 2 4 3
  2 5 3 6
  3 6 7 9
  4 3 8 7
]

# make some hack variables to write
v_nodal_1 = rand(9)
v_nodal_2 = rand(9)

v_elem_1 = rand(4)
v_elem_2 = rand(4)

# set the types
maps_int_type = Int32
ids_int_type  = Int32
bulk_int_type = Int32
float_type    = Float64

# initialization parameters
num_dim, num_nodes = size(coords)
num_elems          = size(conn, 2)
num_elem_blks      = 1
num_side_sets      = 0
num_node_sets      = 0

# make init
init = Initialization{
  bulk_int_type(num_dim), bulk_int_type(num_nodes), bulk_int_type(num_elems),
  bulk_int_type(num_elem_blks), bulk_int_type(num_side_sets), bulk_int_type(num_node_sets)
}()

exo = ExodusDatabase{maps_int_type, ids_int_type, bulk_int_type, float_type}(
  "test_write.e", "w", init
)

# how to write coordinates
write_coordinates(exo, coords)
# how to write a block
write_block(exo, 1, "QUAD4", conn)
# need at least one timestep to output variables
write_time(exo, 1, 0.0)
# write number of variables and their names
write_names(exo, NodalVariable, ["v_nodal_1", "v_nodal_2"])
write_names(exo, ElementVariable, ["v_elem_1", "v_elem_2"])
# write variable values the 1 is for the time step
write_values(exo, NodalVariable, 1, "v_nodal_1", v_nodal_1)
write_values(exo, NodalVariable, 1, "v_nodal_2", v_nodal_2)
# the first 1 is for the time step
# and the second 1 is for the block number
write_values(exo, ElementVariable, 1, 1, "v_elem_1", v_elem_1)
write_values(exo, ElementVariable, 1, 1, "v_elem_2", v_elem_2)
# don't forget to close the exodusdatabase, it can get corrupted otherwise if you're writing
close(exo)

Running the above gives the following output:

julia> include("new_write_example_from_scratch.jl")
ERROR: LoadError: UndefVarError: `error` not defined
Stacktrace:
 [1] (ExodusDatabase{Int32, Int32, Int32, Float64})(file_name::String, mode::String, init::Initialization{2, 9, 4, 1, 0, 0})
   @ Exodus ~/.julia/packages/Exodus/6y2Sw/src/ExodusTypes.jl:495
 [2] top-level scope
   @ ~/Documents/bob/code/julia/exodus_jl_test/new_write_example_from_scratch.jl:42
 [3] include(fname::String)
   @ Base.MainInclude ./client.jl:489
 [4] top-level scope
   @ REPL[7]:1
in expression starting at /Users/browningfamjam/Documents/bob/code/julia/exodus_jl_test/new_write_example_from_scratch.jl:42

julia>

Hopefully this is clear and reboots our conversation. Let me know if this is possibly a version issue as I’d still love to be using your package with my masher, which would hopefully be a helpful use case offering you some feedback.

@Craig_Hamel

See above for picking back up where we left off, but here’s what else I’ve tried/figured out.

I upgraded my Julia package to the current stable release, 1.10.3, and still got the same error.

Upon digging into your code, the problematic line is in ExodusTypes.jl around 495:

  if exo < 0
    error("Error trying to create file $file_name.")
  end

I noticed that in other places you are also defining a variable named error, so I’m wondering if Julia is getting confused by that. I know it’s supposed to be smart enough to with multiple dispatch and all, but good coding would be to maybe make those variables something like errormes to distinguish them. Then again, this may be some entirely other bug! LOL

Anyway, the other interesting point is that it’s apparently attempting to stop with the error message noted above, which means that there’s something wrong with opening the input file.

Do you see anything glaringly wrong with the file name or other parameters I’ve set in the example? I’m pretty sure I’m mostly just using your example you’d sent previously. I’m beginning to wonder if this is a Mac vs Windows issue if you’re running on Windows (don’t know).

I’ll let you know if I figure anything else out.

@Craig_Hamel

This is really silly, but I believe I’ve figured out “the bug”… it appears to be throwing an error when it tries to initialize the Exodus output file if that file already exists. On top of that, the error message is also not displaying correctly, which I think is related to the issue I described above.

But the good news is that the example does appear to be working. You just have to manually delete the old file before running the script.