-
Notifications
You must be signed in to change notification settings - Fork 108
avoid using threadid in landau example, instead use OhMyThreads + ChunkSplitters
#1294
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -26,6 +26,7 @@ using Ferrite | |||||||||||||||||||||
| using Optim, LineSearches | ||||||||||||||||||||||
| using SparseArrays | ||||||||||||||||||||||
| using Tensors | ||||||||||||||||||||||
| using OhMyThreads, ChunkSplitters | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ## Energy terms | ||||||||||||||||||||||
| # ### 4th order Landau free energy | ||||||||||||||||||||||
|
|
@@ -47,7 +48,7 @@ struct ModelParams{V, T} | |||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ### ThreadCache | ||||||||||||||||||||||
| # This holds the values that each thread will use during the assembly. | ||||||||||||||||||||||
| # This holds the values that each task will use during the assembly. | ||||||||||||||||||||||
| struct ThreadCache{CV, T, DIM, F <: Function, GC <: GradientConfig, HC <: HessianConfig} | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| cvP::CV | ||||||||||||||||||||||
| element_indices::Vector{Int} | ||||||||||||||||||||||
|
|
@@ -72,16 +73,17 @@ function ThreadCache(dpc::Int, nodespercell, cvP::CellValues, modelparams, elpot | |||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ## The Model | ||||||||||||||||||||||
| # everything is combined into a model. | ||||||||||||||||||||||
| # Everything is combined into a model. The caches are pre-allocated (one per task) | ||||||||||||||||||||||
| # and indexed by chunk index during assembly. | ||||||||||||||||||||||
| mutable struct LandauModel{T, DH <: DofHandler, CH <: ConstraintHandler, TC <: ThreadCache} | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| dofs::Vector{T} | ||||||||||||||||||||||
| dofhandler::DH | ||||||||||||||||||||||
| boundaryconds::CH | ||||||||||||||||||||||
| threadindices::Vector{Vector{Int}} | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| threadcaches::Vector{TC} | ||||||||||||||||||||||
| caches::Vector{TC} | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| function LandauModel(α, G, gridsize, left::Vec{DIM, T}, right::Vec{DIM, T}, elpotential) where {DIM, T} | ||||||||||||||||||||||
| function LandauModel(α, G, gridsize, left::Vec{DIM, T}, right::Vec{DIM, T}, elpotential, ntasks) where {DIM, T} | ||||||||||||||||||||||
| grid = generate_grid(Tetrahedron, gridsize, left, right) | ||||||||||||||||||||||
| threadindices = Ferrite.create_coloring(grid) | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -106,7 +108,7 @@ function LandauModel(α, G, gridsize, left::Vec{DIM, T}, right::Vec{DIM, T}, elp | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| dpc = ndofs_per_cell(dofhandler) | ||||||||||||||||||||||
| cpc = length(grid.cells[1].nodes) | ||||||||||||||||||||||
| caches = [ThreadCache(dpc, cpc, copy(cvP), ModelParams(α, G), elpotential) for t in 1:Threads.maxthreadid()] | ||||||||||||||||||||||
| caches = [ThreadCache(dpc, cpc, copy(cvP), ModelParams(α, G), elpotential) for _ in 1:ntasks] | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| return LandauModel(dofvector, dofhandler, boundaryconds, threadindices, caches) | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -119,75 +121,77 @@ function save_landau(path, model, dofs = model.dofs) | |||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ## Assembly | ||||||||||||||||||||||
| # This macro defines most of the assembly step, since the structure is the same for | ||||||||||||||||||||||
| # the energy, gradient and Hessian calculations. | ||||||||||||||||||||||
| macro assemble!(innerbody) | ||||||||||||||||||||||
| return esc( | ||||||||||||||||||||||
| quote | ||||||||||||||||||||||
| dofhandler = model.dofhandler | ||||||||||||||||||||||
| for indices in model.threadindices | ||||||||||||||||||||||
| Threads.@threads for i in indices | ||||||||||||||||||||||
| cache = model.threadcaches[Threads.threadid()] | ||||||||||||||||||||||
| eldofs = cache.element_dofs | ||||||||||||||||||||||
| nodeids = dofhandler.grid.cells[i].nodes | ||||||||||||||||||||||
| for j in 1:length(cache.element_coords) | ||||||||||||||||||||||
| cache.element_coords[j] = dofhandler.grid.nodes[nodeids[j]].x | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| reinit!(cache.cvP, cache.element_coords) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| celldofs!(cache.element_indices, dofhandler, i) | ||||||||||||||||||||||
| for j in 1:length(cache.element_dofs) | ||||||||||||||||||||||
| eldofs[j] = dofvector[cache.element_indices[j]] | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| $innerbody | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| # This helper sets up the cell data in the cache for a given cell index, | ||||||||||||||||||||||
| # and returns the element dof values. | ||||||||||||||||||||||
| function setup_cell!(cache, dofhandler, dofvector, cellidx) | ||||||||||||||||||||||
| nodeids = dofhandler.grid.cells[cellidx].nodes | ||||||||||||||||||||||
| for j in 1:length(cache.element_coords) | ||||||||||||||||||||||
| cache.element_coords[j] = dofhandler.grid.nodes[nodeids[j]].x | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| reinit!(cache.cvP, cache.element_coords) | ||||||||||||||||||||||
| celldofs!(cache.element_indices, dofhandler, cellidx) | ||||||||||||||||||||||
| eldofs = cache.element_dofs | ||||||||||||||||||||||
| for j in 1:length(eldofs) | ||||||||||||||||||||||
| eldofs[j] = dofvector[cache.element_indices[j]] | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| return eldofs | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # This calculates the total energy calculation of the grid | ||||||||||||||||||||||
| # This calculates the total energy of the grid. | ||||||||||||||||||||||
| function F(dofvector::Vector{T}, model) where {T} | ||||||||||||||||||||||
| outs = fill(zero(T), Threads.maxthreadid()) | ||||||||||||||||||||||
| @assemble! begin | ||||||||||||||||||||||
| outs[Threads.threadid()] += cache.element_potential(eldofs) | ||||||||||||||||||||||
| out = zero(T) | ||||||||||||||||||||||
| for indices in model.threadindices | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| partial = OhMyThreads.@tasks for (ichunk, range) in enumerate(chunks(indices; n = length(model.caches))) | ||||||||||||||||||||||
|
termi-official marked this conversation as resolved.
|
||||||||||||||||||||||
| @set reducer = + | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this make sense to be extra clear where this macro comes from? (I assume it is from here)
Suggested change
|
||||||||||||||||||||||
| cache = model.caches[ichunk] | ||||||||||||||||||||||
| local_energy = zero(T) | ||||||||||||||||||||||
| for i in range | ||||||||||||||||||||||
| eldofs = setup_cell!(cache, model.dofhandler, dofvector, i) | ||||||||||||||||||||||
| local_energy += cache.element_potential(eldofs) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| local_energy | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| out += partial | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| return sum(outs) | ||||||||||||||||||||||
| return out | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # The gradient calculation for each dof | ||||||||||||||||||||||
| # The gradient calculation for each dof. | ||||||||||||||||||||||
| # The grid coloring ensures no two tasks within a color share dofs, | ||||||||||||||||||||||
| # so assembly is safe without locks. | ||||||||||||||||||||||
| function ∇F!(∇f::Vector{T}, dofvector::Vector{T}, model::LandauModel{T}) where {T} | ||||||||||||||||||||||
| fill!(∇f, zero(T)) | ||||||||||||||||||||||
| @assemble! begin | ||||||||||||||||||||||
| ForwardDiff.gradient!(cache.element_gradient, cache.element_potential, eldofs, cache.gradconf) | ||||||||||||||||||||||
| @inbounds assemble!(∇f, cache.element_indices, cache.element_gradient) | ||||||||||||||||||||||
| for indices in model.threadindices | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| OhMyThreads.@tasks for (ichunk, range) in enumerate(chunks(indices; n = length(model.caches))) | ||||||||||||||||||||||
| cache = model.caches[ichunk] | ||||||||||||||||||||||
| for i in range | ||||||||||||||||||||||
| eldofs = setup_cell!(cache, model.dofhandler, dofvector, i) | ||||||||||||||||||||||
| ForwardDiff.gradient!(cache.element_gradient, cache.element_potential, eldofs, cache.gradconf) | ||||||||||||||||||||||
| @inbounds assemble!(∇f, cache.element_indices, cache.element_gradient) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| return | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # The Hessian calculation for the whole grid | ||||||||||||||||||||||
| function ∇²F!(∇²f::SparseMatrixCSC, dofvector::Vector{T}, model::LandauModel{T}) where {T} | ||||||||||||||||||||||
| assemblers = [start_assemble(∇²f) for t in 1:Threads.maxthreadid()] | ||||||||||||||||||||||
| @assemble! begin | ||||||||||||||||||||||
| ForwardDiff.hessian!(cache.element_hessian, cache.element_potential, eldofs, cache.hessconf) | ||||||||||||||||||||||
| @inbounds assemble!(assemblers[Threads.threadid()], cache.element_indices, cache.element_hessian) | ||||||||||||||||||||||
| dh = model.dofhandler | ||||||||||||||||||||||
| ntasks = length(model.caches) | ||||||||||||||||||||||
| assemblers = [start_assemble(∇²f; fillzero = (i == 1)) for i in 1:ntasks] | ||||||||||||||||||||||
| for indices in model.threadindices | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| OhMyThreads.@tasks for (ichunk, range) in enumerate(chunks(indices; n = ntasks)) | ||||||||||||||||||||||
| cache = model.caches[ichunk] | ||||||||||||||||||||||
| for i in range | ||||||||||||||||||||||
| eldofs = setup_cell!(cache, dh, dofvector, i) | ||||||||||||||||||||||
| ForwardDiff.hessian!(cache.element_hessian, cache.element_potential, eldofs, cache.hessconf) | ||||||||||||||||||||||
| @inbounds assemble!(assemblers[ichunk], cache.element_indices, cache.element_hessian) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| return | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # We can also calculate all things in one go! | ||||||||||||||||||||||
| function calcall(∇²f::SparseMatrixCSC, ∇f::Vector{T}, dofvector::Vector{T}, model::LandauModel{T}) where {T} | ||||||||||||||||||||||
| outs = fill(zero(T), Threads.maxthreadid()) | ||||||||||||||||||||||
| fill!(∇f, zero(T)) | ||||||||||||||||||||||
| assemblers = [start_assemble(∇²f, ∇f) for t in 1:Threads.maxthreadid()] | ||||||||||||||||||||||
| @assemble! begin | ||||||||||||||||||||||
| outs[Threads.threadid()] += cache.element_potential(eldofs) | ||||||||||||||||||||||
| ForwardDiff.hessian!(cache.element_hessian, cache.element_potential, eldofs, cache.hessconf) | ||||||||||||||||||||||
| ForwardDiff.gradient!(cache.element_gradient, cache.element_potential, eldofs, cache.gradconf) | ||||||||||||||||||||||
| @inbounds assemble!(assemblers[Threads.threadid()], cache.element_indices, cache.element_gradient, cache.element_hessian) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
| return sum(outs) | ||||||||||||||||||||||
| end | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ## Minimization | ||||||||||||||||||||||
| # Now everything can be combined to minimize the energy, and find the equilibrium | ||||||||||||||||||||||
|
|
@@ -255,7 +259,7 @@ G = V2T(1.0e2, 0.0, 1.0e2) | |||||||||||||||||||||
| α = Vec{3}((-1.0, 1.0, 1.0)) | ||||||||||||||||||||||
| left = Vec{3}((-75.0, -25.0, -2.0)) | ||||||||||||||||||||||
| right = Vec{3}((75.0, 25.0, 2.0)) | ||||||||||||||||||||||
| model = LandauModel(α, G, (50, 50, 2), left, right, element_potential) | ||||||||||||||||||||||
| model = LandauModel(α, G, (50, 50, 2), left, right, element_potential, Threads.nthreads()) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to add some quick tests to check that we don't make unintended changes (both here and for future)?
Suggested change
|
||||||||||||||||||||||
| save_landau("landauorig", model) | ||||||||||||||||||||||
| @time minimize!(model) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.