Skip to content
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

Adds a pertubation advection open boundary matching scheme #3977

Open
wants to merge 54 commits into
base: main
Choose a base branch
from

Conversation

jagoosw
Copy link
Collaborator

@jagoosw jagoosw commented Dec 6, 2024

This PR adds a PertubationAdvection open boundary condition which assumes that there is some mean flow (i.e. prescribed in a channel or from a coarser resolution model) which is homogeneous on the boundary but can vary in time.

On the boundary, we approximate (for an x-boundary) to:

$$\frac{\partial u}{\partial t} \approx -U\frac{\partial u\prime}{\partial x},$$

where $u=u\prime+U$
I have chosen to take an explicit/backwards Euler step:

$$\frac{u\prime(t^{n+1}) - u\prime(t^n)}{\Delta t} + \frac{U\prime(t^{n+1}) - U\prime(t^n)}{\Delta t} \approx -U\frac{u\prime(x_b, t^{n+1}) - u\prime(x_{b-1}, t^{n+1})}{\Delta x},$$

because then we don't have to store any other information (i.e. if we did a forward step we would need $u\prime(x_{b-1}, t^n)$ ). This results in:

$$u(t^{n+1}) = \frac{u^n+\tilde{U}u(x_{b-1}, t^{n+1})}{1+\tilde{U}},$$

where $\tilde{U}=\min\left(1, U\Delta t / \Delta x\right)$. I have also added restoring to $U$ (i.e. damping $u\prime\to0$) in some timescale $\tau$ which can be different for inflow and outflow to allow the scheme to work when there is inflow, which results in:

$$u(t^{n+1}) = \frac{u^n+\tilde{U}u(x_{b-1}, t^{n+1}) + U\tilde{\tau}}{1+\tilde{U}+\tilde{\tau}},$$

where $\tilde{\tau}=\Delta t / \tau$.

This has the limitation that if we want to extend to have wall tangent mean velocity ($\partial_t u \approx -(\vec{U}\cdot\nabla) u$) then we either have to solve the whole boundary at once since every point is going to depend on its boundary neighbours, or we need to take a forward Euler step in which case we need the first interior point at the previous time step.

I think we probably will need to address this for real nesting cases at some point.

u.mp4

For now, it seems to be working okay (left plot vorticity, right plot x-velocity):

(old plot) https://github.com/user-attachments/assets/21ae3eb2-5d3b-4c08-86fb-bb9c222e8e6a
and the drag coefficient is ~1.4 at Re = 100 and I'm running a case at Re=1000 now.

I have also checked the Strouhal number which matches exactly to the expected values (~0.17).

@jagoosw jagoosw added feature 🌟 Something new and shiny science 🌊 Sometimes addictive, sometimes allergenic numerics 🧮 So things don't blow up and boil the lobsters alive labels Dec 6, 2024
@jagoosw
Copy link
Collaborator Author

jagoosw commented Dec 6, 2024

@tomchor, do you think something like this:

"""
drag(modell; bounding_box = (-1, 3, -2, 2), ν = 1e-3)
Returns the drag within the `bounding_box` computed by:
```math
\\frac{\\partial \\vec{u}}{\\partial t} + (\\vec{u}\\cdot\\nabla)\\vec{u}=-\\nabla P + \\nabla\\cdot\\vec{\\tau} + \\vec{F},\\newline
\\vec{F}_T=\\int_\\Omega\\vec{F}dV = \\int_\\Omega\\left(\\frac{\\partial \\vec{u}}{\\partial t} + (\\vec{u}\\cdot\\nabla)\\vec{u}+\\nabla P - \\nabla\\cdot\\vec{\\tau}\\right)dV,\\newline
\\vec{F}_T=\\int_\\Omega\\left(\\frac{\\partial \\vec{u}}{\\partial t}\\right)dV + \\oint_{\\partial\\Omega}\\left(\\vec{u}(\\vec{u}\\cdot\\hat{n}) + P\\hat{n} - \\vec{\\tau}\\cdot\\hat{n}\\right)dS,\\newline
\\F_u=\\int_\\Omega\\left(\\frac{\\partial u}{\\partial t}\\right)dV + \\oint_{\\partial\\Omega}\\left(u(\\vec{u}\\cdot\\hat{n}) - \\tau_{xx}\\right)dS + \\int_{\\partial\\Omega}P\\hat{x}\\cdot d\\vec{S},\\newline
F_u=\\int_\\Omega\\left(\\frac{\\partial u}{\\partial t}\\right)dV - \\int_{\\partial\\Omega_1} \\left(u^2 - 2\\nu\\frac{\\partial u}{\\partial x} + P\\right)dS + \\int_{\\partial\\Omega_2}\\left(u^2 - 2\\nu\\frac{\\partial u}{\\partial x}+P\\right)dS - \\int_{\\partial\\Omega_2} uvdS + \\int_{\\partial\\Omega_4} uvdS,
```
where the bounding box is ``\\Omega`` which is formed from the boundaries ``\\partial\\Omega_{1}``, ``\\partial\\Omega_{2}``, ``\\partial\\Omega_{3}``, and ``\\partial\\Omega_{4}``
which have outward directed normals ``-\\hat{x}``, ``\\hat{x}``, ``-\\hat{y}``, and ``\\hat{y}``
"""
function drag(model;
bounding_box = (-1, 3, -2, 2),
ν = 1e-3)
u, v, _ = model.velocities
uᶜ = Field(@at (Center, Center, Center) u)
vᶜ = Field(@at (Center, Center, Center) v)
xc, yc, _ = nodes(uᶜ)
i₁ = findfirst(xc .> bounding_box[1])
i₂ = findlast(xc .< bounding_box[2])
j₁ = findfirst(yc .> bounding_box[3])
j₂ = findlast(yc .< bounding_box[4])
uₗ² = Field(uᶜ^2, indices = (i₁, j₁:j₂, 1))
uᵣ² = Field(uᶜ^2, indices = (i₂, j₁:j₂, 1))
uvₗ = Field(uᶜ*vᶜ, indices = (i₁:i₂, j₁, 1))
uvᵣ = Field(uᶜ*vᶜ, indices = (i₁:i₂, j₂, 1))
∂₁uₗ = Field(∂x(uᶜ), indices = (i₁, j₁:j₂, 1))
∂₁uᵣ = Field(∂x(uᶜ), indices = (i₂, j₁:j₂, 1))
∂ₜuᶜ = Field(@at (Center, Center, Center) model.timestepper.Gⁿ.u)
∂ₜu = Field(∂ₜuᶜ, indices = (i₁:i₂, j₁:j₂, 1))
p = model.pressures.pNHS
∫∂ₓp = Field(∂x(p), indices = (i₁:i₂, j₁:j₂, 1))
a_local = Field(Integral(∂ₜu))
a_flux = Field(Integral(uᵣ²)) - Field(Integral(uₗ²)) + Field(Integral(uvᵣ)) - Field(Integral(uvₗ))
a_viscous_stress = 2ν * (Field(Integral(∂₁uᵣ)) - Field(Integral(∂₁uₗ)))
a_pressure = Field(Integral(∫∂ₓp))
return a_local + a_flux + a_pressure - a_viscous_stress
end

could belong in Oceanostics?

@jagoosw
Copy link
Collaborator Author

jagoosw commented Dec 6, 2024

I have also run the same case with different domain lengths (6m, 12m - shown, 18m and 30m) and they all produce very similar Cd and St

@tomchor
Copy link
Collaborator

tomchor commented Dec 6, 2024

@tomchor, do you think something like this:

"""
drag(modell; bounding_box = (-1, 3, -2, 2), ν = 1e-3)
Returns the drag within the `bounding_box` computed by:
```math
\\frac{\\partial \\vec{u}}{\\partial t} + (\\vec{u}\\cdot\\nabla)\\vec{u}=-\\nabla P + \\nabla\\cdot\\vec{\\tau} + \\vec{F},\\newline
\\vec{F}_T=\\int_\\Omega\\vec{F}dV = \\int_\\Omega\\left(\\frac{\\partial \\vec{u}}{\\partial t} + (\\vec{u}\\cdot\\nabla)\\vec{u}+\\nabla P - \\nabla\\cdot\\vec{\\tau}\\right)dV,\\newline
\\vec{F}_T=\\int_\\Omega\\left(\\frac{\\partial \\vec{u}}{\\partial t}\\right)dV + \\oint_{\\partial\\Omega}\\left(\\vec{u}(\\vec{u}\\cdot\\hat{n}) + P\\hat{n} - \\vec{\\tau}\\cdot\\hat{n}\\right)dS,\\newline
\\F_u=\\int_\\Omega\\left(\\frac{\\partial u}{\\partial t}\\right)dV + \\oint_{\\partial\\Omega}\\left(u(\\vec{u}\\cdot\\hat{n}) - \\tau_{xx}\\right)dS + \\int_{\\partial\\Omega}P\\hat{x}\\cdot d\\vec{S},\\newline
F_u=\\int_\\Omega\\left(\\frac{\\partial u}{\\partial t}\\right)dV - \\int_{\\partial\\Omega_1} \\left(u^2 - 2\\nu\\frac{\\partial u}{\\partial x} + P\\right)dS + \\int_{\\partial\\Omega_2}\\left(u^2 - 2\\nu\\frac{\\partial u}{\\partial x}+P\\right)dS - \\int_{\\partial\\Omega_2} uvdS + \\int_{\\partial\\Omega_4} uvdS,
```
where the bounding box is ``\\Omega`` which is formed from the boundaries ``\\partial\\Omega_{1}``, ``\\partial\\Omega_{2}``, ``\\partial\\Omega_{3}``, and ``\\partial\\Omega_{4}``
which have outward directed normals ``-\\hat{x}``, ``\\hat{x}``, ``-\\hat{y}``, and ``\\hat{y}``
"""
function drag(model;
bounding_box = (-1, 3, -2, 2),
ν = 1e-3)
u, v, _ = model.velocities
uᶜ = Field(@at (Center, Center, Center) u)
vᶜ = Field(@at (Center, Center, Center) v)
xc, yc, _ = nodes(uᶜ)
i₁ = findfirst(xc .> bounding_box[1])
i₂ = findlast(xc .< bounding_box[2])
j₁ = findfirst(yc .> bounding_box[3])
j₂ = findlast(yc .< bounding_box[4])
uₗ² = Field(uᶜ^2, indices = (i₁, j₁:j₂, 1))
uᵣ² = Field(uᶜ^2, indices = (i₂, j₁:j₂, 1))
uvₗ = Field(uᶜ*vᶜ, indices = (i₁:i₂, j₁, 1))
uvᵣ = Field(uᶜ*vᶜ, indices = (i₁:i₂, j₂, 1))
∂₁uₗ = Field(∂x(uᶜ), indices = (i₁, j₁:j₂, 1))
∂₁uᵣ = Field(∂x(uᶜ), indices = (i₂, j₁:j₂, 1))
∂ₜuᶜ = Field(@at (Center, Center, Center) model.timestepper.Gⁿ.u)
∂ₜu = Field(∂ₜuᶜ, indices = (i₁:i₂, j₁:j₂, 1))
p = model.pressures.pNHS
∫∂ₓp = Field(∂x(p), indices = (i₁:i₂, j₁:j₂, 1))
a_local = Field(Integral(∂ₜu))
a_flux = Field(Integral(uᵣ²)) - Field(Integral(uₗ²)) + Field(Integral(uvᵣ)) - Field(Integral(uvₗ))
a_viscous_stress = 2ν * (Field(Integral(∂₁uᵣ)) - Field(Integral(∂₁uₗ)))
a_pressure = Field(Integral(∫∂ₓp))
return a_local + a_flux + a_pressure - a_viscous_stress
end

could belong in Oceanostics?

Sure! Why not? :)

Comment on lines 38 to 64
@inline function _fill_east_halo!(j, k, grid, u, bc::PAOBC, loc::Tuple{Face, Any, Any}, clock, model_fields)
i = grid.Nx + 1

Δt = clock.last_stage_Δt

Δt = ifelse(isinf(Δt), 0, Δt)

Δx = xspacing(i, j, k, grid, loc...)

ūⁿ⁺¹ = getbc(bc, j, k, grid, clock, model_fields)

uᵢⁿ = @inbounds u[i, j, k]
uᵢ₋₁ⁿ⁺¹ = @inbounds u[i - 1, j, k]

U = max(0, min(1, Δt / Δx * ūⁿ⁺¹))

τ = ifelse(ūⁿ⁺¹ >= 0,
bc.classification.matching_scheme.outflow_timescale,
bc.classification.matching_scheme.inflow_timescale)


τ̃ = Δt / τ

uᵢⁿ⁺¹ = (uᵢⁿ + U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ + U)

@inbounds u[i, j, k] = uᵢⁿ⁺¹#ifelse(active_cell(i, j, k, grid), uᵢⁿ⁺¹, zero(grid))
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could implement everything using getindex() so that we implement it once (or at max twice; one for left and other for right BC) and can use it in three dimensions.

For example this

    uᵢⁿ     = @inbounds u[i, j, k]
    uᵢ₋₁ⁿ⁺¹ = @inbounds u[i - 1, j, k]

would become

    uᵢⁿ     = @inbounds getindex(u, boundary_indices...)
    uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, one_off_boundary_indices...)

This would avoid errors when transcribing to other dimensions (I remember catching a couple for the flat extrapolation matching scheme).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I was trying to think of a clean way to do this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempted this now (but I've still not written out the other directions in case we want to change things first)

@jagoosw jagoosw force-pushed the jsw/pertubation-advection-obc branch from 0e645c5 to 32cd354 Compare December 6, 2024 20:11
@jagoosw jagoosw force-pushed the jsw/pertubation-advection-obc branch from afecfb3 to e66f3d1 Compare December 6, 2024 20:43
@glwagner
Copy link
Member

glwagner commented Dec 6, 2024

There's a typo in your top equation right? I think it should be $\partial_t (u + U) = U \partial_x u$.

@glwagner
Copy link
Member

glwagner commented Dec 6, 2024

A problem I think this scheme might have is that as the flow changes direction the assumption that the perturbation is small falls apart, which is maybe why it's been a bit unstable so far in an oscillating case.

What do you mean? What is the consequence of this approximation?

@jagoosw
Copy link
Collaborator Author

jagoosw commented Dec 6, 2024

What do you mean? What is the consequence of this approximation?

I was thinking about this more and really to remain valid then in :

$$\partial_t (u\prime+U)\approx u\prime\partial_xu\prime + U\partial_xu\prime + (U - u\prime)/\tau$$

as $U\to0$ then we need $u\prime\partial_xu\prime\ll u\prime/\tau$ to still be able to throw away the first term, so I think its actually okay as long as you have the relaxation.

I found a typo in the west boundary which might be why the oscillating case wasn't working, rerunning now

@jagoosw
Copy link
Collaborator Author

jagoosw commented Dec 6, 2024

There's a typo in your top equation right? I think it should be ∂ t ( u + U ) = U ∂ x u .
Yeah thanks for catching!

@glwagner
Copy link
Member

glwagner commented Dec 6, 2024

What do you mean? What is the consequence of this approximation?

I was thinking about this more and really to remain valid then in :

as U → 0 then we need u ′ ∂ x u ′ ≪ u ′ / τ to still be able to throw away the first term, so I think its actually okay as long as you have the relaxation.

I found a typo in the west boundary which might be why the oscillating case wasn't working, rerunning now

Okay, I agree with you. You can also analyze the update formula / backward Euler step in the limit U -> 0. It doesn't look like it needs to be regularized in any way in that case though, it looks ok.

@tomchor
Copy link
Collaborator

tomchor commented Dec 9, 2024

Is there a reference for this method? If there is, please include it on the methods docstring. If not, it'd be good to include a brief explanation like the one at the top comment in the dosctring. I don't think this radiation method is very well known.

@jagoosw
Copy link
Collaborator Author

jagoosw commented Jan 18, 2025

Also feel free to mark this as ready for review once you add tests.

Should be ready now

@jagoosw
Copy link
Collaborator Author

jagoosw commented Jan 20, 2025

Boundary condition tests passed just some GPU tests failed because they lost Sverdrup

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jagoosw you still need to remove this file from here, right?

Is this only used for the perturbation OBC? If so, it can go in the same directory.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We never resolved this, the problem is that AbstractOperations are defined after BoundaryConditions so this can't go in the boundary module

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I see. I don't have a good answer here, but I don't think it can be in /src. @glwagner @simone-silvestri can you advise here?

Also, is there a simple way to define these functions without AbstractOperations?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be possible to write it without but it would not be trivial to do it for general grids and would end up reinventing the wheel to get the flux.

Perhaps we could move it to Utils?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with that.

src/boundary_mean.jl Outdated Show resolved Hide resolved

u = normal_velocity(Val(orientation), model)

CUDA.@allowscalar u.data .= 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're trying to avoid introducing new @alloscalar instances to testing. @glwagner can you confirm?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the problem was that tests currently have a global @allowscalar, but some tests need them or will be more complicated to write?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can write most of them simply without allowscalar, but I'm not an expert on this. For example you may be able to write something like interior(u) .= 1 without it (I haven't tested it though), and it's a pretty simple change.

I say try to avoid it with simple statements like the one I just mentioned. If we can't do it simply and @glwagner doesn't manifest any opinions on it, we move forward. How does that sound?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sorted this now, it wasn't as straight forward as just using interior because I needed to set a peripheral node, but I just used view instead

Copy link
Collaborator

@tomchor tomchor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a few comments, but it looks like there are old unresolved comments and some files here and there which do not seem to be ready for prime yet. let me know if anything needs clarification.

@jagoosw
Copy link
Collaborator Author

jagoosw commented Jan 21, 2025

@tomchor I think I've addressed your comments now


ax = Axis(fig[1, 1], aspect = DataAspect())
simulation.output_writers[:drag] = JLD2OutputWriter(model, (; drag_force),
schedule = IterationInterval(Int(0.1/Δt)),#TimeInterval(0.1),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
schedule = IterationInterval(Int(0.1/Δt)),#TimeInterval(0.1),
schedule = IterationInterval(Int(0.1/Δt)),

outputs = (; u, v, p, ζ)

simulation.output_writers[:jld2] = JLD2OutputWriter(model, outputs,
schedule = IterationInterval(Int(2/Δt)),#TimeInterval(0.1),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
schedule = IterationInterval(Int(2/Δt)),#TimeInterval(0.1),
schedule = IterationInterval(Int(2/Δt)),


progress(sim) = @info "$(time(sim)) with Δt = $(prettytime(sim.Δt)) in $(prettytime(sim.run_wall_time))"
simulation = Simulation(model; Δt, stop_time)
#conjure_time_step_wizard!(simulation, cfl=1.0, IterationInterval(3); max_Δt)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#conjure_time_step_wizard!(simulation, cfl=1.0, IterationInterval(3); max_Δt)

Comment on lines +12 to +13
# there is some problem using ConjugateGradientPoissonSolver with TimeInterval because the timestep can go really small
# so while I identify the issue I'm using IterationInterval and a fixed timestep
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried setting minimum_relative_step? (see #3606)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to fix the issue! I hadn't tried this since early november/december so I hadn't seen you'd made this fix so this is great, thank you

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update the validation script

@jagoosw jagoosw changed the title [WIP] Adds a pertubation advection open boundary matching scheme Adds a pertubation advection open boundary matching scheme Jan 22, 2025
F⃗ₜ = ∫ᵥF⃗dV = ∫ᵥ(∂ₜ u⃗ + (u⃗⋅∇)u⃗ + ∇P − ∇⋅τ⃗)dV
F⃗ₜ = ∫ᵥ(∂ₜu⃗)dV + ∮ₛ(u⃗(u⃗⋅n̂) + Pn̂ − τ⃗⋅n̂)dS
Fᵤ = ∫ᵥ ∂ₜu dV + ∮ₛ(u(u⃗⋅n̂) − τₓₓ)dS + ∮ₛPx̂⋅dS⃗
Fᵤ = ∫ᵥ ∂ₜ u dV − ∫ₛ₁(u² − 2ν∂ₓ u + P)dS + ∫ₛ₂(u² − 2ν∂ₓ u+P)dS − ∫ₛ₃uvdS + ∫ₛ₄ uvdS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI what this looks like on my screen / browser

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looks similarly messed up on my browser, but the actual document looks fine on my laptop:

image

Probably it's best to prioritize rendering on github, since a lot of people use it. I guess the easiest way to do that is to copy-paste stuff on a github text box and see what displays correctly and what doesn't. I just tested it out right now and it seems to work. The \oint character seems to not work for example.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Arguably everyone uses github btw. Eg we are using github now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably it's best to prioritize rendering on github, since a lot of people use it. I guess the easiest way to do that is to copy-paste stuff on a github text box and see what displays correctly and what doesn't. I just tested it out right now and it seems to work. The \oint character seems to not work for example.

I tried this but then when I copy it over it renders wrong:

$$\frac{\partial \vec{u}}{\partial t} + (\vec{u}\cdot\nabla)\vec{u}=-\nabla P + \nabla\cdot\vec{\tau} + \vec{F},$$ $$\vec{F}_T=\int_\Omega\vec{F}dV = \int_\Omega\left(\frac{\partial \vec{u}}{\partial t} + (\vec{u}\cdot\nabla)\vec{u}+\nabla P - \nabla\cdot\vec{\tau}\right)dV,\newline$$ $$\vec{F}_T=\int_\Omega\left(\frac{\partial \vec{u}}{\partial t}\right)dV + \oint_{\partial\Omega}\left(\vec{u}(\vec{u}\cdot\hat{n}) + P\hat{n} - \vec{\tau}\cdot\hat{n}\right)dS,$$ $$F_u=\int_\Omega\left(\frac{\partial u}{\partial t}\right)dV + \oint_{\partial\Omega}\left(u(\vec{u}\cdot\hat{n}) - \tau_{xx}\right)dS + \int_{\partial\Omega}P\hat{x}\cdot d\vec{S},$$ $$F_u=\int_\Omega\left(\frac{\partial u}{\partial t}\right)dV - \int_{\partial\Omega_1} \left(u^2 - 2\nu\frac{\partial u}{\partial x} + P\right)dS + \int_{\partial\Omega_2}\left(u^2 - 2\nu\frac{\partial u}{\partial x}+P\right)dS - \int_{\partial\Omega_2} uvdS + \int_{\partial\Omega_4} uvdS$$

where the bounding box is $\Omega$ which is formed from the boundaries $\partial\Omega_1$, $\partial\Omega_2$, $\partial\Omega_3$, $\partial\Omega_4$ which have outward directed normals $-\hat{x}$, $\hat{x}$, $-\hat{y}$ and $\hat{y}$

Rendered in julia file:
∂ u → ∂ t + ( u → ⋅ ∇ ) u → = − ∇ P + ∇ ⋅ τ → + F → ,
F → T = ∫ Ω F → d V = ∫ Ω ( ∂ u → ∂ t + ( u → ⋅ ∇ ) u → + ∇ P − ∇ ⋅ τ → ) d V ,
F → T = ∫ Ω ( ∂ u → ∂ t ) d V + ∮ ∂ Ω ( u → ( u → ⋅ n ^ ) + P n ^ − τ → ⋅ n ^ ) d S ,
F u = ∫ Ω ( ∂ u ∂ t ) d V + ∮ ∂ Ω ( u ( u → ⋅ n ^ ) − τ x x ) d S + ∫ ∂ Ω P x ^ ⋅ d S → ,
F u = ∫ Ω ( ∂ u ∂ t ) d V − ∫ ∂ Ω 1 ( u 2 − 2 ν ∂ u ∂ x + P ) d S + ∫ ∂ Ω 2 ( u 2 − 2 ν ∂ u ∂ x + P ) d S − ∫ ∂ Ω 2 u v d S + ∫ ∂ Ω 4 u v d S

where the bounding box is Ω which is formed from the boundaries ∂ Ω 1 , ∂ Ω 2 , ∂ Ω 3 , ∂ Ω 4 which have outward directed normals − x ^ , x ^ , − y ^ and y

I'll play around and try and find an intermediary

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this look:

Suggested change
Fᵤ = ∫ᵥ ∂ₜ u dV ∫ₛ₁(u² 2ν∂ₓ u + P)dS + ∫ₛ₂(u² 2ν∂ₓ u+P)dS ∫ₛ₃uvdS + ∫ₛ₄ uvdS
∂ₜU + (U∇)U = ∇P +τ + F⃗
F = ∫ᵥFdV = ∫ᵥ(∂U/∂t + (U∇)U + ∇P τ)dV
F = ∫ᵥ(∂U/∂t)dV + ∫ₛ(U(Un̂) + Pn̂ τn̂)dS
Fᵤ = ∫ᵥ ∂U/∂t dV + ∫ₛ(u(Un̂) τₓₓ)dS + ∮ₛPx̂dS⃗
Fᵤ = ∫ᵥ ∂U/∂t dV ∫ₛ₁(u² 2ν∂ₓ u + P)dS + ∫ₛ₂(u² 2ν∂ₓ u+P)dS ∫ₛ₃uvdS + ∫ₛ₄ uvdS

I think I got all of the unrendered characters gone (vectors and oint?).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange that GH renders the original fine for me, maybe because I have a systemwide juliamono installation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure. But your update renders fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature 🌟 Something new and shiny numerics 🧮 So things don't blow up and boil the lobsters alive science 🌊 Sometimes addictive, sometimes allergenic
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants