Skip to content

Commit 2eac4cb

Browse files
committed
Workaround redistributing the mass (for saturation) after an adapt to ensure mass conservation after adapting.
1 parent e6160fd commit 2eac4cb

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

ICFERST/src/Multiphase_TimeLoop.F90

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ subroutine MultiFluids_SolveTimeLoop( state, &
253253
integer :: phreeqc_id
254254
double precision, ALLOCATABLE, dimension(:,:) :: concetration_phreeqc
255255
real :: total_mass_metal_before_adapt, total_mass_metal_after_adapt, total_mass_metal_after_correction, total_mass_metal_after_bound
256+
real, allocatable, dimension(:) :: total_mass_sat_before_adapt, total_mass_sat_after_adapt
256257
logical :: viscosity_EOS
257258
character(len=PYTHON_FUNC_LEN) :: pyfunc
258259

@@ -999,6 +1000,12 @@ subroutine MultiFluids_SolveTimeLoop( state, &
9991000
call total_mass_metal(state, packed_state, Mdims, ndgln, CV_funs, total_mass_metal_before_adapt)
10001001
end if
10011002

1003+
! Call to calculate the saturation total mass before adapting
1004+
allocate(total_mass_sat_before_adapt(Mdims%nphase))
1005+
allocate(total_mass_sat_after_adapt(Mdims%nphase))
1006+
1007+
call total_mass_sat(state, packed_state, Mdims, ndgln, CV_funs, total_mass_sat_before_adapt)
1008+
10021009
! Call to adapt the mesh if required! If adapting within the FPI then the adaption is controlled elsewhere
10031010
if(acctim >= t_adapt_threshold .and. .not. have_option( '/mesh_adaptivity/hr_adaptivity/adapt_mesh_within_FPI')) then
10041011
call adapt_mesh_mp()
@@ -1014,6 +1021,14 @@ subroutine MultiFluids_SolveTimeLoop( state, &
10141021
call correction_mass_metal(state, packed_state, Mdims, ndgln, total_mass_metal_before_adapt, total_mass_metal_after_bound)
10151022
end if
10161023

1024+
! Call to calculate the saturation total mass after adapting
1025+
call total_mass_sat(state, packed_state, Mdims, ndgln, CV_funs, total_mass_sat_after_adapt)
1026+
1027+
! Apply correction factor if needed to conserve mass
1028+
call correction_mass_sat(state, packed_state, Mdims, ndgln, total_mass_sat_before_adapt, total_mass_sat_after_adapt)
1029+
1030+
deallocate(total_mass_sat_before_adapt,total_mass_sat_after_adapt)
1031+
10171032
! ####Packing this section inside a internal subroutine breaks the code for non-debugging####
10181033
!!$ Simple adaptive time stepping algorithm
10191034

ICFERST/src/multi_eos.F90

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4046,4 +4046,114 @@ subroutine copy_metal_field(state, packed_state, Mdims, ndgln)
40464046

40474047
end subroutine copy_metal_field
40484048

4049+
!> @author Meissam Bahlali
4050+
!>@brief: subroutine to calculate the saturation total mass (in kg).
4051+
!>@param state Linked list containing all the fields defined in diamond and considered by Fluidity
4052+
!>@param packed_state Linked list containing all the fields used by IC-FERST, memory partially shared with state
4053+
!>@param Mdims Data type storing all the dimensions describing the mesh, fields, nodes, etc
4054+
!>@param ndgln Global to local variables
4055+
subroutine total_mass_sat(state, packed_state, Mdims, ndgln, CV_funs, total_mass)
4056+
implicit none
4057+
type(state_type), dimension(:), intent (inout) :: state
4058+
type(state_type), intent (inout) :: packed_state
4059+
type(multi_dimensions), intent (in) :: Mdims
4060+
type(multi_ndgln), intent (in) :: ndgln
4061+
type (multi_shape_funs) :: CV_funs
4062+
!Local variables
4063+
type(multi_dev_shape_funs) :: DevFuns
4064+
type(tensor_field), pointer :: density, sat_field
4065+
type(vector_field), pointer :: porosity_field
4066+
integer :: cv_nod, stat, ele, cv_iloc
4067+
real :: correction_factor, ref_rho
4068+
real, intent(out), dimension(Mdims%n_in_pres) :: total_mass
4069+
real, dimension (:), pointer :: mass_ele
4070+
type(vector_field), pointer :: vfield
4071+
type( vector_field ), pointer :: x
4072+
integer, dimension( : ), pointer :: x_ndgln
4073+
integer :: iphase
4074+
4075+
porosity_field=>extract_vector_field(packed_state,"Porosity")
4076+
density => extract_tensor_field(packed_state,"PackedDensity")
4077+
x => extract_vector_field( packed_state, "PressureCoordinate" )
4078+
x_ndgln => get_ndglno( extract_mesh( state( 1 ), "PressureMesh_Continuous" ) )
4079+
vfield => extract_vector_field(packed_state,"MASS_ELE")
4080+
mass_ele => vfield%val(1,:)
4081+
4082+
! here we run multi_dev_shape_funs just to calculate element volumes
4083+
call allocate_multi_dev_shape_funs(CV_funs, DevFuns)
4084+
4085+
sat_field => extract_tensor_field( packed_state, "PackedPhaseVolumeFraction" )
4086+
4087+
total_mass = 0.0
4088+
do iphase = 1, Mdims%n_in_pres
4089+
if (has_boussinesq_aprox) then
4090+
ref_rho=retrieve_reference_density(state, packed_state, iphase, 0, Mdims%nphase)
4091+
end if
4092+
do ele = 1, Mdims%totele
4093+
call DETNLXR(ele, X%val, x_ndgln, CV_funs%cvweight, CV_funs%CVFEN, CV_funs%CVFENLX_ALL, DevFuns)
4094+
Mass_ELE(ele) = DevFuns%volume
4095+
do cv_iloc = 1, Mdims%cv_nloc
4096+
cv_nod = ndgln%cv((ele-1)*Mdims%cv_nloc + cv_iloc)
4097+
if (node_owned(sat_field, cv_nod)) then
4098+
if (has_boussinesq_aprox) then
4099+
total_mass(iphase) = total_mass(iphase) + (porosity_field%val(1, ele) * ref_rho * sat_field%val(1,iphase,cv_nod) ) * (Mass_ELE(ele) / Mdims%cv_nloc)
4100+
else
4101+
total_mass(iphase) = total_mass(iphase) + (porosity_field%val(1, ele) * density%val(1,iphase,cv_nod) * sat_field%val(1,iphase,cv_nod)) * (Mass_ELE(ele) / Mdims%cv_nloc)
4102+
end if
4103+
end if
4104+
end do
4105+
end do
4106+
end do
4107+
4108+
call allsum(total_mass)
4109+
4110+
end subroutine total_mass_sat
4111+
4112+
!> @author Meissam Bahlali
4113+
!>@brief: subroutine to apply a correction factor to the saturation in order to conserve mass if needed.
4114+
!>@param state Linked list containing all the fields defined in diamond and considered by Fluidity
4115+
!>@param packed_state Linked list containing all the fields used by IC-FERST, memory partially shared with state
4116+
!>@param Mdims Data type storing all the dimensions describing the mesh, fields, nodes, etc
4117+
!>@param ndgln Global to local variables
4118+
subroutine correction_mass_sat(state, packed_state, Mdims, ndgln, total_mass_before, total_mass_after)
4119+
implicit none
4120+
type(state_type), dimension(:), intent (inout) :: state
4121+
type(state_type), intent (inout) :: packed_state
4122+
type(multi_dimensions), intent (in) :: Mdims
4123+
type(multi_ndgln), intent (in) :: ndgln
4124+
!Local variables
4125+
type(tensor_field), pointer :: sat_field
4126+
integer :: cv_nod, stat
4127+
real, intent(in), dimension(Mdims%n_in_pres) :: total_mass_before, total_mass_after
4128+
real, dimension(Mdims%n_in_pres) :: correction_factor, error
4129+
integer :: iphase
4130+
4131+
sat_field => extract_tensor_field( packed_state, "PackedPhaseVolumeFraction" )
4132+
4133+
do iphase = 1, Mdims%n_in_pres
4134+
if ( total_mass_after(iphase) > 0 ) then
4135+
4136+
correction_factor(iphase) = total_mass_before(iphase) / total_mass_after(iphase)
4137+
error(iphase) = 1.0 / correction_factor(iphase) - 1.0
4138+
4139+
! Uncomment below, if you want to debug the mass/adaptivity
4140+
! if ( abs(error(iphase)) >= 0.01 ) then
4141+
! if ( getprocno() == 1 ) then
4142+
! print *, "------------------------------------------------------------"
4143+
! print *, "Mass conservation issue after adaptivity step"
4144+
! print *, "Phase :", iphase
4145+
! print *, "Relative error (%) :", error(iphase) * 100.0
4146+
! print *, "Too much mass has to be redistributed across the domain."
4147+
! print *, "It is strongly advised to stop the simulation."
4148+
! print *, "------------------------------------------------------------"
4149+
! end if
4150+
! end if
4151+
4152+
sat_field%val(1,iphase,:) = sat_field%val(1,iphase,:) * correction_factor(iphase)
4153+
4154+
end if
4155+
end do
4156+
4157+
end subroutine correction_mass_sat
4158+
40494159
end module multiphase_EOS

0 commit comments

Comments
 (0)