Merge lp:~ctjacobs-multiphase/fluidity/compressible-multiphase into lp:fluidity

Proposed by Christian Jacobs
Status: Merged
Approved by: Christian Jacobs
Approved revision: 4067
Merged at revision: 4024
Proposed branch: lp:~ctjacobs-multiphase/fluidity/compressible-multiphase
Merge into: lp:fluidity
Diff against target: 46667 lines (+44935/-226)
90 files modified
assemble/Advection_Diffusion_CG.F90 (+159/-38)
assemble/Compressible_Projection.F90 (+81/-28)
assemble/Diagnostic_Fields_Matrices.F90 (+161/-13)
assemble/Diagnostic_fields_wrapper.F90 (+15/-0)
assemble/Divergence_Matrix_CG.F90 (+146/-33)
assemble/Makefile.dependencies (+10/-10)
assemble/Momentum_Equation.F90 (+37/-27)
assemble/Multiphase.F90 (+391/-40)
main/Fluids.F90 (+1/-1)
main/Shallow_Water.F90 (+17/-16)
manual/bibliography.bib (+29/-0)
manual/configuring_fluidity.tex (+52/-13)
manual/model_equations.tex (+21/-5)
manual/visualisation_and_diagnostics.tex (+1/-0)
schemas/fluidity_options.rnc (+35/-2)
schemas/fluidity_options.rng (+40/-0)
schemas/multiphase_interaction.rnc (+58/-0)
schemas/multiphase_interaction.rng (+65/-0)
tests/flux_bc/Makefile (+22/-0)
tests/flux_bc/flux_bc.xml (+44/-0)
tests/flux_bc/flux_bc_2d.flml (+396/-0)
tests/flux_bc/flux_bc_3d.flml (+405/-0)
tests/flux_bc/src/flux_bc_2d.geo (+19/-0)
tests/flux_bc/src/flux_bc_3d.geo (+69/-0)
tests/mphase_dusty_gas_shock_tube/Makefile (+18/-0)
tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml (+733/-0)
tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.xml (+156/-0)
tests/mphase_dusty_gas_shock_tube/plot.py (+93/-0)
tests/mphase_dusty_gas_shock_tube/shocktube.py (+157/-0)
tests/mphase_dusty_gas_shock_tube/single_phase_frozen_flow_test.flml (+379/-0)
tests/mphase_dusty_gas_shock_tube/single_phase_frozen_flow_test.py (+75/-0)
tests/mphase_inlet_velocity_bc_incompressible/Makefile (+17/-0)
tests/mphase_inlet_velocity_bc_incompressible/mphase_inlet_velocity_bc_incompressible.flml (+527/-0)
tests/mphase_inlet_velocity_bc_incompressible/mphase_inlet_velocity_bc_incompressible.xml (+63/-0)
tests/mphase_mms_p2p1_compressible/MMS_A.flml (+933/-0)
tests/mphase_mms_p2p1_compressible/MMS_B.flml (+933/-0)
tests/mphase_mms_p2p1_compressible/MMS_C.flml (+933/-0)
tests/mphase_mms_p2p1_compressible/MMS_D.flml (+933/-0)
tests/mphase_mms_p2p1_compressible/Makefile (+22/-0)
tests/mphase_mms_p2p1_compressible/get_residual_compressible.sage (+74/-0)
tests/mphase_mms_p2p1_compressible/mphase_mms_p2p1_compressible.xml (+349/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_A.geo (+15/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_A.msh (+190/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_B.geo (+15/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_B.msh (+739/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_C.geo (+15/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_C.msh (+3013/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_D.geo (+15/-0)
tests/mphase_mms_p2p1_compressible/src/MMS_D.msh (+12055/-0)
tests/mphase_mms_p2p1_compressible_ie/MMS_A.flml (+1233/-0)
tests/mphase_mms_p2p1_compressible_ie/MMS_B.flml (+1233/-0)
tests/mphase_mms_p2p1_compressible_ie/MMS_C.flml (+1233/-0)
tests/mphase_mms_p2p1_compressible_ie/Makefile (+20/-0)
tests/mphase_mms_p2p1_compressible_ie/get_residual_compressible.sage (+75/-0)
tests/mphase_mms_p2p1_compressible_ie/mphase_mms_p2p1_compressible_ie.xml (+311/-0)
tests/mphase_mms_p2p1_compressible_ie/src/MMS_A.geo (+15/-0)
tests/mphase_mms_p2p1_compressible_ie/src/MMS_A.msh (+238/-0)
tests/mphase_mms_p2p1_compressible_ie/src/MMS_B.geo (+15/-0)
tests/mphase_mms_p2p1_compressible_ie/src/MMS_B.msh (+832/-0)
tests/mphase_mms_p2p1_compressible_ie/src/MMS_C.geo (+15/-0)
tests/mphase_mms_p2p1_compressible_ie/src/MMS_C.msh (+3238/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/MMS_A.flml (+1316/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/MMS_B.flml (+1316/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/MMS_C.flml (+1316/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/Makefile (+20/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/get_residual_compressible.sage (+75/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/mphase_mms_p2p1_compressible_ie_heat_transfer.xml (+311/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/src/MMS_A.geo (+15/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/src/MMS_A.msh (+238/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/src/MMS_B.geo (+15/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/src/MMS_B.msh (+832/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/src/MMS_C.geo (+15/-0)
tests/mphase_mms_p2p1_compressible_ie_heat_transfer/src/MMS_C.msh (+3238/-0)
tests/mphase_rogue_shock_tube_dense_bed_glass/Makefile (+18/-0)
tests/mphase_rogue_shock_tube_dense_bed_glass/mphase_rogue_shock_tube_dense_bed_glass.flml (+824/-0)
tests/mphase_rogue_shock_tube_dense_bed_glass/mphase_rogue_shock_tube_dense_bed_glass.xml (+108/-0)
tests/mphase_rogue_shock_tube_dense_bed_glass/plot.py (+70/-0)
tests/mphase_rogue_shock_tube_dense_bed_glass/src/mphase_rogue_shock_tube_dense_bed_glass.geo (+19/-0)
tests/mphase_rogue_shock_tube_dense_bed_nylon/Makefile (+17/-0)
tests/mphase_rogue_shock_tube_dense_bed_nylon/mphase_rogue_shock_tube_dense_bed_nylon.flml (+824/-0)
tests/mphase_rogue_shock_tube_dense_bed_nylon/mphase_rogue_shock_tube_dense_bed_nylon.xml (+108/-0)
tests/mphase_rogue_shock_tube_dense_bed_nylon/plot.py (+96/-0)
tests/mphase_rogue_shock_tube_dense_bed_nylon/src/mphase_rogue_shock_tube_dense_bed_nylon.geo (+19/-0)
tests/mphase_stokes_law/mphase_stokes_law.flml (+5/-0)
tests/mphase_tephra_settling/mphase_tephra_settling.flml (+5/-0)
tests/mphase_wen_yu_drag_correlation/Makefile (+17/-0)
tests/mphase_wen_yu_drag_correlation/c_against_re.py (+26/-0)
tests/mphase_wen_yu_drag_correlation/mphase_wen_yu_drag_correlation.flml (+793/-0)
tests/mphase_wen_yu_drag_correlation/mphase_wen_yu_drag_correlation.xml (+76/-0)
tests/mphase_wen_yu_drag_correlation/src/mphase_wen_yu_drag_correlation.geo (+19/-0)
To merge this branch: bzr merge lp:~ctjacobs-multiphase/fluidity/compressible-multiphase
Reviewer Review Type Date Requested Status
Stephan Kramer Approve
Cian Wilson Pending
Review via email: mp+114294@code.launchpad.net

Description of the change

Proposing merge of compressible-multiphase branch revisions r3955 to r4050 (inclusive) into trunk.

Summary of changes:
===================

- Added multiphase support for the compressible projection method (currently only for CG Pressure).

- Small changes to the logic in Momentum_Equation.F90. Replaced the use_compressible_projection logical with compressible_eos which is .true. if option_count("/material_phase/equation_of_state/compressible") > 0, and .false. otherwise.

- Added multiphase support for the InternalEnergy equation. Note that the whole state array is now passed to solve_field_equation_cg.

- Implemented the heat transfer term by Gunn (1978).

- Added three P2-P1 multiphase MMS tests for model verification: one without InternalEnergy fields, one with InternalEnergy fields, and one with InternalEnergy fields and heat transfer. The tests will become longtests after merging into the trunk.

- The manual now has documentation on the compressible multiphase model, including the multiphase version of the InternalEnergy equation.

- Added a diagnostic field called CompressibleContinuity which computes the residual of the compressible multiphase continuity equation. This is similar to the SumVelocityDivergence field for incompressible multiphase flow which computes \sum{div(vfrac*u)}.

- Added two gas-solid shock tube tests to help to validate the model: mphase_rogue_shock_tube_dense_bed_glass and mphase_rogue_shock_tube_dense_bed_nylon.

- Added another gas-solid shock tube test (mphase_dusty_gas_shock_tube) which uses the setup by Miura & Glass (1982).

- Implemented two new correlations for fluid-particle drag. The one by Wen & Yu (1966) can support higher Reynolds numbers (compared to the existing Stokes' law correlation). The one by Ergun (1952) can support dense flows where the volume fraction of the particle phase is greater than 0.2, like in the dense bed shock tube tests (and in the pyroclastic flow tests which will hopefully come later).

- Changed the structure of the schema. Users now explicitly select which interaction terms they wish to include, as well as the drag correlation, under "/multiphase_interaction" in Diamond. These options are stored in the new files multiphase_interaction.rnc and multiphase_interaction.rng.

- Added a test for the Wen & Yu (1966) drag correlation. This is similar to mphase_stokes_law.

- Added a test to check if inlet velocity boundary conditions work with the incompressible multiphase flow model.

- Added a test for the flux boundary condition.

To post a comment you must log in.
Revision history for this message
Stephan Kramer (s-kramer) wrote :

Hey there. I've only looked at Advection_Diffusion_CG.F90 yet. Looking great so far, the maths of the changes in the i.e. equation seem to make sense to me. Here it goes:

* Currently the multiphase logical is only set within the
equation_type==FIELD_EQUATION_INTERNALENERGY case. Can we either:
- always set multiphase to be true or false, or
- rename it to mean multiphase_internal_energy_equation
As it is now suggested that multiphase can be used independently of
the value of equation_type.

* Just being picky here: can we get rid of the nullify(vfrac) in line 506. It seems
to suggest that vfrac is used later on, which it's not.

* Advection_Diffusion_CG.F90, line 517:

Why does the behaviour change if we're not multiphase? Do you maybe mean:

if (.not. multiphase .or. have_option(....compressible) then

* Advection_Diffusion_CG.F90, line 794 having an allocate within an element
loop is not ideal. It's not efficient, and it's also not thread-safe. I can
see the problem with following the usual approach (nvfrac might
not be defined), but I think it's better to do some kludge with allocating
a dummy nvfrac or something rather.

* Advection_Diffusion_CG.F90, lines 1492 and 1502: I don't think you intended to
add (istate) there.

* Not too excited about having to pass in an array of states
to advection_diffusion_cg now tbh. One way to keep the damage limited would be
to move the call to add_heat_transfer up one level inside
solve_field_equation_cg. And keep everything else just limited to a
single state, i.e. not passing istate all the way down and changing state ->
state(istate) *everywhere*.

4051. By Christian Jacobs

Improvements to Advection_Diffusion_CG.F90 based on Stephan's feedback.

4052. By Christian Jacobs

Moving the call to add_heat_transfer up one level.

4053. By Christian Jacobs

Merging trunk revisions (from r4011 to r4019 inclusive) into branch.

Revision history for this message
Christian Jacobs (ctjacobs) wrote :

Thanks for the feedback Stephan - improvements have now been made to Advection_Diffusion_CG.F90. I have decided to always set the 'multiphase' logical rather than rename it to something involving a specific equation type, since it might be used later on when adding multiphase support to the k-epsilon model.

Revision history for this message
Stephan Kramer (s-kramer) wrote :

Some more comments trickling through:

* assemble/Compressible_Projection.F90, line 463: dnvfrac_t is not used

* assemble/Compressible_Projection.F90, line 650,660: Why are we setting this
multiphase variable there, it's not used afaics and a bit confusing...

* assemble/Diagnostic_Fields_Matrices.F90, line 372: you query the timestep now
but it doesn't seem to be used? Also in the same routine you've added vfrac
and temp_vfrac that aren't used.

* calculate_compressible_continuity() looks good to me. Is it tested? Would a
better maybe be compressible_continuity_residual? As it's not directly clear
what "compressible_continuity" as a diagnostic quantity is...

4054. By Christian Jacobs

Some more improvements based on Stephan's feedback.

4055. By Christian Jacobs

Added a test for the CompressibleContinuityResidual diagnostic field.

4056. By Christian Jacobs

More tests for the CompressibleContinuityResidual diagnostic field.

Revision history for this message
Christian Jacobs (ctjacobs) wrote :

Thanks again - improvements made and the (renamed) CompressibleContinuityResidual diagnostic field is now tested within the MMS tests by checking that it converges to the analytical solution at the expected order.

4057. By Christian Jacobs

Merging trunk revisions (from r4020 to r4022 inclusive) into branch.

Revision history for this message
Stephan Kramer (s-kramer) wrote :

Some final, small remarks:

* assemble/Divergence_Matrix.F90: is there a reason you're not using state%option_path? I prefer that as it makes future redesigns of the optionstree easier.

* assemble/Momentum_Equation.F90, line 471: does this comment still apply? if not, how is this fixed?

* assemble/Momentum_Equation.F90, line 1049: why do we all of a sudden extract density from state there? AFAIK Density is not a required field, for instance for Boussinesq. Similar for line 1585: does this not break if we don't have
a Density, but do have a prognostic Velocity and Pressure?

* assemble/Multiphase.F90, add_fluid_particle_drag_element(): doing string comparisons at the element level is not ideal. In particular with OPTION_PATH_LEN (8192 or so?) length string, the compiler might do something
sensible, but I'm not sure and I don't like second-guessing. A solution would be to move the select case up one level, and set an integer with some "enum"-like parameters DRAG_CORRELATION_TYPE_ERGUN=3, etc.

* assemble/Multiphase.F90, line 625 and 632: again here, why not use state%option_path?

* assemble/Multiphase.F90, add_heat_transfer(): looks great and I'm sure is 100% correct - good to see it's well tested though!

Great stuff, well documented, lots of tests. Next time, could we maybe merge this in smaller bits?

4058. By Christian Jacobs

Using state%option_path instead.

4059. By Christian Jacobs

- Don't try to extract the Density field here, as it's not necessary.
- Another change to use state%option_path instead.

4060. By Christian Jacobs

Call FLExit if use_theta_pg or use_theta_divergence are true when running a compressible multiphase flow simulation.

4061. By Christian Jacobs

Introduced integer parameters to represent the different drag correlations.

4062. By Christian Jacobs

Merging trunk revision r4023 into branch.

Revision history for this message
Stephan Kramer (s-kramer) wrote :

Awesome!

review: Approve
4063. By Christian Jacobs

Corrected a typo introduced when changing to state%option_path.

4064. By Christian Jacobs

- Corrected a few typos in the XML files.
- Set the mphase_rogue_shock_tube_dense_bed_glass test's length to "medium".

4065. By Christian Jacobs

Line continuation fix. The code now compiles on the Intel compiler.

4066. By Christian Jacobs

Fixed an assert statement. Only noticed this when debugging was enabled.

4067. By Christian Jacobs

Updates from "make makefiles".

Revision history for this message
Christian Jacobs (ctjacobs) wrote :

The build queue now has a green light on buildbot. Thanks for the review.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'assemble/Advection_Diffusion_CG.F90'
--- assemble/Advection_Diffusion_CG.F90 2012-04-16 16:41:59 +0000
+++ assemble/Advection_Diffusion_CG.F90 2012-08-09 00:46:20 +0000
@@ -47,6 +47,7 @@
47 use upwind_stabilisation47 use upwind_stabilisation
48 use sparsity_patterns_meshes48 use sparsity_patterns_meshes
49 use porous_media49 use porous_media
50 use multiphase_module
50 use sparse_tools_petsc51 use sparse_tools_petsc
51 use colouring52 use colouring
52#ifdef _OPENMP53#ifdef _OPENMP
@@ -117,16 +118,19 @@
117 logical :: move_mesh118 logical :: move_mesh
118 ! Include porosity?119 ! Include porosity?
119 logical :: include_porosity120 logical :: include_porosity
121 ! Are we running a multiphase flow simulation?
122 logical :: multiphase
120123
121contains124contains
122125
123 subroutine solve_field_equation_cg(field_name, state, dt, velocity_name, iterations_taken)126 subroutine solve_field_equation_cg(field_name, state, istate, dt, velocity_name, iterations_taken)
124 !!< Construct and solve the advection-diffusion equation for the given127 !!< Construct and solve the advection-diffusion equation for the given
125 !!< field using a continuous Galerkin discretisation. Based on128 !!< field using a continuous Galerkin discretisation. Based on
126 !!< Advection_Diffusion_DG and Momentum_CG.129 !!< Advection_Diffusion_DG and Momentum_CG.
127 130
128 character(len = *), intent(in) :: field_name131 character(len = *), intent(in) :: field_name
129 type(state_type), intent(inout) :: state132 type(state_type), dimension(:), intent(inout) :: state
133 integer, intent(in) :: istate
130 real, intent(in) :: dt134 real, intent(in) :: dt
131 character(len = *), optional, intent(in) :: velocity_name135 character(len = *), optional, intent(in) :: velocity_name
132 integer, intent(out), optional :: iterations_taken136 integer, intent(out), optional :: iterations_taken
@@ -138,16 +142,22 @@
138 ewrite(1, *) "In solve_field_equation_cg"142 ewrite(1, *) "In solve_field_equation_cg"
139 143
140 ewrite(2, *) "Solving advection-diffusion equation for field " // &144 ewrite(2, *) "Solving advection-diffusion equation for field " // &
141 & trim(field_name) // " in state " // trim(state%name)145 & trim(field_name) // " in state " // trim(state(istate)%name)
142146
143 call initialise_advection_diffusion_cg(field_name, t, delta_t, matrix, rhs, state)147 call initialise_advection_diffusion_cg(field_name, t, delta_t, matrix, rhs, state(istate))
144 148
145 call profiler_tic(t, "assembly")149 call profiler_tic(t, "assembly")
146 call assemble_advection_diffusion_cg(t, matrix, rhs, state, dt, velocity_name = velocity_name) 150 call assemble_advection_diffusion_cg(t, matrix, rhs, state(istate), dt, velocity_name = velocity_name)
151
152 ! Note: the assembly of the heat transfer term is done here to avoid
153 ! passing in the whole state array to assemble_advection_diffusion_cg.
154 if(have_option("/multiphase_interaction/heat_transfer")) then
155 call add_heat_transfer(state, istate, t, matrix, rhs)
156 end if
147 call profiler_toc(t, "assembly")157 call profiler_toc(t, "assembly")
148158
149 call profiler_tic(t, "solve_total")159 call profiler_tic(t, "solve_total")
150 call solve_advection_diffusion_cg(t, delta_t, matrix, rhs, state, &160 call solve_advection_diffusion_cg(t, delta_t, matrix, rhs, state(istate), &
151 iterations_taken = iterations_taken)161 iterations_taken = iterations_taken)
152 call profiler_toc(t, "solve_total")162 call profiler_toc(t, "solve_total")
153163
@@ -234,6 +244,11 @@
234 type(scalar_field), pointer :: density, olddensity244 type(scalar_field), pointer :: density, olddensity
235 character(len = FIELD_NAME_LEN) :: density_name245 character(len = FIELD_NAME_LEN) :: density_name
236 type(scalar_field), pointer :: pressure246 type(scalar_field), pointer :: pressure
247
248 ! Volume fraction fields for multiphase flow simulation
249 type(scalar_field), pointer :: vfrac
250 type(scalar_field) :: nvfrac ! Non-linear version
251
237 ! Porosity field252 ! Porosity field
238 type(scalar_field) :: porosity_theta253 type(scalar_field) :: porosity_theta
239 254
@@ -373,6 +388,7 @@
373 call allocate(porosity_theta, t%mesh, field_type=FIELD_TYPE_CONSTANT)388 call allocate(porosity_theta, t%mesh, field_type=FIELD_TYPE_CONSTANT)
374 call set(porosity_theta, 1.0)389 call set(porosity_theta, 1.0)
375 end if390 end if
391
376 392
377 ! Step 2: Pull options out of the options tree393 ! Step 2: Pull options out of the options tree
378 394
@@ -462,6 +478,21 @@
462 stabilisation_scheme = STABILISATION_NONE478 stabilisation_scheme = STABILISATION_NONE
463 end if479 end if
464 480
481 ! PhaseVolumeFraction for multiphase flow simulations
482 if(option_count("/material_phase/vector_field::Velocity/prognostic") > 1) then
483 multiphase = .true.
484 vfrac => extract_scalar_field(state, "PhaseVolumeFraction")
485 call allocate(nvfrac, vfrac%mesh, "NonlinearPhaseVolumeFraction")
486 call zero(nvfrac)
487 call get_nonlinear_volume_fraction(state, nvfrac)
488
489 ewrite_minmax(nvfrac)
490 else
491 multiphase = .false.
492 call allocate(nvfrac, t%mesh, "DummyNonlinearPhaseVolumeFraction", field_type=FIELD_TYPE_CONSTANT)
493 call set(nvfrac, 1.0)
494 end if
495
465 call allocate(dummydensity, t%mesh, "DummyDensity", field_type=FIELD_TYPE_CONSTANT)496 call allocate(dummydensity, t%mesh, "DummyDensity", field_type=FIELD_TYPE_CONSTANT)
466 call set(dummydensity, 1.0)497 call set(dummydensity, 1.0)
467 ! find out equation type and hence if density is needed or not498 ! find out equation type and hence if density is needed or not
@@ -479,19 +510,28 @@
479 if(move_mesh) then510 if(move_mesh) then
480 FLExit("Haven't implemented a moving mesh energy equation yet.")511 FLExit("Haven't implemented a moving mesh energy equation yet.")
481 end if512 end if
513
514 ! Get old and current densities
482 call get_option(trim(t%option_path)//'/prognostic/equation[0]/density[0]/name', &515 call get_option(trim(t%option_path)//'/prognostic/equation[0]/density[0]/name', &
483 density_name)516 density_name)
484 density=>extract_scalar_field(state, trim(density_name))517 density=>extract_scalar_field(state, trim(density_name))
485 ewrite_minmax(density)518 ewrite_minmax(density)
486
487 olddensity=>extract_scalar_field(state, "Old"//trim(density_name))519 olddensity=>extract_scalar_field(state, "Old"//trim(density_name))
488 ewrite_minmax(olddensity)520 ewrite_minmax(olddensity)
489 521
490 call get_option(trim(density%option_path)//"/prognostic/temporal_discretisation/theta", &522 if(.not.multiphase .or. have_option('/material_phase::'//trim(state%name)//&
491 density_theta)523 &'/equation_of_state/compressible')) then
524 call get_option(trim(density%option_path)//"/prognostic/temporal_discretisation/theta", &
525 density_theta)
526 else
527 ! Since the particle phase is always incompressible then its Density
528 ! will not be prognostic. Just use a fixed theta value of 1.0.
529 density_theta = 1.0
530 end if
492 531
493 pressure=>extract_scalar_field(state, "Pressure")532 pressure=>extract_scalar_field(state, "Pressure")
494 ewrite_minmax(pressure)533 ewrite_minmax(pressure)
534
495 case default535 case default
496 FLExit("Unknown field equation type for cg advection diffusion.")536 FLExit("Unknown field equation type for cg advection diffusion.")
497 end select537 end select
@@ -531,7 +571,7 @@
531 positions, old_positions, new_positions, &571 positions, old_positions, new_positions, &
532 velocity, grid_velocity, &572 velocity, grid_velocity, &
533 source, absorption, diffusivity, &573 source, absorption, diffusivity, &
534 density, olddensity, pressure, porosity_theta, &574 density, olddensity, pressure, porosity_theta, nvfrac, &
535 supg_element(thread_num+1))575 supg_element(thread_num+1))
536 end do element_loop576 end do element_loop
537 !$OMP END DO577 !$OMP END DO
@@ -545,6 +585,7 @@
545 ! which must be included before dirichlet BC's.585 ! which must be included before dirichlet BC's.
546 if (add_src_directly_to_rhs) call addto(rhs, source)586 if (add_src_directly_to_rhs) call addto(rhs, source)
547 587
588
548 ! Step 4: Boundary conditions589 ! Step 4: Boundary conditions
549 590
550 if( &591 if( &
@@ -571,7 +612,7 @@
571 call assemble_advection_diffusion_face_cg(i, t_bc_types(i), t, t_bc, t_bc_2, &612 call assemble_advection_diffusion_face_cg(i, t_bc_types(i), t, t_bc, t_bc_2, &
572 matrix, rhs, &613 matrix, rhs, &
573 positions, velocity, grid_velocity, &614 positions, velocity, grid_velocity, &
574 density, olddensity)615 density, olddensity, nvfrac)
575 end do616 end do
576 617
577 call deallocate(t_bc)618 call deallocate(t_bc)
@@ -586,6 +627,7 @@
586 ewrite_minmax(rhs)627 ewrite_minmax(rhs)
587 628
588 call deallocate(velocity)629 call deallocate(velocity)
630 call deallocate(nvfrac)
589 call deallocate(dummydensity)631 call deallocate(dummydensity)
590 if (stabilisation_scheme == STABILISATION_SUPG) then632 if (stabilisation_scheme == STABILISATION_SUPG) then
591 do i = 1, num_threads633 do i = 1, num_threads
@@ -645,7 +687,7 @@
645 positions, old_positions, new_positions, &687 positions, old_positions, new_positions, &
646 velocity, grid_velocity, &688 velocity, grid_velocity, &
647 source, absorption, diffusivity, &689 source, absorption, diffusivity, &
648 density, olddensity, pressure, porosity_theta, supg_shape)690 density, olddensity, pressure, porosity_theta, nvfrac, supg_shape)
649 integer, intent(in) :: ele691 integer, intent(in) :: ele
650 type(scalar_field), intent(in) :: t692 type(scalar_field), intent(in) :: t
651 type(csr_matrix), intent(inout) :: matrix693 type(csr_matrix), intent(inout) :: matrix
@@ -661,6 +703,7 @@
661 type(scalar_field), intent(in) :: olddensity703 type(scalar_field), intent(in) :: olddensity
662 type(scalar_field), intent(in) :: pressure704 type(scalar_field), intent(in) :: pressure
663 type(scalar_field), intent(in) :: porosity_theta705 type(scalar_field), intent(in) :: porosity_theta
706 type(scalar_field), intent(in) :: nvfrac
664 type(element_type), intent(inout) :: supg_shape707 type(element_type), intent(inout) :: supg_shape
665708
666 integer, dimension(:), pointer :: element_nodes709 integer, dimension(:), pointer :: element_nodes
@@ -669,6 +712,9 @@
669 real, dimension(ele_loc(density, ele), ele_ngi(density, ele), mesh_dim(density)) :: drho_t712 real, dimension(ele_loc(density, ele), ele_ngi(density, ele), mesh_dim(density)) :: drho_t
670 real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t 713 real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t
671 real, dimension(ele_loc(positions, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: dug_t 714 real, dimension(ele_loc(positions, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: dug_t
715 ! Derivative of shape function for nvfrac field
716 real, dimension(ele_loc(nvfrac, ele), ele_ngi(nvfrac, ele), mesh_dim(nvfrac)) :: dnvfrac_t
717
672 real, dimension(mesh_dim(t), mesh_dim(t), ele_ngi(t, ele)) :: j_mat 718 real, dimension(mesh_dim(t), mesh_dim(t), ele_ngi(t, ele)) :: j_mat
673 type(element_type) :: test_function719 type(element_type) :: test_function
674 type(element_type), pointer :: t_shape720 type(element_type), pointer :: t_shape
@@ -741,6 +787,16 @@
741 end if787 end if
742 end if788 end if
743 789
790 if(have_advection .and. multiphase .and. (equation_type==FIELD_EQUATION_INTERNALENERGY)) then
791 ! If the field and nvfrac meshes are different, then we need to
792 ! compute the derivatives of the nvfrac shape functions.
793 if(ele_shape(nvfrac, ele) == t_shape) then
794 dnvfrac_t = dt_t
795 else
796 call transform_to_physical(positions, ele, ele_shape(nvfrac, ele), dshape=dnvfrac_t)
797 end if
798 end if
799
744 ! Step 2: Set up test function800 ! Step 2: Set up test function
745 801
746 select case(stabilisation_scheme)802 select case(stabilisation_scheme)
@@ -763,13 +819,13 @@
763 ! Step 3: Assemble contributions819 ! Step 3: Assemble contributions
764 820
765 ! Mass821 ! Mass
766 if(have_mass) call add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)822 if(have_mass) call add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, nvfrac, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)
767 823
768 ! Advection824 ! Advection
769 if(have_advection) call add_advection_element_cg(ele, test_function, t, &825 if(have_advection) call add_advection_element_cg(ele, test_function, t, &
770 velocity, grid_velocity, diffusivity, &826 velocity, grid_velocity, diffusivity, &
771 density, olddensity, &827 density, olddensity, nvfrac, &
772 dt_t, du_t, dug_t, drho_t, detwei, j_mat, matrix_addto, rhs_addto)828 dt_t, du_t, dug_t, drho_t, dnvfrac_t, detwei, j_mat, matrix_addto, rhs_addto)
773 829
774 ! Absorption830 ! Absorption
775 if(have_absorption) call add_absorption_element_cg(ele, test_function, t, absorption, detwei, matrix_addto, rhs_addto)831 if(have_absorption) call add_absorption_element_cg(ele, test_function, t, absorption, detwei, matrix_addto, rhs_addto)
@@ -784,8 +840,8 @@
784 840
785 ! Pressure841 ! Pressure
786 if(equation_type==FIELD_EQUATION_INTERNALENERGY) call add_pressurediv_element_cg(ele, test_function, t, &842 if(equation_type==FIELD_EQUATION_INTERNALENERGY) call add_pressurediv_element_cg(ele, test_function, t, &
787 velocity, pressure, &843 velocity, pressure, nvfrac, &
788 du_t, detwei, rhs_addto)844 du_t, dnvfrac_t, detwei, rhs_addto)
789 845
790 ! Step 4: Insertion846 ! Step 4: Insertion
791 847
@@ -795,12 +851,13 @@
795851
796 end subroutine assemble_advection_diffusion_element_cg852 end subroutine assemble_advection_diffusion_element_cg
797 853
798 subroutine add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)854 subroutine add_mass_element_cg(ele, test_function, t, density, olddensity, porosity_theta, nvfrac, detwei, detwei_old, detwei_new, matrix_addto, rhs_addto)
799 integer, intent(in) :: ele855 integer, intent(in) :: ele
800 type(element_type), intent(in) :: test_function856 type(element_type), intent(in) :: test_function
801 type(scalar_field), intent(in) :: t857 type(scalar_field), intent(in) :: t
802 type(scalar_field), intent(in) :: density, olddensity858 type(scalar_field), intent(in) :: density, olddensity
803 type(scalar_field), intent(in) :: porosity_theta 859 type(scalar_field), intent(in) :: porosity_theta
860 type(scalar_field), intent(in) :: nvfrac
804 real, dimension(ele_ngi(t, ele)), intent(in) :: detwei, detwei_old, detwei_new861 real, dimension(ele_ngi(t, ele)), intent(in) :: detwei, detwei_old, detwei_new
805 real, dimension(ele_loc(t, ele), ele_loc(t, ele)), intent(inout) :: matrix_addto862 real, dimension(ele_loc(t, ele), ele_loc(t, ele)), intent(inout) :: matrix_addto
806 real, dimension(ele_loc(t, ele)), intent(inout) :: rhs_addto863 real, dimension(ele_loc(t, ele)), intent(inout) :: rhs_addto
@@ -827,6 +884,8 @@
827 else884 else
828 if (include_porosity) then885 if (include_porosity) then
829 mass_matrix = shape_shape(test_function, ele_shape(t, ele), detwei*density_at_quad*porosity_theta_at_quad) 886 mass_matrix = shape_shape(test_function, ele_shape(t, ele), detwei*density_at_quad*porosity_theta_at_quad)
887 else if(multiphase) then
888 mass_matrix = shape_shape(test_function, ele_shape(t, ele), detwei*density_at_quad*ele_val_at_quad(nvfrac, ele))
830 else889 else
831 mass_matrix = shape_shape(test_function, ele_shape(t, ele), detwei*density_at_quad)890 mass_matrix = shape_shape(test_function, ele_shape(t, ele), detwei*density_at_quad)
832 end if891 end if
@@ -877,8 +936,8 @@
877 936
878 subroutine add_advection_element_cg(ele, test_function, t, &937 subroutine add_advection_element_cg(ele, test_function, t, &
879 velocity, grid_velocity, diffusivity, &938 velocity, grid_velocity, diffusivity, &
880 density, olddensity, &939 density, olddensity, nvfrac, &
881 dt_t, du_t, dug_t, drho_t, detwei, j_mat, matrix_addto, rhs_addto)940 dt_t, du_t, dug_t, drho_t, dnvfrac_t, detwei, j_mat, matrix_addto, rhs_addto)
882 integer, intent(in) :: ele941 integer, intent(in) :: ele
883 type(element_type), intent(in) :: test_function942 type(element_type), intent(in) :: test_function
884 type(scalar_field), intent(in) :: t943 type(scalar_field), intent(in) :: t
@@ -886,10 +945,12 @@
886 type(vector_field), pointer :: grid_velocity945 type(vector_field), pointer :: grid_velocity
887 type(tensor_field), intent(in) :: diffusivity946 type(tensor_field), intent(in) :: diffusivity
888 type(scalar_field), intent(in) :: density, olddensity947 type(scalar_field), intent(in) :: density, olddensity
948 type(scalar_field), intent(in) :: nvfrac
889 real, dimension(ele_loc(t, ele), ele_ngi(t, ele), mesh_dim(t)), intent(in) :: dt_t949 real, dimension(ele_loc(t, ele), ele_ngi(t, ele), mesh_dim(t)), intent(in) :: dt_t
890 real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t950 real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t
891 real, dimension(:, :, :) :: dug_t951 real, dimension(:, :, :) :: dug_t
892 real, dimension(ele_loc(density, ele), ele_ngi(density, ele), mesh_dim(density)), intent(in) :: drho_t952 real, dimension(ele_loc(density, ele), ele_ngi(density, ele), mesh_dim(density)), intent(in) :: drho_t
953 real, dimension(:, :, :), intent(in) :: dnvfrac_t
893 real, dimension(ele_ngi(t, ele)), intent(in) :: detwei954 real, dimension(ele_ngi(t, ele)), intent(in) :: detwei
894 real, dimension(mesh_dim(t), mesh_dim(t), ele_ngi(t, ele)), intent(in) :: j_mat 955 real, dimension(mesh_dim(t), mesh_dim(t), ele_ngi(t, ele)), intent(in) :: j_mat
895 real, dimension(ele_loc(t, ele), ele_loc(t, ele)), intent(inout) :: matrix_addto956 real, dimension(ele_loc(t, ele), ele_loc(t, ele)), intent(inout) :: matrix_addto
@@ -904,6 +965,10 @@
904 real, dimension(velocity%dim, ele_ngi(density, ele)) :: densitygrad_at_quad965 real, dimension(velocity%dim, ele_ngi(density, ele)) :: densitygrad_at_quad
905 real, dimension(ele_ngi(density, ele)) :: udotgradrho_at_quad966 real, dimension(ele_ngi(density, ele)) :: udotgradrho_at_quad
906 967
968 real, dimension(ele_ngi(t, ele)) :: nvfrac_at_quad
969 real, dimension(velocity%dim, ele_ngi(t, ele)) :: nvfracgrad_at_quad
970 real, dimension(ele_ngi(t, ele)) :: udotgradnvfrac_at_quad
971
907 assert(have_advection)972 assert(have_advection)
908 973
909 t_shape => ele_shape(t, ele)974 t_shape => ele_shape(t, ele)
@@ -922,6 +987,10 @@
922 densitygrad_at_quad = density_theta*ele_grad_at_quad(density, ele, drho_t) &987 densitygrad_at_quad = density_theta*ele_grad_at_quad(density, ele, drho_t) &
923 +(1.-density_theta)*ele_grad_at_quad(olddensity, ele, drho_t)988 +(1.-density_theta)*ele_grad_at_quad(olddensity, ele, drho_t)
924 udotgradrho_at_quad = sum(densitygrad_at_quad*velocity_at_quad, 1)989 udotgradrho_at_quad = sum(densitygrad_at_quad*velocity_at_quad, 1)
990
991 if(multiphase) then
992 nvfrac_at_quad = ele_val_at_quad(nvfrac, ele)
993 end if
925 end select994 end select
926 995
927 if(integrate_advection_by_parts) then996 if(integrate_advection_by_parts) then
@@ -931,12 +1000,26 @@
931 ! / /1000 ! / /
932 select case(equation_type)1001 select case(equation_type)
933 case(FIELD_EQUATION_INTERNALENERGY)1002 case(FIELD_EQUATION_INTERNALENERGY)
934 advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei*density_at_quad)1003 if(multiphase) then
1004 advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei*density_at_quad*nvfrac_at_quad)
1005 else
1006 advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei*density_at_quad)
1007 end if
1008
935 if(abs(1.0 - beta) > epsilon(0.0)) then1009 if(abs(1.0 - beta) > epsilon(0.0)) then
936 velocity_div_at_quad = ele_div_at_quad(velocity, ele, du_t)1010 velocity_div_at_quad = ele_div_at_quad(velocity, ele, du_t)
937 advection_mat = advection_mat &1011
938 - (1.0-beta) * shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad &1012 if(multiphase) then
939 +udotgradrho_at_quad)* detwei)1013
1014 nvfracgrad_at_quad = ele_grad_at_quad(nvfrac, ele, dnvfrac_t)
1015 udotgradnvfrac_at_quad = sum(nvfracgrad_at_quad*velocity_at_quad, 1)
1016
1017 advection_mat = advection_mat - (1.0-beta) * ( shape_shape(test_function, t_shape, detwei*velocity_div_at_quad*density_at_quad*nvfrac_at_quad) &
1018 + shape_shape(test_function, t_shape, detwei*nvfrac_at_quad*udotgradrho_at_quad) &
1019 + shape_shape(test_function, t_shape, detwei*density_at_quad*udotgradnvfrac_at_quad) )
1020 else
1021 advection_mat = advection_mat - (1.0-beta) * shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad + udotgradrho_at_quad)*detwei)
1022 end if
940 end if1023 end if
941 case default1024 case default
942 advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei)1025 advection_mat = -dshape_dot_vector_shape(dt_t, velocity_at_quad, t_shape, detwei)
@@ -953,12 +1036,31 @@
953 ! / /1036 ! / /
954 select case(equation_type)1037 select case(equation_type)
955 case(FIELD_EQUATION_INTERNALENERGY)1038 case(FIELD_EQUATION_INTERNALENERGY)
956 advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei*density_at_quad)1039
1040 if(multiphase) then
1041 ! vfrac*rho*nu*grad(internalenergy)
1042 advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei*density_at_quad*nvfrac_at_quad)
1043 else
1044 advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei*density_at_quad)
1045 end if
1046
957 if(abs(beta) > epsilon(0.0)) then1047 if(abs(beta) > epsilon(0.0)) then
958 velocity_div_at_quad = ele_div_at_quad(velocity, ele, du_t)1048 velocity_div_at_quad = ele_div_at_quad(velocity, ele, du_t)
959 advection_mat = advection_mat &1049
960 + beta*shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad &1050 if(multiphase) then
961 +udotgradrho_at_quad)*detwei)1051 ! advection_mat + internalenergy*div(vfrac*rho*nu)
1052 ! Split up div(vfrac*rho*nu) = vfrac*rho*div(nu) + nu*grad(vfrac*rho) = vfrac*rho*div(nu) + nu*(vfrac*grad(rho) + rho*grad(nvfrac))
1053
1054 nvfracgrad_at_quad = ele_grad_at_quad(nvfrac, ele, dnvfrac_t)
1055 udotgradnvfrac_at_quad = sum(nvfracgrad_at_quad*velocity_at_quad, 1)
1056
1057 advection_mat = advection_mat + beta * ( shape_shape(test_function, t_shape, detwei*velocity_div_at_quad*density_at_quad*nvfrac_at_quad) &
1058 + shape_shape(test_function, t_shape, detwei*nvfrac_at_quad*udotgradrho_at_quad) &
1059 + shape_shape(test_function, t_shape, detwei*density_at_quad*udotgradnvfrac_at_quad) )
1060 else
1061 advection_mat = advection_mat + beta*shape_shape(test_function, t_shape, (velocity_div_at_quad*density_at_quad &
1062 +udotgradrho_at_quad)*detwei)
1063 end if
962 end if1064 end if
963 case default1065 case default
964 advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei)1066 advection_mat = shape_vector_dot_dshape(test_function, velocity_at_quad, dt_t, detwei)
@@ -1060,26 +1162,39 @@
1060 1162
1061 end subroutine add_diffusivity_element_cg1163 end subroutine add_diffusivity_element_cg
1062 1164
1063 subroutine add_pressurediv_element_cg(ele, test_function, t, velocity, pressure, du_t, detwei, rhs_addto)1165 subroutine add_pressurediv_element_cg(ele, test_function, t, velocity, pressure, nvfrac, du_t, dnvfrac_t, detwei, rhs_addto)
1064 1166
1065 integer, intent(in) :: ele1167 integer, intent(in) :: ele
1066 type(element_type), intent(in) :: test_function1168 type(element_type), intent(in) :: test_function
1067 type(scalar_field), intent(in) :: t1169 type(scalar_field), intent(in) :: t
1068 type(vector_field), intent(in) :: velocity1170 type(vector_field), intent(in) :: velocity
1069 type(scalar_field), intent(in) :: pressure1171 type(scalar_field), intent(in) :: pressure
1070 real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)) :: du_t1172 type(scalar_field), intent(in) :: nvfrac
1173 real, dimension(ele_loc(velocity, ele), ele_ngi(velocity, ele), mesh_dim(t)), intent(in) :: du_t
1174 real, dimension(:, :, :), intent(in) :: dnvfrac_t
1071 real, dimension(ele_ngi(t, ele)), intent(in) :: detwei1175 real, dimension(ele_ngi(t, ele)), intent(in) :: detwei
1072 real, dimension(ele_loc(t, ele)), intent(inout) :: rhs_addto1176 real, dimension(ele_loc(t, ele)), intent(inout) :: rhs_addto
1073 1177
1178 real, dimension(velocity%dim, ele_ngi(t, ele)) :: nvfracgrad_at_quad
1179 real, dimension(ele_ngi(t, ele)) :: udotgradnvfrac_at_quad
1180
1074 assert(equation_type==FIELD_EQUATION_INTERNALENERGY)1181 assert(equation_type==FIELD_EQUATION_INTERNALENERGY)
1075 assert(ele_ngi(pressure, ele)==ele_ngi(t, ele))1182 assert(ele_ngi(pressure, ele)==ele_ngi(t, ele))
1076 1183
1077 rhs_addto = rhs_addto - &1184 if(multiphase) then
1078 shape_rhs(test_function, ele_div_at_quad(velocity, ele, du_t) * ele_val_at_quad(pressure, ele) * detwei)1185 ! -p * (div(vfrac*nu))
1186 nvfracgrad_at_quad = ele_grad_at_quad(nvfrac, ele, dnvfrac_t)
1187 udotgradnvfrac_at_quad = sum(nvfracgrad_at_quad*ele_val_at_quad(velocity, ele), 1)
1188
1189 rhs_addto = rhs_addto - ( shape_rhs(test_function, ele_div_at_quad(velocity, ele, du_t) * ele_val_at_quad(nvfrac, ele) * ele_val_at_quad(pressure, ele) * detwei) &
1190 + shape_rhs(test_function, udotgradnvfrac_at_quad * ele_val_at_quad(pressure, ele) * detwei) )
1191 else
1192 rhs_addto = rhs_addto - shape_rhs(test_function, ele_div_at_quad(velocity, ele, du_t) * ele_val_at_quad(pressure, ele) * detwei)
1193 end if
1079 1194
1080 end subroutine add_pressurediv_element_cg1195 end subroutine add_pressurediv_element_cg
1081 1196
1082 subroutine assemble_advection_diffusion_face_cg(face, bc_type, t, t_bc, t_bc_2, matrix, rhs, positions, velocity, grid_velocity, density, olddensity)1197 subroutine assemble_advection_diffusion_face_cg(face, bc_type, t, t_bc, t_bc_2, matrix, rhs, positions, velocity, grid_velocity, density, olddensity, nvfrac)
1083 integer, intent(in) :: face1198 integer, intent(in) :: face
1084 integer, intent(in) :: bc_type1199 integer, intent(in) :: bc_type
1085 type(scalar_field), intent(in) :: t1200 type(scalar_field), intent(in) :: t
@@ -1092,6 +1207,7 @@
1092 type(vector_field), pointer :: grid_velocity1207 type(vector_field), pointer :: grid_velocity
1093 type(scalar_field), intent(in) :: density1208 type(scalar_field), intent(in) :: density
1094 type(scalar_field), intent(in) :: olddensity1209 type(scalar_field), intent(in) :: olddensity
1210 type(scalar_field), intent(in) :: nvfrac
1095 1211
1096 integer, dimension(face_loc(t, face)) :: face_nodes1212 integer, dimension(face_loc(t, face)) :: face_nodes
1097 real, dimension(face_ngi(t, face)) :: detwei1213 real, dimension(face_ngi(t, face)) :: detwei
@@ -1125,7 +1241,7 @@
1125 1241
1126 ! Advection1242 ! Advection
1127 if(have_advection .and. integrate_advection_by_parts) &1243 if(have_advection .and. integrate_advection_by_parts) &
1128 call add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, detwei, normal, matrix_addto, rhs_addto)1244 call add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, nvfrac, detwei, normal, matrix_addto, rhs_addto)
1129 1245
1130 ! Diffusivity1246 ! Diffusivity
1131 if(have_diffusivity) call add_diffusivity_face_cg(face, bc_type, t, t_bc, t_bc_2, detwei, matrix_addto, rhs_addto)1247 if(have_diffusivity) call add_diffusivity_face_cg(face, bc_type, t, t_bc, t_bc_2, detwei, matrix_addto, rhs_addto)
@@ -1138,7 +1254,7 @@
1138 1254
1139 end subroutine assemble_advection_diffusion_face_cg1255 end subroutine assemble_advection_diffusion_face_cg
1140 1256
1141 subroutine add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, detwei, normal, matrix_addto, rhs_addto)1257 subroutine add_advection_face_cg(face, bc_type, t, t_bc, velocity, grid_velocity, density, olddensity, nvfrac, detwei, normal, matrix_addto, rhs_addto)
1142 integer, intent(in) :: face1258 integer, intent(in) :: face
1143 integer, intent(in) :: bc_type1259 integer, intent(in) :: bc_type
1144 type(scalar_field), intent(in) :: t1260 type(scalar_field), intent(in) :: t
@@ -1147,6 +1263,7 @@
1147 type(vector_field), pointer :: grid_velocity1263 type(vector_field), pointer :: grid_velocity
1148 type(scalar_field), intent(in) :: density1264 type(scalar_field), intent(in) :: density
1149 type(scalar_field), intent(in) :: olddensity1265 type(scalar_field), intent(in) :: olddensity
1266 type(scalar_field), intent(in) :: nvfrac
1150 real, dimension(face_ngi(t, face)), intent(in) :: detwei1267 real, dimension(face_ngi(t, face)), intent(in) :: detwei
1151 real, dimension(mesh_dim(t), face_ngi(t, face)), intent(in) :: normal1268 real, dimension(mesh_dim(t), face_ngi(t, face)), intent(in) :: normal
1152 real, dimension(face_loc(t, face), face_loc(t, face)), intent(inout) :: matrix_addto1269 real, dimension(face_loc(t, face), face_loc(t, face)), intent(inout) :: matrix_addto
@@ -1171,8 +1288,12 @@
1171 case(FIELD_EQUATION_INTERNALENERGY)1288 case(FIELD_EQUATION_INTERNALENERGY)
1172 density_at_quad = density_theta*face_val_at_quad(density, face) &1289 density_at_quad = density_theta*face_val_at_quad(density, face) &
1173 +(1.0-density_theta)*face_val_at_quad(olddensity, face)1290 +(1.0-density_theta)*face_val_at_quad(olddensity, face)
11741291
1175 advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1) * density_at_quad)1292 if(multiphase) then
1293 advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1) * density_at_quad * face_val_at_quad(nvfrac, face))
1294 else
1295 advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1) * density_at_quad)
1296 end if
1176 case default1297 case default
1177 1298
1178 advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1))1299 advection_mat = shape_shape(t_shape, t_shape, detwei * sum(velocity_at_quad * normal, 1))
11791300
=== modified file 'assemble/Compressible_Projection.F90'
--- assemble/Compressible_Projection.F90 2012-01-20 15:54:44 +0000
+++ assemble/Compressible_Projection.F90 2012-08-09 00:46:20 +0000
@@ -39,6 +39,7 @@
39 use fefields, only: compute_cv_mass39 use fefields, only: compute_cv_mass
40 use state_fields_module40 use state_fields_module
41 use upwind_stabilisation41 use upwind_stabilisation
42 use multiphase_module
42 implicit none 43 implicit none
4344
44 ! Buffer for output messages.45 ! Buffer for output messages.
@@ -56,7 +57,10 @@
56 integer :: nu_bar_scheme57 integer :: nu_bar_scheme
57 real :: nu_bar_scale58 real :: nu_bar_scale
5859
59contains60 !! Are we running a multiphase flow simulation?
61 logical :: multiphase
62
63 contains
6064
61 subroutine assemble_compressible_projection_cv(state, cmc, rhs, dt, theta_pg, theta_divergence, cmcget)65 subroutine assemble_compressible_projection_cv(state, cmc, rhs, dt, theta_pg, theta_divergence, cmcget)
6266
@@ -367,11 +371,12 @@
367371
368 end subroutine assemble_mmat_compressible_projection_cv372 end subroutine assemble_mmat_compressible_projection_cv
369 373
370 subroutine assemble_compressible_projection_cg(state, cmc, rhs, dt, theta_pg, theta_divergence, cmcget)374 subroutine assemble_compressible_projection_cg(state, istate, cmc, rhs, dt, theta_pg, theta_divergence, cmcget)
371375
372 ! inputs:376 ! inputs:
373 ! bucket full of fields377 ! bucket full of fields
374 type(state_type), dimension(:), intent(inout) :: state378 type(state_type), dimension(:), intent(inout) :: state
379 integer, intent(in) :: istate
375380
376 type(csr_matrix), intent(inout) :: cmc381 type(csr_matrix), intent(inout) :: cmc
377 type(scalar_field), intent(inout) :: rhs382 type(scalar_field), intent(inout) :: rhs
@@ -380,17 +385,25 @@
380 real, intent(in) :: theta_pg, theta_divergence385 real, intent(in) :: theta_pg, theta_divergence
381 logical, intent(in) :: cmcget386 logical, intent(in) :: cmcget
382387
383 if((size(state)==1).and.(.not.has_scalar_field(state(1), "MaterialVolumeFraction"))) then388 if(option_count("/material_phase/vector_field::Velocity/prognostic") > 1) then
384 389 multiphase = .true.
385 call assemble_1mat_compressible_projection_cg(state(1), cmc, rhs, dt, &390 call assemble_1mat_compressible_projection_cg(state(istate), cmc, rhs, dt, &
386 theta_pg, theta_divergence, cmcget)391 theta_pg, theta_divergence, cmcget)
387
388 else392 else
389 393 multiphase = .false.
390 FLExit("Multimaterial compressible continuous_galerkin pressure not possible.")394
391 395 if((size(state)==1).and.(.not.has_scalar_field(state(1), "MaterialVolumeFraction"))) then
392 end if396
393 397 call assemble_1mat_compressible_projection_cg(state(1), cmc, rhs, dt, &
398 theta_pg, theta_divergence, cmcget)
399
400 else
401
402 FLExit("Multimaterial compressible continuous_galerkin pressure not possible.")
403
404 end if
405
406 end if
394407
395 end subroutine assemble_compressible_projection_cg408 end subroutine assemble_compressible_projection_cg
396409
@@ -441,6 +454,11 @@
441 logical :: have_absorption, have_source454 logical :: have_absorption, have_source
442 integer :: stat455 integer :: stat
443456
457 !! Multiphase variables
458 ! Volume fraction fields
459 type(scalar_field), pointer :: vfrac
460 type(scalar_field) :: nvfrac
461
444 ! =============================================================462 ! =============================================================
445 ! Subroutine to construct the matrix CT_m (a.k.a. C1/2/3T).463 ! Subroutine to construct the matrix CT_m (a.k.a. C1/2/3T).
446 ! =============================================================464 ! =============================================================
@@ -470,6 +488,15 @@
470 488
471 velocity=>extract_vector_field(state, "Velocity")489 velocity=>extract_vector_field(state, "Velocity")
472 nonlinearvelocity=>extract_vector_field(state, "NonlinearVelocity") ! maybe this should be updated after the velocity solve?490 nonlinearvelocity=>extract_vector_field(state, "NonlinearVelocity") ! maybe this should be updated after the velocity solve?
491
492 ! Get the non-linear PhaseVolumeFraction field if multiphase
493 if(multiphase) then
494 vfrac => extract_scalar_field(state, "PhaseVolumeFraction")
495 call allocate(nvfrac, vfrac%mesh, "NonlinearPhaseVolumeFraction")
496 call zero(nvfrac)
497 call get_nonlinear_volume_fraction(state, nvfrac)
498 ewrite_minmax(nvfrac)
499 end if
473 500
474 pressure => extract_scalar_field(state, "Pressure")501 pressure => extract_scalar_field(state, "Pressure")
475 502
@@ -552,7 +579,11 @@
552 ! Important note: with SUPG the test function derivatives have not been579 ! Important note: with SUPG the test function derivatives have not been
553 ! modified.580 ! modified.
554 581
555 ele_mat = (1./(dt*dt*theta_divergence*theta_pg))*shape_shape(test_shape, test_shape_ptr, detwei*drhodp_at_quad)582 if(multiphase) then
583 ele_mat = (1./(dt*dt*theta_divergence*theta_pg))*shape_shape(test_shape, test_shape_ptr, detwei*ele_val_at_quad(nvfrac, ele)*drhodp_at_quad)
584 else
585 ele_mat = (1./(dt*dt*theta_divergence*theta_pg))*shape_shape(test_shape, test_shape_ptr, detwei*drhodp_at_quad)
586 end if
556 ! /587 ! /
557 ! rhs = |test_shape* &588 ! rhs = |test_shape* &
558 ! /589 ! /
@@ -560,8 +591,14 @@
560 ! +(absorption)*(drhodp*theta*(eospressure - (pressure + atmospheric_pressure)) 591 ! +(absorption)*(drhodp*theta*(eospressure - (pressure + atmospheric_pressure))
561 ! - theta*density - (1-theta)*olddensity)592 ! - theta*density - (1-theta)*olddensity)
562 ! +source)dV593 ! +source)dV
563 ele_rhs = (1./dt)*shape_rhs(test_shape, detwei*((drhodp_at_quad*(eosp_at_quad - p_at_quad)) &594
564 +(olddensity_at_quad - density_at_quad)))595 if(multiphase) then
596 ele_rhs = (1./dt)*shape_rhs(test_shape, detwei*(ele_val_at_quad(nvfrac, ele))*((drhodp_at_quad*(eosp_at_quad - p_at_quad)) &
597 +(olddensity_at_quad - density_at_quad)))
598 else
599 ele_rhs = (1./dt)*shape_rhs(test_shape, detwei*((drhodp_at_quad*(eosp_at_quad - p_at_quad)) &
600 +(olddensity_at_quad - density_at_quad)))
601 end if
565 602
566 if(have_source) then603 if(have_source) then
567 ele_rhs = ele_rhs + shape_rhs(test_shape, detwei*ele_val_at_quad(source, ele))604 ele_rhs = ele_rhs + shape_rhs(test_shape, detwei*ele_val_at_quad(source, ele))
@@ -587,6 +624,10 @@
587 624
588 call deallocate(drhodp)625 call deallocate(drhodp)
589 call deallocate(eospressure)626 call deallocate(eospressure)
627
628 if(multiphase) then
629 call deallocate(nvfrac)
630 end if
590 631
591 end if632 end if
592633
@@ -597,17 +638,29 @@
597 type(state_type), dimension(:), intent(inout) :: state638 type(state_type), dimension(:), intent(inout) :: state
598 639
599 type(scalar_field), pointer :: density640 type(scalar_field), pointer :: density
600 641
601 if((size(state)==1).and.(.not.has_scalar_field(state(1), "MaterialVolumeFraction"))) then642 integer :: istate
602 643
603 density=>extract_scalar_field(state(1),'Density')644 if(option_count("/material_phase/vector_field::Velocity/prognostic") > 1) then
604 645 do istate=1,size(state)
605 if(have_option(trim(density%option_path)//"/prognostic")) then646 density=>extract_scalar_field(state(istate),'Density')
606 647
607 call compressible_eos(state(1), density=density)648 if(have_option(trim(density%option_path)//"/prognostic")) then
608 649 call compressible_eos(state(istate), density=density)
609 end if650 end if
610 651 end do
652 else
653 if((size(state)==1).and.(.not.has_scalar_field(state(1), "MaterialVolumeFraction"))) then
654
655 density=>extract_scalar_field(state(1),'Density')
656
657 if(have_option(trim(density%option_path)//"/prognostic")) then
658
659 call compressible_eos(state(1), density=density)
660
661 end if
662
663 end if
611 end if664 end if
612 665
613 end subroutine update_compressible_density666 end subroutine update_compressible_density
@@ -620,8 +673,8 @@
620 do i=0, option_count("/material_phase")-1673 do i=0, option_count("/material_phase")-1
621 prognostic_pressure_path="/material_phase"//int2str(i)//"/scalar_field::Pressure/prognostic"674 prognostic_pressure_path="/material_phase"//int2str(i)//"/scalar_field::Pressure/prognostic"
622 if (have_option(trim(prognostic_pressure_path)//"/spatial_discretisation/discontinuous_galerkin") &675 if (have_option(trim(prognostic_pressure_path)//"/spatial_discretisation/discontinuous_galerkin") &
623 .and. have_option(trim(prognostic_pressure_path)//"/scheme/use_compressible_projection")) then676 .and. have_option(trim(prognostic_pressure_path)//"/scheme/use_compressible_projection_method")) then
624 FLExit("With a DG pressure you cannot have use_compressible_projection")677 FLExit("With a DG pressure you cannot have use_compressible_projection_method")
625 end if678 end if
626 end do679 end do
627680
628681
=== modified file 'assemble/Diagnostic_Fields_Matrices.F90'
--- assemble/Diagnostic_Fields_Matrices.F90 2012-05-27 16:09:33 +0000
+++ assemble/Diagnostic_Fields_Matrices.F90 2012-08-09 00:46:20 +0000
@@ -40,7 +40,7 @@
40 use spud40 use spud
41 use parallel_fields, only: zero_non_owned41 use parallel_fields, only: zero_non_owned
42 use divergence_matrix_cv, only: assemble_divergence_matrix_cv42 use divergence_matrix_cv, only: assemble_divergence_matrix_cv
43 use divergence_matrix_cg, only: assemble_divergence_matrix_cg43 use divergence_matrix_cg, only: assemble_divergence_matrix_cg, assemble_compressible_divergence_matrix_cg
44 use gradient_matrix_cg, only: assemble_gradient_matrix_cg44 use gradient_matrix_cg, only: assemble_gradient_matrix_cg
45 use parallel_tools45 use parallel_tools
46 use sparsity_patterns, only: make_sparsity46 use sparsity_patterns, only: make_sparsity
@@ -58,7 +58,8 @@
58 58
59 public :: calculate_divergence_cv, calculate_divergence_fe, &59 public :: calculate_divergence_cv, calculate_divergence_fe, &
60 calculate_div_t_cv, calculate_div_t_fe, &60 calculate_div_t_cv, calculate_div_t_fe, &
61 calculate_grad_fe, calculate_sum_velocity_divergence61 calculate_grad_fe, calculate_sum_velocity_divergence, &
62 calculate_compressible_continuity_residual
6263
63contains64contains
6465
@@ -356,9 +357,9 @@
356357
357 ! Allocate memory for matrices and sparsity patterns358 ! Allocate memory for matrices and sparsity patterns
358 call allocate(ctfield, sum_velocity_divergence%mesh, name="CTField")359 call allocate(ctfield, sum_velocity_divergence%mesh, name="CTField")
359 call zero (ctfield)360 call zero(ctfield)
360 call allocate(temp, sum_velocity_divergence%mesh, name="Temp")361 call allocate(temp, sum_velocity_divergence%mesh, name="Temp")
361 362
362 ! Require a mass matrix type if not CV tested equation.363 ! Require a mass matrix type if not CV tested equation.
363 if (.not. test_with_cv_dual) then364 if (.not. test_with_cv_dual) then
364 mass_sparsity=make_sparsity(sum_velocity_divergence%mesh, sum_velocity_divergence%mesh, "MassSparsity")365 mass_sparsity=make_sparsity(sum_velocity_divergence%mesh, sum_velocity_divergence%mesh, "MassSparsity")
@@ -382,27 +383,29 @@
382383
383 ! Allocate sparsity patterns, C^T matrix and C^T RHS for current state384 ! Allocate sparsity patterns, C^T matrix and C^T RHS for current state
384 divergence_sparsity=make_sparsity(sum_velocity_divergence%mesh, u%mesh, "DivergenceSparsity")385 divergence_sparsity=make_sparsity(sum_velocity_divergence%mesh, u%mesh, "DivergenceSparsity")
386
385 allocate(ct_m)387 allocate(ct_m)
386 call allocate(ct_m, divergence_sparsity, (/1, u%dim/), name="DivergenceMatrix" )388 call allocate(ct_m, divergence_sparsity, (/1, u%dim/), name="DivergenceMatrix" )
387 call allocate(ct_rhs, sum_velocity_divergence%mesh, name="CTRHS")389 call allocate(ct_rhs, sum_velocity_divergence%mesh, name="CTRHS")
388 390
389 ! Reassemble C^T matrix here391 ! Reassemble C^T matrix here
390 if (test_with_cv_dual) then392 if (test_with_cv_dual) then
391 call assemble_divergence_matrix_cv(ct_m, state(i), ct_rhs=ct_rhs, &393 call assemble_divergence_matrix_cv(ct_m, state(i), ct_rhs=ct_rhs, &
392 test_mesh=sum_velocity_divergence%mesh, field=u)394 test_mesh=sum_velocity_divergence%mesh, field=u)
393 else395 else
394 if(i==1) then ! Construct the mass matrix (just do this once) 396 if(i==1) then ! Construct the mass matrix (just do this once)
395 call assemble_divergence_matrix_cg(ct_m, state(i), ct_rhs=ct_rhs, &397 call assemble_divergence_matrix_cg(ct_m, state(i), ct_rhs=ct_rhs, &
396 test_mesh=sum_velocity_divergence%mesh, field=u, &398 test_mesh=sum_velocity_divergence%mesh, field=u, &
397 option_path=sum_velocity_divergence%option_path, div_mass=mass)399 option_path=sum_velocity_divergence%option_path, div_mass=mass)
398 else400 else
399 call assemble_divergence_matrix_cg(ct_m, state(i), ct_rhs=ct_rhs, &401 call assemble_divergence_matrix_cg(ct_m, state(i), ct_rhs=ct_rhs, &
400 test_mesh=sum_velocity_divergence%mesh, field=u, &402 test_mesh=sum_velocity_divergence%mesh, field=u, &
401 option_path=sum_velocity_divergence%option_path)403 option_path=sum_velocity_divergence%option_path)
402 end if 404 end if
405
403 end if406 end if
404407
405 ! Construct the linear system of equations to solve for \sum{div(vfrac*u)}408 ! Construct the linear system of equations
406 call zero(temp)409 call zero(temp)
407 call mult(temp, ct_m, u)410 call mult(temp, ct_m, u)
408 call addto(temp, ct_rhs, -1.0)411 call addto(temp, ct_rhs, -1.0)
@@ -417,7 +420,8 @@
417420
418 end do421 end do
419422
420 ! Solve for sum_velocity_divergence ( = \sum{div(vfrac*u)} ) 423 ! Solve for sum_velocity_divergence
424 ! ( = \sum{div(vfrac*u)} for incompressible multiphase flows )
421 if (test_with_cv_dual) then425 if (test_with_cv_dual) then
422 ! get the cv mass matrix426 ! get the cv mass matrix
423 cv_mass => get_cv_mass(state(1), sum_velocity_divergence%mesh)427 cv_mass => get_cv_mass(state(1), sum_velocity_divergence%mesh)
@@ -442,4 +446,148 @@
442 446
443 end subroutine calculate_sum_velocity_divergence447 end subroutine calculate_sum_velocity_divergence
444448
449
450 subroutine calculate_compressible_continuity_residual(state, compressible_continuity_residual)
451 !!< Calculates the residual of the continity equation used in compressible multiphase flow simulations:
452 !!< vfrac_c*d(rho_c)/dt + div(rho_c*vfrac_c*u_c) + \sum_i{ rho_c*div(vfrac_i*u_i) }
453
454 type(state_type), dimension(:), intent(inout) :: state
455 type(scalar_field), pointer :: compressible_continuity_residual, density, olddensity, vfrac
456 type(scalar_field) :: drhodt
457
458 ! Local variables
459 type(vector_field), pointer :: u, x
460 integer :: i, stat, ele
461 logical :: dg
462
463 type(csr_sparsity) :: divergence_sparsity
464 type(block_csr_matrix), pointer :: ct_m
465
466 type(csr_sparsity) :: mass_sparsity
467 type(csr_matrix) :: mass
468 type(scalar_field) :: ctfield, ct_rhs, temp
469
470 type(element_type) :: test_function
471 type(element_type), pointer :: compressible_continuity_residual_shape
472 integer, dimension(:), pointer :: compressible_continuity_residual_nodes
473 real, dimension(:), allocatable :: detwei
474 real, dimension(:), allocatable :: drhodt_addto
475
476 real :: dt
477
478 ewrite(1,*) 'Entering calculate_compressible_continuity_residual'
479
480 ! Allocate memory for matrices and sparsity patterns
481 call allocate(ctfield, compressible_continuity_residual%mesh, name="CTField")
482 call zero(ctfield)
483 call allocate(temp, compressible_continuity_residual%mesh, name="Temp")
484
485 mass_sparsity=make_sparsity(compressible_continuity_residual%mesh, compressible_continuity_residual%mesh, "MassSparsity")
486 call allocate(mass, mass_sparsity, name="MassMatrix")
487 call zero(mass)
488
489 call get_option("/timestepping/timestep", dt)
490
491 ! Sum up over the div's
492 do i = 1, size(state)
493 u => extract_vector_field(state(i), "Velocity", stat)
494
495 ! If there's no velocity then cycle
496 if(stat/=0) cycle
497 ! If this is an aliased velocity then cycle
498 if(aliased(u)) cycle
499 ! If the velocity isn't prognostic then cycle
500 if(.not.have_option(trim(u%option_path)//"/prognostic")) cycle
501
502 ! If velocity field is prognostic, begin calculations below
503 x => extract_vector_field(state(i), "Coordinate")
504
505 ! Allocate sparsity patterns, C^T matrix and C^T RHS for current state
506 divergence_sparsity=make_sparsity(compressible_continuity_residual%mesh, u%mesh, "DivergenceSparsity")
507 allocate(ct_m)
508 call allocate(ct_m, divergence_sparsity, (/1, u%dim/), name="DivergenceMatrix")
509 call allocate(ct_rhs, compressible_continuity_residual%mesh, name="CTRHS")
510
511 ! Reassemble C^T matrix here
512 if(i==1) then ! Construct the mass matrix (just do this once)
513 call assemble_compressible_divergence_matrix_cg(ct_m, state, i, ct_rhs, div_mass=mass)
514 else
515 call assemble_compressible_divergence_matrix_cg(ct_m, state, i, ct_rhs)
516 end if
517
518 if(have_option("/material_phase::"//trim(state(i)%name)//"/equation_of_state/compressible")) then
519 ! Get the time derivative term for the compressible phase's density, vfrac_c * d(rho_c)/dt
520
521 call allocate(drhodt, compressible_continuity_residual%mesh, name="drhodt")
522
523 density => extract_scalar_field(state(i), "Density", stat)
524 olddensity => extract_scalar_field(state(i), "OldDensity", stat)
525 vfrac => extract_scalar_field(state(i), "PhaseVolumeFraction")
526
527 ! Assumes Density and OldDensity are on the same mesh as Pressure,
528 ! as it should be according to the manual.
529 call zero(drhodt)
530
531 dg = continuity(compressible_continuity_residual) < 0
532
533 element_loop: do ele = 1, element_count(compressible_continuity_residual)
534
535 if(.not.dg .or. (dg .and. element_owned(compressible_continuity_residual,ele))) then
536
537 allocate(detwei(ele_ngi(compressible_continuity_residual, ele)))
538 allocate(drhodt_addto(ele_loc(compressible_continuity_residual, ele)))
539
540 compressible_continuity_residual_nodes => ele_nodes(compressible_continuity_residual, ele)
541 compressible_continuity_residual_shape => ele_shape(compressible_continuity_residual, ele)
542 test_function = compressible_continuity_residual_shape
543
544 call transform_to_physical(x, ele, detwei=detwei)
545
546 drhodt_addto = shape_rhs(test_function, detwei*(ele_val_at_quad(vfrac,ele)*(ele_val_at_quad(density,ele) - ele_val_at_quad(olddensity,ele))/dt))
547
548 call addto(drhodt, compressible_continuity_residual_nodes, drhodt_addto)
549
550 deallocate(detwei)
551 deallocate(drhodt_addto)
552 end if
553
554 end do element_loop
555
556 call addto(ctfield, drhodt)
557
558 call deallocate(drhodt)
559
560 end if
561
562 ! Construct the linear system of equations
563 call zero(temp)
564 call mult(temp, ct_m, u)
565 call addto(temp, ct_rhs, -1.0)
566
567 ! Now add it to the sum
568 call addto(ctfield, temp)
569
570 call deallocate(ct_m)
571 deallocate(ct_m)
572 call deallocate(ct_rhs)
573 call deallocate(divergence_sparsity)
574
575 end do
576
577 ! Solve for compressible_continuity_residual
578 call zero(compressible_continuity_residual)
579 call petsc_solve(compressible_continuity_residual, mass, ctfield)
580 ewrite_minmax(compressible_continuity_residual)
581
582 ! Deallocate memory
583 call deallocate(ctfield)
584 call deallocate(temp)
585 call deallocate(mass_sparsity)
586 call deallocate(mass)
587
588 ewrite(1,*) 'Exiting calculate_compressible_continuity_residual'
589
590 end subroutine calculate_compressible_continuity_residual
591
592
445end module diagnostic_fields_matrices593end module diagnostic_fields_matrices
446594
=== modified file 'assemble/Diagnostic_fields_wrapper.F90'
--- assemble/Diagnostic_fields_wrapper.F90 2012-02-18 15:45:48 +0000
+++ assemble/Diagnostic_fields_wrapper.F90 2012-08-09 00:46:20 +0000
@@ -585,6 +585,21 @@
585 FLExit("The SumVelocityDivergence field is only used in multiphase simulations.")585 FLExit("The SumVelocityDivergence field is only used in multiphase simulations.")
586 end if586 end if
587 end if587 end if
588
589 s_field => extract_scalar_field(state(i), "CompressibleContinuityResidual", stat)
590 if(stat == 0) then
591 ! Check that we are running a compressible multiphase simulation
592 if(option_count("/material_phase/vector_field::Velocity/prognostic") > 1 .and. option_count("/material_phase/equation_of_state/compressible") > 0) then
593 diagnostic = have_option(trim(s_field%option_path)//"/diagnostic")
594 if(diagnostic .and. .not.(aliased(s_field))) then
595 if(recalculate(trim(s_field%option_path))) then
596 call calculate_compressible_continuity_residual(state, s_field)
597 end if
598 end if
599 else
600 FLExit("The CompressibleContinuityResidual field is only used in compressible multiphase simulations.")
601 end if
602 end if
588603
589 ! end of fields that cannot be called through the generic604 ! end of fields that cannot be called through the generic
590 ! calculate_diagnostic_variable interface, i.e. - those that need things605 ! calculate_diagnostic_variable interface, i.e. - those that need things
591606
=== modified file 'assemble/Divergence_Matrix_CG.F90'
--- assemble/Divergence_Matrix_CG.F90 2012-05-27 16:09:33 +0000
+++ assemble/Divergence_Matrix_CG.F90 2012-08-09 00:46:20 +0000
@@ -58,7 +58,10 @@
58 integer :: nu_bar_scheme58 integer :: nu_bar_scheme
59 real :: nu_bar_scale59 real :: nu_bar_scale
6060
61contains61 !! Are we running a multiphase flow simulation?
62 logical :: multiphase
63
64 contains
6265
63 subroutine assemble_divergence_matrix_cg(CT_m, state, ct_rhs, & 66 subroutine assemble_divergence_matrix_cg(CT_m, state, ct_rhs, &
64 test_mesh, field, option_path, &67 test_mesh, field, option_path, &
@@ -119,7 +122,6 @@
119 logical :: l_get_ct122 logical :: l_get_ct
120123
121 !! Multiphase variables124 !! Multiphase variables
122 logical :: multiphase
123 ! Volume fraction fields125 ! Volume fraction fields
124 type(scalar_field), pointer :: vfrac126 type(scalar_field), pointer :: vfrac
125 type(scalar_field) :: nvfrac127 type(scalar_field) :: nvfrac
@@ -355,40 +357,55 @@
355357
356 end subroutine assemble_divergence_matrix_cg358 end subroutine assemble_divergence_matrix_cg
357359
358 subroutine assemble_compressible_divergence_matrix_cg(ctp_m, state, ct_rhs)360 subroutine assemble_compressible_divergence_matrix_cg(ctp_m, state, istate, ct_rhs, div_mass)
359 361
360 ! inputs/outputs362 ! inputs/outputs
361 ! bucket full of fields363 ! bucket full of fields
362 type(state_type), dimension(:), intent(inout) :: state364 type(state_type), dimension(:), intent(inout) :: state
363365 integer, intent(in) :: istate
364 ! the compressible divergence matrix366 ! the compressible divergence matrix
365 type(block_csr_matrix), pointer :: ctp_m367 type(block_csr_matrix), pointer :: ctp_m
366368
367 type(scalar_field), intent(inout), optional :: ct_rhs369 type(scalar_field), intent(inout), optional :: ct_rhs
368370
369 if((size(state)==1).and.(.not.has_scalar_field(state(1), "MaterialVolumeFraction"))) then371 type(csr_matrix), intent(inout), optional :: div_mass
370 372
371 call assemble_1mat_compressible_divergence_matrix_cg(ctp_m, state(1), ct_rhs)373 if(option_count("/material_phase/vector_field::Velocity/prognostic") > 1) then
372 374 multiphase = .true.
375 call assemble_1mat_compressible_divergence_matrix_cg(ctp_m, state, istate, ct_rhs, div_mass)
373 else376 else
374 377 multiphase = .false.
375 FLExit("Multimaterial compressible continuous_galerkin pressure not possible.")378
376 379 if((size(state)==1).and.(.not.has_scalar_field(state(1), "MaterialVolumeFraction"))) then
380
381 call assemble_1mat_compressible_divergence_matrix_cg(ctp_m, state, 1, ct_rhs, div_mass)
382
383 else
384
385 FLExit("Multimaterial compressible continuous_galerkin pressure not possible.")
386
387 end if
388
377 end if389 end if
390
391
378 392
379 end subroutine assemble_compressible_divergence_matrix_cg393 end subroutine assemble_compressible_divergence_matrix_cg
380394
381 subroutine assemble_1mat_compressible_divergence_matrix_cg(ctp_m, state, ct_rhs) 395 subroutine assemble_1mat_compressible_divergence_matrix_cg(ctp_m, state, istate, ct_rhs, div_mass)
382396
383 ! inputs/outputs397 ! inputs/outputs
384 ! bucket full of fields398 ! bucket full of fields
385 type(state_type), intent(inout) :: state399 type(state_type), dimension(:), intent(inout) :: state
400 integer, intent(in) :: istate
386401
387 ! the compressible divergence matrix402 ! the compressible divergence matrix
388 type(block_csr_matrix), pointer :: ctp_m403 type(block_csr_matrix), pointer :: ctp_m
389404
390 type(scalar_field), intent(inout), optional :: ct_rhs405 type(scalar_field), intent(inout), optional :: ct_rhs
391406
407 type(csr_matrix), intent(inout), optional :: div_mass
408
392 ! local409 ! local
393 type(mesh_type), pointer :: test_mesh410 type(mesh_type), pointer :: test_mesh
394411
@@ -408,6 +425,8 @@
408 real, dimension(:), allocatable :: density_at_quad, olddensity_at_quad425 real, dimension(:), allocatable :: density_at_quad, olddensity_at_quad
409 real, dimension(:,:), allocatable :: density_grad_at_quad, nlvelocity_at_quad426 real, dimension(:,:), allocatable :: density_grad_at_quad, nlvelocity_at_quad
410427
428 real, dimension(:,:), allocatable :: div_mass_mat
429
411 ! loop integers430 ! loop integers
412 integer :: ele, sele, dim431 integer :: ele, sele, dim
413432
@@ -425,7 +444,16 @@
425 integer, dimension(:), allocatable :: density_bc_type444 integer, dimension(:), allocatable :: density_bc_type
426 type(scalar_field) :: density_bc445 type(scalar_field) :: density_bc
427 446
428 integer :: stat447 integer :: i, stat
448
449 !! Multiphase variables
450 ! Volume fraction fields
451 type(scalar_field), pointer :: vfrac
452 type(scalar_field) :: nvfrac
453 type(element_type), pointer :: nvfrac_shape
454 ! Transformed gradient function for the non-linear PhaseVolumeFraction.
455 real, dimension(:, :, :), allocatable :: dnvfrac_t
456 logical :: is_compressible_phase ! Is this the (single) compressible phase in a multiphase simulation?
429457
430 ! =============================================================458 ! =============================================================
431 ! Subroutine to construct the matrix ctp_m (a.k.a. C1/2/3TP).459 ! Subroutine to construct the matrix ctp_m (a.k.a. C1/2/3TP).
@@ -433,16 +461,42 @@
433461
434 ewrite(2,*) 'In assemble_1mat_compressible_divergence_matrix_cg'462 ewrite(2,*) 'In assemble_1mat_compressible_divergence_matrix_cg'
435463
436 coordinate=> extract_vector_field(state, "Coordinate")464 coordinate=> extract_vector_field(state(istate), "Coordinate")
437 465
438 density => extract_scalar_field(state, "Density")466 density => extract_scalar_field(state(istate), "Density")
439 olddensity => extract_scalar_field(state, "OldDensity")467 olddensity => extract_scalar_field(state(istate), "OldDensity")
440 468
441 pressure => extract_scalar_field(state, "Pressure")469 if(have_option(trim(state(istate)%option_path)//"/equation_of_state/compressible")) then
442 470 is_compressible_phase = .true.
443 velocity=>extract_vector_field(state, "Velocity")471 else
444 nonlinearvelocity=>extract_vector_field(state, "NonlinearVelocity") ! maybe this should be updated after the velocity solve?472 is_compressible_phase = .false.
445 473
474 ! Find the compressible phase and extract it's density to form rho_c * div(vfrac_i*u_i), where _c and _i represent
475 ! the compressible and incompressible phases respectively.
476 do i = 1, size(state)
477 if(have_option(trim(state(i)%option_path)//"/equation_of_state/compressible")) then
478 density => extract_scalar_field(state(i), "Density")
479 olddensity => extract_scalar_field(state(i), "OldDensity")
480 end if
481 end do
482 end if
483
484 pressure => extract_scalar_field(state(istate), "Pressure")
485
486 velocity=>extract_vector_field(state(istate), "Velocity")
487 nonlinearvelocity=>extract_vector_field(state(istate), "NonlinearVelocity") ! maybe this should be updated after the velocity solve?
488
489 ! Get the non-linear PhaseVolumeFraction field if multiphase
490 if(multiphase) then
491 vfrac => extract_scalar_field(state(istate), "PhaseVolumeFraction")
492 call allocate(nvfrac, vfrac%mesh, "NonlinearPhaseVolumeFraction")
493 call zero(nvfrac)
494 call get_nonlinear_volume_fraction(state(istate), nvfrac)
495 ewrite_minmax(nvfrac)
496 else
497 nullify(vfrac)
498 end if
499
446 integrate_by_parts=have_option(trim(complete_field_path(density%option_path, stat=stat))//&500 integrate_by_parts=have_option(trim(complete_field_path(density%option_path, stat=stat))//&
447 &"/spatial_discretisation/continuous_galerkin/advection_terms/integrate_advection_by_parts")&501 &"/spatial_discretisation/continuous_galerkin/advection_terms/integrate_advection_by_parts")&
448 .or. have_option(trim(complete_field_path(velocity%option_path, stat=stat))//&502 .or. have_option(trim(complete_field_path(velocity%option_path, stat=stat))//&
@@ -474,7 +528,7 @@
474 end if528 end if
475529
476 call get_option(trim(complete_field_path(density%option_path, stat=stat))//&530 call get_option(trim(complete_field_path(density%option_path, stat=stat))//&
477 &"/temporal_discretisation/theta", theta)531 &"/temporal_discretisation/theta", theta)
478 call get_option("/timestepping/timestep", dt)532 call get_option("/timestepping/timestep", dt)
479 533
480 test_mesh => pressure%mesh534 test_mesh => pressure%mesh
@@ -494,8 +548,14 @@
494 olddensity_at_quad(ele_ngi(density, 1)), &548 olddensity_at_quad(ele_ngi(density, 1)), &
495 nlvelocity_at_quad(nonlinearvelocity%dim, ele_ngi(nonlinearvelocity, 1)), &549 nlvelocity_at_quad(nonlinearvelocity%dim, ele_ngi(nonlinearvelocity, 1)), &
496 density_grad_at_quad(field%dim, ele_ngi(density,1)), &550 density_grad_at_quad(field%dim, ele_ngi(density,1)), &
497 j_mat(field%dim, field%dim, ele_ngi(density, 1)))551 j_mat(field%dim, field%dim, ele_ngi(density, 1)), &
552 div_mass_mat(ele_loc(test_mesh, 1), ele_loc(test_mesh, 1)))
498 553
554 if(multiphase) then
555 ! We will need grad(nvfrac) if we are not integrating by parts below
556 allocate(dnvfrac_t(ele_loc(nvfrac,1), ele_ngi(nvfrac,1), field%dim))
557 end if
558
499 do ele=1, element_count(test_mesh)559 do ele=1, element_count(test_mesh)
500560
501 test_nodes=>ele_nodes(test_mesh, ele)561 test_nodes=>ele_nodes(test_mesh, ele)
@@ -509,7 +569,7 @@
509 olddensity_at_quad = ele_val_at_quad(olddensity, ele)569 olddensity_at_quad = ele_val_at_quad(olddensity, ele)
510 570
511 nlvelocity_at_quad = ele_val_at_quad(nonlinearvelocity, ele)571 nlvelocity_at_quad = ele_val_at_quad(nonlinearvelocity, ele)
512 572
513 if(any(stabilisation_scheme == (/STABILISATION_STREAMLINE_UPWIND, STABILISATION_SUPG/))) then573 if(any(stabilisation_scheme == (/STABILISATION_STREAMLINE_UPWIND, STABILISATION_SUPG/))) then
514 call transform_to_physical(coordinate, ele, test_shape_ptr, dshape = dtest_t, &574 call transform_to_physical(coordinate, ele, test_shape_ptr, dshape = dtest_t, &
515 detwei = detwei, j = j_mat)575 detwei = detwei, j = j_mat)
@@ -517,7 +577,7 @@
517 call transform_to_physical(coordinate, ele, test_shape_ptr, dshape = dtest_t, detwei=detwei)577 call transform_to_physical(coordinate, ele, test_shape_ptr, dshape = dtest_t, detwei=detwei)
518 end if578 end if
519 579
520 if(.not.integrate_by_parts) then580 if(.not.integrate_by_parts .or. (multiphase .and. integrate_by_parts .and. .not.is_compressible_phase)) then
521 ! transform the field (velocity) derivatives into physical space581 ! transform the field (velocity) derivatives into physical space
522 call transform_to_physical(coordinate, ele, field_shape, dshape=dfield_t)582 call transform_to_physical(coordinate, ele, field_shape, dshape=dfield_t)
523 583
@@ -545,16 +605,53 @@
545605
546606
547 if(integrate_by_parts) then607 if(integrate_by_parts) then
608
548 ! if SUPG is fixed for P>1 then this dtest_t should be updated609 ! if SUPG is fixed for P>1 then this dtest_t should be updated
549 ele_mat = -dshape_shape(dtest_t, field_shape, &610 if(multiphase .and. .not.is_compressible_phase) then
550 detwei*(theta*density_at_quad + (1-theta)*olddensity_at_quad))611 density_grad_at_quad = theta*(ele_grad_at_quad(density, ele, ddensity_t))+&
612 (1-theta)*(ele_grad_at_quad(olddensity, ele, ddensity_t))
613
614 ele_mat = -dshape_shape(dtest_t, field_shape, detwei*ele_val_at_quad(nvfrac, ele)*(theta*density_at_quad + (1-theta)*olddensity_at_quad)) - shape_shape_vector(test_shape, field_shape, detwei*ele_val_at_quad(nvfrac, ele), density_grad_at_quad)
615
616 else if(multiphase .and. is_compressible_phase) then
617 ele_mat = -dshape_shape(dtest_t, field_shape, detwei*ele_val_at_quad(nvfrac, ele)*(theta*density_at_quad + (1-theta)*olddensity_at_quad))
618
619 else
620
621 ele_mat = -dshape_shape(dtest_t, field_shape, detwei*(theta*density_at_quad + (1-theta)*olddensity_at_quad))
622 end if
551 else623 else
552 density_grad_at_quad = theta*(ele_grad_at_quad(density, ele, ddensity_t))+&624 density_grad_at_quad = theta*(ele_grad_at_quad(density, ele, ddensity_t))+&
553 (1-theta)*(ele_grad_at_quad(olddensity, ele, ddensity_t))625 (1-theta)*(ele_grad_at_quad(olddensity, ele, ddensity_t))
554 626
555 ele_mat = shape_dshape(test_shape, dfield_t, &627 if(multiphase) then
628
629 ! If the field and nvfrac meshes are different, then we need to
630 ! compute the derivatives of the nvfrac shape functions.
631 if(.not.(nvfrac%mesh == field%mesh)) then
632 nvfrac_shape => ele_shape(nvfrac%mesh, ele)
633 call transform_to_physical(coordinate, ele, nvfrac_shape, dshape=dnvfrac_t)
634 else
635 dnvfrac_t = dfield_t
636 end if
637
638 ! Split up the divergence term div(rho*vfrac*u) = rho*div(u*vfrac) + vfrac*u*grad(rho)
639 ! = (rho*vfrac*div(u) + rho*u*grad(vfrac)) + u*vfrac*grad(rho)
640
641 ! First assemble rho*div(u*vfrac). This is the incompressible phase's divergence matrix.
642 ele_mat = shape_dshape(test_shape, dfield_t, detwei*(theta*density_at_quad + (1-theta)*olddensity_at_quad)*ele_val_at_quad(nvfrac, ele)) + shape_shape_vector(test_shape, field_shape, detwei*(theta*density_at_quad + (1-theta)*olddensity_at_quad), ele_grad_at_quad(nvfrac, ele, dnvfrac_t))
643
644 ! If the phase is compressible, then we now complete the assembly of div(rho*vfrac*u) below.
645 if(is_compressible_phase) then
646 ele_mat = ele_mat + shape_shape_vector(test_shape, field_shape, detwei*ele_val_at_quad(nvfrac, ele), density_grad_at_quad)
647 end if
648
649 else
650 ele_mat = shape_dshape(test_shape, dfield_t, &
556 detwei*(theta*density_at_quad + (1-theta)*olddensity_at_quad)) + &651 detwei*(theta*density_at_quad + (1-theta)*olddensity_at_quad)) + &
557 shape_shape_vector(test_shape, field_shape, detwei, density_grad_at_quad)652 shape_shape_vector(test_shape, field_shape, detwei, density_grad_at_quad)
653 end if
654
558 end if655 end if
559 656
560 ! Stabilisation does not return the right shape for this operator!657 ! Stabilisation does not return the right shape for this operator!
@@ -568,6 +665,11 @@
568 do dim = 1, field%dim665 do dim = 1, field%dim
569 call addto(ctp_m, 1, dim, test_nodes, field_nodes, ele_mat(dim,:,:))666 call addto(ctp_m, 1, dim, test_nodes, field_nodes, ele_mat(dim,:,:))
570 end do667 end do
668
669 if(present(div_mass)) then
670 div_mass_mat = shape_shape(test_shape, test_shape, detwei)
671 call addto(div_mass, test_nodes, test_nodes, div_mass_mat)
672 end if
571 673
572 call deallocate(test_shape)674 call deallocate(test_shape)
573 675
@@ -618,8 +720,14 @@
618 & detwei_f=detwei_bdy,&720 & detwei_f=detwei_bdy,&
619 & normal=normal_bdy) 721 & normal=normal_bdy)
620722
621 ele_mat_bdy = shape_shape_vector(test_shape_ptr, field_shape, &723
622 detwei_bdy*density_bdy, normal_bdy)724 if(multiphase) then
725 ele_mat_bdy = shape_shape_vector(test_shape_ptr, field_shape, &
726 detwei_bdy*density_bdy*face_val_at_quad(nvfrac, sele), normal_bdy)
727 else
728 ele_mat_bdy = shape_shape_vector(test_shape_ptr, field_shape, &
729 detwei_bdy*density_bdy, normal_bdy)
730 end if
623731
624 do dim = 1, field%dim732 do dim = 1, field%dim
625 if((field_bc_type(dim, sele)==1).and.present(ct_rhs)) then733 if((field_bc_type(dim, sele)==1).and.present(ct_rhs)) then
@@ -641,6 +749,11 @@
641 deallocate(test_nodes_bdy, field_nodes_bdy)749 deallocate(test_nodes_bdy, field_nodes_bdy)
642750
643 end if751 end if
752
753 if(multiphase) then
754 deallocate(dnvfrac_t)
755 call deallocate(nvfrac)
756 end if
644 757
645 end subroutine assemble_1mat_compressible_divergence_matrix_cg758 end subroutine assemble_1mat_compressible_divergence_matrix_cg
646759
647760
=== modified file 'assemble/Makefile.dependencies'
--- assemble/Makefile.dependencies 2012-08-02 13:03:52 +0000
+++ assemble/Makefile.dependencies 2012-08-09 00:46:20 +0000
@@ -79,12 +79,12 @@
79 ../include/boundary_conditions_from_options.mod ../include/colouring.mod \79 ../include/boundary_conditions_from_options.mod ../include/colouring.mod \
80 ../include/elements.mod ../include/fdebug.h ../include/field_options.mod \80 ../include/elements.mod ../include/fdebug.h ../include/field_options.mod \
81 ../include/fields.mod ../include/fldebug.mod \81 ../include/fields.mod ../include/fldebug.mod \
82 ../include/global_parameters.mod ../include/petsc_solve_state_module.mod \82 ../include/global_parameters.mod ../include/multiphase_module.mod \
83 ../include/porous_media.mod ../include/profiler.mod \83 ../include/petsc_solve_state_module.mod ../include/porous_media.mod \
84 ../include/quadrature.mod ../include/sparse_tools.mod \84 ../include/profiler.mod ../include/quadrature.mod \
85 ../include/sparse_tools_petsc.mod ../include/sparsity_patterns_meshes.mod \85 ../include/sparse_tools.mod ../include/sparse_tools_petsc.mod \
86 ../include/spud.mod ../include/state_module.mod \86 ../include/sparsity_patterns_meshes.mod ../include/spud.mod \
87 ../include/upwind_stabilisation.mod87 ../include/state_module.mod ../include/upwind_stabilisation.mod
8888
89../include/advection_diffusion_dg.mod: Advection_Diffusion_DG.o89../include/advection_diffusion_dg.mod: Advection_Diffusion_DG.o
90 @true90 @true
@@ -154,10 +154,10 @@
154 Compressible_Projection.F90 ../include/equation_of_state.mod \154 Compressible_Projection.F90 ../include/equation_of_state.mod \
155 ../include/fdebug.h ../include/fefields.mod ../include/field_options.mod \155 ../include/fdebug.h ../include/fefields.mod ../include/field_options.mod \
156 ../include/fields.mod ../include/fldebug.mod \156 ../include/fields.mod ../include/fldebug.mod \
157 ../include/global_parameters.mod ../include/sparse_matrices_fields.mod \157 ../include/global_parameters.mod ../include/multiphase_module.mod \
158 ../include/sparse_tools.mod ../include/spud.mod \158 ../include/sparse_matrices_fields.mod ../include/sparse_tools.mod \
159 ../include/state_fields_module.mod ../include/state_module.mod \159 ../include/spud.mod ../include/state_fields_module.mod \
160 ../include/upwind_stabilisation.mod160 ../include/state_module.mod ../include/upwind_stabilisation.mod
161161
162../include/coriolis_module.mod: Coriolis.o162../include/coriolis_module.mod: Coriolis.o
163 @true163 @true
164164
=== modified file 'assemble/Momentum_Equation.F90'
--- assemble/Momentum_Equation.F90 2012-04-16 14:55:55 +0000
+++ assemble/Momentum_Equation.F90 2012-08-09 00:46:20 +0000
@@ -92,7 +92,7 @@
92 logical :: assemble_schur_auxiliary_matrix92 logical :: assemble_schur_auxiliary_matrix
9393
94 ! Do we want to use the compressible projection method?94 ! Do we want to use the compressible projection method?
95 logical :: use_compressible_projection95 logical :: compressible_eos
96 ! Are we doing a full Schur solve?96 ! Are we doing a full Schur solve?
97 logical :: full_schur97 logical :: full_schur
98 ! Are we lumping mass or assuming consistent mass?98 ! Are we lumping mass or assuming consistent mass?
@@ -282,7 +282,7 @@
282 multiphase = .false.282 multiphase = .false.
283 end if283 end if
284 ! Do we have fluid-particle drag (for multi-phase simulations)?284 ! Do we have fluid-particle drag (for multi-phase simulations)?
285 have_fp_drag = option_count("/material_phase/multiphase_properties/particle_diameter") > 0285 have_fp_drag = have_option("/multiphase_interaction/fluid_particle_drag")
286286
287 ! Get the pressure p^{n}, and get the assembly options for the divergence and CMC matrices287 ! Get the pressure p^{n}, and get the assembly options for the divergence and CMC matrices
288 ! find the first non-aliased pressure288 ! find the first non-aliased pressure
@@ -388,7 +388,7 @@
388 ! get the CV tested pressure gradient matrix (i.e. the divergence matrix)388 ! get the CV tested pressure gradient matrix (i.e. the divergence matrix)
389 ! if required with a different unique name. Note there is no need389 ! if required with a different unique name. Note there is no need
390 ! to again decide reassemble_ct_m as ctp_m for this case is assembled when ct_m is.390 ! to again decide reassemble_ct_m as ctp_m for this case is assembled when ct_m is.
391 if ((.not. use_compressible_projection) .and. cg_pressure_cv_test_continuity) then391 if ((.not. compressible_eos) .and. cg_pressure_cv_test_continuity) then
392 ctp_m(istate)%ptr => get_velocity_divergence_matrix(state(istate), ct_m_name = "CVTestedVelocityDivergenceMatrix")392 ctp_m(istate)%ptr => get_velocity_divergence_matrix(state(istate), ct_m_name = "CVTestedVelocityDivergenceMatrix")
393 end if393 end if
394394
@@ -467,17 +467,16 @@
467 end select467 end select
468 end if468 end if
469469
470 if (has_boundary_condition(u, "free_surface") .or. use_compressible_projection) then470 if (has_boundary_condition(u, "free_surface") .or. compressible_eos) then
471 ! this needs fixing for multiphase theta_pg could in principle be chosen471 ! This needs fixing for multiphase. theta_pg could in principle be chosen
472 ! per phase but then we need an array and we'd have to include theta_pg472 ! per phase but then we need an array and we'd have to include theta_pg
473 ! in cmc_m, i.e. solve for theta_div*dt*dp instead of theta_div*theta_pg*dt*dp473 ! in cmc_m, i.e. solve for theta_div*dt*dp instead of theta_div*theta_pg*dt*dp
474 ! theta_div can only be set once, but where and what is the default?474 ! theta_div can only be set once, but where and what is the default?
475 if (multiphase) then475 if (has_boundary_condition(u, "free_surface") .and. multiphase) then
476 FLExit("Multiphase does not work with a free surface or compressible flow.")476 FLExit("Multiphase does not work with a free surface.")
477 end if477 end if
478478
479479 ! With free surface or compressible-projection, pressures are at integer
480 ! With free surface or compressible-projection pressures are at integer
481 ! time levels and we apply a theta-weighting to the pressure gradient term480 ! time levels and we apply a theta-weighting to the pressure gradient term
482 ! Also, obtain theta-weighting to be used in divergence term481 ! Also, obtain theta-weighting to be used in divergence term
483 call get_option( trim(u%option_path)//'/prognostic/temporal_discretisation/theta', &482 call get_option( trim(u%option_path)//'/prognostic/temporal_discretisation/theta', &
@@ -491,6 +490,15 @@
491 ewrite(2,*) "theta_pg: ", theta_pg490 ewrite(2,*) "theta_pg: ", theta_pg
492 ewrite(2,*) "Velocity divergence is evaluated at n+theta_divergence"491 ewrite(2,*) "Velocity divergence is evaluated at n+theta_divergence"
493 ewrite(2,*) "theta_divergence: ", theta_divergence492 ewrite(2,*) "theta_divergence: ", theta_divergence
493
494 ! Note: Compressible multiphase simulations work, but only when use_theta_pg and use_theta_divergence
495 ! are false. This needs improving - see comment above.
496 if(compressible_eos .and. multiphase .and. (use_theta_pg .or. use_theta_divergence)) then
497 ewrite(-1,*) "Currently, for compressible multiphase flow simulations, the"
498 ewrite(-1,*) "temporal_discretisation/theta and temporal_discretisation/theta_divergence values"
499 ewrite(-1,*) "for each Velocity field must be set to 1.0."
500 FLExit("Multiphase does not work when use_theta_pg or use_theta_divergence are true.")
501 end if
494 else502 else
495 ! Pressures are, as usual, staggered in time with the velocities503 ! Pressures are, as usual, staggered in time with the velocities
496 use_theta_pg=.false.504 use_theta_pg=.false.
@@ -514,6 +522,7 @@
514 ! Allocation of big_m522 ! Allocation of big_m
515 if(dg(istate)) then523 if(dg(istate)) then
516 call allocate_big_m_dg(state(istate), big_m(istate), u)524 call allocate_big_m_dg(state(istate), big_m(istate), u)
525
517 if(subcycle(istate)) then526 if(subcycle(istate)) then
518 u_sparsity => get_csr_sparsity_firstorder(state, u%mesh, u%mesh)527 u_sparsity => get_csr_sparsity_firstorder(state, u%mesh, u%mesh)
519 ! subcycle_m currently only contains advection, so diagonal=.true.528 ! subcycle_m currently only contains advection, so diagonal=.true.
@@ -531,8 +540,8 @@
531 ! Initialise the big_m, ct_m and ctp_m matrices540 ! Initialise the big_m, ct_m and ctp_m matrices
532 call zero(big_m(istate))541 call zero(big_m(istate))
533 if(reassemble_ct_m) then542 if(reassemble_ct_m) then
534 call zero(ct_m(istate)%ptr) 543 call zero(ct_m(istate)%ptr)
535 if ((.not. use_compressible_projection) .and. cg_pressure_cv_test_continuity) then544 if ((.not. compressible_eos) .and. cg_pressure_cv_test_continuity) then
536 call zero(ctp_m(istate)%ptr)545 call zero(ctp_m(istate)%ptr)
537 end if546 end if
538 end if547 end if
@@ -580,7 +589,7 @@
580 call subtract_geostrophic_pressure_gradient(mom_rhs(istate), state(istate))589 call subtract_geostrophic_pressure_gradient(mom_rhs(istate), state(istate))
581 end if590 end if
582 else591 else
583 ! This call will form the ct_rhs, which for use_compressible_projection592 ! This call will form the ct_rhs, which for compressible_eos
584 ! or cg_pressure_cv_test_continuity is formed for a second time later below.593 ! or cg_pressure_cv_test_continuity is formed for a second time later below.
585 call construct_momentum_cg(u, p, density, x, &594 call construct_momentum_cg(u, p, density, x, &
586 big_m(istate), mom_rhs(istate), ct_m(istate)%ptr, &595 big_m(istate), mom_rhs(istate), ct_m(istate)%ptr, &
@@ -635,7 +644,7 @@
635644
636 call profiler_tic(p, "assembly")645 call profiler_tic(p, "assembly")
637 if(cv_pressure) then646 if(cv_pressure) then
638 ! This call will form the ct_rhs, which for use_compressible_projection647 ! This call will form the ct_rhs, which for compressible_eos
639 ! is formed for a second time later below.648 ! is formed for a second time later below.
640 call assemble_divergence_matrix_cv(ct_m(istate)%ptr, state(istate), ct_rhs=ct_rhs(istate), &649 call assemble_divergence_matrix_cv(ct_m(istate)%ptr, state(istate), ct_rhs=ct_rhs(istate), &
641 test_mesh=p%mesh, field=u, get_ct=reassemble_ct_m)650 test_mesh=p%mesh, field=u, get_ct=reassemble_ct_m)
@@ -643,7 +652,7 @@
643652
644 ! Assemble divergence matrix C^T.653 ! Assemble divergence matrix C^T.
645 ! At the moment cg does its own ct assembly. We might change this in the future.654 ! At the moment cg does its own ct assembly. We might change this in the future.
646 ! This call will form the ct_rhs, which for use_compressible_projection655 ! This call will form the ct_rhs, which for compressible_eos
647 ! or cg_pressure_cv_test_continuity is formed for a second time later below.656 ! or cg_pressure_cv_test_continuity is formed for a second time later below.
648 if(dg(istate) .and. .not. cv_pressure) then657 if(dg(istate) .and. .not. cv_pressure) then
649 call assemble_divergence_matrix_cg(ct_m(istate)%ptr, state(istate), ct_rhs=ct_rhs(istate), &658 call assemble_divergence_matrix_cg(ct_m(istate)%ptr, state(istate), ct_rhs=ct_rhs(istate), &
@@ -683,7 +692,11 @@
683 692
684 ! Set up the left C matrix in CMC693 ! Set up the left C matrix in CMC
685 694
686 if(use_compressible_projection) then695 if(compressible_eos) then
696 ! Note: If we are running a compressible multiphase simulation then the C^T matrix for each phase becomes:
697 ! rho*div(vfrac*u) for each incompressible phase
698 ! rho*div(vfrac*u) + vfrac*u*grad(rho) for the single compressible phase.
699
687 allocate(ctp_m(istate)%ptr)700 allocate(ctp_m(istate)%ptr)
688 call allocate(ctp_m(istate)%ptr, ct_m(istate)%ptr%sparsity, (/1, u%dim/), name="CTP_m")701 call allocate(ctp_m(istate)%ptr, ct_m(istate)%ptr%sparsity, (/1, u%dim/), name="CTP_m")
689 ! NOTE that this is not optimal in that the ct_rhs702 ! NOTE that this is not optimal in that the ct_rhs
@@ -691,7 +704,7 @@
691 if(cv_pressure) then704 if(cv_pressure) then
692 call assemble_compressible_divergence_matrix_cv(ctp_m(istate)%ptr, state, ct_rhs(istate))705 call assemble_compressible_divergence_matrix_cv(ctp_m(istate)%ptr, state, ct_rhs(istate))
693 else706 else
694 call assemble_compressible_divergence_matrix_cg(ctp_m(istate)%ptr, state, ct_rhs(istate))707 call assemble_compressible_divergence_matrix_cg(ctp_m(istate)%ptr, state, istate, ct_rhs(istate))
695 end if 708 end if
696 else 709 else
697 ! Incompressible scenario710 ! Incompressible scenario
@@ -708,7 +721,7 @@
708 end if721 end if
709 end if722 end if
710 723
711 if (use_compressible_projection .or. cg_pressure_cv_test_continuity) then724 if (compressible_eos .or. cg_pressure_cv_test_continuity) then
712 if (have_rotated_bcs(u)) then725 if (have_rotated_bcs(u)) then
713 if (dg(istate)) then726 if (dg(istate)) then
714 call zero_non_owned(u)727 call zero_non_owned(u)
@@ -1041,7 +1054,7 @@
10411054
1042 call profiler_toc(u, "assembly")1055 call profiler_toc(u, "assembly")
10431056
1044 if(use_compressible_projection) then1057 if(compressible_eos) then
1045 call deallocate(ctp_m(istate)%ptr)1058 call deallocate(ctp_m(istate)%ptr)
1046 deallocate(ctp_m(istate)%ptr)1059 deallocate(ctp_m(istate)%ptr)
1047 end if1060 end if
@@ -1252,15 +1265,12 @@
12521265
1253 ewrite(1,*) 'Entering get_pressure_options'1266 ewrite(1,*) 'Entering get_pressure_options'
12541267
1255
1256 ! Are we using a compressible projection?1268 ! Are we using a compressible projection?
1257 use_compressible_projection = have_option(trim(p%option_path)//&1269 compressible_eos = option_count("/material_phase/equation_of_state/compressible") > 0
1258 "/prognostic/scheme&
1259 &/use_compressible_projection_method")
12601270
1261 reassemble_all_cmc_m = have_option(trim(p%option_path)//&1271 reassemble_all_cmc_m = have_option(trim(p%option_path)//&
1262 "/prognostic/scheme/update_discretised_equation") .or. &1272 "/prognostic/scheme/update_discretised_equation") .or. &
1263 use_compressible_projection1273 compressible_eos
12641274
1265 reassemble_all_ct_m = have_option(trim(p%option_path)//&1275 reassemble_all_ct_m = have_option(trim(p%option_path)//&
1266 "/prognostic/scheme/update_discretised_equation")1276 "/prognostic/scheme/update_discretised_equation")
@@ -1579,15 +1589,15 @@
1579 call deallocate(kmk_rhs)1589 call deallocate(kmk_rhs)
15801590
1581 cmc_m => extract_csr_matrix(state(istate), "PressurePoissonMatrix", stat)1591 cmc_m => extract_csr_matrix(state(istate), "PressurePoissonMatrix", stat)
15821592
1583 if(use_compressible_projection) then1593 if(compressible_eos .and. have_option(trim(state(istate)%option_path)//'/equation_of_state/compressible')) then
1584 call allocate(compress_projec_rhs, p%mesh, "CompressibleProjectionRHS")1594 call allocate(compress_projec_rhs, p%mesh, "CompressibleProjectionRHS")
15851595
1586 if(cv_pressure) then1596 if(cv_pressure) then
1587 call assemble_compressible_projection_cv(state, cmc_m, compress_projec_rhs, dt, &1597 call assemble_compressible_projection_cv(state, cmc_m, compress_projec_rhs, dt, &
1588 theta_pg, theta_divergence, reassemble_cmc_m)1598 theta_pg, theta_divergence, reassemble_cmc_m)
1589 else1599 else
1590 call assemble_compressible_projection_cg(state, cmc_m, compress_projec_rhs, dt, &1600 call assemble_compressible_projection_cg(state, istate, cmc_m, compress_projec_rhs, dt, &
1591 theta_pg, theta_divergence, reassemble_cmc_m)1601 theta_pg, theta_divergence, reassemble_cmc_m)
1592 end if1602 end if
15931603
@@ -1720,7 +1730,7 @@
1720 call addto(p, delta_p, scale=1.0/(theta_pg*dt))1730 call addto(p, delta_p, scale=1.0/(theta_pg*dt))
1721 ewrite_minmax(p)1731 ewrite_minmax(p)
17221732
1723 if(use_compressible_projection) then1733 if(compressible_eos) then
1724 call update_compressible_density(state)1734 call update_compressible_density(state)
1725 end if1735 end if
17261736
17271737
=== modified file 'assemble/Multiphase.F90'
--- assemble/Multiphase.F90 2011-09-03 00:57:43 +0000
+++ assemble/Multiphase.F90 2012-08-09 00:46:20 +0000
@@ -46,7 +46,7 @@
46 private46 private
47 public :: get_phase_submaterials, get_nonlinear_volume_fraction, &47 public :: get_phase_submaterials, get_nonlinear_volume_fraction, &
48 calculate_diagnostic_phase_volume_fraction, &48 calculate_diagnostic_phase_volume_fraction, &
49 add_fluid_particle_drag49 add_fluid_particle_drag, add_heat_transfer
5050
51 contains51 contains
5252
@@ -268,7 +268,7 @@
268 integer :: ele268 integer :: ele
269 type(element_type) :: test_function269 type(element_type) :: test_function
270 type(element_type), pointer :: u_shape270 type(element_type), pointer :: u_shape
271 integer, dimension(:), pointer :: u_ele271 integer, dimension(:), pointer :: u_nodes
272 logical :: dg272 logical :: dg
273 273
274 type(vector_field), pointer :: velocity_fluid274 type(vector_field), pointer :: velocity_fluid
@@ -281,14 +281,20 @@
281 integer :: i, dim281 integer :: i, dim
282 logical :: not_found ! Error flag. Have we found the fluid phase?282 logical :: not_found ! Error flag. Have we found the fluid phase?
283 integer :: istate_fluid, istate_particle283 integer :: istate_fluid, istate_particle
284 284
285 ! Types of drag correlation
286 integer, parameter :: DRAG_CORRELATION_TYPE_STOKES = 1, DRAG_CORRELATION_TYPE_WEN_YU = 2, DRAG_CORRELATION_TYPE_ERGUN = 3
285 287
286 ewrite(1, *) "Entering add_fluid_particle_drag"288 ewrite(1, *) "Entering add_fluid_particle_drag"
289
290 ! Let's check whether we actually have at least one particle phase.
291 if(option_count("/material_phase/multiphase_properties/particle_diameter") == 0) then
292 FLExit("Fluid-particle drag enabled but no particle_diameter has been specified for the particle phase(s).")
293 end if
287 294
288 ! Get the timestepping options295 ! Get the timestepping options
289 call get_option("/timestepping/timestep", dt)296 call get_option("/timestepping/timestep", dt)
290 call get_option(trim(u%option_path)//"/prognostic/temporal_discretisation/theta", &297 call get_option(trim(u%option_path)//"/prognostic/temporal_discretisation/theta", theta)
291 theta)
292 298
293 ! For the big_m matrix. Controls whether the off diagonal entries are used 299 ! For the big_m matrix. Controls whether the off diagonal entries are used
294 block_mask = .false.300 block_mask = .false.
@@ -300,15 +306,13 @@
300 dg = continuity(u) < 0306 dg = continuity(u) < 0
301307
302 ! Is this phase a particle phase?308 ! Is this phase a particle phase?
303 is_particle_phase = have_option("/material_phase["//int2str(istate-1)//&309 is_particle_phase = have_option(trim(state(istate)%option_path)//"/multiphase_properties/particle_diameter")
304 &"]/multiphase_properties/particle_diameter")
305 310
306 ! Retrieve the index of the fluid phase in the state array.311 ! Retrieve the index of the fluid phase in the state array.
307 not_found = .true.312 not_found = .true.
308 if(is_particle_phase) then 313 if(is_particle_phase) then
309 do i = 1, size(state)314 do i = 1, size(state)
310 if(.not.have_option("/material_phase["//int2str(i-1)//&315 if(.not.have_option(trim(state(i)%option_path)//"/multiphase_properties/particle_diameter")) then
311 &"]/multiphase_properties/particle_diameter")) then
312316
313 velocity_fluid => extract_vector_field(state(i), "Velocity")317 velocity_fluid => extract_vector_field(state(i), "Velocity")
314 ! Aliased material_phases will also not have a particle_diameter,318 ! Aliased material_phases will also not have a particle_diameter,
@@ -359,6 +363,8 @@
359 type(tensor_field), pointer :: viscosity_fluid363 type(tensor_field), pointer :: viscosity_fluid
360 type(scalar_field) :: nvfrac_fluid, nvfrac_particle364 type(scalar_field) :: nvfrac_fluid, nvfrac_particle
361 real :: d ! Particle diameter365 real :: d ! Particle diameter
366 character(len=OPTION_PATH_LEN) :: drag_correlation_name
367 integer :: drag_correlation
362368
363 ! Get the necessary fields to calculate the drag force369 ! Get the necessary fields to calculate the drag force
364 velocity_fluid => extract_vector_field(state(istate_fluid), "Velocity")370 velocity_fluid => extract_vector_field(state(istate_fluid), "Velocity")
@@ -371,8 +377,7 @@
371 density_particle => extract_scalar_field(state(istate_particle), "Density")377 density_particle => extract_scalar_field(state(istate_particle), "Density")
372 viscosity_fluid => extract_tensor_field(state(istate_fluid), "Viscosity")378 viscosity_fluid => extract_tensor_field(state(istate_fluid), "Viscosity")
373 379
374 call get_option("/material_phase["//int2str(istate_particle-1)//&380 call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter", d)
375 &"]/multiphase_properties/particle_diameter", d)
376381
377 ! Calculate the non-linear approximation to the PhaseVolumeFractions382 ! Calculate the non-linear approximation to the PhaseVolumeFractions
378 call allocate(nvfrac_fluid, vfrac_fluid%mesh, "NonlinearPhaseVolumeFraction")383 call allocate(nvfrac_fluid, vfrac_fluid%mesh, "NonlinearPhaseVolumeFraction")
@@ -387,13 +392,25 @@
387 nu_particle => extract_vector_field(state(istate_particle), "NonlinearVelocity")392 nu_particle => extract_vector_field(state(istate_particle), "NonlinearVelocity")
388 oldu_fluid => extract_vector_field(state(istate_fluid), "OldVelocity")393 oldu_fluid => extract_vector_field(state(istate_fluid), "OldVelocity")
389 oldu_particle => extract_vector_field(state(istate_particle), "OldVelocity")394 oldu_particle => extract_vector_field(state(istate_particle), "OldVelocity")
390 395
396 call get_option("/multiphase_interaction/fluid_particle_drag/drag_correlation/name", drag_correlation_name)
397 select case(trim(drag_correlation_name))
398 case("stokes")
399 drag_correlation = DRAG_CORRELATION_TYPE_STOKES
400 case("wen_yu")
401 drag_correlation = DRAG_CORRELATION_TYPE_WEN_YU
402 case("ergun")
403 drag_correlation = DRAG_CORRELATION_TYPE_ERGUN
404 case("default")
405 FLAbort("Unknown correlation for fluid-particle drag")
406 end select
407
391 ! ----- Volume integrals over elements ------------- 408 ! ----- Volume integrals over elements -------------
392 call profiler_tic(u, "element_loop")409 call profiler_tic(u, "element_loop")
393 element_loop: do ele = 1, element_count(u)410 element_loop: do ele = 1, element_count(u)
394411
395 if(.not.dg .or. (dg .and. element_owned(u,ele))) then412 if(.not.dg .or. (dg .and. element_owned(u,ele))) then
396 u_ele=>ele_nodes(u, ele)413 u_nodes => ele_nodes(u, ele)
397 u_shape => ele_shape(u, ele)414 u_shape => ele_shape(u, ele)
398 test_function = u_shape 415 test_function = u_shape
399416
@@ -403,7 +420,7 @@
403 density_fluid, density_particle, &420 density_fluid, density_particle, &
404 nu_fluid, nu_particle, &421 nu_fluid, nu_particle, &
405 oldu_fluid, oldu_particle, &422 oldu_fluid, oldu_particle, &
406 viscosity_fluid, d)423 viscosity_fluid, d, drag_correlation)
407 end if424 end if
408425
409 end do element_loop426 end do element_loop
@@ -421,7 +438,7 @@
421 density_fluid, density_particle, &438 density_fluid, density_particle, &
422 nu_fluid, nu_particle, &439 nu_fluid, nu_particle, &
423 oldu_fluid, oldu_particle, &440 oldu_fluid, oldu_particle, &
424 viscosity_fluid, d)441 viscosity_fluid, d, drag_correlation)
425 442
426 integer, intent(in) :: ele443 integer, intent(in) :: ele
427 type(element_type), intent(in) :: test_function444 type(element_type), intent(in) :: test_function
@@ -436,6 +453,7 @@
436 type(vector_field), intent(in) :: oldu_fluid, oldu_particle453 type(vector_field), intent(in) :: oldu_fluid, oldu_particle
437 type(tensor_field), intent(in) :: viscosity_fluid 454 type(tensor_field), intent(in) :: viscosity_fluid
438 real, intent(in) :: d ! Particle diameter 455 real, intent(in) :: d ! Particle diameter
456 integer, intent(in) :: drag_correlation
439 457
440 ! Local variables458 ! Local variables
441 real, dimension(ele_ngi(u,ele)) :: vfrac_fluid_gi, vfrac_particle_gi459 real, dimension(ele_ngi(u,ele)) :: vfrac_fluid_gi, vfrac_particle_gi
@@ -447,14 +465,14 @@
447 465
448 real, dimension(ele_loc(u, ele), ele_ngi(u, ele), x%dim) :: du_t466 real, dimension(ele_loc(u, ele), ele_ngi(u, ele), x%dim) :: du_t
449 real, dimension(ele_ngi(u, ele)) :: detwei467 real, dimension(ele_ngi(u, ele)) :: detwei
450 real, dimension(u%dim, ele_loc(u,ele)) :: interaction_rhs_mat468 real, dimension(u%dim, ele_loc(u,ele)) :: interaction_rhs
451 real, dimension(ele_loc(u, ele), ele_loc(u, ele)) :: interaction_big_m_mat469 real, dimension(ele_loc(u, ele), ele_loc(u, ele)) :: interaction_big_m_mat
452 real, dimension(u%dim, ele_loc(u,ele)) :: rhs_addto470 real, dimension(u%dim, ele_loc(u,ele)) :: rhs_addto
453 real, dimension(u%dim, u%dim, ele_loc(u,ele), ele_loc(u,ele)) :: big_m_tensor_addto471 real, dimension(u%dim, u%dim, ele_loc(u,ele), ele_loc(u,ele)) :: big_m_tensor_addto
454 472
455 real, dimension(ele_ngi(u,ele)) :: particle_re ! Particle Reynolds number473 real, dimension(ele_ngi(u,ele)) :: particle_re_gi ! Particle Reynolds number
456 real, dimension(ele_ngi(u,ele)) :: drag_coefficient474 real, dimension(ele_ngi(u,ele)) :: drag_coefficient_gi
457 real, dimension(ele_ngi(u,ele)) :: magnitude ! |v_f - v_p|475 real, dimension(ele_ngi(u,ele)) :: magnitude_gi ! |v_f - v_p|
458 476
459 real, dimension(ele_ngi(u,ele)) :: K477 real, dimension(ele_ngi(u,ele)) :: K
460 real, dimension(ele_ngi(u,ele)) :: drag_force_big_m478 real, dimension(ele_ngi(u,ele)) :: drag_force_big_m
@@ -476,34 +494,55 @@
476 494
477 ! Compute the magnitude of the relative velocity495 ! Compute the magnitude of the relative velocity
478 do gi = 1, ele_ngi(u,ele)496 do gi = 1, ele_ngi(u,ele)
479 magnitude(gi) = norm2(nu_fluid_gi(:,gi) - nu_particle_gi(:,gi))497 magnitude_gi(gi) = norm2(nu_fluid_gi(:,gi) - nu_particle_gi(:,gi))
480 end do498 end do
481499
482 ! Compute the particle Reynolds number500 ! Compute the particle Reynolds number
483 ! (Assumes isotropic viscosity for now)501 ! (Assumes isotropic viscosity for now)
484 particle_re = (vfrac_fluid_gi*density_fluid_gi*magnitude*d) / viscosity_fluid_gi(1,1,:)502 particle_re_gi = (vfrac_fluid_gi*density_fluid_gi*magnitude_gi*d) / viscosity_fluid_gi(1,1,:)
485 503
486 ! Compute the drag coefficient504 ! Compute the drag coefficient
487 do gi = 1, ele_ngi(u,ele)505 select case(drag_correlation)
488 if(particle_re(gi) < 1000) then506 case(DRAG_CORRELATION_TYPE_STOKES)
489 drag_coefficient(gi) = (24.0/particle_re(gi))507 ! Stokes drag correlation
490 ! For the Wen & Yu (1966) drag term, this should be:508 do gi = 1, ele_ngi(u,ele)
491 ! drag_coefficient(gi) = (24.0/particle_re(gi))*(1.0+0.15*particle_re(gi)**0.687)509 if(particle_re_gi(gi) < 1000) then
492 else510 drag_coefficient_gi(gi) = (24.0/particle_re_gi(gi))
493 drag_coefficient(gi) = 0.44511 else
494 end if512 drag_coefficient_gi(gi) = 0.44
495 end do513 end if
514 end do
515
516 case(DRAG_CORRELATION_TYPE_WEN_YU)
517 ! Wen & Yu (1966) drag correlation
518 do gi = 1, ele_ngi(u,ele)
519 if(particle_re_gi(gi) < 1000) then
520 drag_coefficient_gi(gi) = (24.0/particle_re_gi(gi))*(1.0+0.15*particle_re_gi(gi)**0.687)
521 else
522 drag_coefficient_gi(gi) = 0.44
523 end if
524 end do
525
526 case(DRAG_CORRELATION_TYPE_ERGUN)
527 ! No drag coefficient is needed here.
528 end select
496 529
497 ! Don't let the drag_coefficient be NaN530 ! Don't let the drag_coefficient_gi be NaN
498 do gi = 1, ele_ngi(u,ele)531 do gi = 1, ele_ngi(u,ele)
499 if(particle_re(gi) == 0) then532 if(particle_re_gi(gi) == 0) then
500 drag_coefficient(gi) = 1e16533 drag_coefficient_gi(gi) = 1e16
501 end if534 end if
502 end do535 end do
503 536
504 ! For the Wen & Yu (1966) drag term, this should be:537 select case(drag_correlation)
505 ! K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient*(vfrac_fluid_gi*density_fluid_gi*magnitude)/(d*vfrac_fluid_gi**2.7)538 case(DRAG_CORRELATION_TYPE_STOKES)
506 K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient*(vfrac_fluid_gi*density_fluid_gi*magnitude)/(d)539 K = vfrac_particle_gi*(3.0/4.0)*drag_coefficient_gi*(vfrac_fluid_gi*density_fluid_gi*magnitude_gi)/(d)
540 case(DRAG_CORRELATION_TYPE_WEN_YU)
541 ! Wen & Yu (1966) drag term
542 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)
543 case(DRAG_CORRELATION_TYPE_ERGUN)
544 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)
545 end select
507 546
508 if(is_particle_phase) then547 if(is_particle_phase) then
509 drag_force_big_m = -K548 drag_force_big_m = -K
@@ -519,7 +558,7 @@
519 558
520 ! Form the element interaction/drag matrix559 ! Form the element interaction/drag matrix
521 interaction_big_m_mat = shape_shape(test_function, u_shape, detwei*drag_force_big_m)560 interaction_big_m_mat = shape_shape(test_function, u_shape, detwei*drag_force_big_m)
522 interaction_rhs_mat = shape_vector_rhs(test_function, drag_force_rhs, detwei)561 interaction_rhs = shape_vector_rhs(test_function, drag_force_rhs, detwei)
523 562
524 ! Add contribution 563 ! Add contribution
525 big_m_tensor_addto = 0.0 564 big_m_tensor_addto = 0.0
@@ -531,16 +570,328 @@
531 end if570 end if
532 do dim = 1, u%dim571 do dim = 1, u%dim
533 big_m_tensor_addto(dim, dim, :, :) = big_m_tensor_addto(dim, dim, :, :) - dt*theta*interaction_big_m_mat572 big_m_tensor_addto(dim, dim, :, :) = big_m_tensor_addto(dim, dim, :, :) - dt*theta*interaction_big_m_mat
534 rhs_addto(dim,:) = rhs_addto(dim,:) + matmul(interaction_big_m_mat, oldu_val(dim,:)) + interaction_rhs_mat(dim,:)573 rhs_addto(dim,:) = rhs_addto(dim,:) + matmul(interaction_big_m_mat, oldu_val(dim,:)) + interaction_rhs(dim,:)
535 end do574 end do
536 575
537 ! Add the contribution to mom_rhs576 ! Add the contribution to mom_rhs
538 call addto(mom_rhs, u_ele, rhs_addto) 577 call addto(mom_rhs, u_nodes, rhs_addto)
539 ! Add to the big_m matrix578 ! Add to the big_m matrix
540 call addto(big_m, u_ele, u_ele, big_m_tensor_addto, block_mask=block_mask)579 call addto(big_m, u_nodes, u_nodes, big_m_tensor_addto, block_mask=block_mask)
541580
542 end subroutine add_fluid_particle_drag_element581 end subroutine add_fluid_particle_drag_element
543582
544 end subroutine add_fluid_particle_drag583 end subroutine add_fluid_particle_drag
545584
585
586 !! Multiphase energy interaction term Q_i
587 !! to be added to the RHS of the internal energy equation.
588 subroutine add_heat_transfer(state, istate, internal_energy, matrix, rhs)
589 !!< This computes the inter-phase heat transfer term.
590 !!< Only between fluid and particle phase pairs.
591 !!< Uses the empirical correlation by Gunn (1978).
592
593 type(state_type), dimension(:), intent(inout) :: state
594 integer, intent(in) :: istate
595 type(scalar_field), intent(in) :: internal_energy
596 type(csr_matrix), intent(inout) :: matrix
597 type(scalar_field), intent(inout) :: rhs
598
599 ! Local variables
600 integer :: ele
601 type(element_type) :: test_function
602 type(element_type), pointer :: internal_energy_shape
603 integer, dimension(:), pointer :: internal_energy_nodes
604 logical :: dg
605
606 type(vector_field), pointer :: x, velocity_fluid
607
608 real :: dt, theta
609
610 logical :: is_particle_phase
611 logical :: not_found ! Error flag. Have we found the fluid phase?
612 integer :: i, istate_fluid, istate_particle
613
614
615 ewrite(1, *) "Entering add_heat_transfer"
616
617 ! Get the timestepping options
618 call get_option("/timestepping/timestep", dt)
619 call get_option(trim(internal_energy%option_path)//"/prognostic/temporal_discretisation/theta", &
620 theta)
621
622 ! Get the coordinate field from state(istate)
623 x => extract_vector_field(state(istate), "Coordinate")
624 ewrite_minmax(x)
625 assert(x%dim == mesh_dim(internal_energy))
626 assert(ele_count(x) == ele_count(internal_energy))
627
628 ! Are we using a discontinuous Galerkin discretisation?
629 dg = continuity(internal_energy) < 0
630
631 ! Is this phase a particle phase?
632 is_particle_phase = have_option(trim(state(istate)%option_path)//"/multiphase_properties/particle_diameter")
633
634 ! Retrieve the index of the fluid phase in the state array.
635 not_found = .true.
636 if(is_particle_phase) then
637 do i = 1, size(state)
638 if(.not.have_option(trim(state(i)%option_path)//"/multiphase_properties/particle_diameter")) then
639
640 velocity_fluid => extract_vector_field(state(i), "Velocity")
641 ! Aliased material_phases will also not have a particle_diameter,
642 ! so here we make sure that we don't count these as the fluid phase
643 if(.not.aliased(velocity_fluid)) then
644 istate_fluid = i
645 if(.not.not_found) then
646 FLExit("Heat transfer term does not currently support more than one fluid phase.")
647 end if
648 not_found = .false.
649 end if
650
651 end if
652 end do
653 else
654 istate_fluid = istate
655 not_found = .false.
656 end if
657
658 if(not_found) then
659 FLExit("No fluid phase found for the heat transfer term.")
660 end if
661
662 ! If we have a fluid-particle pair, then assemble the heat transfer term
663 if(is_particle_phase) then
664 call assemble_heat_transfer(istate_fluid, istate)
665 else
666 state_loop: do i = 1, size(state)
667 if(i /= istate_fluid) then
668 call assemble_heat_transfer(istate_fluid, i)
669 end if
670 end do state_loop
671 end if
672
673 ewrite(1, *) "Exiting add_heat_transfer"
674
675 contains
676
677 subroutine assemble_heat_transfer(istate_fluid, istate_particle)
678
679 integer, intent(in) :: istate_fluid, istate_particle
680
681 type(scalar_field), pointer :: vfrac_fluid, vfrac_particle
682 type(scalar_field), pointer :: density_fluid, density_particle
683 type(vector_field), pointer :: velocity_fluid, velocity_particle
684 type(scalar_field), pointer :: internal_energy_fluid, internal_energy_particle
685 type(scalar_field), pointer :: old_internal_energy_fluid, old_internal_energy_particle
686 type(vector_field), pointer :: nu_fluid, nu_particle ! Non-linear approximation to the Velocities
687 type(tensor_field), pointer :: viscosity_fluid
688 type(scalar_field) :: nvfrac_fluid, nvfrac_particle
689 real :: d ! Particle diameter
690 real :: k ! Effective gas conductivity
691 real :: C_fluid, C_particle ! Specific heat of the fluid and particle phases at constant volume
692 real :: gamma ! Ratio of specific heats for compressible phase
693 integer :: kstat, cstat_fluid, cstat_particle, gstat
694
695 ! Get the necessary fields to calculate the heat transfer term
696 velocity_fluid => extract_vector_field(state(istate_fluid), "Velocity")
697 velocity_particle => extract_vector_field(state(istate_particle), "Velocity")
698 if(.not.aliased(velocity_particle)) then ! Don't count the aliased material_phases
699
700 vfrac_fluid => extract_scalar_field(state(istate_fluid), "PhaseVolumeFraction")
701 vfrac_particle => extract_scalar_field(state(istate_particle), "PhaseVolumeFraction")
702 density_fluid => extract_scalar_field(state(istate_fluid), "Density")
703 density_particle => extract_scalar_field(state(istate_particle), "Density")
704 viscosity_fluid => extract_tensor_field(state(istate_fluid), "Viscosity")
705
706 call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/particle_diameter", d)
707
708 call get_option(trim(state(istate_fluid)%option_path)//"/multiphase_properties/effective_conductivity", k, kstat)
709
710 call get_option(trim(state(istate_fluid)%option_path)//"/multiphase_properties/specific_heat", C_fluid, cstat_fluid)
711
712 call get_option(trim(state(istate_particle)%option_path)//"/multiphase_properties/specific_heat", C_particle, cstat_particle)
713
714 call get_option(trim(state(istate_fluid)%option_path)//"/equation_of_state/compressible/stiffened_gas/ratio_specific_heats", gamma, gstat)
715
716 if(kstat /= 0) then
717 FLExit("For inter-phase heat transfer, an effective_conductivity needs to be specified for the fluid phase.")
718 end if
719 if(cstat_fluid /= 0 .or. cstat_particle /= 0) then
720 FLExit("For inter-phase heat transfer, a specific_heat needs to be specified for each phase.")
721 end if
722 if(gstat /= 0) then
723 FLExit("For inter-phase heat transfer, ratio_specific_heats needs to be specified for the compressible phase.")
724 end if
725
726 ! Calculate the non-linear approximation to the PhaseVolumeFractions
727 call allocate(nvfrac_fluid, vfrac_fluid%mesh, "NonlinearPhaseVolumeFraction")
728 call allocate(nvfrac_particle, vfrac_particle%mesh, "NonlinearPhaseVolumeFraction")
729 call zero(nvfrac_fluid)
730 call zero(nvfrac_particle)
731 call get_nonlinear_volume_fraction(state(istate_fluid), nvfrac_fluid)
732 call get_nonlinear_volume_fraction(state(istate_particle), nvfrac_particle)
733
734 ! Get the non-linear approximation to the Velocities
735 nu_fluid => extract_vector_field(state(istate_fluid), "NonlinearVelocity")
736 nu_particle => extract_vector_field(state(istate_particle), "NonlinearVelocity")
737
738 ! Get the current and old internal energy fields
739 internal_energy_fluid => extract_scalar_field(state(istate_fluid), "InternalEnergy")
740 internal_energy_particle => extract_scalar_field(state(istate_particle), "InternalEnergy")
741 old_internal_energy_fluid => extract_scalar_field(state(istate_fluid), "OldInternalEnergy")
742 old_internal_energy_particle => extract_scalar_field(state(istate_particle), "OldInternalEnergy")
743
744 ! ----- Volume integrals over elements -------------
745 call profiler_tic(internal_energy, "element_loop")
746 element_loop: do ele = 1, element_count(internal_energy)
747
748 if(.not.dg .or. (dg .and. element_owned(internal_energy,ele))) then
749 internal_energy_nodes => ele_nodes(internal_energy, ele)
750 internal_energy_shape => ele_shape(internal_energy, ele)
751 test_function = internal_energy_shape
752
753 call add_heat_transfer_element(ele, test_function, internal_energy_shape, &
754 x, internal_energy, matrix, rhs, &
755 nvfrac_fluid, nvfrac_particle, &
756 density_fluid, density_particle, &
757 nu_fluid, nu_particle, &
758 internal_energy_fluid, &
759 internal_energy_particle, &
760 old_internal_energy_fluid, &
761 old_internal_energy_particle, &
762 viscosity_fluid, d, k, C_fluid, &
763 C_particle, gamma)
764 end if
765
766 end do element_loop
767 call profiler_toc(internal_energy, "element_loop")
768
769 call deallocate(nvfrac_fluid)
770 call deallocate(nvfrac_particle)
771 end if
772
773 end subroutine assemble_heat_transfer
774
775 subroutine add_heat_transfer_element(ele, test_function, internal_energy_shape, &
776 x, internal_energy, matrix, rhs, &
777 vfrac_fluid, vfrac_particle, &
778 density_fluid, density_particle, &
779 nu_fluid, nu_particle, &
780 internal_energy_fluid, &
781 internal_energy_particle, &
782 old_internal_energy_fluid, &
783 old_internal_energy_particle, &
784 viscosity_fluid, d, k, C_fluid, &
785 C_particle, gamma)
786
787 integer, intent(in) :: ele
788 type(element_type), intent(in) :: test_function
789 type(element_type), intent(in) :: internal_energy_shape
790 type(vector_field), intent(in) :: x
791 type(scalar_field), intent(in) :: internal_energy
792 type(csr_matrix), intent(inout) :: matrix
793 type(scalar_field), intent(inout) :: rhs
794
795 type(scalar_field), intent(in) :: vfrac_fluid, vfrac_particle
796 type(scalar_field), intent(in) :: density_fluid, density_particle
797 type(vector_field), intent(in) :: nu_fluid, nu_particle
798 type(scalar_field), intent(in) :: internal_energy_fluid, internal_energy_particle
799 type(scalar_field), intent(in) :: old_internal_energy_fluid, old_internal_energy_particle
800 type(tensor_field), intent(in) :: viscosity_fluid
801 real, intent(in) :: d, k, C_fluid, C_particle, gamma
802
803 ! Local variables
804 real, dimension(ele_ngi(x,ele)) :: internal_energy_fluid_gi, internal_energy_particle_gi
805 real, dimension(ele_ngi(x,ele)) :: vfrac_fluid_gi, vfrac_particle_gi
806 real, dimension(ele_ngi(x,ele)) :: density_fluid_gi, density_particle_gi
807 real, dimension(x%dim, ele_ngi(x,ele)) :: nu_fluid_gi, nu_particle_gi
808 real, dimension(x%dim, x%dim, ele_ngi(x,ele)) :: viscosity_fluid_gi
809
810 real, dimension(ele_loc(internal_energy,ele)) :: old_internal_energy_val
811
812 real, dimension(ele_ngi(x,ele)) :: detwei
813 real, dimension(ele_ngi(x,ele)) :: coefficient_for_matrix, coefficient_for_rhs
814 real, dimension(ele_loc(internal_energy,ele)) :: rhs_addto
815 real, dimension(ele_loc(internal_energy,ele), ele_loc(internal_energy,ele)) :: matrix_addto
816
817 real, dimension(ele_ngi(x,ele)) :: particle_Re ! Particle Reynolds number
818 real, dimension(ele_ngi(x,ele)) :: Pr ! Prandtl number
819 real, dimension(ele_ngi(x,ele)) :: particle_Nu ! Particle Nusselt number
820 real, dimension(ele_ngi(x,ele)) :: velocity_magnitude ! |v_f - v_p|
821
822 real, dimension(ele_ngi(x,ele)) :: Q ! heat transfer term = Q*(T_p - T_f)
823 real, dimension(ele_loc(internal_energy,ele), ele_loc(internal_energy,ele)) :: heat_transfer_matrix
824 real, dimension(ele_loc(internal_energy,ele)) :: heat_transfer_rhs
825
826 integer :: gi
827
828 ! Compute detwei
829 call transform_to_physical(x, ele, detwei)
830
831 ! Get the values of the necessary fields at the Gauss points
832 vfrac_fluid_gi = ele_val_at_quad(vfrac_fluid, ele)
833 vfrac_particle_gi = ele_val_at_quad(vfrac_particle, ele)
834 density_fluid_gi = ele_val_at_quad(density_fluid, ele)
835 density_particle_gi = ele_val_at_quad(density_particle, ele)
836 nu_fluid_gi = ele_val_at_quad(nu_fluid, ele)
837 nu_particle_gi = ele_val_at_quad(nu_particle, ele)
838 viscosity_fluid_gi = ele_val_at_quad(viscosity_fluid, ele)
839 internal_energy_fluid_gi = ele_val_at_quad(internal_energy_fluid, ele)
840 internal_energy_particle_gi = ele_val_at_quad(internal_energy_particle, ele)
841
842 ! Compute the magnitude of the relative velocity
843 do gi = 1, ele_ngi(x,ele)
844 velocity_magnitude(gi) = norm2(nu_fluid_gi(:,gi) - nu_particle_gi(:,gi))
845 end do
846
847 ! Compute the particle Reynolds number
848 ! (Assumes isotropic viscosity for now)
849 particle_Re = (density_fluid_gi*velocity_magnitude*d) / viscosity_fluid_gi(1,1,:)
850
851 ! Compute the Prandtl number
852 ! (Assumes isotropic viscosity for now)
853 ! Note: C_fluid (at constant volume) multiplied by gamma = C_fluid at constant pressure
854 Pr = C_fluid*gamma*viscosity_fluid_gi(1,1,:)/k
855
856 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))) + &
857 (1.33 - 2.4*vfrac_fluid_gi + 1.2*vfrac_fluid_gi**2)*(particle_Re**0.7)*(Pr**(1.0/3.0))
858
859 Q = (6.0*k*vfrac_particle_gi*particle_Nu)/(d**2)
860
861 ! Note that the transfer term is defined in terms of temperatures (T_fluid and T_particle)
862 ! Let's convert the temperatures to internal energy (E) using E_i = C_i*T_i,
863 ! where C is the specific heat of phase i at constant volume.
864 if(is_particle_phase) then
865 coefficient_for_matrix = -Q/C_particle
866 coefficient_for_rhs = -Q*(-internal_energy_fluid_gi/C_fluid)
867 else
868 coefficient_for_matrix = -Q/C_fluid
869 coefficient_for_rhs = Q*(internal_energy_particle_gi/C_particle)
870 end if
871
872 ! Form the element heat transfer matrix and RHS
873 heat_transfer_matrix = shape_shape(test_function, internal_energy_shape, detwei*coefficient_for_matrix)
874 heat_transfer_rhs = shape_rhs(test_function, coefficient_for_rhs*detwei)
875
876 ! Add contribution
877 matrix_addto = 0.0
878 rhs_addto = 0.0
879 if(is_particle_phase) then
880 old_internal_energy_val = ele_val(old_internal_energy_particle, ele)
881 else
882 old_internal_energy_val = ele_val(old_internal_energy_fluid, ele)
883 end if
884
885 matrix_addto = matrix_addto - dt*theta*heat_transfer_matrix
886 rhs_addto = rhs_addto + matmul(heat_transfer_matrix, old_internal_energy_val) + heat_transfer_rhs
887
888 ! Add to the internal energy equation's RHS
889 call addto(rhs, internal_energy_nodes, rhs_addto)
890 ! Add to the matrix
891 call addto(matrix, internal_energy_nodes, internal_energy_nodes, matrix_addto)
892
893 end subroutine add_heat_transfer_element
894
895 end subroutine add_heat_transfer
896
546 end module multiphase_module897 end module multiphase_module
547898
=== modified file 'main/Fluids.F90'
--- main/Fluids.F90 2012-05-29 13:43:29 +0000
+++ main/Fluids.F90 2012-08-09 00:46:20 +0000
@@ -699,7 +699,7 @@
699 else if(have_option(trim(field_optionpath_list(it)) // &699 else if(have_option(trim(field_optionpath_list(it)) // &
700 & "/prognostic/spatial_discretisation/continuous_galerkin")) then700 & "/prognostic/spatial_discretisation/continuous_galerkin")) then
701701
702 call solve_field_equation_cg(field_name_list(it), state(field_state_list(it)), dt)702 call solve_field_equation_cg(field_name_list(it), state, field_state_list(it), dt)
703 else703 else
704704
705 ewrite(2, *) "Not solving scalar field " // trim(field_name_list(it)) // " in state " // trim(state(field_state_list(it))%name) //" in an advdif-like subroutine."705 ewrite(2, *) "Not solving scalar field " // trim(field_name_list(it)) // " in state " // trim(state(field_state_list(it))%name) //" in an advdif-like subroutine."
706706
=== modified file 'main/Shallow_Water.F90'
--- main/Shallow_Water.F90 2011-07-22 12:39:08 +0000
+++ main/Shallow_Water.F90 2012-08-09 00:46:20 +0000
@@ -241,7 +241,7 @@
241 call project_cartesian_to_local(state(1), v_field)241 call project_cartesian_to_local(state(1), v_field)
242 end if 242 end if
243243
244 call execute_timestep(state(1), dt)244 call execute_timestep(state, 1, dt)
245245
246 call set_prescribed_field_values(state, exclude_interpolated=.true., &246 call set_prescribed_field_values(state, exclude_interpolated=.true., &
247 exclude_nonreprescribed=.true., time=current_time + dt)247 exclude_nonreprescribed=.true., time=current_time + dt)
@@ -528,9 +528,10 @@
528528
529 end subroutine insert_time_in_state529 end subroutine insert_time_in_state
530530
531 subroutine execute_timestep(state, dt)531 subroutine execute_timestep(state, istate, dt)
532 implicit none532 implicit none
533 type(state_type), intent(inout) :: state533 type(state_type), dimension(:), intent(inout) :: state
534 integer, intent(in) :: istate
534 real, intent(in) :: dt535 real, intent(in) :: dt
535536
536 !! Layer thickness537 !! Layer thickness
@@ -548,20 +549,20 @@
548 real :: energy549 real :: energy
549 logical :: have_source550 logical :: have_source
550551
551 !Pull the fields out of state552 !Pull the fields out of state(istate)
552 D=>extract_scalar_field(state, "LayerThickness")553 D=>extract_scalar_field(state(istate), "LayerThickness")
553 U=>extract_vector_field(state, "LocalVelocity")554 U=>extract_vector_field(state(istate), "LocalVelocity")
554 have_source = .false.555 have_source = .false.
555 if (has_vector_field(state, "LocalVelocitySource")) then556 if (has_vector_field(state(istate), "LocalVelocitySource")) then
556 have_source = .true.557 have_source = .true.
557 source => extract_vector_field(state, "LocalVelocitySource")558 source => extract_vector_field(state(istate), "LocalVelocitySource")
558 end if559 end if
559 dim = U%dim560 dim = U%dim
560561
561 call execute_timestep_setup(D,U,d_rhs,u_rhs,advecting_u, &562 call execute_timestep_setup(D,U,d_rhs,u_rhs,advecting_u, &
562 old_u,old_d,delta_d,delta_u)563 old_u,old_d,delta_d,delta_u)
563564
564 call insert(state,advecting_u,"NonlinearVelocity")565 call insert(state(istate),advecting_u,"NonlinearVelocity")
565566
566 call set(advecting_u,u)567 call set(advecting_u,u)
567 call set(old_u,u)568 call set(old_u,u)
@@ -577,20 +578,20 @@
577 do d1 = 1, dim578 do d1 = 1, dim
578 velocity_cpt = extract_scalar_field(u,d1)579 velocity_cpt = extract_scalar_field(u,d1)
579 old_velocity_cpt = extract_scalar_field(old_u,d1)580 old_velocity_cpt = extract_scalar_field(old_u,d1)
580 call insert(state,velocity_cpt,"VelocityComponent")581 call insert(state(istate),velocity_cpt,"VelocityComponent")
581 call insert(state,old_velocity_cpt,"VelocityComponentOld")582 call insert(state(istate),old_velocity_cpt,"VelocityComponentOld")
582 call solve_advection_diffusion_dg("VelocityComponent", state)583 call solve_advection_diffusion_dg("VelocityComponent", state(istate))
583 end do584 end do
584 end if585 end if
585 !pressure advection586 !pressure advection
586 if(.not.exclude_pressure_advection) then587 if(.not.exclude_pressure_advection) then
587 call solve_field_equation_cg("LayerThickness", state, dt, &588 call solve_field_equation_cg("LayerThickness", state, 1, dt, &
588 "NonlinearVelocity")589 "NonlinearVelocity")
589 end if590 end if
590591
591 if(hybridized) then592 if(hybridized) then
592 call solve_hybridized_helmholtz(&593 call solve_hybridized_helmholtz(&
593 &state,&594 &state(istate),&
594 &U_out=U_rhs,D_out=D_rhs,&595 &U_out=U_rhs,D_out=D_rhs,&
595 &compute_cartesian=.true.,&596 &compute_cartesian=.true.,&
596 &check_continuity=.true.,output_dense=.false.)597 &check_continuity=.true.,output_dense=.false.)
@@ -623,8 +624,8 @@
623 !Construct explicit parts of h rhs in wave equation624 !Construct explicit parts of h rhs in wave equation
624 call get_d_rhs(d_rhs,u_rhs,D,U,div_mat,big_mat,D0,dt,theta)625 call get_d_rhs(d_rhs,u_rhs,D,U,div_mat,big_mat,D0,dt,theta)
625626
626 if (has_scalar_field(state, "LayerThicknessSource")) then627 if (has_scalar_field(state(istate), "LayerThicknessSource")) then
627 d_src => extract_scalar_field(state, "LayerThicknessSource")628 d_src => extract_scalar_field(state(istate), "LayerThicknessSource")
628 call allocate(md_src, d_src%mesh, "MassMatrixTimesLayerThicknessSource")629 call allocate(md_src, d_src%mesh, "MassMatrixTimesLayerThicknessSource")
629 call zero(md_src)630 call zero(md_src)
630 call mult(md_src, h_mass_mat, d_src)631 call mult(md_src, h_mass_mat, d_src)
631632
=== modified file 'manual/bibliography.bib'
--- manual/bibliography.bib 2011-11-25 12:32:35 +0000
+++ manual/bibliography.bib 2012-08-09 00:46:20 +0000
@@ -912,6 +912,16 @@
912 year = {2005}912 year = {2005}
913}913}
914914
915@Article{ ergun1952,
916 author = {Ergun, S.},
917 journal = {Chemical Engineering Progress},
918 number = {2},
919 pages = {89-94},
920 title = {Fluid flow through packed columns},
921 volume = {48},
922 year = {1952}
923}
924
915@Article{ erturk2005,925@Article{ erturk2005,
916 author = {E. Erturk and T. C. Corke and C. Gokcol},926 author = {E. Erturk and T. C. Corke and C. Gokcol},
917 journal = {International Journal for Numerical Methods in Fluids},927 journal = {International Journal for Numerical Methods in Fluids},
@@ -1298,6 +1308,16 @@
1298 year = {1994}1308 year = {1994}
1299}1309}
13001310
1311@Article{ gunn1978,
1312 author = {Gunn, D. J.},
1313 journal = {International Journal of Heat and Mass Transfer},
1314 number = {4},
1315 pages = {467-476},
1316 title = {Transfer of heat or mass to particles in fixed and fluidised beds},
1317 volume = {21},
1318 year = {1978}
1319}
1320
1301@Book{ haidvogelbook,1321@Book{ haidvogelbook,
1302 author = {D. B. Haidvogel and A. Beckmann},1322 author = {D. B. Haidvogel and A. Beckmann},
1303 publisher = {Imperial {C}ollege {P}ress},1323 publisher = {Imperial {C}ollege {P}ress},
@@ -2877,6 +2897,15 @@
2877 year = 20082897 year = 2008
2878}2898}
28792899
2900@Article{ wen_yu_1966,
2901 title = {Mechanics of Fluidization},
2902 author = {C.~Y. Wen and Y.~H. Yu},
2903 journal = {Chem. Eng. Prog. Symp. Ser.},
2904 volume = 62,
2905 number = 100,
2906 year = 1966
2907}
2908
2880@Book{ wilcox1998turbulence,2909@Book{ wilcox1998turbulence,
2881 author = {Wilcox, D.C.},2910 author = {Wilcox, D.C.},
2882 publisher = {DCW industries La Canada, CA},2911 publisher = {DCW industries La Canada, CA},
28832912
=== modified file 'manual/configuring_fluidity.tex'
--- manual/configuring_fluidity.tex 2012-07-26 15:38:42 +0000
+++ manual/configuring_fluidity.tex 2012-08-09 00:46:20 +0000
@@ -719,7 +719,7 @@
719719
720When configuring ocean problems (or single material/single phase fluids720When configuring ocean problems (or single material/single phase fluids
721problems), only one \option{/material\_phase} is required. Multi-material721problems), only one \option{/material\_phase} is required. Multi-material
722and multi-phase problems will require one \option{/material\_phase} for each722and multiphase problems will require one \option{/material\_phase} for each
723phase or material in the problem.723phase or material in the problem.
724724
725Note that you must give each of your material phases a name.725Note that you must give each of your material phases a name.
@@ -1184,7 +1184,8 @@
1184\index{conjugate gradient}1184\index{conjugate gradient}
1185\index{multigrid}1185\index{multigrid}
1186\index{PETSc}1186\index{PETSc}
1187As described in Section \ref{ND_Linear_solvers}, for the solution of large sparse linear systems, the so called iterative methods are usually employed. These methods avoid having to explicitly construct the inverse of the matrix, which is generally dense and therefore costly to compute (both in memory and computer time). FLUIDITY is linked to PETSc: a suite of data structures and routines for the scalable (parallel) solution of scientific applications modelled by partial differential equations. It employs the MPI standard for parallelism. FLUIDITY therefore supports any iterative method provided by the PETSc library (http://www-unix.mcs.anl.gov/petsc/petsc-2/snapshots/petsc-dev/docs/manualpages/KSP/KSPType.html --- available methods may depend on the PETSc library installed on your system). Examples include Conjugate Gradient (CG), GMRES and FGMRES (Flexible GMRES). Some options are explicitly listed under \option{solver/iterative\_method}, for example CG: \option{solver/iterative\_method::cg}, whereas others can be selected entering the name of the chosen scheme in \option{solver/iterative\_method}.1187As described in Section \ref{ND_Linear_solvers}, for the solution of large sparse linear systems, the so called iterative methods are usually employed. These methods avoid having to explicitly construct the inverse of the matrix, which is generally dense and therefore costly to compute (both in memory and computer time). FLUIDITY is linked to PETSc: a suite of data structures and routines for the scalable (parallel) solution of scientific applications modelled by partial differential equations. It employs the MPI standard for parallelism. FLUIDITY therefore supports any iterative method provided by the PETSc library (http://www-unix.mcs.anl.gov/petsc/petsc-2/snapshots/petsc-dev/docs/manualpages/KSP/KSPType.html --- available methods may depend on the PETSc library installed on your system). Examples include Conjugate Gradient (CG), GMRES and FGMRES (Flexible GMRES). Some options are explicitly listed under \option{solver/iterative\_method}, for example CG: \option{solver/iterative\_method::cg}, whereas
1188others can be selected entering the name of the chosen scheme in \option{solver/iterative\_method}.
11881189
1189\subsection{Preconditioner}1190\subsection{Preconditioner}
1190\index{linear solvers!preconditioners}1191\index{linear solvers!preconditioners}
@@ -2313,7 +2314,7 @@
2313Models with one prognostic velocity field per \option{material\_phase} are referred to as multiple phase models. The use of these multiple velocity fields permits the inter-penetration and interaction between different phases.2314Models with one prognostic velocity field per \option{material\_phase} are referred to as multiple phase models. The use of these multiple velocity fields permits the inter-penetration and interaction between different phases.
23142315
2315\subsubsection{Simulation requirements}2316\subsubsection{Simulation requirements}
2316In a multi-phase simulation, each \option{material\_phase} requires:2317In a multiphase simulation, each \option{material\_phase} requires:
2317\begin{itemize}2318\begin{itemize}
2318 \item an equation of state, and2319 \item an equation of state, and
2319 \item a PhaseVolumeFraction scalar field.2320 \item a PhaseVolumeFraction scalar field.
@@ -2328,13 +2329,15 @@
2328\alpha_N = 1 - \sum_{i=1}^{N-1}\alpha_i\textrm{.}2329\alpha_N = 1 - \sum_{i=1}^{N-1}\alpha_i\textrm{.}
2329\end{equation}2330\end{equation}
23302331
2331\subsubsection{Inter-phase interactions}2332\subsubsection{Inter-phase momentum interaction}
2332Inter-phase interactions can be included under \option{../multiphase\_properties} in Diamond. Currently, \fluidity\ only supports fluid-particle drag between the continuous phase and dispersed phase(s), given by:2333Currently, \fluidity\ only supports fluid-particle drag between the continuous phase and dispersed phase(s). This can be enabled by switching on the \option{/multiphase\_interaction/fluid\_particle\_drag} option in Diamond and specifying the drag correlation: Stokes, \cite{wen_yu_1966} or \cite{ergun1952}.
2333\begin{equation}\label{eq:multiphase_drag_term}2334
2335The drag force using the Stokes drag correlation is given by:
2336\begin{equation}\label{eq:stokes_drag_force}
2334\mathbf{F}_D = \frac{3\ \alpha_p\ C_D\ \alpha_f\ \rho_f\ |\mathbf{u}_f-\mathbf{u}_p|\ (\mathbf{u}_f-\mathbf{u}_p)}{4\ d},2337\mathbf{F}_D = \frac{3\ \alpha_p\ C_D\ \alpha_f\ \rho_f\ |\mathbf{u}_f-\mathbf{u}_p|\ (\mathbf{u}_f-\mathbf{u}_p)}{4\ d},
2335\end{equation}2338\end{equation}
2336where $f$ and $p$ denote the fluid (i.e. continuous) and particle (i.e. dispersed) phases respectively, and $d$ is the diameter of a single particle in the dispersed phase. The drag coefficient $C_D$ is defined as:2339where $f$ and $p$ denote the fluid (i.e. continuous) and particle (i.e. dispersed) phases respectively, and $d$ is the diameter of a single particle in the dispersed phase. The drag coefficient $C_D$ is defined as:
2337\begin{equation}\label{eq:drag_coefficient}2340\begin{equation}\label{eq:stokes_drag_coefficient}
2338C_D = \frac{24}{\mathrm{Re}},2341C_D = \frac{24}{\mathrm{Re}},
2339\end{equation}2342\end{equation}
2340with2343with
@@ -2343,17 +2346,52 @@
2343\end{equation}2346\end{equation}
2344Note that $\mu_f$ denotes the isotropic viscosity of the fluid (i.e. continuous) phase.2347Note that $\mu_f$ denotes the isotropic viscosity of the fluid (i.e. continuous) phase.
23452348
2346Within a dispersed phase, entering a value for $d$ in the \option{../multiphase\_properties/particle\_diameter} option enables fluid-particle interaction between itself and the continuous phase.2349With the drag correlation by \cite{wen_yu_1966}, $\mathbf{F}_D$ and $C_D$ become:
2350\begin{equation}\label{eq:wen_yu_drag_force}
2351\mathbf{F}_D = \frac{3\ \alpha_p\ C_D\ \alpha_f\ \rho_f\ |\mathbf{u}_f-\mathbf{u}_p|\ (\mathbf{u}_f-\mathbf{u}_p)}{4\ d\alpha_f^{2.7}},
2352\end{equation}
2353\begin{equation}\label{eq:wen_yu_drag_coefficient}
2354C_D = \frac{24}{\mathrm{Re}}\left(1.0 + 0.15\mathrm{Re}^{0.687}\right).
2355\end{equation}
2356In contrast to the Stokes drag correlation, the \cite{wen_yu_1966} drag correlation is more suitable for larger particle Reynolds number flows.
2357
2358For dense multiphase flows with $\alpha_p > 0.2$, the drag correlation by \cite{ergun1952} is often the most appropriate:
2359\begin{equation}\label{eq:ergun_drag_force}
2360\mathbf{F}_D = \left(150\frac{\alpha_p^2\mu_f}{\alpha_f d_p^2} + 1.75\frac{\alpha_p\rho_f|\mathbf{u}_f-\mathbf{u}_p|}{d_p}\right)\left(\mathbf{u}_f-\mathbf{u}_p\right).
2361\end{equation}
2362
2363Note that within each dispersed phase, a value for $d$ must be specified in \option{../multiphase\_properties/particle\_diameter} regardless of which drag correlation is used.
2364
2365\subsubsection{Inter-phase energy interaction}
2366This subsection considers compressible multiphase flow simulations where each phase has its own InternalEnergy field. Users can choose to include the inter-phase heat transfer term by \cite{gunn1978}, denoted $Q$ in Section \ref{sec:multiphase_equations}, on the RHS of each internal energy equation:
2367
2368\begin{equation}\label{eq:gunn_heat_transfer_term}
2369Q = \frac{6 k \alpha_p \mathrm{Nu}_p}{d_p^2}\left(\frac{e_f}{C_f} - \frac{e_p}{C_p}\right),
2370\end{equation}
2371where
2372\begin{equation}
2373\mathrm{Nu}_p = \left(7 - 10\alpha_f + 5\alpha_f^2\right)\left(1 + 0.7\mathrm{Re}_p^{0.2}\mathrm{Pr}^{\frac{1}{3}}\right) + \left(1.33 - 2.4\alpha_f + 1.2\alpha_f^2\right)\mathrm{Re}_p^{0.7}\mathrm{Pr}^{\frac{1}{3}},
2374\end{equation}
2375\begin{equation}
2376 \mathrm{Pr} = \frac{C_f \gamma \mu_f}{k},
2377\end{equation}
2378and
2379\begin{equation}
2380 \mathrm{Re} = \frac{\rho_f d_p |\mathbf{u}_f-\mathbf{u}_p|}{\mu_f},
2381\end{equation}
2382are the Nusselt, Prandtl and Reynolds number respectively. $C_i$ denotes the specific heat of phase i at constant volume, and $k$ denotes the effective conductivity of the fluid phase; these must be specified in \option{../multiphase\_properties/effective\_conductivity} and \option{../multiphase\_properties/specific\_heat}. Note that we have written the above in terms of internal energy (rather than temperature) by dividing $e_i$ by the specific heat at constant volume.
2383
2384To include this term, switch on the \option{/multiphase\_interaction/heat\_transfer} option in Diamond.
23472385
2348\subsubsection{Current limitations}2386\subsubsection{Current limitations}
2349\begin{itemize}2387\begin{itemize}
2350 \item Boussinesq and fully compressible multi-phase simulations are not yet supported.2388 \item Boussinesq multiphase simulations are not yet supported.
2351 \item The momentum equation for each \option{material\_phase} can only be discretised in non-conservative form.2389 \item The momentum equation for each \option{material\_phase} can only be discretised in non-conservative form.
2352 \item The stress term must be in tensor form, and only works with an isotropic viscosity.2390 \item The stress term must be in tensor form, and only works with an isotropic viscosity.
2353 \item \option{bassi\_rebay} and \option{compact\_discontinuous\_galerkin} are currently the only DG viscosity schemes available for multi-phase flow simulations.2391 \item \option{bassi\_rebay} and \option{compact\_discontinuous\_galerkin} are currently the only DG viscosity schemes available for multiphase flow simulations.
2354 \item Discontinuous \option{PhaseVolumeFraction} fields are not yet supported.2392 \item Discontinuous \option{PhaseVolumeFraction} fields are not yet supported.
2355 \item The Pressure field only supports \option{continuous\_galerkin} and \option{control\_volume} discretisations.2393 \item For compressible multiphase flow simulations, the Pressure field only supports a \option{continuous\_galerkin} discretisation.
2356 \item Prescribed velocity fields cannot yet be used in multi-phase simulations.2394 \item Prescribed velocity fields cannot yet be used in multiphase simulations.
2357 \item Fluid-particle drag can currently only support one continuous (i.e. fluid) phase.2395 \item Fluid-particle drag can currently only support one continuous (i.e. fluid) phase.
2358\end{itemize}2396\end{itemize}
23592397
@@ -2396,7 +2434,8 @@
23962434
2397This section describes how to configure \fluidity to simulate single phase incompressible Darcy flow.2435This section describes how to configure \fluidity to simulate single phase incompressible Darcy flow.
23982436
2399First, the \option{Porosity} and \option{Permeability} fields found under the option element \option{/porous\_media} require configuring. Both fields can be either \option{prescribed} or \option{diagnostic}. The \option{Permeability} field can be either a \option{scalar\_field} or a \option{vector\_field}. The \option{Porosity} field will only be used in the transport of scalar fields and the metric tensor. The \option{Permeability} field will only be used in forming the absorption coefficient in the Darcy velocity equation. The use of these two fields should be considered when selecting their associated mesh. If \option{Porosity} is to be included in the transport of scalar fields (and the metric tensor) that are discretised using control volumes, due to the way this method is coded, the mesh associated with the \option{Porosity} must be either element wise (meaning discontinuous order zero) or the same order as field to be transported. It is therefore recommended that the \option{Porosity} field always be associated with a mesh that is discontinuous order zero. It is recommended that the \option{Permeability} field also be associated with a mesh that is discontinuous order zero, due to the recommended Darcy velocity - pressure element pair (being p0p1cv or p0p1 with the continuity tested with the p1 control volume dual space)2437First, the \option{Porosity} and \option{Permeability} fields found under the option element \option{/porous\_media} require configuring. Both fields can be either \option{prescribed} or \option{diagnostic}. The \option{Permeability} field can be either a \option{scalar\_field} or a \option{vector\_field}. The \option{Porosity} field will only be used in the transport of scalar fields and the metric tensor. The \option{Permeability} field will only be used in forming the absorption coefficient in the Darcy velocity equation. The use of these two fields should be considered when selecting their associated mesh. If \option{Porosity} is to be included in the transport of scalar fields (and the metric tensor) that are discretised using control volumes, due to the way this method is coded, the mesh associated with the \option{Porosity} must be either element wise (meaning discontinuous order zero) or the same order as field to be transported. It is therefore recommended that the \option{Porosity} field always be
2438associated with a mesh that is discontinuous order zero. It is recommended that the \option{Permeability} field also be associated with a mesh that is discontinuous order zero, due to the recommended Darcy velocity - pressure element pair (being p0p1cv or p0p1 with the continuity tested with the p1 control volume dual space)
24002439
2401Second, the prognostic \option{Velocity} vector field of the (only) phase is now taken to be the Darcy velocity \ref{sec:porous_media_darcy_flow_equations}. There is no option to select Darcy flow but this can be achieved via a careful selection of the \option{Velocity} field options tree given by:2440Second, the prognostic \option{Velocity} vector field of the (only) phase is now taken to be the Darcy velocity \ref{sec:porous_media_darcy_flow_equations}. There is no option to select Darcy flow but this can be achieved via a careful selection of the \option{Velocity} field options tree given by:
2402\begin{itemize}2441\begin{itemize}
24032442
=== modified file 'manual/model_equations.tex'
--- manual/model_equations.tex 2012-07-26 15:38:42 +0000
+++ manual/model_equations.tex 2012-08-09 00:46:20 +0000
@@ -727,7 +727,7 @@
727727
728\subsection{Multi-material simulations}728\subsection{Multi-material simulations}
729\index{multi-material flow}729\index{multi-material flow}
730The ability to differentiate between regions with distinct material properties is of fundamental importance in the modelling of many physical systems. Two different approaches exist for achieving this: the multi-material approach and the multi-phase approach. The multi-material approach is implemented within \fluidity, and the multi-phase approach (discussed in the next subsection) is currently under development.730The ability to differentiate between regions with distinct material properties is of fundamental importance in the modelling of many physical systems. Two different approaches exist for achieving this: the multi-material approach and the multiphase approach. The multi-material approach is implemented within \fluidity, and the multiphase approach (discussed in the next subsection) is currently under development.
731In situations where the model can resolve physical mixing of immiscible materials, or where there is no mixing, only one velocity field (and hence one momentum equation) is required to describe the flow of all materials. The \emph{multi-material} approach, considers all materials to be immiscible materials separated by a sharp interface.731In situations where the model can resolve physical mixing of immiscible materials, or where there is no mixing, only one velocity field (and hence one momentum equation) is required to describe the flow of all materials. The \emph{multi-material} approach, considers all materials to be immiscible materials separated by a sharp interface.
732732
733In a multi-material approach, the various forms of the conservation equations can be solved for multiple material flows if the point-wise mass density $\rho$ in the equations is defined as the bulk density at each point. If the flow comprises $n$ materials and the volume fraction of the $i^{th}$ material is denoted $\phi_i$ then the bulk density is given by:733In a multi-material approach, the various forms of the conservation equations can be solved for multiple material flows if the point-wise mass density $\rho$ in the equations is defined as the bulk density at each point. If the flow comprises $n$ materials and the volume fraction of the $i^{th}$ material is denoted $\phi_i$ then the bulk density is given by:
@@ -749,14 +749,17 @@
749\end{equation}749\end{equation}
750where the volume fraction field at time zero must be specified.750where the volume fraction field at time zero must be specified.
751751
752\subsection{Multi-phase simulations}752\subsection{Multiphase simulations}
753\label{sec:multiphase_equations}753\label{sec:multiphase_equations}
754\index{multi-phase flow}754\index{multiphase flow}
755Multi-phase flows are defined by \cite{prosperettiEtAl2007} to be flows in which two or more phases of matter (solid, liquid, gas, etc) are simultaneously present and are allowed to inter-penetrate. Simple examples include the flow of a fizzy drink which is composed of a liquid and a finite number of gas bubbles, the transportation of solid sediment particles in a river, and the flow of blood cells around the human body.755Multiphase flows are defined by \cite{prosperettiEtAl2007} to be flows in which two or more phases of matter (solid, liquid, gas, etc) are simultaneously present and are allowed to inter-penetrate. Simple examples include the flow of a fizzy drink which is composed of a liquid and a finite number of gas bubbles, the transportation of solid sediment particles in a river, and the flow of blood cells around the human body.
756756
757Further to the above definition, each phase is classed as either \textit{continuous} or \textit{dispersed}, where a continuous phase is a connected liquid or gas substance in which dispersed phases (comprising a finite number of solid particles, liquid droplets and/or gas bubbles) may be immersed \citep{croweEtAl1998}.757Further to the above definition, each phase is classed as either \textit{continuous} or \textit{dispersed}, where a continuous phase is a connected liquid or gas substance in which dispersed phases (comprising a finite number of solid particles, liquid droplets and/or gas bubbles) may be immersed \citep{croweEtAl1998}.
758758
759To enable the mixing and inter-penetration of phases, a separate velocity field (and hence a separate momentum equation) is assigned to each one and solved for. Extra terms are then included to account for inter-phase interactions. Furthermore, the model currently assumes no mass transfer between phases, incompressible flow, and a common pressure field $p$ so that only one continuity equation is used. Thus, the continuity equation and momentum equation for phase $i$ (based on the derivation in \cite{ishii1975}, written in non-conservative form) are:759To enable the mixing and inter-penetration of phases, a separate velocity field (and hence a separate momentum equation) is assigned to each one and solved for. Extra terms are then included to account for inter-phase interactions. Furthermore, the model currently assumes no mass transfer between phases, incompressible flow, and a common pressure field $p$ so that only one continuity equation is used. The form of the governing equations depends on whether we are dealing with incompressible or compressible flow.
760
761\subsubsection{Incompressible flow}
762For an incompressible multiphase flow, the continuity equation and momentum equation for phase $i$ (based on the derivation in \cite{ishii1975}, written in non-conservative form) are:
760\begin{equation}763\begin{equation}
761\sum_{i=1}^N\nabla\cdot\left(\alpha_i\mathbf{u}_i\right) = 0,764\sum_{i=1}^N\nabla\cdot\left(\alpha_i\mathbf{u}_i\right) = 0,
762\end{equation}765\end{equation}
@@ -769,6 +772,19 @@
769\end{equation}772\end{equation}
770where $\mathbf{u}_i$, $\rho_i$, $\mu_i$ and $\alpha_i$ are the velocity, density, isotropic viscosity and volume fraction of phase $i$ respectively, and $\mathbf{F}_i$ represents the forces imposed on phase $i$ by the other $N-1$ phases. Details of momentum transfer terms are given in Chapter \ref{chap:configuration}.773where $\mathbf{u}_i$, $\rho_i$, $\mu_i$ and $\alpha_i$ are the velocity, density, isotropic viscosity and volume fraction of phase $i$ respectively, and $\mathbf{F}_i$ represents the forces imposed on phase $i$ by the other $N-1$ phases. Details of momentum transfer terms are given in Chapter \ref{chap:configuration}.
771774
775\subsubsection{Compressible flow}
776Fluidity currently only supports the case where the continuous phase is compressible. All other phases (the dispersed phases) are incompressible. The momentum equation is the same as the one given above, but the continuity equation becomes:
777\begin{equation}
778\alpha_1\frac{\partial\rho_1}{\partial t} + \nabla\cdot\left(\alpha_1\rho_1\mathbf{u}_1\right) + \rho_1\left(\sum_{i=2}^N\nabla\cdot\left(\alpha_i\mathbf{u}_i\right)\right) = 0,
779\end{equation}
780where the compressible phase has an index of $i=1$ here.
781
782An internal energy equation may also need to be solved depending on the equation of state used for the compressible phase. This is given by:
783\begin{equation}
784\alpha_i\rho_i\frac{\partial e_i}{\partial t} + \alpha_i\rho_i\mathbf{u}_i\cdot\nabla e_i = -p\nabla\cdot\left(\alpha_i\mathbf{u}_i\right) + Q_i
785\end{equation}
786where $e_i$ is the internal energy and $Q_i$ is an inter-phase energy transfer term described in Chapter \ref{chap:configuration}.
787
772\subsection{Porous Media Darcy Flow}788\subsection{Porous Media Darcy Flow}
773\label{sec:porous_media_darcy_flow_equations}789\label{sec:porous_media_darcy_flow_equations}
774\index{porous media darcy flow}790\index{porous media darcy flow}
775791
=== modified file 'manual/visualisation_and_diagnostics.tex'
--- manual/visualisation_and_diagnostics.tex 2012-03-06 10:47:48 +0000
+++ manual/visualisation_and_diagnostics.tex 2012-08-09 00:46:20 +0000
@@ -66,6 +66,7 @@
66Limitations: Requires the diagnostic \option{scalar\_field::IsopycnalCoordinate} and (therefore) is not parallelised.66Limitations: Requires the diagnostic \option{scalar\_field::IsopycnalCoordinate} and (therefore) is not parallelised.
67\item[BulkMaterialPressure:]Calculates the bulk material pressure based on the MaterialDensity and MaterialVolumeFraction (and MaterialInternalEnergy if appropriate) for the equation of state of all materials.67\item[BulkMaterialPressure:]Calculates the bulk material pressure based on the MaterialDensity and MaterialVolumeFraction (and MaterialInternalEnergy if appropriate) for the equation of state of all materials.
68\item[CFLNumber:]CFLNumber as defined on the co-ordinate mesh. It is calculated as $\triangle t \vec{u} \mat{J}^{-1}$ where $\triangle t$ is the timestep, $\vec{u}$ the velocity and $\mat{J}$ the Jacobian. 68\item[CFLNumber:]CFLNumber as defined on the co-ordinate mesh. It is calculated as $\triangle t \vec{u} \mat{J}^{-1}$ where $\triangle t$ is the timestep, $\vec{u}$ the velocity and $\mat{J}$ the Jacobian.
69\item[CompressibleContinuity:]Computes the residual of the compressible multiphase continuity equation. Used only in compressible multiphase flow simulations.
69\item[ControlVolumeCFLNumber:]CFL Number as defined on a control volume mesh. It is calculated as $\triangle t \frac{1}{V} \int _{cv_{face}} \vec{u}$ where $\triangle t$ is the timestep and $\vec{u}$ the velocity. The integral is taken over the faces of the control volume and $V$ is the volume of the control volume.70\item[ControlVolumeCFLNumber:]CFL Number as defined on a control volume mesh. It is calculated as $\triangle t \frac{1}{V} \int _{cv_{face}} \vec{u}$ where $\triangle t$ is the timestep and $\vec{u}$ the velocity. The integral is taken over the faces of the control volume and $V$ is the volume of the control volume.
70\item[ControlVolumeDivergence:]Divergence of the velocity field where the divergence operator is defined using the control volume $\mathrm{C}^\mathrm{T}$ matrix. This assumes that the test space is discontinuous control volumes.71\item[ControlVolumeDivergence:]Divergence of the velocity field where the divergence operator is defined using the control volume $\mathrm{C}^\mathrm{T}$ matrix. This assumes that the test space is discontinuous control volumes.
71\item[CVMaterialDensityCFLNumber:]Courant Number as defined on a control volume mesh and incorporating the MaterialDensity. Requires a MaterialDensity field!72\item[CVMaterialDensityCFLNumber:]Courant Number as defined on a control volume mesh and incorporating the MaterialDensity. Requires a MaterialDensity field!
7273
=== modified file 'schemas/fluidity_options.rnc'
--- schemas/fluidity_options.rnc 2012-06-27 14:47:10 +0000
+++ schemas/fluidity_options.rnc 2012-08-09 00:46:20 +0000
@@ -15,6 +15,7 @@
15include "embedded_models.rnc"15include "embedded_models.rnc"
16include "flredecomp.rnc"16include "flredecomp.rnc"
17include "porous_media.rnc"17include "porous_media.rnc"
18include "multiphase_interaction.rnc"
18include "equation_of_state.rnc"19include "equation_of_state.rnc"
1920
20start =21start =
@@ -1387,6 +1388,17 @@
1387 comment,1388 comment,
1388 element particle_diameter { 1389 element particle_diameter {
1389 real 1390 real
1391 }?,
1392 ## If this is the fluid phase,
1393 ## the effective conductivity is required
1394 ## for the inter-phase heat transfer term.
1395 element effective_conductivity {
1396 real
1397 }?,
1398 ## The specific heat (at constant volume) is required
1399 ## for the inter-phase heat transfer term.
1400 element specific_heat {
1401 real
1390 }?1402 }?
1391 }?,1403 }?,
1392 sediment?1404 sediment?
@@ -1570,7 +1582,8 @@
1570 reduced_model?,1582 reduced_model?,
1571 porous_media_model?,1583 porous_media_model?,
1572 embedded_models?,1584 embedded_models?,
1573 flredecomp?1585 flredecomp?,
1586 multiphase_interaction?
1574 }1587 }
1575 ) 1588 )
15761589
@@ -4681,7 +4694,27 @@
4681 }4694 }
4682 }4695 }
4683 )4696 )
4684 } 4697 }|
4698
4699 ## CompressibleContinuityResidual
4700 ##
4701 ## Computes the residual of the continuity equation used in compressible multiphase flow simulations
4702 ## i.e. vfrac_c*d(rho_c)/dt + div(rho_c*vfrac_c*u_c) + \sum_i{ rho_c*div(vfrac_i*u_i) }
4703 ## where _c and _i denote the compressible and incompressible phases respectively.
4704 element scalar_field {
4705 attribute rank { "0" },
4706 attribute name { "CompressibleContinuityResidual" },
4707 (
4708 element diagnostic {
4709 velocity_mesh_choice,
4710 internal_algorithm,
4711 diagnostic_scalar_field_no_adapt,
4712 element solver {
4713 linear_solver_options_sym
4714 }
4715 }
4716 )
4717 }
46854718
4686# Insert new diagnostic scalar fields here using the template:4719# Insert new diagnostic scalar fields here using the template:
4687# element scalar_field {4720# element scalar_field {
46884721
=== modified file 'schemas/fluidity_options.rng'
--- schemas/fluidity_options.rng 2012-08-02 13:03:52 +0000
+++ schemas/fluidity_options.rng 2012-08-09 00:46:20 +0000
@@ -16,6 +16,7 @@
16 <include href="embedded_models.rng"/>16 <include href="embedded_models.rng"/>
17 <include href="flredecomp.rng"/>17 <include href="flredecomp.rng"/>
18 <include href="porous_media.rng"/>18 <include href="porous_media.rng"/>
19 <include href="multiphase_interaction.rng"/>
19 <include href="equation_of_state.rng"/>20 <include href="equation_of_state.rng"/>
20 <start>21 <start>
21 <element name="fluidity_options">22 <element name="fluidity_options">
@@ -1852,6 +1853,21 @@
1852 <ref name="real"/>1853 <ref name="real"/>
1853 </element>1854 </element>
1854 </optional>1855 </optional>
1856 <optional>
1857 <element name="effective_conductivity">
1858 <a:documentation>If this is the fluid phase,
1859the effective conductivity is required
1860for the inter-phase heat transfer term.</a:documentation>
1861 <ref name="real"/>
1862 </element>
1863 </optional>
1864 <optional>
1865 <element name="specific_heat">
1866 <a:documentation>The specific heat (at constant volume) is required
1867for the inter-phase heat transfer term.</a:documentation>
1868 <ref name="real"/>
1869 </element>
1870 </optional>
1855 </element>1871 </element>
1856 </optional>1872 </optional>
1857 <optional>1873 <optional>
@@ -2185,6 +2201,9 @@
2185 <optional>2201 <optional>
2186 <ref name="flredecomp"/>2202 <ref name="flredecomp"/>
2187 </optional>2203 </optional>
2204 <optional>
2205 <ref name="multiphase_interaction"/>
2206 </optional>
2188 </element>2207 </element>
2189 </start>2208 </start>
2190 <define name="sediment">2209 <define name="sediment">
@@ -5935,6 +5954,27 @@
5935 </element>5954 </element>
5936 </element>5955 </element>
5937 </element>5956 </element>
5957 <element name="scalar_field">
5958 <a:documentation>CompressibleContinuityResidual
5959
5960Computes the residual of the continuity equation used in compressible multiphase flow simulations
5961i.e. vfrac_c*d(rho_c)/dt + div(rho_c*vfrac_c*u_c) + \sum_i{ rho_c*div(vfrac_i*u_i) }
5962where _c and _i denote the compressible and incompressible phases respectively.</a:documentation>
5963 <attribute name="rank">
5964 <value>0</value>
5965 </attribute>
5966 <attribute name="name">
5967 <value>CompressibleContinuityResidual</value>
5968 </attribute>
5969 <element name="diagnostic">
5970 <ref name="velocity_mesh_choice"/>
5971 <ref name="internal_algorithm"/>
5972 <ref name="diagnostic_scalar_field_no_adapt"/>
5973 <element name="solver">
5974 <ref name="linear_solver_options_sym"/>
5975 </element>
5976 </element>
5977 </element>
5938 </choice>5978 </choice>
5939 <!--5979 <!--
5940 Insert new diagnostic scalar fields here using the template:5980 Insert new diagnostic scalar fields here using the template:
59415981
=== added file 'schemas/multiphase_interaction.rnc'
--- schemas/multiphase_interaction.rnc 1970-01-01 00:00:00 +0000
+++ schemas/multiphase_interaction.rnc 2012-08-09 00:46:20 +0000
@@ -0,0 +1,58 @@
1# Phase interaction options for Fluidity's multiphase flow model.
2
3multiphase_interaction =
4 (
5 ## Phase interaction options for Fluidity's multiphase flow model.
6 element multiphase_interaction {
7 comment,
8 fluid_particle_drag?,
9 heat_transfer?
10 }
11 )
12
13fluid_particle_drag =
14 (
15 ## Fluid-particle drag term.
16 element fluid_particle_drag {
17 drag_correlation
18 }
19 )
20
21drag_correlation =
22 (
23 ## Stokes drag correlation: 24/Re_p
24 ## where Re_p is the particle Reynolds number.
25 element drag_correlation {
26 attribute name { "stokes" },
27 comment
28 }|
29 ## Fluid-particle drag term by Wen & Yu (1966).
30 element drag_correlation {
31 attribute name { "wen_yu" },
32 comment
33 }|
34 ## Fluid-particle drag term by Ergun (1952).
35 element drag_correlation {
36 attribute name { "ergun" },
37 comment
38 }
39 )
40
41heat_transfer =
42 (
43 ## Heat transfer term for the
44 ## multiphase internal energy equation.
45 ## Note: Only for fluid-particle phase pairs.
46 element heat_transfer {
47 heat_transfer_coefficient
48 }
49 )
50
51heat_transfer_coefficient =
52 (
53 ## Heat transfer coefficient by Gunn (1978).
54 element heat_transfer_coefficient {
55 attribute name { "gunn" },
56 comment
57 }
58 )
0\ No newline at end of file59\ No newline at end of file
160
=== added file 'schemas/multiphase_interaction.rng'
--- schemas/multiphase_interaction.rng 1970-01-01 00:00:00 +0000
+++ schemas/multiphase_interaction.rng 2012-08-09 00:46:20 +0000
@@ -0,0 +1,65 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0">
3 <!-- Phase interaction options for Fluidity's multiphase flow model. -->
4 <define name="multiphase_interaction">
5 <element name="multiphase_interaction">
6 <a:documentation>Phase interaction options for Fluidity's multiphase flow model.</a:documentation>
7 <ref name="comment"/>
8 <optional>
9 <ref name="fluid_particle_drag"/>
10 </optional>
11 <optional>
12 <ref name="heat_transfer"/>
13 </optional>
14 </element>
15 </define>
16 <define name="fluid_particle_drag">
17 <element name="fluid_particle_drag">
18 <a:documentation>Fluid-particle drag term.</a:documentation>
19 <ref name="drag_correlation"/>
20 </element>
21 </define>
22 <define name="drag_correlation">
23 <choice>
24 <element name="drag_correlation">
25 <a:documentation>Stokes drag correlation: 24/Re_p
26where Re_p is the particle Reynolds number.</a:documentation>
27 <attribute name="name">
28 <value>stokes</value>
29 </attribute>
30 <ref name="comment"/>
31 </element>
32 <element name="drag_correlation">
33 <a:documentation>Fluid-particle drag term by Wen &amp; Yu (1966).</a:documentation>
34 <attribute name="name">
35 <value>wen_yu</value>
36 </attribute>
37 <ref name="comment"/>
38 </element>
39 <element name="drag_correlation">
40 <a:documentation>Fluid-particle drag term by Ergun (1952).</a:documentation>
41 <attribute name="name">
42 <value>ergun</value>
43 </attribute>
44 <ref name="comment"/>
45 </element>
46 </choice>
47 </define>
48 <define name="heat_transfer">
49 <element name="heat_transfer">
50 <a:documentation>Heat transfer term for the
51multiphase internal energy equation.
52Note: Only for fluid-particle phase pairs.</a:documentation>
53 <ref name="heat_transfer_coefficient"/>
54 </element>
55 </define>
56 <define name="heat_transfer_coefficient">
57 <element name="heat_transfer_coefficient">
58 <a:documentation>Heat transfer coefficient by Gunn (1978).</a:documentation>
59 <attribute name="name">
60 <value>gunn</value>
61 </attribute>
62 <ref name="comment"/>
63 </element>
64 </define>
65</grammar>
066
=== added directory 'tests/flux_bc'
=== added file 'tests/flux_bc/Makefile'
--- tests/flux_bc/Makefile 1970-01-01 00:00:00 +0000
+++ tests/flux_bc/Makefile 2012-08-09 00:46:20 +0000
@@ -0,0 +1,22 @@
1preprocess:
2 @echo **********Creating meshes
3 gmsh -2 -o flux_bc_2d.msh src/flux_bc_2d.geo
4 gmsh -3 -o flux_bc_3d.msh src/flux_bc_3d.geo
5 ../../bin/gmsh2triangle --2d flux_bc_2d.msh
6 ../../bin/gmsh2triangle flux_bc_3d.msh
7
8run:
9 @echo **********Running 2D simulation
10 ../../bin/fluidity flux_bc_2d.flml
11 @echo **********Running 3D simulation
12 ../../bin/fluidity flux_bc_3d.flml
13
14input: clean preprocess
15
16clean:
17 rm -f *.stat *.steady_state*
18 rm -f *.d.* *.vtu
19 rm -f *.msh
20 rm -f *.ele *.edge *.node *.poly *.face
21 rm -f matrixdump* *checkpoint* *.log* *.err*
22
023
=== added file 'tests/flux_bc/flux_bc.xml'
--- tests/flux_bc/flux_bc.xml 1970-01-01 00:00:00 +0000
+++ tests/flux_bc/flux_bc.xml 2012-08-09 00:46:20 +0000
@@ -0,0 +1,44 @@
1<?xml version="1.0" encoding="UTF-8" ?>
2<!DOCTYPE testproblem SYSTEM "regressiontest.dtd">
3
4<testproblem>
5
6 <name>flux_bc</name>
7 <owner userid="ctj10"/>
8 <tags>flml</tags>
9
10 <problem_definition length="medium" nprocs="1">
11 <command_line>make run</command_line>
12 <!-- This checks the integral of the PhaseVolumeFraction field at t = 1 second. -->
13 <!-- The volumetric flux (r) is set to 0.5 m^3/s/m^2, and the flux boundary condition -->
14 <!-- enforces d/dt \int_{volume} vfrac = \int_{surface} r -->
15 </problem_definition>
16
17 <variables>
18 <variable name="vfrac_integral_2d" language="python">
19from fluidity_tools import stat_parser
20s = stat_parser("flux_bc_2d.stat")
21vfrac_integral_2d = s["Tephra"]["PhaseVolumeFraction"]["integral"]
22 </variable>
23
24 <variable name="vfrac_integral_3d" language="python">
25from fluidity_tools import stat_parser
26s = stat_parser("flux_bc_3d.stat")
27vfrac_integral_3d = s["Tephra"]["PhaseVolumeFraction"]["integral"]
28 </variable>
29 </variables>
30
31 <pass_tests>
32 <test name="Integral of PhaseVolumeFraction after 1 second = 0.15 in 2D simulation." language="python">
33assert abs(vfrac_integral_2d[10] - 0.15) &lt; 1.0e-9
34 </test>
35
36 <test name="Integral of PhaseVolumeFraction after 1 second = 0.045 in 3D simulation." language="python">
37assert abs(vfrac_integral_3d[10] - 0.045) &lt; 1.0e-9
38 </test>
39 </pass_tests>
40
41 <warn_tests>
42 </warn_tests>
43
44</testproblem>
045
=== added file 'tests/flux_bc/flux_bc_2d.flml'
--- tests/flux_bc/flux_bc_2d.flml 1970-01-01 00:00:00 +0000
+++ tests/flux_bc/flux_bc_2d.flml 2012-08-09 00:46:20 +0000
@@ -0,0 +1,396 @@
1<?xml version='1.0' encoding='utf-8'?>
2<fluidity_options>
3 <simulation_name>
4 <string_value lines="1">flux_bc_2d</string_value>
5 </simulation_name>
6 <problem_type>
7 <string_value lines="1">fluids</string_value>
8 </problem_type>
9 <geometry>
10 <dimension>
11 <integer_value rank="0">2</integer_value>
12 </dimension>
13 <mesh name="CoordinateMesh">
14 <from_file file_name="flux_bc_2d">
15 <format name="triangle"/>
16 <stat>
17 <include_in_stat/>
18 </stat>
19 </from_file>
20 </mesh>
21 <mesh name="VelocityMesh">
22 <from_mesh>
23 <mesh name="CoordinateMesh"/>
24 <mesh_shape>
25 <polynomial_degree>
26 <integer_value rank="0">1</integer_value>
27 </polynomial_degree>
28 </mesh_shape>
29 <mesh_continuity>
30 <string_value>discontinuous</string_value>
31 </mesh_continuity>
32 <stat>
33 <exclude_from_stat/>
34 </stat>
35 </from_mesh>
36 </mesh>
37 <mesh name="PressureMesh">
38 <from_mesh>
39 <mesh name="CoordinateMesh"/>
40 <mesh_shape>
41 <polynomial_degree>
42 <integer_value rank="0">2</integer_value>
43 </polynomial_degree>
44 </mesh_shape>
45 <stat>
46 <exclude_from_stat/>
47 </stat>
48 </from_mesh>
49 </mesh>
50 <quadrature>
51 <degree>
52 <integer_value rank="0">4</integer_value>
53 </degree>
54 </quadrature>
55 </geometry>
56 <io>
57 <dump_format>
58 <string_value>vtk</string_value>
59 </dump_format>
60 <dump_period>
61 <constant>
62 <real_value rank="0">1.0</real_value>
63 </constant>
64 </dump_period>
65 <output_mesh name="VelocityMesh"/>
66 <stat>
67 <output_at_start/>
68 </stat>
69 </io>
70 <timestepping>
71 <current_time>
72 <real_value rank="0">0.0</real_value>
73 </current_time>
74 <timestep>
75 <real_value rank="0">0.1</real_value>
76 </timestep>
77 <finish_time>
78 <real_value rank="0">1.0</real_value>
79 </finish_time>
80 <nonlinear_iterations>
81 <integer_value rank="0">2</integer_value>
82 <tolerance>
83 <real_value rank="0">1.0e-12</real_value>
84 <infinity_norm/>
85 </tolerance>
86 </nonlinear_iterations>
87 </timestepping>
88 <physical_parameters>
89 <gravity>
90 <magnitude>
91 <real_value rank="0">9.8</real_value>
92 </magnitude>
93 <vector_field name="GravityDirection" rank="1">
94 <prescribed>
95 <mesh name="CoordinateMesh"/>
96 <value name="WholeMesh">
97 <constant>
98 <real_value shape="2" dim1="dim" rank="1">0.0 -1.0</real_value>
99 </constant>
100 </value>
101 <output/>
102 <stat>
103 <include_in_stat/>
104 </stat>
105 <detectors>
106 <exclude_from_detectors/>
107 </detectors>
108 </prescribed>
109 </vector_field>
110 </gravity>
111 </physical_parameters>
112 <material_phase name="Tephra">
113 <equation_of_state>
114 <fluids>
115 <linear>
116 <reference_density>
117 <real_value rank="0">2340</real_value>
118 </reference_density>
119 </linear>
120 </fluids>
121 </equation_of_state>
122 <scalar_field name="Pressure" rank="0">
123 <prognostic>
124 <mesh name="PressureMesh"/>
125 <spatial_discretisation>
126 <continuous_galerkin>
127 <remove_stabilisation_term/>
128 </continuous_galerkin>
129 </spatial_discretisation>
130 <reference_node>
131 <integer_value rank="0">1</integer_value>
132 </reference_node>
133 <scheme>
134 <poisson_pressure_solution>
135 <string_value lines="1">never</string_value>
136 </poisson_pressure_solution>
137 <use_projection_method/>
138 </scheme>
139 <solver>
140 <iterative_method name="cg"/>
141 <preconditioner name="sor"/>
142 <relative_error>
143 <real_value rank="0">1.0e-7</real_value>
144 </relative_error>
145 <max_iterations>
146 <integer_value rank="0">1000</integer_value>
147 </max_iterations>
148 <never_ignore_solver_failures/>
149 <diagnostics>
150 <monitors/>
151 </diagnostics>
152 </solver>
153 <output/>
154 <stat/>
155 <convergence>
156 <include_in_convergence/>
157 </convergence>
158 <detectors>
159 <exclude_from_detectors/>
160 </detectors>
161 <steady_state>
162 <include_in_steady_state/>
163 </steady_state>
164 <no_interpolation/>
165 </prognostic>
166 </scalar_field>
167 <scalar_field name="Density" rank="0">
168 <diagnostic>
169 <algorithm name="Internal" material_phase_support="multiple"/>
170 <mesh name="CoordinateMesh"/>
171 <output/>
172 <stat/>
173 <convergence>
174 <include_in_convergence/>
175 </convergence>
176 <detectors>
177 <include_in_detectors/>
178 </detectors>
179 <steady_state>
180 <include_in_steady_state/>
181 </steady_state>
182 </diagnostic>
183 </scalar_field>
184 <vector_field name="Velocity" rank="1">
185 <prognostic>
186 <mesh name="VelocityMesh"/>
187 <equation name="LinearMomentum"/>
188 <spatial_discretisation>
189 <discontinuous_galerkin>
190 <viscosity_scheme>
191 <bassi_rebay/>
192 </viscosity_scheme>
193 <advection_scheme>
194 <upwind/>
195 <integrate_advection_by_parts>
196 <twice/>
197 </integrate_advection_by_parts>
198 </advection_scheme>
199 </discontinuous_galerkin>
200 <conservative_advection>
201 <real_value rank="0">0.0</real_value>
202 </conservative_advection>
203 </spatial_discretisation>
204 <temporal_discretisation>
205 <theta>
206 <real_value rank="0">1.0</real_value>
207 </theta>
208 <relaxation>
209 <real_value rank="0">0.5</real_value>
210 </relaxation>
211 </temporal_discretisation>
212 <solver>
213 <iterative_method name="gmres">
214 <restart>
215 <integer_value rank="0">30</integer_value>
216 </restart>
217 </iterative_method>
218 <preconditioner name="sor"/>
219 <relative_error>
220 <real_value rank="0">1.0e-7</real_value>
221 </relative_error>
222 <max_iterations>
223 <integer_value rank="0">1000</integer_value>
224 </max_iterations>
225 <never_ignore_solver_failures/>
226 <diagnostics>
227 <monitors/>
228 </diagnostics>
229 </solver>
230 <initial_condition name="WholeMesh">
231 <constant>
232 <real_value shape="2" dim1="dim" rank="1">0.0 0.0</real_value>
233 </constant>
234 </initial_condition>
235 <boundary_conditions name="Sides">
236 <surface_ids>
237 <integer_value shape="1" rank="1">666</integer_value>
238 </surface_ids>
239 <type name="dirichlet">
240 <apply_weakly/>
241 <align_bc_with_cartesian>
242 <x_component>
243 <constant>
244 <real_value rank="0">0.0</real_value>
245 </constant>
246 </x_component>
247 </align_bc_with_cartesian>
248 </type>
249 </boundary_conditions>
250 <boundary_conditions name="Bottom">
251 <surface_ids>
252 <integer_value shape="1" rank="1">444</integer_value>
253 </surface_ids>
254 <type name="dirichlet">
255 <apply_weakly/>
256 <align_bc_with_cartesian>
257 <y_component>
258 <constant>
259 <real_value rank="0">0.0</real_value>
260 </constant>
261 </y_component>
262 </align_bc_with_cartesian>
263 </type>
264 </boundary_conditions>
265 <boundary_conditions name="Top">
266 <surface_ids>
267 <integer_value shape="1" rank="1">333</integer_value>
268 </surface_ids>
269 <type name="dirichlet">
270 <apply_weakly/>
271 <align_bc_with_cartesian>
272 <y_component>
273 <constant>
274 <real_value rank="0">0.0</real_value>
275 </constant>
276 </y_component>
277 </align_bc_with_cartesian>
278 </type>
279 </boundary_conditions>
280 <tensor_field name="Viscosity" rank="2">
281 <prescribed>
282 <value name="WholeMesh">
283 <isotropic>
284 <constant>
285 <real_value rank="0">0.001</real_value>
286 </constant>
287 </isotropic>
288 </value>
289 <output/>
290 </prescribed>
291 </tensor_field>
292 <output/>
293 <stat>
294 <include_in_stat/>
295 <previous_time_step>
296 <exclude_from_stat/>
297 </previous_time_step>
298 <nonlinear_field>
299 <exclude_from_stat/>
300 </nonlinear_field>
301 </stat>
302 <convergence>
303 <include_in_convergence/>
304 </convergence>
305 <detectors>
306 <include_in_detectors/>
307 </detectors>
308 <steady_state>
309 <include_in_steady_state/>
310 </steady_state>
311 <consistent_interpolation/>
312 </prognostic>
313 </vector_field>
314 <scalar_field name="PhaseVolumeFraction" rank="0">
315 <prognostic>
316 <mesh name="CoordinateMesh"/>
317 <equation name="AdvectionDiffusion"/>
318 <spatial_discretisation>
319 <control_volumes>
320 <face_value name="FiniteElement">
321 <limit_face_value>
322 <limiter name="Sweby"/>
323 </limit_face_value>
324 </face_value>
325 <diffusion_scheme name="BassiRebay"/>
326 </control_volumes>
327 <conservative_advection>
328 <real_value rank="0">1.0</real_value>
329 </conservative_advection>
330 </spatial_discretisation>
331 <temporal_discretisation>
332 <theta>
333 <real_value rank="0">1.0</real_value>
334 </theta>
335 </temporal_discretisation>
336 <solver>
337 <iterative_method name="gmres">
338 <restart>
339 <integer_value rank="0">30</integer_value>
340 </restart>
341 </iterative_method>
342 <preconditioner name="sor"/>
343 <relative_error>
344 <real_value rank="0">1.0e-7</real_value>
345 </relative_error>
346 <max_iterations>
347 <integer_value rank="0">1000</integer_value>
348 </max_iterations>
349 <never_ignore_solver_failures/>
350 <diagnostics>
351 <monitors/>
352 </diagnostics>
353 </solver>
354 <initial_condition name="WholeMesh">
355 <constant>
356 <real_value rank="0">0.0</real_value>
357 </constant>
358 </initial_condition>
359 <boundary_conditions name="Top">
360 <surface_ids>
361 <integer_value shape="1" rank="1">333</integer_value>
362 </surface_ids>
363 <type name="flux">
364 <constant>
365 <real_value rank="0">0.5</real_value>
366 </constant>
367 </type>
368 </boundary_conditions>
369 <boundary_conditions name="Bottom">
370 <surface_ids>
371 <integer_value shape="1" rank="1">444</integer_value>
372 </surface_ids>
373 <type name="zero_flux"/>
374 </boundary_conditions>
375 <boundary_conditions name="Sides">
376 <surface_ids>
377 <integer_value shape="1" rank="1">666</integer_value>
378 </surface_ids>
379 <type name="zero_flux"/>
380 </boundary_conditions>
381 <output/>
382 <stat/>
383 <convergence>
384 <include_in_convergence/>
385 </convergence>
386 <detectors>
387 <include_in_detectors/>
388 </detectors>
389 <steady_state>
390 <include_in_steady_state/>
391 </steady_state>
392 <consistent_interpolation/>
393 </prognostic>
394 </scalar_field>
395 </material_phase>
396</fluidity_options>
0397
=== added file 'tests/flux_bc/flux_bc_3d.flml'
--- tests/flux_bc/flux_bc_3d.flml 1970-01-01 00:00:00 +0000
+++ tests/flux_bc/flux_bc_3d.flml 2012-08-09 00:46:20 +0000
@@ -0,0 +1,405 @@
1<?xml version='1.0' encoding='utf-8'?>
2<fluidity_options>
3 <simulation_name>
4 <string_value lines="1">flux_bc_3d</string_value>
5 </simulation_name>
6 <problem_type>
7 <string_value lines="1">fluids</string_value>
8 </problem_type>
9 <geometry>
10 <dimension>
11 <integer_value rank="0">3</integer_value>
12 </dimension>
13 <mesh name="CoordinateMesh">
14 <from_file file_name="flux_bc_3d">
15 <format name="triangle"/>
16 <stat>
17 <include_in_stat/>
18 </stat>
19 </from_file>
20 </mesh>
21 <mesh name="VelocityMesh">
22 <from_mesh>
23 <mesh name="CoordinateMesh"/>
24 <mesh_shape>
25 <polynomial_degree>
26 <integer_value rank="0">1</integer_value>
27 </polynomial_degree>
28 </mesh_shape>
29 <mesh_continuity>
30 <string_value>discontinuous</string_value>
31 </mesh_continuity>
32 <stat>
33 <exclude_from_stat/>
34 </stat>
35 </from_mesh>
36 </mesh>
37 <mesh name="PressureMesh">
38 <from_mesh>
39 <mesh name="CoordinateMesh"/>
40 <mesh_shape>
41 <polynomial_degree>
42 <integer_value rank="0">2</integer_value>
43 </polynomial_degree>
44 </mesh_shape>
45 <stat>
46 <exclude_from_stat/>
47 </stat>
48 </from_mesh>
49 </mesh>
50 <quadrature>
51 <degree>
52 <integer_value rank="0">4</integer_value>
53 </degree>
54 </quadrature>
55 </geometry>
56 <io>
57 <dump_format>
58 <string_value>vtk</string_value>
59 </dump_format>
60 <dump_period>
61 <constant>
62 <real_value rank="0">1.0</real_value>
63 </constant>
64 </dump_period>
65 <output_mesh name="VelocityMesh"/>
66 <stat>
67 <output_at_start/>
68 </stat>
69 </io>
70 <timestepping>
71 <current_time>
72 <real_value rank="0">0.0</real_value>
73 </current_time>
74 <timestep>
75 <real_value rank="0">0.1</real_value>
76 </timestep>
77 <finish_time>
78 <real_value rank="0">1.0</real_value>
79 </finish_time>
80 <nonlinear_iterations>
81 <integer_value rank="0">2</integer_value>
82 <tolerance>
83 <real_value rank="0">1.0e-12</real_value>
84 <infinity_norm/>
85 </tolerance>
86 </nonlinear_iterations>
87 </timestepping>
88 <physical_parameters>
89 <gravity>
90 <magnitude>
91 <real_value rank="0">9.8</real_value>
92 </magnitude>
93 <vector_field name="GravityDirection" rank="1">
94 <prescribed>
95 <mesh name="CoordinateMesh"/>
96 <value name="WholeMesh">
97 <constant>
98 <real_value shape="3" dim1="dim" rank="1">0.0 -1.0 0.0</real_value>
99 </constant>
100 </value>
101 <output/>
102 <stat>
103 <include_in_stat/>
104 </stat>
105 <detectors>
106 <exclude_from_detectors/>
107 </detectors>
108 </prescribed>
109 </vector_field>
110 </gravity>
111 </physical_parameters>
112 <material_phase name="Tephra">
113 <equation_of_state>
114 <fluids>
115 <linear>
116 <reference_density>
117 <real_value rank="0">2340.0</real_value>
118 </reference_density>
119 </linear>
120 </fluids>
121 </equation_of_state>
122 <scalar_field name="Pressure" rank="0">
123 <prognostic>
124 <mesh name="PressureMesh"/>
125 <spatial_discretisation>
126 <continuous_galerkin>
127 <remove_stabilisation_term/>
128 </continuous_galerkin>
129 </spatial_discretisation>
130 <reference_node>
131 <integer_value rank="0">1</integer_value>
132 </reference_node>
133 <scheme>
134 <poisson_pressure_solution>
135 <string_value lines="1">never</string_value>
136 </poisson_pressure_solution>
137 <use_projection_method/>
138 </scheme>
139 <solver>
140 <iterative_method name="cg"/>
141 <preconditioner name="sor"/>
142 <relative_error>
143 <real_value rank="0">1.0e-7</real_value>
144 </relative_error>
145 <max_iterations>
146 <integer_value rank="0">1000</integer_value>
147 </max_iterations>
148 <never_ignore_solver_failures/>
149 <diagnostics>
150 <monitors/>
151 </diagnostics>
152 </solver>
153 <output/>
154 <stat/>
155 <convergence>
156 <include_in_convergence/>
157 </convergence>
158 <detectors>
159 <exclude_from_detectors/>
160 </detectors>
161 <steady_state>
162 <include_in_steady_state/>
163 </steady_state>
164 <no_interpolation/>
165 </prognostic>
166 </scalar_field>
167 <scalar_field name="Density" rank="0">
168 <diagnostic>
169 <algorithm name="Internal" material_phase_support="multiple"/>
170 <mesh name="CoordinateMesh"/>
171 <output/>
172 <stat/>
173 <convergence>
174 <include_in_convergence/>
175 </convergence>
176 <detectors>
177 <include_in_detectors/>
178 </detectors>
179 <steady_state>
180 <include_in_steady_state/>
181 </steady_state>
182 </diagnostic>
183 </scalar_field>
184 <vector_field name="Velocity" rank="1">
185 <prognostic>
186 <mesh name="VelocityMesh"/>
187 <equation name="LinearMomentum"/>
188 <spatial_discretisation>
189 <discontinuous_galerkin>
190 <viscosity_scheme>
191 <bassi_rebay/>
192 </viscosity_scheme>
193 <advection_scheme>
194 <upwind/>
195 <integrate_advection_by_parts>
196 <twice/>
197 </integrate_advection_by_parts>
198 </advection_scheme>
199 </discontinuous_galerkin>
200 <conservative_advection>
201 <real_value rank="0">0.0</real_value>
202 </conservative_advection>
203 </spatial_discretisation>
204 <temporal_discretisation>
205 <theta>
206 <real_value rank="0">1.0</real_value>
207 </theta>
208 <relaxation>
209 <real_value rank="0">0.5</real_value>
210 </relaxation>
211 </temporal_discretisation>
212 <solver>
213 <iterative_method name="gmres">
214 <restart>
215 <integer_value rank="0">30</integer_value>
216 </restart>
217 </iterative_method>
218 <preconditioner name="sor"/>
219 <relative_error>
220 <real_value rank="0">1.0e-7</real_value>
221 </relative_error>
222 <max_iterations>
223 <integer_value rank="0">1000</integer_value>
224 </max_iterations>
225 <never_ignore_solver_failures/>
226 <diagnostics>
227 <monitors/>
228 </diagnostics>
229 </solver>
230 <initial_condition name="WholeMesh">
231 <constant>
232 <real_value shape="3" dim1="dim" rank="1">0.0 0.0 0.0</real_value>
233 </constant>
234 </initial_condition>
235 <boundary_conditions name="Top">
236 <surface_ids>
237 <integer_value shape="1" rank="1">444</integer_value>
238 </surface_ids>
239 <type name="dirichlet">
240 <apply_weakly/>
241 <align_bc_with_cartesian>
242 <y_component>
243 <constant>
244 <real_value rank="0">0</real_value>
245 </constant>
246 </y_component>
247 </align_bc_with_cartesian>
248 </type>
249 </boundary_conditions>
250 <boundary_conditions name="Sides_X">
251 <surface_ids>
252 <integer_value shape="1" rank="1">777</integer_value>
253 </surface_ids>
254 <type name="dirichlet">
255 <apply_weakly/>
256 <align_bc_with_cartesian>
257 <x_component>
258 <constant>
259 <real_value rank="0">0.0</real_value>
260 </constant>
261 </x_component>
262 </align_bc_with_cartesian>
263 </type>
264 </boundary_conditions>
265 <boundary_conditions name="Sides_Z">
266 <surface_ids>
267 <integer_value shape="1" rank="1">666</integer_value>
268 </surface_ids>
269 <type name="dirichlet">
270 <apply_weakly/>
271 <align_bc_with_cartesian>
272 <z_component>
273 <constant>
274 <real_value rank="0">0.0</real_value>
275 </constant>
276 </z_component>
277 </align_bc_with_cartesian>
278 </type>
279 </boundary_conditions>
280 <boundary_conditions name="Bottom">
281 <surface_ids>
282 <integer_value shape="1" rank="1">333</integer_value>
283 </surface_ids>
284 <type name="dirichlet">
285 <apply_weakly/>
286 <align_bc_with_cartesian>
287 <y_component>
288 <constant>
289 <real_value rank="0">0.0</real_value>
290 </constant>
291 </y_component>
292 </align_bc_with_cartesian>
293 </type>
294 </boundary_conditions>
295 <tensor_field name="Viscosity" rank="2">
296 <prescribed>
297 <value name="WholeMesh">
298 <isotropic>
299 <constant>
300 <real_value rank="0">0.001</real_value>
301 </constant>
302 </isotropic>
303 </value>
304 <output/>
305 </prescribed>
306 </tensor_field>
307 <output/>
308 <stat>
309 <include_in_stat/>
310 <previous_time_step>
311 <exclude_from_stat/>
312 </previous_time_step>
313 <nonlinear_field>
314 <exclude_from_stat/>
315 </nonlinear_field>
316 </stat>
317 <convergence>
318 <include_in_convergence/>
319 </convergence>
320 <detectors>
321 <include_in_detectors/>
322 </detectors>
323 <steady_state>
324 <include_in_steady_state/>
325 </steady_state>
326 <consistent_interpolation/>
327 </prognostic>
328 </vector_field>
329 <scalar_field name="PhaseVolumeFraction" rank="0">
330 <prognostic>
331 <mesh name="CoordinateMesh"/>
332 <equation name="AdvectionDiffusion"/>
333 <spatial_discretisation>
334 <control_volumes>
335 <face_value name="FiniteElement">
336 <limit_face_value>
337 <limiter name="Sweby"/>
338 </limit_face_value>
339 </face_value>
340 <diffusion_scheme name="BassiRebay"/>
341 </control_volumes>
342 <conservative_advection>
343 <real_value rank="0">1.0</real_value>
344 </conservative_advection>
345 </spatial_discretisation>
346 <temporal_discretisation>
347 <theta>
348 <real_value rank="0">1.0</real_value>
349 </theta>
350 </temporal_discretisation>
351 <solver>
352 <iterative_method name="gmres">
353 <restart>
354 <integer_value rank="0">30</integer_value>
355 </restart>
356 </iterative_method>
357 <preconditioner name="sor"/>
358 <relative_error>
359 <real_value rank="0">1.0e-7</real_value>
360 </relative_error>
361 <max_iterations>
362 <integer_value rank="0">1000</integer_value>
363 </max_iterations>
364 <never_ignore_solver_failures/>
365 <diagnostics>
366 <monitors/>
367 </diagnostics>
368 </solver>
369 <initial_condition name="WholeMesh">
370 <constant>
371 <real_value rank="0">0.0</real_value>
372 </constant>
373 </initial_condition>
374 <boundary_conditions name="Top">
375 <surface_ids>
376 <integer_value shape="1" rank="1">444</integer_value>
377 </surface_ids>
378 <type name="flux">
379 <constant>
380 <real_value rank="0">0.5</real_value>
381 </constant>
382 </type>
383 </boundary_conditions>
384 <boundary_conditions name="Others">
385 <surface_ids>
386 <integer_value shape="3" rank="1">333 666 777</integer_value>
387 </surface_ids>
388 <type name="zero_flux"/>
389 </boundary_conditions>
390 <output/>
391 <stat/>
392 <convergence>
393 <include_in_convergence/>
394 </convergence>
395 <detectors>
396 <include_in_detectors/>
397 </detectors>
398 <steady_state>
399 <include_in_steady_state/>
400 </steady_state>
401 <consistent_interpolation/>
402 </prognostic>
403 </scalar_field>
404 </material_phase>
405</fluidity_options>
0406
=== added directory 'tests/flux_bc/src'
=== added file 'tests/flux_bc/src/flux_bc_2d.geo'
--- tests/flux_bc/src/flux_bc_2d.geo 1970-01-01 00:00:00 +0000
+++ tests/flux_bc/src/flux_bc_2d.geo 2012-08-09 00:46:20 +0000
@@ -0,0 +1,19 @@
1Point(1) = {0.0, 0.0, 0.0, 0.05};
2Point(2) = {0.0, 1.0, 0.0, 0.05};
3Point(3) = {0.3, 1.0, 0.0, 0.05};
4Point(4) = {0.3, 0.0, 0.0, 0.05};
5Line(1) = {3,4};
6Line(2) = {4,1};
7Line(3) = {1,2};
8Line(4) = {2,3};
9Line Loop(5) = {1,2,3,4};
10Plane Surface(6) = {5};
11// Top of the box
12Physical Line(333) = {4};
13// Box sides
14Physical Line(666) = {3,1};
15// Box bottom
16Physical Line(444) = {2};
17// This is just to ensure all the interior
18// elements get written out.
19Physical Surface(10) = {6};
020
=== added file 'tests/flux_bc/src/flux_bc_3d.geo'
--- tests/flux_bc/src/flux_bc_3d.geo 1970-01-01 00:00:00 +0000
+++ tests/flux_bc/src/flux_bc_3d.geo 2012-08-09 00:46:20 +0000
@@ -0,0 +1,69 @@
1Point(1) = {0.0, 0.0, 0.0, 0.05};
2Point(2) = {0.3, 0.0, 0.0, 0.05};
3Point(3) = {0.3, 0.0, 0.3, 0.05};
4Point(4) = {0.0, 0.0, 0.3, 0.05};
5Point(5) = {0.0, 1.0, 0.0, 0.05};
6Point(6) = {0.3, 1.0, 0.0, 0.05};
7Point(7) = {0.3, 1.0, 0.3, 0.05};
8Point(8) = {0.0, 1.0, 0.3, 0.05};
9
10Line(1) = {1,2};
11Line(2) = {2,3};
12Line(3) = {3,4};
13Line(4) = {4,1};
14
15Line(5) = {5,6};
16Line(6) = {6,7};
17Line(7) = {7,8};
18Line(8) = {8,5};
19
20Line(9) = {5,1};
21Line(10) = {6,2};
22Line(11) = {7,3};
23Line(12) = {8,4};
24
25// Bottom surface
26Line Loop(5) = {1,2,3,4};
27
28// Side surface, nearest to the x axis
29Line Loop(6) = {1,-10,-5,9};
30
31// Side surface, furthest from the x axis
32Line Loop(7) = {-3,-11,7,12};
33
34// Side surface, nearest to the z axis
35Line Loop(8) = {-4,-12,8,9};
36
37// Side surface, furthest from the z axis
38Line Loop(9) = {2,-11,-6,10};
39
40// Top surface
41Line Loop(10) = {5,6,7,8};
42
43Plane Surface(20) = {5};
44Plane Surface(21) = {6};
45Plane Surface(22) = {7};
46Plane Surface(23) = {8};
47Plane Surface(24) = {9};
48Plane Surface(25) = {10};
49
50// Bottom of the box
51Physical Line(333) = {5};
52// Sides of the box perpendicular to the z axis
53Physical Line(666) = {6,7};
54// Sides of the box perpendicular to the x axis
55Physical Line(777) = {8,9};
56// Top of the box
57Physical Line(444) = {10};
58
59// This is just to ensure all the interior
60// elements get written out.
61Physical Surface(333) = {20};
62Physical Surface(666) = {21,22};
63Physical Surface(777) = {23,24};
64Physical Surface(444) = {25};
65
66Surface Loop(800) = {22, 20, 21, 24, 25, 23};
67Volume(900) = {800};
68Physical Volume(999) = {900};
69
070
=== added directory 'tests/mphase_dusty_gas_shock_tube'
=== added file 'tests/mphase_dusty_gas_shock_tube/Makefile'
--- tests/mphase_dusty_gas_shock_tube/Makefile 1970-01-01 00:00:00 +0000
+++ tests/mphase_dusty_gas_shock_tube/Makefile 2012-08-09 00:46:20 +0000
@@ -0,0 +1,18 @@
1preprocess:
2 @echo **********Creating 1D mesh
3 ../../bin/interval --dx=0.00271002710027 -- -1.35501355014 1.35501355014 line
4
5run:
6 @echo **********Running simulation
7 ../../bin/fluidity -v2 -l mphase_dusty_gas_shock_tube.flml
8 ../../bin/fluidity -v2 -l single_phase_frozen_flow_test.flml
9
10input: clean preprocess
11
12clean:
13 rm -f *.stat *.steady_state*
14 rm -f *.d.* *.vtu
15 rm -f *.msh
16 rm -f *.ele *.edge *.node *.poly *.bound
17 rm -f matrixdump* *.log* *.err*
18
019
=== added file 'tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml'
--- tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml 1970-01-01 00:00:00 +0000
+++ tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.flml 2012-08-09 00:46:20 +0000
@@ -0,0 +1,733 @@
1<?xml version='1.0' encoding='utf-8'?>
2<fluidity_options>
3 <simulation_name>
4 <string_value lines="1">mphase_dusty_gas_shock_tube</string_value>
5 </simulation_name>
6 <problem_type>
7 <string_value lines="1">multiphase</string_value>
8 </problem_type>
9 <geometry>
10 <dimension>
11 <integer_value rank="0">1</integer_value>
12 </dimension>
13 <mesh name="CoordinateMesh">
14 <from_file file_name="line">
15 <format name="triangle"/>
16 <stat>
17 <include_in_stat/>
18 </stat>
19 </from_file>
20 </mesh>
21 <mesh name="VelocityMesh">
22 <from_mesh>
23 <mesh name="CoordinateMesh"/>
24 <mesh_shape>
25 <polynomial_degree>
26 <integer_value rank="0">1</integer_value>
27 </polynomial_degree>
28 </mesh_shape>
29 <stat>
30 <exclude_from_stat/>
31 </stat>
32 </from_mesh>
33 </mesh>
34 <mesh name="PressureMesh">
35 <from_mesh>
36 <mesh name="CoordinateMesh"/>
37 <mesh_shape>
38 <polynomial_degree>
39 <integer_value rank="0">1</integer_value>
40 </polynomial_degree>
41 </mesh_shape>
42 <stat>
43 <exclude_from_stat/>
44 </stat>
45 </from_mesh>
46 </mesh>
47 <mesh name="DensityMesh">
48 <from_mesh>
49 <mesh name="CoordinateMesh"/>
50 <mesh_shape>
51 <polynomial_degree>
52 <integer_value rank="0">1</integer_value>
53 </polynomial_degree>
54 </mesh_shape>
55 <stat>
56 <exclude_from_stat/>
57 </stat>
58 </from_mesh>
59 </mesh>
60 <quadrature>
61 <degree>
62 <integer_value rank="0">5</integer_value>
63 </degree>
64 </quadrature>
65 </geometry>
66 <io>
67 <dump_format>
68 <string_value>vtk</string_value>
69 </dump_format>
70 <dump_period>
71 <constant>
72 <real_value rank="0">0.0</real_value>
73 </constant>
74 </dump_period>
75 <output_mesh name="VelocityMesh"/>
76 <stat>
77 <output_at_start/>
78 </stat>
79 </io>
80 <timestepping>
81 <current_time>
82 <real_value rank="0">0.0</real_value>
83 </current_time>
84 <timestep>
85 <real_value rank="0">0.000001</real_value>
86 </timestep>
87 <finish_time>
88 <real_value rank="0">0.00037772998222</real_value>
89 <comment>This corresponds to a non-dimensional time of tau = 4. Multiplying this by the reference time of l/u_ref gives 0.00037772998222 seconds.
90
91l = (4/3)*(rho_p/rho_g)*d
92u_ref = sqrt(p/rho_g)</comment>
93 </finish_time>
94 <nonlinear_iterations>
95 <integer_value rank="0">3</integer_value>
96 <tolerance>
97 <real_value rank="0">1.0e-9</real_value>
98 <infinity_norm/>
99 </tolerance>
100 </nonlinear_iterations>
101 </timestepping>
102 <material_phase name="Air">
103 <equation_of_state>
104 <compressible>
105 <stiffened_gas>
106 <ratio_specific_heats>
107 <real_value rank="0">1.4</real_value>
108 </ratio_specific_heats>
109 </stiffened_gas>
110 </compressible>
111 </equation_of_state>
112 <scalar_field name="Pressure" rank="0">
113 <prognostic>
114 <mesh name="PressureMesh"/>
115 <spatial_discretisation>
116 <continuous_galerkin>
117 <remove_stabilisation_term/>
118 </continuous_galerkin>
119 </spatial_discretisation>
120 <scheme>
121 <poisson_pressure_solution>
122 <string_value lines="1">never</string_value>
123 </poisson_pressure_solution>
124 <use_compressible_projection_method/>
125 </scheme>
126 <solver>
127 <iterative_method name="preonly"/>
128 <preconditioner name="lu"/>
129 <relative_error>
130 <real_value rank="0">1e-7</real_value>
131 </relative_error>
132 <max_iterations>
133 <integer_value rank="0">10000</integer_value>
134 </max_iterations>
135 <never_ignore_solver_failures/>
136 <diagnostics>
137 <monitors/>
138 </diagnostics>
139 </solver>
140 <output/>
141 <stat/>
142 <convergence>
143 <include_in_convergence/>
144 </convergence>
145 <detectors>
146 <exclude_from_detectors/>
147 </detectors>
148 <steady_state>
149 <include_in_steady_state/>
150 </steady_state>
151 <no_interpolation/>
152 </prognostic>
153 </scalar_field>
154 <scalar_field name="Density" rank="0">
155 <prognostic>
156 <mesh name="PressureMesh"/>
157 <spatial_discretisation>
158 <continuous_galerkin>
159 <stabilisation>
160 <no_stabilisation/>
161 </stabilisation>
162 <advection_terms/>
163 <mass_terms/>
164 </continuous_galerkin>
165 <conservative_advection>
166 <real_value rank="0">0.0</real_value>
167 </conservative_advection>
168 </spatial_discretisation>
169 <temporal_discretisation>
170 <theta>
171 <real_value rank="0">1.0</real_value>
172 </theta>
173 </temporal_discretisation>
174 <initial_condition name="WholeMesh">
175 <python>
176 <string_value lines="20" type="code" language="python">def val(X,t):
177 if(X[0] &lt;= 0):
178 return 12.3
179 else:
180 return 1.23</string_value>
181 </python>
182 </initial_condition>
183 <output/>
184 <stat/>
185 <convergence>
186 <include_in_convergence/>
187 </convergence>
188 <detectors>
189 <include_in_detectors/>
190 </detectors>
191 <steady_state>
192 <include_in_steady_state/>
193 </steady_state>
194 <consistent_interpolation/>
195 </prognostic>
196 </scalar_field>
197 <vector_field name="Velocity" rank="1">
198 <prognostic>
199 <mesh name="VelocityMesh"/>
200 <equation name="LinearMomentum"/>
201 <spatial_discretisation>
202 <continuous_galerkin>
203 <stabilisation>
204 <streamline_upwind>
205 <nu_bar_optimal/>
206 <nu_scale name="0.5">
207 <real_value shape="1" rank="0">0.5</real_value>
208 </nu_scale>
209 </streamline_upwind>
210 </stabilisation>
211 <mass_terms>
212 <lump_mass_matrix/>
213 </mass_terms>
214 <advection_terms/>
215 <stress_terms>
216 <tensor_form/>
217 </stress_terms>
218 </continuous_galerkin>
219 <conservative_advection>
220 <real_value rank="0">0.0</real_value>
221 </conservative_advection>
222 </spatial_discretisation>
223 <temporal_discretisation>
224 <theta>
225 <real_value rank="0">1.0</real_value>
226 </theta>
227 <relaxation>
228 <real_value rank="0">0.5</real_value>
229 </relaxation>
230 </temporal_discretisation>
231 <solver>
232 <iterative_method name="preonly"/>
233 <preconditioner name="lu"/>
234 <relative_error>
235 <real_value rank="0">1e-7</real_value>
236 </relative_error>
237 <max_iterations>
238 <integer_value rank="0">10000</integer_value>
239 </max_iterations>
240 <never_ignore_solver_failures/>
241 <diagnostics>
242 <monitors/>
243 </diagnostics>
244 </solver>
245 <initial_condition name="WholeMesh">
246 <constant>
247 <real_value shape="1" dim1="dim" rank="1">0.0</real_value>
248 </constant>
249 </initial_condition>
250 <boundary_conditions name="Ends">
251 <surface_ids>
252 <integer_value shape="2" rank="1">1 2</integer_value>
253 </surface_ids>
254 <type name="dirichlet">
255 <align_bc_with_cartesian>
256 <x_component>
257 <constant>
258 <real_value rank="0">0.0</real_value>
259 </constant>
260 </x_component>
261 </align_bc_with_cartesian>
262 </type>
263 </boundary_conditions>
264 <tensor_field name="Viscosity" rank="2">
265 <prescribed>
266 <value name="WholeMesh">
267 <isotropic>
268 <constant>
269 <real_value rank="0">1.83e-5</real_value>
270 </constant>
271 </isotropic>
272 </value>
273 <output/>
274 </prescribed>
275 </tensor_field>
276 <output/>
277 <stat>
278 <include_in_stat/>
279 <previous_time_step>
280 <exclude_from_stat/>
281 </previous_time_step>
282 <nonlinear_field>
283 <exclude_from_stat/>
284 </nonlinear_field>
285 </stat>
286 <convergence>
287 <include_in_convergence/>
288 </convergence>
289 <detectors>
290 <include_in_detectors/>
291 </detectors>
292 <steady_state>
293 <include_in_steady_state/>
294 </steady_state>
295 <consistent_interpolation/>
296 </prognostic>
297 </vector_field>
298 <scalar_field name="PhaseVolumeFraction" rank="0">
299 <diagnostic>
300 <mesh name="CoordinateMesh"/>
301 <algorithm name="Internal" material_phase_support="multiple"/>
302 <output/>
303 <stat/>
304 <detectors>
305 <include_in_detectors/>
306 </detectors>
307 </diagnostic>
308 </scalar_field>
309 <scalar_field name="CompressibleContinuityResidual" rank="0">
310 <diagnostic>
311 <mesh name="PressureMesh"/>
312 <algorithm name="Internal" material_phase_support="multiple"/>
313 <output/>
314 <stat/>
315 <detectors>
316 <include_in_detectors/>
317 </detectors>
318 <solver>
319 <iterative_method name="gmres">
320 <restart>
321 <integer_value rank="0">30</integer_value>
322 </restart>
323 </iterative_method>
324 <preconditioner name="sor"/>
325 <relative_error>
326 <real_value rank="0">1.0e-7</real_value>
327 </relative_error>
328 <max_iterations>
329 <integer_value rank="0">10000</integer_value>
330 </max_iterations>
331 <never_ignore_solver_failures/>
332 <diagnostics>
333 <monitors/>
334 </diagnostics>
335 </solver>
336 </diagnostic>
337 </scalar_field>
338 <scalar_field name="InternalEnergy" rank="0">
339 <prognostic>
340 <mesh name="PressureMesh"/>
341 <equation name="InternalEnergy">
342 <density name="Density"/>
343 </equation>
344 <spatial_discretisation>
345 <continuous_galerkin>
346 <stabilisation>
347 <streamline_upwind>
348 <nu_bar_optimal/>
349 <nu_scale name="0.5">
350 <real_value shape="1" rank="0">0.5</real_value>
351 </nu_scale>
352 </streamline_upwind>
353 </stabilisation>
354 <advection_terms/>
355 <mass_terms/>
356 </continuous_galerkin>
357 <conservative_advection>
358 <real_value rank="0">0.0</real_value>
359 </conservative_advection>
360 </spatial_discretisation>
361 <temporal_discretisation>
362 <theta>
363 <real_value rank="0">1.0</real_value>
364 </theta>
365 </temporal_discretisation>
366 <solver>
367 <iterative_method name="preonly"/>
368 <preconditioner name="lu"/>
369 <relative_error>
370 <real_value rank="0">1.0e-7</real_value>
371 </relative_error>
372 <max_iterations>
373 <integer_value rank="0">10000</integer_value>
374 </max_iterations>
375 <never_ignore_solver_failures/>
376 <diagnostics>
377 <monitors/>
378 </diagnostics>
379 </solver>
380 <initial_condition name="WholeMesh">
381 <constant>
382 <real_value rank="0">205894.308943</real_value>
383 <comment>InternalEnergy from the formula: (3/2)*R*Temperature = (3/2)*287.04*300 K = 203252
384InternalEnergy needed for a Pressure of 1.013e5 = 205894.308943</comment>
385 </constant>
386 </initial_condition>
387 <output/>
388 <stat/>
389 <convergence>
390 <include_in_convergence/>
391 </convergence>
392 <detectors>
393 <include_in_detectors/>
394 </detectors>
395 <steady_state>
396 <include_in_steady_state/>
397 </steady_state>
398 <consistent_interpolation/>
399 </prognostic>
400 </scalar_field>
401 <scalar_field name="CFLNumber" rank="0">
402 <diagnostic>
403 <algorithm name="Internal" material_phase_support="multiple"/>
404 <mesh name="VelocityMesh"/>
405 <output/>
406 <stat/>
407 <convergence>
408 <include_in_convergence/>
409 </convergence>
410 <detectors>
411 <include_in_detectors/>
412 </detectors>
413 <steady_state>
414 <include_in_steady_state/>
415 </steady_state>
416 </diagnostic>
417 </scalar_field>
418 <multiphase_properties>
419 <effective_conductivity>
420 <real_value rank="0">0.026</real_value>
421 </effective_conductivity>
422 <specific_heat>
423 <real_value rank="0">758</real_value>
424 </specific_heat>
425 </multiphase_properties>
426 </material_phase>
427 <material_phase name="Dust">
428 <equation_of_state>
429 <fluids>
430 <linear>
431 <reference_density>
432 <real_value rank="0">2500</real_value>
433 </reference_density>
434 </linear>
435 </fluids>
436 </equation_of_state>
437 <scalar_field name="Pressure" rank="0">
438 <aliased material_phase_name="Air" field_name="Pressure"/>
439 </scalar_field>
440 <scalar_field name="Density" rank="0">
441 <diagnostic>
442 <algorithm name="Internal" material_phase_support="multiple"/>
443 <mesh name="PressureMesh"/>
444 <output/>
445 <stat/>
446 <convergence>
447 <include_in_convergence/>
448 </convergence>
449 <detectors>
450 <include_in_detectors/>
451 </detectors>
452 <steady_state>
453 <include_in_steady_state/>
454 </steady_state>
455 </diagnostic>
456 </scalar_field>
457 <vector_field name="Velocity" rank="1">
458 <prognostic>
459 <mesh name="VelocityMesh"/>
460 <equation name="LinearMomentum"/>
461 <spatial_discretisation>
462 <continuous_galerkin>
463 <stabilisation>
464 <no_stabilisation/>
465 </stabilisation>
466 <mass_terms>
467 <lump_mass_matrix/>
468 </mass_terms>
469 <advection_terms/>
470 <stress_terms>
471 <tensor_form/>
472 </stress_terms>
473 </continuous_galerkin>
474 <conservative_advection>
475 <real_value rank="0">0.0</real_value>
476 </conservative_advection>
477 </spatial_discretisation>
478 <temporal_discretisation>
479 <theta>
480 <real_value rank="0">1.0</real_value>
481 </theta>
482 <relaxation>
483 <real_value rank="0">0.5</real_value>
484 </relaxation>
485 </temporal_discretisation>
486 <solver>
487 <iterative_method name="preonly"/>
488 <preconditioner name="lu"/>
489 <relative_error>
490 <real_value rank="0">1e-7</real_value>
491 </relative_error>
492 <max_iterations>
493 <integer_value rank="0">10000</integer_value>
494 </max_iterations>
495 <never_ignore_solver_failures/>
496 <diagnostics>
497 <monitors/>
498 </diagnostics>
499 </solver>
500 <initial_condition name="WholeMesh">
501 <constant>
502 <real_value shape="1" dim1="dim" rank="1">0.0</real_value>
503 </constant>
504 </initial_condition>
505 <boundary_conditions name="Ends">
506 <surface_ids>
507 <integer_value shape="2" rank="1">1 2</integer_value>
508 </surface_ids>
509 <type name="dirichlet">
510 <align_bc_with_cartesian>
511 <x_component>
512 <constant>
513 <real_value rank="0">0.0</real_value>
514 </constant>
515 </x_component>
516 </align_bc_with_cartesian>
517 </type>
518 </boundary_conditions>
519 <output/>
520 <stat>
521 <include_in_stat/>
522 <previous_time_step>
523 <exclude_from_stat/>
524 </previous_time_step>
525 <nonlinear_field>
526 <exclude_from_stat/>
527 </nonlinear_field>
528 </stat>
529 <convergence>
530 <include_in_convergence/>
531 </convergence>
532 <detectors>
533 <include_in_detectors/>
534 </detectors>
535 <steady_state>
536 <include_in_steady_state/>
537 </steady_state>
538 <consistent_interpolation/>
539 </prognostic>
540 </vector_field>
541 <scalar_field name="PhaseVolumeFraction" rank="0">
542 <prognostic>
543 <mesh name="CoordinateMesh"/>
544 <equation name="AdvectionDiffusion"/>
545 <spatial_discretisation>
546 <control_volumes>
547 <face_value name="FiniteElement">
548 <limit_face_value>
549 <limiter name="Sweby"/>
550 </limit_face_value>
551 </face_value>
552 <diffusion_scheme name="BassiRebay"/>
553 </control_volumes>
554 <conservative_advection>
555 <real_value rank="0">1.0</real_value>
556 </conservative_advection>
557 </spatial_discretisation>
558 <temporal_discretisation>
559 <theta>
560 <real_value rank="0">1.0</real_value>
561 </theta>
562 </temporal_discretisation>
563 <solver>
564 <iterative_method name="preonly"/>
565 <preconditioner name="lu"/>
566 <relative_error>
567 <real_value rank="0">1.0e-7</real_value>
568 </relative_error>
569 <max_iterations>
570 <integer_value rank="0">10000</integer_value>
571 </max_iterations>
572 <never_ignore_solver_failures/>
573 <diagnostics>
574 <monitors/>
575 </diagnostics>
576 </solver>
577 <initial_condition name="WholeMesh">
578 <python>
579 <string_value lines="20" type="code" language="python">def val(X,t):
580 if(X[0] &lt;= 0):
581 return 4.92e-8
582 else:
583 return 4.92e-4</string_value>
584 <comment>alpha_p = 0.000492 in dusty gas region.
585
586We know that the ratio of gas density (rho_g) to particle mass concentration (sigma_p) is assumed to be 1.0, so rho_g = sigma_p = 1.23 kg/m^3.
587The normalised mass concentration is 1.0 in the dusty gas region, so we divide 1.23 by the particle density (2500 kg/m^3) get obtain the particle phase volume fraction.</comment>
588 </python>
589 </initial_condition>
590 <boundary_conditions name="All">
591 <surface_ids>
592 <integer_value shape="2" rank="1">1 2</integer_value>
593 </surface_ids>
594 <type name="zero_flux"/>
595 </boundary_conditions>
596 <output/>
597 <stat/>
598 <convergence>
599 <include_in_convergence/>
600 </convergence>
601 <detectors>
602 <include_in_detectors/>
603 </detectors>
604 <steady_state>
605 <include_in_steady_state/>
606 </steady_state>
607 <consistent_interpolation/>
608 </prognostic>
609 </scalar_field>
610 <scalar_field name="ParticleReynoldsNumber" rank="0">
611 <diagnostic>
612 <algorithm name="particle_reynolds_number" material_phase_support="multiple">
613 <depends>
614 <string_value lines="1">Dust::Velocity,Air::Velocity,Air::PhaseVolumeFraction,Air::Density</string_value>
615 </depends>
616 <particle_diameter>
617 <real_value rank="0">10e-6</real_value>
618 </particle_diameter>
619 <continuous_phase_name>Air</continuous_phase_name>
620 </algorithm>
621 <mesh name="VelocityMesh"/>
622 <output/>
623 <stat/>
624 <convergence>
625 <include_in_convergence/>
626 </convergence>
627 <detectors>
628 <include_in_detectors/>
629 </detectors>
630 <steady_state>
631 <include_in_steady_state/>
632 </steady_state>
633 </diagnostic>
634 </scalar_field>
635 <scalar_field name="CFLNumber" rank="0">
636 <diagnostic>
637 <algorithm name="Internal" material_phase_support="multiple"/>
638 <mesh name="VelocityMesh"/>
639 <output/>
640 <stat/>
641 <convergence>
642 <include_in_convergence/>
643 </convergence>
644 <detectors>
645 <include_in_detectors/>
646 </detectors>
647 <steady_state>
648 <include_in_steady_state/>
649 </steady_state>
650 </diagnostic>
651 </scalar_field>
652 <scalar_field name="InternalEnergy" rank="0">
653 <prognostic>
654 <mesh name="PressureMesh"/>
655 <equation name="InternalEnergy">
656 <density name="Density"/>
657 </equation>
658 <spatial_discretisation>
659 <continuous_galerkin>
660 <stabilisation>
661 <streamline_upwind>
662 <nu_bar_optimal/>
663 <nu_scale name="0.5">
664 <real_value shape="1" rank="0">0.5</real_value>
665 </nu_scale>
666 </streamline_upwind>
667 </stabilisation>
668 <advection_terms/>
669 <mass_terms/>
670 </continuous_galerkin>
671 <conservative_advection>
672 <real_value rank="0">0.0</real_value>
673 </conservative_advection>
674 </spatial_discretisation>
675 <temporal_discretisation>
676 <theta>
677 <real_value rank="0">1.0</real_value>
678 </theta>
679 </temporal_discretisation>
680 <solver>
681 <iterative_method name="preonly"/>
682 <preconditioner name="lu"/>
683 <relative_error>
684 <real_value rank="0">1.0e-7</real_value>
685 </relative_error>
686 <max_iterations>
687 <integer_value rank="0">10000</integer_value>
688 </max_iterations>
689 <never_ignore_solver_failures/>
690 <diagnostics>
691 <monitors/>
692 </diagnostics>
693 </solver>
694 <initial_condition name="WholeMesh">
695 <constant>
696 <real_value rank="0">205894.308943</real_value>
697 <comment>InternalEnergy from the formula: (3/2)*R*Temperature = (3/2)*287.04*300 K = 203252
698InternalEnergy needed for a Pressure of 1.013e5 = 205894.308943</comment>
699 </constant>
700 </initial_condition>
701 <output/>
702 <stat/>
703 <convergence>
704 <include_in_convergence/>
705 </convergence>
706 <detectors>
707 <include_in_detectors/>
708 </detectors>
709 <steady_state>
710 <include_in_steady_state/>
711 </steady_state>
712 <consistent_interpolation/>
713 </prognostic>
714 </scalar_field>
715 <multiphase_properties>
716 <particle_diameter>
717 <real_value rank="0">10e-6</real_value>
718 </particle_diameter>
719 <specific_heat>
720 <real_value rank="0">758</real_value>
721 <comment>1406</comment>
722 </specific_heat>
723 </multiphase_properties>
724 </material_phase>
725 <multiphase_interaction>
726 <fluid_particle_drag>
727 <drag_correlation name="wen_yu"/>
728 </fluid_particle_drag>
729 <heat_transfer>
730 <heat_transfer_coefficient name="gunn"/>
731 </heat_transfer>
732 </multiphase_interaction>
733</fluidity_options>
0734
=== added file 'tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.xml'
--- tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.xml 1970-01-01 00:00:00 +0000
+++ tests/mphase_dusty_gas_shock_tube/mphase_dusty_gas_shock_tube.xml 2012-08-09 00:46:20 +0000
@@ -0,0 +1,156 @@
1<?xml version="1.0" encoding="UTF-8" ?>
2
3<testproblem>
4
5 <!-- A 1D gas-solid shock tube problem. The setup is the same as the one given in the paper by Miura & Glass (1982). -->
6 <!-- This test uses results at approximately t = 3.77e-4 seconds (normalised time of tau = 4 in the paper by Miura & Glass (1982)). -->
7
8 <name>mphase_dusty_gas_shock_tube</name>
9 <owner userid="ctj10"/>
10 <tags>flml</tags>
11
12 <problem_definition length="medium" nprocs="1">
13 <command_line>make run</command_line>
14 </problem_definition>
15
16 <variables>
17 <variable name="time" language="python">
18from fluidity_tools import stat_parser
19s = stat_parser("mphase_dusty_gas_shock_tube.stat")
20time=s["ElapsedTime"]["value"]
21 </variable>
22
23 <variable name="positions" language="python">
24import vtktools
25
26file = vtktools.vtu('mphase_dusty_gas_shock_tube_378.vtu')
27file.GetFieldNames()
28p = file.GetLocations()
29positions = p[:,1]
30 </variable>
31
32 <variable name="air_velocity" language="python">
33import vtktools
34
35file = vtktools.vtu('mphase_dusty_gas_shock_tube_378.vtu')
36file.GetFieldNames()
37air_velocity = file.GetVectorField('Air::Velocity')
38 </variable>
39
40 <variable name="dust_vfrac" language="python">
41import vtktools
42
43file = vtktools.vtu('mphase_dusty_gas_shock_tube_378.vtu')
44file.GetFieldNames()
45dust_vfrac = file.GetScalarField('Dust::PhaseVolumeFraction')
46 </variable>
47
48 <variable name="pressure" language="python">
49import vtktools
50
51file = vtktools.vtu('mphase_dusty_gas_shock_tube_378.vtu')
52file.GetFieldNames()
53pressure = file.GetScalarField('Air::Pressure')
54 </variable>
55
56 <variable name="max_dust_density" language="python">
57from fluidity_tools import stat_parser
58s = stat_parser("mphase_dusty_gas_shock_tube.stat")
59max_dust_density=s["Dust"]["Density"]["max"][-1]
60 </variable>
61
62 <variable name="min_dust_density" language="python">
63from fluidity_tools import stat_parser
64s = stat_parser("mphase_dusty_gas_shock_tube.stat")
65min_dust_density=s["Dust"]["Density"]["min"][-1]
66 </variable>
67 </variables>
68
69 <pass_tests>
70 <test name="Solvers have converged" language="python">
71import os
72files = os.listdir("./")
73solvers_converged = not "matrixdump" in files and not "matrixdump.info" in files
74assert solvers_converged
75 </test>
76
77 <test name="Finish time is 3.77e-4 seconds" language="python">
78assert (time[-1] &gt;= 3.77e-4)
79assert (time[-1] &lt; (3.77e-4 + 0.000002))
80 </test>
81
82 <test name="Normalised Gas::Velocity is 0 for normalised x in [-50, -10]" language="python">
83nnodes = len(air_velocity)
84
85vals = []
86for i in range(nnodes):
87 if(positions[i]/0.0271002710027 &lt; -10.0):
88 assert abs(air_velocity[i,0]/286.980353992) &lt; 1.0e-12
89 </test>
90
91 <test name="Normalised Gas::Velocity is in [0, 0.9] for normalised x in [-10, 10]" language="python">
92nnodes = len(air_velocity)
93
94vals = []
95for i in range(nnodes):
96 if( (positions[i]/0.0271002710027 &gt; -10.0) and (positions[i]/0.0271002710027 &lt; 10.0) ):
97 assert abs(air_velocity[i,0]/286.980353992) &lt; 0.9
98 <!-- -1.0e-9 is needed to deal with small under-shoots -->
99 assert abs(air_velocity[i,0]/286.980353992) &gt; -1.0e-12
100 </test>
101
102 <test name="Normalised Gas::Velocity is 0 for normalised x in [10, 50]" language="python">
103nnodes = len(air_velocity)
104
105vals = []
106for i in range(nnodes):
107 if(positions[i]/0.0271002710027 &gt; 10.0):
108 assert abs(air_velocity[i,0]/286.980353992) &lt; 1.0e-12
109 </test>
110
111 <test name="Normalised Pressure is 10.0 for normalised x in [-50, -10]" language="python">
112nnodes = len(pressure)
113
114vals = []
115for i in range(nnodes):
116 if(positions[i]/0.0271002710027 &lt; -10.0):
117 assert abs(pressure[i]/1.013e5 - 10.0) &lt; 1.0e-6
118 </test>
119
120 <test name="Normalised Pressure is in [1.0, 10.0] for normalised x in [-10, 10]" language="python">
121nnodes = len(pressure)
122<!-- Note: values of 0.9 and 10.1 have been used instead of 1.0 and 10.0 because of small over-shoots/under-shoots -->
123vals = []
124for i in range(nnodes):
125 if( (positions[i]/0.0271002710027 &gt; -10.0) and (positions[i]/0.0271002710027 &lt; 10.0) ):
126 assert abs(pressure[i]/1.013e5) &lt; 10.1
127 assert abs(pressure[i]/1.013e5) &gt; 0.9
128 </test>
129
130 <test name="Normalised Pressure is 1.0 for normalised x in [10, 50]" language="python">
131nnodes = len(air_velocity)
132
133vals = []
134for i in range(nnodes):
135 if(positions[i]/0.0271002710027 &gt; 10.0):
136 assert abs(pressure[i]/1.013e5) &gt;= 1.0
137 </test>
138
139 <test name="Mass concentration of Dust is between 0 and 2.5" language="python">
140nnodes = len(air_velocity)
141
142vals = []
143for i in range(nnodes):
144 assert abs(dust_vfrac[i]*2500.0/1.23) &lt; 2.5
145 assert abs(dust_vfrac[i]*2500.0/1.23) &gt; 0
146 </test>
147
148 <test name="Dust density stays constant" language="python">
149assert abs(max_dust_density - min_dust_density) &lt; 1.0e-16
150 </test>
151 </pass_tests>
152
153 <warn_tests>
154 </warn_tests>
155
156</testproblem>
0157
=== added file 'tests/mphase_dusty_gas_shock_tube/plot.py'
--- tests/mphase_dusty_gas_shock_tube/plot.py 1970-01-01 00:00:00 +0000
+++ tests/mphase_dusty_gas_shock_tube/plot.py 2012-08-09 00:46:20 +0000
@@ -0,0 +1,93 @@
1import pylab
2import numpy
3import shocktube
4import vtktools
5params = {'text.fontsize': 6,
6 'legend.fontsize': 8,
7 'xtick.labelsize': 8,
8 'ytick.labelsize': 8,
9 'lines.markersize': 6,
10 'axes.titlesize': 'small'}
11pylab.rcParams.update(params)
12
13filename='mphase_dusty_gas_shock_tube_378.vtu' # This corresponds to approximately t = 3.77e-4 seconds (normalised time of tau = 4 in the paper by Miura & Glass (1982))
14vt=vtktools.vtu(filename)
15
16# Time and coordinates
17t=vt.GetScalarField('Air::Time')[0]
18xyz=vt.GetLocations()
19x=xyz[:,0]
20
21# Solution fields
22p=vt.GetScalarField('Air::Pressure')
23uvw_air=vt.GetVectorField('Air::Velocity')
24u_air=uvw_air[:,0]
25uvw_dust=vt.GetVectorField('Dust::Velocity')
26u_dust=uvw_dust[:,0]
27rho_air=vt.GetScalarField('Air::Density')
28rho_dust=vt.GetScalarField('Dust::Density')
29ie_air=vt.GetScalarField('Air::InternalEnergy')
30ie_dust=vt.GetScalarField('Dust::InternalEnergy')
31vfrac=vt.GetScalarField('Dust::PhaseVolumeFraction')
32
33# Plot the numerical results.
34# Note that we have divided the results by the reference velocity/pressure/density/internal energy to normalise them.
35# x is normalised by the reference length.
36pylab.figure(1)
37pylab.subplot(321)
38pylab.plot( x/0.0271002710027, p/1.013e5,'b.', label="Numerical")
39
40pylab.subplot(322)
41print len(x)
42print len(u_air)
43pylab.plot( x[:len(x)]/0.0271002710027, u_air/286.980353992,'b.', label="Numerical (Air)")
44pylab.plot( x[:len(x)]/0.0271002710027, u_dust/286.980353992,'r.', label="Numerical (Particles)")
45
46pylab.subplot(323)
47pylab.plot( x/0.0271002710027, rho_air/1.23,'b.', label="Numerical")
48
49pylab.subplot(324)
50pylab.plot( x/0.0271002710027, rho_dust,'b.', label="Numerical")
51pylab.title('Density of Particles')
52pylab.legend(loc=2)
53
54pylab.subplot(325)
55pylab.plot( x/0.0271002710027, ie_air/82357.7235772,'b.', label="Numerical (Air)")
56pylab.plot( x/0.0271002710027, ie_dust/82357.7235772,'r.', label="Numerical (Dust)")
57
58# Multiply the PhaseVolumeFraction by the Dust Density to get the mass concentration, and then normalise.
59pylab.subplot(326)
60pylab.plot( x/0.0271002710027, vfrac*2500.0/1.23,'b.', label="Numerical")
61pylab.title('Mass Concentration from PhaseVolumeFraction of Particles')
62pylab.legend(loc=2)
63
64# Now work out the frozen flow ('analytical') solutions
65sol=numpy.array([shocktube.solution(xi,4.0) for xi in x/0.0271002710027])
66p=sol[:,0]
67u=sol[:,1]
68rho=sol[:,2]
69ie=p/rho/(shocktube.gamma-1.0)
70
71pylab.subplot(321)
72pylab.plot( x/0.0271002710027, p,'-g', label='Frozen flow')
73pylab.title('Normalised Pressure')
74pylab.legend(loc=2)
75
76pylab.subplot(322)
77pylab.plot( x/0.0271002710027, u,'g-', label='Frozen flow (Air)')
78pylab.title('Normalised Velocity')
79pylab.legend(loc=2)
80
81pylab.subplot(323)
82pylab.plot( x/0.0271002710027, rho,'g-', label='Frozen flow')
83pylab.title('Normalised Density of Air')
84pylab.legend(loc=2)
85
86pylab.subplot(325)
87pylab.plot( x/0.0271002710027, ie,'g-', label='Frozen flow')
88pylab.title('Normalised Internal Energy of Air')
89pylab.legend(loc=2)
90
91pylab.savefig('mphase_dusty_gas_shock_tube.png')
92
93pylab.show()
094
=== added file 'tests/mphase_dusty_gas_shock_tube/shocktube.py'
--- tests/mphase_dusty_gas_shock_tube/shocktube.py 1970-01-01 00:00:00 +0000
+++ tests/mphase_dusty_gas_shock_tube/shocktube.py 2012-08-09 00:46:20 +0000
@@ -0,0 +1,157 @@
1# bit of python to compute analytical solution for the shock tube problem
2# solution taken from "Mathematical and Computational Methods for Compressible Flow"
3# by Miloslav Feistauer, Jiri Felcman and Ivan Straskraba, 2003
4# eqn numbers below refer to this books
5from math import sqrt
6from scipy.optimize import newton
7
8# ratio of specific heats
9gamma=1.4
10
11# left state:
12ul=0.
13rhol=10.0
14iel=2.5
15
16# right state:
17ur=0.
18rhor=1.0
19ier=2.5
20
21# this eos is assumed in the eqns below (so can't change this):
22def p_eos(ie, rho):
23 return rho*ie*(gamma-1.0)
24
25def rho_eos(ie, p):
26 return p/ie/(gamma-1.0)
27
28
29# derived quantities, left:
30pl=p_eos(iel,rhol)
31El=rhol*iel
32al=sqrt(gamma*pl/rhol)
33# derived quantities, right:
34pr=p_eos(ier,rhor)
35Er=rhor*ier
36ar=sqrt(gamma*pr/rhor)
37
38
39def F1l(p):
40 """Function F1l defines difference between us and ul:
41 us=ul+F1l(p) eqn. (3.1.159)"""
42
43 # eqn. (3.1.160)
44 if p<=pl:
45 return 2.*al/(gamma-1.)*(1.-(p/pl)**((gamma-1.)/(2.*gamma)))
46 else:
47 return -(p-pl)*sqrt((2./(gamma+1.)/rhol)/(p+(gamma-1.)/(gamma+1.)*pl))
48
49def F1lprime(p):
50 # derivative of the above
51 if p<=pl:
52 return -al/gamma*(p/pl)**((gamma-1.)/(2.*gamma)-1.)
53 else:
54 return -1.*sqrt((2./(gamma+1.)/rhol)/(p+(gamma-1.)/(gamma+1.)*pl)) + \
55 -(p-pl)/2./sqrt((2./(gamma+1.)/rhol)/(p+(gamma-1.)/(gamma+1.)*pl))
56
57def F3r(p):
58 """Function F3r defines difference between us and ur:
59 us=ur+F3r(p) eqn. (3.1.161)"""
60
61 # eqn. (3.1.162)
62 if p<=pr:
63 return -2.*ar/(gamma-1.)*(1.-(p/pr)**((gamma-1.)/(2.*gamma)))
64 else:
65 return (p-pr)*sqrt((2./(gamma+1.)/rhor)/(p+(gamma-1.)/(gamma+1.)*pr))
66
67def F3rprime(p):
68 # derivative of the above
69 if p<=pr:
70 return ar/gamma*(p/pr)**((gamma-1.)/(2.*gamma)-1.)
71 else:
72 return sqrt((2./(gamma+1.)/rhor)/(p+(gamma-1.)/(gamma+1.)*pr)) + \
73 (p-pr)/2./sqrt((2./(gamma+1.)/rhor)/(p+(gamma-1.)/(gamma+1.)*pr))
74
75def F(p):
76 # eqn (3.1.165)
77 return F3r(p)-F1l(p)+ur-ul
78
79def Fprime(p):
80 return F3rprime(p)-F1lprime(p)
81
82# inital guess:
83p=(pl+pr)/2.
84
85# solve eqn (3.1.164): F(p*)=0, to find p* the pressure between the u-a and u+a waves
86# (is constant over contact discontinuity at the u wave)
87ps=newton(F, p, fprime=Fprime, maxiter=500)
88print "should be zero: F(p*) = ", F(ps)
89print "p* =", ps
90us=ul+F1l(ps)
91print "u* =", us
92print "should be equal to:", ur+F3r(ps)
93
94# the star region is divide by the contact discontinuity which gives a discontinuity in
95# density rhosl/rhosr and internal energy iesl/iesr
96
97# left:
98if ps<pl: # rarefaction
99 rhosl=rhol*(ps/pl)**(1/gamma) # eqn (3.1.172)
100else: # shock
101 rhosl=rhol*( (gamma-1.)/(gamma+1.)*pl/ps +1. )/(pl/ps+(gamma-1.)/(gamma+1.)) # eqn (3.1.176)
102 s1=ul-al*sqrt((gamma+1.)/2./gamma*ps/pl + (gamma-1.)/2./gamma) # shock speed, eqn (3.1.177)
103iesl=ps/rhosl/(gamma-1.)
104asl=sqrt(gamma*ps/rhosl)
105
106# right:
107if ps<pr: # rarefaction
108 rhosr=rhor*(ps/pr)**(1/gamma) # eqn (3.1.178)
109else: # shock
110 rhosr=rhor*( ps/pr + (gamma-1.)/(gamma+1.) )/( (gamma-1.)/(gamma+1.)*ps/pr +1. ) # eqn (3.1.182)
111 s3=ur+ar*sqrt((gamma+1.)/2./gamma*ps/pr + (gamma-1.)/2./gamma) # shock speed, eqn (3.1.183)
112iesr=ps/rhosr/(gamma-1.)
113asr=sqrt(gamma*pr/rhosr)
114
115def solution(x,t):
116 if x/t<us:
117 # before the contact discontinuity:
118
119 if ps<pl:
120 # u-a is a rarefaction wave
121 if x/t<ul-al: # left
122 return (pl, ul, rhol)
123 elif x/t<us-asl: # within the rarefaction wave
124 p=pl*(2./(gamma+1.) + (gamma-1.)/(gamma+1.)/al*(ul-x/t))**(2*gamma/(gamma-1.)) # eqn (3.1.97)
125 u=2./(gamma+1.)*(al + (gamma-1.)/2.*ul + x/t) # eqn (3.1.97)
126 rho=rhol*(2./(gamma+1.) + (gamma-1.)/(gamma+1.)/al*(ul-x/t))**(2./(gamma-1.)) # eqn (3.1.97)
127 return (p, u, rho)
128 else: # after the rarefaction before the contact disc.
129 return (ps,us,rhosl)
130 else:
131 # u-a is a shock wave
132 if x/t<s1: # left
133 return (pl, ul, rhol)
134 else: # between u-a shock and contact disc.
135 return (psl, us, rhosl)
136
137 else:
138 # after the contact discontinuity:
139
140 if ps<pr:
141 # u+a is a rarefaction wave
142 if x/t>ur+ar: # right
143 return (pr, ur, rhor)
144 elif x/t>usr+asr: # within the rarefaction wave
145 p=pr*(2./(gamma+1.) + (gamma-1.)/(gamma+1.)/ar*(ur-x/t))**(2*gamma/(gamma-1.)) # eqn (3.1.98)
146 u=2./(gamma+1.)*(-ar + (gamma-1.)/2.*ur + x/t) # eqn (3.1.98)
147 rho=rhor*(2./(gamma+1.) - (gamma-1.)/(gamma+1.)/ar*(ur-x/t))**(2./(gamma-1.)) # eqn (3.1.98)
148 return (p, u, rho)
149 else: # after the contact disc. before the rarefaction
150 return (ps,us, rhosr)
151 else:
152 # u+a is a shock wave
153 if x/t>s3: # right
154 return (pr, ur, rhor)
155 else: # between contact disc. and u-a shock
156 return (ps, us, rhosr)
157
0158
=== added file 'tests/mphase_dusty_gas_shock_tube/single_phase_frozen_flow_test.flml'
--- tests/mphase_dusty_gas_shock_tube/single_phase_frozen_flow_test.flml 1970-01-01 00:00:00 +0000
+++ tests/mphase_dusty_gas_shock_tube/single_phase_frozen_flow_test.flml 2012-08-09 00:46:20 +0000
@@ -0,0 +1,379 @@
1<?xml version='1.0' encoding='utf-8'?>
2<fluidity_options>
3 <simulation_name>
4 <string_value lines="1">single_phase_frozen_flow_test</string_value>
5 </simulation_name>
6 <problem_type>
7 <string_value lines="1">fluids</string_value>
8 </problem_type>
9 <geometry>
10 <dimension>
11 <integer_value rank="0">1</integer_value>
12 </dimension>
13 <mesh name="CoordinateMesh">
14 <from_file file_name="line">
15 <format name="triangle"/>
16 <stat>
17 <include_in_stat/>
18 </stat>
19 </from_file>
20 </mesh>
21 <mesh name="VelocityMesh">
22 <from_mesh>
23 <mesh name="CoordinateMesh"/>
24 <mesh_shape>
25 <polynomial_degree>
26 <integer_value rank="0">1</integer_value>
27 </polynomial_degree>
28 </mesh_shape>
29 <stat>
30 <exclude_from_stat/>
31 </stat>
32 </from_mesh>
33 </mesh>
34 <mesh name="PressureMesh">
35 <from_mesh>
36 <mesh name="CoordinateMesh"/>
37 <mesh_shape>
38 <polynomial_degree>
39 <integer_value rank="0">1</integer_value>
40 </polynomial_degree>
41 </mesh_shape>
42 <stat>
43 <exclude_from_stat/>
44 </stat>
45 </from_mesh>
46 </mesh>
47 <mesh name="DensityMesh">
48 <from_mesh>
49 <mesh name="CoordinateMesh"/>
50 <mesh_shape>
51 <polynomial_degree>
52 <integer_value rank="0">1</integer_value>
53 </polynomial_degree>
54 </mesh_shape>
55 <stat>
56 <exclude_from_stat/>
57 </stat>
58 </from_mesh>
59 </mesh>
60 <quadrature>
61 <degree>
62 <integer_value rank="0">5</integer_value>
63 </degree>
64 </quadrature>
65 </geometry>
66 <io>
67 <dump_format>
68 <string_value>vtk</string_value>
69 </dump_format>
70 <dump_period>
71 <constant>
72 <real_value rank="0">0.0</real_value>
73 </constant>
74 </dump_period>
75 <output_mesh name="VelocityMesh"/>
76 <stat>
77 <output_at_start/>
78 </stat>
79 </io>
80 <timestepping>
81 <current_time>
82 <real_value rank="0">0.0</real_value>
83 </current_time>
84 <timestep>
85 <real_value rank="0">0.000001</real_value>
86 </timestep>
87 <finish_time>
88 <real_value rank="0">0.00037772998222</real_value>
89 <comment>This corresponds to a non-dimensional time of tau = 4. Multiplying this by the reference time of l/u_ref gives 0.00037772998222 seconds.
90
91l = (4/3)*(rho_p/rho_g)*d
92u_ref = sqrt(p/rho_g)</comment>
93 </finish_time>
94 <nonlinear_iterations>
95 <integer_value rank="0">3</integer_value>
96 <tolerance>
97 <real_value rank="0">1.0e-9</real_value>
98 <infinity_norm/>
99 </tolerance>
100 </nonlinear_iterations>
101 </timestepping>
102 <material_phase name="Air">
103 <equation_of_state>
104 <compressible>
105 <stiffened_gas>
106 <ratio_specific_heats>
107 <real_value rank="0">1.4</real_value>
108 </ratio_specific_heats>
109 </stiffened_gas>
110 </compressible>
111 </equation_of_state>
112 <scalar_field name="Pressure" rank="0">
113 <prognostic>
114 <mesh name="PressureMesh"/>
115 <spatial_discretisation>
116 <continuous_galerkin>
117 <remove_stabilisation_term/>
118 </continuous_galerkin>
119 </spatial_discretisation>
120 <scheme>
121 <poisson_pressure_solution>
122 <string_value lines="1">never</string_value>
123 </poisson_pressure_solution>
124 <use_compressible_projection_method/>
125 </scheme>
126 <solver>
127 <iterative_method name="preonly"/>
128 <preconditioner name="lu"/>
129 <relative_error>
130 <real_value rank="0">1e-7</real_value>
131 </relative_error>
132 <max_iterations>
133 <integer_value rank="0">10000</integer_value>
134 </max_iterations>
135 <never_ignore_solver_failures/>
136 <diagnostics>
137 <monitors/>
138 </diagnostics>
139 </solver>
140 <output/>
141 <stat/>
142 <convergence>
143 <include_in_convergence/>
144 </convergence>
145 <detectors>
146 <exclude_from_detectors/>
147 </detectors>
148 <steady_state>
149 <include_in_steady_state/>
150 </steady_state>
151 <no_interpolation/>
152 </prognostic>
153 </scalar_field>
154 <scalar_field name="Density" rank="0">
155 <prognostic>
156 <mesh name="PressureMesh"/>
157 <spatial_discretisation>
158 <continuous_galerkin>
159 <stabilisation>
The diff has been truncated for viewing.