117
118
logical :: move_mesh
118
119
! Include porosity?
119
120
logical :: include_porosity
121
! Are we running a multiphase flow simulation?
122
logical :: multiphase
123
subroutine solve_field_equation_cg(field_name, state, dt, velocity_name, iterations_taken)
126
subroutine solve_field_equation_cg(field_name, state, istate, dt, velocity_name, iterations_taken)
124
127
!!< Construct and solve the advection-diffusion equation for the given
125
128
!!< field using a continuous Galerkin discretisation. Based on
126
129
!!< Advection_Diffusion_DG and Momentum_CG.
128
131
character(len = *), intent(in) :: field_name
129
type(state_type), intent(inout) :: state
132
type(state_type), dimension(:), intent(inout) :: state
133
integer, intent(in) :: istate
130
134
real, intent(in) :: dt
131
135
character(len = *), optional, intent(in) :: velocity_name
132
136
integer, intent(out), optional :: iterations_taken
138
142
ewrite(1, *) "In solve_field_equation_cg"
140
144
ewrite(2, *) "Solving advection-diffusion equation for field " // &
141
& trim(field_name) // " in state " // trim(state%name)
145
& trim(field_name) // " in state " // trim(state(istate)%name)
143
call initialise_advection_diffusion_cg(field_name, t, delta_t, matrix, rhs, state)
147
call initialise_advection_diffusion_cg(field_name, t, delta_t, matrix, rhs, state(istate))
145
149
call profiler_tic(t, "assembly")
146
call assemble_advection_diffusion_cg(t, matrix, rhs, state, dt, velocity_name = velocity_name)
150
call assemble_advection_diffusion_cg(t, matrix, rhs, state(istate), dt, velocity_name = velocity_name)
152
! Note: the assembly of the heat transfer term is done here to avoid
153
! passing in the whole state array to assemble_advection_diffusion_cg.
154
if(have_option("/multiphase_interaction/heat_transfer")) then
155
call add_heat_transfer(state, istate, t, matrix, rhs)
147
157
call profiler_toc(t, "assembly")
149
159
call profiler_tic(t, "solve_total")
150
call solve_advection_diffusion_cg(t, delta_t, matrix, rhs, state, &
160
call solve_advection_diffusion_cg(t, delta_t, matrix, rhs, state(istate), &
151
161
iterations_taken = iterations_taken)
152
162
call profiler_toc(t, "solve_total")
462
478
stabilisation_scheme = STABILISATION_NONE
481
! PhaseVolumeFraction for multiphase flow simulations
482
if(option_count("/material_phase/vector_field::Velocity/prognostic") > 1) then
484
vfrac => extract_scalar_field(state, "PhaseVolumeFraction")
485
call allocate(nvfrac, vfrac%mesh, "NonlinearPhaseVolumeFraction")
487
call get_nonlinear_volume_fraction(state, nvfrac)
489
ewrite_minmax(nvfrac)
492
call allocate(nvfrac, t%mesh, "DummyNonlinearPhaseVolumeFraction", field_type=FIELD_TYPE_CONSTANT)
493
call set(nvfrac, 1.0)
465
496
call allocate(dummydensity, t%mesh, "DummyDensity", field_type=FIELD_TYPE_CONSTANT)
466
497
call set(dummydensity, 1.0)
467
498
! find out equation type and hence if density is needed or not
479
510
if(move_mesh) then
480
511
FLExit("Haven't implemented a moving mesh energy equation yet.")
514
! Get old and current densities
482
515
call get_option(trim(t%option_path)//'/prognostic/equation[0]/density[0]/name', &
484
517
density=>extract_scalar_field(state, trim(density_name))
485
518
ewrite_minmax(density)
487
519
olddensity=>extract_scalar_field(state, "Old"//trim(density_name))
488
520
ewrite_minmax(olddensity)
490
call get_option(trim(density%option_path)//"/prognostic/temporal_discretisation/theta", &
522
if(.not.multiphase .or. have_option('/material_phase::'//trim(state%name)//&
523
&'/equation_of_state/compressible')) then
524
call get_option(trim(density%option_path)//"/prognostic/temporal_discretisation/theta", &
527
! Since the particle phase is always incompressible then its Density
528
! will not be prognostic. Just use a fixed theta value of 1.0.
493
532
pressure=>extract_scalar_field(state, "Pressure")
494
533
ewrite_minmax(pressure)
496
536
FLExit("Unknown field equation type for cg advection diffusion.")
531
571
positions, old_positions, new_positions, &
532
572
velocity, grid_velocity, &
533
573
source, absorption, diffusivity, &
534
density, olddensity, pressure, porosity_theta, &
574
density, olddensity, pressure, porosity_theta, nvfrac, &
535
575
supg_element(thread_num+1))
536
576
end do element_loop
645
687
positions, old_positions, new_positions, &
646
688
velocity, grid_velocity, &
647
689
source, absorption, diffusivity, &
648
density, olddensity, pressure, porosity_theta, supg_shape)
690
density, olddensity, pressure, porosity_theta, nvfrac, supg_shape)
649
691
integer, intent(in) :: ele
650
692
type(scalar_field), intent(in) :: t
651
693
type(csr_matrix), intent(inout) :: matrix
669
712
real, dimension(ele_loc(density, ele), ele_ngi(density, ele), mesh_dim(density)) :: drho_t
670
713
real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t
671
714
real, dimension(ele_loc(positions, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: dug_t
715
! Derivative of shape function for nvfrac field
716
real, dimension(ele_loc(nvfrac, ele), ele_ngi(nvfrac, ele), mesh_dim(nvfrac)) :: dnvfrac_t
672
718
real, dimension(mesh_dim(t), mesh_dim(t), ele_ngi(t, ele)) :: j_mat
673
719
type(element_type) :: test_function
674
720
type(element_type), pointer :: t_shape
763
819
! Step 3: Assemble contributions
766
if(have_mass) call add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)
822
if(have_mass) call add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, nvfrac, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)
769
825
if(have_advection) call add_advection_element_cg(ele, test_function, t, &
770
826
velocity, grid_velocity, diffusivity, &
771
density, olddensity, &
772
dt_t, du_t, dug_t, drho_t, detwei, j_mat, matrix_addto, rhs_addto)
827
density, olddensity, nvfrac, &
828
dt_t, du_t, dug_t, drho_t, dnvfrac_t, detwei, j_mat, matrix_addto, rhs_addto)
775
831
if(have_absorption) call add_absorption_element_cg(ele, test_function, t, absorption, detwei, matrix_addto, rhs_addto)
796
852
end subroutine assemble_advection_diffusion_element_cg
798
subroutine add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)
854
subroutine add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, nvfrac, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)
799
855
integer, intent(in) :: ele
800
856
type(element_type), intent(in) :: test_function
801
857
type(scalar_field), intent(in) :: t
802
858
type(scalar_field), intent(in) :: density, olddensity
803
859
type(scalar_field), intent(in) :: porosity_theta
860
type(scalar_field), intent(in) :: nvfrac
804
861
real, dimension(ele_ngi(t, ele)), intent(in) :: detwei, detwei_old, detwei_new
805
862
real, dimension(ele_loc(t, ele), ele_loc(t, ele)), intent(inout) :: matrix_addto
806
863
real, dimension(ele_loc(t, ele)), intent(inout) :: rhs_addto
878
937
subroutine add_advection_element_cg(ele, test_function, t, &
879
938
velocity, grid_velocity, diffusivity, &
880
density, olddensity, &
881
dt_t, du_t, dug_t, drho_t, detwei, j_mat, matrix_addto, rhs_addto)
939
density, olddensity, nvfrac, &
940
dt_t, du_t, dug_t, drho_t, dnvfrac_t, detwei, j_mat, matrix_addto, rhs_addto)
882
941
integer, intent(in) :: ele
883
942
type(element_type), intent(in) :: test_function
884
943
type(scalar_field), intent(in) :: t
886
945
type(vector_field), pointer :: grid_velocity
887
946
type(tensor_field), intent(in) :: diffusivity
888
947
type(scalar_field), intent(in) :: density, olddensity
948
type(scalar_field), intent(in) :: nvfrac
889
949
real, dimension(ele_loc(t, ele), ele_ngi(t, ele), mesh_dim(t)), intent(in) :: dt_t
890
950
real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t
891
951
real, dimension(:, :, :) :: dug_t
892
952
real, dimension(ele_loc(density, ele), ele_ngi(density, ele), mesh_dim(density)), intent(in) :: drho_t
953
real, dimension(:, :, :), intent(in) :: dnvfrac_t
893
954
real, dimension(ele_ngi(t, ele)), intent(in) :: detwei
894
955
real, dimension(mesh_dim(t), mesh_dim(t), ele_ngi(t, ele)), intent(in) :: j_mat
895
956
real, dimension(ele_loc(t, ele), ele_loc(t, ele)), intent(inout) :: matrix_addto
904
965
real, dimension(velocity%dim, ele_ngi(density, ele)) :: densitygrad_at_quad
905
966
real, dimension(ele_ngi(density, ele)) :: udotgradrho_at_quad
968
real, dimension(ele_ngi(t, ele)) :: nvfrac_at_quad
969
real, dimension(velocity%dim, ele_ngi(t, ele)) :: nvfracgrad_at_quad
970
real, dimension(ele_ngi(t, ele)) :: udotgradnvfrac_at_quad
907
972
assert(have_advection)
909
974
t_shape => ele_shape(t, ele)
932
1001
select case(equation_type)
933
1002
case(FIELD_EQUATION_INTERNALENERGY)
934
advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei*density_at_quad)
1004
advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei*density_at_quad*nvfrac_at_quad)
1006
advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei*density_at_quad)
935
1009
if(abs(1.0 - beta) > epsilon(0.0)) then
936
1010
velocity_div_at_quad = ele_div_at_quad(velocity, ele, du_t)
937
advection_mat = advection_mat &
938
- (1.0-beta) * shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad &
939
+udotgradrho_at_quad)* detwei)
1014
nvfracgrad_at_quad = ele_grad_at_quad(nvfrac, ele, dnvfrac_t)
1015
udotgradnvfrac_at_quad = sum(nvfracgrad_at_quad*velocity_at_quad, 1)
1017
advection_mat = advection_mat - (1.0-beta) * ( shape_shape(test_function, t_shape, detwei*velocity_div_at_quad*density_at_quad*nvfrac_at_quad) &
1018
+ shape_shape(test_function, t_shape, detwei*nvfrac_at_quad*udotgradrho_at_quad) &
1019
+ shape_shape(test_function, t_shape, detwei*density_at_quad*udotgradnvfrac_at_quad) )
1021
advection_mat = advection_mat - (1.0-beta) * shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad + udotgradrho_at_quad)*detwei)
942
1025
advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei)
954
1037
select case(equation_type)
955
1038
case(FIELD_EQUATION_INTERNALENERGY)
956
advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei*density_at_quad)
1041
! vfrac*rho*nu*grad(internalenergy)
1042
advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei*density_at_quad*nvfrac_at_quad)
1044
advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei*density_at_quad)
957
1047
if(abs(beta) > epsilon(0.0)) then
958
1048
velocity_div_at_quad = ele_div_at_quad(velocity, ele, du_t)
959
advection_mat = advection_mat &
960
+ beta*shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad &
961
+udotgradrho_at_quad)*detwei)
1051
! advection_mat + internalenergy*div(vfrac*rho*nu)
1052
! Split up div(vfrac*rho*nu) = vfrac*rho*div(nu) + nu*grad(vfrac*rho) = vfrac*rho*div(nu) + nu*(vfrac*grad(rho) + rho*grad(nvfrac))
1054
nvfracgrad_at_quad = ele_grad_at_quad(nvfrac, ele, dnvfrac_t)
1055
udotgradnvfrac_at_quad = sum(nvfracgrad_at_quad*velocity_at_quad, 1)
1057
advection_mat = advection_mat + beta * ( shape_shape(test_function, t_shape, detwei*velocity_div_at_quad*density_at_quad*nvfrac_at_quad) &
1058
+ shape_shape(test_function, t_shape, detwei*nvfrac_at_quad*udotgradrho_at_quad) &
1059
+ shape_shape(test_function, t_shape, detwei*density_at_quad*udotgradnvfrac_at_quad) )
1061
advection_mat = advection_mat + beta*shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad &
1062
+udotgradrho_at_quad)*detwei)
964
1066
advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei)
1061
1163
end subroutine add_diffusivity_element_cg
1063
subroutine add_pressurediv_element_cg(ele, test_function, t, velocity, pressure, du_t, detwei, rhs_addto)
1165
subroutine add_pressurediv_element_cg(ele, test_function, t, velocity, pressure, nvfrac, du_t, dnvfrac_t, detwei, rhs_addto)
1065
1167
integer, intent(in) :: ele
1066
1168
type(element_type), intent(in) :: test_function
1067
1169
type(scalar_field), intent(in) :: t
1068
1170
type(vector_field), intent(in) :: velocity
1069
1171
type(scalar_field), intent(in) :: pressure
1070
real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t
1172
type(scalar_field), intent(in) :: nvfrac
1173
real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)), intent(in) :: du_t
1174
real, dimension(:, :, :), intent(in) :: dnvfrac_t
1071
1175
real, dimension(ele_ngi(t, ele)), intent(in) :: detwei
1072
1176
real, dimension(ele_loc(t, ele)), intent(inout) :: rhs_addto
1178
real, dimension(velocity%dim, ele_ngi(t, ele)) :: nvfracgrad_at_quad
1179
real, dimension(ele_ngi(t, ele)) :: udotgradnvfrac_at_quad
1074
1181
assert(equation_type==FIELD_EQUATION_INTERNALENERGY)
1075
1182
assert(ele_ngi(pressure, ele)==ele_ngi(t, ele))
1077
rhs_addto = rhs_addto - &
1078
shape_rhs(test_function, ele_div_at_quad(velocity, ele, du_t) * ele_val_at_quad(pressure, ele) * detwei)
1185
! -p * (div(vfrac*nu))
1186
nvfracgrad_at_quad = ele_grad_at_quad(nvfrac, ele, dnvfrac_t)
1187
udotgradnvfrac_at_quad = sum(nvfracgrad_at_quad*ele_val_at_quad(velocity, ele), 1)
1189
rhs_addto = rhs_addto - ( shape_rhs(test_function, ele_div_at_quad(velocity, ele, du_t) * ele_val_at_quad(nvfrac, ele) * ele_val_at_quad(pressure, ele) * detwei) &
1190
+ shape_rhs(test_function, udotgradnvfrac_at_quad * ele_val_at_quad(pressure, ele) * detwei) )
1192
rhs_addto = rhs_addto - shape_rhs(test_function, ele_div_at_quad(velocity, ele, du_t) * ele_val_at_quad(pressure, ele) * detwei)
1080
1195
end subroutine add_pressurediv_element_cg
1082
subroutine assemble_advection_diffusion_face_cg(face, bc_type, t, t_bc, t_bc_2, matrix, rhs, positions, velocity, grid_velocity, density, olddensity)
1197
subroutine assemble_advection_diffusion_face_cg(face, bc_type, t, t_bc, t_bc_2, matrix, rhs, positions, velocity, grid_velocity, density, olddensity, nvfrac)
1083
1198
integer, intent(in) :: face
1084
1199
integer, intent(in) :: bc_type
1085
1200
type(scalar_field), intent(in) :: t
1127
1243
if(have_advection .and. integrate_advection_by_parts) &
1128
call add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, detwei, normal, matrix_addto, rhs_addto)
1244
call add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, nvfrac, detwei, normal, matrix_addto, rhs_addto)
1131
1247
if(have_diffusivity) call add_diffusivity_face_cg(face, bc_type, t, t_bc, t_bc_2, detwei, matrix_addto, rhs_addto)
1139
1255
end subroutine assemble_advection_diffusion_face_cg
1141
subroutine add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, detwei, normal, matrix_addto, rhs_addto)
1257
subroutine add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, nvfrac, detwei, normal, matrix_addto, rhs_addto)
1142
1258
integer, intent(in) :: face
1143
1259
integer, intent(in) :: bc_type
1144
1260
type(scalar_field), intent(in) :: t
1147
1263
type(vector_field), pointer :: grid_velocity
1148
1264
type(scalar_field), intent(in) :: density
1149
1265
type(scalar_field), intent(in) :: olddensity
1266
type(scalar_field), intent(in) :: nvfrac
1150
1267
real, dimension(face_ngi(t, face)), intent(in) :: detwei
1151
1268
real, dimension(mesh_dim(t), face_ngi(t, face)), intent(in) :: normal
1152
1269
real, dimension(face_loc(t, face), face_loc(t, face)), intent(inout) :: matrix_addto
1171
1288
case(FIELD_EQUATION_INTERNALENERGY)
1172
1289
density_at_quad = density_theta*face_val_at_quad(density, face) &
1173
1290
+(1.0-density_theta)*face_val_at_quad(olddensity, face)
1175
advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1) * density_at_quad)
1293
advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1) * density_at_quad * face_val_at_quad(nvfrac, face))
1295
advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1) * density_at_quad)
1178
1299
advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1))