Files
JuliaFEM.jl/src/analysis.jl
T
Jukka Aho 73ec910589 feat: Consolidate FEMBase.jl into JuliaFEM (Phase 1 complete)
MAJOR MILESTONE: FEMBase + FEMBasis fully consolidated, JuliaFEM loads!

Consolidated files:
- src/elements/ (3 files): elements.jl, elements_lagrange.jl, integrate.jl
- src/fields/ (1 file): fields.jl (DCTI, DVTI, DCTV, DVTV, etc.)
- src/sparse/ (1 file): sparse.jl (SparseMatrixCOO, SparseVectorCOO)
- src/assembly/ (2 files): problems.jl, assembly.jl
- src/solvers/ (1 file): solvers_base.jl
- src/analysis.jl, src/core_types.jl (Node, IP, IntegrationPoint)

Changes to JuliaFEM.jl:
- Added dependencies: Tensors, Calculus
- Removed @reexport using FEMBase (now consolidated)
- Added 20+ include statements for consolidated files
- Include order: fields → core_types → fembase_compat → sparse → elements

Compatibility layer:
- Created fembase_compat.jl: Minimal FEMBase submodule for vendor packages
- Temporarily disabled vendor-specific Mortar2D functions in solvers_modal.jl

Bug fixes:
- Changed i == 1 → isequal(i, 1) in integrate.jl (== operator overridden by fields)
- Resolved all FEMBasis. namespace references throughout codebase

Result:
-  JuliaFEM loads successfully on Julia 1.12.1
-  134 exported symbols (was 171 with separate FEMBase)
-  Core types accessible: Seg2, Quad4, Problem, AbstractProblem, etc.
- ⚠️  Vendor packages show FEMBase cache warnings (expected, harmless)

TODO:
- Re-enable Mortar2D functions after vendor consolidation
- Field system == operator override needs redesign (Phase 4)
- Continue Phase 2: Consolidate remaining vendor packages
2025-11-08 09:39:16 +02:00

106 lines
3.4 KiB
Julia

# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/FEMBase.jl/blob/master/LICENSE
abstract type AbstractAnalysis end
abstract type AbstractResultsWriter end
mutable struct Analysis{A<:AbstractAnalysis}
name :: String
problems :: Vector{Problem}
fields :: Dict{String, AbstractField}
results_writers :: Vector{AbstractResultsWriter}
properties :: A
end
"""
Analysis(A, analysis_name)
Create a new analysis of type `A`, where `A` is a subtype of `AbstractAnalysis`.
Analysis can be e.g. `Linear` for linear quasistatic analysis, `Nonlinear` for
nonlinear quasistatic analysis or `Modal` for natural frequency analysis.
# Examples
```julia
analysis = Analysis(Linear, "linear quasistatic analysis of beam structure")
```
"""
function Analysis(::Type{A}, name::String="$A Analysis") where A<:AbstractAnalysis
analysis = Analysis{A}(name, [], Dict(), [], A())
@info("Creating a new analysis of type $A with name `$name`.")
return analysis
end
function add_problem!(analysis::Analysis, problems::Problem...)
for problem in problems
@info("Adding problem `$(problem.name)` to analysis `$(analysis.name)`.")
push!(analysis.problems, problem)
end
return nothing
end
add_problems!(analysis::Analysis, problems::Union{Vector, Tuple}) = add_problem!(analysis, problems...)
"""
add_problems!(analysis, problem...)
Add problem(s) to analysis.
# Examples
Add two problems, `beam` and `bc`, to linear quasistatic analysis:
```julia
beam = Problem(Beam, "beam structure", 6)
bc = Problem(Dirichlet, "fix", 6, "displacement")
analysis = Analysis(Linear, "linear quasistatic analysis")
add_problems!(analysis, beam, bc)
```
"""
add_problems!(analysis::Analysis, problems...) = add_problem!(analysis, problems...)
function get_problems(analysis::Analysis)
return analysis.problems
end
function get_problem(analysis::Analysis, problem_name)
problems = filter(p -> p.name == problem_name, get_problems(analysis))
if length(problems) != 1
error("Several problem with name $problem_name found from analysis $(analysis.name).")
end
return first(problems)
end
function add_results_writer!(analysis::Analysis, writer::W) where W<:AbstractResultsWriter
push!(analysis.results_writers, writer)
return nothing
end
function get_results_writers(analysis::Analysis)
return analysis.results_writers
end
function run!(::Analysis{A}) where A<:AbstractAnalysis
@info("This is a placeholder function for running an analysis $A for a set of problems.")
end
function write_results!(::Analysis{A}, ::W) where {A<:AbstractAnalysis, W<:AbstractResultsWriter}
@info("Writing the results of analysis $A is not supported by a results writer $W")
return nothing
end
function write_results!(analysis)
results_writers = get_results_writers(analysis)
if isempty(results_writers)
@info("No result writers attached to the analysis $(analysis.name). " *
"In order to get results of the analysis stored to the disk, one " *
"must attach some results writer to the analysis using " *
"add_results_writer!, e.g. xdmf_writer = Xdmf(\"results\"); " *
"add_results_writer!(analysis, xdmf_writer)")
return nothing
end
for results_writer in results_writers
write_results!(analysis, results_writer)
end
return nothing
end