Repository navigation
MethodError in LUSolver due to Float64/Float32 mismatch when using vector_type=Vector{Float32} #68
Copy link
Copy link
Closed
Description
Description
I am trying to generate FEM snapshots and extract the solution vectors directly in Float32. However, passing vector_type=Vector{Float32} to OrderedFESpace causes a MethodError during the time integration phase (solution_snapshots).
It appears that the underlying system matrix is factored as Float64 (resulting in an UmfpackLU{Float64, Int64} object), which clashes with the Float32 state vectors during the ldiv! operation inside the LUSolver (likely because UMFPACK strictly requires Float64 or ComplexF64).
Minimal Working Example
Here is a self-contained script that reproduces the crash:
using Gridap
using GridapROMs
using GridapROMs.ParamDataStructures
# Spatial domain and reference element
domain = (0.0, 1.0)
partition = (10,)
model = CartesianDiscreteModel(domain, partition)
reffe = ReferenceFE(lagrangian, Float32, 1) # Explicitly using Float32
# FE Space with Float32 vector type
println("Creating OrderedFESpace with Float32...")
V = OrderedFESpace(model, reffe; vector_type=Vector{Float32})
# Parametric transient setup
println("Creating TransientTrialParamFESpace...")
u(σ, t) = x -> σ[1] * x[1] * t
uₚₜ(σ, t) = parameterise(u, σ, t)
U = TransientTrialParamFESpace(V, uₚₜ)
# Weak form definition
println("Defining Weak Form & Parametric Operator...")
dΩ = Measure(Triangulation(model), 2)
m(σ, t, du, v) = ∫(v * du)dΩ
a(σ, t, u, v) = ∫(v * u)dΩ
r(σ, t, u, v) = m(σ, t, ∂t(u), v) + a(σ, t, u, v)
tdomain = 0.0:0.1:0.5
D = TransientParamSpace((1.0, 2.0), tdomain)
feop = TransientLinearParamOperator(r, (a, m), D, U, V)
# Solver and initial conditions
println("Setting up Initial Conditions and Solver...")
u₀(σ) = x -> 0.0
u₀ₚ(σ) = parameterise(u₀, σ)
uh₀ₚ(σ) = interpolate_everywhere(u₀ₚ(σ), U(σ, 0.0))
slvr = ThetaMethod(LUSolver(), 0.1, 0.5)
σₒₙ = TransientRealisation(Realisation([[1.5]]), tdomain)
# Time integration (Triggering the MethodError)
println("Extracting solution snapshots...")
snapshots, _ = solution_snapshots(slvr, feop, σₒₙ, uh₀ₚ)Error / Stacktrace
(Note the type mismatch in the first line between UmfpackLU{Float64, Int64} and Matrix{Float32})
Creating OrderedFESpace with Float32...
Creating TransientTrialParamFESpace...
Defining Weak Form & Parametric Operator...
Setting up Initial Conditions and Solver...
Extracting solution snapshots...
ERROR: LoadError: MethodError: no method matching ldiv!(::SparseArrays.UMFPACK.UmfpackLU{Float64, Int64}, ::SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true})
The function `ldiv!` exists, but no method is defined for this combination of argument types.
Closest candidates are:
ldiv!(::IterativeSolvers.Identity, ::Any)
@ IterativeSolvers ~/.julia/packages/IterativeSolvers/bjiMt/src/common.jl:31
ldiv!(::LinearAlgebra.Tridiagonal, ::AbstractVecOrMat)
@ LinearAlgebra ~/.julia/juliaup/julia-1.12.6+0.x64.linux.gnu/share/julia/stdlib/v1.12/LinearAlgebra/src/tridiag.jl:1004
ldiv!(::SparseArrays.UMFPACK.UmfpackLU{T}, ::StridedVecOrMat{T}) where T<:Union{Float64, ComplexF64}
@ SparseArrays ~/.julia/juliaup/julia-1.12.6+0.x64.linux.gnu/share/julia/stdlib/v1.12/SparseArrays/src/solvers/umfpack.jl:932
...
Stacktrace:
[1] ldiv!(Y::SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}, A::SparseArrays.UMFPACK.UmfpackLU{Float64, Int64}, B::SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true})
@ LinearAlgebra ~/.julia/juliaup/julia-1.12.6+0.x64.linux.gnu/share/julia/stdlib/v1.12/LinearAlgebra/src/factorization.jl:164
[2] solve!(x::SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true}, ns::Gridap.Algebra.LUNumericalSetup{SparseArrays.UMFPACK.UmfpackLU{Float64, Int64}}, b::SubArray{Float32, 1, Matrix{Float32}, Tuple{Base.Slice{Base.OneTo{Int64}}, Int64}, true})
@ Gridap.Algebra ~/.julia/packages/Gridap/cvsif/src/Algebra/LinearSolvers.jl:274
[3] solve!(x::ConsecutiveParamVector{Float32, Matrix{Float32}}, ns::Gridap.Algebra.LUNumericalSetup{SparseArrays.UMFPACK.UmfpackLU{Float64, Int64}}, A::ConsecutiveParamSparseMatrixCSC{Float32, Int64, Matrix{Float32}}, b::ConsecutiveParamVector{Float32, Matrix{Float32}})
@ GridapROMs.ParamAlgebra ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamAlgebra/ParamSolvers.jl:41
[4] solve!(x::ConsecutiveParamVector{Float32, Matrix{Float32}}, ls::LUSolver, A::ConsecutiveParamSparseMatrixCSC{Float32, Int64, Matrix{Float32}}, b::ConsecutiveParamVector{Float32, Matrix{Float32}})
@ GridapROMs.ParamAlgebra ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamAlgebra/ParamSolvers.jl:25
[5] solve!(x::ConsecutiveParamVector{Float32, Matrix{Float32}}, ls::LUSolver, op::GridapROMs.ParamODEs.ParamStageOperator, cache::GridapROMs.ParamAlgebra.SystemCache)
@ GridapROMs.ParamAlgebra ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamAlgebra/ParamSolvers.jl:69
[6] ode_march!(statef::Tuple{ConsecutiveParamVector{Float32, Matrix{Float32}}, ConsecutiveParamVector{Float32, Matrix{Float32}}}, solver::ThetaMethod, odeop::GridapROMs.ParamSteady.GenericParamOperator{GridapROMs.ParamODEs.LinearParamODE, GridapROMs.Utils.JointDomains}, r::GridapROMs.ParamDataStructures.TransientRealisationAt{Realisation{Vector{Vector{Float64}}}, Float64}, state::Tuple{ConsecutiveParamVector{Float32, Matrix{Float32}}, ConsecutiveParamVector{Float32, Matrix{Float32}}}, odecache::Tuple{Tuple{ConsecutiveParamVector{Float32, Matrix{Float32}}, ConsecutiveParamVector{Float32, Matrix{Float32}}}, GridapROMs.ParamAlgebra.ParamCache, GridapROMs.ParamAlgebra.SystemCache})
@ GridapROMs.ParamODEs ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamODEs/ThetaMethod.jl:64
[7] iterate(sol::GridapROMs.ParamODEs.ODEParamSolution{ConsecutiveParamVector{Float32, Matrix{Float32}}})
@ GridapROMs.ParamODEs ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamODEs/ODEParamSolutions.jl:23
[8] iterate
@ ./iterators.jl:197 [inlined]
[9] iterate
@ ./iterators.jl:196 [inlined]
[10] collect_param_solutions(sol::GridapROMs.ParamODEs.ODEParamSolution{ConsecutiveParamVector{Float32, Matrix{Float32}}})
@ GridapROMs.ParamODEs ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamODEs/ODEParamSolutions.jl:116
[11] macro expansion
@ ./timing.jl:697 [inlined]
[12] collect(sol::GridapROMs.ParamODEs.ODEParamSolution{ConsecutiveParamVector{Float32, Matrix{Float32}}})
@ GridapROMs.ParamODEs ~/.julia/packages/GridapROMs/N03YZ/src/FEM/ParamODEs/ODEParamSolutions.jl:51
[13] solution_snapshots(fesolver::ThetaMethod, op::GridapROMs.ParamSteady.GenericParamOperator{GridapROMs.ParamODEs.LinearParamODE, GridapROMs.Utils.JointDomains}, r::GridapROMs.ParamDataStructures.GenericTransientRealisation{Realisation{Vector{Vector{Float64}}}, Float64, Vector{Float64}}, args::Function)
@ GridapROMs.RBTransient ~/.julia/packages/GridapROMs/N03YZ/src/RB/RBTransient/RBSolvers.jl:52Environment
- Julia version: 1.12.6
- Gridap version: 0.20.8
- GridapROMs version: 0.1.4
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
nichomueller commentedon Aug 4, 2026
Thank you for opening the issue! The problem lies within
LinearAlgebra(more specifically, theUmfpackpackage for factorizations). Indeed, an analogous test inGridapwill still fail, meaning the problem is not inherent toGridapROMs:This will result in the following error:
Until
LinearAlgebraexposes new factorization methods, it's necessary to stick withFloat64element types.