Skip to content

Commit

Permalink
Disabled cached Unfitted evolution due to bug + testing
Browse files Browse the repository at this point in the history
  • Loading branch information
zjwegert committed Dec 15, 2024
1 parent 8448a39 commit 3dec36c
Show file tree
Hide file tree
Showing 7 changed files with 512 additions and 29 deletions.
250 changes: 250 additions & 0 deletions scripts/Embedded/Bugs/odes_reassemble_stiffness.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
using Test

using GridapTopOpt
using Gridap, Gridap.Geometry, Gridap.Adaptivity, Gridap.ODEs
using GridapEmbedded

function update_reuse!(state,reuse_new,op;zero_tF=false)
U, (tF, stateF, state0, uF, odecache) = state
odeslvrcache, odeopcache = odecache
_, ui_pre, slopes, J, r, sysslvrcaches = odeslvrcache

data = allocate_odecache(ode_solver,ODEOpFromTFEOp(op),tF,stateF)
odeslvrcache_new = (reuse_new, ui_pre, slopes, J, r, data[1][end])
odecache_new = odeslvrcache_new, odeopcache
_tF = zero_tF ? 0.0 : tF
return U, (_tF, stateF, state0, uF, odecache_new)
end

order = 1
n = 50
_model = CartesianDiscreteModel((0,1,0,1),(n,n))
cd = Gridap.Geometry.get_cartesian_descriptor(_model)
base_model = UnstructuredDiscreteModel(_model)
ref_model = refine(base_model, refinement_method = "barycentric")
model = ref_model.model
h = maximum(cd.sizes)
steps = 10

reffe_scalar = ReferenceFE(lagrangian,Float64,order)
V_φ = TestFESpace(model,reffe_scalar)
φh = interpolate(x->-sqrt((x[1]-0.5)^2+(x[2]-0.5)^2)+0.25,V_φ)
velh = interpolate(x->-1,V_φ)

## Trians

Ω = Triangulation(model)
= Measure(Ω,2*order)
Γg = SkeletonTriangulation(Ω)
dΓg = Measure(Γg,2order)
n_Γg = get_normal_vector(Γg)

## ODE Solver
ode_ls = LUSolver()
ode_nl = NLSolver(ode_ls, show_trace=false, method=:newton, iterations=10)
ode_solver = GridapTopOpt.MutableRungeKutta(ode_nl, ode_ls, 0.1*h, :DIRK_CrankNicolson_2_2)

## ODE Op
v_norm = maximum(abs,get_free_dof_values(velh))
β(vh,∇φ) = vh/(1e-20 + v_norm) * ∇φ/(1e-20 + norm(∇φ))
stiffness(t,u,v) = (((β (velh,(φh))) (u)) * v)dΩ + (0.1*h^2*jump((u) n_Γg)*jump((v) n_Γg))dΓg
mass(t, ∂ₜu, v) = (∂ₜu * v)dΩ
forcing(t,v) = (0v)dΩ + (0*jump((v) n_Γg))dΓg
Ut_φ = TransientTrialFESpace(V_φ)

# Both forms constant
op = TransientLinearFEOperator((stiffness,mass),forcing,Ut_φ,V_φ;
constant_forms=(true,true))
ode_sol = ODEs.solve(ode_solver,op,0.0,ode_solver.dt*steps,φh)
data0, state0 = Base.iterate(ode_sol)
data1, state1 = Base.iterate(ode_sol,state0)

# # Update φh and velh
# φh_new = FEFunction(V_φ,copy(get_free_dof_values(data1[2])))
# velh_new = interpolate(x->-2,V_φ)
# v_norm_new = maximum(abs,get_free_dof_values(velh_new))
# β_new(vh,∇φ) = vh/(1e-20 + v_norm_new) * ∇φ/(1e-20 + norm(∇φ))
# stiffness_new(t,u,v) = ∫(((β_new ∘ (velh,∇(φh))) ⋅ ∇(u)) * v)dΩ + ∫(0.1*h^2*jump(∇(u) ⋅ n_Γg)*jump(∇(v) ⋅ n_Γg))dΓg
# op = TransientLinearFEOperator((stiffness_new,mass),forcing,Ut_φ,V_φ;
# constant_forms=(true,true))
# ode_sol_new = ODEs.solve(ode_solver,op,0.0,ode_solver.dt*steps,φh_new)
# data2, state2 = Base.iterate(ode_sol)
# data3, state3 = Base.iterate(ode_sol,state2)

# first form non-constant
nc_op = TransientLinearFEOperator((stiffness,mass),forcing,Ut_φ,V_φ;
constant_forms=(false,true))
nc_ode_sol = ODEs.solve(ode_solver,nc_op,0.0,ode_solver.dt*steps,φh)
nc_data0, nc_state0 = Base.iterate(nc_ode_sol)
nc_data1, nc_state1 = Base.iterate(nc_ode_sol,nc_state0)

data1[1] == nc_data1[1]
norm(get_free_dof_values(data1[2]) - get_free_dof_values(nc_data1[2]),Inf)

# first form non-constant then switch to constant
s_op = TransientLinearFEOperator((stiffness,mass),forcing,Ut_φ,V_φ;
constant_forms=(false,true))
s_ode_sol = ODEs.solve(ode_solver,s_op,0.0,ode_solver.dt*steps,φh)
s_data0, s_state0 = Base.iterate(s_ode_sol)
s_state0_new = update_reuse!(s_state0,true)
s_data1, s_state1 = Base.iterate(s_ode_sol,s_state0_new)

data1[1] == s_data1[1]
norm(get_free_dof_values(data1[2]) - get_free_dof_values(s_data1[2]),Inf)

########################################################
using Gridap.FESpaces, Gridap.Polynomials
using LinearAlgebra
# TrianientLinearFEOpFromWeakForm2
struct TransientLinearFEOpFromWeakForm2 <: TransientFEOperator{LinearODE}
forms::Tuple{Vararg{Function}}
res::Function
jacs::Tuple{Vararg{Function}}
constant_forms::BitVector
assembler::Assembler
trial::FESpace
test::FESpace
order::Integer
end

# Constructor with manual jacobians
function TransientLinearFEOperator2(
forms::Tuple{Vararg{Function}}, res::Function, jacs::Tuple{Vararg{Function}},
trial, test;
constant_forms::BitVector=falses(length(forms)),
assembler=SparseMatrixAssembler(trial, test)
)
order = length(jacs) - 1
TransientLinearFEOpFromWeakForm2(
forms, res, jacs, constant_forms,
assembler, trial, test, order
)
end

# No constructor with flat arguments: would clash with the constructors
# below with flat forms and automatic jacobians, which are more useful

# Constructor with automatic jacobians
function TransientLinearFEOperator2(
forms::Tuple{Vararg{Function}}, res::Function,
trial, test;
constant_forms::BitVector=falses(length(forms)),
assembler=SparseMatrixAssembler(trial, test)
)
# When the operator is linear, the jacobians are the forms themselves
order = length(forms) - 1
jacs = ntuple(k -> ((t, u, duk, v) -> forms[k](t, duk, v)), order + 1)

TransientLinearFEOperator2(
forms, res, jacs, trial, test;
constant_forms, assembler
)
end

# Constructor with flat forms and automatic jacobians (orders 0, 1, 2)
function TransientLinearFEOperator2(
mass::Function, res::Function,
trial, test;
constant_forms::BitVector=falses(1),
assembler=SparseMatrixAssembler(trial, test)
)
TransientLinearFEOperator2(
(mass,), res, trial, test;
constant_forms, assembler
)
end

function TransientLinearFEOperator2(
stiffness::Function, mass::Function, res::Function,
trial, test;
constant_forms::BitVector=falses(2),
assembler=SparseMatrixAssembler(trial, test)
)
TransientLinearFEOperator2(
(stiffness, mass), res, trial, test;
constant_forms, assembler
)
end

function TransientLinearFEOperator2(
stiffness::Function, damping::Function, mass::Function, res::Function,
trial, test;
constant_forms::BitVector=falses(3),
assembler=SparseMatrixAssembler(trial, test)
)
TransientLinearFEOpFromWeakForm2(
(stiffness, damping, mass), res, trial, test;
constant_forms, assembler
)
end

# TransientFEOperator interface
FESpaces.get_test(tfeop::TransientLinearFEOpFromWeakForm2) = tfeop.test

FESpaces.get_trial(tfeop::TransientLinearFEOpFromWeakForm2) = tfeop.trial

Polynomials.get_order(tfeop::TransientLinearFEOpFromWeakForm2) = tfeop.order

ODEs.get_res(tfeop::TransientLinearFEOpFromWeakForm2) = (t, u, v) -> tfeop.res(t, v)

ODEs.get_jacs(tfeop::TransientLinearFEOpFromWeakForm2) = tfeop.jacs

ODEs.get_forms(tfeop::TransientLinearFEOpFromWeakForm2) = tfeop.forms

function ODEs.is_form_constant(tfeop::TransientLinearFEOpFromWeakForm2, k::Integer)
tfeop.constant_forms[k+1]
end

ODEs.get_assembler(tfeop::TransientLinearFEOpFromWeakForm2) = tfeop.assembler

#######
ss_op = TransientLinearFEOperator2((stiffness,mass),forcing,Ut_φ,V_φ;
constant_forms=BitVector((false,true)))
ss_ode_sol = ODEs.solve(ode_solver,ss_op,0.0,ode_solver.dt*steps,φh)
ss_data0, ss_state0 = Base.iterate(ss_ode_sol)

_t = ss_data0[1]
stiff_const_form = copy(ss_state0[2][5][1][4]) # <- cache this guy

#...

us = (get_free_dof_values(ss_data0[2]),get_free_dof_values(ss_data0[2]))
order = get_order(ss_op)
Ut = get_trial(ss_op)
# U = allocate_space(Ut)
# Uts = (Ut,)
# Us = (U,)
# for k in 1:order
# Uts = (Uts..., ∂t(Uts[k]))
# Us = (Us..., allocate_space(Uts[k+1]))
# end

_odeopcache = ss_state0[end][end][end]
Us = ()
for k in 0:get_order(ss_op)
Us = (Us..., evaluate!(_odeopcache.Us[k+1], _odeopcache.Uts[k+1], _t))
end

uh = ODEs._make_uh_from_us(ss_op, us, Us)
du = get_trial_fe_basis(Ut_φ)
V = get_test(ss_op)
v = get_fe_basis(V)

jacs = ODEs.get_jacs(ss_op)
jac = jacs[1]
dc = jac(_t, uh, du, v)
matdata = collect_cell_matrix(Ut, V, dc)
LinearAlgebra.fillstored!(stiff_const_form, zero(eltype(stiff_const_form)))
assemble_matrix_add!(stiff_const_form, get_assembler(ss_op), matdata)

## Update
new_const_forms = (stiff_const_form,ss_state0[end][end][end].const_forms[2])
ss_state0[end][end][end].const_forms = new_const_forms

ss_state0_new = update_reuse!(ss_state0,true)
ss_op.constant_forms[1] = true
ss_data1, ss_state1 = Base.iterate(ss_ode_sol,ss_state0_new)

data1[1] == ss_data1[1]
norm(get_free_dof_values(data1[2]) - get_free_dof_values(ss_data1[2]),Inf)

22 changes: 11 additions & 11 deletions scripts/Embedded/Examples/FCM_2d_compliance_L.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ using GridapEmbedded, GridapEmbedded.LevelSetCutters

using GridapTopOpt: StateParamIntegrandWithMeasure

path="./results/FCM_elastic_compliance_LShape_ALM_diffusion/"
path="./results/FCM_elastic_compliance_LShape_ALM_n100/"
rm(path,force=true,recursive=true)
mkpath(path)
n = 100
order = 1
γ = 0.1
max_steps = floor(Int,order*n/5)
γ = 0.2
max_steps = floor(Int,order*n/10)
vf = 0.4
α_coeff = 3max_steps*γ
α_coeff = max_steps*γ
iter_mod = 1

_model = CartesianDiscreteModel((0,1,0,1),(n,n))
Expand Down Expand Up @@ -49,7 +49,7 @@ U_reg = TrialFESpace(V_reg,0)
V_φ = TestFESpace(model,reffe_scalar)

## Levet-set function
φh = interpolate(x->-cos(8π*x[1])*cos(8π*x[2])-0.2,V_φ)
φh = interpolate(x->-cos(6π*x[1])*cos(8π*x[2])-0.2,V_φ)
Ωs = EmbeddedCollection(model,φh) do cutgeo,_
Ωin = DifferentiableTriangulation(Triangulation(cutgeo,PHYSICAL_IN),V_φ)
Ωout = DifferentiableTriangulation(Triangulation(cutgeo,PHYSICAL_OUT),V_φ)
Expand Down Expand Up @@ -84,8 +84,7 @@ g = VectorValue(0,-0.1)

const ϵ =+ μ)*1e-3
a(u,v,φ) = (ε(v) ε(u)))Ωs.dΩin +
# ∫(ϵ*(ε(v) ⊙ (σ ∘ ε(u))))Ωs.dΩout # Ersatz
* (v) (u))Ωs.dΩout # Pure diffusion
*(ε(v) ε(u))))Ωs.dΩout
l(v,φ) = (vg)dΓ_N

## Optimisation functionals
Expand All @@ -101,13 +100,14 @@ state_map = AffineFEStateMap(a,l,U,V,V_φ,U_reg,φh)
pcfs = PDEConstrainedFunctionals(J,[Vol],state_map;analytic_dC=(dVol,))

## Evolution Method
evo = CutFEMEvolve(V_φ,Ωs,dΩ,h;max_steps,γg=0.5)
reinit = StabilisedReinit(V_φ,Ωs,dΩ,h;stabilisation_method=ArtificialViscosity(3.0))
evo = CutFEMEvolve(V_φ,Ωs,dΩ,h;max_steps,γg=0.1)
reinit1 = StabilisedReinit(V_φ,Ωs,dΩ,h;stabilisation_method=ArtificialViscosity(3.0))
reinit2 = StabilisedReinit(V_φ,Ωs,dΩ,h;stabilisation_method=GridapTopOpt.InteriorPenalty(V_φ,γg=2.0))
reinit = GridapTopOpt.MultiStageStabilisedReinit([reinit1,reinit2])
ls_evo = UnfittedFEEvolution(evo,reinit)
reinit!(ls_evo,φh)

## Hilbertian extension-regularisation problems
α = α_coeff*(h_refine/order)^2
α = (α_coeff*h_refine/order)^2
a_hilb(p,q) =*(p)(q) + p*q)dΩ;
vel_ext = VelocityExtension(a_hilb,U_reg,V_reg)

Expand Down
13 changes: 7 additions & 6 deletions scripts/Embedded/Examples/FCM_2d_thermal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ rm(path,force=true,recursive=true)
mkpath(path)
n = 50
order = 1
γ = 0.1
max_steps = floor(Int,order*n/5)
γ = 0.2
max_steps = floor(Int,order*n/10)
vf = 0.4
α_coeff = 4max_steps*γ
α_coeff = max_steps*γ
iter_mod = 1

_model = CartesianDiscreteModel((0,1,0,1),(n,n))
Expand Down Expand Up @@ -79,10 +79,11 @@ state_map = AffineFEStateMap(a,l,U,V,V_φ,U_reg,φh)
pcfs = PDEConstrainedFunctionals(J,[Vol],state_map;analytic_dC=(dVol,))

## Evolution Method
evo = CutFEMEvolve(V_φ,Ωs,dΩ,h;max_steps)
reinit = StabilisedReinit(V_φ,Ωs,dΩ,h;stabilisation_method=ArtificialViscosity(3.0))
evo = CutFEMEvolve(V_φ,Ωs,dΩ,h;max_steps,γg=0.1)
reinit1 = StabilisedReinit(V_φ,Ωs,dΩ,h;stabilisation_method=ArtificialViscosity(3.0))
reinit2 = StabilisedReinit(V_φ,Ωs,dΩ,h;stabilisation_method=GridapTopOpt.InteriorPenalty(V_φ,γg=2.0))
reinit = GridapTopOpt.MultiStageStabilisedReinit([reinit1,reinit2])
ls_evo = UnfittedFEEvolution(evo,reinit)
reinit!(ls_evo,φh)

## Hilbertian extension-regularisation problems
α = α_coeff*(h_refine/order)^2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ using GridapTopOpt

#############

path = "./results/GMSH-TO-6-Brinkmann_stokes_P2-P1_Ersatz_elast_fsi_multistage_reinit/results/"
path = "./results/GMSH-TO-6-Brinkmann_stokes_P2-P1_Ersatz_elast_fsi/results/"
mkpath(path)

γ_evo = 0.1
max_steps = 20
vf = 0.025
α_coeff = 2
α_coeff = 1
iter_mod = 1
D = 2

Expand Down Expand Up @@ -148,16 +148,14 @@ l_coupled((v,q,s),φ) = ∫(0.0q)dΩ_act
J_pres((u,p,d),φ) = (p)dΓf_D - (p)dΓf_N
J_comp((u,p,d),φ) = (ε(d) ε(d)))Ω.dΩs
Vol((u,p,d),φ) = (vol_D)Ω.dΩs - (vf/vol_D)dΩ_act
dVol(q,(u,p,d),φ) = (-1/vol_D*q/(norm ((φ))))Ω.

## Setup solver and FE operators
state_map = AffineFEStateMap(a_coupled,l_coupled,X,Y,V_φ,U_reg,φh)
pcfs = PDEConstrainedFunctionals(J_comp,[Vol],state_map)
pcfs = PDEConstrainedFunctionals(J_comp,[Vol],state_map;analytic_dC=(dVol,))

## Evolution Method
# evo = CutFEMEvolve(V_φ,Ω,dΩ_act,hmin;max_steps,γg=0.075)
# reinit = StabilisedReinit(V_φ,Ω,dΩ_act,hmin;stabilisation_method=ArtificialViscosity(3.0))
# ls_evo = UnfittedFEEvolution(evo,reinit)
evo = CutFEMEvolve(V_φ,Ω,dΩ_act,hₕ;max_steps,γg=0.1)
evo = CutFEMEvolve(V_φ,Ω,dΩ_act,hₕ;max_steps,γg=0.01)
reinit1 = StabilisedReinit(V_φ,Ω,dΩ_act,hₕ;stabilisation_method=ArtificialViscosity(2.0))
reinit2 = StabilisedReinit(V_φ,Ω,dΩ_act,hₕ;stabilisation_method=GridapTopOpt.InteriorPenalty(V_φ,γg=1.0))
reinit = GridapTopOpt.MultiStageStabilisedReinit([reinit1,reinit2])
Expand All @@ -180,7 +178,7 @@ function has_oscillations(m,os_it)
all(@.(abs(history[:C,it]) < 0.05vf)) && GridapTopOpt.default_has_oscillations(m,os_it)
end
optimiser = AugmentedLagrangian(pcfs,ls_evo,vel_ext,φh;
γ=γ_evo,verbose=true,constraint_names=[:Vol],converged,has_oscillations,Λ_update_tol=0)
γ=γ_evo,verbose=true,constraint_names=[:Vol],converged,has_oscillations)
for (it,(uh,ph,dh),φh) in optimiser
GC.gc()
if iszero(it % iter_mod)
Expand Down
Loading

0 comments on commit 3dec36c

Please sign in to comment.