@@ -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+
40494159end module multiphase_EOS
0 commit comments