Merge lp:~fluidity-core/fluidity/darcy_impes_proper into lp:fluidity
- darcy_impes_proper
- Merge into dev-trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~fluidity-core/fluidity/darcy_impes_proper |
Merge into: | lp:fluidity |
Diff against target: |
272198 lines (+267531/-1508) 278 files modified
Makefile.in (+13/-4) assemble/Darcy_IMPES_Assemble.F90 (+5920/-0) assemble/Makefile.dependencies (+19/-0) assemble/Makefile.in (+1/-1) assemble/Petsc_Solve_State.F90 (+53/-1) error_measures/Metric_advection.F90 (+9/-1) examples/flow_past_sphere_Re1/unit_sphere.ele (+130208/-0) examples/flow_past_sphere_Re1/unit_sphere.face (+11294/-0) examples/flow_past_sphere_Re1/unit_sphere.node (+24975/-0) femtools/Boundary_Conditions.F90 (+95/-12) femtools/CV_Face_Values.F90 (+2/-1) femtools/CV_Options.F90 (+2/-1) femtools/Petsc_Tools.F90 (+108/-3) femtools/Solvers.F90 (+120/-11) femtools/Sparse_Tools_Petsc.F90 (+24/-1) femtools/Transform_elements.F90 (+15/-1) main/Darcy_IMPES.F90 (+2221/-0) main/Makefile.dependencies (+25/-0) manual/configuring_fluidity.tex (+1/-2) manual/model_equations.tex (+1/-1) preprocessor/Boundary_Conditions_From_Options.F90 (+7/-5) preprocessor/Populate_State.F90 (+234/-33) schemas/adaptivity_options.rnc (+902/-739) schemas/adaptivity_options.rng (+612/-545) schemas/darcy_impes_options.rnc (+2386/-0) schemas/darcy_impes_options.rng (+2499/-0) schemas/porous_media.rnc (+4/-4) schemas/porous_media.rng (+4/-4) tests/darcy_impes_common/Depend.mk (+18/-0) tests/darcy_impes_common/batch_tools.py (+186/-0) tests/darcy_impes_common/buckley_leverett_test_tools.py (+312/-0) tests/darcy_impes_common/manufactured_solution_generation_tools.py (+222/-0) tests/darcy_impes_common/manufactured_solution_test_tools.py (+393/-0) tests/darcy_impes_common/mesh_data/cube_A.geo (+41/-0) tests/darcy_impes_common/mesh_data/cube_A.msh (+524/-0) tests/darcy_impes_common/mesh_data/cube_B.geo (+41/-0) tests/darcy_impes_common/mesh_data/cube_B.msh (+1014/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_A.bound (+4/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_A.ele (+12/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_A.node (+13/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_B.bound (+4/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_B.ele (+22/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_B.node (+23/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_C.bound (+4/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_C.ele (+42/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_C.node (+43/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_D.bound (+4/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_D.ele (+82/-0) tests/darcy_impes_common/mesh_data/line_mesh_1d_D.node (+83/-0) tests/darcy_impes_common/mesh_data/square_A.geo (+30/-0) tests/darcy_impes_common/mesh_data/square_A.msh (+106/-0) tests/darcy_impes_common/mesh_data/square_B.geo (+30/-0) tests/darcy_impes_common/mesh_data/square_B.msh (+196/-0) tests/darcy_impes_common/mesh_data/square_C.geo (+30/-0) tests/darcy_impes_common/mesh_data/square_C.msh (+376/-0) tests/darcy_impes_common/mesh_data/template_cuboid_irreg.geo (+51/-0) tests/darcy_impes_common/mesh_data/template_cuboid_reg.geo (+26/-0) tests/darcy_impes_common/mesh_data/template_line.sh (+1/-0) tests/darcy_impes_common/mesh_data/template_rectangle_irreg.geo (+20/-0) tests/darcy_impes_common/mesh_data/template_rectangle_reg.geo (+19/-0) tests/darcy_impes_common/test_tools.py (+412/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/Makefile (+62/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/darcy_impes_mms_p1_2phase_coreyrelperm.py (+99/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/darcy_impes_mms_p1_2phase_coreyrelperm.xml (+51/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/processing.py (+60/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/solution_generator.py (+82/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/template_darcy_impes_mms_p1_2phase_coreyrelperm.diml (+616/-0) tests/darcy_impes_mms_p1_2phase_coreyrelperm/template_darcy_impes_mms_p1_2phase_coreyrelperm_velbc.diml (+609/-0) tests/darcy_impes_mms_p1_2phase_quadraticrelperm/Makefile (+62/-0) tests/darcy_impes_mms_p1_2phase_quadraticrelperm/darcy_impes_mms_p1_2phase_quadraticrelperm.py (+93/-0) tests/darcy_impes_mms_p1_2phase_quadraticrelperm/darcy_impes_mms_p1_2phase_quadraticrelperm.xml (+83/-0) tests/darcy_impes_mms_p1_2phase_quadraticrelperm/processing.py (+54/-0) tests/darcy_impes_mms_p1_2phase_quadraticrelperm/solution_generator.py (+76/-0) tests/darcy_impes_mms_p1_2phase_quadraticrelperm/template_darcy_impes_mms_p1_2phase_quadraticrelperm.diml (+619/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/Makefile (+40/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag.xml (+630/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_A.diml (+498/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_A.diml (+510/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_3d_A.diml (+510/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_A.diml (+493/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_A.diml (+505/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_3d_A.diml (+505/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/processing.py (+17/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/analytic_BL_CoreyPerm_saturation2.txt (+480/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_A_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_B_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_C_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_D_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_A_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_B_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_C_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_3d_A_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_3d_B_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_A_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_B_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_C_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_D_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_A_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_B_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_C_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_3d_A_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_3d_B_1.vtu (+53/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive/Makefile (+34/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive.xml (+105/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive_relpermupwind_2d_A.diml (+611/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive/mesh_data/square_A.geo (+30/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive/mesh_data/square_A.msh (+106/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_adaptive/reference_solution/analytic_BL_CoreyPerm_saturation2.txt (+480/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel/Makefile (+36/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel.xml (+105/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel_relpermupwind_2d_A.diml (+548/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel/mesh_data/square_A.geo (+30/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_parallel/reference_solution/analytic_BL_CoreyPerm_saturation2.txt (+480/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle/Makefile (+34/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle.xml (+114/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle_relpermupwind_2d_A.diml (+561/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle/mesh_data/square_A.geo (+30/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle/reference_solution/analytic_BL_CoreyPerm_saturation2.txt (+480/-0) tests/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle/reference_solution/darcy_impes_p1_2phase_coreyrelperm_velBCinlet_strongpressoutlet_p1satdiag_subcycle_relpermupwind_2d_A_1.vtu (+52/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/Makefile (+41/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag.xml (+823/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_A.diml (+561/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_A.diml (+573/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_3d_A.diml (+573/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_A.diml (+556/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_A.diml (+568/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_3d_A.diml (+568/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/processing.py (+16/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/analytic_BL_QuadraticPerm_pressure2.txt (+299/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/analytic_BL_QuadraticPerm_saturation2.txt (+345/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_A_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_B_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_C_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_1d_D_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_A_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_B_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_2d_C_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_3d_A_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_modrelpermupwind_satfesweby_3d_B_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_A_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_B_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_C_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_1d_D_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_A_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_B_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_2d_C_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_3d_A_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_p1satdiag_relpermupwind_3d_B_1.vtu (+57/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/Makefile (+41/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip.xml (+767/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_1d_A.diml (+552/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_2d_A.diml (+563/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_3d_A.diml (+563/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_1d_A.diml (+547/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_2d_A.diml (+558/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_3d_A.diml (+558/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/processing.py (+16/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/analytic_BL_QuadraticPerm_nogravity_saturation2.txt (+633/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/analytic_BL_QuadraticPerm_withgravity_updip_saturation2.txt (+605/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_1d_A_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_1d_B_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_1d_C_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_1d_D_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_2d_A_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_2d_B_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_2d_C_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_3d_A_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_modrelpermupwind_satfesweby_3d_B_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_1d_A_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_1d_B_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_1d_C_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_1d_D_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_2d_A_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_2d_B_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_2d_C_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_3d_A_1.vtu (+56/-0) tests/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip/reference_solution/darcy_impes_p1_2phase_quadraticrelperm_velBCinlet_strongpressoutlet_withgravity_updip_relpermupwind_3d_B_1.vtu (+56/-0) tests/darcy_impes_p1_3phase_layered/Makefile (+40/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered.xml (+1201/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered_modrelpermupwind_satfesweby_1d.diml (+744/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered_modrelpermupwind_satfesweby_2d.diml (+744/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered_modrelpermupwind_satfesweby_3d.diml (+746/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered_relpermupwind_1d.diml (+739/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered_relpermupwind_2d.diml (+739/-0) tests/darcy_impes_p1_3phase_layered/darcy_impes_p1_3phase_layered_relpermupwind_3d.diml (+741/-0) tests/darcy_impes_p1_3phase_layered/mesh_data/cube.geo (+43/-0) tests/darcy_impes_p1_3phase_layered/mesh_data/cube.msh (+4665/-0) tests/darcy_impes_p1_3phase_layered/mesh_data/square.geo (+31/-0) tests/darcy_impes_p1_3phase_layered/mesh_data/square.msh (+385/-0) tests/darcy_impes_p1_3phase_layered/reference_solution/darcy_impes_p1_3phase_layered_modrelpermupwind_satfesweby_1d_1.vtu (+365/-0) tests/darcy_impes_p1_3phase_layered/reference_solution/darcy_impes_p1_3phase_layered_modrelpermupwind_satfesweby_2d_1.vtu (+1665/-0) tests/darcy_impes_p1_3phase_layered/reference_solution/darcy_impes_p1_3phase_layered_modrelpermupwind_satfesweby_3d_1.vtu (+13792/-0) tests/darcy_impes_p1_3phase_layered/reference_solution/darcy_impes_p1_3phase_layered_relpermupwind_1d_1.vtu (+365/-0) tests/darcy_impes_p1_3phase_layered/reference_solution/darcy_impes_p1_3phase_layered_relpermupwind_2d_1.vtu (+1665/-0) tests/darcy_impes_p1_3phase_layered/reference_solution/darcy_impes_p1_3phase_layered_relpermupwind_3d_1.vtu (+13792/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/Makefile (+40/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/darcy_impes_p1_pseudo1phase_pressBCinlet.xml (+439/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/darcy_impes_p1_pseudo1phase_pressBCinlet_1d.diml (+517/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/darcy_impes_p1_pseudo1phase_pressBCinlet_2d.diml (+529/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/darcy_impes_p1_pseudo1phase_pressBCinlet_3d.diml (+529/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/mesh_data/cube.geo (+43/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/mesh_data/cube.msh (+4665/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/mesh_data/square.geo (+31/-0) tests/darcy_impes_p1_pseudo1phase_pressBCinlet/mesh_data/square.msh (+385/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/Makefile (+35/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/darcy_impes_p1_pseudo1phase_velBCinlet.xml (+472/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/darcy_impes_p1_pseudo1phase_velBCinlet_1d.diml (+613/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/darcy_impes_p1_pseudo1phase_velBCinlet_2d.diml (+625/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/darcy_impes_p1_pseudo1phase_velBCinlet_3d.diml (+625/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/cube.geo (+43/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/cube.msh (+4665/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/darcy_impes_p1_pseudo1phase_velBCinlet_1d.bound (+4/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/darcy_impes_p1_pseudo1phase_velBCinlet_1d.ele (+22/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/darcy_impes_p1_pseudo1phase_velBCinlet_1d.node (+23/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/square.geo (+31/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/mesh_data/square.msh (+385/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/reference_solution/darcy_impes_p1_pseudo1phase_velBCinlet_1d_1.vtu (+55/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/reference_solution/darcy_impes_p1_pseudo1phase_velBCinlet_2d_1.vtu (+55/-0) tests/darcy_impes_p1_pseudo1phase_velBCinlet/reference_solution/darcy_impes_p1_pseudo1phase_velBCinlet_3d_1.vtu (+58/-0) tests/darcy_p0p1_test_cty_cv_pressBCinlet/darcy_p0p1_test_cty_cv_pressBCinlet_1d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet/darcy_p0p1_test_cty_cv_pressBCinlet_3d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p0_steptwochannel/advect_tracer_cons_exp_weakbc_upwind_p0_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p0_steptwochannel/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cg/advect_tracer_cons_imp_p1cg_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cg/advect_tracer_cons_imp_p1cg_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cg/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cg/darcy_p0p1_test_cty_cv_pressBCinlet_3d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_exp_weakbc_feultimate_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_exp_weakbc_feultimate_p1cv_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_exp_weakbc_hyperc_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_exp_weakbc_hyperc_p1cv_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_exp_weakbc_upwind_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_exp_weakbc_upwind_p1cv_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_imp_weakbc_fesweby_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_imp_weakbc_fesweby_p1cv_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_imp_weakbc_upwind_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/advect_tracer_cons_imp_weakbc_upwind_p1cv_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv/darcy_p0p1_test_cty_cv_pressBCinlet_3d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv_steptwochannel/advect_tracer_cons_exp_weakbc_hyperc_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv_steptwochannel/advect_tracer_cons_exp_weakbc_upwind_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv_steptwochannel/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv_steptwochannel_adaptive/advect_tracer_cons_exp_weakbc_hyperc_p1cv_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1cv_steptwochannel_adaptive/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1dg/advect_tracer_cons_imp_p1dg_2d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1dg/advect_tracer_cons_imp_p1dg_3d.flml (+1/-1) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1dg/darcy_p0p1_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_advect_tracer_p1dg/darcy_p0p1_test_cty_cv_pressBCinlet_3d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_pressBCinlet_rotated_domain/darcy_p0p1_test_cty_cv_pressBCinlet_rotated_domain_2d.flml (+2/-2) tests/darcy_p0p1_test_cty_cv_velBCinlet/darcy_p0p1_test_cty_cv_velBCinlet_1d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_velBCinlet/darcy_p0p1_test_cty_cv_velBCinlet_2d.flml (+3/-3) tests/darcy_p0p1_test_cty_cv_velBCinlet/darcy_p0p1_test_cty_cv_velBCinlet_3d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet/darcy_p0p1cv_pressBCinlet_1d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet/darcy_p0p1cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet/darcy_p0p1cv_pressBCinlet_3d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet_1solidphase/darcy_p0p1cv_pressBCinlet_1solidphase_1d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet_1solidphase/darcy_p0p1cv_pressBCinlet_1solidphase_2d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet_1solidphase/darcy_p0p1cv_pressBCinlet_1solidphase_3d.flml (+3/-3) tests/darcy_p0p1cv_pressBCinlet_rotated_domain/darcy_p0p1cv_pressBCinlet_rotated_domain_2d.flml (+2/-2) tests/darcy_p0p1cv_velBCinlet/darcy_p0p1cv_velBCinlet_1d.flml (+3/-3) tests/darcy_p0p1cv_velBCinlet/darcy_p0p1cv_velBCinlet_2d.flml (+2/-2) tests/darcy_p0p1cv_velBCinlet/darcy_p0p1cv_velBCinlet_3d.flml (+3/-3) tests/darcy_p0p1cv_velBCinlet_1solidphase/darcy_p0p1cv_velBCinlet_1solidphase_1d.flml (+3/-3) tests/darcy_p0p1cv_velBCinlet_1solidphase/darcy_p0p1cv_velBCinlet_1solidphase_2d.flml (+3/-3) tests/darcy_p0p1cv_velBCinlet_1solidphase/darcy_p0p1cv_velBCinlet_1solidphase_3d.flml (+3/-3) tests/darcy_p0p1cv_velBCinlet_rotated_domain/darcy_p0p1cv_velBCinlet_rotated_domain_2d.flml (+2/-2) tests/darcy_p1dgp2_pressBCinlet/darcy_p1dgp2_pressBCinlet_1d.flml (+3/-3) tests/darcy_p1dgp2_pressBCinlet/darcy_p1dgp2_pressBCinlet_2d.flml (+5/-5) tests/darcy_p1dgp2_pressBCinlet/darcy_p1dgp2_pressBCinlet_3d.flml (+5/-5) tests/darcy_p1dgp2_test_cty_cv_pressBCinlet/darcy_p1dgp2_test_cty_cv_pressBCinlet_2d.flml (+3/-3) tests/darcy_p1dgp2_test_cty_cv_pressBCinlet/darcy_p1dgp2_test_cty_cv_pressBCinlet_3d.flml (+3/-3) tests/darcy_p1dgp2_velBCinlet/darcy_p1dgp2_velBCinlet_1d.flml (+3/-3) tests/darcy_p1dgp2_velBCinlet/darcy_p1dgp2_velBCinlet_2d.flml (+3/-3) tests/darcy_p1dgp2_velBCinlet/darcy_p1dgp2_velBCinlet_3d.flml (+3/-3) tests/electrochemical_p1p1_2d/electrochemical.flml (+2/-2) tests/electrokinetic_p1p1_2d/electrokinetic.flml (+2/-2) tests/electrothermal_p1p1_2d/electrothermal.flml (+2/-2) |
To merge this branch: | bzr merge lp:~fluidity-core/fluidity/darcy_impes_proper |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Robert Percival | Pending | ||
Review via email:
|
Commit message
Description of the change
The darcy_impes program solves multiphase flow through porous media using an implicit pressure, explicit saturation (IMPES) method. See, for example, Mostaghini P., Tollit B.S., Neethling S.J., Gorman G.J. and Pain C.C., A control volume finite element method for adaptive mesh simulation of flow in heap leaching, J Eng Math, 1--11, 2013.
The test/darcy_
Brendan Tollit (btollit) implemented an extensive coverage of the three types of test, to which I have made a few changes. The general idea is to promote analytical comparisons over regression tests (or implement the latter only where analytical solutions are not available), since the regression solutions are sensitive to e.g. mesh design and are not guaranteed to be correct. It is intended that analytical tests will eventually come to replace regression tests, although I have erred on the side of caution and not deleted regression tests at this stage.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Richard Ferrier (rjferrier) wrote : | # |
Good point Stephen. I had completely missed the Tarantula folders. I will have a look and see what can be done with them. It will probably need discussion with Peyman who is on leave at the moment.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
James Robert Percival (j-percival) wrote : | # |
It appears that neither directory actually contains a test (in the test harness sense) at the moment anyway. As a secondary part of the question of the trunk merge, I note that the darcy solver gets built as default by the root makefile. Other similar codes (e.g. Colin Cotter's shallow water code) are only built if requested, or if the code is being tested.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerard (g-gorman) wrote : | # |
Hi Richards
Can I suggest that you create a new branch to cache this tarantula work (call it tarantula), and then delete it entirely from the Darcy branch.
Cheers
Gerard
On 24 Feb 2014, at 15:06, Stephan Kramer <email address hidden> wrote:
> Hello, only had a quick look at this merge. Most code changes to code shared with fluidity seem reasonable at first glance.
>
> I have some worries about the need to add this to trunk Fluidity, in terms of maintainability, etc. but these are probably better discussed in another forum.
>
> The main problem at the moment is that this merge seems to add about 150M to a clean checkout (current checkout size is 300M). The main cause of this seem to be the tests/Tarantula
> --
> https:/
> Your team Fluidity Core Team is subscribed to branch lp:fluidity.
- 4136. By Richard Ferrier
-
Default building of darcy_impes binary removed from the root Makefile. The 3phase test folder's meshes had not been checked into R4133 (oops); they are herewith restored. This will be the last revision to contain the Tarantula test folders, deemed to bulky/experimental to include in the proposed merge. A new development branch will be created to keep those folders.
- 4137. By Richard Ferrier
-
Tarantula folders deleted.
- 4138. By Richard Ferrier
-
Makefile was still buggy, trying to test before the binary had been built. Fixed it and added a diagnostic line to the python script.
- 4139. By Richard Ferrier
-
Refactored python code in preparation for tests based on the method of manufactured solutions (MMS). Previously the code was littered with nested for-loops to iterate over various simulation options, error norms and convergence rates. This situation onlys worsens with MMS-based tests. The current revision therefore replaces the loops with handling trees that can be composed at run-time to suit the context. The trees are passed command objects encapsulating operations at various levels. These Handler classes and abstract Command class have been placed in test_tools.py. The classes are used in buckley_
leverett_ test_tools. py (replacing darcy_impes_ tools.py) and will be used in manufactured_ solution_ test_tools. py. - 4140. By Richard Ferrier
-
Corrected commented-out line that was breaking a test
- 4141. By Richard Ferrier
-
Added manufactured_
solution_ test_tools. py; split up test_tools.py to reflect general-purpose and problem-specific classes - 4142. By Richard Ferrier
-
Added the first MMS-based test (the harness will be added shortly). Parameters may be adjusted in due course.
- 4143. By Richard Ferrier
-
Added code for generating the XML file and cleaning up.
- 4144. By Richard Ferrier
-
Forgot to add geometry templates to the previous two revisions; these are now in place. Fixed some scripting bugs that were breaking tests.
- 4145. By Richard Ferrier
-
Geometry templates really checked in this time\!
- 4146. By Richard Ferrier
-
Minor changes, adding functionality to support factorial experiments where physical variables are controlled.
- 4147. By Richard Ferrier
-
Continuing the changes of the last revision, generation of symbolic expressions is now done within ManufacturedSol
utionTestSuite. Also, WriteXMLSnippet has been replaced by WriteXMLFile to allow multiple solution-dependent XML files to be generated. - 4148. By Richard Ferrier
-
Fixed XML inconsistency with schema. Adjusted symbolic expressions to work when generated by a different version of sympy (this generation is not triggered by the test harness, however).
- 4149. By Richard Ferrier
-
Tweak to the Makefile in darcy_impes_
mms_p1_ 2phase_ quadraticrelper m - 4150. By Richard Ferrier
-
Added another MMS-based test.
- 4151. By Richard Ferrier
-
Edited the tests to work around a problem with spatial convergence of the pressure field. The nonconvergence is caused by the pressure fields reconfiguring themselves to be completely different to the forced solution at certain levels of mesh and timestep refinement. This effect has appeared since introducing more timesteps into the tests to make them more rigorous. Saturation fields appear to be unaffected, and they will continue to be used in checking convergence. Note the necessary change of minus sign on diff(phi*self.s[i], t) in darcy_impes_
common/ manufactured_ solution_ generation_ tools.py. The now-transient tests break otherwise. - 4152. By Richard Ferrier
-
Merge with fluidity trunk.
- 4153. By Richard Ferrier
-
Minor changes.
- 4154. By Richard Ferrier
-
Merge with fluidity trunk.
Unmerged revisions
- 4154. By Richard Ferrier
-
Merge with fluidity trunk.
- 4153. By Richard Ferrier
-
Minor changes.
- 4152. By Richard Ferrier
-
Merge with fluidity trunk.
- 4151. By Richard Ferrier
-
Edited the tests to work around a problem with spatial convergence of the pressure field. The nonconvergence is caused by the pressure fields reconfiguring themselves to be completely different to the forced solution at certain levels of mesh and timestep refinement. This effect has appeared since introducing more timesteps into the tests to make them more rigorous. Saturation fields appear to be unaffected, and they will continue to be used in checking convergence. Note the necessary change of minus sign on diff(phi*self.s[i], t) in darcy_impes_
common/ manufactured_ solution_ generation_ tools.py. The now-transient tests break otherwise. - 4150. By Richard Ferrier
-
Added another MMS-based test.
- 4149. By Richard Ferrier
-
Tweak to the Makefile in darcy_impes_
mms_p1_ 2phase_ quadraticrelper m - 4148. By Richard Ferrier
-
Fixed XML inconsistency with schema. Adjusted symbolic expressions to work when generated by a different version of sympy (this generation is not triggered by the test harness, however).
- 4147. By Richard Ferrier
-
Continuing the changes of the last revision, generation of symbolic expressions is now done within ManufacturedSol
utionTestSuite. Also, WriteXMLSnippet has been replaced by WriteXMLFile to allow multiple solution-dependent XML files to be generated. - 4146. By Richard Ferrier
-
Minor changes, adding functionality to support factorial experiments where physical variables are controlled.
- 4145. By Richard Ferrier
-
Geometry templates really checked in this time\!
Preview Diff
1 | === modified file 'Makefile.in' |
2 | --- Makefile.in 2013-12-13 16:00:27 +0000 |
3 | +++ Makefile.in 2014-05-30 12:10:35 +0000 |
4 | @@ -185,6 +185,7 @@ |
5 | sw: bin/shallow_water |
6 | be: bin/burgers_equation |
7 | hh: bin/hybridized_helmholtz_solver |
8 | +di: bin/darcy_impes |
9 | |
10 | bin/shallow_water: fluidity_library bin/hybridized_helmholtz_solver main/Shallow_Water.F90 |
11 | @cd main; $(MAKE) Shallow_Water.o |
12 | @@ -211,6 +212,14 @@ |
13 | @echo " LD burgers_equation" |
14 | @$(EVAL) $(FC) -o bin/burgers_equation main/Burgers_Equation.o $(FCFLAGS) $(LIBS) |
15 | |
16 | +bin/darcy_impes: fluidity_library main/Darcy_IMPES.F90 |
17 | + @cd main; $(MAKE) Darcy_IMPES.o |
18 | + @echo "BUILD darcy_impes" |
19 | + @echo " MKDIR bin" |
20 | + @mkdir -p bin |
21 | + @echo " LD darcy_impes" |
22 | + @$(EVAL) $(FC) -o bin/darcy_impes main/Darcy_IMPES.o $(FCFLAGS) $(LIBS) |
23 | + |
24 | ifeq (@ENABLE_PSMILE@,yes) |
25 | LIBPSMILE=@FLPSMILE_PATH@/lib/libpsmile_oa4.MPI1.a @FLPSMILE_PATH@/lib/libcommon_oa4.a @FLPSMILE_PATH@/lib/libmpp_io.a -lxml2 |
26 | bin/test_coupler: fluidity_library main/test_coupler.F90 |
27 | @@ -498,12 +507,12 @@ |
28 | @find ./ \( -name make.log \) -exec rm -f {} \; > /dev/null |
29 | @rm -f Makefile > /dev/null |
30 | |
31 | -test: fltools bin/$(FLUIDITY) bin/shallow_water serialtest bin/burgers_equation |
32 | +test: fltools bin/$(FLUIDITY) bin/shallow_water bin/darcy_impes serialtest bin/burgers_equation |
33 | |
34 | -serialtest: fltools bin/$(FLUIDITY) bin/shallow_water |
35 | +serialtest: fltools bin/$(FLUIDITY) bin/shallow_water bin/darcy_impes |
36 | @cd tests; ../bin/testharness -l short $(EXCLUDE_TAGS) -n $(THREADS) |
37 | |
38 | -mediumtest: fltools bin/$(FLUIDITY) manual bin/burgers_equation bin/shallow_water spudtools |
39 | +mediumtest: fltools bin/$(FLUIDITY) manual bin/burgers_equation bin/shallow_water bin/darcy_impes spudtools |
40 | @cd tests; ../bin/testharness -l medium $(EXCLUDE_TAGS) -n $(THREADS) |
41 | |
42 | .PHONY: spudtools |
43 | @@ -607,7 +616,7 @@ |
44 | $(MAKE) clean-light |
45 | @echo " Congratulations, make makefiles succeeded!" |
46 | |
47 | -install: default fltools bin/shallow_water bin/burgers_equation |
48 | +install: default fltools bin/shallow_water bin/burgers_equation bin/darcy_impes |
49 | @mkdir -p $(DESTDIR)$(bindir) $(DESTDIR)$(docdir)/fluidity |
50 | find bin/ -maxdepth 1 -type f -exec cp '{}' $(DESTDIR)$(bindir) \; |
51 | rm -f $(DESTDIR)$(bindir)/spud-* $(DESTDIR)$(bindir)/diamond $(DESTDIR)$(bindir)/silenteval $(DESTDIR)$(bindir)/runut |
52 | |
53 | === added file 'assemble/Darcy_IMPES_Assemble.F90' |
54 | --- assemble/Darcy_IMPES_Assemble.F90 1970-01-01 00:00:00 +0000 |
55 | +++ assemble/Darcy_IMPES_Assemble.F90 2014-05-30 12:10:35 +0000 |
56 | @@ -0,0 +1,5920 @@ |
57 | +! Copyright (C) 2006 Imperial College London and others. |
58 | +! |
59 | +! Please see the AUTHORS file in the main source directory for a full list |
60 | +! of copyright holders. |
61 | +! |
62 | +! Prof. C Pain |
63 | +! Applied Modelling and Computation Group |
64 | +! Department of Earth Science and Engineering |
65 | +! Imperial College London |
66 | +! |
67 | +! amcgsoftware@imperial.ac.uk |
68 | +! |
69 | +! This library is free software; you can redistribute it and/or |
70 | +! modify it under the terms of the GNU Lesser General Public |
71 | +! License as published by the Free Software Foundation, |
72 | +! version 2.1 of the License. |
73 | +! |
74 | +! This library is distributed in the hope that it will be useful, |
75 | +! but WITHOUT ANY WARRANTY; without even the implied warranty of |
76 | +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
77 | +! Lesser General Public License for more details. |
78 | +! |
79 | +! You should have received a copy of the GNU Lesser General Public |
80 | +! License along with this library; if not, write to the Free Software |
81 | +! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
82 | +! USA |
83 | + |
84 | +#include "fdebug.h" |
85 | + |
86 | +module darcy_impes_assemble_module |
87 | + |
88 | + ! keep in this order, please: |
89 | + use quadrature |
90 | + use elements |
91 | + use sparse_tools |
92 | + use fields |
93 | + use sparse_tools_petsc |
94 | + ! |
95 | + use field_derivatives |
96 | + use cv_shape_functions |
97 | + use cv_faces |
98 | + use cvtools |
99 | + use cv_fields |
100 | + use cv_upwind_values |
101 | + use cv_face_values |
102 | + use cv_options |
103 | + use boundary_conditions |
104 | + use fefields, only: compute_cv_mass |
105 | + use petsc_solve_state_module |
106 | + use sparse_matrices_fields |
107 | + use transform_elements, only: transform_cvsurf_to_physical, & |
108 | + transform_cvsurf_facet_to_physical |
109 | + use state_module |
110 | + use fldebug |
111 | + use spud |
112 | + use porous_media |
113 | + use parallel_tools |
114 | + use adaptive_timestepping |
115 | + use halos |
116 | + use signal_vars, only : SIG_INT |
117 | + use global_parameters, only : FIELD_NAME_LEN, OPTION_PATH_LEN |
118 | + |
119 | + implicit none |
120 | + |
121 | + private |
122 | + |
123 | + public :: darcy_impes_type, & |
124 | + darcy_impes_cv_options_type, & |
125 | + darcy_impes_copy_to_old, & |
126 | + darcy_impes_copy_to_iterated, & |
127 | + darcy_impes_assemble_and_solve_part_one, & |
128 | + darcy_impes_assemble_and_solve_part_two, & |
129 | + darcy_impes_assemble_and_solve_part_three, & |
130 | + darcy_impes_calculate_gradient_pressures, & |
131 | + darcy_impes_calculate_non_first_phase_pressures, & |
132 | + darcy_impes_calculate_phase_one_saturation_diagnostic, & |
133 | + darcy_impes_calculate_vel_mob_ff_and_cfl_fields, & |
134 | + darcy_impes_calculate_sum_saturation, & |
135 | + darcy_impes_calculate_relperm_fields, & |
136 | + darcy_impes_calculate_densities, & |
137 | + darcy_impes_calculate_cflnumber_field_based_dt, & |
138 | + darcy_impes_initialise_cached_face_value, & |
139 | + darcy_impes_calculate_inverse_characteristic_length, & |
140 | + darcy_impes_calculate_relperm_den_first_face_values, & |
141 | + darcy_impes_calculate_relperm_isub_face_values, & |
142 | + darcy_impes_get_entire_sfield_boundary_condition, & |
143 | + darcy_impes_get_v_boundary_condition, & |
144 | + darcy_impes_assemble_saturation_rhs_adv, & |
145 | + darcy_impes_assemble_and_solve_phase_pressures, & |
146 | + darcy_impes_calculate_divergence_total_darcy_velocity, & |
147 | + darcy_impes_calculate_inverse_cv_sa |
148 | + |
149 | + ! Parameters defining Darcy IMPES cached options |
150 | + integer, parameter, public :: RELPERM_CORRELATION_POWER = 1, & |
151 | + RELPERM_CORRELATION_COREY2PHASE = 2, & |
152 | + RELPERM_CORRELATION_COREY2PHASEOPPOSITE = 3, & |
153 | + RELPERM_CORRELATION_MINERAL = 4, & |
154 | + RELPERM_CORRELATION_VANGENUCHTEN = 5, & |
155 | + RELPERM_CORRELATION_JACKSON2PHASE = 6, & |
156 | + RELPERM_CORRELATION_JACKSON2PHASEOPPOSITE = 7 |
157 | + |
158 | + ! Parameters defining Darcy IMPES CV face value schemes |
159 | + integer, parameter, public :: DARCY_IMPES_CV_FACEVALUE_NONE = 0, & |
160 | + DARCY_IMPES_CV_FACEVALUE_FIRSTORDERUPWIND = 1, & |
161 | + DARCY_IMPES_CV_FACEVALUE_FINITEELEMENT = 2, & |
162 | + DARCY_IMPES_CV_FACEVALUE_RELPERMOVERSATUPWIND = 3, & |
163 | + DARCY_IMPES_CV_FACEVALUE_RELPERMOVERSATFINITEELEMENT = 4, & |
164 | + DARCY_IMPES_CV_FACEVALUE_RELPERMOVERSATCORRELATION = 5 |
165 | + |
166 | + ! Options associated with the relative permeability correlation |
167 | + type darcy_impes_relperm_corr_options_type |
168 | + ! The correlation type to use |
169 | + integer :: type |
170 | + ! The exponent for the power law correlation for each phase |
171 | + real, dimension(:), pointer :: exponents |
172 | + ! The residual saturation for each phase |
173 | + real, dimension(:), pointer :: residual_saturations |
174 | + ! The cut off value for saturation when calculating relperm |
175 | + real, dimension(:), pointer :: cutoff_saturations |
176 | + ! The scaling_coefficients when calculating relperm |
177 | + real, dimension(:), pointer :: scaling_coefficients |
178 | + end type darcy_impes_relperm_corr_options_type |
179 | + |
180 | + ! Options associated with the CV discretisation for the darcy impes solver |
181 | + type darcy_impes_cv_options_type |
182 | + ! what CV_FACEVALUE_ to use |
183 | + integer :: facevalue |
184 | + ! the number of face value iterations |
185 | + integer :: number_face_value_iteration |
186 | + ! whether to limit the face value spatially |
187 | + logical :: limit_facevalue |
188 | + ! what CV_LIMITER_ to use |
189 | + integer :: limiter |
190 | + ! the slopes of the limiter being used (if Sweby) |
191 | + real, dimension(2) :: limiter_slopes |
192 | + ! what upwind scheme are we using (if any) |
193 | + integer :: upwind_scheme |
194 | + end type darcy_impes_cv_options_type |
195 | + |
196 | + ! Options associated with explicit advection subcycling for CV scalar field solver |
197 | + type darcy_impes_subcycle_options_type |
198 | + logical :: have |
199 | + integer :: number |
200 | + logical :: consistent |
201 | + end type darcy_impes_subcycle_options_type |
202 | + |
203 | + ! Options associated with adaptive time stepping |
204 | + type darcy_impes_adaptive_dt_options_type |
205 | + logical :: have |
206 | + real :: requested_cfl |
207 | + real :: min_dt |
208 | + real :: max_dt |
209 | + real :: increase_tolerance |
210 | + logical :: min_dt_terminate_if_reached |
211 | + logical :: at_first_dt |
212 | + end type darcy_impes_adaptive_dt_options_type |
213 | + |
214 | + ! Options associated with EoS for a phase |
215 | + type darcy_impes_eos_options_type |
216 | + logical :: have_fluids_linear |
217 | + real :: fluids_linear_reference_density |
218 | + end type darcy_impes_eos_options_type |
219 | + |
220 | + ! Data associated with the cached CV face values |
221 | + type cached_face_value_type |
222 | + real, dimension(:,:,:,:), pointer :: relperm ! nsub, ngi_vele, vele, nphase |
223 | + real, dimension(:,:,:,:), pointer :: relperm_bdy ! nsub, ngi_sele, sele, nphase |
224 | + real, dimension(:,:,:), pointer :: den ! ngi_vele, vele, nphase |
225 | + real, dimension(:,:,:), pointer :: den_bdy ! ngi_sele, sele, nphase |
226 | + real, dimension(:,:), pointer :: detwei ! ngi_vele, vele |
227 | + real, dimension(:,:), pointer :: detwei_bdy ! ngi_sele, sele |
228 | + real, dimension(:,:,:), pointer :: normal ! ndim, ngi_vele, vele |
229 | + real, dimension(:,:,:), pointer :: normal_bdy ! ndim, ngi_sele, sele |
230 | + real, dimension(:,:,:,:), pointer :: p_dshape ! nloc, ngi_vele, ndim, vele |
231 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
232 | +!!!!! real, dimension(:,:,:,:), pointer :: p_dshape_bdy ! nloc, ngi_sele, ndim, sele |
233 | + logical :: cached_detwei_normal |
234 | + logical :: cached_p_dshape |
235 | + end type cached_face_value_type |
236 | + |
237 | + ! Data associated with a generic prognostic sfield, some of which will point to fields in state |
238 | + type darcy_impes_generic_prog_sfield_type |
239 | + ! The phase this sfield is associated with |
240 | + integer :: phase |
241 | + type(scalar_field), pointer :: sfield |
242 | + type(scalar_field), pointer :: old_sfield |
243 | + type(scalar_field), pointer :: sfield_abs |
244 | + type(scalar_field), pointer :: sfield_src |
245 | + type(tensor_field), pointer :: sfield_diff |
246 | + logical :: have_diff |
247 | + logical :: have_abs |
248 | + logical :: have_src |
249 | + logical :: have_adv |
250 | + type(darcy_impes_cv_options_type) :: sfield_cv_options |
251 | + end type darcy_impes_generic_prog_sfield_type |
252 | + |
253 | + type darcy_impes_type |
254 | + ! *** Pointers to fields from state that have array length of number of phases *** |
255 | + type(vector_field_pointer), dimension(:), pointer :: darcy_velocity |
256 | + type(scalar_field_pointer), dimension(:), pointer :: mobility |
257 | + type(scalar_field_pointer), dimension(:), pointer :: fractional_flow |
258 | + type(scalar_field_pointer), dimension(:), pointer :: saturation |
259 | + type(scalar_field_pointer), dimension(:), pointer :: old_saturation |
260 | + type(scalar_field_pointer), dimension(:), pointer :: saturation_source |
261 | + type(scalar_field_pointer), dimension(:), pointer :: relative_permeability |
262 | + type(scalar_field_pointer), dimension(:), pointer :: old_relative_permeability |
263 | + type(scalar_field_pointer), dimension(:), pointer :: viscosity |
264 | + type(scalar_field_pointer), dimension(:), pointer :: cfl |
265 | + type(scalar_field_pointer), dimension(:), pointer :: pressure |
266 | + type(scalar_field_pointer), dimension(:), pointer :: capilliary_pressure |
267 | + type(scalar_field_pointer), dimension(:), pointer :: density |
268 | + type(scalar_field_pointer), dimension(:), pointer :: old_density |
269 | + ! *** Pointers to fields from state that are NOT phase dependent *** |
270 | + type(mesh_type), pointer :: pressure_mesh |
271 | + type(mesh_type), pointer :: elementwise_mesh |
272 | + type(scalar_field), pointer :: average_pressure |
273 | + type(scalar_field), pointer :: porosity |
274 | + type(scalar_field), pointer :: absolute_permeability |
275 | + type(vector_field), pointer :: positions |
276 | + type(vector_field), pointer :: total_darcy_velocity |
277 | + type(scalar_field), pointer :: total_mobility |
278 | + type(scalar_field), pointer :: sum_saturation |
279 | + type(scalar_field), pointer :: div_total_darcy_velocity |
280 | + type(vector_field), pointer :: gravity_direction |
281 | + type(vector_field), pointer :: bulk_darcy_velocity |
282 | + ! ***** Pointers to DUAL fields from state that have array length of number of phases ***** |
283 | + type(scalar_field_pointer), dimension(:), pointer :: pressure_other_porous_media |
284 | + type(scalar_field_pointer), dimension(:), pointer :: transmissibility_lambda_dual |
285 | + ! *** Pointer to the pressure mesh - pressure mesh sparsity, used for pressure matrix and finding CV upwind values *** |
286 | + type(csr_sparsity), pointer :: sparsity_pmesh_pmesh |
287 | + ! *** Data associated with generic prognostic scalar fields, some of which points to fields in state *** |
288 | + type(darcy_impes_generic_prog_sfield_type), dimension(:), pointer :: generic_prog_sfield |
289 | + ! *** Data associated with GradientPressure fields *** |
290 | + type(element_type) :: gradient_pressure_shape |
291 | + type(mesh_type) :: gradient_pressure_mesh |
292 | + type(vector_field_pointer), dimension(:), pointer :: gradient_pressure |
293 | + type(vector_field_pointer), dimension(:), pointer :: iterated_gradient_pressure |
294 | + ! *** Data associated with gravity *** |
295 | + logical :: have_gravity |
296 | + real :: gravity_magnitude |
297 | + type(vector_field) :: gravity |
298 | + ! *** Fields allocated here used in assemble algorithm *** |
299 | + type(vector_field) :: positions_pressure_mesh |
300 | + type(csr_matrix) :: matrix |
301 | + type(petsc_csr_matrix) :: dual_block_pressure_matrix |
302 | + type(csr_matrix) :: pressure_matrix |
303 | + type(scalar_field), pointer :: pressure_rhs |
304 | + type(scalar_field) :: lhs |
305 | + type(scalar_field) :: rhs |
306 | + type(scalar_field) :: rhs_full |
307 | + type(scalar_field) :: rhs_high_resolution |
308 | + type(scalar_field) :: inverse_cv_mass_pressure_mesh |
309 | + type(scalar_field) :: cv_mass_pressure_mesh_with_source |
310 | + type(scalar_field) :: cv_mass_pressure_mesh_with_porosity |
311 | + type(scalar_field) :: cv_mass_pressure_mesh_with_old_porosity |
312 | + type(scalar_field) :: inverse_cv_sa_pressure_mesh |
313 | + type(scalar_field) :: modified_relative_permeability |
314 | + type(scalar_field), pointer :: constant_zero_sfield_pmesh |
315 | + type(scalar_field), pointer :: constant_zero_sfield_elementwisemesh |
316 | + type(scalar_field_pointer), dimension(:), pointer :: old_saturation_subcycle |
317 | + ! ***** coupling field associated with DUAL model ***** |
318 | + type(scalar_field) :: cv_mass_pressure_mesh_with_lambda_dual |
319 | + ! ***** rhs src field associated with DUAL model ***** |
320 | + type(scalar_field) :: rhs_dual |
321 | + ! *** Data associated with v, pressure and sfield BC allocated here *** |
322 | + type(mesh_type) :: bc_surface_mesh |
323 | + type(scalar_field) :: v_bc_value |
324 | + integer, dimension(:), pointer :: v_bc_flag |
325 | + type(scalar_field) :: sfield_bc_value |
326 | + integer, dimension(:), pointer :: sfield_bc_flag |
327 | + type(scalar_field) :: pressure_bc_value |
328 | + integer, dimension(:), pointer :: pressure_bc_flag |
329 | + type(scalar_field) :: inverse_characteristic_length |
330 | + real :: weak_pressure_bc_coeff |
331 | + ! *** The number of phase and the CV surface quadrature degree to use *** |
332 | + integer :: number_phase, cv_surface_quaddegree |
333 | + ! *** Data specifically associated with the CV discretisation allocated here *** |
334 | + type(darcy_impes_cv_options_type) :: saturation_cv_options |
335 | + type(darcy_impes_cv_options_type) :: relperm_cv_options |
336 | + type(darcy_impes_cv_options_type) :: density_cv_options |
337 | + type(cv_faces_type) :: cvfaces |
338 | + type(element_type) :: x_cvshape_full |
339 | + type(element_type) :: p_cvshape_full |
340 | + type(element_type) :: gradp_cvshape_full |
341 | + type(element_type) :: x_cvshape |
342 | + type(element_type) :: p_cvshape |
343 | + type(element_type) :: gradp_cvshape |
344 | + type(element_type) :: x_cvbdyshape |
345 | + type(element_type) :: p_cvbdyshape |
346 | + type(element_type) :: gradp_cvbdyshape |
347 | + type(darcy_impes_subcycle_options_type) :: subcy_opt_sat |
348 | + type(csr_matrix) :: relperm_upwind |
349 | + type(csr_matrix) :: sfield_upwind |
350 | + ! *** The minimum value of saturation to use in the denominator of modrelperm face value *** |
351 | + real :: minimum_denominator_saturation_value |
352 | + ! *** A flag for whether saturation face values need to be determined |
353 | + logical :: determine_saturation_face_values |
354 | + ! *** Data associate with the relperm correlation options *** |
355 | + type(darcy_impes_relperm_corr_options_type) :: relperm_corr_options |
356 | + ! *** Flag for each phase for whether there is capilliary pressure *** |
357 | + logical, dimension(:), pointer :: have_capilliary_pressure |
358 | + ! *** Flag for each phase for whether there is a saturation source *** |
359 | + logical, dimension(:), pointer :: have_saturation_source |
360 | + ! *** Flag for whether the first phase saturation is diagnostic, else it is prognostic *** |
361 | + logical :: phase_one_saturation_diagnostic |
362 | + ! *** Flag for whether the first phase pressure is prognostic, else it is prescribed *** |
363 | + logical :: first_phase_pressure_prognostic |
364 | + ! *** The cached face values for all phases *** |
365 | + type(cached_face_value_type) :: cached_face_value |
366 | + ! *** The advection subcycle timestep size *** |
367 | + real :: dt_subcycle |
368 | + ! *** Time time step size, also stored here for convenience *** |
369 | + real :: dt |
370 | + ! *** The current time, also stored here for convenience *** |
371 | + real :: current_time |
372 | + ! *** Non linear iteration, also stored here for convencience *** |
373 | + integer :: nonlinear_iter |
374 | + ! *** Max Non linear iteration for this timestep, also stored here for convencience *** |
375 | + integer :: max_nonlinear_iter_this_timestep |
376 | + ! *** The number of volume, surface elements and nodes, stored here for convenience *** |
377 | + integer :: number_vele |
378 | + integer :: number_sele |
379 | + integer :: number_pmesh_node |
380 | + ! *** Geometric dimension, also stored here for convenience *** |
381 | + integer :: ndim |
382 | + ! *** Options data associated with adaptive time stepping stored here *** |
383 | + type(darcy_impes_adaptive_dt_options_type) :: adaptive_dt_options |
384 | + ! *** Options data associated with each phase EoS stored here *** |
385 | + type(darcy_impes_eos_options_type), dimension(:), pointer :: eos_options |
386 | + ! *** Pointer to main state array, for convenience *** |
387 | + type(state_type), dimension(:), pointer :: state |
388 | + end type darcy_impes_type |
389 | + |
390 | + contains |
391 | + |
392 | +! ---------------------------------------------------------------------------- |
393 | + |
394 | + subroutine darcy_impes_copy_to_old(di) |
395 | + |
396 | + !!< Copy to old darcy impes data not associated with di%state |
397 | + |
398 | + type(darcy_impes_type), intent(inout) :: di |
399 | + |
400 | + call set(di%cv_mass_pressure_mesh_with_old_porosity, di%cv_mass_pressure_mesh_with_porosity) |
401 | + |
402 | + end subroutine darcy_impes_copy_to_old |
403 | + |
404 | +! ---------------------------------------------------------------------------- |
405 | + |
406 | + subroutine darcy_impes_copy_to_iterated(di) |
407 | + |
408 | + !!< Copy to iterated darcy impes data not associated with di%state |
409 | + |
410 | + type(darcy_impes_type), intent(inout) :: di |
411 | + |
412 | + ! local variables |
413 | + integer :: p |
414 | + |
415 | + do p = 1, di%number_phase |
416 | + |
417 | + call set(di%iterated_gradient_pressure(p)%ptr, di%gradient_pressure(p)%ptr) |
418 | + |
419 | + end do |
420 | + |
421 | + end subroutine darcy_impes_copy_to_iterated |
422 | + |
423 | +! ---------------------------------------------------------------------------- |
424 | + |
425 | + subroutine darcy_impes_assemble_and_solve_part_one(di, have_dual) |
426 | + |
427 | + !!< Assemble and solve the Darcy equations using an CIMPESS algorithm |
428 | + !!< which is a modification of the IMPES to include consistent subcycling. |
429 | + !!< Part one: form cv mass and initial saturation solve for subcycling |
430 | + |
431 | + type(darcy_impes_type), intent(inout) :: di |
432 | + logical , intent(in) :: have_dual |
433 | + |
434 | + ! local variables |
435 | + logical :: form_new_subcycle_relperm_face_values |
436 | + |
437 | + ewrite(1,*) 'Start Darcy IMPES assemble and solve part one' |
438 | + |
439 | + ! Calculate the latest CV mass on the pressure mesh with porosity included |
440 | + call compute_cv_mass(di%positions, di%cv_mass_pressure_mesh_with_porosity, di%porosity) |
441 | + |
442 | + ! If it is the first iteration and there is subcycling (>1) |
443 | + ! and a consistent global continuity then solve the saturations |
444 | + if ((di%nonlinear_iter == 1) .and. & |
445 | + (di%subcy_opt_sat%number > 1) .and. & |
446 | + (di%subcy_opt_sat%consistent)) then |
447 | + |
448 | + form_new_subcycle_relperm_face_values = .true. |
449 | + |
450 | + call darcy_impes_assemble_and_solve_phase_saturations(di, & |
451 | + form_new_subcycle_relperm_face_values, & |
452 | + have_dual) |
453 | + |
454 | + end if |
455 | + |
456 | + ewrite(1,*) 'Finished Darcy IMPES assemble and solve part one' |
457 | + |
458 | + end subroutine darcy_impes_assemble_and_solve_part_one |
459 | + |
460 | +! ---------------------------------------------------------------------------- |
461 | + |
462 | + subroutine darcy_impes_assemble_and_solve_part_two(di, di_dual, have_dual, solve_dual_pressure) |
463 | + |
464 | + !!< Assemble and solve the Darcy equations using an CIMPESS algorithm |
465 | + !!< which is a modification of the IMPES to include consistent subcycling. |
466 | + !!< Part two: solve for the pressure |
467 | + |
468 | + type(darcy_impes_type), intent(inout) :: di |
469 | + type(darcy_impes_type), intent(inout) :: di_dual |
470 | + logical , intent(in) :: have_dual |
471 | + logical , intent(in) :: solve_dual_pressure |
472 | + |
473 | + ewrite(1,*) 'Start Darcy IMPES assemble and solve part two' |
474 | + |
475 | + ! Assemble and solve the phase pressures |
476 | + call darcy_impes_assemble_and_solve_phase_pressures(di, di_dual, have_dual, solve_dual_pressure) |
477 | + |
478 | + ewrite(1,*) 'Finished Darcy IMPES assemble and solve part two' |
479 | + |
480 | + end subroutine darcy_impes_assemble_and_solve_part_two |
481 | + |
482 | +! ---------------------------------------------------------------------------- |
483 | + |
484 | + subroutine darcy_impes_assemble_and_solve_part_three(di, have_dual) |
485 | + |
486 | + !!< Assemble and solve the Darcy equations using an CIMPESS algorithm |
487 | + !!< which is a modification of the IMPES to include consistent subcycling. |
488 | + !!< Part three: find pressure gradients, calc div.u, solve for saturation |
489 | + !!< and generic scalar fields, calc sum S, calc density, calc relperm. |
490 | + |
491 | + type(darcy_impes_type), intent(inout) :: di |
492 | + logical , intent(in) :: have_dual |
493 | + |
494 | + ! local variables |
495 | + logical :: form_new_subcycle_relperm_face_values |
496 | + |
497 | + ewrite(1,*) 'Start Darcy IMPES assemble and solve part three' |
498 | + |
499 | + ! Calculate the gradient pressures |
500 | + call darcy_impes_calculate_gradient_pressures(di) |
501 | + |
502 | + ! Calculate the divergence total darcy velocity |
503 | + call darcy_impes_calculate_divergence_total_darcy_velocity(di) |
504 | + |
505 | + ! Assemble and solve the phase saturations |
506 | + |
507 | + if ((di%nonlinear_iter == di%max_nonlinear_iter_this_timestep) .and. & |
508 | + (di%subcy_opt_sat%consistent)) then |
509 | + |
510 | + form_new_subcycle_relperm_face_values = .false. |
511 | + |
512 | + else |
513 | + |
514 | + form_new_subcycle_relperm_face_values = .true. |
515 | + |
516 | + end if |
517 | + |
518 | + call darcy_impes_assemble_and_solve_phase_saturations(di, & |
519 | + form_new_subcycle_relperm_face_values, & |
520 | + have_dual) |
521 | + |
522 | + call darcy_impes_assemble_and_solve_generic_prog_sfields(di) |
523 | + |
524 | + ! Calculate the sum of the saturations |
525 | + call darcy_impes_calculate_sum_saturation(di) |
526 | + |
527 | + ! Calculate the density field of each phase |
528 | + call darcy_impes_calculate_densities(di) |
529 | + |
530 | + ! Calculate the relative permeabilities of each phase |
531 | + call darcy_impes_calculate_relperm_fields(di) |
532 | + |
533 | + ewrite(1,*) 'Finished Darcy IMPES assemble and solve part three' |
534 | + |
535 | + end subroutine darcy_impes_assemble_and_solve_part_three |
536 | + |
537 | +! ---------------------------------------------------------------------------- |
538 | + |
539 | + subroutine darcy_impes_assemble_and_solve_phase_pressures(di, di_dual, have_dual, solve_dual_pressure) |
540 | + |
541 | + !!< Assemble and solve the phase pressures. The first phase pressure |
542 | + !!< is solved via a matrix equation (if prognostic) and the other |
543 | + !!< phases pressures are calculated from the first phase pressure |
544 | + !!< and their own capilliary pressures |
545 | + |
546 | + type(darcy_impes_type), intent(inout) :: di |
547 | + type(darcy_impes_type), intent(inout) :: di_dual |
548 | + logical , intent(in) :: have_dual |
549 | + logical , intent(in) :: solve_dual_pressure |
550 | + |
551 | + ! Assemble and solve the first phase pressure if it is prognostic |
552 | + if (di%first_phase_pressure_prognostic) call darcy_impes_assemble_and_solve_first_phase_pressure(di, di_dual, have_dual, solve_dual_pressure) |
553 | + |
554 | + ! Calculate the non first phase pressure's |
555 | + call darcy_impes_calculate_non_first_phase_pressures(di) |
556 | + if (have_dual) call darcy_impes_calculate_non_first_phase_pressures(di_dual) |
557 | + |
558 | + ! Calculate the average pressure |
559 | + call darcy_impes_calculate_average_pressure(di) |
560 | + if (have_dual) call darcy_impes_calculate_average_pressure(di_dual) |
561 | + |
562 | + end subroutine darcy_impes_assemble_and_solve_phase_pressures |
563 | + |
564 | +! ---------------------------------------------------------------------------- |
565 | + |
566 | + subroutine darcy_impes_assemble_and_solve_first_phase_pressure(di, di_dual, have_dual, solve_dual_pressure) |
567 | + |
568 | + !!< Assemble and solve the first phase pressure. A source is included |
569 | + !!< due to the capilliary pressures of non first phases as well as gravity |
570 | + !!< and the rate of change of porosity and the individual phase sources. |
571 | + !!< Face values for relative permeability and density have already been evaluated. |
572 | + !!< If have_dual and solve_dual_pressure are both true then a block matrix using |
573 | + !!< di%dual_block_pressure_matrix is solved for. If have_dual is true but |
574 | + !!< solve_dual_pressure is false then a single matrix using di%pressure_matrix |
575 | + !!< is solved for the prime pressure phase 1 then the dual pressure phase 1 |
576 | + !!< is set to this. If have_dual is false then di%pressure_matrix is used. |
577 | + !!< (This is because an error is occuring for petsc_csr_matrix in 2d) |
578 | + |
579 | + type(darcy_impes_type), intent(inout) :: di |
580 | + type(darcy_impes_type), intent(inout) :: di_dual |
581 | + logical , intent(in) :: have_dual |
582 | + logical , intent(in) :: solve_dual_pressure |
583 | + |
584 | + ! local variables |
585 | + type(scalar_field_pointer), dimension(:), pointer :: all_pressure |
586 | + type(scalar_field_pointer), dimension(:), pointer :: all_rhs |
587 | + integer :: p, vele, sele, iloc, oloc, jloc, face, gi, ggi |
588 | + real :: face_value, grad_cap_p_dot_n, g_dot_n |
589 | + real, dimension(1) :: absperm_ele, visc_ele |
590 | + real, dimension(:,:), pointer :: grav_ele |
591 | + real, dimension(:,:), pointer :: grad_cap_pressure_face_quad |
592 | + real, dimension(:,:), pointer :: x_ele |
593 | + real, dimension(:,:,:), pointer :: p_dshape |
594 | + real, dimension(:,:), pointer :: normal |
595 | + real, dimension(:), pointer :: detwei |
596 | + real, dimension(:), pointer :: normgi |
597 | + logical, dimension(:), pointer :: notvisited |
598 | + real, dimension(:,:), pointer :: p_mat_local |
599 | + real, dimension(:), pointer :: p_rhs_local |
600 | + real, dimension(:,:), pointer :: x_face_quad |
601 | + integer, dimension(:), pointer :: x_pmesh_nodes |
602 | + integer, dimension(:), pointer :: p_nodes |
603 | + real, dimension(1) :: absperm_ele_bdy, visc_ele_bdy |
604 | + real, dimension(:,:), pointer :: grav_ele_bdy |
605 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
606 | +!!!!! real, dimension(:,:), pointer :: grad_cap_pressure_face_quad_bdy |
607 | +!!!!! real, dimension(:,:,:), pointer :: p_dshape_bdy |
608 | + real, dimension(:), pointer :: bc_sele_val |
609 | + real, dimension(:), pointer :: inv_char_len_ele_bdy |
610 | + real, dimension(:,:), pointer :: normal_bdy |
611 | + real, dimension(:), pointer :: detwei_bdy |
612 | + real, dimension(:,:), pointer :: x_ele_bdy |
613 | + real, dimension(:), pointer :: p_rhs_local_bdy |
614 | + real, dimension(:,:), pointer :: p_matrix_local_bdy |
615 | + integer, dimension(:), pointer :: p_nodes_bdy |
616 | + integer, parameter :: PRESSURE_BC_TYPE_WEAKDIRICHLET = 1, PRESSURE_BC_TYPE_DIRICHLET = 2 |
617 | + integer, parameter :: V_BC_TYPE_PRESCRIBED_NORMAL_FLOW = 1, V_BC_TYPE_NO_NORMAL_FLOW = 2 |
618 | + |
619 | + ! allocate arrays used in assemble process - many assume |
620 | + ! that all elements are the same type. |
621 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
622 | + if (.not. di%cached_face_value%cached_p_dshape) then |
623 | + allocate(p_dshape(ele_loc(di%pressure_mesh,1), di%p_cvshape%ngi, mesh_dim(di%pressure_mesh))) |
624 | + end if |
625 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
626 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
627 | + allocate(detwei(di%x_cvshape%ngi)) |
628 | + end if |
629 | + allocate(normgi(di%ndim)) |
630 | + allocate(notvisited(di%x_cvshape%ngi)) |
631 | + allocate(p_mat_local(ele_loc(di%pressure_mesh,1), ele_loc(di%pressure_mesh,1))) |
632 | + allocate(p_rhs_local(ele_loc(di%pressure_mesh,1))) |
633 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
634 | + allocate(grav_ele(di%ndim,1)) |
635 | + allocate(grad_cap_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
636 | + |
637 | + allocate(grav_ele_bdy(di%ndim,1)) |
638 | + allocate(bc_sele_val(face_loc(di%pressure_mesh,1))) |
639 | + allocate(inv_char_len_ele_bdy(face_loc(di%pressure_mesh,1))) |
640 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
641 | + allocate(detwei_bdy(di%x_cvbdyshape%ngi)) |
642 | + allocate(normal_bdy(di%ndim, di%x_cvbdyshape%ngi)) |
643 | + end if |
644 | + allocate(p_rhs_local_bdy(face_loc(di%pressure_mesh,1))) |
645 | + allocate(p_matrix_local_bdy(face_loc(di%pressure_mesh,1),face_loc(di%pressure_mesh,1))) |
646 | + allocate(x_ele_bdy(di%ndim, face_loc(di%positions,1))) |
647 | + allocate(p_nodes_bdy(face_loc(di%pressure_mesh,1))) |
648 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
649 | +!!!!! allocate(grad_cap_pressure_face_quad_bdy(di%ndim, di%p_cvbdyshape_full%ngi)) |
650 | +!!!!! if (.not. di%cached_face_value%cached_p_dshape) then |
651 | +!!!!! allocate(p_dshape_bdy(face_loc(di%pressure_mesh,1), di%p_cvbdyshape_full%ngi, mesh_dim(di%pressure_mesh))) |
652 | +!!!!! end if |
653 | + |
654 | + ewrite(1,*) 'Solve first phase Pressure' |
655 | + |
656 | + ! Initialise the matrix and rhs and solution pointer |
657 | + call zero(di%pressure_rhs) |
658 | + |
659 | + if (have_dual .and. solve_dual_pressure) then |
660 | + call zero(di%dual_block_pressure_matrix) |
661 | + call zero(di_dual%pressure_rhs) |
662 | + |
663 | + allocate(all_pressure(2)) |
664 | + allocate(all_rhs(2)) |
665 | + all_pressure(1)%ptr => di%pressure(1)%ptr |
666 | + all_pressure(2)%ptr => di_dual%pressure(1)%ptr |
667 | + all_rhs(1)%ptr => di%pressure_rhs |
668 | + all_rhs(2)%ptr => di_dual%pressure_rhs |
669 | + else |
670 | + call zero(di%pressure_matrix) |
671 | + allocate(all_pressure(1)) |
672 | + allocate(all_rhs(1)) |
673 | + all_pressure(1)%ptr => di%pressure(1)%ptr |
674 | + all_rhs(1)%ptr => di%pressure_rhs |
675 | + end if |
676 | + |
677 | + ewrite(1,*) 'Add phase sources to global continuity' |
678 | + |
679 | + src_phase_loop: do p = 1, di%number_phase |
680 | + |
681 | + ! Should this take account of subcycling?!?! |
682 | + call compute_cv_mass(di%positions, di%cv_mass_pressure_mesh_with_source, di%saturation_source(p)%ptr) |
683 | + |
684 | + ! Should this include porosity ?!?! |
685 | + call addto(di%pressure_rhs, di%cv_mass_pressure_mesh_with_source) |
686 | + |
687 | + end do src_phase_loop |
688 | + |
689 | + if (have_dual .and. solve_dual_pressure) then |
690 | + |
691 | + dual_src_phase_loop: do p = 1, di_dual%number_phase |
692 | + |
693 | + ! Should this take account of subcycling?!?! |
694 | + call compute_cv_mass(di_dual%positions, di_dual%cv_mass_pressure_mesh_with_source, di_dual%saturation_source(p)%ptr) |
695 | + |
696 | + ! Should this include porosity ?!?! |
697 | + call addto(di_dual%pressure_rhs, di_dual%cv_mass_pressure_mesh_with_source) |
698 | + |
699 | + end do dual_src_phase_loop |
700 | + |
701 | + end if |
702 | + |
703 | + ! Add the transmissibility lambda dual to each block diagonal |
704 | + if (have_dual .and. solve_dual_pressure) then |
705 | + transmiss_phase_loop: do p = 1, di_dual%number_phase |
706 | + call compute_cv_mass(di_dual%positions, di_dual%cv_mass_pressure_mesh_with_lambda_dual, di_dual%transmissibility_lambda_dual(p)%ptr) |
707 | + |
708 | + call addto_diag(di%dual_block_pressure_matrix, 1, 1, di_dual%cv_mass_pressure_mesh_with_lambda_dual, scale = 1.0) |
709 | + call addto_diag(di%dual_block_pressure_matrix, 1, 2, di_dual%cv_mass_pressure_mesh_with_lambda_dual, scale = -1.0) |
710 | + call addto_diag(di%dual_block_pressure_matrix, 2, 1, di_dual%cv_mass_pressure_mesh_with_lambda_dual, scale = -1.0) |
711 | + call addto_diag(di%dual_block_pressure_matrix, 2, 2, di_dual%cv_mass_pressure_mesh_with_lambda_dual, scale = 1.0) |
712 | + |
713 | + if (p > 1) then |
714 | + ! Add lambda*(PC_dual - PC_prime) to prime rhs |
715 | + call set(di%rhs, di_dual%capilliary_pressure(p)%ptr) |
716 | + call addto(di%rhs, di%capilliary_pressure(p)%ptr, scale = -1.0) |
717 | + call scale(di%rhs, di_dual%cv_mass_pressure_mesh_with_lambda_dual) |
718 | + call addto(di%pressure_rhs, di%rhs) |
719 | + |
720 | + ! Add lambda*(PC_prime- PC_dual) to dual rhs |
721 | + call set(di%rhs, di%capilliary_pressure(p)%ptr) |
722 | + call addto(di%rhs, di_dual%capilliary_pressure(p)%ptr, scale = -1.0) |
723 | + call scale(di%rhs, di_dual%cv_mass_pressure_mesh_with_lambda_dual) |
724 | + |
725 | + call addto(di_dual%pressure_rhs, di%rhs) |
726 | + end if |
727 | + end do transmiss_phase_loop |
728 | + end if |
729 | + |
730 | + ewrite(1,*) 'Add rate of change of porosity to global continuity equation' |
731 | + |
732 | + ! Add rate of change of porosity to rhs |
733 | + call addto(di%pressure_rhs, di%cv_mass_pressure_mesh_with_old_porosity, scale = 1.0/di%dt) |
734 | + |
735 | + call addto(di%pressure_rhs, di%cv_mass_pressure_mesh_with_porosity, scale = -1.0/di%dt) |
736 | + |
737 | + if (have_dual .and. solve_dual_pressure) then |
738 | + |
739 | + call addto(di_dual%pressure_rhs, di_dual%cv_mass_pressure_mesh_with_old_porosity, scale = 1.0/di%dt) |
740 | + |
741 | + call addto(di_dual%pressure_rhs, di_dual%cv_mass_pressure_mesh_with_porosity, scale = -1.0/di%dt) |
742 | + |
743 | + end if |
744 | + |
745 | + ! Assemble a contribution from each phase to form a global continuity equation to solve for first phase pressure |
746 | + phase_loop: do p = 1, di%number_phase |
747 | + |
748 | + ewrite(1,*) 'Assemble volume contribution to global continuity from phase ',p |
749 | + |
750 | + ! Loop volume elements assembling local contributions |
751 | + vol_element_loop: do vele = 1, di%number_vele |
752 | + |
753 | + call pressure_volume_element_local_assemble(di) |
754 | + |
755 | + ! Add volume element contribution to global pressure matrix and rhs |
756 | + if (have_dual .and. solve_dual_pressure) then |
757 | + call addto(di%dual_block_pressure_matrix, 1, 1, p_nodes, p_nodes, p_mat_local) |
758 | + |
759 | + call addto(di%pressure_rhs, p_nodes, p_rhs_local) |
760 | + |
761 | + call pressure_volume_element_local_assemble(di_dual) |
762 | + |
763 | + call addto(di%dual_block_pressure_matrix, 2, 2, p_nodes, p_nodes, p_mat_local) |
764 | + |
765 | + call addto(di_dual%pressure_rhs, p_nodes, p_rhs_local) |
766 | + |
767 | + else |
768 | + |
769 | + call addto(di%pressure_matrix, p_nodes, p_nodes, p_mat_local) |
770 | + |
771 | + call addto(di%pressure_rhs, p_nodes, p_rhs_local) |
772 | + |
773 | + end if |
774 | + |
775 | + end do vol_element_loop |
776 | + |
777 | + end do phase_loop |
778 | + |
779 | + ! Add normal v BC integrals for each phase, else include if required |
780 | + ! a weak pressure BC (which if not given is assumed zero). |
781 | + |
782 | + ! Get the pressure BC - if no v and weak pressure then extra integrals are added |
783 | + ! - also get strong pressure BC as this implies no need to add any surface integrals |
784 | + call darcy_impes_get_entire_sfield_boundary_condition(di%pressure(1)%ptr, & |
785 | + (/"weakdirichlet", & |
786 | + "dirichlet "/), & |
787 | + di%bc_surface_mesh, & |
788 | + di%pressure_bc_value, & |
789 | + di%pressure_bc_flag) |
790 | + |
791 | + if (have_dual .and. solve_dual_pressure) then |
792 | + call darcy_impes_get_entire_sfield_boundary_condition(di_dual%pressure(1)%ptr, & |
793 | + (/"weakdirichlet", & |
794 | + "dirichlet "/), & |
795 | + di_dual%bc_surface_mesh, & |
796 | + di_dual%pressure_bc_value, & |
797 | + di_dual%pressure_bc_flag) |
798 | + end if |
799 | + |
800 | + phase_loop_bc: do p = 1, di%number_phase |
801 | + |
802 | + ewrite(1,*) 'Assemble boundary contribution to global continuity from phase ',p |
803 | + |
804 | + ! Get this phase v BC info - only for no_normal_flow and prescribed_normal_flow which is special as it is a scalar |
805 | + call darcy_impes_get_v_boundary_condition(di%darcy_velocity(p)%ptr, & |
806 | + (/"prescribed_normal_flow", & |
807 | + "no_normal_flow "/), & |
808 | + di%bc_surface_mesh, & |
809 | + di%v_bc_value, & |
810 | + di%v_bc_flag) |
811 | + |
812 | + if (have_dual .and. solve_dual_pressure) then |
813 | + call darcy_impes_get_v_boundary_condition(di_dual%darcy_velocity(p)%ptr, & |
814 | + (/"prescribed_normal_flow", & |
815 | + "no_normal_flow "/), & |
816 | + di_dual%bc_surface_mesh, & |
817 | + di_dual%v_bc_value, & |
818 | + di_dual%v_bc_flag) |
819 | + end if |
820 | + |
821 | + sele_loop: do sele = 1, di%number_sele |
822 | + |
823 | + call pressure_surface_element_local_assemble(di) |
824 | + |
825 | + if (have_dual .and. solve_dual_pressure) then |
826 | + |
827 | + call addto(di%dual_block_pressure_matrix, 1, 1, p_nodes_bdy, p_nodes_bdy, p_matrix_local_bdy) |
828 | + |
829 | + call addto(di%pressure_rhs, p_nodes_bdy, p_rhs_local_bdy) |
830 | + |
831 | + call pressure_surface_element_local_assemble(di_dual) |
832 | + |
833 | + call addto(di%dual_block_pressure_matrix, 2, 2, p_nodes_bdy, p_nodes_bdy, p_matrix_local_bdy) |
834 | + |
835 | + call addto(di_dual%pressure_rhs, p_nodes_bdy, p_rhs_local_bdy) |
836 | + |
837 | + else |
838 | + |
839 | + call addto(di%pressure_matrix, p_nodes_bdy, p_nodes_bdy, p_matrix_local_bdy) |
840 | + |
841 | + call addto(di%pressure_rhs, p_nodes_bdy, p_rhs_local_bdy) |
842 | + |
843 | + end if |
844 | + |
845 | + end do sele_loop |
846 | + |
847 | + end do phase_loop_bc |
848 | + |
849 | + ! Apply any strong dirichlet BC's - that can only be applied to the first phase pressure |
850 | + ! of both the prime and dual porous media |
851 | + if (have_dual .and. solve_dual_pressure) then |
852 | + call apply_dirichlet_conditions(di%dual_block_pressure_matrix, all_rhs, all_pressure) |
853 | + else |
854 | + call apply_dirichlet_conditions(di%pressure_matrix, all_rhs(1)%ptr, all_pressure(1)%ptr) |
855 | + end if |
856 | + |
857 | + ! Solve the pressure(s) |
858 | + if (have_dual .and. solve_dual_pressure) then |
859 | + call petsc_solve(all_pressure, di%dual_block_pressure_matrix, all_rhs, di%state(1)) |
860 | + else |
861 | + call petsc_solve(all_pressure(1)%ptr, di%pressure_matrix, all_rhs(1)%ptr, di%state(1)) |
862 | + end if |
863 | + |
864 | + ! Set the strong BC nodes to the values to be consistent |
865 | + call set_dirichlet_consistent(di%pressure(1)%ptr) |
866 | + |
867 | + if (have_dual) then |
868 | + |
869 | + if (solve_dual_pressure) then |
870 | + |
871 | + call set_dirichlet_consistent(di_dual%pressure(1)%ptr) |
872 | + |
873 | + else |
874 | + |
875 | + call set(di_dual%pressure(1)%ptr, di%pressure(1)%ptr) |
876 | + |
877 | + end if |
878 | + |
879 | + end if |
880 | + |
881 | + ! deallocate local variables as required |
882 | + deallocate(x_ele) |
883 | + if (di%cached_face_value%cached_p_dshape) then |
884 | + nullify(p_dshape) |
885 | + else |
886 | + deallocate(p_dshape) |
887 | + end if |
888 | + if (di%cached_face_value%cached_detwei_normal) then |
889 | + nullify(detwei) |
890 | + nullify(normal) |
891 | + else |
892 | + deallocate(detwei) |
893 | + deallocate(normal) |
894 | + end if |
895 | + deallocate(normgi) |
896 | + deallocate(notvisited) |
897 | + deallocate(p_mat_local) |
898 | + deallocate(p_rhs_local) |
899 | + deallocate(x_face_quad) |
900 | + deallocate(grav_ele) |
901 | + deallocate(grad_cap_pressure_face_quad) |
902 | + |
903 | + deallocate(grav_ele_bdy) |
904 | + deallocate(bc_sele_val) |
905 | + deallocate(inv_char_len_ele_bdy) |
906 | + if (di%cached_face_value%cached_detwei_normal) then |
907 | + nullify(detwei_bdy) |
908 | + nullify(normal_bdy) |
909 | + else |
910 | + deallocate(detwei_bdy) |
911 | + deallocate(normal_bdy) |
912 | + end if |
913 | + deallocate(p_rhs_local_bdy) |
914 | + deallocate(p_matrix_local_bdy) |
915 | + deallocate(x_ele_bdy) |
916 | + deallocate(p_nodes_bdy) |
917 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
918 | +!!!!! deallocate(grad_cap_pressure_face_quad_bdy) |
919 | + |
920 | + deallocate(all_pressure) |
921 | + deallocate(all_rhs) |
922 | + |
923 | + ewrite(1,*) 'Finished solve first phase Pressure' |
924 | + |
925 | + ewrite_minmax(di%pressure(1)%ptr) |
926 | + |
927 | + if (have_dual) then |
928 | + ewrite_minmax(di_dual%pressure(1)%ptr) |
929 | + end if |
930 | + |
931 | + contains |
932 | + |
933 | + ! -------------------------------------------------------------------------------------- |
934 | + |
935 | + subroutine pressure_volume_element_local_assemble(di) |
936 | + |
937 | + !!< Assemble the local volume element pressure matrix and rhs |
938 | + |
939 | + type(darcy_impes_type), intent(inout) :: di |
940 | + |
941 | + ! The node indices of the pressure mesh |
942 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
943 | + |
944 | + ! The gravity values for this element for each direction |
945 | + grav_ele = ele_val(di%gravity, vele) |
946 | + |
947 | + ! get the viscosity value for this element for this phase |
948 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
949 | + |
950 | + ! get the absolute permeability value for this element |
951 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
952 | + |
953 | + ! obtain the transformed determinant*weight and normals |
954 | + if (di%cached_face_value%cached_detwei_normal) then |
955 | + |
956 | + detwei => di%cached_face_value%detwei(:,vele) |
957 | + |
958 | + normal => di%cached_face_value%normal(:,:,vele) |
959 | + |
960 | + else |
961 | + |
962 | + ! get the coordinate values for this element for each positions local node |
963 | + x_ele = ele_val(di%positions, vele) |
964 | + |
965 | + ! get the coordinate values for this element for each quadrature point |
966 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
967 | + |
968 | + ! The node indices of the positions projected to the pressure mesh |
969 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
970 | + |
971 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
972 | + |
973 | + end if |
974 | + |
975 | + ! obtain the derivative of the pressure mesh shape function at the CV face quadrature points |
976 | + if (di%cached_face_value%cached_p_dshape) then |
977 | + |
978 | + p_dshape => di%cached_face_value%p_dshape(:,:,:,vele) |
979 | + |
980 | + else |
981 | + |
982 | + call transform_to_physical(di%positions, vele, x_shape = di%x_cvshape_full, & |
983 | + shape = di%p_cvshape_full, dshape = p_dshape) |
984 | + |
985 | + end if |
986 | + |
987 | + ! get the gradient capilliary pressure at the cv surface quadrature points for each direction |
988 | + if (p > 1) then |
989 | + grad_cap_pressure_face_quad = & |
990 | + &darcy_impes_ele_grad_at_quad_scalar(di%capilliary_pressure(p)%ptr, vele, dn = p_dshape) |
991 | + end if |
992 | + |
993 | + ! Initialise array for the quadrature points of this |
994 | + ! element for whether it has already been visited |
995 | + notvisited = .true. |
996 | + |
997 | + ! Initialise the local p matrix and rhs to assemble for this element |
998 | + p_mat_local = 0.0 |
999 | + p_rhs_local = 0.0 |
1000 | + |
1001 | + ! loop over local nodes within this element |
1002 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
1003 | + |
1004 | + ! loop over CV faces internal to this element |
1005 | + face_loop: do face = 1, di%cvfaces%faces |
1006 | + |
1007 | + ! is this a face neighbouring iloc? |
1008 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
1009 | + |
1010 | + ! find the opposing local node across the CV face |
1011 | + oloc = di%cvfaces%neiloc(iloc, face) |
1012 | + |
1013 | + ! loop over gauss points on face |
1014 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
1015 | + |
1016 | + ! global gauss pt index for this element |
1017 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
1018 | + |
1019 | + ! check if this quadrature point has already been visited |
1020 | + check_visited: if(notvisited(ggi)) then |
1021 | + |
1022 | + notvisited(ggi) = .false. |
1023 | + |
1024 | + if (di%cached_face_value%cached_detwei_normal) then |
1025 | + |
1026 | + ! cached normal has correct orientation already |
1027 | + normgi = normal(:,ggi) |
1028 | + |
1029 | + else |
1030 | + |
1031 | + ! correct the orientation of the normal so it points away from iloc |
1032 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
1033 | + &x_face_quad(:,ggi), normal(:,ggi)) |
1034 | + |
1035 | + end if |
1036 | + |
1037 | + ! Form the face value = detwei * (relperm*absperm/visc) |
1038 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1039 | + |
1040 | + face_value = detwei(ggi) * & |
1041 | + sum(di%cached_face_value%relperm(:,ggi,vele,p)) * & |
1042 | + absperm_ele(1) / & |
1043 | + visc_ele(1) |
1044 | + |
1045 | + else |
1046 | + |
1047 | + face_value = detwei(ggi) * & |
1048 | + di%cached_face_value%relperm(1,ggi,vele,p) * & |
1049 | + absperm_ele(1) / & |
1050 | + visc_ele(1) |
1051 | + |
1052 | + end if |
1053 | + |
1054 | + ! Form the local matrix given by - n_i . sum_{phase} ( relperm*absperm/visc ) dP_1/dx_j |
1055 | + do jloc = 1,di%pressure_mesh%shape%loc |
1056 | + |
1057 | + p_mat_local(iloc,jloc) = p_mat_local(iloc,jloc) - & |
1058 | + sum(p_dshape(jloc, ggi, :)*normgi, 1) * & |
1059 | + face_value |
1060 | + |
1061 | + p_mat_local(oloc,jloc) = p_mat_local(oloc,jloc) - & |
1062 | + sum(p_dshape(jloc, ggi, :)*(-normgi), 1) * & |
1063 | + face_value |
1064 | + |
1065 | + end do |
1066 | + |
1067 | + ! Add gravity term to rhs = - n_i . sum_{phase} ( relperm*absperm/visc ) * den*grav |
1068 | + |
1069 | + ! Find g dot n |
1070 | + g_dot_n = dot_product(grav_ele(:,1), normgi) |
1071 | + |
1072 | + p_rhs_local(iloc) = p_rhs_local(iloc) - & |
1073 | + face_value * & |
1074 | + di%cached_face_value%den(ggi,vele,p) * & |
1075 | + g_dot_n |
1076 | + |
1077 | + ! Add opposite node value with change of sign due to opposite normal direction |
1078 | + p_rhs_local(oloc) = p_rhs_local(oloc) + & |
1079 | + face_value * & |
1080 | + di%cached_face_value%den(ggi,vele,p) * & |
1081 | + g_dot_n |
1082 | + |
1083 | + ! Add capilliary pressure term to rhs = n_i . sum_{phase} ( relperm*absperm/visc ) dP_c/dx_j |
1084 | + ! only for phase > 1 |
1085 | + if (p > 1) then |
1086 | + |
1087 | + ! Find grad_P_c dot n |
1088 | + grad_cap_p_dot_n = dot_product(grad_cap_pressure_face_quad(:,ggi), normgi) |
1089 | + |
1090 | + p_rhs_local(iloc) = p_rhs_local(iloc) + & |
1091 | + face_value * & |
1092 | + grad_cap_p_dot_n |
1093 | + |
1094 | + ! Add opposite node value with change of sign due to opposite normal direction |
1095 | + p_rhs_local(oloc) = p_rhs_local(oloc) - & |
1096 | + face_value * & |
1097 | + grad_cap_p_dot_n |
1098 | + |
1099 | + end if |
1100 | + |
1101 | + end if check_visited |
1102 | + |
1103 | + end do quadrature_loop |
1104 | + |
1105 | + end if is_neigh |
1106 | + |
1107 | + end do face_loop |
1108 | + |
1109 | + end do nodal_loop_i |
1110 | + |
1111 | + end subroutine pressure_volume_element_local_assemble |
1112 | + |
1113 | + ! -------------------------------------------------------------------------------------- |
1114 | + |
1115 | + subroutine pressure_surface_element_local_assemble(di) |
1116 | + |
1117 | + !!< Assemble the local surface element pressure matrix and rhs |
1118 | + |
1119 | + type(darcy_impes_type), intent(inout) :: di |
1120 | + |
1121 | + p_matrix_local_bdy = 0.0 |
1122 | + p_rhs_local_bdy = 0.0 |
1123 | + |
1124 | + p_nodes_bdy = face_global_nodes(di%pressure_mesh, sele) |
1125 | + |
1126 | + ! A no_normal_flow BC adds nothing to the matrix and rhs so return zeros |
1127 | + if (di%v_bc_flag(sele) == V_BC_TYPE_NO_NORMAL_FLOW) return |
1128 | + |
1129 | + ! If phase 1 and strong pressure BC then no need to add integrals so return zeros |
1130 | + if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_DIRICHLET) return |
1131 | + |
1132 | + ! obtain the transformed determinant*weight and normals |
1133 | + if (di%cached_face_value%cached_detwei_normal) then |
1134 | + |
1135 | + detwei_bdy => di%cached_face_value%detwei_bdy(:,sele) |
1136 | + |
1137 | + normal_bdy => di%cached_face_value%normal_bdy(:,:,sele) |
1138 | + |
1139 | + else |
1140 | + |
1141 | + x_ele = ele_val(di%positions, face_ele(di%positions, sele)) |
1142 | + x_ele_bdy = face_val(di%positions, sele) |
1143 | + |
1144 | + call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, di%x_cvbdyshape, normal_bdy, detwei_bdy) |
1145 | + |
1146 | + end if |
1147 | + |
1148 | + if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
1149 | + |
1150 | + bc_sele_val = ele_val(di%v_bc_value, sele) |
1151 | + |
1152 | + else |
1153 | + |
1154 | + ! get the viscosity value for this sele for this phase |
1155 | + visc_ele_bdy = face_val(di%viscosity(p)%ptr, sele) |
1156 | + |
1157 | + ! get the absolute permeability value for this sele |
1158 | + absperm_ele_bdy = face_val(di%absolute_permeability, sele) |
1159 | + |
1160 | + ! the inverse characteristic length used for pressure weak bc |
1161 | + inv_char_len_ele_bdy = ele_val(di%inverse_characteristic_length, sele) |
1162 | + |
1163 | + ! Get the pressure BC value if required |
1164 | + if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
1165 | + |
1166 | + bc_sele_val = ele_val(di%pressure_bc_value, sele) |
1167 | + |
1168 | + end if |
1169 | + |
1170 | + ! The gravity values for this element for each direction |
1171 | + grav_ele_bdy = face_val(di%gravity, sele) |
1172 | + |
1173 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
1174 | +!!!!! ! get the gradient capilliary pressure at the cv surface quadrature points for each direction |
1175 | +!!!!! if (p > 1) then |
1176 | +!!!!! grad_cap_pressure_face_quad_bdy = & |
1177 | +!!!!! &darcy_impes_face_grad_at_quad_scalar(di%capilliary_pressure(p)%ptr, sele, dn = p_dshape) |
1178 | +!!!!! end if |
1179 | + |
1180 | +!!!!! ! obtain the derivative of the pressure mesh shape function at the CV face quadrature points |
1181 | +!!!!! if (di%cached_face_value%cached_p_dshape) then |
1182 | + |
1183 | +!!!!! p_dshape_bdy => di%cached_face_value%p_dshape_bdy(:,:,:,sele) |
1184 | + |
1185 | +!!!!! else |
1186 | + |
1187 | +!!!!! call transform_to_physical(di%positions, sele, x_shape = di%x_cvbdyshape_full, & |
1188 | +!!!!! shape = di%p_cvbdyshape_full, dshape = p_dshape_bdy) |
1189 | + |
1190 | +!!!!! end if |
1191 | + |
1192 | + end if |
1193 | + |
1194 | + bc_iloc_loop: do iloc = 1, di%pressure_mesh%faces%shape%loc |
1195 | + |
1196 | + bc_face_loop: do face = 1, di%cvfaces%sfaces |
1197 | + |
1198 | + bc_neigh_if: if(di%cvfaces%sneiloc(iloc,face)/=0) then |
1199 | + |
1200 | + bc_quad_loop: do gi = 1, di%cvfaces%shape%ngi |
1201 | + |
1202 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
1203 | + |
1204 | + prescribed_normal_flow: if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
1205 | + |
1206 | + ! If have prescribed_normal_flow BC for this phase then include CV integral of value |
1207 | + |
1208 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1209 | + |
1210 | + p_rhs_local_bdy(iloc) = p_rhs_local_bdy(iloc) - & |
1211 | + di%subcy_opt_sat%number * & |
1212 | + bc_sele_val(iloc) * & |
1213 | + detwei_bdy(ggi) |
1214 | + |
1215 | + else |
1216 | + |
1217 | + p_rhs_local_bdy(iloc) = p_rhs_local_bdy(iloc) - & |
1218 | + bc_sele_val(iloc) * & |
1219 | + detwei_bdy(ggi) |
1220 | + |
1221 | + end if |
1222 | + |
1223 | + else prescribed_normal_flow |
1224 | + |
1225 | + ! Form the face value = detwei * (relperm*absperm/visc) |
1226 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1227 | + |
1228 | + face_value = detwei_bdy(ggi) * & |
1229 | + sum(di%cached_face_value%relperm_bdy(:,ggi,sele,p)) * & |
1230 | + absperm_ele_bdy(1) / & |
1231 | + visc_ele_bdy(1) |
1232 | + |
1233 | + else |
1234 | + |
1235 | + face_value = detwei_bdy(ggi) * & |
1236 | + di%cached_face_value%relperm_bdy(1,ggi,sele,p) * & |
1237 | + absperm_ele_bdy(1) / & |
1238 | + visc_ele_bdy(1) |
1239 | + |
1240 | + end if |
1241 | + |
1242 | + ! Add gravity term to rhs = - n_i . sum_{phase} ( relperm*absperm/visc ) * den*grav |
1243 | + |
1244 | + ! Find g dot n |
1245 | + g_dot_n = dot_product(grav_ele_bdy(:,1), normal_bdy(:,ggi)) |
1246 | + |
1247 | + p_rhs_local_bdy(iloc) = p_rhs_local_bdy(iloc) - & |
1248 | + face_value * & |
1249 | + di%cached_face_value%den_bdy(ggi,sele,p) * & |
1250 | + g_dot_n |
1251 | + |
1252 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
1253 | +!!!!! ! Add capilliary pressure term to rhs = n_i . sum_{phase} ( relperm*absperm/visc ) dP_c/dx_j |
1254 | +!!!!! ! only for phase > 1 |
1255 | +!!!!! if (p > 1) then |
1256 | + |
1257 | +!!!!! ! Find grad_P_c dot n |
1258 | +!!!!! grad_cap_p_dot_n = dot_product(grad_cap_pressure_face_quad_bdy(:,ggi), normal_bdy(:,ggi)) |
1259 | + |
1260 | +!!!!! p_rhs_local(iloc) = p_rhs_local(iloc) + & |
1261 | +!!!!! face_value * & |
1262 | +!!!!! grad_cap_p_dot_n |
1263 | + |
1264 | +!!!!! end if |
1265 | + |
1266 | +!!!!! ! Add implicit gradient of pressure phase 1 to matrix with coeff |
1267 | +!!!!! ! - n_i . sum_{phase} ( relperm*absperm/visc ) |
1268 | + |
1269 | + |
1270 | + ! If have phase weak pressure BC then include integral of BC value in rhs |
1271 | + ! and an implicit surface mass matrix term |
1272 | + pressure_weak: if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
1273 | + |
1274 | + do jloc = 1,di%pressure_mesh%faces%shape%loc |
1275 | + |
1276 | + p_rhs_local_bdy(iloc) = p_rhs_local_bdy(iloc) - & |
1277 | + inv_char_len_ele_bdy(jloc) * & |
1278 | + di%p_cvbdyshape%n(jloc,ggi) * & |
1279 | + bc_sele_val(jloc) * & |
1280 | + sum(normal_bdy(:,ggi)) * & |
1281 | + face_value * & |
1282 | + di%weak_pressure_bc_coeff |
1283 | + |
1284 | + end do |
1285 | + |
1286 | + do jloc = 1,di%pressure_mesh%faces%shape%loc |
1287 | + |
1288 | + p_matrix_local_bdy(iloc,jloc) = p_matrix_local_bdy(iloc,jloc) - & |
1289 | + inv_char_len_ele_bdy(jloc) * & |
1290 | + di%p_cvbdyshape%n(jloc,ggi) * & |
1291 | + sum(normal_bdy(:,ggi)) * & |
1292 | + face_value * & |
1293 | + di%weak_pressure_bc_coeff |
1294 | + |
1295 | + end do |
1296 | + |
1297 | + end if pressure_weak |
1298 | + |
1299 | + end if prescribed_normal_flow |
1300 | + |
1301 | + end do bc_quad_loop |
1302 | + |
1303 | + end if bc_neigh_if |
1304 | + |
1305 | + end do bc_face_loop |
1306 | + |
1307 | + end do bc_iloc_loop |
1308 | + |
1309 | + end subroutine pressure_surface_element_local_assemble |
1310 | + |
1311 | + ! -------------------------------------------------------------------------------------- |
1312 | + |
1313 | + end subroutine darcy_impes_assemble_and_solve_first_phase_pressure |
1314 | + |
1315 | +! ---------------------------------------------------------------------------- |
1316 | + |
1317 | + subroutine darcy_impes_get_v_boundary_condition(v, & |
1318 | + types, & |
1319 | + bc_surface_mesh, & |
1320 | + v_bc_value, & |
1321 | + v_bc_flag) |
1322 | + |
1323 | + !!< Form the data associated with any v BC by returning |
1324 | + !!< full surface mesh arrays of a flag indicating either |
1325 | + !!< no_normal_flow or prescribed_normal_flow and the value. |
1326 | + |
1327 | + type(vector_field), intent(in), target :: v |
1328 | + character(len=*), dimension(:), intent(in) :: types |
1329 | + type(mesh_type), intent(in) :: bc_surface_mesh |
1330 | + type(scalar_field), intent(inout) :: v_bc_value |
1331 | + integer, dimension(:), intent(inout) :: v_bc_flag |
1332 | + |
1333 | + ! Local variables |
1334 | + character(len=FIELD_NAME_LEN) :: bctype |
1335 | + type(scalar_field) :: scalar_surface_field |
1336 | + integer, dimension(:), pointer :: surface_element_list |
1337 | + integer :: i, j, k, sele |
1338 | + |
1339 | + ewrite(1,*) 'Get DarcyVelocity boundary condition data' |
1340 | + |
1341 | + ! Zero the prescribed_normal_flow value surface field on whole boundary mesh |
1342 | + call zero(v_bc_value) |
1343 | + |
1344 | + ! Initialise flag for whether surface element has prescribed_normal_flow BC |
1345 | + v_bc_flag = 0 |
1346 | + |
1347 | + ! Loop each BC object instance for the v |
1348 | + ! (May have multiple prescribed_normal_flow BC's applied to different surface id's) |
1349 | + BC_loop: do i=1, get_boundary_condition_count(v) |
1350 | + |
1351 | + ! Get this BC info |
1352 | + call get_boundary_condition(v, i, type = bctype, & |
1353 | + surface_element_list = surface_element_list) |
1354 | + |
1355 | + ! check this is a prescribed_normal_flow BC or no_normal_flow (nothing else is permitted) |
1356 | + if ((trim(bctype) /= 'prescribed_normal_flow') .and. (trim(bctype) /= 'no_normal_flow')) then |
1357 | + FLAbort('Have unknown BC type for a DarcyVelocity') |
1358 | + end if |
1359 | + |
1360 | + ! Extract the surface_field for this BC for prescribed_normal_flow |
1361 | + if (trim(bctype) == 'prescribed_normal_flow') then |
1362 | + if (associated(v%bc%boundary_condition(i)%surface_fields)) then |
1363 | + scalar_surface_field = extract_scalar_field(& |
1364 | + v%bc%boundary_condition(i)%surface_fields(1), 1) |
1365 | + else |
1366 | + FLAbort('Component surface_fields for DarcyVelocity BC type not associated') |
1367 | + end if |
1368 | + end if |
1369 | + |
1370 | + ! Loop the surface elements associated with this BC instance |
1371 | + ! and place the required BC value in whole boundary field |
1372 | + ! for the prescribed_normal_flow BC type |
1373 | + BC_sele_loop: do k = 1, size(surface_element_list) |
1374 | + |
1375 | + ! Find the whole domain surface element number |
1376 | + sele = surface_element_list(k) |
1377 | + |
1378 | + ! Check that there is only 1 BC applied per surface element |
1379 | + if (v_bc_flag(sele) /= 0) then |
1380 | + FLExit('Cannot apply more than 1 BC to a surface element for DarcyVelocity') |
1381 | + end if |
1382 | + |
1383 | + ! Set the sele flag to indicate the BC type |
1384 | + do j = 1, size(types) |
1385 | + if (trim(types(j)) == trim(bctype)) exit |
1386 | + end do |
1387 | + if (j > size(types)) then |
1388 | + FLAbort('Cannot find no_normal_flow or prescribed_normal_flow bctype for DarcyVelocity') |
1389 | + end if |
1390 | + |
1391 | + v_bc_flag(sele) = j |
1392 | + |
1393 | + ! Set the prescribed_normal_flow field values from this BC for its sele |
1394 | + if (trim(bctype) == 'prescribed_normal_flow') then |
1395 | + call set(v_bc_value, & |
1396 | + ele_nodes(bc_surface_mesh, sele), & |
1397 | + ele_val(scalar_surface_field, k)) |
1398 | + end if |
1399 | + |
1400 | + end do BC_sele_loop |
1401 | + |
1402 | + end do BC_loop |
1403 | + |
1404 | + ewrite_minmax(v_bc_value) |
1405 | + |
1406 | + ewrite(1,*) 'Finished get DarcyVelocity boundary condition data' |
1407 | + |
1408 | + end subroutine darcy_impes_get_v_boundary_condition |
1409 | + |
1410 | +! ---------------------------------------------------------------------------- |
1411 | + |
1412 | + subroutine darcy_impes_get_entire_sfield_boundary_condition(sfield, & |
1413 | + types, & |
1414 | + bc_surface_mesh, & |
1415 | + sfield_bc_value, & |
1416 | + sfield_bc_flag) |
1417 | + |
1418 | + !!< Get the entire BC data for either the saturation or pressure field |
1419 | + |
1420 | + type(scalar_field), intent(in), target :: sfield |
1421 | + character(len=*), dimension(:), intent(in) :: types |
1422 | + type(mesh_type), intent(in) :: bc_surface_mesh |
1423 | + type(scalar_field), intent(inout) :: sfield_bc_value |
1424 | + integer, dimension(:), intent(inout) :: sfield_bc_flag |
1425 | + |
1426 | + ! local variables |
1427 | + character(len=FIELD_NAME_LEN) :: bctype |
1428 | + type(scalar_field), pointer :: surface_field |
1429 | + integer, dimension(:), pointer :: surface_element_list |
1430 | + integer :: i, j, k, sele |
1431 | + |
1432 | + ewrite(1,*) 'Get ',trim(sfield%name),' boundary condition data' |
1433 | + |
1434 | + ! zero the bc value field |
1435 | + call zero(sfield_bc_value) |
1436 | + |
1437 | + ! Initialise the bc type list for each sele |
1438 | + sfield_bc_flag = 0 |
1439 | + |
1440 | + ! Loop each BC object for the sfield |
1441 | + ! (May have multiple BC's applied to different suface id's) |
1442 | + BC_loop: do i=1, get_boundary_condition_count(sfield) |
1443 | + |
1444 | + ! Get this BC info |
1445 | + call get_boundary_condition(sfield, i, type = bctype, & |
1446 | + surface_element_list = surface_element_list) |
1447 | + |
1448 | + ! see if we're interested in this one, if not skip it |
1449 | + do j = 1, size(types) |
1450 | + if (trim(types(j)) == trim(bctype)) exit |
1451 | + end do |
1452 | + if (j > size(types)) cycle |
1453 | + |
1454 | + ! Extract the surface field for this BC |
1455 | + if (associated(sfield%bc%boundary_condition(i)%surface_fields)) then |
1456 | + ! extract 1st surface field |
1457 | + surface_field => sfield%bc%boundary_condition(i)%surface_fields(1) |
1458 | + else |
1459 | + FLAbort('Component surface_fields for Saturation or Pressure BC type not associated') |
1460 | + end if |
1461 | + |
1462 | + ! Loop the surface elements associated with this BC instance |
1463 | + ! and place the required BC value in whole boundary field |
1464 | + BC_sele_loop: do k = 1, size(surface_element_list) |
1465 | + |
1466 | + ! Find the whole domain surface element number |
1467 | + sele = surface_element_list(k) |
1468 | + |
1469 | + ! Check that there is only 1 BC applied per surface element |
1470 | + if (sfield_bc_flag(sele)/=0) then |
1471 | + ewrite(0,*) 'Requested types:', types |
1472 | + ewrite(0,*) 'Of these boundary condition types only one may be applied' |
1473 | + ewrite(0,*) 'to each surface element.' |
1474 | + ewrite(0,*) 'Surface element nr.:', sele |
1475 | + ewrite(0,*) 'has types', types(sfield_bc_flag(sele)), bctype |
1476 | + ewrite(0,*) 'on field: ', sfield%name |
1477 | + FLAbort('Issue with BC data for Saturation or Pressure') |
1478 | + end if |
1479 | + |
1480 | + ! Set the sele flag to indicate the BC type |
1481 | + sfield_bc_flag(sele) = j |
1482 | + |
1483 | + ! Set the BC sfield values from this BC for its sele |
1484 | + call set(sfield_bc_value, & |
1485 | + ele_nodes(bc_surface_mesh, sele), & |
1486 | + ele_val(surface_field, k)) |
1487 | + |
1488 | + end do BC_sele_loop |
1489 | + |
1490 | + end do BC_loop |
1491 | + |
1492 | + ewrite_minmax(sfield_bc_value) |
1493 | + |
1494 | + ewrite(1,*) 'Finished get ',trim(sfield%name),' boundary condition data' |
1495 | + |
1496 | + end subroutine darcy_impes_get_entire_sfield_boundary_condition |
1497 | + |
1498 | +! ---------------------------------------------------------------------------- |
1499 | + |
1500 | + subroutine darcy_impes_calculate_non_first_phase_pressures(di) |
1501 | + |
1502 | + !!< Calcuate the non first phase pressures which = first_phase_pressure + capilliary pressure |
1503 | + |
1504 | + type(darcy_impes_type), intent(inout) :: di |
1505 | + |
1506 | + ! local variables |
1507 | + integer :: p |
1508 | + |
1509 | + ewrite(1,*) 'Calculate Non first phase Pressures' |
1510 | + |
1511 | + phase_loop: do p = 2, di%number_phase |
1512 | + |
1513 | + call set(di%pressure(p)%ptr, di%pressure(1)%ptr) |
1514 | + |
1515 | + call addto(di%pressure(p)%ptr, di%capilliary_pressure(p)%ptr) |
1516 | + |
1517 | + ewrite_minmax(di%pressure(p)%ptr) |
1518 | + |
1519 | + end do phase_loop |
1520 | + |
1521 | + ewrite(1,*) 'Finished Calculate Non first phase Pressures' |
1522 | + |
1523 | + end subroutine darcy_impes_calculate_non_first_phase_pressures |
1524 | + |
1525 | +! ---------------------------------------------------------------------------- |
1526 | + |
1527 | + subroutine darcy_impes_calculate_average_pressure(di) |
1528 | + |
1529 | + !!< Calcuate the average phase pressure |
1530 | + |
1531 | + type(darcy_impes_type), intent(inout) :: di |
1532 | + |
1533 | + ! local variables |
1534 | + integer :: p |
1535 | + |
1536 | + ewrite(1,*) 'Calculate AveragePressure' |
1537 | + |
1538 | + call zero(di%average_pressure) |
1539 | + |
1540 | + phase_loop: do p = 1, di%number_phase |
1541 | + |
1542 | + call addto(di%average_pressure, di%pressure(p)%ptr) |
1543 | + |
1544 | + end do phase_loop |
1545 | + |
1546 | + call scale(di%average_pressure, 1.0/real(di%number_phase)) |
1547 | + |
1548 | + ewrite_minmax(di%average_pressure) |
1549 | + |
1550 | + ewrite(1,*) 'Finished Calculate AveragePressure' |
1551 | + |
1552 | + end subroutine darcy_impes_calculate_average_pressure |
1553 | + |
1554 | +! ---------------------------------------------------------------------------- |
1555 | + |
1556 | + subroutine darcy_impes_calculate_gradient_pressures(di) |
1557 | + |
1558 | + !!< Calculate the gradient pressures for each phase |
1559 | + |
1560 | + ! This routine requires optimisation and would become |
1561 | + ! not required if ele_grad_at_quad is used for pressure |
1562 | + ! and a face_grad_at_quad is made available |
1563 | + |
1564 | + type(darcy_impes_type), intent(inout) :: di |
1565 | + |
1566 | + ! local variables |
1567 | + integer :: p |
1568 | + |
1569 | + ewrite(1,*) 'Calculate GradientPressure for each phase' |
1570 | + |
1571 | + phase_loop: do p = 1, di%number_phase |
1572 | + |
1573 | + call grad(di%pressure(p)%ptr, & |
1574 | + di%positions, & |
1575 | + di%gradient_pressure(p)%ptr) |
1576 | + |
1577 | + ewrite_minmax(di%gradient_pressure(p)%ptr) |
1578 | + |
1579 | + end do phase_loop |
1580 | + |
1581 | + ewrite(1,*) 'Finished Calculate GradientPressure for each phase' |
1582 | + |
1583 | + end subroutine darcy_impes_calculate_gradient_pressures |
1584 | + |
1585 | +! ---------------------------------------------------------------------------- |
1586 | + |
1587 | + subroutine darcy_impes_calculate_divergence_total_darcy_velocity(di) |
1588 | + |
1589 | + !!< Calculate the divergence of the total divergence velocity, |
1590 | + !!< which may include terms summed over subcycles |
1591 | + |
1592 | + type(darcy_impes_type), intent(inout) :: di |
1593 | + |
1594 | + ! local variables |
1595 | + integer :: vele, p, iloc, oloc, jloc, face, gi, ggi, sele, dim |
1596 | + real :: darcy_vel_face_value_dot_n, v_over_relperm_dot_n, face_value |
1597 | + real, dimension(1) :: absperm_ele, visc_ele |
1598 | + real, dimension(:,:), pointer :: grad_pressure_face_quad |
1599 | + real, dimension(:,:), pointer :: grav_ele |
1600 | + real, dimension(:,:), pointer :: x_ele |
1601 | + real, dimension(:,:), pointer :: normal |
1602 | + real, dimension(:), pointer :: detwei |
1603 | + real, dimension(:), pointer :: normgi |
1604 | + logical, dimension(:), pointer :: notvisited |
1605 | + real, dimension(:), pointer :: div_tvel_rhs_local |
1606 | + real, dimension(:,:), pointer :: x_face_quad |
1607 | + integer, dimension(:), pointer :: x_pmesh_nodes |
1608 | + integer, dimension(:), pointer :: p_nodes |
1609 | + real, dimension(1) :: absperm_ele_bdy, visc_ele_bdy |
1610 | + real, dimension(:,:), pointer :: grav_ele_bdy |
1611 | + real, dimension(:,:), pointer :: grad_pressure_face_quad_bdy |
1612 | + real, dimension(:,:), pointer :: v_over_relperm_face_quad_bdy |
1613 | + real, dimension(:), pointer :: bc_sele_val |
1614 | + real, dimension(:), pointer :: pressure_ele_bdy |
1615 | + real, dimension(:), pointer :: inv_char_len_ele_bdy |
1616 | + real, dimension(:,:), pointer :: normal_bdy |
1617 | + real, dimension(:), pointer :: detwei_bdy |
1618 | + real, dimension(:,:), pointer :: x_ele_bdy |
1619 | + real, dimension(:), pointer :: div_tvel_rhs_local_bdy |
1620 | + integer, dimension(:), pointer :: p_nodes_bdy |
1621 | + integer, parameter :: V_BC_TYPE_PRESCRIBED_NORMAL_FLOW = 1, V_BC_TYPE_NO_NORMAL_FLOW = 2 |
1622 | + integer, parameter :: PRESSURE_BC_TYPE_WEAKDIRICHLET = 1 |
1623 | + |
1624 | + ewrite(1,*) 'Calculate the DivergenceTotalDarcyVelocity' |
1625 | + |
1626 | + ! allocate arrays used in assemble process - many assume |
1627 | + ! that all elements are the same type. |
1628 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
1629 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
1630 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
1631 | + allocate(detwei(di%x_cvshape%ngi)) |
1632 | + end if |
1633 | + allocate(normgi(di%ndim)) |
1634 | + allocate(notvisited(di%x_cvshape%ngi)) |
1635 | + allocate(div_tvel_rhs_local(ele_loc(di%pressure_mesh,1))) |
1636 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
1637 | + allocate(grad_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
1638 | + allocate(grav_ele(di%ndim,1)) |
1639 | + |
1640 | + allocate(grav_ele_bdy(di%ndim,1)) |
1641 | + allocate(grad_pressure_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
1642 | + allocate(v_over_relperm_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
1643 | + allocate(bc_sele_val(face_loc(di%pressure_mesh,1))) |
1644 | + allocate(pressure_ele_bdy(face_loc(di%pressure_mesh,1))) |
1645 | + allocate(inv_char_len_ele_bdy(face_loc(di%pressure_mesh,1))) |
1646 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
1647 | + allocate(detwei_bdy(di%x_cvbdyshape%ngi)) |
1648 | + allocate(normal_bdy(di%ndim, di%x_cvbdyshape%ngi)) |
1649 | + end if |
1650 | + allocate(div_tvel_rhs_local_bdy(face_loc(di%pressure_mesh,1))) |
1651 | + allocate(x_ele_bdy(di%ndim, face_loc(di%positions,1))) |
1652 | + allocate(p_nodes_bdy(face_loc(di%pressure_mesh,1))) |
1653 | + |
1654 | + call zero(di%div_total_darcy_velocity) |
1655 | + |
1656 | + ! Get the pressure BC - required if no v given and weak pressure dirichlet given for extra integrals |
1657 | + call darcy_impes_get_entire_sfield_boundary_condition(di%pressure(1)%ptr, & |
1658 | + (/"weakdirichlet"/), & |
1659 | + di%bc_surface_mesh, & |
1660 | + di%pressure_bc_value, & |
1661 | + di%pressure_bc_flag) |
1662 | + |
1663 | + phase_loop: do p = 1, di%number_phase |
1664 | + |
1665 | + vele_loop: do vele = 1, di%number_vele |
1666 | + |
1667 | + ! The node indices of the pressure field |
1668 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
1669 | + |
1670 | + ! The gravity values for this element for each direction |
1671 | + grav_ele = ele_val(di%gravity, vele) |
1672 | + |
1673 | + ! get the viscosity value for this element for this phase |
1674 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
1675 | + |
1676 | + ! get the absolute permeability value for this element |
1677 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
1678 | + |
1679 | + ! get the latest gradient pressure at the cv surface quadrature points for each direction for this phase |
1680 | + grad_pressure_face_quad = ele_val_at_quad(di%gradient_pressure(p)%ptr, vele, di%gradp_cvshape) |
1681 | + |
1682 | + ! obtain the transformed determinant*weight and normals |
1683 | + if (di%cached_face_value%cached_detwei_normal) then |
1684 | + |
1685 | + detwei => di%cached_face_value%detwei(:,vele) |
1686 | + |
1687 | + normal => di%cached_face_value%normal(:,:,vele) |
1688 | + |
1689 | + else |
1690 | + |
1691 | + ! get the coordinate values for this element for each positions local node |
1692 | + x_ele = ele_val(di%positions, vele) |
1693 | + |
1694 | + ! get the coordinate values for this element for each quadrature point |
1695 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
1696 | + |
1697 | + ! The node indices of the positions projected to the pressure mesh |
1698 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
1699 | + |
1700 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
1701 | + |
1702 | + end if |
1703 | + |
1704 | + ! Initialise array for the quadrature points of this |
1705 | + ! element for whether it has already been visited |
1706 | + notvisited = .true. |
1707 | + |
1708 | + ! Initialise the local rhs to assemble for this element |
1709 | + div_tvel_rhs_local = 0.0 |
1710 | + |
1711 | + ! loop over local nodes within this element |
1712 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
1713 | + |
1714 | + ! loop over CV faces internal to this element |
1715 | + face_loop: do face = 1, di%cvfaces%faces |
1716 | + |
1717 | + ! is this a face neighbouring iloc? |
1718 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
1719 | + |
1720 | + ! find the opposing local node across the CV face |
1721 | + oloc = di%cvfaces%neiloc(iloc, face) |
1722 | + |
1723 | + ! loop over gauss points on face |
1724 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
1725 | + |
1726 | + ! global gauss pt index for this element |
1727 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
1728 | + |
1729 | + ! check if this quadrature point has already been visited |
1730 | + check_visited: if(notvisited(ggi)) then |
1731 | + |
1732 | + notvisited(ggi) = .false. |
1733 | + |
1734 | + if (di%cached_face_value%cached_detwei_normal) then |
1735 | + |
1736 | + ! cached normal has correct orientation already |
1737 | + normgi = normal(:,ggi) |
1738 | + |
1739 | + else |
1740 | + |
1741 | + ! correct the orientation of the normal so it points away from iloc |
1742 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
1743 | + &x_face_quad(:,ggi), normal(:,ggi)) |
1744 | + |
1745 | + end if |
1746 | + |
1747 | + ! Form the face value = detwei * (relperm*absperm/visc) |
1748 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1749 | + |
1750 | + face_value = detwei(ggi) * & |
1751 | + sum(di%cached_face_value%relperm(:,ggi,vele,p)) * & |
1752 | + absperm_ele(1) / & |
1753 | + visc_ele(1) |
1754 | + |
1755 | + else |
1756 | + |
1757 | + face_value = detwei(ggi) * & |
1758 | + di%cached_face_value%relperm(1,ggi,vele,p) * & |
1759 | + absperm_ele(1) / & |
1760 | + visc_ele(1) |
1761 | + |
1762 | + end if |
1763 | + |
1764 | + darcy_vel_face_value_dot_n = - dot_product( normgi, & |
1765 | + &face_value * (grad_pressure_face_quad(:,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(:,1)) ) |
1766 | + |
1767 | + div_tvel_rhs_local(iloc) = div_tvel_rhs_local(iloc) + & |
1768 | + darcy_vel_face_value_dot_n |
1769 | + |
1770 | + div_tvel_rhs_local(oloc) = div_tvel_rhs_local(oloc) - & |
1771 | + darcy_vel_face_value_dot_n |
1772 | + |
1773 | + end if check_visited |
1774 | + |
1775 | + end do quadrature_loop |
1776 | + |
1777 | + end if is_neigh |
1778 | + |
1779 | + end do face_loop |
1780 | + |
1781 | + end do nodal_loop_i |
1782 | + |
1783 | + call addto(di%div_total_darcy_velocity, p_nodes, div_tvel_rhs_local) |
1784 | + |
1785 | + end do vele_loop |
1786 | + |
1787 | + ! Get this phase v BC info - only for no_normal_flow and prescribed_normal_flow which is special as it is a scalar |
1788 | + call darcy_impes_get_v_boundary_condition(di%darcy_velocity(p)%ptr, & |
1789 | + (/"prescribed_normal_flow", & |
1790 | + "no_normal_flow "/), & |
1791 | + di%bc_surface_mesh, & |
1792 | + di%v_bc_value, & |
1793 | + di%v_bc_flag) |
1794 | + |
1795 | + sele_loop: do sele = 1, di%number_sele |
1796 | + |
1797 | + if (di%v_bc_flag(sele) == V_BC_TYPE_NO_NORMAL_FLOW) cycle sele_loop |
1798 | + |
1799 | + p_nodes_bdy = face_global_nodes(di%pressure_mesh, sele) |
1800 | + |
1801 | + ! obtain the transformed determinant*weight and normals |
1802 | + if (di%cached_face_value%cached_detwei_normal) then |
1803 | + |
1804 | + detwei_bdy => di%cached_face_value%detwei_bdy(:,sele) |
1805 | + |
1806 | + normal_bdy => di%cached_face_value%normal_bdy(:,:,sele) |
1807 | + |
1808 | + else |
1809 | + |
1810 | + x_ele = ele_val(di%positions, face_ele(di%positions, sele)) |
1811 | + x_ele_bdy = face_val(di%positions, sele) |
1812 | + |
1813 | + call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, di%x_cvbdyshape, normal_bdy, detwei_bdy) |
1814 | + |
1815 | + end if |
1816 | + |
1817 | + if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
1818 | + |
1819 | + bc_sele_val = ele_val(di%v_bc_value, sele) |
1820 | + |
1821 | + else |
1822 | + |
1823 | + visc_ele_bdy = face_val(di%viscosity(p)%ptr, sele) |
1824 | + absperm_ele_bdy = face_val(di%absolute_permeability, sele) |
1825 | + inv_char_len_ele_bdy = ele_val(di%inverse_characteristic_length, sele) |
1826 | + if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
1827 | + bc_sele_val = ele_val(di%pressure_bc_value, sele) |
1828 | + end if |
1829 | + grad_pressure_face_quad_bdy = face_val_at_quad(di%gradient_pressure(p)%ptr, sele, di%gradp_cvbdyshape) |
1830 | + grav_ele_bdy = face_val(di%gravity, sele) |
1831 | + pressure_ele_bdy = face_val(di%pressure(p)%ptr, sele) |
1832 | + |
1833 | + ! the latest DarcyVelocity/relperm at the quadrature points |
1834 | + do dim = 1,di%ndim |
1835 | + |
1836 | + v_over_relperm_face_quad_bdy(dim,:) = & |
1837 | +- (absperm_ele_bdy(1) / visc_ele_bdy(1)) * & |
1838 | +(grad_pressure_face_quad_bdy(dim,:) - face_val_at_quad(di%density(p)%ptr, sele, di%p_cvbdyshape) * grav_ele_bdy(dim,1)) |
1839 | + |
1840 | + end do |
1841 | + |
1842 | + end if |
1843 | + |
1844 | + ! Initialise the local rhs to assemble for this element |
1845 | + div_tvel_rhs_local_bdy = 0.0 |
1846 | + |
1847 | + bc_iloc_loop: do iloc = 1, di%pressure_mesh%faces%shape%loc |
1848 | + |
1849 | + bc_face_loop: do face = 1, di%cvfaces%sfaces |
1850 | + |
1851 | + bc_neigh_if: if(di%cvfaces%sneiloc(iloc,face)/=0) then |
1852 | + |
1853 | + bc_quad_loop: do gi = 1, di%cvfaces%shape%ngi |
1854 | + |
1855 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
1856 | + |
1857 | + prescribed_normal_flow: if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
1858 | + |
1859 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1860 | + |
1861 | + div_tvel_rhs_local_bdy(iloc) = div_tvel_rhs_local_bdy(iloc) + & |
1862 | + di%subcy_opt_sat%number * & |
1863 | + bc_sele_val(iloc) * & |
1864 | + detwei_bdy(ggi) |
1865 | + |
1866 | + else |
1867 | + |
1868 | + div_tvel_rhs_local_bdy(iloc) = div_tvel_rhs_local_bdy(iloc) + & |
1869 | + bc_sele_val(iloc) * & |
1870 | + detwei_bdy(ggi) |
1871 | + |
1872 | + end if |
1873 | + |
1874 | + else prescribed_normal_flow |
1875 | + |
1876 | + ! NOTE this v_over_relperm_dot_n does not contain the relperm terms |
1877 | + v_over_relperm_dot_n = dot_product(v_over_relperm_face_quad_bdy(:,ggi), normal_bdy(:,ggi)) |
1878 | + |
1879 | + ! Adding this term includes the gradient of pressure, gradient of |
1880 | + ! capilliary pressure and the gravity term. |
1881 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1882 | + |
1883 | + div_tvel_rhs_local_bdy(iloc) = div_tvel_rhs_local_bdy(iloc) + & |
1884 | + sum(di%cached_face_value%relperm_bdy(:,ggi,sele,p)) * & |
1885 | + v_over_relperm_dot_n * & |
1886 | + detwei_bdy(ggi) |
1887 | + |
1888 | + else |
1889 | + |
1890 | + div_tvel_rhs_local_bdy(iloc) = div_tvel_rhs_local_bdy(iloc) + & |
1891 | + di%cached_face_value%relperm_bdy(1,ggi,sele,p) * & |
1892 | + v_over_relperm_dot_n * & |
1893 | + detwei_bdy(ggi) |
1894 | + |
1895 | + end if |
1896 | + |
1897 | + ! Add two extra terms associated with weak pressure BC's |
1898 | + |
1899 | + ! Add two extra terms associated with weak pressure BC's |
1900 | + pressure_weak: if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
1901 | + |
1902 | + ! Form the face value = detwei * (relperm*absperm/visc) |
1903 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
1904 | + |
1905 | + face_value = detwei_bdy(ggi) * & |
1906 | + sum(di%cached_face_value%relperm_bdy(:,ggi,sele,p)) * & |
1907 | + absperm_ele_bdy(1) / & |
1908 | + visc_ele_bdy(1) |
1909 | + |
1910 | + else |
1911 | + |
1912 | + face_value = detwei_bdy(ggi) * & |
1913 | + di%cached_face_value%relperm_bdy(1,ggi,sele,p) * & |
1914 | + absperm_ele_bdy(1) / & |
1915 | + visc_ele_bdy(1) |
1916 | + |
1917 | + end if |
1918 | + |
1919 | + do jloc = 1, di%pressure_mesh%faces%shape%loc |
1920 | + |
1921 | + div_tvel_rhs_local_bdy(iloc) = div_tvel_rhs_local_bdy(iloc) - & |
1922 | + inv_char_len_ele_bdy(jloc) * & |
1923 | + di%p_cvbdyshape%n(jloc,ggi) * & |
1924 | + bc_sele_val(jloc) * & |
1925 | + sum(normal_bdy(:,ggi)) * & |
1926 | + face_value * & |
1927 | + di%weak_pressure_bc_coeff |
1928 | + |
1929 | + end do |
1930 | + |
1931 | + do jloc = 1, di%pressure_mesh%faces%shape%loc |
1932 | + |
1933 | + div_tvel_rhs_local_bdy(iloc) = div_tvel_rhs_local_bdy(iloc) + & |
1934 | + inv_char_len_ele_bdy(jloc) * & |
1935 | + di%p_cvbdyshape%n(jloc,ggi) * & |
1936 | + pressure_ele_bdy(jloc) * & |
1937 | + sum(normal_bdy(:,ggi)) * & |
1938 | + face_value * & |
1939 | + di%weak_pressure_bc_coeff |
1940 | + |
1941 | + end do |
1942 | + |
1943 | + end if pressure_weak |
1944 | + |
1945 | + end if prescribed_normal_flow |
1946 | + |
1947 | + end do bc_quad_loop |
1948 | + |
1949 | + end if bc_neigh_if |
1950 | + |
1951 | + end do bc_face_loop |
1952 | + |
1953 | + end do bc_iloc_loop |
1954 | + |
1955 | + call addto(di%div_total_darcy_velocity, p_nodes_bdy, div_tvel_rhs_local_bdy) |
1956 | + |
1957 | + end do sele_loop |
1958 | + |
1959 | + end do phase_loop |
1960 | + |
1961 | + call scale(di%div_total_darcy_velocity, di%inverse_cv_mass_pressure_mesh) |
1962 | + |
1963 | + ewrite_minmax(di%div_total_darcy_velocity) |
1964 | + |
1965 | + ! deallocate local variables as required |
1966 | + deallocate(x_ele) |
1967 | + if (di%cached_face_value%cached_detwei_normal) then |
1968 | + nullify(detwei) |
1969 | + nullify(normal) |
1970 | + else |
1971 | + deallocate(detwei) |
1972 | + deallocate(normal) |
1973 | + end if |
1974 | + deallocate(normgi) |
1975 | + deallocate(notvisited) |
1976 | + deallocate(div_tvel_rhs_local) |
1977 | + deallocate(x_face_quad) |
1978 | + deallocate(grad_pressure_face_quad) |
1979 | + deallocate(grav_ele) |
1980 | + |
1981 | + deallocate(grav_ele_bdy) |
1982 | + deallocate(grad_pressure_face_quad_bdy) |
1983 | + deallocate(v_over_relperm_face_quad_bdy) |
1984 | + deallocate(bc_sele_val) |
1985 | + deallocate(pressure_ele_bdy) |
1986 | + deallocate(inv_char_len_ele_bdy) |
1987 | + if (di%cached_face_value%cached_detwei_normal) then |
1988 | + nullify(detwei_bdy) |
1989 | + nullify(normal_bdy) |
1990 | + else |
1991 | + deallocate(detwei_bdy) |
1992 | + deallocate(normal_bdy) |
1993 | + end if |
1994 | + deallocate(div_tvel_rhs_local_bdy) |
1995 | + deallocate(x_ele_bdy) |
1996 | + deallocate(p_nodes_bdy) |
1997 | + |
1998 | + ewrite(1,*) 'Finished Calculate the DivergenceTotalDarcyVelocity' |
1999 | + |
2000 | + end subroutine darcy_impes_calculate_divergence_total_darcy_velocity |
2001 | + |
2002 | +! ---------------------------------------------------------------------------- |
2003 | + |
2004 | + subroutine darcy_impes_assemble_and_solve_phase_saturations(di, & |
2005 | + form_new_subcycle_relperm_face_values, & |
2006 | + have_dual) |
2007 | + |
2008 | + !!< Assemble and solve the saturations for each subcycle. |
2009 | + !!< If form_new_subcycle_relperm_face_values is true |
2010 | + !!< and there are subcycles then new relperm face values are |
2011 | + !!< formed. Phase 1 is special as it may be either solved |
2012 | + !!< prognostically or calculated diagnostically from the |
2013 | + !!< other phase saturation values that are solved first (for each subcycle). |
2014 | + |
2015 | + type(darcy_impes_type), intent(inout) :: di |
2016 | + logical, intent(in) :: form_new_subcycle_relperm_face_values |
2017 | + logical, intent(in) :: have_dual |
2018 | + |
2019 | + ! local variables |
2020 | + integer :: p, isub, isub_index |
2021 | + real :: alpha_start, alpha_end |
2022 | + |
2023 | + ewrite(1,*) 'Assemble and solve the saturations for each phase' |
2024 | + |
2025 | + ! Solve the saturations for each subcycle via: |
2026 | + ! - Form the relperm face values for each phase if required |
2027 | + ! - For each phase: |
2028 | + ! - Form the lhs = cv_mass_sfield_mesh_with_porosity / dt |
2029 | + ! - Form the rhs time = cv_mass_pressure_mesh_with_old_porosity * old_saturation_field / dt and add to rhs |
2030 | + ! - Add the s_source to rhs, which may include the dual perm transmissibility term |
2031 | + ! - Assemble and add the rhs adv to rhs |
2032 | + ! - Apply any strong dirichlet BCs |
2033 | + ! - solve for latest saturations and copy to start subcycle saturations step |
2034 | + |
2035 | + ! Note: the porosity at the start and end of a subcycle time step |
2036 | + ! are linearly interpolated values from the main time step start and end |
2037 | + |
2038 | + ! Deduce the subcycle time step size |
2039 | + if (di%subcy_opt_sat%have) then |
2040 | + |
2041 | + di%dt_subcycle = di%dt/real(di%subcy_opt_sat%number) |
2042 | + |
2043 | + else |
2044 | + |
2045 | + di%dt_subcycle = di%dt |
2046 | + |
2047 | + end if |
2048 | + |
2049 | + ! Set the initial old saturation subcycle field |
2050 | + do p = 1, di%number_phase |
2051 | + call set(di%old_saturation_subcycle(p)%ptr, di%old_saturation(p)%ptr) |
2052 | + end do |
2053 | + |
2054 | + ! Get the pressure BC - required if no v given and weak pressure dirichlet given for extra integrals |
2055 | + call darcy_impes_get_entire_sfield_boundary_condition(di%pressure(1)%ptr, & |
2056 | + (/"weakdirichlet"/), & |
2057 | + di%bc_surface_mesh, & |
2058 | + di%pressure_bc_value, & |
2059 | + di%pressure_bc_flag) |
2060 | + |
2061 | + sub_loop: do isub = 1, di%subcy_opt_sat%number |
2062 | + |
2063 | + ewrite(1,*) 'Start subcycle ',isub |
2064 | + |
2065 | + ! form the start and end of subcycle dt |
2066 | + ! porosity linear interpolents |
2067 | + alpha_start = (isub - 1) / di%subcy_opt_sat%number |
2068 | + alpha_end = isub / di%subcy_opt_sat%number |
2069 | + |
2070 | + ! Determine the index for cached face values depending on subcycling |
2071 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
2072 | + isub_index = isub |
2073 | + else |
2074 | + isub_index = 1 |
2075 | + end if |
2076 | + |
2077 | + ! If this is not the first subcycle then form the relperms |
2078 | + ! for the start of this subcycle from the end of last subcycle sat |
2079 | + ! and face values if required |
2080 | + if (form_new_subcycle_relperm_face_values .and. (isub > 1)) then |
2081 | + call darcy_impes_calculate_relperm_fields(di) |
2082 | + |
2083 | + call darcy_impes_calculate_relperm_isub_face_values(di, isub_index) |
2084 | + end if |
2085 | + |
2086 | + phase_loop: do p = di%number_phase, 1, -1 |
2087 | + |
2088 | + ewrite(1,*) 'Assemble and solve phase ',p |
2089 | + |
2090 | + ! If this is phase 1 and it is diagnostic then calculate it and exit loop |
2091 | + if ((p == 1) .and. di%phase_one_saturation_diagnostic) then |
2092 | + |
2093 | + call darcy_impes_calculate_phase_one_saturation_diagnostic(di) |
2094 | + |
2095 | + ! Copy latest phase 1 solution to old subcycle field |
2096 | + call set(di%old_saturation_subcycle(1)%ptr, di%saturation(1)%ptr) |
2097 | + |
2098 | + exit phase_loop |
2099 | + |
2100 | + end if |
2101 | + |
2102 | + ! Allocate and get the BC data. If the BC is time dependent then |
2103 | + ! the end of overall time step values are used for all subcycles. |
2104 | + |
2105 | + ! Get this phase v BC info - only for no_normal_flow and prescribed_normal_flow which is special as it is a scalar |
2106 | + call darcy_impes_get_v_boundary_condition(di%darcy_velocity(p)%ptr, & |
2107 | + (/"prescribed_normal_flow", & |
2108 | + "no_normal_flow "/), & |
2109 | + di%bc_surface_mesh, & |
2110 | + di%v_bc_value, & |
2111 | + di%v_bc_flag) |
2112 | + |
2113 | + call zero(di%lhs) |
2114 | + call zero(di%rhs) |
2115 | + |
2116 | + call addto(di%lhs, di%cv_mass_pressure_mesh_with_porosity, scale = alpha_end / di%dt_subcycle) |
2117 | + |
2118 | + call addto(di%lhs, di%cv_mass_pressure_mesh_with_old_porosity, scale = (1.0 - alpha_end) / di%dt_subcycle) |
2119 | + |
2120 | + ! form the rhs time contribution and add |
2121 | + call addto(di%rhs, di%cv_mass_pressure_mesh_with_porosity, scale = alpha_start / di%dt_subcycle) |
2122 | + |
2123 | + call addto(di%rhs, di%cv_mass_pressure_mesh_with_old_porosity, scale = (1.0 - alpha_start) / di%dt_subcycle) |
2124 | + |
2125 | + call scale(di%rhs, di%old_saturation_subcycle(p)%ptr) |
2126 | + |
2127 | + ! Add the saturation_source contribution |
2128 | + call compute_cv_mass(di%positions, di%cv_mass_pressure_mesh_with_source, di%saturation_source(p)%ptr) |
2129 | + |
2130 | + ! Should this include porosity ?!?! |
2131 | + call addto(di%rhs, di%cv_mass_pressure_mesh_with_source) |
2132 | + |
2133 | + ! Add the dual source term |
2134 | + if (have_dual) then |
2135 | + call compute_cv_mass(di%positions, di%cv_mass_pressure_mesh_with_lambda_dual, di%transmissibility_lambda_dual(p)%ptr) |
2136 | + |
2137 | + call set(di%rhs_dual, di%pressure_other_porous_media(p)%ptr) |
2138 | + call addto(di%rhs_dual, di%pressure(p)%ptr, scale = -1.0) |
2139 | + call scale(di%rhs_dual, di%cv_mass_pressure_mesh_with_lambda_dual) |
2140 | + |
2141 | + call addto(di%rhs, di%rhs_dual) |
2142 | + end if |
2143 | + |
2144 | + ! assemble the rhs adv contribution and add |
2145 | + call darcy_impes_assemble_saturation_rhs_adv(di, & |
2146 | + p, & |
2147 | + isub_index) |
2148 | + |
2149 | + ! apply strong dirichlet BC |
2150 | + call apply_dirichlet_conditions(di%lhs, di%rhs, di%saturation(p)%ptr) |
2151 | + |
2152 | + ! Solve for the saturation |
2153 | + di%saturation(p)%ptr%val = di%rhs%val / di%lhs%val |
2154 | + |
2155 | + ! Update the halos |
2156 | + call halo_update(di%saturation(p)%ptr) |
2157 | + |
2158 | + ! Set the strong BC nodes to the values to be consistent |
2159 | + call set_dirichlet_consistent(di%saturation(p)%ptr) |
2160 | + |
2161 | + ! Copy latest solution to old subcycle |
2162 | + call set(di%old_saturation_subcycle(p)%ptr, di%saturation(p)%ptr) |
2163 | + |
2164 | + end do phase_loop |
2165 | + |
2166 | + end do sub_loop |
2167 | + |
2168 | + ewrite(1,*) 'Finished assemble and solve the saturations for each phase' |
2169 | + |
2170 | + end subroutine darcy_impes_assemble_and_solve_phase_saturations |
2171 | + |
2172 | +! ---------------------------------------------------------------------------- |
2173 | + |
2174 | + subroutine darcy_impes_assemble_saturation_rhs_adv(di, & |
2175 | + p, & |
2176 | + isub_index) |
2177 | + |
2178 | + !!< Assemble the rhs advection contribtion for saturation phase p |
2179 | + |
2180 | + type(darcy_impes_type), intent(inout) :: di |
2181 | + integer, intent(in) :: p |
2182 | + integer, intent(in) :: isub_index |
2183 | + |
2184 | + ! local variables |
2185 | + integer :: vele, iloc, oloc, jloc, face, gi, ggi, sele, dim |
2186 | + real :: face_value, v_over_relperm_dot_n |
2187 | + real, dimension(1) :: absperm_ele, visc_ele |
2188 | + real, dimension(:,:), pointer :: grad_pressure_face_quad |
2189 | + real, dimension(:,:), pointer :: grav_ele |
2190 | + real, dimension(:,:), pointer :: x_ele |
2191 | + real, dimension(:,:), pointer :: normal |
2192 | + real, dimension(:), pointer :: detwei |
2193 | + real, dimension(:), pointer :: normgi |
2194 | + logical, dimension(:), pointer :: notvisited |
2195 | + real, dimension(:), pointer :: s_rhs_local |
2196 | + real, dimension(:,:), pointer :: x_face_quad |
2197 | + integer, dimension(:), pointer :: x_pmesh_nodes |
2198 | + integer, dimension(:), pointer :: p_nodes |
2199 | + real, dimension(1) :: absperm_ele_bdy, visc_ele_bdy |
2200 | + real, dimension(:,:), pointer :: grav_ele_bdy |
2201 | + real, dimension(:,:), pointer :: grad_pressure_face_quad_bdy |
2202 | + real, dimension(:,:), pointer :: v_over_relperm_face_quad_bdy |
2203 | + real, dimension(:), pointer :: bc_sele_val |
2204 | + real, dimension(:), pointer :: pressure_ele_bdy |
2205 | + real, dimension(:), pointer :: inv_char_len_ele_bdy |
2206 | + real, dimension(:,:), pointer :: normal_bdy |
2207 | + real, dimension(:), pointer :: detwei_bdy |
2208 | + real, dimension(:,:), pointer :: x_ele_bdy |
2209 | + real, dimension(:), pointer :: s_rhs_local_bdy |
2210 | + integer, dimension(:), pointer :: p_nodes_bdy |
2211 | + integer, parameter :: V_BC_TYPE_PRESCRIBED_NORMAL_FLOW = 1, V_BC_TYPE_NO_NORMAL_FLOW = 2 |
2212 | + integer, parameter :: PRESSURE_BC_TYPE_WEAKDIRICHLET = 1 |
2213 | + |
2214 | + ! allocate arrays used in assemble process - many assume |
2215 | + ! that all elements are the same type. |
2216 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
2217 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
2218 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
2219 | + allocate(detwei(di%x_cvshape%ngi)) |
2220 | + end if |
2221 | + allocate(normgi(di%ndim)) |
2222 | + allocate(notvisited(di%x_cvshape%ngi)) |
2223 | + allocate(s_rhs_local(ele_loc(di%pressure_mesh,1))) |
2224 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
2225 | + allocate(grad_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
2226 | + allocate(grav_ele(di%ndim,1)) |
2227 | + |
2228 | + allocate(grav_ele_bdy(di%ndim,1)) |
2229 | + allocate(grad_pressure_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
2230 | + allocate(v_over_relperm_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
2231 | + allocate(bc_sele_val(face_loc(di%pressure_mesh,1))) |
2232 | + allocate(pressure_ele_bdy(face_loc(di%pressure_mesh,1))) |
2233 | + allocate(inv_char_len_ele_bdy(face_loc(di%pressure_mesh,1))) |
2234 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
2235 | + allocate(detwei_bdy(di%x_cvbdyshape%ngi)) |
2236 | + allocate(normal_bdy(di%ndim, di%x_cvbdyshape%ngi)) |
2237 | + end if |
2238 | + allocate(s_rhs_local_bdy(face_loc(di%pressure_mesh,1))) |
2239 | + allocate(x_ele_bdy(di%ndim, face_loc(di%positions,1))) |
2240 | + allocate(p_nodes_bdy(face_loc(di%pressure_mesh,1))) |
2241 | + |
2242 | + ! Loop volume elements assembling local contributions |
2243 | + vol_element_loop: do vele = 1, di%number_vele |
2244 | + |
2245 | + ! The node indices of the pressure mesh (which saturation is associated with) |
2246 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
2247 | + |
2248 | + ! The node indices of the positions projected to the pressure mesh (which saturation is associated with) |
2249 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
2250 | + |
2251 | + ! The gravity values for this element for each direction |
2252 | + grav_ele = ele_val(di%gravity, vele) |
2253 | + |
2254 | + ! get the viscosity value for this element |
2255 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
2256 | + |
2257 | + ! get the absolute permeability value for this element |
2258 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
2259 | + |
2260 | + ! get the latest gradient pressure at the cv surface quadrature points for each direction |
2261 | + grad_pressure_face_quad = ele_val_at_quad(di%gradient_pressure(p)%ptr, vele, di%gradp_cvshape) |
2262 | + |
2263 | + ! obtain the transformed determinant*weight and normals |
2264 | + if (di%cached_face_value%cached_detwei_normal) then |
2265 | + |
2266 | + detwei => di%cached_face_value%detwei(:,vele) |
2267 | + |
2268 | + normal => di%cached_face_value%normal(:,:,vele) |
2269 | + |
2270 | + else |
2271 | + |
2272 | + ! get the coordinate values for this element for each positions local node |
2273 | + x_ele = ele_val(di%positions, vele) |
2274 | + |
2275 | + ! get the coordinate values for this element for each quadrature point |
2276 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
2277 | + |
2278 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
2279 | + |
2280 | + end if |
2281 | + |
2282 | + ! Initialise array for the quadrature points of this |
2283 | + ! element for whether it has already been visited |
2284 | + notvisited = .true. |
2285 | + |
2286 | + ! Initialise the local rhs to assemble for this element |
2287 | + s_rhs_local = 0.0 |
2288 | + |
2289 | + ! loop over local nodes within this element |
2290 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
2291 | + |
2292 | + ! loop over CV faces internal to this element |
2293 | + face_loop: do face = 1, di%cvfaces%faces |
2294 | + |
2295 | + ! is this a face neighbouring iloc? |
2296 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
2297 | + |
2298 | + ! find the opposing local node across the CV face |
2299 | + oloc = di%cvfaces%neiloc(iloc, face) |
2300 | + |
2301 | + ! loop over gauss points on face |
2302 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
2303 | + |
2304 | + ! global gauss pt index for this element |
2305 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
2306 | + |
2307 | + ! check if this quadrature point has already been visited |
2308 | + check_visited: if(notvisited(ggi)) then |
2309 | + |
2310 | + notvisited(ggi) = .false. |
2311 | + |
2312 | + if (di%cached_face_value%cached_detwei_normal) then |
2313 | + |
2314 | + ! cached normal has correct orientation already |
2315 | + normgi = normal(:,ggi) |
2316 | + |
2317 | + else |
2318 | + |
2319 | + ! correct the orientation of the normal so it points away from iloc |
2320 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
2321 | + &x_face_quad(:,ggi), normal(:,ggi)) |
2322 | + |
2323 | + end if |
2324 | + |
2325 | + face_value = detwei(ggi) * di%cached_face_value%relperm(isub_index,ggi,vele,p) * absperm_ele(1) * & |
2326 | +dot_product((grad_pressure_face_quad(:,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(:,1)), normgi)/ visc_ele(1) |
2327 | + |
2328 | + ! Form the local rhs for iloc and opposing oloc with normal vector sign change |
2329 | + s_rhs_local(iloc) = s_rhs_local(iloc) + face_value |
2330 | + |
2331 | + s_rhs_local(oloc) = s_rhs_local(oloc) - face_value |
2332 | + |
2333 | + end if check_visited |
2334 | + |
2335 | + end do quadrature_loop |
2336 | + |
2337 | + end if is_neigh |
2338 | + |
2339 | + end do face_loop |
2340 | + |
2341 | + end do nodal_loop_i |
2342 | + |
2343 | + ! Add volume element contribution to global rhs field |
2344 | + call addto(di%rhs, p_nodes, s_rhs_local) |
2345 | + |
2346 | + end do vol_element_loop |
2347 | + |
2348 | + ! Add BC integrals |
2349 | + |
2350 | + sele_loop: do sele = 1, di%number_sele |
2351 | + |
2352 | + if (di%v_bc_flag(sele) == V_BC_TYPE_NO_NORMAL_FLOW) cycle sele_loop |
2353 | + |
2354 | + p_nodes_bdy = face_global_nodes(di%pressure_mesh, sele) |
2355 | + |
2356 | + ! obtain the transformed determinant*weight and normals |
2357 | + if (di%cached_face_value%cached_detwei_normal) then |
2358 | + |
2359 | + detwei_bdy => di%cached_face_value%detwei_bdy(:,sele) |
2360 | + |
2361 | + normal_bdy => di%cached_face_value%normal_bdy(:,:,sele) |
2362 | + |
2363 | + else |
2364 | + |
2365 | + x_ele = ele_val(di%positions, face_ele(di%positions, sele)) |
2366 | + x_ele_bdy = face_val(di%positions, sele) |
2367 | + |
2368 | + call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, di%x_cvbdyshape, normal_bdy, detwei_bdy) |
2369 | + |
2370 | + end if |
2371 | + |
2372 | + if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
2373 | + |
2374 | + bc_sele_val = ele_val(di%v_bc_value, sele) |
2375 | + |
2376 | + else |
2377 | + |
2378 | + visc_ele_bdy = face_val(di%viscosity(p)%ptr, sele) |
2379 | + absperm_ele_bdy = face_val(di%absolute_permeability, sele) |
2380 | + inv_char_len_ele_bdy = ele_val(di%inverse_characteristic_length, sele) |
2381 | + if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
2382 | + bc_sele_val = ele_val(di%pressure_bc_value, sele) |
2383 | + end if |
2384 | + grad_pressure_face_quad_bdy = face_val_at_quad(di%gradient_pressure(p)%ptr, sele, di%gradp_cvbdyshape) |
2385 | + grav_ele_bdy = face_val(di%gravity, sele) |
2386 | + pressure_ele_bdy = face_val(di%pressure(p)%ptr, sele) |
2387 | + |
2388 | + ! the latest DarcyVelocity/relperm at the quadrature points for start of subcycle |
2389 | + ! determined from FE interpolation of each component, |
2390 | + do dim = 1, di%ndim |
2391 | + |
2392 | + v_over_relperm_face_quad_bdy(dim,:) = & |
2393 | +- (absperm_ele_bdy(1) / visc_ele_bdy(1)) * & |
2394 | +(grad_pressure_face_quad_bdy(dim,:) - face_val_at_quad(di%density(p)%ptr, sele, di%p_cvbdyshape) * grav_ele_bdy(dim,1)) |
2395 | + |
2396 | + end do |
2397 | + |
2398 | + end if |
2399 | + |
2400 | + ! Initialise the local rhs to assemble for this element |
2401 | + s_rhs_local_bdy = 0.0 |
2402 | + |
2403 | + bc_iloc_loop: do iloc = 1, di%pressure_mesh%faces%shape%loc |
2404 | + |
2405 | + bc_face_loop: do face = 1, di%cvfaces%sfaces |
2406 | + |
2407 | + bc_neigh_if: if(di%cvfaces%sneiloc(iloc,face)/=0) then |
2408 | + |
2409 | + bc_quad_loop: do gi = 1, di%cvfaces%shape%ngi |
2410 | + |
2411 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
2412 | + |
2413 | + prescribed_normal_flow: if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
2414 | + |
2415 | + s_rhs_local_bdy(iloc) = s_rhs_local_bdy(iloc) - & |
2416 | + bc_sele_val(iloc) * & |
2417 | + detwei_bdy(ggi) |
2418 | + |
2419 | + else prescribed_normal_flow |
2420 | + |
2421 | + ! NOTE this v_over_relperm_dot_n does not contain the relperm terms |
2422 | + v_over_relperm_dot_n = dot_product(v_over_relperm_face_quad_bdy(:,ggi), normal_bdy(:,ggi)) |
2423 | + |
2424 | + ! This term includes the gradient pressure, gradient capilliary pressure |
2425 | + ! and the gravity term. |
2426 | + s_rhs_local_bdy(iloc) = s_rhs_local_bdy(iloc) - & |
2427 | + di%cached_face_value%relperm_bdy(isub_index,ggi,sele,p) * & |
2428 | + v_over_relperm_dot_n * & |
2429 | + detwei_bdy(ggi) |
2430 | + |
2431 | + ! Add two extra terms associated with weak pressure BC's |
2432 | + pressure_weak: if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
2433 | + |
2434 | + ! Form the face value = detwei * (relperm*absperm/visc) |
2435 | + face_value = detwei_bdy(ggi) * & |
2436 | + di%cached_face_value%relperm_bdy(isub_index,ggi,sele,p) * & |
2437 | + absperm_ele_bdy(1) / & |
2438 | + visc_ele_bdy(1) |
2439 | + |
2440 | + do jloc = 1, di%pressure_mesh%faces%shape%loc |
2441 | + |
2442 | + s_rhs_local_bdy(iloc) = s_rhs_local_bdy(iloc) - & |
2443 | + inv_char_len_ele_bdy(jloc) * & |
2444 | + di%p_cvbdyshape%n(jloc,ggi) * & |
2445 | + bc_sele_val(jloc) * & |
2446 | + sum(normal_bdy(:,ggi)) * & |
2447 | + face_value * & |
2448 | + di%weak_pressure_bc_coeff |
2449 | + |
2450 | + end do |
2451 | + |
2452 | + do jloc = 1, di%pressure_mesh%faces%shape%loc |
2453 | + |
2454 | + s_rhs_local_bdy(iloc) = s_rhs_local_bdy(iloc) + & |
2455 | + inv_char_len_ele_bdy(jloc) * & |
2456 | + di%p_cvbdyshape%n(jloc,ggi) * & |
2457 | + pressure_ele_bdy(jloc) * & |
2458 | + sum(normal_bdy(:,ggi)) * & |
2459 | + face_value * & |
2460 | + di%weak_pressure_bc_coeff |
2461 | + |
2462 | + end do |
2463 | + |
2464 | + end if pressure_weak |
2465 | + |
2466 | + end if prescribed_normal_flow |
2467 | + |
2468 | + end do bc_quad_loop |
2469 | + |
2470 | + end if bc_neigh_if |
2471 | + |
2472 | + end do bc_face_loop |
2473 | + |
2474 | + end do bc_iloc_loop |
2475 | + |
2476 | + call addto(di%rhs, p_nodes_bdy, s_rhs_local_bdy) |
2477 | + |
2478 | + end do sele_loop |
2479 | + |
2480 | + ! deallocate local variables as required |
2481 | + deallocate(x_ele) |
2482 | + if (di%cached_face_value%cached_detwei_normal) then |
2483 | + nullify(detwei) |
2484 | + nullify(normal) |
2485 | + else |
2486 | + deallocate(detwei) |
2487 | + deallocate(normal) |
2488 | + end if |
2489 | + deallocate(normgi) |
2490 | + deallocate(notvisited) |
2491 | + deallocate(s_rhs_local) |
2492 | + deallocate(x_face_quad) |
2493 | + deallocate(grad_pressure_face_quad) |
2494 | + deallocate(grav_ele) |
2495 | + |
2496 | + deallocate(grav_ele_bdy) |
2497 | + deallocate(grad_pressure_face_quad_bdy) |
2498 | + deallocate(v_over_relperm_face_quad_bdy) |
2499 | + deallocate(bc_sele_val) |
2500 | + deallocate(pressure_ele_bdy) |
2501 | + deallocate(inv_char_len_ele_bdy) |
2502 | + if (di%cached_face_value%cached_detwei_normal) then |
2503 | + nullify(detwei_bdy) |
2504 | + nullify(normal_bdy) |
2505 | + else |
2506 | + deallocate(detwei_bdy) |
2507 | + deallocate(normal_bdy) |
2508 | + end if |
2509 | + deallocate(s_rhs_local_bdy) |
2510 | + deallocate(x_ele_bdy) |
2511 | + deallocate(p_nodes_bdy) |
2512 | + |
2513 | + end subroutine darcy_impes_assemble_saturation_rhs_adv |
2514 | + |
2515 | +! ---------------------------------------------------------------------------- |
2516 | + |
2517 | + subroutine darcy_impes_assemble_and_solve_generic_prog_sfields(di) |
2518 | + |
2519 | + !!< Assemble and solve generic prognostic scalar fields |
2520 | + |
2521 | + type(darcy_impes_type), intent(inout) :: di |
2522 | + |
2523 | + ! local variables |
2524 | + integer :: f, p |
2525 | + |
2526 | + ewrite(1,*) 'Assemble and solve generic prognostic scalar fields' |
2527 | + |
2528 | + sfield_loop: do f = 1, size(di%generic_prog_sfield) |
2529 | + |
2530 | + p = di%generic_prog_sfield(f)%phase |
2531 | + |
2532 | + call darcy_impes_assemble_and_solve_generic_prog_sfield(di, f, p) |
2533 | + |
2534 | + end do sfield_loop |
2535 | + |
2536 | + ewrite(1,*) 'Finished assemble and solve generic prognostic scalar fields' |
2537 | + |
2538 | + end subroutine darcy_impes_assemble_and_solve_generic_prog_sfields |
2539 | + |
2540 | +! ---------------------------------------------------------------------------- |
2541 | + |
2542 | + subroutine darcy_impes_assemble_and_solve_generic_prog_sfield(di, f, p) |
2543 | + |
2544 | + !!< Assemble and a solve generic prognostic scalar field given by index f and p |
2545 | + |
2546 | + type(darcy_impes_type), intent(inout) :: di |
2547 | + integer, intent(in) :: f |
2548 | + integer, intent(in) :: p |
2549 | + |
2550 | + ! local variables |
2551 | + integer :: i |
2552 | + |
2553 | + ewrite(1,*) 'Assemble and solve sfield ',trim(di%generic_prog_sfield(f)%sfield%name),' of phase ',p |
2554 | + |
2555 | + ! Get this phase v BC info - only for no_normal_flow and prescribed_normal_flow which is special as it is a scalar |
2556 | + call darcy_impes_get_v_boundary_condition(di%darcy_velocity(p)%ptr, & |
2557 | + (/"prescribed_normal_flow", & |
2558 | + "no_normal_flow "/), & |
2559 | + di%bc_surface_mesh, & |
2560 | + di%v_bc_value, & |
2561 | + di%v_bc_flag) |
2562 | + |
2563 | + ! Get the pressure BC - required if no v given and weak pressure dirichlet given for extra integrals |
2564 | + call darcy_impes_get_entire_sfield_boundary_condition(di%pressure(1)%ptr, & |
2565 | + (/"weakdirichlet"/), & |
2566 | + di%bc_surface_mesh, & |
2567 | + di%pressure_bc_value, & |
2568 | + di%pressure_bc_flag) |
2569 | + |
2570 | + ! Get the sfield BC |
2571 | + call darcy_impes_get_entire_sfield_boundary_condition(di%generic_prog_sfield(f)%sfield, & |
2572 | + (/"weakdirichlet"/), & |
2573 | + di%bc_surface_mesh, & |
2574 | + di%sfield_bc_value, & |
2575 | + di%sfield_bc_flag) |
2576 | + |
2577 | + call zero(di%lhs) |
2578 | + call zero(di%matrix) |
2579 | + call zero(di%rhs) |
2580 | + call zero(di%rhs_full) |
2581 | + |
2582 | + ! Add porosity*saturation(absorption + 1/dt) to lhs |
2583 | + if (di%generic_prog_sfield(f)%have_abs) then |
2584 | + |
2585 | + call addto(di%lhs, di%generic_prog_sfield(f)%sfield_abs) |
2586 | + |
2587 | + end if |
2588 | + |
2589 | + call addto(di%lhs, 1.0/di%dt) |
2590 | + call scale(di%lhs, di%cv_mass_pressure_mesh_with_porosity) |
2591 | + call scale(di%lhs, di%saturation(p)%ptr) |
2592 | + |
2593 | + ! Add old_porosity*old_saturation*old_sfield/dt to rhs |
2594 | + call addto(di%rhs, 1.0/di%dt) |
2595 | + call scale(di%rhs, di%cv_mass_pressure_mesh_with_old_porosity) |
2596 | + call scale(di%rhs, di%old_saturation(p)%ptr) |
2597 | + call scale(di%rhs, di%generic_prog_sfield(f)%old_sfield) |
2598 | + |
2599 | + ! Add source to rhs |
2600 | + if (di%generic_prog_sfield(f)%have_src) then |
2601 | + |
2602 | + call compute_cv_mass(di%positions, di%cv_mass_pressure_mesh_with_source, di%generic_prog_sfield(f)%sfield_src) |
2603 | + |
2604 | + call addto(di%rhs, di%cv_mass_pressure_mesh_with_source) |
2605 | + |
2606 | + end if |
2607 | + |
2608 | + ! Add diagonal lhs to matrix |
2609 | + call addto_diag(di%matrix, di%lhs) |
2610 | + |
2611 | + ! Add implicit low order advection and diffusion terms to matrix and rhs |
2612 | + if (di%generic_prog_sfield(f)%have_adv .or. di%generic_prog_sfield(f)%have_diff) then |
2613 | + |
2614 | + call darcy_impes_assemble_generic_prog_sfield_adv_diff(di, f, p) |
2615 | + |
2616 | + end if |
2617 | + |
2618 | + ! Solve for each face value iteration (default is 1) |
2619 | + do i = 1, di%generic_prog_sfield(f)%sfield_cv_options%number_face_value_iteration |
2620 | + |
2621 | + call set(di%rhs_full, di%rhs) |
2622 | + |
2623 | + ! Assmemble the high resolution rhs and to to rhs_full |
2624 | + if (di%generic_prog_sfield(f)%have_adv .and. & |
2625 | + di%generic_prog_sfield(f)%sfield_cv_options%facevalue == DARCY_IMPES_CV_FACEVALUE_FINITEELEMENT) then |
2626 | + |
2627 | + call zero(di%rhs_high_resolution) |
2628 | + |
2629 | + call darcy_impes_assemble_generic_prog_sfield_rhs_high_resolution(di, f, p) |
2630 | + |
2631 | + call addto(di%rhs_full, di%rhs_high_resolution) |
2632 | + |
2633 | + end if |
2634 | + |
2635 | + ! Apply any strong dirichlet BC's |
2636 | + call apply_dirichlet_conditions(di%matrix, di%rhs_full, di%generic_prog_sfield(f)%sfield) |
2637 | + |
2638 | + ! Solve the sfield |
2639 | + call petsc_solve(di%generic_prog_sfield(f)%sfield, di%matrix, di%rhs_full, di%state(p)) |
2640 | + |
2641 | + ! Set the strong BC nodes to the values to be consistent |
2642 | + call set_dirichlet_consistent(di%generic_prog_sfield(f)%sfield) |
2643 | + |
2644 | + end do |
2645 | + |
2646 | + ewrite(1,*) 'Finished assemble and solve sfield ',trim(di%generic_prog_sfield(f)%sfield%name),' of phase ',p |
2647 | + |
2648 | + end subroutine darcy_impes_assemble_and_solve_generic_prog_sfield |
2649 | + |
2650 | +! ---------------------------------------------------------------------------- |
2651 | + |
2652 | + subroutine darcy_impes_assemble_generic_prog_sfield_adv_diff(di, f, p) |
2653 | + |
2654 | + !!< Assemble the advection and diffusion terms for the |
2655 | + !!< generic prognostic scalar field given by index f and p |
2656 | + |
2657 | + type(darcy_impes_type), intent(inout) :: di |
2658 | + integer, intent(in) :: f |
2659 | + integer, intent(in) :: p |
2660 | + |
2661 | + ! local variables |
2662 | + logical :: inflow |
2663 | + integer :: vele, iloc, oloc, jloc, face, gi, ggi, sele |
2664 | + real :: face_value, v_dot_n, income, sat_face_value |
2665 | + real, dimension(1) :: absperm_ele, visc_ele, porosity_ele |
2666 | + real, dimension(:,:), pointer :: grad_pressure_face_quad |
2667 | + real, dimension(:,:), pointer :: grav_ele |
2668 | + real, dimension(:,:,:), pointer :: diff_ele |
2669 | + real, dimension(:), pointer :: sat_ele |
2670 | + real, dimension(:,:), pointer :: x_ele |
2671 | + real, dimension(:,:,:), pointer :: p_dshape |
2672 | + real, dimension(:,:), pointer :: normal |
2673 | + real, dimension(:), pointer :: detwei |
2674 | + real, dimension(:), pointer :: normgi |
2675 | + logical, dimension(:), pointer :: notvisited |
2676 | + real, dimension(:,:), pointer :: matrix_local |
2677 | + real, dimension(:,:), pointer :: x_face_quad |
2678 | + integer, dimension(:), pointer :: x_pmesh_nodes |
2679 | + integer, dimension(:), pointer :: p_nodes |
2680 | + real, dimension(1) :: absperm_ele_bdy, visc_ele_bdy |
2681 | + real, dimension(:,:), pointer :: grav_ele_bdy |
2682 | + real, dimension(:), pointer :: ghost_sfield_ele_bdy |
2683 | + real, dimension(:,:), pointer :: grad_pressure_face_quad_bdy |
2684 | + real, dimension(:,:), pointer :: v_over_relperm_face_quad_bdy |
2685 | + real, dimension(:), pointer :: bc_sele_val |
2686 | + real, dimension(:), pointer :: pressure_ele_bdy |
2687 | + real, dimension(:), pointer :: inv_char_len_ele_bdy |
2688 | + real, dimension(:,:), pointer :: normal_bdy |
2689 | + real, dimension(:), pointer :: detwei_bdy |
2690 | + real, dimension(:,:), pointer :: x_ele_bdy |
2691 | + real, dimension(:), pointer :: rhs_local_bdy |
2692 | + real, dimension(:), pointer :: matrix_local_bdy |
2693 | + integer, dimension(:), pointer :: p_nodes_bdy |
2694 | + integer, parameter :: V_BC_TYPE_PRESCRIBED_NORMAL_FLOW = 1, V_BC_TYPE_NO_NORMAL_FLOW = 2 |
2695 | + integer, parameter :: PRESSURE_BC_TYPE_WEAKDIRICHLET = 1 |
2696 | + integer, parameter :: SFIELD_BC_TYPE_WEAKDIRICHLET = 1 |
2697 | + |
2698 | + ! allocate arrays used in assemble process - many assume |
2699 | + ! that all elements are the same type. |
2700 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
2701 | + if (.not. di%cached_face_value%cached_p_dshape) then |
2702 | + allocate(p_dshape(ele_loc(di%pressure_mesh,1), di%p_cvshape%ngi, mesh_dim(di%pressure_mesh))) |
2703 | + end if |
2704 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
2705 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
2706 | + allocate(detwei(di%x_cvshape%ngi)) |
2707 | + end if |
2708 | + allocate(normgi(di%ndim)) |
2709 | + allocate(notvisited(di%x_cvshape%ngi)) |
2710 | + allocate(matrix_local(ele_loc(di%pressure_mesh,1),ele_loc(di%pressure_mesh,1))) |
2711 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
2712 | + allocate(grad_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
2713 | + allocate(grav_ele(di%ndim,1)) |
2714 | + allocate(diff_ele(di%ndim,di%ndim,1)) |
2715 | + allocate(sat_ele(ele_loc(di%positions,1))) |
2716 | + |
2717 | + allocate(grav_ele_bdy(di%ndim,1)) |
2718 | + allocate(ghost_sfield_ele_bdy(face_loc(di%pressure_mesh,1))) |
2719 | + allocate(grad_pressure_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
2720 | + allocate(v_over_relperm_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
2721 | + allocate(bc_sele_val(face_loc(di%pressure_mesh,1))) |
2722 | + allocate(pressure_ele_bdy(face_loc(di%pressure_mesh,1))) |
2723 | + allocate(inv_char_len_ele_bdy(face_loc(di%pressure_mesh,1))) |
2724 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
2725 | + allocate(detwei_bdy(di%x_cvbdyshape%ngi)) |
2726 | + allocate(normal_bdy(di%ndim, di%x_cvbdyshape%ngi)) |
2727 | + end if |
2728 | + allocate(rhs_local_bdy(face_loc(di%pressure_mesh,1))) |
2729 | + allocate(matrix_local_bdy(face_loc(di%pressure_mesh,1))) |
2730 | + allocate(x_ele_bdy(di%ndim, face_loc(di%positions,1))) |
2731 | + allocate(p_nodes_bdy(face_loc(di%pressure_mesh,1))) |
2732 | + |
2733 | + ! Loop volume elements assembling local contributions |
2734 | + vol_element_loop: do vele = 1, di%number_vele |
2735 | + |
2736 | + ! The node indices of the pressure mesh (which saturation is associated with) |
2737 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
2738 | + |
2739 | + ! The node indices of the positions projected to the pressure mesh (which saturation is associated with) |
2740 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
2741 | + |
2742 | + ! The gravity values for this element for each direction |
2743 | + grav_ele = ele_val(di%gravity, vele) |
2744 | + |
2745 | + ! get the viscosity value for this element |
2746 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
2747 | + |
2748 | + ! get the absolute permeability value for this element |
2749 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
2750 | + |
2751 | + ! get the latest gradient pressure at the cv surface quadrature points for each direction |
2752 | + grad_pressure_face_quad = ele_val_at_quad(di%gradient_pressure(p)%ptr, vele, di%gradp_cvshape) |
2753 | + |
2754 | + ! obtain the transformed determinant*weight and normals |
2755 | + if (di%cached_face_value%cached_detwei_normal) then |
2756 | + |
2757 | + detwei => di%cached_face_value%detwei(:,vele) |
2758 | + |
2759 | + normal => di%cached_face_value%normal(:,:,vele) |
2760 | + |
2761 | + else |
2762 | + |
2763 | + ! get the coordinate values for this element for each positions local node |
2764 | + x_ele = ele_val(di%positions, vele) |
2765 | + |
2766 | + ! get the coordinate values for this element for each quadrature point |
2767 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
2768 | + |
2769 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
2770 | + |
2771 | + end if |
2772 | + |
2773 | + if (di%generic_prog_sfield(f)%have_diff) then |
2774 | + |
2775 | + ! get the sfield diffusivity |
2776 | + diff_ele = ele_val(di%generic_prog_sfield(f)%sfield_diff,vele) |
2777 | + |
2778 | + ! get the element values for porosity |
2779 | + porosity_ele = ele_val(di%porosity, vele) |
2780 | + |
2781 | + ! get the element values for saturation |
2782 | + sat_ele = ele_val(di%saturation(p)%ptr, vele) |
2783 | + |
2784 | + ! obtain the derivative of the pressure mesh shape function at the CV face quadrature points |
2785 | + if (di%cached_face_value%cached_p_dshape) then |
2786 | + |
2787 | + p_dshape => di%cached_face_value%p_dshape(:,:,:,vele) |
2788 | + |
2789 | + else |
2790 | + |
2791 | + call transform_to_physical(di%positions, vele, x_shape = di%x_cvshape_full, & |
2792 | + shape = di%p_cvshape_full, dshape = p_dshape) |
2793 | + |
2794 | + end if |
2795 | + |
2796 | + end if |
2797 | + |
2798 | + ! Initialise array for the quadrature points of this |
2799 | + ! element for whether it has already been visited |
2800 | + notvisited = .true. |
2801 | + |
2802 | + ! Initialise the local matrix to assemble for this element |
2803 | + matrix_local = 0.0 |
2804 | + |
2805 | + ! loop over local nodes within this element |
2806 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
2807 | + |
2808 | + ! loop over CV faces internal to this element |
2809 | + face_loop: do face = 1, di%cvfaces%faces |
2810 | + |
2811 | + ! is this a face neighbouring iloc? |
2812 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
2813 | + |
2814 | + ! find the opposing local node across the CV face |
2815 | + oloc = di%cvfaces%neiloc(iloc, face) |
2816 | + |
2817 | + ! loop over gauss points on face |
2818 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
2819 | + |
2820 | + ! global gauss pt index for this element |
2821 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
2822 | + |
2823 | + ! check if this quadrature point has already been visited |
2824 | + check_visited: if(notvisited(ggi)) then |
2825 | + |
2826 | + notvisited(ggi) = .false. |
2827 | + |
2828 | + if (di%cached_face_value%cached_detwei_normal) then |
2829 | + |
2830 | + ! cached normal has correct orientation already |
2831 | + normgi = normal(:,ggi) |
2832 | + |
2833 | + else |
2834 | + |
2835 | + ! correct the orientation of the normal so it points away from iloc |
2836 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
2837 | + &x_face_quad(:,ggi), normal(:,ggi)) |
2838 | + |
2839 | + end if |
2840 | + |
2841 | + v_dot_n = - di%cached_face_value%relperm(1,ggi,vele,p) * absperm_ele(1) * & |
2842 | +dot_product((grad_pressure_face_quad(:,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(:,1)), normgi)/ visc_ele(1) |
2843 | + |
2844 | + inflow = (v_dot_n<=0.0) |
2845 | + |
2846 | + income = merge(1.0,0.0,inflow) |
2847 | + |
2848 | + if (di%generic_prog_sfield(f)%have_adv) then |
2849 | + |
2850 | + matrix_local(iloc, oloc) = matrix_local(iloc, oloc) + & |
2851 | + detwei(ggi) * & |
2852 | + v_dot_n * & |
2853 | + income |
2854 | + |
2855 | + matrix_local(oloc, iloc) = matrix_local(oloc, iloc) + & |
2856 | + detwei(ggi) * & |
2857 | + (-v_dot_n) * & |
2858 | + (1.0-income) |
2859 | + |
2860 | + matrix_local(iloc, iloc) = matrix_local(iloc, iloc) + & |
2861 | + detwei(ggi) * & |
2862 | + v_dot_n * & |
2863 | + (1.0-income) |
2864 | + |
2865 | + matrix_local(oloc, oloc) = matrix_local(oloc, oloc) + & |
2866 | + detwei(ggi) * & |
2867 | + (-v_dot_n) * & |
2868 | + income |
2869 | + |
2870 | + end if |
2871 | + |
2872 | + if (di%generic_prog_sfield(f)%have_diff) then |
2873 | + |
2874 | + ! Find the diffusion term saturation face value (taking upwind) |
2875 | + sat_face_value = income*sat_ele(oloc) + (1.0-income)*sat_ele(iloc) |
2876 | + |
2877 | + do jloc=1, di%pressure_mesh%shape%loc |
2878 | + |
2879 | + matrix_local(iloc,jloc) = matrix_local(iloc,jloc) - & |
2880 | + sum(matmul(diff_ele(:,:,1), p_dshape(jloc, ggi, :))*normgi, 1) * & |
2881 | + porosity_ele(1) * & |
2882 | + sat_face_value * & |
2883 | + detwei(ggi) |
2884 | + |
2885 | + matrix_local(oloc, jloc) = matrix_local(oloc,jloc) - & |
2886 | + sum(matmul(diff_ele(:,:,1), p_dshape(jloc, ggi, :))*(-normgi), 1) * & |
2887 | + porosity_ele(1) * & |
2888 | + sat_face_value * & |
2889 | + detwei(ggi) |
2890 | + |
2891 | + end do |
2892 | + |
2893 | + end if |
2894 | + |
2895 | + end if check_visited |
2896 | + |
2897 | + end do quadrature_loop |
2898 | + |
2899 | + end if is_neigh |
2900 | + |
2901 | + end do face_loop |
2902 | + |
2903 | + end do nodal_loop_i |
2904 | + |
2905 | + call addto(di%matrix, p_nodes, p_nodes, matrix_local) |
2906 | + |
2907 | + end do vol_element_loop |
2908 | + |
2909 | + ! Add BC integrals associated with an advection term (diffusive flux is assumed zero on all boundary) |
2910 | + |
2911 | + have_adv_so_add_bc: if (di%generic_prog_sfield(f)%have_adv) then |
2912 | + |
2913 | + sele_loop: do sele = 1, di%number_sele |
2914 | + |
2915 | + if (di%v_bc_flag(sele) == V_BC_TYPE_NO_NORMAL_FLOW) cycle sele_loop |
2916 | + |
2917 | + p_nodes_bdy = face_global_nodes(di%pressure_mesh, sele) |
2918 | + |
2919 | + ! obtain the transformed determinant*weight and normals |
2920 | + if (di%cached_face_value%cached_detwei_normal) then |
2921 | + |
2922 | + detwei_bdy => di%cached_face_value%detwei_bdy(:,sele) |
2923 | + |
2924 | + normal_bdy => di%cached_face_value%normal_bdy(:,:,sele) |
2925 | + |
2926 | + else |
2927 | + |
2928 | + x_ele = ele_val(di%positions, face_ele(di%positions, sele)) |
2929 | + x_ele_bdy = face_val(di%positions, sele) |
2930 | + |
2931 | + call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, di%x_cvbdyshape, normal_bdy, detwei_bdy) |
2932 | + |
2933 | + end if |
2934 | + |
2935 | + if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
2936 | + |
2937 | + bc_sele_val = ele_val(di%v_bc_value, sele) |
2938 | + |
2939 | + else |
2940 | + |
2941 | + visc_ele_bdy = face_val(di%viscosity(p)%ptr, sele) |
2942 | + absperm_ele_bdy = face_val(di%absolute_permeability, sele) |
2943 | + inv_char_len_ele_bdy = ele_val(di%inverse_characteristic_length, sele) |
2944 | + if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
2945 | + bc_sele_val = ele_val(di%pressure_bc_value, sele) |
2946 | + end if |
2947 | + grad_pressure_face_quad_bdy = face_val_at_quad(di%gradient_pressure(p)%ptr, sele, di%gradp_cvbdyshape) |
2948 | + grav_ele_bdy = face_val(di%gravity, sele) |
2949 | + pressure_ele_bdy = face_val(di%pressure(p)%ptr, sele) |
2950 | + |
2951 | + end if |
2952 | + |
2953 | + if (di%sfield_bc_flag(sele) == SFIELD_BC_TYPE_WEAKDIRICHLET) then |
2954 | + ghost_sfield_ele_bdy = ele_val(di%sfield_bc_value, sele) |
2955 | + else |
2956 | + ghost_sfield_ele_bdy = face_val(di%generic_prog_sfield(f)%sfield, sele) |
2957 | + end if |
2958 | + |
2959 | + ! Initialise the local arrays to assemble for this element |
2960 | + rhs_local_bdy = 0.0 |
2961 | + matrix_local_bdy = 0.0 |
2962 | + |
2963 | + bc_iloc_loop: do iloc = 1, di%pressure_mesh%faces%shape%loc |
2964 | + |
2965 | + bc_face_loop: do face = 1, di%cvfaces%sfaces |
2966 | + |
2967 | + bc_neigh_if: if(di%cvfaces%sneiloc(iloc,face)/=0) then |
2968 | + |
2969 | + bc_quad_loop: do gi = 1, di%cvfaces%shape%ngi |
2970 | + |
2971 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
2972 | + |
2973 | + prescribed_normal_flow: if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
2974 | + |
2975 | + if (bc_sele_val(iloc) <= 0) then |
2976 | + |
2977 | + income = 1.0 |
2978 | + |
2979 | + else |
2980 | + |
2981 | + income = 0.0 |
2982 | + |
2983 | + end if |
2984 | + |
2985 | + rhs_local_bdy(iloc) = rhs_local_bdy(iloc) - & |
2986 | + bc_sele_val(iloc) * & |
2987 | + ghost_sfield_ele_bdy(iloc) * & |
2988 | + detwei_bdy(ggi) * & |
2989 | + income |
2990 | + |
2991 | + matrix_local_bdy(iloc) = matrix_local_bdy(iloc) + & |
2992 | + bc_sele_val(iloc) * & |
2993 | + detwei_bdy(ggi) * & |
2994 | + (1.0 - income) |
2995 | + |
2996 | + else prescribed_normal_flow |
2997 | + |
2998 | + v_dot_n = - di%cached_face_value%relperm_bdy(1,ggi,sele,p) * absperm_ele_bdy(1) * & |
2999 | +dot_product((grad_pressure_face_quad_bdy(:,ggi) - di%cached_face_value%den_bdy(ggi,sele,p) * grav_ele_bdy(:,1)), normal_bdy(:,ggi))/ visc_ele_bdy(1) |
3000 | + |
3001 | + if (v_dot_n <= 0) then |
3002 | + |
3003 | + income = 1.0 |
3004 | + |
3005 | + else |
3006 | + |
3007 | + income = 0.0 |
3008 | + |
3009 | + end if |
3010 | + |
3011 | + rhs_local_bdy(iloc) = rhs_local_bdy(iloc) - & |
3012 | + v_dot_n * & |
3013 | + ghost_sfield_ele_bdy(iloc) * & |
3014 | + detwei_bdy(ggi) * & |
3015 | + income |
3016 | + |
3017 | + matrix_local_bdy(iloc) = matrix_local_bdy(iloc) + & |
3018 | + v_dot_n * & |
3019 | + detwei_bdy(ggi) * & |
3020 | + (1.0 - income) |
3021 | + |
3022 | + ! Add two extra terms associated with weak pressure BC's |
3023 | + pressure_weak: if (di%pressure_bc_flag(sele) == PRESSURE_BC_TYPE_WEAKDIRICHLET) then |
3024 | + |
3025 | + ! Form the face value = detwei * (relperm*absperm/visc) |
3026 | + face_value = detwei_bdy(ggi) * & |
3027 | + di%cached_face_value%relperm_bdy(1,ggi,sele,p) * & |
3028 | + absperm_ele_bdy(1) / & |
3029 | + visc_ele_bdy(1) |
3030 | + |
3031 | + do jloc = 1, di%pressure_mesh%faces%shape%loc |
3032 | + |
3033 | + rhs_local_bdy(iloc) = rhs_local_bdy(iloc) - & |
3034 | + inv_char_len_ele_bdy(jloc) * & |
3035 | + di%p_cvbdyshape%n(jloc,ggi) * & |
3036 | + bc_sele_val(jloc) * & |
3037 | + sum(normal_bdy(:,ggi)) * & |
3038 | + face_value * & |
3039 | + ghost_sfield_ele_bdy(iloc) * & |
3040 | + di%weak_pressure_bc_coeff * & |
3041 | + income |
3042 | + |
3043 | + matrix_local_bdy(iloc) = matrix_local_bdy(iloc) - & |
3044 | + inv_char_len_ele_bdy(jloc) * & |
3045 | + di%p_cvbdyshape%n(jloc,ggi) * & |
3046 | + bc_sele_val(jloc) * & |
3047 | + sum(normal_bdy(:,ggi)) * & |
3048 | + face_value * & |
3049 | + di%weak_pressure_bc_coeff * & |
3050 | + (1.0 - income) |
3051 | + |
3052 | + end do |
3053 | + |
3054 | + do jloc = 1, di%pressure_mesh%faces%shape%loc |
3055 | + |
3056 | + rhs_local_bdy(iloc) = rhs_local_bdy(iloc) + & |
3057 | + inv_char_len_ele_bdy(jloc) * & |
3058 | + di%p_cvbdyshape%n(jloc,ggi) * & |
3059 | + pressure_ele_bdy(jloc) * & |
3060 | + sum(normal_bdy(:,ggi)) * & |
3061 | + face_value * & |
3062 | + ghost_sfield_ele_bdy(iloc) * & |
3063 | + di%weak_pressure_bc_coeff * & |
3064 | + income |
3065 | + |
3066 | + matrix_local_bdy(iloc) = matrix_local_bdy(iloc) + & |
3067 | + inv_char_len_ele_bdy(jloc) * & |
3068 | + di%p_cvbdyshape%n(jloc,ggi) * & |
3069 | + pressure_ele_bdy(jloc) * & |
3070 | + sum(normal_bdy(:,ggi)) * & |
3071 | + face_value * & |
3072 | + di%weak_pressure_bc_coeff * & |
3073 | + (1.0 - income) |
3074 | + |
3075 | + end do |
3076 | + |
3077 | + end if pressure_weak |
3078 | + |
3079 | + end if prescribed_normal_flow |
3080 | + |
3081 | + end do bc_quad_loop |
3082 | + |
3083 | + end if bc_neigh_if |
3084 | + |
3085 | + end do bc_face_loop |
3086 | + |
3087 | + end do bc_iloc_loop |
3088 | + |
3089 | + call addto(di%rhs, p_nodes_bdy, rhs_local_bdy) |
3090 | + |
3091 | + call addto_diag(di%matrix, p_nodes_bdy, matrix_local_bdy) |
3092 | + |
3093 | + end do sele_loop |
3094 | + |
3095 | + end if have_adv_so_add_bc |
3096 | + |
3097 | + ! deallocate local variables as required |
3098 | + deallocate(x_ele) |
3099 | + if (di%cached_face_value%cached_p_dshape) then |
3100 | + nullify(p_dshape) |
3101 | + else |
3102 | + deallocate(p_dshape) |
3103 | + end if |
3104 | + if (di%cached_face_value%cached_detwei_normal) then |
3105 | + nullify(detwei) |
3106 | + nullify(normal) |
3107 | + else |
3108 | + deallocate(detwei) |
3109 | + deallocate(normal) |
3110 | + end if |
3111 | + deallocate(normgi) |
3112 | + deallocate(notvisited) |
3113 | + deallocate(matrix_local) |
3114 | + deallocate(x_face_quad) |
3115 | + deallocate(grad_pressure_face_quad) |
3116 | + deallocate(grav_ele) |
3117 | + deallocate(diff_ele) |
3118 | + deallocate(sat_ele) |
3119 | + |
3120 | + deallocate(grav_ele_bdy) |
3121 | + deallocate(ghost_sfield_ele_bdy) |
3122 | + deallocate(grad_pressure_face_quad_bdy) |
3123 | + deallocate(v_over_relperm_face_quad_bdy) |
3124 | + deallocate(bc_sele_val) |
3125 | + deallocate(pressure_ele_bdy) |
3126 | + deallocate(inv_char_len_ele_bdy) |
3127 | + if (di%cached_face_value%cached_detwei_normal) then |
3128 | + nullify(detwei_bdy) |
3129 | + nullify(normal_bdy) |
3130 | + else |
3131 | + deallocate(detwei_bdy) |
3132 | + deallocate(normal_bdy) |
3133 | + end if |
3134 | + deallocate(rhs_local_bdy) |
3135 | + deallocate(matrix_local_bdy) |
3136 | + deallocate(x_ele_bdy) |
3137 | + deallocate(p_nodes_bdy) |
3138 | + |
3139 | + end subroutine darcy_impes_assemble_generic_prog_sfield_adv_diff |
3140 | + |
3141 | +! ---------------------------------------------------------------------------- |
3142 | + |
3143 | + subroutine darcy_impes_assemble_generic_prog_sfield_rhs_high_resolution(di, f, p) |
3144 | + |
3145 | + !!< Assemble the advection high resolution terms for the |
3146 | + !!< generic prognostic scalar field given by index f and p |
3147 | + |
3148 | + type(darcy_impes_type), intent(inout) :: di |
3149 | + integer, intent(in) :: f |
3150 | + integer, intent(in) :: p |
3151 | + |
3152 | + ! local variables |
3153 | + logical :: inflow |
3154 | + integer :: vele, iloc, oloc, face, gi, ggi, s_upwind_pos |
3155 | + real :: v_dot_n, income, sfield_face_value, sfield_low_face_value, sfield_high_face_value |
3156 | + real, dimension(1) :: absperm_ele, visc_ele |
3157 | + real, dimension(:,:), pointer :: grad_pressure_face_quad |
3158 | + real, dimension(:,:), pointer :: grav_ele |
3159 | + real, dimension(:), pointer :: sfield_ele |
3160 | + real, dimension(:,:), pointer :: x_ele |
3161 | + real, dimension(:,:,:), pointer :: p_dshape |
3162 | + real, dimension(:,:), pointer :: normal |
3163 | + real, dimension(:), pointer :: detwei |
3164 | + real, dimension(:), pointer :: normgi |
3165 | + logical, dimension(:), pointer :: notvisited |
3166 | + real, dimension(:), pointer :: rhs_local |
3167 | + real, dimension(:,:), pointer :: x_face_quad |
3168 | + integer, dimension(:), pointer :: x_pmesh_nodes |
3169 | + integer, dimension(:), pointer :: p_nodes |
3170 | + integer, dimension(:), pointer :: s_upwind_nodes |
3171 | + |
3172 | + ! allocate arrays used in assemble process - many assume |
3173 | + ! that all elements are the same type. |
3174 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
3175 | + if (.not. di%cached_face_value%cached_p_dshape) then |
3176 | + allocate(p_dshape(ele_loc(di%pressure_mesh,1), di%p_cvshape%ngi, mesh_dim(di%pressure_mesh))) |
3177 | + end if |
3178 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
3179 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
3180 | + allocate(detwei(di%x_cvshape%ngi)) |
3181 | + end if |
3182 | + allocate(normgi(di%ndim)) |
3183 | + allocate(notvisited(di%x_cvshape%ngi)) |
3184 | + allocate(rhs_local(ele_loc(di%pressure_mesh,1))) |
3185 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
3186 | + allocate(grad_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
3187 | + allocate(grav_ele(di%ndim,1)) |
3188 | + allocate(sfield_ele(ele_loc(di%positions,1))) |
3189 | + |
3190 | + if(di%generic_prog_sfield(f)%sfield_cv_options%limit_facevalue) then |
3191 | + |
3192 | + ! NOTE only new upwind values are required but this procedure |
3193 | + ! expects latest and old. So pass in new twice - not optimal |
3194 | + call find_upwind_values(di%state, & |
3195 | + di%positions_pressure_mesh, & |
3196 | + di%generic_prog_sfield(f)%sfield, & |
3197 | + di%sfield_upwind, & |
3198 | + di%generic_prog_sfield(f)%sfield, & |
3199 | + di%sfield_upwind, & |
3200 | + option_path = trim(di%generic_prog_sfield(f)%sfield%option_path)) |
3201 | + |
3202 | + end if |
3203 | + |
3204 | + ! Initialise optimisation flag used in finding upwind value in high resolution schemes |
3205 | + s_upwind_pos = 0 |
3206 | + |
3207 | + ! Loop volume elements assembling local contributions |
3208 | + vol_element_loop: do vele = 1, di%number_vele |
3209 | + |
3210 | + ! The node indices of the pressure mesh (which saturation is associated with) |
3211 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
3212 | + |
3213 | + ! The node indices of the positions projected to the pressure mesh (which saturation is associated with) |
3214 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
3215 | + |
3216 | + ! The gravity values for this element for each direction |
3217 | + grav_ele = ele_val(di%gravity, vele) |
3218 | + |
3219 | + ! get the viscosity value for this element |
3220 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
3221 | + |
3222 | + ! get the absolute permeability value for this element |
3223 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
3224 | + |
3225 | + ! get the latest gradient pressure at the cv surface quadrature points for each direction |
3226 | + grad_pressure_face_quad = ele_val_at_quad(di%gradient_pressure(p)%ptr, vele, di%gradp_cvshape) |
3227 | + |
3228 | + ! get the sfield value for this element |
3229 | + sfield_ele = ele_val(di%generic_prog_sfield(f)%sfield, vele) |
3230 | + |
3231 | + ! Determine the node numbers to use to determine the sfield upwind values |
3232 | + if((di%generic_prog_sfield(f)%sfield_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_POINT).or.& |
3233 | + (di%generic_prog_sfield(f)%sfield_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_GRAD)) then |
3234 | + |
3235 | + s_upwind_nodes => x_pmesh_nodes |
3236 | + |
3237 | + else |
3238 | + |
3239 | + s_upwind_nodes => p_nodes |
3240 | + |
3241 | + end if |
3242 | + |
3243 | + ! obtain the transformed determinant*weight and normals |
3244 | + if (di%cached_face_value%cached_detwei_normal) then |
3245 | + |
3246 | + detwei => di%cached_face_value%detwei(:,vele) |
3247 | + |
3248 | + normal => di%cached_face_value%normal(:,:,vele) |
3249 | + |
3250 | + else |
3251 | + |
3252 | + ! get the coordinate values for this element for each positions local node |
3253 | + x_ele = ele_val(di%positions, vele) |
3254 | + |
3255 | + ! get the coordinate values for this element for each quadrature point |
3256 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
3257 | + |
3258 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
3259 | + |
3260 | + end if |
3261 | + |
3262 | + ! Initialise array for the quadrature points of this |
3263 | + ! element for whether it has already been visited |
3264 | + notvisited = .true. |
3265 | + |
3266 | + ! Initialise the local rhs to assemble for this element |
3267 | + rhs_local = 0.0 |
3268 | + |
3269 | + ! loop over local nodes within this element |
3270 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
3271 | + |
3272 | + ! loop over CV faces internal to this element |
3273 | + face_loop: do face = 1, di%cvfaces%faces |
3274 | + |
3275 | + ! is this a face neighbouring iloc? |
3276 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
3277 | + |
3278 | + ! find the opposing local node across the CV face |
3279 | + oloc = di%cvfaces%neiloc(iloc, face) |
3280 | + |
3281 | + ! loop over gauss points on face |
3282 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
3283 | + |
3284 | + ! global gauss pt index for this element |
3285 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
3286 | + |
3287 | + ! check if this quadrature point has already been visited |
3288 | + check_visited: if(notvisited(ggi)) then |
3289 | + |
3290 | + notvisited(ggi) = .false. |
3291 | + |
3292 | + if (di%cached_face_value%cached_detwei_normal) then |
3293 | + |
3294 | + ! cached normal has correct orientation already |
3295 | + normgi = normal(:,ggi) |
3296 | + |
3297 | + else |
3298 | + |
3299 | + ! correct the orientation of the normal so it points away from iloc |
3300 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
3301 | + &x_face_quad(:,ggi), normal(:,ggi)) |
3302 | + |
3303 | + end if |
3304 | + |
3305 | + v_dot_n = - di%cached_face_value%relperm(1,ggi,vele,p) * absperm_ele(1) * & |
3306 | +dot_product((grad_pressure_face_quad(:,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(:,1)), normgi)/ visc_ele(1) |
3307 | + |
3308 | + inflow = (v_dot_n<=0.0) |
3309 | + |
3310 | + income = merge(1.0,0.0,inflow) |
3311 | + |
3312 | + ! form the high resolution face value |
3313 | + call darcy_impes_evaluate_sfield_face_val(sfield_high_face_value, & |
3314 | + iloc, & |
3315 | + oloc, & |
3316 | + ggi, & |
3317 | + s_upwind_nodes, & |
3318 | + di%p_cvshape, & |
3319 | + sfield_ele, & |
3320 | + di%sfield_upwind, & |
3321 | + inflow, & |
3322 | + income, & |
3323 | + di%generic_prog_sfield(f)%sfield_cv_options, & |
3324 | + save_pos = s_upwind_pos) |
3325 | + |
3326 | + ! form and add the lower order iterated term to rhs |
3327 | + sfield_low_face_value = income*sfield_ele(oloc) + (1.0-income)*sfield_ele(iloc) |
3328 | + |
3329 | + ! form the rhs face value and add to the rhs field |
3330 | + sfield_face_value = sfield_low_face_value - sfield_high_face_value |
3331 | + |
3332 | + rhs_local(iloc) = rhs_local(iloc) + & |
3333 | + sfield_face_value * & |
3334 | + v_dot_n * & |
3335 | + detwei(ggi) |
3336 | + |
3337 | + rhs_local(oloc) = rhs_local(oloc) - & |
3338 | + sfield_face_value * & |
3339 | + v_dot_n * & |
3340 | + detwei(ggi) |
3341 | + |
3342 | + end if check_visited |
3343 | + |
3344 | + end do quadrature_loop |
3345 | + |
3346 | + end if is_neigh |
3347 | + |
3348 | + end do face_loop |
3349 | + |
3350 | + end do nodal_loop_i |
3351 | + |
3352 | + call addto(di%rhs_high_resolution, p_nodes, rhs_local) |
3353 | + |
3354 | + end do vol_element_loop |
3355 | + |
3356 | + ! deallocate local variables as required |
3357 | + deallocate(x_ele) |
3358 | + if (di%cached_face_value%cached_p_dshape) then |
3359 | + nullify(p_dshape) |
3360 | + else |
3361 | + deallocate(p_dshape) |
3362 | + end if |
3363 | + if (di%cached_face_value%cached_detwei_normal) then |
3364 | + nullify(detwei) |
3365 | + nullify(normal) |
3366 | + else |
3367 | + deallocate(detwei) |
3368 | + deallocate(normal) |
3369 | + end if |
3370 | + deallocate(normgi) |
3371 | + deallocate(notvisited) |
3372 | + deallocate(rhs_local) |
3373 | + deallocate(x_face_quad) |
3374 | + deallocate(grad_pressure_face_quad) |
3375 | + deallocate(grav_ele) |
3376 | + deallocate(sfield_ele) |
3377 | + |
3378 | + end subroutine darcy_impes_assemble_generic_prog_sfield_rhs_high_resolution |
3379 | + |
3380 | +! ---------------------------------------------------------------------------- |
3381 | + |
3382 | + subroutine darcy_impes_calculate_phase_one_saturation_diagnostic(di) |
3383 | + |
3384 | + !!< Calculate the first phase diagnostic saturation as 1.0 - the rest |
3385 | + |
3386 | + type(darcy_impes_type), intent(inout) :: di |
3387 | + |
3388 | + ! local variables |
3389 | + integer :: p |
3390 | + |
3391 | + ewrite(1,*) 'Calculate phase 1 diagnostic Saturation' |
3392 | + |
3393 | + call set(di%saturation(1)%ptr, 1.0) |
3394 | + |
3395 | + do p = 2, di%number_phase |
3396 | + |
3397 | + call addto(di%saturation(1)%ptr, di%saturation(p)%ptr, scale = -1.0) |
3398 | + |
3399 | + end do |
3400 | + |
3401 | + ewrite_minmax(di%saturation(1)%ptr) |
3402 | + |
3403 | + end subroutine darcy_impes_calculate_phase_one_saturation_diagnostic |
3404 | + |
3405 | +! ---------------------------------------------------------------------------- |
3406 | + |
3407 | + subroutine darcy_impes_calculate_vel_mob_ff_and_cfl_fields(di) |
3408 | + |
3409 | + !!< Calculate the various velocities, mobilities, fractional flows, and CFL fields |
3410 | + |
3411 | + type(darcy_impes_type), intent(inout) :: di |
3412 | + |
3413 | + ! local variables |
3414 | + type(vector_field) :: aux_vfield |
3415 | + logical :: inflow |
3416 | + integer :: vele, p, dim, iloc, oloc, face, gi, ggi, sele |
3417 | + real :: income, v_dot_n |
3418 | + real, dimension(1) :: visc_ele, absperm_ele |
3419 | + real, dimension(:,:), pointer :: grad_pressure_face_quad |
3420 | + real, dimension(:,:), pointer :: v_local |
3421 | + real, dimension(:), pointer :: m_local |
3422 | + real, dimension(:,:), pointer :: grav_ele |
3423 | + real, dimension(:,:), pointer :: x_ele |
3424 | + real, dimension(:,:), pointer :: normal |
3425 | + real, dimension(:), pointer :: detwei |
3426 | + real, dimension(:), pointer :: normgi |
3427 | + logical, dimension(:), pointer :: notvisited |
3428 | + real, dimension(:), pointer :: cfl_rhs_local |
3429 | + real, dimension(:,:), pointer :: x_face_quad |
3430 | + integer, dimension(:), pointer :: x_pmesh_nodes |
3431 | + integer, dimension(:), pointer :: p_nodes |
3432 | + real, dimension(1) :: visc_ele_bdy, absperm_ele_bdy |
3433 | + real, dimension(:,:), pointer :: grav_ele_bdy |
3434 | + real, dimension(:,:), pointer :: grad_pressure_face_quad_bdy |
3435 | + real, dimension(:,:), pointer :: normal_bdy |
3436 | + real, dimension(:), pointer :: detwei_bdy |
3437 | + real, dimension(:,:), pointer :: x_ele_bdy |
3438 | + real, dimension(:), pointer :: cfl_rhs_local_bdy |
3439 | + real, dimension(:,:), pointer :: v_local_bdy |
3440 | + real, dimension(:), pointer :: m_local_bdy |
3441 | + integer, dimension(:), pointer :: p_nodes_bdy |
3442 | + real, dimension(:), pointer :: bc_sele_val |
3443 | + integer, parameter :: V_BC_TYPE_PRESCRIBED_NORMAL_FLOW = 1, V_BC_TYPE_NO_NORMAL_FLOW = 2 |
3444 | + |
3445 | + ewrite(1,*) 'Calculate CFL, Velocity, Mobilities and FractionalFlow fields' |
3446 | + |
3447 | + ! allocate arrays used in CFL assemble process - many assume |
3448 | + ! that all elements are the same type. |
3449 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
3450 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
3451 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
3452 | + allocate(detwei(di%x_cvshape%ngi)) |
3453 | + end if |
3454 | + allocate(normgi(di%ndim)) |
3455 | + allocate(notvisited(di%x_cvshape%ngi)) |
3456 | + allocate(cfl_rhs_local(ele_loc(di%pressure_mesh,1))) |
3457 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
3458 | + allocate(grad_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
3459 | + allocate(grav_ele(di%ndim,1)) |
3460 | + |
3461 | + allocate(grav_ele_bdy(di%ndim,1)) |
3462 | + allocate(grad_pressure_face_quad_bdy(di%ndim, di%p_cvbdyshape%ngi)) |
3463 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
3464 | + allocate(detwei_bdy(di%x_cvbdyshape%ngi)) |
3465 | + allocate(normal_bdy(di%ndim, di%x_cvbdyshape%ngi)) |
3466 | + end if |
3467 | + allocate(cfl_rhs_local_bdy(face_loc(di%pressure_mesh,1))) |
3468 | + allocate(x_ele_bdy(di%ndim, face_loc(di%positions,1))) |
3469 | + allocate(p_nodes_bdy(face_loc(di%pressure_mesh,1))) |
3470 | + allocate(bc_sele_val(face_loc(di%pressure_mesh,1))) |
3471 | + |
3472 | + allocate(v_local(di%ndim,ele_loc(di%pressure_mesh,1))) |
3473 | + allocate(m_local(ele_loc(di%pressure_mesh,1))) |
3474 | + allocate(v_local_bdy(di%ndim,face_loc(di%pressure_mesh,1))) |
3475 | + allocate(m_local_bdy(face_loc(di%pressure_mesh,1))) |
3476 | + |
3477 | + phase_loop: do p = 1, di%number_phase |
3478 | + |
3479 | + call zero(di%cfl(p)%ptr) |
3480 | + |
3481 | + call zero(di%darcy_velocity(p)%ptr) |
3482 | + |
3483 | + call zero(di%mobility(p)%ptr) |
3484 | + |
3485 | + vele_loop: do vele = 1, di%number_vele |
3486 | + |
3487 | + ! The node indices of the pressure field |
3488 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
3489 | + |
3490 | + ! The gravity values for this element for each direction |
3491 | + grav_ele = ele_val(di%gravity, vele) |
3492 | + |
3493 | + ! get the viscosity value for this element for this phase |
3494 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
3495 | + |
3496 | + ! get the absolute permeability value for this element |
3497 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
3498 | + |
3499 | + ! get the latest gradient pressure at the cv surface quadrature points for each direction for this phase |
3500 | + grad_pressure_face_quad = ele_val_at_quad(di%gradient_pressure(p)%ptr, vele, di%gradp_cvshape) |
3501 | + |
3502 | + ! obtain the transformed determinant*weight and normals |
3503 | + if (di%cached_face_value%cached_detwei_normal) then |
3504 | + |
3505 | + detwei => di%cached_face_value%detwei(:,vele) |
3506 | + |
3507 | + normal => di%cached_face_value%normal(:,:,vele) |
3508 | + |
3509 | + else |
3510 | + |
3511 | + ! get the coordinate values for this element for each positions local node |
3512 | + x_ele = ele_val(di%positions, vele) |
3513 | + |
3514 | + ! get the coordinate values for this element for each quadrature point |
3515 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
3516 | + |
3517 | + ! The node indices of the positions projected to the pressure mesh |
3518 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
3519 | + |
3520 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
3521 | + |
3522 | + end if |
3523 | + |
3524 | + ! Initialise array for the quadrature points of this |
3525 | + ! element for whether it has already been visited |
3526 | + notvisited = .true. |
3527 | + |
3528 | + ! Initialise the local assemble arrays for this element |
3529 | + cfl_rhs_local = 0.0 |
3530 | + v_local = 0.0 |
3531 | + m_local = 0.0 |
3532 | + |
3533 | + ! loop over local nodes within this element |
3534 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
3535 | + |
3536 | + ! loop over CV faces internal to this element |
3537 | + face_loop: do face = 1, di%cvfaces%faces |
3538 | + |
3539 | + ! is this a face neighbouring iloc? |
3540 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
3541 | + |
3542 | + ! find the opposing local node across the CV face |
3543 | + oloc = di%cvfaces%neiloc(iloc, face) |
3544 | + |
3545 | + ! loop over gauss points on face |
3546 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
3547 | + |
3548 | + ! global gauss pt index for this element |
3549 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
3550 | + |
3551 | + ! check if this quadrature point has already been visited |
3552 | + check_visited: if(notvisited(ggi)) then |
3553 | + |
3554 | + notvisited(ggi) = .false. |
3555 | + |
3556 | + if (di%cached_face_value%cached_detwei_normal) then |
3557 | + |
3558 | + ! cached normal has correct orientation already |
3559 | + normgi = normal(:,ggi) |
3560 | + |
3561 | + else |
3562 | + |
3563 | + ! correct the orientation of the normal so it points away from iloc |
3564 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
3565 | + &x_face_quad(:,ggi), normal(:,ggi)) |
3566 | + |
3567 | + end if |
3568 | + |
3569 | + v_dot_n = & |
3570 | +- di%cached_face_value%relperm(1,ggi,vele,p) * absperm_ele(1) * & |
3571 | +dot_product((grad_pressure_face_quad(:,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(:,1)), normgi) / & |
3572 | +visc_ele(1) |
3573 | + |
3574 | + inflow = (v_dot_n<=0.0) |
3575 | + |
3576 | + income = merge(1.0,0.0,inflow) |
3577 | + |
3578 | + cfl_rhs_local(iloc) = cfl_rhs_local(iloc) + & |
3579 | + abs(v_dot_n) * & |
3580 | + detwei(ggi) * & |
3581 | + (1.0 - income) |
3582 | + |
3583 | + cfl_rhs_local(oloc) = cfl_rhs_local(oloc) + & |
3584 | + abs(v_dot_n) * & |
3585 | + detwei(ggi) * & |
3586 | + income |
3587 | + |
3588 | + do dim = 1, di%ndim |
3589 | + |
3590 | + v_local(dim,iloc) = v_local(dim,iloc) - & |
3591 | +detwei(ggi) * & |
3592 | +di%cached_face_value%relperm(1,ggi,vele,p) * & |
3593 | +absperm_ele(1) * & |
3594 | +(grad_pressure_face_quad(dim,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(dim,1)) / & |
3595 | +visc_ele(1) |
3596 | + |
3597 | + v_local(dim,oloc) = v_local(dim,oloc) - & |
3598 | +detwei(ggi) * & |
3599 | +di%cached_face_value%relperm(1,ggi,vele,p) * & |
3600 | +absperm_ele(1) * & |
3601 | +(grad_pressure_face_quad(dim,ggi) - di%cached_face_value%den(ggi,vele,p) * grav_ele(dim,1)) / & |
3602 | +visc_ele(1) |
3603 | + |
3604 | + end do |
3605 | + |
3606 | + m_local(iloc) = m_local(iloc) + & |
3607 | + detwei(ggi) * & |
3608 | + di%cached_face_value%relperm(1,ggi,vele,p) / & |
3609 | + visc_ele(1) |
3610 | + |
3611 | + m_local(oloc) = m_local(oloc) + & |
3612 | + detwei(ggi) * & |
3613 | + di%cached_face_value%relperm(1,ggi,vele,p) / & |
3614 | + visc_ele(1) |
3615 | + |
3616 | + end if check_visited |
3617 | + |
3618 | + end do quadrature_loop |
3619 | + |
3620 | + end if is_neigh |
3621 | + |
3622 | + end do face_loop |
3623 | + |
3624 | + end do nodal_loop_i |
3625 | + |
3626 | + call addto(di%cfl(p)%ptr, p_nodes, cfl_rhs_local) |
3627 | + |
3628 | + call addto(di%darcy_velocity(p)%ptr, p_nodes, v_local) |
3629 | + |
3630 | + call addto(di%mobility(p)%ptr, p_nodes, m_local) |
3631 | + |
3632 | + end do vele_loop |
3633 | + |
3634 | + ! Get this phase v BC info - only for no_normal_flow and |
3635 | + ! prescribed_normal_flow which is special as it is a scalar |
3636 | + call darcy_impes_get_v_boundary_condition(& |
3637 | + di%darcy_velocity(p)%ptr, & |
3638 | + (/"prescribed_normal_flow", "no_normal_flow "/), & |
3639 | + di%bc_surface_mesh, di%v_bc_value, di%v_bc_flag) |
3640 | + |
3641 | + sele_loop: do sele = 1, di%number_sele |
3642 | + |
3643 | + p_nodes_bdy = face_global_nodes(di%pressure_mesh, sele) |
3644 | + |
3645 | + ! obtain the transformed determinant*weight and normals |
3646 | + if (di%cached_face_value%cached_detwei_normal) then |
3647 | + |
3648 | + detwei_bdy => di%cached_face_value%detwei_bdy(:,sele) |
3649 | + |
3650 | + normal_bdy => di%cached_face_value%normal_bdy(:,:,sele) |
3651 | + |
3652 | + else |
3653 | + |
3654 | + x_ele = ele_val(di%positions, face_ele(di%positions, sele)) |
3655 | + x_ele_bdy = face_val(di%positions, sele) |
3656 | + |
3657 | + call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, di%x_cvbdyshape, normal_bdy, detwei_bdy) |
3658 | + |
3659 | + end if |
3660 | + |
3661 | + if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
3662 | + |
3663 | + bc_sele_val = ele_val(di%v_bc_value, sele) |
3664 | + |
3665 | + end if |
3666 | + |
3667 | + visc_ele_bdy = face_val(di%viscosity(p)%ptr, sele) |
3668 | + absperm_ele_bdy = face_val(di%absolute_permeability, sele) |
3669 | + grad_pressure_face_quad_bdy = face_val_at_quad(di%gradient_pressure(p)%ptr, sele, di%gradp_cvbdyshape) |
3670 | + grav_ele_bdy = face_val(di%gravity, sele) |
3671 | + |
3672 | + ! Initialise the local assemble arrays for this element |
3673 | + cfl_rhs_local_bdy = 0.0 |
3674 | + v_local_bdy = 0.0 |
3675 | + m_local_bdy = 0.0 |
3676 | + |
3677 | + bc_iloc_loop: do iloc = 1, di%pressure_mesh%faces%shape%loc |
3678 | + |
3679 | + bc_face_loop: do face = 1, di%cvfaces%sfaces |
3680 | + |
3681 | + bc_neigh_if: if(di%cvfaces%sneiloc(iloc,face)/=0) then |
3682 | + |
3683 | + bc_quad_loop: do gi = 1, di%cvfaces%shape%ngi |
3684 | + |
3685 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
3686 | + |
3687 | + if (di%v_bc_flag(sele) == V_BC_TYPE_NO_NORMAL_FLOW) then |
3688 | + |
3689 | + v_dot_n = 0.0 |
3690 | + |
3691 | + else if (di%v_bc_flag(sele) == V_BC_TYPE_PRESCRIBED_NORMAL_FLOW) then |
3692 | + |
3693 | + v_dot_n = bc_sele_val(iloc) |
3694 | + |
3695 | + else |
3696 | + |
3697 | + v_dot_n = & |
3698 | +- di%cached_face_value%relperm_bdy(1,ggi,sele,p) * absperm_ele_bdy(1) * & |
3699 | +dot_product((grad_pressure_face_quad_bdy(:,ggi) - di%cached_face_value%den_bdy(ggi,sele,p) * grav_ele_bdy(:,1)), normal_bdy(:,ggi)) / & |
3700 | +visc_ele_bdy(1) |
3701 | + |
3702 | + end if |
3703 | + |
3704 | + if (v_dot_n > 0.0) then |
3705 | + income = 0.0 |
3706 | + else |
3707 | + income = 1.0 |
3708 | + end if |
3709 | + |
3710 | + cfl_rhs_local_bdy(iloc) = cfl_rhs_local_bdy(iloc) + & |
3711 | + abs(v_dot_n) * & |
3712 | + detwei_bdy(ggi) * & |
3713 | + (1.0 - income) |
3714 | + |
3715 | + do dim = 1, di%ndim |
3716 | + |
3717 | + v_local_bdy(dim,iloc) = v_local_bdy(dim,iloc) - & |
3718 | +detwei_bdy(ggi) * & |
3719 | +di%cached_face_value%relperm_bdy(1,ggi,sele,p) * & |
3720 | +absperm_ele_bdy(1) * & |
3721 | +(grad_pressure_face_quad_bdy(dim,ggi) - di%cached_face_value%den_bdy(ggi,sele,p) * grav_ele_bdy(dim,1)) / & |
3722 | +visc_ele_bdy(1) |
3723 | + |
3724 | + end do |
3725 | + |
3726 | + m_local_bdy(iloc) = m_local_bdy(iloc) + & |
3727 | + detwei_bdy(ggi) * & |
3728 | + di%cached_face_value%relperm_bdy(1,ggi,sele,p) / & |
3729 | + visc_ele_bdy(1) |
3730 | + |
3731 | + end do bc_quad_loop |
3732 | + |
3733 | + end if bc_neigh_if |
3734 | + |
3735 | + end do bc_face_loop |
3736 | + |
3737 | + end do bc_iloc_loop |
3738 | + |
3739 | + call addto(di%cfl(p)%ptr, p_nodes_bdy, cfl_rhs_local_bdy) |
3740 | + |
3741 | + call addto(di%darcy_velocity(p)%ptr, p_nodes_bdy, v_local_bdy) |
3742 | + |
3743 | + call addto(di%mobility(p)%ptr, p_nodes_bdy, m_local_bdy) |
3744 | + |
3745 | + end do sele_loop |
3746 | + |
3747 | + di%cfl(p)%ptr%val = di%cfl(p)%ptr%val * di%dt / di%cv_mass_pressure_mesh_with_porosity%val |
3748 | + |
3749 | + call scale(di%darcy_velocity(p)%ptr, di%inverse_cv_sa_pressure_mesh) |
3750 | + |
3751 | + call scale(di%mobility(p)%ptr, di%inverse_cv_sa_pressure_mesh) |
3752 | + |
3753 | + ewrite_minmax(di%cfl(p)%ptr) |
3754 | + |
3755 | + ewrite_minmax(di%darcy_velocity(p)%ptr) |
3756 | + |
3757 | + ewrite_minmax(di%mobility(p)%ptr) |
3758 | + |
3759 | + end do phase_loop |
3760 | + |
3761 | + ewrite(1,*) 'Calculate TotalDarcyVelocity and TotalMobility' |
3762 | + |
3763 | + call set(di%total_darcy_velocity, di%darcy_velocity(1)%ptr) |
3764 | + call set(di%total_mobility, di%mobility(1)%ptr) |
3765 | + |
3766 | + do p = 2, di%number_phase |
3767 | + |
3768 | + call addto(di%total_darcy_velocity, di%darcy_velocity(p)%ptr) |
3769 | + call addto(di%total_mobility, di%mobility(p)%ptr) |
3770 | + |
3771 | + end do |
3772 | + |
3773 | + ewrite_minmax(di%total_darcy_velocity) |
3774 | + ewrite_minmax(di%total_mobility) |
3775 | + |
3776 | + ewrite(1,*) 'Calculate BulkDarcyVelocity' |
3777 | + |
3778 | + call allocate(aux_vfield, di%ndim, di%pressure_mesh) |
3779 | + |
3780 | + call zero(di%bulk_darcy_velocity) |
3781 | + |
3782 | + do p = 1, di%number_phase |
3783 | + |
3784 | + call set(aux_vfield, di%darcy_velocity(p)%ptr) |
3785 | + call scale(aux_vfield, di%saturation(p)%ptr) |
3786 | + |
3787 | + call addto(di%bulk_darcy_velocity, aux_vfield) |
3788 | + |
3789 | + end do |
3790 | + |
3791 | + call deallocate(aux_vfield) |
3792 | + |
3793 | + ewrite_minmax(di%bulk_darcy_velocity) |
3794 | + |
3795 | + ! calculate the fractional flow for each phase |
3796 | + do p = 1, di%number_phase |
3797 | + |
3798 | + ewrite(1,*) 'Calculate FractionalFlow for phase ',p |
3799 | + |
3800 | + call set(di%fractional_flow(p)%ptr, di%total_mobility) |
3801 | + |
3802 | + call invert(di%fractional_flow(p)%ptr) |
3803 | + |
3804 | + call scale(di%fractional_flow(p)%ptr, di%mobility(p)%ptr) |
3805 | + |
3806 | + ewrite_minmax(di%fractional_flow(p)%ptr) |
3807 | + |
3808 | + end do |
3809 | + |
3810 | + ! deallocate local variables as required |
3811 | + deallocate(x_ele) |
3812 | + if (di%cached_face_value%cached_detwei_normal) then |
3813 | + nullify(detwei) |
3814 | + nullify(normal) |
3815 | + else |
3816 | + deallocate(detwei) |
3817 | + deallocate(normal) |
3818 | + end if |
3819 | + deallocate(normgi) |
3820 | + deallocate(notvisited) |
3821 | + deallocate(cfl_rhs_local) |
3822 | + deallocate(x_face_quad) |
3823 | + deallocate(grad_pressure_face_quad) |
3824 | + deallocate(grav_ele) |
3825 | + |
3826 | + deallocate(grav_ele_bdy) |
3827 | + deallocate(grad_pressure_face_quad_bdy) |
3828 | + if (di%cached_face_value%cached_detwei_normal) then |
3829 | + nullify(detwei_bdy) |
3830 | + nullify(normal_bdy) |
3831 | + else |
3832 | + deallocate(detwei_bdy) |
3833 | + deallocate(normal_bdy) |
3834 | + end if |
3835 | + deallocate(x_ele_bdy) |
3836 | + deallocate(p_nodes_bdy) |
3837 | + deallocate(cfl_rhs_local_bdy) |
3838 | + deallocate(bc_sele_val) |
3839 | + |
3840 | + deallocate(v_local) |
3841 | + deallocate(m_local) |
3842 | + deallocate(v_local_bdy) |
3843 | + deallocate(m_local_bdy) |
3844 | + |
3845 | + end subroutine darcy_impes_calculate_vel_mob_ff_and_cfl_fields |
3846 | + |
3847 | +! ---------------------------------------------------------------------------- |
3848 | + |
3849 | + subroutine darcy_impes_calculate_inverse_cv_sa(di) |
3850 | + |
3851 | + !!< Calculate the inverse of the surface area of the CV's on the pressure mesh |
3852 | + |
3853 | + type(darcy_impes_type), intent(inout) :: di |
3854 | + |
3855 | + ! local variables |
3856 | + integer :: vele, iloc, oloc, face, gi, ggi, sele |
3857 | + real, dimension(:), pointer :: sa_local |
3858 | + real, dimension(:,:), pointer :: x_ele |
3859 | + real, dimension(:,:), pointer :: normal |
3860 | + real, dimension(:), pointer :: detwei |
3861 | + logical, dimension(:), pointer :: notvisited |
3862 | + integer, dimension(:), pointer :: p_nodes |
3863 | + real, dimension(:,:), pointer :: normal_bdy |
3864 | + real, dimension(:), pointer :: detwei_bdy |
3865 | + real, dimension(:,:), pointer :: x_ele_bdy |
3866 | + real, dimension(:), pointer :: sa_local_bdy |
3867 | + integer, dimension(:), pointer :: p_nodes_bdy |
3868 | + |
3869 | + ewrite(1,*) 'Calculate the inverse of the surface area of CV on the pressure mesh' |
3870 | + |
3871 | + ! allocate arrays used in assemble process - many assume |
3872 | + ! that all elements are the same type. |
3873 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
3874 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
3875 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
3876 | + allocate(detwei(di%x_cvshape%ngi)) |
3877 | + end if |
3878 | + allocate(notvisited(di%x_cvshape%ngi)) |
3879 | + |
3880 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
3881 | + allocate(detwei_bdy(di%x_cvbdyshape%ngi)) |
3882 | + allocate(normal_bdy(di%ndim, di%x_cvbdyshape%ngi)) |
3883 | + end if |
3884 | + allocate(x_ele_bdy(di%ndim, face_loc(di%positions,1))) |
3885 | + allocate(p_nodes_bdy(face_loc(di%pressure_mesh,1))) |
3886 | + allocate(sa_local(ele_loc(di%pressure_mesh,1))) |
3887 | + allocate(sa_local_bdy(face_loc(di%pressure_mesh,1))) |
3888 | + |
3889 | + call zero(di%inverse_cv_sa_pressure_mesh) |
3890 | + |
3891 | + vele_loop: do vele = 1, di%number_vele |
3892 | + |
3893 | + ! The node indices of the pressure field |
3894 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
3895 | + |
3896 | + ! obtain the transformed determinant*weight and normals |
3897 | + if (di%cached_face_value%cached_detwei_normal) then |
3898 | + |
3899 | + detwei => di%cached_face_value%detwei(:,vele) |
3900 | + |
3901 | + normal => di%cached_face_value%normal(:,:,vele) |
3902 | + |
3903 | + else |
3904 | + |
3905 | + ! get the coordinate values for this element for each positions local node |
3906 | + x_ele = ele_val(di%positions, vele) |
3907 | + |
3908 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
3909 | + |
3910 | + end if |
3911 | + |
3912 | + ! Initialise array for the quadrature points of this |
3913 | + ! element for whether it has already been visited |
3914 | + notvisited = .true. |
3915 | + |
3916 | + sa_local = 0.0 |
3917 | + |
3918 | + ! loop over local nodes within this element |
3919 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
3920 | + |
3921 | + ! loop over CV faces internal to this element |
3922 | + face_loop: do face = 1, di%cvfaces%faces |
3923 | + |
3924 | + ! is this a face neighbouring iloc? |
3925 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
3926 | + |
3927 | + ! find the opposing local node across the CV face |
3928 | + oloc = di%cvfaces%neiloc(iloc, face) |
3929 | + |
3930 | + ! loop over gauss points on face |
3931 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
3932 | + |
3933 | + ! global gauss pt index for this element |
3934 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
3935 | + |
3936 | + ! check if this quadrature point has already been visited |
3937 | + check_visited: if(notvisited(ggi)) then |
3938 | + |
3939 | + notvisited(ggi) = .false. |
3940 | + |
3941 | + sa_local(iloc) = sa_local(iloc) + & |
3942 | + detwei(ggi) |
3943 | + |
3944 | + sa_local(oloc) = sa_local(oloc) + & |
3945 | + detwei(ggi) |
3946 | + |
3947 | + end if check_visited |
3948 | + |
3949 | + end do quadrature_loop |
3950 | + |
3951 | + end if is_neigh |
3952 | + |
3953 | + end do face_loop |
3954 | + |
3955 | + end do nodal_loop_i |
3956 | + |
3957 | + call addto(di%inverse_cv_sa_pressure_mesh, p_nodes, sa_local) |
3958 | + |
3959 | + end do vele_loop |
3960 | + |
3961 | + sele_loop: do sele = 1, di%number_sele |
3962 | + |
3963 | + p_nodes_bdy = face_global_nodes(di%pressure_mesh, sele) |
3964 | + |
3965 | + ! obtain the transformed determinant*weight and normals |
3966 | + if (di%cached_face_value%cached_detwei_normal) then |
3967 | + |
3968 | + detwei_bdy => di%cached_face_value%detwei_bdy(:,sele) |
3969 | + |
3970 | + normal_bdy => di%cached_face_value%normal_bdy(:,:,sele) |
3971 | + |
3972 | + else |
3973 | + |
3974 | + x_ele = ele_val(di%positions, face_ele(di%positions, sele)) |
3975 | + x_ele_bdy = face_val(di%positions, sele) |
3976 | + |
3977 | + call transform_cvsurf_facet_to_physical(x_ele, x_ele_bdy, di%x_cvbdyshape, normal_bdy, detwei_bdy) |
3978 | + |
3979 | + end if |
3980 | + |
3981 | + sa_local_bdy = 0.0 |
3982 | + |
3983 | + bc_iloc_loop: do iloc = 1, di%pressure_mesh%faces%shape%loc |
3984 | + |
3985 | + bc_face_loop: do face = 1, di%cvfaces%sfaces |
3986 | + |
3987 | + bc_neigh_if: if(di%cvfaces%sneiloc(iloc,face)/=0) then |
3988 | + |
3989 | + bc_quad_loop: do gi = 1, di%cvfaces%shape%ngi |
3990 | + |
3991 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
3992 | + |
3993 | + sa_local_bdy(iloc) = sa_local_bdy(iloc) + & |
3994 | + detwei_bdy(ggi) |
3995 | + |
3996 | + end do bc_quad_loop |
3997 | + |
3998 | + end if bc_neigh_if |
3999 | + |
4000 | + end do bc_face_loop |
4001 | + |
4002 | + end do bc_iloc_loop |
4003 | + |
4004 | + call addto(di%inverse_cv_sa_pressure_mesh, p_nodes_bdy, sa_local_bdy) |
4005 | + |
4006 | + end do sele_loop |
4007 | + |
4008 | + call invert(di%inverse_cv_sa_pressure_mesh) |
4009 | + |
4010 | + ! deallocate local variables as required |
4011 | + deallocate(x_ele) |
4012 | + if (di%cached_face_value%cached_detwei_normal) then |
4013 | + nullify(detwei) |
4014 | + nullify(normal) |
4015 | + else |
4016 | + deallocate(detwei) |
4017 | + deallocate(normal) |
4018 | + end if |
4019 | + deallocate(notvisited) |
4020 | + |
4021 | + if (di%cached_face_value%cached_detwei_normal) then |
4022 | + nullify(detwei_bdy) |
4023 | + nullify(normal_bdy) |
4024 | + else |
4025 | + deallocate(detwei_bdy) |
4026 | + deallocate(normal_bdy) |
4027 | + end if |
4028 | + deallocate(x_ele_bdy) |
4029 | + deallocate(p_nodes_bdy) |
4030 | + |
4031 | + deallocate(sa_local) |
4032 | + deallocate(sa_local_bdy) |
4033 | + |
4034 | + ewrite_minmax(di%inverse_cv_sa_pressure_mesh) |
4035 | + |
4036 | + ewrite(1,*) 'Finished Calculate the inverse of the surface area of CV on the pressure mesh' |
4037 | + |
4038 | + end subroutine darcy_impes_calculate_inverse_cv_sa |
4039 | + |
4040 | +! ---------------------------------------------------------------------------- |
4041 | + |
4042 | + subroutine darcy_impes_calculate_sum_saturation(di) |
4043 | + |
4044 | + !!< Calculate the sum of the saturation fields |
4045 | + |
4046 | + type(darcy_impes_type), intent(inout) :: di |
4047 | + |
4048 | + ! local variables |
4049 | + integer :: p |
4050 | + |
4051 | + ewrite(1,*) 'Calculate SumSaturation' |
4052 | + |
4053 | + call zero(di%sum_saturation) |
4054 | + |
4055 | + do p = 1, di%number_phase |
4056 | + |
4057 | + call addto(di%sum_saturation, di%saturation(p)%ptr) |
4058 | + |
4059 | + end do |
4060 | + |
4061 | + ewrite_minmax(di%sum_saturation) |
4062 | + |
4063 | + end subroutine darcy_impes_calculate_sum_saturation |
4064 | + |
4065 | +! ---------------------------------------------------------------------------- |
4066 | + |
4067 | + subroutine darcy_impes_calculate_densities(di) |
4068 | + |
4069 | + !!< Calculate the density field of each phase |
4070 | + |
4071 | + type(darcy_impes_type), intent(inout) :: di |
4072 | + |
4073 | + ! local variables |
4074 | + integer :: p |
4075 | + |
4076 | + ewrite(1,*) 'Calculate Density of each phase' |
4077 | + |
4078 | + do p = 1, di%number_phase |
4079 | + |
4080 | + if (di%eos_options(p)%have_fluids_linear) then |
4081 | + |
4082 | + ! Currently no variation of the reference density by any pertubation |
4083 | + |
4084 | + call set(di%density(p)%ptr, di%eos_options(p)%fluids_linear_reference_density) |
4085 | + |
4086 | + end if |
4087 | + |
4088 | + ewrite_minmax(di%density(p)%ptr) |
4089 | + |
4090 | + end do |
4091 | + |
4092 | + ewrite(1,*) 'Finished Calculate Density of each phase' |
4093 | + |
4094 | + end subroutine darcy_impes_calculate_densities |
4095 | + |
4096 | +! ---------------------------------------------------------------------------- |
4097 | + |
4098 | + subroutine darcy_impes_calculate_relperm_fields(di) |
4099 | + |
4100 | + !!< Calculate the latest relperm fields from the latest saturations. |
4101 | + !!< This is assumes that the relperm and saturation fields are |
4102 | + !!< on the same mesh, which is all the input permits |
4103 | + |
4104 | + type(darcy_impes_type), intent(inout) :: di |
4105 | + |
4106 | + ! local variables |
4107 | + integer :: p, node |
4108 | + real :: relperm_node_val |
4109 | + real, dimension(:), pointer :: sat_node_val_all_phases |
4110 | + |
4111 | + ewrite(1,*) 'Calculate RelativePermeability field of each phase' |
4112 | + |
4113 | + allocate(sat_node_val_all_phases(di%number_phase)) |
4114 | + |
4115 | + ! Calc relperm phase values for each node |
4116 | + node_loop: do node = 1, di%number_pmesh_node |
4117 | + |
4118 | + ! Find all the phase saturation node values |
4119 | + do p = 1, di%number_phase |
4120 | + |
4121 | + sat_node_val_all_phases(p) = node_val(di%saturation(p)%ptr, node) |
4122 | + |
4123 | + end do |
4124 | + |
4125 | + ! Calc and set relperm node value for each phase |
4126 | + do p = 1, di%number_phase |
4127 | + |
4128 | + call darcy_impes_calculate_relperm_value(relperm_node_val, & |
4129 | + sat_node_val_all_phases, & |
4130 | + p, & |
4131 | + di%relperm_corr_options%type, & |
4132 | + di%relperm_corr_options%exponents, & |
4133 | + di%relperm_corr_options%residual_saturations, & |
4134 | + di%relperm_corr_options%cutoff_saturations, & |
4135 | + di%relperm_corr_options%scaling_coefficients) |
4136 | + |
4137 | + call set(di%relative_permeability(p)%ptr, & |
4138 | + node, & |
4139 | + relperm_node_val) |
4140 | + |
4141 | + end do |
4142 | + |
4143 | + end do node_loop |
4144 | + |
4145 | + deallocate(sat_node_val_all_phases) |
4146 | + |
4147 | + ewrite(1,*) 'Finished Calculate RelativePermeability field of each phase' |
4148 | + |
4149 | + end subroutine darcy_impes_calculate_relperm_fields |
4150 | + |
4151 | +! ---------------------------------------------------------------------------- |
4152 | + |
4153 | + subroutine darcy_impes_calculate_relperm_value(relperm_val, & |
4154 | + sat_val_all_phases, & |
4155 | + p, & |
4156 | + relperm_corr_type, & |
4157 | + relperm_corr_exponents, & |
4158 | + relperm_corr_residual_sats, & |
4159 | + relperm_corr_cutoff_sats, & |
4160 | + relperm_corr_scaling_coefficients) |
4161 | + |
4162 | + !!< Calculate the latest relperm value for phase p for the |
4163 | + !!< given saturation values of all phases using the given options. |
4164 | + |
4165 | + real, intent(out) :: relperm_val |
4166 | + real, dimension(:), intent(in) :: sat_val_all_phases |
4167 | + integer, intent(in) :: p |
4168 | + integer, intent(in) :: relperm_corr_type |
4169 | + real, dimension(:), intent(in) :: relperm_corr_exponents |
4170 | + real, dimension(:), intent(in) :: relperm_corr_residual_sats |
4171 | + real, dimension(:), intent(in) :: relperm_corr_cutoff_sats |
4172 | + real, dimension(:), intent(in) :: relperm_corr_scaling_coefficients |
4173 | + |
4174 | + ! local variables |
4175 | + real :: sat_minus_res_sat |
4176 | + real :: sat_effective |
4177 | + |
4178 | + select case (relperm_corr_type) |
4179 | + |
4180 | + case (RELPERM_CORRELATION_POWER) |
4181 | + |
4182 | + relperm_val = (sat_val_all_phases(p) - relperm_corr_residual_sats(p)) ** relperm_corr_exponents(p) |
4183 | + |
4184 | + case (RELPERM_CORRELATION_COREY2PHASE) |
4185 | + |
4186 | + sat_minus_res_sat = sat_val_all_phases(1) - relperm_corr_residual_sats(1) |
4187 | + |
4188 | + if (p == 1) then |
4189 | + |
4190 | + relperm_val = sat_minus_res_sat ** 4 |
4191 | + |
4192 | + else if (p == 2) then |
4193 | + |
4194 | + relperm_val = (1.0 - sat_minus_res_sat ** 2) * (1.0 - sat_minus_res_sat) ** 2 |
4195 | + |
4196 | + else |
4197 | + |
4198 | + ! This has already been option checked so should not happen |
4199 | + FLAbort('Trying to use Corey2Phase relative permeabiltiy correlation for simulation with more than 2 phases') |
4200 | + |
4201 | + end if |
4202 | + |
4203 | + case (RELPERM_CORRELATION_COREY2PHASEOPPOSITE) |
4204 | + |
4205 | + sat_minus_res_sat = sat_val_all_phases(2) - relperm_corr_residual_sats(2) |
4206 | + |
4207 | + if (p == 1) then |
4208 | + |
4209 | + relperm_val = (1.0 - sat_minus_res_sat ** 2) * (1.0 - sat_minus_res_sat) ** 2 |
4210 | + |
4211 | + else if (p == 2) then |
4212 | + |
4213 | + relperm_val = sat_minus_res_sat ** 4 |
4214 | + |
4215 | + else |
4216 | + |
4217 | + ! This has already been option checked so should not happen |
4218 | + FLAbort('Trying to use Corey2PhaseOpposite relative permeabiltiy correlation for simulation with more than 2 phases') |
4219 | + |
4220 | + end if |
4221 | + |
4222 | + case (RELPERM_CORRELATION_MINERAL) |
4223 | + |
4224 | + relperm_val = ((max(relperm_corr_cutoff_sats(p), sat_val_all_phases(p)) - relperm_corr_residual_sats(p)) **& |
4225 | + &relperm_corr_exponents(p)) / ((1.0 - relperm_corr_residual_sats(p)) ** relperm_corr_exponents(p)) |
4226 | + |
4227 | + case (RELPERM_CORRELATION_VANGENUCHTEN) |
4228 | + |
4229 | + sat_effective = (sat_val_all_phases(2) - relperm_corr_residual_sats(2) ) / ( 1.0 - relperm_corr_residual_sats(1) - & |
4230 | + &relperm_corr_residual_sats(2)) |
4231 | + |
4232 | + if (p == 1) then |
4233 | + |
4234 | + relperm_val = ( 1.0 - sat_effective )**(1.0/3.0) * (1.0 - sat_effective ** ( 1.0/ relperm_corr_exponents(p)) ) ** (2* relperm_corr_exponents(p)) |
4235 | + |
4236 | + else if (p == 2) then |
4237 | + |
4238 | + relperm_val = sat_effective ** (1.0/2.0) * ( 1.0 - ( 1.0 - sat_effective ** ( 1.0 / relperm_corr_exponents(p))) ** relperm_corr_exponents(p))**2.0 |
4239 | + |
4240 | + else |
4241 | + |
4242 | + ! This has already been option checked so should not happen |
4243 | + FLAbort('Trying to use VanGenuchten relative permeabiltiy correlation for simulation with more than 2 phases') |
4244 | + |
4245 | + end if |
4246 | + |
4247 | + case (RELPERM_CORRELATION_JACKSON2PHASE) |
4248 | + |
4249 | + sat_effective = (sat_val_all_phases(2) - relperm_corr_residual_sats(2)) / & |
4250 | + (1.0 - relperm_corr_residual_sats(1) - relperm_corr_residual_sats(2)) |
4251 | + if ( sat_effective >= 1.0 ) then |
4252 | + sat_effective = 1.0 |
4253 | + end if |
4254 | + |
4255 | + if ( sat_effective <= 0.0 ) then |
4256 | + sat_effective = 0.0 |
4257 | + end if |
4258 | + |
4259 | + if (p == 1) then |
4260 | + |
4261 | + relperm_val = relperm_corr_scaling_coefficients(1) * (1.0 - sat_effective) ** relperm_corr_exponents(1) |
4262 | + |
4263 | + else if (p == 2) then |
4264 | + |
4265 | + relperm_val = relperm_corr_scaling_coefficients(2) * sat_effective ** relperm_corr_exponents(2) |
4266 | + |
4267 | + else |
4268 | + |
4269 | + ! This has already been option checked so should not happen |
4270 | + FLAbort('Trying to use Jackson2Phase relative permeabiltiy correlation for simulation with more than 2 phases') |
4271 | + |
4272 | + end if |
4273 | + |
4274 | + case (RELPERM_CORRELATION_JACKSON2PHASEOPPOSITE) |
4275 | + |
4276 | + sat_effective = (sat_val_all_phases(1) - relperm_corr_residual_sats(1)) / & |
4277 | + (1.0 - relperm_corr_residual_sats(1) - relperm_corr_residual_sats(2)) |
4278 | + |
4279 | + if (p == 1) then |
4280 | + |
4281 | + relperm_val = relperm_corr_scaling_coefficients(1) * sat_effective ** relperm_corr_exponents(1) |
4282 | + |
4283 | + else if (p == 2) then |
4284 | + |
4285 | + relperm_val = relperm_corr_scaling_coefficients(2) * (1.0 - sat_effective) ** relperm_corr_exponents(2) |
4286 | + |
4287 | + else |
4288 | + |
4289 | + ! This has already been option checked so should not happen |
4290 | + FLAbort('Trying to use Jackson2PhaseOpposite relative permeabiltiy correlation for simulation with more than 2 phases') |
4291 | + |
4292 | + end if |
4293 | + |
4294 | + end select |
4295 | + |
4296 | + end subroutine darcy_impes_calculate_relperm_value |
4297 | + |
4298 | +! ---------------------------------------------------------------------------- |
4299 | + |
4300 | + subroutine darcy_impes_calculate_cflnumber_field_based_dt(di) |
4301 | + |
4302 | + !!< Calculate the cfl number field based adaptive time step |
4303 | + |
4304 | + type(darcy_impes_type), intent(inout) :: di |
4305 | + |
4306 | + !! NEW NoT TESTED FROM HERE |
4307 | + type(logical) :: diff_cfl |
4308 | + |
4309 | + |
4310 | + real :: ds, dpds, diff, deltax |
4311 | + type(scalar_field), pointer::sat, phi, perm, vis |
4312 | + |
4313 | + type(vector_field), pointer:: X |
4314 | + |
4315 | + real, dimension(:), allocatable :: detwei |
4316 | + real, dimension(:), pointer :: phi_ele, perm_ele, sat_ele, vis_ele |
4317 | + integer, dimension(:), pointer :: sat_ele_nodes |
4318 | + integer :: i , ele |
4319 | + real, dimension(:, :, :), allocatable :: invJ |
4320 | + real :: sat_node |
4321 | + type(state_type) :: state |
4322 | + |
4323 | + !! TILL HERE |
4324 | + |
4325 | + |
4326 | + ! local variables |
4327 | + integer :: p |
4328 | + real, dimension(di%number_phase) :: phase_dt, dtdiff |
4329 | + |
4330 | + ewrite(1,*) 'Calculate CFL number field based adaptive timestep' |
4331 | + |
4332 | + ! Find the adaptive dt for each phase then take the minimum |
4333 | + |
4334 | + phase_dt = di%dt |
4335 | + |
4336 | + phase_loop: do p = 1, di%number_phase |
4337 | + |
4338 | + phase_dt(p) = cflnumber_field_based_dt(di%cfl(p)%ptr, & |
4339 | + di%dt, & |
4340 | + di%adaptive_dt_options%requested_cfl, & |
4341 | + di%adaptive_dt_options%min_dt, & |
4342 | + di%adaptive_dt_options%max_dt, & |
4343 | + di%adaptive_dt_options%increase_tolerance) |
4344 | + |
4345 | + end do phase_loop |
4346 | + |
4347 | + |
4348 | + ! NEW NOT TESTED FROM HERE |
4349 | +! diff_cfl = .False. |
4350 | +! if (diff_cfl) then |
4351 | + |
4352 | +! do p = 1, di%number_phase |
4353 | + |
4354 | +! sat=>extract_scalar_field(state(p), "Saturation") |
4355 | +! phi=>extract_scalar_field(state(p), "Porosity") |
4356 | +! perm=>extract_scalar_field(state(p), "Permeability") |
4357 | +! vis=>extract_scalar_field(state(p), "Viscosity") |
4358 | + |
4359 | +! X=>extract_vector_field(state(1), "Coordinate") |
4360 | +! allocate (invj(mesh_dim(x), mesh_dim(x), ele_ngi(x, 1))) |
4361 | +! allocate (detwei(ele_ngi(X,ele))) |
4362 | + |
4363 | + |
4364 | +! ds = 1.e-10 |
4365 | +! dpds=0. |
4366 | + |
4367 | +! diff= 0. |
4368 | + |
4369 | +! do ele = 1, ele_count(sat) |
4370 | + |
4371 | +! sat_ele_nodes => ele_nodes(sat, ele) |
4372 | + |
4373 | +! phi_ele = ele_val(phi, ele) |
4374 | +! perm_ele = ele_val(perm, ele) |
4375 | +! vis_ele = ele_val(vis, ele) |
4376 | + |
4377 | + ! call compute_inverse_jacobian(ele_val(X,ele), ele_shape(X,ele), & |
4378 | + ! detwei=detwei, invJ=invJ) |
4379 | + |
4380 | + |
4381 | + |
4382 | +! deltax = minval(invJ) |
4383 | + |
4384 | +! do i = 1, size(sat_ele_nodes) |
4385 | + |
4386 | +! sat_node = node_val(sat, sat_ele_nodes(i) ) |
4387 | +! dpds = abs( ( (sat_node+ds)**(-0.5) - (sat_node-ds)**(-0.5) ) /(2.*ds) ) |
4388 | + |
4389 | + ! diff = max( diff, ( 1./phi_ele(ele)) * (perm_ele(ele) / vis_ele(ele)) * dpds ) |
4390 | + |
4391 | +! end do |
4392 | + |
4393 | +! dtdiff(p) = deltax**2 / (2*diff) |
4394 | + |
4395 | + ! end do |
4396 | + |
4397 | +! deallocate (invj) |
4398 | +! deallocate (detwei) |
4399 | + |
4400 | +! end do |
4401 | + |
4402 | + |
4403 | + |
4404 | +! di%dt = min(minval(dtdiff), minval(phase_dt)) |
4405 | + |
4406 | +! end if |
4407 | + |
4408 | +! UNTIL HERE |
4409 | + |
4410 | + di%dt = minval(phase_dt) |
4411 | + |
4412 | + if(di%adaptive_dt_options%min_dt_terminate_if_reached) then |
4413 | + if(di%dt <= di%adaptive_dt_options%min_dt + spacing(di%adaptive_dt_options%min_dt)) then |
4414 | + ewrite(0, *) "Minimum timestep reached - terminating" |
4415 | + SIG_INT = .true. |
4416 | + end if |
4417 | + end if |
4418 | + |
4419 | + ewrite(1,*) 'Finished Calculate CFL number field based adaptive timestep' |
4420 | + |
4421 | + end subroutine darcy_impes_calculate_cflnumber_field_based_dt |
4422 | + |
4423 | +! ---------------------------------------------------------------------------- |
4424 | + |
4425 | + subroutine darcy_impes_initialise_cached_face_value(di) |
4426 | + |
4427 | + !!< Initialise the cached_face_value variable's by |
4428 | + !!< allocating and zeroing the values and setting the |
4429 | + !!< detwei, normal and p_dshape components as required. |
4430 | + |
4431 | + type(darcy_impes_type), intent(inout) :: di |
4432 | + |
4433 | + ! local variable |
4434 | + integer :: vele, sele, iloc, face, gi, ggi |
4435 | + real, dimension(:), allocatable :: normgi |
4436 | + logical, dimension(:), allocatable :: notvisited |
4437 | + real, dimension(:,:), allocatable :: x_face_quad |
4438 | + integer, dimension(:), pointer :: x_pmesh_nodes |
4439 | + |
4440 | + ewrite(1,*) 'Initialise cached phase face value types' |
4441 | + |
4442 | + if (di%subcy_opt_sat%have .and. di%subcy_opt_sat%consistent) then |
4443 | + |
4444 | + allocate(di%cached_face_value%relperm(di%subcy_opt_sat%number, di%p_cvshape%ngi, di%number_vele, di%number_phase)) |
4445 | + allocate(di%cached_face_value%relperm_bdy(di%subcy_opt_sat%number, di%p_cvbdyshape%ngi, di%number_sele, di%number_phase)) |
4446 | + |
4447 | + else |
4448 | + |
4449 | + allocate(di%cached_face_value%relperm(1, di%p_cvshape%ngi, di%number_vele, di%number_phase)) |
4450 | + allocate(di%cached_face_value%relperm_bdy(1, di%p_cvbdyshape%ngi, di%number_sele, di%number_phase)) |
4451 | + |
4452 | + end if |
4453 | + |
4454 | + di%cached_face_value%relperm = 0.0 |
4455 | + di%cached_face_value%relperm_bdy = 0.0 |
4456 | + |
4457 | + allocate(di%cached_face_value%den(di%p_cvshape%ngi, di%number_vele, di%number_phase)) |
4458 | + allocate(di%cached_face_value%den_bdy(di%p_cvbdyshape%ngi, di%number_sele, di%number_phase)) |
4459 | + |
4460 | + di%cached_face_value%den = 0.0 |
4461 | + di%cached_face_value%den_bdy = 0.0 |
4462 | + |
4463 | + if (di%cached_face_value%cached_detwei_normal) then |
4464 | + |
4465 | + allocate(di%cached_face_value%detwei(di%p_cvshape%ngi, di%number_vele)) |
4466 | + allocate(di%cached_face_value%detwei_bdy(di%p_cvbdyshape%ngi, di%number_sele)) |
4467 | + |
4468 | + di%cached_face_value%detwei = 0.0 |
4469 | + di%cached_face_value%detwei_bdy = 0.0 |
4470 | + |
4471 | + allocate(di%cached_face_value%normal(di%ndim, di%p_cvshape%ngi, di%number_vele)) |
4472 | + allocate(di%cached_face_value%normal_bdy(di%ndim, di%p_cvbdyshape%ngi, di%number_sele)) |
4473 | + |
4474 | + di%cached_face_value%normal = 0.0 |
4475 | + di%cached_face_value%normal_bdy = 0.0 |
4476 | + |
4477 | + end if |
4478 | + |
4479 | + if (di%cached_face_value%cached_p_dshape) then |
4480 | + |
4481 | + allocate(di%cached_face_value%p_dshape(di%pressure_mesh%shape%loc, di%p_cvshape%ngi, di%ndim, di%number_vele)) |
4482 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
4483 | +!!!!! allocate(di%cached_face_value%p_dshape_bdy(di%pressure_mesh%faces%shape%loc, di%p_cvbdyshape_full%ngi, di%ndim, di%number_sele)) |
4484 | + |
4485 | + di%cached_face_value%p_dshape = 0.0 |
4486 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
4487 | +!!!!! di%cached_face_value%p_dshape_bdy = 0.0 |
4488 | + |
4489 | + end if |
4490 | + |
4491 | + allocate(normgi(di%ndim)) |
4492 | + allocate(notvisited(di%p_cvshape%ngi)) |
4493 | + allocate(x_face_quad(di%ndim, di%p_cvshape%ngi)) |
4494 | + |
4495 | + ! Determine the detwei and normal if required |
4496 | + find_cached_detwei_normal: if (di%cached_face_value%cached_detwei_normal) then |
4497 | + |
4498 | + vele_loop_detwei_normal: do vele = 1, di%number_vele |
4499 | + |
4500 | + call transform_cvsurf_to_physical(ele_val(di%positions, vele), & |
4501 | + di%x_cvshape, & |
4502 | + di%cached_face_value%detwei(:,vele), & |
4503 | + di%cached_face_value%normal(:,:,vele), & |
4504 | + di%cvfaces) |
4505 | + |
4506 | + ! Correct the orientation of the normal |
4507 | + |
4508 | + ! get the coordinate values for this element for each quadrature point |
4509 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
4510 | + |
4511 | + ! The node indices of the positions projected to the pressure mesh |
4512 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
4513 | + |
4514 | + ! Initialise array for the quadrature points of this |
4515 | + ! element for whether it has already been visited |
4516 | + notvisited = .true. |
4517 | + |
4518 | + ! loop over local nodes within this element |
4519 | + nodal_loop_i: do iloc = 1, di%pressure_mesh%shape%loc |
4520 | + |
4521 | + ! loop over CV faces internal to this element |
4522 | + face_loop: do face = 1, di%cvfaces%faces |
4523 | + |
4524 | + ! is this a face neighbouring iloc? |
4525 | + is_neigh: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
4526 | + |
4527 | + ! loop over gauss points on face |
4528 | + quadrature_loop: do gi = 1, di%cvfaces%shape%ngi |
4529 | + |
4530 | + ! global gauss pt index for this element |
4531 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
4532 | + |
4533 | + ! check if this quadrature point has already been visited |
4534 | + check_visited: if(notvisited(ggi)) then |
4535 | + |
4536 | + notvisited(ggi) = .false. |
4537 | + |
4538 | + ! correct the orientation of the normal so it points away from iloc |
4539 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
4540 | + x_face_quad(:,ggi), & |
4541 | + di%cached_face_value%normal(:,ggi,vele)) |
4542 | + |
4543 | + di%cached_face_value%normal(:,ggi,vele) = normgi |
4544 | + |
4545 | + end if check_visited |
4546 | + |
4547 | + end do quadrature_loop |
4548 | + |
4549 | + end if is_neigh |
4550 | + |
4551 | + end do face_loop |
4552 | + |
4553 | + end do nodal_loop_i |
4554 | + |
4555 | + end do vele_loop_detwei_normal |
4556 | + |
4557 | + sele_loop_detwei_normal: do sele = 1, di%number_sele |
4558 | + |
4559 | + call transform_cvsurf_facet_to_physical(ele_val(di%positions, face_ele(di%positions, sele)), & |
4560 | + face_val(di%positions, sele), & |
4561 | + di%x_cvbdyshape, & |
4562 | + di%cached_face_value%normal_bdy(:,:,sele), & |
4563 | + di%cached_face_value%detwei_bdy(:,sele)) |
4564 | + |
4565 | + end do sele_loop_detwei_normal |
4566 | + |
4567 | + end if find_cached_detwei_normal |
4568 | + |
4569 | + deallocate(normgi) |
4570 | + deallocate(notvisited) |
4571 | + deallocate(x_face_quad) |
4572 | + |
4573 | + ! Determine the p_dshape if required |
4574 | + find_cached_p_dshape: if (di%cached_face_value%cached_p_dshape) then |
4575 | + |
4576 | + vele_loop_p_dshape: do vele = 1, di%number_vele |
4577 | + |
4578 | + call transform_to_physical(di%positions, & |
4579 | + vele, & |
4580 | + x_shape = di%x_cvshape_full, & |
4581 | + shape = di%p_cvshape_full, & |
4582 | + dshape = di%cached_face_value%p_dshape(:,:,:,vele)) |
4583 | + |
4584 | + end do vele_loop_p_dshape |
4585 | + |
4586 | +!!!!! *** THIS IS NOT POSSIBLE YET *** |
4587 | +!!!!! sele_loop_p_dshape: do sele = 1, di%number_sele |
4588 | + |
4589 | +!!!!! call transform_to_physical(di%positions, & |
4590 | +!!!!! sele, & |
4591 | +!!!!! x_shape = di%x_cvbdyshape_full, & |
4592 | +!!!!! shape = di%p_cvbdyshape_full, & |
4593 | +!!!!! dshape = di%cached_face_value%p_dshape_bdy(:,:,:,sele)) |
4594 | + |
4595 | +!!!!! end do sele_loop_p_dshape |
4596 | + |
4597 | + end if find_cached_p_dshape |
4598 | + |
4599 | + ewrite(1,*) 'Finished Initialise cached face value types' |
4600 | + |
4601 | + end subroutine darcy_impes_initialise_cached_face_value |
4602 | + |
4603 | +! ---------------------------------------------------------------------------- |
4604 | + |
4605 | + subroutine darcy_impes_calculate_relperm_den_first_face_values(di) |
4606 | + |
4607 | + !!< Find the relperm and density CV first face values for all phase and cache. |
4608 | + |
4609 | + type(darcy_impes_type), intent(inout) :: di |
4610 | + |
4611 | + ! local variables |
4612 | + logical :: inflow |
4613 | + integer :: p, vele, sele, iloc, oloc, face, gi, ggi |
4614 | + integer :: r_upwind_pos, d_upwind_pos, s_upwind_pos, dim, sat_p |
4615 | + real :: income, v_over_relperm_dot_n, old_relperm_face_value, den_face_value, old_sat_face_value |
4616 | + real, dimension(1) :: absperm_ele, visc_ele |
4617 | + real, dimension(:), pointer :: old_relperm_ele |
4618 | + real, dimension(:), pointer :: den_ele |
4619 | + real, dimension(:,:), pointer :: old_sat_ele |
4620 | + real, dimension(:,:), pointer :: grav_ele |
4621 | + real, dimension(:,:), pointer :: grad_pressure_face_quad |
4622 | + real, dimension(:,:), pointer :: v_over_relperm_face_quad |
4623 | + real, dimension(:,:), pointer :: x_ele |
4624 | + real, dimension(:,:,:), pointer :: p_dshape |
4625 | + real, dimension(:,:), pointer :: normal |
4626 | + real, dimension(:), pointer :: detwei |
4627 | + real, dimension(:), pointer :: normgi |
4628 | + logical, dimension(:), pointer :: notvisited |
4629 | + real, dimension(:,:), pointer :: x_face_quad |
4630 | + integer, dimension(:), pointer :: x_pmesh_nodes |
4631 | + integer, dimension(:), pointer :: p_nodes |
4632 | + integer, dimension(:), pointer :: r_upwind_nodes |
4633 | + integer, dimension(:), pointer :: d_upwind_nodes |
4634 | + integer, dimension(:), pointer :: s_upwind_nodes |
4635 | + real, dimension(:), pointer :: den_ele_bdy |
4636 | + real, dimension(:), pointer :: old_relperm_ele_bdy |
4637 | + |
4638 | + ! allocate arrays used in assemble process - many assume |
4639 | + ! that all elements are the same type. |
4640 | + allocate(x_ele(di%ndim, ele_loc(di%positions,1))) |
4641 | + if (.not. di%cached_face_value%cached_p_dshape) then |
4642 | + allocate(p_dshape(ele_loc(di%pressure_mesh,1), di%x_cvshape%ngi, mesh_dim(di%pressure_mesh))) |
4643 | + end if |
4644 | + if (.not. di%cached_face_value%cached_detwei_normal) then |
4645 | + allocate(normal(di%ndim,di%x_cvshape%ngi)) |
4646 | + allocate(detwei(di%x_cvshape%ngi)) |
4647 | + end if |
4648 | + allocate(normgi(di%ndim)) |
4649 | + allocate(notvisited(di%x_cvshape%ngi)) |
4650 | + allocate(x_face_quad(di%ndim, di%x_cvshape%ngi)) |
4651 | + allocate(old_relperm_ele(ele_loc(di%pressure_mesh,1))) |
4652 | + allocate(den_ele(ele_loc(di%pressure_mesh,1))) |
4653 | + allocate(old_sat_ele(ele_loc(di%pressure_mesh,1), di%number_phase)) |
4654 | + allocate(grav_ele(di%ndim,1)) |
4655 | + allocate(grad_pressure_face_quad(di%ndim, di%p_cvshape%ngi)) |
4656 | + allocate(v_over_relperm_face_quad(di%ndim,di%p_cvshape%ngi)) |
4657 | + |
4658 | + allocate(den_ele_bdy(face_loc(di%pressure_mesh,1))) |
4659 | + allocate(old_relperm_ele_bdy(face_loc(di%pressure_mesh,1))) |
4660 | + |
4661 | + ewrite(1,*) 'Calculate relperm and density and first face values' |
4662 | + |
4663 | + ! Initialise the cached face values |
4664 | + di%cached_face_value%relperm(1,:,:,:) = 0.0 |
4665 | + di%cached_face_value%relperm_bdy(1,:,:,:) = 0.0 |
4666 | + di%cached_face_value%den = 0.0 |
4667 | + di%cached_face_value%den_bdy = 0.0 |
4668 | + |
4669 | + phase_loop: do p = 1, di%number_phase |
4670 | + |
4671 | + ! Determine the upwind relperm values of all node pairs if required for higher order CV face value. |
4672 | + ! If the relperm face value is a RELPERMOVERSAT... scheme then the upwind values |
4673 | + ! of modrelperm are required (= relperm / sat) |
4674 | + if(di%relperm_cv_options%limit_facevalue) then |
4675 | + |
4676 | + if (di%determine_saturation_face_values) then |
4677 | + |
4678 | + call darcy_impes_calculate_old_modified_relative_permeability(di, p) |
4679 | + |
4680 | + ! NOTE only old values are required but this procedure |
4681 | + ! expects latest and old. So pass in old twice - not optimal |
4682 | + call find_upwind_values(di%state, & |
4683 | + di%positions_pressure_mesh, & |
4684 | + di%modified_relative_permeability, & |
4685 | + di%relperm_upwind, & |
4686 | + di%modified_relative_permeability, & |
4687 | + di%relperm_upwind, & |
4688 | + option_path = trim(di%relative_permeability(p)%ptr%option_path)) |
4689 | + |
4690 | + else |
4691 | + |
4692 | + ! NOTE only old values are required but this procedure |
4693 | + ! expects latest and old. So pass in old twice - not optimal |
4694 | + call find_upwind_values(di%state, & |
4695 | + di%positions_pressure_mesh, & |
4696 | + di%old_relative_permeability(p)%ptr, & |
4697 | + di%relperm_upwind, & |
4698 | + di%old_relative_permeability(p)%ptr, & |
4699 | + di%relperm_upwind, & |
4700 | + option_path = trim(di%relative_permeability(p)%ptr%option_path)) |
4701 | + |
4702 | + end if |
4703 | + |
4704 | + end if |
4705 | + |
4706 | + ! If the relperm face value is a RELPERMOVERSAT... scheme then the saturation |
4707 | + ! face values need determining which may require the upwind values. |
4708 | + if (di%determine_saturation_face_values .and. di%saturation_cv_options%limit_facevalue) then |
4709 | + |
4710 | + ! NOTE only old values are required but this procedure |
4711 | + ! expects latest and old. So pass in old twice - not optimal |
4712 | + call find_upwind_values(di%state, & |
4713 | + di%positions_pressure_mesh, & |
4714 | + di%old_saturation(p)%ptr, & |
4715 | + di%sfield_upwind, & |
4716 | + di%old_saturation(p)%ptr, & |
4717 | + di%sfield_upwind, & |
4718 | + option_path = trim(di%saturation(p)%ptr%option_path)) |
4719 | + |
4720 | + end if |
4721 | + |
4722 | + ! Initialise optimisation flag used in finding upwind value in high resolution schemes |
4723 | + r_upwind_pos = 0 |
4724 | + s_upwind_pos = 0 |
4725 | + |
4726 | + vol_element_loop_relperm: do vele = 1, di%number_vele |
4727 | + |
4728 | + ! The node indices of the pressure mesh |
4729 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
4730 | + |
4731 | + ! The node indices of the positions projected to the pressure mesh |
4732 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
4733 | + |
4734 | + ! Determine the node numbers to use to determine the relperm upwind values |
4735 | + if((di%relperm_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_POINT).or.& |
4736 | + (di%relperm_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_GRAD)) then |
4737 | + |
4738 | + r_upwind_nodes => x_pmesh_nodes |
4739 | + |
4740 | + else |
4741 | + |
4742 | + r_upwind_nodes => p_nodes |
4743 | + |
4744 | + end if |
4745 | + |
4746 | + if (di%determine_saturation_face_values) then |
4747 | + |
4748 | + ! Determine the node numbers to use to determine the saturation upwind values |
4749 | + if((di%saturation_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_POINT).or.& |
4750 | + (di%saturation_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_GRAD)) then |
4751 | + |
4752 | + s_upwind_nodes => x_pmesh_nodes |
4753 | + |
4754 | + else |
4755 | + |
4756 | + s_upwind_nodes => p_nodes |
4757 | + |
4758 | + end if |
4759 | + |
4760 | + do sat_p = 1, di%number_phase |
4761 | + |
4762 | + ! get the old saturation ele values for this phase |
4763 | + old_sat_ele(:,sat_p) = ele_val(di%old_saturation(sat_p)%ptr, vele) |
4764 | + |
4765 | + end do |
4766 | + |
4767 | + end if |
4768 | + |
4769 | + ! get the old_relperm ele values for this phase |
4770 | + old_relperm_ele = ele_val(di%old_relative_permeability(p)%ptr, vele) |
4771 | + |
4772 | + ! The gravity values for this element for each direction |
4773 | + grav_ele = ele_val(di%gravity, vele) |
4774 | + |
4775 | + ! get the viscosity value for this element for this phase |
4776 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
4777 | + |
4778 | + ! get the absolute permeability value for this element |
4779 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
4780 | + |
4781 | + ! obtain the transformed determinant*weight and normals |
4782 | + if (di%cached_face_value%cached_detwei_normal) then |
4783 | + |
4784 | + detwei => di%cached_face_value%detwei(:,vele) |
4785 | + |
4786 | + normal => di%cached_face_value%normal(:,:,vele) |
4787 | + |
4788 | + else |
4789 | + |
4790 | + ! get the coordinate values for this element for each positions local node |
4791 | + x_ele = ele_val(di%positions, vele) |
4792 | + |
4793 | + ! get the coordinate values for this element for each quadrature point |
4794 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
4795 | + |
4796 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
4797 | + |
4798 | + end if |
4799 | + |
4800 | + ! obtain the derivative of the pressure mesh shape function at the CV face quadrature points |
4801 | + if (di%cached_face_value%cached_p_dshape) then |
4802 | + |
4803 | + p_dshape => di%cached_face_value%p_dshape(:,:,:,vele) |
4804 | + |
4805 | + else |
4806 | + |
4807 | + call transform_to_physical(di%positions, vele, x_shape = di%x_cvshape_full, & |
4808 | + shape = di%p_cvshape_full, dshape = p_dshape) |
4809 | + |
4810 | + end if |
4811 | + |
4812 | + ! get the gradient pressure at the cv surface quadrature points for each direction for this phase |
4813 | + grad_pressure_face_quad = darcy_impes_ele_grad_at_quad_scalar(di%pressure(p)%ptr, vele, dn = p_dshape) |
4814 | + |
4815 | + ! the latest DarcyVelocity/relperm at the quadrature points |
4816 | + ! determined from FE interpolation of each component, only used to determine upwind. |
4817 | + do dim = 1,di%ndim |
4818 | + |
4819 | + v_over_relperm_face_quad(dim,:) = - (absperm_ele(1) / visc_ele(1)) * & |
4820 | +(grad_pressure_face_quad(dim,:) - ele_val_at_quad(di%density(p)%ptr, vele, di%p_cvshape) * grav_ele(dim,1)) |
4821 | + |
4822 | + end do |
4823 | + |
4824 | + ! Initialise array for the quadrature points of this |
4825 | + ! element for whether it has already been visited |
4826 | + notvisited = .true. |
4827 | + |
4828 | + ! loop over local nodes within this element |
4829 | + nodal_loop_i_relperm: do iloc = 1, di%pressure_mesh%shape%loc |
4830 | + |
4831 | + ! loop over CV faces internal to this element |
4832 | + face_loop_relperm: do face = 1, di%cvfaces%faces |
4833 | + |
4834 | + ! is this a face neighbouring iloc? |
4835 | + is_neigh_relperm: if(di%cvfaces%neiloc(iloc, face) /= 0) then |
4836 | + |
4837 | + ! find the opposing local node across the CV face |
4838 | + oloc = di%cvfaces%neiloc(iloc, face) |
4839 | + |
4840 | + ! loop over gauss points on face |
4841 | + quadrature_loop_relperm: do gi = 1, di%cvfaces%shape%ngi |
4842 | + |
4843 | + ! global gauss pt index for this element |
4844 | + ggi = (face-1)*di%cvfaces%shape%ngi + gi |
4845 | + |
4846 | + ! check if this quadrature point has already been visited |
4847 | + check_visited_relperm: if(notvisited(ggi)) then |
4848 | + |
4849 | + notvisited(ggi) = .false. |
4850 | + |
4851 | + if (di%cached_face_value%cached_detwei_normal) then |
4852 | + |
4853 | + ! cached normal has correct orientation already |
4854 | + normgi = normal(:,ggi) |
4855 | + |
4856 | + else |
4857 | + |
4858 | + ! correct the orientation of the normal so it points away from iloc |
4859 | + normgi = orientate_cvsurf_normgi(node_val(di%positions_pressure_mesh, x_pmesh_nodes(iloc)), & |
4860 | + &x_face_quad(:,ggi), normal(:,ggi)) |
4861 | + |
4862 | + end if |
4863 | + |
4864 | + ! determine if the flow is in or out of the face at this quadrature |
4865 | + ! with respect to the normal orientation using the latest v_over_relperm |
4866 | + v_over_relperm_dot_n = dot_product(v_over_relperm_face_quad(:,ggi), normgi) |
4867 | + |
4868 | + inflow = (v_over_relperm_dot_n<=0.0) |
4869 | + |
4870 | + income = merge(1.0,0.0,inflow) |
4871 | + |
4872 | + ! Evaluate the face value for relperm |
4873 | + call darcy_impes_evaluate_relperm_face_val(old_relperm_face_value, & |
4874 | + iloc, & |
4875 | + oloc, & |
4876 | + ggi, & |
4877 | + r_upwind_nodes, & |
4878 | + di%p_cvshape, & |
4879 | + old_relperm_ele, & |
4880 | + di%relperm_upwind, & |
4881 | + inflow, & |
4882 | + income, & |
4883 | + old_sat_ele, & |
4884 | + di%minimum_denominator_saturation_value, & |
4885 | + p, & |
4886 | + di%number_phase, & |
4887 | + di%relperm_corr_options, & |
4888 | + di%relperm_cv_options, & |
4889 | + save_pos = r_upwind_pos) |
4890 | + |
4891 | + ! Evaluate the face value for saturation if required, else set to 1.0 |
4892 | + if (di%determine_saturation_face_values) then |
4893 | + |
4894 | + call darcy_impes_evaluate_sfield_face_val(old_sat_face_value, & |
4895 | + iloc, & |
4896 | + oloc, & |
4897 | + ggi, & |
4898 | + s_upwind_nodes, & |
4899 | + di%p_cvshape, & |
4900 | + old_sat_ele(:,p), & |
4901 | + di%sfield_upwind, & |
4902 | + inflow, & |
4903 | + income, & |
4904 | + di%saturation_cv_options, & |
4905 | + save_pos = s_upwind_pos) |
4906 | + |
4907 | + else |
4908 | + |
4909 | + old_sat_face_value = 1.0 |
4910 | + |
4911 | + end if |
4912 | + |
4913 | + ! Cache the old relperm (or modrelperm*sat) face value |
4914 | + di%cached_face_value%relperm(1,ggi,vele,p) = old_relperm_face_value * old_sat_face_value |
4915 | + |
4916 | + end if check_visited_relperm |
4917 | + |
4918 | + end do quadrature_loop_relperm |
4919 | + |
4920 | + end if is_neigh_relperm |
4921 | + |
4922 | + end do face_loop_relperm |
4923 | + |
4924 | + end do nodal_loop_i_relperm |
4925 | + |
4926 | + end do vol_element_loop_relperm |
4927 | + |
4928 | + ! Determine the upwind density values of all node pairs if required for higher order CV face value |
4929 | + if(di%density_cv_options%limit_facevalue) then |
4930 | + |
4931 | + ! NOTE only new upwind values are required but this procedure |
4932 | + ! expects latest and old. So pass in new twice - not optimal |
4933 | + call find_upwind_values(di%state, & |
4934 | + di%positions_pressure_mesh, & |
4935 | + di%density(p)%ptr, & |
4936 | + di%sfield_upwind, & |
4937 | + di%density(p)%ptr, & |
4938 | + di%sfield_upwind, & |
4939 | + option_path = trim(di%density(p)%ptr%option_path)) |
4940 | + |
4941 | + end if |
4942 | + |
4943 | + ! Initialise optimisation flag used in finding upwind value in high resolution schemes |
4944 | + d_upwind_pos = 0 |
4945 | + |
4946 | + vol_element_loop_den: do vele = 1, di%number_vele |
4947 | + |
4948 | + ! The node indices of the pressure mesh |
4949 | + p_nodes => ele_nodes(di%pressure_mesh, vele) |
4950 | + |
4951 | + ! The node indices of the positions projected to the pressure mesh |
4952 | + x_pmesh_nodes => ele_nodes(di%positions_pressure_mesh, vele) |
4953 | + |
4954 | + ! Determine the node numbers to use to determine the density upwind values |
4955 | + if((di%density_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_POINT).or.& |
4956 | + (di%density_cv_options%upwind_scheme == CV_UPWINDVALUE_PROJECT_GRAD)) then |
4957 | + |
4958 | + d_upwind_nodes => x_pmesh_nodes |
4959 | + |
4960 | + else |
4961 | + |
4962 | + d_upwind_nodes => p_nodes |
4963 | + |
4964 | + end if |
4965 | + |
4966 | + ! get the density value for this element for this phase |
4967 | + den_ele = ele_val(di%density(p)%ptr, vele) |
4968 | + |
4969 | + ! The gravity values for this element for each direction |
4970 | + grav_ele = ele_val(di%gravity, vele) |
4971 | + |
4972 | + ! get the viscosity value for this element for this phase |
4973 | + visc_ele = ele_val(di%viscosity(p)%ptr, vele) |
4974 | + |
4975 | + ! get the absolute permeability value for this element |
4976 | + absperm_ele = ele_val(di%absolute_permeability, vele) |
4977 | + |
4978 | + ! obtain the transformed determinant*weight and normals |
4979 | + if (di%cached_face_value%cached_detwei_normal) then |
4980 | + |
4981 | + detwei => di%cached_face_value%detwei(:,vele) |
4982 | + |
4983 | + normal => di%cached_face_value%normal(:,:,vele) |
4984 | + |
4985 | + else |
4986 | + |
4987 | + ! get the coordinate values for this element for each positions local node |
4988 | + x_ele = ele_val(di%positions, vele) |
4989 | + |
4990 | + ! get the coordinate values for this element for each quadrature point |
4991 | + x_face_quad = ele_val_at_quad(di%positions, vele, di%x_cvshape) |
4992 | + |
4993 | + call transform_cvsurf_to_physical(x_ele, di%x_cvshape, detwei, normal, di%cvfaces) |
4994 | + |
4995 | + end if |
4996 | + |
4997 | + ! obtain the derivative of the pressure mesh shape function at the CV face quadrature points |
4998 | + if (di%cached_face_value%cached_p_dshape) then |
4999 | + |
5000 | + p_dshape => di%cached_face_value%p_dshape(:,:,:,vele) |
Hello, only had a quick look at this merge. Most code changes to code shared with fluidity seem reasonable at first glance.
I have some worries about the need to add this to trunk Fluidity, in terms of maintainability, etc. but these are probably better discussed in another forum.
The main problem at the moment is that this merge seems to add about 150M to a clean checkout (current checkout size is 300M). The main cause of this seem to be the tests/Tarantula _mesh/ and tests/Tarantula _mesh_v2 directories that were added. In general there seems to be a whole lot of things in there (reports and stuff) that are not appropriate in the tests directory. If such a large data set is needed for testing, I suggest changing it to a long test. Also, are we sure that there are no license issues associated with any of it? If we do remove these directories, we have to rebuild the history after their commits to avoid polluting the history with these.