Evaluates the advective, diffusive, and pressure terms of the momentum equation.
Supports both Upwind (stable) and Central (high-accuracy) convection schemes. Advection is computed using a flux-form discretization.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_t), | intent(in) | :: | mesh | |||
| type(flow_mpi_t), | intent(in) | :: | flow | |||
| type(bc_set_t), | intent(in) | :: | bc | |||
| type(case_params_t), | intent(in) | :: | params | |||
| type(transport_properties_t), | intent(in) | :: | transport | |||
| real(kind=rk), | intent(in) | :: | u(:,:) | |||
| real(kind=rk), | intent(in) | :: | p(:) | |||
| real(kind=rk), | intent(out) | :: | local_rhs(:,:) |
subroutine compute_momentum_rhs(mesh, flow, bc, params, transport, u, p, local_rhs) type(mesh_t), intent(in) :: mesh type(flow_mpi_t), intent(in) :: flow type(bc_set_t), intent(in) :: bc type(case_params_t), intent(in) :: params type(transport_properties_t), intent(in) :: transport real(rk), intent(in) :: u(:,:) real(rk), intent(in) :: p(:) real(rk), intent(out) :: local_rhs(:,:) integer :: c, lf, f, nb real(rk) :: nvec(3), nhat(3) real(rk) :: uf(3), ub(3), advected(3) real(rk) :: un_area real(rk) :: conv(3), diff(3), gradp(3) real(rk) :: dist, diff_face, rho_cell logical :: use_central use_central = .false. select case (trim(params%momentum_convection_scheme)) case ('central', 'central_difference', 'central-difference') use_central = .true. case ('upwind', 'first_order_upwind', 'first-order-upwind') use_central = .false. case default call fatal_error('flow', 'unknown momentum_convection_scheme '//trim(params%momentum_convection_scheme)) end select local_rhs = zero do c = flow%first_cell, flow%last_cell conv = zero diff = zero ! Compute local pressure gradient at cell center call pressure_gradient_cell(mesh, bc, p, c, gradp) do lf = 1, mesh%ncell_faces(c) f = mesh%cell_faces(lf, c) nvec = outward_normal(mesh, f, c) nhat = nvec nb = face_effective_neighbor(mesh, bc, f, c) if (nb > 0) then uf = face_linear_vector(mesh, bc, f, c, nb, u(:, c), u(:, nb)) ub = u(:, nb) dist = face_normal_distance(mesh, bc, f, c, nb) else call boundary_velocity(mesh, bc, f, u(:, c), ub, & boundary_density=boundary_density_for_cell(params, transport, c)) uf = ub dist = face_normal_distance(mesh, bc, f, c, 0) end if un_area = dot_product(uf, nhat) * mesh%faces(f)%area ! Scheme selection for advection if (use_central) then advected = uf else if (un_area >= zero) then advected = u(:, c) else advected = ub end if end if conv = conv + un_area * advected ! Viscous diffusion Term if (nb > 0) then diff_face = half * (transport%nu(c) + transport%nu(nb)) else diff_face = transport%nu(c) end if diff = diff + diff_face * mesh%faces(f)%area * (ub - u(:, c)) / dist end do ! Assemble total RHS. Constant-density mode uses params%rho; guarded ! variable-density mode uses the active cell density. rho_cell = params%rho if (params%enable_variable_density) rho_cell = max(transport%rho(c), tiny_safe) local_rhs(:, c) = -conv / mesh%cells(c)%volume + & diff / mesh%cells(c)%volume + & params%body_force - gradp / rho_cell end do end subroutine compute_momentum_rhs