Merge lp:~g-bhutani12/fluidity/PBM into lp:fluidity

Proposed by Gaurav Bhutani
Status: Work in progress
Proposed branch: lp:~g-bhutani12/fluidity/PBM
Merge into: lp:fluidity
Diff against target: 8540 lines (+7592/-53)
66 files modified
Makefile.in (+7/-0)
assemble/Adapt_State.F90 (+8/-2)
assemble/Diagnostic_fields_wrapper.F90 (+7/-1)
assemble/Multiphase.F90 (+86/-18)
configure (+2/-1)
configure.in (+1/-0)
diagnostics/Multiphase_Diagnostics.F90 (+21/-3)
examples/tephra_settling/tephra_settling.flml (+3/-1)
main/Fluids.F90 (+20/-1)
population_balance/DQMOM.F90 (+999/-0)
population_balance/Makefile.dependencies (+10/-0)
population_balance/Makefile.in (+66/-0)
preprocessor/Field_Priority_Lists.F90 (+42/-0)
preprocessor/Populate_State.F90 (+23/-2)
schemas/diagnostic_algorithms.rnc (+2/-1)
schemas/diagnostic_algorithms.rng (+8/-1)
schemas/fluidity_options.rnc (+448/-2)
schemas/fluidity_options.rng (+649/-1)
schemas/multiphase_interaction.rnc (+6/-1)
schemas/multiphase_interaction.rng (+7/-0)
tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml (+6/-2)
tests/mphase_inlet_velocity_bc_compressible/mphase_inlet_velocity_bc_compressible.flml (+3/-1)
tests/mphase_rogue_shock_tube_dense_bed_glass/mphase_rogue_shock_tube_dense_bed_glass.flml (+3/-1)
tests/mphase_rogue_shock_tube_dense_bed_nylon/mphase_rogue_shock_tube_dense_bed_nylon.flml (+3/-1)
tests/mphase_stokes_law/mphase_stokes_law.flml (+6/-2)
tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p0p1.flml (+3/-1)
tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p2p1.flml (+3/-1)
tests/mphase_subtract_out_reference_profile/mphase_subtract_out_reference_profile_1d.flml (+3/-1)
tests/mphase_tephra_settling/mphase_tephra_settling.flml (+6/-2)
tests/mphase_wen_yu_drag_correlation/mphase_wen_yu_drag_correlation.flml (+6/-2)
tests/popbal_homog_brk_aggr/Makefile (+5/-0)
tests/popbal_homog_brk_aggr/popbal_homog_N2.flml (+723/-0)
tests/popbal_homog_brk_aggr/popbal_homog_N2_brk_aggr.xml (+34/-0)
tests/popbal_homog_brk_aggr/src/minimal.geo (+28/-0)
tests/popbal_nonhomog2_2d_adapt/Makefile (+5/-0)
tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.flml (+670/-0)
tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.xml (+46/-0)
tests/popbal_nonhomog2_2d_adapt/readme (+13/-0)
tests/popbal_nonhomog2_2d_adapt/src/channel.geo (+16/-0)
tests/popbal_nonhomog2_2d_cg_p1/Makefile (+5/-0)
tests/popbal_nonhomog2_2d_cg_p1/popbal_nonhomog2_2d.flml (+614/-0)
tests/popbal_nonhomog2_2d_cg_p1/popbal_nonhomog2_2d_cg_p1.xml (+46/-0)
tests/popbal_nonhomog2_2d_cg_p1/readme (+12/-0)
tests/popbal_nonhomog2_2d_cg_p1/src/channel.geo (+16/-0)
tests/popbal_nonhomog2_2d_cg_p2/Makefile (+5/-0)
tests/popbal_nonhomog2_2d_cg_p2/popbal_nonhomog2_2d.flml (+633/-0)
tests/popbal_nonhomog2_2d_cg_p2/popbal_nonhomog2_2d_cg_p2.xml (+46/-0)
tests/popbal_nonhomog2_2d_cg_p2/readme (+12/-0)
tests/popbal_nonhomog2_2d_cg_p2/src/channel.geo (+16/-0)
tests/popbal_nonhomog2_2d_dg_p1/Makefile (+5/-0)
tests/popbal_nonhomog2_2d_dg_p1/popbal_nonhomog2_2d.flml (+630/-0)
tests/popbal_nonhomog2_2d_dg_p1/popbal_nonhomog2_2d_dg_p1.xml (+46/-0)
tests/popbal_nonhomog2_2d_dg_p1/readme (+11/-0)
tests/popbal_nonhomog2_2d_dg_p1/src/channel.geo (+16/-0)
tests/popbal_nonhomog2_2d_dg_p2/Makefile (+5/-0)
tests/popbal_nonhomog2_2d_dg_p2/popbal_nonhomog2_2d.flml (+630/-0)
tests/popbal_nonhomog2_2d_dg_p2/popbal_nonhomog2_2d_dg_p2.xml (+45/-0)
tests/popbal_nonhomog2_2d_dg_p2/readme (+11/-0)
tests/popbal_nonhomog2_2d_dg_p2/src/channel.geo (+16/-0)
tests/popbal_nonhomog2_2d_dg_p2/time_versus_norm (+20/-0)
tests/popbal_nonhomog_2d_cg_p1/Makefile (+5/-0)
tests/popbal_nonhomog_2d_cg_p1/popbal_nonhomog_2d.flml (+672/-0)
tests/popbal_nonhomog_2d_cg_p1/popbal_nonhomog_2d_cg_p1.xml (+46/-0)
tests/popbal_nonhomog_2d_cg_p1/readme (+12/-0)
tests/popbal_nonhomog_2d_cg_p1/src/channel.geo (+17/-0)
tools/Supermesh_Difference.F90 (+3/-4)
To merge this branch: bzr merge lp:~g-bhutani12/fluidity/PBM
Reviewer Review Type Date Requested Status
sam Pending
Review via email: mp+183296@code.launchpad.net

Description of the change

A fully functional population balance modelling capability has been added to Fluidity, It is based on the famous Direct Quadrature Method of Moments (DQMOM) by Marchisio and Fox (2005). Currently it can solve population balance equations with one internal variable. Support for multiple internal variables will be added at a later stage (1-2 years time). The branch has been tested for adaptivity and parallel runs.

To post a comment you must log in.
lp:~g-bhutani12/fluidity/PBM updated
4210. By Gaurav Bhutani

Removed some old test cases

4211. By Gaurav Bhutani

Merge with trunk

4212. By Gaurav Bhutani

Removed a few old test cases

4213. By Gaurav Bhutani

Changes made to diamond tree in Multiphase options to accept a scalar field for partcle diameter (only accepted a constant earlier). Multiphase.F90 modified to accept a scalar field as particle diameter and use it in drag force term calculations for momentum equations; the file has also been modified for new diamond structure. Multiphase test cases modified to suit modified diamond structure. All tests passed with this new modifications.

4214. By Gaurav Bhutani

Included the scalar field -- SauterMeanDia -- in the list of statistics. Modified the comparison conditions for other statistics to exact string comparison. Modified the rnc file to include the scalar field called SauterMeanDia in the list of statistics. SauterMeanDia has been added to the statistics so that it can be calculated after every non-linear iteration in Fluids.F90 and the new sauter mean diameter be used in the momentum calculations.

4215. By Gaurav Bhutani

Changes to Fluids.F90 to call dqmom_calculate_moments() and dqmom_calculate_statistics inside the nonlinear loop. This updates the SauterMeanDia after every nonlinear iteration to be used in the drag force term in the momentum equation in next nonlinear iteration.

4216. By Gaurav Bhutani

Corrected the PD algorithm implementation in DQMOM.F90

Revision history for this message
Tim Greaves (tim-greaves) wrote :

Hi Gaurav -- given this was proposed more than a couple of months ago and looks to be in active development at the moment I'm setting it back to 'in progress'; if you get to the point you want to move for a review and merge, please do set back to 'needs review'.

Revision history for this message
Gaurav Bhutani (g-bhutani12) wrote :

Hi Tim,

Yes, I have been working on the branch recently to couple it with Multiphase.F90.
Apologies, I completely forgot to change the status of it to WIP.
Thanks for that.
I will propose it for a merge very soon with all the documentation and test cases in it.

Regards,
Gaurav
________________________________________
From: <email address hidden> [<email address hidden>] on behalf of Tim Greaves [<email address hidden>]
Sent: 01 November 2013 17:41
To: Bhutani, Gaurav
Subject: Re: [Merge] lp:~g-bhutani12/fluidity/PBM into lp:fluidity

Hi Gaurav -- given this was proposed more than a couple of months ago and looks to be in active development at the moment I'm setting it back to 'in progress'; if you get to the point you want to move for a review and merge, please do set back to 'needs review'.
--
https://code.launchpad.net/~g-bhutani12/fluidity/PBM/+merge/183296
You are the owner of lp:~g-bhutani12/fluidity/PBM.

lp:~g-bhutani12/fluidity/PBM updated
4217. By Gaurav Bhutani

Included a breakage kernel as used by McCoy and Madras (2003) for the daughter distribution function. Also corrected the aggregation birth term contribution into source to handle negative abscissas and their cube roots.

4218. By Gaurav Bhutani

Added a test case for homogeneous population balance with breakage and aggregation. The analytical solution of McCoy and Madras (2003) was used to compare against the numerical results.

4219. By Gaurav Bhutani

Added saling factor to scale Sauter Mean Diameter in case of non-dimensional implementation of PBE.

4220. By Gaurav Bhutani

Added modified Schiller & Naumann (1933) interphase drag coefficient to Multiphase.F90 as implemented in ANSYS CFX. Changes made to diamond tree for the option for this new drag coefficient. Slight change in Multiphase.F90 to change defualt to default in a switch-case statement.

4221. By Gaurav Bhutani

Slight change to Schiller-Naumann (1933) drag implementation - multiplied by the volume fraction of continuous phase in drag force term as done by Abbasi et. al. (2013).

4222. By Gaurav Bhutani

PBM: Added a sum_aggregation kernel as implemented by Abbasi et. al. (2013). Also added the population balance statistic called MeanDia10 (d_10). DQMOM.F90 and fluidity_oprions.rnc modified for the two changes.

4223. By Gaurav Bhutani

Modified Multiphase_Diagnostics.F90 to allow particle_reynolds_number to take a scalar field for particle diameter. schemas/diagnostic_algorithms.rnc was also modified for the same reason. flml in 4 test cases in multiphase were modified as per the schema modifications.

Unmerged revisions

4223. By Gaurav Bhutani

Modified Multiphase_Diagnostics.F90 to allow particle_reynolds_number to take a scalar field for particle diameter. schemas/diagnostic_algorithms.rnc was also modified for the same reason. flml in 4 test cases in multiphase were modified as per the schema modifications.

4222. By Gaurav Bhutani

PBM: Added a sum_aggregation kernel as implemented by Abbasi et. al. (2013). Also added the population balance statistic called MeanDia10 (d_10). DQMOM.F90 and fluidity_oprions.rnc modified for the two changes.

4221. By Gaurav Bhutani

Slight change to Schiller-Naumann (1933) drag implementation - multiplied by the volume fraction of continuous phase in drag force term as done by Abbasi et. al. (2013).

4220. By Gaurav Bhutani

Added modified Schiller & Naumann (1933) interphase drag coefficient to Multiphase.F90 as implemented in ANSYS CFX. Changes made to diamond tree for the option for this new drag coefficient. Slight change in Multiphase.F90 to change defualt to default in a switch-case statement.

4219. By Gaurav Bhutani

Added saling factor to scale Sauter Mean Diameter in case of non-dimensional implementation of PBE.

4218. By Gaurav Bhutani

Added a test case for homogeneous population balance with breakage and aggregation. The analytical solution of McCoy and Madras (2003) was used to compare against the numerical results.

4217. By Gaurav Bhutani

Included a breakage kernel as used by McCoy and Madras (2003) for the daughter distribution function. Also corrected the aggregation birth term contribution into source to handle negative abscissas and their cube roots.

4216. By Gaurav Bhutani

Corrected the PD algorithm implementation in DQMOM.F90

4215. By Gaurav Bhutani

Changes to Fluids.F90 to call dqmom_calculate_moments() and dqmom_calculate_statistics inside the nonlinear loop. This updates the SauterMeanDia after every nonlinear iteration to be used in the drag force term in the momentum equation in next nonlinear iteration.

4214. By Gaurav Bhutani

Included the scalar field -- SauterMeanDia -- in the list of statistics. Modified the comparison conditions for other statistics to exact string comparison. Modified the rnc file to include the scalar field called SauterMeanDia in the list of statistics. SauterMeanDia has been added to the statistics so that it can be calculated after every non-linear iteration in Fluids.F90 and the new sauter mean diameter be used in the momentum calculations.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.in'
2--- Makefile.in 2013-11-13 00:28:27 +0000
3+++ Makefile.in 2013-12-12 22:35:40 +0000
4@@ -310,6 +310,8 @@
5 @cd horizontal_adaptivity; $(MAKE)
6 @echo " MAKE preprocessor"
7 @cd preprocessor; $(MAKE)
8+ @echo " MAKE population_balance"
9+ @cd population_balance; $(MAKE)
10 @echo " MAKE error_measures"
11 @cd error_measures; $(MAKE)
12 @echo " MAKE assemble"
13@@ -340,6 +342,7 @@
14 forward_interfaces/*.o \
15 horizontal_adaptivity/*.o \
16 preprocessor/*.o \
17+population_balance/*.o \
18 error_measures/*.o \
19 assemble/*.o \
20 diagnostics/*.o \
21@@ -387,6 +390,8 @@
22 @cd diagnostics; $(MAKE) clean
23 @echo " CLEAN preprocessor"
24 @cd preprocessor; $(MAKE) clean
25+ @echo " CLEAN population_balance"
26+ @cd population_balance; $(MAKE) clean
27 @echo " CLEAN error_measures/tests"
28 @cd error_measures/tests; $(MAKE) clean
29 @echo " CLEAN error_measures"
30@@ -588,6 +593,8 @@
31 @echo " Generating preprocessor dependencies"
32 @cd preprocessor; ../bin/create_makefile --exclude \
33 "register_diagnostics.F90 check_options.F90" $(TESTOPTS)
34+ @echo " Generating population_balance dependencies"
35+ @cd population_balance; ../bin/create_makefile $(TESTOPTS)
36 @echo " Generating error_measures dependencies"
37 @cd error_measures; ../bin/create_makefile $(TESTOPTS)
38 @echo " Generating assemble dependencies"
39
40=== modified file 'assemble/Adapt_State.F90'
41--- assemble/Adapt_State.F90 2013-11-13 01:51:23 +0000
42+++ assemble/Adapt_State.F90 2013-12-12 22:35:40 +0000
43@@ -74,6 +74,7 @@
44 use diagnostic_fields_wrapper_new, only : calculate_diagnostic_variables_new => calculate_diagnostic_variables
45 use pickers
46 use write_gmsh
47+ use dqmom
48 #ifdef HAVE_ZOLTAN
49 use zoltan_integration
50 use mpi_interfaces
51@@ -878,7 +879,7 @@
52 type(state_type), dimension(:), intent(inout) :: states
53
54 character(len = *), parameter :: base_path = "/mesh_adaptivity/hr_adaptivity/adapt_at_first_timestep"
55- integer :: adapt_iterations, i
56+ integer :: adapt_iterations, i, i_state
57 type(mesh_type), pointer :: old_mesh
58 type(tensor_field) :: metric
59 type(vector_field), pointer :: output_positions
60@@ -896,7 +897,6 @@
61 call copy_to_stored_values(states,"Old")
62 call copy_to_stored_values(states,"Iterated")
63 call relax_to_nonlinear(states)
64-
65 call calculate_diagnostic_variables(states)
66 call calculate_diagnostic_variables_new(states)
67
68@@ -916,6 +916,12 @@
69 ! Adapt state, initialising fields from the options tree rather than
70 ! interpolating them
71 call adapt_state(states, metric, initialise_fields = .true.)
72+
73+ ! dqmom_init helps to recalculate the abscissas and weights based on moment initial conditions (if provided)
74+ call dqmom_init(states)
75+! do i_state = 1, option_count("/material_phase")
76+! call dqmom_calculate_moments(states(i_state))
77+! end do
78 end do
79
80 if(have_option(trim(base_path) // "/output_adapted_mesh")) then
81
82=== modified file 'assemble/Diagnostic_fields_wrapper.F90'
83--- assemble/Diagnostic_fields_wrapper.F90 2013-04-16 11:38:41 +0000
84+++ assemble/Diagnostic_fields_wrapper.F90 2013-12-12 22:35:40 +0000
85@@ -54,6 +54,7 @@
86 use momentum_diagnostic_fields
87 use spontaneous_potentials, only: calculate_formation_conductivity
88 use sediment_diagnostics
89+ use dqmom
90 use geostrophic_pressure
91 use multiphase_module
92
93@@ -80,7 +81,7 @@
94 type(state_type), dimension(:), pointer :: submaterials
95
96 ewrite(1, *) "In calculate_diagnostic_variables"
97-
98+
99 do i = 1, size(state)
100
101 ! start of fields that can be called through the generic calculate_diagnostic_variable
102@@ -562,6 +563,11 @@
103 call calculate_sediment_active_layer_volume_fractions(state(i))
104 end if
105 ! End of sediment diagnostics.
106+
107+ ! Start of population balance diagnostics.
108+ call dqmom_calculate_moments(state(i))
109+ call dqmom_calculate_statistics(state(i))
110+ ! End of population balance diagnostics.
111
112 ! Multiphase-related diagnostic fields
113 s_field => extract_scalar_field(state(i), "PhaseVolumeFraction", stat)
114
115=== modified file 'assemble/Multiphase.F90'
116--- assemble/Multiphase.F90 2013-03-03 01:36:16 +0000
117+++ assemble/Multiphase.F90 2013-12-12 22:35:40 +0000
118@@ -284,9 +284,10 @@
119
120 ! Types of drag correlation
121 integer, parameter :: DRAG_CORRELATION_TYPE_STOKES = 1, DRAG_CORRELATION_TYPE_WEN_YU = 2, DRAG_CORRELATION_TYPE_ERGUN = 3
122+ integer, parameter :: DRAG_CORRELATION_TYPE_SCHILLER_NAUMANN = 4
123
124 ewrite(1, *) "Entering add_fluid_particle_drag"
125-
126+
127 ! Let's check whether we actually have at least one particle phase.
128 if(option_count("/material_phase/multiphase_properties/particle_diameter") == 0) then
129 FLExit("Fluid-particle drag enabled but no particle_diameter has been specified for the particle phase(s).")
130@@ -357,6 +358,8 @@
131
132 type(scalar_field), pointer :: vfrac_fluid, vfrac_particle
133 type(scalar_field), pointer :: density_fluid, density_particle
134+ type(scalar_field), pointer :: pd_scalar_field ! scalar field defining particle diameter
135+
136 type(vector_field), pointer :: velocity_fluid, velocity_particle
137 type(vector_field), pointer :: oldu_fluid, oldu_particle
138 type(vector_field), pointer :: nu_fluid, nu_particle ! Non-linear approximation to the Velocities
139@@ -364,7 +367,9 @@
140 type(scalar_field) :: nvfrac_fluid, nvfrac_particle
141 real :: d ! Particle diameter
142 character(len=OPTION_PATH_LEN) :: drag_correlation_name
143+ character(len=OPTION_PATH_LEN) :: pd_field_name ! name of scalar field that defines particle diameter (can be the sauter mean dia)
144 integer :: drag_correlation
145+ logical :: have_constant_pd ! checks if the particle diameter is a constant or not
146
147 ! Get the necessary fields to calculate the drag force
148 velocity_fluid => extract_vector_field(state(istate_fluid), "Velocity")
149@@ -376,8 +381,15 @@
150 density_fluid => extract_scalar_field(state(istate_fluid), "Density")
151 density_particle => extract_scalar_field(state(istate_particle), "Density")
152 viscosity_fluid => extract_tensor_field(state(istate_fluid), "Viscosity")
153-
154- call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter", d)
155+
156+ if(have_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/constant")) then
157+ call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/constant", d)
158+ have_constant_pd = .true.
159+ else if(have_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/use_scalar_field")) then
160+ call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/use_scalar_field", pd_field_name)
161+ pd_scalar_field => extract_scalar_field(state(istate_particle), pd_field_name)
162+ have_constant_pd = .false.
163+ end if
164
165 ! Calculate the non-linear approximation to the PhaseVolumeFractions
166 call allocate(nvfrac_fluid, vfrac_fluid%mesh, "NonlinearPhaseVolumeFraction")
167@@ -401,7 +413,9 @@
168 drag_correlation = DRAG_CORRELATION_TYPE_WEN_YU
169 case("ergun")
170 drag_correlation = DRAG_CORRELATION_TYPE_ERGUN
171- case("default")
172+ case("schiller_naumann")
173+ drag_correlation = DRAG_CORRELATION_TYPE_SCHILLER_NAUMANN
174+ case default
175 FLAbort("Unknown correlation for fluid-particle drag")
176 end select
177
178@@ -420,7 +434,9 @@
179 density_fluid, density_particle, &
180 nu_fluid, nu_particle, &
181 oldu_fluid, oldu_particle, &
182- viscosity_fluid, d, drag_correlation)
183+ viscosity_fluid, &
184+ have_constant_pd, d, pd_scalar_field, &
185+ drag_correlation)
186 end if
187
188 end do element_loop
189@@ -438,7 +454,9 @@
190 density_fluid, density_particle, &
191 nu_fluid, nu_particle, &
192 oldu_fluid, oldu_particle, &
193- viscosity_fluid, d, drag_correlation)
194+ viscosity_fluid, &
195+ have_constant_pd, dia, pd_scalar_field, &
196+ drag_correlation)
197
198 integer, intent(in) :: ele
199 type(element_type), intent(in) :: test_function
200@@ -449,12 +467,14 @@
201
202 type(scalar_field), intent(in) :: vfrac_fluid, vfrac_particle
203 type(scalar_field), intent(in) :: density_fluid, density_particle
204+ type(scalar_field), intent(in) :: pd_scalar_field ! Scalar field representing particle diameter
205 type(vector_field), intent(in) :: nu_fluid, nu_particle
206 type(vector_field), intent(in) :: oldu_fluid, oldu_particle
207 type(tensor_field), intent(in) :: viscosity_fluid
208- real, intent(in) :: d ! Particle diameter
209+ real, intent(in) :: dia ! Constant particle diameter
210 integer, intent(in) :: drag_correlation
211-
212+ logical, intent(in) :: have_constant_pd ! is true if particle diameter is a constant. is false if it is a scalar field (e.g. sauter mean dia)
213+
214 ! Local variables
215 real, dimension(ele_ngi(u,ele)) :: vfrac_fluid_gi, vfrac_particle_gi
216 real, dimension(ele_ngi(u,ele)) :: density_fluid_gi, density_particle_gi
217@@ -473,6 +493,7 @@
218 real, dimension(ele_ngi(u,ele)) :: particle_re_gi ! Particle Reynolds number
219 real, dimension(ele_ngi(u,ele)) :: drag_coefficient_gi
220 real, dimension(ele_ngi(u,ele)) :: magnitude_gi ! |v_f - v_p|
221+ real, dimension(ele_ngi(u,ele)) :: d_gi ! particle diameter at the Gauss points
222
223 real, dimension(ele_ngi(u,ele)) :: K
224 real, dimension(ele_ngi(u,ele)) :: drag_force_big_m
225@@ -497,9 +518,16 @@
226 magnitude_gi(gi) = norm2(nu_fluid_gi(:,gi) - nu_particle_gi(:,gi))
227 end do
228
229+ ! Compute the particle diameter at the Gauss points
230+ if(have_constant_pd) then
231+ d_gi = dia
232+ else
233+ d_gi = ele_val_at_quad(pd_scalar_field, ele)
234+ end if
235+
236 ! Compute the particle Reynolds number
237 ! (Assumes isotropic viscosity for now)
238- particle_re_gi = (vfrac_fluid_gi*density_fluid_gi*magnitude_gi*d) / viscosity_fluid_gi(1,1,:)
239+ particle_re_gi = (vfrac_fluid_gi*density_fluid_gi*magnitude_gi*d_gi) / viscosity_fluid_gi(1,1,:)
240
241 ! Compute the drag coefficient
242 select case(drag_correlation)
243@@ -525,6 +553,18 @@
244
245 case(DRAG_CORRELATION_TYPE_ERGUN)
246 ! No drag coefficient is needed here.
247+
248+ case(DRAG_CORRELATION_TYPE_SCHILLER_NAUMANN)
249+ ! Schiller & Naumann (1933) drag correlation
250+ ! Since the particle Reynolds number definition currently contains vfrac_fluid in numerator,
251+ ! we need to take that out by dividing as done below. Must be changed when Reynolds number defn is changed - gb812
252+ do gi = 1, ele_ngi(u,ele)
253+ if((particle_re_gi(gi)/vfrac_fluid_gi(gi)) < 1000) then
254+ drag_coefficient_gi(gi) = (24.0/(particle_re_gi(gi)/vfrac_fluid_gi(gi)))*(1.0+0.15*(particle_re_gi(gi)/vfrac_fluid_gi(gi))**0.687)
255+ else
256+ drag_coefficient_gi(gi) = 0.44
257+ end if
258+ end do
259 end select
260
261 ! Don't let the drag_coefficient_gi be NaN
262@@ -536,12 +576,15 @@
263
264 select case(drag_correlation)
265 case(DRAG_CORRELATION_TYPE_STOKES)
266- K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient_gi*(vfrac_fluid_gi*density_fluid_gi*magnitude_gi)/(d)
267+ K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient_gi*(vfrac_fluid_gi*density_fluid_gi*magnitude_gi)/(d_gi)
268 case(DRAG_CORRELATION_TYPE_WEN_YU)
269 ! Wen & Yu (1966) drag term
270- K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient_gi*(vfrac_fluid_gi*density_fluid_gi*magnitude_gi)/(d*vfrac_fluid_gi**2.7)
271+ K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient_gi*(vfrac_fluid_gi*density_fluid_gi*magnitude_gi)/(d_gi*vfrac_fluid_gi**2.7)
272 case(DRAG_CORRELATION_TYPE_ERGUN)
273- K = 150.0*((vfrac_particle_gi**2)*viscosity_fluid_gi(1,1,:))/(vfrac_fluid_gi*(d**2)) + 1.75*(vfrac_particle_gi*density_fluid_gi*magnitude_gi/d)
274+ K = 150.0*((vfrac_particle_gi**2)*viscosity_fluid_gi(1,1,:))/(vfrac_fluid_gi*(d_gi**2)) + &
275+ 1.75*(vfrac_particle_gi*density_fluid_gi*magnitude_gi/d_gi)
276+ case(DRAG_CORRELATION_TYPE_SCHILLER_NAUMANN)
277+ K = vfrac_fluid_gi*vfrac_particle_gi*(3.0/4.0)*drag_coefficient_gi*(density_fluid_gi*magnitude_gi)/(d_gi)
278 end select
279
280 if(is_particle_phase) then
281@@ -680,6 +723,7 @@
282
283 type(scalar_field), pointer :: vfrac_fluid, vfrac_particle
284 type(scalar_field), pointer :: density_fluid, density_particle
285+ type(scalar_field), pointer :: pd_scalar_field ! scalar field defining particle diameter
286 type(vector_field), pointer :: velocity_fluid, velocity_particle
287 type(scalar_field), pointer :: internal_energy_fluid, internal_energy_particle
288 type(scalar_field), pointer :: old_internal_energy_fluid, old_internal_energy_particle
289@@ -691,6 +735,8 @@
290 real :: C_fluid, C_particle ! Specific heat of the fluid and particle phases at constant volume
291 real :: gamma ! Ratio of specific heats for compressible phase
292 integer :: kstat, cstat_fluid, cstat_particle, gstat
293+ character(len=OPTION_PATH_LEN) :: pd_field_name ! name of scalar field that defines particle diameter (can be the sauter mean dia)
294+ logical :: have_constant_pd ! checks if the particle diameter is a constant or not
295
296 ! Get the necessary fields to calculate the heat transfer term
297 velocity_fluid => extract_vector_field(state(istate_fluid), "Velocity")
298@@ -703,7 +749,14 @@
299 density_particle => extract_scalar_field(state(istate_particle), "Density")
300 viscosity_fluid => extract_tensor_field(state(istate_fluid), "Viscosity")
301
302- call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter", d)
303+ if(have_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/constant")) then
304+ call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/constant", d)
305+ have_constant_pd = .true.
306+ else if(have_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/use_scalar_field")) then
307+ call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter/use_scalar_field", pd_field_name)
308+ pd_scalar_field => extract_scalar_field(state(istate_particle), pd_field_name)
309+ have_constant_pd = .false.
310+ end if
311
312 call get_option(trim(state(istate_fluid)%option_path)//"/multiphase_properties/effective_conductivity", k, kstat)
313
314@@ -759,7 +812,9 @@
315 internal_energy_particle, &
316 old_internal_energy_fluid, &
317 old_internal_energy_particle, &
318- viscosity_fluid, d, k, C_fluid, &
319+ viscosity_fluid, &
320+ have_constant_pd, d, pd_scalar_field, &
321+ k, C_fluid, &
322 C_particle, gamma)
323 end if
324
325@@ -781,7 +836,9 @@
326 internal_energy_particle, &
327 old_internal_energy_fluid, &
328 old_internal_energy_particle, &
329- viscosity_fluid, d, k, C_fluid, &
330+ viscosity_fluid, &
331+ have_constant_pd, dia, pd_scalar_field, &
332+ k, C_fluid, &
333 C_particle, gamma)
334
335 integer, intent(in) :: ele
336@@ -794,11 +851,14 @@
337
338 type(scalar_field), intent(in) :: vfrac_fluid, vfrac_particle
339 type(scalar_field), intent(in) :: density_fluid, density_particle
340+ type(scalar_field), intent(in) :: pd_scalar_field ! Scalar field representing particle diameter
341 type(vector_field), intent(in) :: nu_fluid, nu_particle
342 type(scalar_field), intent(in) :: internal_energy_fluid, internal_energy_particle
343 type(scalar_field), intent(in) :: old_internal_energy_fluid, old_internal_energy_particle
344 type(tensor_field), intent(in) :: viscosity_fluid
345- real, intent(in) :: d, k, C_fluid, C_particle, gamma
346+ real, intent(in) :: dia ! Constant particle diameter
347+ real, intent(in) :: k, C_fluid, C_particle, gamma
348+ logical, intent(in) :: have_constant_pd ! is true if particle diameter is a constant. is false if it is a scalar field (e.g. sauter mean dia)
349
350 ! Local variables
351 real, dimension(ele_ngi(x,ele)) :: internal_energy_fluid_gi, internal_energy_particle_gi
352@@ -814,6 +874,7 @@
353 real, dimension(ele_loc(internal_energy,ele)) :: rhs_addto
354 real, dimension(ele_loc(internal_energy,ele), ele_loc(internal_energy,ele)) :: matrix_addto
355
356+ real, dimension(ele_ngi(x,ele)) :: d_gi ! particle diameter at quadrature points
357 real, dimension(ele_ngi(x,ele)) :: particle_Re ! Particle Reynolds number
358 real, dimension(ele_ngi(x,ele)) :: Pr ! Prandtl number
359 real, dimension(ele_ngi(x,ele)) :: particle_Nu ! Particle Nusselt number
360@@ -844,9 +905,16 @@
361 velocity_magnitude(gi) = norm2(nu_fluid_gi(:,gi) - nu_particle_gi(:,gi))
362 end do
363
364+ ! Compute the particle diameter at quadrature points
365+ if(have_constant_pd) then
366+ d_gi = dia
367+ else
368+ d_gi = ele_val_at_quad(pd_scalar_field, ele)
369+ end if
370+
371 ! Compute the particle Reynolds number
372 ! (Assumes isotropic viscosity for now)
373- particle_Re = (density_fluid_gi*velocity_magnitude*d) / viscosity_fluid_gi(1,1,:)
374+ particle_Re = (density_fluid_gi*velocity_magnitude*d_gi) / viscosity_fluid_gi(1,1,:)
375
376 ! Compute the Prandtl number
377 ! (Assumes isotropic viscosity for now)
378@@ -856,7 +924,7 @@
379 particle_Nu = (7.0 - 10.0*vfrac_fluid_gi + 5.0*vfrac_fluid_gi**2)*(1.0 + 0.7*(particle_Re**0.2)*(Pr**(1.0/3.0))) + &
380 (1.33 - 2.4*vfrac_fluid_gi + 1.2*vfrac_fluid_gi**2)*(particle_Re**0.7)*(Pr**(1.0/3.0))
381
382- Q = (6.0*k*vfrac_particle_gi*particle_Nu)/(d**2)
383+ Q = (6.0*k*vfrac_particle_gi*particle_Nu)/(d_gi**2)
384
385 ! Note that the transfer term is defined in terms of temperatures (T_fluid and T_particle)
386 ! Let's convert the temperatures to internal energy (E) using E_i = C_i*T_i,
387
388=== modified file 'configure'
389--- configure 2013-10-17 17:13:25 +0000
390+++ configure 2013-12-12 22:35:40 +0000
391@@ -14918,7 +14918,7 @@
392
393 #*******************
394
395-ac_config_files="$ac_config_files Makefile debug/Makefile bathymetry/Makefile ocean_forcing/Makefile ocean_forcing/tests/Makefile sediments/Makefile hyperlight/Makefile femtools/Makefile femtools/tests/Makefile forward_interfaces/Makefile horizontal_adaptivity/Makefile horizontal_adaptivity/tests/Makefile preprocessor/Makefile error_measures/Makefile error_measures/tests/Makefile parameterisation/Makefile parameterisation/tests/Makefile fldecomp/Makefile assemble/Makefile assemble/tests/Makefile diagnostics/Makefile main/Makefile tools/Makefile tools/version-info python/setup.py adjoint/Makefile adjoint/tests/Makefile climatology/Makefile libmba2d/Makefile libmba3d/Makefile libjudy/Makefile libjudy/src/Makefile libjudy/src/JudyCommon/Makefile libjudy/src/Judy1/Makefile libjudy/src/JudyL/Makefile libjudy/src/JudySL/Makefile libjudy/src/JudyHS/Makefile libwm/Makefile libvtkfortran/Makefile schemas/flml reduced_modelling/Makefile"
396+ac_config_files="$ac_config_files Makefile debug/Makefile bathymetry/Makefile ocean_forcing/Makefile ocean_forcing/tests/Makefile sediments/Makefile population_balance/Makefile hyperlight/Makefile femtools/Makefile femtools/tests/Makefile forward_interfaces/Makefile horizontal_adaptivity/Makefile horizontal_adaptivity/tests/Makefile preprocessor/Makefile error_measures/Makefile error_measures/tests/Makefile parameterisation/Makefile parameterisation/tests/Makefile fldecomp/Makefile assemble/Makefile assemble/tests/Makefile diagnostics/Makefile main/Makefile tools/Makefile tools/version-info python/setup.py adjoint/Makefile adjoint/tests/Makefile climatology/Makefile libmba2d/Makefile libmba3d/Makefile libjudy/Makefile libjudy/src/Makefile libjudy/src/JudyCommon/Makefile libjudy/src/Judy1/Makefile libjudy/src/JudyL/Makefile libjudy/src/JudySL/Makefile libjudy/src/JudyHS/Makefile libwm/Makefile libvtkfortran/Makefile schemas/flml reduced_modelling/Makefile"
397
398 cat >confcache <<\_ACEOF
399 # This file is a shell script that caches the results of configure
400@@ -15629,6 +15629,7 @@
401 "ocean_forcing/Makefile") CONFIG_FILES="$CONFIG_FILES ocean_forcing/Makefile" ;;
402 "ocean_forcing/tests/Makefile") CONFIG_FILES="$CONFIG_FILES ocean_forcing/tests/Makefile" ;;
403 "sediments/Makefile") CONFIG_FILES="$CONFIG_FILES sediments/Makefile" ;;
404+ "population_balance/Makefile") CONFIG_FILES="$CONFIG_FILES population_balance/Makefile" ;;
405 "hyperlight/Makefile") CONFIG_FILES="$CONFIG_FILES hyperlight/Makefile" ;;
406 "femtools/Makefile") CONFIG_FILES="$CONFIG_FILES femtools/Makefile" ;;
407 "femtools/tests/Makefile") CONFIG_FILES="$CONFIG_FILES femtools/tests/Makefile" ;;
408
409=== modified file 'configure.in'
410--- configure.in 2013-09-23 20:07:28 +0000
411+++ configure.in 2013-12-12 22:35:40 +0000
412@@ -1503,6 +1503,7 @@
413 bathymetry/Makefile
414 ocean_forcing/Makefile ocean_forcing/tests/Makefile
415 sediments/Makefile
416+ population_balance/Makefile
417 hyperlight/Makefile
418 femtools/Makefile femtools/tests/Makefile
419 forward_interfaces/Makefile
420
421=== modified file 'diagnostics/Multiphase_Diagnostics.F90'
422--- diagnostics/Multiphase_Diagnostics.F90 2011-10-24 02:20:27 +0000
423+++ diagnostics/Multiphase_Diagnostics.F90 2013-12-12 22:35:40 +0000
424@@ -56,7 +56,10 @@
425 type(scalar_field), intent(inout) :: s_field ! Particle Reynolds number field
426
427 !! Sub-options of the diagnostic field
428- real :: d ! Particle diameter
429+ real :: dia ! Particle diameter
430+ character(len = OPTION_PATH_LEN) :: pd_field_name !name of scalar field that defines particle diameter (can be the sauter mean dia)
431+ type(scalar_field), pointer :: pd_scalar_field ! scalar field referring to particle diameter
432+ logical :: have_constant_pd ! checks if the particle diameter is a constant or not
433 character(len = OPTION_PATH_LEN) :: continuous_phase_name
434
435 !! Other local variables
436@@ -78,6 +81,7 @@
437 real, dimension(mesh_dim(s_field), ele_ngi(s_field, 1)) :: u_continuous_gi, u_particle_gi
438 real, dimension(mesh_dim(s_field), mesh_dim(s_field), ele_ngi(s_field, 1)) :: viscosity_gi
439 real, dimension(ele_ngi(s_field, 1)) :: density_gi, vfrac_gi
440+ real, dimension(ele_ngi(s_field, 1)) :: d_gi ! particle diameter at the Gauss points
441
442 real, dimension(:), allocatable :: magnitude ! |v_f - v_p|
443
444@@ -93,7 +97,14 @@
445 ewrite(1,*) 'Entering calculate_particle_reynolds_number'
446
447 ! Get sub-options from under the diagnostic field in the options tree
448- call get_option(trim(s_field%option_path)//'/diagnostic/algorithm::particle_reynolds_number/particle_diameter', d)
449+ if(have_option(trim(s_field%option_path)//'/diagnostic/algorithm::particle_reynolds_number/particle_diameter/constant')) then
450+ call get_option(trim(s_field%option_path)//'/diagnostic/algorithm::particle_reynolds_number/particle_diameter/constant', dia)
451+ have_constant_pd = .true.
452+ else if(have_option(trim(s_field%option_path)//'/diagnostic/algorithm::particle_reynolds_number/particle_diameter/use_scalar_field')) then
453+ call get_option(trim(s_field%option_path)//'/diagnostic/algorithm::particle_reynolds_number/particle_diameter/use_scalar_field', pd_field_name)
454+ pd_scalar_field => extract_scalar_field(states(state_index), pd_field_name)
455+ have_constant_pd = .false.
456+ end if
457 call get_option(trim(s_field%option_path)//'/diagnostic/algorithm::particle_reynolds_number/continuous_phase_name', continuous_phase_name)
458
459 ! Find the index of the continuous phase in states
460@@ -130,13 +141,20 @@
461 density_gi = ele_val_at_quad(density, ele)
462 vfrac_gi = ele_val_at_quad(vfrac, ele)
463
464+ ! Compute the particle diameter at the Gauss points
465+ if(have_constant_pd) then
466+ d_gi = dia
467+ else
468+ d_gi = ele_val_at_quad(pd_scalar_field, ele)
469+ end if
470+
471 do gi = 1, ele_ngi(u_continuous, ele)
472 magnitude(gi) = norm2(u_continuous_gi(:,gi) - u_particle_gi(:,gi))
473 end do
474
475 ! Compute the particle Reynolds number
476 ! (Assumes isotropic viscosity for now)
477- particle_re_gi = (vfrac_gi*density_gi*magnitude*d) / viscosity_gi(1,1,:)
478+ particle_re_gi = (vfrac_gi*density_gi*magnitude*d_gi) / viscosity_gi(1,1,:)
479
480 ! Invert the mass matrix to get the particle_re value at each node
481 particle_re_mat = matmul(inverse(shape_shape(particle_re_shape, particle_re_shape, detwei)), &
482
483=== modified file 'examples/tephra_settling/tephra_settling.flml'
484--- examples/tephra_settling/tephra_settling.flml 2013-05-30 11:47:42 +0000
485+++ examples/tephra_settling/tephra_settling.flml 2013-12-12 22:35:40 +0000
486@@ -584,7 +584,9 @@
487 </scalar_field>
488 <multiphase_properties>
489 <particle_diameter>
490- <real_value rank="0">48e-6</real_value>
491+ <constant>
492+ <real_value rank="0">48e-6</real_value>
493+ </constant>
494 </particle_diameter>
495 </multiphase_properties>
496 </material_phase>
497
498=== modified file 'main/Fluids.F90'
499--- main/Fluids.F90 2013-10-07 16:23:35 +0000
500+++ main/Fluids.F90 2013-12-12 22:35:40 +0000
501@@ -103,6 +103,7 @@
502 use detector_parallel, only: sync_detector_coordinates, deallocate_detector_list_array
503 use momentum_diagnostic_fields, only: calculate_densities
504 use sediment_diagnostics, only: calculate_sediment_flux
505+ use DQMOM
506
507 implicit none
508
509@@ -248,13 +249,16 @@
510 & default=1)
511 call get_option("/timestepping/nonlinear_iterations/tolerance", &
512 & nonlinear_iteration_tolerance, default=0.0)
513-
514+
515 if(have_option("/mesh_adaptivity/hr_adaptivity/adapt_at_first_timestep")) then
516
517 if(have_option("/timestepping/nonlinear_iterations/nonlinear_iterations_at_adapt")) then
518 call get_option('/timestepping/nonlinear_iterations/nonlinear_iterations_at_adapt',nonlinear_iterations_adapt)
519 nonlinear_iterations = nonlinear_iterations_adapt
520 end if
521+
522+ ! set population balance initial conditions - for first adaptivity
523+ call dqmom_init(state)
524
525 call adapt_state_first_timestep(state)
526
527@@ -299,6 +303,9 @@
528 call populate_sub_state(state,sub_state)
529 end if
530
531+ ! set population balance initial conditions
532+ call dqmom_init(state)
533+
534 ! Calculate the number of scalar fields to solve for and their correct
535 ! solve order taking into account dependencies.
536 call get_ntsol(ntsol)
537@@ -571,6 +578,9 @@
538
539 call compute_goals(state)
540
541+ ! Calculate source terms for populations ------
542+ call dqmom_calculate_source_terms(state, ITS)
543+
544 !------------------------------------------------
545 ! Addition for calculating drag force ------ jem 05-06-2008
546 if (have_option("/imported_solids/calculate_drag_on_surface")) then
547@@ -750,6 +760,7 @@
548 end if
549 end do
550
551+
552 ! This is where the non-legacy momentum stuff happens
553 ! a loop over state (hence over phases) is incorporated into this subroutine call
554 ! hence this lives outside the phase_loop
555@@ -762,6 +773,14 @@
556 call solve_momentum(state,at_first_timestep=((timestep==1).and.(its==1)),timestep=timestep, POD_state=POD_state)
557 end if
558
559+ ! calculate abscissa for populations -----
560+ ! this must be done at the end of each non-linear iteration
561+ call dqmom_calculate_abscissa(state)
562+ do i = 1, size(state)
563+ call dqmom_calculate_moments(state(i))
564+ call dqmom_calculate_statistics(state(i))
565+ end do
566+
567 if(nonlinear_iterations > 1) then
568 ! Check for convergence between non linear iteration loops
569 call test_and_write_convergence(state, current_time + dt, dt, its, change)
570
571=== added directory 'population_balance'
572=== added file 'population_balance/DQMOM.F90'
573--- population_balance/DQMOM.F90 1970-01-01 00:00:00 +0000
574+++ population_balance/DQMOM.F90 2013-12-12 22:35:40 +0000
575@@ -0,0 +1,999 @@
576+! Copyright (C) 2006 Imperial College London and others.
577+!
578+! Please see the AUTHORS file in the main source directory for a full list
579+! of copyright holders.
580+!
581+! Prof. C Pain
582+! Applied Modelling and Computation Group
583+! Department of Earth Science and Engineering
584+! Imperial College London
585+!
586+! amcgsoftware@imperial.ac.uk
587+!
588+! This library is free software; you can redistribute it and/or
589+! modify it under the terms of the GNU Lesser General Public
590+! License as published by the Free Software Foundation,
591+! version 2.1 of the License.
592+!
593+! This library is distributed in the hope that it will be useful,
594+! but WITHOUT ANY WARRANTY; without even the implied arranty of
595+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
596+! Lesser General Public License for more details.
597+!
598+! You should have received a copy of the GNU Lesser General Public
599+! License along with this library; if not, write to the Free Software
600+! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
601+! USA
602+
603+#include "fdebug.h"
604+
605+module dqmom
606+
607+ use vector_tools
608+ use spud
609+ use fields
610+ use state_module
611+ use state_fields_module
612+ use initialise_fields_module
613+ use global_parameters, only: OPTION_PATH_LEN, FIELD_NAME_LEN
614+! use sparsity_patterns_meshes
615+ use sparse_tools
616+ use solvers
617+
618+ implicit none
619+
620+ public dqmom_init, dqmom_calculate_source_terms, dqmom_calculate_abscissa,&
621+ & dqmom_check_options, dqmom_calculate_moments, dqmom_calculate_statistics
622+
623+ private
624+
625+ !! TODO:
626+ !! 1. Make field_finding algorithm work for multiple phases and make sure it works for
627+ !! several pop_balances
628+ !! 3. Make check_options run
629+ !! 4. Check all prognostic fields are identical (possible bar initial conditions)
630+ !! 5. Check prognostic Source terms are set to diagnostic, Internal
631+ !! 6. Minimum weight
632+ !! 7. Check diagnostic fields are set to Internal
633+ !! 8. Entire set up of fields is a horrible hack - could do with sorting out - suggest
634+ !! new blueprint for how this could work - will only work for one pop_balance per phase. IMPORTANT
635+ !! 9. Make changes to function dqmom_calculate_abscissa so that it works for a state insteaad of all states.
636+ !! Make necessary changes to the place this is called in the code.
637+ !! 10.In Fluids.F90 use conditions on presence of population balance tree and call the functions inside the if condition.
638+ !! Loop on states inside Fluids.F90 (or any other file where DQMOM functions are called) instead of doing it inside DQMOM functions.
639+
640+ !! Changes made by gb812
641+ !! 1. in 'Construct C matrix (rhs pt. 2)' -> took grad_D out or squared term
642+ !! 2. in 'Construct C matrix (rhs pt. 2)' -> while summing grad_D in the next line, changed from sum(grad_D) to sum(grad_D,1)
643+contains
644+
645+ subroutine get_pop_field(state, i_pop, i_field, type, item, stat, iterated)
646+
647+ ! Returns the required population balance field
648+
649+ type(state_type), intent(in) :: state
650+ integer, intent(in) :: i_pop, i_field
651+ character(len=FIELD_NAME_LEN) :: type ! moments, weights, ascissa, or weighted_abscissa
652+ type(scalar_field), pointer, intent(out) :: item
653+ integer, intent(out), optional :: stat
654+ logical, intent(in), optional :: iterated
655+
656+ character(len=FIELD_NAME_LEN) :: name
657+ character(len=OPTION_PATH_LEN) :: option_path
658+
659+ call get_pop_option_path(state, i_pop, option_path)
660+ call get_option(trim(option_path)//'/'//trim(type)//'/scalar_field['//int2str(i_field -&
661+ 1)//']/name', name)
662+ if (present(iterated)) then
663+ if (iterated) then
664+ name = 'Iterated'//trim(name)
665+ end if
666+ end if
667+ item => extract_scalar_field(state, trim(name), stat)
668+
669+ end subroutine get_pop_field
670+
671+ subroutine get_pop_option_path(state, i_pop, option_path)
672+
673+ type(state_type), intent(in) :: state
674+ integer, intent(in) :: i_pop
675+ character(len=OPTION_PATH_LEN), intent(out) :: option_path
676+
677+ option_path = trim(state%option_path)//'/population_balance'
678+ if (option_count(option_path) > 1) then
679+ option_path = trim(state%option_path)//'/population_balance['&
680+ &//int2str(i_pop)//']'
681+ end if
682+
683+ end subroutine get_pop_option_path
684+
685+ subroutine dqmom_init(states)
686+
687+ type(state_type), intent(in), dimension(:) :: states
688+
689+ integer :: i_state, i_pop
690+ character(len=OPTION_PATH_LEN) :: option_path
691+
692+ do i_state = 1, option_count("/material_phase")
693+ do i_pop = 1, option_count(trim(states(i_state)%option_path)//&
694+ '/population_balance')
695+ call get_pop_option_path(states(i_state), i_pop, option_path)
696+ if (have_option(trim(option_path)// &
697+ '/calculate_initial_conditions_from_moments')) then
698+ call dqmom_PD_algorithm(states(i_state), i_pop)
699+ end if
700+ end do
701+ end do
702+
703+ call dqmom_calculate_abscissa(states)
704+
705+ end subroutine dqmom_init
706+
707+ subroutine dqmom_PD_algorithm(state, i_pop)
708+
709+ ! Algorithm for calculating abscissa and weights from the moment of a distribution
710+ ! See Gordon 1968 and Mcgraw 1997
711+
712+ type(state_type), intent(in) :: state
713+ integer, intent(in) :: i_pop
714+
715+ type(scalar_field_pointer), dimension(:), allocatable :: moments
716+ type(scalar_field_pointer), dimension(:), allocatable :: weighted_abscissa
717+ type(scalar_field_pointer), dimension(:), allocatable :: weights
718+ type(vector_field), pointer:: position
719+
720+ ! J - Jacobi matrix
721+ ! P and alpha are required working arrays
722+ ! e_values - eigenvalues
723+ ! e_vectors - corresponding eigenvectors
724+ real, dimension(:,:), allocatable :: P, Jac, e_vectors
725+ real, dimension(:), allocatable :: alpha, e_values
726+ character(len=OPTION_PATH_LEN) :: option_path
727+ character(len=FIELD_NAME_LEN) :: type
728+ integer :: i_field, n_abscissa, i_node, i, j, stat
729+
730+ call get_pop_option_path(state, i_pop, option_path)
731+ n_abscissa = option_count(trim(option_path)//'/abscissa/scalar_field')
732+
733+ allocate(moments(2*n_abscissa))
734+ allocate(weighted_abscissa(n_abscissa))
735+ allocate(weights(n_abscissa))
736+ allocate(P(2*n_abscissa + 1,2*n_abscissa + 1))
737+ allocate(Jac(n_abscissa,n_abscissa))
738+ allocate(alpha(2*n_abscissa))
739+ allocate(e_vectors(n_abscissa,n_abscissa))
740+ allocate(e_values(n_abscissa))
741+
742+ position => extract_vector_field(state, "Coordinate")
743+ do i_field = 1, 2*n_abscissa
744+ ! collect moment fields and initialise from initial conditions
745+ ! will not be done automatically as this is a diagnostic field
746+ type = 'moments'
747+ call get_pop_field(state, i_pop, i_field, type, moments(i_field)%ptr)
748+ call zero(moments(i_field)%ptr)
749+ call initialise_field_over_regions(moments(i_field)%ptr, &
750+ trim(moments(i_field)%ptr%option_path)//'/diagnostic/initial_condition', position)
751+ end do
752+
753+ do i_field = 1, n_abscissa
754+ ! collect weighted_abscissa and weight fields and zero
755+ type = 'weights'
756+ call get_pop_field(state, i_pop, i_field, type, weights(i_field)%ptr)
757+ type = 'weighted_abscissa'
758+ call get_pop_field(state, i_pop, i_field, type, &
759+ weighted_abscissa(i_field)%ptr)
760+ call zero(weights(i_field)%ptr)
761+ call zero(weighted_abscissa(i_field)%ptr)
762+ end do
763+
764+ do i_node = 1, node_count(moments(1)%ptr)
765+ ! zero working arrays
766+ P = 0.0
767+ Jac = 0.0
768+ alpha = 0.0
769+ e_vectors = 0.0
770+ e_values = 0.0
771+
772+ ! Construct P matrix
773+ P(1,1) = 1.0
774+ ! set the zero'th moment to 1.0 for the purposes of finding the abscissa
775+ ! weights will be multiplied by the zero'th moment later to obtain their correct
776+ ! values
777+ P(1,2) = 1.0
778+ do i = 2, 2*n_abscissa
779+ P(i,2) = (-1)**(i-1)*(node_val(moments(i)%ptr, i_node)/node_val(moments(1)%ptr, i_node))
780+ end do
781+ do j = 3, 2*n_abscissa + 1
782+ do i = 1, (2*n_abscissa + 1) - (j - 1)
783+ P(i,j) = P(1,j-1)*P(i+1,j-2) - P(1,j-2)*P(i+1,j-1)
784+ end do
785+ end do
786+ ! Construct alpha array
787+ alpha(1) = 0.0
788+ do i = 2, 2*n_abscissa
789+ alpha(i) = P(1,i+1)/(P(1,i)*P(1,i-1))
790+ end do
791+ ! Construct jacobi matrix
792+ do i = 1, n_abscissa
793+ Jac(i,i) = alpha(2*i) + alpha(2*i - 1)
794+ end do
795+ do i = 1, n_abscissa - 1
796+ Jac(i, i+1) = ((alpha(2*i + 1)*alpha(2*i))**2.0)**0.25
797+ Jac(i+1, i) = ((alpha(2*i + 1)*alpha(2*i))**2.0)**0.25
798+ end do
799+
800+ ! Calculate eigenvalues and eigenvectors
801+ call eigendecomposition_symmetric(Jac, e_vectors, e_values, stat)
802+ if (stat /= 0) then
803+ FLExit('Cannot compute abscissa and weights using PD algorithm')
804+ end if
805+
806+ do i_field = 1, n_abscissa
807+ ! set prognostic field values
808+ call set(weights(i_field)%ptr, i_node, &
809+ node_val(moments(1)%ptr, i_node) * e_vectors(1,i_field)**2)
810+ call set(weighted_abscissa(i_field)%ptr, i_node, &
811+ node_val(weights(i_field)%ptr, i_node) * e_values(i_field))
812+ end do
813+
814+ end do
815+
816+ deallocate(moments, weighted_abscissa, weights, P, Jac, alpha, e_vectors, e_values)
817+
818+ end subroutine dqmom_PD_algorithm
819+
820+ subroutine dqmom_calculate_abscissa(states)
821+
822+ type(state_type), dimension(:), intent(in) :: states
823+
824+ type(scalar_field), pointer :: abscissa, weight, weighted_abscissa
825+ type(scalar_field) :: inv_weight
826+ integer :: i_state, i_pop, i_abscissa
827+ character(len=OPTION_PATH_LEN) :: option_path
828+ character(len=FIELD_NAME_LEN) :: type
829+
830+ ewrite(1, *) "In dqmom_calculate_abscissa"
831+ do i_state = 1, option_count("/material_phase")
832+ do i_pop = 1, option_count(trim(states(i_state)%option_path)//'/population_balance')
833+ call get_pop_option_path(states(i_state), i_pop, option_path)
834+ do i_abscissa = 1, option_count(trim(option_path)//'/abscissa/scalar_field')
835+ ! get required fields
836+ type = 'abscissa'
837+ call get_pop_field(states(i_state), i_pop, i_abscissa, type, abscissa)
838+ type = 'weights'
839+ call get_pop_field(states(i_state), i_pop, i_abscissa, type, weight)
840+ type = 'weighted_abscissa'
841+ call get_pop_field(states(i_state), i_pop, i_abscissa, type, weighted_abscissa)
842+
843+ ! calculate the inverse of the weights
844+ call allocate(inv_weight, weight%mesh, 'InverseWeight')
845+ call set(inv_weight, weight)
846+ where (inv_weight%val/=0.0)
847+ inv_weight%val=1./inv_weight%val
848+ end where
849+
850+ ! calculate abscissa
851+ call set(abscissa, weighted_abscissa)
852+ call scale(abscissa, inv_weight)
853+
854+ call deallocate(inv_weight)
855+ end do
856+ end do
857+ end do
858+ ewrite(1, *) "Exiting dqmom_calculate_abscissa"
859+ end subroutine dqmom_calculate_abscissa
860+
861+ subroutine dqmom_calculate_source_terms(states, it)
862+
863+ type(state_type), dimension(:), intent(inout) :: states
864+ integer, intent(in) :: it
865+
866+ integer :: i_state, i_pop
867+
868+ do i_state = 1, option_count("/material_phase")
869+ do i_pop = 1, option_count(trim(states(i_state)%option_path)//'/population_balance')
870+ call dqmom_calculate_source_term_pop(states(i_state), it, i_pop)
871+ end do
872+ end do
873+
874+ end subroutine dqmom_calculate_source_terms
875+
876+ subroutine dqmom_calculate_source_term_pop(state, it, i_pop)
877+
878+ type(state_type), intent(inout) :: state
879+ integer, intent(in) :: it
880+
881+ type(scalar_field_pointer), dimension(:), allocatable :: abscissa,&
882+ weight, it_abscissa, it_weight, s_weighted_abscissa, s_weight
883+ type(scalar_field), pointer :: lumped_mass
884+ type(csr_matrix), pointer :: mass_matrix
885+ type(scalar_field), dimension(:), allocatable :: r_abscissa, r_weight
886+ type(tensor_field), pointer :: D
887+ type(vector_field), pointer :: X
888+ real :: theta, cond, growth_r, internal_dispersion_coeff, aggregation_freq_const, breakage_freq_const, breakage_freq_degree, perturb_val
889+ integer :: i_pop, N, i, j, stat
890+ character(len=OPTION_PATH_LEN) :: option_path
891+ character(len=FIELD_NAME_LEN) :: type, field_name, growth_type, aggregation_freq_type, breakage_freq_type, breakage_dist_type, singular_option
892+ logical :: have_D = .false.
893+ logical :: have_growth = .FALSE.
894+ logical :: have_internal_dispersion = .FALSE.
895+ logical :: have_aggregation = .FALSE.
896+ logical :: have_breakage = .FALSE.
897+
898+ call get_pop_option_path(state, i_pop, option_path)
899+ N = option_count(trim(option_path)//'/abscissa/scalar_field')
900+ allocate(abscissa(N), weight(N), it_abscissa(N), it_weight(N), &
901+ r_abscissa(N), r_weight(N), s_weighted_abscissa(N), s_weight(N))
902+
903+ do i = 1, N
904+ ! collect abscissa and weight fields
905+ type = 'weights'
906+ call get_pop_field(state, i_pop, i, type, weight(i)%ptr)
907+ call get_pop_field(state, i_pop, i, type, it_weight(i)%ptr, iterated=.true.)
908+ type = 'abscissa'
909+ call get_pop_field(state, i_pop, i, type, abscissa(i)%ptr)
910+ call get_pop_field(state, i_pop, i, type, it_abscissa(i)%ptr, iterated=.true.)
911+
912+ ! get source fields (note this is the weighted abscissa source not the abscissa source)
913+ s_weight(i)%ptr => extract_scalar_field(state, trim(weight(i)%ptr%name)//'Source')
914+ call get_option(trim(option_path)//'/weighted_abscissa/scalar_field['// &
915+ int2str(i - 1)//']/name', field_name)
916+ s_weighted_abscissa(i)%ptr => extract_scalar_field(state, trim(field_name)//'Source')
917+ call zero(s_weight(i)%ptr)
918+ call zero(s_weighted_abscissa(i)%ptr)
919+
920+ ! relax non-linear values
921+ ! all temporal relaxations must be the same
922+ call get_option(trim(weight(i)%ptr%option_path)// &
923+ '/prognostic/temporal_discretisation/theta', theta)
924+ ! do not recalculate source terms if theta = 0.0 after first non-linear iteration
925+ if ((theta == 0.0) .and. (it /= 1)) then
926+ return
927+ end if
928+ call allocate(r_abscissa(i), abscissa(i)%ptr%mesh, &
929+ "RelaxedAbscissa"//int2str(i))
930+ call allocate(r_weight(i), weight(i)%ptr%mesh, "RelaxedWeight"//int2str(i))
931+ call set(r_abscissa(i), it_abscissa(i)%ptr)
932+ call scale(r_abscissa(i), theta)
933+ call addto(r_abscissa(i), abscissa(i)%ptr, 1.0-theta)
934+ call set(r_weight(i), it_weight(i)%ptr)
935+ call scale(r_weight(i), theta)
936+ call addto(r_weight(i), weight(i)%ptr, 1.0-theta)
937+ end do
938+
939+ ! get diffusion
940+ D => extract_tensor_field(state, trim(weight(1)%ptr%name)//'Diffusivity',stat)
941+ if (stat == 0) then
942+ have_D = .true.
943+ end if
944+
945+ ! check for growth term
946+ if (have_option(trim(option_path)//'/population_balance_source_terms/growth')) then
947+ have_growth = .TRUE.
948+ if (have_option(trim(option_path)//'/population_balance_source_terms/growth/power_law_growth')) then
949+ growth_type = 'power_law_growth';
950+ call get_option(trim(option_path)//'/population_balance_source_terms/growth/power_law_growth', growth_r)
951+ end if
952+ else
953+ have_growth = .FALSE.
954+ end if
955+
956+ ! check for internal dispersion term
957+ if (have_option(trim(option_path)//'/population_balance_source_terms/internal_dispersion')) then
958+ have_internal_dispersion = .TRUE.
959+ call get_option(trim(option_path)//'/population_balance_source_terms/internal_dispersion', internal_dispersion_coeff)
960+ else
961+ have_internal_dispersion = .FALSE.
962+ end if
963+
964+ ! check for aggregation term
965+ if (have_option(trim(option_path)//'/population_balance_source_terms/aggregation')) then
966+ have_aggregation = .TRUE.
967+ if (have_option(trim(option_path)//'/population_balance_source_terms/aggregation/aggregation_frequency/constant_aggregation')) then
968+ aggregation_freq_type = 'constant_aggregation'
969+ call get_option(trim(option_path)//'/population_balance_source_terms/aggregation/aggregation_frequency/constant_aggregation', aggregation_freq_const)
970+ else if (have_option(trim(option_path)//'/population_balance_source_terms/aggregation/aggregation_frequency/hydrodynamic_aggregation')) then
971+ aggregation_freq_type = 'hydrodynamic_aggregation'
972+ else if (have_option(trim(option_path)//'/population_balance_source_terms/aggregation/aggregation_frequency/sum_aggregation')) then
973+ aggregation_freq_type = 'sum_aggregation'
974+ call get_option(trim(option_path)//'/population_balance_source_terms/aggregation/aggregation_frequency/sum_aggregation', aggregation_freq_const)
975+ end if
976+ else
977+ have_aggregation = .FALSE.
978+ end if
979+
980+ ! check for breakage term
981+ if (have_option(trim(option_path)//'/population_balance_source_terms/breakage')) then
982+ have_breakage = .TRUE.
983+ if (have_option(trim(option_path)//'/population_balance_source_terms/breakage/breakage_frequency/constant_breakage')) then
984+ breakage_freq_type = 'constant_breakage'
985+ call get_option(trim(option_path)//'/population_balance_source_terms/breakage/breakage_frequency/constant_breakage', breakage_freq_const)
986+ else if (have_option(trim(option_path)//'/population_balance_source_terms/breakage/breakage_frequency/power_law_breakage')) then
987+ breakage_freq_type = 'power_law_breakage'
988+ call get_option(trim(option_path)//'/population_balance_source_terms/breakage/breakage_frequency/power_law_breakage/coefficient', breakage_freq_const)
989+ call get_option(trim(option_path)//'/population_balance_source_terms/breakage/breakage_frequency/power_law_breakage/degree', breakage_freq_degree)
990+ end if
991+
992+ if (have_option(trim(option_path)//'/population_balance_source_terms/breakage/distribution_function/symmetric_fragmentation')) then
993+ breakage_dist_type = 'symmetric_fragmentation'
994+ else if (have_option(trim(option_path)//'/population_balance_source_terms/breakage/distribution_function/mcCoy_madras_2003')) then
995+ breakage_dist_type = 'mcCoy_madras_2003'
996+ end if
997+
998+ else
999+ have_breakage = .FALSE.
1000+ end if
1001+
1002+ ! get ill-conditioned matrix settings
1003+ call get_option(trim(option_path)//'/ill_conditioned_matrices/required_condition_number', cond)
1004+ if (have_option(trim(option_path)//'/ill_conditioned_matrices/set_source_to_zero')) then
1005+ singular_option = 'set_source_to_zero';
1006+ else if (have_option(trim(option_path)//'/ill_conditioned_matrices/perturbate')) then
1007+ singular_option = 'perturbate';
1008+ call get_option(trim(option_path)//'/ill_conditioned_matrices/perturbate/perturbation', perturb_val)
1009+! else if (have_option(trim(option_path)//'/ill_conditioned_matrices/average_surrounding_nodes')) then
1010+! singular_option = 'average_surrounding_nodes';
1011+ end if
1012+
1013+ X => extract_vector_field(state, 'Coordinate')
1014+ ! assembly loop
1015+ do i = 1, ele_count(r_abscissa(1))
1016+ call dqmom_calculate_source_term_ele(r_abscissa, r_weight, s_weighted_abscissa, s_weight, &
1017+ &D, have_D, have_growth, growth_type, growth_r, have_internal_dispersion, internal_dispersion_coeff, &
1018+ &have_aggregation, aggregation_freq_type, aggregation_freq_const, &
1019+ &have_breakage, breakage_freq_type, breakage_freq_const, breakage_freq_degree, breakage_dist_type, X, singular_option, perturb_val, cond, i)
1020+ end do
1021+
1022+ ! for non-DG we apply inverse mass globally
1023+ if(continuity(r_abscissa(1))>=0) then
1024+ if(have_option(trim(option_path)//'/adv_diff_source_term_interpolation/use_full_mass_matrix')) then
1025+ mass_matrix => get_mass_matrix(state, r_abscissa(1)%mesh)
1026+ ! r_abscissa(1) is used as a dummy scalar field here since it is not needed anymore.
1027+ do j = 1, N
1028+ call zero(r_abscissa(1))
1029+ call petsc_solve(r_abscissa(1), mass_matrix, s_weight(j)%ptr, trim(option_path)//'/adv_diff_source_term_interpolation/use_full_mass_matrix')
1030+ call set(s_weight(j)%ptr, r_abscissa(1))
1031+ call zero(r_abscissa(1))
1032+ call petsc_solve(r_abscissa(1), mass_matrix, s_weighted_abscissa(j)%ptr, trim(option_path)//'/adv_diff_source_term_interpolation/use_full_mass_matrix')
1033+ call set(s_weighted_abscissa(j)%ptr, r_abscissa(1))
1034+ end do
1035+ else if(have_option(trim(option_path)//'/adv_diff_source_term_interpolation/use_mass_lumping')) then
1036+ lumped_mass => get_lumped_mass(state, r_abscissa(1)%mesh)
1037+ do j = 1, N
1038+ do i = 1, node_count(r_abscissa(1))
1039+ call set(s_weighted_abscissa(j)%ptr, i, node_val(s_weighted_abscissa(j)%ptr,i)&
1040+ &/node_val(lumped_mass,i))
1041+ call set(s_weight(j)%ptr, i, node_val(s_weight(j)%ptr,i)&
1042+ &/node_val(lumped_mass,i))
1043+ end do
1044+ end do
1045+ else
1046+ FLAbort("Check the .flml file. You must specify an option under 'population_balance/adv_diff_source_term_interpolation'")
1047+ end if
1048+ end if
1049+
1050+ do i = 1, N
1051+ call deallocate(r_abscissa(i))
1052+ call deallocate(r_weight(i))
1053+ end do
1054+ deallocate(abscissa, weight, it_abscissa, it_weight, &
1055+ r_abscissa, r_weight)
1056+
1057+ end subroutine dqmom_calculate_source_term_pop
1058+
1059+ subroutine dqmom_calculate_source_term_ele(abscissa, weight, s_weighted_abscissa, s_weight, &
1060+ &D, have_D, have_growth, growth_type, growth_r, have_internal_dispersion, internal_dispersion_coeff, &
1061+ &have_aggregation, aggregation_freq_type, aggregation_freq_const, &
1062+ &have_breakage, breakage_freq_type, breakage_freq_const, breakage_freq_degree, breakage_dist_type, X, singular_option, perturb_val, cond, ele)
1063+
1064+ type(scalar_field), dimension(:), intent(in) :: abscissa, weight
1065+ type(scalar_field_pointer), dimension(:), intent(inout) :: s_weighted_abscissa, s_weight
1066+ type(tensor_field), pointer, intent(in) :: D
1067+ type(vector_field), pointer, intent(in) :: X
1068+ integer, intent(in) :: ele
1069+ real, intent(in) :: cond, growth_r, internal_dispersion_coeff, aggregation_freq_const, breakage_freq_const, breakage_freq_degree, perturb_val
1070+ logical, intent(in) :: have_D, have_growth, have_internal_dispersion, have_aggregation, have_breakage
1071+ character(len=FIELD_NAME_LEN), intent(in) :: growth_type, aggregation_freq_type, breakage_freq_type, breakage_dist_type, singular_option
1072+
1073+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)) :: abscissa_val_at_quad
1074+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)*2, size(abscissa)*2) :: A
1075+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)*2, size(abscissa)) :: A_3
1076+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)) :: C
1077+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)*2) :: S_rhs ! source term (includes growth, breakage and coalescence term): gb 15-11-2012
1078+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)*2, size(abscissa)) :: moment_daughter_dist_func
1079+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)) :: break_freq
1080+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa), size(abscissa)) :: aggregation_freq ! at present it is not dependent on space coordinate, but can be dependent and will have to be a scalar fields
1081+ real, dimension(size(abscissa)*2, 1) :: b
1082+ real, dimension(ele_ngi(abscissa(1), ele), size(abscissa)) :: abscissa_S_at_quad
1083+ real, dimension(ele_ngi(abscissa(1), ele), size(weight)) :: weight_S_at_quad
1084+ real, dimension(ele_loc(abscissa(1), ele)) :: abscissa_S_at_nodes
1085+ real, dimension(ele_loc(abscissa(1), ele)) :: weight_S_at_nodes
1086+ real, dimension(ele_loc(abscissa(1), ele), ele_loc(abscissa(1), ele)) :: invmass
1087+ real, dimension(ele_ngi(abscissa(1), ele)) :: detwei
1088+ real, dimension(X%dim, ele_ngi(abscissa(1), ele)) :: grad_D
1089+ real, dimension(X%dim, X%dim, ele_ngi(abscissa(1), ele)) :: D_at_quad
1090+ type(element_type), pointer :: shape
1091+ integer, dimension(:), pointer :: nodes
1092+ real, dimension(ele_loc(abscissa(1), ele), ele_ngi(abscissa(1), ele), X%dim) :: dshape
1093+ real, dimension(size(abscissa)*2, size(abscissa)*2) :: svd_tmp1, svd_tmp2
1094+ real, dimension(size(abscissa)*2) :: SV
1095+ integer :: stat, N, i, j, k
1096+ real :: curr_time
1097+ real, dimension(size(abscissa)) :: perturb
1098+ integer :: p_num
1099+ real, dimension(size(abscissa)) :: absc_init
1100+
1101+ N = size(abscissa)
1102+
1103+ nodes => ele_nodes(abscissa(1), ele)
1104+ shape => ele_shape(abscissa(1), ele)
1105+
1106+ call transform_to_physical(X, ele, shape, dshape=dshape, detwei=detwei)
1107+
1108+ ! construct A matrices (lhs knowns)
1109+ do i = 1, N
1110+ abscissa_val_at_quad(:,i) = ele_val_at_quad(abscissa(i), ele)
1111+!! print*, "abscissa = ", abscissa_val_at_quad(1,i)
1112+ end do
1113+ A = A_matrix(abscissa_val_at_quad)
1114+
1115+ ! construct A_3 matrix (rhs pt.1)
1116+ do i = 1, 2*N
1117+ do j = 1, N
1118+ A_3(:,i,j) = (i-1)*(i-2)*ele_val_at_quad(abscissa(j), ele)**(i-3)
1119+ end do
1120+ end do
1121+
1122+ ! construct C matrix (rhs pt.2)
1123+ if (have_D) then
1124+ do i = 1, N
1125+ D_at_quad = ele_val_at_quad(D, ele)
1126+ do j = 1, X%dim
1127+ grad_D(j,:) = D_at_quad(j,j,:)
1128+ end do
1129+ grad_D = ((ele_grad_at_quad(abscissa(i), ele, dshape))**2)*grad_D
1130+ C(:,i) = ele_val_at_quad(weight(i), ele)*sum(grad_D,1)
1131+ end do
1132+ else
1133+ C = 0.0
1134+ end if
1135+
1136+
1137+ !! gb nov-2012---
1138+ ! initialize dqmom source term to zero
1139+ S_rhs = 0.0
1140+
1141+ ! construct S vector (rhs pt.3) for GROWTH term
1142+ if (have_growth) then
1143+ if (growth_type=='power_law_growth') then
1144+ do i = 1, 2*N
1145+ do j = 1, N
1146+ S_rhs(:,i) = S_rhs(:,i) + (i-1)*ele_val_at_quad(weight(j), ele)*(ele_val_at_quad(abscissa(j), ele)**(i-2))*(ele_val_at_quad(abscissa(j), ele)**growth_r)
1147+ end do
1148+ end do
1149+ end if
1150+ end if
1151+
1152+ if (have_internal_dispersion) then
1153+ do i = 1, 2*N
1154+ do j = 1, N
1155+ ! S_rhs(:,i) = S_rhs(:,i) + (i-1)*(i-2)*ele_val_at_quad(weight(j), ele)*(ele_val_at_quad(abscissa(j), ele)**(i-3))*Diffusion_internal(j)
1156+ ! abscissa_val_at_quad() takes care of the perturbed abscissas
1157+ S_rhs(:,i) = S_rhs(:,i) + (i-1)*(i-2)*ele_val_at_quad(weight(j), ele)*(abscissa_val_at_quad(:,j)**(i-3))*internal_dispersion_coeff
1158+ end do
1159+ end do
1160+ end if
1161+
1162+ !!! construct S vector for BREAKAGE
1163+! do i = 1, N
1164+! break_freq(:,i) = 0.02*abscissa_val_at_quad(:,i)**3
1165+! end do
1166+
1167+ if (have_breakage) then
1168+ if (breakage_freq_type=='constant_breakage') then
1169+ break_freq = breakage_freq_const
1170+ else if (breakage_freq_type=='power_law_breakage') then
1171+ do i = 1, N
1172+ break_freq(:,i) = breakage_freq_const*abscissa_val_at_quad(:,i)**breakage_freq_degree
1173+ end do
1174+ end if
1175+
1176+ if (breakage_dist_type=='symmetric_fragmentation') then
1177+ do i = 1, 2*N
1178+ do j = 1, N
1179+ moment_daughter_dist_func(:,i,j) = (2.0**(((3-(i-1))/3.0)))*(abscissa_val_at_quad(:,j)**(i-1))
1180+! moment_daughter_dist_func(:,i,j) = (2.0**(((3-(i-1))/3.0)))*(ele_val_at_quad(abscissa(j), ele)**(i-1))
1181+ end do
1182+ end do
1183+ else if (breakage_dist_type=='mcCoy_madras_2003') then
1184+ do i = 1, 2*N
1185+ do j = 1, N
1186+ moment_daughter_dist_func(:,i,j) = (6.0/((i-1)+3.0))*(abscissa_val_at_quad(:,j)**(i-1))
1187+! moment_daughter_dist_func(:,i,j) = (6.0/((i-1)+3.0))*(ele_val_at_quad(abscissa(j), ele)**(i-1))
1188+ end do
1189+ end do
1190+ end if
1191+
1192+ do i = 1, 2*N
1193+ do j = 1, N
1194+ ! birth term due to breakage
1195+ S_rhs(:,i) = S_rhs(:,i) + break_freq(:,j)*ele_val_at_quad(weight(j), ele)*moment_daughter_dist_func(:,i,j) ! daughter distribution function already includes the factor for number of particles formed after breakage
1196+ ! death term due to breakage
1197+ S_rhs(:,i) = S_rhs(:,i) - break_freq(:,j)*ele_val_at_quad(weight(j), ele)*(abscissa_val_at_quad(:,j)**(i-1))
1198+! S_rhs(:,i) = S_rhs(:,i) - break_freq(:,j)*ele_val_at_quad(weight(j), ele)*(ele_val_at_quad(abscissa(j), ele)**(i-1))
1199+ end do
1200+ end do
1201+ endif
1202+
1203+
1204+ !!! construct S vector for AGGREGATION
1205+ if (have_aggregation) then
1206+ if (aggregation_freq_type=='constant_aggregation') then
1207+ aggregation_freq = aggregation_freq_const
1208+ else if (aggregation_freq_type=='hydrodynamic_aggregation') then
1209+ do i = 1, N
1210+ do j = 1, N
1211+ aggregation_freq(:,i,j) = abscissa_val_at_quad(:,i)**3 + abscissa_val_at_quad(:,j)**3
1212+ end do
1213+ end do
1214+ else if (aggregation_freq_type=='sum_aggregation') then
1215+ do i = 1, N
1216+ do j = 1, N
1217+ aggregation_freq(:,i,j) = (abscissa_val_at_quad(:,i) + abscissa_val_at_quad(:,j))*aggregation_freq_const
1218+ end do
1219+ end do
1220+ end if
1221+
1222+ do i = 1, 2*N
1223+ do j = 1, N
1224+ do k = 1, N
1225+ ! birth term due to aggregation
1226+ S_rhs(:,i) = S_rhs(:,i) + 0.5 * aggregation_freq(:,j,k) * ele_val_at_quad(weight(j), ele) * ele_val_at_quad(weight(k), ele) * &
1227+ ((abs(abscissa_val_at_quad(:,j)**3 + abscissa_val_at_quad(:,k)**3)**(1.0/3.0)) * &
1228+ sign(1.0,(abscissa_val_at_quad(:,j)**3 + abscissa_val_at_quad(:,k)**3)))**(i-1)
1229+! S_rhs(:,i) = S_rhs(:,i) + 0.5 * aggregation_freq(:,j,k) * ele_val_at_quad(weight(j), ele) * ele_val_at_quad(weight(k), ele) * &
1230+! &(ele_val_at_quad(abscissa(j), ele)**3 + ele_val_at_quad(abscissa(k), ele)**3)**((i-1)/3.0)
1231+ ! death term due to aggregation
1232+ S_rhs(:,i) = S_rhs(:,i) - aggregation_freq(:,j,k) * ele_val_at_quad(weight(j), ele) * ele_val_at_quad(weight(k), ele) * abscissa_val_at_quad(:,j)**(i-1)
1233+! S_rhs(:,i) = S_rhs(:,i) - aggregation_freq(:,j,k) * ele_val_at_quad(weight(j), ele)*ele_val_at_quad(weight(k), ele)*ele_val_at_quad(abscissa(j), ele)**(i-1)
1234+ end do
1235+ end do
1236+ end do
1237+ endif
1238+
1239+ !! ----------------
1240+
1241+! perturb(1) = 0.00
1242+! perturb(2) = 0.01
1243+! perturb(3) = -0.01
1244+ ! check for ill-conditioned matrices
1245+ if (singular_option=='perturbate') then
1246+ do i = 1, ele_ngi(abscissa(1), ele)
1247+ call svd(A(i,:,:), svd_tmp1, SV, svd_tmp2)
1248+ p_num=1
1249+ do while (SV(size(SV))/SV(1) < cond)
1250+ !if (SV(size(SV))/SV(1) < cond) then
1251+ print*, "SINGULAR MATRIX"
1252+ print*, "condition number=", (SV(size(SV))/SV(1))
1253+ do j = 1, N
1254+ !! perturbation coefficient should be taken from diamond options with a check for default value
1255+ call random_number(perturb(1))
1256+ perturb(1)=-1.0+2.0*perturb(1)
1257+ print*, "perturb(1)=", N, perturb(1)
1258+ abscissa_val_at_quad(i,j) = abscissa_val_at_quad(i,j)*(1.0+perturb(1)*perturb_val)
1259+ print*, "abscissa", j, " = ", abscissa_val_at_quad(i,j)
1260+ end do
1261+ A = A_matrix(abscissa_val_at_quad)
1262+ call svd(A(i,:,:), svd_tmp1, SV, svd_tmp2)
1263+ print*, "perturbed condition number=", (SV(size(SV))/SV(1))
1264+ p_num=p_num+1
1265+ print*, "p_num=", p_num
1266+! if (SV(size(SV))/SV(1) < cond) then
1267+! print*, "perturbing does not help"
1268+! end if
1269+! end if
1270+ end do
1271+ end do
1272+ else if (singular_option=='set_source_to_zero') then
1273+ do i = 1, ele_ngi(abscissa(1), ele)
1274+ call svd(A(i,:,:), svd_tmp1, SV, svd_tmp2)
1275+ if (SV(size(SV))/SV(1) < cond) then
1276+ ewrite(2,*) 'ill-conditioned matrix found', SV(size(SV))/SV(1)
1277+ A(i,:,:) = 0.0
1278+ A_3(i,:,:) = 0.0
1279+ C(i,:) = 0.0
1280+ do j = 1, 2*N
1281+ A(i,j,j) = 1.0
1282+ end do
1283+ end if
1284+ end do
1285+ end if
1286+!! p_num = 1
1287+
1288+
1289+!! do j = 1, N
1290+!! absc_init(j) = abscissa_val_at_quad(i,j)
1291+!! end do
1292+
1293+!! do while (SV(size(SV))/SV(1) < cond)
1294+! call get_option("/timestepping/current_time", curr_time) ! get the current simulation time
1295+ !! a better check for the first timestep instead of small value of the current time
1296+ ! if (curr_time < 1e-7) then ! this block perturbates the abscissas in A matrix if current time is 0
1297+!! print*, "perturbing %g \n", p_num
1298+!! do j = 1, N
1299+ !! perturbation coefficient should be taken from diamond options with a check for default value
1300+!! call random_number(perturb(1))
1301+!! abscissa_val_at_quad(i,j) = absc_init(j) + perturb(1)
1302+! abscissa_val_at_quad(:,j) = abscissa_val_at_quad(:,j) + (2-j)*(0.1)
1303+!! print*, "abscissa", j, " = ", abscissa_val_at_quad(i,j)
1304+!! end do
1305+!! A = A_matrix(abscissa_val_at_quad)
1306+!! call svd(A(i,:,:), svd_tmp1, SV, svd_tmp2)
1307+!! print*, "condition number=", (SV(size(SV))/SV(1))
1308+!! p_num = p_num+1
1309+! print*, "perturbed condition number=", (SV(size(SV))/SV(1))
1310+! if (SV(size(SV))/SV(1) < cond) then
1311+! print*, "perturbing does not help"
1312+! end if
1313+
1314+! else
1315+! ewrite(2,*) 'ill-conditioned matrix found'
1316+! A(i,:,:) = 0.0
1317+! A_3(i,:,:) = 0.0
1318+! C(i,:) = 0.0
1319+! do j = 1, 2*N
1320+! A(i,j,j) = 1.0
1321+! end do
1322+! end if
1323+! end if
1324+!! end do
1325+! end do
1326+
1327+
1328+
1329+
1330+ ! solve linear system to find source values
1331+ do i = 1, ele_ngi(abscissa(1), ele)
1332+ b(:,1) = matmul(A_3(i,:,:), C(i,:)) + S_rhs(i,:) !! gb 15-11-2012! added S_rhs term
1333+ call dqmom_solve(A(i,:,:), b, stat)
1334+ weight_S_at_quad(i,:) = b(:N,1)
1335+ abscissa_S_at_quad(i,:) = b(N+1:,1)
1336+ end do
1337+
1338+ ! In the DG case we apply the inverse mass locally.
1339+ invmass = inverse(shape_shape(shape, shape, detwei))
1340+
1341+ ! integrate and add to source fields
1342+ do i = 1, N
1343+ weight_S_at_nodes = shape_rhs(shape, detwei* weight_S_at_quad(:,i))
1344+ abscissa_S_at_nodes = shape_rhs(shape, detwei* abscissa_S_at_quad(:,i))
1345+ if(continuity(abscissa(1))<0) then
1346+ weight_S_at_nodes = matmul(weight_S_at_nodes, invmass)
1347+ abscissa_S_at_nodes = matmul(abscissa_S_at_nodes, invmass)
1348+ end if
1349+ call addto(s_weight(i)%ptr, nodes, weight_S_at_nodes)
1350+ call addto(s_weighted_abscissa(i)%ptr, nodes, abscissa_S_at_nodes)
1351+ end do
1352+
1353+ end subroutine dqmom_calculate_source_term_ele
1354+
1355+ function A_matrix(abscissa)
1356+
1357+ real, dimension(:,:), intent(in) :: abscissa
1358+
1359+ real, dimension(size(abscissa,1), size(abscissa,2)*2, size(abscissa,2)*2) :: A_matrix
1360+ integer :: i, j, N
1361+
1362+ N = size(abscissa,2)
1363+ do i = 1, 2*N
1364+ do j = 1, N
1365+ A_matrix(:,i,j) = (2-i)*abscissa(:,j)**(i-1)
1366+ A_matrix(:,i,j+N) = (i-1)*abscissa(:,j)**(i-2)
1367+ end do
1368+ end do
1369+
1370+ end function A_matrix
1371+
1372+ subroutine dqmom_solve(A, b, stat)
1373+ !!< Solve Ax=b for right hand sides b putting the result in b.
1374+ !!<
1375+ !!< This is simply a wrapper for lapack.
1376+ real, dimension(:,:), intent(in) :: A
1377+ real, dimension(:,:), intent(inout) :: b
1378+ integer, optional, intent(out) :: stat
1379+
1380+ real, dimension(size(A,1), size(A,2)) :: Atmp
1381+ integer, dimension(size(A,1)) :: ipiv
1382+ integer :: info
1383+
1384+ interface
1385+#ifdef DOUBLEP
1386+ SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
1387+ INTEGER :: INFO, LDA, LDB, N, NRHS
1388+ INTEGER :: IPIV( * )
1389+ REAL :: A( LDA, * ), B( LDB, * )
1390+ END SUBROUTINE DGESV
1391+#else
1392+ SUBROUTINE SGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
1393+ INTEGER :: INFO, LDA, LDB, N, NRHS
1394+ INTEGER :: IPIV( * )
1395+ REAL :: A( LDA, * ), B( LDB, * )
1396+ END SUBROUTINE SGESV
1397+#endif
1398+ end interface
1399+
1400+ if (present(stat)) stat = 0
1401+
1402+ Atmp=A
1403+
1404+#ifdef DOUBLEP
1405+ call dgesv(&
1406+#else
1407+ call sgesv(&
1408+#endif
1409+ size(A,1), size(b,2), Atmp, size(A,1), ipiv, b, size(b,1), info)
1410+
1411+ if (present(stat)) then
1412+ stat = info
1413+ end if
1414+
1415+ end subroutine dqmom_solve
1416+
1417+ subroutine dqmom_calculate_moments(state)
1418+
1419+ type(state_type), intent(in) :: state
1420+
1421+ type(scalar_field), pointer :: abscissa, weight, moment
1422+ type(scalar_field) :: work
1423+ integer :: i_pop, N, i_moment, i_abscissa, i
1424+ character(len=OPTION_PATH_LEN) :: option_path
1425+ character(len=FIELD_NAME_LEN) :: type
1426+
1427+ ewrite(1, *) "In dqmom_calculate_moments"
1428+ do i_pop = 1, option_count(trim(state%option_path)//'/population_balance')
1429+ call get_pop_option_path(state, i_pop, option_path)
1430+ N = option_count(trim(option_path)//'/abscissa/scalar_field')
1431+ do i_moment = 1, 2*N
1432+ type = 'moments'
1433+ call get_pop_field(state, i_pop, i_moment, type, moment)
1434+ call zero(moment)
1435+ call allocate(work, moment%mesh, 'work')
1436+ do i_abscissa = 1, N
1437+ ! get required fields
1438+ type = 'abscissa'
1439+ call get_pop_field(state, i_pop, i_abscissa, type, abscissa)
1440+ type = 'weights'
1441+ call get_pop_field(state, i_pop, i_abscissa, type, weight)
1442+
1443+ ! calculate moment -> m(i) = sum_j(w(j)*q(j)**i)
1444+ call zero(work)
1445+ call set(work, 1.0)
1446+ do i = 1, i_moment - 1
1447+ call scale(work, abscissa)
1448+ end do
1449+ call scale(work, weight)
1450+ call addto(moment, work)
1451+ end do
1452+ call deallocate(work)
1453+ end do
1454+ end do
1455+ ewrite(1, *) "Exiting dqmom_calculate_moments"
1456+ end subroutine dqmom_calculate_moments
1457+
1458+ subroutine dqmom_calculate_statistics(state)
1459+
1460+ type(state_type), intent(in) :: state
1461+
1462+ type(scalar_field_pointer), dimension(:), allocatable :: moments
1463+ type(scalar_field), pointer :: stats
1464+ integer :: i_pop, N, i, j, i_stat
1465+ real :: mean, std, scaling_factor_Dia
1466+ character(len=OPTION_PATH_LEN) :: option_path
1467+ character(len=FIELD_NAME_LEN) :: type
1468+
1469+ ewrite(1, *) "In dqmom_calculate_statistics"
1470+ do i_pop = 1, option_count(trim(state%option_path)//'/population_balance')
1471+ call get_pop_option_path(state, i_pop, option_path)
1472+
1473+ if (option_count(trim(option_path)//'/statistics/scalar_field') > 0) then
1474+
1475+ N = option_count(trim(option_path)//'/moments/scalar_field')
1476+ allocate(moments(N))
1477+ do i = 1, N
1478+ ! get required fields
1479+ type = 'moments'
1480+ call get_pop_field(state, i_pop, i, type, moments(i)%ptr)
1481+ end do
1482+
1483+ type = 'statistics'
1484+ do i_stat = 1, option_count(trim(option_path)//'/statistics/scalar_field')
1485+ call get_pop_field(state, i_pop, i_stat, type, stats)
1486+ if (trim(stats%name) == "Mean") then
1487+ call zero(stats)
1488+ do j = 1, node_count(stats)
1489+ call set(stats, j, node_val(moments(2)%ptr,j)/node_val(moments(1)%ptr,j))
1490+ end do
1491+ end if
1492+ if (trim(stats%name) == "StandardDeviation") then
1493+ call zero(stats)
1494+ do j = 1, node_count(stats)
1495+ mean = node_val(moments(2)%ptr,j)/node_val(moments(1)%ptr,j)
1496+ call set(stats, j, (node_val(moments(3)%ptr,j)/node_val(moments(1)%ptr,j) -&
1497+ mean**2)**0.5)
1498+ end do
1499+ end if
1500+ if (trim(stats%name) == "Skew") then
1501+ call zero(stats)
1502+ do j = 1, node_count(stats)
1503+ mean = node_val(moments(2)%ptr,j)/node_val(moments(1)%ptr,j)
1504+ std = (node_val(moments(3)%ptr,j)/node_val(moments(1)%ptr,j) - mean**2)**0.5
1505+ call set(stats, j, &
1506+ (node_val(moments(4)%ptr,j)/node_val(moments(1)%ptr,j) - &
1507+ 3*mean*std**2.0 - mean**3.0) / std**3.0)
1508+ end do
1509+ end if
1510+ if (trim(stats%name) == "SauterMeanDia") then
1511+ call zero(stats)
1512+ if (have_option(trim(option_path)//'/scaling_factor_Dia')) then
1513+ call get_option(trim(option_path)//'/scaling_factor_Dia', scaling_factor_Dia)
1514+ else
1515+ scaling_factor_Dia=1.0
1516+ end if
1517+ do j = 1, node_count(stats)
1518+ call set(stats, j, scaling_factor_Dia*(node_val(moments(4)%ptr,j)/node_val(moments(3)%ptr,j)) )
1519+ end do
1520+ end if
1521+ if (trim(stats%name) == "MeanDia10") then
1522+ call zero(stats)
1523+ if (have_option(trim(option_path)//'/scaling_factor_Dia')) then
1524+ call get_option(trim(option_path)//'/scaling_factor_Dia', scaling_factor_Dia)
1525+ else
1526+ scaling_factor_Dia=1.0
1527+ end if
1528+ do j = 1, node_count(stats)
1529+ call set(stats, j, scaling_factor_Dia*(node_val(moments(2)%ptr,j)/node_val(moments(1)%ptr,j)) )
1530+ end do
1531+ end if
1532+
1533+ end do
1534+
1535+ deallocate(moments)
1536+
1537+ end if
1538+ end do
1539+ ewrite(1, *) "Exiting dqmom_calculate_statistics"
1540+
1541+
1542+ end subroutine dqmom_calculate_statistics
1543+
1544+ subroutine dqmom_check_options(state)
1545+
1546+ type(state_type), intent(in) :: state
1547+
1548+ integer :: i_pop
1549+ integer :: n_abscissa, n_weights, n_weighted_abscissa, n_moments
1550+ character(len=OPTION_PATH_LEN) :: option_path
1551+
1552+ write(*,*) 'in dqmom_check_options'
1553+
1554+ do i_pop = 1, option_count(trim(state%option_path)//'/population_balance')
1555+ option_path = trim(state%option_path)//'/population_balance['//int2str(i_pop)//']'
1556+
1557+ ! Check there are the same number of abscissa, weight and weighted abscissa fields
1558+ n_abscissa = option_count(trim(option_path)//'/abscissa/scalar_field')
1559+ n_weights = option_count(trim(option_path)//'/weights/scalar_field')
1560+ n_weighted_abscissa = option_count(trim(option_path)// &
1561+ '/weighted_abscissa/scalar_field')
1562+ assert(n_weights == n_abscissa)
1563+ assert(n_weights == n_weighted_abscissa)
1564+
1565+ ! Check there are sufficient abscissa to calculate requested moments
1566+ n_moments = option_count(trim(option_path)//'/moments/scalar_field')
1567+ assert((n_moments / 2) == n_abscissa)
1568+
1569+ ! Need to check that all fields are on the same mesh
1570+ end do
1571+
1572+ end subroutine dqmom_check_options
1573+
1574+end module dqmom
1575
1576=== added file 'population_balance/Makefile.dependencies'
1577--- population_balance/Makefile.dependencies 1970-01-01 00:00:00 +0000
1578+++ population_balance/Makefile.dependencies 2013-12-12 22:35:40 +0000
1579@@ -0,0 +1,10 @@
1580+# Dependencies generated by create_makefile.py. DO NOT EDIT
1581+../include/dqmom.mod: DQMOM.o
1582+ @true
1583+
1584+DQMOM.o ../include/dqmom.mod: DQMOM.F90 ../include/fdebug.h \
1585+ ../include/fields.mod ../include/global_parameters.mod \
1586+ ../include/initialise_fields_module.mod ../include/spud.mod \
1587+ ../include/state_fields_module.mod ../include/state_module.mod \
1588+ ../include/vector_tools.mod
1589+
1590
1591=== added file 'population_balance/Makefile.in'
1592--- population_balance/Makefile.in 1970-01-01 00:00:00 +0000
1593+++ population_balance/Makefile.in 2013-12-12 22:35:40 +0000
1594@@ -0,0 +1,66 @@
1595+# Copyright (C) 2006 Imperial College London and others.
1596+#
1597+# Please see the AUTHORS file in the main source directory for a full list
1598+# of copyright holders.
1599+#
1600+# Prof. C Pain
1601+# Applied Modelling and Computation Group
1602+# Department of Earth Science and Engineering
1603+# Imperial College London
1604+#
1605+# amcgsoftware@imperial.ac.uk
1606+#
1607+# This library is free software; you can redistribute it and/or
1608+# modify it under the terms of the GNU Lesser General Public
1609+# License as published by the Free Software Foundation,
1610+# version 2.1 of the License.
1611+#
1612+# This library is distributed in the hope that it will be useful,
1613+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1614+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1615+# Lesser General Public License for more details.
1616+#
1617+# You should have received a copy of the GNU Lesser General Public
1618+# License along with this library; if not, write to the Free Software
1619+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1620+# USA
1621+SHELL = @SHELL@
1622+
1623+PACKAGE_NAME = @PACKAGE_NAME@
1624+FLUIDITY = $(PACKAGE_NAME)
1625+
1626+FC = @FC@
1627+FCFLAGS = -I../include @MOD_FLAG@../include @FCFLAGS@ -I/usr/local/include -I./
1628+
1629+CC = @CC@
1630+CFLAGS = @CFLAGS@ -I../include -I/usr/local/include
1631+
1632+CXX = @CXX@
1633+CXXFLAGS= @CXXFLAGS@ -I../include -I/usr/local/include
1634+
1635+MAKE = @MAKE@
1636+AR = @AR@
1637+ARFLAGS = @ARFLAGS@
1638+
1639+LIB = ../lib/lib$(FLUIDITY).a
1640+
1641+OBJS = DQMOM.o \
1642+
1643+.SUFFIXES: .f90 .F90 .c .o .a
1644+
1645+.f90.o:
1646+ @echo " FC $<"
1647+ $(FC) $(FCFLAGS) -c $<
1648+.F90.o:
1649+ @echo " FC $<"
1650+ $(FC) $(FCFLAGS) $(GENFLAGS) -c $<
1651+
1652+$(LIB): $(OBJS)
1653+ @mkdir -p ../lib
1654+
1655+default: $(LIB)
1656+
1657+clean:
1658+ rm -f *.o *.d *.mod
1659+
1660+include Makefile.dependencies
1661
1662=== modified file 'preprocessor/Field_Priority_Lists.F90'
1663--- preprocessor/Field_Priority_Lists.F90 2013-02-01 17:50:12 +0000
1664+++ preprocessor/Field_Priority_Lists.F90 2013-12-12 22:35:40 +0000
1665@@ -133,6 +133,37 @@
1666 end do
1667 end if
1668
1669+ ! added as hack for now - but this whole set up of fields could be way better!
1670+ ! prognostic pop balance fields - very limited applicability
1671+ if (have_option('/material_phase['//int2str(p)//']/population_balance/')) then
1672+ do f = 0, option_count('/material_phase['//int2str(p)//&
1673+ ']/population_balance/weights/scalar_field') - 1
1674+ nsol=nsol+1
1675+ temp_field_optionpath_list(nsol)='/material_phase['//int2str(p)// &
1676+ ']/population_balance/weights/scalar_field['//int2str(f)//']'
1677+ call get_option('/material_phase['//int2str(p)//&
1678+ ']/population_balance/weights/scalar_field['//int2str(f)//&
1679+ ']/name',temp_field_name_list(nsol))
1680+ call get_option('/material_phase['//int2str(p)//&
1681+ ']/population_balance/weights/scalar_field['//int2str(f)//&
1682+ ']/prognostic/priority', priority(nsol), default=0)
1683+ temp_field_state_list(nsol) = p+1
1684+ end do
1685+ do f = 0, option_count('/material_phase['//int2str(p)//&
1686+ ']/population_balance/weighted_abscissa/scalar_field') - 1
1687+ nsol=nsol+1
1688+ temp_field_optionpath_list(nsol)='/material_phase['//int2str(p)// &
1689+ ']/population_balance/weighted_abscissa/scalar_field['//int2str(f)//']'
1690+ call get_option('/material_phase['//int2str(p)//&
1691+ ']/population_balance/weighted_abscissa/scalar_field['//int2str(f)//&
1692+ ']/name',temp_field_name_list(nsol))
1693+ call get_option('/material_phase['//int2str(p)//&
1694+ ']/population_balance/weighted_abscissa/scalar_field['//int2str(f)//&
1695+ ']/prognostic/priority', priority(nsol), default=0)
1696+ temp_field_state_list(nsol) = p+1
1697+ end do
1698+ end if
1699+
1700 ! prognostic Mellor Yamada fields:
1701 if (have_option('/material_phase[' &
1702 //int2str(p)//']/subgridscale_parameterisations/Mellor_Yamada/scalar_field::KineticEnergy/prognostic')) then
1703@@ -315,6 +346,17 @@
1704 ntsol = ntsol + 1
1705 end if
1706 end do
1707+
1708+ ! added as hack for now - but this whole set up of fields could be way better!
1709+ ! prognostic pop balance fields - very limited applicability
1710+ if (have_option('/material_phase['//int2str(p)//']/population_balance/')) then
1711+ ntsol = ntsol + &
1712+ option_count('/material_phase['//int2str(p)//&
1713+ ']/population_balance/weights/scalar_field') + &
1714+ option_count('/material_phase['//int2str(p)//&
1715+ ']/population_balance/weighted_abscissa/scalar_field')
1716+ end if
1717+
1718 ! prognostic scalar fields for Mellor Yamada:
1719 if (have_option('/material_phase[' &
1720 //int2str(p)//']/subgridscale_parameterisations/Mellor_Yamada/scalar_field::KineticEnergy/prognostic')) then
1721
1722=== modified file 'preprocessor/Populate_State.F90'
1723--- preprocessor/Populate_State.F90 2013-10-28 06:46:48 +0000
1724+++ preprocessor/Populate_State.F90 2013-12-12 22:35:40 +0000
1725@@ -97,7 +97,7 @@
1726
1727 !! A list of relative paths under /material_phase[i]
1728 !! that are searched for additional fields to be added.
1729- character(len=OPTION_PATH_LEN), dimension(13) :: additional_fields_relative=&
1730+ character(len=OPTION_PATH_LEN), dimension(18) :: additional_fields_relative=&
1731 (/ &
1732 "/subgridscale_parameterisations/Mellor_Yamada ", &
1733 "/subgridscale_parameterisations/prescribed_diffusivity ", &
1734@@ -111,7 +111,12 @@
1735 "/vector_field::Velocity/prognostic/spatial_discretisation/continuous_galerkin/les_model/dynamic_les ", &
1736 "/vector_field::Velocity/prognostic/equation::ShallowWater ", &
1737 "/vector_field::Velocity/prognostic/equation::ShallowWater/bottom_drag ", &
1738- "/vector_field::BedShearStress/diagnostic/calculation_method/velocity_gradient " &
1739+ "/vector_field::BedShearStress/diagnostic/calculation_method/velocity_gradient ", &
1740+ "/population_balance[#]/abscissa/ ", &
1741+ "/population_balance[#]/weights/ ", &
1742+ "/population_balance[#]/weighted_abscissa/ ", &
1743+ "/population_balance[#]/moments/ ", &
1744+ "/population_balance[#]/statistics/ " &
1745 /)
1746
1747 !! Relative paths under a field that are searched for grandchildren
1748@@ -121,6 +126,22 @@
1749 & "/spatial_discretisation/inner_element" &
1750 /)
1751
1752+
1753+ !! Dynamic paths that are searched for fields
1754+ !! This allows for searching for field within paths that may branch several times
1755+ !! The index of any particular path should be replaced with #
1756+ character(len=OPTION_PATH_LEN), dimension(6):: &
1757+ dynamic_paths = (/&
1758+ & "/material_phase[#]/equation_of_state/fluids/linear/ ", &
1759+ & "/material_phase[#]/population_balance[#]/abscissa/ ", &
1760+ & "/material_phase[#]/population_balance[#]/weights/ ", &
1761+ & "/material_phase[#]/population_balance[#]/weighted_abscissa/", &
1762+ & "/material_phase[#]/population_balance[#]/moments/ ", &
1763+ & "/material_phase[#]/population_balance[#]/statistics/ " &
1764+ /)
1765+
1766+ character(len=OPTION_PATH_LEN), dimension(:), allocatable :: field_locations
1767+
1768 contains
1769
1770
1771
1772=== modified file 'schemas/diagnostic_algorithms.rnc'
1773--- schemas/diagnostic_algorithms.rnc 2013-02-21 15:25:41 +0000
1774+++ schemas/diagnostic_algorithms.rnc 2013-12-12 22:35:40 +0000
1775@@ -1289,7 +1289,8 @@
1776 },
1777 ## The particle diameter
1778 element particle_diameter {
1779- real
1780+ element constant { real }|
1781+ element use_scalar_field { anystring }
1782 },
1783 ## The name of the state representing the continuous phase
1784 element continuous_phase_name {
1785
1786=== modified file 'schemas/diagnostic_algorithms.rng'
1787--- schemas/diagnostic_algorithms.rng 2013-02-21 15:25:41 +0000
1788+++ schemas/diagnostic_algorithms.rng 2013-12-12 22:35:40 +0000
1789@@ -1754,7 +1754,14 @@
1790 </element>
1791 <element name="particle_diameter">
1792 <a:documentation>The particle diameter</a:documentation>
1793- <ref name="real"/>
1794+ <choice>
1795+ <element name="constant">
1796+ <ref name="real"/>
1797+ </element>
1798+ <element name="use_scalar_field">
1799+ <ref name="anystring"/>
1800+ </element>
1801+ </choice>
1802 </element>
1803 <element name="continuous_phase_name">
1804 <a:documentation>The name of the state representing the continuous phase</a:documentation>
1805
1806=== modified file 'schemas/fluidity_options.rnc'
1807--- schemas/fluidity_options.rnc 2013-10-11 10:48:07 +0000
1808+++ schemas/fluidity_options.rnc 2013-12-12 22:35:40 +0000
1809@@ -1472,6 +1472,7 @@
1810 scalar_field_choice*,
1811 vector_field_choice*,
1812 tensor_field_choice*,
1813+ population_balance*,
1814 ## Parameters required to model spontaneous electrical potentials in porous media.
1815 element electrical_properties {
1816 (
1817@@ -1613,8 +1614,9 @@
1818 ## Phase interaction options for Fluidity's multiphase flow model
1819 element multiphase_properties {
1820 comment,
1821- element particle_diameter {
1822- real
1823+ element particle_diameter {
1824+ element constant { real }|
1825+ element use_scalar_field { anystring }
1826 }?,
1827 ## If this is the fluid phase,
1828 ## the effective conductivity is required
1829@@ -1814,6 +1816,450 @@
1830 }
1831 )
1832
1833+population_balance =
1834+ (
1835+ ##
1836+ element population_balance {
1837+ (
1838+ ## Determine initial weighted_abscissa and weights using the PD algorithm and the
1839+ ## initial conditions set in the diagnostic moment fields.
1840+ ##
1841+ ## In this case it does not matter what is set in the weighted_abscissa and weights
1842+ ## fields initial conditions option
1843+ element calculate_initial_conditions_from_moments {
1844+ empty
1845+ }|
1846+ ## Use initial conditions set in the weighted_abscissa and weights prognostic
1847+ ## fields
1848+ ##
1849+ ## In this case it does not matter what is set in the moment field initial conditions
1850+ ## options
1851+ element use_prognostic_field_initial_conditions {
1852+ empty
1853+ }
1854+ ),
1855+ attribute name { xsd:string },
1856+ element abscissa {
1857+ element scalar_field {
1858+ attribute rank { "0" },
1859+ attribute name { "Abscissa_0" },
1860+ ## Field type
1861+ element diagnostic {
1862+ internal_algorithm,
1863+ velocity_mesh_choice,
1864+ diagnostic_scalar_field
1865+ }
1866+ },
1867+ element scalar_field {
1868+ attribute rank { "0" },
1869+ attribute name { "Abscissa_1" },
1870+ ## Field type
1871+ element diagnostic {
1872+ internal_algorithm,
1873+ velocity_mesh_choice,
1874+ diagnostic_scalar_field
1875+ }
1876+ },
1877+ element scalar_field {
1878+ attribute rank { "0" },
1879+ attribute name { xsd:string },
1880+ ## Field type
1881+ element diagnostic {
1882+ internal_algorithm,
1883+ velocity_mesh_choice,
1884+ diagnostic_scalar_field
1885+ }
1886+ }*
1887+ },
1888+ element weights {
1889+ element scalar_field {
1890+ attribute rank { "0" },
1891+ attribute name { "Weight_0" },
1892+ ## Field type
1893+ element prognostic {
1894+ velocity_mesh_choice,
1895+ prognostic_scalar_field
1896+ }
1897+ },
1898+ element scalar_field {
1899+ attribute rank { "0" },
1900+ attribute name { "Weight_1" },
1901+ ## Field type
1902+ element prognostic {
1903+ velocity_mesh_choice,
1904+ prognostic_scalar_field
1905+ }
1906+ },
1907+ element scalar_field {
1908+ attribute rank { "0" },
1909+ attribute name { xsd:string },
1910+ ## Field type
1911+ element prognostic {
1912+ velocity_mesh_choice,
1913+ prognostic_scalar_field
1914+ }
1915+ }*
1916+ },
1917+ element weighted_abscissa {
1918+ element scalar_field {
1919+ attribute rank { "0" },
1920+ attribute name { "WeightedAbscissa_0" },
1921+ ## Field type
1922+ element prognostic {
1923+ velocity_mesh_choice,
1924+ prognostic_scalar_field
1925+ }
1926+ },
1927+ element scalar_field {
1928+ attribute rank { "0" },
1929+ attribute name { "WeightedAbscissa_1" },
1930+ ## Field type
1931+ element prognostic {
1932+ velocity_mesh_choice,
1933+ prognostic_scalar_field
1934+ }
1935+ },
1936+ element scalar_field {
1937+ attribute rank { "0" },
1938+ attribute name { xsd:string },
1939+ ## Field type
1940+ element prognostic {
1941+ velocity_mesh_choice,
1942+ prognostic_scalar_field
1943+ }
1944+ }*
1945+ },
1946+ ## This option only works if you are using a continuous mesh for the population balance scalar fields.
1947+ ## A DG mesh will use inverse mass calculated at element level.
1948+ ## In the population balance DQMOM algorithm all sources for the
1949+ ## advection-diffusion equations are calculated at the quadrature points first
1950+ ## and then interpolated back to the nodal points.
1951+ ## For a continuous mesh, this interpolation is made by inverting the mass matrix.
1952+ ## Mass lumping is fairly quick and can be used with 1st order continuous meshes.
1953+ ## But the error is high for higher order continuous meshes and full mass matrix should be used.
1954+ element adv_diff_source_term_interpolation {
1955+ ## The mass matrix is lumped to obtain source fields at nodal points.
1956+ element use_mass_lumping { empty } |
1957+ ## Full mass marix is used and the linear system is solved iteratively to obtain source fields at nodal points.
1958+ element use_full_mass_matrix {
1959+ ## This block specifies the solver options for solving the linear system to interpolate advection-diffusion source terms at nodal points.
1960+ element solver {
1961+ linear_solver_options_asym_scalar
1962+ }
1963+ }
1964+ },
1965+ element moments {
1966+ element scalar_field {
1967+ attribute rank { "0" },
1968+ attribute name { "Moment_0" },
1969+ element diagnostic {
1970+ internal_algorithm,
1971+ velocity_mesh_choice,
1972+ (
1973+ ## Initial condition for WholeMesh
1974+ ##
1975+ ## Only specify one condition if not using mesh regions.
1976+ ## Otherwise select other initial_condition option, specify region_ids
1977+ ## and distinct names. Then add extra intial conditions for other regions.
1978+ element initial_condition {
1979+ attribute name { "WholeMesh" },
1980+ input_choice_initial_condition_real
1981+ }|
1982+ ## Multiple initial_conditions are allowed if specifying
1983+ ## different values in different
1984+ ## regions of the mesh (defined by region_ids). In this case
1985+ ## each initial_condition
1986+ ## requires a distinct name for the options dictionary.
1987+ element initial_condition {
1988+ attribute name { string },
1989+ region_ids?,
1990+ input_choice_initial_condition_real
1991+ }
1992+ )+,
1993+ diagnostic_scalar_field
1994+ }
1995+ },
1996+ element scalar_field {
1997+ attribute rank { "0" },
1998+ attribute name { "Moment_1" },
1999+ element diagnostic {
2000+ internal_algorithm,
2001+ velocity_mesh_choice,
2002+ (
2003+ ## Initial condition for WholeMesh
2004+ ##
2005+ ## Only specify one condition if not using mesh regions.
2006+ ## Otherwise select other initial_condition option, specify region_ids
2007+ ## and distinct names. Then add extra intial conditions for other regions.
2008+ element initial_condition {
2009+ attribute name { "WholeMesh" },
2010+ input_choice_initial_condition_real
2011+ }|
2012+ ## Multiple initial_conditions are allowed if specifying
2013+ ## different values in different
2014+ ## regions of the mesh (defined by region_ids). In this case
2015+ ## each initial_condition
2016+ ## requires a distinct name for the options dictionary.
2017+ element initial_condition {
2018+ attribute name { string },
2019+ region_ids?,
2020+ input_choice_initial_condition_real
2021+ }
2022+ )+,
2023+ diagnostic_scalar_field
2024+ }
2025+ },
2026+ element scalar_field {
2027+ attribute rank { "0" },
2028+ attribute name { "Moment_2" },
2029+ element diagnostic {
2030+ internal_algorithm,
2031+ velocity_mesh_choice,
2032+ (
2033+ ## Initial condition for WholeMesh
2034+ ##
2035+ ## Only specify one condition if not using mesh regions.
2036+ ## Otherwise select other initial_condition option, specify region_ids
2037+ ## and distinct names. Then add extra intial conditions for other regions.
2038+ element initial_condition {
2039+ attribute name { "WholeMesh" },
2040+ input_choice_initial_condition_real
2041+ }|
2042+ ## Multiple initial_conditions are allowed if specifying
2043+ ## different values in different
2044+ ## regions of the mesh (defined by region_ids). In this case
2045+ ## each initial_condition
2046+ ## requires a distinct name for the options dictionary.
2047+ element initial_condition {
2048+ attribute name { string },
2049+ region_ids?,
2050+ input_choice_initial_condition_real
2051+ }
2052+ )+,
2053+ diagnostic_scalar_field
2054+ }
2055+ },
2056+ element scalar_field {
2057+ attribute rank { "0" },
2058+ attribute name { "Moment_3" },
2059+ element diagnostic {
2060+ internal_algorithm,
2061+ velocity_mesh_choice,
2062+ (
2063+ ## Initial condition for WholeMesh
2064+ ##
2065+ ## Only specify one condition if not using mesh regions.
2066+ ## Otherwise select other initial_condition option, specify region_ids
2067+ ## and distinct names. Then add extra intial conditions for other regions.
2068+ element initial_condition {
2069+ attribute name { "WholeMesh" },
2070+ input_choice_initial_condition_real
2071+ }|
2072+ ## Multiple initial_conditions are allowed if specifying
2073+ ## different values in different
2074+ ## regions of the mesh (defined by region_ids). In this case
2075+ ## each initial_condition
2076+ ## requires a distinct name for the options dictionary.
2077+ element initial_condition {
2078+ attribute name { string },
2079+ region_ids?,
2080+ input_choice_initial_condition_real
2081+ }
2082+ )+,
2083+ diagnostic_scalar_field
2084+ }
2085+ },
2086+ element scalar_field {
2087+ attribute rank { "0" },
2088+ attribute name { xsd:string },
2089+ element diagnostic {
2090+ internal_algorithm,
2091+ velocity_mesh_choice,
2092+ (
2093+ ## Initial condition for WholeMesh
2094+ ##
2095+ ## Only specify one condition if not using mesh regions.
2096+ ## Otherwise select other initial_condition option, specify region_ids
2097+ ## and distinct names. Then add extra intial conditions for other regions.
2098+ element initial_condition {
2099+ attribute name { "WholeMesh" },
2100+ input_choice_initial_condition_real
2101+ }|
2102+ ## Multiple initial_conditions are allowed if specifying
2103+ ## different values in different
2104+ ## regions of the mesh (defined by region_ids). In this case
2105+ ## each initial_condition
2106+ ## requires a distinct name for the options dictionary.
2107+ element initial_condition {
2108+ attribute name { string },
2109+ region_ids?,
2110+ input_choice_initial_condition_real
2111+ }
2112+ )+,
2113+ diagnostic_scalar_field
2114+ }
2115+ }*
2116+ },
2117+ element statistics {
2118+ element scalar_field {
2119+ attribute rank { "0" },
2120+ attribute name { "Mean" },
2121+ ## Field type
2122+ element diagnostic {
2123+ internal_algorithm,
2124+ velocity_mesh_choice,
2125+ diagnostic_scalar_field
2126+ }
2127+ }?,
2128+ element scalar_field {
2129+ attribute rank { "0" },
2130+ attribute name { "StandardDeviation" },
2131+ ## Field type
2132+ element diagnostic {
2133+ internal_algorithm,
2134+ velocity_mesh_choice,
2135+ diagnostic_scalar_field
2136+ }
2137+ }?,
2138+ element scalar_field {
2139+ attribute rank { "0" },
2140+ attribute name { "Skew" },
2141+ ## Field type
2142+ element diagnostic {
2143+ internal_algorithm,
2144+ velocity_mesh_choice,
2145+ diagnostic_scalar_field
2146+ }
2147+ }?,
2148+ element scalar_field {
2149+ attribute rank { "0" },
2150+ attribute name { "SauterMeanDia" },
2151+ ## Field type
2152+ element diagnostic {
2153+ internal_algorithm,
2154+ velocity_mesh_choice,
2155+ diagnostic_scalar_field
2156+ }
2157+ }?,
2158+ element scalar_field {
2159+ attribute rank { "0" },
2160+ attribute name { "MeanDia10" },
2161+ ## Field type
2162+ element diagnostic {
2163+ internal_algorithm,
2164+ velocity_mesh_choice,
2165+ diagnostic_scalar_field
2166+ }
2167+ }?
2168+ },
2169+
2170+ ## Source terms for the population balance equation like growth,
2171+ ## breakage, aggegation and internal dispersion
2172+ element population_balance_source_terms {
2173+ ## Growth term in the internal coordinate space
2174+ element growth{
2175+ ## Enter the growth degree (r) for the power-law growth G(\xi)=\xi^{r}
2176+ element power_law_growth{ real }
2177+ }?,
2178+ ## Dispersion coefficient D. Currently it only works for constant dispersion and can't handle dispersion varying with internal coordinate
2179+ element internal_dispersion{ real }?,
2180+ ##
2181+ element aggregation{
2182+ ##
2183+ element aggregation_frequency{
2184+ ##
2185+ element constant_aggregation{ real }|
2186+ ## aggregation frequency is given by \beta_{alpha gamma} = \xi_{alpha}^3 + \xi_{gamma}^3
2187+ element hydrodynamic_aggregation{ empty }|
2188+ ## aggregation frequency is given by \beta_{alpha gamma} = \beta_o (\xi_{alpha} + \xi_{gamma}). Enter the value of constant \beta_o below
2189+ element sum_aggregation{ real }
2190+ }
2191+ }?,
2192+ ##
2193+ element breakage{
2194+ ##
2195+ element breakage_frequency{
2196+ ##
2197+ element constant_breakage{ real }|
2198+ ## breakage frequency is given by a_{alpha} = p * \xi_{alpha}^r
2199+ element power_law_breakage{
2200+ ## coefficient p in breakage frequency a_{alpha} = p * \xi_{alpha}^r
2201+ element coefficient{ real },
2202+ ## degree r in breakage frequency a_{alpha} = p * \xi_{alpha}^r
2203+ element degree{ real }
2204+ }
2205+ },
2206+ element distribution_function{
2207+ ##
2208+ element symmetric_fragmentation{ empty }|
2209+ ## McCoy and Madras (2003) used P(v|v') = 2/v' for v<v' and 0 otherwise, where v stands for volume.
2210+ ## When written in terms of particle diameter, this converts to P(x|x')=(6x^2)/x'^3 for x<x' and 0 otherwise.
2211+ element mcCoy_madras_2003{ empty }
2212+ }
2213+ }?
2214+ },
2215+
2216+ ## At each vertex a linear system is solved to determine source terms
2217+ ## for the abscissa and weight transport equations. This requires inversion
2218+ ## of a matrix that has terms that are a function of the weighted abscissa.
2219+ ## If any two abscissa happen to lie very close to one another this can cause
2220+ ## this matrix to be ill-conditioned which can cause large errors or solver
2221+ ## failures when attempting to invert the matrix. There several options for
2222+ ## evading this problem:
2223+ ##
2224+ ## (a) Set the abscissa and weight source terms to zero at the offending vertex.
2225+ ## (b) Perturbate the weighted absciss used to construct the matrix until the
2226+ ## matrix is no longer ill conditioned and can be inverted.
2227+ ## (c) Use the source terms of neighbouring cells (not implemented)
2228+ element ill_conditioned_matrices {
2229+ ## The required condition number of the matrix. Recommended value of 1e-12
2230+ element required_condition_number{ real },
2231+ (
2232+ ## This is a better option when much of the domain has a minimum 0'th moment
2233+ element set_source_to_zero { empty }|
2234+ element perturbate{
2235+ ## The amount to perturbate the weighted abscissa. The values are
2236+ ## iteratively perturbated by rand(-1,1)*perturbation until the matrix
2237+ ## exceeds the required condition number. Too low a value can cause
2238+ ## very long run times but a higher value will lead to larger errors.
2239+ ## After every ten perturbations at any one grid location a message is
2240+ ## printed to the log file noting the difficulties in solving the linear
2241+ ## system.
2242+ ## Recommended value of 1e-7
2243+ element perturbation{ real }
2244+ }|
2245+ ## Do not check for ill-conditioning of matrix A
2246+ element do_nothing{ empty }
2247+ )
2248+ },
2249+ ## weights of zero can cause instabilities. It is recommended that a minimum
2250+ ## weight of approx 1e-10 is used.
2251+ element minimum_weight{ real },
2252+ ## Scaling factor to be used for the Sauter Mean Diameter / Mean Diameter calculated in the
2253+ ## statistics. It is useful in a non-dimensional implementation of the PBE.
2254+ element scaling_factor_Dia{ real }?,
2255+ ## This is the submerged specific gravity, R, of this population balance
2256+ ## as a function of internal coordinate, Z.
2257+ ## It will be used in the equation of state.
2258+ ##
2259+ ## R(Z) = (rho_c(Z) - rho_a)/(rho_a)
2260+ ##
2261+ ## Where: rho_c(Z) is the density of the dispersed phase and rho_a is
2262+ ## the ambient fluid density
2263+ ##
2264+ ## Must be given as a python function in the form:
2265+ ##
2266+ ## def R(Z):
2267+ ## # Function code
2268+ ## return # Return value of R
2269+ element submerged_specific_gravity {
2270+ python_code
2271+ }?,
2272+ element output_abscissa_and_weights{ empty }?,
2273+ element output_sources{ empty }?
2274+ }
2275+ )
2276+
2277 sediment =
2278 (
2279 ## A sediment model. See the manual for details on how to use this model.
2280
2281=== modified file 'schemas/fluidity_options.rng'
2282--- schemas/fluidity_options.rng 2013-11-06 21:30:29 +0000
2283+++ schemas/fluidity_options.rng 2013-12-12 22:35:40 +0000
2284@@ -1957,6 +1957,9 @@
2285 <zeroOrMore>
2286 <ref name="tensor_field_choice"/>
2287 </zeroOrMore>
2288+ <zeroOrMore>
2289+ <ref name="population_balance"/>
2290+ </zeroOrMore>
2291 <optional>
2292 <element name="electrical_properties">
2293 <a:documentation>Parameters required to model spontaneous electrical potentials in porous media.</a:documentation>
2294@@ -2191,7 +2194,14 @@
2295 <ref name="comment"/>
2296 <optional>
2297 <element name="particle_diameter">
2298- <ref name="real"/>
2299+ <choice>
2300+ <element name="constant">
2301+ <ref name="real"/>
2302+ </element>
2303+ <element name="use_scalar_field">
2304+ <ref name="anystring"/>
2305+ </element>
2306+ </choice>
2307 </element>
2308 </optional>
2309 <optional>
2310@@ -2547,6 +2557,644 @@
2311 </optional>
2312 </element>
2313 </start>
2314+ <define name="population_balance">
2315+ <element name="population_balance">
2316+ <a:documentation/>
2317+ <choice>
2318+ <element name="calculate_initial_conditions_from_moments">
2319+ <a:documentation>Determine initial weighted_abscissa and weights using the PD algorithm and the
2320+initial conditions set in the diagnostic moment fields.
2321+
2322+In this case it does not matter what is set in the weighted_abscissa and weights
2323+fields initial conditions option</a:documentation>
2324+ <empty/>
2325+ </element>
2326+ <element name="use_prognostic_field_initial_conditions">
2327+ <a:documentation>Use initial conditions set in the weighted_abscissa and weights prognostic
2328+fields
2329+
2330+In this case it does not matter what is set in the moment field initial conditions
2331+options</a:documentation>
2332+ <empty/>
2333+ </element>
2334+ </choice>
2335+ <attribute name="name">
2336+ <data type="string"/>
2337+ </attribute>
2338+ <element name="abscissa">
2339+ <element name="scalar_field">
2340+ <attribute name="rank">
2341+ <value>0</value>
2342+ </attribute>
2343+ <attribute name="name">
2344+ <value>Abscissa_0</value>
2345+ </attribute>
2346+ <element name="diagnostic">
2347+ <a:documentation>Field type</a:documentation>
2348+ <ref name="internal_algorithm"/>
2349+ <ref name="velocity_mesh_choice"/>
2350+ <ref name="diagnostic_scalar_field"/>
2351+ </element>
2352+ </element>
2353+ <element name="scalar_field">
2354+ <attribute name="rank">
2355+ <value>0</value>
2356+ </attribute>
2357+ <attribute name="name">
2358+ <value>Abscissa_1</value>
2359+ </attribute>
2360+ <element name="diagnostic">
2361+ <a:documentation>Field type</a:documentation>
2362+ <ref name="internal_algorithm"/>
2363+ <ref name="velocity_mesh_choice"/>
2364+ <ref name="diagnostic_scalar_field"/>
2365+ </element>
2366+ </element>
2367+ <zeroOrMore>
2368+ <element name="scalar_field">
2369+ <attribute name="rank">
2370+ <value>0</value>
2371+ </attribute>
2372+ <attribute name="name">
2373+ <data type="string"/>
2374+ </attribute>
2375+ <element name="diagnostic">
2376+ <a:documentation>Field type</a:documentation>
2377+ <ref name="internal_algorithm"/>
2378+ <ref name="velocity_mesh_choice"/>
2379+ <ref name="diagnostic_scalar_field"/>
2380+ </element>
2381+ </element>
2382+ </zeroOrMore>
2383+ </element>
2384+ <element name="weights">
2385+ <element name="scalar_field">
2386+ <attribute name="rank">
2387+ <value>0</value>
2388+ </attribute>
2389+ <attribute name="name">
2390+ <value>Weight_0</value>
2391+ </attribute>
2392+ <element name="prognostic">
2393+ <a:documentation>Field type</a:documentation>
2394+ <ref name="velocity_mesh_choice"/>
2395+ <ref name="prognostic_scalar_field"/>
2396+ </element>
2397+ </element>
2398+ <element name="scalar_field">
2399+ <attribute name="rank">
2400+ <value>0</value>
2401+ </attribute>
2402+ <attribute name="name">
2403+ <value>Weight_1</value>
2404+ </attribute>
2405+ <element name="prognostic">
2406+ <a:documentation>Field type</a:documentation>
2407+ <ref name="velocity_mesh_choice"/>
2408+ <ref name="prognostic_scalar_field"/>
2409+ </element>
2410+ </element>
2411+ <zeroOrMore>
2412+ <element name="scalar_field">
2413+ <attribute name="rank">
2414+ <value>0</value>
2415+ </attribute>
2416+ <attribute name="name">
2417+ <data type="string"/>
2418+ </attribute>
2419+ <element name="prognostic">
2420+ <a:documentation>Field type</a:documentation>
2421+ <ref name="velocity_mesh_choice"/>
2422+ <ref name="prognostic_scalar_field"/>
2423+ </element>
2424+ </element>
2425+ </zeroOrMore>
2426+ </element>
2427+ <element name="weighted_abscissa">
2428+ <element name="scalar_field">
2429+ <attribute name="rank">
2430+ <value>0</value>
2431+ </attribute>
2432+ <attribute name="name">
2433+ <value>WeightedAbscissa_0</value>
2434+ </attribute>
2435+ <element name="prognostic">
2436+ <a:documentation>Field type</a:documentation>
2437+ <ref name="velocity_mesh_choice"/>
2438+ <ref name="prognostic_scalar_field"/>
2439+ </element>
2440+ </element>
2441+ <element name="scalar_field">
2442+ <attribute name="rank">
2443+ <value>0</value>
2444+ </attribute>
2445+ <attribute name="name">
2446+ <value>WeightedAbscissa_1</value>
2447+ </attribute>
2448+ <element name="prognostic">
2449+ <a:documentation>Field type</a:documentation>
2450+ <ref name="velocity_mesh_choice"/>
2451+ <ref name="prognostic_scalar_field"/>
2452+ </element>
2453+ </element>
2454+ <zeroOrMore>
2455+ <element name="scalar_field">
2456+ <attribute name="rank">
2457+ <value>0</value>
2458+ </attribute>
2459+ <attribute name="name">
2460+ <data type="string"/>
2461+ </attribute>
2462+ <element name="prognostic">
2463+ <a:documentation>Field type</a:documentation>
2464+ <ref name="velocity_mesh_choice"/>
2465+ <ref name="prognostic_scalar_field"/>
2466+ </element>
2467+ </element>
2468+ </zeroOrMore>
2469+ </element>
2470+ <element name="adv_diff_source_term_interpolation">
2471+ <a:documentation>This option only works if you are using a continuous mesh for the population balance scalar fields.
2472+A DG mesh will use inverse mass calculated at element level.
2473+In the population balance DQMOM algorithm all sources for the
2474+advection-diffusion equations are calculated at the quadrature points first
2475+and then interpolated back to the nodal points.
2476+For a continuous mesh, this interpolation is made by inverting the mass matrix.
2477+Mass lumping is fairly quick and can be used with 1st order continuous meshes.
2478+But the error is high for higher order continuous meshes and full mass matrix should be used.</a:documentation>
2479+ <choice>
2480+ <element name="use_mass_lumping">
2481+ <a:documentation>The mass matrix is lumped to obtain source fields at nodal points.</a:documentation>
2482+ <empty/>
2483+ </element>
2484+ <element name="use_full_mass_matrix">
2485+ <a:documentation>Full mass marix is used and the linear system is solved iteratively to obtain source fields at nodal points.</a:documentation>
2486+ <element name="solver">
2487+ <a:documentation>This block specifies the solver options for solving the linear system to interpolate advection-diffusion source terms at nodal points.</a:documentation>
2488+ <ref name="linear_solver_options_asym_scalar"/>
2489+ </element>
2490+ </element>
2491+ </choice>
2492+ </element>
2493+ <element name="moments">
2494+ <element name="scalar_field">
2495+ <attribute name="rank">
2496+ <value>0</value>
2497+ </attribute>
2498+ <attribute name="name">
2499+ <value>Moment_0</value>
2500+ </attribute>
2501+ <element name="diagnostic">
2502+ <ref name="internal_algorithm"/>
2503+ <ref name="velocity_mesh_choice"/>
2504+ <oneOrMore>
2505+ <choice>
2506+ <element name="initial_condition">
2507+ <a:documentation>Initial condition for WholeMesh
2508+
2509+Only specify one condition if not using mesh regions.
2510+Otherwise select other initial_condition option, specify region_ids
2511+and distinct names. Then add extra intial conditions for other regions.</a:documentation>
2512+ <attribute name="name">
2513+ <value>WholeMesh</value>
2514+ </attribute>
2515+ <ref name="input_choice_initial_condition_real"/>
2516+ </element>
2517+ <element name="initial_condition">
2518+ <a:documentation>Multiple initial_conditions are allowed if specifying
2519+different values in different
2520+regions of the mesh (defined by region_ids). In this case
2521+each initial_condition
2522+requires a distinct name for the options dictionary.</a:documentation>
2523+ <attribute name="name">
2524+ <data type="string" datatypeLibrary=""/>
2525+ </attribute>
2526+ <optional>
2527+ <ref name="region_ids"/>
2528+ </optional>
2529+ <ref name="input_choice_initial_condition_real"/>
2530+ </element>
2531+ </choice>
2532+ </oneOrMore>
2533+ <ref name="diagnostic_scalar_field"/>
2534+ </element>
2535+ </element>
2536+ <element name="scalar_field">
2537+ <attribute name="rank">
2538+ <value>0</value>
2539+ </attribute>
2540+ <attribute name="name">
2541+ <value>Moment_1</value>
2542+ </attribute>
2543+ <element name="diagnostic">
2544+ <ref name="internal_algorithm"/>
2545+ <ref name="velocity_mesh_choice"/>
2546+ <oneOrMore>
2547+ <choice>
2548+ <element name="initial_condition">
2549+ <a:documentation>Initial condition for WholeMesh
2550+
2551+Only specify one condition if not using mesh regions.
2552+Otherwise select other initial_condition option, specify region_ids
2553+and distinct names. Then add extra intial conditions for other regions.</a:documentation>
2554+ <attribute name="name">
2555+ <value>WholeMesh</value>
2556+ </attribute>
2557+ <ref name="input_choice_initial_condition_real"/>
2558+ </element>
2559+ <element name="initial_condition">
2560+ <a:documentation>Multiple initial_conditions are allowed if specifying
2561+different values in different
2562+regions of the mesh (defined by region_ids). In this case
2563+each initial_condition
2564+requires a distinct name for the options dictionary.</a:documentation>
2565+ <attribute name="name">
2566+ <data type="string" datatypeLibrary=""/>
2567+ </attribute>
2568+ <optional>
2569+ <ref name="region_ids"/>
2570+ </optional>
2571+ <ref name="input_choice_initial_condition_real"/>
2572+ </element>
2573+ </choice>
2574+ </oneOrMore>
2575+ <ref name="diagnostic_scalar_field"/>
2576+ </element>
2577+ </element>
2578+ <element name="scalar_field">
2579+ <attribute name="rank">
2580+ <value>0</value>
2581+ </attribute>
2582+ <attribute name="name">
2583+ <value>Moment_2</value>
2584+ </attribute>
2585+ <element name="diagnostic">
2586+ <ref name="internal_algorithm"/>
2587+ <ref name="velocity_mesh_choice"/>
2588+ <oneOrMore>
2589+ <choice>
2590+ <element name="initial_condition">
2591+ <a:documentation>Initial condition for WholeMesh
2592+
2593+Only specify one condition if not using mesh regions.
2594+Otherwise select other initial_condition option, specify region_ids
2595+and distinct names. Then add extra intial conditions for other regions.</a:documentation>
2596+ <attribute name="name">
2597+ <value>WholeMesh</value>
2598+ </attribute>
2599+ <ref name="input_choice_initial_condition_real"/>
2600+ </element>
2601+ <element name="initial_condition">
2602+ <a:documentation>Multiple initial_conditions are allowed if specifying
2603+different values in different
2604+regions of the mesh (defined by region_ids). In this case
2605+each initial_condition
2606+requires a distinct name for the options dictionary.</a:documentation>
2607+ <attribute name="name">
2608+ <data type="string" datatypeLibrary=""/>
2609+ </attribute>
2610+ <optional>
2611+ <ref name="region_ids"/>
2612+ </optional>
2613+ <ref name="input_choice_initial_condition_real"/>
2614+ </element>
2615+ </choice>
2616+ </oneOrMore>
2617+ <ref name="diagnostic_scalar_field"/>
2618+ </element>
2619+ </element>
2620+ <element name="scalar_field">
2621+ <attribute name="rank">
2622+ <value>0</value>
2623+ </attribute>
2624+ <attribute name="name">
2625+ <value>Moment_3</value>
2626+ </attribute>
2627+ <element name="diagnostic">
2628+ <ref name="internal_algorithm"/>
2629+ <ref name="velocity_mesh_choice"/>
2630+ <oneOrMore>
2631+ <choice>
2632+ <element name="initial_condition">
2633+ <a:documentation>Initial condition for WholeMesh
2634+
2635+Only specify one condition if not using mesh regions.
2636+Otherwise select other initial_condition option, specify region_ids
2637+and distinct names. Then add extra intial conditions for other regions.</a:documentation>
2638+ <attribute name="name">
2639+ <value>WholeMesh</value>
2640+ </attribute>
2641+ <ref name="input_choice_initial_condition_real"/>
2642+ </element>
2643+ <element name="initial_condition">
2644+ <a:documentation>Multiple initial_conditions are allowed if specifying
2645+different values in different
2646+regions of the mesh (defined by region_ids). In this case
2647+each initial_condition
2648+requires a distinct name for the options dictionary.</a:documentation>
2649+ <attribute name="name">
2650+ <data type="string" datatypeLibrary=""/>
2651+ </attribute>
2652+ <optional>
2653+ <ref name="region_ids"/>
2654+ </optional>
2655+ <ref name="input_choice_initial_condition_real"/>
2656+ </element>
2657+ </choice>
2658+ </oneOrMore>
2659+ <ref name="diagnostic_scalar_field"/>
2660+ </element>
2661+ </element>
2662+ <zeroOrMore>
2663+ <element name="scalar_field">
2664+ <attribute name="rank">
2665+ <value>0</value>
2666+ </attribute>
2667+ <attribute name="name">
2668+ <data type="string"/>
2669+ </attribute>
2670+ <element name="diagnostic">
2671+ <ref name="internal_algorithm"/>
2672+ <ref name="velocity_mesh_choice"/>
2673+ <oneOrMore>
2674+ <choice>
2675+ <element name="initial_condition">
2676+ <a:documentation>Initial condition for WholeMesh
2677+
2678+Only specify one condition if not using mesh regions.
2679+Otherwise select other initial_condition option, specify region_ids
2680+and distinct names. Then add extra intial conditions for other regions.</a:documentation>
2681+ <attribute name="name">
2682+ <value>WholeMesh</value>
2683+ </attribute>
2684+ <ref name="input_choice_initial_condition_real"/>
2685+ </element>
2686+ <element name="initial_condition">
2687+ <a:documentation>Multiple initial_conditions are allowed if specifying
2688+different values in different
2689+regions of the mesh (defined by region_ids). In this case
2690+each initial_condition
2691+requires a distinct name for the options dictionary.</a:documentation>
2692+ <attribute name="name">
2693+ <data type="string" datatypeLibrary=""/>
2694+ </attribute>
2695+ <optional>
2696+ <ref name="region_ids"/>
2697+ </optional>
2698+ <ref name="input_choice_initial_condition_real"/>
2699+ </element>
2700+ </choice>
2701+ </oneOrMore>
2702+ <ref name="diagnostic_scalar_field"/>
2703+ </element>
2704+ </element>
2705+ </zeroOrMore>
2706+ </element>
2707+ <element name="statistics">
2708+ <optional>
2709+ <element name="scalar_field">
2710+ <attribute name="rank">
2711+ <value>0</value>
2712+ </attribute>
2713+ <attribute name="name">
2714+ <value>Mean</value>
2715+ </attribute>
2716+ <element name="diagnostic">
2717+ <a:documentation>Field type</a:documentation>
2718+ <ref name="internal_algorithm"/>
2719+ <ref name="velocity_mesh_choice"/>
2720+ <ref name="diagnostic_scalar_field"/>
2721+ </element>
2722+ </element>
2723+ </optional>
2724+ <optional>
2725+ <element name="scalar_field">
2726+ <attribute name="rank">
2727+ <value>0</value>
2728+ </attribute>
2729+ <attribute name="name">
2730+ <value>StandardDeviation</value>
2731+ </attribute>
2732+ <element name="diagnostic">
2733+ <a:documentation>Field type</a:documentation>
2734+ <ref name="internal_algorithm"/>
2735+ <ref name="velocity_mesh_choice"/>
2736+ <ref name="diagnostic_scalar_field"/>
2737+ </element>
2738+ </element>
2739+ </optional>
2740+ <optional>
2741+ <element name="scalar_field">
2742+ <attribute name="rank">
2743+ <value>0</value>
2744+ </attribute>
2745+ <attribute name="name">
2746+ <value>Skew</value>
2747+ </attribute>
2748+ <element name="diagnostic">
2749+ <a:documentation>Field type</a:documentation>
2750+ <ref name="internal_algorithm"/>
2751+ <ref name="velocity_mesh_choice"/>
2752+ <ref name="diagnostic_scalar_field"/>
2753+ </element>
2754+ </element>
2755+ </optional>
2756+ <optional>
2757+ <element name="scalar_field">
2758+ <attribute name="rank">
2759+ <value>0</value>
2760+ </attribute>
2761+ <attribute name="name">
2762+ <value>SauterMeanDia</value>
2763+ </attribute>
2764+ <element name="diagnostic">
2765+ <a:documentation>Field type</a:documentation>
2766+ <ref name="internal_algorithm"/>
2767+ <ref name="velocity_mesh_choice"/>
2768+ <ref name="diagnostic_scalar_field"/>
2769+ </element>
2770+ </element>
2771+ </optional>
2772+ <optional>
2773+ <element name="scalar_field">
2774+ <attribute name="rank">
2775+ <value>0</value>
2776+ </attribute>
2777+ <attribute name="name">
2778+ <value>MeanDia10</value>
2779+ </attribute>
2780+ <element name="diagnostic">
2781+ <a:documentation>Field type</a:documentation>
2782+ <ref name="internal_algorithm"/>
2783+ <ref name="velocity_mesh_choice"/>
2784+ <ref name="diagnostic_scalar_field"/>
2785+ </element>
2786+ </element>
2787+ </optional>
2788+ </element>
2789+ <element name="population_balance_source_terms">
2790+ <a:documentation>Source terms for the population balance equation like growth,
2791+breakage, aggegation and internal dispersion</a:documentation>
2792+ <optional>
2793+ <element name="growth">
2794+ <a:documentation>Growth term in the internal coordinate space</a:documentation>
2795+ <element name="power_law_growth">
2796+ <a:documentation>Enter the growth degree (r) for the power-law growth G(\xi)=\xi^{r}</a:documentation>
2797+ <ref name="real"/>
2798+ </element>
2799+ </element>
2800+ </optional>
2801+ <optional>
2802+ <element name="internal_dispersion">
2803+ <a:documentation>Dispersion coefficient D. Currently it only works for constant dispersion and can't handle dispersion varying with internal coordinate</a:documentation>
2804+ <ref name="real"/>
2805+ </element>
2806+ </optional>
2807+ <optional>
2808+ <element name="aggregation">
2809+ <a:documentation/>
2810+ <element name="aggregation_frequency">
2811+ <a:documentation/>
2812+ <choice>
2813+ <element name="constant_aggregation">
2814+ <a:documentation/>
2815+ <ref name="real"/>
2816+ </element>
2817+ <element name="hydrodynamic_aggregation">
2818+ <a:documentation>aggregation frequency is given by \beta_{alpha gamma} = \xi_{alpha}^3 + \xi_{gamma}^3</a:documentation>
2819+ <empty/>
2820+ </element>
2821+ <element name="sum_aggregation">
2822+ <a:documentation>aggregation frequency is given by \beta_{alpha gamma} = \beta_o (\xi_{alpha} + \xi_{gamma})</a:documentation>
2823+ <ref name="real"/>
2824+ </element>
2825+ </choice>
2826+ </element>
2827+ </element>
2828+ </optional>
2829+ <optional>
2830+ <element name="breakage">
2831+ <a:documentation/>
2832+ <element name="breakage_frequency">
2833+ <a:documentation/>
2834+ <choice>
2835+ <element name="constant_breakage">
2836+ <a:documentation/>
2837+ <ref name="real"/>
2838+ </element>
2839+ <element name="power_law_breakage">
2840+ <a:documentation>breakage frequency is given by a_{alpha} = p * \xi_{alpha}^r</a:documentation>
2841+ <element name="coefficient">
2842+ <a:documentation>coefficient p in breakage frequency a_{alpha} = p * \xi_{alpha}^r</a:documentation>
2843+ <ref name="real"/>
2844+ </element>
2845+ <element name="degree">
2846+ <a:documentation>degree r in breakage frequency a_{alpha} = p * \xi_{alpha}^r</a:documentation>
2847+ <ref name="real"/>
2848+ </element>
2849+ </element>
2850+ </choice>
2851+ </element>
2852+ <element name="distribution_function">
2853+ <choice>
2854+ <element name="symmetric_fragmentation">
2855+ <a:documentation/>
2856+ <empty/>
2857+ </element>
2858+ <element name="mcCoy_madras_2003">
2859+ <a:documentation>McCoy and Madras (2003) used P(v|v') = 2/v' for v&lt;v' and 0 otherwise, where v stands for volume.
2860+When written in terms of particle diameter, this converts to P(x|x')=(6x^2)/x'^3 for x&lt;x' and 0 otherwise.</a:documentation>
2861+ <empty/>
2862+ </element>
2863+ </choice>
2864+ </element>
2865+ </element>
2866+ </optional>
2867+ </element>
2868+ <element name="ill_conditioned_matrices">
2869+ <a:documentation>At each vertex a linear system is solved to determine source terms
2870+for the abscissa and weight transport equations. This requires inversion
2871+of a matrix that has terms that are a function of the weighted abscissa.
2872+If any two abscissa happen to lie very close to one another this can cause
2873+this matrix to be ill-conditioned which can cause large errors or solver
2874+failures when attempting to invert the matrix. There several options for
2875+evading this problem:
2876+
2877+(a) Set the abscissa and weight source terms to zero at the offending vertex.
2878+(b) Perturbate the weighted absciss used to construct the matrix until the
2879+matrix is no longer ill conditioned and can be inverted.
2880+(c) Use the source terms of neighbouring cells (not implemented)</a:documentation>
2881+ <element name="required_condition_number">
2882+ <a:documentation>The required condition number of the matrix. Recommended value of 1e-12</a:documentation>
2883+ <ref name="real"/>
2884+ </element>
2885+ <choice>
2886+ <element name="set_source_to_zero">
2887+ <a:documentation>This is a better option when much of the domain has a minimum 0'th moment</a:documentation>
2888+ <empty/>
2889+ </element>
2890+ <element name="perturbate">
2891+ <element name="perturbation">
2892+ <a:documentation>The amount to perturbate the weighted abscissa. The values are
2893+iteratively perturbated by rand(-1,1)*perturbation until the matrix
2894+exceeds the required condition number. Too low a value can cause
2895+very long run times but a higher value will lead to larger errors.
2896+After every ten perturbations at any one grid location a message is
2897+printed to the log file noting the difficulties in solving the linear
2898+system.
2899+Recommended value of 1e-7</a:documentation>
2900+ <ref name="real"/>
2901+ </element>
2902+ </element>
2903+ <element name="do_nothing">
2904+ <a:documentation>Do not check for ill-conditioning of matrix A</a:documentation>
2905+ <empty/>
2906+ </element>
2907+ </choice>
2908+ </element>
2909+ <element name="minimum_weight">
2910+ <a:documentation>weights of zero can cause instabilities. It is recommended that a minimum
2911+weight of approx 1e-10 is used.</a:documentation>
2912+ <ref name="real"/>
2913+ </element>
2914+ <optional>
2915+ <element name="scaling_factor_Dia">
2916+ <a:documentation>Scaling factor to be used for the Sauter Mean Diameter / Mean Diameter calculated in the
2917+statistics. It is useful in a non-dimensional implementation of the PBE.</a:documentation>
2918+ <ref name="real"/>
2919+ </element>
2920+ </optional>
2921+ <optional>
2922+ <element name="submerged_specific_gravity">
2923+ <a:documentation>This is the submerged specific gravity, R, of this population balance
2924+as a function of internal coordinate, Z.
2925+It will be used in the equation of state.
2926+
2927+R(Z) = (rho_c(Z) - rho_a)/(rho_a)
2928+
2929+Where: rho_c(Z) is the density of the dispersed phase and rho_a is
2930+the ambient fluid density
2931+
2932+Must be given as a python function in the form:
2933+
2934+ def R(Z):
2935+ # Function code
2936+ return # Return value of R</a:documentation>
2937+ <ref name="python_code"/>
2938+ </element>
2939+ </optional>
2940+ <optional>
2941+ <element name="output_abscissa_and_weights">
2942+ <empty/>
2943+ </element>
2944+ </optional>
2945+ <optional>
2946+ <element name="output_sources">
2947+ <empty/>
2948+ </element>
2949+ </optional>
2950+ </element>
2951+ </define>
2952 <define name="sediment">
2953 <element name="sediment">
2954 <a:documentation>A sediment model. See the manual for details on how to use this model.</a:documentation>
2955
2956=== modified file 'schemas/multiphase_interaction.rnc'
2957--- schemas/multiphase_interaction.rnc 2012-06-15 19:32:03 +0000
2958+++ schemas/multiphase_interaction.rnc 2013-12-12 22:35:40 +0000
2959@@ -35,6 +35,11 @@
2960 element drag_correlation {
2961 attribute name { "ergun" },
2962 comment
2963+ }|
2964+ ## Fluid-particle drag term by Schiller-Naumann (1933).
2965+ element drag_correlation {
2966+ attribute name { "schiller_naumann" },
2967+ comment
2968 }
2969 )
2970
2971@@ -55,4 +60,4 @@
2972 attribute name { "gunn" },
2973 comment
2974 }
2975- )
2976\ No newline at end of file
2977+ )
2978
2979=== modified file 'schemas/multiphase_interaction.rng'
2980--- schemas/multiphase_interaction.rng 2012-06-15 19:32:03 +0000
2981+++ schemas/multiphase_interaction.rng 2013-12-12 22:35:40 +0000
2982@@ -43,6 +43,13 @@
2983 </attribute>
2984 <ref name="comment"/>
2985 </element>
2986+ <element name="drag_correlation">
2987+ <a:documentation>Fluid-particle drag term by Schiller-Naumann (1933).</a:documentation>
2988+ <attribute name="name">
2989+ <value>schiller_naumann</value>
2990+ </attribute>
2991+ <ref name="comment"/>
2992+ </element>
2993 </choice>
2994 </define>
2995 <define name="heat_transfer">
2996
2997=== modified file 'tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml'
2998--- tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml 2013-10-28 06:46:48 +0000
2999+++ tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml 2013-12-12 22:35:40 +0000
3000@@ -624,7 +624,9 @@
3001 <string_value lines="1">Dust::Velocity,Air::Velocity,Air::PhaseVolumeFraction,Air::Density</string_value>
3002 </depends>
3003 <particle_diameter>
3004- <real_value rank="0">10e-6</real_value>
3005+ <constant>
3006+ <real_value rank="0">10e-6</real_value>
3007+ </constant>
3008 </particle_diameter>
3009 <continuous_phase_name>Air</continuous_phase_name>
3010 </algorithm>
3011@@ -726,7 +728,9 @@
3012 </scalar_field>
3013 <multiphase_properties>
3014 <particle_diameter>
3015- <real_value rank="0">10e-6</real_value>
3016+ <constant>
3017+ <real_value rank="0">10e-6</real_value>
3018+ </constant>
3019 </particle_diameter>
3020 <specific_heat>
3021 <real_value rank="0">758</real_value>
3022
3023=== modified file 'tests/mphase_inlet_velocity_bc_compressible/mphase_inlet_velocity_bc_compressible.flml'
3024--- tests/mphase_inlet_velocity_bc_compressible/mphase_inlet_velocity_bc_compressible.flml 2013-10-28 06:46:48 +0000
3025+++ tests/mphase_inlet_velocity_bc_compressible/mphase_inlet_velocity_bc_compressible.flml 2013-12-12 22:35:40 +0000
3026@@ -845,7 +845,9 @@
3027 </scalar_field>
3028 <multiphase_properties>
3029 <particle_diameter>
3030- <real_value rank="0">2e-4</real_value>
3031+ <constant>
3032+ <real_value rank="0">2e-4</real_value>
3033+ </constant>
3034 </particle_diameter>
3035 <specific_heat>
3036 <real_value rank="0">954</real_value>
3037
3038=== modified file 'tests/mphase_rogue_shock_tube_dense_bed_glass/mphase_rogue_shock_tube_dense_bed_glass.flml'
3039--- tests/mphase_rogue_shock_tube_dense_bed_glass/mphase_rogue_shock_tube_dense_bed_glass.flml 2013-10-28 06:46:48 +0000
3040+++ tests/mphase_rogue_shock_tube_dense_bed_glass/mphase_rogue_shock_tube_dense_bed_glass.flml 2013-12-12 22:35:40 +0000
3041@@ -842,7 +842,9 @@
3042 </scalar_field>
3043 <multiphase_properties>
3044 <particle_diameter>
3045- <real_value rank="0">1.5e-3</real_value>
3046+ <constant>
3047+ <real_value rank="0">1.5e-3</real_value>
3048+ </constant>
3049 </particle_diameter>
3050 <specific_heat>
3051 <real_value rank="0">758</real_value>
3052
3053=== modified file 'tests/mphase_rogue_shock_tube_dense_bed_nylon/mphase_rogue_shock_tube_dense_bed_nylon.flml'
3054--- tests/mphase_rogue_shock_tube_dense_bed_nylon/mphase_rogue_shock_tube_dense_bed_nylon.flml 2013-10-28 06:46:48 +0000
3055+++ tests/mphase_rogue_shock_tube_dense_bed_nylon/mphase_rogue_shock_tube_dense_bed_nylon.flml 2013-12-12 22:35:40 +0000
3056@@ -842,7 +842,9 @@
3057 </scalar_field>
3058 <multiphase_properties>
3059 <particle_diameter>
3060- <real_value rank="0">2.0e-3</real_value>
3061+ <constant>
3062+ <real_value rank="0">2.0e-3</real_value>
3063+ </constant>
3064 </particle_diameter>
3065 <specific_heat>
3066 <real_value rank="0">758</real_value>
3067
3068=== modified file 'tests/mphase_stokes_law/mphase_stokes_law.flml'
3069--- tests/mphase_stokes_law/mphase_stokes_law.flml 2012-05-19 22:54:15 +0000
3070+++ tests/mphase_stokes_law/mphase_stokes_law.flml 2013-12-12 22:35:40 +0000
3071@@ -502,7 +502,9 @@
3072 <string_value lines="1">Water::Velocity,Tephra::Velocity,Water::Density</string_value>
3073 </depends>
3074 <particle_diameter>
3075- <real_value rank="0">48e-6</real_value>
3076+ <constant>
3077+ <real_value rank="0">48e-6</real_value>
3078+ </constant>
3079 </particle_diameter>
3080 <continuous_phase_name>Water</continuous_phase_name>
3081 </algorithm>
3082@@ -676,7 +678,9 @@
3083 </vector_field>
3084 <multiphase_properties>
3085 <particle_diameter>
3086- <real_value rank="0">48e-6</real_value>
3087+ <constant>
3088+ <real_value rank="0">48e-6</real_value>
3089+ </constant>
3090 </particle_diameter>
3091 </multiphase_properties>
3092 </material_phase>
3093
3094=== modified file 'tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p0p1.flml'
3095--- tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p0p1.flml 2013-10-28 06:46:48 +0000
3096+++ tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p0p1.flml 2013-12-12 22:35:40 +0000
3097@@ -725,7 +725,9 @@
3098 </scalar_field>
3099 <multiphase_properties>
3100 <particle_diameter>
3101- <real_value rank="0">2e-4</real_value>
3102+ <constant>
3103+ <real_value rank="0">2.0e-4</real_value>
3104+ </constant>
3105 </particle_diameter>
3106 <specific_heat>
3107 <real_value rank="0">954</real_value>
3108
3109=== modified file 'tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p2p1.flml'
3110--- tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p2p1.flml 2013-10-28 06:46:48 +0000
3111+++ tests/mphase_strong_pressure_bc_compressible/mphase_strong_pressure_bc_compressible_p2p1.flml 2013-12-12 22:35:40 +0000
3112@@ -732,7 +732,9 @@
3113 </scalar_field>
3114 <multiphase_properties>
3115 <particle_diameter>
3116- <real_value rank="0">2e-4</real_value>
3117+ <constant>
3118+ <real_value rank="0">2.0e-4</real_value>
3119+ </constant>
3120 </particle_diameter>
3121 <specific_heat>
3122 <real_value rank="0">954</real_value>
3123
3124=== modified file 'tests/mphase_subtract_out_reference_profile/mphase_subtract_out_reference_profile_1d.flml'
3125--- tests/mphase_subtract_out_reference_profile/mphase_subtract_out_reference_profile_1d.flml 2013-10-28 06:46:48 +0000
3126+++ tests/mphase_subtract_out_reference_profile/mphase_subtract_out_reference_profile_1d.flml 2013-12-12 22:35:40 +0000
3127@@ -811,7 +811,9 @@
3128 </scalar_field>
3129 <multiphase_properties>
3130 <particle_diameter>
3131- <real_value rank="0">2e-4</real_value>
3132+ <constant>
3133+ <real_value rank="0">2e-4</real_value>
3134+ </constant>
3135 </particle_diameter>
3136 <specific_heat>
3137 <real_value rank="0">954</real_value>
3138
3139=== modified file 'tests/mphase_tephra_settling/mphase_tephra_settling.flml'
3140--- tests/mphase_tephra_settling/mphase_tephra_settling.flml 2013-05-30 11:47:42 +0000
3141+++ tests/mphase_tephra_settling/mphase_tephra_settling.flml 2013-12-12 22:35:40 +0000
3142@@ -636,7 +636,9 @@
3143 <string_value lines="1">Water::Density, Water::Velocity, Water::PhaseVolumeFraction, Tephra::Velocity</string_value>
3144 </depends>
3145 <particle_diameter>
3146- <real_value rank="0">48e-6</real_value>
3147+ <constant>
3148+ <real_value rank="0">48e-6</real_value>
3149+ </constant>
3150 </particle_diameter>
3151 <continuous_phase_name>Water</continuous_phase_name>
3152 </algorithm>
3153@@ -656,7 +658,9 @@
3154 </scalar_field>
3155 <multiphase_properties>
3156 <particle_diameter>
3157- <real_value rank="0">48e-6</real_value>
3158+ <constant>
3159+ <real_value rank="0">48e-6</real_value>
3160+ </constant>
3161 </particle_diameter>
3162 </multiphase_properties>
3163 </material_phase>
3164
3165=== modified file 'tests/mphase_wen_yu_drag_correlation/mphase_wen_yu_drag_correlation.flml'
3166--- tests/mphase_wen_yu_drag_correlation/mphase_wen_yu_drag_correlation.flml 2012-10-17 05:47:11 +0000
3167+++ tests/mphase_wen_yu_drag_correlation/mphase_wen_yu_drag_correlation.flml 2013-12-12 22:35:40 +0000
3168@@ -499,7 +499,9 @@
3169 <string_value lines="1">Water::Velocity,Tephra::Velocity,Water::Density</string_value>
3170 </depends>
3171 <particle_diameter>
3172- <real_value rank="0">1e-3</real_value>
3173+ <constant>
3174+ <real_value rank="0">1e-3</real_value>
3175+ </constant>
3176 </particle_diameter>
3177 <continuous_phase_name>Water</continuous_phase_name>
3178 </algorithm>
3179@@ -781,7 +783,9 @@
3180 </vector_field>
3181 <multiphase_properties>
3182 <particle_diameter>
3183- <real_value rank="0">1e-3</real_value>
3184+ <constant>
3185+ <real_value rank="0">1e-3</real_value>
3186+ </constant>
3187 </particle_diameter>
3188 </multiphase_properties>
3189 </material_phase>
3190
3191=== added directory 'tests/popbal_homog_brk_aggr'
3192=== added file 'tests/popbal_homog_brk_aggr/Makefile'
3193--- tests/popbal_homog_brk_aggr/Makefile 1970-01-01 00:00:00 +0000
3194+++ tests/popbal_homog_brk_aggr/Makefile 2013-12-12 22:35:40 +0000
3195@@ -0,0 +1,5 @@
3196+input: clean
3197+ gmsh -2 src/minimal.geo -optimize -bin
3198+
3199+clean:
3200+ rm -f *.vtu *.pvtu fluidity.* *.s *.d.1 *.stat src/minimal.msh
3201
3202=== added file 'tests/popbal_homog_brk_aggr/popbal_homog_N2.flml'
3203--- tests/popbal_homog_brk_aggr/popbal_homog_N2.flml 1970-01-01 00:00:00 +0000
3204+++ tests/popbal_homog_brk_aggr/popbal_homog_N2.flml 2013-12-12 22:35:40 +0000
3205@@ -0,0 +1,723 @@
3206+<?xml version='1.0' encoding='utf-8'?>
3207+<fluidity_options>
3208+ <simulation_name>
3209+ <string_value lines="1">popbal_homog_N2_brk_aggr</string_value>
3210+ </simulation_name>
3211+ <problem_type>
3212+ <string_value lines="1">fluids</string_value>
3213+ </problem_type>
3214+ <geometry>
3215+ <dimension>
3216+ <integer_value rank="0">2</integer_value>
3217+ </dimension>
3218+ <mesh name="CoordinateMesh">
3219+ <from_file file_name="src/minimal">
3220+ <format name="gmsh"/>
3221+ <stat>
3222+ <include_in_stat/>
3223+ </stat>
3224+ </from_file>
3225+ </mesh>
3226+ <mesh name="VelocityMesh">
3227+ <from_mesh>
3228+ <mesh name="CoordinateMesh"/>
3229+ <stat>
3230+ <exclude_from_stat/>
3231+ </stat>
3232+ </from_mesh>
3233+ </mesh>
3234+ <quadrature>
3235+ <degree>
3236+ <integer_value rank="0">3</integer_value>
3237+ </degree>
3238+ </quadrature>
3239+ </geometry>
3240+ <io>
3241+ <dump_format>
3242+ <string_value>vtk</string_value>
3243+ </dump_format>
3244+ <dump_period>
3245+ <constant>
3246+ <real_value rank="0">5</real_value>
3247+ </constant>
3248+ </dump_period>
3249+ <output_mesh name="VelocityMesh"/>
3250+ <stat/>
3251+ </io>
3252+ <timestepping>
3253+ <current_time>
3254+ <real_value rank="0">0.0</real_value>
3255+ </current_time>
3256+ <timestep>
3257+ <real_value rank="0">0.001</real_value>
3258+ </timestep>
3259+ <finish_time>
3260+ <real_value rank="0">5</real_value>
3261+ </finish_time>
3262+ </timestepping>
3263+ <material_phase name="fluid">
3264+ <vector_field name="Velocity" rank="1">
3265+ <prescribed>
3266+ <mesh name="VelocityMesh"/>
3267+ <value name="WholeMesh">
3268+ <constant>
3269+ <real_value shape="2" dim1="dim" rank="1">0 0</real_value>
3270+ </constant>
3271+ </value>
3272+ <output/>
3273+ <stat>
3274+ <include_in_stat/>
3275+ </stat>
3276+ <detectors>
3277+ <exclude_from_detectors/>
3278+ </detectors>
3279+ </prescribed>
3280+ </vector_field>
3281+ <scalar_field name="m0_anal" rank="0">
3282+ <prescribed>
3283+ <mesh name="VelocityMesh"/>
3284+ <value name="WholeMesh">
3285+ <python>
3286+ <string_value lines="20" type="code" language="python">def val(X,t):
3287+ from math import tanh
3288+ phi_inf=10.0
3289+ phi_t = phi_inf*( (1.0+phi_inf*tanh(phi_inf*(t/2.0)))/(phi_inf+tanh(phi_inf*(t/2.0))) )
3290+ return phi_t</string_value>
3291+ </python>
3292+ </value>
3293+ <output/>
3294+ <stat/>
3295+ <detectors>
3296+ <exclude_from_detectors/>
3297+ </detectors>
3298+ </prescribed>
3299+ </scalar_field>
3300+ <scalar_field name="m1_anal" rank="0">
3301+ <prescribed>
3302+ <mesh name="VelocityMesh"/>
3303+ <value name="WholeMesh">
3304+ <python>
3305+ <string_value lines="20" type="code" language="python">def val(X,t):
3306+ from math import tanh, gamma, pi
3307+ phi_inf=10.0
3308+ phi_t = phi_inf*( (1.0+phi_inf*tanh(phi_inf*(t/2.0)))/(phi_inf+tanh(phi_inf*(t/2.0))) )
3309+ k1 = (pi/2.)*phi_t**2
3310+ k2 = (pi/6.)*phi_t
3311+ mom1 = (k1/(3.0*k2**(4./3.)))*gamma(4./3.)
3312+ return mom1</string_value>
3313+ </python>
3314+ </value>
3315+ <output/>
3316+ <stat/>
3317+ <detectors>
3318+ <exclude_from_detectors/>
3319+ </detectors>
3320+ </prescribed>
3321+ </scalar_field>
3322+ <scalar_field name="m2_anal" rank="0">
3323+ <prescribed>
3324+ <mesh name="VelocityMesh"/>
3325+ <value name="WholeMesh">
3326+ <python>
3327+ <string_value lines="20" type="code" language="python">def val(X,t):
3328+ from math import tanh, gamma, pi
3329+ phi_inf=10.0
3330+ phi_t = phi_inf*( (1.0+phi_inf*tanh(phi_inf*(t/2.0)))/(phi_inf+tanh(phi_inf*(t/2.0))) )
3331+ k1 = (pi/2.)*phi_t**2
3332+ k2 = (pi/6.)*phi_t
3333+ mom2 = (k1/(3.0*k2**(5./3.)))*gamma(5./3.)
3334+ return mom2</string_value>
3335+ </python>
3336+ </value>
3337+ <output/>
3338+ <stat/>
3339+ <detectors>
3340+ <exclude_from_detectors/>
3341+ </detectors>
3342+ </prescribed>
3343+ </scalar_field>
3344+ <scalar_field name="m3_anal" rank="0">
3345+ <prescribed>
3346+ <mesh name="VelocityMesh"/>
3347+ <value name="WholeMesh">
3348+ <python>
3349+ <string_value lines="20" type="code" language="python">def val(X,t):
3350+ from math import tanh, gamma, pi
3351+ phi_inf=10.0
3352+ phi_t = phi_inf*( (1.0+phi_inf*tanh(phi_inf*(t/2.0)))/(phi_inf+tanh(phi_inf*(t/2.0))) )
3353+ k1 = (pi/2.)*phi_t**2
3354+ k2 = (pi/6.)*phi_t
3355+ mom3 = k1/(3.*k2**2)
3356+ return mom3</string_value>
3357+ </python>
3358+ </value>
3359+ <output/>
3360+ <stat/>
3361+ <detectors>
3362+ <exclude_from_detectors/>
3363+ </detectors>
3364+ </prescribed>
3365+ </scalar_field>
3366+ <scalar_field name="diff_m0" rank="0">
3367+ <diagnostic>
3368+ <algorithm name="scalar_python_diagnostic" material_phase_support="single">
3369+ <string_value lines="20" type="code" language="python">mom0_anal=state.scalar_fields["m0_anal"]
3370+mom0_dqmom=state.scalar_fields["Moment_0"]
3371+for i in range(field.node_count):
3372+ field.set(i, abs(mom0_dqmom.node_val(i)-mom0_anal.node_val(i))/abs(mom0_anal.node_val(i)))</string_value>
3373+ <depends>
3374+ <string_value lines="1">fluid::m0_anal</string_value>
3375+ </depends>
3376+ </algorithm>
3377+ <mesh name="VelocityMesh"/>
3378+ <output/>
3379+ <stat/>
3380+ <convergence>
3381+ <exclude_from_convergence/>
3382+ </convergence>
3383+ <detectors>
3384+ <include_in_detectors/>
3385+ </detectors>
3386+ <steady_state>
3387+ <exclude_from_steady_state/>
3388+ </steady_state>
3389+ </diagnostic>
3390+ </scalar_field>
3391+ <scalar_field name="diff_m1" rank="0">
3392+ <diagnostic>
3393+ <algorithm name="scalar_python_diagnostic" material_phase_support="single">
3394+ <string_value lines="20" type="code" language="python">mom1_anal=state.scalar_fields["m1_anal"]
3395+mom1_dqmom=state.scalar_fields["Moment_1"]
3396+for i in range(field.node_count):
3397+ field.set(i, abs(mom1_dqmom.node_val(i)-mom1_anal.node_val(i))/abs(mom1_anal.node_val(i)))</string_value>
3398+ <depends>
3399+ <string_value lines="1">fluid::m1_anal</string_value>
3400+ </depends>
3401+ </algorithm>
3402+ <mesh name="VelocityMesh"/>
3403+ <output/>
3404+ <stat/>
3405+ <convergence>
3406+ <exclude_from_convergence/>
3407+ </convergence>
3408+ <detectors>
3409+ <include_in_detectors/>
3410+ </detectors>
3411+ <steady_state>
3412+ <exclude_from_steady_state/>
3413+ </steady_state>
3414+ </diagnostic>
3415+ </scalar_field>
3416+ <scalar_field name="diff_m2" rank="0">
3417+ <diagnostic>
3418+ <algorithm name="scalar_python_diagnostic" material_phase_support="single">
3419+ <string_value lines="20" type="code" language="python">mom2_anal=state.scalar_fields["m2_anal"]
3420+mom2_dqmom=state.scalar_fields["Moment_2"]
3421+for i in range(field.node_count):
3422+ field.set(i, abs(mom2_dqmom.node_val(i)-mom2_anal.node_val(i))/abs(mom2_anal.node_val(i)))</string_value>
3423+ <depends>
3424+ <string_value lines="1">fluid::m2_anal</string_value>
3425+ </depends>
3426+ </algorithm>
3427+ <mesh name="VelocityMesh"/>
3428+ <output/>
3429+ <stat/>
3430+ <convergence>
3431+ <exclude_from_convergence/>
3432+ </convergence>
3433+ <detectors>
3434+ <include_in_detectors/>
3435+ </detectors>
3436+ <steady_state>
3437+ <exclude_from_steady_state/>
3438+ </steady_state>
3439+ </diagnostic>
3440+ </scalar_field>
3441+ <scalar_field name="diff_m3" rank="0">
3442+ <diagnostic>
3443+ <algorithm name="scalar_python_diagnostic" material_phase_support="single">
3444+ <string_value lines="20" type="code" language="python">mom3_anal=state.scalar_fields["m3_anal"]
3445+mom3_dqmom=state.scalar_fields["Moment_3"]
3446+for i in range(field.node_count):
3447+ field.set(i, abs(mom3_dqmom.node_val(i)-mom3_anal.node_val(i))/abs(mom3_anal.node_val(i)))</string_value>
3448+ <depends>
3449+ <string_value lines="1">fluid::m3_anal</string_value>
3450+ </depends>
3451+ </algorithm>
3452+ <mesh name="VelocityMesh"/>
3453+ <output/>
3454+ <stat/>
3455+ <convergence>
3456+ <exclude_from_convergence/>
3457+ </convergence>
3458+ <detectors>
3459+ <include_in_detectors/>
3460+ </detectors>
3461+ <steady_state>
3462+ <exclude_from_steady_state/>
3463+ </steady_state>
3464+ </diagnostic>
3465+ </scalar_field>
3466+ <population_balance name="DQMOM">
3467+ <calculate_initial_conditions_from_moments/>
3468+ <abscissa>
3469+ <scalar_field name="Abscissa_0" rank="0">
3470+ <diagnostic>
3471+ <algorithm name="Internal" material_phase_support="multiple"/>
3472+ <mesh name="VelocityMesh"/>
3473+ <output/>
3474+ <stat/>
3475+ <convergence>
3476+ <include_in_convergence/>
3477+ </convergence>
3478+ <detectors>
3479+ <include_in_detectors/>
3480+ </detectors>
3481+ <steady_state>
3482+ <include_in_steady_state/>
3483+ </steady_state>
3484+ </diagnostic>
3485+ </scalar_field>
3486+ <scalar_field name="Abscissa_1" rank="0">
3487+ <diagnostic>
3488+ <algorithm name="Internal" material_phase_support="multiple"/>
3489+ <mesh name="VelocityMesh"/>
3490+ <output/>
3491+ <stat/>
3492+ <convergence>
3493+ <include_in_convergence/>
3494+ </convergence>
3495+ <detectors>
3496+ <include_in_detectors/>
3497+ </detectors>
3498+ <steady_state>
3499+ <include_in_steady_state/>
3500+ </steady_state>
3501+ </diagnostic>
3502+ </scalar_field>
3503+ </abscissa>
3504+ <weights>
3505+ <scalar_field name="Weight_0" rank="0">
3506+ <prognostic>
3507+ <mesh name="VelocityMesh"/>
3508+ <equation name="AdvectionDiffusion"/>
3509+ <spatial_discretisation>
3510+ <continuous_galerkin>
3511+ <stabilisation>
3512+ <no_stabilisation/>
3513+ </stabilisation>
3514+ <advection_terms>
3515+ <exclude_advection_terms/>
3516+ </advection_terms>
3517+ <mass_terms/>
3518+ </continuous_galerkin>
3519+ <conservative_advection>
3520+ <real_value rank="0">0.0</real_value>
3521+ </conservative_advection>
3522+ </spatial_discretisation>
3523+ <temporal_discretisation>
3524+ <theta>
3525+ <real_value rank="0">0.5</real_value>
3526+ </theta>
3527+ </temporal_discretisation>
3528+ <solver>
3529+ <iterative_method name="gmres">
3530+ <restart>
3531+ <integer_value rank="0">30</integer_value>
3532+ </restart>
3533+ </iterative_method>
3534+ <preconditioner name="sor"/>
3535+ <relative_error>
3536+ <real_value rank="0">1e-7</real_value>
3537+ </relative_error>
3538+ <max_iterations>
3539+ <integer_value rank="0">1000</integer_value>
3540+ </max_iterations>
3541+ <never_ignore_solver_failures/>
3542+ <diagnostics>
3543+ <monitors/>
3544+ </diagnostics>
3545+ </solver>
3546+ <initial_condition name="WholeMesh">
3547+ <constant>
3548+ <real_value rank="0">0.99480625</real_value>
3549+ </constant>
3550+ </initial_condition>
3551+ <scalar_field name="Source" rank="0">
3552+ <diagnostic>
3553+ <algorithm name="Internal" material_phase_support="multiple"/>
3554+ <output/>
3555+ <stat/>
3556+ <detectors>
3557+ <include_in_detectors/>
3558+ </detectors>
3559+ </diagnostic>
3560+ </scalar_field>
3561+ <output/>
3562+ <stat/>
3563+ <convergence>
3564+ <include_in_convergence/>
3565+ </convergence>
3566+ <detectors>
3567+ <include_in_detectors/>
3568+ </detectors>
3569+ <steady_state>
3570+ <include_in_steady_state/>
3571+ </steady_state>
3572+ <consistent_interpolation/>
3573+ </prognostic>
3574+ </scalar_field>
3575+ <scalar_field name="Weight_1" rank="0">
3576+ <prognostic>
3577+ <mesh name="VelocityMesh"/>
3578+ <equation name="AdvectionDiffusion"/>
3579+ <spatial_discretisation>
3580+ <continuous_galerkin>
3581+ <stabilisation>
3582+ <no_stabilisation/>
3583+ </stabilisation>
3584+ <advection_terms>
3585+ <exclude_advection_terms/>
3586+ </advection_terms>
3587+ <mass_terms/>
3588+ </continuous_galerkin>
3589+ <conservative_advection>
3590+ <real_value rank="0">0.0</real_value>
3591+ </conservative_advection>
3592+ </spatial_discretisation>
3593+ <temporal_discretisation>
3594+ <theta>
3595+ <real_value rank="0">0.5</real_value>
3596+ </theta>
3597+ </temporal_discretisation>
3598+ <solver>
3599+ <iterative_method name="gmres">
3600+ <restart>
3601+ <integer_value rank="0">30</integer_value>
3602+ </restart>
3603+ </iterative_method>
3604+ <preconditioner name="sor"/>
3605+ <relative_error>
3606+ <real_value rank="0">1e-7</real_value>
3607+ </relative_error>
3608+ <max_iterations>
3609+ <integer_value rank="0">1000</integer_value>
3610+ </max_iterations>
3611+ <never_ignore_solver_failures/>
3612+ <diagnostics>
3613+ <monitors/>
3614+ </diagnostics>
3615+ </solver>
3616+ <initial_condition name="WholeMesh">
3617+ <constant>
3618+ <real_value rank="0">0.00519377</real_value>
3619+ </constant>
3620+ </initial_condition>
3621+ <scalar_field name="Source" rank="0">
3622+ <diagnostic>
3623+ <algorithm name="Internal" material_phase_support="multiple"/>
3624+ <output/>
3625+ <stat/>
3626+ <detectors>
3627+ <include_in_detectors/>
3628+ </detectors>
3629+ </diagnostic>
3630+ </scalar_field>
3631+ <output/>
3632+ <stat/>
3633+ <convergence>
3634+ <include_in_convergence/>
3635+ </convergence>
3636+ <detectors>
3637+ <include_in_detectors/>
3638+ </detectors>
3639+ <steady_state>
3640+ <include_in_steady_state/>
3641+ </steady_state>
3642+ <consistent_interpolation/>
3643+ </prognostic>
3644+ </scalar_field>
3645+ </weights>
3646+ <weighted_abscissa>
3647+ <scalar_field name="WeightedAbscissa_0" rank="0">
3648+ <prognostic>
3649+ <mesh name="VelocityMesh"/>
3650+ <equation name="AdvectionDiffusion"/>
3651+ <spatial_discretisation>
3652+ <continuous_galerkin>
3653+ <stabilisation>
3654+ <no_stabilisation/>
3655+ </stabilisation>
3656+ <advection_terms>
3657+ <exclude_advection_terms/>
3658+ </advection_terms>
3659+ <mass_terms/>
3660+ </continuous_galerkin>
3661+ <conservative_advection>
3662+ <real_value rank="0">0.0</real_value>
3663+ </conservative_advection>
3664+ </spatial_discretisation>
3665+ <temporal_discretisation>
3666+ <theta>
3667+ <real_value rank="0">0.5</real_value>
3668+ </theta>
3669+ </temporal_discretisation>
3670+ <solver>
3671+ <iterative_method name="gmres">
3672+ <restart>
3673+ <integer_value rank="0">30</integer_value>
3674+ </restart>
3675+ </iterative_method>
3676+ <preconditioner name="sor"/>
3677+ <relative_error>
3678+ <real_value rank="0">1e-7</real_value>
3679+ </relative_error>
3680+ <max_iterations>
3681+ <integer_value rank="0">1000</integer_value>
3682+ </max_iterations>
3683+ <never_ignore_solver_failures/>
3684+ <diagnostics>
3685+ <monitors/>
3686+ </diagnostics>
3687+ </solver>
3688+ <initial_condition name="WholeMesh">
3689+ <python>
3690+ <string_value lines="20" type="code" language="python">def val(X,t):
3691+ return (0.99480625*1.13701522)</string_value>
3692+ </python>
3693+ </initial_condition>
3694+ <scalar_field name="Source" rank="0">
3695+ <diagnostic>
3696+ <algorithm name="Internal" material_phase_support="multiple"/>
3697+ <output/>
3698+ <stat/>
3699+ <detectors>
3700+ <include_in_detectors/>
3701+ </detectors>
3702+ </diagnostic>
3703+ </scalar_field>
3704+ <output/>
3705+ <stat/>
3706+ <convergence>
3707+ <include_in_convergence/>
3708+ </convergence>
3709+ <detectors>
3710+ <include_in_detectors/>
3711+ </detectors>
3712+ <steady_state>
3713+ <include_in_steady_state/>
3714+ </steady_state>
3715+ <consistent_interpolation/>
3716+ </prognostic>
3717+ </scalar_field>
3718+ <scalar_field name="WeightedAbscissa_1" rank="0">
3719+ <prognostic>
3720+ <mesh name="VelocityMesh"/>
3721+ <equation name="AdvectionDiffusion"/>
3722+ <spatial_discretisation>
3723+ <continuous_galerkin>
3724+ <stabilisation>
3725+ <no_stabilisation/>
3726+ </stabilisation>
3727+ <advection_terms>
3728+ <exclude_advection_terms/>
3729+ </advection_terms>
3730+ <mass_terms/>
3731+ </continuous_galerkin>
3732+ <conservative_advection>
3733+ <real_value rank="0">0.0</real_value>
3734+ </conservative_advection>
3735+ </spatial_discretisation>
3736+ <temporal_discretisation>
3737+ <theta>
3738+ <real_value rank="0">0.5</real_value>
3739+ </theta>
3740+ </temporal_discretisation>
3741+ <solver>
3742+ <iterative_method name="gmres">
3743+ <restart>
3744+ <integer_value rank="0">30</integer_value>
3745+ </restart>
3746+ </iterative_method>
3747+ <preconditioner name="sor"/>
3748+ <relative_error>
3749+ <real_value rank="0">1e-7</real_value>
3750+ </relative_error>
3751+ <max_iterations>
3752+ <integer_value rank="0">1000</integer_value>
3753+ </max_iterations>
3754+ <never_ignore_solver_failures/>
3755+ <diagnostics>
3756+ <monitors/>
3757+ </diagnostics>
3758+ </solver>
3759+ <initial_condition name="WholeMesh">
3760+ <python>
3761+ <string_value lines="20" type="code" language="python">def val(X,t):
3762+ return (0.00519377*-4.46492922)</string_value>
3763+ </python>
3764+ </initial_condition>
3765+ <scalar_field name="Source" rank="0">
3766+ <diagnostic>
3767+ <algorithm name="Internal" material_phase_support="multiple"/>
3768+ <output/>
3769+ <stat/>
3770+ <detectors>
3771+ <include_in_detectors/>
3772+ </detectors>
3773+ </diagnostic>
3774+ </scalar_field>
3775+ <output/>
3776+ <stat/>
3777+ <convergence>
3778+ <include_in_convergence/>
3779+ </convergence>
3780+ <detectors>
3781+ <include_in_detectors/>
3782+ </detectors>
3783+ <steady_state>
3784+ <include_in_steady_state/>
3785+ </steady_state>
3786+ <consistent_interpolation/>
3787+ </prognostic>
3788+ </scalar_field>
3789+ </weighted_abscissa>
3790+ <adv_diff_source_term_interpolation>
3791+ <use_mass_lumping/>
3792+ </adv_diff_source_term_interpolation>
3793+ <moments>
3794+ <scalar_field name="Moment_0" rank="0">
3795+ <diagnostic>
3796+ <algorithm name="Internal" material_phase_support="multiple"/>
3797+ <mesh name="VelocityMesh"/>
3798+ <initial_condition name="WholeMesh">
3799+ <constant>
3800+ <real_value rank="0">1.0</real_value>
3801+ </constant>
3802+ </initial_condition>
3803+ <output/>
3804+ <stat/>
3805+ <convergence>
3806+ <include_in_convergence/>
3807+ </convergence>
3808+ <detectors>
3809+ <include_in_detectors/>
3810+ </detectors>
3811+ <steady_state>
3812+ <include_in_steady_state/>
3813+ </steady_state>
3814+ </diagnostic>
3815+ </scalar_field>
3816+ <scalar_field name="Moment_1" rank="0">
3817+ <diagnostic>
3818+ <algorithm name="Internal" material_phase_support="multiple"/>
3819+ <mesh name="VelocityMesh"/>
3820+ <initial_condition name="WholeMesh">
3821+ <python>
3822+ <string_value lines="20" type="code" language="python">def val(X,t):
3823+ from math import gamma, pi
3824+ mom1 = (6./pi)**(1./3.) * gamma(4./3.)
3825+ return mom1</string_value>
3826+ </python>
3827+ </initial_condition>
3828+ <output/>
3829+ <stat/>
3830+ <convergence>
3831+ <include_in_convergence/>
3832+ </convergence>
3833+ <detectors>
3834+ <include_in_detectors/>
3835+ </detectors>
3836+ <steady_state>
3837+ <include_in_steady_state/>
3838+ </steady_state>
3839+ </diagnostic>
3840+ </scalar_field>
3841+ <scalar_field name="Moment_2" rank="0">
3842+ <diagnostic>
3843+ <algorithm name="Internal" material_phase_support="multiple"/>
3844+ <mesh name="VelocityMesh"/>
3845+ <initial_condition name="WholeMesh">
3846+ <python>
3847+ <string_value lines="20" type="code" language="python">def val(X,t):
3848+ from math import gamma, pi
3849+ mom2 = (6./pi)**(2./3.) * gamma(5./3.)
3850+ return mom2</string_value>
3851+ </python>
3852+ </initial_condition>
3853+ <output/>
3854+ <stat/>
3855+ <convergence>
3856+ <include_in_convergence/>
3857+ </convergence>
3858+ <detectors>
3859+ <include_in_detectors/>
3860+ </detectors>
3861+ <steady_state>
3862+ <include_in_steady_state/>
3863+ </steady_state>
3864+ </diagnostic>
3865+ </scalar_field>
3866+ <scalar_field name="Moment_3" rank="0">
3867+ <diagnostic>
3868+ <algorithm name="Internal" material_phase_support="multiple"/>
3869+ <mesh name="VelocityMesh"/>
3870+ <initial_condition name="WholeMesh">
3871+ <python>
3872+ <string_value lines="20" type="code" language="python">def val(X,t):
3873+ from math import pi
3874+ mom3 = (6./pi)
3875+ return mom3</string_value>
3876+ </python>
3877+ </initial_condition>
3878+ <output/>
3879+ <stat/>
3880+ <convergence>
3881+ <include_in_convergence/>
3882+ </convergence>
3883+ <detectors>
3884+ <include_in_detectors/>
3885+ </detectors>
3886+ <steady_state>
3887+ <include_in_steady_state/>
3888+ </steady_state>
3889+ </diagnostic>
3890+ </scalar_field>
3891+ </moments>
3892+ <statistics/>
3893+ <population_balance_source_terms>
3894+ <aggregation>
3895+ <aggregation_frequency>
3896+ <constant_aggregation>
3897+ <real_value rank="0">1.0</real_value>
3898+ </constant_aggregation>
3899+ </aggregation_frequency>
3900+ </aggregation>
3901+ <breakage>
3902+ <breakage_frequency>
3903+ <power_law_breakage>
3904+ <coefficient>
3905+ <real_value rank="0">26.17993878</real_value>
3906+ </coefficient>
3907+ <degree>
3908+ <real_value rank="0">3</real_value>
3909+ </degree>
3910+ </power_law_breakage>
3911+ </breakage_frequency>
3912+ <distribution_function>
3913+ <mcCoy_madras_2003/>
3914+ </distribution_function>
3915+ </breakage>
3916+ </population_balance_source_terms>
3917+ <ill_conditioned_matrices>
3918+ <required_condition_number>
3919+ <real_value rank="0">1.0e-12</real_value>
3920+ </required_condition_number>
3921+ <set_source_to_zero/>
3922+ </ill_conditioned_matrices>
3923+ <minimum_weight>
3924+ <real_value rank="0">1e-10</real_value>
3925+ </minimum_weight>
3926+ </population_balance>
3927+ </material_phase>
3928+</fluidity_options>
3929
3930=== added file 'tests/popbal_homog_brk_aggr/popbal_homog_N2_brk_aggr.xml'
3931--- tests/popbal_homog_brk_aggr/popbal_homog_N2_brk_aggr.xml 1970-01-01 00:00:00 +0000
3932+++ tests/popbal_homog_brk_aggr/popbal_homog_N2_brk_aggr.xml 2013-12-12 22:35:40 +0000
3933@@ -0,0 +1,34 @@
3934+<?xml version='1.0' encoding='utf-8'?>
3935+<testproblem>
3936+ <name>Transient population balance using direct quadrature method of moments (N=2) for a homogeneous case with breakage and aggregation (McCoy and Madras (2003))</name>
3937+ <owner userid="gb812"/>
3938+ <tags>flml</tags>
3939+ <problem_definition length="medium" nprocs="1">
3940+ <command_line>fluidity popbal_homog_N2.flml</command_line>
3941+ </problem_definition>
3942+ <variables>
3943+ <variable name="solvers_converged" language="python">import os
3944+files = os.listdir("./")
3945+solvers_converged = not "matrixdump" in files and not "matrixdump.info" in files</variable>
3946+ <variable name="moment0_maxerror_t_5s" language="python">from fluidity_tools import stat_parser
3947+s = stat_parser("popbal_homog_N2_brk_aggr.stat")
3948+moment0_maxerror_t_5s = s["fluid"]["diff_m0"]["max"][-1]</variable>
3949+ <variable name="moment1_maxerror_t_5s" language="python">from fluidity_tools import stat_parser
3950+s = stat_parser("popbal_homog_N2_brk_aggr.stat")
3951+moment1_maxerror_t_5s = s["fluid"]["diff_m1"]["max"][-1]</variable>
3952+ <variable name="moment2_maxerror_t_5s" language="python">from fluidity_tools import stat_parser
3953+s = stat_parser("popbal_homog_N2_brk_aggr.stat")
3954+moment2_maxerror_t_5s = s["fluid"]["diff_m2"]["max"][-1]</variable>
3955+ <variable name="moment3_maxerror_t_5s" language="python">from fluidity_tools import stat_parser
3956+s = stat_parser("popbal_homog_N2_brk_aggr.stat")
3957+moment3_maxerror_t_5s = s["fluid"]["diff_m3"]["max"][-1]</variable>
3958+ </variables>
3959+ <pass_tests>
3960+ <test name="Solvers converged" language="python">assert(solvers_converged)</test>
3961+ <test name="moment0 max percent error at 5s less than 0.006" language="python">assert moment0_maxerror_t_5s &lt; 0.006</test>
3962+ <test name="moment1 max percent error at 5s less than 0.003" language="python">assert moment1_maxerror_t_5s &lt; 0.003</test>
3963+ <test name="moment2 max percent error at 5s less than 0.003" language="python">assert moment2_maxerror_t_5s &lt; 0.003</test>
3964+ <test name="moment3 max percent error at 5s less than 0.01" language="python">assert moment3_maxerror_t_5s &lt; 0.01</test>
3965+ </pass_tests>
3966+ <warn_tests/>
3967+</testproblem>
3968
3969=== added directory 'tests/popbal_homog_brk_aggr/src'
3970=== added file 'tests/popbal_homog_brk_aggr/src/minimal.geo'
3971--- tests/popbal_homog_brk_aggr/src/minimal.geo 1970-01-01 00:00:00 +0000
3972+++ tests/popbal_homog_brk_aggr/src/minimal.geo 2013-12-12 22:35:40 +0000
3973@@ -0,0 +1,28 @@
3974+$MeshFormat
3975+2.2 0 8
3976+$EndMeshFormat
3977+$Nodes
3978+7
3979+1 0 0 0
3980+2 1 0 0
3981+3 1 1 0
3982+4 0.4999999999990216 0 0
3983+5 1 0.4999999999990216 0
3984+6 0.5000000000013878 0.5000000000013878 0
3985+7 0.7499999999999051 0.2499999999999052 0
3986+$EndNodes
3987+$Elements
3988+12
3989+1 1 2 6 1 1 4
3990+2 1 2 6 1 4 2
3991+3 1 2 6 2 2 5
3992+4 1 2 6 2 5 3
3993+5 1 2 6 3 3 6
3994+6 1 2 6 3 6 1
3995+7 2 2 7 5 4 7 6
3996+8 2 2 7 5 2 7 4
3997+9 2 2 7 5 2 5 7
3998+10 2 2 7 5 5 6 7
3999+11 2 2 7 5 5 3 6
4000+12 2 2 7 5 4 6 1
4001+$EndElements
4002
4003=== added directory 'tests/popbal_nonhomog2_2d_adapt'
4004=== added file 'tests/popbal_nonhomog2_2d_adapt/Makefile'
4005--- tests/popbal_nonhomog2_2d_adapt/Makefile 1970-01-01 00:00:00 +0000
4006+++ tests/popbal_nonhomog2_2d_adapt/Makefile 2013-12-12 22:35:40 +0000
4007@@ -0,0 +1,5 @@
4008+input: clean
4009+ gmsh -2 src/channel.geo -optimize
4010+
4011+clean:
4012+ rm -f *.vtu *.pvtu fluidity.* *.s *.d.1 *.stat src/channel.msh
4013
4014=== added file 'tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.flml'
4015--- tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.flml 1970-01-01 00:00:00 +0000
4016+++ tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.flml 2013-12-12 22:35:40 +0000
4017@@ -0,0 +1,670 @@
4018+<?xml version='1.0' encoding='utf-8'?>
4019+<fluidity_options>
4020+ <simulation_name>
4021+ <string_value lines="1">popbal_nonhomog2_2d</string_value>
4022+ </simulation_name>
4023+ <problem_type>
4024+ <string_value lines="1">fluids</string_value>
4025+ </problem_type>
4026+ <geometry>
4027+ <dimension>
4028+ <integer_value rank="0">2</integer_value>
4029+ </dimension>
4030+ <mesh name="CoordinateMesh">
4031+ <from_file file_name="./src/channel">
4032+ <format name="gmsh"/>
4033+ <stat>
4034+ <include_in_stat/>
4035+ </stat>
4036+ </from_file>
4037+ </mesh>
4038+ <mesh name="VelocityMesh">
4039+ <from_mesh>
4040+ <mesh name="CoordinateMesh"/>
4041+ <mesh_shape>
4042+ <polynomial_degree>
4043+ <integer_value rank="0">1</integer_value>
4044+ </polynomial_degree>
4045+ </mesh_shape>
4046+ <mesh_continuity>
4047+ <string_value>continuous</string_value>
4048+ </mesh_continuity>
4049+ <stat>
4050+ <exclude_from_stat/>
4051+ </stat>
4052+ </from_mesh>
4053+ </mesh>
4054+ <quadrature>
4055+ <degree>
4056+ <integer_value rank="0">3</integer_value>
4057+ </degree>
4058+ </quadrature>
4059+ </geometry>
4060+ <io>
4061+ <dump_format>
4062+ <string_value>vtk</string_value>
4063+ </dump_format>
4064+ <dump_period>
4065+ <constant>
4066+ <real_value rank="0">1</real_value>
4067+ </constant>
4068+ </dump_period>
4069+ <output_mesh name="VelocityMesh"/>
4070+ <stat/>
4071+ </io>
4072+ <timestepping>
4073+ <current_time>
4074+ <real_value rank="0">0.0</real_value>
4075+ </current_time>
4076+ <timestep>
4077+ <real_value rank="0">0.005</real_value>
4078+ </timestep>
4079+ <finish_time>
4080+ <real_value rank="0">20</real_value>
4081+ </finish_time>
4082+ </timestepping>
4083+ <material_phase name="fluid">
4084+ <vector_field name="Velocity" rank="1">
4085+ <prescribed>
4086+ <mesh name="VelocityMesh"/>
4087+ <value name="WholeMesh">
4088+ <constant>
4089+ <real_value shape="2" dim1="dim" rank="1">0 0</real_value>
4090+ </constant>
4091+ </value>
4092+ <output/>
4093+ <stat>
4094+ <include_in_stat/>
4095+ </stat>
4096+ <detectors>
4097+ <exclude_from_detectors/>
4098+ </detectors>
4099+ </prescribed>
4100+ </vector_field>
4101+ <scalar_field name="m3_analytical" rank="0">
4102+ <prescribed>
4103+ <mesh name="VelocityMesh"/>
4104+ <value name="WholeMesh">
4105+ <python>
4106+ <string_value lines="20" type="code" language="python">def val(X,t):
4107+ from math import exp, pi, cos
4108+ if (abs(t-round(t))&lt;=0.01):
4109+ nu=0.001
4110+ L=1.0
4111+ n=100
4112+ phi_n=0.0
4113+ i=1
4114+ while i&lt;=n:
4115+ j=2*i
4116+ val = (1.0/j**2)*exp(-(nu*j**2*pi**2*t)/(L**2))*cos((j*pi*X[0])/L)
4117+ phi_n = phi_n + val
4118+ i=i+1
4119+ phi_n = phi_n*(-4.0/pi**2) + 1.0/6.0
4120+ return phi_n
4121+ else:
4122+ return 0.0</string_value>
4123+ </python>
4124+ </value>
4125+ <output/>
4126+ <stat/>
4127+ <detectors>
4128+ <exclude_from_detectors/>
4129+ </detectors>
4130+ </prescribed>
4131+ </scalar_field>
4132+ <scalar_field name="ScalarAbsoluteDifference" rank="0">
4133+ <diagnostic field_name_b="m3_analytical" field_name_a="Moment_3">
4134+ <algorithm name="Internal" material_phase_support="multiple"/>
4135+ <mesh name="VelocityMesh"/>
4136+ <output/>
4137+ <stat/>
4138+ <convergence>
4139+ <exclude_from_convergence/>
4140+ </convergence>
4141+ <detectors>
4142+ <exclude_from_detectors/>
4143+ </detectors>
4144+ <steady_state>
4145+ <exclude_from_steady_state/>
4146+ </steady_state>
4147+ </diagnostic>
4148+ </scalar_field>
4149+ <population_balance name="DQMOM">
4150+ <use_prognostic_field_initial_conditions/>
4151+ <abscissa>
4152+ <scalar_field name="Abscissa_0" rank="0">
4153+ <diagnostic>
4154+ <algorithm name="Internal" material_phase_support="multiple"/>
4155+ <mesh name="VelocityMesh"/>
4156+ <output/>
4157+ <stat/>
4158+ <convergence>
4159+ <include_in_convergence/>
4160+ </convergence>
4161+ <detectors>
4162+ <include_in_detectors/>
4163+ </detectors>
4164+ <steady_state>
4165+ <include_in_steady_state/>
4166+ </steady_state>
4167+ <consistent_interpolation/>
4168+ </diagnostic>
4169+ </scalar_field>
4170+ <scalar_field name="Abscissa_1" rank="0">
4171+ <diagnostic>
4172+ <algorithm name="Internal" material_phase_support="multiple"/>
4173+ <mesh name="VelocityMesh"/>
4174+ <output/>
4175+ <stat/>
4176+ <convergence>
4177+ <include_in_convergence/>
4178+ </convergence>
4179+ <detectors>
4180+ <include_in_detectors/>
4181+ </detectors>
4182+ <steady_state>
4183+ <include_in_steady_state/>
4184+ </steady_state>
4185+ <consistent_interpolation/>
4186+ </diagnostic>
4187+ </scalar_field>
4188+ </abscissa>
4189+ <weights>
4190+ <scalar_field name="Weight_0" rank="0">
4191+ <prognostic>
4192+ <mesh name="VelocityMesh"/>
4193+ <equation name="AdvectionDiffusion"/>
4194+ <spatial_discretisation>
4195+ <continuous_galerkin>
4196+ <stabilisation>
4197+ <no_stabilisation/>
4198+ </stabilisation>
4199+ <advection_terms/>
4200+ <mass_terms/>
4201+ </continuous_galerkin>
4202+ <conservative_advection>
4203+ <real_value rank="0">0.0</real_value>
4204+ </conservative_advection>
4205+ </spatial_discretisation>
4206+ <temporal_discretisation>
4207+ <theta>
4208+ <real_value rank="0">0.5</real_value>
4209+ </theta>
4210+ </temporal_discretisation>
4211+ <solver>
4212+ <iterative_method name="gmres">
4213+ <restart>
4214+ <integer_value rank="0">30</integer_value>
4215+ </restart>
4216+ </iterative_method>
4217+ <preconditioner name="sor"/>
4218+ <relative_error>
4219+ <real_value rank="0">1e-7</real_value>
4220+ </relative_error>
4221+ <max_iterations>
4222+ <integer_value rank="0">1000</integer_value>
4223+ </max_iterations>
4224+ <never_ignore_solver_failures/>
4225+ <diagnostics>
4226+ <monitors/>
4227+ </diagnostics>
4228+ </solver>
4229+ <initial_condition name="WholeMesh">
4230+ <constant>
4231+ <real_value rank="0">0.5</real_value>
4232+ </constant>
4233+ </initial_condition>
4234+ <tensor_field name="Diffusivity" rank="2">
4235+ <prescribed>
4236+ <value name="WholeMesh">
4237+ <isotropic>
4238+ <constant>
4239+ <real_value rank="0">1e-3</real_value>
4240+ </constant>
4241+ </isotropic>
4242+ </value>
4243+ <output/>
4244+ </prescribed>
4245+ </tensor_field>
4246+ <scalar_field name="Source" rank="0">
4247+ <diagnostic>
4248+ <algorithm name="Internal" material_phase_support="multiple"/>
4249+ <output/>
4250+ <stat/>
4251+ <detectors>
4252+ <include_in_detectors/>
4253+ </detectors>
4254+ </diagnostic>
4255+ </scalar_field>
4256+ <output/>
4257+ <stat/>
4258+ <convergence>
4259+ <include_in_convergence/>
4260+ </convergence>
4261+ <detectors>
4262+ <include_in_detectors/>
4263+ </detectors>
4264+ <steady_state>
4265+ <include_in_steady_state/>
4266+ </steady_state>
4267+ <consistent_interpolation/>
4268+ </prognostic>
4269+ </scalar_field>
4270+ <scalar_field name="Weight_1" rank="0">
4271+ <prognostic>
4272+ <mesh name="VelocityMesh"/>
4273+ <equation name="AdvectionDiffusion"/>
4274+ <spatial_discretisation>
4275+ <continuous_galerkin>
4276+ <stabilisation>
4277+ <no_stabilisation/>
4278+ </stabilisation>
4279+ <advection_terms/>
4280+ <mass_terms/>
4281+ </continuous_galerkin>
4282+ <conservative_advection>
4283+ <real_value rank="0">0.0</real_value>
4284+ </conservative_advection>
4285+ </spatial_discretisation>
4286+ <temporal_discretisation>
4287+ <theta>
4288+ <real_value rank="0">0.5</real_value>
4289+ </theta>
4290+ </temporal_discretisation>
4291+ <solver>
4292+ <iterative_method name="gmres">
4293+ <restart>
4294+ <integer_value rank="0">30</integer_value>
4295+ </restart>
4296+ </iterative_method>
4297+ <preconditioner name="sor"/>
4298+ <relative_error>
4299+ <real_value rank="0">1e-7</real_value>
4300+ </relative_error>
4301+ <max_iterations>
4302+ <integer_value rank="0">1000</integer_value>
4303+ </max_iterations>
4304+ <never_ignore_solver_failures/>
4305+ <diagnostics>
4306+ <monitors/>
4307+ </diagnostics>
4308+ </solver>
4309+ <initial_condition name="WholeMesh">
4310+ <constant>
4311+ <real_value rank="0">0.5</real_value>
4312+ </constant>
4313+ </initial_condition>
4314+ <tensor_field name="Diffusivity" rank="2">
4315+ <prescribed>
4316+ <value name="WholeMesh">
4317+ <isotropic>
4318+ <constant>
4319+ <real_value rank="0">1e-3</real_value>
4320+ </constant>
4321+ </isotropic>
4322+ </value>
4323+ <output/>
4324+ </prescribed>
4325+ </tensor_field>
4326+ <scalar_field name="Source" rank="0">
4327+ <diagnostic>
4328+ <algorithm name="Internal" material_phase_support="multiple"/>
4329+ <output/>
4330+ <stat/>
4331+ <detectors>
4332+ <include_in_detectors/>
4333+ </detectors>
4334+ </diagnostic>
4335+ </scalar_field>
4336+ <output/>
4337+ <stat/>
4338+ <convergence>
4339+ <include_in_convergence/>
4340+ </convergence>
4341+ <detectors>
4342+ <include_in_detectors/>
4343+ </detectors>
4344+ <steady_state>
4345+ <include_in_steady_state/>
4346+ </steady_state>
4347+ <consistent_interpolation/>
4348+ </prognostic>
4349+ </scalar_field>
4350+ </weights>
4351+ <weighted_abscissa>
4352+ <scalar_field name="WeightedAbscissa_0" rank="0">
4353+ <prognostic>
4354+ <mesh name="VelocityMesh"/>
4355+ <equation name="AdvectionDiffusion"/>
4356+ <spatial_discretisation>
4357+ <continuous_galerkin>
4358+ <stabilisation>
4359+ <no_stabilisation/>
4360+ </stabilisation>
4361+ <advection_terms/>
4362+ <mass_terms/>
4363+ </continuous_galerkin>
4364+ <conservative_advection>
4365+ <real_value rank="0">0.0</real_value>
4366+ </conservative_advection>
4367+ </spatial_discretisation>
4368+ <temporal_discretisation>
4369+ <theta>
4370+ <real_value rank="0">0.5</real_value>
4371+ </theta>
4372+ </temporal_discretisation>
4373+ <solver>
4374+ <iterative_method name="gmres">
4375+ <restart>
4376+ <integer_value rank="0">30</integer_value>
4377+ </restart>
4378+ </iterative_method>
4379+ <preconditioner name="sor"/>
4380+ <relative_error>
4381+ <real_value rank="0">1e-7</real_value>
4382+ </relative_error>
4383+ <max_iterations>
4384+ <integer_value rank="0">1000</integer_value>
4385+ </max_iterations>
4386+ <never_ignore_solver_failures/>
4387+ <diagnostics>
4388+ <monitors/>
4389+ </diagnostics>
4390+ </solver>
4391+ <initial_condition name="WholeMesh">
4392+ <python>
4393+ <string_value lines="20" type="code" language="python">def val(X, t):
4394+ zeta1=0.5* (1.0 + 2.0*X[0]*(1-X[0]))**(1.0/3.0)
4395+ return zeta1</string_value>
4396+ </python>
4397+ </initial_condition>
4398+ <tensor_field name="Diffusivity" rank="2">
4399+ <prescribed>
4400+ <value name="WholeMesh">
4401+ <isotropic>
4402+ <constant>
4403+ <real_value rank="0">1e-3</real_value>
4404+ </constant>
4405+ </isotropic>
4406+ </value>
4407+ <output/>
4408+ </prescribed>
4409+ </tensor_field>
4410+ <scalar_field name="Source" rank="0">
4411+ <diagnostic>
4412+ <algorithm name="Internal" material_phase_support="multiple"/>
4413+ <output/>
4414+ <stat/>
4415+ <detectors>
4416+ <include_in_detectors/>
4417+ </detectors>
4418+ </diagnostic>
4419+ </scalar_field>
4420+ <output/>
4421+ <stat/>
4422+ <convergence>
4423+ <include_in_convergence/>
4424+ </convergence>
4425+ <detectors>
4426+ <include_in_detectors/>
4427+ </detectors>
4428+ <steady_state>
4429+ <include_in_steady_state/>
4430+ </steady_state>
4431+ <consistent_interpolation/>
4432+ </prognostic>
4433+ </scalar_field>
4434+ <scalar_field name="WeightedAbscissa_1" rank="0">
4435+ <prognostic>
4436+ <mesh name="VelocityMesh"/>
4437+ <equation name="AdvectionDiffusion"/>
4438+ <spatial_discretisation>
4439+ <continuous_galerkin>
4440+ <stabilisation>
4441+ <no_stabilisation/>
4442+ </stabilisation>
4443+ <advection_terms/>
4444+ <mass_terms/>
4445+ </continuous_galerkin>
4446+ <conservative_advection>
4447+ <real_value rank="0">0.0</real_value>
4448+ </conservative_advection>
4449+ </spatial_discretisation>
4450+ <temporal_discretisation>
4451+ <theta>
4452+ <real_value rank="0">0.5</real_value>
4453+ </theta>
4454+ </temporal_discretisation>
4455+ <solver>
4456+ <iterative_method name="gmres">
4457+ <restart>
4458+ <integer_value rank="0">30</integer_value>
4459+ </restart>
4460+ </iterative_method>
4461+ <preconditioner name="sor"/>
4462+ <relative_error>
4463+ <real_value rank="0">1e-7</real_value>
4464+ </relative_error>
4465+ <max_iterations>
4466+ <integer_value rank="0">1000</integer_value>
4467+ </max_iterations>
4468+ <never_ignore_solver_failures/>
4469+ <diagnostics>
4470+ <monitors/>
4471+ </diagnostics>
4472+ </solver>
4473+ <initial_condition name="WholeMesh">
4474+ <python>
4475+ <string_value lines="20" type="code" language="python">def val(X, t):
4476+ zeta2=0.5*(-1.0)
4477+ return zeta2</string_value>
4478+ </python>
4479+ </initial_condition>
4480+ <tensor_field name="Diffusivity" rank="2">
4481+ <prescribed>
4482+ <value name="WholeMesh">
4483+ <isotropic>
4484+ <constant>
4485+ <real_value rank="0">1e-3</real_value>
4486+ </constant>
4487+ </isotropic>
4488+ </value>
4489+ <output/>
4490+ </prescribed>
4491+ </tensor_field>
4492+ <scalar_field name="Source" rank="0">
4493+ <diagnostic>
4494+ <algorithm name="Internal" material_phase_support="multiple"/>
4495+ <output/>
4496+ <stat/>
4497+ <detectors>
4498+ <include_in_detectors/>
4499+ </detectors>
4500+ </diagnostic>
4501+ </scalar_field>
4502+ <output/>
4503+ <stat/>
4504+ <convergence>
4505+ <include_in_convergence/>
4506+ </convergence>
4507+ <detectors>
4508+ <include_in_detectors/>
4509+ </detectors>
4510+ <steady_state>
4511+ <include_in_steady_state/>
4512+ </steady_state>
4513+ <consistent_interpolation/>
4514+ </prognostic>
4515+ </scalar_field>
4516+ </weighted_abscissa>
4517+ <adv_diff_source_term_interpolation>
4518+ <use_mass_lumping/>
4519+ </adv_diff_source_term_interpolation>
4520+ <moments>
4521+ <scalar_field name="Moment_0" rank="0">
4522+ <diagnostic>
4523+ <algorithm name="Internal" material_phase_support="multiple"/>
4524+ <mesh name="VelocityMesh"/>
4525+ <initial_condition name="WholeMesh">
4526+ <python>
4527+ <string_value lines="20" type="code" language="python">def val(X, t):
4528+ if X[0] &lt; 0.5:
4529+ return 0.6
4530+ else:
4531+ return 0.4</string_value>
4532+ </python>
4533+ </initial_condition>
4534+ <output/>
4535+ <stat/>
4536+ <convergence>
4537+ <include_in_convergence/>
4538+ </convergence>
4539+ <detectors>
4540+ <include_in_detectors/>
4541+ </detectors>
4542+ <steady_state>
4543+ <include_in_steady_state/>
4544+ </steady_state>
4545+ <consistent_interpolation/>
4546+ </diagnostic>
4547+ </scalar_field>
4548+ <scalar_field name="Moment_1" rank="0">
4549+ <diagnostic>
4550+ <algorithm name="Internal" material_phase_support="multiple"/>
4551+ <mesh name="VelocityMesh"/>
4552+ <initial_condition name="WholeMesh">
4553+ <python>
4554+ <string_value lines="20" type="code" language="python">def val(X, t):
4555+ if X[0] &lt; 0.5:
4556+ return 1.0
4557+ else:
4558+ return 1.5</string_value>
4559+ </python>
4560+ </initial_condition>
4561+ <output/>
4562+ <stat/>
4563+ <convergence>
4564+ <include_in_convergence/>
4565+ </convergence>
4566+ <detectors>
4567+ <include_in_detectors/>
4568+ </detectors>
4569+ <steady_state>
4570+ <include_in_steady_state/>
4571+ </steady_state>
4572+ <consistent_interpolation/>
4573+ </diagnostic>
4574+ </scalar_field>
4575+ <scalar_field name="Moment_2" rank="0">
4576+ <diagnostic>
4577+ <algorithm name="Internal" material_phase_support="multiple"/>
4578+ <mesh name="VelocityMesh"/>
4579+ <initial_condition name="WholeMesh">
4580+ <constant>
4581+ <real_value rank="0">4.0</real_value>
4582+ </constant>
4583+ </initial_condition>
4584+ <output/>
4585+ <stat/>
4586+ <convergence>
4587+ <include_in_convergence/>
4588+ </convergence>
4589+ <detectors>
4590+ <include_in_detectors/>
4591+ </detectors>
4592+ <steady_state>
4593+ <include_in_steady_state/>
4594+ </steady_state>
4595+ <consistent_interpolation/>
4596+ </diagnostic>
4597+ </scalar_field>
4598+ <scalar_field name="Moment_3" rank="0">
4599+ <diagnostic>
4600+ <algorithm name="Internal" material_phase_support="multiple"/>
4601+ <mesh name="VelocityMesh"/>
4602+ <initial_condition name="WholeMesh">
4603+ <constant>
4604+ <real_value rank="0">12.0</real_value>
4605+ </constant>
4606+ </initial_condition>
4607+ <output/>
4608+ <stat/>
4609+ <convergence>
4610+ <include_in_convergence/>
4611+ </convergence>
4612+ <detectors>
4613+ <include_in_detectors/>
4614+ </detectors>
4615+ <steady_state>
4616+ <include_in_steady_state/>
4617+ </steady_state>
4618+ <adaptivity_options>
4619+ <absolute_measure>
4620+ <scalar_field name="InterpolationErrorBound" rank="0">
4621+ <prescribed>
4622+ <value name="WholeMesh">
4623+ <constant>
4624+ <real_value rank="0">0.001</real_value>
4625+ </constant>
4626+ </value>
4627+ <output/>
4628+ <stat/>
4629+ <detectors>
4630+ <exclude_from_detectors/>
4631+ </detectors>
4632+ </prescribed>
4633+ </scalar_field>
4634+ <p_norm>
4635+ <integer_value rank="0">2</integer_value>
4636+ </p_norm>
4637+ </absolute_measure>
4638+ </adaptivity_options>
4639+ <consistent_interpolation/>
4640+ </diagnostic>
4641+ </scalar_field>
4642+ </moments>
4643+ <statistics/>
4644+ <population_balance_source_terms/>
4645+ <ill_conditioned_matrices>
4646+ <required_condition_number>
4647+ <real_value rank="0">1e-12</real_value>
4648+ </required_condition_number>
4649+ <set_source_to_zero/>
4650+ </ill_conditioned_matrices>
4651+ <minimum_weight>
4652+ <real_value rank="0">1e-10</real_value>
4653+ </minimum_weight>
4654+ </population_balance>
4655+ </material_phase>
4656+ <mesh_adaptivity>
4657+ <hr_adaptivity>
4658+ <period_in_timesteps>
4659+ <integer_value rank="0">20</integer_value>
4660+ </period_in_timesteps>
4661+ <maximum_number_of_nodes>
4662+ <integer_value rank="0">20000</integer_value>
4663+ </maximum_number_of_nodes>
4664+ <enable_gradation/>
4665+ <tensor_field name="MinimumEdgeLengths">
4666+ <anisotropic_symmetric>
4667+ <constant>
4668+ <real_value symmetric="true" dim2="dim" shape="2 2" dim1="dim" rank="2">0.001 0.00 0.00 0.001</real_value>
4669+ </constant>
4670+ </anisotropic_symmetric>
4671+ </tensor_field>
4672+ <tensor_field name="MaximumEdgeLengths">
4673+ <anisotropic_symmetric>
4674+ <constant>
4675+ <real_value symmetric="true" dim2="dim" shape="2 2" dim1="dim" rank="2">0.1 0.0 0.0 0.1</real_value>
4676+ </constant>
4677+ </anisotropic_symmetric>
4678+ </tensor_field>
4679+ <adapt_at_first_timestep>
4680+ <number_of_adapts>
4681+ <integer_value rank="0">4</integer_value>
4682+ </number_of_adapts>
4683+ </adapt_at_first_timestep>
4684+ <debug/>
4685+ </hr_adaptivity>
4686+ </mesh_adaptivity>
4687+</fluidity_options>
4688
4689=== added file 'tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.xml'
4690--- tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.xml 1970-01-01 00:00:00 +0000
4691+++ tests/popbal_nonhomog2_2d_adapt/popbal_nonhomog2_2d_adapt.xml 2013-12-12 22:35:40 +0000
4692@@ -0,0 +1,46 @@
4693+<?xml version='1.0' encoding='utf-8'?>
4694+<testproblem>
4695+ <name>Transient population balance using direct quadrature method of moments (N=2) for 2d mesh using P1 CG using ADAPTIVITY</name>
4696+ <owner userid="gb812"/>
4697+ <tags>flml</tags>
4698+ <problem_definition length="medium" nprocs="1">
4699+ <command_line>fluidity popbal_nonhomog2_2d_adapt.flml</command_line>
4700+ </problem_definition>
4701+ <variables>
4702+ <variable name="solvers_converged" language="python">import os
4703+files = os.listdir("./")
4704+solvers_converged = not "matrixdump" in files and not "matrixdump.info" in files</variable>
4705+ <variable name="moment3_L2error_t_5s" language="python">from fluidity_tools import stat_parser
4706+s = stat_parser("popbal_nonhomog2_2d.stat")
4707+timestep=0.005
4708+t=5.0
4709+index_time_for_norm=((1.0/timestep)*t)-1
4710+moment3_L2error_t_5s = s["fluid"]["ScalarAbsoluteDifference"]["l2norm"][index_time_for_norm]</variable>
4711+ <variable name="moment3_L2error_t_20s" language="python">from fluidity_tools import stat_parser
4712+s = stat_parser("popbal_nonhomog2_2d.stat")
4713+timestep=0.005
4714+t=20.0
4715+index_time_for_norm=((1.0/timestep)*t)-1
4716+moment3_L2error_t_20s = s["fluid"]["ScalarAbsoluteDifference"]["l2norm"][index_time_for_norm]</variable>
4717+ <variable name="moment3_maxerror_t_5s" language="python">from fluidity_tools import stat_parser
4718+s = stat_parser("popbal_nonhomog2_2d.stat")
4719+timestep=0.005
4720+t=5.0
4721+index_time_for_norm=((1.0/timestep)*t)-1
4722+moment3_maxerror_t_5s = s["fluid"]["ScalarAbsoluteDifference"]["max"][index_time_for_norm]</variable>
4723+ <variable name="moment3_maxerror_t_20s" language="python">from fluidity_tools import stat_parser
4724+s = stat_parser("popbal_nonhomog2_2d.stat")
4725+timestep=0.005
4726+t=20.0
4727+index_time_for_norm=((1.0/timestep)*t)-1
4728+moment3_maxerror_t_20s = s["fluid"]["ScalarAbsoluteDifference"]["max"][index_time_for_norm]</variable>
4729+ </variables>
4730+ <pass_tests>
4731+ <test name="Solvers converged" language="python">assert(solvers_converged)</test>
4732+ <test name="moment3 L2error at 5s less than 0.0001" language="python">assert moment3_L2error_t_5s &lt; 0.0001</test>
4733+ <test name="moment3 L2error at 20s less than 0.0001" language="python">assert moment3_L2error_t_20s &lt; 0.0001</test>
4734+ <test name="moment3 maxerror at 5s less than 0.001" language="python">assert moment3_maxerror_t_5s &lt; 0.001</test>
4735+ <test name="moment3 maxerror at 20s less than 0.001" language="python">assert moment3_maxerror_t_20s &lt; 0.001</test>
4736+ </pass_tests>
4737+ <warn_tests/>
4738+</testproblem>
4739
4740=== added file 'tests/popbal_nonhomog2_2d_adapt/readme'
4741--- tests/popbal_nonhomog2_2d_adapt/readme 1970-01-01 00:00:00 +0000
4742+++ tests/popbal_nonhomog2_2d_adapt/readme 2013-12-12 22:35:40 +0000
4743@@ -0,0 +1,13 @@
4744+quad=3
4745+2d
4746+CG
4747+p1
4748+unstructured grid cl=1/25
4749+lumped mass
4750+time=0:0.005:20
4751+vel=0, transient external diffusion only. Diffusion 2 with a parabolic initial condition
4752+only moment 3 compared to the analytical case
4753+analytical case derived using separation of variables
4754+N=2
4755+tests for L2error and max error at 5s and 20s
4756+adaptivity
4757
4758=== added directory 'tests/popbal_nonhomog2_2d_adapt/src'
4759=== added file 'tests/popbal_nonhomog2_2d_adapt/src/channel.geo'
4760--- tests/popbal_nonhomog2_2d_adapt/src/channel.geo 1970-01-01 00:00:00 +0000
4761+++ tests/popbal_nonhomog2_2d_adapt/src/channel.geo 2013-12-12 22:35:40 +0000
4762@@ -0,0 +1,16 @@
4763+cl1 = 1.0/25.0;
4764+Point(1) = {0, 0, 0, cl1};
4765+Point(2) = {1, 0, 0, cl1};
4766+Point(3) = {0, 1, 0, cl1};
4767+Point(4) = {1, 1, 0, cl1};
4768+Line(1) = {1, 2};
4769+Line(2) = {3, 4};
4770+Line(3) = {1, 3};
4771+Line(4) = {2, 4};
4772+Line Loop(5) = {1, 4, -2, -3};
4773+Ruled Surface(5) = {5};
4774+Physical Line(1) = {1};
4775+Physical Line(2) = {2};
4776+Physical Line(3) = {3};
4777+Physical Line(4) = {4};
4778+Physical Surface(6) = {5};
4779
4780=== added directory 'tests/popbal_nonhomog2_2d_cg_p1'
4781=== added file 'tests/popbal_nonhomog2_2d_cg_p1/Makefile'
4782--- tests/popbal_nonhomog2_2d_cg_p1/Makefile 1970-01-01 00:00:00 +0000
4783+++ tests/popbal_nonhomog2_2d_cg_p1/Makefile 2013-12-12 22:35:40 +0000
4784@@ -0,0 +1,5 @@
4785+input: clean
4786+ gmsh -2 src/channel.geo -optimize -bin
4787+
4788+clean:
4789+ rm -f *.vtu *.pvtu fluidity.* *.s *.d.1 *.stat src/channel.msh
4790
4791=== added file 'tests/popbal_nonhomog2_2d_cg_p1/popbal_nonhomog2_2d.flml'
4792--- tests/popbal_nonhomog2_2d_cg_p1/popbal_nonhomog2_2d.flml 1970-01-01 00:00:00 +0000
4793+++ tests/popbal_nonhomog2_2d_cg_p1/popbal_nonhomog2_2d.flml 2013-12-12 22:35:40 +0000
4794@@ -0,0 +1,614 @@
4795+<?xml version='1.0' encoding='utf-8'?>
4796+<fluidity_options>
4797+ <simulation_name>
4798+ <string_value lines="1">popbal_nonhomog2_2d</string_value>
4799+ </simulation_name>
4800+ <problem_type>
4801+ <string_value lines="1">fluids</string_value>
4802+ </problem_type>
4803+ <geometry>
4804+ <dimension>
4805+ <integer_value rank="0">2</integer_value>
4806+ </dimension>
4807+ <mesh name="CoordinateMesh">
4808+ <from_file file_name="./src/channel">
4809+ <format name="gmsh"/>
4810+ <stat>
4811+ <include_in_stat/>
4812+ </stat>
4813+ </from_file>
4814+ </mesh>
4815+ <mesh name="VelocityMesh">
4816+ <from_mesh>
4817+ <mesh name="CoordinateMesh"/>
4818+ <mesh_shape>
4819+ <polynomial_degree>
4820+ <integer_value rank="0">1</integer_value>
4821+ </polynomial_degree>
4822+ </mesh_shape>
4823+ <mesh_continuity>
4824+ <string_value>continuous</string_value>
4825+ </mesh_continuity>
4826+ <stat>
4827+ <exclude_from_stat/>
4828+ </stat>
4829+ </from_mesh>
4830+ </mesh>
4831+ <quadrature>
4832+ <degree>
4833+ <integer_value rank="0">3</integer_value>
4834+ </degree>
4835+ </quadrature>
4836+ </geometry>
4837+ <io>
4838+ <dump_format>
4839+ <string_value>vtk</string_value>
4840+ </dump_format>
4841+ <dump_period>
4842+ <constant>
4843+ <real_value rank="0">1</real_value>
4844+ </constant>
4845+ </dump_period>
4846+ <output_mesh name="VelocityMesh"/>
4847+ <stat/>
4848+ </io>
4849+ <timestepping>
4850+ <current_time>
4851+ <real_value rank="0">0.0</real_value>
4852+ </current_time>
4853+ <timestep>
4854+ <real_value rank="0">0.005</real_value>
4855+ </timestep>
4856+ <finish_time>
4857+ <real_value rank="0">20</real_value>
4858+ </finish_time>
4859+ </timestepping>
4860+ <material_phase name="fluid">
4861+ <vector_field name="Velocity" rank="1">
4862+ <prescribed>
4863+ <mesh name="VelocityMesh"/>
4864+ <value name="WholeMesh">
4865+ <constant>
4866+ <real_value shape="2" dim1="dim" rank="1">0 0</real_value>
4867+ </constant>
4868+ </value>
4869+ <output/>
4870+ <stat>
4871+ <include_in_stat/>
4872+ </stat>
4873+ <detectors>
4874+ <exclude_from_detectors/>
4875+ </detectors>
4876+ </prescribed>
4877+ </vector_field>
4878+ <scalar_field name="m3_analytical" rank="0">
4879+ <prescribed>
4880+ <mesh name="VelocityMesh"/>
4881+ <value name="WholeMesh">
4882+ <python>
4883+ <string_value lines="20" type="code" language="python">def val(X,t):
4884+ from math import exp, pi, cos
4885+ if (abs(t-round(t))&lt;=0.01):
4886+ nu=0.001
4887+ L=1.0
4888+ n=100
4889+ phi_n=0.0
4890+ i=1
4891+ while i&lt;=n:
4892+ j=2*i
4893+ val = (1.0/j**2)*exp(-(nu*j**2*pi**2*t)/(L**2))*cos((j*pi*X[0])/L)
4894+ phi_n = phi_n + val
4895+ i=i+1
4896+ phi_n = phi_n*(-4.0/pi**2) + 1.0/6.0
4897+ return phi_n
4898+ else:
4899+ return 0.0</string_value>
4900+ </python>
4901+ </value>
4902+ <output/>
4903+ <stat/>
4904+ <detectors>
4905+ <exclude_from_detectors/>
4906+ </detectors>
4907+ </prescribed>
4908+ </scalar_field>
4909+ <scalar_field name="ScalarAbsoluteDifference" rank="0">
4910+ <diagnostic field_name_b="m3_analytical" field_name_a="Moment_3">
4911+ <algorithm name="Internal" material_phase_support="multiple"/>
4912+ <mesh name="VelocityMesh"/>
4913+ <output/>
4914+ <stat/>
4915+ <convergence>
4916+ <exclude_from_convergence/>
4917+ </convergence>
4918+ <detectors>
4919+ <exclude_from_detectors/>
4920+ </detectors>
4921+ <steady_state>
4922+ <exclude_from_steady_state/>
4923+ </steady_state>
4924+ </diagnostic>
4925+ </scalar_field>
4926+ <population_balance name="DQMOM">
4927+ <use_prognostic_field_initial_conditions/>
4928+ <abscissa>
4929+ <scalar_field name="Abscissa_0" rank="0">
4930+ <diagnostic>
4931+ <algorithm name="Internal" material_phase_support="multiple"/>
4932+ <mesh name="VelocityMesh"/>
4933+ <output/>
4934+ <stat/>
4935+ <convergence>
4936+ <include_in_convergence/>
4937+ </convergence>
4938+ <detectors>
4939+ <include_in_detectors/>
4940+ </detectors>
4941+ <steady_state>
4942+ <include_in_steady_state/>
4943+ </steady_state>
4944+ <consistent_interpolation/>
4945+ </diagnostic>
4946+ </scalar_field>
4947+ <scalar_field name="Abscissa_1" rank="0">
4948+ <diagnostic>
4949+ <algorithm name="Internal" material_phase_support="multiple"/>
4950+ <mesh name="VelocityMesh"/>
4951+ <output/>
4952+ <stat/>
4953+ <convergence>
4954+ <include_in_convergence/>
4955+ </convergence>
4956+ <detectors>
4957+ <include_in_detectors/>
4958+ </detectors>
4959+ <steady_state>
4960+ <include_in_steady_state/>
4961+ </steady_state>
4962+ <consistent_interpolation/>
4963+ </diagnostic>
4964+ </scalar_field>
4965+ </abscissa>
4966+ <weights>
4967+ <scalar_field name="Weight_0" rank="0">
4968+ <prognostic>
4969+ <mesh name="VelocityMesh"/>
4970+ <equation name="AdvectionDiffusion"/>
4971+ <spatial_discretisation>
4972+ <continuous_galerkin>
4973+ <stabilisation>
4974+ <no_stabilisation/>
4975+ </stabilisation>
4976+ <advection_terms/>
4977+ <mass_terms/>
4978+ </continuous_galerkin>
4979+ <conservative_advection>
4980+ <real_value rank="0">0.0</real_value>
4981+ </conservative_advection>
4982+ </spatial_discretisation>
4983+ <temporal_discretisation>
4984+ <theta>
4985+ <real_value rank="0">0.5</real_value>
4986+ </theta>
4987+ </temporal_discretisation>
4988+ <solver>
4989+ <iterative_method name="gmres">
4990+ <restart>
4991+ <integer_value rank="0">30</integer_value>
4992+ </restart>
4993+ </iterative_method>
4994+ <preconditioner name="sor"/>
4995+ <relative_error>
4996+ <real_value rank="0">1e-7</real_value>
4997+ </relative_error>
4998+ <max_iterations>
4999+ <integer_value rank="0">1000</integer_value>
5000+ </max_iterations>
The diff has been truncated for viewing.